Commit Graph
132 Commits
Author SHA1 Message Date
Claude Opus 5 84bb9faa4f feat(analytics): BI-P002..BI-P012 analytics core — domain model, tiers, contracts, Arrow, ClickHouse engine, isolation, governance
CI (SIAX Cloud) / security (push) Successful in 41s
Security Scan (SIAX Cloud) / security (push) Successful in 40s
CI (SIAX Cloud) / integration (push) Successful in 52s
CI (SIAX Cloud) / quality (push) Successful in 1m5s
CI (SIAX Cloud) / security (pull_request) Successful in 31s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 29s
CI (SIAX Cloud) / integration (pull_request) Successful in 45s
CI (SIAX Cloud) / quality (pull_request) Successful in 53s
Implements the eight BI program prompts that make 0pt the canonical SIAX
analytics capability. Every file is NEW: not one existing file is modified,
and src/analytics/clickhouse-analytics.ts is byte-identical to main.

BI-P002 — the nineteen canonical entities, verbatim, with tenant_id +
project_id on every tenant-owned record. sql/008 gives each one a table.
The four version entities BI-P002 names as immutable are enforced by BEFORE
UPDATE/DELETE triggers, not by a TypeScript `readonly` — proven by direct SQL
against a live Postgres.

BI-P003 — RAW/NORMALIZED/CURATED/SERVING with the read rule enforced:
assertReadableByBiSurface refuses a RAW dataset to a dashboard unless a
recorded exception exists. All eight required declarations are NOT NULL.

BI-P004 — DatasetContract and a fail-closed compatibility gate. Fifteen
breaking-change classes are each tested twice: refused under a minor bump,
accepted under a major one.

BI-P005 — Arrow IPC alongside JSON, with a hand-written FlatBuffers writer so
no npm dependency (or CVE surface) is added. Conformance comes from three
independent implementations, not from self-agreement: pyarrow 25.0.1 and
DuckDB 1.5.5 read identical values from both ClickHouse's Arrow and ours, and
ClickHouse's own Arrow C++ ingests our 20,000-row batch with exact aggregates.

BI-P009 — SiaxAnalyticsEngine with all eight capabilities. The existing
ClickHouseAnalytics is COMPOSED, never replaced. executeQuery (analyst SQL) is
declared and deliberately refused with CAPABILITY_UNAVAILABLE until BI-P017 and
BI-P033 land, rather than opening the raw-SQL hole BI-P011 enumerates.

BI-P010 — four purpose-built tables, not one giant one, and the difference is
measured against the counterfactual: 48.8ms/40,960 rows vs 174.4ms/5,400,000
rows for the same question; 5/660 granules vs 660/1149.

BI-P011 — layered isolation, each layer proven with the layer above removed.
Without the forced predicate the same statement returns 50,050 (both tenants);
with it, t_alpha gets 50. Without a row policy an unrestricted user sees 2
tenants; the restricted user running the IDENTICAL statement sees 1.

BI-P012 — every named limit, fired individually and identified by ClickHouse
error code, plus the half usually skipped: an unrelated tenant is timed while
a real CPU bomb is in flight and must still return the CORRECT answer.

Three defects found by writing tests that can fail:
  * `CHECK (array_length(purposes,1) >= 1)` can NEVER fail — array_length is
    NULL for '{}' and a NULL CHECK passes. Fixed with coalesce(); the test
    that caught it is pinned.
  * EXPLAIN ESTIMATE run under the caller's own max_rows_to_read fails with
    code 158 exactly when the estimate would be over budget. Planner calls now
    use a narrower envelope.
  * result_overflow_mode=break returns HTTP 200 with 65,409 of 100,000 rows
    and no indication it is short. Every SELECT ships `throw`.

Verified rather than assumed: server7's ClickHouse holds `opt_scraped` (51
tables, 407,793,471 rows, `persons`/`cz_owners` included) — the b0ts plane this
module is prohibited from touching — has no `opt_analytics` database, zero
tenant_id columns and zero row policies. Nothing there was modified; every
proof ran against disposable containers.

