net-kingdom/docs/adr/ADR-0017-root-grant-custody-and-account-authority.md
tegwick de4c4f84f5
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 3s
Accept root grant ADR and approved OpenBao delivery design
Assistant: codex
Assistant-Model: gpt-6.1-sol
Assistant-Session: 01a1029d-2c93-7500-a0e0-e3e089668b29
2026-10-03 19:01:13 +02:00

5.3 KiB

id type title status owner revision decided last_reviewed review_interval
NK-ADR-0017 architecture-decision-record The Root Grant Is Derived From the Custody Record, Scoped to tenant:platform, and Observed as Non-Secret Evidence accepted net-kingdom 2 2026-10-03 2026-10-03 12m

ADR-0017 - Root-Grant Custody and Account Authority

Status: Accepted by Bernd Worsch on 2026-10-03; user-engine mapping confirmed. Date: 2026-10-03 (drafted 2026-09-29) Decider: Bernd Worsch

Context

user-engine implemented account.authority.read (USER-WP-0037-T01) and a workload-authenticated lookup endpoint. It will not derive AccountAuthority.root-grant from JWT roles, a username, or a consumer's configured root subject, and USER-WP-0037-T02 is blocked on NetKingdom specifying the authority. docs/platform-root-custody.md covers custody of the platform-root credential and OpenBao material, but not how a workload-facing "subject X holds the root grant" fact is derived, revoked, or evidenced.

Decision

1. Authority: the custody record; directory membership is a projection

The platform-root custody record (the non-secret ceremony record: custodian assignment, quorum plan, root-token disposition, signoff) is the single authority for who holds the root grant.

  • A root grant exists for a subject only while a custody record names that (issuer, subject) as king/platform-root custodian and no later record revokes it.
  • LLDAP platform-root membership and IAM claims (groups: platform-root, roles: platform-root-custodian) are projections of the record. They are authentication facts and MUST NOT be used alone to derive a root grant.
  • Revocation is a recorded custody action: a new record entry that supersedes the grant, with actor, reason, and time. Revocation must not remove recovery authority (break-glass under king custody stays intact).
  • If the record and a projection disagree, the record wins and the mismatch is a posture finding, not a grant.

2. Mapping: platform:root grants tenant:platform only

  • A root grant is expressed as relation platform-root-custodian in tenant context tenant:platform. It is scoped to the platform control plane.
  • It is never inherited by, or implied for, any other tenant, and tenant admin authority never implies it (consistent with the user-engine boundary contract and IAM Profile v0.3).
  • The grant is a distinct grant type in the membership envelope (scope_type: tenant, scope_id: platform, relation: platform-root-custodian, owner_system: net-kingdom-custody). Consumers such as the Hub read it from user-engine; they do not mint it.

3. Evidence: non-secret observations with explicit freshness

An account/entitlement observation retained by a consumer contains only: subject (issuer, subject), grant, source (custody record id and revision), observed_at, and revoked_at or expires_at when known. It never contains tokens, keys, unseal shares, recovery codes, or reset links.

  • Observations are read models: they carry observed_at and are re-derived from the custody record rather than treated as durable truth.
  • A consumer MAY cache an observation for at most 15 minutes; sensitive platform actions (root-grant-dependent writes) MUST re-check and fail closed when the record cannot be read or the observation is stale.
  • Revocation takes effect at the next re-check; the cache bound is the maximum revocation latency.

Consequences

  • user-engine can represent AccountAuthority.root-grant deterministically from the custody record id and revision, and unblocks USER-WP-0037-T02.
  • The custody record needs a machine-readable, non-secret form that a workload can read. Its schema and OpenBao delivery design are approved; until the owner delivers the live read path, user-engine returns "no root grant" rather than inferring one.
  • The 15-minute bound and the projection-versus-record rule are decisions of this ADR and may be tightened at review.

Delivery design and approval receipt

Bernd explicitly approved: “Accept ADR-0017 and approve the proposed OpenBao delivery design.” Scoped State Hub decision: c2cff929-91b9-4018-bfd6-fa04f7da8280. The separate MFA journey in bundled D10 remains pending.

  • Delivery owner: railiance-platform, RPF-WP-0049.
  • OpenBao KV v2 mount platform; API path /v1/platform/data/custody/net-kingdom/platform-root.
  • Record nk-custody:platform-root, owner net-kingdom-custody; complete document at response data.data.document. KV metadata version is concurrency state, distinct from custody revision.
  • user-engine is the authenticated exact-path read-only consumer. Custody writes use a separate attended human lane. The actual workload identity and writer binding must be established through their owner routing procedures.
  • Read contract and canon/schemas/custody-record_v0.1.schema.json define the document and checks. user-engine confirmed the membership-envelope mapping (message 60acf176).

Design approval does not establish live admission or a real custody entry. Remaining delivery work: real reader identity, reviewed attended executor, recovery/audit configuration, bounded live provisioning approval and genuine ceremony provenance, followed by producer and consumer acceptance receipts.