fix(security,release): qualified FLS keys + lint, PROTOCOL_VERSION auto-sync, D11 honest marking#2800
Merged
Merged
Conversation
…to-sync, D11 honest marking FLS (permission-zoo audit): the runtime evaluator matches field-permission keys by <object>.<field> prefix — a bare `budget` key matches NOTHING, so the showcase contributor's declared budget masking was a silent runtime no-op (the earlier "FLS proof" was actually the spent_within_budget validation rule rejecting a tiny budget). Fixed at every layer: the zoo keys are qualified (showcase_project.budget …); a new D7 lint rule `security-fls-unqualified-key` (error + fix-it) rejects bare keys at compile time — the exact plausible-but-wrong shape AI authoring produces; and the permission-zoo dogfood now proves the served pipeline denies a contributor's budget write while allowing ordinary field edits. Release: `changeset version` now chains scripts/sync-protocol-version.mjs, regenerating the PROTOCOL_VERSION handshake constant from the spec package major. Release PRs opened by changesets/action with the default GITHUB_TOKEN never trigger CI (GitHub anti-recursion), so the lockstep guard could only fire AFTER a release merged — fixing the value at version time closes the drift class that broke main at 14.0.0 (#2769). D11: `externalSharingModel` has no runtime consumer yet (authoring lint + Studio badges only). Its liveness entry moves from the bespoke `authorable` status to the documented `planned` + authorWarn (enforce-or-mark), and the sharing docs, design doc, and showcase comments now state explicitly that external-principal evaluation lands with the principal-taxonomy phase (#2696). ADR-0091 (grant lifecycle) was already authored and accepted upstream — no duplicate draft. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…ed-key + ADR-0091 L1 rules) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
📓 Docs Drift CheckThis PR changes 3 package(s): 94 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
|
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.
Three hardening items from the permission-zoo audit round.
FLS: bare keys were a silent runtime no-op — now impossible to author
The evaluator matches field-permission keys by
<object>.<field>prefix (getFieldPermissions:key.startsWith(objectName + '.')), so a barebudgetkey matches nothing — the showcase contributor's declared budget masking never enforced, and the earlier verification's "budget PATCH → 400" was actually thespent_within_budgetvalidation rule rejecting a tiny budget, not FLS (misattribution now corrected on the record). Fixes at every layer:showcase_project.budget/.spent/.budget_remaining) with a comment explaining why.security-fls-unqualified-key(error + fix-it) — a bare FLS key is exactly the plausible-but-wrong shape AI authoring produces, and it fails silently; now it fails the build with the qualified-key prescription. 2 new fixtures.budgetwrite (with a LARGE value so the validation rule can't be the rejector) while an ordinary field edit passes, and the value is unchanged after the denial. 13/13 green.Release: PROTOCOL_VERSION can no longer drift
changeset versionnow chainsscripts/sync-protocol-version.mjs(regenerates the handshake constant from the spec package major; idempotent, fails loudly on unparseable state). Root cause of the 14.0.0 main breakage (#2769): release PRs opened by changesets/action with the defaultGITHUB_TOKENnever trigger CI (GitHub's anti-recursion rule) — the lockstep test existed but could only fire after the merge. Fixing the value at version time is the one spot that cannot be skipped. Verified both branches: in-lockstep no-op and 13→14 repair.D11:
externalSharingModelhonestly marked (enforce-or-mark)The dial has no runtime consumer (authoring lint
security-external-wider-than-internal+ StudioExtbadges only;effectiveSharingModelreadssharingModelalone, and no principal ever evaluates as external today). Its liveness entry moves from the bespokeauthorablestatus (outside the documented vocabulary, no gate ever checked it) toplanned+authorWarn, so authors are told the dial does not evaluate yet; the sharing docs, design doc, and showcase comments now say the evaluator branch lands with the principal-taxonomy phase (#2696).Also noted: ADR-0091 (grant lifecycle) was already authored and accepted upstream — no duplicate work.
Verification
128/128 turbo tasks green (incl. dogfood with the new FLS enforcement assertion and the lint suite at 34 tests).
🤖 Generated with Claude Code