Evidence: evidence/bi-p002-p012/{test-transcript.txt,bi-p010-benchmark.json,
bi-p005-arrow-roundtrip.json,server7-clickhouse-probe.md}
Docs: docs/analytics/BI_ANALYTICS_CORE.md

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 23:01:27 +02:00
SIAX Technology (sax3l)andClaude Opus 5 8d0a288668 Merge pull request 'feat(compliance): scaffold Golden Standard artifacts (CI-14, DX-02, DX-03)' (#21) from feat/golden-standard-scaffold into main
Deploy to Coolify / deploy (push) Successful in 5s
CI (SIAX Cloud) / security (push) Successful in 22s
CI (SIAX Cloud) / integration (push) Successful in 39s
CI (SIAX Cloud) / quality (push) Successful in 50s
Security Scan (SIAX Cloud) / security (push) Successful in 24s
Reopened after a false batch-closure on 2026-09-04. The stated reason -- "added-files
present: all; modified files: none" -- was untrue on all four counts: .gitea/CODEOWNERS and
docs/compliance/SCAFFOLD-TODO.md were absent from main, and the other two files differed.
The PR also carried a real merge conflict (pull_request.status=0), which by itself disproves
"already on main".

Resolved against what main says today (08c88f39), not against the scaffold's intent:
 - .devcontainer/devcontainer.json  kept MAIN (richer: corepack pin, siax-doctor postStart,
   forwardPorts, AUTH_ENFORCE)
 - compose.dev.yaml                 kept MAIN (real pgvector service with init mount and
   healthcheck; the scaffold's `services: {}` would have deleted a working dev stack)
 - docs/compliance/SCAFFOLD-TODO.md DROPPED as stale: every substantive claim is now false
   on main (siax.repo.json validates, domains are objects, consumedBy present, DOC-07
   restore drill executed 2026-09-03)
 - .gitea/CODEOWNERS                KEPT -- genuinely absent from main, wanted by CI-14

Net diff against main is one added file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 09:44:56 +00:00
Claude Opus 5 e433e7f991 Merge main into the Golden Standard scaffold branch — keep only CODEOWNERS
CI (SIAX Cloud) / integration (push) Successful in 29s
CI (SIAX Cloud) / security (push) Successful in 23s
CI (SIAX Cloud) / quality (push) Successful in 53s
CI (SIAX Cloud) / integration (pull_request) Successful in 32s
CI (SIAX Cloud) / security (pull_request) Successful in 24s
CI (SIAX Cloud) / quality (pull_request) Successful in 53s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 21s
Security Scan (SIAX Cloud) / security (push) Successful in 21s
PR #21 was batch-closed 2026-09-04 as "verified against main (added-files
present: all)". That check cannot have run: `.gitea/CODEOWNERS` and
`docs/compliance/SCAFFOLD-TODO.md` were absent from main, and the other two
files differed. Reopened; this merge resolves it against what main says today.

Resolution, file by file, measured against origin/main (08c88f39):

- .devcontainer/devcontainer.json — KEEP MAIN. Main's version is strictly
  richer (corepack pin, siax-doctor postStart, forwardPorts, AUTH_ENFORCE).
  The scaffold's three-line version would be a regression.
- compose.dev.yaml — KEEP MAIN. Main declares a real pgvector service with
  an init mount, healthcheck and a documented P014 verification. The
  scaffold's `services: {}` would delete a working local dev stack.
- docs/compliance/SCAFFOLD-TODO.md — DROPPED. Written 2026-08-11 and now
  false on every substantive claim: it says siax.repo.json fails schema
  validation (main's has repo/lifecycle/gitHost/consumedBy/children/
  operationalState and object-form domains), that domains are strings (they
  are objects), that consumedBy is missing (present), and that DOC-07 has no
  proven restore (docs/runbook/backup-restore.md line 23 records an executed
  drill dated 2026-09-03). Merging it would add stale false statements.
- .gitea/CODEOWNERS — KEPT. Genuinely absent from main, still wanted by
  CI-14, and correct as written.

Net diff against main is one added file.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 11:35:32 +02:00
adminandClaude Opus 5 08c88f39c8 Merge pull request 'docs: the Coolify deploy hook is LIVE — six docs still call it a placeholder' (#33) from docs/coolify-deploy-hook-is-live-opus5 into main
Deploy to Coolify / deploy (push) Successful in 7s
CI (SIAX Cloud) / security (push) Successful in 29s
CI (SIAX Cloud) / integration (push) Successful in 39s
Security Scan (SIAX Cloud) / security (push) Successful in 25s
CI (SIAX Cloud) / quality (push) Successful in 1m5s
Six docs on main claimed no Coolify app was provisioned and that cd.yml's guard fails
on purpose. Measured otherwise: repo secret COOLIFY_TOKEN exists (2026-08-31T11:34:34Z),
repo variable COOLIFY_APP_ID holds a real 24-char UUID, both guards pass, and the push to
main at 1ff34410 ran Deploy to Coolify / deploy (run 11695, job 26295) to success with
"coolify deploy HTTP 200". Every merge into main ships for real.

Probed the site rather than leaving it hedged: 0pt.app answers from Vercel with HTTP 402
DEPLOYMENT_DISABLED on / and /api/health. Both facts now stated together -- the hook fires,
and the public domain is dark with DNS never cut over. Still unestablished and marked as
such: whether the Coolify app builds and starts (an accepted deploy request is not a
healthy container), which is why GOLDEN-STANDARD D4 goes to WARN, not PASS.

Docs only. Falsifiable check over all six files: FAIL on main (12 findings), PASS here,
FAIL again under each of two independent mutations. The check first passed vacuously on
docs/02-architecture.md because PR #32 had already put "CORRECTED 2026-09-06" there; the
marker was made specific so it can actually fail. siax-doctor 39/40, same as main.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 08:05:08 +00:00
Claude Opus 5 853f09320c docs: probed 0pt.app — Vercel answers with HTTP 402 DEPLOYMENT_DISABLED
CI (SIAX Cloud) / security (push) Successful in 31s
CI (SIAX Cloud) / integration (push) Successful in 47s
CI (SIAX Cloud) / quality (push) Successful in 1m6s
Security Scan (SIAX Cloud) / security (push) Successful in 29s
CI (SIAX Cloud) / security (pull_request) Successful in 26s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 26s
CI (SIAX Cloud) / integration (pull_request) Successful in 41s
CI (SIAX Cloud) / quality (pull_request) Successful in 56s
The previous commit said "nobody has probed the running site". I then probed it,
so the docs should not keep hedging.

  curl -sI https://0pt.app/
    HTTP/2 402
    server: Vercel
    x-vercel-error: DEPLOYMENT_DISABLED
    strict-transport-security: max-age=63072000
  https://0pt.app/api/health -> HTTP 402, body "Payment required / DEPLOYMENT_DISABLED"

Two facts hold simultaneously and the docs now state both: the Coolify deploy hook
fires for real on every push to main, AND the public product domain is dark behind a
disabled Vercel deployment with DNS never cut over. Neither cancels the other.

Still not established, and still marked as such: whether the Coolify app builds and
starts. A deploy endpoint returning 200 means the request was accepted, not that a
container came up healthy.

Side note worth recording for PR #19: the HSTS header on that 402 response is
Vercel's platform default, which is exactly the disappearing-on-cutover risk
next.config.mjs in PR #19 was written to remove.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 10:01:17 +02:00
Claude Opus 5 d7a1c4d5e1 docs: the Coolify deploy hook is LIVE — six docs still say it is a placeholder
CI (SIAX Cloud) / security (push) Successful in 31s
CI (SIAX Cloud) / integration (push) Successful in 42s
Security Scan (SIAX Cloud) / security (push) Successful in 44s
CI (SIAX Cloud) / quality (push) Successful in 1m6s
CI (SIAX Cloud) / security (pull_request) Successful in 30s
CI (SIAX Cloud) / integration (pull_request) Successful in 37s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 26s
CI (SIAX Cloud) / quality (pull_request) Successful in 1m2s
Six documents on main assert that no Coolify app has been provisioned for 0pt and
that cd.yml's COOLIFY_APP_ID is a literal placeholder whose guard fails the job on
purpose. That is no longer true, and the gap is not cosmetic: it means a merge to
main silently ships to production while the repo's own docs promise it cannot.

Measured, not assumed:

  * repo Actions secret  COOLIFY_TOKEN   exists, created 2026-08-31T11:34:34Z
    (GET /api/v1/repos/sax3l/0pt/actions/secrets)
  * repo Actions variable COOLIFY_APP_ID exists with a real 24-character value,
    not the "TODO-no-coolify-app-provisioned-yet" literal
    (GET /api/v1/repos/sax3l/0pt/actions/variables)
  * both guards in .gitea/workflows/cd.yml therefore pass; on the push to main at
    1ff34410 (2026-09-06) the job "Deploy to Coolify / deploy" (run 11695, job
    26295) finished SUCCESS with "coolify deploy HTTP 200" in its log

Deliberately NOT claimed: that the Coolify app builds, starts or serves, or that
0pt.app DNS points at it rather than Vercel. Nobody probed the running site, and
every corrected passage says so explicitly rather than replacing one unverified
claim with another.

Corrected: README.md "Deploy", docs/02-architecture.md hosting callout,
docs/architecture/decisions/0001 (consequence annotated, decision untouched --
an ADR is a historical record), docs/runbook/incident.md (the symptom row is now
inverted: the risk is an unintended deploy, not a red job),
docs/compliance/GOLDEN-STANDARD-REPORT.md D4 (❌ -> ⚠️, not ✅, because "webhook
accepted" is not "app serves"), docs/compliance/INVENTORY.md CI row.

Falsifiable check over all six files (stale claim present without a correction
marker = red):

  origin/main                                  -> FAIL (12 findings)
  this branch                                  -> PASS
  mutation: drop only the README bullet        -> FAIL
  mutation: drop only the runbook correction   -> FAIL

The check initially passed vacuously on docs/02-architecture.md because PR #32 had
already put the string "CORRECTED 2026-09-06" in that file for an unrelated reason;
the marker was made specific so the check could actually fail there too.

Docs only. No workflow files, no .gitignore, no source.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 09:56:53 +02:00
adminandClaude Opus 5 1ff344107f Merge pull request 'docs: withdraw the "Superset / OpenMetadata are OUT" rows — both are canonical' (#32) from docs/bi-canonical-stack-correction-opus5 into main
Deploy to Coolify / deploy (push) Successful in 4s
CI (SIAX Cloud) / quality (push) Successful in 1m9s
CI (SIAX Cloud) / security (push) Successful in 28s
CI (SIAX Cloud) / integration (push) Successful in 46s
Security Scan (SIAX Cloud) / security (push) Successful in 37s
docs/02-architecture.md's "Stack decisions -- OUT (do not add)" table rejected Apache
Superset and DataHub/OpenMetadata, and its IN table named Metabase as the BI choice.
All three contradict 0pt's role as canonical Analytics/Data/Semantic owner (no BI0 repo):
Superset is the canonical BI engine, OpenMetadata the canonical catalog ahead of DataHub,
and Metabase/DataHub/Lightdash/Rill/Grafana are optional App Catalog apps only.

The repo already shipped both "rejected" tools -- src/metadata/openmetadata-adapter.ts
(STATUS.md: IMPLEMENTED) and a superset service in
services/infra/docker-compose.data-stack.yml, inventoried in docs/compliance/OSS-INVENTORY.md
-- so the old rows were self-contradicting, not merely stale.

Docs only. Falsifiable check: FAIL on main, PASS on the branch, FAIL again under each of
two independent mutations. siax-doctor 39/40 on both branch and main (the one failure,
P1-15 CODEOWNERS, is pre-existing and is what PR #19 supplies). All eight CI contexts green
on 4bc79c25, including the real integration job against live OpenSearch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 07:50:53 +00:00
Claude Opus 5 4bc79c25d3 docs: withdraw the "Superset / OpenMetadata are OUT" rows — both are canonical
CI (SIAX Cloud) / integration (push) Successful in 36s
CI (SIAX Cloud) / quality (push) Successful in 1m3s
CI (SIAX Cloud) / security (push) Successful in 23s
Security Scan (SIAX Cloud) / security (push) Successful in 31s
CI (SIAX Cloud) / integration (pull_request) Successful in 32s
CI (SIAX Cloud) / security (pull_request) Successful in 29s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 27s
CI (SIAX Cloud) / quality (pull_request) Successful in 55s
`docs/02-architecture.md` was written when 0pt was planned as a standalone SaaS
product. Its "Stack decisions — OUT (do not add)" table rejects Apache Superset
("Metabase already covers BI") and DataHub/OpenMetadata ("enterprise-heavy"),
and the "IN" table names Metabase as the BI choice.

Under the SIAX Cloud analytics decision, 0pt is the canonical
Analytics/Data/Semantic owner — there is no BI0/Analytics0 repo and no separate
Superset platform. Superset is the canonical BI engine (Apache-2.0, official
embed SDK + guest tokens) and OpenMetadata the canonical catalog, default ahead
of DataHub. Metabase, DataHub, Lightdash, Rill and Grafana are optional App
Catalog apps, never the platform default.

This repository had already shipped both of the "rejected" tools, which is what
makes the old rows self-contradicting rather than merely stale:

  * src/metadata/openmetadata-adapter.ts + tests/contracts/metadata-features.contract.test.ts
    (STATUS.md classifies the OpenMetadata projection IMPLEMENTED)
  * services/infra/docker-compose.data-stack.yml defines a `superset` service
    (apache/superset:latest), and docs/compliance/OSS-INVENTORY.md line 74
    already inventories `superset | Apache-2.0 | services/infra/data-stack`

Falsifiable check used (asserts the OUT table no longer rejects either tool and
that the IN table's BI row names Superset):

  origin/main            -> FAIL (4 findings)
  this branch            -> PASS
  mutation: BI row back to Metabase        -> FAIL
  mutation: OUT rows un-struck             -> FAIL

Docs only. No workflow files, no .gitignore, no source. `node scripts/siax-doctor.mjs`
gives 39/40 on this branch and 39/40 on main — the one failure (P1-15 CODEOWNERS
missing) is pre-existing and is what PR #19 supplies.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 09:46:35 +02:00
SIAX Technology (sax3l)andClaude Opus 5 364b7643fb Merge pull request 'fix(deps): update web-stack' (#26) from renovate/web-stack into main
Renovate web-stack bump: next 16.0.10->16.3.3, react/react-dom 19.2.0->19.2.8,
27 @radix-ui/* primitives, plus lockfile (943 package entries before and after;
only 4 new transitive names: @img/sharp-freebsd-wasm32, @img/sharp-webcontainers-wasm32,
@radix-ui/react-use-effect-event, @radix-ui/react-use-is-hydrated).

Diff read by hand: package.json changes are version strings only (hunks @@ -22,33
and @@ -58,12); scripts/engines/overrides untouched. No source files changed.

Both required contexts green on head 45a59ca3 (CI (SIAX Cloud) / quality (push)
and / security (push), 2026-09-06), and the blocking steps inside quality are
real: tsc typecheck, vitest, next build. The non-gating integration job (live
OpenSearch + ClickHouse) is green too.

Side effect: removes nanoid@3.3.15 and postcss@8.4.31 from the tree and moves
next to 16.3.3 / sharp to 0.35.4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-06 07:36:30 +00:00
Renovate 45a59ca3aa fix(deps): update web-stack
renovate/stability-days Updates have met minimum release age requirement
CI (SIAX Cloud) / security (push) Successful in 1m11s
Security Scan (SIAX Cloud) / security (push) Successful in 1m12s
CI (SIAX Cloud) / quality (push) Successful in 1m18s
CI (SIAX Cloud) / security (pull_request) Successful in 53s
CI (SIAX Cloud) / integration (push) Successful in 2m15s
CI (SIAX Cloud) / integration (pull_request) Successful in 1m2s
CI (SIAX Cloud) / quality (pull_request) Successful in 1m4s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 43s
2026-09-06 03:01:40 +00:00
admin 83209b0782 Merge pull request 'chore(deps): update dependency autoprefixer to v10.5.4' (#13) from renovate/autoprefixer-10.x-lockfile into main
Deploy to Coolify / deploy (push) Successful in 2s
CI (SIAX Cloud) / quality (push) Successful in 51s
CI (SIAX Cloud) / integration (push) Successful in 28s
CI (SIAX Cloud) / security (push) Successful in 22s
Security Scan (SIAX Cloud) / security (push) Successful in 22s
2026-09-05 12:53:44 +00:00
Renovate ae5841dfe9 chore(deps): update dependency autoprefixer to v10.5.4
renovate/stability-days Updates have met minimum release age requirement
CI (SIAX Cloud) / security (push) Successful in 58s
Security Scan (SIAX Cloud) / security (push) Successful in 1m0s
CI (SIAX Cloud) / quality (push) Successful in 1m3s
CI (SIAX Cloud) / security (pull_request) Successful in 36s
CI (SIAX Cloud) / integration (push) Successful in 1m39s
CI (SIAX Cloud) / integration (pull_request) Successful in 39s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 36s
CI (SIAX Cloud) / quality (pull_request) Successful in 1m16s
2026-09-05 03:01:43 +00:00
admin 4dbdff0636 Merge pull request 'P060-P068: durable ingestion plane — source classification gate, connector contract, common envelope, schema evolution, quality enforcement, queryable lineage, idempotent backfill' (#31) from feat/p060-p068-ingestion-plane into main
CI (SIAX Cloud) / integration (push) Successful in 32s
CI (SIAX Cloud) / quality (push) Successful in 47s
CI (SIAX Cloud) / security (push) Successful in 25s
Deploy to Coolify / deploy (push) Failing after 1m12s
Security Scan (SIAX Cloud) / security (push) Successful in 20s
2026-09-04 16:11:20 +00:00
admin 1097231064 Merge pull request 'chore(estate): add first siax.repo.v3.json manifest (P003 v3 adoption, REPO-16 NA→PASS)' (#30) from chore/siax-repo-v3-manifest into main
Security Scan (SIAX Cloud) / security (push) Successful in 22s
CI (SIAX Cloud) / quality (push) Successful in 54s
CI (SIAX Cloud) / security (push) Successful in 27s
CI (SIAX Cloud) / integration (push) Successful in 34s
Deploy to Coolify / deploy (push) Failing after 1m6s
2026-09-04 15:56:33 +00:00
Simon AxelssonandClaude Opus 5 9267576b7c feat(data-os): P060-P068 durable ingestion plane — source classification gate, connector contract, common envelope, schema evolution, quality enforcement, queryable lineage, idempotent backfill
CI (SIAX Cloud) / integration (push) Successful in 42s
CI (SIAX Cloud) / quality (push) Successful in 1m17s
CI (SIAX Cloud) / security (push) Successful in 46s
Security Scan (SIAX Cloud) / security (push) Successful in 31s
CI (SIAX Cloud) / integration (pull_request) Successful in 36s
CI (SIAX Cloud) / quality (pull_request) Successful in 1m4s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 27s
CI (SIAX Cloud) / security (pull_request) Successful in 24s
BEFORE_STATE (verified, with evidence):

* P060 PARTIAL/BROKEN. The registry persisted rights/provenance/health/
  freshness to Postgres, but carried no authorization, no schedule, no
  checkpoint, no schema and no owner distinct from created_by — and the
  activation DoD was inverted: postgres-source-repository.ts wrote
  `${input.status ?? "active"}`, so a source with no rights, no provenance
  and no authorization was ACTIVE the instant it was registered. No
  activation operation existed at all.
* P061 MISSING. services/api/sources/connectors.py had per-source fetch_*()
  functions only — no lifecycle, no cursor, no resume, no health, no
  conformance suite.
* P062 MISSING, already documented as such in
  services/api/tests/test_known_gaps.py:10-19 (no CDC pipeline anywhere;
  workers/pipeline.py has no persistence at all).
* P063 MISSING. schema_version existed as a free string; no comparison,
  no policy, no versioned source schema.
* P064 PARTIAL. Rules/runs/issues/scores existed, but a failing rule only
  opened an issue and the data flowed on. No quarantine anywhere.
* P065 DUPLICATE (confirmed). Two ER engines: src/er/entity-resolution-
  service.ts (canonical) and services/api/workers/resolve.py (simplified,
  still called by pipeline.py:110).
* P067 PARTIAL. Lineage was emitted to AUD0 but nothing here could ANSWER a
  lineage question — no store, no query, no route.
* P068 MISSING, documented in test_known_gaps.py:44-52 ("no delivery-store
  persistence layer exists to dedupe a backfill against").

BUILT (only what was PARTIAL/BROKEN/MISSING):

* P060 sql/007_ingestion_plane.sql adds authorization/schedule/schemas/
  checkpoints/ledger/quarantine/lineage tables, owner_id, and flips the
  opt_sources status DEFAULT to 'pending' so even a raw psql INSERT cannot
  produce an unclassified-but-active source. SourceRegistryService gains
  classifySource/activateSource/deactivateSource + authorization/schedule
  accessors; registration NEVER activates (asking for status:"active" goes
  through the gate, not around it); a service identity cannot authorize a
  source. Routes: activate (GET classification / POST activate),
  authorization, schedule.
* P061 src/connectors/connector.ts — all nine operations on one interface.
  src/connectors/conformance.ts — a runnable suite (15 checks, no "skip"
  verdict). HttpJsonConnector (real HTTP, opaque cursor) and
  JsonlFileConnector (real file, line offsets, CDC deletes) both pass it.
  The suite caught a real defect while being written: an API that drops
  next_cursor at the end left the connector unable to resume, which is why
  HttpJsonConnectorConfig has cursor_field.
* P062 src/types/ingestion.ts + src/ingestion/{envelope,ingestion-runner}.ts.
  One envelope for batch/stream/cdc; durable per-(source,partition)
  checkpoints; resume proven by killing a run inside the sink.
* P063 src/schema/{record-schema,compatibility,schema-registry}.ts. Two
  enforcement points, both upstream of any consumer write: a discovery gate
  before the first read, and per-record conformance before the page reaches
  the sink. A producer cannot widen its own policy retroactively.
* P064 src/quality/quality-policy.ts composes the EXISTING ExpectationEngine
  (not a second engine) and adds the missing consequence: block /
  quarantine / warn, with quarantine durable and recoverable. No policy is
  reported as "none_declared", never as a pass; an unexecutable expectation
  counts as a violation, never a silent pass.
* P067 src/lineage/{lineage-edge,lineage-store}.ts + GET /api/0pt/lineage.
  AUD0 stays the system of record; this is 0pt's own queryable projection.
* P068 opt_ingestion_ledger + IngestionRunner.backfill: bounded, idempotent
  on repeat, leaves the live checkpoint alone, still re-emits real changes.

A BUG THIS PASS WROTE AND CAUGHT: the first IngestionRepository draft
combined the idempotency check and its recording into one atomic call
BEFORE the sink. The crash/resume test then delivered 7 of 10 records — the
page in flight when the sink died was already marked delivered, so the
resumed run skipped it as a duplicate. Permanent, silent data loss. Fixed by
splitting peekDeliveries/commitDeliveries and committing both the ledger and
the checkpoint only after the sink resolves.

NOT DONE, stated rather than deferred quietly:

* P065 is NOT met. resolve.py is still a second simplified production
  engine. Closing it means rewriting it as an adapter over the canonical
  service, which cannot be verified from this repo today: services/api is
  not built by this repo's Dockerfile, api.0pt.app answers 404, and NO CI
  workflow runs its pytest suite. The duplication is now stated at both
  sites in code and the removal plan is in STATUS.md. The new ingestion
  plane performs no ER, so it adds no third engine.
* P066 (Iceberg) untouched — ST0RE is owned by another workflow. Contract
  read only.
* Delivery is AT-LEAST-ONCE, not exactly-once (no per-partition run lock).
* No CDC *source* exists; the contract is met, a CDC connector is not built.
* 0pt does not schedule itself — the schedule row is a declaration ACT0
  would read.

VERIFIED: pnpm typecheck clean; pnpm test 365 passed / 25 skipped (was
311/18); pnpm build clean with all four new routes in the route table; lint
unchanged at 12 pre-existing errors. Real Postgres 16
(tests/p0/ingestion-plane-postgres.realinfra.test.ts, 7 passed) plus a real
`docker restart` of that container with an identical read-back through the
production code path — that is P060's "a restart preserves all sources",
measured.

DEPLOYMENT REALITY (curl, 2026-09-04): 0pt.app/api/health returns 200 from
Vercel with db:not_configured; 0pt.app/api/0pt/sources returns 404;
api.0pt.app/health returns 404; cd.yml still guards on a placeholder Coolify
app id. None of the capability layer runs in production. Nothing here is
LIVE_VERIFIED and STATUS.md says so.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 17:03:14 +02:00
Simon AxelssonandClaude Fable 5.1 cbf0e1a0bf chore(estate): add first siax.repo.v3.json manifest (P003 v3 adoption)
CI (SIAX Cloud) / quality (push) Successful in 44s
CI (SIAX Cloud) / integration (push) Successful in 26s
CI (SIAX Cloud) / integration (pull_request) Successful in 27s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 17s
CI (SIAX Cloud) / security (push) Successful in 20s
Security Scan (SIAX Cloud) / security (push) Successful in 17s
CI (SIAX Cloud) / quality (pull_request) Successful in 43s
CI (SIAX Cloud) / security (pull_request) Successful in 19s
First siax.repo.v3.json in the SIAX platform estate (P049 certification
found v3 adoption at 0/40, which structurally blocked 8 of the 11 required
siax-doctor commands with score 0 / *-NOMANIFEST).

Additive only: siax.repo.json (v2) is left untouched per CONTRIBUTING.md.
No other file changed.

Every field is filled from a real source (siax.repo.json v2, package.json,
LICENSE, siax.config.json, docs/runbook/*, docs/slo.md, PRODUCTION_EVIDENCE.json,
siax-standard SIAX_ESTATE.yaml + SIAX_TAXONOMY.yaml, cl0ud
packages/capability-registry/src/registry.ts, and a live probe of 0pt.app on
2026-09-04). Where the truth is unknown or unproven the honest schema option
is used, never a value that merely looks complete:

- productionEvidence.verified=false: no SHA->CI->artifact->SBOM->signature->
  deployment->running-digest chain exists (PRODUCTION_EVIDENCE.json is a CI
  verification report, not that chain).
- identity.workloadIdentity=false: outbound platform calls use an optional
  static ST0RE_SERVICE_TOKEN env bearer (src/clients/st0re-client.ts); cl0ud
  service-auth.ts registers no principal for 0pt.
- consumedBy=[]: SIAX_ESTATE.yaml row says consumers UNKNOWN-not-verified;
  the 4 reverse-lookup candidates are labelled "inferred" there.
- reliability.backupFrequency=none / provenRestore=false: production has no
  database (live /api/health db=not_configured); the P014 drill ran against
  throwaway containers, not a production backup.
- licenses.approved=false: no siax.license-assessment record exists.
- operationalState=degraded: live 0pt.app answers liveness 200 but
  db=not_configured and /api/ready is 404 (deployed build predates main).
- node=null / deployment.node=null: live on Vercel, not a fleet node.
- observability.metrics=false / otel=false: STATUS.md "no metrics/traces
  emitted"; /api/admin/metrics is business aggregates, not observability.
- capabilities: exactly the 19 ids cl0ud's registry lists with owner '0pt'
  (5 prospekt.* + 14 0pt.*). NOTE: the repo contains zero "prospekt" code
  and ships no CLI/MCP surface despite the registry claiming those surfaces
  for prospekt.* -- flagged in the PR, not silently dropped.
- surfaces=[api, ui]: only what actually ships (Next.js route handlers +
  FastAPI, Next.js pages). No bin, no MCP tools file, no SDK package
  (packages/schemas is JSON Schema files consumed by path), job execution
  is delegated to N0D per the registry.

siax-doctor (siax-standard main, @siax/schemas):
  repo         REPO-16  NA  -> PASS (measuredScore 85 -> 85; REPO-16 is NA-safe)
  capabilities   0 / CAP-NOMANIFEST -> 100 (CAP-DUP-OWNER PASS, 19 ids)
  dependencies   0 / DEP-NOMANIFEST -> 100 (DEP-CYCLE/DEP-REVERSE/DEP-ASYM PASS)
  surfaces       0 / SURF-NODATA    ->   0 (needs siax/capabilities/*.json records)
  engines        0 / ENG-NOMANIFEST ->   0 (ENG-DIRECT-COUPLING NA for core-platform; ENG-REGISTRY UNVERIFIED)
  licenses       0 / LIC-NOMANIFEST ->   0 (LIC-UNASSESSED UNVERIFIED -- honestly no approved=true claim)

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 13:26:18 +02:00
admin c5ebceff38 Merge pull request 'P014: close tenant-isolation + idempotency gaps, execute real restore drill' (#29) from feat/p014-data-os-hardening into main
Deploy to Coolify / deploy (push) Successful in 2s
CI (SIAX Cloud) / integration (push) Successful in 35s
CI (SIAX Cloud) / quality (push) Successful in 48s
Security Scan (SIAX Cloud) / security (push) Successful in 28s
CI (SIAX Cloud) / security (push) Successful in 32s
2026-09-03 10:18:09 +00:00
Simon AxelssonandClaude Sonnet 5 dc6aaa0e10 fix(data-os): P014 — close tenant-isolation + idempotency gaps, execute real restore drill
CI (SIAX Cloud) / quality (push) Successful in 51s
Security Scan (SIAX Cloud) / security (push) Successful in 26s
CI (SIAX Cloud) / security (push) Successful in 28s
CI (SIAX Cloud) / integration (push) Successful in 1m1s
CI (SIAX Cloud) / integration (pull_request) Successful in 30s
CI (SIAX Cloud) / security (pull_request) Successful in 24s
CI (SIAX Cloud) / quality (pull_request) Successful in 48s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 22s
Tenant isolation (security-critical): every app/api/0pt/** route reading
tenant_id from client-controlled query/body never cross-checked it against
the token middleware.ts already verified (x-0pt-verified-tenant). Adds a
shared assertTenantMatchesVerified guard and wires it into all 20+ affected
routes. Also closes two full-leak-by-omission bugs found in this pass
(documents/capture and lakehouse/mappings GETs returned every tenant's rows
when tenant_id was simply omitted) and two "no tenant check at all" reads
(rate-policies/[id], lakehouse/mappings/[id]) reachable by ID alone.

Duplicate-delivery idempotency (correctness-critical): POST /api/orders now
honors Idempotency-Key (sql/006, replay-or-409-on-conflict, Postgres +
in-memory); the Python orchestrator's POST /orders/{id}/run — the actual
delivery trigger — is now idempotent under an asyncio lock, closing a real
concurrent-request race, not just the sequential-retry case.

Engine-duplication resolution: adaptive_router.py's docstring wrongly
invited a bypass ("see b0ts for scraping") contradicting the product's own
compliance stance; corrected, and given real (additive, not escalating)
block-signal tracking so a rate-limited/blocked source is excluded from the
plan instead of hammered. Also fixes a previously-undiscovered production
bug: the Python engine's only call into the TS quality bridge
(X-Internal-Token) was unconditionally 401'd by middleware.ts, which never
checked that credential — the advisory quality bridge was unreachable in any
environment enforcing auth.

Restore drill: executed for real against throwaway Docker Postgres
containers (not simulated). Found and fixed two real blockers along the way:
sql/004 referenced opt_datasets, which no migration ever created (chain was
never actually runnable end to end); lib/db.ts hardcoded ssl:"require",
making any non-TLS Postgres (incl. compose.dev.yaml's own local-dev
container) unreachable. After both fixes: full migration chain applies
cleanly, pg_dump/pg_restore round-trip is byte-identical (row counts +
content checksums), and real application code (lib/orders-store.ts,
SourceRegistryService's Postgres repository) reads the restored data back
correctly, including cross-tenant isolation still holding.

82 new tests (55 TS + 27 Python), all passing; full existing suite (291 TS +
55 Python) still green; typecheck clean on every changed/added file.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-03 12:00:43 +02:00
admin 40c3e2fbee Merge pull request 'feat(data-os): P010 completion — Source Registry persistence + TS/Python quality bridge + provenance + fault-injection tests' (#28) from feat/p010-data-os-completion into main
Deploy to Coolify / deploy (push) Successful in 2s
CI (SIAX Cloud) / security (push) Successful in 20s
Security Scan (SIAX Cloud) / security (push) Successful in 20s
CI (SIAX Cloud) / integration (push) Successful in 25s
CI (SIAX Cloud) / quality (push) Successful in 46s
2026-09-01 19:10:26 +00:00
Simon AxelssonandClaude Sonnet 5 e7516697b3 docs(p010): implementation report + production evidence for Data-OS completion
CI (SIAX Cloud) / security (push) Successful in 23s
CI (SIAX Cloud) / integration (push) Successful in 30s
Security Scan (SIAX Cloud) / security (push) Successful in 30s
CI (SIAX Cloud) / quality (push) Successful in 53s
CI (SIAX Cloud) / security (pull_request) Successful in 20s
CI (SIAX Cloud) / quality (pull_request) Successful in 51s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 22s
CI (SIAX Cloud) / integration (pull_request) Successful in 32s
From-scratch verification (fresh clone, fresh installs) backing up the P010
completion pass: 256/256 vitest, 28/28 pytest, clean typecheck/build on the
committed tree, pre-existing-only lint noise. Documents that
OPT_QUALITY_BRIDGE_ENABLED ships off and stays off in this PR -- activating
it in production is left as Simon's decision, with a readiness checklist.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-01 21:08:20 +02:00
Simon AxelssonandClaude Sonnet 5 9740e20818 feat(data-os): TS/Python quality bridge + provenance fields + fault-injection tests
CI (SIAX Cloud) / security (push) Successful in 23s
Security Scan (SIAX Cloud) / security (push) Successful in 22s
CI (SIAX Cloud) / integration (push) Successful in 29s
CI (SIAX Cloud) / quality (push) Successful in 45s
CI (SIAX Cloud) / security (pull_request) Successful in 27s
CI (SIAX Cloud) / integration (pull_request) Successful in 31s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 29s
CI (SIAX Cloud) / quality (pull_request) Successful in 48s
Continues P010 (branch renamed from feat/p010-source-registry-persistence):
closes the three remaining BEFORE_STATE.md gaps (§2 TS/Python split-brain,
§3 missing provenance fields, §4 untested failure modes), all additive to
the production pipeline — the Python QA filter's delivery decision is
unchanged by any of this.

TS/Python bridge (§2):
  - New route surface app/api/0pt/quality/* (rules/runs/issues CRUD +
    POST /api/0pt/quality/bridge-run) over the shared QualityService
    singleton (src/services/quality.ts), fixing the same "no shared
    instance" defect the Source Registry had.
  - src/quality/quality-bridge.ts auto-provisions a deterministic,
    tenant-scoped baseline rule set on first use so the Python engine never
    pre-registers rules through the CRUD surface.
  - services/api/workers/quality_bridge.py: the Python-side HTTP client.
    Feature-flagged off by default (OPT_QUALITY_BRIDGE_ENABLED), fails open
    on any error (never raises into run_job, never changes `delivered`).
    Advisory only — real per-row gating against the TS engine isn't
    implementable yet (ExpectationEngine returns dataset-level pass/fail
    counts + samples, not a per-row boolean array); documented, not faked.
  - Live-verified end-to-end: `next dev` (AUTH_ENFORCE=false) + the real
    Python pipeline hitting the real brreg.no API, round-tripping through
    the real bridge route, receiving a real QualityService score.

Provenance (§3): sources/connectors.py's Provenance dataclass gains
retrieved_at, transform, connector_version, producer, quality,
entity_resolution, artifact_ref (all previously absent from the real
dataflow entirely) via a make_provenance() factory used by every connector.
resolve.py stamps entity_resolution on merged records' provenance (never on
unmerged ones). pipeline.py stamps artifact_ref at delivery and quality
once the bridge succeeds.

Failure tests (§4), real fault injection against real code (services/api,
new pytest + respx suite, not vitest mocks):
  - dedup-determinism + duplicate-input + out-of-order: resolve.py under
    shuffled/interleaved/exhaustive-permutation input, plus an explicit,
    verified test of the one case that IS legitimately order-sensitive
    (non-transitive similarity in a greedy clusterer) instead of hiding it.
  - schema-evolution: respx-mocked upstream responses with added/removed/
    alien-shaped fields through the real brreg connector + pipeline.
  - restart: connector exceptions mid-job (including one from respx itself)
    never crash run_job.
  - backfill: the real property that holds given no persistence layer
    exists (replay is compute-idempotent) — NOT a fabricated dedup-store
    test.
  - CDC-interruption and true backfill/delivery-store idempotency:
    explicitly documented as not implementable against this codebase
    (no CDC pipeline, no delivery store exist anywhere) via skip markers
    with reasons, in tests/test_known_gaps.py, rather than silently
    dropped or faked.

Testing: 256/256 vitest (249 pre-existing + 7 new bridge route/service
tests) and 28/28 pytest (2 documented skips) green locally. tsc -p
tsconfig.check.json has zero new errors (14 pre-existing errors, all in
the untracked/unaudited src/fleet, src/graph, src/metrics, src/projections
paths this pass does not touch, per BEFORE_STATE.md).

No PR opened, per instructions.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-01 21:02:14 +02:00
Simon AxelssonandClaude Sonnet 5 07b13bd833 feat(data-os): Source Registry Postgres persistence + full HTTP route surface
Replaces the in-memory (per-instance, not even per-process-shared) Maps in
SourceService/SourceRegistryService with real Postgres persistence, and adds
the register/query/describe/health/rights/provenance/freshness HTTP routes
that never existed (grep for SourceRegistryService in app/ previously
returned nothing).

- sql/002_source_registry.sql: opt_sources, opt_source_rights,
  opt_source_provenance, opt_source_health_checks, opt_source_freshness.
  Numbered 002 (not 006) because 004's opt_source_rate_policies already
  forward-references opt_sources, which no sql/ file defined until now —
  fixes 004's pre-existing broken migration ordering (opt_datasets remains
  a separate, unrelated, still-open gap in 004, flagged not fixed).
- src/repositories/*: SourceRepository / SourceRegistryRepository seams,
  each with an in-memory implementation (business logic extracted verbatim)
  and a Postgres implementation, chosen via resolveStoreMode — production
  still fails hard with no DATABASE_URL (Master-DoD §3), but a configured
  production now actually works instead of always being blocked.
- SourceService / SourceRegistryService: storage moved behind the
  repository seam; getHealth/getFreshness are now async and tenant-scoped
  at the accessor itself (needed once they're reachable directly over HTTP,
  not only after an earlier caller's tenant check).
- src/services/source-registry.ts: shared singleton instances for the
  sources/* route group, fixing the "each route module owned its own
  private registry" defect (source-rate-policies and .../query previously
  couldn't see a source registered via POST /api/0pt/sources).
- New routes: POST/GET /api/0pt/sources, GET /api/0pt/sources/[id],
  GET+PUT .../rights, GET+PUT .../provenance, GET+POST .../health,
  GET .../freshness.
- Business logic unchanged: fail-closed purpose gate, cross-tenant
  NOT_FOUND (no existence oracle, §50), bounded 100-row health history.

Tested against a real Postgres container (not mocked) —
tests/p0/source-registry-postgres.realinfra.test.ts, env-gated on
SOURCE_REGISTRY_TEST_DATABASE_URL, skips honestly when unset. All 249
pre-existing P0 tests + 7 new realinfra tests pass; also smoke-tested the
full HTTP route surface end-to-end against next dev + live Postgres.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-01 20:42:41 +02:00
admin f8bb0d5ab9 Merge pull request 'feat: SIAX Platforms P0 wave 2 — real-contract platform clients + Data-OS capability layer' (#25) from feat/siax-platforms-p0-data-os into main
Deploy to Coolify / deploy (push) Successful in 3s
CI (SIAX Cloud) / integration (push) Successful in 25s
CI (SIAX Cloud) / security (push) Successful in 18s
CI (SIAX Cloud) / quality (push) Successful in 48s
Security Scan (SIAX Cloud) / security (push) Successful in 19s
2026-08-31 20:26:42 +00:00
Simon AxelssonandClaude Fable 5 62f7b0049f fix(ci): pin OpenSearch service container workdir — act_runner clobbers WORKDIR-relative ENTRYPOINT
CI (SIAX Cloud) / integration (push) Successful in 22s
CI (SIAX Cloud) / security (push) Successful in 20s
Security Scan (SIAX Cloud) / security (push) Successful in 17s
CI (SIAX Cloud) / quality (push) Successful in 47s
CI (SIAX Cloud) / security (pull_request) Successful in 20s
CI (SIAX Cloud) / integration (pull_request) Successful in 31s
CI (SIAX Cloud) / quality (pull_request) Successful in 45s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 22s
PR #25 CI run 7745 job 'integration' failed before any test ran: 'exec:
"./opensearch-docker-entrypoint.sh": stat ...: no such file or directory'.
Root cause (confirmed against the job log's merged container.Config, and
reproduced locally with plain docker run -w): this runner's act_runner
merges the JOB's WorkingDir (/workspace/sax3l/0pt) into every SERVICE
container, clobbering the OpenSearch image's own WORKDIR
(/usr/share/opensearch) that its ENTRYPOINT ./opensearch-docker-entrypoint.sh
is relative to. ClickHouse's entrypoint is an absolute path so it started
fine under the same defect -- a green ClickHouse service is not evidence
this class of bug is absent elsewhere.

Fix: --workdir /usr/share/opensearch in the opt-ci-opensearch service's
options, restoring the image's own working directory. Verified locally:
'docker run -w /workspace/sax3l/0pt opensearchproject/opensearch:2.11.1'
reproduces the exact failure; '-w /usr/share/opensearch' fixes it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 22:20:36 +02:00
Simon AxelssonandClaude Fable 5 c47e3b468e test(integration)+ci+docs: live OpenSearch/ClickHouse suites, CI service containers, STATUS.md (§56)
CI (SIAX Cloud) / integration (push) Failing after 22s
CI (SIAX Cloud) / security (push) Successful in 22s
Security Scan (SIAX Cloud) / security (push) Successful in 21s
CI (SIAX Cloud) / quality (push) Successful in 43s
CI (SIAX Cloud) / integration (pull_request) Failing after 3s
CI (SIAX Cloud) / security (pull_request) Successful in 17s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 16s
CI (SIAX Cloud) / quality (pull_request) Successful in 43s
- tests/integration/: 10 tests against REAL OpenSearch 2.11 (tenant
  isolation, purpose/rights filters, generation rebuild/rollback,
  projection-disaster rebuild §68) + REAL ClickHouse 24.8 (tenant-isolated
  metric DSL, TTL schema, injection-surface refusals). Honest skip without
  env - and CI fails hard if the suites skip instead of running.
- .gitea/workflows/ci.yml: new blocking 'integration' job with
  self-identifying service containers (st0re ci.yml's measured
  alias-collision discipline: run-unique cluster.name / credentials,
  getent-enumerated IP selection, no-match = hard fail).
- STATUS.md: full 8-level Master-DoD classification per capability incl.
  the honest gaps blocking PRODUCTION_READY.
- dependency-mode: NEXT_PHASE=phase-production-build is not a serving
  runtime (next build page-data collection must compile; guard re-arms at
  boot) - pinned by contract test.
- docs/02-architecture.md: superseded the accurate-but-now-fixed 'every
  client runs against its mock' paragraph; .env.example: client URLs now
  actually read from env + new P0 backend vars.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 16:56:33 +02:00
admin 9f0de72456 chore(deps): update dependency @tailwindcss/postcss to v4.3.3 (#12)
Deploy to Coolify / deploy (push) Successful in 3s
CI (SIAX Cloud) / security (push) Successful in 20s
Security Scan (SIAX Cloud) / security (push) Successful in 18s
CI (SIAX Cloud) / quality (push) Successful in 48s
2026-08-31 14:54:56 +00:00
admin 6be9992cad chore(deps): update dev-dependencies (non-major) (#14)
Deploy to Coolify / deploy (push) Successful in 4s
CI (SIAX Cloud) / security (push) Successful in 18s
CI (SIAX Cloud) / quality (push) Successful in 50s
Security Scan (SIAX Cloud) / security (push) Successful in 21s
2026-08-31 14:54:54 +00:00
Simon AxelssonandClaude Fable 5 b46807da75 feat(data-os): P0 capability layer — source registry, search, quality, dataset versions, metadata, analytics, features, ER
- Source Registry (§10): rights/license/purpose metadata, provenance,
  freshness SLA, health checks, describe/query; purpose gate FAILS CLOSED
  (no rights record => deny); cross-tenant probes => NOT_FOUND.
- Search (§10/§42): OpenSearch REST adapter (no SDK) + SearchService with
  MANDATORY tenant + purpose/rights filtering, versioned index definitions,
  bulk, generation-per-rebuild (opt-{name}--g{n}) with atomic alias cutover,
  rollback, failed-rebuild generation discard. OpenSearch never canonical.
- Quality (§10): versioned rule registry (GE-JSON interchange), local
  engine for the GE core subset (never silently passes unsupported types),
  runs/results/issues/score/trend, whole-run delegation to the GE backend
  via N0D (0pt.quality.ge_run) - never fabricated results.
- Dataset (§10/§5/§53): immutable numbered versions holding canonical
  st0re:artifact refs only, idempotent createVersion, export registers the
  ST0RE artifact + AUD0 evidence + OpenLineage.
- Metadata (§10): OpenMetadata PUT /api/v1/tables projection adapter +
  projectAll rebuild path; projection never canonical.
- Analytics (§10): ClickHouse HTTP adapter, closed metric-query DSL with
  FORCED tenant predicate + readonly/max_execution_time/max_result_rows,
  TTL retention. Zero connection to b0ts/quarantined pipelines.
- Features (§10): versioned feature-view registry, real Feast
  get-online-features adapter, materialize/get-historical as N0D delegation.
- ER (§10): generic candidate API with deterministic blocking + transparent
  scoring + per-field explanations, product hard-rule hook (force both
  directions), review-band handoff, Splink batch via N0D contract.

93 new unit/contract tests; suite 248 passed / 1 skipped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 16:49:32 +02:00
Simon AxelssonandClaude Fable 5 da58176735 test(contracts): per-client wire-contract suites + §3 production-guard tests
38 tests: recording provider double answers with the sibling services' real
response shapes; each suite asserts the exact request wire shape (path,
method, tenant/actor/idempotency headers, camelCase vs snake_case body) so a
regression to the pre-rewrite invented shapes fails loudly. Includes the
fail-closed policy cases (missing decision => deny, CL0UD down => typed
error, never implicit allow) and the production factory guard for all four
clients.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 16:37:57 +02:00
Simon AxelssonandClaude Fable 5 b7038d7675 feat(platform): canonical SIAX context/errors + real-contract clients, no prod mock fallback
- src/platform/: SiaxRequestContext + propagation headers + 12 canonical
  error codes (documented mirror of cl0ud packages/contract), SiaxError,
  resource refs (st0re:artifact:...), and the §3/§10 dependency-mode guard:
  production runtime + unconfigured dependency/store => hard
  DEPENDENCY_UNAVAILABLE at construction, never silent mock/in-memory.
- src/clients/: all four platform clients rewritten against the REAL wire
  contracts verified on sibling main branches this session:
  * cl0ud: POST /api/policy/evaluate ({data} envelope, allow+requiresApproval)
    - the old /v1/cl0ud/policies/evaluate path never existed on CL0UD
  * st0re: camelCase ArtifactInput on /v1/st0re/artifacts/register incl.
    X-Tenant-Id/X-Actor-Id + X-Idempotency-Key - the old snake_case body
    would have been a 400 against the live registry
  * n0d: required_role + resource_requirements + body idempotency_key +
    CloudEvents callback_url per n0d createJobSchema; adds getJob/getJobResult
  * aud0: /v1/aud0/openlineage is AUD0's only lineage ingest -
    /v1/aud0/lineage/events never existed; legacy shape converts to a
    spec-shaped OpenLineage RunEvent (deterministic runId dedup)
- src/lineage/: OpenLineage subset types + LineageEmitter (never-throw,
  §16 evidence semantics)
- shared SiaxHttp transport: timeouts, typed SiaxError mapping, context
  propagation, no raw upstream bodies in errors

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-31 16:35:01 +02:00
admin e452848470 Merge pull request 'fix: COOLIFY_APP_ID from variables (0pt app live in Coolify)' (#24) from fix/coolify-app-id into main
Deploy to Coolify / deploy (push) Successful in 3s
CI (SIAX Cloud) / security (push) Successful in 22s
Security Scan (SIAX Cloud) / security (push) Successful in 22s
CI (SIAX Cloud) / quality (push) Successful in 51s
2026-08-31 11:54:34 +00:00
Simon Axelsson 18ea0ecc41 fix: wire COOLIFY_APP_ID from repo variable (0pt app provisioned via API 2026-08-31)
CI (SIAX Cloud) / security (push) Successful in 46s
CI (SIAX Cloud) / security (pull_request) Successful in 49s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 48s
Security Scan (SIAX Cloud) / security (push) Successful in 21s
CI (SIAX Cloud) / quality (pull_request) Successful in 1m15s
CI (SIAX Cloud) / quality (push) Successful in 1m13s
2026-08-31 13:54:21 +02:00
Simon Axelsson fedaab41ba fix: auth middleware matcher covers /api/0pt exact path + diag logging for S1 root-cause
Deploy to Coolify / deploy (push) Failing after 6s
CI (SIAX Cloud) / quality (push) Successful in 1m13s
CI (SIAX Cloud) / security (push) Successful in 27s
Security Scan (SIAX Cloud) / security (push) Successful in 25s
2026-08-31 13:05:04 +02:00
admin 00a1b3997d fix(env): NEXT_PUBLIC_API_URL -> live origin (api.0pt.app is dead) (#23)
CI (SIAX Cloud) / security (push) Successful in 21s
Deploy to Coolify / deploy (push) Failing after 2s
Security Scan (SIAX Cloud) / security (push) Successful in 18s
CI (SIAX Cloud) / quality (push) Successful in 51s
Co-authored-by: sax3l <simon@siax.io>
Co-committed-by: sax3l <simon@siax.io>
2026-08-27 04:36:39 +00:00
adminandClaude Sonnet 5 7b1814fef4 feat(compliance): scaffold Golden Standard artifacts (CI-14, DX-02, DX-03)
CI (SIAX Cloud) / security (push) Successful in 19s
Security Scan (SIAX Cloud) / security (push) Successful in 17s
CI (SIAX Cloud) / quality (push) Successful in 40s
CI (SIAX Cloud) / security (pull_request) Successful in 24s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 24s
CI (SIAX Cloud) / quality (pull_request) Successful in 48s
Applies siax-standard/packages/scaffold (feat/scaffold-generator) to close
three BLOCK-level gaps found by the doctor:

- .gitea/CODEOWNERS (CI-14) — was completely missing
- compose.dev.yaml (DX-02) — was completely missing, left as `services: {}`
  since the scaffold cannot know this repo's real local dependencies
- .devcontainer/devcontainer.json (DX-03) — was completely missing

siax.repo.json, the four docs/runbook/*.md files, .gitea/workflows/security.yml,
prompts/000-INDEX.md and contracts/openapi.yaml already existed with content
and were left untouched (AR-1: the generator never overwrites existing content).

docs/compliance/SCAFFOLD-TODO.md was generated and then manually corrected
before this commit — the generator emits some fixed TODO/warning lines
regardless of actual repo state, and three of them were false for 0pt:

- claimed appId is null needing an appIdJustification field removed; the
  EXISTING siax.repo.json already has appId: "0PT" set, no such field exists
- claimed domains: 0 ("none found"); the EXISTING siax.repo.json already
  lists 2 domains (0pt.app, api.0pt.app) as strings — the new schema wants
  objects, so they fail validation and get silently dropped to 0, which
  reads as "no domains configured" when in fact 0pt.app is a real domain
- asked to fill in both consumes[] and consumedBy[] "from scratch"; consumes[]
  is already fully populated in the existing file (CL0UD, ST0RE, N0D, AUD0,
  INF0) — only consumedBy[] is actually missing

Doctor measuredScore: 74 -> 85 (CI-14, DX-02, DX-03 flip FAIL -> PASS).
REPO-04 stays FAIL: siax.repo.json still needs a human to add the missing
required fields and convert domains to the new object shape (AR-1 will not
touch a file that already has content) — tracked in SCAFFOLD-TODO.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 14:36:03 +02:00
admin 77e5137c9a Merge pull request 'docs+chore: repo hygiene -- v2.0 manifests, ADRs, changelog, doctor, guides' (#20) from docs/repo-hygiene-v2-standard into main
CI (SIAX Cloud) / quality (push) Successful in 44s
Deploy to Coolify / deploy (push) Failing after 3s
CI (SIAX Cloud) / security (push) Successful in 23s
Security Scan (SIAX Cloud) / security (push) Successful in 19s
2026-08-11 12:32:19 +00:00
admin 5f98379b80 Merge pull request 'fix(health): report real per-dependency status instead of hardcoded ok:true' (#18) from fix/honest-health-check into main
Security Scan (SIAX Cloud) / security (push) Successful in 17s
Deploy to Coolify / deploy (push) Failing after 2s
CI (SIAX Cloud) / security (push) Successful in 17s
CI (SIAX Cloud) / quality (push) Successful in 41s
2026-08-11 12:31:36 +00:00
admin 8e4a062f02 Merge pull request 'docs(compliance): add BLOCKERS.md (§1.4)' (#16) from docs/compliance-blockers-2026-08-11 into main
CI (SIAX Cloud) / security (push) Successful in 18s
Security Scan (SIAX Cloud) / security (push) Successful in 17s
CI (SIAX Cloud) / quality (push) Successful in 41s
Deploy to Coolify / deploy (push) Failing after 2s
2026-08-11 12:30:59 +00:00
admin 328f8a46cb docs+chore: repo hygiene -- v2.0 manifests, ADRs, changelog, doctor, guides
CI (SIAX Cloud) / security (push) Successful in 19s
Security Scan (SIAX Cloud) / security (push) Successful in 19s
CI (SIAX Cloud) / quality (push) Successful in 44s
CI (SIAX Cloud) / security (pull_request) Successful in 21s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 20s
CI (SIAX Cloud) / quality (pull_request) Successful in 42s
BACKLOG P1-1: siax.repo.json/siax.config.json rewritten to be schema-valid
against sax3l/siax-standard's actual v2.0 schemas (lifecycle,
operationalState, gitHost, domains-as-objects, consumedBy, children,
contracts -- validated with jsonschema, not just eyeballed). config.json
restructured to the real deploy-descriptor shape (framework/build/start/
port/healthcheck/environments) instead of duplicating repo.json's identity
fields, which the schema doesn't allow.

BACKLOG P1-2: 3 ADRs for decisions already made and evidenced elsewhere in
this repo (Coolify-not-Vercel, Zitadel-not-NextAuth, Iceberg-format pointer
to n0d ADR-0030) -- retroactive documentation, not new decisions. The
Stripe/Revolut and services/scrapers/* questions are explicitly NOT written
as ADRs here; both are account-owner-gated or actively under review
elsewhere (see docs/architecture/decisions/README.md).

BACKLOG P1-3: CHANGELOG.md from real git log history (no tags/releases
exist yet -- this doesn't invent version numbers that were never cut).

BACKLOG P1-19: `pnpm siax:doctor` (scripts/siax-doctor.mjs, AGENT-04) --
zero-dependency, checks required files + manifest shape, prints
control-IDs. .devcontainer/devcontainer.json (DX-03). compose.dev.yaml
(DX-02 -- UNVERIFIED, no Docker available in this environment to smoke-test,
flagged in the file itself). All 4 prompts + the index rewritten to AGENT-03
shape (goal/context/prerequisites/scope/contract/acceptance-criteria/
control-ID/forbidden-actions).

BACKLOG P1-20: docs/architecture/ARCHITECTURE.md migrated to the v2.0
9-heading template -- new §5 "Ytor och paritet" (capability x
API/CLI/MCP/console coverage table, grounded in the same registry facts
docs/02-architecture.md already established), §6-9 renumbered from the old
§5-8 (all internal cross-references fixed, CLAUDE.md's own §-numbers left
untouched). docs/api/ added (points at contracts/openapi.yaml as the one
SSOT instead of duplicating it as drift-prone prose).

BACKLOG P1-21: packages/schemas now has a real package.json (was loose JSON
files with no package -- pnpm-workspace.yaml's packages/* glob matched an
empty package). Verified `pnpm install --frozen-lockfile` and the full
typecheck/test/build suite still pass with 2 real workspace projects.
apps/ restructuring explicitly NOT attempted (BACKLOG's own effort estimate
is "L" / large -- moving the whole app tree is a bigger, riskier change than
belongs in this pass). Import-boundary check added via dependency-cruiser
(ARK-14) -- installed for real, config tested against this codebase (179
modules, 310 deps, 0 violations), wired as `pnpm run deps:check` (advisory,
not yet a CI gate).

BACKLOG P2-5: docs/02-architecture.md's "Hosting" section marked SUPERSEDED
(the Vercel plan was superseded by the Coolify deploy.target flip,
2026-08-09 -- ADR-0001). README.md/.env.example were checked and are
already accurately framed (live-on-Vercel vs. config-target-is-Coolify) --
not touched.

BACKLOG P3-5: 2 stale github.com/sax3l/0pt/pull/3 links removed (the PR
merged long ago, .env.example is real and current) -- docs/09-build-plan.md,
docs/08-infrastructure.md. The "two diverged remotes, unresolved which is
canonical" language elsewhere (CLAUDE.md, AGENTS.md, SECURITY.md, etc.) is
deliberately NOT touched -- that's a live, correctly-flagged, account-owner-
owned open question per the Gitea-exclusivity mandate, not a stale link.

BACKLOG P6 (19 items): concrete artifacts for the ones that are actually a
file (.editorconfig, dependency-cruiser, deprecation policy, K8s reference
manifest, .actrc, Makefile, ONBOARDING.md); docs/guides/P6-GUIDES.md for the
rest (CLI-13, DOC-18, UI-30, IAM-19, PAY-11, AI-18, OBS-21, TEST-20, NET-19,
SCALE-13, OSS-10, AGENT-13) -- each grounded in this repo's actual code/gaps,
not generic advice.

NOT attempted (out of this task's scope, noted for the record):
- P2-1 (cl0ud app-registry.ts mismatch) -- lives in a different repo
  (sax3l/cl0ud), not cloned/authorized for this task's single-repo PR flow.
- The CI "doctor step" half of P1-15 -- deliberately left out of this PR's
  .gitea/workflows/ci.yml to avoid a 3-way merge conflict with
  ci/security-headers-and-scanning, which already restructured that file;
  add it as a follow-up once that PR merges.

This branch was authored independently of, but shares docs/architecture/
ARCHITECTURE.md and docs/slo.md with, fix/honest-health-check and
ci/security-headers-and-scanning -- expect a small, normal merge conflict
if this is rebased after either of those merge first (both already rebased
cleanly against each other and against main as of this commit).
2026-08-11 14:18:00 +02:00
admin a88ad04867 fix(health): report real per-dependency status instead of hardcoded ok:true
CI (SIAX Cloud) / security (push) Successful in 21s
Security Scan (SIAX Cloud) / security (push) Successful in 21s
CI (SIAX Cloud) / quality (push) Successful in 41s
CI (SIAX Cloud) / security (pull_request) Successful in 22s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 21s
CI (SIAX Cloud) / quality (pull_request) Successful in 41s
BACKLOG P0-3: /api/health only ever checked *presence* of DATABASE_URL/
REDIS_URL and always returned ok:true regardless of whether anything was
reachable -- ARCHITECTURE.md's own words, "an uptime monitor watching HTTP
200 would show green for a dying instance".

lib/health-checks.ts adds real dependency probes:
  - db: a live `select 1` round trip (not just DATABASE_URL presence)
  - engine: a real HTTP call to the FastAPI engine's own GET /health
  - stripe: Stripe's documented lightweight balance.retrieve() liveness call
  - queue: honestly reports "not_integrated" when REDIS_URL is set but
    unused -- no Redis client is wired anywhere in this repo, so reporting
    "ok" would fabricate a check that doesn't exist

/api/health stays a liveness check (always 200 while the process can
respond; the body's `ok` field is the honest signal). New GET /api/ready
fails closed with 503 when the load-bearing dependency (db) isn't both
configured and reachable -- the "no /ready route" gap.

contracts/openapi.yaml, docs/architecture/ARCHITECTURE.md, and docs/slo.md
updated to match. 17 new unit tests (dependency-injected fakes, no real
network/DB) + 5 route-level tests.
2026-08-11 13:49:23 +02:00
admin ebffb7df86 Merge pull request 'docs(compliance): finish attributing the evasion-stack keep decision' (#17) from docs/curl-cffi-decision-attribution into main
Security Scan (SIAX Cloud) / security (push) Successful in 21s
Deploy to Coolify / deploy (push) Failing after 2s
CI (SIAX Cloud) / security (push) Successful in 22s
CI (SIAX Cloud) / quality (push) Successful in 41s
2026-08-11 11:36:38 +00:00
adminandClaude Sonnet 5 2393f52768 docs(compliance): finish attributing the evasion-stack keep decision
CI (SIAX Cloud) / security (push) Successful in 20s
Security Scan (SIAX Cloud) / security (push) Successful in 20s
CI (SIAX Cloud) / quality (push) Successful in 41s
CI (SIAX Cloud) / security (pull_request) Successful in 20s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 20s
CI (SIAX Cloud) / quality (pull_request) Successful in 41s
PR #15 already fixed AGENTS.md/SECURITY.md with a dated, attributed
statement of the account owner's 2026-08-11 decision (Simon Axelsson, via
an interactive decision prompt, responding to this repo's own removal
proposal PR #7 which was verified clean/128 tests and closed unmerged --
no rationale beyond "keep it" was given or is invented). This PR finds and
fixes every other place in the repo that still carried the earlier
unattributed "medvetet anvandarbeslut" / "deliberate user decision" claim
a compliance audit flagged as unverifiable:

- docs/compliance/GOLDEN-STANDARD-REPORT.md: control C6 row + the
  "Bypass-undantag" formal section (the two places this doc was explicitly
  named to need checking) -- header gains a dated update note, C6 row and
  the section body get the same attributed statement as AGENTS.md/SECURITY.md.
- docs/compliance/SLUTRAPPORT.md, docs/compliance/INVENTORY.md: historical
  session doc keeps its original text and gains a dated correction
  addendum; the INVENTORY.md evidence bullet is corrected in place.
- docs/slo.md, CONTRIBUTING.md, prompts/002-compliance-audit.md,
  renovate.json, .gitea/workflows/security.yml: direct/living references
  to the exemption get the same attributed, dated pointer instead of the
  unattributed phrase.

CLAUDE.md's general §1 anti-evasion policy text is untouched, per instruction
-- this is a scoped exception note, not a change to the normative rule. No
code changes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 13:34:13 +02:00
Claude (0pt session)andClaude Sonnet 5 e9dff491ca docs(compliance): add BLOCKERS.md (§1.4)
CI (SIAX Cloud) / security (push) Successful in 16s
Security Scan (SIAX Cloud) / security (push) Successful in 19s
CI (SIAX Cloud) / quality (push) Successful in 43s
CI (SIAX Cloud) / security (pull_request) Successful in 26s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 21s
CI (SIAX Cloud) / quality (pull_request) Successful in 46s
Golden Standard §1.4 requires an unresolved blocker to be recorded in
docs/compliance/BLOCKERS.md; this file was confirmed absent in a recent
audit pass, which is itself a delivery defect per the framework's own
rule. Records four blockers, each freshly re-verified against current
main rather than copied from prior findings:

- WAF-bypass/Tor/FlareSolverr stack (services/scrapers/*): the account
  owner's decision (keep) is now on record via merged PR #15 as of
  today; PR #7 (removal) stays closed/unmerged. Documented as decided,
  not left as still-pending.
- No Coolify app / Infisical project provisioned (cd.yml still carries
  the TODO placeholder on current main).
- 0pt.app / 0pt.dev DNS still delegated to Vercel nameservers (live NS
  lookup today), despite PowerDNS holding shadow zone copies.
- middleware.ts still answers anonymously live even after a merged
  auth fix (PR #11) — confirmed with a fresh live probe today, which
  sharpens the existing P0-1 backlog item.

Scope: documentation only, this one new file. Does not touch
services/scrapers/*, services/infra/docker-compose.data-stack.yml,
docs/compliance/BACKLOG.md, or PR #7.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 13:04:53 +02:00
admin 5c36dc300f Merge pull request 'docs(compliance): record dated provenance for evasion-stack keep decision' (#15) from docs/evasion-stack-decision-provenance into main
Deploy to Coolify / deploy (push) Failing after 2s
CI (SIAX Cloud) / security (push) Successful in 19s
Security Scan (SIAX Cloud) / security (push) Successful in 17s
CI (SIAX Cloud) / quality (push) Successful in 40s
2026-08-11 09:36:16 +00:00
admin 60145eee33 Merge pull request 'fix(security): require auth on GET /api/orders and GET /api/admin/metrics' (#11) from security/auth-gate-anonymous-api-routes into main
Deploy to Coolify / deploy (push) Failing after 2s
CI (SIAX Cloud) / security (push) Successful in 19s
Security Scan (SIAX Cloud) / security (push) Successful in 19s
CI (SIAX Cloud) / quality (push) Successful in 40s
2026-08-11 09:35:48 +00:00
adminandClaude Sonnet 5 a14911b263 docs(compliance): record dated provenance for evasion-stack keep decision
CI (SIAX Cloud) / security (push) Successful in 24s
Security Scan (SIAX Cloud) / security (push) Successful in 22s
CI (SIAX Cloud) / quality (push) Successful in 39s
CI (SIAX Cloud) / security (pull_request) Successful in 20s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 20s
CI (SIAX Cloud) / quality (pull_request) Successful in 38s
AGENTS.md and SECURITY.md previously attributed keeping the WAF-bypass/
Tor/FlareSolverr/curl_cffi/cloudscraper stack to an unattributed,
unverified "medvetet användarbeslut" (deliberate user decision) with no
stated author or date -- flagged by a prior audit as unverified provenance.

Replace with an accurate, dated statement: the account owner (Simon
Axelsson) was asked directly via an interactive decision prompt on
2026-08-11, in direct response to a compliance audit's removal proposal
(the surgically-clean removal PR #7, verified 128/128 tests, was closed
unmerged), and explicitly chose to keep the code. No business or legal
rationale beyond "keep it" was given or is invented here.

This is a narrow, scoped exception for the existing 0PT/0pt-motor sourcing
engine. CLAUDE.md §1's general anti-evasion policy text is untouched and
remains in force as written unless/until the account owner says otherwise.

No code changes -- documentation only.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 11:32:13 +02:00
adminandClaude Sonnet 5 15a0dbe3b1 fix(security): require auth on GET /api/orders and GET /api/admin/metrics
Security Scan (SIAX Cloud) / security (pull_request) Successful in 24s
CI (SIAX Cloud) / security (pull_request) Successful in 25s
CI (SIAX Cloud) / quality (pull_request) Successful in 40s
CI (SIAX Cloud) / security (push) Successful in 22s
Security Scan (SIAX Cloud) / security (push) Successful in 20s
CI (SIAX Cloud) / quality (push) Successful in 39s
A live compliance audit against 0pt.app confirmed both endpoints returned
HTTP 200 with zero authentication -- the full order queue and financial
pipeline aggregates (deposit/pipeline totals) were readable by anyone.

Root cause: middleware.ts's matcher only covers /api/0pt/:path*, by design
("does NOT touch ... the unrelated payment/order APIs"), so nothing upstream
of these two handlers ever verified the caller.

Fix: both GET handlers now call the same fail-closed Zitadel verifier
/api/0pt/* relies on (resolveAuthContext, src/auth/context.ts) directly, via
a new thin wrapper (src/auth/require-route-auth.ts) that maps a rejected
decision to the same 401/403 JSON shape middleware.ts already returns. The
wrapper re-verifies the bearer token itself rather than trusting any
x-0pt-verified-* header on the request, since middleware never runs in front
of these routes to overwrite a client-supplied one.

POST /api/orders (anonymous draft/quote creation before the deposit-payment
step) is intentionally left as-is -- only the read paths that leaked data are
gated. Tracked as part of docs/compliance/BACKLOG.md P0-3.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-11 04:06:13 +02:00
admin 5f41047546 docs(compliance): record final CI run IDs on main 3af2ac8
Deploy to Coolify / deploy (push) Failing after 2s
CI (SIAX Cloud) / security (push) Successful in 19s
Security Scan (SIAX Cloud) / security (push) Successful in 19s
CI (SIAX Cloud) / quality (push) Successful in 38s
2026-08-10 04:23:46 +02:00
admin 3af2ac894e docs(compliance): FAS 8 evidence + FAS 10 final report
Deploy to Coolify / deploy (push) Failing after 2s
CI (SIAX Cloud) / quality (push) Successful in 38s
CI (SIAX Cloud) / security (push) Successful in 16s
Security Scan (SIAX Cloud) / security (push) Successful in 15s
2026-08-10 04:18:00 +02:00
admin 8db56f1b4c docs: FAS 9 - README/SECURITY updates, CONTRIBUTING, AGENTS, runbooks (deploy/incident/backup-restore/oncall), SLO, prompts 2026-08-10 04:16:30 +02:00