Skip to content

feat!: read checks through the control API - #1315

Merged
kvlonge merged 1 commit into
mainfrom
feat/control-checks
Nov 6, 2026
Merged

kvlonge merged 1 commit into
mainfrom
feat/control-checks

Conversation

@kvlonge

@kvlonge kvlonge commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

Why

The control UI needs to list checks, their recent results and their SQL. The audit-result mirror holds every field, but nothing read it, and its only typed identity, audit_name, is not unique: one generic audit such as not_null covers many models and columns. In a playground build, 30 checks shared 9 audit names.

Changes

  • Checks are keyed by binding_key, now a typed, indexed mirror column filled on ingestion. binding_key covers the audit name, model, column, severity, run scope and thresholds, so a model rename or a severity or threshold change starts a new check history; the old history stays readable under its own key.
  • GET /api/control/locations/{location}/targets/{target}/checks returns the newest result of every check. GET …/checks/{binding_key} returns one check's results, newest first (limit, default 50). Both need view on the whole target, like the catalog, and never return SQL, error texts (database errors quote the SQL) or evidence rows.
  • GET …/checks/{binding_key}/sql returns the latest result's SQL and error texts. It needs view.sql on the check's model (or the whole target for a check without one) and writes a sql.read audit entry, like node SQL. A denial is audited and returns 403; its reason names the check's node, a known low risk.
  • Pre-release control stores are not upgraded: a store created by 0.188.x is refused with an error telling the operator to recreate it.
  • Client regenerated; new DuckShop check fixture.

Verification

  • New API test on SQLite and PostgreSQL: checks sharing an audit name list separately with their newest outcomes; the listing holds no SQL or error text; history is per key, newest first; viewers get 403 for SQL with a denial audit; developers read SQL and errors with a sql.read audit holding no SQL; other targets are refused. Keying by audit_name fails it.
  • cargo test -p sqlbuild-orchestration, client check and test, publication tests, make check-ci.

People can list a target's checks with their newest results, read one check's recent results, and, with view.sql, read its SQL. Checks are keyed by binding_key, now a typed, indexed column on the audit-result mirror, because one audit name such as not_null covers many models and columns. A model rename or a severity or threshold change starts a new check history, and the old one stays readable. SQL reads are audited like node SQL.

BREAKING CHANGE: control stores created by 0.188.x are not upgraded. The server refuses them with an error saying to recreate the control store; create a new one when upgrading.
@kvlonge
kvlonge enabled auto-merge (squash) November 6, 2026 03:00
@kvlonge
kvlonge disabled auto-merge November 6, 2026 03:02
@kvlonge
kvlonge enabled auto-merge (squash) November 6, 2026 03:05
@kvlonge
kvlonge merged commit 865f8f7 into main Nov 6, 2026
49 checks passed
@kvlonge
kvlonge deleted the feat/control-checks branch November 6, 2026 03:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant