diff --git a/docs/A2UI-SCREEN-ADDRESSING-PROPOSAL.md b/docs/A2UI-SCREEN-ADDRESSING-PROPOSAL.md index c0aa73f..41aa475 100644 --- a/docs/A2UI-SCREEN-ADDRESSING-PROPOSAL.md +++ b/docs/A2UI-SCREEN-ADDRESSING-PROPOSAL.md @@ -62,6 +62,37 @@ screen — same mechanism, different renderer. brick from the SoC/dedup pipeline). A field the role may not see is not *hidden on the client* — it is **absent from the wire**. Pixel streams cannot make that guarantee; address streams get it for free. + **CORRECTION (codex P2 on #204, verified in-repo):** as merged, this + claim silently breaks for surfaces with >64 fields — the RBAC seam's + `ClassRbac::field_mask` returns a NARROW `FieldMask` (u64; + `CLASSID-RBAC-KEYSTONE-SPEC.md` §4), while the wide renderer exists + precisely because surfaces exceed `FieldMask::MAX_FIELDS` + (`ogar-render-askama::render_class_with_methods_wide`, whose + `WideFieldMask::full_for` "emit everything" sentinel is exactly the + unsafe fallback). Three requirements make the claim hold, all MANDATORY + for W1+: + (a) **Retype in place — `WideFieldMask` already exists (operator + correction, 2026-07-14):** NO parallel `field_mask_wide` method. + `ClassRbac::field_mask` changes its return type to [`WideFieldMask`] + directly — verified cheap: 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 everything else. `WideFieldMask` + is already the universal mask (`Small` repr ≤64, self-promoting past + 64) — a second method name for the same projection would be the + two-vocabularies anti-pattern (T1) applied to the seam itself. + (b) **The permit-all identity is the ONE W1 decision:** `WideFieldMask` + has `EMPTY` + `full_for(count)` but no count-free permit-all, and the + axis-4 default is deliberately "FULL unless configured" (RBAC opt-in). + Either `WideFieldMask` gains `ALL` (the intersection identity) or the + default derives `full_for(field_count)` from the ClassView. W1 decides; + the opt-in default semantics survive either way. + (c) **Zero-extension rule (fail-closed) for legacy narrow interop:** + wherever an existing narrow `FieldMask` (SoC/dedup bricks) meets a wide + surface, the narrow mask extends past bit 63 as ZEROS, never as full. + And the sentinel ban: `full_for` as a RENDER convenience is fine; as an + RBAC fallback it is forbidden — a missing role mask is a refusal, not a + full grant. 5. **rdp-2graph security = reuse, no new crypto:** session KDF via `ogar-auth` (Argon2 — the MedCare Tier-1 password/totp home), transport via `ogar-encryption` (the single generic encryption surface). The diff --git a/docs/DISCOVERY-MAP.md b/docs/DISCOVERY-MAP.md index b537853..0e7e394 100644 --- a/docs/DISCOVERY-MAP.md +++ b/docs/DISCOVERY-MAP.md @@ -1397,3 +1397,14 @@ isolation. The map's job is to keep them visible. Charter: `docs/A2UI-SCREEN-ADDRESSING-PROPOSAL.md`. Depends: D-DOC-IR-SECOND-RETINA (A3 template ruling), D-OGAR-DOC-LAYER (DocRenderer), the Klickwege/ActionDef harvests (MedCare-rs). + **Correction 2026-07-14 (codex P2 on #204, verified in-repo; sharpened by + operator same day — "we already have WideFieldMask"):** the + RBAC-by-projection claim requires WIDE role masks — `ClassRbac::field_mask` + is narrow (u64) while wide surfaces exceed 64 fields. Fix per the charter's + C1.4 CORRECTION: **retype `field_mask` → `WideFieldMask` in place** (NOT an + additive `field_mask_wide` — the type already exists and self-promotes; + verified cheap: production surface = the trait default + one test + override); the one W1 decision is the permit-all identity (`ALL` on + `WideFieldMask`, or default `full_for(field_count)`); zero-extension + fail-closed for legacy narrow-mask interop; sentinel ban (`full_for` is a + render convenience, never an RBAC fallback; missing role mask = refusal).