test(authorization): name the lifecycle bits a tombstone, and stop the guard passing vacuously - #1682
Merged
Conversation
…e guard passing vacuously `test/authorization-coverage.test.ts` scans every permission grant for `allowRestore: true` / `allowPurge: true`. Its comment described those keys as "RBAC-gated" bits "whose operations do not exist yet" — live-but-unenforced. On the pinned `@objectstack/spec` 17.3.0 they are neither: ADR-0049 enforce-or-remove retired both (objectstack#12497) and the schema refuses them at parse time with a prescription, measured verbatim against the installed package and quoted in the comment. Only `true` is refused; the `false` that the pre-retirement schema defaulted into every artifact the published 17.x toolchain built parses as inert residue and is stripped (objectstack#12840), so `=== true` is both what the scan tests and the only value worth testing for. The guard stays, and the comment now says why: `validate` and `build` reject such a source earlier in `pnpm verify`, but `pnpm typecheck` does not — the profile files are untyped object literals and this suite reads the raw `objectstack.config` rather than a schema-parsed object, so a bare `pnpm test` still trips here. objectstack#1883 stays open as the M2 lifecycle anchor. The steady state of this scan is an empty result, which a real pass and a collapsed input look identical in, so it now carries the same guard-the-guard assertion the adjacent `allowTransfer` test has carried all along: the population being scanned must be non-empty. Same file, existing pattern, no new check surface. Co-authored-by: Claude
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
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.
Closes #1634
Description
The lifecycle-bits guard in
test/authorization-coverage.test.tsscanned every permission grant forallowRestore: true/allowPurge: trueunder a comment that described those keys as "RBAC-gated" bits "whose operations do not exist yet" — live-but-unenforced. On the pinned@objectstack/spec17.3.0 they are neither. This PR fixes the prose (ruled disposition 1 on the card) and adds the guard-the-guard assertion the grading asked for. The guard itself is kept and unchanged.Type of Change
allowTransfertest)Related Issues
Closes #1634. Source card #1376. Upstream: objectstack#12497 (ADR-0049 retirement), objectstack#12840 (retired-default residue tolerance), objectstack#1883 (M2 lifecycle anchor, still open).
Changes Made
The comment now names a tombstone. ADR-0049 enforce-or-remove retired both keys (objectstack#12497). Measured against the installed package,
ObjectPermissionSchema.safeParse({ allowRead: true, allowRestore: true })is refused at parse time, and the verbatim prescription is quoted in the comment:(
OBJECTstands for the angle-bracket placeholder the real message prints.)Only
trueis refused. Thefalsethat the pre-retirement schema defaulted into every artifact the published 17.x toolchain built parses as inert residue and is stripped (objectstack#12840). Measured both ways here. That is why the scan tests=== true, and the comment now says so.The comment says why the guard stays.
validateandbuildboth reject such a source earlier inpnpm verify, butpnpm typecheckdoes not:src/profiles/*.profile.tsare untyped object literals and this suite reads the rawobjectstack.configrather than a schema-parsed object, so nothing gives the literal a contextual type and a barepnpm teststill trips here. objectstack#1883 stays open as the M2 anchor.Guard-the-guard. The steady state of this scan is an empty result, in which a real pass and a collapsed input are indistinguishable. It now asserts the scanned population is non-empty, the same shape the adjacent
allowTransfertest has carried all along. No new check surface — the sibling pattern applied to the assertion already in the file (AGENTS.md "do not grow a gate farm" respected).One changeset (patch).
Version references — re-measured, and one card reading corrected
The card and its grading said the retirement "actually landed in 17.2". That does not hold on the pin:
@objectstack/spec's ownCHANGELOG.mdlists the retirement changeset (8af88dd, "retire theallowRestore/allowPurgeobject-permission bits … (#12497, ADR-0049)") under## 17.3.0→ Minor Changes. The## 17.2.0section mentions neither key nor #12497.@objectstack/metadata("spec 17.1 to 17.2 retired the allowRestore/allowPurge permission bits") appears nowhere in any installed@objectstack/*package. What metadata's CHANGELOG does carry, inside its own 17.3.0 section, is a prose aside — "spec 17.2.0'sretiredKeytombstone refused the boot" — which conflicts with spec's own version placement.So the comment cites the major, exactly as the platform's own prescription does ("removed in @objectstack/spec 17"), and says out loud not to "correct" that to an earlier minor. The other two readings held:
@objectstack/specis 17.3.0, and the freshly builtdist/objectstack.jsoncarries 75 object-permission entries with 0 carrying either key.Testing
pnpm verifyfully green —validate→typecheck→lint→lint:i18n-gate→hygiene→hygiene:tokens→build→test.✓ Validation passed,✓ source hygiene clean,✓ source token ratchet clean(comment-stripped andsrc/-scoped, so a test comment does not move it),✓ Build complete.Test Files 161 passed (161)·Tests 3402 passed | 1 skipped (3403).The new assertion was proved able to go red, not merely observed green. The grants set was emptied at its source (
permissionSets→permissionSets.slice(0, 0)), the mutation was proved on disk by blob hash and by grepping both the removed and the injected anchor text, and the run failed on exactly the new line:The first assertion passed under that mutation — which is precisely the vacuity this closes. Restored with
git checkout HEAD -- PATH, and the restore was proved by state rather than by an editor exit code: the on-disk blob hash returned to529dd9483b71ee220bb5f90e9ca5717a79776f17andgit diff HEADprinted nothing. Re-run green.Additional Notes
Scope fence honoured: the diff touches only the lifecycle-bits
it()block, its comment, and the one new assertion.test/authorization-coverage.test.tsis listed in epic #1579 family F5 (#1586) as group A only, i.e. a mixed file — and the lifecycle-bits guard matches none of F5's nine namedsecurity-*/rls-predicate-*rules, so it is group B and stays. Nothing touched undersrc/profiles/, and no assertion or prose relating to those nine rules was touched. The new assertion is also what the epic's own gate 1 (non-vacuous) requires of this block.Generated by Claude Code