CI (SIAX Cloud) / integration (push) Has been skipped
masterplan-lock / check (push) Successful in 8s
masterplan-lock / check (pull_request) Successful in 3s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 14s
CI (SIAX Cloud) / security (pull_request) Successful in 19s
CI (SIAX Cloud) / integration (pull_request) Successful in 28s
CI (SIAX Cloud) / quality (pull_request) Successful in 34s
Security Scan (SIAX Cloud) / security (push) Successful in 1m15s
CI (SIAX Cloud) / security (push) Successful in 1m15s
CI (SIAX Cloud) / quality (push) Successful in 1m25s
278 lines
26 KiB
Markdown
278 lines
26 KiB
Markdown
# 0pt — capability status (Master-DoD §56 status honesty)
|
||
|
||
> Classification scale (Master-DoD §2, exactly one per capability):
|
||
> `MISSING → DOCUMENTED_ONLY → SKELETON → MOCK_ONLY → IMPLEMENTED → INTEGRATION_TESTED → LIVE_VERIFIED → PRODUCTION_READY`.
|
||
> Only `PRODUCTION_READY` may be called DONE. Docs ≠ implementation.
|
||
> Last full audit + re-classification: **2026-08-31** (SIAX Platforms P0 wave 2).
|
||
|
||
## How to read this
|
||
|
||
- **INTEGRATION_TESTED** here means: verified against a REAL dependency
|
||
(live OpenSearch/ClickHouse container, or a recorded wire-contract double
|
||
pinned to the sibling repo's real handler code on its `main`) in CI.
|
||
- **LIVE_VERIFIED** requires a verification against the actual SIAX fleet
|
||
deployment. No new capability in this wave claims it.
|
||
- The unit/contract/integration suites are in `tests/` and run in
|
||
`.gitea/workflows/ci.yml` (jobs `quality` + `integration`).
|
||
|
||
## Cross-product clients (Master-DoD §10 "Cross-product clients")
|
||
|
||
| Capability | Status | Evidence | Honest gaps |
|
||
|---|---|---|---|
|
||
| CL0UD client (policy evaluate, `POST /api/policy/evaluate`) | **INTEGRATION_TESTED** (contract) | `src/clients/cl0ud-client.ts`; `tests/contracts/cl0ud-client.contract.test.ts` pins the real camelCase `{data}` envelope; fail-closed (missing decision ⇒ deny) | Not yet exercised against a live CL0UD deployment (no reachable CL0UD URL this session ⇒ not LIVE_VERIFIED) |
|
||
| CL0UD capability discovery (`GET /api/capabilities`) | **INTEGRATION_TESTED** (contract) | same suite | 0pt's own capabilities are not yet registered in CL0UD's registry (§3 gap) |
|
||
| ST0RE client (artifact register, camelCase `/v1/st0re/artifacts/register`) | **INTEGRATION_TESTED** (contract) | `src/clients/st0re-client.ts`; `tests/contracts/st0re-client.contract.test.ts` | Raw-bytes upload still goes via LocalBlobStore interim (pre-existing, unchanged); presign upload path not consumed yet |
|
||
| N0D client (create/get job, get result) | **INTEGRATION_TESTED** (contract) | `src/clients/n0d-client.ts`; `tests/contracts/n0d-client.contract.test.ts` pins `required_role`/`resource_requirements`/body `idempotency_key` | CloudEvents completion callback receiving endpoint not built in 0pt (poll path works) |
|
||
| AUD0 client (events + OpenLineage ingest) | **INTEGRATION_TESTED** (contract) | `src/clients/aud0-client.ts`; `tests/contracts/aud0-client.contract.test.ts`; legacy lineage shape converts to real OpenLineage | No durable local outbox for AUD0 outages (§70 "durable local/outbox path" — emission failure is surfaced, not queued) |
|
||
| **No production mock fallback (§3/§10)** | **INTEGRATION_TESTED** | `src/platform/dependency-mode.ts`; `tests/contracts/dependency-mode.contract.test.ts` drives NODE_ENV=production for all four factories ⇒ hard `DEPENDENCY_UNAVAILABLE` | — |
|
||
|
||
**Correction of prior state (2026-08-31):** the pre-existing clients' HTTP
|
||
paths were verified against the sibling repos' actual `main` branches and
|
||
THREE of four were wrong: cl0ud (`/v1/cl0ud/policies/evaluate` — never
|
||
existed), st0re (snake_case body — would 400), aud0 lineage
|
||
(`/v1/aud0/lineage/events` — never existed). All fixed and pinned by
|
||
contract tests. The earlier MOCK_ONLY classification in the README was
|
||
accurate.
|
||
|
||
## Data-OS capabilities (Master-DoD §10)
|
||
|
||
| Capability | Status | Evidence | Honest gaps |
|
||
|---|---|---|---|
|
||
| Source Registry — register/query/describe/health, rights/license/purpose, freshness, provenance | **IMPLEMENTED** | `src/services/source-registry-service.ts`, `src/types/source-registry.ts`; `tests/p0/source-registry.test.ts` (fail-closed purpose gate, cross-tenant NOT_FOUND) | In-memory persistence (per-process); no Postgres store yet — production boot must therefore configure one before this counts further. No API route surface yet |
|
||
| Source rate-policy | **IMPLEMENTED** (pre-existing) | `src/services/source-rate-policy-service.ts` | unchanged this wave |
|
||
| Search — OpenSearch adapter, index defs, bulk, tenant + purpose/rights filter, rebuild, generation switch | **INTEGRATION_TESTED** | `src/search/*`; unit `tests/p0/search-service.test.ts`; **real OpenSearch 2.11** `tests/integration/search-opensearch.integration.test.ts` incl. projection-disaster rebuild (§68-style) — runs in CI service container | Hybrid (vector) query not built; no metrics emission; index definitions in-memory |
|
||
| Quality — versioned rules, runs, results, issues, score, trend, GE interchange | **IMPLEMENTED** (local engine) / **SKELETON** (GE delegation) | `src/quality/*`; `tests/p0/quality-service.test.ts`, `tests/p0/expectation-engine` cases | Local engine covers 7 GE core expectation types; everything else delegates via N0D job `0pt.quality.ge_run` whose EXECUTOR (0pt-motor GE runner) does not exist yet — delegated runs stay "delegated" until it does. Never fabricates results |
|
||
| Dataset — create (pre-existing) + version/query/export with `st0re:artifact:` refs | **IMPLEMENTED** | `src/services/dataset-version-service.ts`; `tests/p0/dataset-version-service.test.ts` (idempotency §53, canonical refs §5) | Export assumes bytes already written by a job; no route surface; in-memory persistence |
|
||
| Lineage — OpenLineage emission to AUD0's real ingest | **INTEGRATION_TESTED** (contract) | `src/lineage/*`; aud0 contract suite; emitted from dataset version/export, quality runs, search rebuilds | Emission is best-effort (never-throw); no outbox. AUD0-side ingestion verified against contract double, not live AUD0 |
|
||
| Metadata — OpenMetadata projection (never canonical) | **IMPLEMENTED** | `src/metadata/openmetadata-adapter.ts`; `tests/contracts/metadata-features.contract.test.ts`; `projectAll` rebuild path | No live OpenMetadata exercised (no local container this pass); lineage/glossary/ownership projection not built — only dataset entities |
|
||
| Analytics — ClickHouse, tenant-isolated, query limits, retention | **INTEGRATION_TESTED** | `src/analytics/clickhouse-analytics.ts`; **real ClickHouse 24.8** `tests/integration/analytics-clickhouse.integration.test.ts` (tenant isolation, closed DSL, TTL schema) — runs in CI service container | Closed metric-DSL only (no ad-hoc queries by design); no quota integration with CL0UD |
|
||
| Features — registry + Feast adapter | **IMPLEMENTED** (online path, registry) / **SKELETON** (materialize/get-historical) | `src/features/feast-adapter.ts`; contract suite pins Feast's `get-online-features` wire shape | No live Feast server exercised; offline/materialization are N0D delegation contracts whose executor (0pt-motor) does not exist yet; point-in-time correctness therefore NOT yet proven |
|
||
| Entity Resolution — candidate API, blocking, explanation, hard-rule hook, review handoff | **IMPLEMENTED** | `src/er/entity-resolution-service.ts`; `tests/p0/entity-resolution.test.ts` (hard rules override both directions, review band, blocking refusals) | Generic reference scorer (Jaccard+Levenshtein), NOT Splink probabilistic linkage — that is the `0pt.er.batch_resolution` N0D contract, executor pending in 0pt-motor. No persistence of review queues |
|
||
| Graph (§10 Graph) | **MISSING** | — | Not started this wave (explicitly out of the delivered P0 subset; next in line per §10) |
|
||
|
||
## Canonical platform plumbing
|
||
|
||
| Capability | Status | Evidence |
|
||
|---|---|---|
|
||
| SiaxRequestContext + propagation headers (mirror of cl0ud `@siax/contract`) | **INTEGRATION_TESTED** (contract-pinned) | `src/platform/siax-context.ts`; `tests/contracts/siax-context.contract.test.ts` |
|
||
| Canonical 12-code error model + typed `SiaxError` (§6) | **INTEGRATION_TESTED** (contract-pinned) | `src/platform/errors.ts`; same suite |
|
||
| Canonical resource refs (§5) | **IMPLEMENTED** | `src/platform/resource-ref.ts`; `tests/p0/dataset-version-service.test.ts` |
|
||
|
||
## Pre-existing capabilities (unchanged this wave — prior classifications stand)
|
||
|
||
| Capability | Status | Note |
|
||
|---|---|---|
|
||
| Iceberg write boundary via ST0RE lakehouse | LIVE_VERIFIED (2026-07-13) | `docs/ICEBERG_WRITE_BOUNDARY.md`; untouched |
|
||
| Document capture/extraction | IMPLEMENTED | LocalBlobStore interim persists bytes; ST0RE raw upload still pending |
|
||
| Edge order/payment app (Next.js) | see `docs/architecture/ARCHITECTURE.md` | outside this wave's scope |
|
||
| FastAPI engine (`services/api`) | IMPLEMENTED | outside this wave's scope |
|
||
| `services/scrapers/*` (WAF-bypass stack) | **quarantined, pending deletion PR** | `feature/0pt-remove-noncompliant-scrapers` — NOT touched by this wave; nothing new wires it |
|
||
|
||
## Global gaps blocking PRODUCTION_READY (§3, tracked, not hidden)
|
||
|
||
1. Persistent stores REMAINING: quality runs/rules and feature views are
|
||
still per-process in-memory (`resolveStoreMode` guarantees production
|
||
boot FAILS rather than serving Maps). CLOSED since the last revision:
|
||
dataset registry (`opt_datasets`) + immutable versions
|
||
(`opt_dataset_versions`, monotonic under transaction lock, idempotency
|
||
with payload-drift detection, cross-tenant ⇒ NOT_FOUND) and versioned
|
||
search index definitions (`opt_search_index_definitions`, sequential
|
||
schema versions, replay-idempotent, same-version-different-schema ⇒
|
||
CONFLICT; OpenSearch remains a rebuildable projection, never canonical
|
||
truth) are Postgres-canonical with real-Postgres tests.
|
||
2. Capability registration in CL0UD + API0 discovery for the new
|
||
capabilities (§3 "Capability är registrerad i CL0UD Capability
|
||
Registry") — PARTIALLY CLOSED: the collaboration/meeting domain was
|
||
canonicalized in CL0UD's registry (cl0ud #73/#74); 0pt's own
|
||
capability set still needs the same registration.
|
||
3. CLOSED: AUD0 outbox for evidence durability under AUD0 outage (§70) —
|
||
durable Postgres outbox + dispatcher (at-least-once, bounded batch,
|
||
backoff, dead-letter, SKIP LOCKED leasing, tenant binding, idempotency)
|
||
+ real-Postgres tests; dispatcher uses explicit `durable:false` so it
|
||
never re-enqueues its own delivery evidence.
|
||
4. CLOSED for datasets/versions/search/ER: `app/api/0pt/datasets*`,
|
||
`app/api/0pt/search/definitions` + tenant-safed query route, and
|
||
`app/api/0pt/er/{candidates,batch}` (+ internal ER route) are live;
|
||
clients cannot raise `rights_tag` via request body (fail-closed to
|
||
`internal`). Quality routes exist (`bridge-run/issues/rules/runs`).
|
||
5. 0pt-motor executors for the delegated jobs
|
||
(`0pt.quality.ge_run`, `0pt.features.*`, `0pt.er.batch_resolution`).
|
||
6. Observability: no metrics/traces emitted by the new services (§36).
|
||
|
||
---
|
||
|
||
## P060-P068 ingestion plane (added 2026-09-04)
|
||
|
||
Classification scale unchanged. Every row below states what was actually
|
||
verified, and by which command.
|
||
|
||
| Requirement | BEFORE this pass | Status now | Evidence |
|
||
|---|---|---|---|
|
||
| **P060** Source Registry: durable canonical registry; restart preserves sources; an unclassified source cannot be activated | **PARTIAL / BROKEN.** The registry existed with Postgres persistence (`sql/002_source_registry.sql`, `src/repositories/postgres-source-registry-repository.ts`) and carried source_id/tenant/project/type/status/license/purpose/rights. It had NO authorization, NO schedule, NO checkpoint, NO schema, and no `owner` distinct from `created_by`. The activation DoD was inverted: `postgres-source-repository.ts:70` wrote `${input.status ?? "active"}`, so a source with no rights, no provenance and no authorization was ACTIVE the instant it was registered, and no activation operation existed at all | **INTEGRATION_TESTED** | `sql/007_ingestion_plane.sql` (authorization/schedule/schemas/checkpoints + `ALTER … SET DEFAULT 'pending'` + `owner_id`); `SourceRegistryService.classifySource`/`activateSource`; `tests/p0/source-activation-gate.test.ts` (11); `tests/api/0pt-p060-routes.test.ts` (9); `tests/p0/ingestion-plane-postgres.realinfra.test.ts` against a live Postgres 16 |
|
||
| **P061** Connector contract: discover/validate/connect/checkpoint/read/resume/backfill/health/disconnect; two heterogeneous connectors pass one conformance suite | **MISSING.** `services/api/sources/connectors.py` had per-source `fetch_*()` functions only — no lifecycle, no cursor, no resume, no health, no disconnect, no conformance suite | **INTEGRATION_TESTED** | `src/connectors/connector.ts` (all nine operations); `src/connectors/conformance.ts` (15 checks); `HttpJsonConnector` (real node:http server, opaque cursor) and `JsonlFileConnector` (real file, line-offset cursor, CDC deletes) both pass the identical suite — `tests/p0/connector-conformance.test.ts`, which also proves the suite FAILS a fail-open connector |
|
||
| **P062** CDC/batch/stream normalized to one envelope; restart resumes from a durable checkpoint without silent gaps | **MISSING**, and documented as such: `services/api/tests/test_known_gaps.py:10-19` skipped the CDC case because no CDC pipeline existed anywhere, and `workers/pipeline.py` had no persistence at all | **INTEGRATION_TESTED** | `src/types/ingestion.ts` (one envelope for all three modes); `src/ingestion/ingestion-runner.ts`; `tests/p0/ingestion-runner.test.ts` kills a run inside the sink and proves the resumed run covers all 10 records exactly once; same proof against real Postgres across fresh processes |
|
||
| **P063** Schema versioning + compatibility policy; a breaking schema is detected before consumer corruption | **MISSING.** `schema_version` existed as a free-form string on datasets/Iceberg writes; there was no comparison, no policy, no versioned source schema | **INTEGRATION_TESTED** | `src/schema/compatibility.ts`, `src/schema/schema-registry.ts`; `tests/p0/schema-evolution.test.ts` (12); the runner's schema gate runs before the first read — `tests/p0/ingestion-runner.test.ts` asserts `sinkCalls === 0` on a break |
|
||
| **P064** Quality rules behind the SIAX abstraction; failures block or quarantine per declared policy | **PARTIAL.** `src/quality/*` had rules, runs, results, issues, scores and a GE-compatible engine, but a failing rule only opened an ISSUE — the data flowed on regardless. `grep -ri quarantin src/` found one unrelated hit | **INTEGRATION_TESTED** | `src/quality/quality-policy.ts` composes the EXISTING `ExpectationEngine` (not a second engine) and adds the consequence; block / quarantine / warn each proved in `tests/p0/ingestion-runner.test.ts`; quarantine durability proved against real Postgres |
|
||
| **P065** Normalization/ER: only the canonical highway; no second simplified production engine | **CLOSED.** `services/api/workers/resolve.py` is now a thin adapter: Python no longer scores identity — it POSTs opaque records to `/api/0pt/internal/er/candidates` and applies ONLY explicit hard-rule `match` decisions (score/fuzzy can never merge records, even from a compromised bridge); canonical engine unreachable ⇒ records return UNMERGED, never fallback-scored. Company semantics `stable-identifiers.v3`: LEI global; org_nr hard identity only within the same registration_country; punctuation normalized; negative stable identity dominates every positive; fuzzy alone ⇒ human review, never auto-merge. Cluster-wide hard-negative constraints: A≈B ∧ B≈C never forces A≈C when canonical identity says A≠C | **INTEGRATION_TESTED** | `tests/p0/entity-resolution.test.ts` (v3 semantics incl. hard-negative transitivity), `tests/p0/entity-resolution-http.test.ts` (internal route fails closed: empty/wrong token ⇒ 401), `services/api/tests/test_resolve_determinism.py` (adapter contract: canonical edges only), shared request validation (`src/er/request-validation.ts`, records 2..5000), blocking pytest gate (`.gitea/workflows/python-engine.yml`) |
|
||
| **P066** Iceberg | out of scope — ST0RE is owned by another workflow | **NOT TOUCHED** | Contract read only (`src/services/iceberg-write-service.ts`, `src/clients/st0re-lakehouse-client.ts`) |
|
||
| **P067** Lineage: OpenLineage/AUD0 events; source → output lineage is queryable | **PARTIAL.** `src/lineage/lineage-emitter.ts` emitted OpenLineage to AUD0, but nothing in this repo could ANSWER a lineage question — no store, no query, no route | **INTEGRATION_TESTED** | `src/lineage/lineage-edge.ts`, `src/lineage/lineage-store.ts` (local queryable projection; AUD0 stays the system of record), `GET /api/0pt/lineage`; `tests/p0/ingestion-runner.test.ts` queries both directions and proves tenant scoping |
|
||
| **P068** Durable bounded backfill/replay; repeated backfill is idempotent | **MISSING**, documented as such: `services/api/tests/test_known_gaps.py:44-52` skipped it because "no delivery-store persistence layer exists to dedupe a backfill against" | **INTEGRATION_TESTED** | `opt_ingestion_ledger` + `IngestionRunner.backfill`; `tests/p0/ingestion-runner.test.ts` (repeat emits 0, live checkpoint untouched, a real content change still re-emits); same against real Postgres |
|
||
|
||
### What was actually run (not "should pass")
|
||
|
||
- `pnpm run typecheck` — clean.
|
||
- `pnpm run test` — **365 passed, 25 skipped** (was 311/18 before this pass).
|
||
- `pnpm run build` — clean; the four new routes appear in the route table.
|
||
- `pnpm run lint` — 12 errors / 5 warnings, **all pre-existing** (identical
|
||
count on the base commit; advisory in CI). This pass adds none.
|
||
- Real Postgres 16: `tests/p0/ingestion-plane-postgres.realinfra.test.ts`
|
||
with `INGESTION_TEST_DATABASE_URL` — 7 passed.
|
||
- **Real container restart**, run manually against that same database:
|
||
`docker restart` the Postgres container, then re-read through the real
|
||
repositories. Before and after were identical — 2 sources (one `active`
|
||
with its owner, one `pending`), 1 checkpoint (cursor 6, 6 committed),
|
||
6 ledger rows, 1 lineage edge, 4 quarantined records, 1 schema version.
|
||
That is P060's "a restart preserves all sources", measured rather than
|
||
asserted.
|
||
|
||
### A real bug this pass wrote and then caught
|
||
|
||
The first draft of `IngestionRepository` combined the idempotency check and
|
||
its recording into one atomic call, made BEFORE the sink. The crash/resume
|
||
test then delivered **7 of 10 records**: the page in flight when the sink
|
||
died had already been marked delivered, so the resumed run skipped it as a
|
||
duplicate — permanent, silent data loss. The fix is the `peekDeliveries` /
|
||
`commitDeliveries` split, with both the ledger commit and the checkpoint
|
||
commit after the sink resolves. Recorded here because the failure mode is
|
||
the interesting artifact, not the fix.
|
||
|
||
### Honest gaps in the new plane (not hidden)
|
||
|
||
1. **Delivery is AT-LEAST-ONCE, not exactly-once.** Two concurrent runs on
|
||
the same (source, partition) can both peek "new" and both emit.
|
||
`envelope_id` is deterministic so a dedup-capable sink survives it. There
|
||
is no per-(source, partition) run lock. Do not describe this plane as
|
||
exactly-once.
|
||
2. **No CDC *source* exists.** The envelope, the operations and the runner
|
||
handle change events, and `JsonlFileConnector` emits real deletes from an
|
||
`_op` field — but this repo still has no Debezium/WAL/replication-slot
|
||
consumer. P062's contract is met; a CDC connector is still MISSING.
|
||
3. **0pt does not schedule itself.** `opt_source_schedule` is a declaration
|
||
ACT0 would read; there is no cron daemon here.
|
||
4. **The sink is caller-supplied.** The runner stops at the sink; the
|
||
lakehouse write boundary is ST0RE's (P066, another workflow's repo).
|
||
5. **Nothing here is deployed.** See the deployment note below.
|
||
6. **`QualityService`'s own rule/run/issue registry is still in-process
|
||
Maps** (`src/quality/quality-service.ts:47-50`). The new *enforcement*
|
||
path is durable; the older rule registry is not. Unchanged by this pass.
|
||
7. **Python tests still run nowhere.** `grep -rn "pytest" .gitea/workflows
|
||
.github/workflows` finds nothing — `services/api/tests/*` (9 files) has
|
||
never been executed by CI. Flagged, not fixed (it needs a workflow change
|
||
and a Python toolchain decision).
|
||
|
||
### Deployment reality, measured 2026-09-04
|
||
|
||
`https://0pt.app/api/health` answers **200** from **Vercel** with
|
||
`{"db":"not_configured"}`, and `https://0pt.app/api/0pt/sources` answers
|
||
**404** — the deployed build predates the entire `app/api/0pt/*` capability
|
||
layer. `https://api.0pt.app/health` answers **404** (the FastAPI engine is
|
||
not reachable), and `.gitea/workflows/cd.yml` still guards on
|
||
`COOLIFY_APP_ID = TODO-no-coolify-app-provisioned-yet`. So: none of the
|
||
capability layer — neither this pass's work nor P010/P014's — is running in
|
||
production, and P060's durability guarantee cannot be exercised there,
|
||
because production has no database configured and does not serve the routes.
|
||
Verified with `curl`; not inferred.
|
||
|
||
### P065 — closure record (2026-09-07)
|
||
|
||
The removal plan below was executed in full and is verified in CI:
|
||
|
||
1. ✅ Canonical ER exposed as `POST /api/0pt/er/candidates` (public,
|
||
tenant-safed) AND `POST /api/0pt/internal/er/candidates` (service-token,
|
||
fails closed without `X-Internal-Token`).
|
||
2. ✅ Python CI job: `.gitea/workflows/python-engine.yml` runs
|
||
`services/api/tests` as a BLOCKING pytest gate.
|
||
3. ✅ `workers/resolve.py` rewritten as the HTTP adapter — fail-closed to
|
||
UNMERGED records when the bridge is unreachable; no fallback scorer
|
||
remains. Cluster-wide hard-negative constraints prevent transitive
|
||
matches from overriding canonical identity decisions.
|
||
4. ✅ `services/api/tests/test_resolve_determinism.py` asserts the adapter
|
||
contract: canonical match edges merge; review/non-match edges do not;
|
||
hard negatives are respected transitively.
|
||
|
||
Residual honesty: the PYTHON-side tests run in CI, but the full
|
||
adapter→Next.js route chain has not been exercised against a live deployed
|
||
edge in this branch (the route's own fail-closed behavior is unit-proven).
|
||
That keeps P065 at INTEGRATION_TESTED, not LIVE_VERIFIED.
|
||
|
||
---
|
||
|
||
## SLUTPRODUKTIONS-VERIFIERING 2026-09-22 (live-mätt, ej påstått)
|
||
|
||
**Prod: `https://0pt.app` på flottan (server6, Coolify-app `shxd6lepxuxfsjsp0ath3z1g`),
|
||
container-image på exakt merge-SHA `df6ab70` via den signerade release-kedjan
|
||
(cosign-attestation verifierad före redeploy). DNS A → 65.109.19.146,
|
||
NS chris/maxine.ns.cloudflare.com — Vercel är borta.**
|
||
|
||
### Live-matris, mätt med curl (2026-09-22 04:09 UTC)
|
||
|
||
| Yta | Resultat |
|
||
|---|---|
|
||
| Front `/` + 10 nyckelsidor (bestall, katalog, kallor, tjanster, portal, admin, order) | 200 ×11 |
|
||
| `/api/health` | 200 `{ok:true, db:"ok", engine:"ok"}` |
|
||
| `/api/ready` | 200 (fail-closed-grinden: var 503 före DB-provisioneringen) |
|
||
| `/api/0pt/*` (9 rutter) anonymt | **401 ×9** — S1-luckan (2026-08-07: anonym 200) är STÄNGD |
|
||
| `/api/orders`, `/api/admin/metrics` anonymt | 401 |
|
||
| `/api/subscriptions` | 200 `[]` (var 500: migration 014, se nedan) |
|
||
| `POST /api/estimates` | 200 (edge räknar + engine-wire) |
|
||
| `GET /api/catalog`, `/api/sources` | 200 (publika läsvyter, avsiktligt) |
|
||
| `GET /api/vehicles` utan param | 400 (kräver reg-nr — korrekt) |
|
||
| Security headers | HSTS(63072000+preload) · CSP · XFO DENY · nosniff · ingen X-Powered-By |
|
||
|
||
### Denna pass fixat (3 PR, alla mergerade + deployade live)
|
||
|
||
1. **PR #80** — G17 hook-pin re-bump `7725498 → a401880` (re-review: 0 diff under
|
||
`ci/v2/reference-hooks/`). Release chain + gated deploy gröna igen.
|
||
2. **PR #81 (fix för issue #53)**: 7 legacy money-routes (orders, orders/[id],
|
||
subscriptions, payments/deposit, payments/release, webhooks/stripe,
|
||
admin/metrics) mappar nu `SiaxError(DEPENDENCY_UNAVAILABLE, 503, retryable)`
|
||
via `app/api/siax-error-mapping.ts` i stället för att läcka Next opaka 500.
|
||
Stripe-webhooken svarar 503 `received:false reason:store_unavailable` på
|
||
store-outage — aldrig tyst `received:true` för ett betalt event som inte
|
||
processats. 3 nya tester pinar kontraktet.
|
||
3. **PR #86**: `sql/014_subscriptions_created_at.sql` — `lib/subscriptions-store.ts`
|
||
SELECT:ade `created_at` som `001_init.sql` aldrig definierat (42703 mätt live:
|
||
GET /api/subscriptions har ALWAYS varit 500 mot Postgres). Kolonnen ADD:ad
|
||
idempotent LIVE på 0pt-edge-postgres; route svarar nu 200 `[]`.
|
||
4. **PR #87**: cd-gatens not-ready-regex — cosign 3.1.3 säger
|
||
`no matching attestations:` (utan `found`); en transient not-ready misstolkades
|
||
som hårt verify-fel. Fail-closed för riktiga attestfel oförändrad.
|
||
5. **CI-infra reparerad**: repo-secrets `SIAX_CI_TOKEN` + `REGISTRY_TOKEN` var
|
||
döda efter token-svepet (2026-09-22 eng0-introspect-rotation revoade 107+ tokens;
|
||
fällan: 0pt:s repo-secret överrider org-secreten — org-PUT räcker inte). Nya
|
||
siax-ci-tokens (`write:package,read:package` + all) mintade och satta via
|
||
secrets-API (PUT 204, verifierade via lyckad release-kedja).
|
||
|
||
### 0pt-motor (engine, satellite)
|
||
|
||
- 6 containers Up på server6 (`motor-provisional`), core `/health` ok+pg+redis,
|
||
delivery `/version` = fb67870, core revision = 6cfd433 — båda IN main.
|
||
- CI grön på main (runs 55985/55987/56004) — healer-issue #38 (run 40562,
|
||
2026-09-20) stängd som transient runner-flake (apt-GPG under last).
|
||
- Bara `main` kvar i 0pt och 0pt-motor (8 + 6 stale grenar raderade — alla
|
||
bevisade redan mergerade via `git merge-base --is-ancestor`).
|
||
- motor/-executor-koden (signals/NER/normalization, 3507 rader nya sedan 6cfd433)
|
||
konsumeras av `Dockerfile.motor`-imaget som ännu inte har ett driftsatt runtime
|
||
i stacken (core/ingest/resolve/delivery importerar ej motor/ — verifierat
|
||
import-graf). Byggs enligt `scripts/build-images.sh` + `verify-image.sh`-gaten
|
||
när executor-ytan aktiveras — dokumenterat i `docs/runbook/deploy.md`.
|
||
|
||
### Kvarstår (ärligt, ej gömt)
|
||
|
||
1. **Stripe-creds** (Simon): live-keys → edge-envs `STRIPE_SECRET_KEY`/`STRIPE_WEBHOOK_SECRET`.
|
||
Innan dess förblir payments 501 och issue #67:s staging-triage kan ej köras.
|
||
2. **queue: not_configured** — ingen Redis i edge-stacken (ärligt rapporterat).
|
||
3. **`0pt.siax.io`/`motor.siax.io`**: medvetet ej återupprättade (0pt.app + lokala
|
||
127.0.0.1-portar är kanoniska ytor; issues #70/#35 stängda/avgjorda därefter).
|
||
4. **motor.siax.io**: motor:s publika yta kräver Simon-beslut (traefik-labels + DNS).
|