apiVersion: netkingdom.io/playbook-capability/v0.1 kind: PlaybookCapabilityDeclaration metadata: id: net-kingdom.keycape-client-registration name: KeyCape OIDC client registration (live registry) owner: net-kingdom repo: net-kingdom domain: infotech contract_version: "0.1" source_links: - label: Entry point path: sso-mfa/k8s/keycape/keycape-client.py - label: Tests path: sso-mfa/k8s/keycape/test_keycape_client.py - label: SecurityCaseType path: security-case-types/oidc-browser-relying-party/type.yaml spec: playbook: path: sso-mfa/k8s/keycape/keycape-client.py type: cli-sequence invocation: keycape-client.py apply --client-file --case-acceptance --expected-uid --expected-resource-version description: >- Add or remove exactly one client in the live KeyCape client registry without exporting secret values: contained kubectl, cluster and issuer pins, byte-preserving merge, compare-and-swap, read-back. Replaces the per-client helpers beside it. Field rules follow key-cape's canonical model (KEY-WP-0028). Modes: inspect, dry-run, apply; operations add and remove. capabilities: - id: c1.lightweight-sso tier: C1 resource_kinds: - identities - roles_scopes_policies description: Register one OIDC relying party 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. responsibilities: - resource_kind: identities owner: net-kingdom resources: - oidc:static-clients repo_owns: Live registry change for exactly this client, its idempotency and removal; field rules are key-cape's canonical model. 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/net-kingdom.keycape-client-registration.yaml maturity: implemented consumers: - netkingdom-security-scenario-composer - netkingdom-security-case-types