DataShield Ontology · documentation

Governance and Privacy

Measured against: /home/datashield/library at v0.22.188 (read-only pass, 2026-09-22). Audience: data-governance and privacy teams, developers, and AI agents driving the MCP surface. How to read this document: every claim carries a file:line citation into the tree it was measured from. Where the code and a stated objective disagree, the disagreement is written down rather than smoothed over (CLAUDE.md META-CALIBRATION 5). Normative keywords (MUST / SHOULD / MAY) are used per RFC 2119 only where the cited standard uses them.


On this page

1. The doctrine in one page — STANDARD-009

The privacy doctrine lives in one document: docs/standards/STANDARD-009-privacy-classification-and-masking.md (status MANDATORY, :3). It governs what a column is (classification) and what the platform then does about it (governance, masking, refusal) (:33-38). It binds every producer and consumer of a column classification, every masking seam, the PHI egress gate, and every committed artifact that records a classification (:4-6, :42-59).

The fifteen rules (PC-1 … PC-15) in plain language:

RulePlain-language meaningWhere it is measured
PC-1 One kernel, pureEvery classification decision comes from one function in lib/classification/. It never reads a database, file, clock, network, env var, or random source. Private "is this PII?" helpers elsewhere are forbidden and are deleted, not deprecated.STANDARD-009:80-87; kernel entry lib/classification/classify.ts:73 (classifyColumn(e: ColumnEvidence)), :519 (classifyTable); gate audit:classification-kernel-purity
PC-2 One governance producerOnly deriveGovernance(decision, regime) produces the governance block (piiDetected, phiDetected, securityLevel, encryptionRequired, maskingRules, accessPolicy). Every field is derived through a config ladder, never typed literally at a call site.STANDARD-009:89-95; lib/classification/governance.ts:46; ladder config/classification-evidence.config.ts:871 (GOVERNANCE_DERIVATION); gate audit:classification-governance-coherence
PC-3 One pattern library, as data, joined on ClassIdThe pattern corpus is configuration data, consumed by server lanes and the browser editor from the same artefact. Every join (mask token, severity, regulation, category) keys on ClassId, never on a display name — two distinct classes already shipped both displaying as "DEA Number".STANDARD-009:97-105; config/classification-patterns.config.ts:77 (CLASSIFICATION_PATTERNS, 129 "id" rows measured; :5312 index CLASSIFICATION_PATTERN_BY_ID)
PC-4 unclassified is not publicFive honest states: unscanned (we did not look), unclassified (we looked, nothing cleared its floor), candidate (plausible), classified, overridden. unclassified and candidate derive a non-PUBLIC floor (default INTERNAL). A surface that renders an unlabelled column as safe is non-conformant.STANDARD-009:109-116; vocabulary table :63-72
PC-5 Fail-closed readersA consumer meeting an unknown class, unknown state, missing decision, stale classification_ref, or unavailable classifier must not serve raw values or publish.STANDARD-009:118-124; lib/analytics/classificationRef.ts
PC-6 Value-free artifactsFixtures, corpora, baselines, probe captures, shadow diffs, impact ledgers, bug files, vet records and release notes must not contain a customer value, secret, credential or anything derived from one — shapes only.STANDARD-009:128-139; lib/classification/valueLeak.ts; config/dataset-field-projection.config.ts:153 (FIELD_VALUE_BEARING_KEYS)
PC-7 Masking OFF by default; legally-required onlyOperator rulings R2/R3 (2026-09-06) are reproduced verbatim and may not be re-opened. Posture default development (raw-by-default). Classification is still computed and listed regardless — visibility is not masking. Explicit requests and posture-independent surfaces (the mdm.golden_v1_* views) always mask. A caller-selectable masking framework may not appear on a read surface. No agent introduces a new privacy rule without an operator ruling.STANDARD-009:143-170; config/masking-policy.config.ts:77-89
PC-8 Error paths may not change the masking decisionUnknown-state policies are config-declared (RELOAD_MASKING_ON_UNKNOWN = keep_previous, QUERY_MASKING_ON_UNKNOWN = refuse) and disclosed. A catch that yields "unmasked" is forbidden; so is a fix that turns masking on where doctrine says off.STANDARD-009:172-178; lib/query/maskingPolicy.ts
PC-9 Proposers propose, rules veto, humans on disagreementSee §1.1.STANDARD-009:182-195. The policy is declared in the standard's own table; config/classification-arbitration.config.ts is named there but does not exist in the tree at v0.22.188, and its gate audit:classification-arbitration-integrity is planned — P4 (:320)
PC-10 Protective-only overridesAn override carries actor, reason and evidence legs and writes a ledger row. Relaxing a corroborated PII verdict is refused with a typed refusal, whoever asks. One reclassification verb.STANDARD-009:197-202; gate audit:classification-decision-integrity planned — P3 (:321)
PC-11 Browser, session and model proposals never write directlyA payload from a browser engine, a session agent, or a model is never written verbatim to pii_class, semantic_type, governance, classification_state, has_pii, has_phi, compliance_level.STANDARD-009:204-214
PC-12 Inheritance is declaredA decision inherited through a derivation (join/union/transform) is declared as inherited, not assumed fresh.STANDARD-009:216-225; live inheritance leg planned — P2 (:322)
PC-13 Append-only decisions, provenance mandatoryEvery decision is a new row in an append-only ledger; the live column holds a pointer to the head that is gate-checked against the derived head. Every row carries source, tier, model/prompt version.STANDARD-009:229-238; lib/analytics/evidenceLedger.ts. audit:audit-log-immutability gates the general audit log, not the classification decision ledger: the standard's own PC-13 gates (audit:column-writer-ownership, audit:classification-decision-integrity) are planned — P3 (:323)
PC-14 Measure before and afterNo classification, masking or PHI-gate change ships without a before and an after measurement using the committed script.STANDARD-009:242-266; audit:classification-baseline, audit:classification-shadow-diff, audit:classification-impact-ledger
PC-15 The doctrine is gated or it is theatreA change to classification, masking or the PHI gate updates this standard, docs/codebase/ and the release notes in the same change, and every rule above names the gate that checks it. A rule with no gate is recorded as planned and may not be described anywhere as enforced. Doc claims about this seam are themselves checkable facts.STANDARD-009:270-277; enforcement table :307-328

