Files
Claude Opus 5 ec26ddc296
CI (SIAX Cloud) / security (push) Successful in 22s
CI (SIAX Cloud) / integration (push) Successful in 38s
CI (SIAX Cloud) / quality (push) Successful in 52s
Security Scan (SIAX Cloud) / security (push) Successful in 20s
CI (SIAX Cloud) / security (pull_request) Successful in 22s
CI (SIAX Cloud) / integration (pull_request) Successful in 37s
Security Scan (SIAX Cloud) / security (pull_request) Successful in 20s
CI (SIAX Cloud) / quality (pull_request) Successful in 1m1s
feat(analytics): BI-P022 — dbt canonical transformation CONTRACT and reference project
Scope stated in the module's first paragraph: this defines the contract, it
does not run dbt, and nothing in this repo does. Execution is N0D's (n0d#38),
which consumes this from the other side. There is deliberately no DbtExecutor
implementation here — only the interface — so "0pt can run dbt" cannot become
true by accident and the two repos share one versioned shape.

`analytics/dbt/` is a real reference project covering raw -> staging ->
curated -> serving, with the four layers mapped onto BI-P003's existing tiers
rather than inventing a fifth vocabulary. The tenant predicate is applied at
the FIRST modelled layer so every downstream model inherits it and no later
model has to remember — the same forced-predicate rule as the query compiler's,
one layer up.

Two singular tests ship with it, both aimed at false greens:
  * `assert_mart_is_not_empty` — without it every column test passes trivially
    over zero rows and the whole suite reports green while the pipeline is dead;
  * `assert_no_cross_tenant_rows` — which should be impossible to fail, and
    exists precisely for that reason. An isolation guarantee nobody tests is the
    one that turns out to have four holes rather than the one reported.

BI-P022's version rule is a GATE. `DBT_RUNTIME_PIN` records dbt Core 1.10.13
(stable) with dbt-clickhouse 1.9.2 and BOTH review flags FALSE — no licence or
supply-chain review has been performed in this repo and none is claimed.
`assertDbtRuntimeCertified` refuses a production run until they are true, and
refuses an alpha line in production without a separate certification reference.
A version constant on its own would be the documented-but-unenforced pattern;
a test pins the flags at false so flipping them is a visible deliberate act.

The result is treated as UNTRUSTED INPUT, because it arrives from another
repo's executor and this estate has been burned by green statuses that meant
nothing. Refused: `status: success` with ZERO nodes executed (a dbt selector
matching nothing exits 0 — the dbt-shaped false green); an observed runtime
different from the pin (the models mean something else and nothing says so); a
revision that is not an exact 40-char SHA (a branch name is not reproducible,
and reproducibility is the DoD); a missing manifest.json or run_results.json,
without which the run cannot be audited or its tests ingested by BI-P025.

Layer dependencies are checked against the manifest GRAPH, not asserted as a
convention: a mart reading a source directly, or skipping a layer, or a
staging model reading a mart, are each refused.

Selectors are validated rather than passed through — a free-form argument list
is a shell surface, and a shell surface on a job holding warehouse credentials
is the whole problem. The job also cannot name an arbitrary target schema: it
must be scoped to the job's tenant.

39 tests. typecheck + eslint clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-07 02:45:41 +02:00
..

analytics/dbt/ — BI-P022

The canonical SIAX transformation project. Nothing in this repository runs it. Execution lives in N0D (n0d#38), against the contract in src/analytics/transform/dbt-contract.ts.

Layers, and why they map onto BI-P003

directory tier (BI-P003) may read must not contain
models/sources/ RAW — (declarations only) any SQL
models/staging/ NORMALIZED sources joins, business logic
models/intermediate/ CURATED staging presentation shaping
models/marts/ SERVING intermediate direct source reads

assertLayerDependenciesLegal enforces the "may read" column against the dependency graph in manifest.json. A mart reading a source directly is refused — that is raw data reaching a dashboard, which is precisely what BI-P003's tier rule exists to prevent, and a convention nobody checks would not prevent it.

What a run must produce

manifest.json and run_results.json, both registered as ST0RE artifacts. assertValidDbtJobResult refuses a result missing either: without them the run cannot be audited and its tests cannot be ingested by BI-P025's DbtQualityProvider.

It also refuses:

  • a result whose revision differs from the request — the run is not reproducible;
  • a result whose observed dbt version differs from the pin — a runtime that is not the pinned one silently changes what the models mean;
  • status: success with zero nodes executed — a dbt selector that matches nothing exits 0, which is the dbt-shaped false green.

Version posture

DBT_RUNTIME_PIN records dbt Core 1.10.13 (stable line) with dbt-clickhouse 1.9.2. Both review flags are false. No licence or supply-chain review has been performed in this repo, and none is claimed. assertDbtRuntimeCertified refuses a production run until they are true, so BI-P022's "after current license/security verification" is a gate rather than a sentence in a document.

Credentials

A dbt run never receives a tenant's warehouse credential from this repo. N0D resolves a credential whose write scope matches target_layer and expected_target_schema, and the contract refuses a request whose expected schema is not scoped to the job's tenant.