Skip to content

07 Sql Query Layer

Status: SHARP / PARTIAL RUNTIME. Global SQL contract, generated catalog, and provenance explain surface are implemented. Clinical trials is the first atomically promoted query family; remaining families still publish in place and are not last-known-good protected. Denoising state: sharp (noise -> rough -> sharp -> converged) Updated: 2026-07-24

Specify the only consumer interface. There is no API: agents connect to the database and read stable, documented q_* models. SQL is the contract.

  • Consumers are read-only. Agents get SELECT-only access to the q_* schema. All corrective writes happen via the curation decision log (05-agentic-curation-and-overrides.md), never directly against q_*.
  • q_ prefix = the agent query layer. Internal source/normalized/evidence/canonical assets are not part of the consumer contract and may change freely; only q_* is stable.
  • Self-describing database without duplicate truth. q_catalog is generated from Postgres catalogs/comments plus checked-in contract metadata; it is not a hand-maintained dictionary table.
  • Provenance, not blanket row-lineage. Pipeline/table/column lineage belongs in Dagster metadata and optional OpenLineage export. Agent-facing trust uses q_provenance: a generated explain view over immutable source artifacts, extraction activities, evidence claims, resolution/verifier receipts, canonical assertions, and curation overlays when applicable. It is not a separate ledger to manually synchronize.
  • Search is SQL-native. Trigram, full-text, and vector search are exposed as columns/indexes on q_* (pg_trgm, tsvector, pgvector), not a separate search service.
  • Stable names, additive evolution. Prefer adding columns / new versioned models (q_trials_v2) over breaking changes; deprecate with an overlap window.
flowchart LR
  Canonical[Canonical quality-passing assets]
  Query["q_* read models"]
  Catalog[q_catalog\ngenerated catalog]
  Provenance[q_provenance\nexplain view]
  Dagster[Dagster asset metadata\nasset + column lineage]
  Sources[Immutable source artifacts]
  Extraction[Extraction runs]
  Evidence[Evidence claims]
  Resolution[Resolution/verifier receipts]
  Curation[Reviewed curation overlays]
  Assertions[Canonical assertions]
  Agents[Read-only SQL agents]

  Canonical --> Query --> Agents
  Query --> Catalog
  Query --> Provenance
  Sources --> Provenance
  Extraction --> Provenance
  Evidence --> Provenance
  Resolution --> Provenance
  Curation --> Provenance
  Assertions --> Provenance
  Query -. transformation lineage .-> Dagster

The stable consumer object is a query.q_* view. Its physical backing is an implementation choice, selected per query family:

  • generation table + stable view for a consistency family that needs candidate validation, atomic promotion, and rollback;
  • plain view for a cheap projection where recomputation and in-place definition replacement are acceptable;
  • materialized view only after profiling proves stored results are useful and its refresh/index contract is explicit;
  • table for a large append-only or asset-written projection.

This separates performance from publication safety. A materialized view stores results but does not by itself provide a validated multi-model promotion boundary. PostgreSQL materialized views are refreshed explicitly and do not support CREATE OR REPLACE; use them when measured query cost justifies that lifecycle, not as a blanket default. (PostgreSQL materialized views, CREATE MATERIALIZED VIEW)

Current runtime truth:

  • the seventeen-model clinical-trials family uses immutable generation tables behind stable views;
  • q_catalog, q_provenance, and the remaining domain query models are plain views published in place;
  • no non-trial family may claim last-known-good protection until it adopts the generation protocol and passes the same failure-injection test.

clinical_trials is the first implemented publication family:

  1. one non-subsettable Dagster multi-asset freezes all seventeen checked-in SELECTs into temporary candidate tables under one repeatable-read transaction and a family advisory lock;
  2. primary keys, physical nullability/allowed-value constraints, schema contracts, provenance, row-count, internal/owner-spine references, source-group/endpoint uniqueness, and result-group, endpoint, and arm-link consistency are checked before serving changes;
  3. the candidate is copied into a uniquely named retained generation schema whose tables reject insert, update, delete, and truncate operations;
  4. all stable query.q_trial* views and the one ops.query_publication_heads pointer change in the same transaction;
  5. any exception rolls back the candidate, generation, view changes, head, and event receipt, so the prior generation remains served;
  6. an explicit rollback repoints the complete family to a retained, mutation-protected generation in one transaction, but refuses a target whose contract versions differ from the current family.

