user-engine/docs/flex-auth-caller-identity.md
tegwick 4622b64061 Authenticate flex-auth calls with a rotating caller token
Closes the caller side of FLEX-WP-0015. FlexAuthHTTPAdapter reads the
audience-scoped projected ServiceAccount token from a file on every decision,
so hourly rotation needs no restart, and runtime configuration now requires
USER_ENGINE_FLEX_AUTH_TOKEN_FILE.

A missing, empty, or unreadable token file fails closed as a denial without
reaching flex-auth: OSError joins the caught set and an empty read raises.
Coverage proves all three unusable-token cases deny before any request is
made, and that neither the deny reason nor the decision repr carries the
token value.

Tenant-authority reads now identify user-engine as actor `user-engine` under
the protected tenant.read action, keeping tenant ids opaque and URL-encoded.

Contract: docs/flex-auth-caller-identity.md. Full suite: 148 tests, 3
provider-gated skips.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 10:53:31 +02:00

1.4 KiB

flex-auth caller identity contract

Status: source implemented; production promotion pending.

user-engine calls flex-auth-user-engine with a projected Kubernetes ServiceAccount token whose audience is exactly flex-auth. The adapter reads the token file for every decision so hourly projection rotation requires no restart. A missing, empty or unreadable file fails closed as an authorization denial; the token value is never logged.

flex-auth binds protected system user-engine to principal system:serviceaccount:user-engine:user-engine. The token authenticates the calling workload only. It does not replace the IAM actor/tenant/assurance facts inside the authorization request and grants no Kubernetes API permission to user-engine.

Runtime configuration requires USER_ENGINE_FLEX_AUTH_TOKEN_FILE. Local construction keeps the adapter argument optional so unit tests and explicit non-production adapters remain usable.

The tenant authority seam is distinct: user-engine identifies itself as actor user-engine on tenant lifecycle reads and writes; tenant-engine performs its own flex-auth decision before store access. Tenant ids remain opaque and are URL-encoded. No client may infer existence from an unauthorized read.

The current deployed image predates this file-based caller token. Promote only with the matching flex-auth A2 image and bindings; otherwise enforcing flex-auth will correctly return 401 to the old caller.