generated from coulomb/repo-seed
224 lines
9.2 KiB
Markdown
224 lines
9.2 KiB
Markdown
---
|
|
id: NK-WP-0012
|
|
type: workplan
|
|
title: "NetKingdom IAM Profile Specification"
|
|
domain: netkingdom
|
|
repo: net-kingdom
|
|
status: finished
|
|
owner: worsch
|
|
topic_slug: netkingdom
|
|
planning_priority: high
|
|
planning_order: 12
|
|
created: "2026-05-21"
|
|
updated: "2026-05-22"
|
|
depends_on:
|
|
- NK-WP-0006
|
|
state_hub_workstream_id: 9b8e4afc-eb71-47d9-8750-799a082b320a
|
|
enables:
|
|
- NK-WP-0011
|
|
---
|
|
|
|
# NK-WP-0012 — NetKingdom IAM Profile Specification
|
|
|
|
> The IAM Profile is referenced everywhere as "the contract all applications
|
|
> target," but it does not exist as a net-kingdom artifact. A draft **v0.1
|
|
> exists in the-custodian canon** (`canon/standards/iam-profile_v0.1.md`),
|
|
> scoped "all-hubs" and Custodian-flavored. SCOPE.md says net-kingdom owns
|
|
> the IAM Profile. This workplan resolves that: net-kingdom becomes the
|
|
> canonical owner, and the profile is made provider-neutral, tenant- and
|
|
> agent-aware, and conformance-testable.
|
|
|
|
## Goal
|
|
|
|
Produce the **canonical, versioned NetKingdom IAM Profile** in net-kingdom
|
|
canon — the OIDC/PKCE contract every implementation issues and every
|
|
application and the authorization layer consume — together with an
|
|
**executable conformance check**.
|
|
|
|
The profile is the contract that makes the rest of the architecture
|
|
coherent:
|
|
|
|
- it is what `key-cape` (lightweight) and Keycloak (expanded) each
|
|
implement, interchangeably (capability ladder C1/C5);
|
|
- it is the identity input `flex-auth` consumes for authorization
|
|
decisions (responsibility map: the identity layer owns the claim
|
|
contract — that contract is this profile);
|
|
- it is the thing **NK-WP-0011-T6** runs conformance checks against, so
|
|
this workplan **enables** NK-WP-0011.
|
|
|
|
## Why now / what exists
|
|
|
|
The v0.1 draft is a strong base — discovery contract, Authorization Code +
|
|
PKCE human flow, service-account flow, required claims, token lifecycle,
|
|
emergency/break-glass, and a local-development profile. But it has gaps for
|
|
the current architecture:
|
|
|
|
| Gap in v0.1 | Needed because |
|
|
|---|---|
|
|
| Lives in the-custodian, scoped "all-hubs" | net-kingdom owns the profile (SCOPE.md, responsibility map) |
|
|
| Keycloak named as *the* reference provider | provider-neutral now: key-cape lightweight / Keycloak expanded are interchangeable implementations |
|
|
| Scope/role vocabulary is hub-specific (`hub:*`, `ops:*`, `fin:*`) | the core profile must be platform-neutral; hub/app scopes are downstream extensions |
|
|
| No tenant claim | recursive `tenant:platform` vs tenant model (NK-WP-0006) needs tenant in the token |
|
|
| Only human/service identities | architecture distinguishes human / service / **agent** principals |
|
|
| Assurance is implicit | flex-auth decision envelopes require explicit assurance evidence |
|
|
| No executable conformance check | NK-WP-0011-T6 and every implementation need a runnable contract test |
|
|
|
|
## Scope
|
|
|
|
In scope:
|
|
|
|
- ownership and reconciliation decision (ADR) with the-custodian v0.1
|
|
- a provider-neutral, platform-neutral **v0.2** profile in net-kingdom canon
|
|
- tenant- and agent-aware claims, and explicit assurance evidence
|
|
- the identity→authorization claim contract consumed by flex-auth
|
|
- an executable conformance check
|
|
- versioning and breaking-change governance for the profile
|
|
- migration of downstream references to the canonical net-kingdom spec
|
|
|
|
Out of scope:
|
|
|
|
- implementing the profile in key-cape or Keycloak (their repos own that)
|
|
- defining tenant- or application-specific scope vocabularies
|
|
- deploying any identity provider
|
|
|
|
## Tasks
|
|
|
|
```task
|
|
id: NK-WP-0012-T1
|
|
state_hub_task_id: 284dda38-b778-445a-a7dc-9b5a12fa380f
|
|
status: done
|
|
priority: high
|
|
```
|
|
|
|
**Ownership & reconciliation decision (ADR-0011).** Record that net-kingdom
|
|
is the canonical owner of the IAM Profile. Decide how the-custodian's
|
|
all-hubs v0.1 reconciles: net-kingdom owns the **core/platform profile**;
|
|
hub- and app-specific scope vocabularies (`hub:*`, `ops:*`, `fin:*`) become
|
|
**downstream extensions** that map back to the core, not part of it. Define
|
|
the profile's **versioning and breaking-change governance** (what a
|
|
breaking change is, how downstream is notified, how versions coexist).
|
|
|
|
```task
|
|
id: NK-WP-0012-T2
|
|
state_hub_task_id: 0070398d-b0a4-4c11-a6fa-000166e1108f
|
|
status: done
|
|
priority: high
|
|
```
|
|
|
|
**Author IAM Profile v0.2 (provider-neutral core).** Create
|
|
`canon/standards/iam-profile_v0.2.md` in net-kingdom. Carry forward the
|
|
solid v0.1 material — discovery contract, Authorization Code + PKCE human
|
|
flow, service-account flow, required/recommended claims, token lifecycle,
|
|
emergency/break-glass, local-development profile — and make it
|
|
**provider-neutral**: key-cape (lightweight) and Keycloak (expanded) are
|
|
named as interchangeable implementations, neither as "the" reference.
|
|
Remove hub-specific vocabulary from the core.
|
|
|
|
```task
|
|
id: NK-WP-0012-T3
|
|
state_hub_task_id: 6fc2a5e1-1480-42f1-86a2-3e714359e1ba
|
|
status: done
|
|
priority: high
|
|
```
|
|
|
|
**Extend for the recursive and agent model.** Add a **tenant** claim
|
|
(`tenant:platform` vs tenant id), formalize the **human / service / agent**
|
|
principal types and how each is represented, and define an explicit
|
|
**assurance evidence** claim (how authentication strength / MFA is conveyed
|
|
in the token). Align with NK-WP-0006 and the responsibility map.
|
|
|
|
```task
|
|
id: NK-WP-0012-T4
|
|
state_hub_task_id: 0e52ed45-afa7-4832-9d6a-1ebbbab43872
|
|
status: done
|
|
priority: high
|
|
```
|
|
|
|
**Define the identity→authorization claim contract.** Specify exactly which
|
|
claims the profile guarantees as inputs to flex-auth decision envelopes —
|
|
subject, issuer, audience, tenant, groups, roles, scopes, assurance — so
|
|
flex-auth treats the profile as normative input and never re-derives
|
|
identity. This is the contract named in the responsibility map.
|
|
|
|
```task
|
|
id: NK-WP-0012-T5
|
|
state_hub_task_id: f0a62e77-b781-4625-b8bd-d191b48af58e
|
|
status: done
|
|
priority: high
|
|
```
|
|
|
|
**Executable conformance check.** Build a runnable suite that validates an
|
|
issuer/implementation against the profile: discovery document completeness,
|
|
PKCE enforcement, claim shape, JWKS and key-rotation tolerance, token
|
|
validation (issuer/audience/expiry/signature), and rejection of
|
|
local-development issuers in production. This is the artifact NK-WP-0011-T6
|
|
consumes; it must run against both a key-cape and a Keycloak issuer.
|
|
|
|
```task
|
|
id: NK-WP-0012-T6
|
|
state_hub_task_id: a1fd53a9-526f-4d87-89db-6073710c885d
|
|
status: done
|
|
priority: medium
|
|
```
|
|
|
|
**Migration & cross-references.** Supersede or relink the-custodian v0.1
|
|
(deprecation note pointing at the net-kingdom canonical spec), and update
|
|
downstream references — `key-cape` and `flex-auth` interface docs,
|
|
NK-WP-0011, and any architecture docs — to cite the canonical net-kingdom
|
|
profile. Per ADR-0010, downstream **intents** are not touched; only
|
|
interface/reference docs.
|
|
|
|
## Acceptance Criteria
|
|
|
|
- The canonical IAM Profile lives in net-kingdom canon, versioned, and an
|
|
ADR records ownership and the reconciliation with the-custodian v0.1.
|
|
- The core profile is provider-neutral and platform-neutral (no
|
|
hub-specific scopes in the core; no single "reference provider").
|
|
- The profile carries tenant, principal-type (human/service/agent), and
|
|
assurance claims, aligned with the recursive model.
|
|
- The claims flex-auth consumes are specified as a normative contract.
|
|
- An executable conformance check exists and passes against both a
|
|
key-cape and a Keycloak issuer.
|
|
- Versioning and breaking-change governance is documented.
|
|
- Downstream reference docs point at the canonical spec; the custodian v0.1
|
|
carries a deprecation/relocation note.
|
|
|
|
## Completion Notes
|
|
|
|
- ADR: `docs/adr/ADR-0011-iam-profile-ownership-and-version-governance.md`
|
|
- Canonical profile: `canon/standards/iam-profile_v0.2.md`
|
|
- Executable conformance suite:
|
|
`tools/iam-profile-conformance/iam_profile_conformance.py`
|
|
- Fixture tests cover key-cape-like and Keycloak-like issuers, local-dev
|
|
rejection in production mode, tenant claim enforcement, provider-native
|
|
role normalization warnings, and delegated-agent claim shape.
|
|
- Cross-repo reference docs updated without touching downstream
|
|
`INTENT.md`: key-cape README/spec references now point at v0.2, and
|
|
flex-auth consumption docs plus claim fixtures now include v0.2 tenant,
|
|
principal, and assurance inputs.
|
|
|
|
## Dependencies & Sequencing
|
|
|
|
- **Depends on NK-WP-0006** for the recursive tenant model the claims encode.
|
|
- **Enables NK-WP-0011** — T6 (IAM Profile conformance) cannot pass without
|
|
the spec and the conformance check from this workplan. NK-WP-0012 should
|
|
land before NK-WP-0011-T6.
|
|
- Coordinates with **flex-auth** (the consumed claim contract, T4) and with
|
|
**key-cape**/**Keycloak** as the implementations the conformance check
|
|
runs against — those repos implement, this workplan specifies and tests.
|
|
|
|
## Resolved Questions
|
|
|
|
- Canonical role claim: `roles` is canonical. `realm_access.roles` is a
|
|
transitional/provider-native source that must be mapped before
|
|
production consumption.
|
|
- Audience granularity: the core profile requires the receiving service
|
|
in `aud`; endpoint/resource granularity belongs to flex-auth
|
|
resource/action policy.
|
|
- Agent principals differ from service accounts through
|
|
`principal_type: agent`, an `agent` object, and delegated actor context
|
|
(`actor_sub` or `act.sub`) when applicable.
|
|
- The conformance check is a standalone tool in net-kingdom for v0.2.
|
|
Other repos consume it as an executable contract rather than importing
|
|
a shared library for now.
|