Implement identity canon alignment

This commit is contained in:
2026-06-05 16:04:43 +02:00
parent fe446711de
commit c6d211f472
15 changed files with 1008 additions and 21 deletions

View File

@@ -0,0 +1,118 @@
subsystem: user-engine
description: >
NetKingdom identity-domain integration layer for user, account, identity-link,
tenant, membership, profile, lifecycle, and evidence-facing context.
status: candidate
owner: codex
updated: "2026-06-05"
implements:
- identity-canon conceptual model as an implementation-facing domain facade
- InfoTechCanon user-engine evaluation pack
- small-saas user-management alignment surface
produces:
- User
- Account
- Identity Record
- Scoped Identifier
- Profile
- Tenant
- Membership Relationship
- Authenticated Subject reference
- Authorization Principal reference
- Evidence Source reference
- Access Grant or grant-like membership fact
consumes:
- NetKingdom IAM Profile claims
- verified issuer and subject identifiers
- assurance and principal type claims
- authorization decisions and obligations
- policy, control, review, exception, and evidence references
- lifecycle task references from downstream task systems
- platform audit and event sinks
owned_concepts:
user_record: User-engine local user record mapped to identity-canon User as a convenience term.
account_record: Operational account state for a user-engine scope.
external_identity_link: Source-specific issuer and subject link to a user record.
profile_value: Scoped profile or preference value.
membership_fact: User-domain relationship to tenant, team, application, or scope.
identity_context: Canon-facing read model over user, account, actor, subject, principal, scope, memberships, profile, and evidence references.
mapped_not_owned:
Actor: Consumed from verified identity claims and represented as canon reference.
Authenticated Subject: Projected from issuer and subject after authentication.
Authorization Principal: Projected for the authorization system; final decisions remain outside user-engine.
Policy: Referenced from authorization/governance systems.
Control: Referenced from security/governance systems.
Evidence Source: Referenced from audit, review, approval, or verification systems.
AccessReview: Referenced from governance or review systems.
Organization: Referenced when tenants, teams, or users map to organization systems.
Credential: Explicitly not stored or lifecycle-managed by user-engine.
accepted_relationships:
- identity_link
- belongs_to_tenant
- authenticates_as
- evaluated_as
- member_of
- role_label
- scoped_to
- governed_by
- implemented_by
- evidenced_by
- creates_task
emitted_events:
- user.created
- account.status_changed
- tenant_account.status_changed
- identity.linked
- membership.added
- profile.value_set
- application.registered
- catalog.published
required_identifiers:
actor_key: "issuer + subject"
user_id: "opaque user-engine user id"
account_id: "opaque user-engine account id"
identity_id: "opaque user-engine external identity id"
tenant: "NetKingdom-aligned tenant or platform scope"
application_id: "registered application id when projection is application-scoped"
correlation_id: "operation-level audit and event correlation id"
mapping_rules:
- Resolve source terms such as user, group, role, tenant, subject, and principal into identity-canon layers before exposing them as implementation concepts.
- Keep account records, authenticated subjects, and authorization principals distinct even when they share issuer or subject identifiers.
- Treat memberships as relationship facts that may produce grant-like access facts, not as final authorization decisions.
- Preserve source system, scope, lifecycle state, and evidence reference whenever a relationship affects access, privacy, or lifecycle.
- Link policy, control, review, exception, and task concepts by reference unless user-engine is the actual source of truth.
validation_rules:
- User, Account, Actor, Authenticated Subject, Authorization Principal, Tenant, Team, Membership, and Profile must remain distinguishable in the identity context read model.
- Tenant-scoped privileged membership must expose scope and evidence or an explicit evidence gap.
- Cross-tenant context must be denied unless the actor is a platform operator.
- Claims enrichment projections must not imply token issuance ownership.
- Credential, MFA, policy decision, and durable platform audit ownership must remain outside user-engine.
source_of_truth:
user_records: user-engine
account_state: user-engine
external_identity_links: user-engine
profile_values: user-engine
membership_facts_created_here: user-engine
authentication: NetKingdom IAM infrastructure
credential_assurance: NetKingdom IAM/security infrastructure
authorization_decisions: NetKingdom authorization infrastructure
policy_and_control_definitions: NetKingdom governance/security infrastructure
durable_platform_audit: NetKingdom audit infrastructure
organization_authority: NetKingdom organization or directory systems
known_deviations:
- User remains a local implementation class even though identity-canon treats user as a non-root convenience term; mappings must state whether it represents actor-facing profile holder, account owner, or local user record.
- Access Grant is currently a grant-like reference derived from memberships, not a durable authorization grant table.
- Evidence Source references currently derive from local audit records unless an external evidence exporter is supplied.
- AccessReview, Policy, Control, Exception, and lifecycle Task are references or gaps, not first-class owned records.

