netkingdom-iam-profile-v0.3 accepted · accepted-1 net-kingdom reviewed 2026-08-22generated from canonical source — do not edit

NetKingdom IAM Profile v0.3

Source: net-kingdom · canon/standards/iam-profile_v0.3.md · 9781102e2971d762ae42fdd5085a6647afd1cd66

Review due: 2027-02-22

Minor version. Per ADR-0011's versioning rule, this adds an optional claim and clarifies non-normative guidance — no required claim, validation rule, or previously-issued token is invalidated. Existing v0.2 implementations remain conformant; tenant_roles and the revised Tenant Claim guidance are additive.

Purpose

The NetKingdom IAM Profile is the provider-neutral OIDC contract that identity implementations issue and applications consume.

It defines:

  • OIDC discovery and endpoint requirements;
  • Authorization Code + PKCE for human login;
  • service-account and workload identity token requirements;
  • human, service, and agent principal representation;
  • tenant, tenant-grouping, and platform-boundary claims;
  • tenant capability roles and their carrying mechanism;
  • explicit assurance evidence;
  • the identity-to-authorization claim contract consumed by flex-auth;
  • local-development and emergency-access behavior;
  • executable conformance expectations.

Applications target this profile, not a concrete identity provider. key-cape is the lightweight implementation. Keycloak is the expanded-mode implementation. Both are interchangeable at the application and authorization boundary when they conform to this document.

Ownership

NetKingdom owns the core/platform profile. See ADR-0011.

Downstream systems may define extension scopes, roles, resource names, and tenant policy vocabularies. Those extensions are not part of the core profile unless a future version explicitly adopts them. Extension vocabularies must map back to the core claims in this document before flex-auth or applications consume them.

Design Principles

  • Consumers trust signed OIDC tokens, not provider-specific sessions.
  • Identity providers assert identity and authentication evidence; they do not make final resource authorization decisions.
  • The same profile works in lightweight key-cape mode and expanded Keycloak mode.
  • Tenancy is explicit. tenant:platform is distinct from tenant planes such as tenant:coulomb and from later tenants grouped per ADR-0013.
  • A tenant's onboarding grouping (ADR-0013) and its capability roles (ADR-0014) are independent axes. Neither is encoded in the other; a tenant's roles may change without renaming its identifier.
  • Human, service, and agent principals are distinguishable.
  • Assurance evidence is explicit enough for flex-auth policy.
  • Local-development issuers are useful but never accepted by production.
  • Emergency access is auditable, time-bounded, and reviewable.

Discovery Contract

Every IAM Profile implementation MUST expose OIDC discovery at:

GET <issuer>/.well-known/openid-configuration

The discovery response MUST include:

FieldRequirement
issuerExact issuer identifier used in tokens
authorization_endpointRequired for human Authorization Code + PKCE
token_endpointRequired for token exchange and service accounts
jwks_uriRequired for signature validation
userinfo_endpointRequired when userinfo is supported by the flow
scopes_supportedMUST include openid; SHOULD include profile and email
response_types_supportedMUST include code
grant_types_supportedMUST include authorization_code; MUST include client_credentials or a documented workload-token exchange for service identities
id_token_signing_alg_values_supportedMUST include the implementation signing algorithm; RS256 is required for v0.2+ conformance
code_challenge_methods_supportedMUST include S256

The response SHOULD include end_session_endpoint where logout is supported and claims_supported listing the core claims below.

Consumers MUST discover endpoints and key material from the issuer metadata instead of hardcoding provider-specific paths.

Required Flows

Human Interactive Flow

Human users authenticate with Authorization Code + PKCE.

Required properties:

  • PKCE with S256 is mandatory for browser and CLI clients.
  • Implicit flow is not part of the profile.
  • MFA or equivalent strong assurance is mandatory for privileged, destructive, platform-root, and emergency access in production.
  • Access tokens are short-lived.
  • Refresh tokens are allowed only for trusted clients with explicit rotation and revocation.

Service Account Flow

Service-to-service traffic uses client credentials or a deployment's documented workload identity token-exchange equivalent.

