key-cape/workplans/KEY-WP-0024-tenant-roles-opt-in-wiring.md
tegwick a9296fdf84 chore(consistency): register KEY-WP-0024 [auto]
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NV9oijZukGyGbRQGGKnK4P

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 713576@bnt-lap001
Assistant-Session: 384c511d-9bce-4cb8-a676-2aef6c0c8df6
2026-09-08 09:00:39 +02:00

62 lines
2.3 KiB
Markdown

---
id: KEY-WP-0024
type: workplan
title: "Wire tenant_roles as explicit opt-in configuration"
domain: infotech
repo: key-cape
status: finished
owner: claude
topic_slug: tenant-roles-opt-in-wiring
created: "2026-09-08"
updated: "2026-09-08"
state_hub_workstream_id: "d75f52f2-df0d-5a56-8394-892feeec4b4d"
---
Closes gap G07. The tenant-engine client and `TokenHandler.TenantEngine` were
implemented and tested, but `main.go` supplied no client and exposed no
configuration, so the stock executable left the field nil and never emitted
`tenant_roles`. The capability existed at library level only.
Wired rather than documented away as library-only: the claim is cheap, the
adapter already fails open, and leaving a tested capability unreachable from the
binary invites the same gap being rediscovered later.
## Add opt-in configuration and wire the client
```task
id: KEY-WP-0024-T01
status: done
priority: medium
state_hub_task_id: "0e53485b-7e94-5dd8-8e02-1d18f5413a78"
```
Added a `tenantEngine` config block with `baseURL` and an optional `timeout`.
An empty `baseURL` disables the claim, which keeps the stock server's behaviour
exactly as it was — enabling it is a deliberate act.
Validation treats a configured source as one that must work: the URL must be
http/https with a host, and the timeout must parse and fall in (0, 10s], since it
sits on the synchronous token-issuance path. A `timeout` set without a `baseURL`
is rejected rather than ignored — it means someone expected the claim to be on
and it silently would not have been.
## Verify it in the built executable
```task
id: KEY-WP-0024-T02
status: done
priority: medium
state_hub_task_id: "c4279ce0-f6f8-5612-a48a-c1d2fd3da3b6"
```
G07's closure criterion is the built executable, not the wiring, so all three
behaviours were checked by running `bin/keycape` and inspecting real tokens
rather than by reading the code:
- configured against a stub tenant-engine, a `client_credentials` token carries
`tenant_roles: [capability:approve, capability:observe]`;
- with no `tenantEngine` block, the claim is absent;
- configured but with the source down, issuance still succeeds and the claim is
absent — the fail-open behaviour the adapter documents, confirmed end to end.
Nine validation cases cover the accepted and rejected configurations.