103
docs/canon-mapping.md Normal file
View File

@@ -0,0 +1,103 @@
# 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.

View File

@@ -10,9 +10,32 @@ HTTP or RPC adapters should preserve these operation names:
- `resolve_tenant_context`, `set_tenant_account_status`, `add_membership`,
`tenant_diagnostics`
- `register_application`, `publish_catalog`
- `set_profile_value`, `effective_profile`, `projection`
- `set_profile_value`, `effective_profile`, `projection`, `identity_context`
- `audit_records`, `outbox_events`
## Identity Context Contract
`identity_context` is the first canon-facing read model for NetKingdom
identity-domain consumers. It resolves a verified actor into the local user,
account, external identity links, tenant scope, memberships, optional
application scope, optional effective profile, canon entity references,
relationship references, grant-like membership facts, and evidence references.
The method keeps these concepts distinct:
- user-engine `User` record;
- operational `Account`;
- external `Identity Record` and scoped issuer/subject identifier;
- `Actor` from verified claims;
- `Authenticated Subject` projected from issuer and subject;
- `Authorization Principal` projected for policy evaluation;
- `Tenant`, `Team`, `Scope`, `Membership Relationship`, and `Role` references.
Evidence references are currently derived from local audit records. External
policy, control, access-review, exception, and lifecycle task references belong
to adapter contracts and remain non-owned unless a later workplan assigns
source-of-truth responsibility to user-engine.
## Error Taxonomy
- `ValidationError`: caller supplied an invalid shape, state transition, or
@@ -42,6 +65,9 @@ Every mutating service operation appends an audit record and outbox event with
the same correlation id and resolved tenant. Authorization denials are audited
without emitting outbox events.
Local audit records may be exported as identity-canon `Evidence Source`
references. Durable platform audit custody remains outside user-engine.
## Migration Contract
The isolated store exposes `SCHEMA_VERSION = 0001_initial` and a `migrate`

View File

@@ -0,0 +1,62 @@
# Evidence Gap Examples
Status: candidate
Updated: 2026-06-05
`user-engine` should not pretend missing review or governance material exists.
When identity-domain context lacks evidence, policy, control, review, or task
references, the gap must be explicit and handoff-ready.
## Gap Shape
```yaml
gap_id: evidence:no-audit-records
subject:
concept: Account
identifier: acct_example
scope: tenant:acme
reason: No local audit or external evidence reference supports this identity-domain claim.
proposed_disposition: create_or_link_lifecycle_task
owner: user-engine adapter boundary
```
## Privileged Membership Without External Review
```yaml
gap_id: review:tenant-admin-membership
subject:
concept: Access Grant
identifier: mem_example
scope: tenant:acme
reason: Tenant admin membership has local audit evidence but no external access review reference.
proposed_disposition: link AccessReview through EvidenceReferenceExporter or create review task through LifecycleTaskSink.
```
## Policy Or Control Reference Missing
```yaml
gap_id: control:tenant-isolation-reference
subject:
concept: Membership Relationship
identifier: mem_example
scope: tenant:acme
reason: Membership is tenant-scoped, but no external policy/control reference was supplied.
proposed_disposition: resolve policy and control through PolicyControlReferenceResolver.
```
## Lifecycle Task Handoff
```yaml
task_reference:
concept: Task
identifier: task_from_lifecycle_sink
source_gap: review:tenant-admin-membership
summary: Review tenant-admin membership for tenant:acme.
evidence:
- concept: Evidence Source
identifier: aud_example
```
These examples are intentionally adapter-neutral. The task, review, policy, and
control source of truth belongs to the surrounding NetKingdom systems unless a
future workplan assigns one of those responsibilities to `user-engine`.

View File