ops.query_publication_generations stores immutable manifests, ops.query_publication_heads stores the active/previous pointer, and ops.query_publication_events records promotions and rollbacks. Generation retention/pruning and adoption by other families remain operational follow-up; no automatic pruning runs today.

All consumer objects live in a dedicated database schema named query.

query.q_trials
query.q_drug_approvals
query.q_publication_evidence
query.q_catalog
query.q_provenance

The q_ prefix remains part of every model name even inside the query schema. This makes exported dumps, copied result sets, and provenance receipts self-describing.

Access rules:

  • agent roles receive USAGE on query and SELECT on approved q_* objects only;
  • agent roles do not receive write privileges on source, evidence, canonical, or query objects;
  • curation override writes use the curation decision-log contract in 05-agentic-curation-and-overrides.md, not ad hoc updates to q_*;
  • indexes are part of the contract when they enable promised search/filter behavior.

This section is a registry, not duplicate ownership. 07 owns the global mechanics (query schema, q_catalog, q_provenance, access rules, metadata/provenance contract). Domain slices own the row grains, semantics, and column-level contracts for their q_* families; the registry only prevents naming drift across docs.

q_trials -- one row per trial; denormalized headline facts
q_trial_interventions -- resolved interventions per trial (drug | ncit concept)
q_trial_endpoints -- endpoints / outcome measures per trial
q_trial_outcomes -- reported outcomes per trial arm
q_trial_eligibility -- structured eligibility per trial
q_regulatory_product_protections -- source-scoped patent/exclusivity records (owned by 22-slice-regulatory-approvals.md)
q_drugs -- canonical drug facts (owned by 29-slice-drug-identity.md)
q_diseases -- canonical disease facts + hierarchy (owned by 30-slice-disease-biomarker-identity.md)
q_targets -- canonical target facts (owned by 31-slice-target-technology-identity.md)
q_technologies -- canonical modality/technology facts (owned by 31-slice-target-technology-identity.md)
q_endpoints -- canonical endpoint catalog (owned by 32-slice-endpoint-adverse-event-identity.md)
q_adverse_event_terms -- standardized adverse-event terms (owned by 32-slice-endpoint-adverse-event-identity.md)
q_ae_grade_vocabulary -- CTCAE grade bands, separate from seriousness (owned by 32)
q_organisations -- canonical organisation facts (owned by 26-slice-organisation-intelligence.md)
q_development_programs -- current contextual therapeutic-development state (owned by 33-slice-development-landscapes.md)
q_epidemiology_observations -- full-grain disease-burden observations (owned by 34-slice-epidemiology.md)
q_product_sales -- source-reported product commercial observations (owned by 35-slice-commercial-intelligence.md)
q_catalog -- generated catalog of q_* models/columns/comments/contracts
q_provenance -- explain surface -> source/evidence/resolution-verifier/canonical/curation-overlay receipts

