Prepare reviewed Forgejo consumer ESO scope and truthful recovery records
Assistant: codex Assistant-Model: gpt-6.1-sol Assistant-Session: 01a126e1-76f8-7643-8cf3-e93336539ade
This commit is contained in:
parent
6180f87894
commit
c26b018328
7 changed files with 1142 additions and 0 deletions
21
docs/proposals/2026-10-11-forgejo-consumer-eso/case-1.2.yaml
Normal file
21
docs/proposals/2026-10-11-forgejo-consumer-eso/case-1.2.yaml
Normal file
|
|
@ -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
|
||||
385
docs/proposals/2026-10-11-forgejo-consumer-eso/render-1.2.json
Normal file
385
docs/proposals/2026-10-11-forgejo-consumer-eso/render-1.2.json
Normal file
|
|
@ -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 <client.yaml> --case-acceptance <record> --expected-uid <uid> --expected-resource-version <rv>",
|
||||
"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 <client-from-case> --case-acceptance <record> --check-config <keycape binary> (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
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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.
|
||||
442
docs/proposals/2026-10-11-forgejo-consumer-eso/type-1.2.yaml
Normal file
442
docs/proposals/2026-10-11-forgejo-consumer-eso/type-1.2.yaml
Normal file
|
|
@ -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 <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
|
||||
|
|
@ -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.
|
||||
|
|
@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -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.*.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue