From f6856cdb53c051e35c984bad927395b7e8a8e5e0 Mon Sep 17 00:00:00 2001 From: tegwick Date: Sun, 11 Oct 2026 08:56:45 +0200 Subject: [PATCH] Record founder source acknowledgment for isolated Forgejo type 1.2 Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a126e1-76f8-7643-8cf3-e93336539ade --- .../native-authoring-receipt.json | 1 + .../native-outcome.json | 1 + .../recording-validation.json | 18 + ...e12-source-acknowledgment-followthrough.md | 39 ++ ...-type12-source-recording-owner-review.json | 32 ++ .../1.2/oidc-browser-relying-party/README.md | 54 +++ .../decision/acknowledgment.json | 79 ++++ .../examples/example-public-portal.yaml | 20 + .../examples/forgejo.yaml | 21 + .../tests/test_source_contract.py | 88 ++++ .../1.2/oidc-browser-relying-party/type.yaml | 442 ++++++++++++++++++ workplans/ADHOC-2026-10-11.md | 15 + workplans/NK-WP-0048-security-case-types.md | 51 +- 13 files changed, 859 insertions(+), 2 deletions(-) create mode 100644 docs/evidence/2026-10-11-forgejo-type12-source-acknowledgment/native-authoring-receipt.json create mode 100644 docs/evidence/2026-10-11-forgejo-type12-source-acknowledgment/native-outcome.json create mode 100644 docs/evidence/2026-10-11-forgejo-type12-source-acknowledgment/recording-validation.json create mode 100644 docs/forgejo-type12-source-acknowledgment-followthrough.md create mode 100644 docs/reviews/2026-10-11-forgejo-type12-source-recording-owner-review.json create mode 100644 security-case-type-revisions/1.2/oidc-browser-relying-party/README.md create mode 100644 security-case-type-revisions/1.2/oidc-browser-relying-party/decision/acknowledgment.json create mode 100644 security-case-type-revisions/1.2/oidc-browser-relying-party/examples/example-public-portal.yaml create mode 100644 security-case-type-revisions/1.2/oidc-browser-relying-party/examples/forgejo.yaml create mode 100644 security-case-type-revisions/1.2/oidc-browser-relying-party/tests/test_source_contract.py create mode 100644 security-case-type-revisions/1.2/oidc-browser-relying-party/type.yaml diff --git a/docs/evidence/2026-10-11-forgejo-type12-source-acknowledgment/native-authoring-receipt.json b/docs/evidence/2026-10-11-forgejo-type12-source-acknowledgment/native-authoring-receipt.json new file mode 100644 index 0000000..3161c31 --- /dev/null +++ b/docs/evidence/2026-10-11-forgejo-type12-source-acknowledgment/native-authoring-receipt.json @@ -0,0 +1 @@ +{"memo_id": "infd-20261011-forgejo-type12-source-r1", "version": 1, "register_event_id": "66d85468-6cd9-4a40-8c35-febc152758c0", "revision_event_id": null, "publication_event_id": "cbe4a05f-c7ab-4770-8e6e-8b537b165f7e", "review_event_id": "5be59cf9-a207-43aa-9fe2-131dc1e53538", "review_memo_id": "review-126c6c90-11ba-4609-b8d1-75e054c246cd", "queue_status": "pending", "queue_detail": "queued", "workspace_url": "https://decisions.coulomb.social/decisions/infd-20261011-forgejo-type12-source-r1?version=1", "outcome_review": {"intake_state": "not_submitted", "memo_id": "review-126c6c90-11ba-4609-b8d1-75e054c246cd", "stale": false}, "human_dispositions": 0} diff --git a/docs/evidence/2026-10-11-forgejo-type12-source-acknowledgment/native-outcome.json b/docs/evidence/2026-10-11-forgejo-type12-source-acknowledgment/native-outcome.json new file mode 100644 index 0000000..34256f5 --- /dev/null +++ b/docs/evidence/2026-10-11-forgejo-type12-source-acknowledgment/native-outcome.json @@ -0,0 +1 @@ +{"memo_id": "infd-20261011-forgejo-type12-source-r1", "review": {"intake_state": "ready", "memo_id": "review-126c6c90-11ba-4609-b8d1-75e054c246cd", "path": "/review?memo_id=review-126c6c90-11ba-4609-b8d1-75e054c246cd", "stale": false}, "disposition_count": 1, "dispositions": [{"id": null, "approval_id": null, "submission_state": "confirmed", "disposition": {"actor": {"kind": "person", "sub": "uid=platform-root,ou=people,dc=netkingdom,dc=local"}, "approval_id": "8e9332c8-754a-420c-b8b7-445cb4fe6765", "at": "2026-10-11T06:47:39Z", "id": "disp-315d54ad-20f1-40e6-862c-6c7d2e8f0ea8", "memo_id": "review-126c6c90-11ba-4609-b8d1-75e054c246cd", "memo_version": 1, "note": null, "presentation_id": "pres-5a52f932-8c65-46cc-8054-0264f47f934a", "reasons": [], "verb": "accept"}, "approved_at": "2026-10-11T06:47:39+00:00", "decided_at": null}]} diff --git a/docs/evidence/2026-10-11-forgejo-type12-source-acknowledgment/recording-validation.json b/docs/evidence/2026-10-11-forgejo-type12-source-acknowledgment/recording-validation.json new file mode 100644 index 0000000..80e6060 --- /dev/null +++ b/docs/evidence/2026-10-11-forgejo-type12-source-acknowledgment/recording-validation.json @@ -0,0 +1,18 @@ +{ + "acknowledged_type_sha256": "9e60ff569fb0d860a2bbde7bbb0991a54d4b0688f62b56df0fa5d161fd624578", + "only_type_status_semantic_delta": true, + "full_package_validator_pass": true, + "independent_acknowledged_package_tests_passed": 22, + "closed_schema_checks_pass": true, + "explicit_version_root_loads_exact12": true, + "default11_type_and_case_byte_unchanged": true, + "canonical_case12_proposed_no_acceptance": true, + "ordinary_admission_refused": true, + "full_render_regeneration_identical": true, + "full_render_digest": "sha256:c0afd5576cdae0cbc807eccb2b9fa87ac668f15e32ec7cf79d295bdb23c75b35", + "execution_permitted": false, + "packet_bound_files_mutated": false, + "genuine_native_human_source_accept_confirmed": true, + "human_approval_id": "8e9332c8-754a-420c-b8b7-445cb4fe6765", + "new_native_action_by_worker": false +} diff --git a/docs/forgejo-type12-source-acknowledgment-followthrough.md b/docs/forgejo-type12-source-acknowledgment-followthrough.md new file mode 100644 index 0000000..6a3e118 --- /dev/null +++ b/docs/forgejo-type12-source-acknowledgment-followthrough.md @@ -0,0 +1,39 @@ +# Forgejo type1.2 source acknowledgment and existing implementation gates + +Confirmed human source ACCEPT at2026-10-11T06:47:39Z is recorded separately from +implementation. Exact type package lives at +security-case-type-revisions/1.2/oidc-browser-relying-party/; its external +decision/acknowledgment.json binds actual memo, human actor/disposition, packet, +proposed/acknowledged source hashes and post-anchor review. Type.yaml changes +only semantic status proposed→acknowledged; README history and one test expectation +adapt to the recorded source state. The frozen proposed human packet stays +immutable. Independent acknowledged-package validator and22 tests pass; closed +schema/version load and identical c0afd preparation render are proved. + +Current canonical1.1 package and accepted1.1 case remain unchanged, without +inherited1.2 authority. Current load_type reads one type.yaml per id and requires +exact version, so selecting1.2 as default would break that1.1 case. The explicit +version root loads1.2 through existing --types/--types-root input, only for source +validation/preparation. This record changes no resolver/default, native broker +pin, canonicalcase or adapter. The1.2 reference remains proposed without +acceptance fields; normal admission still refuses acknowledged/unimplemented type. +Separate Apps receipt records only actual human reference-design scope. + +## Actual next source/proof gates in existing work + +| Owner work | Remaining contract and evidence | +| --- | --- | +| NK-WP-0048-T06 / existing ORGREF driver | Deliberately integrate explicit version selection and first-reference source receipts under the accepted lifecycle. Ordinary case acceptance requires implemented type; preparation flags and design receipt are no waiver. Define source bootstrap integration without inventing canonical admission. Type becomes implemented only after materialization/follow-through capability and actual live verified reference proof, with distinct owner acceptance. | +| WARDEN-WP-0044-T03, then T04 | Current case_run.py is a closed local kernel with no installed owner adapters/live CLI dispatch; case_receipt_state.py is a pure/proposed reducer. Need exact owner-acknowledged descriptors/adapters, independently authenticated global provenance verifier, durable attempt/recovery receipts, bounded caller grant/session/source pins and confirmed revocation. No shell/type prose execution, privilege manufacture, native success from local prototype or pending-owner receipt. | +| MASON-WP-0010-T03, then T04 | Current case_structure.py prepares typed evidence requests, not native materialization. Rebuild reviewed source deliberately with exact version/type/case/render and corrected CCR targets; obtain independent authenticated layout/policy/role/catalog observations and created-versus-preexisting ownership/change receipts for all six objects. No mint prerequisite for structural proof and no trusted self-authored JSON acceptance. Preserve old wrong-target bundle refusal. | +| Platform existing CCR-2026-0042 and broker owner path | Reconcile historical/current/proposed body and actual exact SA/namespace/audience/read-only policy; bound claims are still false. Any source broker/case pin adaptation needs exact owner review and source tests, not blanket version bypass. Native apply/capabilities/created-object/issued-token revocation or verified-expiry receipts require separately approved authority. A source role deletion does not revoke issued tokens. | +| NetKingdom/KeyCape registration/group/env owners | Supply exact attended registration/config/group/verify/undo adapters or owner receipt-only steps through existing lanes. Bind registry/environment/groups to reviewed case; do not substitute user-engine runtime identity or give Warden new broad Kubernetes authority. Native unknown outcomes remain unresolved pending owner reconciliation. | +| RAPPS-WP-0016-T02, with its existing T01 prerequisite | Refresh exact ESO/CRD/RBAC/dedicatedSA/no legacy refs and target ownership metadata. Prepare reviewed Helm OIDC secret consumption and group enforcement adapters or receipt-only consumer step; native Store/ExternalSecret Ready is not browser/MFA/group refusal, break-glass/account-link or first-case completion. Shared ESO trust/default workloadSA remain explicit. | + +All created-only undo retains immutable UIDs/ownership and exact source references; +preserve matched/shared resources, revert consumer references first, revoke issued +reader tokens or independently prove expiry before role removal, then policy. +No new login/remint or speculative delete authority follows from this record. +Existing native acceptance and human gates remain in their current owner/project +records. This document adds no broad plan, promoted residual or implementation +permission and marks no existing implementation task done. diff --git a/docs/reviews/2026-10-11-forgejo-type12-source-recording-owner-review.json b/docs/reviews/2026-10-11-forgejo-type12-source-recording-owner-review.json new file mode 100644 index 0000000..e4faf0c --- /dev/null +++ b/docs/reviews/2026-10-11-forgejo-type12-source-recording-owner-review.json @@ -0,0 +1,32 @@ +{ + "reviewer": "net-kingdom-owner (agent net-kingdom, codex)", + "decision": "approved", + "work_item": "NK-WP-ADHOC-2026-10-11-T06", + "comment": "Same NetKingdom source role/trial after actual completedT06 anchor. INTENT Taxonomy and Meta-Orchestration support truthful exact human source acknowledgment recording in explicit version root without default1.1 repoint, package authority inflation or canonicalcase acceptance. Root requesting agent transcribes actual human8e9332c8 disposition; this technical review supplies no founder decision or other owner role.", + "acknowledged_type_sha256": "9e60ff569fb0d860a2bbde7bbb0991a54d4b0688f62b56df0fa5d161fd624578", + "independent_recording_checks": { + "acknowledged_type_sha256": "9e60ff569fb0d860a2bbde7bbb0991a54d4b0688f62b56df0fa5d161fd624578", + "only_type_status_semantic_delta": true, + "full_package_validator_pass": true, + "independent_acknowledged_package_tests_passed": 22, + "closed_schema_checks_pass": true, + "explicit_version_root_loads_exact12": true, + "default11_type_and_case_byte_unchanged": true, + "canonical_case12_proposed_no_acceptance": true, + "ordinary_admission_refused": true, + "full_render_regeneration_identical": true, + "full_render_digest": "sha256:c0afd5576cdae0cbc807eccb2b9fa87ac668f15e32ec7cf79d295bdb23c75b35", + "execution_permitted": false, + "packet_bound_files_mutated": false, + "genuine_native_human_source_accept_confirmed": true, + "human_approval_id": "8e9332c8-754a-420c-b8b7-445cb4fe6765", + "new_native_action_by_worker": false + }, + "completed_actual_anchor_sha256": "b33f203ff9e6318442b04374a5c6c97518097c2c9cad2bc38f65e3e9050f7820", + "canonical_package_type_path": "security-case-type-revisions/1.2/oidc-browser-relying-party/type.yaml", + "only_type_semantic_delta": "status proposed to acknowledged", + "packet_bound_type_sources_changed": false, + "default11_type_and_case_changed": false, + "next_owner_gates": "docs/forgejo-type12-source-acknowledgment-followthrough.md", + "new_native_operation": false +} diff --git a/security-case-type-revisions/1.2/oidc-browser-relying-party/README.md b/security-case-type-revisions/1.2/oidc-browser-relying-party/README.md new file mode 100644 index 0000000..6f166ce --- /dev/null +++ b/security-case-type-revisions/1.2/oidc-browser-relying-party/README.md @@ -0,0 +1,54 @@ +# Acknowledged OIDC browser relying-party 1.2 source package + +This package supplements the exact proposed 1.2 type and Forgejo reference design. It is source-only and unimplemented. Its examples are proposed, including Forgejo; normal admission must refuse them until the separate implemented-type and canonical-case acceptance requirements are discharged. Completing this package or acknowledging its type does not accept a canonical case or authorize native work. Immutable acknowledged 1.1 history remains unchanged. + +## Purpose + +Register exact-redirect browser OIDC relying parties through KeyCape, with groups enforced by the consumer. Confidential clients add a custody path, two reader policies, the existing KeyCape ESO role and a sixth dedicated consumer ESO reader role. consumer_namespace is explicit and independently constrained; a consuming service name does not establish its namespace or workload identity. Public clients require no secret materialization. + +## Threat model + +Exact HTTPS redirects prohibit wildcard, query, fragment and plaintext HTTP. Requested scopes always include groups, but KeyCape issues identity tokens without a per-client group gate: each consumer must enforce its required claims. MFA pinning is client configuration, not proof of a human MFA session. Secret custody parameters and reader identities cannot be overridden by case authors. + +The namespace SecretStore references a dedicated automount-disabled service account rather than forgejo/default. ESO's broadly privileged common controller remains trusted; this is routing and identity attribution, not cryptographic controller isolation. The supported v0.16.1 TokenRequest path requests a 600-second token; its legacy fallback must not acquire static tokens. The proposed OpenBao role has a 900-second maximum token TTL and no default policy. Neither rendered claims nor source tests prove native bindings, token audience, capabilities, delivery readiness or revocation. + +## Alternatives considered + +Retain 1.1 with the observed Forgejo/runner workload ServiceAccount forgejo/default: preserves existing history but does not express the dedicated reader boundary. This describes observed workload identity only; the historical 1.1 consumer OpenBao policy was unbound and no historical default-SA OpenBao reader binding is claimed. Reuse the KeyCape reader role: combines provider and consumer identities unnecessarily. Adopt a separate controller: potentially reduces shared trust but adds infrastructure outside this bounded proposal. Proposed 1.2 retains shared-controller trust explicitly while adding the sixth dedicated role; no new grant follows from this source design. + +## Known limits + +All native bound claims remain unconfirmed and execution remains false. HTTP OpenBao transport, shared ESO controller trust, legacy fallback, retained target Secrets and later dependency handling require owner verification before any separately approved session. A SecretStore/SA deletion alone does not revoke issued tokens. Recovery may remove only authenticated case-created resources with unchanged UID/ownership, must preserve preexisting exact matches, revert consumer references first and revoke issued tokens or verify expiry before declaring deactivation. Owner adapter and global verifier observations remain required. No human login, MFA, credentials, native materialization or first-case completion is claimed. + +## Verification + +Run the existing owner full-package validator against this directory, then run its tests. Tests use the existing owner validator/composer and actual declarations; they prove source schema, examples, deterministic rendering, six-object confidential versus public boundaries, refused mutation/parameters, normal admission refusal and bounded rollback ordering. They do not contact native services. + +```sh +python3 tools/security-case-types/security_case_validator.py validate-type docs/proposals/2026-10-11-forgejo-consumer-eso/package-1.2 +NET_KINGDOM_ROOT=/home/worsch/net-kingdom python3 -m pytest docs/proposals/2026-10-11-forgejo-consumer-eso/package-1.2/tests +``` + +## Governance and recording + +SecurityCaseTypes section 3 requires the complete package and a separate NetKingdom source-owner review before type acknowledgment recording. Sections 4/5 require an implemented type for canonical case acceptance; section 6 requires a genuine new acknowledgment for the sixth role/authentication path. The old 1.1 acknowledgment is not inherited. Reference-migration source approval is a separate owner receipt; canonical 1.2 stays proposed without acceptance fields or phase acceptance. + +## Recorded source acknowledgment — 2026-10-11 + +Confirmed native human ACCEPT of infd-20261011-forgejo-type12-source-r1@1 +at2026-10-11T06:47:39Z, approval8e9332c8-754a-420c-b8b7-445cb4fe6765, +acknowledges source architecture only. Exact reviewed proposed typeSHA +017885bdd139cd66a5bf6d9839b1b8ec9bc08fb051d9577adc3928b76a7be6db is preserved +in the immutable proposal package. This copy changes type status to acknowledged +and documents that source record; it remains unimplemented. See +decision/acknowledgment.json for exact native disposition, packet, owner returns, +post-anchor review and source digests. Tests adapt only the expected type status; +examples remain proposed without acceptance fields. Current canonical1.1 type, +package and acceptedcase remain unchanged and selected by the default loader. + +This explicit version root is security-case-type-revisions/1.2; choose it only +for separate source validation/preparation using the existing --types/--types-root +option. No default loader/repoint or canonicalcase1.2 admission is introduced. +The full proposed package test/validator proof is retained; run this acknowledged +copy's package validator/tests before recording its acknowledgment. The separate +reference-migration owner design receipt is not canonical case acceptance. diff --git a/security-case-type-revisions/1.2/oidc-browser-relying-party/decision/acknowledgment.json b/security-case-type-revisions/1.2/oidc-browser-relying-party/decision/acknowledgment.json new file mode 100644 index 0000000..d80232d --- /dev/null +++ b/security-case-type-revisions/1.2/oidc-browser-relying-party/decision/acknowledgment.json @@ -0,0 +1,79 @@ +{ + "kind": "security-case-type-source-acknowledgment", + "type": "oidc-browser-relying-party@1.2", + "stable_proposal": "NK-FORGEJO-TYPE12-SOURCE-20261011-R1", + "work_item": "NK-WP-ADHOC-2026-10-11-T06", + "source_implementation_task": "NK-WP-0048-T06", + "memo_id": "infd-20261011-forgejo-type12-source-r1", + "memo_version": 1, + "review_id": "review-126c6c90-11ba-4609-b8d1-75e054c246cd", + "approval_id": "8e9332c8-754a-420c-b8b7-445cb4fe6765", + "disposition_id": "disp-315d54ad-20f1-40e6-862c-6c7d2e8f0ea8", + "presentation_id": "pres-5a52f932-8c65-46cc-8054-0264f47f934a", + "actual_human_actor": { + "kind": "person", + "sub": "uid=platform-root,ou=people,dc=netkingdom,dc=local" + }, + "actual_disposition_at": "2026-10-11T06:47:39Z", + "verb": "accept", + "confirmed_nonstale": true, + "exact_human_packet_manifest_sha256": "0b377d647ca748cd03c92f9792396412048055d4bde9f7bb06ff6d413f7acd68", + "submission_digest": "sha256:585cee731de30d2b37883a57abfd9eb32f023ee694e8d911989109d5caf80569", + "proposed_type_sha256": "017885bdd139cd66a5bf6d9839b1b8ec9bc08fb051d9577adc3928b76a7be6db", + "acknowledged_type_sha256": "9e60ff569fb0d860a2bbde7bbb0991a54d4b0688f62b56df0fa5d161fd624578", + "canonical_case12_source_sha256": "1c868c1da7d9077fae97bc6bc029706ec3dc418cfeaae30dc0f92b5b4ba6f2ab", + "full_render_digest": "sha256:c0afd5576cdae0cbc807eccb2b9fa87ac668f15e32ec7cf79d295bdb23c75b35", + "version_types_root": "security-case-type-revisions/1.2", + "package_type_path": "security-case-type-revisions/1.2/oidc-browser-relying-party/type.yaml", + "packet_bound_sources_edited": false, + "default_type_loader_or_11_case_repointed": false, + "current11_preserved": { + "type_path": "security-case-types/oidc-browser-relying-party/type.yaml", + "type_sha256": "f705c64e4875e9b8e18a912fb51c135e77898926d6a451f5cb74ab3c0cbe4d1c", + "case_path": "security-cases/forgejo-netkingdom-oidc.yaml", + "case_sha256": "bcc2c6d5bae0d28242b3cdb71e74d8ca297c2afe04766b55d53597f86893351d" + }, + "review_receipts": [ + { + "path": "docs/reviews/2026-10-11-forgejo-type12-human-packet-net-owner-final-review.md", + "sha256": "9e9b8dda889203c064b35e1bbcd4d0c62d76d4ba1935c9a10f4b2dbf1c6e8497" + }, + { + "path": "docs/reviews/2026-10-11-forgejo-type12-human-packet-final-hash-ack.json", + "sha256": "7f2264668ad205d127bb216bc726f62a6ee447759f9899fcccc6c439b9bbefe5" + }, + { + "path": "docs/reviews/2026-10-11-forgejo-type12-post-anchor-owner-review.json", + "sha256": "0893b8fe936c72394147bc511c6a21af8e75866c96549ceec8af5d2abd1ee100" + } + ], + "native_source_provenance": [ + { + "path": "docs/evidence/2026-10-11-forgejo-type12-source-acknowledgment/native-outcome.json", + "sha256": "042fcc80dbd450ad6901d91624b544e2128d4bb3045ae201d570ec0bf96f5f2d" + }, + { + "path": "docs/evidence/2026-10-11-forgejo-type12-source-acknowledgment/native-authoring-receipt.json", + "sha256": "67b581d2f825d0ba10bcbf0296e7f9e63f5d78e5d6d723150b0983f067635172", + "initial_authoring_was_queued_not_disposed": true + } + ], + "scope": "Confirmed human source architecture acknowledgment only; reference-migration design approval recorded separately. No agent decision. Root requesting agent records exact actual founder disposition after verifying these staged files.", + "type_implemented": false, + "canonical_case12_status": "proposed", + "canonical_case12_acceptance_fields_present": false, + "claims_confirmed": false, + "execution_permitted": false, + "native_operation_authorized": false, + "recording_act": "Transcribe confirmed human source acknowledgment; requesting coordinator applies this exact record after independent verification. This is not an agent approval.", + "recorded_status": "source-acknowledged", + "recorded_package_validation": { + "actual_full_package_validator": "PASS acknowledged1.2", + "independent_runnable_tests": 22, + "closed_type_case_schemas": "PASS", + "ordinary_case_admission": "REFUSED unimplemented acknowledged type", + "explicit_types_root_load": "PASS", + "full_render_regenerated_digest": "sha256:c0afd5576cdae0cbc807eccb2b9fa87ac668f15e32ec7cf79d295bdb23c75b35", + "execution_permitted": false + } +} diff --git a/security-case-type-revisions/1.2/oidc-browser-relying-party/examples/example-public-portal.yaml b/security-case-type-revisions/1.2/oidc-browser-relying-party/examples/example-public-portal.yaml new file mode 100644 index 0000000..6b349fa --- /dev/null +++ b/security-case-type-revisions/1.2/oidc-browser-relying-party/examples/example-public-portal.yaml @@ -0,0 +1,20 @@ +apiVersion: netkingdom.io/security-case/v0.1 +kind: SecurityCase +spec: + id: example-public-portal + type: oidc-browser-relying-party@1.2 + status: proposed + owner: + repo: net-kingdom + person: example-owner + parameters: + client_id: example-portal + display_name: Example portal + redirect_uris: https://portal.example.invalid/auth/callback + allowed_scopes: openid,profile,email,groups + client_type: public + mfa_required: 'false' + access_groups: example-portal-users + consuming_service: example-portal + consumer_owner_repo: net-kingdom + consumer_namespace: example-portal diff --git a/security-case-type-revisions/1.2/oidc-browser-relying-party/examples/forgejo.yaml b/security-case-type-revisions/1.2/oidc-browser-relying-party/examples/forgejo.yaml new file mode 100644 index 0000000..8c7c4bc --- /dev/null +++ b/security-case-type-revisions/1.2/oidc-browser-relying-party/examples/forgejo.yaml @@ -0,0 +1,21 @@ +apiVersion: netkingdom.io/security-case/v0.1 +kind: SecurityCase +spec: + id: forgejo-netkingdom-oidc + type: oidc-browser-relying-party@1.2 + status: proposed + owner: + repo: railiance-apps + person: founder + parameters: + client_id: forgejo + display_name: Forgejo source forge + redirect_uris: https://forgejo.coulomb.social/user/oauth2/netkingdom/callback + allowed_scopes: openid,profile,email,groups + client_type: confidential + mfa_required: 'true' + access_groups: forge-admins,forge-coulomb-owners,forge-coulomb-readers + initial_members: forge-admins=tegwick;forge-coulomb-owners=tegwick + consuming_service: forgejo + consumer_owner_repo: railiance-apps + consumer_namespace: forgejo diff --git a/security-case-type-revisions/1.2/oidc-browser-relying-party/tests/test_source_contract.py b/security-case-type-revisions/1.2/oidc-browser-relying-party/tests/test_source_contract.py new file mode 100644 index 0000000..a1229f1 --- /dev/null +++ b/security-case-type-revisions/1.2/oidc-browser-relying-party/tests/test_source_contract.py @@ -0,0 +1,88 @@ +"""Source-only contract checks against the actual owner validator and declarations.""" +import copy, importlib.util, os, sys +from pathlib import Path +import pytest, yaml +PACKAGE=Path(__file__).resolve().parents[1] +OWNER=Path(os.environ.get("NET_KINGDOM_ROOT", "/home/worsch/net-kingdom")) +VP=OWNER/"tools/security-case-types/security_case_validator.py" +sys.path.insert(0,str(VP.parent)) +spec=importlib.util.spec_from_file_location("security_case_validator",VP) +v=importlib.util.module_from_spec(spec);sys.modules[spec.name]=v;spec.loader.exec_module(v) +TYPE=yaml.safe_load((PACKAGE/"type.yaml").read_text()) +FORGEJO=yaml.safe_load((PACKAGE/"examples/forgejo.yaml").read_text()) +paths,discovery=v.discover_declarations(TYPE,OWNER.parent) +DECLS,loading=v.composer.load_declarations(paths) +def render(case): + issues,result=v.render_case(case,TYPE,DECLS,require_implemented=False) + assert not v.has_errors(discovery+loading+issues) + return result + +def test_full_package_and_proposed_boundary(): + assert not v.has_errors(v.validate_type(TYPE,PACKAGE)) + assert TYPE["spec"]["status"]=="acknowledged" + assert FORGEJO["spec"]["status"]=="proposed" + assert "acceptance" not in FORGEJO["spec"] + assert v.has_errors(v.validate_case(FORGEJO,TYPE)) + +def test_acknowledged_is_still_not_implemented_admission(): + acknowledged=copy.deepcopy(TYPE);acknowledged["spec"]["status"]="acknowledged" + assert v.has_errors(v.validate_case(FORGEJO,acknowledged)) + +@pytest.mark.parametrize("example",sorted((PACKAGE/"examples").glob("*.yaml"))) +def test_examples_valid_deterministic_and_nonexecuting(example): + case=yaml.safe_load(example.read_text()) + assert not v.has_errors(v.validate_case(case,TYPE,require_implemented=False)) + first=render(case);assert first==render(case) + assert first["execution"]["permitted"] is False + assert first["composition"]["execution"]["permitted"] is False + +def test_sixth_role_is_exact_consumer_identity_and_namespace(): + case=copy.deepcopy(FORGEJO);case["spec"]["parameters"]["consumer_namespace"]="forgejo-preview" + r=render(case);objects={x["id"]:x for x in r["materialization"]} + assert len(objects)==6 + consumer=yaml.safe_load(objects["consumer-eso-role"]["body"]) + assert consumer["bound_service_account_names"]==["forgejo-keycape-forgejo-eso"] + assert consumer["bound_service_account_namespaces"]==["forgejo-preview"] + assert consumer["audience"]=="openbao" + assert consumer["token_policies"]==["workload-kv-read-keycape-forgejo-forgejo"] + assert consumer["token_no_default_policy"] is True + provider=yaml.safe_load(objects["eso-role"]["body"]) + assert provider["bound_service_account_names"]!=consumer["bound_service_account_names"] + +def test_original_five_structural_bodies_unchanged(): + old=yaml.safe_load((OWNER/"security-case-types/oidc-browser-relying-party/type.yaml").read_text()) + case=yaml.safe_load((OWNER/"security-cases/forgejo-netkingdom-oidc.yaml").read_text()) + issues,before=v.render_case(case,old,DECLS,require_implemented=False) + assert not v.has_errors(issues) + after={x["id"]:x["body"] for x in render(FORGEJO)["materialization"]} + for item in before["materialization"]:assert item["body"]==after[item["id"]] + +def test_public_has_no_secret_or_delivery_hooks(): + r=render(yaml.safe_load((PACKAGE/"examples/example-public-portal.yaml").read_text())) + assert [x["id"] for x in r["materialization"]]==["catalog-entry"] + assert not {"mint-secret","deliver-secret","deliver-consumer-secret","bind-env"}&{x["id"] for x in r["follow_through"]} + +@pytest.mark.parametrize("key,value",[("consumer_namespace",None),("consumer_namespace","default/other"),("consumer_namespace","x"*64),("consuming_service","x"*64),("redirect_uris","http://portal.invalid/callback"),("redirect_uris","https://portal.invalid/*"),("redirect_uris","https://portal.invalid/callback?x=y"),("redirect_uris","https://portal.invalid/callback#x"),("allowed_scopes","openid,email"),("consumer_reader_service_account","default"),("secret_path","other/path")]) +def test_invalid_or_unsettable_parameter_refused(key,value): + case=copy.deepcopy(FORGEJO) + if value is None:case["spec"]["parameters"].pop(key) + else:case["spec"]["parameters"][key]=value + assert v.has_errors(v.validate_case(case,TYPE,require_implemented=False)) + +def test_created_only_role_recovery_precedes_policy_and_needs_revocation(): + rollback=render(FORGEJO)["rollback"];ids=[x["reverses"] for x in rollback] + assert ids.index("consumer-eso-role") + --case-acceptance --check-config (net-kingdom.keycape-client-registration) + auth: operator write access to the live KeyCape client registry in namespace sso + lane: key-cape-oidc-login + warden_executes: false + attended: true + value_handling: none + attended_justification: 'The live KeyCape client registry is a Kubernetes Secret, + and agents do not read or write Secrets. Until KeyCape loads clients from a + non-secret registry with secrets referenced from custody, one attended operator + session applies the rendered registration. ops-warden groups all attended steps + of a run into that one session. KeyCape loads clients at startup and keeps login, + authorization and handoff state in memory, so the restart drops in-flight logins + and sessions for every client; runs go in a quiet window (key-cape type review + R4). The rendered registry must pass KeyCape''s own startup checks (keycape + check-config, key-cape c528daa, which keycape-client.py runs before it patches) + before the restart: a refused entry stops the single replica and every client + loses sign-in (R1).' + - id: deliver-consumer-secret + owner: '{consumer_owner_repo}' + when: client_type == confidential + entry_point: Owner applies dedicated ServiceAccount {consumer_namespace}/{consuming_service}-keycape-{client_id}-eso + (automount=false, no legacy tokens), namespace SecretStore openbao-keycape-{client_id}-consumer + with serviceAccountRef and audiences [openbao], and ExternalSecret {consuming_service}-netkingdom-oidc-client + with Owner target, Retain remote deletion and only CLIENT_SECRET from workloads/keycape/{client_id}. + Admission validates actual installed ESO TokenRequest support and common controller + RBAC before any owner-approved apply. + auth: Consumer owner contained Kubernetes deployment authority; ESO authenticates + to OpenBao role external-secrets-keycape-{client_id}-{consuming_service} with + a TokenRequest for the dedicated namespaced serviceAccountRef; controller remains + trusted + warden_executes: false + attended: false + value_handling: none + ready_check: Namespace SecretStore and ExternalSecret both report Ready=True; + dedicated SA has no legacy token refs; status and fixed metadata only, never + Secret values. + - id: hand-over + owner: '{consumer_owner_repo}' + entry_point: configure {consuming_service} with issuer {issuer}, client {client_id} + and custody bao:platform/workloads/keycape/{client_id}, and make it require + one of {access_groups} in the groups claim before sign-in completes + auth: the consumer owner's own deployment path + warden_executes: false + attended: false + value_handling: none + verification: + - id: authorize-accepts-redirects + check: GET {issuer}/authorize with client {client_id} and each of {redirect_uris} + returns the login page + expect: present + reads_secret_value: false + - id: authorize-refuses-other-redirect + check: GET {issuer}/authorize with client {client_id} and an unregistered redirect + returns an OAuth error + expect: deny + reads_secret_value: false + - id: custody-denied-to-default + when: client_type == confidential + check: a default-only OpenBao identity has no read capability on bao:platform/workloads/keycape/{client_id} + expect: deny + reads_secret_value: false + - id: custody-allowed-to-consumer + when: client_type == confidential + check: policy workload-kv-read-keycape-{client_id}-{consuming_service} grants + read on bao:platform/workloads/keycape/{client_id} (capabilities check only) + expect: allow + reads_secret_value: false + - id: groups-present + check: LLDAP groups {access_groups} exist, with exactly the memberships of the + accepted case added + expect: present + reads_secret_value: false + - id: consumer-enforces-groups + check: '{consuming_service}''s OIDC source for {client_id} (owner {consumer_owner_repo}) + requires one of {access_groups} in the groups claim (configuration read, no + secret value)' + expect: present + reads_secret_value: false + - id: secret-delivered + when: client_type == confidential + check: the delivery for sso/keycape-{client_id}-client reports Ready=True (status + only) + expect: present + reads_secret_value: false + - id: mfa-pinned + when: mfa_required == true + check: keycape-client.py inspect for {client_id} shows the MFA pin on the registered + client (non-secret client view) + expect: present + reads_secret_value: false + - id: consumer-secret-delivered + when: client_type == confidential + check: '{consumer_namespace} SecretStore openbao-keycape-{client_id}-consumer + and ExternalSecret {consuming_service}-netkingdom-oidc-client Ready=True, exact + dedicated SA/audience role binding, fixed CLIENT_SECRET mapping; no Secret value + read' + expect: present + reads_secret_value: false + rollback: + - reverses: hand-over + action: remove the OIDC source for {client_id} from {consuming_service} (owner + {consumer_owner_repo}) + - reverses: deliver-consumer-secret + when: client_type == confidential + action: After reverting consumer secret reference, delete only authenticated created + ExternalSecret/owned target by UID and ownerReference, then SecretStore and + dedicated SA; preserve preexisting-matched resources and never delete a shared + target. Retain audit and ownership receipts; removing SecretStore/SA alone is + not immediate OpenBao token revocation. + - reverses: register-client + action: keycape-client.py apply --operation remove for {client_id} + - reverses: bind-env + when: client_type == confidential + action: remove env KEYCAPE_{client_id:env}_CLIENT_SECRET from Deployment sso/keycape, + after register-client is reversed + - reverses: deliver-secret + when: client_type == confidential + action: delete ExternalSecret sso/keycape-{client_id}-client and its target + - reverses: mint-secret + when: client_type == confidential + action: 'covered by client-secret-path: one metadata delete, after deliver-secret + is reversed' + - reverses: ensure-groups + action: identity-provisioner revoke_service_groups inside the provisioner pod + (attended, as ensure-groups) with the case's memberships; delete_if_empty only + if no other case uses {access_groups} + - reverses: client-secret-path + when: client_type == confidential + action: delete metadata and all versions at platform/workloads/keycape/{client_id}, + after the ExternalSecret is gone (this also reverses mint-secret) + - reverses: eso-role + when: client_type == confidential + action: delete Kubernetes-auth role external-secrets-keycape-{client_id} + - reverses: keycape-reader-policy + when: client_type == confidential + action: delete policy workload-kv-read-keycape-{client_id}-eso, after eso-role + - reverses: consumer-eso-role + when: client_type == confidential + action: Delete only this case-created role external-secrets-keycape-{client_id}-{consuming_service}, + before deleting consumer-reader-policy; revoke case-issued OpenBao tokens or + prove expiration before declaring deactivation. + - reverses: consumer-reader-policy + when: client_type == confidential + action: delete policy workload-kv-read-keycape-{client_id}-{consuming_service} + - reverses: catalog-entry + action: remove catalog entry {consuming_service}-keycape-client + acceptance: + accepted_by: + - owner + - founder + risk_class: medium diff --git a/workplans/ADHOC-2026-10-11.md b/workplans/ADHOC-2026-10-11.md index fb938d5..6ed614c 100644 --- a/workplans/ADHOC-2026-10-11.md +++ b/workplans/ADHOC-2026-10-11.md @@ -147,3 +147,18 @@ keeps canonicalcaseproposed, ordinary admission blocked and executionfalse. Original eeb changes-requested review and prepackage12ce failures remain history, not new scored successes. Final source agreement is separate receipt only; no actual founder acknowledgment, native intake, acceptance or runtime change. + +2026-10-11T06:47:39Z source-recording preparation, same T06 trial: latest native +outcome confirms nonstale person ACCEPT of exactmemo1, approval +8e9332c8-754a-420c-b8b7-445cb4fe6765, disposition +disp-315d54ad-20f1-40e6-862c-6c7d2e8f0ea8. Prepared external acknowledgment +receipt and complete acknowledged1.2 package in explicit version source root +security-case-type-revisions/1.2, changing type semantic status only. Independent +fullvalidator and22 adapted-source tests pass; schema/versionload/render checks +pass and normalcase admission remains refused. Packet-bound proposed sources +and defaultcanonical1.1 package/case stay byte-identical. Separate Apps design +receipt transcribes the actual human source scope, not an agent ownerreview or +canonicalcase acceptance. Requesting coordinator records actual foundergo; no +worker native/credential/grant action. Canonical1.2case remains proposed without +acceptance; implementation followthrough remains existing NK0048-T06/project +owner tasks. No new trial, taskT07, broad plan or whole-workplan finish. diff --git a/workplans/NK-WP-0048-security-case-types.md b/workplans/NK-WP-0048-security-case-types.md index 8f3200e..49a81fc 100644 --- a/workplans/NK-WP-0048-security-case-types.md +++ b/workplans/NK-WP-0048-security-case-types.md @@ -9,7 +9,7 @@ flavor: implementation owner: claude-code topic_slug: netkingdom created: "2026-10-08" -updated: "2026-10-09" +updated: "2026-10-10" depends_on: [] related_repos: - ops-mason @@ -324,7 +324,7 @@ the rationale. The type is `acknowledged`; it becomes `implemented` with T06. id: NK-WP-0048-T06 status: wait depends_on: [NK-WP-0048-T05, NK-WP-0048-T08, NK-WP-0048-T09, MASON-WP-0010-T03, WARDEN-WP-0044-T03] -blocking_reason: "Type 1.1, both light paths and the mint lane exist (RPF-WP-0054; CCR-2026-0040/0041/0043 applied). Waits on: CCR-2026-0042 consumer reader (in_flight, platform-owner review); the mint-secret run; ops-warden's run sheet (WARDEN-WP-0044-T03); then the founder's attended session (bind-env, ensure-groups, register-client with --check-config) in a quiet window." +blocking_reason: "Type1.2 architecture has a confirmed source-only founder acknowledgment; canonical1.1 remains unchanged/default and the1.2 reference case stays proposed. Needs explicit version selection/reference-source integration without normal admission bypass, closed owner adapters plus global/native receipt verifier (WARDEN-WP-0044-T03), independently verified six-object structural materialization and CCR42 claims/created-only provenance, exact broker/case/source reconciliation, then separately authorized native mint/delivery and attended registry/consumer verification. Source acknowledgment, a bundle or local tests do not prove implemented/materialized/live status." priority: high state_hub_task_id: "d9b26bcf-a7c6-59a2-92a0-f913d76a203c" ``` @@ -500,3 +500,50 @@ and for confidential clients adds `deliver-secret` (delivery from custody into the sso namespace) and `bind-env` (Deployment env), attended in the same session as `register-client`. The per-client helpers stay until their clients are adopted as cases. + +2026-10-10 — NetKingdom owner review of the execution seam, source only: +ops-warden/docs/security-case-execution-proposal.md SHA256 78ab1439e4c5beb205aeccf15b1b2e706511be55ab195c5a3aa682f326c7c77c +was reviewed against INTENT, SecurityCase canon, acknowledged type1.1, current +case and owner source. docs/security-case-execution-owner-review.md supports +the closed adapter/receipt direction with explicit versioned schema, structural +materialization provenance, unchanged caller/session boundaries, safe CAS +reconciliation and exact-created-object rollback requirements. This is owner +review, not approval. Supporting file digests are in the adjacent sources JSON. + +Current source exposes a circular wait: ops-mason T03 waits on mint while Warden +and the broker refuse a non-materialized case. Structural acceptance therefore +needs its own native pinned receipt before mint, not a successful mint before +materialized. The platform broker additionally pins type1.0 while Forgejo is +accepted at1.1; platform-owner alignment and tests are required, not an unchecked +version bypass. T06 remains wait. No case/type lifecycle status, grant, authority +or live runtime changed by this review. A proposed informed-decision would +adopt the source contract only; native materialization and execution acceptance +stay distinct. + +Final proposal re-review: staged Warden proposal SHA256 78ab1439e4c5beb205aeccf15b1b2e706511be55ab195c5a3aa682f326c7c77c +adds only the explicitly local reducer appendix, not an accepted wire protocol +or executor. The exact-final review and sources JSON supersede the earlier +1035f049... proposal review. Platform staged the exact type1.1 broker correction +with ten fake-backend subprocess checks (script SHA256 +9576cd211cfc06526ec4cc9bd0a5b06f0f59287a68931bb2d6e3592a951ddc7d). +The next source work is the versioned closed adapter/receipt/materialization +contract, not another relaxation of the broker's status gate. Native work still +requires installed broker provenance, structural reader receipts, exact new +materialized-case bytes, caller grant/session revocation and verified execution. +No installed/native acceptance is inferred from that staged correction. + +2026-10-11 — new source-only type1.2 architecture acknowledgment: +Confirmed native founder ACCEPT of infd-20261011-forgejo-type12-source-r1@1 +at06:47:39Z, approval8e9332c8-754a-420c-b8b7-445cb4fe6765. Exact frozen packet +0b377d647ca748cd03c92f9792396412048055d4bde9f7bb06ff6d413f7acd68 and submission +585cee731de30d2b37883a57abfd9eb32f023ee694e8d911989109d5caf80569; native receipt +retained in docs/evidence/2026-10-11-forgejo-type12-source-acknowledgment/. +The complete acknowledged1.2 source package is isolated under +security-case-type-revisions/1.2/oidc-browser-relying-party; default loader and +current accepted1.1 case remain untouched because load_type is single-version. +The new proposed1.2 case is NOT accepted/materialized/live and has no acceptance +fields. Actual reference-migration design approval is a separate Apps owner +receipt; no1.1 approval is inherited. Source-recording review/test proof and exact +next gates are in docs/forgejo-type12-source-acknowledgment-followthrough.md. +T06 remains wait and T07 remains its existing dependent task; type is NOT +implemented and no first-case/native grant or broader workplan finish is asserted.