diff --git a/docs/proposals/2026-10-11-forgejo-consumer-eso/case-1.2.yaml b/docs/proposals/2026-10-11-forgejo-consumer-eso/case-1.2.yaml new file mode 100644 index 0000000..8c7c4bc --- /dev/null +++ b/docs/proposals/2026-10-11-forgejo-consumer-eso/case-1.2.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/docs/proposals/2026-10-11-forgejo-consumer-eso/render-1.2.json b/docs/proposals/2026-10-11-forgejo-consumer-eso/render-1.2.json new file mode 100644 index 0000000..02cf311 --- /dev/null +++ b/docs/proposals/2026-10-11-forgejo-consumer-eso/render-1.2.json @@ -0,0 +1,385 @@ +{ + "apiVersion": "netkingdom.io/security-case-render/v0.1", + "case": "forgejo-netkingdom-oidc", + "composition": { + "apiVersion": "netkingdom.io/security-scenario-composition/v0.1", + "authority": "netkingdom", + "capability_providers": { + "c1.lightweight-sso": "net-kingdom.keycape-client-registration" + }, + "composition_digest": "sha256:f51e45eab2f2c15c93e2f7b8ef7d8fcc1daf1059da5749429ff5678b45c5214f", + "execution": { + "mode": "plan-only", + "permitted": false, + "reason": "Composition does not authorize or perform provider execution." + }, + "execution_steps": [ + { + "capabilities": [ + "c1.lightweight-sso" + ], + "declaration_id": "net-kingdom.keycape-client-registration", + "entry_point": { + "description": "Add or remove exactly one client in the live KeyCape client registry without exporting secret values: contained kubectl, cluster and issuer pins, byte-preserving merge, compare-and-swap, read-back. Replaces the per-client helpers beside it. Field rules follow key-cape's canonical model (KEY-WP-0028). Modes: inspect, dry-run, apply; operations add and remove.", + "invocation": "keycape-client.py apply --client-file --case-acceptance --expected-uid --expected-resource-version ", + "path": "sso-mfa/k8s/keycape/keycape-client.py", + "type": "cli-sequence" + }, + "executor_owner": "net-kingdom", + "order": 1, + "parameters": { + "allowed_scopes": { + "sensitivity": "security_sensitive", + "source": "override", + "tuning_authority": "netkingdom_tunable", + "value": "openid,profile,email,groups" + }, + "client_id": { + "sensitivity": "operational", + "source": "override", + "tuning_authority": "netkingdom_tunable", + "value": "forgejo" + }, + "client_type": { + "sensitivity": "security_sensitive", + "source": "override", + "tuning_authority": "netkingdom_tunable", + "value": "confidential" + }, + "display_name": { + "sensitivity": "public", + "source": "override", + "tuning_authority": "netkingdom_tunable", + "value": "Forgejo source forge" + }, + "mfa_required": { + "sensitivity": "security_sensitive", + "source": "override", + "tuning_authority": "netkingdom_tunable", + "value": "true" + }, + "redirect_uris": { + "sensitivity": "security_sensitive", + "source": "override", + "tuning_authority": "netkingdom_tunable", + "value": "https://forgejo.coulomb.social/user/oauth2/netkingdom/callback" + } + }, + "readiness_obligations": [ + { + "checks": [ + { + "description": "The authorization endpoint accepts the client with each registered redirect URI.", + "evidence": "GET /authorize with client_id and each redirect_uri returns the login page, not an error.", + "id": "client-authorize-accepts-registered-redirect" + }, + { + "description": "The authorization endpoint refuses an unregistered redirect URI for the client.", + "evidence": "GET /authorize with an unregistered redirect_uri returns an OAuth error.", + "id": "client-authorize-refuses-other-redirect" + } + ], + "state": "tenant_onboarding_trust" + } + ], + "repo": "net-kingdom", + "requires_trust": [ + { + "readiness_checks": [], + "state": "runtime_secret_trust" + }, + { + "readiness_checks": [], + "state": "runtime_identity_trust" + } + ], + "satisfies_trust": [ + { + "readiness_checks": [ + { + "description": "The authorization endpoint accepts the client with each registered redirect URI.", + "evidence": "GET /authorize with client_id and each redirect_uri returns the login page, not an error.", + "id": "client-authorize-accepts-registered-redirect" + }, + { + "description": "The authorization endpoint refuses an unregistered redirect URI for the client.", + "evidence": "GET /authorize with an unregistered redirect_uri returns an OAuth error.", + "id": "client-authorize-refuses-other-redirect" + } + ], + "state": "tenant_onboarding_trust" + } + ] + } + ], + "initial_trust": [ + "runtime_identity_trust", + "runtime_secret_trust" + ], + "kind": "SecurityScenarioComposition", + "planned_final_trust": [ + "runtime_identity_trust", + "runtime_secret_trust", + "tenant_onboarding_trust" + ], + "requested_capabilities": [ + "c1.lightweight-sso" + ], + "responsibility_map": [ + { + "declaration_id": "net-kingdom.keycape-client-registration", + "netkingdom_orchestrates": "Supply the case's validated, non-secret client fields.", + "owner": "net-kingdom", + "repo_owns": "Live registry change for exactly this client, its idempotency and removal; field rules are key-cape's canonical model.", + "resource_kind": "identities", + "resources": [ + "oidc:static-clients" + ] + }, + { + "declaration_id": "net-kingdom.keycape-client-registration", + "netkingdom_orchestrates": "Choose scopes and MFA posture per SecurityCaseType.", + "owner": "key-cape", + "repo_owns": "Enforce exact redirect URIs, allowed scopes and the MFA pin at authorization time.", + "resource_kind": "roles_scopes_policies", + "resources": [ + "iam-profile:client-scope-allowlists" + ] + } + ], + "scenario": "scenario:case:forgejo-netkingdom-oidc" + }, + "digest": "sha256:c0afd5576cdae0cbc807eccb2b9fa87ac668f15e32ec7cf79d295bdb23c75b35", + "execution": { + "permitted": false + }, + "follow_through": [ + { + "attended": true, + "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.", + "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", + "entry_point": "identity-provisioner ensure_service_groups, run inside the provisioner pod through the session's contained cluster access (groups forge-admins,forge-coulomb-owners,forge-coulomb-readers; members exactly forge-admins=tegwick;forge-coulomb-owners=tegwick as recorded in the accepted case, nothing else)", + "id": "ensure-groups", + "lane": "key-cape-oidc-login", + "owner": "net-kingdom", + "value_handling": "none", + "warden_executes": false + }, + { + "attended": false, + "auth": "the caller's broker grant for the case's KV path, through its lane; the value is generated in custody and never returned", + "entry_point": "railiance-platform credential broker: generate a client secret inside custody at bao:platform/workloads/keycape/forgejo", + "id": "mint-secret", + "lane": "keycape-client-secret-generate", + "owner": "railiance-platform", + "value_handling": "generated_in_custody", + "warden_executes": true + }, + { + "attended": false, + "auth": "railiance-platform ESO delivery through role external-secrets-keycape-forgejo; no value leaves custody", + "entry_point": "ExternalSecret sso/keycape-forgejo-client (key client-secret) from bao:platform/workloads/keycape/forgejo", + "id": "deliver-secret", + "owner": "railiance-platform", + "ready_check": "the delivery for sso/keycape-forgejo-client reports Ready=True (status only, no value read)", + "value_handling": "none", + "warden_executes": false + }, + { + "attended": true, + "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.", + "auth": "operator kube credentials for namespace sso", + "entry_point": "patch Deployment sso/keycape: env KEYCAPE_FORGEJO_CLIENT_SECRET from sso/keycape-forgejo-client", + "id": "bind-env", + "lane": "key-cape-oidc-login", + "owner": "net-kingdom", + "value_handling": "none", + "warden_executes": false + }, + { + "attended": true, + "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).", + "auth": "operator write access to the live KeyCape client registry in namespace sso", + "entry_point": "sso-mfa/k8s/keycape/keycape-client.py apply --client-file --case-acceptance --check-config (net-kingdom.keycape-client-registration)", + "id": "register-client", + "lane": "key-cape-oidc-login", + "owner": "net-kingdom", + "value_handling": "none", + "warden_executes": false + }, + { + "attended": false, + "auth": "Consumer owner contained Kubernetes deployment authority; ESO authenticates to OpenBao role external-secrets-keycape-forgejo-forgejo with a TokenRequest for the dedicated namespaced serviceAccountRef; controller remains trusted", + "entry_point": "Owner applies dedicated ServiceAccount forgejo/forgejo-keycape-forgejo-eso (automount=false, no legacy tokens), namespace SecretStore openbao-keycape-forgejo-consumer with serviceAccountRef and audiences [openbao], and ExternalSecret forgejo-netkingdom-oidc-client with Owner target, Retain remote deletion and only CLIENT_SECRET from workloads/keycape/forgejo. Admission validates actual installed ESO TokenRequest support and common controller RBAC before any owner-approved apply.", + "id": "deliver-consumer-secret", + "owner": "railiance-apps", + "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.", + "value_handling": "none", + "warden_executes": false + }, + { + "attended": false, + "auth": "the consumer owner's own deployment path", + "entry_point": "configure forgejo with issuer https://kc.coulomb.social, client forgejo and custody bao:platform/workloads/keycape/forgejo, and make it require one of forge-admins,forge-coulomb-owners,forge-coulomb-readers in the groups claim before sign-in completes", + "id": "hand-over", + "owner": "railiance-apps", + "value_handling": "none", + "warden_executes": false + } + ], + "kind": "SecurityCaseRender", + "materialization": [ + { + "body": "field CLIENT_SECRET; minted by the credential broker, never written by hand", + "id": "client-secret-path", + "kind": "kv_path", + "template": "platform/workloads/keycape/forgejo" + }, + { + "body": "path \"platform/data/workloads/keycape/forgejo\" {\n capabilities = [\"read\"]\n}\n", + "description": "KeyCape reads its client secret only through ESO. No metadata, list, parent or sibling access.", + "id": "keycape-reader-policy", + "kind": "openbao_policy", + "template": "workload-kv-read-keycape-forgejo-eso" + }, + { + "body": "path \"platform/data/workloads/keycape/forgejo\" {\n capabilities = [\"read\"]\n}\n", + "description": "The consuming service reads the same secret. No metadata, list, parent or sibling access.", + "id": "consumer-reader-policy", + "kind": "openbao_policy", + "template": "workload-kv-read-keycape-forgejo-forgejo" + }, + { + "body": "auth: kubernetes\nbound_service_account_names: [external-secrets]\nbound_service_account_namespaces: [external-secrets]\ntoken_policies: [workload-kv-read-keycape-forgejo-eso]\ntoken_no_default_policy: true\ntoken_ttl: 15m\ntoken_max_ttl: 15m\n", + "description": "The Kubernetes-auth role deliver-secret uses; bound to the ESO service account only.", + "id": "eso-role", + "kind": "openbao_role", + "template": "external-secrets-keycape-forgejo" + }, + { + "body": "auth: kubernetes\nbound_service_account_names: [forgejo-keycape-forgejo-eso]\nbound_service_account_namespaces: [forgejo]\naudience: openbao\ntoken_policies: [workload-kv-read-keycape-forgejo-forgejo]\ntoken_no_default_policy: true\ntoken_ttl: 15m\ntoken_max_ttl: 15m\n", + "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": "consumer-eso-role", + "kind": "openbao_role", + "template": "external-secrets-keycape-forgejo-forgejo" + }, + { + "body": "id: forgejo-keycape-client\nowner_repo: key-cape\nwarden_executes: false\nrisk: high\nstatus: active once verification passes\nworkload_ref: applicable, name forgejo, declaration_ref of the consumer's published declaration or the explicit unknown form, never inferred\npath_template: platform/workloads/keycape/forgejo\nfield: CLIENT_SECRET\ndelegation: native, intended_owner key-cape\nrotation: mint-secret then verification; automatable false until a run has been proven\n", + "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.", + "id": "catalog-entry", + "kind": "catalog_entry", + "template": "forgejo-keycape-client" + } + ], + "rollback": [ + { + "action": "remove the OIDC source for forgejo from forgejo (owner railiance-apps)", + "reverses": "hand-over" + }, + { + "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": "deliver-consumer-secret" + }, + { + "action": "keycape-client.py apply --operation remove for forgejo", + "reverses": "register-client" + }, + { + "action": "remove env KEYCAPE_FORGEJO_CLIENT_SECRET from Deployment sso/keycape, after register-client is reversed", + "reverses": "bind-env" + }, + { + "action": "delete ExternalSecret sso/keycape-forgejo-client and its target", + "reverses": "deliver-secret" + }, + { + "action": "covered by client-secret-path: one metadata delete, after deliver-secret is reversed", + "reverses": "mint-secret" + }, + { + "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 forge-admins,forge-coulomb-owners,forge-coulomb-readers", + "reverses": "ensure-groups" + }, + { + "action": "delete metadata and all versions at platform/workloads/keycape/forgejo, after the ExternalSecret is gone (this also reverses mint-secret)", + "reverses": "client-secret-path" + }, + { + "action": "delete Kubernetes-auth role external-secrets-keycape-forgejo", + "reverses": "eso-role" + }, + { + "action": "delete policy workload-kv-read-keycape-forgejo-eso, after eso-role", + "reverses": "keycape-reader-policy" + }, + { + "action": "Delete only this case-created role external-secrets-keycape-forgejo-forgejo, before deleting consumer-reader-policy; revoke case-issued OpenBao tokens or prove expiration before declaring deactivation.", + "reverses": "consumer-eso-role" + }, + { + "action": "delete policy workload-kv-read-keycape-forgejo-forgejo", + "reverses": "consumer-reader-policy" + }, + { + "action": "remove catalog entry forgejo-keycape-client", + "reverses": "catalog-entry" + } + ], + "type": "oidc-browser-relying-party@1.2", + "verification": [ + { + "check": "GET https://kc.coulomb.social/authorize with client forgejo and each of https://forgejo.coulomb.social/user/oauth2/netkingdom/callback returns the login page", + "expect": "present", + "id": "authorize-accepts-redirects", + "reads_secret_value": false + }, + { + "check": "GET https://kc.coulomb.social/authorize with client forgejo and an unregistered redirect returns an OAuth error", + "expect": "deny", + "id": "authorize-refuses-other-redirect", + "reads_secret_value": false + }, + { + "check": "a default-only OpenBao identity has no read capability on bao:platform/workloads/keycape/forgejo", + "expect": "deny", + "id": "custody-denied-to-default", + "reads_secret_value": false + }, + { + "check": "policy workload-kv-read-keycape-forgejo-forgejo grants read on bao:platform/workloads/keycape/forgejo (capabilities check only)", + "expect": "allow", + "id": "custody-allowed-to-consumer", + "reads_secret_value": false + }, + { + "check": "LLDAP groups forge-admins,forge-coulomb-owners,forge-coulomb-readers exist, with exactly the memberships of the accepted case added", + "expect": "present", + "id": "groups-present", + "reads_secret_value": false + }, + { + "check": "forgejo's OIDC source for forgejo (owner railiance-apps) requires one of forge-admins,forge-coulomb-owners,forge-coulomb-readers in the groups claim (configuration read, no secret value)", + "expect": "present", + "id": "consumer-enforces-groups", + "reads_secret_value": false + }, + { + "check": "the delivery for sso/keycape-forgejo-client reports Ready=True (status only)", + "expect": "present", + "id": "secret-delivered", + "reads_secret_value": false + }, + { + "check": "keycape-client.py inspect for forgejo shows the MFA pin on the registered client (non-secret client view)", + "expect": "present", + "id": "mfa-pinned", + "reads_secret_value": false + }, + { + "check": "forgejo SecretStore openbao-keycape-forgejo-consumer and ExternalSecret forgejo-netkingdom-oidc-client Ready=True, exact dedicated SA/audience role binding, fixed CLIENT_SECRET mapping; no Secret value read", + "expect": "present", + "id": "consumer-secret-delivered", + "reads_secret_value": false + } + ] +} diff --git a/docs/proposals/2026-10-11-forgejo-consumer-eso/review-boundary.md b/docs/proposals/2026-10-11-forgejo-consumer-eso/review-boundary.md new file mode 100644 index 0000000..0f3df18 --- /dev/null +++ b/docs/proposals/2026-10-11-forgejo-consumer-eso/review-boundary.md @@ -0,0 +1,5 @@ +# Proposed successor 1.2 review boundary + +Review type-1.2.yaml and case-1.2.yaml as proposed source alongside the consumer owner's concrete delivery design and CCR42 body. Existing accepted1.1 type/case and full run source remain unchanged. Adding a dedicated consumer role changes the structural inventory from five to six; no structural-equality shortcut may inherit old acceptance for that sixth object. The old five bodies compare exactly unchanged. Proposed type passes current native owner validator; direct source render passes current composition resolver. Mason intentionally refuses proposed source until acknowledgment, and no fixture acceptance is a founder receipt. + +Exact owner returns must agree on consumer namespace/SA/audience, common ESO trust, policy and role naming, generic TokenRequest semantics, created-only rollback, consumer group enforcement, and full current follow-through provider/source pins. Existing native per-owner evidence and session/revocation/machine-descriptor gates remain pending. Source preparation creates no policy, role, service account, value or client and marks no case materialized/live. diff --git a/docs/proposals/2026-10-11-forgejo-consumer-eso/type-1.2.yaml b/docs/proposals/2026-10-11-forgejo-consumer-eso/type-1.2.yaml new file mode 100644 index 0000000..89b9f6a --- /dev/null +++ b/docs/proposals/2026-10-11-forgejo-consumer-eso/type-1.2.yaml @@ -0,0 +1,442 @@ +apiVersion: netkingdom.io/security-case-type/v0.1 +kind: SecurityCaseType +spec: + id: oidc-browser-relying-party + version: '1.2' + status: proposed + 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 + --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/docs/reviews/2026-10-11-forgejo-consumer-eso-net-owner-final-review.md b/docs/reviews/2026-10-11-forgejo-consumer-eso-net-owner-final-review.md new file mode 100644 index 0000000..d3e6c55 --- /dev/null +++ b/docs/reviews/2026-10-11-forgejo-consumer-eso-net-owner-final-review.md @@ -0,0 +1,75 @@ +--- +reviewer: net-kingdom-owner (agent net-kingdom, codex) +decision: approved +work_item: NK-WP-ADHOC-2026-10-11-T05 +reviewed_manifest_sha256: 5dbd04cf96d73a2604cbf113073d618c03434fc87508ba614cbe3820a1a0e431 +scope: final-nineteen-path-proposed-source-technical-review-only +--- + +# NetKingdom final Forgejo consumer ESO source review + +Technical agreement on exact nineteen-path manifest +5dbd04cf96d73a2604cbf113073d618c03434fc87508ba614cbe3820a1a0e431 under completed +own NK-WP-ADHOC-2026-10-11-T05. This is the same NetKingdom role only; apply the +work record before this formal entry. Original SHA guards preserve already +applied T03/T04 and any State Hub UUIDs. The earlier271 review and its evidence +remain historical; they are not claimed as an exact review of this final source. + +INTENT's Taxonomy declaration, Identity is the Control Plane, Minimize Threat +Exposure and Meta-Orchestration principles support truthful consumer identity, +inspectable canonical contracts and separate owner-executed acceptance. The two +Platform counterexamples touched that contract: an incorrectly generated keycape +consumer identity and delete-only lifecycle wording. Builder source SHA256 +c2b140f380407779ce5478ca57c97eb0e6375d6a9cad4591b0b29ddd177db686 corrects them +without changing canonical proposed type/case or its six-object render. + +Independently checked all19 hashes and seven current source pins, preparation +validators, refusal of proposed source by normal implemented-type admission and +full regeneration of render +sha256:c0afd5576cdae0cbc807eccb2b9fa87ac668f15e32ec7cf79d295bdb23c75b35. +execution.permitted stays false. Direct isolated projections reproduce both +failures against preserved271 builder and verify the corrected generated CCR +against its exact retained projection. The consumer target is forgejo, KeyCape +reader output matches the earlier builder exactly, and unbound consumer output +changes only the previously incorrect workload field. No fixture provenance or +private projection call is accepted-case/native evidence. Fresh distinct Mason +and Platform owner receipts pin this exact final manifest and each report44 +independently rerun focused passes; neither is a native installation receipt. + +The generator requires consumer-reference recovery, independently proved +case-created ownership, preservation of preexisting/shared objects, owner issued +reader-token revocation or independently verified expiry, no new login/remint, +retained receipts and refusal on changed references/UIDs/ownership. These are +obligations, not an implemented revocation adapter or recovery permission. +Canonical/manual proposed rollback still orders role before policy and requires +revocation/expiry before removal of the created role; deleting role/SA/store alone +never proves token deactivation. Historical1.1 bundles/CCR history are preserved: +the old wrongly targeted bundle now correctly fails matching. A corrected source +build/bundle needs fresh exact owner reconciliation after successor acceptance; +old approvals are not silently reassigned and the verifier is not weakened. + +All earlier exact271 identity/trust/acceptance boundaries remain applicable: +forgejo/forgejo-keycape-forgejo-eso only, namespace forgejo, audience openbao, +exact CLIENT_SECRET data read and no default policy. Forgejo/runner default SA +must never bind. Dedicated automount=false identity must have no legacy token +refs; no static fallback. Shared ESO controller authority and existing HTTP +custody remain disclosed rather than described as isolation. Delivery applies +only three admitted namespaced objects and acquires no deletion authority over +matched/shared target objects. + +The sixth structural role changes authentication/materialization under +SecurityCaseTypes §6 and therefore needs a new founder informed-decision +acknowledgment as for a new type, regardless of proposed1.2 label. Existing +acknowledgedtype1.1/acceptedcase1.1 cannot authorize it. Pending claims still +block apply. No type/case acknowledgment, implemented marker, broker pin bypass, +role/policy grant, source materialization, installed adapter/session or live go +follows from this review. Refresh exact ESO/native identity metadata; obtain +independent admitted bindings, capability/creation receipts and Warden native +session/revocation/descriptors before their existing acceptance steps. + +Helm secret consumption/group enforcement, break-glass/account-link/MFA and +positive/negative browser checks stay separate owner/project gates. Delivery +Ready and source tests do not complete the first case. Existing ORGREF/NK0048, +Mason, Warden, Platform and consumer work records retain that work; no duplicate +plan or new standing authority is introduced. No further NetKingdom source +correction is required in this exact final candidate. diff --git a/docs/reviews/2026-10-11-forgejo-consumer-eso-net-owner-final-review.sources.json b/docs/reviews/2026-10-11-forgejo-consumer-eso-net-owner-final-review.sources.json new file mode 100644 index 0000000..17eefd3 --- /dev/null +++ b/docs/reviews/2026-10-11-forgejo-consumer-eso-net-owner-final-review.sources.json @@ -0,0 +1,191 @@ +{ + "independent_checks": { + "exact_manifest_sha256": "5dbd04cf96d73a2604cbf113073d618c03434fc87508ba614cbe3820a1a0e431", + "verified_files": 19, + "all_seven_current_source_pins_match": true, + "type_case_preparation_validation_pass": true, + "runtime_admission_of_proposed_type_refused": true, + "render_regeneration_identical": true, + "render_digest": "sha256:c0afd5576cdae0cbc807eccb2b9fa87ac668f15e32ec7cf79d295bdb23c75b35", + "prior271_wrong_consumer_target_counterexample_reproduced": true, + "prior271_missing_recovery_guards_counterexample_reproduced": true, + "corrected_generated_projection_verified": true, + "keycape_projection_unchanged": true, + "unbound_consumer_projection_only_workload_changed": true, + "native_mutation": false, + "execution_permitted": false + }, + "reviewed_proposal_files": [ + { + "repo": "railiance-apps", + "path": "docs/proposals/2026-10-11-forgejo-consumer-eso/consumer-delivery.yaml", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/railiance-apps/docs/proposals/2026-10-11-forgejo-consumer-eso/consumer-delivery.yaml", + "original_sha256": null, + "staged_sha256": "56478a83d799c08dc1e5159983b1e843a46b16dfeee7e84c31401d1f92430df2" + }, + { + "repo": "railiance-apps", + "path": "docs/proposals/2026-10-11-forgejo-consumer-eso/native-metadata.json", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/railiance-apps/docs/proposals/2026-10-11-forgejo-consumer-eso/native-metadata.json", + "original_sha256": null, + "staged_sha256": "4e2993f5920215f41e4a235743023f22b78b8f597d3d70ed279991b2fc3204b5" + }, + { + "repo": "railiance-apps", + "path": "docs/proposals/2026-10-11-forgejo-consumer-eso/observe-native-metadata.py", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/railiance-apps/docs/proposals/2026-10-11-forgejo-consumer-eso/observe-native-metadata.py", + "original_sha256": null, + "staged_sha256": "3732aa0ff45b5197ac7837cbc5814f59ea3d694d4a157d19d00711f29da76913" + }, + { + "repo": "railiance-apps", + "path": "docs/proposals/2026-10-11-forgejo-consumer-eso/owner-design.md", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/railiance-apps/docs/proposals/2026-10-11-forgejo-consumer-eso/owner-design.md", + "original_sha256": null, + "staged_sha256": "c523949454e4c6eb58e8caee382380a561f561704136de62bf5783c592f962f2" + }, + { + "repo": "railiance-apps", + "path": "docs/proposals/2026-10-11-forgejo-consumer-eso/owner-source-pins.json", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/railiance-apps/docs/proposals/2026-10-11-forgejo-consumer-eso/owner-source-pins.json", + "original_sha256": null, + "staged_sha256": "775971a60db57f7334f68b0916a27760e28f02c62f2c653e963237925a1c2711" + }, + { + "repo": "railiance-apps", + "path": "docs/proposals/2026-10-11-forgejo-consumer-eso/primary-source-provenance.json", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/railiance-apps/docs/proposals/2026-10-11-forgejo-consumer-eso/primary-source-provenance.json", + "original_sha256": null, + "staged_sha256": "c3d5ce5c6a5e89f19be5e293034c8d633183d19666fc61d837537527246d9a42" + }, + { + "repo": "railiance-apps", + "path": "docs/proposals/2026-10-11-forgejo-consumer-eso/validation.json", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/railiance-apps/docs/proposals/2026-10-11-forgejo-consumer-eso/validation.json", + "original_sha256": null, + "staged_sha256": "95318f54942871a125a5200ec05d6f9dc80077918f26ebe671b9ab4d150b112d" + }, + { + "repo": "railiance-platform", + "path": "docs/proposals/2026-10-11-forgejo-consumer-eso/CCR-2026-0042-proposed-body.yaml", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/railiance-platform/docs/proposals/2026-10-11-forgejo-consumer-eso/CCR-2026-0042-proposed-body.yaml", + "original_sha256": null, + "staged_sha256": "6544600c63a86559ba053240c476d493f4d2f25c9cd22cf6a9a05f09ee617a86" + }, + { + "repo": "railiance-platform", + "path": "docs/proposals/2026-10-11-forgejo-consumer-eso/reader-role.json", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/railiance-platform/docs/proposals/2026-10-11-forgejo-consumer-eso/reader-role.json", + "original_sha256": null, + "staged_sha256": "976b19e0780b6056ed54bf5e8f27a0eb786af65817d9ec00ca161ac46e7d72e7" + }, + { + "repo": "railiance-platform", + "path": "docs/proposals/2026-10-11-forgejo-consumer-eso/workload-kv-read-keycape-forgejo-forgejo.hcl", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/railiance-platform/docs/proposals/2026-10-11-forgejo-consumer-eso/workload-kv-read-keycape-forgejo-forgejo.hcl", + "original_sha256": null, + "staged_sha256": "af3a638605c1f6dff7879771fede4c56a6b9a7e430d4b5b58c370063b2c888ca" + }, + { + "repo": "net-kingdom", + "path": "docs/proposals/2026-10-11-forgejo-consumer-eso/case-1.2.yaml", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/net-kingdom/docs/proposals/2026-10-11-forgejo-consumer-eso/case-1.2.yaml", + "original_sha256": null, + "staged_sha256": "1c868c1da7d9077fae97bc6bc029706ec3dc418cfeaae30dc0f92b5b4ba6f2ab" + }, + { + "repo": "net-kingdom", + "path": "docs/proposals/2026-10-11-forgejo-consumer-eso/render-1.2.json", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/net-kingdom/docs/proposals/2026-10-11-forgejo-consumer-eso/render-1.2.json", + "original_sha256": null, + "staged_sha256": "96b25108335e2cf5f96af481fe8a7735831c8320d81b50f7c6e6d4e53d0c0f02" + }, + { + "repo": "net-kingdom", + "path": "docs/proposals/2026-10-11-forgejo-consumer-eso/review-boundary.md", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/net-kingdom/docs/proposals/2026-10-11-forgejo-consumer-eso/review-boundary.md", + "original_sha256": null, + "staged_sha256": "21c8d666a46490f829cfb9c043ea168ad1c02873dc6baf7e50173188e0c99ea9" + }, + { + "repo": "net-kingdom", + "path": "docs/proposals/2026-10-11-forgejo-consumer-eso/type-1.2.yaml", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/net-kingdom/docs/proposals/2026-10-11-forgejo-consumer-eso/type-1.2.yaml", + "original_sha256": null, + "staged_sha256": "017885bdd139cd66a5bf6d9839b1b8ec9bc08fb051d9577adc3928b76a7be6db" + }, + { + "repo": "ops-mason", + "path": "docs/forgejo-consumer-eso-builder-review.md", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/ops-mason/docs/forgejo-consumer-eso-builder-review.md", + "original_sha256": null, + "staged_sha256": "27d20e4d6915a8d16d65e4fcdf20cd565b2742d6bc2a0999a8ec21522fb0a590" + }, + { + "repo": "ops-mason", + "path": "docs/forgejo-consumer-generated-ccr-refinement.json", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/ops-mason/docs/forgejo-consumer-generated-ccr-refinement.json", + "original_sha256": null, + "staged_sha256": "29aabe3e5d1f9c3c55a1d0c2580da89a97e707600358232f4c0bd79f02c8442e" + }, + { + "repo": "ops-mason", + "path": "src/ops_mason/case_build.py", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/ops-mason/src/ops_mason/case_build.py", + "original_sha256": "249cc8574939d2c3193f968309781c472c96c199e04206c336463b4d65ea6659", + "staged_sha256": "c2b140f380407779ce5478ca57c97eb0e6375d6a9cad4591b0b29ddd177db686" + }, + { + "repo": "ops-mason", + "path": "tests/test_case_build.py", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/ops-mason/tests/test_case_build.py", + "original_sha256": "177e8feed5d1af9abe96522fb5399780b3199daed6bf360882398044357071bc", + "staged_sha256": "aea22297178b5bb1eaaf5d59bbd1c71112dfc32bed2075b33ccc0598c8fc5be5" + }, + { + "repo": "ops-mason", + "path": "tests/test_case_structure.py", + "staged_path": "/tmp/forgejo-consumer-eso-refinement-stage/ops-mason/tests/test_case_structure.py", + "original_sha256": "524e8567183b6989aa5791b8d85350771c15988833b0d5221ab082dc6a920ffb", + "staged_sha256": "2e7446eaf01d4bb59d7d8fb3c3cdc5e6e3007b3ae84d8ed0a49f11f745f2e386" + } + ], + "sources": [ + { + "path": "/home/worsch/net-kingdom/AGENTS.md", + "sha256": "065d47b7bdbfe829672a2a6161a7f8cf243237a1210fb61d82f153fa37f22131" + }, + { + "path": "/home/worsch/net-kingdom/INTENT.md", + "sha256": "fd2ba8dff9dfd5583ec6d8b0348f273bfe00c59923b5d5d47cd22b1fb4658c54" + }, + { + "path": "/home/worsch/net-kingdom/canon/standards/security-case-types_v0.1.md", + "sha256": "a4fda906d5138d2594a1f8d047c7c28e1cdf96b1eae051f543b9a5e5852bcb5e" + }, + { + "path": "/home/worsch/net-kingdom/canon/standards/security-layer-model_v0.8.md", + "sha256": "3d8298560069ef471fba28d2b1245fb2309328f231dad1a667cdf0ce5a5a7c8b" + }, + { + "path": "/home/worsch/net-kingdom/docs/reviews/2026-10-11-forgejo-consumer-eso-net-owner-review.md", + "sha256": "c9f2ce444de9007370a0b2ea68f9474054e46a403cbbb38232797b1395057e80" + }, + { + "path": "/home/worsch/net-kingdom/workplans/ADHOC-2026-10-11.md", + "sha256": "9910c22c0ad2b161543865610b72bff53ed00112005e2c2e3cc9a0db369664fe" + }, + { + "path": "/tmp/forgejo-eso-mason-independent-review/refined-return-stage/ops-mason/docs/evidence/2026-10-11-forgejo-consumer-eso-independent-mason-review-refined.json", + "sha256": "28541874fb437a06a8f1749bc50c88f6fee3d7c100c2f3ee0c52b59afaf8e102" + }, + { + "path": "/tmp/forgejo-platform-owner-review-stage/railiance-platform/docs/evidence/2026-10-11-forgejo-consumer-eso-owner-review/final-review.json", + "sha256": "72854a798e01c6d65a16770efb1329d211fe3c59a3f4ad3190d6972f5c886f6e" + }, + { + "path": "/tmp/forgejo-consumer-eso-refinement-original-271/manifest.json", + "sha256": "271afd04512b3dac642b3385013cac03d28afde22ff97bcca8d0e262ab3d9279" + } + ] +} diff --git a/workplans/ADHOC-2026-10-11.md b/workplans/ADHOC-2026-10-11.md index 9210040..533633f 100644 --- a/workplans/ADHOC-2026-10-11.md +++ b/workplans/ADHOC-2026-10-11.md @@ -93,3 +93,26 @@ or serving/deployment is inferred. Live successor adoption/publication is retained first as NET-IN-0004; INFD-IN-0007 stays open pending accepted voice. Gate House handoff completion is distinct from this source-owner's outstanding standard adoption. No finished INFD implementation plan is reopened. + +## Review the final nineteen-path Forgejo consumer ESO source revision + +```task +id: NK-WP-ADHOC-2026-10-11-T05 +status: done +priority: high +``` + +Final narrow NetKingdom source-owner review of manifest +5dbd04cf96d73a2604cbf113073d618c03434fc87508ba614cbe3820a1a0e431. +Retains T03 and its earlier271 proposal review as history, not current exact +acknowledgment. Verified all19 staged hashes, seven current source pins, proposed +type/case admission refusal, identical c0afd render and independent projections. +Both prior271 counterexamples reproduced: wrong consumer target and missing +created-only issued-token recovery guards. Corrected builder derives forgejo, +preserves KeyCape output and requires owner revocation or verified expiry, +created-only preservation and no recovery login/remint. Fresh Mason/Platform +owner44-test reports checked; no native proof inferred. Proposed type/case +need fresh founder acknowledgment under §6, source rebundle/reconciliation and +existing per-owner/native acceptance. No role/grant/materialization/runtime +change or first-case completion. Exact final review/sources retained in +docs/reviews/2026-10-11-forgejo-consumer-eso-net-owner-final-review.*.