26 KiB
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. OnlyPRODUCTION_READYmay 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(jobsquality+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)
- Persistent stores REMAINING: quality runs/rules and feature views are
still per-process in-memory (
resolveStoreModeguarantees 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. - 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.
- 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:falseso it never re-enqueues its own delivery evidence.
- real-Postgres tests; dispatcher uses explicit
- CLOSED for datasets/versions/search/ER:
app/api/0pt/datasets*,app/api/0pt/search/definitions+ tenant-safed query route, andapp/api/0pt/er/{candidates,batch}(+ internal ER route) are live; clients cannot raiserights_tagvia request body (fail-closed tointernal). Quality routes exist (bridge-run/issues/rules/runs). - 0pt-motor executors for the delegated jobs
(
0pt.quality.ge_run,0pt.features.*,0pt.er.batch_resolution). - 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.tswithINGESTION_TEST_DATABASE_URL— 7 passed. - Real container restart, run manually against that same database:
docker restartthe Postgres container, then re-read through the real repositories. Before and after were identical — 2 sources (oneactivewith its owner, onepending), 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)
- Delivery is AT-LEAST-ONCE, not exactly-once. Two concurrent runs on
the same (source, partition) can both peek "new" and both emit.
envelope_idis deterministic so a dedup-capable sink survives it. There is no per-(source, partition) run lock. Do not describe this plane as exactly-once. - No CDC source exists. The envelope, the operations and the runner
handle change events, and
JsonlFileConnectoremits real deletes from an_opfield — but this repo still has no Debezium/WAL/replication-slot consumer. P062's contract is met; a CDC connector is still MISSING. - 0pt does not schedule itself.
opt_source_scheduleis a declaration ACT0 would read; there is no cron daemon here. - The sink is caller-supplied. The runner stops at the sink; the lakehouse write boundary is ST0RE's (P066, another workflow's repo).
- Nothing here is deployed. See the deployment note below.
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.- Python tests still run nowhere.
grep -rn "pytest" .gitea/workflows .github/workflowsfinds 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:
- ✅ Canonical ER exposed as
POST /api/0pt/er/candidates(public, tenant-safed) ANDPOST /api/0pt/internal/er/candidates(service-token, fails closed withoutX-Internal-Token). - ✅ Python CI job:
.gitea/workflows/python-engine.ymlrunsservices/api/testsas a BLOCKING pytest gate. - ✅
workers/resolve.pyrewritten 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. - ✅
services/api/tests/test_resolve_determinism.pyasserts 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)
- PR #80 — G17 hook-pin re-bump
7725498 → a401880(re-review: 0 diff underci/v2/reference-hooks/). Release chain + gated deploy gröna igen. - 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)viaapp/api/siax-error-mapping.tsi stället för att läcka Next opaka 500. Stripe-webhooken svarar 503received:false reason:store_unavailablepå store-outage — aldrig tystreceived:trueför ett betalt event som inte processats. 3 nya tester pinar kontraktet. - PR #86:
sql/014_subscriptions_created_at.sql—lib/subscriptions-store.tsSELECT:adecreated_atsom001_init.sqlaldrig 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[]. - PR #87: cd-gatens not-ready-regex — cosign 3.1.3 säger
no matching attestations:(utanfound); en transient not-ready misstolkades som hårt verify-fel. Fail-closed för riktiga attestfel oförändrad. - CI-infra reparerad: repo-secrets
SIAX_CI_TOKEN+REGISTRY_TOKENvar 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/healthok+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
mainkvar i 0pt och 0pt-motor (8 + 6 stale grenar raderade — alla bevisade redan mergerade viagit 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 enligtscripts/build-images.sh+verify-image.sh-gaten när executor-ytan aktiveras — dokumenterat idocs/runbook/deploy.md.
Kvarstår (ärligt, ej gömt)
- 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. - queue: not_configured — ingen Redis i edge-stacken (ärligt rapporterat).
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).- motor.siax.io: motor:s publika yta kräver Simon-beslut (traefik-labels + DNS).