|
| 1 | +# D-QR-IAM: typed QR256 relationship composition over dir-sim's borrowed views |
| 2 | + |
| 3 | +**Date:** 2026-10-21. **Status:** LAB-ONLY PLAN / FALSIFIERS, unimplemented. No AD, Entra, Exchange, LDAP or PowerShell writes. |
| 4 | + |
| 5 | +## Hypothesis |
| 6 | + |
| 7 | +**Avoid handrolling derived IAM edges** by compiling already-known identity, predicate, role and group mappings into a small Boolean relational view, with `ClassView` + `WideFieldMask` identifying **eligible stable field positions**, #1659 providing a candidate borrowed global→local register, and #1660 a typed QR256 Bool `OR/AND` fold plus optional cold proof DAG. |
| 8 | + |
| 9 | +The derivation `EffectiveRole(user,role) = EXISTS group: Member(user,group) AND Grant(group,role)` is one test target. `WideFieldMask` DOES NOT itself encode group membership, evidence origin, a group path, identity correspondence or permission. No automatic assumption that equals numeric row ordinal means equals entity across populations. |
| 10 | + |
| 11 | +## Existing ground truth |
| 12 | + |
| 13 | +- `lance-graph-dir-sim/src/lib.rs`: snapshots have independent users/groups 16-bit ordinal spaces (up to 65,536 each) and sparse many-to-many membership, shared version with overlays, Quack selection and simulated execution only. |
| 14 | +- `bind.rs::UserBinder` resolves UPN/SMTP to comparison `KeyId` once using existing Quack binding. |
| 15 | +- `groups.rs` separates MailEnabled and SecurityEnabled from nesting; mail chains and SID chains have distinct semantics. |
| 16 | +- `View::members_transitive[_through]`, `View::groups_transitive` and `actors` are the **independent oracles**, not code to remove before parity is proven. |
| 17 | +- `ClassView::fields` (append-only positions) and `WideFieldMask` in contract are the candidate schema geometry. `OrderedLaneWitness` means order must be sealed, not inferred. EXO-46 / #1640 ADMISSION B still apply. |
| 18 | + |
| 19 | +## Contract sketch (not new Rust API) |
| 20 | + |
| 21 | +```text |
| 22 | +BoundRelationship { |
| 23 | + source_class, target_class, predicate_id, |
| 24 | + field_basis: ClassView::fields(...), presence: WideFieldMask, |
| 25 | + source_identity: GUID/CodebookWitness, target_identity: GUID/CodebookWitness, |
| 26 | + source_order, target_order, snapshot_generation, authority_scope, |
| 27 | + method8: BoolCompose, axes: UserLocal8×GroupLocal8 | GroupLocal8×RoleLocal8 |
| 28 | +} |
| 29 | +``` |
| 30 | + |
| 31 | +The **QR256 register stores up to 256×256 bits**, not all 65k×65k directory edges at once. Chunked focuses require explicit external-frontier continuation and witnessed remapping. A 64×64 QR64 is 512 B and can serve smaller focuses; never silently drop an external membership. |
| 32 | + |
| 33 | +## Falsifier paths |
| 34 | + |
| 35 | +| Test | Independent reference | Fail condition | |
| 36 | +|---|---|---| |
| 37 | +| I1 Mapping | stable ClassId + ordered FieldRef and `WideFieldMask` selection; compare `UserBinder` exact UPN/SMTP | unknown field/key or swapped class/ref yields relation anyway | |
| 38 | +| I2 One hop | parent group→member, user group→role Boolean existence vs `View`/RBAC oracle | same numerical ordinal used as foreign identity | |
| 39 | +| I3 Security chain | nested security groups grant role; existence and complete witness chain match source | a non-security intermediate group unexpectedly transmits permission | |
| 40 | +| I4 Mail chain | distinct `MailEnabled` semantics, no SID-derived email permission | an unaddressable group transmits mail | |
| 41 | +| I5 Duplicates | Count/BAG matches independent multiset oracle; Bool EXISTS remains idempotent | two supporting paths XOR-cancel or support deletion erases surviving grant | |
| 42 | +| I6 Version delta | edit membership, group property or authorization; recompute `BEFORE XOR AFTER` and independent full refresh | stale index, deleted group, old thought incarnation or revoked access still returns authorized true | |
| 43 | +| I7 Focus | 256-slot maximum focus with bridges beyond focus, 257th edge external-frontier case | truncated reachability or implicit out-of-scope dereference | |
| 44 | +| I8 Cost | direct `View` walk, existing Quack, borrowed co-addressed masks, QR64/QR256; count allocations and source bytes | unprofitable index/materialization promoted as win | |
| 45 | + |
| 46 | +## Execution plan |
| 47 | + |
| 48 | +1. Perform a read-only census of `snapshot.rs`, `view.rs`, `groups.rs`, `actors.rs`, `ogar_rbac::group_policy`; distinguish what's implemented vs planned. |
| 49 | +2. Register a prototype typed relationship declaration **outside production directory store**; compile eligible FieldRefs/selection masks through existing contract surfaces. |
| 50 | +3. Introduce a bounded borrowed address view with version/authority witness. Do not write an index from a foreign lane's value to select positions in another table; #1640 ADMISSION B forbids this. |
| 51 | +4. Evaluate Boolean join/closure via existing mask-risc / ndarray tiles; no new recursive VM, no new permissions engine, and no template-as-string materialization. |
| 52 | +5. Verify all positive and counterexample fixtures against `View` and independent multiset reference. If any premise is unknown, return typed UNKNOWN/refusal, not FALSE. |
| 53 | +6. Measure 1, 8, 64 and 256 slots, nested depth, 257/external focus, duplicate supports; log cold/index + hot + proof costs separately. |
| 54 | +7. Only after parity and permissions, propose cross-domain generalization to actual SAP or HubSPO; NO production IAM changes. |
| 55 | + |
| 56 | +**Explicit non-goals:** no live directory mutation, no group-role schema minting without OGAR evidence, no CE64 encoding change, no privilege inferred from class presence, no new `Edge` heap object, no assumed transitivity for an arbitrary relation. |
| 57 | + |
| 58 | +**References:** [#1659](https://github.com/AdaWorldAPI/lance-graph/pull/1659), [#1660](https://github.com/AdaWorldAPI/lance-graph/pull/1660), [EXO-79](https://linear.app/exo-red/issue/EXO-79), [EXO-86](https://linear.app/exo-red/issue/EXO-86), [EXO-46](https://linear.app/exo-red/issue/EXO-46), [EXO-50](https://linear.app/exo-red/issue/EXO-50). |
| 59 | + |
| 60 | + |
| 61 | +## Cross-PR ISA/PART_OF zipper experiment |
| 62 | + |
| 63 | +See the [capstone](https://github.com/AdaWorldAPI/lance-graph/blob/research/qr-abi-classview-capstone-20261021/.claude/plans/d-qr-abi-classview-rails-capstone-v1.md). Existing `FacetCascade` already carries six `8:8` pairs after its 4-byte class prefix. Test the *declared* horizontal interpretation `(part_of:u8, is_a:u8)` with 256 local codes/axis against dir-sim's **distinct** `UserOrdinal` and `GroupOrdinal` u16 spaces. The proposed `HHTL16-IsA[16]` and `HHTL16-PartOf[16]` are two separate **logical 16-byte vertical chains**, NOT available 16-byte persisted registers in current code; the existing HHTL nibble path is 16×4-bit, not this 16×8-bit proposal. Compression/fold from global u16 ordinals into local u8 codes must be witnessed and bounded, or return continuation/refusal. |
| 64 | + |
| 65 | +**I9 additional probe:** on a mixed membership/is_a/part_of fixture, preserve typed rules: a subtype does not become a group member, a containment edge does not automatically confer a role, and identity itself does not prove permission. Test 256th vs 257th local entity, cycle, ambiguity, class prefix mismatch, and two distinct global IDs mapped to the same u8. Prefix-composition laws must be separately declared, not inferred from byte adjacency. |
0 commit comments