Which of these are actually enforced: STANDARD-009:298-328 is the authority, and its own status vocabulary (:300-305) distinguishes chained (a release:gates link today) from unchained (exists, run deliberately) from planned (does not exist yet). PC-1, PC-2 (legs 1–3), PC-3, PC-5's golden-boundary leg, PC-6's residue gate and PC-14's regression/quality gates are chained; the PC-4/PC-5 fail-closed gate, the PC-9/PC-11 arbitration gate, the PC-10 override-direction gate, the PC-12 live inheritance leg and the PC-13 writer-ownership gates do not exist yet. Nothing in that table may be read as enforced until it is chained.

1.1 Who decides (PC-9, A1–A8)

STANDARD-009:186-195 declares the arbitration policy as a table; the operational meaning:

  1. The rule floor vetoes. A proposal failing gates G1–G7 is suppressed with a disclosed reason — "a veto a vote could reverse is not a veto" (A1). The kernel comment at lib/classification/classify.ts:195 names the forbidden case: a vote that moves unclassified to classified by removing a deterministic suppression.
  2. Votes are over the vocabulary bucket (pii | secret | format, config/conduit-analysis.config.ts:273 PATTERN_CATEGORY_VOCABULARY), never the pattern id; the id is chosen by the specificity lattice (lib/classification/lattice.ts) (A2).
  3. Abstention is not dissent — an engine outage cannot change a classification (A3).
  4. Disagreement produces candidate plus a steward-queue entry. That is the only point where a human appears; silent tie-breaks are forbidden (A4), and the interim tie-break is the more protective bucket, with the dissent recorded verbatim (A5).
  5. Every proposal, including losers, is recorded with tier and model/prompt version (A7); the governance bucket is derived from the id, never from a proposer's self-report (A8 — measured contradicting its own id 3 times in 40).

2. The kernel and its configuration

