Files
user-engine/docs/contracts.md

265 lines
13 KiB
Markdown

# Public Contracts
## Headless Service Surface
`UserEngineService` is the stable in-process API for the current MVP. Future
HTTP or RPC adapters should preserve these operation names:
- `health`, `readiness`, `operability_snapshot`, `outbox_diagnostics`
- `start_registration`, `attach_registration_factor`, `complete_registration`,
`abandon_registration`, `expire_registration`, `resume_registration`,
`registration_diagnostics`
- `prepare_account`, `update_prepared_account`, `list_prepared_accounts`,
`revoke_prepared_account`, `expire_prepared_account`,
`claim_prepared_account`
- `register_access_profile`, `list_access_profiles`, `select_active_hat`,
`export_access_control_facts`, `access_profile_diagnostics`
- `register_welcome_protocol`, `list_welcome_protocols`,
`start_onboarding_journey`, `start_onboarding_for_registration`,
`start_onboarding_for_prepared_account`, `progress_onboarding_step`,
`complete_onboarding_step`, `skip_onboarding_step`,
`fail_onboarding_step`, `resume_onboarding_journey`,
`onboarding_diagnostics`
- `me`, `create_user`, `set_account_status`, `link_identity`
- `resolve_tenant_context`, `set_tenant_account_status`, `add_membership`,
`tenant_diagnostics`
- `register_application`, `publish_catalog`
- `set_profile_value`, `effective_profile`, `projection`, `identity_context`
- `onboard_family_dataspace`, `invite_family_member`,
`resend_family_invitation`, `revoke_family_invitation`,
`accept_family_invitation`
- `audit_records`, `outbox_events`
## UI Contract Surface
`RegistrationAccessManagementUi` is the optional UI-facing contract facade for
registration and access management. It returns screen/view models and route
definitions over `UserEngineService`; transport adapters may serve those as
HTTP, RPC, desktop, CLI, or rendered HTML.
The facade covers self-service registration, factor status, terms/consent,
prepared-rights review and claim, active hat selection, admin diagnostics, and
accessible HTML verification. It does not handle credential entry, MFA
challenges, token issuance, hidden policy decisions, notifications, or
service-specific admin consoles.
## Scenario And Security Conformance Contract
`user_engine.testing.scenarios` defines `SCENARIO_MATRIX` and
`REGISTRATION_SCENARIO_MATRIX` for local conformance. The matrix covers
self-registration, prepared-account claims, privileged approval gates,
eID-backed assurance, family invite, tenant admin invite, group access,
cross-tenant denial, and USER-WP-0014 UI workflows.
Conformance tests must run without production IAM, proofing, notification,
workflow, authorization-engine, or database infrastructure. They exercise
adapter seams with local harnesses and assert fail-closed behavior, audit
evidence, outbox replay, redaction, and durable transaction semantics.
## Registration Contract
Registration is a headless user-entry facade. It creates a
`RegistrationSession`, accepts safe `FactorVerification` evidence from external
proofing adapters, records persisted `IdentityFactor` metadata, and completes
the session into a stable NetKingdom ID.
The first NetKingdom ID contract is `User.user_id`: an opaque, stable user
identifier that must not encode IAM issuer/subject pairs, email addresses,
phone numbers, postal addresses, eID payloads, tenant names, or other proofing
data.
Registration completion creates or resolves a `User`, `Account`,
`TenantAccount`, and `ExternalIdentity` link for the verified actor, attaches
verified factors to that user, emits audit/outbox records, and returns
`identity_context`.
user-engine does not verify factors itself, issue credentials, perform MFA,
run eID proofing, or issue tokens. Those remain external IAM/proofing adapter
responsibilities.
## Prepared Account Contract
Prepared accounts are pending user-domain facts for people who have not yet
registered or have not yet claimed their prepared rights. They can carry
required factor matches, entitlement intent, preparer metadata, expiry, and
claim lifecycle state, but they do not create credentials.
`claim_prepared_account` requires a completed registration session and
unexpired verified `IdentityFactor` records that satisfy every prepared factor
requirement. A successful claim marks the package claimed and converts
prepared entitlements into user-engine-owned facts: tenant account state,
memberships, catalog validated profile values, application bindings, and
onboarding-request events.
Expired, revoked, claimed, mismatching, ambiguous, duplicate, or
approval-required packages fail closed. Denied claim decisions are audited
without outbox events. Mutation outbox payloads include ids, counts, statuses,
factor types, and journey names, but not normalized factor values.
## Access Profile And Hat Contract
Access profiles are tenant-scoped templates for selecting an active hat across
tenant, realm, service, asset, or group contexts. A profile combines required
memberships, required verified factor types, profile defaults, projection
claims, optional group references, and explicit realm/service/asset scope ids.
`select_active_hat` requires an active tenant account, satisfied membership
requirements, unexpired verified factor evidence, and authorization-port
approval. The selected hat is persisted as `ActiveAccessContext` and is exposed
through `identity_context` and claims-enrichment projections.
`export_access_control_facts` returns adapter-neutral `AccessControlFact`
records for authorization engines and ACL systems. These facts include direct
membership facts, group-derived facts, and active-context facts, but
user-engine still does not make final access decisions or enforce protected
service runtime policy.
Access-profile diagnostics report counts, factor requirement types, and
approval-required issues without exposing profile default values, projection
claim values, or raw factor values.
## Onboarding Journey Contract
Welcome protocols are tenant-scoped onboarding templates. They can match
registration completion, prepared-account claims, invitations, access-profile
events, or manual starts by trigger type and optional context keys.
Onboarding journeys are persisted user state. They track protocol, source
event, trigger type, ordered steps, task references, subsystem handoff
references, lifecycle gaps, active step, status, and correlation ids.
Registration completion and prepared-account claim automatically start matching
welcome protocols. Manual start/progress/complete/skip/fail/resume operations
are also exposed through `UserEngineService` and authorization-gated.
Missing required subsystem callbacks produce explicit lifecycle gaps and block
the journey. The service records audit/outbox events with ids, statuses, step
keys, source ids, and lifecycle gap identifiers, but not factor values, support
content, notification payloads, or subsystem-specific tour data.
## 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, optional active access context,
exportable access-control facts, onboarding journeys, 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.
## Family Dataspace Onboarding Contract
`onboard_family_dataspace` is a convenience facade for personal-family
identity-domain setup. It composes existing user, account, tenant-account,
membership, application, catalog, profile, audit, outbox, projection, and
identity-context operations.
The facade represents a family as a NetKingdom tenant plus a `family` scope. It
does not provision the tenant, issue SSO tokens, own credentials, or implement
the protected dataspace runtime. Family roles are scoped membership facts such
as `owner`, `adult`, `child`, `guest`, and `delegated-caretaker`; authorization
systems decide how those facts affect access.
Invitation acceptance requires already-verified claims. user-engine stores
local invitation lifecycle, links the verified external identity, activates
account state, and returns both `identity_context` and a
`CLAIMS_ENRICHMENT` projection for SSO adapters.
## Error Taxonomy
- `ValidationError`: caller supplied an invalid shape, state transition, or
catalog/profile value.
- `AuthorizationDenied`: the authorization port or tenant boundary denied the
operation.
- `NotFoundError`: a requested user, account, or active attribute is missing.
- `ConflictError`: uniqueness or ownership would be violated.
## Catalog Contract
Catalogs are active by namespace and owning application. Attribute keys must
use the namespace prefix. Active namespace ownership cannot move to another
application. Catalog updates cannot move versions backwards or downgrade
attribute sensitivity.
## Projection Contract
Application runtime, agent-context, and claims-enrichment projections require
an `application_id` and are filtered to that application's active catalogs.
Sensitive and secret values are redacted outside admin, audit, and
self-service projections.
## Audit And Event Contract
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.
## Durable Store Contract
`UserEngineService` depends on the `UserEngineStore` protocol, not the
in-memory adapter's concrete collections. Store implementations must expose
schema readiness, logical record accessors, audit-log reads, pending-outbox
reads, adapter-neutral record counts, and a `transaction` context for atomic
mutations.
Mutating writes happen after validation and authorization, inside the store
transaction. Domain changes, local mutation audit records, and outbox events
must commit or roll back together. Authorization-denial audit records must
remain durable without outbox events, including when a denial occurs inside a
composed mutation that rolls back other writes.
Postgres-specific connection handling, SQL, locks, credentials, tenant
isolation primitives, backup, restore, and platform observability remain
adapter or provider concerns outside the domain service.
## Migration Contract
`user_engine.migrations` exposes the ordered durable-store manifest,
`LATEST_SCHEMA_VERSION`, logical record types, and adapter-neutral diagnostic
count keys. The isolated store's `SCHEMA_VERSION` is derived from that manifest
and its `migrate` hook must be idempotent. Database-backed stores must expose
equivalent readiness semantics before they are accepted by platform adapters.
Provider-backed Postgres adapters can use
`migrations/postgres/0001_user_engine_store.sql` as the bootstrap contract or
translate it into their own migration framework while preserving schema-version
tracking, logical record uniqueness, audit durability, and pending-outbox
reads.
Future adapters should run
`user_engine.testing.assert_user_engine_store_conformance(testcase, factory)`
with a factory that returns a fresh store. The harness covers readiness,
idempotent migration, core save/read/query behavior, transaction rollback,
outbox ordering, and diagnostics that expose counts without raw factor or
profile values.
`user_engine.store_records` defines the JSONB serialization contract for the
generic record table. `store_record_for` turns supported domain dataclasses
into `StoreRecord` envelopes with deterministic keys and index metadata, while
`domain_record_from_store_record` restores those payloads to domain objects.
These payloads are durable state and may contain sensitive values, so they must
not be emitted as diagnostics.
`user_engine.adapters.postgres.PostgresUserEngineStore` is the optional
Postgres implementation. It accepts a provider-owned DB-API or psycopg-like
connection, applies the bootstrap SQL in `migrate`, and persists generic
records, audit records, and pending outbox events without depending on a
specific driver package.