Data governance
The datagov agent (grpc/agents/datagov) assesses the tenant’s registered data sources. It is deterministic and calls no model. As assess.go puts it, a model-authored governance score “would be a fabrication wearing a number”. It holds no credential, dials no source, and reads no row or cell value.
When it runs
.github/workflows/core-agent-datagov.yml:
- a schedule,
11 7 * * *(daily 07:11 UTC); - an
@core_datagovissue comment; workflow_dispatch;repository_dispatch: core-playbook, when an Atlas playbook step namesdatagov.
Arm or disarm it with the gate agentic_datagov from DataEx › Agents.
What it reads
- The connection snapshot: the
core-console-connectionsConfigMap that the console publishes from its table after every write, projected into the job by kubectl. This covers the governance and risk-compliance axes. - What Resolve’s Explore recorded, from
GET /api/data-governance-estate(datagov_estate.go), on the App-token contract. It holds structure and counts only: names, declared types, nullability and primary keys, row and null counts with their basis, the source’s PII flag and mask, and access counts. This covers the data-quality and PII-exposure axes.
It is a GET door rather than a ConfigMap on purpose. A description is the tenant’s schema and is sealed at rest in the console. A ConfigMap is unencrypted in etcd and capped at 1 MiB.
Verdicts
pass, fail, warn and unable-to-assess. The last one is the point: a control the agent cannot evaluate is never shown as satisfied or omitted, and it always carries the reason.
Controls
governance
| Control | Pass when |
|---|---|
governance/owner-declared | a property owner, owner_email, steward, data_steward or team is set. There is no typed Owner field |
governance/environment-declared | environment is non-empty. Only presence is checked, because the set of values belongs to the consumer |
governance/type-catalogued | the connector catalog has a descriptor for the type. Otherwise warn, and the credential and transport controls have no contract to check against |
governance/credential-bundle-not-shared | no other connection resolves to the same credential bundle |
governance/no-secret-in-settings | no secret-shaped key in the non-secret maps. Only key names are reported |
risk-compliance
| Control | Notes |
|---|---|
risk-compliance/address-declared | the catalog’s address settings are non-empty. Unable when the type is uncatalogued or reaches its system through non-dialable coordinates (an account locator, a project id) |
risk-compliance/no-credential-in-address | no credentials embedded in the declared address settings |
risk-compliance/transport-encrypted | for example, ssl_mode set to a value that requires TLS. prefer and allow do not count |
data-quality (from Resolve’s Explore)
| Control | Rule |
|---|---|
data-quality/source-profile | a measured null in a declared NOT NULL column fails. A column that is all null in its measured population warns. No measured null count means unable |
data-quality/primary-key-declared | every described table declares a primary key. Evaluated only when the source’s constraints were actually read |
data-quality/freshness | always unable. Last-altered is a DDL/DML stamp, not a load time, and no expected cadence is declared anywhere |
pii-exposure (from Resolve’s Explore and access patterns)
| Control | Rule |
|---|---|
pii-exposure/column-classification | column name plus declared type against the rule table in dataaxes.go, plus the source’s own PII flag. Unmasked candidates warn, and partial coverage never passes |
pii-exposure/access-breadth | more than 10 distinct principals (piiBroadAccess) reading a dataset that holds an unmasked candidate warns |
A source nobody has explored gets one unable-to-assess per axis, saying “not explored yet — run Explore in Intelligence › Resolve”. To fill the two data axes, Explore the source on Resolve.
Where the results land
- The console findings store:
POST /api/data-governance-findings, App-authorized, and read back withGETon a session. Findings name column paths so an owner can act. - The living GitHub issue, “🗃️ Data governance status”. It carries counts only, so the tenant’s schema stays on the platform.
- A successful store write raises the harness event
findings.reported(fail_count,warn_count), which can start a matching Atlas playbook. See Playbooks.
Tests hold the value boundary: TestNoFindingCarriesASettingValue, TestNoFindingCarriesACellValue and TestGovEstateProjectionCarriesNoValue.
Not the same as
compliance: checks CORE’s own code againstdocs/COMPLIANCE.md.risk: govulncheck over dependencies.judge: judges findings submitted by other platforms. See Judgements.