(Slice-specific models are defined and owned in their slice docs, not here. Cross-doc naming is reconciled as follows so global query, gates, and tests agree:

  • Regulatory approvals own q_drug_approvals (one approval), q_approval_indications (one indication assertion), and the downstream meaning of resolved_approval_key(s). They are sibling models at different grains, not renames (22-slice-regulatory-approvals.md).
  • Publications own q_publication_evidence (broad evidence search) and q_publication_outcomes (one endpoint/group/statistic). q_publication_outcomes is a sharper-grain sibling of q_publication_evidence, not a replacement (23-slice-publications.md).
  • Clinical trials own q_trials, the downstream meaning of resolved_trial_key(s), and q_publications-adjacent links via q_trial_references; q_publications itself is owned by the publications slice (21/23).
  • Discovery/search owns q_discovery_chunks and the other q_discovery_*/q_search_* models; resolved_entity_keys is only a reference union over keys owned by other slice/spine docs, not a new identity namespace (27-slice-discovery-search.md).
  • Standard of care owns q_standard_of_care_recommendations, the other q_soc_* models, soc_key, and approach_key; news owns q_news_events; organisation intelligence owns q_organisations-family models and the downstream meaning of resolved_org_key(s).
  • Drug identity owns the q_drugs family (q_drugs, q_drug_aliases, q_drug_external_ids, q_drug_brands, q_drug_regimens) and the canonical meaning of resolved_drug_key(s) (29-slice-drug-identity.md). q_diseases/q_biomarkers families are owned by 30-slice-disease-biomarker-identity.md, which also defines the canonical meaning of resolved_disease_key(s), resolved_biomarker_key(s), segment_key, and treatment_line_key. Target/technology identity owns q_targets, q_target_aliases, q_drug_target_actions, q_technologies, q_technology_hierarchy, q_drug_technologies, q_payloads, and q_drug_payloads, plus the canonical meaning of resolved_target_key(s) and resolved_technology_key(s) (31-slice-target-technology-identity.md). Endpoint/adverse-event identity owns q_endpoints, q_endpoint_groups, q_adverse_event_terms, and q_ae_grade_vocabulary, plus the canonical meaning of canonical_endpoint_key and resolved_ae_term_key(s) (32-slice-endpoint-adverse-event-identity.md); trials/publications/SOC reference these keys rather than minting endpoint identity, and keep regulatory seriousness separate from CTCAE grade.
  • Development programs owns q_development_programs, q_development_program_state_history, q_development_program_milestones, q_development_program_evidence, and q_emerging_clinical_evidence. Drug identity does not own phase or development status (33-slice-development-landscapes.md, ADR 0008).
  • Epidemiology owns q_epidemiology_observations, q_epidemiology_series, and q_disease_epidemiology_summary (34-slice-epidemiology.md). Commercial intelligence owns q_product_sales and q_product_commercial_summary (35-slice-commercial-intelligence.md). Regulatory approvals owns q_regulatory_product_protections; commercial summaries may project its canonical facts without duplicating ownership.

Any example or fixture in 08/10 must reference one of these owned model names.)

Query surfaceProducing ownerRole of this doc
q_catalog07-sql-query-layer.mdOwn generated catalog semantics and required metadata fields.
q_provenance07-sql-query-layer.mdOwn global explain-view semantics over provenance/evidence/resolution/curation receipts.
Clinical-trial q_* family21-slice-clinical-trials.mdRegister names and global contract expectations only.
Regulatory q_* family22-slice-regulatory-approvals.mdRegister names and global contract expectations only.
Publication q_* family23-slice-publications.mdRegister names and global contract expectations only.
News/intelligence q_* family24-slice-news-intelligence.mdRegister names and global contract expectations only.
Standard-of-care q_* family25-slice-standard-of-care.mdRegister names and global contract expectations only.
Organisation q_* family26-slice-organisation-intelligence.mdRegister names and global contract expectations only.
Discovery/search q_* family27-slice-discovery-search.mdRegister names and global contract expectations only.
Forecasting/TPP support q_* family28-slice-forecasting-tpp.mdRegister names and global contract expectations only.
Foundational identity q_* families2932Register names and shared-key contract expectations only.
Development-program/landscape q_* family33-slice-development-landscapes.mdRegister names and global contract expectations only.
Epidemiology q_* family34-slice-epidemiology.mdRegister names and global contract expectations only.
Commercial-intelligence q_* family35-slice-commercial-intelligence.mdRegister names and global contract expectations only.

Do not overload one table with every kind of metadata.