ModuleRole (measured)
lib/classification/classify.ts522 lines. classifyColumn(e: ColumnEvidence): ClassificationDecision (:73); candidate set built from regex hits, name-lexicon rules, secret rules, custom detectors and generalizer hints (:113-124); per-class floors resolve to classified / candidate / below-floor (:12). classifyTable (:519).
lib/classification/governance.ts:46deriveGovernance(decision, regime) — the single PC-2 producer.
lib/classification/frameworks.tsobligationsFor(classId) — the ONE reader of the compliance-obligation table (config/classification-frameworks.config.ts:24).
lib/classification/index.ts, patterns.ts, lattice.ts, regexSafety.ts, valueLeak.ts, shadowSink.ts, digest.ts, wire.ts, types.ts, collect/, signals/, text/Pattern access, specificity lattice, regex-safety gate, value-leak detector (PC-6), shadow-run sink (PC-14), evidence digesting, wire shapes.

2.1 Compliance frameworks and obligationsFor(classId)

config/classification-frameworks.config.ts declares seven frameworks (COMPLIANCE_FRAMEWORKS, :52-59) with edition, jurisdiction and a citation URL — five active and two charter. A charter row is a crosswalk placeholder and MUST carry zero obligations; an active row MUST carry at least one (:22-23, validator :209):

idFrameworkEdition citedStatusLegacy tags absorbed
hipaaHIPAA Privacy Rule — Safe Harbor de-identification45 CFR §164.514 (2013 Omnibus)activeHIPAA
gdprGeneral Data Protection RegulationRegulation (EU) 2016/679activeGDPR, UK-GDPR
pci_dssPCI Data Security Standardv4.0.1 (2024)activePCI-DSS, PCI
soc2AICPA SOC 2 Trust Services CriteriaTSC 2017 (2022 revised points of focus)activeSOC2
fedrampFedRAMP Moderate baselineRev. 5 (2023)activeNIST
iso27701ISO/IEC 27701 Privacy Information Management2019charterISO27001
nist_800_53NIST SP 800-53 Security and Privacy ControlsRev. 5 (2020)charter

Obligations are rows joined on ClassId (COMPLIANCE_OBLIGATIONS, :108-163): HIPAA Safe-Harbor letters A–Q are attached to the kernel's hipaa_* classes across 21 rows (e.g. hipaa_email → letter F, :115; hipaa_ssn_dashed/hipaa_ssn_nodash → G, :116-117); letter R, the statute's catch-all "any other unique identifying number", has no kernel class and so no row. One builder per active framework — HIPAA Safe Harbor, GDPR personal-data, PCI PAN, SOC 2 credential, FedRAMP PII (:78-102) — emits 49 obligations in total. Obligation text is bounded to 240 characters and must carry an RFC 2119 keyword (:74-76). The compliance[] free strings that predate this table (PCI-DSS vs PCI) are recorded as the disagreement this file resolved (:8).

Count discipline (a live disagreement, verified twice): STANDARD-009 :72 warns that the 18 statutory HIPAA identifiers and the number of hipaa_* pattern rows are different numbers and must not be conflated, and puts the pattern-row figure at 10 after the Safe-Harbor taxonomy split (restated at :276). The live config does not reproduce it: grep -c '"id": "hipaa_' config/classification-patterns.config.ts measures 40 rows, of which 12 carry the PHI category and 33 carry PII_QUASI_IDENTIFIER — so 10 is not the count of hipaa_-id rows, nor of PHI-category rows, under any reading. Treat the live config as authoritative and the standard's figure as a stale snapshot; PC-15 (:270-277) makes the mismatch a defect of the standard, not a cosmetic one.

2.2 The regex-safety gate

config/classification-regex-safety.config.ts makes every kernel regex answer to a structural bound and an adversarial time budget (:7):

2.3 A naming disagreement to know about

