diff --git a/.claude/board/LATEST_STATE.md b/.claude/board/LATEST_STATE.md index 450c78bfc..574d06b0d 100644 --- a/.claude/board/LATEST_STATE.md +++ b/.claude/board/LATEST_STATE.md @@ -1,4 +1,8 @@ -## 2026-11-06 — branch `ccr-fd2682ed-sai06j-lanesock-harden` (D-LANESOCK-3, in PR) +## 2026-11-06 — branch `ccr-fd2682ed-sai06j-scope-inventory` (D-LANESOCK-4, in PR) + +- Spec §8 records where a sealed reader scope and its issuer can live: OGAR `VerifiedLogin` is the only login proof, decisions are values not witnesses, `FrameStore` is the sealing precedent, and the issuer belongs in OGAR or downstream (dependency direction). No code. + +## 2026-11-06 — main after #1970 (merged `fb27c46`, D-LANESOCK-3) - `LaneSource::lane_of` takes the `FieldRef` DT64 validated (`basis`); `AbiLanes` holds no ClassView. A check through a reordered ClassView of equal class, revision and count refuses `MappingChanged`. - `AbiLanes::unwitnessed` is `#[cfg(test)]`; the `unwitnessed-scope` feature is gone, so no build (any features) constructs an `AbiLanes`. diff --git a/.claude/board/PR_ARC_INVENTORY.md b/.claude/board/PR_ARC_INVENTORY.md index 329b86832..e7f6e8919 100644 --- a/.claude/board/PR_ARC_INVENTORY.md +++ b/.claude/board/PR_ARC_INVENTORY.md @@ -1,3 +1,10 @@ +## 2026-11-06 — lance-graph PR #1970 (merged `fb27c46`) — D-LANESOCK-3: one field basis, test-only scope admission + +- **Added:** `LaneSource::lane_of(.., basis: &FieldRef, ..)` carries the field DT64 validated; `AbiLanes` holds no ClassView; three implementers updated; `AbiLanes::unwitnessed` and its suite moved to `#[cfg(test)]`, the `unwitnessed-scope` feature removed; spec §8 consumer contract and reader-scope inventory; board for #1969. +- **Locked (measured):** RED reproducer at `49d11c2` (a reordered ClassView of equal class, revision and count returned another lane); after the fix a check through it refuses `MappingChanged`; disable run turns the test red; report crate 55 tests. +- **Not done:** no reader-scope issuer; no production admission; value ingress, writer, codebook, exact decimal, D4/S-INGRESS open. +- **Confidence:** CI green on the merged head. + ## 2026-11-06 — lance-graph PR #1969 (merged `53e849a`) — D-LANESOCK-2: AbiBatch lanes through the DT64 lane socket - **Added:** `lance-graph-report::AbiLanes` (`LaneSource` over a resident `AbiBatch`, `publish`, `PublishRefusal`); `AbiBatch` column cap `MAX_COLUMNS` with a checked `u16` lane index (Codex P2: `i as u16` wrapped column 65,536 onto column 0 for every caller); `RegistryClassView` concept-half key test; `rust-test.yml` runs the report tests. diff --git a/.claude/board/STATUS_BOARD.md b/.claude/board/STATUS_BOARD.md index e19cc647f..0e93774c2 100644 --- a/.claude/board/STATUS_BOARD.md +++ b/.claude/board/STATUS_BOARD.md @@ -5,7 +5,8 @@ | D-LANESOCK-0 | normative spec: socket, joint version witness, refusals | Shipped (#1966) | | D-LANESOCK-1 | `LaneSource` + `BindStore::bind_lanes` + falsifiers in lance-graph-dt64 and the dir-sim lab | Shipped (#1967) | | D-LANESOCK-2 | `AbiLanes`: resident `AbiBatch` I32/U32 lanes through `LaneSource` (read adapter; no production constructor until a DR reader-scope witness exists) | Shipped (#1969) | -| D-LANESOCK-3 | one field basis (`lane_of` receives DT64's validated `FieldRef`); `AbiLanes` constructor `#[cfg(test)]`-only; downstream consumer contract + reader-scope inventory (spec §8) | In PR | +| D-LANESOCK-3 | one field basis (`lane_of` receives DT64's validated `FieldRef`); `AbiLanes` constructor `#[cfg(test)]`-only; downstream consumer contract + reader-scope inventory (spec §8) | Shipped (#1970) | +| D-LANESOCK-4 | reader-scope seam inventory: where a sealed scope and its issuer can live (spec §8); no code | In PR | ## D-CGMM — Lazy Codegraph fact/demand + MeTTa class-method scratch (2026-11-04) diff --git a/.claude/board/entries/2026-11-06-reader-scope-seam-inventory.md b/.claude/board/entries/2026-11-06-reader-scope-seam-inventory.md new file mode 100644 index 000000000..39475b071 --- /dev/null +++ b/.claude/board/entries/2026-11-06-reader-scope-seam-inventory.md @@ -0,0 +1,12 @@ +# Reader-scope seam inventory (D-LANESOCK-4) + +**Date:** 2026-11-06. **Status:** in PR, docs only. Follows D-LANESOCK-3 (#1970, merged `fb27c46`). + +- `ogar_auth::federation::VerifiedLogin` is the only sealed proof of login; `AuthenticatedUser` has public fields and proves nothing. +- `authorize_identity` / `authorize_user` return decisions (allow/deny, row scope, field mask) that carry no actor, class, frame or issuer: values, not witnesses. +- `dr::Scope` is a bare id compared by equality; all literal constructions are in tests, examples or probes. `FrameStore`/`Frame` is the sealing precedent; `GuardWitness` is value-derived and cannot carry authority. +- dt64 and rbac depend only on the contract; OGAR depends on lance-graph. An issuer starting from `VerifiedLogin` lives in OGAR or downstream. +- Shape: a sealed scope type next to `Scope` in dt64, issued by its own store; the issuer holds the store and issues only from `VerifiedLogin` via `authorize_identity`. +- Downstream (report-rs `83093de`, reported to its owner): `None` → all customers in `LanceGraphScope::decide_in`; `RoleScopeAuthority::scope_for` accepts a hand-built `AuthenticatedUser`. + +Full text: `.claude/plans/d-lanesock-dr-dt64-lane-socket-v1.md` §8. diff --git a/.claude/board/entries/README.md b/.claude/board/entries/README.md index 2105f5edb..e0eff89d2 100644 --- a/.claude/board/entries/README.md +++ b/.claude/board/entries/README.md @@ -25,11 +25,12 @@ index row, (3) no duplicate entry id. Checks 1 and 2 are deliberately opposite directions; the stranding this convention prevents shows up in exactly one of them, never both. -582 entries, 2026-08-06 .. 2026-11-06. +583 entries, 2026-08-06 .. 2026-11-06. | date | entry id | finding | file | |---|---|---|---| | 2026-11-06 | `ruler-plane-batch-selection-lab` | | [2026-11-06-ruler-plane-batch-selection-lab.md](2026-11-06-ruler-plane-batch-selection-lab.md) | +| 2026-11-06 | `D-LANESOCK-4` | | [2026-11-06-reader-scope-seam-inventory.md](2026-11-06-reader-scope-seam-inventory.md) | | 2026-11-06 | `D-LANESOCK-3` | | [2026-11-06-lanesock-one-field-basis.md](2026-11-06-lanesock-one-field-basis.md) | | 2026-11-06 | `D-LANESOCK-2` | | [2026-11-06-abibatch-lane-socket.md](2026-11-06-abibatch-lane-socket.md) | | 2026-11-05 | `hybrid-ordinal-chain-lab-v2` | | [2026-11-05-hybrid-ordinal-chain-lab-v2.md](2026-11-05-hybrid-ordinal-chain-lab-v2.md) | diff --git a/.claude/plans/d-lanesock-dr-dt64-lane-socket-v1.md b/.claude/plans/d-lanesock-dr-dt64-lane-socket-v1.md index 7764518e4..e4c301d19 100644 --- a/.claude/plans/d-lanesock-dr-dt64-lane-socket-v1.md +++ b/.claude/plans/d-lanesock-dr-dt64-lane-socket-v1.md @@ -130,6 +130,29 @@ The missing seam is a witness that seals an authorized decision (decision + row - report-rs's ZITADEL login and its `RoleScopeAuthority` are a downstream integration point that would supply the actor to this chain, not a second upstream identity authority. - Source status (available, stale, unknown) is reported only from observed evidence. +### Reader-scope seam: where it can live (2026-11-06, D-LANESOCK-4) + +Read in code at lance-graph `fb27c46`, OGAR main and report-rs `83093de`. Nothing here is built. + +**Authentication.** OGAR `ogar_auth::federation::VerifiedLogin` is the proof of a login: private fields, no public constructor, `From` or `Default`; `establish` is its only producer (`ogar-auth/src/federation.rs:199-213`). `AuthenticatedUser` is not a proof: its fields are public and its own docs call it "descriptive, not a proof" (`ogar-auth/src/user.rs:296-308`). + +**Authorization.** `ogar_rbac::authorize_identity(&RbacBinding, &AuthenticatedUser, class, op) -> MembershipDecision` (`ogar-rbac/src/lib.rs:327`) and `OgarRbac::authorize_user -> ScopedDecision` (`:155`) run the `lance-graph-rbac` kernels. A decision carries allow/deny, a row scope and a field mask, but no actor, class, frame or issuer identity: it is a value, not a witness. `scope: None` means at least one granting membership is unscoped. + +**DR.** `dr::Scope { pub id: u64 }` is compared by equality only (`dr.rs:503`, `lane.rs:209`). Every literal construction in lance-graph and OGAR is in a test, example or probe crate (about 50 sites). The sealing precedent is `FrameStore` / `Frame`: issuer identity, no public constructor, two stores never equal. `GuardWitness` is the other precedent and is value-derived (equal guards, equal witnesses), so it cannot carry authority. + +**Dependency direction.** `lance-graph-dt64` and `lance-graph-rbac` each depend only on the contract; OGAR depends on lance-graph (`ogar-rbac` → `lance-graph-rbac`), never the reverse. An issuer that starts from `VerifiedLogin` therefore lives in OGAR or a downstream consumer, not in lance-graph. + +**Shape the code admits.** + +1. dt64 gains a sealed reader scope next to `Scope`, issued by its own store like `FrameStore` issues `Frame`. A new type, so the test literals of `Scope` stay valid; the lane socket would compare the sealed scope instead of the bare id. +2. The issuer holds that store, lives in OGAR or downstream, and issues only from a `VerifiedLogin` through `authorize_identity`, binding actor, class, row scope, field mask and policy version, checked against the frame it was issued for. +3. It keeps the rules above, plus: nothing keys on a hand-built `AuthenticatedUser`. + +**Downstream observations (report-rs `83093de`, reported to its owner, not changed here).** + +- `LanceGraphScope::decide_in` maps `scope: None` to all customers (`src/iam.rs:231`). Safe today only because report-rs's actor source emits `None` solely for an explicit all-customers grant. +- `RoleScopeAuthority::scope_for(&AuthenticatedUser)` (`src/flow_scratch.rs`, around 288-306) binds the user id from a `VerifiedLogin` at construction but accepts any `AuthenticatedUser` with that id. The trait is OGAR's (`ReportAuthority`, `ogar-flow-m365/src/host.rs:88`). + ### Still closed Value ingress and the durable workbook writer; D4/S-INGRESS and layout admission; text/codebook authority; exact decimal; production CRM_COMPANY XVERWEIS; cross-coordinate Gather, ADMISSION B, NotASide, OP-14; the `RegistryClassView` DOLCE `entity_type_id` defect (tracked separately).