user-engine/docs/portal-threat-model.md
tegwick f762161d84
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 2s
Build and Publish Container Image / build-and-push (push) Successful in 1m1s
Adapt USER-WP-0021 and USER-WP-0023 to published policy-nexus contracts
IAM Profile v0.3 and Tenancy Posture v0.1 are now live on
policy.coulomb.social. Close the portal expansion workplan against those
documents, keep the flex-auth live A2 probe waiting, and forward optional
tenant_roles to flex-auth without authorizing from them locally.
2026-08-19 09:51:08 +02:00

2.8 KiB

Portal boundary and threat model

The portal is a transport adapter for user-engine, not a new identity authority. KeyCape owns login, credentials, MFA, authentication sessions and OIDC tokens. flex-auth owns authorization decisions. user-engine owns users, tenant memberships, profiles, registration, invitations, onboarding, audit records and lifecycle intent. NetKingdom implements IdentityProvisioningPort without leaking provider clients into the domain.

Trust boundaries

  • The public edge terminates TLS, rate-limits login/registration and validates OIDC tokens. It strips all inbound X-Verified-* and X-User-Engine-Proxy-Secret headers before injecting verified claims and the runtime-only proxy marker.
  • user-engine rejects every protected route if that marker or verified claims are absent. Direct pod traffic is blocked by NetworkPolicy.
  • Browser state is navigation state only. It is never authoritative for roles, tenants, registration progress or lifecycle status.
  • Provider credentials come from approved runtime secret references. They do not enter requests, logs, audit payloads, workplans or Git.

Controls

Protected writes receive a flex-auth decision through the existing AuthorizationCheckPort. Tenant context is re-resolved in the service, so a tenant administrator cannot select another tenant. Mutations carry request correlation IDs and emit redacted audit/outbox records. Provisioning requests carry independent idempotency keys and support safe resume after ambiguity.

The application emits a restrictive content security policy, prevents framing and MIME sniffing, disables sensitive response caching and escapes all server-rendered values. State-changing browser forms must use same-site cookies plus edge-issued CSRF tokens; the initial JSON API is intended for bearer-authenticated same-origin clients. Invitation tokens are single-use, hashed at rest, time-bound and rate-limited at both identity and address dimensions. Public errors must not reveal whether an email or tenant exists.

Audit retention, identity erasure and external deprovisioning are distinct operations. Audit identifiers remain pseudonymous after erasure. Provider outage leaves a retryable outbox item and never reports the lifecycle change as externally complete. Compensation is idempotent and operator-visible.

Deferred

Enterprise SAML/OIDC federation, SCIM and corporate directory synchronization remain provider adapters. Their external ownership metadata and identity links must fit the existing neutral boundaries rather than becoming user-engine domain dependencies. The published target is IAM Profile v0.3 Keycloak expanded mode (https://policy.coulomb.social/standards/iam-profile/v0.3/); a dedicated workplan is created only when a tenant demands those integrations.