The MCP umbrella named classification is not the PII kernel. Its published description (docs/versions/v0.22.188/tools/classification.md:14-16) is "Product/industry classification catalog lookup + AI dataset tagging with a human-review workflow" — six commands: systems_list, lookup (UNSPSC-style codes), dataset_classify, batch_classify, proposals_list, proposal_decide (:18-23). It shares the STANDARD-009 posture that proposals never auto-apply (batch_classify "never auto-applies"; proposal_decide is the only way a proposal becomes live), but its subject is product/industry taxonomy tags. The PII/PHI kernel is reached through the catalog and loader seams (lib/data_catalog/piiLabel.ts, lib/query/loader.ts), not through a same-named umbrella. Agents searching for "classification" should read both.


3. Masking

3.1 Posture

config/masking-policy.config.ts is "the privacy-posture knob" (:4). Two postures (:19-26): development (DEFAULT — the loader applies no auto-masking at any compliance level) and protected (auto-mask per reconciled authority). MASKING_POLICY_CONFIG.posture = "development" (:89), typed as the union so === "protected" comparisons still type-check (:87). Three things are posture-independent by design (:43-69): the MDM read boundary (the inner compliance boundary, always_protected, :50-54), at-rest write maskers (a value captured under development must not become exposable by a later flip, :59-61lib/mdm/goldenRecordMasking.ts maskFreeTextPiiAlways), and any explicit per-dataset masking_mode. The documented consequence — one golden served raw by the read boundary while the golden_v1_* view masks it, under development — is stated so it "can never again be read as a defect" (:64-69).

3.2 masking_set and the masked-view family

3.3 generalization — privacy-preserving column transforms

Umbrella generalization (7 commands: list, apply, preview, update, delete, bulk_apply, stats; docs/versions/v0.22.188/tools/generalization.md:14). View-mode (reversible masking at query/prompt egress) works; physical in-place transform is not implemented and returns not_implemented (FEAT-033) (:16). config/generalization.config.ts declares a strategy↔column domain-fit preflight (domainFitMinHitRate, :29-44, LIB-BUG-482) and a per-regime strategy map (COMPLIANCE_STRATEGY_MAP, :96-101): hipaadob_generalize, zip_generalize, age_band; gdpremail_domain, phone_partial; ccpassn_partial, email_domain; pciempty, deliberately — no built-in strategy addresses PAN (:93).


4. Sample values, statistics and acknowledgements

4.1 The sample-value ladder

config/data-catalog.config.ts defines SAMPLE_VALUE_POLICIES = ["plain", "masked", "omit"] (:1110) and SAMPLE_VALUE_POLICY with default: "omit" (:1116). The prior default was plain (operator ruling 2026-09-06, :1088); plain remains available but requiresAcknowledgement: ["plain"] (:1133) — a caller must pass acknowledge_plain_samples: true, and the acknowledgement is written to the job record (:1106). masked is shapeOnly (:1158); omit is the withheldPolicy (:1146). The ladder's rungs are properties of a catalog.* asset: column / scope / provider / platform (config/dataset-field-projection.config.ts:22), with scope outranking provider (config/data-catalog.config.ts:1123).

config/dataset-field-projection.config.ts closes the read side: the registry detail read had bypassed the ladder (:16); it now resolves the same ladder (no second ladder, no new rule — :11-13) and, when it withholds, writes a sample_values_withheld: { reason, policy } marker (SAMPLE_WITHHELD_KEY, :107) citing GDPR Art. 5(2) accountability (:55). Reasons are a closed vocabulary of five (:87-102): audience_not_entitled (the audience floor — a public audience never receives values), sample_policy_omit, plain_samples_not_acknowledged, sample_policy_masked, sample_policy_plain. Value-bearing keys are absent, not nulled, so the marker is not an existence probe for anonymous callers (:59-61).

4.2 Export statistics and sidecars

lib/catalog/exportCatalog.ts writes sidecars into the customer's destination bucket beside the data (config/catalog-export-statistics.config.ts:5): catalog/_metadata/governance.json carries "PII exposure, masking rules, framework applicability" (exportCatalog.ts:9) and has exactly one writer (:134). Sidecar format versions (config/catalog-export-statistics.config.ts:75-88): dataset 1.0, schema 1.1, lineage 1.0, quality 1.1, governance 1.3 — 1.3 added data_file, the first governance claim about the data artefact itself rather than about the generated masked view (LIB-BUG-1412), after LIB-BUG-1394 found a sidecar claiming masking no artefact applied (:22).

