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
This commit is contained in:
parent
584a964684
commit
f6856cdb53
13 changed files with 859 additions and 2 deletions
|
|
@ -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}
|
||||
|
|
@ -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}]}
|
||||
|
|
@ -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
|
||||
}
|
||||
39
docs/forgejo-type12-source-acknowledgment-followthrough.md
Normal file
39
docs/forgejo-type12-source-acknowledgment-followthrough.md
Normal file
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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.
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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")<ids.index("consumer-reader-policy")
|
||||
action=next(x["action"] for x in rollback if x["reverses"]=="consumer-eso-role")
|
||||
assert "case-created" in action and "revoke" in action and "expiration" in action
|
||||
delivery=next(x["action"] for x in rollback if x["reverses"]=="deliver-consumer-secret")
|
||||
assert "UID" in delivery and "preexisting" in delivery and "consumer secret reference" in delivery
|
||||
|
||||
@pytest.mark.parametrize("omitted",["README.md","tests/test_source_contract.py","examples"])
|
||||
def test_full_package_validator_rejects_incomplete_supplement(tmp_path,omitted):
|
||||
import shutil
|
||||
trial=tmp_path/"package";shutil.copytree(PACKAGE,trial,ignore=shutil.ignore_patterns("__pycache__",".pytest_cache"))
|
||||
target=trial/omitted
|
||||
if target.is_dir():
|
||||
for example in target.glob("*.yaml"):example.unlink()
|
||||
else:target.unlink()
|
||||
assert v.has_errors(v.validate_type(TYPE,trial))
|
||||
|
|
@ -0,0 +1,442 @@
|
|||
apiVersion: netkingdom.io/security-case-type/v0.1
|
||||
kind: SecurityCaseType
|
||||
spec:
|
||||
id: oidc-browser-relying-party
|
||||
version: '1.2'
|
||||
status: acknowledged
|
||||
title: Browser OIDC relying party for an internal service
|
||||
purpose: 'Let an internal web service sign its human users in through NetKingdom
|
||||
(KeyCape): an exact-redirect OIDC client, optional MFA pin, the LLDAP groups the
|
||||
service maps to its own roles, and, for confidential clients, a client secret
|
||||
minted straight into OpenBao custody. Replaces the per-client rollout scripts
|
||||
in sso-mfa/k8s/keycape. First case: Forgejo (KEY-WP-0038).'
|
||||
parameters:
|
||||
- name: client_id
|
||||
type: string
|
||||
case_settable: true
|
||||
constraints:
|
||||
pattern: ^[a-z0-9][a-z0-9-]{1,62}$
|
||||
sensitivity: operational
|
||||
description: OAuth2 client_id, unique in KeyCape.
|
||||
- name: display_name
|
||||
type: string
|
||||
case_settable: true
|
||||
constraints:
|
||||
pattern: ^[^\n\r]{1,80}$
|
||||
sensitivity: public
|
||||
description: Name shown on the sign-in page.
|
||||
- name: redirect_uris
|
||||
type: string
|
||||
case_settable: true
|
||||
constraints:
|
||||
pattern: ^https://[^*?#\s,]+(,https://[^*?#\s,]+)*$
|
||||
sensitivity: security_sensitive
|
||||
description: 'Comma-separated exact https redirect URIs. No wildcards, no plain
|
||||
http, no query and no fragment: KeyCape refuses ''*'' and ''?'' at startup,
|
||||
and OAuth 2.0 forbids fragments (key-cape type review R1).'
|
||||
- name: allowed_scopes
|
||||
type: string
|
||||
case_settable: true
|
||||
constraints:
|
||||
enum:
|
||||
- openid,profile,email,groups
|
||||
- openid,email,groups
|
||||
- openid,profile,groups
|
||||
- openid,groups
|
||||
sensitivity: security_sensitive
|
||||
description: Scopes the client may request, openid first. Always includes groups,
|
||||
because access_groups is required and KeyCape's UserInfo returns groups only
|
||||
for that scope (key-cape type review R2).
|
||||
- name: client_type
|
||||
type: string
|
||||
case_settable: true
|
||||
constraints:
|
||||
enum:
|
||||
- confidential
|
||||
- public
|
||||
sensitivity: security_sensitive
|
||||
description: confidential for server-side services that can hold a secret; public
|
||||
for SPAs and native apps (PKCE only).
|
||||
- name: mfa_required
|
||||
type: string
|
||||
case_settable: true
|
||||
constraints:
|
||||
enum:
|
||||
- 'true'
|
||||
- 'false'
|
||||
sensitivity: security_sensitive
|
||||
description: '"true" pins MFA on this client; required when the service grants
|
||||
administrative or owner rights. "false" is not "no MFA": the client then carries
|
||||
no mfaRequired field and KeyCape applies the per-user privacyIDEA policy. A
|
||||
renderer must never emit an explicit mfaRequired false, which would skip that
|
||||
policy (key-cape type review R3).'
|
||||
- name: access_groups
|
||||
type: string
|
||||
case_settable: true
|
||||
constraints:
|
||||
pattern: ^[a-z][a-z0-9-]{1,62}(,[a-z][a-z0-9-]{1,62})*$
|
||||
sensitivity: operational
|
||||
description: 'Comma-separated LLDAP groups that the service maps to its roles.
|
||||
Created if absent. KeyCape has no per-client group gate: it issues tokens to
|
||||
any authenticated user and only carries the groups claim, so the consuming service
|
||||
enforces the gate itself (for Forgejo, its required-claim setting; key-cape
|
||||
type review R2).'
|
||||
- name: initial_members
|
||||
type: string
|
||||
required: false
|
||||
case_settable: true
|
||||
constraints:
|
||||
pattern: ^[a-z][a-z0-9-]*=[a-z][a-z0-9._-]*(\+[a-z][a-z0-9._-]*)*(;[a-z][a-z0-9-]*=[a-z][a-z0-9._-]*(\+[a-z][a-z0-9._-]*)*)*$
|
||||
sensitivity: operational
|
||||
description: Initial memberships as group=user+user;group=user. Usernames are
|
||||
directory usernames, never secrets.
|
||||
- name: consuming_service
|
||||
type: string
|
||||
case_settable: true
|
||||
constraints:
|
||||
pattern: ^[a-z0-9][a-z0-9-]{0,62}$
|
||||
sensitivity: operational
|
||||
description: The service that signs users in with this client.
|
||||
- name: consumer_owner_repo
|
||||
type: string
|
||||
case_settable: true
|
||||
constraints:
|
||||
pattern: ^[a-z0-9][a-z0-9-]*$
|
||||
sensitivity: operational
|
||||
description: The repository that owns the consuming service's configuration.
|
||||
- name: consumer_namespace
|
||||
type: string
|
||||
case_settable: true
|
||||
constraints:
|
||||
pattern: ^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$
|
||||
sensitivity: security_sensitive
|
||||
description: Consumer namespace for namespaced ESO TokenRequest reader; actual
|
||||
workload owner must confirm; never infer from service name.
|
||||
- name: issuer
|
||||
type: string
|
||||
case_settable: false
|
||||
default: https://kc.coulomb.social
|
||||
sensitivity: security_sensitive
|
||||
description: The NetKingdom issuer; fixed by the type.
|
||||
composition:
|
||||
authority: netkingdom
|
||||
initial_trust:
|
||||
- runtime_secret_trust
|
||||
- runtime_identity_trust
|
||||
capabilities:
|
||||
- c1.lightweight-sso
|
||||
providers:
|
||||
c1.lightweight-sso: net-kingdom.keycape-client-registration
|
||||
parameter_bindings:
|
||||
net-kingdom.keycape-client-registration.client_id: client_id
|
||||
net-kingdom.keycape-client-registration.display_name: display_name
|
||||
net-kingdom.keycape-client-registration.redirect_uris: redirect_uris
|
||||
net-kingdom.keycape-client-registration.allowed_scopes: allowed_scopes
|
||||
net-kingdom.keycape-client-registration.client_type: client_type
|
||||
net-kingdom.keycape-client-registration.mfa_required: mfa_required
|
||||
materialization:
|
||||
- id: client-secret-path
|
||||
kind: kv_path
|
||||
when: client_type == confidential
|
||||
template: platform/workloads/keycape/{client_id}
|
||||
body: field CLIENT_SECRET; minted by the credential broker, never written by hand
|
||||
- id: keycape-reader-policy
|
||||
kind: openbao_policy
|
||||
when: client_type == confidential
|
||||
template: workload-kv-read-keycape-{client_id}-eso
|
||||
body: "path \"platform/data/workloads/keycape/{client_id}\" {{\n capabilities\
|
||||
\ = [\"read\"]\n}}\n"
|
||||
description: KeyCape reads its client secret only through ESO. No metadata, list,
|
||||
parent or sibling access.
|
||||
- id: consumer-reader-policy
|
||||
kind: openbao_policy
|
||||
when: client_type == confidential
|
||||
template: workload-kv-read-keycape-{client_id}-{consuming_service}
|
||||
body: "path \"platform/data/workloads/keycape/{client_id}\" {{\n capabilities\
|
||||
\ = [\"read\"]\n}}\n"
|
||||
description: The consuming service reads the same secret. No metadata, list, parent
|
||||
or sibling access.
|
||||
- id: eso-role
|
||||
kind: openbao_role
|
||||
when: client_type == confidential
|
||||
template: external-secrets-keycape-{client_id}
|
||||
body: 'auth: kubernetes
|
||||
|
||||
bound_service_account_names: [external-secrets]
|
||||
|
||||
bound_service_account_namespaces: [external-secrets]
|
||||
|
||||
token_policies: [workload-kv-read-keycape-{client_id}-eso]
|
||||
|
||||
token_no_default_policy: true
|
||||
|
||||
token_ttl: 15m
|
||||
|
||||
token_max_ttl: 15m
|
||||
|
||||
'
|
||||
description: The Kubernetes-auth role deliver-secret uses; bound to the ESO service
|
||||
account only.
|
||||
- id: consumer-eso-role
|
||||
kind: openbao_role
|
||||
when: client_type == confidential
|
||||
template: external-secrets-keycape-{client_id}-{consuming_service}
|
||||
body: 'auth: kubernetes
|
||||
|
||||
bound_service_account_names: [{consuming_service}-keycape-{client_id}-eso]
|
||||
|
||||
bound_service_account_namespaces: [{consumer_namespace}]
|
||||
|
||||
audience: openbao
|
||||
|
||||
token_policies: [workload-kv-read-keycape-{client_id}-{consuming_service}]
|
||||
|
||||
token_no_default_policy: true
|
||||
|
||||
token_ttl: 15m
|
||||
|
||||
token_max_ttl: 15m
|
||||
|
||||
'
|
||||
description: Consumer ESO requests a token for this separate reference identity.
|
||||
Common ESO controller remains trusted and can request tokens; no cryptographic
|
||||
controller isolation is claimed.
|
||||
- id: catalog-entry
|
||||
kind: catalog_entry
|
||||
template: '{consuming_service}-keycape-client'
|
||||
body: 'id: {consuming_service}-keycape-client
|
||||
|
||||
owner_repo: key-cape
|
||||
|
||||
warden_executes: false
|
||||
|
||||
risk: high
|
||||
|
||||
status: active once verification passes
|
||||
|
||||
workload_ref: applicable, name {consuming_service}, declaration_ref of the consumer''s
|
||||
published declaration or the explicit unknown form, never inferred
|
||||
|
||||
path_template: platform/workloads/keycape/{client_id}
|
||||
|
||||
field: CLIENT_SECRET
|
||||
|
||||
delegation: native, intended_owner key-cape
|
||||
|
||||
rotation: mint-secret then verification; automatable false until a run has been
|
||||
proven
|
||||
|
||||
'
|
||||
description: One entry per case (ops-mason item 5, ops-warden R4'). It carries
|
||||
the consumer's workload reference, which ADR-0009 needs for zone selection.
|
||||
follow_through:
|
||||
- id: ensure-groups
|
||||
owner: net-kingdom
|
||||
entry_point: identity-provisioner ensure_service_groups, run inside the provisioner
|
||||
pod through the session's contained cluster access (groups {access_groups};
|
||||
members exactly {initial_members} as recorded in the accepted case, nothing
|
||||
else)
|
||||
auth: operator cluster access in the attended register-client session; the in-pod
|
||||
call uses the provisioner's own directory binding, and no provisioner or user-engine
|
||||
token is read or sent
|
||||
lane: key-cape-oidc-login
|
||||
warden_executes: false
|
||||
attended: true
|
||||
value_handling: none
|
||||
attended_justification: The provisioner's only HTTP credential is user-engine's
|
||||
runtime token, and its NetworkPolicy admits only user-engine pods. A proxy lane
|
||||
would act as user-engine (ops-warden review R8; canon section 3; ops-warden
|
||||
ADR-0002). Running it in the session register-client already needs adds no attended
|
||||
session. It can become unattended once the provisioner has an operator credential
|
||||
of its own and an admitted path.
|
||||
- id: mint-secret
|
||||
owner: railiance-platform
|
||||
when: client_type == confidential
|
||||
entry_point: 'railiance-platform credential broker: generate a client secret inside
|
||||
custody at bao:platform/workloads/keycape/{client_id}'
|
||||
auth: the caller's broker grant for the case's KV path, through its lane; the
|
||||
value is generated in custody and never returned
|
||||
lane: keycape-client-secret-generate
|
||||
warden_executes: true
|
||||
attended: false
|
||||
value_handling: generated_in_custody
|
||||
- id: deliver-secret
|
||||
owner: railiance-platform
|
||||
when: client_type == confidential
|
||||
entry_point: ExternalSecret sso/keycape-{client_id}-client (key client-secret)
|
||||
from bao:platform/workloads/keycape/{client_id}
|
||||
auth: railiance-platform ESO delivery through role external-secrets-keycape-{client_id};
|
||||
no value leaves custody
|
||||
warden_executes: false
|
||||
attended: false
|
||||
value_handling: none
|
||||
ready_check: the delivery for sso/keycape-{client_id}-client reports Ready=True
|
||||
(status only, no value read)
|
||||
- id: bind-env
|
||||
owner: net-kingdom
|
||||
when: client_type == confidential
|
||||
entry_point: 'patch Deployment sso/keycape: env KEYCAPE_{client_id:env}_CLIENT_SECRET
|
||||
from sso/keycape-{client_id}-client'
|
||||
auth: operator kube credentials for namespace sso
|
||||
lane: key-cape-oidc-login
|
||||
warden_executes: false
|
||||
attended: true
|
||||
value_handling: none
|
||||
attended_justification: A change to the live identity provider's Deployment. It
|
||||
runs in the same attended operator session as register-client, before it, because
|
||||
KeyCape resolves a confidential client's secret at start and fails closed if
|
||||
the binding is missing.
|
||||
- id: register-client
|
||||
owner: net-kingdom
|
||||
entry_point: sso-mfa/k8s/keycape/keycape-client.py apply --client-file <client-from-case>
|
||||
--case-acceptance <record> --check-config <keycape binary> (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
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue