user-engine/docs/configuration.md
tegwick 869de4080b USER-WP-0026-T03: access-engine application access readback client
Read FLEX-DEC-2026-019 readback answers for workloads bound in all three
records (user-engine application, protected system, key-cape client) and
show them on the account page. No row is inferred as allow; failures,
missing rows and expired allows render 'could not be checked'. Off unless
USER_ENGINE_READBACK_URL and its own token file are set.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 629164@bnt-lap001
Assistant-Session: 22dee475-6a23-47f3-8588-00a7f62d8720
2026-10-10 00:45:03 +02:00

5.6 KiB
Raw Blame History

Configuration Boundaries

Standalone Mode

Standalone mode is for local development, tests, prototypes, and small single-service deployments.

Expected characteristics:

  • local configuration file or environment variables;
  • local database or file-backed persistence during early development;
  • fixture or local identity claims adapter;
  • deterministic authorization test adapter;
  • no password, MFA, or token issuance responsibility inside user-engine.

Platform Mode

Platform mode is for a NetKingdom-aligned shared service deployment.

Expected characteristics:

  • verified IAM Profile claims arrive from an identity layer;
  • authorization decisions are requested through the authorization check port;
  • runtime secrets are delivered through a scoped secret provider;
  • audit records and outbox events are correlated with platform sinks;
  • tenant and application bindings are explicit.

Secret Names

The code should refer to logical secret names, not platform paths. Concrete secret lookup is owned by the active SecretProvider adapter.

Initial logical names:

  • database.url
  • event.signing_key
  • webhook.shared_secret

Production Guardrails

  • Local issuers must be rejected by production adapters.
  • Sensitive writes must fail closed when authorization is unavailable.
  • Claims enrichment must be optional and must not make user-engine a token issuer.

Portal integration settings

The production portal requires its existing database, OIDC, proxy-marker, and identity-provisioning settings. Platform tenant creation is enabled only when both of these settings are present:

  • USER_ENGINE_TENANT_MANAGEMENT_URL — tenant-authority base URL;
  • USER_ENGINE_TENANT_MANAGEMENT_TOKEN — workload-scoped bearer token.

The adapter calls POST /v1/tenants with correlation and idempotency headers. The token is never returned in errors, audit records, outbox events, or browser responses. When the settings are absent, ordinary portal behavior remains available and platform tenant creation fails closed as unavailable.

Public registration is off unless USER_ENGINE_PUBLIC_REGISTRATION=true. Enabling it also requires the verification adapter and allow-lists:

  • USER_ENGINE_REGISTRATION_VERIFICATION_URL
  • USER_ENGINE_REGISTRATION_VERIFICATION_TOKEN
  • USER_ENGINE_REGISTRATION_CLIENTS
  • USER_ENGINE_REGISTRATION_TENANTS
  • USER_ENGINE_REGISTRATION_PASSWORD_SETUP_ORIGINS
  • USER_ENGINE_MAIL_URL and USER_ENGINE_MAIL_TOKEN when verification mail is delivered through the outbox

The service fails closed when those settings are absent. Do not add a placeholder or reused credential to turn the flag on.

USER_ENGINE_MAIL_CLIENT_BINDINGS is optional and unset by default. When unset, invitation mail envelopes keep the legacy shape (no client_id). When set, it is a JSON list of [tenant_glob, client_id] pairs (1–128 rows, unique globs, case-sensitive whole-string */? matching), for example [["tenant:*-family", "coulomb-social"]]. Each invitation mail carries the single matching client_id, so email-connect can admit it as a scoped caller (EMAIL-WP-0008). A tenant with no match, or with matches naming different clients, is denied as mail_binding_denied before either delivery lane is contacted; the platform event never carries client_id. An invalid value stops startup — it never falls back to the legacy shape.

Application access readback

Off unless USER_ENGINE_READBACK_URL is set. When it is set, these are also needed:

  • USER_ENGINE_READBACK_URL: base URL of access-engine's dedicated flex-auth-application-readback pin;
  • USER_ENGINE_READBACK_TOKEN_FILE: the readback caller token, read on every call. This is a separate file from USER_ENGINE_FLEX_AUTH_TOKEN_FILE. The pin admits it only under the application-readback binding, so it can never act on /v1/check;
  • USER_ENGINE_READBACK_TIMEOUT: optional, in seconds (default 3).

The account page (/onboarding) then lists each workload bound in all three records:

  • the user-engine application record;
  • its binding's protected_system_id;
  • the readback system's client_binding, whose issuer and client id must equal our OIDC issuer and the binding's oidc_client_id.

The rows are rendered as follows. No row is ever inferred as allow:

access-engine answer Shown
allow before expires_at Available
deny Not available
not_applicable Not available: not offered here
failure, missing row, or allow past or without expires_at Not available: could not be checked

Answers are read only on account-page views. They are reused per session and subject for at most 60 seconds, and never past the earliest allow's expires_at. Logout drops them. A failed read is not reused. Contract: access-engine docs/application-access-readback.md (FLEX-DEC-2026-019).

Authenticator management handoff

USER_ENGINE_MFA_MANAGEMENT_URL is optional and empty by default. When set, the public /security help page offers a fixed HTTPS provider-management link. No credentials, query parameters or fragments are allowed in this URL. The portal never collects an OTP, reads an OTP seed, or marks a factor enabled from a return URL. It cannot currently display authoritative enrollment status.

Enable only after verifying provider self-service identity checks, confirmation before activation, cancellation/recovery, and enrolled-factor enforcement under KEY-WP-0035. A reachable provider homepage alone is insufficient. Leave unset while this dependency is unresolved; users get an explicit unavailable state and help without needing to complete OTP login first. See account journeys.