Required properties:

  • Service subjects are stable and named for service plus environment.
  • Secrets or workload credentials are delivered through the credential-management standard, not plaintext configuration.
  • Tokens include an audience that identifies the target service.
  • Tokens carry principal_type: service.
  • Service accounts receive only required scopes and roles.
  • Credentials are rotated and never shared between environments.

Agent Principal Flow

Agents are automation principals that may act autonomously or under delegated authority.

Required properties:

  • Tokens carry principal_type: agent.
  • Tokens include an agent object with id and mode.
  • agent.mode is autonomous or delegated.
  • Delegated agents MUST identify the delegating actor using actor_sub or an equivalent act.sub claim.
  • Agent tokens MUST carry the tenant they operate within.
  • Agent tokens MUST include assurance evidence for both the agent credential and any delegated human authority when policy needs it.

Core Claims

Access tokens accepted by production consumers MUST provide the following claims after provider mapping or normalization:

ClaimTypeMeaning
issstringOIDC issuer URL or issuer identifier
substringStable subject identifier unique within iss
audstring or arrayIntended audience; MUST include the receiving service
expnumberExpiry timestamp
iatnumberIssued-at timestamp
nbfnumberNot-before timestamp, recommended for production tokens
jtistringToken identifier, recommended for audit and replay controls
tenantstringTenant identifier such as tenant:platform or tenant:friendly:binky
principal_typestringhuman, service, or agent
groupsarrayGroup memberships, possibly empty
rolesarrayCoarse identity roles for the subject, possibly empty
scope or scpstring or arrayGranted OAuth scopes
assuranceobjectAuthentication and credential assurance evidence

Recommended human claims:

ClaimMeaning
preferred_usernameHuman-readable username
emailContact identity
nameDisplay name

Recommended service claims:

ClaimMeaning
azp or client_idAuthorized client/service identifier
serviceObject naming the service and environment

Recommended agent claims:

ClaimMeaning
agent.idStable agent identifier
agent.modeautonomous or delegated
actor_sub or act.subDelegating subject for delegated agents

Optional claims (new in v0.3):

ClaimTypeMeaning
tenant_rolesarrayCached tenant capability roles (PLTF/IAM/VEN/CUS), possibly empty. See "Tenant Roles" below — this is a point-in-time cache, not the authoritative source.

Role Claim

The canonical subject-level role claim is roles, an array of strings. This is distinct from tenant_roles (below) — a subject's own coarse identity roles are not the same fact as which capability roles the subject's tenant holds.

Expanded-mode Keycloak deployments may also expose provider-native roles such as realm_access.roles, but conforming tokens consumed by flex-auth or applications MUST either emit roles directly or pass through a normalizing adapter that produces roles.

Scope Vocabulary

The core profile defines only OAuth/OIDC base scopes:

ScopeMeaning
openidRequired for OIDC login
profileBasic profile claims
emailEmail claim where appropriate
offline_accessRefresh-token capable access where explicitly allowed

Hub-, application-, and resource-specific scopes such as hub:*, ops:*, fin:*, or storage actions are downstream extensions. They are valid only when the consuming system defines them and maps them to flex-auth resource/action semantics.

Tenant Claim

tenant is required for every token accepted by profile consumers.

Tenant identifiers follow tenant:<grouping>:<name>, where <grouping> is one of the taxonomy ratified by ADR-0013 at identifier creation:

trial        - test/trial/showcase tenants only
friendly     - known, easily reached, tolerant of experimentation/instability
single       - one-person business entities (freelance consultants)
small        - up to 10 employees at time of onboarding (attoo)
medium       - up to 100 employees (attoo)
large        - up to 1000 employees (attoo)
enterprise   - 1001+ employees (attoo)
consumer     - private individuals
family       - a legal family
community    - a non-legal group of people
association  - a legal association of people
agentic      - financially enabled AI entities

tenant:platform and tenant:coulomb remain reserved, ungrouped identifiers outside this taxonomy: tenant:platform is the platform control-plane tenant, not a business entity being onboarded; tenant:coulomb is the first internal/reference tenant established by ADR-0006, predating this taxonomy. Tenant administration for tenant:coulomb or any grouped tenant must never imply platform-root authority.

Subjects may have access to multiple tenants, but a token used for a request MUST identify the tenant context for that request. If a client needs to switch tenant context, it obtains a new token or uses an approved token-exchange flow that records the target tenant.

The grouping segment is an immutable record of the tenant's onboarding-time onboarding-risk / entity-shape classification. It remains vocabulary-valid but becomes historical if the tenant's classification later changes. The authoritative current grouping is the grouping field held by tenant-engine; consumers MUST NOT split tenant and treat its middle segment as current policy input. Changing current grouping never renames the tenant. Neither the historical segment nor current grouping gates which capability roles (below) a tenant may hold — see Tenant Roles.

Tenant Roles

Tenant capability roles are a separate fact from the grouping above and from the subject-level roles claim: PLTF, IAM, VEN, CUS (ratified by ADR-0014), non-exclusive — a tenant may hold several simultaneously, and holding one does not require or restrict any grouping.

Source of truth: tenant-engine (canon/standards/tenant-engine-boundary-contract_v0.1.md), not this profile and not any token. tenant-engine records role grants/revocations, their link (if any) to a plan/subscription, and emits domain events on change.

Carrying mechanism — hybrid, not claim-only:

  • key-cape (or Keycloak) MAY stamp a cached tenant_roles claim onto an issued token at issuance time, sourced from tenant-engine.
  • Consumers MAY trust the cached claim for ordinary, non-privileged decisions.
  • Consumers MUST NOT trust the cached claim for privileged, destructive, platform-root, secret, credential-vending, or otherwise assurance.level >= aal2-class decisions. Those decisions MUST query tenant-engine live for current role state before authorizing the action.
  • This bounds staleness for ordinary actions to the issuing token's lifetime (5-30 minutes for service/agent tokens, see Token Lifecycle) while guaranteeing freshness exactly where a stale grant (e.g. VEN surviving a plan cancellation) would matter most.

trial-grouped tenants may hold any capability role without restriction — the grouping exists to showcase, test, and explore every role. Safety for trial tenants is enforced through tenant-engine-owned resource guardrails (spend limits, entity/action counts — reserved, not yet specified), not through role gating.

Assurance Evidence

The canonical assurance claim is assurance.

It is an object with these fields:

FieldTypeMeaning
levelstringaal0, aal1, aal2, aal3, or break_glass
methodsarrayAuthentication methods, e.g. pwd, otp, webauthn, client_secret, workload_identity, upstream_mfa
mfabooleanWhether the authentication included multiple factors or equivalent upstream evidence
sourcestringProvider of the evidence, e.g. key-cape, keycloak, privacyidea, entra, local-identity
atnumberAuthentication time, recommended

Level meanings:

LevelMeaning
aal0Local/dev or unauthenticated bootstrap evidence; never production privileged
aal1Single-factor or service credential evidence
aal2MFA or equivalent strong upstream assurance
aal3Phishing-resistant or hardware-backed assurance
break_glassTime-bounded emergency access with post-event review

Privileged, destructive, platform-root, secret, credential-vending, and emergency flows require aal2 or stronger unless a policy explicitly permits a narrower service or workload identity path. Emergency access MUST use break_glass and short token lifetimes. This is the same threshold class that gates when tenant_roles MUST be re-validated live against tenant-engine rather than trusted from the token — see Tenant Roles.

Provider-native claims such as acr and amr may be present, but consumers use assurance as the normalized profile claim.

Identity To Authorization Contract

flex-auth consumes IAM Profile tokens as normative identity input. flex-auth MUST NOT re-derive identity, tenant, group, role, or assurance facts from provider-specific session state.

The profile guarantees these inputs for authorization decision envelopes:

Decision inputSource claim
Subjectsub
Issueriss
Audienceaud
Tenanttenant
Principal typeprincipal_type
Groupsgroups
Subject rolesroles
Tenant capability rolestenant_roles (cached); tenant-engine live lookup required for high-stakes decisions
Scopesscope or scp
Assuranceassurance
Authorized clientazp or client_id, where present
Agent/delegation contextagent, actor_sub, or act, where present
Token lifetime/audit idsiat, nbf, exp, jti, where present

Authorization decisions are made by flex-auth and its delegated PDP adapters. Identity providers may assert roles or scopes, but those claims are inputs to policy, not final permission to act on a resource.

Token Lifecycle

Recommended production defaults:

TokenLifetimeNotes
Human access token5-15 minutesShort-lived bearer token
Refresh token8-12 hoursRotated and revoked on logout or suspicion
Service token5-30 minutesReissued by client credentials or workload identity
Agent token5-30 minutesShorter when delegated or platform-scoped
Emergency token5-15 minutesRequires incident/review record

Consumers MUST reject expired tokens and tokens with invalid issuer, audience, signature, nbf, or algorithm. Clock skew tolerance SHOULD be small, normally no more than 60 seconds.

JWKS material may be cached, but consumers MUST tolerate key rotation by refreshing JWKS when a token uses an unknown kid.

Local Development Profile

A local file-backed provider may be used for development, tests, and bootstrap contexts where the full platform is unavailable.

It MUST:

  • expose OIDC discovery;
  • issue signed JWTs;
  • support deterministic test users and service accounts;
  • use local-only issuer URLs or a clearly local issuer identifier;
  • mark tokens as local/development through issuer, audience, or assurance evidence;
  • be rejected by production consumers.

Production consumers MUST reject:

  • issuer local-identity;
  • http:// issuers;
  • loopback issuers such as localhost or 127.0.0.1;
  • tokens with assurance.level: aal0;
  • tokens where the environment marks the issuer as local/dev.

Emergency And Break-Glass Access

Emergency access is allowed only as a break-glass path.

Requirements:

  • Emergency identities are disabled by default.
  • Activation requires an incident, decision, or human-recorded review reference.
  • Tokens are short-lived and carry the emergency role.
  • Tokens carry assurance.level: break_glass.
  • Every emergency action emits an audit/progress/incident event.
  • Emergency access is reviewed after use and then disabled again.

Emergency access MUST NOT bypass audit logging or flex-auth policy.

Conformance

An implementation conforms to IAM Profile v0.3 when it passes the executable conformance suite in:

tools/iam-profile-conformance/

The suite validates:

  • discovery document completeness;
  • PKCE S256 advertisement and rejection of authorization requests that omit a code challenge;
  • JWKS structure and key ids;
  • token issuer, audience, expiry, nbf, iat, and RS256 signature;
  • tenant, principal type, groups, roles, scopes, and assurance claim shape;
  • tenant_roles claim shape when present (array of ratified role strings);
  • agent and delegated-agent claim shape;
  • local-development issuer rejection in production mode.

Conformance must be runnable against both key-cape lightweight issuers and Keycloak expanded-mode issuers. Implementations may add provider adapters, but the token consumed by applications and flex-auth must match the core claim contract above. tenant_roles conformance does not require an implementation to emit the claim (it is optional); when emitted, it must match the ratified vocabulary.

Validation Checklist

A service or implementation is profile-ready when:

  • it reads OIDC discovery rather than hardcoding endpoints;
  • it validates issuer, audience, expiry, nbf, algorithm, and signature;
  • it refreshes JWKS on unknown kid;
  • it supports Authorization Code + PKCE for human login;
  • it supports service-account or workload identity tokens;
  • it emits tenant, principal_type, groups, roles, scope/scp, and assurance;
  • it uses the ADR-0013 grouping vocabulary for new tenant identifiers;
  • if it consumes tenant_roles, it treats the claim as a cache and re-validates live against tenant-engine before any aal2-class decision;
  • it maps provider-native claims into the canonical core claims;
  • it rejects local-development issuers in production;
  • it logs emergency access with a durable audit trail;
  • flex-auth receives identity facts from the profile, not from provider-specific sessions.