@@ -0,0 +1,55 @@
# Identity Domain Naming Decision
Status: candidate
Decision date: 2026-06-05
## Context
`user-engine` is moving from a narrow user/profile service toward a NetKingdom
identity-domain integration layer. That raises the question of whether the
repository should be renamed to `identity-engine`, `identity-domain-engine`, or
`organization-engine`.
## Decision
Keep the repository named `user-engine` for USER-WP-0007 implementation.
Treat `identity-engine` or `identity-domain-engine` as future candidate names
only after the canon interface card, mapping export, identity-context read
model, NetKingdom adapter contracts, and conformance tests are established and
reviewed.
Do not use `organization-engine` for this scope.
## Rationale
- `user-engine` is already the implemented package, module, docs, and workplan
identity.
- The current implementation still owns user-domain facts: users, accounts,
identity links, profiles, memberships, catalogs, projections, audit, and
events.
- `identity-engine` could imply ownership of the full identity provider,
credential lifecycle, federation, MFA, token issuance, and IAM substrate unless
the boundary is already well proven.
- `organization-engine` would imply ownership of organization, HR, authority,
responsibility, reporting, legal entity, customer, vendor, and community
modeling. Those are adjacent canon concepts, not this repo's current source of
truth.
## Rename Criteria
Revisit the name when all of the following are true:
- consumers primarily use the identity-context API rather than only user/profile
APIs;
- NetKingdom IAM, authorization, audit, and evidence adapters are stable;
- identity-canon mappings are validated by executable scenarios;
- docs consistently describe the repo as an identity-domain facade and not as an
identity provider;
- downstream consumers would be misled by the old `user-engine` name.
## Consequences
- Existing imports, package names, workplans, and docs remain stable.
- The intent and interface card carry the strategic direction explicitly.
- Naming pressure becomes a tracked decision rather than hidden scope drift.

View File

@@ -23,6 +23,9 @@ See also the cross-repo assessment in the net-kingdom repo:
| `MembershipFactExporter` | outbound | Export user-engine-owned membership facts as read models for authorization systems. |
| `EventOutbox` | outbound | Publish durable lifecycle/profile/catalog/membership events after commit. |
| `AuditWriter` | local/outbound | Persist local audit and provide redacted summaries for platform audit sinks. |
| `EvidenceReferenceExporter` | outbound | Export local audit/review material as identity-canon evidence references without owning the platform audit system. |
| `PolicyControlReferenceResolver` | outbound | Resolve policy, control, review, exception, or waiver references for identity-domain traces. |
| `LifecycleTaskSink` | outbound | Create or link lifecycle, review, remediation, or integration-gap work in a task system. |
| `SecretProvider` | inbound | Load runtime secrets through environment/local config in standalone mode and scoped secret providers in platform mode. |
## Source-Of-Truth Rules
@@ -33,6 +36,11 @@ See also the cross-repo assessment in the net-kingdom repo:
- Identity providers are the source of truth for authentication-time subject,
issuer, assurance, coarse role, and group claims.
- Authorization systems decide whether an actor may perform an action.
- Governance, security, and authorization systems own policy, control, review,
exception, and waiver definitions. user-engine can reference them in identity
context traces.
- Task systems own lifecycle work queues. user-engine can create or link
identity-domain work through an explicit task sink.
- Event sinks and audit stores consume user-engine events; they do not become
profile stores.
@@ -64,6 +72,41 @@ context:
The domain layer should depend on this port, not on a concrete authorization
client.
## Identity Context Shape
Every domain-facing identity context should be reducible to:
```yaml
actor:
issuer: string
subject: string
tenant: string
principal_type: human | service | agent
user:
user_id: string
account:
account_id: string
status: string
identity_links:
- issuer: string
subject: string
tenant: string
application_id: string | null
memberships:
- scope_type: string
scope_id: string
kind: string
canon_refs:
entities: object
relationships: object
grant_like_refs: object
evidence_refs: object
gaps: [string]
```
The context is a facade over NetKingdom IAM and security infrastructure. It
does not issue tokens, decide authorization policy, or own credentials.
## Projection Types
- `self_service`: current-user view and allowed mutations.

View File

@@ -14,6 +14,7 @@ projection, audit, and event behavior testable without a UI.
| two_applications | Catalog ownership and projections prevent application data leakage. |
| sensitive_redaction | Sensitive values are redacted in runtime and claims-enrichment projections. |
| audit_event_replay | Mutations carry audit records, outbox events, and correlation ids. |
| identity_canon_context | Actor, user, account, authenticated subject, authorization principal, tenant, membership, grant-like facts, and evidence references stay distinguishable. |
## Fixture Actors