# Canon Mapping Status: candidate Updated: 2026-06-05 This document maps current `user-engine` implementation concepts to identity-canon and InfoTechCanon concepts. It is intentionally explicit about owned facts, consumed facts, references, and gaps. ## Mapping Stance `identity-canon` treats `User` as a convenience term, not the root concept. `user-engine` keeps the existing `User` implementation class for compatibility, but exposes canon-facing context through `identity_context` so consumers can see the distinct account, actor, subject, principal, tenant, membership, profile, and evidence references. ## Entity Mapping | user-engine concept | Canon concept | Ownership | Notes | | --- | --- | --- | --- | | `Actor` | Actor | consumed/reference | Normalized from verified IAM claims; not persisted as source of truth. | | `Actor.issuer + Actor.subject` | Authenticated Subject / Scoped Identifier | consumed/reference | Protocol-level identity after authentication. | | `User` | User convenience term / profile holder | owned local record | Not treated as Natural Person unless a future mapping proves that relationship. | | `Account` | Account | owned | Operational account state for the user-engine scope. | | `TenantAccount` | Account scoped to Tenant | owned | Tenant-local account lifecycle state. | | `ExternalIdentity` | Identity Record / Scoped Identifier / Synonymity Assertion seed | owned link | Links issuer-subject pairs to local user records without destructive merge. | | `Application` | Scope / Application Service reference | owned local registry | Application-specific profile consumer and catalog owner. | | `ApplicationBinding` | Trust Relationship / integration binding | owned local registry | Binds user-engine app IDs to external clients, protected systems, events, and catalogs. | | `Membership` | Membership Relationship | owned when created here | Relationship from user/account context to tenant, team, application, group, or other scope. | | `Membership.kind` | Role label / grant-like fact | owned local label | Role-like string is not a final authorization decision. | | `ProfileValue` | Profile | owned | Scoped presentation or preference value. | | `Catalog` / `AttributeDefinition` | Profile schema / governance metadata | owned | Attribute ownership, sensitivity, visibility, and mutability metadata. | | `AuthorizationRequest` | Authorization request | emitted/consumed | Sent to authorization port; policy decision remains external. | | `AuthorizationDecision` | Authorization decision | consumed/reference | Enforced locally; decision authority remains external. | | `AuditRecord` | Evidence Source | owned local evidence, exportable | Local operational evidence; durable platform audit is external. | | `OutboxEvent` | Lifecycle event / evidence source | owned local event | Integration event queue for downstream systems. | ## Relationship Mapping | Relationship | Source | Target | Implementation source | | --- | --- | --- | --- | | `identity_link` | Identity Record | User | `ExternalIdentity.user_id` | | `belongs_to_tenant` | User or Account | Tenant | `TenantAccount` and tenant-scoped operations | | `authenticates_as` | Account | Authenticated Subject | normalized IAM claims | | `evaluated_as` | Authenticated Subject | Authorization Principal | `identity_context` principal projection | | `member_of` | User | Team / Group / Scope | `Membership(scope_type, scope_id)` | | `role_label` | Membership Relationship | Role | `Membership.kind` | | `scoped_to` | Access Grant or grant-like fact | Tenant / Scope | `Membership.tenant` and operation tenant | | `governed_by` | Grant-like fact / decision | Policy reference | external policy/control resolver gap | | `implemented_by` | Policy reference | Control reference | external policy/control resolver gap | | `evidenced_by` | Identity-domain claim or grant-like fact | Evidence Source | local audit or external evidence exporter | | `creates_task` | Evidence gap / integration gap | lifecycle task reference | lifecycle task sink gap | ## Read Model `UserEngineService.identity_context(...)` returns the current implementation surface for canon-facing identity context. It includes: - the normalized actor; - local user and account records; - external identity links; - tenant and optional application scope; - membership facts; - entity references for User, Account, Actor, Authenticated Subject, Authorization Principal, Tenant, Identity Record, Scoped Identifier, Team, Scope, Membership Relationship, and Role; - relationship references for identity link, tenant scope, authentication, principal evaluation, membership, role label, and grant-like scope; - access grant-like references derived from memberships; - evidence references derived from audit records; - an optional effective profile projection; - explicit gaps when evidence is missing. ## Current Gaps - `Natural Person` is not modeled directly. A user record may represent a human profile holder, but that relationship is not currently asserted. - `Synonymity Assertion` is implicit in identity linking. Strong/weak link confidence, verification method, privacy scope, and revocation state are not first-class yet. - `Organization`, `Customer`, `Vendor`, and `Legal Entity` are referenced only through tenant, team, owner, or external system identifiers. - `AccessReview`, `Policy`, `Control`, `Exception`, and lifecycle `Task` references depend on external NetKingdom systems or future adapter implementations. - `Access Grant` is currently an exported grant-like reference derived from memberships. It is not a durable authorization grant table. - Evidence references currently derive from local audit records unless an `EvidenceReferenceExporter` is supplied. ## Validation Hooks The first executable checks live in `tests/test_identity_canon_alignment.py`. They verify that: - user, account, authenticated subject, authorization principal, tenant, team, membership, and grant-like references remain distinct; - service accounts project into service principals without becoming natural persons; - cross-tenant identity context is denied without platform scope; - claims-enrichment context can be read without implying token issuance ownership.