|
| 1 | +# D-IAM-SAG-0 — IAM substrate: dir_sim × OGAR × Class/Methods × Software Awareness Graph |
| 2 | + |
| 3 | +> **RFC / implementation handoff, documentation only.** Based on merged [#1509](https://github.com/AdaWorldAPI/lance-graph/pull/1509), merge commit `42fa2a347cda22eaaa327bba514f2029cc9daa82`. The goal is to specify executable, falsifiable IAM projections, not announce six shipped IAM products. No connector writes, security-authority migration, new opcode, second graph engine, or CE64 byte-semantic change is authorized. |
| 4 | +> |
| 5 | +> **Companions:** [Software Awareness Graph](software-awareness-graph-v1.md), [Class × Schema × Methods HotPlug](class-method-schema-hotplug-v1.md), [class/method falsifiers](class-method-hotplug-falsifiers-v1.md), [dir-sim persistence](dir-sim-persist-v1.md), [RBAC nested scope](../board/entries/2026-10-08-rbac-nested-scope-path.md), [research excerpts](../../.arxiv/2026-10_iam_access_paths_temporal_provenance_primary_excerpts.md), [implementation prompt](../prompts/iam-substrate-after-1509.md). OGAR semantic sibling [#357](https://github.com/AdaWorldAPI/OGAR/pull/357) is an RFC, not a shipped dynamic-method link. |
| 6 | +
|
| 7 | +## 0. Question and answer boundary |
| 8 | + |
| 9 | +Could the six functional domains in a typical IAM stack be *typed views* over one provenance-aware identity/entitlement substrate, using existing OGAR/dir_sim/Quack/SoftwareGraph infrastructure rather than reproducing SailPoint, CyberArk, Okta or Intune? |
| 10 | + |
| 11 | +**Candidate answer:** yes for read-only explanation, simulation and proposal *when the relevant graph edges and source-authority semantics are available*. No for live enforcement, SSO, session control, device management and privileged vault features without independent real provider APIs and permission gates. A syntactic class method is not an authorizing identity provider. |
| 12 | + |
| 13 | +Three distinct questions must survive every projection: |
| 14 | +1. **Observed:** what did a version-pinned source actually return? Preserve source, source object identity, effective time, observation time, schema version and completeness. |
| 15 | +2. **Inferred:** what follows from membership, role, device, resource and policy relationships? Preserve complete witness sets or explicitly label a *single* witness, assumptions, rule version and uncertainty. |
| 16 | +3. **Authorized:** which action may a particular actor request or execute *now*, against which authority and version? Re-evaluate outside the analytical graph; mere high confidence never confers permission. |
| 17 | + |
| 18 | +## 1. First-hand inventory and exclusions (as of #1509) |
| 19 | + |
| 20 | +| Surface | Code-grounded behavior [G] | Remaining boundary [P]/[ABSENT] | |
| 21 | +|---|---|---| |
| 22 | +| `crates/lance-graph-dir-sim/src/lib.rs` | Separate users/groups SoA populations, GUID identities, Dn128 location, sparse membership, pure rules, validation, readonly LDAP bytes | Not an AD/Entra/PowerShell writer; no live authentication/authorization product | |
| 23 | +| `dir-sim/src/store.rs`, `view.rs` | `VersionStore` observe/simulate/diff/plan; shared snapshot + delta-sized overlay; versioned provenance and refusal | Cross-policy/source coherent IAM snapshot and schema bridge must be designed | |
| 24 | +| `dir-sim/src/actors.rs` | `GroupRoles::from_policy`, `role_evidence` and `RoleImpact::between`; SID/security-group paths; `Held/NotHeld/Undetermined/NotDeclared` | Role evidence is version-specific and role-scope binding is consumer-owned; don't reinterpret a distribution group as a security group | |
| 25 | +| `dir-sim/src/log.rs`, `image.rs`, `lance-graph-dir-sim-lance` | Persist/replay ingredients with logical VersionId distinct from Lance batch versions; torn-save refusal contract | Availability in production does not imply multi-system transaction or tenant snapshot equivalence | |
| 26 | +| `crates/lance-graph-contract/src/hotplug.rs` and `class_view.rs` | Per-plug authority activation, checked reading, ordered field basis, WideFieldMask | WideFieldMask is field selection, not row-RBAC or access verdict; slab physical reading is distinct from semantic view | |
| 27 | +| `crates/lance-graph-glove-parity/src/awareness.rs` (#1509) | `SoftwareGraph::project` from prepared MethodTable; method/field/program/capability/refusal edges with tier and provenance; Quack Binder | In-memory one-hop projection, caller-supplied revision, limited digest; neither a directory membership store nor persistent general graph engine | |
| 28 | +| `crates/lance-graph-quack/src/bind.rs`, `crates/lance-graph-r2il` | `Draft::bind`, Quack lowering into mask-risc; R2IL FoldDialect execution over borrowed planes | Multi-hop relation composition not automatically solved; cannot carry result masks as an undeclared population between programs | |
| 29 | +| `crates/lance-graph-rbac`, OGAR `GroupRolePolicy` | Separate policy authority and scope/grant primitives | Not an entitlement-certification UI or PDP/PEP for arbitrary external systems | |
| 30 | +| OGAR MethodDecl / `ogar-loco` Inventory / class-method RFC | Source method metadata and keyed body inventory exist; binding composer proposed | `MethodDecl::body_source` is not an executable method; no implicit DO capability | |
| 31 | + |
| 32 | +[#1509](https://github.com/AdaWorldAPI/lance-graph/pull/1509) explicitly leaves **D-SAG-1-4 multi-hop**, **D-SAG-1-6 persistence**, and method identity canonicalization open. Preserve its no-new-opcode/no-second-engine/no-applied-transformation rules. Its H1 SIMD fusion has *not* demonstrated a speedup over the scalar reference. Reuse its `Tier`, `Provenance` and compiler refusals as projected evidence, **not** as a new authority. |
| 33 | + |
| 34 | +## 2. Map the six IAM functions to typed projections |
| 35 | + |
| 36 | +| IAM function | Read-only projection / canonical question | Adapter + side-effect boundary | Honest status | |
| 37 | +|---|---|---|---| |
| 38 | +| IGA (SailPoint, Saviynt) | Identity lifecycle, role/entitlement history, access certification, SoD finding, `why_effective_access?` | HR and entitlement catalogs, review decisions, independent provisioning executor | Core identities/simulation exist, review workflow proposed | |
| 39 | +| PAM (CyberArk, BeyondTrust) | `has_privileged_capability?`, `through_which_grant?`, session and approval evidence | Vault/JIT/session products retain privileged access control, recording and rotation | Projection proposed; not a PAM replacement | |
| 40 | +| Access/SSO (Okta, Ping) | Federation principal, application assignment, role mapping, conditional access evidence | IdP does authentication, token issuance, MFA and session policy | Read graph proposed; **no SSO** implemented | |
| 41 | +| Directory & identity (AD, Entra) | Principal, group, immutable ID, DN location, synced anchor, nested path, what-if membership | Read observations; eventual writes remain external and separately authorized | dir_sim active; cloud correlation depends on available adapter fields | |
| 42 | +| Device/app (Intune) | Device ownership, compliant/unknown/noncompliant, app & CA dependencies | MDM supplies compliance, enrollment and enforcement | New domain schema + adapter required | |
| 43 | +| Automation (PowerShell, APIs) | Auditable `propose/rehearse/approve/execute/verify/revert` | Capabilities checked at immutable context and just before any external write | Quack/R2IL + plans exist; guarded provider DO seam proposed | |
| 44 | + |
| 45 | +The marketing categories overlap; none establishes an ontology or guarantees a source can provide every required edge. |
| 46 | + |
| 47 | +## 3. Minimal IAM graph vocabulary, not a second graph engine |
| 48 | + |
| 49 | +**Node classes** (concept roles, not a mandate to mint numeric ClassIds): `Identity`, `Group`, `Role`, `Entitlement`, `Resource`, `Application`, `Device`, `Policy`, `Grant`, `Session`, `Evidence`, `Change`. Optional source-specific subtypes (human/service identity, privileged role, tenant, cloud object) are *declared schema refinements* only. |
| 50 | + |
| 51 | +**Edges** (direction is part of semantic contract): |
| 52 | +- `Identity MEMBER_OF Group`, `Group MEMBER_OF Group` (source-specific group type/security semantics, nesting scope, witness); |
| 53 | +- `Group GRANTED_ROLE Role`, `Role GRANTS Entitlement`, `Entitlement ALLOWS_ACTION Resource`; |
| 54 | +- `Identity ASSIGNED_APP Application`, `Identity USES Device`, `Policy REQUIRES_CONDITION Device/Session`; |
| 55 | +- `Grant AUTHORIZED_BY Evidence/Policy`, `Session EVIDENCED_BY Evidence`, `Change DERIVED_FROM Evidence`; |
| 56 | +- `ExternalObject CORRESPONDS_TO Identity` only under a reviewed match rule and tenant/sync-anchor evidence. |
| 57 | + |
| 58 | +**Identity:** source AD object GUID, Entra objectId and external provider UUIDs are *source keys* with their own tenant and namespace. DN is a **mutable location** (not the primary key). UPN, mail, aliases and display names are **attributes**, never joins by default. Distinguish OGAR's canonical NodeGuid and per-view ordinals from external GUIDs; map with explicit provenance, don't cast/repack equal-sized values or silently unify tenants. `ClassId` high-u16 concept and full u32 addressed class are different views per D-CMH-0. |
| 59 | + |
| 60 | +**Edges are claims:** identity, source/tenant, (valid_from, valid_to), observed_at, source revision, rule revision, completeness/knownness, provenance and verification tier. `Unknown` is not `false`; `observed` is not `authorized`; a hypothetical delta is not an observation. |
| 61 | + |
| 62 | +**Layered canonicalization:** OGIT canonical field URI and reviewed native alias conversion -> OGAR class/reading authority -> ClassView ordered basis and WideFieldMask for field selection -> Quack numeric binding. Do not equate SAP/Odoo/AD fields by label, and don't move schema semantics into the 8-bit ALU/ISA register contract. CE64, CARE, ONA belief and epistemic tiers can remain contextual readings/evidence policies, not hard-coded identity or action bits. |
| 63 | + |
| 64 | +## 4. Two graphs, one substrate, no semantic conflation |
| 65 | + |
| 66 | +**Business/access graph:** version-pinned directory and authority relationships, entitlements, policy provenance and source observations. `dir_sim` governs directory what-if state; versioned GroupRolePolicy remains policy authority. Real IdP/PAM/MDM behavior is modeled as imported evidence, not delegated to `dir_sim`. |
| 67 | + |
| 68 | +**Software-awareness graph (SAG):** methods, inputs, lowering programs, compiler refusals, capability *claims* and tests from #1509. A proposed IAM `effective_access` method should have a `USES_FIELD`/program dependency projection and can report if it is compiled or refused. A SAG assertion `MayRequire` never supplies an observed entitlement. |
| 69 | + |
| 70 | +The bridge is a **versioned method binding/receipt**: |
| 71 | +`(source snapshot ids, policy version, canonical schema seal, prepared method key, body/plan digest, actor/read scope) -> query result + witness + tier + refusal`. |
| 72 | +Use the D-CMH composer, not another metadata registry. Do not mint method identity in this PR. |
| 73 | + |
| 74 | +**Multi-hop gate:** #1509's one-hop method queries do not implement `Identity -> Group -> Role -> Entitlement`. Compare two legal candidates in D-SAG-1-4/D-CMH-G1-4: (a) typed relation carrier connecting a population output to the next input; (b) factored `EqU32Via` read. Require compiler/Quack/mask-risc parity with a pinned slow reference on cyclic, nested, multiple-path and deleted-edge fixtures. Until one passes, use existing directory membership path logic for directory subgraph and mark broader entitlement closure as proposed. NEVER pipe an arbitrary output Mask as the next program's `LIVE` population. |
| 75 | + |
| 76 | +## 5. Worked scenario: Anna's accounting entitlement |
| 77 | + |
| 78 | +Illustrative data, never real personal data: |
| 79 | +```text |
| 80 | +Principal AD-guid(A), Tenant(T) --MEMBER_OF/security--> GRP_Finance |
| 81 | +GRP_Finance --MEMBER_OF/security--> APP_ERP_Accounting |
| 82 | +APP_ERP_Accounting --GRANTED_ROLE/policy-v7--> ERP_Write |
| 83 | +ERP_Write --GRANTS--> Accounting_Write on ERP_Ledger |
| 84 | +Device(D) --COMPLIANCE@mdm-v12--> Unknown |
| 85 | +``` |
| 86 | + |
| 87 | +Requests: |
| 88 | +1. `explain_access(A, ERP_Ledger, Write, as_of=V, policy=p7)`: enumerate **all** supporting paths or declare `one witness / nonexhaustive`; include policy, source and snapshot receipt. |
| 89 | +2. `revoke_preview(A, GRP_Finance)`: `VersionStore.simulate` on base V, evaluate effective roles for both views with `RoleImpact::between`, compute target entitlement deltas; ensure another valid path preserves access. |
| 90 | +3. `why_not_access?`: if the device/CA policy is missing, report `Undetermined/Unknown`, *not* a denial or approval. |
| 91 | +4. `propose_action`: stage an inert change with preconditions and impact; policy authority separately gates `approve` and eventual external executor. |
| 92 | + |
| 93 | +Distinguish **effective graph grant**, **authentication success**, **conditional access evaluation**, and **live enforcement**. A directory membership cannot prove an IdP token was accepted. |
| 94 | + |
| 95 | +## 6. Method sketch (illustrative, intentionally not a Rust API claim) |
| 96 | + |
| 97 | +```text |
| 98 | +class Identity { memberships, effective_access, access_history, |
| 99 | + role_evidence, simulate_removal, reconcile } |
| 100 | +class Entitlement { explain, principals, blast_radius, revoke_preview } |
| 101 | +class Device { compliance, linked_identities, access_dependencies } |
| 102 | +class Grant { policy, witnesses, effective_during } |
| 103 | +class Change { preview, validate, approve, execute, verify, revert } |
| 104 | +``` |
| 105 | + |
| 106 | +**Execution class:** `PureRead | VersionPinnedRead | Propose | ExternalMutate` is an RFC name only. `PureRead` and `Propose` use existing Quack/R2IL and dir_sim primitives. `ExternalMutate` is not a Quack opcode and must refuse unless independently authorized, with fresh source preconditions and external connector attestation. An absent field, alias, authority, schema seal, body, read scope, source version, evidence completeness or capability causes an explicit typed refusal. |
| 107 | + |
| 108 | +## 7. Falsifiers and acceptance matrix |
| 109 | + |
| 110 | +| ID | Fixture / negative test | Expected oracle | |
| 111 | +|---|---|---| |
| 112 | +| IAM-01 | Same UPN across tenants, renamed DN | two distinct source keys; stable GUID identity; no accidental join | |
| 113 | +| IAM-02 | user -> security group -> nested security group -> role | same effective role and witness as dir_sim `role_evidence` | |
| 114 | +| IAM-03 | distribution group in nested chain | no transitive security role gained | |
| 115 | +| IAM-04 | two independent routes to the same entitlement; remove one | access remains; lost witness != lost entitlement | |
| 116 | +| IAM-05 | unknown group policy (never observed) vs explicitly empty policy | `Undetermined` vs `NotHeld`; cannot certify absence from unknown | |
| 117 | +| IAM-06 | stale source observation, policy revision changes mid-query | pinned result or typed `VersionMismatch`; never silently mix | |
| 118 | +| IAM-07 | one simulated membership removal + replay | original unchanged; deterministic diff/plan; replay matches; no external IO | |
| 119 | +| IAM-08 | revoked and newly minted grant; two time windows | access only inside authorized interval; no time-travel leakage | |
| 120 | +| IAM-09 | schema/reading drift or missing required field/validity plane | explicit refusal; no default known/allowed | |
| 121 | +| IAM-10 | SAG declares `MayRequire FirstOfRun` but no compiled program | hypothesized/claimed, not shipped; no fabricated authorization | |
| 122 | +| IAM-11 | duplicate log/evidence derivations | provenance distinguishes source vs inference; no double confidence count | |
| 123 | +| IAM-12 | actor without execute permission; forged approval or policy confidence | all external action attempts refuse, no provider writes | |
| 124 | +| IAM-13 | unknown device compliance under conditional-access dependency | indeterminate, not permitted/denied based on guess | |
| 125 | +| IAM-14 | cost benchmark of multi-hop vs pinned reference | correctness first, memory/latency measured by dataset and CPU tier; no claimed speedup without data | |
| 126 | +| IAM-15 | disable key checks separately (source scope, knownness, external effect gate, witness alternatives, snapshot pinning) | each deliberate mutation makes a named test red | |
| 127 | + |
| 128 | +Represent each test with source data, sealed schema/policy revisions, `actual`, `expected`, refusal/witness and oracle provenance. Record disable tests rather than merely asserting the guard exists. |
| 129 | + |
| 130 | +**Two high-value regression models:** (a) duplicate license assignment from competing sources and (b) legitimate user losing a license during reconciliation. Define synthetic inputs and precedence rules, run proposed changes through `dir_sim`; neither incident should be claimed fixed until the relevant semantics and parity tests exist. |
| 131 | + |
| 132 | +## 8. Execution slices and stop signs |
| 133 | + |
| 134 | +- **W0 Inventory, no Rust changes:** verify #1509 source/tests, OGAR semantic ownership, dir_sim latest exact APIs, policy version model, Quack relation carrier. Label each contract `[G]`, `[P]`, `[ABSENT]`. Review whether analogous methods already exist before adding one. |
| 135 | +- **W1 Typed read-only IAM fixture:** reuse version-pinned `VersionStore`, `GroupRolePolicy`, existing membership/role evidence. Produce explainable `Held/NotHeld/Undetermined` rows with provenance, including one-witness vs all-paths semantics. Pin IAM-01..05. |
| 136 | +- **W2 Canonical class/method binding:** compose in existing allowed consumer layer under D-CMH-0, OGIT field identity, ClassView field basis, schema seal, per-plug authority and existing Quack Binder; project methods/actual compiler verdicts into SAG. Pin IAM-09/10 and policy-source separation. |
| 137 | +- **W3 Multihop/read-only access impact:** select a legal relation carrier or existing `EqU32Via` plan after oracle comparison; don't introduce a traversal runtime by stealth. Implement two-version before/after and alternate-path cases, pin IAM-04/06..08/13. |
| 138 | +- **W4 Optional ONA-style introspective proposer:** SAG can inspect `refusal -> gap -> test -> candidate`; choose what to investigate using declared budget/uncertainty but *never* let an uncertain signal mutate provider state. Keep epistemic confidence, causal hypothesis, and authority separate. Pin IAM-11/12 and ablate the prioritizer against no-observer baseline. |
| 139 | +- **W5 Authorized execution (separate PR only):** source authority and RBAC signing, actor-bound scope, reviewed change, idempotency, check-and-set, provider-specific receipts, conflict/refusal and revert feasibility. NO execution in this RFC. |
| 140 | + |
| 141 | +### W4 observation/control loop (optional) |
| 142 | + |
| 143 | +```text |
| 144 | +observe actual grant/policy evidence -> explain via existing graph |
| 145 | + -> identify unverified/undetermined/violating claim (not an enforcement verdict) |
| 146 | + -> produce candidate explanation/test/dir_sim delta |
| 147 | + -> run read-only counterfactual and dependency ablation |
| 148 | + -> label Verified / Refuted / Undetermined with source receipts |
| 149 | + -> present proposal for human/provider authority, no automatic DO |
| 150 | +``` |
| 151 | + |
| 152 | +Do not equate Shannon entropy with epistemic uncertainty, policy risk or access authorization; report them as distinct measures. The Rubicon/Heckhausen, ONA, Hyperon metagraph and CARE analogies are **research hypotheses** for investigation priority, not license to repurpose CE64 bits 59..63 or identify a policy action with a belief. |
| 153 | + |
| 154 | +## 9. Research decisions and traceability |
| 155 | + |
| 156 | +See [primary-source excerpts](../../.arxiv/2026-10_iam_access_paths_temporal_provenance_primary_excerpts.md) for paraphrased page/section references, direct publication links, transfer limits and falsifiers. Key non-claims: |
| 157 | + |
| 158 | +- NIST SP 800-162 ABAC and SP 800-207 Zero Trust constrain access evaluation and enforcement; neither validates an IAM product built from a graph query. |
| 159 | +- Why-provenance can be computationally hard for recursive queries; do not conflate *one witness* with a complete minimal explanation. |
| 160 | +- Temporal RBAC constraints require who/what/when; an immutable snapshot alone does not define real-time authorization. |
| 161 | +- Hyperon and NARS are architectural references for self-representation and revisable observation, not security accreditation, a replacement engine, or evidence of subjective cognition. |
| 162 | + |
| 163 | +## 10. Deliverables for the implementation successor PR |
| 164 | + |
| 165 | +- A code-grounded contract matrix and accepted naming/authority for canonical IAM concepts. |
| 166 | +- A small sealed synthetic dataset and a strict reference evaluator for graph access/role impact. |
| 167 | +- Read-only method projections whose compiler proofs/refusals appear in SAG, not hand-authored 'Verified' tiers. |
| 168 | +- IAM-01..15 test matrix with disable/falsification evidence; one passing end-to-end `explain -> simulate -> re-evaluate -> propose` demo. |
| 169 | +- Measurement table (baseline, candidate, environment, versions) before any performance claim. |
| 170 | +- Security review showing external provider writes impossible in read-only mode; no unreviewed policy/byte-layout/ISA drift. |
0 commit comments