EXPORT_STATISTICS_POLICIES = ["omit", "aggregate_only", "plain"] (:29); statistics_policy is stamped on each document (:62-70). lib/catalog/statisticsPolicy.ts resolves the policy (resolveExportStatisticsPolicy, :81) and throws ExportStatisticsAcknowledgementError when a plain-persisting policy is requested without acknowledgePlainStatistics: true (:90-91); the value-exposure predicate is shared with the catalog ladder (policyPersistsPlainValues, :26) so this module "contributes no policy vocabulary" (:14).

4.3 The acknowledgements audit

audit:catalog-plain-sample-sweep (scripts/audit/catalog-plain-sample-sweep.ts, LIB-BUG-1041 item 3) reports every row still at plain. It is read-only by default: an earlier version healed legacy acknowledgements forward into the immutable ledger as a side effect of reading; the heal is now opt-in (--heal) and announced in output (:5-9). Sibling gates measured in package.json: audit:sample-store-integrity, audit:classification-config-agreement, audit:classification-row-predicate, audit:classification-single-seam, audit:governance-vocab-integrity, audit:catalog-classification-quality, audit:classification-coverage-floor, audit:classification-ootb, audit:classification-golden-file, audit:classification-golden-bakeoff, audit:classification-regression.


5. Stewardship — what a steward does

5.1 The MCP surface

Umbrella stewardship (29 commands, docs/versions/v0.22.188/tools/stewardship.md:14-16): worklists (worklist_get), supervised proposals (proposal_get, proposal_decide), pattern trust (trust_status), notification config, audit_queue, disposition rules (rule_enact / rule_release / rule_suspend / rule_resume / rule_retire / rule_backfill / rule_status), masked golden consumption (golden_read, golden_events), quality KPIs (quality_recovered, quality_status, quality_refresh), predictive recommendations (recommendations, recommendation_summary, recommendation_decide, recommendation_efficacy, recommendation_refresh), and dashboard reads (flow_summary, subflow_summary, workbench, alerts_queue, impact_preview). Golden changes go through one decision writer (lib/mdm/stewardshipDecisionWriter.ts) and surface an events envelope {emitted, visible_after, read_with} — an empty read before visible_after is expected lag, not a lost event (:20).

5.2 The UI

app/app/stewardship/page.tsx mounts StewardshipDashboard.tsx. Slots (app/app/stewardship/slots/): HeaderBand, TabsRail, FilterBar, StatTiles, StewardCards, FlowSankey (the Sankey flow), RecoveryTrend, AlertList, RecordsTable, WhyColumnMenu, GovernancePopout, Chat, ReportsPage, SubmapHeader, PopupHost. Popups (popups/): Workbench, RecordDetailDrawer, CompareRecordsTable, LineageWorkspace, SourcesPopup, StagePopup, StepDrillPopup, StepLensPopup, RibbonPopover. A steward therefore: sees the flow and its bottlenecks (age buckets are ISO 8601 durations from config/stewardship-aging.config.ts:18,62-86), opens a queue item, compares candidate records, reads lineage, decides (approve / reject / reopen / assign / escalate / undo — lib/mdm/stewardshipUndo.ts), previews blast radius (lib/mdm/stewardshipImpactPreview.ts), and enacts disposition rules that dispose of future items automatically. Chat grounding and governance help are config-driven (config/stewardship-chat-grounding.config.ts, config/stewardship-help.config.ts) and surface-tested (__tests__/chat-grounding.surface.test.tsx, governance-help.surface.test.tsx).


6. Master data — mdm and mdm_project

6.1 mdm