ConcernSource of truthAgent-facing surfaceWhy
Table/column existence, type, nullability, commentsPostgres information_schema / catalogs and COMMENT ON TABLE/COLUMNq_catalog generated viewThe database already knows physical shape and supports comments; duplicating this by hand creates drift. (https://www.postgresql.org/docs/current/information-schema.html, https://www.postgresql.org/docs/current/sql-comment.html)
Asset/materialization lineageDagster asset graph and materialization metadataDagster UI/metadata; optional exported metadataDagster assets natively model upstream/downstream dependencies and materializations. (https://docs.dagster.io/guides/build/assets)
Column-level transformation lineageDagster TableColumnLineage metadata and/or OpenLineage column-lineage facetDagster/OpenLineage catalog, not normal agent SQLColumn lineage is transformation metadata, not domain evidence. Dagster has table schema/column-lineage metadata; OpenLineage has a column-lineage facet for dataset fields. (https://docs.dagster.io/api/dagster/metadata, https://openlineage.io/docs/spec/facets/dataset-facets/column_lineage_facet/)
Source/evidence/resolution/curation trust for factsSource artifacts, extraction runs, evidence claims, resolution/verifier receipts, canonical assertions, curation overlays when applicableq_provenance generated explain viewAgents need receipts: source locator, authority, extractor, verifier state, curation review state when an override exists. This is domain provenance, closer to W3C PROV’s entity/activity/agent framing than to database schema metadata. (https://www.w3.org/TR/prov-overview/)

q_catalog is a read-only generated catalog view that makes the SQL layer self-discoverable. It has one row per published q_* model column and combines:

  • Postgres physical metadata from information_schema and system catalogs;
  • Postgres table/column comments;
  • ops.query_contract_columns, regenerated by the Dagster ops.query_contract_metadata asset from checked-in contracts_schema/*.yaml.

The YAML contracts are the executable source of grain, stable row key, owner, closed enum, provenance policy, version, and deprecation state. Postgres is the executable source of physical shape. Product docs explain semantics but are not parsed at runtime. Unregistered q_* relations remain visible with null contract fields and fail the blocking catalog_contract_coverage check.

ColumnTypeRequiredMeaning
model_schematextyesAlways query unless a future warehouse dialect forces a different namespace.
model_nametextyesPublished model name, e.g. q_trials.
column_nametextyesPublished column name.
ordinal_positionintegeryesStable display/order position.
data_typetextyesSQL type family exposed to agents.
udt_nametextnoPostgres-specific underlying type where useful.
is_nullablebooleanyesContracted nullability.
is_primary_key_partbooleanyesWhether the column participates in the stable row key.
graintextyesRow grain for the model, repeated on every column for easy agent discovery.
allowed_valuestext[]noSmall closed enum values, if applicable.
descriptiontextyesHuman-readable column definition.
owner_slicetextyesSlice responsible for the column contract.
provenance_requiredbooleanyesWhether non-null values need row-level or field-level provenance in q_provenance.
provenance_graintextyesnone, row, field, or bundle. bundle means a stable provenance_key expands into multiple receipts.
comment_sourcetextyespostgres_comment, contract_metadata, or generated.
asset_keytext[]yesDagster query asset that owns the column.
contract_versiontextyesVersion in which the column contract is active.
contract_statustextyesactive or deprecated.
introduced_attimestamptzyesExplicit contract date, version date, or the catalog-baseline date for older undated contracts.
deprecated_afterdatenoEarliest removal date after overlap, if deprecated.

Contract rules:

  • every published q_* column must have exactly one active catalog row;
  • q_catalog must not describe internal source/evidence/canonical tables;
  • additive columns are allowed only when comments and contract metadata appear in the same change;
  • removed or renamed columns require a versioned successor model or a deprecation overlap window.

The catalog intentionally does not invent a generic semantic-type or index-contract language before the repository has an executable consumer for it. Units, large biomedical vocabularies, and search behavior remain in owning column comments, vocabulary relations, and query recipes. Small closed enums use allowed_values. Physical performance indexes remain checked-in SQL and database catalog facts; adding a stable agent-facing index contract later requires a real checker in the same change.

q_provenance is not a monolithic lineage ledger and not a hand-maintained sidecar. It is a generated/read-only SQL explain view over first-class domain provenance tables. Its conceptual shape follows W3C PROV: entities (source artifacts, evidence claims, resolution candidates, verifier receipts, canonical assertions, curation overlays, and query facts), activities (ingestion, extraction, resolution, verification, curation review, materialization), and agents (source systems, extractors, LLM/model/prompt versions, curator agents, and human reviewers). This does not require RDF/PROV-O storage in v1; it requires the relational model to keep the same distinctions. (https://www.w3.org/TR/prov-overview/, https://www.w3.org/TR/prov-dm/)

The word “lineage” overloaded too many jobs, so the greenfield contract splits it:

QuestionOwnerAgent SQL surfaceNotes
Where did the value come from?source artifact + source locatorq_provenanceExact immutable source snapshot/document/API row/span/table/page/payload path. A live URL alone is never enough.
Why is this value trustworthy?evidence claim + resolution/verifier receipt + canonical assertion + curation overlay if applicableq_provenanceReceipts for source authority, assertion state, verifier basis, curation review state, and conflict/supersession status.
How did pipeline code transform it?Dagster asset graph, materialization metadata, column lineage; optional OpenLineage exportDagster/OpenLineage, not normal agent SQLThis is transformation lineage. Dagster has typed metadata including table schema/column lineage; OpenLineage has dataset facets such as column-level lineage. (https://docs.dagster.io/api/dagster/metadata, https://openlineage.io/docs/spec/facets/dataset-facets/column_lineage_facet/)

q_provenance therefore answers:

For this q_* row or semantic fact, which immutable source artifact, evidence claim,
resolution/verifier receipt, canonical assertion, and optional curation overlay make it publishable?

It deliberately does not answer:

Which upstream table columns produced this SQL expression?

That second question belongs to Dagster/OpenLineage column lineage.

First-class provenance tables behind the view

Section titled “First-class provenance tables behind the view”

The generated view expands the following durable nouns. Exact physical schema can be refined per slice, but the concepts must exist before high-impact q_* facts publish.

Table / asset conceptGrainRequired responsibility
provenance.source_artifactsone immutable source snapshot, document, release, or API payloadStore source_artifact_key, source family, source native id/version/release/snapshot id, immutable storage URI, content hash + algorithm, source URL if any, observed/fetched timestamps, and retrieval metadata.
provenance.extraction_runsone parser/LLM/verifier extraction activity over one artifact or partitionStore extractor code version, prompt/schema/model version where applicable, run id, started/ended timestamps, and deterministic config.
evidence.evidence_claimsone source-grounded claim extracted from an artifactStore claim type, subject candidate, claim payload, source locator, source authority tier, extraction run id, and claim state.
resolution.resolution_candidatesone proposed link from source mention/claim to canonical subjectStore candidate target, basis category, verifier status, ambiguity set, and acceptance/supersession state.
curation.decision_eventsone append-only curator-agent/human-reviewed overlay eventStore actor, decision type, rationale, review state, precedence, idempotency key, supersession link, and affected subject/assertion.
canonical.canonical_assertionsone effective quality-passing fact or relationshipStore canonical subject, assertion type, value payload, temporal validity, effective state, and owning canonical asset.
provenance.assertion_provenance_linksone receipt link from canonical/query fact to its supportJoin assertions to evidence claims, source artifacts, extraction runs, accepted inference decisions, resolution/verifier receipts, and curation overlays when applicable with role and semantic fact_path.

This table set keeps domain provenance normalized and queryable without forcing every q_* row to carry dozens of evidence columns. It also lets reviewed curation overlays change effective truth without rewriting immutable source artifacts or historical extraction runs.

q_* models should remain readable. Each row has one stable scalar key that maps to q_provenance.q_row_key; high-impact rows or facts may also carry a compact provenance_key that represents an explanation bundle. q_provenance expands that key into one or more receipts.

For a single-column primary key, that column is the provenance row key by default. A model with a natural composite key must expose a deterministic scalar relation key and declare it as provenance_row_key in the checked-in contract. The provenance gate fails closed when a composite contract omits this mapping; it never silently uses only the first key component.

query.q_trial_outcomes.provenance_key = 7b3d...
-> primary registry result claim
-> supporting publication claim
-> accepted endpoint-resolution/verifier receipt
-> canonical outcome assertion
-> Dagster materialization run id

Use q_catalog.provenance_grain to declare required coverage:

GrainMeaning
noneConvenience/derived/display value that does not need direct receipts.
rowOne receipt bundle explains the row as a whole.
fieldSpecific high-impact scalar fields require their own semantic receipt.
bundleA row or fact carries a stable provenance_key that expands into multiple receipts.

q_provenance has one or more rows per provenance-bearing q_* row/fact. It does not require every low-risk convenience column to explode into sidecar rows; q_catalog.provenance_required and q_catalog.provenance_grain define where provenance is mandatory.

ColumnTypeRequiredMeaning
provenance_iduuidyesStable generated provenance row id.
q_model_nametextyesPublished model name, e.g. q_trials.
q_row_keytextyesStable row key used by the model.
q_row_key_hashtextyesHash for compact joins and drift checks.
fact_pathtextnoSemantic path to the fact being explained; null means row-level. Use stable business paths, not brittle JSON array indexes.
receipt_kindtextyessource_artifact, extraction_run, evidence_claim, resolution_candidate, verifier_receipt, inference_decision, canonical_assertion, curation_overlay, materialization, or search_source.
activity_kindtextnoingestion, extraction, normalization, resolution, verification, curation_review, canonicalization, query_materialization, or search_projection.
provenance_roletextyesprimary, supporting, conflicting, superseded, curation_overlay, or search_source.
required_for_publicationbooleanyesWhether this receipt is part of the complete gate-required bundle for the row/fact.
receipt_statustextyesactive, superseded, rejected, warning_only, or quarantined.
provenance_keyuuidnoEvidence/explanation bundle key when multiple receipts are grouped.
canonical_asset_keytext[]noDagster asset key for the canonical assertion source.
canonical_assertion_iduuidnoEffective assertion behind the visible row/value.
evidence_claim_iduuidnoSource-grounded evidence claim behind the assertion.
curation_decision_idtextnoOpaque effective reviewed curation/override decision id, if applicable.
resolution_candidate_iduuidnoResolution record used to link a source mention to a canonical subject.
extraction_run_iduuidnoExtraction/verifier activity that produced or checked the claim.
inference_decision_iduuidnoAppend-only accepted decision authorizing a projected inference value.
inference_decision_statetextnoDecision state retained by the inference lifecycle. Published projected values require accepted.
inference_policy_key, inference_policy_revisiontextnoDeterministic acceptance policy that authorized reuse/projection.
inference_attempt_iduuidnoImmutable provider attempt selected by the decision.
inference_profile_key, inference_profile_revisiontextnoExecution profile snapshot identity for the attempt.
inference_request_keytextnoProvider-independent semantic request identity.
inference_task_key, inference_contract_revision, inference_contract_hashtextnoExact task contract governing the projected value.
source_artifact_keytextnoImmutable source snapshot/document/version key.
source_immutable_uritextnoInternal immutable storage URI; required for document/payload-derived claims.
source_content_hashtextnoHash/checksum of the exact artifact used.
source_locatorjsonbnoRow, section, table, span, page, URL, API id, or payload path locator within the artifact.
source_authority_tiertextnoClaim-specific trust tier used by quality gates.
assertion_statetextyesaccepted, agent_verified, curation_override, provisional, warning_only, etc.
review_statetextnoCuration review state when receipt_kind='curation_overlay', e.g. not_required, pending_human_review, human_approved, human_rejected.
resolution_basistextnoexact, cross_reference, context_verified, fuzzy_llm, reviewed_curation_override, etc.
extractor_versiontextnoDeterministic parser / LLM extractor / prompt schema version.
materialization_run_idtextyesDagster run id that produced the visible row.
observed_attimestamptznoSource observation time.
valid_fromdatenoStart of asserted validity when temporal.
valid_todatenoEnd of asserted validity when temporal.

At least one of canonical_assertion_id, evidence_claim_id, or source_artifact_key must be present on each receipt row. A provenance-required row/fact is publishable only when the complete receipt set required by q_catalog.provenance_grain, the source family, and the gate contract is present. High-impact canonical facts must include source artifact, extraction run, evidence, resolution/verifier, and canonical assertion receipts; curation receipts are required when an override affects the fact. Document/payload-derived facts must include immutable artifact URI and content hash. Discovery/search rows must trace to the source q_* row or content item they index.

fact_path names the business fact, not a fragile physical JSON path. Examples:

trial.status
trial_outcome:endpoint=orr:group=experimental:attr=p_value
approval_indication:drug=trastuzumab:disease=breast_cancer:attr=label_text
publication_outcome:pmid=123:endpoint=pfs:arm=control:attr=hazard_ratio
organisation_relationship:parent=pfizer:child=seagen:attr=valid_from

The slice docs define allowed fact-path conventions for their query models. A path must remain stable across harmless physical reshaping of arrays, tables, or SQL implementation.

Field-level provenance needs a generated contract so checks can compare required semantic paths against emitted receipts. The implementation may expose this as a view or as rows inside the same contract registry that generates q_catalog; either way, provenance_coverage must be able to query it.

ColumnMeaning
model_namePublished q_* model.
fact_path_patternExact path or parameterized pattern, e.g. trial_outcome:*:attr=p_value.
column_namesOne or more columns whose values require this path.
required_receipt_kindsReceipt kinds required for publication, e.g. source artifact + extraction run + evidence claim + verifier receipt.
source_authority_ruleAllowed source authority tiers for this fact path.
gate_idsGate ids that enforce the path.
contract_versionVersion of the fact-path contract.

Each q_* row should include a compact stable row key and, where useful, an explanation handle such as provenance_key or canonical assertion id. The row itself stays readable; detailed receipts live in q_provenance.

select t.trial_key, t.brief_title, t.trial_status, p.source_authority_tier, p.source_locator
from query.q_trials t
join query.q_provenance p
on p.q_model_name = 'q_trials'
and p.q_row_key = t.trial_key
where t.trial_key = 'NCT01234567'
and (p.fact_path is null or p.fact_path = 'trial.status');
  • Prospective provenance is the contract/check expectation: q_catalog.provenance_required, provenance_grain, source-authority rules, and gate factory configuration.
  • Retrospective provenance is what actually happened for a specific row/fact: the q_provenance receipts emitted for a materialization run.

Checks compare the two. If the contract says a fact requires bundle provenance and the materialized row has no complete bundle, publication fails.

There is one authoritative global q_provenance explain surface. Slice docs may define convenience views such as q_trial_provenance or q_regulatory_provenance, but they must be simple filters/projections over q_provenance; they are not separate stores. Agents can always fall back to:

select *
from query.q_provenance
where q_model_name = 'q_trials'
and q_row_key = :row_key;

Each slice doc defines its query-family contract. Checked-in contracts, Postgres metadata, and database comments are compiled into q_catalog; the prose remains the owning semantic explanation rather than a second runtime registry.

For every q_* model, specify:

  1. Purpose — what agent question the model answers.
  2. Grain — exactly one row per what.
  3. Stable row key — columns or expression used for q_row_key.
  4. Required columns — name, type, nullability, semantic type, definition.
  5. Search affordances — filters, trigram columns, tsvector, vector embeddings, facets, and required indexes.
  6. Provenance rule — which rows/facts require q_provenance, which provenance_grain applies, and which source/evidence/resolution-verifier/canonical/curation-overlay ids must appear.
  7. Refresh policy — view/materialized view/table plus cadence/trigger.
  8. Deprecation policy — how breaking changes are versioned.

This keeps 07 global and lets entity resolution/domain modelling stay slice-local.

  • existence: every catalogued q_* table/view exists;
  • shape: column names, types, nullability, and grain match q_catalog;
  • catalog generation: q_catalog matches actual Postgres schema/comments plus checked-in contract metadata;
  • provenance: every q_* row/fact marked provenance_required resolves to the complete q_provenance receipt set required by q_catalog.provenance_grain, q_fact_path_contract, and the relevant gate ids;
  • publication gate: only quality-passing assertions plus reviewed curation overlays appear (see 08-contracts-and-quality.md).

Drift in any of the above is a breaking-change failure.

  • Postgres is the query engine. A warehouse is a future deployment decision only if measured scale or workload isolation requires it; it does not alter the q_* SQL contract.
  • Each model declares its physical materialization and publication-family policy. Concurrent materialized-view refresh is allowed only when its qualifying unique index is part of the checked contract; generation-backed families promote only as complete non-subsettable units.
  • contract_version is an opaque, non-empty model contract identifier. Consumers compare it for equality, never parse it. It remains stable across compatible refreshes and changes whenever columns, grain, semantics, or provenance obligations change.