Draft KEY-WP-0005: IAM Profile core claims (tenant, principal_type, roles, assurance, tenant_roles)
Discovered while planning tenant-engine's flex-auth WriteAuthorizer
(TEN-WP-0003): src/internal/server/oidc/token.go emits none of
iam-profile_v0.3.md's Core Claims yet -- not tenant, principal_type,
groups, roles, or assurance. tenant_roles isn't a small addition on top of
existing tenant support; it's the last, optional claim on top of a
baseline that doesn't exist yet.
Registered, not implemented -- security-sensitive Go token-issuance code
deserves dedicated context before changing, not a rushed edit from a first
read of the file.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 22:47:00 +02:00
|
|
|
|
---
|
|
|
|
|
|
id: KEY-WP-0005
|
|
|
|
|
|
type: workplan
|
|
|
|
|
|
title: "IAM Profile core claims: tenant, principal_type, groups, roles, assurance, tenant_roles"
|
|
|
|
|
|
domain: infotech
|
|
|
|
|
|
repo: key-cape
|
|
|
|
|
|
status: ready
|
|
|
|
|
|
owner: codex
|
|
|
|
|
|
topic_slug: netkingdom
|
|
|
|
|
|
created: "2026-07-23"
|
|
|
|
|
|
updated: "2026-07-23"
|
2026-07-23 23:52:13 +02:00
|
|
|
|
state_hub_workstream_id: "74ac0d31-b86e-449d-89b2-4e15263bf050"
|
Draft KEY-WP-0005: IAM Profile core claims (tenant, principal_type, roles, assurance, tenant_roles)
Discovered while planning tenant-engine's flex-auth WriteAuthorizer
(TEN-WP-0003): src/internal/server/oidc/token.go emits none of
iam-profile_v0.3.md's Core Claims yet -- not tenant, principal_type,
groups, roles, or assurance. tenant_roles isn't a small addition on top of
existing tenant support; it's the last, optional claim on top of a
baseline that doesn't exist yet.
Registered, not implemented -- security-sensitive Go token-issuance code
deserves dedicated context before changing, not a rushed edit from a first
read of the file.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 22:47:00 +02:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
# IAM Profile core claims: tenant, principal_type, groups, roles, assurance, tenant_roles
|
|
|
|
|
|
|
|
|
|
|
|
Discovered while planning `tenant-engine/workplans/TEN-WP-0003-flex-auth-write-authorizer.md`:
|
|
|
|
|
|
`key-cape`'s token issuance (`src/internal/server/oidc/token.go`) does not
|
|
|
|
|
|
currently emit `tenant`, `principal_type`, `groups`, `roles`, or
|
|
|
|
|
|
`assurance` — none of `net-kingdom/canon/standards/iam-profile_v0.3.md`'s
|
|
|
|
|
|
Core Claims are implemented yet, only `preferred_username`/`email`/`groups`
|
|
|
|
|
|
(LDAP-sourced, not the profile's normalized `groups` claim) and OIDC's own
|
|
|
|
|
|
base claims (`nonce`, etc.).
|
|
|
|
|
|
|
|
|
|
|
|
This is bigger than "add the `tenant_roles` claim on top of existing tenant
|
|
|
|
|
|
support" — `key-cape` isn't yet profile-conformant at all on the tenant/
|
|
|
|
|
|
principal/assurance axis. `tenant_roles` (the reason this workplan exists)
|
|
|
|
|
|
is the last, optional claim in that same set (v0.3's addition on top of
|
|
|
|
|
|
v0.2's baseline) — implementing it in isolation without the claims it
|
|
|
|
|
|
depends on for meaning (`tenant`, `principal_type`) would be incoherent.
|
|
|
|
|
|
|
|
|
|
|
|
**This workplan is registered, not implemented, by the same session that
|
|
|
|
|
|
found the gap.** Token issuance is security-sensitive code in a Go codebase
|
|
|
|
|
|
with its own adapter conventions (`internal/adapters/{lldap,privacyidea,authelia}`)
|
|
|
|
|
|
that deserves dedicated context before changing, not a rushed edit from a
|
|
|
|
|
|
first read of `token.go`. Scoped and sequenced here so the work isn't lost.
|
|
|
|
|
|
|
|
|
|
|
|
**Depends on:** `net-kingdom/canon/standards/iam-profile_v0.3.md` (ratified).
|
|
|
|
|
|
**Related:** `tenant-engine/workplans/TEN-WP-0003-flex-auth-write-authorizer.md`
|
|
|
|
|
|
(the consumer waiting on `tenant_roles`); `key-cape/workplans/KEY-WP-0004-binky-hedgehog-tenant-onboarding.md`
|
|
|
|
|
|
(Binky's onboarding, which needs `tenant` claim support to produce a
|
|
|
|
|
|
correct `tenant:friendly:binky` token at all).
|
|
|
|
|
|
|
|
|
|
|
|
## Task: Emit `tenant`, `principal_type`, `groups`, `roles`, `assurance`
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: KEY-WP-0005-T01
|
|
|
|
|
|
status: todo
|
|
|
|
|
|
priority: high
|
2026-07-23 23:52:13 +02:00
|
|
|
|
state_hub_task_id: "66107caf-ba26-4291-bb09-1f9e58275505"
|
Draft KEY-WP-0005: IAM Profile core claims (tenant, principal_type, roles, assurance, tenant_roles)
Discovered while planning tenant-engine's flex-auth WriteAuthorizer
(TEN-WP-0003): src/internal/server/oidc/token.go emits none of
iam-profile_v0.3.md's Core Claims yet -- not tenant, principal_type,
groups, roles, or assurance. tenant_roles isn't a small addition on top of
existing tenant support; it's the last, optional claim on top of a
baseline that doesn't exist yet.
Registered, not implemented -- security-sensitive Go token-issuance code
deserves dedicated context before changing, not a rushed edit from a first
read of the file.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 22:47:00 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Bring `token.go`'s claim assembly up to `iam-profile_v0.3.md`'s Core Claims
|
|
|
|
|
|
table baseline (the v0.2-originated set):
|
|
|
|
|
|
|
|
|
|
|
|
- `tenant`: resolve from whatever user/service/agent-to-tenant mapping
|
|
|
|
|
|
`key-cape`'s LLDAP/Authelia backend can provide today; if no such mapping
|
|
|
|
|
|
exists yet, that's itself a sub-task — this claim cannot be stamped from
|
|
|
|
|
|
nothing.
|
|
|
|
|
|
- `principal_type`: `human` for the existing Authorization Code + PKCE flow;
|
|
|
|
|
|
`service` for client-credentials flows (check whether `key-cape` already
|
|
|
|
|
|
issues client-credentials tokens at all — `grant_types_supported` in the
|
|
|
|
|
|
discovery contract claims it does, but that needs verifying against real
|
|
|
|
|
|
code, the same way this workplan verified `tenant` claim absence).
|
|
|
|
|
|
- `groups`, `roles`: normalize from LDAP group/role data into the profile's
|
|
|
|
|
|
flat string-array shape.
|
|
|
|
|
|
- `assurance`: `{level, methods, mfa, source, at}` per the profile —
|
|
|
|
|
|
`privacyIDEA`-backed MFA evidence maps to `aal2`; single-factor maps to
|
|
|
|
|
|
`aal1`.
|
|
|
|
|
|
|
|
|
|
|
|
Done when: `tools/iam-profile-conformance/` (already exists) passes against
|
|
|
|
|
|
these claims for both human and service token issuance paths.
|
|
|
|
|
|
|
|
|
|
|
|
## Task: Emit `tenant_roles` (optional, cached)
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: KEY-WP-0005-T02
|
|
|
|
|
|
status: todo
|
|
|
|
|
|
priority: high
|
2026-07-23 23:52:13 +02:00
|
|
|
|
state_hub_task_id: "1b8f44b4-2763-4d5a-a3eb-1c2b9a25dd15"
|
Draft KEY-WP-0005: IAM Profile core claims (tenant, principal_type, roles, assurance, tenant_roles)
Discovered while planning tenant-engine's flex-auth WriteAuthorizer
(TEN-WP-0003): src/internal/server/oidc/token.go emits none of
iam-profile_v0.3.md's Core Claims yet -- not tenant, principal_type,
groups, roles, or assurance. tenant_roles isn't a small addition on top of
existing tenant support; it's the last, optional claim on top of a
baseline that doesn't exist yet.
Registered, not implemented -- security-sensitive Go token-issuance code
deserves dedicated context before changing, not a rushed edit from a first
read of the file.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 22:47:00 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
At token-issuance time, call `tenant-engine`'s cache-read endpoint
|
|
|
|
|
|
(`GET /tenants/{tenant_id}/roles`) using the `tenant` claim resolved in T01,
|
|
|
|
|
|
and stamp the result as the optional `tenant_roles` claim
|
|
|
|
|
|
(`iam-profile_v0.3.md`, "Tenant Roles" section). Follows the same adapter
|
|
|
|
|
|
pattern as `internal/adapters/{lldap,privacyidea,authelia}` — a new
|
|
|
|
|
|
`internal/adapters/tenantengine` package, not inline HTTP calls in
|
|
|
|
|
|
`token.go`.
|
|
|
|
|
|
|
|
|
|
|
|
Fail open on this claim specifically, not closed: `tenant_roles` is
|
|
|
|
|
|
documented as a cache callers must not trust for privileged decisions
|
|
|
|
|
|
anyway (`flex-auth` re-validates live). If `tenant-engine` is unreachable at
|
|
|
|
|
|
issuance time, omit the claim rather than fail the entire token issuance —
|
|
|
|
|
|
losing a performance optimization is acceptable; blocking login because a
|
|
|
|
|
|
cache source is down is not. This is the one place in the whole `tenant_roles`
|
|
|
|
|
|
design where fail-open is correct, precisely because the live-lookup path
|
|
|
|
|
|
exists as the real gate.
|
|
|
|
|
|
|
|
|
|
|
|
Done when: token issuance still succeeds with `tenant_roles` omitted when
|
|
|
|
|
|
`tenant-engine` is unreachable (test simulates the outage); present and
|
|
|
|
|
|
correct when reachable, for a tenant with known role grants.
|
|
|
|
|
|
|
|
|
|
|
|
## Task: Closure review
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: KEY-WP-0005-T03
|
|
|
|
|
|
status: todo
|
|
|
|
|
|
priority: low
|
2026-07-23 23:52:13 +02:00
|
|
|
|
state_hub_task_id: "34555bf7-0f18-4dac-ade2-6ff3738f353f"
|
Draft KEY-WP-0005: IAM Profile core claims (tenant, principal_type, roles, assurance, tenant_roles)
Discovered while planning tenant-engine's flex-auth WriteAuthorizer
(TEN-WP-0003): src/internal/server/oidc/token.go emits none of
iam-profile_v0.3.md's Core Claims yet -- not tenant, principal_type,
groups, roles, or assurance. tenant_roles isn't a small addition on top of
existing tenant support; it's the last, optional claim on top of a
baseline that doesn't exist yet.
Registered, not implemented -- security-sensitive Go token-issuance code
deserves dedicated context before changing, not a rushed edit from a first
read of the file.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 22:47:00 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Confirm T01–T02 done; conformance suite green for both tasks together.
|
|
|
|
|
|
Note in closure: this unblocks `KEY-WP-0004`'s Binky onboarding actually
|
|
|
|
|
|
producing conformant tokens, and unblocks `flex-auth`'s side of the
|
|
|
|
|
|
`tenant_roles` picture receiving a real claim to reason about (though
|
|
|
|
|
|
`flex-auth`'s live-lookup path doesn't depend on this claim existing — only
|
|
|
|
|
|
the cache-read/performance path does). Run `statehub fix-consistency`.
|