Published purpose (docs/versions/v0.22.188/tools/mdm.md:14-17): golden entities, source links, relationships; a stewardship review queue with survivorship-based golden materialisation; match-config authoring (config_create / config_trial / match_explain / config_train / battery_run / config_promote / config_demote) with an absolute-identifier tier that routes identifier conflicts to review instead of blind-merging; normalization and enrichment registries; curated reference sets; parent-scoped hierarchies; governance overrides and confirmed goldens; an open entity-type vocabulary (entity_type_list / entity_type_get / entity_type_create / entity_type_retire) with per-type matching_mode. Resolution runs are resolution_run; goldens are read via entity_get / golden_explain and masked via the read boundary (§3.1).

Key configuration:

ConcernConfigMeasured detail
Blocking + scoringconfig/mdm-resolution.config.tschunked blocking-key buckets with a memory bound (:39-57, LIB-BUG-592); cross-parent threshold min(match_threshold + delta, 1) (:69-76); sentinel-fraction backstop against constant collapse — the case that "mega-merged 286 people into one" (:412-415); mistyped safety controls can never fail open as always-blocking (:195)
Enrichersconfig/mdm-enricher-kinds.config.tsstages pre_match / post_golden / post_master (:40); kinds regex, builtin, reference_lookup, sql_lookup, rest_lookup, classification_lookup (:71-138); DB CHECK ≡ matrix ≡ dispatch enforced by a release gate (:13)
Consent, forbid-clearing, authzconfig/mdm-consent.config.ts, config/mdm-forbid-clearing.config.ts, config/mdm-enricher-authz.config.tsconsent fixture domain seeded by scripts/mdm/seed-consent-fixture-domain.ts
Stewardship, quality, validationconfig/mdm-stewardship.config.ts, mdm-quality.config.ts, mdm-validation.config.ts

Known limitation — LIB-BUG-1450 (open): a match configuration with empty blocking rules succeeds rather than being refused; recorded as hardening owed in docs/audit/catalog-elt-3-BOOT-PROMPT.md:53 alongside 1448 (tests excluded from typecheck), 1449 (duplicate detector blind to lowercase) and an identity-mask quality note (^\d+ regexp on city/state columns). Until it lands, a config_trial / resolution_run over a config with no blocking keys should be treated by governance reviewers as unbounded pairwise comparison, not as a validated model.

6.2 mdm_project

Guided onboarding by interview (15 commands, docs/versions/v0.22.188/tools/mdm_project.md:14-16): project_startinterview_next / interview_answer / interview_skipproject_status / systems_map_get / project_briefspec_generatespec_get / decision_answer / group_accept / gate_statusmodel_generate / generation_status; project_abandon is terminal. config/mdm-project.config.ts holds the interview bank (INTERVIEW_QUESTION_BANK, :119), system roles source_of_record / contributing_source / destination (:54), and an entity_types question (:165). The privacy-relevant question is the exclusion list: a field the business names is dropped from the matching model — no comparison, no blocking key — "so a sensitive field is never used to decide that two records are the same, even internally"; display masking is unaffected because it is governed elsewhere (:195-203).


7. Evidence and fingerprints


8. Governance evidence harvested from providers

