feat: implement prepared account claims

This commit is contained in:
2026-06-15 22:37:31 +02:00
parent a36a25898e
commit 97cd03b551
14 changed files with 1376 additions and 13 deletions

View File

@@ -9,6 +9,9 @@ HTTP or RPC adapters should preserve these operation names:
- `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`
- `me`, `create_user`, `set_account_status`, `link_identity`
- `resolve_tenant_context`, `set_tenant_account_status`, `add_membership`,
`tenant_diagnostics`
@@ -40,6 +43,25 @@ 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.
## Identity Context Contract
`identity_context` is the first canon-facing read model for NetKingdom

View File

@@ -235,6 +235,10 @@ once.
## Recommended Workplans
As of 2026-06-15, `USER-WP-0010` and `USER-WP-0011` are implemented as
headless user-engine slices. The later workplans remain recommended follow-on
work.
| Workplan | Title | Purpose |
| --- | --- | --- |
| USER-WP-0010 | Registration Identity And Factor Model | Add registration sessions, NetKingdom ID semantics, factor evidence, and verification adapter boundaries. |

View File

@@ -0,0 +1,117 @@
# Prepared Accounts And Entitlement Claims
Status: implemented headless slice
Date: 2026-06-15
Related workplan: USER-WP-0011
## Purpose
Prepared accounts let a tenant admin, operator, family owner, service owner, or
upstream system prepare user-domain intent before a person registers. The
package can name expected factor matches, tenant account state, memberships,
profile defaults, application bindings, and onboarding journey hints.
Prepared accounts are not credentials. A package is claimable only after a
completed registration presents matching verified factor evidence.
## Domain Model
`PreparedAccount` stores pending account intent:
- tenant
- required factor matches
- prepared entitlements
- status: `pending`, `claimed`, `revoked`, or `expired`
- preparer subject
- optional display name and primary email hints
- optional expiry
- claim metadata and lifecycle timestamps
`PreparedFactorRequirement` stores the factor type and normalized value to
match against verified registration factors. The model also carries optional
source-system and evidence references.
`PreparedEntitlement` stores the activation intent. Supported kinds are:
- `tenant_account`
- `membership`
- `profile_value`
- `application_binding`
- `onboarding_journey`
Entitlements may be marked `requires_approval`. Those packages fail closed in
the current claim facade until an explicit approval workflow is added.
## Public Facade
`UserEngineService` exposes:
- `prepare_account(...)`
- `update_prepared_account(...)`
- `list_prepared_accounts(...)`
- `revoke_prepared_account(...)`
- `expire_prepared_account(...)`
- `claim_prepared_account(...)`
Create, update, list, revoke, expire, and claim operations all pass through the
authorization port. The service depends on `UserEngineStore` protocol methods,
not the in-memory adapter internals.
## Claim Rules
Claims are only evaluated for completed registration sessions with a resolved
canonical user. A prepared account matches when every required factor is
present as unexpired verified `IdentityFactor` evidence on the registration.
The claim facade fails closed when:
- the caller names a missing, revoked, expired, claimed, or mismatching package;
- no prepared account matches the registration factors;
- multiple pending prepared accounts match the same verified factors;
- any entitlement in the package requires manual approval;
- entitlement activation references an invalid profile attribute or
unregistered application.
Factor requirements must include non-empty normalized values. Duplicate
pending packages with the same tenant and factor-signature are blocked during
create/update. Expired packages are ignored by duplicate checks and cannot be
claimed.
## Activation
Successful claim converts prepared entitlements into user-engine-owned facts:
- `TenantAccount` for tenant access state;
- `Membership` for scoped role facts;
- `ProfileValue` for catalog-validated profile defaults;
- `ApplicationBinding` for registered protected-system mappings;
- `prepared_account.onboarding_requested` outbox events for journey starts.
The prepared account is then marked `claimed` with the claiming user and
registration id.
## Audit, Outbox, And Redaction
Prepared-account mutations emit audit and outbox records:
- `prepared_account.created`
- `prepared_account.updated`
- `prepared_account.revoked`
- `prepared_account.expired`
- `prepared_account.claimed`
- `prepared_account.onboarding_requested`
Denied claim decisions are audited without outbox events. Outbox payloads use
ids, counts, factor types, statuses, and journey names. They deliberately avoid
normalized factor values such as email addresses, phone numbers, postal
addresses, and eID payloads.
## Current Limits
- Prepared accounts do not issue credentials, invitations, MFA challenges, or
tokens.
- Approval-required entitlement packages are blocked until a later workplan
adds explicit approval decisions.
- Final authorization policy and ACL evaluation remains outside user-engine;
user-engine only activates owned facts for policy systems to consume.
- Journey orchestration beyond outbox requests is left to USER-WP-0013.

View File

@@ -106,9 +106,10 @@ payloads.
Diagnostics report counts by status and total verified factors. They do not
return factor values.
## Current Limits
## Follow-On Boundaries
- Prepared account claiming is intentionally left to USER-WP-0011.
- Prepared account claiming is implemented by USER-WP-0011 and documented in
`docs/prepared-accounts-and-entitlement-claims.md`.
- Hats, realms, services, assets, and access profiles are left to
USER-WP-0012.
- Welcome protocols and onboarding journeys are left to USER-WP-0013.