feat(verify): extract dogfood engine into public @objectstack/verify + CLI#2041
Merged
Conversation
…+ CLI Productize the internal dogfood regression engine as a published library and an `objectstack verify` CLI so third-party and template authors can run the same runtime proofs (auto-derived CRUD round-trip fidelity + the cross-owner RLS invariant) against their own apps. - new public @objectstack/verify: bootStack / deriveCrudCases / runCrudVerification / runRlsProofs, moved+generalized from packages/dogfood/src (tsup ESM+CJS+DTS, publishConfig public) - new `objectstack verify` oclif command (--app/--rls/--multi-tenant/--json); exits 1 on create-failed/read-failed/fidelity-gaps/rls-hole - dogfood now consumes @objectstack/verify; drop 3 redundant auto-verify tests (replaced by an `objectstack verify` CI step over the example apps); keep the hand-written golden regressions (#2018 tz, #1994 RLS, #2004 field fidelity) - fix: the harness used a port-less loopback inject origin (http://localhost) that fails better-auth's default dev trusted-origins (http://localhost:*); use a ported base so dev-admin sign-in passes in a bare node CLI and the test runner alike - add @objectstack/verify to the changeset `fixed` group; changeset for verify+cli Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 15 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
…delity gaps Surfaced by running `objectstack verify` against the real third-party hotcrm app: - The CLI ran data-fidelity and RLS proofs against the SAME in-process stack, so the RLS phase's admin-creates collided with rows the fidelity phase had already written on unique-constrained fields (e.g. a unique `sku`/`account_number`) → a 409 that silently skipped those objects' authorization check. Boot a separate pristine stack for the RLS phase. hotcrm `--rls --multi-tenant` goes from 5-consistent/3-skipped(409) to 8-consistent/0-holes. - Document the known limitation that fields normalized on write (uppercase/trim hooks, canonicalizing formulas) read back as `fidelity-gaps` even when working as designed (hotcrm's `sku`/`account_number` uppercase hooks). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ctstack/verify ADR-0054 assigned the prove-it-runs mechanism to @objectstack/dogfood; this PR extracted that engine into the published @objectstack/verify. Append an Update addendum (and list it as a consumer) mapping the package to the ADR's phases — dogfood stays the gate (hand-written golden proofs) and now runs on the verify engine; Phase 1's field/RLS matrix is the published derive/verify/rls; Phase 3's generative pass has deriveCrudCases as its seed — and stating the honest scope of the auto-derived path (scalar round-trip + by-id RLS only) so it doesn't read as subsuming the golden proofs. Decision unchanged. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
ObjectStack is a platform where third parties have an AI author arbitrary metadata. The real risk isn't "a platform change broke the CRM example" — it's "the AI used a valid primitive the examples don't exercise, and it silently breaks at runtime" (the #2018 timezone-bucketing class: green on build / 900+ unit tests / spec-liveness / CodeQL, only visible when the real engine + services + HTTP run together).
The internal
@objectstack/dogfoodpackage already contained an app-agnosticobjectstack verifyengine in embryo (itsderive/verifycomments literally say "point it at any app … a third-party app like hotcrm"). This PR productizes that engine so third-party and template authors can run the same runtime proofs against their own apps.What changed
New public library
@objectstack/verify(packages/verify)bootStack(wasbootDogfoodStack),deriveCrudCases,runCrudVerification,runRlsProofs+ report types — moved & generalized out ofpackages/dogfood/src.publishConfig.access: public, third-party-facing README.New
objectstack verifyCLI command (packages/cli/src/commands/verify.ts)loadConfig; flags--app/--rls/--multi-tenant/--json.create-failed/read-failed/fidelity-gaps/rls-hole→ exit 1; inconclusive verdicts (needs-fixture/skipped/member-visible) warn and exit 0.@objectstack/dogfoodkept, slimmed (single source of truth)@objectstack/verify; deps 14 → 6.objectstack verify --rlsCI step over the example apps (Dogfood Regression Gate job).Release plumbing
@objectstack/verifyadded to the changesetfixedgroup (@objectstack/dogfoodstays private/excluded);check-changeset-fixed.mjspasses (73 packages in sync). Changeset added for verify + cli.Validated end-to-end on a real third-party app (hotcrm)
Ran the built CLI against
../hotcrm(a standalone marketplace CRM on published@objectstack@^9.9.1, with real sharing / territory / role-hierarchy rules — not in this repo):crm_product.skureads back uppercased (an intentional normalization hook), correctly flagged as afidelity-gapsmismatch → exit 1.--rls --multi-tenant→ 8 consistent / 0 holes (a fresh member can neither read404nor mutate403cross-org records) across its real sharing rules.The exercise also surfaced two
@objectstack/verifytool-quality issues (not hotcrm bugs), both addressed here:--rls --multi-tenant: 5-consistent/3-skipped → 8-consistent/0-skipped-by-409).fidelity-gapseven when working as designed; the report shows thewrote → readdiff. A declared-transform allowlist is a planned enhancement.Validated across the template corpus (9 apps)
Ran the CLI across all 9 apps in
../templates(the AI-authored starter corpus: expense, contracts, content, compliance, todo, project, procurement, hr, helpdesk), on an older@objectstackthan this branch — a cross-version run:--multi-tenant: 0 holes — every auto-exercised object isrls-consistent; the fix(security)[P0]: enforce RLS on by-id writes — close member-edits-others'-records hole (#1985) #1994 invariant holds across all 9 AI-authored apps.Coverage caveat: the auto-derive skips objects whose required fields it can't synthesize (lookups / master-detail), so relational-heavy templates have ~half their objects skipped — "0 holes" is over the auto-exercised subset. Auto-synthesizing related records in topological order to reach those objects is a planned enhancement.
Verification
@objectstack/verifybuilds (ESM+CJS+DTS).main(which carries spec/RLS schema changes) — zero behavior change.objectstack verifyagainst the framework examples: crm4 verified / 2 skipped / exit 0, crm--rls0 holes, showcaseexit 0; clean process exit (fixed a hang: the in-process stack leaves handles open afterstop(), so the command forcesthis.exit()).objectstack verifyagainst hotcrm (real third-party): boots, verifies, proves exit-1 and the fix(security)[P0]: enforce RLS on by-id writes — close member-edits-others'-records hole (#1985) #1994 invariant (above).check-changeset-fixed.mjs, andci.ymlYAML all green/valid.Fix found along the way
The harness used a port-less loopback inject origin (
http://localhost) which fails better-auth's default dev trusted-origins (http://localhost:*) →objectstack verifygot a 403 on dev-admin sign-in in a barenodeCLI (the dogfood tests passed only because turbo's strict-env run masked it). Switched to a ported loopback base so sign-in is deterministic across the node CLI and the test runner.🤖 Generated with Claude Code