user-engine/SCOPE.md
tegwick c431915d56
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Hygiene: SCOPE stance sentence, stack/architecture stubs, first-session archive
Record the published fail-closed PEP stance in SCOPE, fill the agent
stack and architecture stubs from the shipped layout, and retire the
first-session protocol now that USER-WP-0001–0024 exist.

Assistant: grok
Assistant-Session: 01a04cea-f0d6-7ab3-9ffd-881eb6bea6cb
2026-08-29 14:37:38 +02:00

198 lines
10 KiB
Markdown

# 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 is published
in `pep-stance.yaml`, tested equal to `FlexAuthHTTPAdapter`, and recorded
as stance application (`decision_id` absent) 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.