Activate NK-WP-0009/0011; add tutorials slice and proposed ADR-0009
Some checks are pending
CI Smoke / host-smoke (push) Waiting to run
CI Smoke / container-smoke (push) Waiting to run

- docs/tutorials: template, OpenBao and SSH tutorials (unexercised)
- tools/tutorial-verify + make tutorials-verify (NK-WP-0009-T06)
- ADR-0009 proposed: expanded-mode Keycloak trigger and topology

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>

Assistant: claude-code
Assistant-Model: sonnet
Assistant-Process: 295952@bnt-lap001
Assistant-Session: e93f64ad-516c-46eb-9666-aad8d300c477
This commit is contained in:
tegwick 2026-09-28 23:31:48 +02:00
parent 5c4bc16706
commit 0d460e3c02
11 changed files with 469 additions and 8 deletions

View file

@ -0,0 +1,111 @@
---
id: NK-ADR-0009
type: architecture-decision-record
title: "Expanded-Mode Keycloak: Adoption Trigger and Federation Topology"
status: proposed
owner: net-kingdom
revision: "1"
proposed: "2026-09-28"
last_reviewed: "2026-09-28"
review_interval: 12m
---
# ADR-0009 - Expanded-Mode Keycloak: Adoption Trigger and Federation Topology
**Status:** Proposed (awaiting Bernd's decision; NK-WP-0011-T01)
**Date:** 2026-09-28
**Deciders:** Bernd Worsch, Claude
## Context
The live IAM Profile issuer is KeyCape (Authelia + LLDAP + privacyIDEA) at
`https://kc.coulomb.social`. No Keycloak Deployment exists. The architecture
doc says expanded mode is capability-driven, chiefly inbound enterprise
federation (Entra ID, AD, SAML), and leaves the per-tenant trigger and
dual-issuer rule open. ADR-0014 defines the `IAM` capability role as a tenant
operating its own dedicated IAM instance. ADR-0006 keeps flex-auth as the PDP.
ADR-0016 makes MFA a user preference with workload opt-in step-up. The user-engine
extension-point doc requires immutable provider subjects, tenant-scoped group
mappings, and no privilege from unmapped upstream claims. The estate is one
node with single-instance databases, so no option here buys HA.
NK-WP-0001 decision D2 (Keycloak as primary internal user store) predates all
of this.
## Decision (proposed)
1. **Trigger.** A tenant moves to expanded mode only when all three hold: a
named tenant, a named owner of the upstream IdP, and a concrete federation
requirement the lightweight stack cannot meet. User count, or the wish to
have Keycloak, is not a trigger. Until then NK-WP-0011 implementation tasks
stay unstarted.
2. **Role: OIDC identity broker only.** Keycloak brokers upstream Entra ID
(OIDC), AD (LDAP federation) and generic SAML 2.0 IdPs (SAML as an
upstream, via Keycloak's identity-provider brokering). Downstream it issues
only IAM Profile OIDC/PKCE tokens. Emitting SAML assertions to downstream
applications is out of scope. Keycloak is not the primary user store
(**supersedes D2**), not the PDP, and not a secret store.
3. **Isolation.** Realms are the tenant boundary. The `tenant:platform` realm
is separate and reserved. A tenant without the `IAM` role gets a realm in
the shared broker; a tenant with the `IAM` role gets a dedicated broker
instance (ADR-0014). A shared broker gives realm-level, not process-level,
isolation, so it is acceptable only for tenants whose federation trust and
data classification allow that. Realm admins may not alter IAM Profile
semantics, the platform realm, federation trust settings, or audit
retention. tenant-engine, not Keycloak, is the source of truth for tenant
existence and capability roles.
4. **Coexistence.** Each tenant has exactly one active issuer at a time,
recorded by tenant-engine and published as issuer configuration. KeyCape
stays unchanged and keeps serving lightweight tenants. Applications target
the IAM Profile and discover the issuer; they do not embed provider
choice. Account bindings remain keyed on issuer plus immutable subject, so
moving a tenant between issuers is a planned migration with an explicit
subject-mapping step, never a silent dual login.
5. **Assurance.** Federated login is AAL1 by default. Upstream MFA (for example
Entra Conditional Access) counts as higher assurance only through a
reviewed, per-IdP trust mapping written down before use. Privileged step-up
continues to use privacyIDEA under ADR-0016 and the proposed IAM v0.4
step-up. The privacyIDEA provider JAR is added only if a tenant needs
Keycloak-side MFA.
6. **Provisioning and mapping.** Follow the user-engine extension-point rules:
JIT creates a pending projection; group mappings are tenant-scoped,
versioned and deny ambiguous envelopes; no platform role from raw upstream
group names.
7. **Hostname and issuer.** Not chosen here. It is assigned by the package
owner under ADR-0015 with the first tenant, as a distinct host from
`kc.coulomb.social`; the issuer URL is then treated as immutable.
8. **Ownership.** net-kingdom owns this contract and conformance checks.
Packaging and runtime belong to the ADR-0015 owner; the database consumer to
railiance-platform; OpenBao roles to railiance-platform.
## Alternatives considered
- **Keycloak replaces KeyCape.** Rejected: unnecessary migration risk for
working tenants; contradicts capability-driven adoption.
- **Dedicated instance for every federated tenant.** Strongest isolation, but on
one node the cost is multiplied database, memory and patching for tenants
that do not need it. Kept for `IAM`-role tenants.
- **Realm-per-tenant only, including `IAM` tenants.** Contradicts ADR-0014's
meaning of `IAM`.
- **Keycloak as SAML IdP downstream too.** No consumer requires it; widens the
contract surface. Revisit on a named need.
- **Trust upstream MFA claims by default.** Rejected: assurance would depend on
each customer's tenant configuration.
- **Build ahead of demand.** Rejected: adds an issuer, a database and a
break-glass path with no owner or user.
## Consequences
- NK-WP-0011 T02 onward stay gated on the trigger in decision 1.
- T06 conformance uses `tools/iam-profile-conformance/` against IAM v0.3.
- tenant-engine needs an issuer-per-tenant field; this is a dependency to
raise with its owner, not something built here.
- Shared-broker realms cannot be described as strongly isolated tenants.
- No HA is implied; T02 and T08 must name backup ownership, off-host custody
and an isolated restore proof.
## Open questions
- Which named tenant and IdP owner will trigger the first deployment?
- Does key-cape require changes for issuer-per-tenant discovery (EP-NK-001)?
- Which claim carries the federated-assurance mapping so flex-auth can consume it?