These workplans exist only in the retired local hub. Their random pre-ADR-007 identifiers are refused by C-06 as stale references, so they cannot be registered. Deriving from the canonical record id takes no identity from anything: central does not hold them and the old ids die with the cache. Records central already holds were deliberately left untouched. Refs CUST-WP-0068-T06 Assistant: claude-code Assistant-Model: opus Assistant-Process: 2583210@bnt-lap001 Assistant-Session: f2bff2d5-e9b2-4338-92ca-10282a927006
116 lines
4.1 KiB
Markdown
116 lines
4.1 KiB
Markdown
---
|
|
id: KEY-WP-0006
|
|
type: workplan
|
|
title: "Client credentials and service-token issuance"
|
|
domain: infotech
|
|
repo: key-cape
|
|
status: finished
|
|
owner: codex
|
|
topic_slug: netkingdom
|
|
created: "2026-07-27"
|
|
updated: "2026-07-27"
|
|
state_hub_workstream_id: "d8d20d8f-61e0-54e2-9a88-a3958f0b6f2d"
|
|
---
|
|
|
|
# KEY-WP-0006 - Client credentials and service tokens
|
|
|
|
Implement the missing service-principal half of the IAM Profile so
|
|
`KEY-WP-0004` can issue a least-privilege identity to `rapp-qonto`.
|
|
|
|
## T01 - Model confidential service clients
|
|
|
|
```task
|
|
id: KEY-WP-0006-T01
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "993913a7-f951-50ee-9b10-d5b9e67b523c"
|
|
```
|
|
|
|
Extend static client registration with an explicit service subject, tenant,
|
|
roles, and an environment-backed secret reference. Refuse startup when a
|
|
`client_credentials` client is public, lacks its identity fields, or cannot
|
|
resolve its secret. Never serialize or log the resolved secret.
|
|
|
|
2026-07-27: Added explicit service subject, tenant, roles, and in-memory-only
|
|
resolved secret fields. Configuration validation rejects public or incomplete
|
|
service clients, and startup resolves only `env:` secret references while
|
|
reporting the variable name—not its value—on failure.
|
|
|
|
## T02 - Implement secure client_credentials exchange
|
|
|
|
```task
|
|
id: KEY-WP-0006-T02
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "801a6d55-2f91-51b1-88e4-cc7f0867238d"
|
|
```
|
|
|
|
Accept confidential client authentication through HTTP Basic, compare secrets
|
|
in constant time, restrict requested scopes to the registered allowlist, and
|
|
issue a short-lived access token with `principal_type=service`,
|
|
tenant-specific subject/roles, empty groups, `aal1` client-secret assurance,
|
|
and optional cached `tenant_roles`. Do not issue an ID token for this
|
|
non-human grant.
|
|
|
|
2026-07-27: Implemented HTTP Basic confidential-client authentication with
|
|
fixed-length SHA-256 constant-time comparison, allowlisted scopes, short-lived
|
|
service claims, optional tenant-role cache, token-issued telemetry, and no ID
|
|
token.
|
|
|
|
## T03 - Prove positive and negative conformance
|
|
|
|
```task
|
|
id: KEY-WP-0006-T03
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "e5c2a8b1-0879-57fa-a197-250a34c75bdb"
|
|
```
|
|
|
|
Cover valid exchange, unknown client, public client, missing/wrong secret,
|
|
unsupported grant, excess scope, tenant isolation, telemetry redaction, and
|
|
discovery metadata. Run the full Go build, vet, and test suite.
|
|
|
|
2026-07-27: Added positive service-claim and negative wrong-secret/excess-scope
|
|
tests, updated discovery to advertise only implemented grants/auth methods,
|
|
and verified `go test ./...`, `go vet ./...`, and `go build ./...` across the
|
|
module.
|
|
|
|
## T04 - Provision and verify rapp-qonto
|
|
|
|
```task
|
|
id: KEY-WP-0006-T04
|
|
status: done
|
|
priority: high
|
|
state_hub_task_id: "31af6b8c-96ff-5060-87db-3803b9a9dd12"
|
|
```
|
|
|
|
Generate the client secret without disclosure, store it through the approved
|
|
OpenBao lane, register the static `rapp-qonto` client, deploy KeyCape, and
|
|
verify a real exchange yields only the documented Binky service claims.
|
|
Publish non-secret evidence to `KEY-WP-0004-T03` through T05.
|
|
|
|
2026-07-27: Provisioned the confidential client secret at
|
|
`platform/workloads/rapp-qonto/keycape-client`, injected it into
|
|
`sso/keycape-rapp-qonto-client`, registered `rapp-qonto-client`, and deployed
|
|
image `main-e877d27-2` on railiance01. A real exchange produced only
|
|
`sub=rapp-qonto`, `tenant=tenant:friendly:binky`, `principal_type=service`,
|
|
`roles=[qonto-reader]`, empty groups, and `scope=qonto:read`; excessive scope
|
|
and a wrong secret were denied. Public DNS still resolves
|
|
`kc.coulomb.social` to the older CoulombCore endpoint, so the deployment proof
|
|
used TLS-preserving direct resolution to railiance01 (`92.205.62.239`).
|
|
|
|
## T05 - Closure review
|
|
|
|
```task
|
|
id: KEY-WP-0006-T05
|
|
status: done
|
|
priority: low
|
|
state_hub_task_id: "8c72d7d9-4086-5e64-b939-a12bff076124"
|
|
```
|
|
|
|
Close after T01-T04 pass and the repeatable verification path is documented.
|
|
|
|
2026-07-27: Closure review passed. Build, vet, unit/profile tests, live
|
|
positive claims, negative authentication/scope checks, and discovery metadata
|
|
all passed. The stale public DNS target is handed off as routing work rather
|
|
than weakening the service-token contract.
|