coulomb-social/docs/identity/user-engine-binding.md
tegwick d88767f05b Wire user-engine HTTP /me for member provisioning (CSOC-WP-0002-T04)
HttpUserEngineClient uses trusted-proxy claims against live user-engine.
Offline stub when URL/secret unset. Align default tenant with KeyCape
tenant:coulomb; map OIDC tenant/principal_type/groups into the envelope.
2026-08-09 01:56:44 +02:00

2 KiB

user-engine application binding

Field Value
application id coulomb-social (USER_ENGINE_APPLICATION_ID)
display name coulomb.social
tenant (v1) tenant:coulomb (KeyCape default; Binky friendly slug later)
identity link (issuer, sub) via user-engine GET /api/v1/me auto-provision
local row members.Member (no passwords)
live base URL https://users.92-205-62-239.nip.io (cluster ingress)

Runtime

Mode When Behavior
stub USER_ENGINE_BASE_URL or USER_ENGINE_PROXY_SECRET empty Deterministic user_id from sha256(iss|sub)
http both set Trusted-proxy GET /api/v1/me with IAM-shaped claims envelope

Trusted proxy envelope

user-engine accepts claims only when:

X-User-Engine-Proxy-Secret: <secret from user-engine-runtime>
X-Verified-Oidc-Claims: {"iss","sub","tenant","principal_type","aud",...}

aud must include the portal audience user-engine-portal (deployed expectation) plus coulomb-social. Trust is the proxy secret; claims were verified by KeyCape OIDC at the app edge.

Operator: enable HTTP mode locally

# secret never printed to shell history if you use process substitution carefully
export USER_ENGINE_BASE_URL=https://users.92-205-62-239.nip.io
export USER_ENGINE_PROXY_SECRET="$(kubectl -n user-engine get secret user-engine-runtime \
  -o jsonpath='{.data.proxy-secret}' | base64 -d)"
export USER_ENGINE_EXPECTED_AUDIENCE=user-engine-portal
# then OIDC or dev-login

OpenBao lane for the proxy secret (future): document under railiance-platform workload KV; until then kubectl-sourced secret is operator-only on the workstation.

Profile attributes (shell only)

  • display name (OIDC name / user-engine user.display_name)
  • email (optional)

Bubble content fields are not part of this binding.

Live probe (2026-08-09)

GET /api/v1/me with probe claims returned user_id usr_… and actor.tenant=tenant:coulomb (HTTP 200).