config/governance-control.config.ts declares, per provider kind, which native governance surfaces are real evidence, which are not a surface of that kind, and why — so an absent label is never read as "nothing is sensitive". Capability vocabulary GOVERNANCE_CAPABILITIES (:67-86) includes sensitivity_label (a vendor's own taxonomy), policy_tag, security_label, dynamic_masking, field_encryption, column_comment, field_security.

ProviderMeasured posture (GOVERNANCE_CONTROL, :244+)
SQL Serversensitivity_label real: sys.sensitivity_classifications label, information type and rank, each under its own tag namespace (:328-332); DDM real: sys.masked_columns is a per-column binding, so the masking function token (partial, email, default) is collectable evidence (:340)
BigQuerypolicy_tag is the governed taxonomy whose bindings are the access control (:222); masking is a data policy bound to a policy tag, so no separate per-column DDM surface is read (:426)
MySQL Community 8.4no sensitivity catalog, no catalog-level dynamic masking (:376, :392) — declared absent, not approximated
Snowflakeschema-inventory masking policies are OBJECTS, not per-column bindings, and are declared under masking_policy (:224)
Salesforcethe field-classification gap: Salesforce ships SecurityClassification, ComplianceGroup, DataOwner, DataSensitivityLevel on FieldDefinition, reachable only via the Tooling API or SOQL, both refused by this kind's metadata-only allowlist; "its absence here MUST NOT be read as 'the org classified nothing'" — closing it needs a second transport with its own value-freedom argument and is recorded as owed (:560). Write is unsupported (Metadata API only, :568). Shield Platform Encryption is the one field_encryption surface (:86, :227).

row_level_security is its own declared capability (:83), not a synonym for field_security or security_label: it is real on SQL Server (:346-348, captured by lib/data_catalog/harvest/sqlserver.ts), and on BigQuery (:428), Databricks (:475) and PostgreSQL (:522) it is declared readable but unread by this release's harvest — an honest "not looked at", distinct from the NOT_A_SURFACE_OF declarations that cover tag / policy_tag / security_label for the SaaS and generic-SQL kinds (:234, :322). Harvested tags are mapped to kernel classes by PROVIDER_TAG_CLASS_MAP rules and enter the kernel as evidence — a proposer, never a direct writer (PC-11). Snowflake SYSTEM$CLASSIFY opt-in is an open operator decision, "as proposer only" (docs/audit/catalog-elt-3-BOOT-PROMPT.md:56).


9. Pre-production checklist posture

docs/audit/pre-production-checklist.md (31 lines) is the single place to re-raise security-hygiene items the operator ruled to defer until cutover; they "should not be re-raised as standing 'owed' items before then" (:3-6). Listed, without urging action:

#ItemIdRecorded step
1Redact 4 plaintext ai.oauth_token rows in registry.app_settings_historyDecision 18under the STANDARD-007 lock, --plan then npm run ops:redact-app-settings-history -- --apply --operator-authorised (:12)
2Rotate the AI OAuth tokenAction 19 / LIB-BUG-1392 (P1, open)requires the vault-backing bundle first (:13)
3Re-store the Snowflake key-pair credential for connection f45c3042…Action 13fixture credential for acceptance, not a production rotation (:14)
4Out-of-schedule pdl-billing-reconcile runLIB-BUG-1369 / Decision 21operator-attended, quiet hour (:15)
5Build the FEAT-027 admin credential vaultFEAT-027 (not built)registry.connections.config_encrypted is the only credential store; the vault umbrella is the PII detokenization vault (:16)

Warn-mode gates to flip at cutover (:20-23): audit:consumer-env-currency; audit:lineage-emitter-enrolment (chain-linked from v0.22.188 as release:gates link 26; measured 1 of 11 declared writers enrolled, so the platform openly declares lineage_pending). Each row is to be re-verified against current state before actioning (:27-31).


10. Quick reference for agents

Want to…UseConstraint
Know what a column iscatalog field projection / data_catalog readsstates per PC-4; unclassified ≠ public; withheld samples carry sample_values_withheld
Change masking on a datasetdataset_admin.masking_setmasking_reloadposture is config; never expose a framework on a read (PC-7)
See plain sample valuespass acknowledge_plain_samples: truerecorded on the job (config/data-catalog.config.ts:1106)
Export with plain statisticsstatistics_policy: "plain" + acknowledgePlainStatistics: trueotherwise ExportStatisticsAcknowledgementError
Review a proposalstewardship.proposal_decide, classification.proposal_decideproposals never auto-apply (PC-11)
Read a goldenstewardship.golden_read (masked view)always masked regardless of posture
Propose or override a classno such verb is on the MCP surface at v0.22.188 — proposals enter the kernel as evidence (PC-11)PC-10's "exactly ONE reclassification verb", protective-only, is doctrine awaiting its gate (audit:classification-decision-integrity, planned — P3, STANDARD-009:321)
Add a privacy rule or thresholddo not — operator ruling requiredSTANDARD-009:169-170

Measured against the release named in the text. Raw Markdown: /ontology/documentation/governance-privacy.md. This page is also served as raw Markdown at the same URL with a .md suffix, for agents and search tools that prefer plain text. Every capability statement cites the source file and line it was measured from.

You've seen the proof

Ready for a number? Scope your deployment and we'll price it against your own economics.

Get your quote →