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.
This commit is contained in:
parent
a6a380b19f
commit
d88767f05b
13 changed files with 325 additions and 48 deletions
|
|
@ -33,14 +33,16 @@ See `.env.example`. Summary:
|
|||
|----------|---------|---------|
|
||||
| `SECRET_KEY` | insecure dev default | Django secret |
|
||||
| `DATABASE_URL` | sqlite `./db.sqlite3` | DB |
|
||||
| `DEFAULT_TENANT_ID` | `binky` | Client #1 tenant key |
|
||||
| `DEFAULT_TENANT_ID` | `tenant:coulomb` | Platform tenant claim (KeyCape default) |
|
||||
| `OIDC_ENABLED` | `false` | Use KeyCape / real issuer |
|
||||
| `OIDC_ISSUER` | | e.g. `https://kc.coulomb.social` |
|
||||
| `OIDC_CLIENT_ID` | | `coulomb-social` |
|
||||
| `OIDC_CLIENT_SECRET` | empty | **public client** — leave empty |
|
||||
| `OIDC_REDIRECT_URI` | | `http://127.0.0.1:8008/auth/callback/` |
|
||||
| `USER_ENGINE_BASE_URL` | empty (stub) | user-engine HTTP |
|
||||
| `USER_ENGINE_APPLICATION_ID` | `coulomb-social` | App id in user-engine |
|
||||
| `USER_ENGINE_BASE_URL` | empty (stub) | e.g. `https://users.92-205-62-239.nip.io` |
|
||||
| `USER_ENGINE_PROXY_SECRET` | empty | trusted proxy secret (with base URL → HTTP) |
|
||||
| `USER_ENGINE_APPLICATION_ID` | `coulomb-social` | App id |
|
||||
| `USER_ENGINE_EXPECTED_AUDIENCE` | `user-engine-portal` | required aud for /me |
|
||||
| `FLEX_AUTH_BASE_URL` | empty (fail-closed except shell:view) | PDP |
|
||||
|
||||
### Platform OIDC (KeyCape)
|
||||
|
|
|
|||
|
|
@ -4,20 +4,53 @@
|
|||
|-------|--------|
|
||||
| application id | `coulomb-social` (`USER_ENGINE_APPLICATION_ID`) |
|
||||
| display name | coulomb.social |
|
||||
| tenant (v1) | `binky` (client #1) |
|
||||
| identity link | `(issuer, sub)` → `user_engine_user_id` on first login |
|
||||
| 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 | Behavior |
|
||||
|------|----------|
|
||||
| `USER_ENGINE_BASE_URL` empty | `StubUserEngineClient` — deterministic user id from issuer+sub hash |
|
||||
| URL set | `HttpUserEngineClient` placeholder (T04: wire real link/projection API) |
|
||||
| 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:
|
||||
|
||||
```http
|
||||
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
|
||||
|
||||
```bash
|
||||
# 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 (from OIDC `name` / `preferred_username`)
|
||||
- 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).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue