# SCOPE ## Layer **Engine, role PIP** — deterministic API for users, accounts, and memberships. Subject context is an input to the authorization decision and never a decision. Protected mutations are PEP-shaped: they consume `access-engine` (`flex-auth`) and do not substitute for it. Declaration: `INTENT.md` frontmatter. Statute: `net-kingdom/canon/standards/security-layer-model_v0.7.md` (accepted). Working companion: `net-kingdom/SECURITY-COMPANION.md`. Boundary contract unchanged: `net-kingdom/canon/standards/user-engine-boundary-contract_v0.1.md`. ## One-Liner Headless user-domain and identity-domain Engine (PIP) for accounts, identity links, memberships, catalogs, projections, local audit, and events, with an optional in-repo portal. It consumes NetKingdom IAM, authorization, tenant authority, provisioning, and delivery; it does not own them and it does not decide them. ## In Scope - user and account records, and account lifecycle state; - external identity links keyed by `(issuer, subject)`; - actor, authenticated-subject, authorization-principal, and user-context mappings from verified IAM Profile claims; - global, tenant, application, and membership profile values and preferences; - tenant, application, team, and scope memberships; - hats, realms, services, assets, access profiles, and active access context as user-domain facts and claim templates; - identity-context read models for domain consumers; - PIP exports: subject, membership, and access-control facts for `access-engine` and other engines to consume as claims; - canon interface cards, entity and relationship mappings, and explicit gap records; - application registry for profile consumers; - customization catalog registry, versioning, and validation; - effective profile resolution and projections (self-service, admin, application runtime, audit, agent, claims-enrichment); - local audit records and durable outbox events; - local evidence references derived from audit and events; - invitations, prepared accounts, entitlement claims, and onboarding journeys that user-engine owns; - public registration *orchestration* (start, verify, resume, cancel, provider handoff) behind an explicit runtime flag; - provider-neutral tenant lifecycle *calls* to the tenant authority (create, read, update, retire, reactivate, recover); - optional CSRF-protected portal over the same APIs (self-service, onboarding, tenant admin, platform operator); - standalone/local fixtures and a production PostgreSQL store of the modeled concept; - integration ports for claims, flex-auth decisions (including a rotating caller token), provisioning, registration verification, tenant management, outbox delivery, and runtime secrets; - PEP enforcement of `access-engine` decisions on user-engine-owned mutations, including a published unreachable-engine stance. ## Out Of Scope - login, OIDC/SAML token issuance, passwords, passkeys, sessions, and MFA lifecycle — `key-cape`, Keycloak, or `local-identity`; - final authorization policy decisions and the protected-system registry — `flex-auth` / `access-engine`; - caching or compiling an authorization decision, including from hats, access profiles, or memberships; - durable authorization grants beyond user-engine-owned memberships; - tenant identifier authority, grouping reclassification, and capability role grants — `tenant-engine`; - application-owned first-login profiles, unlink, and action step-up — consuming apps (e.g. coulomb-social) and KeyCape client policy; - policy, control, access-review, exception, and organization source-of-truth ownership; - runtime secret custody — OpenBao / Railiance; no OpenBao client here; - a Keycloak or key-cape admin client; - platform audit store and transactional SMTP — `audit-core` and `email-connect`; - full SCIM server, enterprise directory replacement, or inbound SAML/OIDC federation (demand-triggered; Keycloak expanded mode is the published path); - a generic extracted profile engine; - observing production security events — `kings-guard`, and currently unstaffed; - actuation: reduce authority, require step-up, isolate a workload — an Engine concept held at zero estate-wide. The in-repo portal is an optional surface, not a UI product. Password and MFA screens stay on the identity provider. `LocalAuthorizationCheckPort` is a test and standalone double, not a production decision point. ## Boundary Rule user-engine owns user-domain facts, identity-context mappings, and projections. Adjacent systems provide authentication, IAM claims, authorization decisions, tenant authority, policy/control definitions, deployment, event transport, durable audit, secrets, organization records, or additional UI — and they integrate through explicit adapters. They must not become hidden sources of profile or identity-domain truth. user-engine must not become a hidden source of authorization truth. Memberships, hats, and access-control facts are claims. `access-engine` renders the decision. When `access-engine` is unreachable, shipped behaviour is fail-closed for protected mutations; that stance still has to be published, tested equal to the code, and recorded as stance application rather than as a minted local decision id. Governing published contracts: - IAM Profile v0.3 — https://policy.coulomb.social/standards/iam-profile/v0.3/ - Tenancy Posture v0.1 — https://policy.coulomb.social/standards/tenancy-posture/v0.1/ - NetKingdom architecture — https://policy.coulomb.social/architecture/net-kingdom/v0.1/ - User-engine boundary contract (accepted, not yet published) — `~/net-kingdom/canon/standards/user-engine-boundary-contract_v0.1.md` - NetKingdom Security Layer Model v0.7 (accepted) — `~/net-kingdom/canon/standards/security-layer-model_v0.7.md` - Working companion — `~/net-kingdom/SECURITY-COMPANION.md` ## Current Status Workplans `USER-WP-0001` through `USER-WP-0023` are finished. The isolated MVP, multi-tenancy, catalogs, canon alignment, durable PostgreSQL store, self-service and admin portal, public-registration orchestration, and flex-auth caller identity (live A2 on `flex-auth-user-engine`) are in the repo and, where applicable, on Railiance. `USER-WP-0024` ships the layer-conformance follow-through: `layer.yaml` and `pep-stance.yaml`, fail-closed stance recording without a minted decision id, request-bound allow lifetime, local-authorization confinement, evidence classification and heartbeat, and the access-control-fact claim contract. Still operator-owned, not remaining product scope: - public registration and outbox mail stay fail-closed until governed OpenBao verification/delivery tokens and the transactional SMTP lane are installed; - the live tenant-lifecycle probe from a user-engine pod (GET / PATCH / retire / reactivate on a disposable tenant) is still owed; - `policy.enabled` and tenant-engine caller `enforce` belong to flex-auth / tenant-engine. Layer-model residue that `USER-WP-0024` closed, assessed in `history/2026-08-29-security-layer-scope-intent-assessment.md`: - `layer.yaml` plus `scripts/check_layer_conformance.py`; - published `pep-stance.yaml`, fail-closed total, tested equal to `FlexAuthHTTPAdapter`; engine-unavailable DENY records stance application and carries no `decision_id`; - `AuthorizationDecision` allows are request-bound with a 30s lifetime; - denials and revocations are load-bearing; cadence is `record_evidence_heartbeat()`; - `LocalAuthorizationCheckPort` cannot be constructed when `USER_ENGINE_FLEX_AUTH_TOKEN_FILE` is set, and `runtime.py` does not import it. ## Against INTENT.md INTENT is the stable aspiration. Against the pre-layer product aims, the repo still does the job it set out to do. Against the layer declaration now in INTENT, SCOPE is narrower than INTENT on conformance artifacts and PEP obligations. | INTENT aim | Status | | --- | --- | | Headless user-domain service, provider- and PDP-agnostic | Met. Ports and adapters; production uses IAM Profile v0.3 and flex-auth. | | Standalone now, multi-tenant / multi-app later | Met. Fixtures and in-memory conformance plus live PostgreSQL and Railiance. | | Users, links, memberships, catalogs, projections, events | Met. | | NetKingdom identity-domain integration layer | Met for the owned slice. Consumes KeyCape, flex-auth, tenant-engine, identity-provisioner, audit-core, email-connect. | | Applications answer who / which scopes / what to project | Met via `/me`, identity context, catalogs, and projections. | | Engine / PIP declaration in own voice | Met in `INTENT.md` and `layer.yaml`. Closes `USER-IN-0001`. | | Subject context is a claim, never a decision | Held. Production asks flex-auth. Hats and access-control facts have no effect field; tests forbid compiling them into allow/deny. The local double is confined to tests/standalone. | | PEP-shaped: no side effect without a decision or recorded stance | Met. Unavailable DENY records `stance_applied=fail_closed` and no `decision_id`. | | Published unreachable-engine stance map, tested equal to shipped behaviour | Met (`pep-stance.yaml`). Gate-house still owes the §13.1 inventory row. | | Every allow has a lifetime | Met. Production allows are request-bound, 30s. Standing grants are denied. | | Evidence bound: no completeness claim; cadence for load-bearing events | Met. Classification and heartbeat in `docs/evidence-classification.md` and `UserEngineService.record_evidence_heartbeat()`. | | Not an IdP, PDP, secret store, directory, or org authority | Held. | | Optional UI, not UI-driven | Held, with a narrower reading: an optional portal now lives *in this repo* over the same APIs. INTENT's "not a UI application" still applies to product identity. | | Canon-aligned mappings without taking IAM as SoT | Met (`USER-WP-0007`, interface card). Access-review, policy, and control remain references, not owned records. | | Path from local setup to governed NetKingdom deploy | Met. | | No OpenBao / key-cape admin client | Held. `SecretProvider` is an unused port; runtime reads env. | Still aspirational, and deliberately not started here: - inbound federation / SCIM / directory sync — new workplan only on tenant demand, targeting published Keycloak expanded mode; - first-class access-review and governance records; - a dedicated agent consumption product (projections exist); - extracting a generic profile engine; - observing production, or actuating containment — estate-wide zeros, not this repo's gaps to close. Those remain INTENT, not a hole in SCOPE. Layer-conformance rows above are met by `USER-WP-0024`; the §13.1 inventory row is gate-house's.