docs(a2ui): C1.4 correction — projection security requires WIDE role masks (codex P2 on #204)#205
Merged
Merged
Conversation
…masks Codex P2 on #204, verified in-repo before amending: the merged charter's "RBAC by projection" claim silently breaks for surfaces with >64 fields — ClassRbac::field_mask returns a NARROW FieldMask (u64, keystone spec §4) while render_class_with_methods_wide exists precisely because surfaces exceed FieldMask::MAX_FIELDS, and WideFieldMask::full_for ("emit everything") is exactly the unsafe sentinel fallback codex predicted. Three requirements added to C1.4, mandatory for W1+: (a) zero-extension fail-closed rule — a narrow role mask extends past bit 63 as ZEROS, never as full; absent wide role data, unauthorized by default; (b) additive seam — ClassRbac::field_mask_wide(role, class) -> WideFieldMask, so wide grants are expressible at all (narrow field_mask stays for <=64 surfaces); (c) sentinel ban on the RBAC path — full_for is a render convenience, never a role-mask fallback; a missing role mask is a refusal. Interim alternative: page the surface into <=64-field panes. Matching correction line appended to the D-A2UI-SCREEN-ADDRESSING ledger entry (append-only, cites the codex pass). Co-Authored-By: Claude <noreply@anthropic.com>
Bugbot couldn't run - usage limit reachedBugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit. A user or team admin can review and increase usage limits in the Cursor dashboard. (requestId: serverGenReqId_9a8ddfc2-4225-49d0-95b2-e843d2363d5d) |
… no new method
"We already have WideFieldMask" — the C1.4 fix collapses: NO parallel
field_mask_wide (a second name for the same projection would be the T1
two-vocabularies anti-pattern applied to the seam itself). Instead
ClassRbac::field_mask retypes to WideFieldMask IN PLACE — verified cheap
against source: the entire production surface is the trait default
(FieldMask::FULL, rbac.rs:176) + one test override (rbac.rs:455); no
production impl overrides it, so the retype touches two bodies and the
compiler surfaces the rest. WideFieldMask is already universal (Small repr
<=64, self-promoting past 64).
The one genuine W1 decision named: the permit-all identity — WideFieldMask
has EMPTY + full_for(count) but no count-free ALL, and the axis-4 default is
deliberately opt-in ("FULL unless configured"). Either WideFieldMask gains
ALL (the intersection identity) or the default derives full_for(field_count)
from the ClassView.
Kept: zero-extension fail-closed (now scoped to legacy narrow-mask interop
sites) + the sentinel ban (full_for = render convenience, never an RBAC
fallback). Ledger correction line updated to match, citing both passes.
Co-Authored-By: Claude <noreply@anthropic.com>
This was referenced Jul 14, 2026
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.
What
Follow-up to the merged #204: codex's P2 is a real catch, verified against source before amending, and this PR folds the fix into the charter's C1.4 + the ledger entry.
The verified finding
The merged "RBAC by projection" claim (
WideFieldMask ∩ role-mask⇒ unauthorized fields absent from the wire) silently breaks past 64 fields:ClassRbac::field_maskreturns a narrowFieldMask(u64) —docs/CLASSID-RBAC-KEYSTONE-SPEC.md§4 (verified :85-90).ogar-render-askama::render_class_with_methods_wide, verified :154-180) exists precisely because surfaces exceedFieldMask::MAX_FIELDS— and itsWideFieldMask::full_for"unmasked, emit everything" sentinel is exactly the unsafe fallback codex predicted.So on a wide screen, the intersection either can't express grants ≥ 64 or degrades to emit-everything — the opposite of the security headline.
The fix (now MANDATORY for W1+ in the charter)
wide-surface ∩ narrow-role-maskdrops every field ≥ 64 unless a wide grant exists. Absent wide role data: unauthorized by default.ClassRbac::field_mask_wide(role, class) -> WideFieldMask, so wide grants are expressible at all (narrowfield_maskstays for ≤64 surfaces).full_foris a render convenience, never a role-mask fallback — a missing role mask is a refusal. Interim alternative where (b) isn't wired: page the surface into ≤64-field panes and intersect per-pane.Matching correction line appended to
D-A2UI-SCREEN-ADDRESSING(append-only, cites the codex pass).Docs only; the
field_mask_widetrait addition itself is W1 implementation work, in lance-graph-contract/OGAR per the keystone spec's seam.Generated with Claude Code
Generated by Claude Code