Declare key-cape.oidc-client-registration; add KEY-WP-0038-T04 entry point

Playbook capability (contract PASS, maturity planned) composed by net-kingdom's
SecurityCaseType oidc-browser-relying-party. T04 implements tools/keycape-client,
generalizing the per-client rollout helpers.

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

Assistant: claude-code
Assistant-Model: opus
Assistant-Process: 5457@bnt-lap001
Assistant-Session: 792bf84a-3783-4f5d-a811-cded61dd2012
This commit is contained in:
tegwick 2026-10-08 22:44:43 +02:00
parent d8f3668a18
commit c737e361ce
2 changed files with 154 additions and 0 deletions

View file

@ -0,0 +1,125 @@
apiVersion: netkingdom.io/playbook-capability/v0.1
kind: PlaybookCapabilityDeclaration
metadata:
id: key-cape.oidc-client-registration
name: KeyCape OIDC client registration
owner: key-cape
repo: key-cape
domain: infotech
contract_version: "0.1"
source_links:
- label: Client field rules
path: spec/canonical-model.yaml
- label: First case request (Forgejo)
path: docs/forgejo-oidc-client-request.yaml
- label: Workplan
path: workplans/KEY-WP-0038-forgejo-oidc-client.md
spec:
playbook:
path: tools/keycape-client/
type: cli-sequence
invocation: keycape-client register --client-file <rendered-client.yaml>
description: >-
Idempotently add, update or remove exactly one client in the running
KeyCape client registry, without exporting secret values. Generalizes the
per-client helpers in net-kingdom sso-mfa/k8s/keycape (register-coulomb-social,
portal-client-rollout, vergabe-client-rollout, secrets-engine-openbao-client-rollout).
Modes: inspect, dry-run, apply, remove.
capabilities:
- id: c1.lightweight-sso
tier: C1
resource_kinds:
- identities
- roles_scopes_policies
description: Register one OIDC relying party (browser or service) with the running lightweight issuer.
parameters:
- name: client_id
type: string
required: true
constraints:
pattern: ^[a-z0-9][a-z0-9-]{1,62}$
sensitivity: operational
tuning_authority: netkingdom_tunable
description: OAuth2 client_id, unique in the registry.
- name: display_name
type: string
required: true
constraints:
pattern: ^[^\n\r]{1,80}$
sensitivity: public
tuning_authority: netkingdom_tunable
description: Human-readable client name shown at sign-in.
- name: redirect_uris
type: string
required: true
constraints:
pattern: ^https://[^*\s,]+(,https://[^*\s,]+)*$
sensitivity: security_sensitive
tuning_authority: netkingdom_tunable
description: Comma-separated exact redirect URIs; wildcards are never accepted.
- name: allowed_scopes
type: string
required: true
constraints:
pattern: ^openid(,(profile|email|groups))*$
sensitivity: security_sensitive
tuning_authority: netkingdom_tunable
description: Comma-separated scopes the client may request; openid first.
- name: client_type
type: string
required: true
constraints:
pattern: ^(confidential|public)$
sensitivity: security_sensitive
tuning_authority: netkingdom_tunable
description: confidential (server-side, holds a secret) or public (PKCE only).
- name: mfa_required
type: string
required: true
constraints:
pattern: ^(true|false)$
sensitivity: security_sensitive
tuning_authority: netkingdom_tunable
description: Pin MFA on this client instead of relying on the provider default.
- name: secret_ref
type: string
required: false
constraints:
pattern: ^bao:[a-z0-9/_-]+$
sensitivity: secret_reference
tuning_authority: netkingdom_tunable
description: Custody reference for a confidential client's secret, omitted for public clients; the registry reads the value from custody, never from the request.
responsibilities:
- resource_kind: identities
owner: key-cape
resources:
- oidc:static-clients
repo_owns: Registry change for exactly this client, field validation (KEY-WP-0028 rules), idempotency and removal.
netkingdom_orchestrates: Supply the case's validated, non-secret client fields.
- resource_kind: roles_scopes_policies
owner: key-cape
resources:
- iam-profile:client-scope-allowlists
repo_owns: Enforce exact redirect URIs, allowed scopes and the MFA pin at authorization time.
netkingdom_orchestrates: Choose scopes and MFA posture per SecurityCaseType.
trust:
requires:
- state: runtime_secret_trust
readiness_checks: []
- state: runtime_identity_trust
readiness_checks: []
satisfies:
- state: tenant_onboarding_trust
readiness_checks:
- id: client-authorize-accepts-registered-redirect
description: The authorization endpoint accepts the client with each registered redirect URI.
evidence: GET /authorize with client_id and each redirect_uri returns the login page, not an error.
- id: client-authorize-refuses-other-redirect
description: The authorization endpoint refuses an unregistered redirect URI for the client.
evidence: GET /authorize with an unregistered redirect_uri returns an OAuth error.
catalog:
publish: capabilities/playbooks/key-cape.oidc-client-registration.yaml
maturity: planned
consumers:
- netkingdom-security-scenario-composer
- netkingdom-security-case-types

View file

@ -140,3 +140,32 @@ all, or receive scoped Forgejo tokens bound to a NetKingdom service identity
Acceptance: evidence for all three principals; the agent and service decision is
recorded. Then hand over to RAPPS-WP-0016.
```task
id: KEY-WP-0038-T04
status: todo
priority: high
```
### T04 — Implement the `keycape-client` entry point
`capabilities/playbooks/key-cape.oidc-client-registration.yaml` (contract PASS,
`maturity: planned`) declares client registration as a playbook capability, so
that the SecurityCaseType `oidc-browser-relying-party` (net-kingdom NK-WP-0048)
can compose it. Implement the entry point it names, `tools/keycape-client/`:
- `keycape-client register --client-file <rendered-client.yaml>` with modes
`inspect`, `dry-run`, `apply` and `remove`; adds, updates or removes exactly one
client in the live registry; idempotent; never prints or writes secret values;
a confidential client's secret is read from its custody reference
- one implementation replacing the per-client helpers in net-kingdom
`sso-mfa/k8s/keycape/` (register-coulomb-social, portal-client-rollout,
vergabe-client-rollout, secrets-engine-openbao-client-rollout), keeping their
safeguards (byte-preserving merge, compare-and-swap, cluster pin, safe receipts)
and their tests as regression cases
- client field validation by the KEY-WP-0028 rules
- then set the declaration's `maturity` to `implemented`
Longer term, loading clients from a non-secret registry with secrets referenced
from custody would remove the type's only attended step (see the type README,
"Attended steps").