Repository navigation
test: dispatch the nine new grant fixtures, and sharpen the package gate - #129
Merged
Merged
Conversation
Bumps @haverstack/conformance-fixtures to ^0.31.0 and handles what it adds. The caret pins the minor on a 0.x range, so 0.30.0 would never have picked these up on its own — the bump is what puts the coverage gate to work. Seven of the nine are plain POST /records bodies and share one dispatch. The other two need prior state, and each carries the control that makes it mean what it says: a grant naming _app@1 confers no create *while the same shape on a grantable family does*, and update-any with no read companion conveys nothing *while the same grant with read-any beside it conveys the update*. Without those, both tests would pass against a server holding no grant for the requester at all, since a missing grant answers 403 and 404 the same way. Two fixes to the whole-package gate, both visible the first time it fired in anger. It recorded a block's names only after that block's own assertions passed, so one failing block reported nothing and the gate blamed it for every fixture it does dispatch — 90 names for 9 real ones. And it read the allConformanceFixtures aggregate, which is a union of the arrays beside it, so every name arrived twice. Recording first and skipping the aggregate leaves the failure naming exactly what is unhandled. Co-Authored-By: Claude Opus 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01St5i1czsAp26y8H56pmANC
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.
Summary
The follow-up haverstack/core#320 unblocked. Bumps
@haverstack/conformance-fixturesto^0.31.0and handles the nine fixtures it adds.The bump is the forcing act, not a formality. The range was
^0.30.0, and a caret on a0.xversion pins the minor — so 0.31.0 would never have been resolved, the coverage gate would never have fired, and CI would have stayed green with nine fixtures unhandled. Nothing about a release reaches this repo until the range moves.Seven of the nine are plain
POST /recordsbodies and share one dispatch loop. The other two need prior state, and each carries a control that makes it mean what it claims:…grant-on-an-ungrantable-family-confers-nothing_app@1confers no create →403comment@1does confer the create →200…mutate-grant-with-no-read-companionupdate-anywith noread-anyconveys nothing →404read-anybeside it conveys the update →200Without those controls both tests would pass against a server holding no grant for the requester at all, since a missing grant answers
403on the create and404on the patch exactly the same way. The control is the whole difference between pinning the rule and pinning a coincidence.Both grants are written directly rather than through
stack.grant(), which refuses each of these outright — which is the point. These fixtures pin the second half of the two-sided rule: what happens when a grant reaches storage some other way and is read back.Gate fixes
Two problems with the whole-package gate added in #128, both visible the first time it fired in anger rather than in a simulation:
It recorded a block's names only after that block's own assertions passed. So a block that failed its coverage reported nothing, and the gate blamed it for every fixture it does dispatch — 90 names for 9 real ones. Recording first and asserting second keeps one block's failure from cascading.
It read the
allConformanceFixturesaggregate, which is a union of the arrays beside it, so every name arrived twice under two different export names.The failure now names exactly what is unhandled:
That is the output an unread block should produce, and it is what I checked against before adding the dispatch arms.
Docs
No behavior change — tests and a devDependency bump. No route, status code, error code, auth rule or environment variable moved.
Verification
I ran the gate against the bumped dependency before writing any dispatch, and it failed as designed on both the
errorResponseFixturesblock coverage and the whole-package test, naming all nine. The two noise problems above are what that run surfaced.The two evaluation-time fixtures passing here is independent confirmation of core#320 through this repo's conformance harness — those expectations were originally observed with a throwaway wire client, and this is the first time they have been checked by the gate that will keep checking them.
Notes for reviewers
pnpm-lock.yamlmoves for the single devDependency bump; nothing else in the tree changed version.The nine fixtures assert status and
error.codeonly, via the block's existingexpectError(). Theirdetails— the field paths and messages, which I probed off a live server when writing them in core — remain documentation rather than an asserted contract on either side of the wire. Whether that should change is the open question I raised in core#320, and I have deliberately not pre-empted it here.Completes the split: docs in #127, the server-specific coverage in #128, the cross-implementation rules in core#320, and their dispatch here.
🤖 Generated with Claude Code
https://claude.ai/code/session_01St5i1czsAp26y8H56pmANC
Generated by Claude Code