From 3a4fd38c009480c28d55e6410818ed8bd3aa4a9d Mon Sep 17 00:00:00 2001 From: tegwick Date: Wed, 9 Sep 2026 02:18:12 +0200 Subject: [PATCH] docs: close live approval service registration gate Assistant: codex Assistant-Model: gpt-5.6-luna Assistant-Session: 01a07ff8-19d0-7820-b4d0-1353833cb7fc --- docs/approval-clients-rollout.md | 117 +++------- ...2026-09-09-keycape-verifier-admission.json | 220 ++++++++++++++++++ ...-0013-approval-engine-resource-audience.md | 21 +- 3 files changed, 275 insertions(+), 83 deletions(-) create mode 100644 docs/evidence/2026-09-09-keycape-verifier-admission.json diff --git a/docs/approval-clients-rollout.md b/docs/approval-clients-rollout.md index 7283b46..08b3e12 100644 --- a/docs/approval-clients-rollout.md +++ b/docs/approval-clients-rollout.md @@ -1,89 +1,42 @@ -# Approval service clients: prepared rollout +# Approval service clients: live rollout accepted -`KEY-WP-0013-T02/T06`, 2026-09-08. Prepared candidate; **not deployed**. +KEY-WP-0013-T02 is complete on 2026-09-09. Both verifier-side credential requests, +CCR-2026-0017 and CCR-2026-0018, have explicit user approval as platform operator +and KeyCape owner and are now verified. [Live receipt](evidence/2026-09-09-keycape-verifier-admission.json). -The implementation and verification correction are published at `dcebd46`. -Forgejo's image is `main-dcebd46`, with immutable manifest digest -`sha256:7ff54c54e63ee172ae9e6e7fd2da96e427352f712343d74626ee6fe0f6f82611`. -The complete Go suite and `go vet ./...` passed. The registry image was pulled -by digest and its `/keycape verify-client --help` command enumerated the expected -verification options (the Go flag help path exits 1). The verifier is a keycape -subcommand, not a separate `/verify-client` executable. No live credential was -used in these checks. +Both clients run on one ready KeyCape replica using the immutable image +`forgejo.coulomb.social/coulomb/key-cape@sha256:7ff54c54e63ee172ae9e6e7fd2da96e427352f712343d74626ee6fe0f6f82611`. +NetKingdom owns the deployed manifest, `Recreate` strategy, `/readyz` readiness, +and exact client registrations. Both ESO-owned Secrets are synchronized from +OpenBao version 1. The signing key and unrelated configuration bytes are preserved. -Negative evidence now requires the exact token endpoint, issuer error and -feature: scope rejection is HTTP 400 / `invalid_profile_usage` / `scope`; -predecessor rejection is HTTP 401 / `invalid_profile_usage` / `Authorization`. -A timeout, server error, invalid token, JWKS failure or unrelated refusal fails -verification. Provider response bodies and tokens are never printed. +Both clients passed the native verifier from that pinned image and independent +RS256/JWKS verification with exact issuer, audience, subject, tenant, roles, +scopes and a 900-second lifetime. Wrong secrets and excess scopes were refused; +the human OpenBao client was refused `approval:consume`. Existing human OpenBao +login passed before and after cutover, with attended sessions self-revoked. -## Admission inputs +The deployment owner exercised compatible rollback and version-preserving +resume. Its executable procedure and reproducible synthetic HTTPS exercise live +in `net-kingdom:sso-mfa/k8s/keycape/`, documented in +`net-kingdom:docs/keycape-approval-clients-rollout.md`. The verifier runs inside +the existing attended owner process; credentials stay in memory and a child +environment. The pod's internal-only egress policy remains unchanged. -1. Platform `CCR-2026-0017` and `CCR-2026-0018` remain proposed. Their named - platform-operator and key-cape-owner reviews precede any activation. - [provisioning request](approval-engine-provisioning-request.yaml) records the - exact paths, `CLIENT_SECRET` field and Kubernetes/env mappings. -2. The actual signed upstream issuer is now proved as - **`https://auth.coulomb.social`** by the admitted one-shot probe on 2026-09-08 - at 21:44:44 UTC. Signature, audience, validity window and nonce passed; the - Job exited 0 and every temporary resource was removed. See - [the live receipt](evidence/2026-09-08-upstream-issuer-live-proof.json). - NetKingdom pinned that exact value in `authelia.issuer` on 2026-09-09 - through its exercised issuer-only helper; Secret revision `58713343`. - [Pin receipt](evidence/2026-09-09-upstream-issuer-pin.json) proves all other - config bytes and Secret data unchanged. The running Deployment was unchanged. Prove an existing - human login before and after cutover; the probe established upstream identity - only, while this image also changes redirect and grant binding. -3. The platform-owned attended first-provision command uses only - `warden access openbao-platform-admin-login --exec -- ` - with its unique metadata-only receipt. It must follow the two CCRs and the - platform rollout document. Do not execute the child directly. The unrelated - interim credential proxy's explicit policy 403 remains WARDEN-WP-0039-T03; - an outage fallback is not permission to get credentials for this rollout. +Containerd readiness matches the manifest in `imageID`. Independent JWT checks +use the native contract's 30-second future-iat bound while retaining strict +not-before and expiry. Natural JWT expiry and actual predecessor rotation were +not exercised by this initial provision and remain required for their relevant +subsequent owner acceptance. -## Prepared deployment change +The original [candidate patch](approval-clients-deployment.patch.yaml) remains a +preparation reference; NetKingdom's manifest is deployment authority. Candidate +Go tests and vet passed previously; this window added eight real local OpenBao +checks, ten configuration/recovery/clock checks, 53 credential-change regressions, +and a complete pinned-image HTTPS/native-verifier exercise with synthetic keys. -[approval-clients-deployment.patch.yaml](approval-clients-deployment.patch.yaml) -is a strategic merge patch for `sso/keycape`, whose deployment source remains -`net-kingdom/sso-mfa/k8s/keycape/deployment.yaml`. Transfer the reviewed changes -into that owning source at the admitted cutover; this file is a preparation, -not a second deployment authority. - -It pins the image, adds the two exact Secret references and uses `/readyz` for -traffic readiness while retaining `/healthz` for liveness. `Recreate` ensures -one issuer instance during replacement: [operations.md](operations.md) states -that login sessions and authorization codes are process-local. The old manifest's -default rolling surge can briefly create two instances. Expect a short login -interruption and loss of in-flight login sessions during replacement. - -Apply the platform policies/roles, CAS=0 initial custody, two stores and two -ExternalSecrets in their owner-prescribed order; require Valid/SecretSynced -before deploying the reading image and updated client config together. Do not -pre-create ESO-owned Secrets. A dry-run of this patch proves API acceptance of -the object shape only; it cannot prove the referenced Secrets or configuration. - -## Acceptance and rollback - -Run the two `verify-client` commands from the provisioning request through the -admitted protected delivery. In addition to the tool's checked signature, -issuer, audience, subject, tenant, scopes and required roles, record independent -verification of the exact role set and `exp - iat = 900`: the tool's -`expect-roles` checks inclusion and does not itself establish the 15-minute -lifetime. Initial provisioning has no real predecessor to revoke; test a wrong -secret and retain predecessor rejection for an actual subsequent rotation. -Retain expiry/revocation and excessive-scope evidence, and platform cross-path, -wrong-service-account, outside-namespace and parent-listing denials. - -Before mutation the deployment/configuration owner retains the previous image, -configuration revision and Secret metadata through its protected recovery path. -On failed readiness or existing-human-login regression, restore that compatible -configuration/image pair (`main-153258b` is the observed prior image), then -follow the platform document's ExternalSecret/policy rollback. An image-only -revert does not restore the changed client configuration. Keep custody versions -until registrations are explicitly disabled; never destroy as incidental cleanup. - -These CCRs supply **verifier-side copies only**. Client-side read lanes, the -approval audit sender credential and live claim/consume proof remain open in -RPF-WP-0035-T05, AUDIT-WP-0009-T09, APPROVAL-WP-0002 and GLAS-WP-0015's -existing coordination chain. The human UI's real callback and MFA proof remain -KEY-WP-0013-T05; they do not block these independent service registrations. +KEY-WP-0013-T05 retains the real approval UI callback and MFA/PKCE proof. +RPF-WP-0035-T05 retains separate client-side credential delivery; AUDIT-WP-0009-T09 +retains audit custody. APPROVAL-WP-0002 and SECRETS-WP-0009-T03 retain deployed +claim/consume, expiry/revocation and native credential delivery. These verifier +copies do not grant client retrieval or factory execution/spending. diff --git a/docs/evidence/2026-09-09-keycape-verifier-admission.json b/docs/evidence/2026-09-09-keycape-verifier-admission.json new file mode 100644 index 0000000..6ae6fc7 --- /dev/null +++ b/docs/evidence/2026-09-09-keycape-verifier-admission.json @@ -0,0 +1,220 @@ +{ + "schema": "helixforge.keycape-verifier-admission.v1", + "recorded_at": "2026-09-09T00:14:27.155338+00:00", + "approval": { + "schema": "railiance.keycape-custody-user-approval.v1", + "recorded_at": "2026-09-08T23:05:19.886216+00:00", + "user_response": "I approve, go on.", + "approved_question": "Do you approve CCR-2026-0017 and CCR-2026-0018, as platform operator and KeyCape owner, for the verifier-side credential delivery described in the review packet?", + "review_packet_revision": "52b24eab9a8aff3396e71b2296d0240a44f3b0db", + "roles": [ + "platform-operator", + "key-cape-owner" + ], + "scope": "Two verifier-side KeyCape client credential custody requests, including their governed attended provisioning and compatible rollout sequence.", + "client_side_read_authorized": false, + "factory_spending_authorized": false, + "requests": [ + { + "id": "CCR-2026-0017", + "decision_id": "b533a271-b704-4c5c-98a2-9a5951aadfb6", + "status": "approved", + "decision_status": "resolved", + "reviewed_roles": [ + "platform-operator", + "key-cape-owner" + ] + }, + { + "id": "CCR-2026-0018", + "decision_id": "efa90517-0cae-4eb6-a68d-5b0489c84d65", + "status": "approved", + "decision_status": "resolved", + "reviewed_roles": [ + "platform-operator", + "key-cape-owner" + ] + } + ] + }, + "activation": { + "schema": "platform.keycape-approval-custody.v1", + "status": "custody_and_service_acceptance_passed_pending_fresh_human_login", + "lanes": [ + { + "ccr": "CCR-2026-0017", + "source_sha256": "dc2bbd86e213edecc2f2f91a99d0f51136e9a0853a90e55f65dda2b942305416", + "custody_seeded": false, + "existing_version_reused": true, + "kv_version": 1, + "initial_request_id": "94c98373-33fa-591d-c201-d36dddf9879b", + "policy_applied": false, + "role_applied": true, + "native_reader_verified": true, + "cross_path_denied": true, + "parent_listing_denied": true, + "auth_ttl": 900, + "reader_revocation_verified": true, + "wrong_service_account_denied": true, + "coding_agent_deny_wins": true, + "store_ready": true, + "external_secret_ready": true, + "delivery_matches": true, + "secret_uid": "eaa28bdf-04af-4e4e-a1fc-fe395c7689a7", + "secret_resource_version": "58747058", + "wrong_namespace_denied": true, + "outside_namespace_store_denied": true + }, + { + "ccr": "CCR-2026-0018", + "source_sha256": "99148133ddf1eb15dce3c03862b51dc001818ca3121045035a0b0e5897c55dad", + "custody_seeded": false, + "existing_version_reused": true, + "kv_version": 1, + "initial_request_id": "a62ee5c5-b5ba-b7dc-0f51-e6fd8a6dde32", + "policy_applied": false, + "role_applied": true, + "native_reader_verified": true, + "cross_path_denied": true, + "parent_listing_denied": true, + "auth_ttl": 900, + "reader_revocation_verified": true, + "wrong_service_account_denied": true, + "coding_agent_deny_wins": true, + "store_ready": true, + "external_secret_ready": true, + "delivery_matches": true, + "secret_uid": "599a61a7-8244-4618-8c44-6473195bbe4e", + "secret_resource_version": "58747062", + "wrong_namespace_denied": true, + "outside_namespace_store_denied": true + } + ], + "started_at": "2026-09-09T00:09:28.852280+00:00", + "credential_values_emitted": false, + "client_side_read_admitted": false, + "keycape_rollout_completed": true, + "issuer_pin_revision": "58746187", + "phase": "awaiting_fresh_human_login", + "custody_versions_unchanged": true, + "namespace_probe_cleanup_requested": true, + "keycape": { + "existing_human_login_before": true, + "protected_recovery_retained": true, + "deployment_uid": "99ddd83c-cb3f-4847-bcf8-35f1aa87627f", + "generation": 38, + "pod_uid": "8d62e972-d466-413e-a2e4-08b9a08016bc", + "single_ready_replica": true, + "acceptance_phase": "passed", + "clients": [ + { + "client_id": "secrets-engine-approval", + "live_jwks_signature_verified": true, + "exact_claims_verified": true, + "lifetime_seconds": 900, + "maximum_future_iat_seconds": 30, + "expiry_leeway_seconds": 0, + "excess_scope_denied": true, + "wrong_secret_denied": true, + "pinned_artifact_verifier_passed": true, + "verifier_location": "attended owner process", + "verifier_sha256": "4bf93bbe9afe0bf2e21d51c03373a7e2b4be6864586bcc2d472eeb9abc913d92", + "real_predecessor_rotation_tested": false, + "observed_wall_clock_expiry": false + }, + { + "client_id": "approval-engine-operator", + "live_jwks_signature_verified": true, + "exact_claims_verified": true, + "lifetime_seconds": 900, + "maximum_future_iat_seconds": 30, + "expiry_leeway_seconds": 0, + "excess_scope_denied": true, + "wrong_secret_denied": true, + "pinned_artifact_verifier_passed": true, + "verifier_location": "attended owner process", + "verifier_sha256": "4bf93bbe9afe0bf2e21d51c03373a7e2b4be6864586bcc2d472eeb9abc913d92", + "real_predecessor_rotation_tested": false, + "observed_wall_clock_expiry": false + } + ], + "acceptance_client": "approval-engine-operator", + "human_client_consume_denied": true, + "status": "service_acceptance_passed_pending_fresh_human_login", + "image": "forgejo.coulomb.social/coulomb/key-cape@sha256:7ff54c54e63ee172ae9e6e7fd2da96e427352f712343d74626ee6fe0f6f82611", + "config_resource_version": "58747126", + "signing_key_unchanged": true, + "unrelated_config_bytes_preserved": true, + "existing_human_login_after": false + }, + "finished_at": "2026-09-09T00:10:09.099481+00:00" + }, + "post_rollout_login": { + "schema": "netkingdom.keycape-approval-rollout.v1", + "status": "service_and_existing_human_login_acceptance_passed", + "values_emitted": false, + "deployment_uid": "99ddd83c-cb3f-4847-bcf8-35f1aa87627f", + "generation": 38, + "pod_uid": "8d62e972-d466-413e-a2e4-08b9a08016bc", + "single_ready_replica": true, + "acceptance_phase": "passed", + "clients": [ + { + "client_id": "secrets-engine-approval", + "live_jwks_signature_verified": true, + "exact_claims_verified": true, + "lifetime_seconds": 900, + "maximum_future_iat_seconds": 30, + "expiry_leeway_seconds": 0, + "excess_scope_denied": true, + "wrong_secret_denied": true, + "pinned_artifact_verifier_passed": true, + "verifier_location": "attended owner process", + "verifier_sha256": "4bf93bbe9afe0bf2e21d51c03373a7e2b4be6864586bcc2d472eeb9abc913d92", + "real_predecessor_rotation_tested": false, + "observed_wall_clock_expiry": false + }, + { + "client_id": "approval-engine-operator", + "live_jwks_signature_verified": true, + "exact_claims_verified": true, + "lifetime_seconds": 900, + "maximum_future_iat_seconds": 30, + "expiry_leeway_seconds": 0, + "excess_scope_denied": true, + "wrong_secret_denied": true, + "pinned_artifact_verifier_passed": true, + "verifier_location": "attended owner process", + "verifier_sha256": "4bf93bbe9afe0bf2e21d51c03373a7e2b4be6864586bcc2d472eeb9abc913d92", + "real_predecessor_rotation_tested": false, + "observed_wall_clock_expiry": false + } + ], + "acceptance_client": "approval-engine-operator", + "human_client_consume_denied": true, + "existing_human_login_after": true, + "receipt_written_at": "2026-09-09T00:11:59.113549+00:00" + }, + "attended_envelope": { + "all_attempted_sessions_revoked": true, + "successful_activation_exit_code": 0, + "post_rollout_login_exit_code": 0 + }, + "validation": { + "local_openbao_tests": 8, + "configuration_and_recovery_tests": 10, + "credential_change_tests": 53, + "pinned_image_synthetic_https_and_native_verifier": "passed" + }, + "failed_attempt_receipts": [ + "net-kingdom:docs/evidence/2026-09-09-keycape-activation-attempts.json" + ], + "limits": { + "client_side_read_admitted": false, + "factory_spending_admitted": false, + "wall_clock_jwt_expiry_observed": false, + "actual_predecessor_rotation_observed": false + }, + "temporary_probe_namespaces_remaining": 0, + "owner_manifest_api_defaults_match_live": true +} diff --git a/workplans/KEY-WP-0013-approval-engine-resource-audience.md b/workplans/KEY-WP-0013-approval-engine-resource-audience.md index 718cb48..4e35ec8 100644 --- a/workplans/KEY-WP-0013-approval-engine-resource-audience.md +++ b/workplans/KEY-WP-0013-approval-engine-resource-audience.md @@ -36,7 +36,7 @@ including grants removed after authorization. ```task id: KEY-WP-0013-T02 -status: wait +status: done priority: high state_hub_task_id: "607897c5-bad9-55e5-86df-7802f592d6e8" ``` @@ -148,6 +148,25 @@ image rollout, custody activation or downstream login proof occurred. T02 stays wait for the named CCR reviews, attended custody and compatible rollout. The single-instance replacement and existing-human-login checks remain mandatory. +2026-09-09 completion: both named CCR reviews are recorded. Verifier-side custody, +ESO delivery and the compatible pinned image/config are now live. Both service +clients passed the pinned verifier plus independent live signature and exact +claim/lifetime checks; wrong-secret and excess-scope requests were rejected. +The existing OpenBao human login passed before and after replacement; each +attended session self-revoked. Receipt: `docs/evidence/2026-09-09-keycape-verifier-admission.json`. + +The deployment owner exercised compatible rollback and version-preserving resume. +The final helper checks containerd imageID against the pinned manifest and uses +the existing 30-second future-iat bound without extending token expiry. The +pinned native verifier runs in the contained owner process because workload +network policy excludes public issuer HTTPS. No network grant was broadened. + +Live residual ownership remains KEY-WP-0013-T05 for the approval UI callback/MFA; +RPF-WP-0035-T05 for separate client-side delivery; AUDIT-WP-0009-T09 for audit +custody; APPROVAL-WP-0002 and SECRETS-WP-0009-T03 for end-to-end claim/consume, +expiry/revocation and native delivery. Natural JWT expiry and real predecessor +rotation were not exercised by initial provisioning. + ## Reconcile tenant vocabularies across approval layers ```task