Skip to content

feat(spec,verify): prove-it-runs proof field + ratchet, binding 4 high-risk classes (ADR-0054 #1 + Phase 2) - #2045

Merged
os-zhuang merged 4 commits into
mainfrom
claude/lucid-gauss-t7dd3z
Jun 19, 2026
Merged

feat(spec,verify): prove-it-runs proof field + ratchet, binding 4 high-risk classes (ADR-0054 #1 + Phase 2)#2045
os-zhuang merged 4 commits into
mainfrom
claude/lucid-gauss-t7dd3z

Conversation

@os-zhuang

@os-zhuangos-zhuang commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

What & why

ADR-0054 follow-up (1) + Phase 2: define the authoritative high-risk-class list and add the proof field + ratchet to the spec liveness gate, then bind the high-risk classes — including new runtime proofs/bindings for flow nodes and analytics.

Until now, a live classification in the liveness ledger meant only a static pointer to a consumer — proof that something reads the property. That is necessary but not sufficient: a property can be live at every layer yet broken end-to-end (the break lives in the engine↔driver↔service↔HTTP integration — #2018, the rating/slider/toggle fidelity leak). ADR-0054 adds the third leg — prove-it-runs: for high-risk authorable classes, live must carry a proof (a @objectstack/dogfood test that authors the property against the real in-process stack and asserts the runtime outcome).

The earlier ADR-0054 follow-ups are already merged: field-fidelity fix + field-zoo (#2025/#2022), tz-bucketing proof (#2018), the @objectstack/verify engine (#2041), and the #1994 RLS seed + multi-user harness (#2024/#2032). This adds the missing keystone (the ratchet) and binds four classes.

Design (the proof contract)

  • proof = "<repo-relative-file>#<proof-id>". The dogfood test self-declares the id with a greppable // @proof: <id> tag near its top.
  • Validation is STATIC — the gate checks the file exists and declares the tag; it never runs the test (that's the dogfood gate's job), keeping the liveness gate seconds-cheap (ADR §4). A greppable tag (not a test title) is deliberate: field-zoo titles are generated in a loop.
  • Bidirectional integrity. A bound live entry must carry a valid proof of its own class. The reverse check flags any @proof: tag under packages/dogfood/test/** not registered in proof-registry.mts (warning).
  • Gate also triggers on packages/dogfood/**, so deleting/renaming a proof re-runs the check and a dangling reference is caught.

The ratchet — four classes bound (ADR §3)

A class is CI-enforced only once it has both a runtime proof and a governed ledger entry to carry it.

High-risk classBound?Ledger bindingProof
Field types✅ enforcedfield.typefield-zoo-roundtrip#field-type-roundtrip
RLS / sharing✅ enforcedpermission.rowLevelSecurity.usingrls-fixture#rls-by-id-write
Flow nodes✅ enforcedflow.nodes.typeflow-node#flow-node-execution (new proof)
Analytics dims/measures✅ enforceddataset.dimensions.dateGranularityanalytics-timezone#analytics-tz-bucketing (newly bound)
Form layout/section/widget⛔ pendingnone yet (form surface not governed)

Phase 2 — new this PR

Flow-node runtime proof. Flow execution wasn't reachable through the harness (bootStack registered no automation service). Mirroring how the RLS proof first needed a multi-user harness capability:

  • @objectstack/verify: bootStack gains an opt-in automation flag that registers @objectstack/service-automation; the app's flows are then pulled from the registry and their nodes execute. Default off — standard boot stays lean.
  • dogfood proof: a self-contained fixture (one object + one autolaunched flow whose update_record node stamps a record) triggers the flow over HTTP and asserts both directions — the targeted record IS stamped (node executed) and a bystander is not (the input variable wired into the node's filter, not a blanket update).

Govern dataset + bind analytics. The analytics proof existed (#2018) but its surface wasn't governed. This adds liveness/dataset.json (all 19 authorable props classified with file:line evidence from a consumer audit; 26 live, 1 dead) and binds dataset.dimensions.dateGranularity to the tz-bucketing proof.

Verification (all local, green)

  • pnpm --filter @objectstack/spec check:liveness → green; 11 governed types; reports the 4 bound classes.
  • Red paths confirmed: dangling proof tag → fail; bound live with no proof → fail; orphan tag → warning.
  • 17 unit + wiring tests (proof-registry.test.ts).
  • Flow-node proof runs green; analytics tz proof runs green; full dogfood suite 59/59.

🤖 Generated with Claude Code

…(ADR-0054 #1)
ADR-0054 follow-up (1): the liveness ledger's `live` meant only a static
consumer pointer — necessary but not sufficient, since a property can be live at
every layer yet broken end-to-end. This adds the third leg: high-risk authorable
properties must carry a `proof` (a dogfood test reference) that asserts the
runtime outcome.
- proof-registry.mts: the authoritative high-risk-class list (field types,
analytics, RLS, flow nodes, form widgets) + which classes the ratchet enforces
this phase. Field types and RLS are bound (matrix exists AND surface governed);
analytics/flow/form are listed-but-blocked with honest reasons (their surface
isn't governed yet / no proof yet — Phase 2).
- check-liveness.mts: a bound `live` entry must carry a valid `proof` of its own
class. Validation is STATIC (file exists + declares the `@proof: <id>` tag) so
the gate stays seconds-cheap; running the proof remains the dogfood gate's job.
Reverse check flags unregistered `@proof:` tags.
- Ledger: field.type → field-zoo proof; permission.rowLevelSecurity.using →
#1994 RLS proof. Dogfood proofs self-declare their `@proof:` tag.
- Gate now also triggers on packages/dogfood/** so deleting/renaming a proof
re-runs the check and the dangling reference is caught.
- 15 unit + wiring tests; README documents the contract and ratchet.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XVdnfUAx85amkerym26vdx
@vercel

vercelBot commented Jun 19, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJun 19, 2026 10:33am

Request Review

@github-actionsgithub-actionsBot added documentation Improvements or additions to documentation ci/cd tests tooling size/l labels Jun 19, 2026
@github-actions

github-actionsBot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 3 package(s): @objectstack/dogfood, @objectstack/spec, @objectstack/verify.

89 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/concepts/architecture.mdx(via @objectstack/spec)
  • content/docs/concepts/cloud-artifact-api.mdx(via packages/spec)
  • content/docs/concepts/cluster-semantics.mdx(via @objectstack/spec)
  • content/docs/concepts/design-principles.mdx(via packages/spec)
  • content/docs/concepts/implementation-status.mdx(via @objectstack/spec)
  • content/docs/concepts/index.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-driven.mdx(via @objectstack/spec)
  • content/docs/concepts/metadata-lifecycle.mdx(via packages/spec)
  • content/docs/concepts/north-star.mdx(via packages/spec)
  • content/docs/concepts/packages.mdx(via @objectstack/spec)
  • content/docs/concepts/setup-app.mdx(via @objectstack/spec)
  • content/docs/concepts/skills.mdx(via @objectstack/spec)
  • content/docs/concepts/webhook-delivery.mdx(via @objectstack/spec)
  • content/docs/getting-started/architecture.mdx(via @objectstack/spec)
  • content/docs/getting-started/cli.mdx(via @objectstack/spec)
  • content/docs/getting-started/core-concepts.mdx(via @objectstack/spec)
  • content/docs/getting-started/examples.mdx(via @objectstack/spec)
  • content/docs/getting-started/quick-start.mdx(via @objectstack/spec)
  • content/docs/guides/adding-a-metadata-type.mdx(via @objectstack/spec)
  • content/docs/guides/ai-capabilities.mdx(via @objectstack/spec)
  • content/docs/guides/airtable-dashboard-analysis.mdx(via @objectstack/spec)
  • content/docs/guides/analytics-datasets.mdx(via @objectstack/spec)
  • content/docs/guides/api-reference.mdx(via @objectstack/spec)
  • content/docs/guides/business-logic.mdx(via @objectstack/spec)
  • content/docs/guides/cheatsheets/backward-compatibility.mdx(via @objectstack/spec)
  • content/docs/guides/cheatsheets/error-catalog.mdx(via @objectstack/spec)
  • content/docs/guides/cheatsheets/field-type-gallery.mdx(via @objectstack/spec)
  • content/docs/guides/cheatsheets/field-validation-rules.mdx(via @objectstack/spec)
  • content/docs/guides/cheatsheets/permissions-matrix.mdx(via @objectstack/spec)
  • content/docs/guides/cheatsheets/protocol-diagram.mdx(via packages/spec)
  • content/docs/guides/cheatsheets/query-cheat-sheet.mdx(via @objectstack/spec)
  • content/docs/guides/cheatsheets/quick-reference.mdx(via @objectstack/spec)
  • content/docs/guides/client-sdk.mdx(via @objectstack/spec)
  • content/docs/guides/common-patterns.mdx(via @objectstack/spec)
  • content/docs/guides/contracts/auth-service.mdx(via packages/spec)
  • content/docs/guides/contracts/cache-service.mdx(via packages/spec)
  • content/docs/guides/contracts/data-engine.mdx(via @objectstack/spec)
  • content/docs/guides/contracts/index.mdx(via @objectstack/spec)
  • content/docs/guides/contracts/metadata-service.mdx(via packages/spec)
  • content/docs/guides/contracts/storage-service.mdx(via packages/spec)
  • content/docs/guides/data-modeling.mdx(via @objectstack/spec)
  • content/docs/guides/deployment-vercel.mdx(via @objectstack/spec)
  • content/docs/guides/driver-configuration.mdx(via @objectstack/spec)
  • content/docs/guides/error-handling-client.mdx(via @objectstack/spec)
  • content/docs/guides/error-handling-server.mdx(via @objectstack/spec)
  • content/docs/guides/formula.mdx(via @objectstack/spec)
  • content/docs/guides/hook-bodies.mdx(via packages/spec)
  • content/docs/guides/kernel-services.mdx(via @objectstack/spec)
  • content/docs/guides/metadata/dashboard.mdx(via @objectstack/spec)
  • content/docs/guides/metadata/field.mdx(via @objectstack/spec)
  • content/docs/guides/metadata/flow.mdx(via @objectstack/spec)
  • content/docs/guides/metadata/index.mdx(via @objectstack/spec)
  • content/docs/guides/metadata/object.mdx(via @objectstack/spec)
  • content/docs/guides/metadata/validation.mdx(via @objectstack/spec)
  • content/docs/guides/metadata/workflow.mdx(via @objectstack/spec)
  • content/docs/guides/packages.mdx(via @objectstack/spec)
  • content/docs/guides/plugin-development.mdx(via @objectstack/spec)
  • content/docs/guides/plugins.mdx(via @objectstack/spec)
  • content/docs/guides/project-scoping.mdx(via @objectstack/spec)
  • content/docs/guides/public-forms.mdx(via @objectstack/spec)
  • content/docs/guides/runtime-services/email-service.mdx(via packages/spec)
  • content/docs/guides/runtime-services/index.mdx(via packages/spec)
  • content/docs/guides/runtime-services/queue-service.mdx(via packages/spec)
  • content/docs/guides/runtime-services/sharing-service.mdx(via packages/spec)
  • content/docs/guides/runtime-services/storage-service.mdx(via packages/spec)
  • content/docs/guides/security.mdx(via @objectstack/spec)
  • content/docs/guides/seed-data.mdx(via @objectstack/spec)
  • content/docs/guides/skills.mdx(via @objectstack/spec)
  • content/docs/guides/standards.mdx(via @objectstack/spec)
  • content/docs/guides/troubleshooting.mdx(via @objectstack/spec)
  • content/docs/protocol/knowledge.mdx(via @objectstack/spec)
  • content/docs/protocol/objectos/config-resolution.mdx(via @objectstack/spec)
  • content/docs/protocol/objectos/i18n-standard.mdx(via @objectstack/spec)
  • content/docs/protocol/objectos/lifecycle.mdx(via @objectstack/spec)
  • content/docs/protocol/objectos/plugin-spec.mdx(via @objectstack/spec)
  • content/docs/protocol/objectos/runtime-capabilities.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/index.mdx(via packages/spec)
  • content/docs/protocol/objectql/query-syntax.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/schema.mdx(via @objectstack/spec)
  • content/docs/protocol/objectql/security.mdx(via packages/spec)
  • content/docs/protocol/objectql/state-machine.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/actions.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/concept.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/index.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/layout-dsl.mdx(via packages/spec)
  • content/docs/protocol/objectui/record-alert.mdx(via @objectstack/spec)
  • content/docs/protocol/objectui/widget-contract.mdx(via @objectstack/spec)
  • content/docs/releases/index.mdx(via @objectstack/spec)
  • content/docs/releases/v9.mdx(via @objectstack/spec)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

…f (ADR-0054 Phase 2)
Phase 2 extends the prove-it-runs ratchet to the flow-node class.
- verify: bootStack gains an opt-in `automation` flag that registers
@objectstack/service-automation, so authored flows are pulled from the registry
and POST /automation/:name/trigger runs their nodes. Without it, flow execution
was unreachable through the harness (the dispatcher's automation routes resolved
no service). Mirrors the existing `multiTenant`/`security` opt-ins; default off.
- dogfood: a self-contained flow fixture (one object + one autolaunched flow whose
update_record node stamps a record) + the flow-node proof. It authors the flow,
triggers it over HTTP, and asserts both directions — the targeted record is
stamped (node executed) AND a bystander is untouched (the input variable wired
into the node filter, not a blanket update). Runs green end-to-end.
- spec: flow-node class is now `bound` in proof-registry.mts; flow.nodes.type
carries the proof; the liveness gate enforces it. Three classes now bound:
field types, RLS, flow nodes.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XVdnfUAx85amkerym26vdx
@github-actionsgithub-actionsBot added the dependencies Pull requests that update a dependency file label Jun 19, 2026
@os-zhuangos-zhuang changed the title feat(spec): prove-it-runs proof field + ratchet for the liveness gate (ADR-0054 #1)feat(spec,verify): prove-it-runs proof field + ratchet, and the flow-node Phase 2 proof (ADR-0054 #1 + Phase 2)Jun 19, 2026
…0054)
Unlocks the analytics binding that was previously blocked because its authorable
surface wasn't governed.
- Govern the `dataset` metadata type: new liveness/dataset.json classifies all 19
authorable props with file:line evidence from the analytics service consumer
audit (26 live, 1 dead — measures.certified has no runtime consumer). `dataset`
added to GOVERNED in check-liveness.mts.
- Bind the analytics class: dataset.dimensions.dateGranularity carries the
tz-bucketing proof (#1982/#2018) — the property whose org-timezone day-bucket
behavior the proof asserts. proof-registry.mts flips analytics to bound.
- Four high-risk classes now CI-enforced: field types, RLS, flow nodes, analytics.
- README governed-types + high-risk tables updated; changeset description updated.
Verified: liveness gate green (dataset 27 classified); 17 registry tests; the
analytics proof runs green; full dogfood suite 59/59.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XVdnfUAx85amkerym26vdx
@os-zhuangos-zhuang changed the title feat(spec,verify): prove-it-runs proof field + ratchet, and the flow-node Phase 2 proof (ADR-0054 #1 + Phase 2)feat(spec,verify): prove-it-runs proof field + ratchet, binding 4 high-risk classes (ADR-0054 #1 + Phase 2)Jun 19, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review June 19, 2026 11:00
@os-zhuang
os-zhuang merged commit a8e4f3b into mainJun 19, 2026
18 checks passed
@os-zhuang
os-zhuang deleted the claude/lucid-gauss-t7dd3z branch June 19, 2026 11:01
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cddependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/lteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@os-zhuang@claude