Record reviewed case source evidence (6/13)
This commit is contained in:
parent
5c456215ea
commit
a4c1f893de
20 changed files with 1246 additions and 0 deletions
|
|
@ -0,0 +1,84 @@
|
|||
"""Four-file local source integration only. Default check; --apply writes files.
|
||||
|
||||
No staging, commit, sync, native call, credentials or NetKingdom mutation.
|
||||
"""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
|
||||
HERE = Path(__file__).resolve().parent
|
||||
BASE = '0a9617a62d4696a8070798923b459e8405c3dbf2'
|
||||
FILES = ('docs/keycape-issuer-eso-contract.md',
|
||||
'manifests/templates/keycape-issuer-eso.yaml',
|
||||
'scripts/keycape_issuer_eso.py', 'tests/test_keycape_issuer_eso.py')
|
||||
def sha(data):
|
||||
return hashlib.sha256(data).hexdigest()
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(__doc__)
|
||||
parser.add_argument('--repo', type=Path, default=Path('/home/worsch/railiance-platform'))
|
||||
parser.add_argument('--apply', action='store_true')
|
||||
args = parser.parse_args()
|
||||
repo = args.repo.resolve()
|
||||
env = {'PATH': '/usr/local/bin:/usr/bin:/bin', 'HOME': '/tmp', 'GIT_OPTIONAL_LOCKS': '0'}
|
||||
def git(*words):
|
||||
result = subprocess.run(['git', '-C', str(repo), *words], env=env,
|
||||
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
if result.returncode:
|
||||
raise SystemExit('Refused: local Git check failed; no command output emitted')
|
||||
return result.stdout
|
||||
if git('rev-parse', 'HEAD').decode().strip() != BASE:
|
||||
raise SystemExit('Refused: Platform HEAD changed; rebase/review exact inputs first')
|
||||
if Path(git('rev-parse', '--show-toplevel').decode().strip()).resolve() != repo:
|
||||
raise SystemExit('Refused: repository root differs')
|
||||
manifest = json.loads((HERE / 'manifest.json').read_text())
|
||||
entries = {x['path']: x for x in manifest['files']}
|
||||
if set(entries) != set(FILES) or len(manifest['files']) != 4:
|
||||
raise SystemExit('Refused: four-file scope differs')
|
||||
prepared = {}
|
||||
for name in FILES:
|
||||
target = repo / name
|
||||
for parent in (target, *target.parents):
|
||||
if parent == repo.parent:
|
||||
break
|
||||
if parent.is_symlink():
|
||||
raise SystemExit('Refused: target or parent is a symlink')
|
||||
if target.exists() or git('ls-files', '--', name):
|
||||
raise SystemExit('Refused: expected absent preimage differs: ' + name)
|
||||
data = (HERE / 'platform-source' / name).read_bytes()
|
||||
if sha(data) != entries[name]['sha256']:
|
||||
raise SystemExit('Refused: prepared source hash differs: ' + name)
|
||||
prepared[name] = data
|
||||
# Git status gets no lock; do not stage, refresh, reset or replace the index.
|
||||
excluded = [':(exclude)' + name for name in FILES]
|
||||
def state():
|
||||
index_name = git('rev-parse', '--git-path', 'index').decode().strip()
|
||||
index = Path(index_name)
|
||||
if not index.is_absolute():
|
||||
index = repo / index
|
||||
return {'other_status_sha256': sha(git('status', '--porcelain=v1', '-z',
|
||||
'--untracked-files=all', '--', '.', *excluded)),
|
||||
'index_sha256': sha(index.read_bytes()) if index.exists() else None}
|
||||
before = state()
|
||||
if not args.apply:
|
||||
print(json.dumps({'outcome': 'checked-no-write', 'files': list(FILES),
|
||||
'preserved_state': before}, indent=2))
|
||||
return
|
||||
# Exclusive creation independently refuses racing target creation.
|
||||
for name, data in prepared.items():
|
||||
target = repo / name
|
||||
target.parent.mkdir(parents=True, exist_ok=True)
|
||||
with target.open('xb') as stream:
|
||||
stream.write(data)
|
||||
after = state()
|
||||
if before != after:
|
||||
raise SystemExit('Refused: unrelated status or index changed during integration; inspect concurrency')
|
||||
if any(sha((repo / name).read_bytes()) != entries[name]['sha256'] for name in FILES):
|
||||
raise SystemExit('Refused: post-write verification failed')
|
||||
print(json.dumps({'outcome': 'applied-source-only', 'files': list(FILES),
|
||||
'before': before, 'after': after, 'workplan_changed': False,
|
||||
'source_owner_assent_inferred': False}, indent=2))
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"check": {
|
||||
"outcome": "checked-no-write",
|
||||
"files": [
|
||||
"docs/keycape-issuer-eso-contract.md",
|
||||
"manifests/templates/keycape-issuer-eso.yaml",
|
||||
"scripts/keycape_issuer_eso.py",
|
||||
"tests/test_keycape_issuer_eso.py"
|
||||
],
|
||||
"preserved_state": {
|
||||
"other_status_sha256": "b274ecee79380c3670afa2ff40790064bdbe0565ecea4cfc1eec586deb409990",
|
||||
"index_sha256": "9c08aefaf66ea19285e143e7c8f0de6402b340307391d7433ba2772b5dd02cf7"
|
||||
}
|
||||
},
|
||||
"applied": {
|
||||
"outcome": "applied-source-only",
|
||||
"files": [
|
||||
"docs/keycape-issuer-eso-contract.md",
|
||||
"manifests/templates/keycape-issuer-eso.yaml",
|
||||
"scripts/keycape_issuer_eso.py",
|
||||
"tests/test_keycape_issuer_eso.py"
|
||||
],
|
||||
"before": {
|
||||
"other_status_sha256": "b274ecee79380c3670afa2ff40790064bdbe0565ecea4cfc1eec586deb409990",
|
||||
"index_sha256": "9c08aefaf66ea19285e143e7c8f0de6402b340307391d7433ba2772b5dd02cf7"
|
||||
},
|
||||
"after": {
|
||||
"other_status_sha256": "b274ecee79380c3670afa2ff40790064bdbe0565ecea4cfc1eec586deb409990",
|
||||
"index_sha256": "9c08aefaf66ea19285e143e7c8f0de6402b340307391d7433ba2772b5dd02cf7"
|
||||
},
|
||||
"workplan_changed": false,
|
||||
"source_owner_assent_inferred": false
|
||||
},
|
||||
"existing_preimage_refused": true,
|
||||
"tests_returncode": 0,
|
||||
"test_output": "test_delivery_document_is_only_external_and_detached (test_keycape_issuer_eso.FixedIssuerContract.test_delivery_document_is_only_external_and_detached) ... ok\ntest_external_drift_refuses (test_keycape_issuer_eso.FixedIssuerContract.test_external_drift_refuses) ... ok\ntest_independent_forgejo_binding (test_keycape_issuer_eso.FixedIssuerContract.test_independent_forgejo_binding) ... ok\ntest_missing_or_unready_refuses (test_keycape_issuer_eso.FixedIssuerContract.test_missing_or_unready_refuses) ... ok\ntest_no_caller_store_or_path_override (test_keycape_issuer_eso.FixedIssuerContract.test_no_caller_store_or_path_override) ... ok\ntest_store_drift_refuses (test_keycape_issuer_eso.FixedIssuerContract.test_store_drift_refuses) ... ok\ntest_type_admitted_trailing_dash_is_preserved (test_keycape_issuer_eso.FixedIssuerContract.test_type_admitted_trailing_dash_is_preserved) ... ok\ntest_valid_ready_metadata_allows_extra_controller_metadata (test_keycape_issuer_eso.FixedIssuerContract.test_valid_ready_metadata_allows_extra_controller_metadata) ... ok\n\n----------------------------------------------------------------------\nRan 8 tests in 0.248s\n\nOK\n",
|
||||
"canonical_mutation": false,
|
||||
"native_calls": false
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"schema": "custodian.nk48-r5-f2-source-publication.v1",
|
||||
"status": "prepared-not-executed",
|
||||
"platform_base": "0a9617a62d4696a8070798923b459e8405c3dbf2",
|
||||
"platform_source_status": "proposed-source-only",
|
||||
"source_owner_assent_received": false,
|
||||
"files": [
|
||||
{
|
||||
"path": "docs/keycape-issuer-eso-contract.md",
|
||||
"preimage": "absent",
|
||||
"sha256": "7f59e59b17c58252982931ac61fe50dd7a07340add6c437fe48af36971eafe68"
|
||||
},
|
||||
{
|
||||
"path": "manifests/templates/keycape-issuer-eso.yaml",
|
||||
"preimage": "absent",
|
||||
"sha256": "e17498bd8a4c820041a4105e4efe9c60c6a50953db8f621ff54887080065c743"
|
||||
},
|
||||
{
|
||||
"path": "scripts/keycape_issuer_eso.py",
|
||||
"preimage": "absent",
|
||||
"sha256": "21c5797280c2a7825dbda8ac970d34a0cdef4c6458f68bce0b1c12407f122a87"
|
||||
},
|
||||
{
|
||||
"path": "tests/test_keycape_issuer_eso.py",
|
||||
"preimage": "absent",
|
||||
"sha256": "223d4c5b349062b9f93e6af79e8d5feda44377ba41a11726f6f2b762691e8308"
|
||||
}
|
||||
],
|
||||
"canonical_workplan_delta": null,
|
||||
"workplan_discovery": "RPF-1.3-T4 exists only in the original Platform owner-review JSON, not in a Platform workplan. No workplan created or repurposed.",
|
||||
"conditional_netkingdom": {
|
||||
"base": "3236d5000e52e0643f33906a26a7825aa0b67465",
|
||||
"patch_sha256": "6784a21fbd10bd62712be2e0f4929034601c94629aa74ccaa2e93fc815eecd61",
|
||||
"status": "prepared-only; await F3 combined regeneration before application"
|
||||
},
|
||||
"observed_dirt": [
|
||||
"M .custodian-brief.md",
|
||||
" M WORK-RECORDS.md"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
--- a/security-case-type-revisions/1.3/oidc-browser-relying-party/type.yaml
|
||||
+++ b/security-case-type-revisions/1.3/oidc-browser-relying-party/type.yaml
|
||||
@@ -269,8 +269,11 @@
|
||||
when: client_type == confidential
|
||||
entry_point: reviewed adapter railiance-platform/keycape-deliver-secret, dispatched
|
||||
by Warden's case kernel; Platform's deliver capability applies ExternalSecret
|
||||
- sso/keycape-{client_id}-client (key client-secret) through the ESO store for
|
||||
- role external-secrets-keycape-{client_id}, from bao:platform/workloads/keycape/{client_id}
|
||||
+ sso/keycape-{client_id}-client (key client-secret) through fixed ClusterSecretStore
|
||||
+ openbao-keycape-{client_id}-issuer (cluster-scoped, restricted to namespace sso),
|
||||
+ defined by Platform-controlled manifests/templates/keycape-issuer-eso.yaml
|
||||
+ (sha256:e17498bd8a4c820041a4105e4efe9c60c6a50953db8f621ff54887080065c743),
|
||||
+ using role external-secrets-keycape-{client_id}, from bao:platform/workloads/keycape/{client_id}
|
||||
auth: Platform's own delivery path on lane platform-secret-delivery, inside the human
|
||||
aal2 session; ESO reads custody through role external-secrets-keycape-{client_id};
|
||||
Warden holds no Platform credential, and no value leaves custody
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"README.md": "sha256:522392bd35d2e0b22fd097509361d1476200a361c2ced22603d43e5758aa691d",
|
||||
"integrate_platform.py": "sha256:ef8a1647e54013c0c6f2c11c8f74ef43fc97ceaca99e8f8caa89ee16ff80efba",
|
||||
"integration-checks.json": "sha256:0ab8b058414dde1be9c7fd6ee2cb3f246e4deef2036d17472e846fae23bba4b9",
|
||||
"manifest.json": "sha256:c52692fb154cd46f1bfa62e7a0cda73241716b1024d992449e24e87e18750bbb",
|
||||
"netkingdom-entry-point.conditional.patch": "sha256:6784a21fbd10bd62712be2e0f4929034601c94629aa74ccaa2e93fc815eecd61",
|
||||
"platform-source/docs/keycape-issuer-eso-contract.md": "sha256:7f59e59b17c58252982931ac61fe50dd7a07340add6c437fe48af36971eafe68",
|
||||
"platform-source/manifests/templates/keycape-issuer-eso.yaml": "sha256:e17498bd8a4c820041a4105e4efe9c60c6a50953db8f621ff54887080065c743",
|
||||
"platform-source/scripts/keycape_issuer_eso.py": "sha256:21c5797280c2a7825dbda8ac970d34a0cdef4c6458f68bce0b1c12407f122a87",
|
||||
"platform-source/tests/test_keycape_issuer_eso.py": "sha256:223d4c5b349062b9f93e6af79e8d5feda44377ba41a11726f6f2b762691e8308",
|
||||
"progress-paragraph.md": "sha256:151199597ba37225e5d46922ae90453f7338c5602ff81b3d870b579278bef2d4"
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
# Proposed fixed issuer ESO contract — RPF-1.3-T4 / NK48-R5-F2
|
||||
|
||||
Status: proposed source; not admitted, deployed, or owner-acknowledged. This is a
|
||||
new Platform declaration for review, not an existing Forgejo grant discovery.
|
||||
|
||||
The only substitution in `manifests/templates/keycape-issuer-eso.yaml`
|
||||
(sha256:e17498bd8a4c820041a4105e4efe9c60c6a50953db8f621ff54887080065c743) is the admitted `client_id`. The proposed issuer
|
||||
store is **ClusterSecretStore `openbao-keycape-{client_id}-issuer`**, cluster
|
||||
scoped (no metadata namespace), restricted by conditions to ExternalSecrets in
|
||||
`sso`. For Forgejo it is `openbao-keycape-forgejo-issuer`. The suffix makes the
|
||||
issuer purpose explicit and keeps type-admitted IDs ending in `-` representable.
|
||||
The store's DNS subdomain name can exceed 63 characters; the existing adapter's
|
||||
63-character target Secret reference bound is preserved (client ID at most 48).
|
||||
No type parameter is added or changed.
|
||||
|
||||
The provider is `http://openbao.openbao.svc:8200`, KV v2 mount `platform`,
|
||||
Kubernetes auth mount `kubernetes`, role `external-secrets-keycape-{client_id}`,
|
||||
serviceAccountRef `external-secrets/external-secrets`, audience `openbao`.
|
||||
CCR-2026-0041 already records that Forgejo role/identity/audience, not this new
|
||||
store name or an unrestricted client family grant. Other clients still require
|
||||
their own existing owner-controlled role/case admission.
|
||||
|
||||
The ExternalSecret is `sso/keycape-{client_id}-client`, references precisely that
|
||||
ClusterSecretStore, refreshes every 5m and targets the same name with Owner
|
||||
creation and Retain remote deletion. Its only data entry maps `client-secret`
|
||||
from remoteRef `workloads/keycape/{client_id}`, property `CLIENT_SECRET`. The
|
||||
provider mount plus mount-relative remoteRef equals custody reference
|
||||
`platform/workloads/keycape/{client_id}`; do not double-prefix `platform/`.
|
||||
This is distinct from the Apps-owned consumer namespace SecretStore
|
||||
`openbao-keycape-{client_id}-consumer` and its dedicated consumer identity.
|
||||
|
||||
Store provisioning belongs to Platform's separate owner-controlled path. The
|
||||
proposed `platform-secret-delivery` lane retains ONLY create/get/watch/delete on
|
||||
the exact ExternalSecret in `sso`; this source does not delegate store creation
|
||||
or Secret read/list. Never apply the multi-document template through that lane.
|
||||
The pure `scripts/keycape_issuer_eso.py` module exposes only the ExternalSecret
|
||||
document through `external_secret()` and validates fixed public observations
|
||||
through `require_fixed_store()` and `require_ready_delivery()`. It performs no
|
||||
API call and issues no evidence/receipt. It is not a real capability or admission
|
||||
boundary; a caller-supplied observation alone establishes no authenticity.
|
||||
|
||||
The existing RPF-1.3-T4 delivery binding must validate the case/client binding,
|
||||
verify this exact preexisting store's public identity/spec/Ready state, apply or
|
||||
compare the exact ExternalSecret, and wait for matching spec plus Ready=True.
|
||||
The proposed helper accepts extra controller metadata but deliberately refuses
|
||||
spec drift. Actual API defaulting/normalization and installed ESO schema support
|
||||
must be checked in that implementation; these fixtures establish no native
|
||||
compatibility or credential isolation. ESO's shared controller remains trusted.
|
||||
No Secret bodies, values, arbitrary remoteRefs, or raw errors may enter receipts.
|
||||
|
||||
Existing owner requirements remain: closed `netkingdom.deliver-secret.v1`
|
||||
metadata receipt with authenticated before/after UID/resourceVersion provenance,
|
||||
unchanged objects reported NO_CHANGE, attempt-session revocation, and created-only
|
||||
rollback guarded by exact UID/resourceVersion (drift or uncertain ownership goes
|
||||
to owner reconciliation). The helper neither deletes a target Secret nor creates
|
||||
an OpenBao role/policy nor changes CCR-0041. These capabilities and catalog routing
|
||||
remain unimplemented/unaccepted under RPF-1.3-T4. Independent Platform source
|
||||
review of this declaration precedes adopting the conditional NetKingdom type
|
||||
text; no descriptor acceptance, acknowledgment, pin, grant, catalog or native
|
||||
permission is inferred.
|
||||
|
||||
Grounding: CCR-2026-0041 exact role/identity; the approved historical
|
||||
`docs/provisioning-windows/2026-10-04-1000/keycape/eso.draft.yaml` issuer
|
||||
ClusterSecretStore and target pattern; `scripts/catalog_lane_scaffold.py`
|
||||
ClusterSecretStore/namespace restriction and mount-relative remoteRef model;
|
||||
RPF-1.3-C1 and RPF-1.3-T4 in the frozen owner review. The scaffold's historical
|
||||
audience field placement differs from the issuer draft; this candidate uses
|
||||
the issuer draft's serviceAccountRef.audiences, not a claim of installed support.
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
# PROPOSED SOURCE ONLY — RPF-1.3-T4 / NK48-R5-F2; not admitted or applied.
|
||||
# Platform controls this template. Only admitted client_id is substituted.
|
||||
# Provision the store through Platform's separate reviewed owner path; the
|
||||
# platform-secret-delivery lane applies ONLY the ExternalSecret document.
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ClusterSecretStore
|
||||
metadata:
|
||||
name: openbao-keycape-{client_id}-issuer
|
||||
spec:
|
||||
provider:
|
||||
vault:
|
||||
server: http://openbao.openbao.svc:8200
|
||||
path: platform
|
||||
version: v2
|
||||
auth:
|
||||
kubernetes:
|
||||
mountPath: kubernetes
|
||||
role: external-secrets-keycape-{client_id}
|
||||
serviceAccountRef:
|
||||
name: external-secrets
|
||||
namespace: external-secrets
|
||||
audiences:
|
||||
- openbao
|
||||
conditions:
|
||||
- namespaces:
|
||||
- sso
|
||||
---
|
||||
apiVersion: external-secrets.io/v1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: keycape-{client_id}-client
|
||||
namespace: sso
|
||||
spec:
|
||||
refreshInterval: 5m
|
||||
secretStoreRef:
|
||||
kind: ClusterSecretStore
|
||||
name: openbao-keycape-{client_id}-issuer
|
||||
target:
|
||||
name: keycape-{client_id}-client
|
||||
creationPolicy: Owner
|
||||
deletionPolicy: Retain
|
||||
data:
|
||||
- secretKey: client-secret
|
||||
remoteRef:
|
||||
key: workloads/keycape/{client_id}
|
||||
property: CLIENT_SECRET
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
"""Proposed fixed issuer ESO source contract for RPF-1.3-T4 / NK48-R5-F2.
|
||||
|
||||
Pure public metadata only. No API/credential/Secret access or apply path. This
|
||||
new declaration requires independent Platform review before type integration.
|
||||
The delivery lane may use only external_secret(); store provisioning is a
|
||||
separate owner action and is never delegated by this module.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from copy import deepcopy
|
||||
from pathlib import Path
|
||||
import re
|
||||
|
||||
import yaml
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[1]
|
||||
TEMPLATE = ROOT / 'manifests/templates/keycape-issuer-eso.yaml'
|
||||
|
||||
|
||||
class Refused(ValueError):
|
||||
"""Fixed issuer metadata differs; never return an owner delivery receipt."""
|
||||
|
||||
|
||||
def documents(client_id: str) -> tuple[dict, dict]:
|
||||
# Match the frozen type client_id pattern and existing adapter's derived bound.
|
||||
# No caller can supply a store name/kind/namespace or an OpenBao path.
|
||||
if not isinstance(client_id, str) or not re.fullmatch(r'[a-z0-9][a-z0-9-]{1,62}', client_id):
|
||||
raise Refused('bounded admitted client_id required')
|
||||
if len('keycape-' + client_id + '-client') > 63:
|
||||
raise Refused('derived issuer reference exceeds existing adapter bound')
|
||||
store, external = yaml.safe_load_all(TEMPLATE.read_text().format(client_id=client_id))
|
||||
return store, external
|
||||
|
||||
|
||||
def external_secret(client_id: str) -> dict:
|
||||
"""The ONLY document the proposed delivery capability may apply."""
|
||||
return deepcopy(documents(client_id)[1])
|
||||
|
||||
|
||||
def _matching_public_resource(observed: dict, expected: dict) -> None:
|
||||
if not isinstance(observed, dict):
|
||||
raise Refused('public resource observation required')
|
||||
metadata = observed.get('metadata')
|
||||
if not isinstance(metadata, dict):
|
||||
raise Refused('resource metadata required')
|
||||
expected_namespace = expected['metadata'].get('namespace')
|
||||
namespace_matches = (metadata.get('namespace') == expected_namespace
|
||||
if expected_namespace else metadata.get('namespace') in (None, ''))
|
||||
if (observed.get('apiVersion') != expected['apiVersion']
|
||||
or observed.get('kind') != expected['kind']
|
||||
or metadata.get('name') != expected['metadata']['name']
|
||||
or not namespace_matches
|
||||
or observed.get('spec') != expected['spec']):
|
||||
raise Refused('fixed issuer resource differs')
|
||||
status = observed.get('status')
|
||||
conditions = status.get('conditions', []) if isinstance(status, dict) else []
|
||||
if not isinstance(conditions, list) or not any(
|
||||
isinstance(c, dict) and c.get('type') == 'Ready' and c.get('status') == 'True'
|
||||
for c in conditions):
|
||||
raise Refused('fixed issuer resource not ready')
|
||||
|
||||
|
||||
def require_fixed_store(observed: dict, client_id: str) -> None:
|
||||
"""Refuse a missing/drifted/not-ready store; never create it through delivery."""
|
||||
_matching_public_resource(observed, documents(client_id)[0])
|
||||
|
||||
|
||||
def require_ready_delivery(observed: dict, client_id: str) -> None:
|
||||
"""Spec equality and Ready precede a created/NO_CHANGE owner receipt."""
|
||||
_matching_public_resource(observed, documents(client_id)[1])
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
"""Public metadata fixtures only: no API, credentials, or native calls."""
|
||||
import copy
|
||||
import sys
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts"))
|
||||
import keycape_issuer_eso as contract
|
||||
|
||||
|
||||
class FixedIssuerContract(unittest.TestCase):
|
||||
def observations(self):
|
||||
resources = contract.documents("forgejo")
|
||||
for resource in resources:
|
||||
resource["metadata"].update(uid="public-fixture-uid", resourceVersion="7")
|
||||
resource["status"] = {"conditions": [{"type": "Ready", "status": "True"}]}
|
||||
return resources
|
||||
|
||||
def test_independent_forgejo_binding(self):
|
||||
# Independent owner-source example: CCR0041 role/SA/audience and the
|
||||
# existing issuer ESO draft's provider/target/relative key convention.
|
||||
store, external = contract.documents("forgejo")
|
||||
self.assertEqual(store["kind"], "ClusterSecretStore")
|
||||
self.assertEqual(store["metadata"], {"name": "openbao-keycape-forgejo-issuer"})
|
||||
self.assertEqual(store["spec"], {
|
||||
"provider": {"vault": {
|
||||
"server": "http://openbao.openbao.svc:8200", "path": "platform", "version": "v2",
|
||||
"auth": {"kubernetes": {"mountPath": "kubernetes",
|
||||
"role": "external-secrets-keycape-forgejo",
|
||||
"serviceAccountRef": {"name": "external-secrets", "namespace": "external-secrets",
|
||||
"audiences": ["openbao"]}}}}},
|
||||
"conditions": [{"namespaces": ["sso"]}]})
|
||||
self.assertEqual(external["metadata"], {"name": "keycape-forgejo-client", "namespace": "sso"})
|
||||
self.assertEqual(external["spec"], {
|
||||
"refreshInterval": "5m",
|
||||
"secretStoreRef": {"kind": "ClusterSecretStore", "name": "openbao-keycape-forgejo-issuer"},
|
||||
"target": {"name": "keycape-forgejo-client", "creationPolicy": "Owner", "deletionPolicy": "Retain"},
|
||||
"data": [{"secretKey": "client-secret", "remoteRef": {
|
||||
"key": "workloads/keycape/forgejo", "property": "CLIENT_SECRET"}}]})
|
||||
|
||||
def test_valid_ready_metadata_allows_extra_controller_metadata(self):
|
||||
store, external = self.observations()
|
||||
contract.require_fixed_store(store, "forgejo")
|
||||
contract.require_ready_delivery(external, "forgejo")
|
||||
|
||||
def test_store_drift_refuses(self):
|
||||
changes = [
|
||||
("kind", "SecretStore"),
|
||||
("metadata.namespace", "sso"),
|
||||
("metadata.name", "caller-store"),
|
||||
("spec.provider.vault.server", "https://wrong.invalid"),
|
||||
("spec.provider.vault.path", "tenant"),
|
||||
("spec.provider.vault.auth.kubernetes.role", "external-secrets-keycape-sibling"),
|
||||
("spec.provider.vault.auth.kubernetes.serviceAccountRef.audiences", ["wrong"]),
|
||||
("spec.provider.vault.auth.kubernetes.serviceAccountRef.namespace", "sso"),
|
||||
("spec.conditions", [{"namespaces": ["sso", "other"]}]),
|
||||
]
|
||||
for path, value in changes:
|
||||
with self.subTest(path=path):
|
||||
store = self.observations()[0]
|
||||
mutate(store, path, value)
|
||||
with self.assertRaises(contract.Refused):
|
||||
contract.require_fixed_store(store, "forgejo")
|
||||
|
||||
def test_external_drift_refuses(self):
|
||||
changes = [
|
||||
("metadata.namespace", ""), ("metadata.namespace", None), ("metadata.namespace", "other"),
|
||||
("metadata.name", "keycape-sibling-client"),
|
||||
("spec.secretStoreRef.kind", "SecretStore"),
|
||||
("spec.secretStoreRef.name", "openbao-keycape-forgejo-consumer"),
|
||||
("spec.target.name", "other"), ("spec.target.creationPolicy", "Merge"),
|
||||
("spec.target.deletionPolicy", "Delete"),
|
||||
("spec.data", [{"secretKey": "client-secret", "remoteRef": {
|
||||
"key": "platform/workloads/keycape/forgejo", "property": "CLIENT_SECRET"}}]),
|
||||
("spec.data", [{"secretKey": "wrong", "remoteRef": {
|
||||
"key": "workloads/keycape/forgejo", "property": "CLIENT_SECRET"}}]),
|
||||
("spec.data", [{"secretKey": "client-secret", "remoteRef": {
|
||||
"key": "workloads/keycape/forgejo", "property": "wrong"}}]),
|
||||
]
|
||||
for path, value in changes:
|
||||
with self.subTest(path=path, value=value):
|
||||
external = self.observations()[1]
|
||||
mutate(external, path, value)
|
||||
with self.assertRaises(contract.Refused):
|
||||
contract.require_ready_delivery(external, "forgejo")
|
||||
|
||||
def test_missing_or_unready_refuses(self):
|
||||
for check, index in [(contract.require_fixed_store, 0), (contract.require_ready_delivery, 1)]:
|
||||
for status in [None, {}, [], "bad", {"conditions": None},
|
||||
{"conditions": [{"type": "Ready", "status": "False"}]}]:
|
||||
with self.subTest(check=check.__name__, status=status):
|
||||
observed = self.observations()[index]
|
||||
observed["status"] = status
|
||||
with self.assertRaises(contract.Refused):
|
||||
check(observed, "forgejo")
|
||||
for malformed in [None, [], {}, {"metadata": None}]:
|
||||
with self.assertRaises(contract.Refused):
|
||||
check(malformed, "forgejo")
|
||||
|
||||
def test_no_caller_store_or_path_override(self):
|
||||
for invalid in ["", "f", "../forgejo", "forgejo/sibling", "Forgejo", "forgejo\n", "-forgejo", "f" * 49, None]:
|
||||
with self.subTest(invalid=invalid), self.assertRaises(contract.Refused):
|
||||
contract.documents(invalid)
|
||||
with self.assertRaises(TypeError):
|
||||
contract.external_secret("forgejo", store_name="caller-store")
|
||||
|
||||
def test_type_admitted_trailing_dash_is_preserved(self):
|
||||
self.assertEqual(contract.external_secret("forgejo-")["metadata"]["name"],
|
||||
"keycape-forgejo--client")
|
||||
self.assertEqual(contract.documents("forgejo-")[0]["metadata"]["name"],
|
||||
"openbao-keycape-forgejo--issuer")
|
||||
|
||||
def test_delivery_document_is_only_external_and_detached(self):
|
||||
external = contract.external_secret("forgejo")
|
||||
self.assertEqual(external["kind"], "ExternalSecret")
|
||||
external["spec"]["secretStoreRef"]["name"] = "tampered"
|
||||
self.assertEqual(contract.external_secret("forgejo")["spec"]["secretStoreRef"]["name"],
|
||||
"openbao-keycape-forgejo-issuer")
|
||||
|
||||
|
||||
def mutate(resource, path, value):
|
||||
parts = path.split(".")
|
||||
for key in parts[:-1]:
|
||||
resource = resource[key]
|
||||
resource[parts[-1]] = copy.deepcopy(value)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main(verbosity=2)
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
2026-10-17 source preparation: the proposed fixed issuer ESO template
|
||||
`manifests/templates/keycape-issuer-eso.yaml`, pure metadata helper
|
||||
`scripts/keycape_issuer_eso.py`, focused fixtures and owner contract doc passed
|
||||
independent Platform-scoped source-fit review (Custodian
|
||||
`docs/changes/netkingdom-target-2026-10-17/nk48-r5-f2-review-r1/REVIEW.md`). This
|
||||
supplies reviewable source for the exact-store-reference gap NK48-R5-F2 under
|
||||
the existing owner-review obligation RPF-1.3-T4; it establishes no owner assent,
|
||||
deployment, grant or lane activation. Real authenticated delivery/remove,
|
||||
attempt-session revocation, authentic before/after provenance and metadata
|
||||
receipts, preexisting/adoption protection, guarded created-only rollback,
|
||||
installed ESO compatibility and Warden catalog routing remain incomplete. Do
|
||||
not mark the delivery obligation done on the strength of template/helper source.
|
||||
|
||||
Placement: reference material only. No legitimate Platform workplan/task for
|
||||
RPF-1.3-T4 exists in the reviewed current source. The identifier originates in
|
||||
`nk48-1.3-owner-review/owner-review-railiance-platform.json`, whose review explicitly
|
||||
created no workplan. This paragraph is retained here for the existing coordinator
|
||||
work record; it must not be appended to an unrelated finished Platform task or
|
||||
used to invent a task, status, dependency or owner assent.
|
||||
|
|
@ -0,0 +1,443 @@
|
|||
{
|
||||
"ok": true,
|
||||
"status": "applied",
|
||||
"repo_slug": "railiance-platform",
|
||||
"commit": "104ed90f42a9a86bf9fda343b49b65a85c9ee4b9",
|
||||
"requests": 2,
|
||||
"elapsed_ms": 5105.9,
|
||||
"git": {
|
||||
"upstream": "origin/main",
|
||||
"behind": 0,
|
||||
"ahead": 0
|
||||
},
|
||||
"identifiers": {
|
||||
"schema": "repo-manager.identifier-assignment.v1",
|
||||
"ok": true,
|
||||
"executed": true,
|
||||
"repo": "railiance-platform",
|
||||
"namespace": "helixforge",
|
||||
"assignments": [],
|
||||
"historical_invalid_identifiers": [],
|
||||
"historical_identity_collisions": [],
|
||||
"files_changed": []
|
||||
},
|
||||
"receipt": {
|
||||
"schema": "state-hub.repository-projection-reconcile.v1",
|
||||
"instance_role": "primary",
|
||||
"instance_label": "railiance01",
|
||||
"expected_commit": "104ed90f42a9a86bf9fda343b49b65a85c9ee4b9",
|
||||
"derived_commit": "104ed90f42a9a86bf9fda343b49b65a85c9ee4b9",
|
||||
"outcome": {
|
||||
"schema": "state-hub.projection-reset.v1",
|
||||
"repo_slug": "railiance-platform",
|
||||
"commit": "104ed90f42a9a86bf9fda343b49b65a85c9ee4b9",
|
||||
"status": "applied",
|
||||
"counts": {
|
||||
"created": 0,
|
||||
"updated": 64,
|
||||
"retired": 0,
|
||||
"refused": 0,
|
||||
"released": 0,
|
||||
"created_tasks": 0,
|
||||
"updated_tasks": 0,
|
||||
"cancelled_tasks": 0,
|
||||
"created_edges": 0,
|
||||
"removed_edges": 0,
|
||||
"unresolved_edges": 12,
|
||||
"external_edges": 24
|
||||
},
|
||||
"created": [],
|
||||
"updated": [
|
||||
"RAIL-PL-WP-0001",
|
||||
"RAIL-PL-WP-0002",
|
||||
"RPF-WP-0001",
|
||||
"RPF-WP-0002",
|
||||
"RPF-WP-0003",
|
||||
"RPF-WP-0004",
|
||||
"RPF-WP-0005",
|
||||
"RPF-WP-0006",
|
||||
"RPF-WP-0007",
|
||||
"RPF-WP-0008",
|
||||
"RPF-WP-0009",
|
||||
"RPF-WP-0010",
|
||||
"RPF-WP-0011",
|
||||
"RPF-WP-0012",
|
||||
"RPF-WP-0013",
|
||||
"RPF-WP-0014",
|
||||
"RPF-WP-0015",
|
||||
"RPF-WP-0016",
|
||||
"RPF-WP-0017",
|
||||
"RPF-WP-0018",
|
||||
"RPF-WP-0019",
|
||||
"RPF-WP-0020",
|
||||
"RPF-WP-0021",
|
||||
"RPF-WP-0022",
|
||||
"RPF-WP-0023",
|
||||
"RPF-WP-0024",
|
||||
"RPF-WP-0025",
|
||||
"RPF-WP-0026",
|
||||
"RPF-WP-0027",
|
||||
"RPF-WP-0028",
|
||||
"RPF-WP-0029",
|
||||
"RPF-WP-0030",
|
||||
"RPF-WP-0031",
|
||||
"RPF-WP-0032",
|
||||
"RPF-WP-0033",
|
||||
"RPF-WP-0034",
|
||||
"RPF-WP-0035",
|
||||
"RPF-WP-0036",
|
||||
"RPF-WP-0037",
|
||||
"RPF-WP-0038",
|
||||
"RPF-WP-0039",
|
||||
"RPF-WP-0040",
|
||||
"RPF-WP-0041",
|
||||
"RPF-WP-0042",
|
||||
"RPF-WP-0043",
|
||||
"RPF-WP-0044",
|
||||
"RPF-WP-0045",
|
||||
"RPF-WP-0046",
|
||||
"RPF-WP-0047",
|
||||
"RPF-WP-0048",
|
||||
"RPF-WP-0049",
|
||||
"RPF-WP-0050",
|
||||
"RPF-WP-0051",
|
||||
"RPF-WP-0052",
|
||||
"RPF-WP-0053",
|
||||
"RPF-WP-0054",
|
||||
"RPF-WP-0055",
|
||||
"RPF-WP-0056",
|
||||
"RPF-WP-0057",
|
||||
"RPF-WP-0058",
|
||||
"RPF-WP-0059",
|
||||
"RPF-WP-ADHOC-2026-08-23",
|
||||
"RPF-WP-ADHOC-2026-10-10",
|
||||
"RPF-WP-ADHOC-2026-10-11"
|
||||
],
|
||||
"retired": [],
|
||||
"released": [],
|
||||
"created_tasks": [],
|
||||
"updated_tasks": [],
|
||||
"cancelled_tasks": [],
|
||||
"created_edges": [],
|
||||
"removed_edges": [],
|
||||
"unresolved_edges": [
|
||||
{
|
||||
"workplan": "RAIL-PL-WP-0002",
|
||||
"from": "RAIL-PL-WP-0002",
|
||||
"target": "RAIL-PL-WP-0001",
|
||||
"reason": "missing"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0002",
|
||||
"from": "RPF-WP-0002",
|
||||
"target": "RAILIANCE-WP-0005",
|
||||
"reason": "missing"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0002",
|
||||
"from": "RPF-WP-0002",
|
||||
"target": "RAILIANCE-WP-0006",
|
||||
"reason": "missing"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0002",
|
||||
"from": "RPF-WP-0002",
|
||||
"target": "RAILIANCE-WP-0007",
|
||||
"reason": "missing"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0003",
|
||||
"from": "RPF-WP-0003",
|
||||
"target": "RAILIANCE-WP-0007",
|
||||
"reason": "missing"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0003",
|
||||
"from": "RPF-WP-0003",
|
||||
"target": "RAILIANCE-WP-0008",
|
||||
"reason": "missing"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0004",
|
||||
"from": "RPF-WP-0004",
|
||||
"target": "RAILIANCE-WP-0007",
|
||||
"reason": "missing"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0004",
|
||||
"from": "RPF-WP-0004",
|
||||
"target": "RAILIANCE-WP-0008",
|
||||
"reason": "missing"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0005",
|
||||
"from": "RPF-WP-0005",
|
||||
"target": "RAILIANCE-WP-0007",
|
||||
"reason": "missing"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0005",
|
||||
"from": "RPF-WP-0005",
|
||||
"target": "RAILIANCE-WP-0008",
|
||||
"reason": "missing"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0024",
|
||||
"from": "RPF-WP-0024",
|
||||
"target": "RAILIANCE-WP-0005",
|
||||
"reason": "missing"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0024",
|
||||
"from": "RPF-WP-0024",
|
||||
"target": "RAILIANCE-WP-0006",
|
||||
"reason": "missing"
|
||||
}
|
||||
],
|
||||
"external_edges": [
|
||||
{
|
||||
"workplan": "RPF-WP-0057",
|
||||
"from": "RPF-WP-0057-T04",
|
||||
"target": "RPF-WP-0057-T03",
|
||||
"relationship_type": "starts_after",
|
||||
"from_workplan_id": "04f7c4aa-0a24-5d61-994d-2487ca6bfb91",
|
||||
"from_task_id": "94cdfd1c-c639-5c5e-9bd6-7db823ab0265",
|
||||
"to_workplan_id": null,
|
||||
"to_task_id": "afa14a91-1ebf-5a45-a28b-380f9a933336"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0003",
|
||||
"from": "RPF-WP-0003",
|
||||
"target": "RAIL-PL-WP-0002",
|
||||
"relationship_type": "blocks",
|
||||
"from_workplan_id": "5fb6b6a7-3a40-5658-9804-21c0928c6dd9",
|
||||
"from_task_id": null,
|
||||
"to_workplan_id": "fd1c045a-01d4-43be-980f-acbda6c64e6c",
|
||||
"to_task_id": null
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0024",
|
||||
"from": "RPF-WP-0024",
|
||||
"target": "RAIL-PL-WP-0002",
|
||||
"relationship_type": "blocks",
|
||||
"from_workplan_id": "6c2e61cf-7aa9-58ee-bb22-3514b9692eb5",
|
||||
"from_task_id": null,
|
||||
"to_workplan_id": "fd1c045a-01d4-43be-980f-acbda6c64e6c",
|
||||
"to_task_id": null
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0035",
|
||||
"from": "RPF-WP-0035-T07",
|
||||
"target": "SECRETS-WP-0006-T06",
|
||||
"relationship_type": "starts_after",
|
||||
"from_workplan_id": "975db491-5412-5e27-8e34-14a2417bb039",
|
||||
"from_task_id": "0dd7c9a5-65a0-53fc-b6c3-5ad96ee56f7b",
|
||||
"to_workplan_id": null,
|
||||
"to_task_id": "1431edae-5791-5892-8c4b-829419b537d2"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0035",
|
||||
"from": "RPF-WP-0035-T12",
|
||||
"target": "RPF-WP-0035-T11",
|
||||
"relationship_type": "starts_after",
|
||||
"from_workplan_id": "975db491-5412-5e27-8e34-14a2417bb039",
|
||||
"from_task_id": "914bf383-c13f-5247-9af0-91d7e3a4784a",
|
||||
"to_workplan_id": null,
|
||||
"to_task_id": "7952c8cd-c066-5b72-a025-78d24341c1ab"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0035",
|
||||
"from": "RPF-WP-0035-T02",
|
||||
"target": "KEY-WP-0039-T02",
|
||||
"relationship_type": "starts_after",
|
||||
"from_workplan_id": "975db491-5412-5e27-8e34-14a2417bb039",
|
||||
"from_task_id": "e0c82ea9-05a5-537e-8fbf-67534263572e",
|
||||
"to_workplan_id": null,
|
||||
"to_task_id": "03da4c38-1dac-53b1-8b0b-e697df48e9d3"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0035",
|
||||
"from": "RPF-WP-0035-T02",
|
||||
"target": "MASON-WP-0009-T05",
|
||||
"relationship_type": "starts_after",
|
||||
"from_workplan_id": "975db491-5412-5e27-8e34-14a2417bb039",
|
||||
"from_task_id": "e0c82ea9-05a5-537e-8fbf-67534263572e",
|
||||
"to_workplan_id": null,
|
||||
"to_task_id": "1b1a0566-add7-59c1-94b0-6bb81d2d1537"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0035",
|
||||
"from": "RPF-WP-0035-T03",
|
||||
"target": "MASON-WP-0005-T05",
|
||||
"relationship_type": "starts_after",
|
||||
"from_workplan_id": "975db491-5412-5e27-8e34-14a2417bb039",
|
||||
"from_task_id": "f47e5bc5-6f3c-54bb-aa35-260ad03892ba",
|
||||
"to_workplan_id": null,
|
||||
"to_task_id": "4c205be7-4f1f-5dd1-aafa-fc112fdd640e"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0035",
|
||||
"from": "RPF-WP-0035-T03",
|
||||
"target": "FT-WP-0002",
|
||||
"relationship_type": "blocks",
|
||||
"from_workplan_id": "975db491-5412-5e27-8e34-14a2417bb039",
|
||||
"from_task_id": "f47e5bc5-6f3c-54bb-aa35-260ad03892ba",
|
||||
"to_workplan_id": "f2373858-c932-5a4d-81b6-db9a3595135a",
|
||||
"to_task_id": null
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0044",
|
||||
"from": "RPF-WP-0044-T06",
|
||||
"target": "RPF-WP-0044-T04",
|
||||
"relationship_type": "starts_after",
|
||||
"from_workplan_id": "98140775-3b9a-5cf9-9af6-722502d487dc",
|
||||
"from_task_id": "4ca54868-c31f-5e3d-b7d3-a15b84c15f80",
|
||||
"to_workplan_id": null,
|
||||
"to_task_id": "0e619658-0453-51ed-b9a0-bed28b5544fd"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0044",
|
||||
"from": "RPF-WP-0044-T06",
|
||||
"target": "RPF-WP-0044-T05",
|
||||
"relationship_type": "starts_after",
|
||||
"from_workplan_id": "98140775-3b9a-5cf9-9af6-722502d487dc",
|
||||
"from_task_id": "4ca54868-c31f-5e3d-b7d3-a15b84c15f80",
|
||||
"to_workplan_id": null,
|
||||
"to_task_id": "d418068a-6fb0-5416-aac5-d23c93924d9c"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0044",
|
||||
"from": "RPF-WP-0044-T07",
|
||||
"target": "RPF-WP-0044-T04",
|
||||
"relationship_type": "starts_after",
|
||||
"from_workplan_id": "98140775-3b9a-5cf9-9af6-722502d487dc",
|
||||
"from_task_id": "844ff115-def2-55ca-ab01-413ba7e6857d",
|
||||
"to_workplan_id": null,
|
||||
"to_task_id": "0e619658-0453-51ed-b9a0-bed28b5544fd"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0044",
|
||||
"from": "RPF-WP-0044-T07",
|
||||
"target": "RPF-WP-0044-T06",
|
||||
"relationship_type": "starts_after",
|
||||
"from_workplan_id": "98140775-3b9a-5cf9-9af6-722502d487dc",
|
||||
"from_task_id": "844ff115-def2-55ca-ab01-413ba7e6857d",
|
||||
"to_workplan_id": null,
|
||||
"to_task_id": "4ca54868-c31f-5e3d-b7d3-a15b84c15f80"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0044",
|
||||
"from": "RPF-WP-0044-T07",
|
||||
"target": "RPF-WP-0044-T03",
|
||||
"relationship_type": "starts_after",
|
||||
"from_workplan_id": "98140775-3b9a-5cf9-9af6-722502d487dc",
|
||||
"from_task_id": "844ff115-def2-55ca-ab01-413ba7e6857d",
|
||||
"to_workplan_id": null,
|
||||
"to_task_id": "6d5fc801-e361-579b-bcd8-6fe719a82e94"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0044",
|
||||
"from": "RPF-WP-0044-T07",
|
||||
"target": "RPF-WP-0044-T05",
|
||||
"relationship_type": "starts_after",
|
||||
"from_workplan_id": "98140775-3b9a-5cf9-9af6-722502d487dc",
|
||||
"from_task_id": "844ff115-def2-55ca-ab01-413ba7e6857d",
|
||||
"to_workplan_id": null,
|
||||
"to_task_id": "d418068a-6fb0-5416-aac5-d23c93924d9c"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0004",
|
||||
"from": "RPF-WP-0004",
|
||||
"target": "RAIL-PL-WP-0002",
|
||||
"relationship_type": "blocks",
|
||||
"from_workplan_id": "afc66064-7ba4-5f11-b61f-d76890244b7e",
|
||||
"from_task_id": null,
|
||||
"to_workplan_id": "fd1c045a-01d4-43be-980f-acbda6c64e6c",
|
||||
"to_task_id": null
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0023",
|
||||
"from": "RPF-WP-0023",
|
||||
"target": "RAIL-PL-WP-0002",
|
||||
"relationship_type": "blocks",
|
||||
"from_workplan_id": "b07930f7-ff0e-5fda-b7b9-3b56467173b1",
|
||||
"from_task_id": null,
|
||||
"to_workplan_id": "fd1c045a-01d4-43be-980f-acbda6c64e6c",
|
||||
"to_task_id": null
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0001",
|
||||
"from": "RPF-WP-0001",
|
||||
"target": "RAIL-PL-WP-0002",
|
||||
"relationship_type": "blocks",
|
||||
"from_workplan_id": "bcc11cf9-d008-5e42-8fff-e2b33a1d0ff2",
|
||||
"from_task_id": null,
|
||||
"to_workplan_id": "fd1c045a-01d4-43be-980f-acbda6c64e6c",
|
||||
"to_task_id": null
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0002",
|
||||
"from": "RPF-WP-0002",
|
||||
"target": "RAIL-PL-WP-0002",
|
||||
"relationship_type": "blocks",
|
||||
"from_workplan_id": "c69cb4e7-15c8-5858-aebd-73a6e46f0f21",
|
||||
"from_task_id": null,
|
||||
"to_workplan_id": "fd1c045a-01d4-43be-980f-acbda6c64e6c",
|
||||
"to_task_id": null
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0036",
|
||||
"from": "RPF-WP-0036-T04",
|
||||
"target": "RTEL-WP-0002",
|
||||
"relationship_type": "blocks",
|
||||
"from_workplan_id": "ca639c3d-3a87-5fa4-ad13-6f2e014b0c84",
|
||||
"from_task_id": "5351e0e4-6263-58f0-afb2-7c78c4cd6f68",
|
||||
"to_workplan_id": "08a5db92-7293-50d3-b589-55287b9850b3",
|
||||
"to_task_id": null
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0036",
|
||||
"from": "RPF-WP-0036-T03",
|
||||
"target": "ACTIVITY-WP-0042",
|
||||
"relationship_type": "blocks",
|
||||
"from_workplan_id": "ca639c3d-3a87-5fa4-ad13-6f2e014b0c84",
|
||||
"from_task_id": "d64446fb-870b-5ae9-9628-f1fb9d06c5a4",
|
||||
"to_workplan_id": "e1bfb5a4-e647-592d-883f-fe8728ad2f5f",
|
||||
"to_task_id": null
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0043",
|
||||
"from": "RPF-WP-0043-T03",
|
||||
"target": "RAPP-POLICY-NEXUS-WP-0002-T02",
|
||||
"relationship_type": "starts_after",
|
||||
"from_workplan_id": "ec41a4bd-df18-5b07-9b63-ccb80d9f001c",
|
||||
"from_task_id": "2afb1aac-66dd-5e1e-92e1-fc020a59a927",
|
||||
"to_workplan_id": null,
|
||||
"to_task_id": "18b26ecc-4fb8-516b-8d97-62ff39a85f24"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0043",
|
||||
"from": "RPF-WP-0043-T04",
|
||||
"target": "RPF-WP-0043-T03",
|
||||
"relationship_type": "starts_after",
|
||||
"from_workplan_id": "ec41a4bd-df18-5b07-9b63-ccb80d9f001c",
|
||||
"from_task_id": "8638fa73-439d-5dcd-85c7-81aa125170e1",
|
||||
"to_workplan_id": null,
|
||||
"to_task_id": "2afb1aac-66dd-5e1e-92e1-fc020a59a927"
|
||||
},
|
||||
{
|
||||
"workplan": "RPF-WP-0043",
|
||||
"from": "RPF-WP-0043-T04",
|
||||
"target": "RPF-WP-0044-T07",
|
||||
"relationship_type": "starts_after",
|
||||
"from_workplan_id": "ec41a4bd-df18-5b07-9b63-ccb80d9f001c",
|
||||
"from_task_id": "8638fa73-439d-5dcd-85c7-81aa125170e1",
|
||||
"to_workplan_id": null,
|
||||
"to_task_id": "844ff115-def2-55ca-ab01-413ba7e6857d"
|
||||
}
|
||||
],
|
||||
"refused": [],
|
||||
"notes": []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"exit_code": 0,
|
||||
"commit": "104ed90f42a9a86bf9fda343b49b65a85c9ee4b9",
|
||||
"base": "0a9617a62d4696a8070798923b459e8405c3dbf2",
|
||||
"files": [
|
||||
{
|
||||
"path": "docs/keycape-issuer-eso-contract.md",
|
||||
"sha256": "7f59e59b17c58252982931ac61fe50dd7a07340add6c437fe48af36971eafe68"
|
||||
},
|
||||
{
|
||||
"path": "manifests/templates/keycape-issuer-eso.yaml",
|
||||
"sha256": "e17498bd8a4c820041a4105e4efe9c60c6a50953db8f621ff54887080065c743"
|
||||
},
|
||||
{
|
||||
"path": "scripts/keycape_issuer_eso.py",
|
||||
"sha256": "21c5797280c2a7825dbda8ac970d34a0cdef4c6458f68bce0b1c12407f122a87"
|
||||
},
|
||||
{
|
||||
"path": "tests/test_keycape_issuer_eso.py",
|
||||
"sha256": "223d4c5b349062b9f93e6af79e8d5feda44377ba41a11726f6f2b762691e8308"
|
||||
}
|
||||
],
|
||||
"stdout": "[main 104ed90] feat: declare proposed fixed KeyCape issuer ESO source contract\n 4 files changed, 313 insertions(+)\n create mode 100644 docs/keycape-issuer-eso-contract.md\n create mode 100644 manifests/templates/keycape-issuer-eso.yaml\n create mode 100644 scripts/keycape_issuer_eso.py\n create mode 100644 tests/test_keycape_issuer_eso.py\n",
|
||||
"stderr": "{\"blocked_blob_ids\": [], \"scanned_blobs\": 4, \"scanner_sha256\": \"88f91962aa2f93ac6ab281d553b9e125f5197bbbce38f9f2437f7299c32e5509\", \"scanner_version\": \"8.30.1\", \"scope\": \"changed-staged-blobs\", \"status\": \"clean\"}\n"
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"owner": "railiance-platform",
|
||||
"base_revision": "0a9617a62d4696a8070798923b459e8405c3dbf2",
|
||||
"files": [
|
||||
{
|
||||
"path": "docs/keycape-issuer-eso-contract.md",
|
||||
"sha256": "7f59e59b17c58252982931ac61fe50dd7a07340add6c437fe48af36971eafe68"
|
||||
},
|
||||
{
|
||||
"path": "manifests/templates/keycape-issuer-eso.yaml",
|
||||
"sha256": "e17498bd8a4c820041a4105e4efe9c60c6a50953db8f621ff54887080065c743"
|
||||
},
|
||||
{
|
||||
"path": "scripts/keycape_issuer_eso.py",
|
||||
"sha256": "21c5797280c2a7825dbda8ac970d34a0cdef4c6458f68bce0b1c12407f122a87"
|
||||
},
|
||||
{
|
||||
"path": "tests/test_keycape_issuer_eso.py",
|
||||
"sha256": "223d4c5b349062b9f93e6af79e8d5feda44377ba41a11726f6f2b762691e8308"
|
||||
}
|
||||
],
|
||||
"message": "feat: declare proposed fixed KeyCape issuer ESO source contract"
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
# Independent Platform-scoped source review: NK48-R5-F2
|
||||
|
||||
Decision: **accept the exact Platform candidate as reviewable source**. No blocking
|
||||
source-fit defect was reproduced. This is an independent reviewer decision, not
|
||||
Platform owner assent, source adoption, descriptor acceptance or execution authority.
|
||||
The conditional NetKingdom patch may be incorporated into the coordinator's
|
||||
combined candidate; report F2's exact-store-reference requirement closed only
|
||||
after the Platform source is actually adopted. No canonical files were edited.
|
||||
|
||||
The proposed `ClusterSecretStore openbao-keycape-{client_id}-issuer` is a new,
|
||||
explicit owner-controlled declaration. It is not a store name granted by
|
||||
CCR-2026-0041. For Forgejo, its role, Kubernetes auth mount, service account,
|
||||
audience and exact KV path agree with that CCR. The `platform` provider mount
|
||||
and `workloads/keycape/forgejo` remoteRef correctly form the custody path without
|
||||
double-prefixing it. The `sso` condition and cluster scope agree with Platform's
|
||||
historical issuer draft. The consumer namespace SecretStore is never substituted.
|
||||
No role, policy, grant, catalog or caller-selectable store/path is added.
|
||||
|
||||
The pure helper is appropriate preparation under existing RPF-1.3-T4. It checks
|
||||
fixed identity, complete spec equality and Ready status; it exposes only the
|
||||
ExternalSecret through its delivery-facing function. It neither provisions the
|
||||
store nor issues receipts. Admitted IDs ending in `-` remain representable because
|
||||
the fixed suffix completes the resource name. The adapter's effective bound is
|
||||
client ID length 48: `keycape-` + ID + `-client` is at most 63 characters. The
|
||||
store reaches 71 characters and is a DNS subdomain resource name, so a separate
|
||||
63-character store label bound would incorrectly narrow the type.
|
||||
|
||||
Both patches applied to clean archives of the exact specified commits, all nine
|
||||
source-pins matched, the eight supplied tests passed, and independent boundary
|
||||
checks accepted IDs of length 2, 47 and 48 while rejecting 1, 49 and 63. Parsing
|
||||
the patched type proved that only
|
||||
`spec.follow_through[id=deliver-secret].entry_point` changed. The pinned template
|
||||
hash matches its exact content. See `evidence.json`, `focused-tests.txt` and the
|
||||
replayable `reproduce.py`. Archive subprocesses and tests received a minimal
|
||||
environment with no ambient credentials; no native infrastructure calls occurred.
|
||||
|
||||
These source checks establish neither the installed ESO CRD shape/defaulting nor
|
||||
trusted live resource observations. Strict spec equality may reject harmless API
|
||||
defaults; the actual owner implementation must handle them deliberately without
|
||||
allowing semantic drift. The audience placement follows the historical issuer
|
||||
draft, not the older scaffold's differing placement. No installed schema proof is
|
||||
claimed. The `sso` condition limits store users by namespace; the shared ESO
|
||||
controller and writers in that namespace remain within the documented trust
|
||||
boundary.
|
||||
|
||||
The concrete next implementation is the existing RPF-1.3-T4 binding: authenticate
|
||||
the admitted case/client and attempt session; retrieve and validate this exact
|
||||
preexisting store through a contained owner path; create the exact ExternalSecret
|
||||
or refuse a differing one; issue NO_CHANGE for an exact preexisting match only
|
||||
after Ready readback; and publish/authenticate the closed metadata receipt. Its
|
||||
before/after UID and resourceVersion must come from that trusted operation, not
|
||||
from caller-supplied fixture dictionaries. Preserve the preexisting/adoption guard:
|
||||
these helpers confer no ownership on a preexisting ExternalSecret or target Secret,
|
||||
and no created receipt may be fabricated from matching spec or Ready alone. The
|
||||
real binding must handle preexisting target collisions through the owner's
|
||||
containment/adoption policy, without broad Secret reads or inferred adoption.
|
||||
|
||||
Implement remove using authenticated case-created provenance plus exact UID and
|
||||
resourceVersion delete preconditions, allow owned target garbage collection,
|
||||
revoke the parent session per attempt, and route drift or uncertain ownership to
|
||||
owner reconciliation. Catalog routing remains the existing Warden owner work.
|
||||
These are carried implementation obligations, not new tasks or permission gates.
|
||||
|
||||
Inputs: Platform `0a9617a62d4696a8070798923b459e8405c3dbf2`, NetKingdom
|
||||
`3236d5000e52e0643f33906a26a7825aa0b67465`, and the adjacent
|
||||
`nk48-r5-f2-implementation-r1` packet. Exact packet file hashes and archive hashes
|
||||
are in `evidence.json`. Review also read Platform AGENTS/INTENT, the original
|
||||
Platform owner contract and CCR0041, issuer ESO draft, lane design and scaffold,
|
||||
plus r5's F2 finding and the NetKingdom security companion. No separate fix was
|
||||
needed and the author's record was not rewritten.
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
{
|
||||
"source_only": true,
|
||||
"ambient_credentials_passed": false,
|
||||
"native_calls": false,
|
||||
"bases": {
|
||||
"railiance-platform": "0a9617a62d4696a8070798923b459e8405c3dbf2",
|
||||
"net-kingdom": "3236d5000e52e0643f33906a26a7825aa0b67465"
|
||||
},
|
||||
"input_hashes": {
|
||||
"OWNER-REVIEW.md": "sha256:7983fd841f09bc7584047426912c33d568c97b4c1126776f99aac42b34d2b742",
|
||||
"canonical-source-readonly-state.json": "sha256:129d6926bb996e510ab4b41d30e738096b53b71de1fb2dd470fe0ac94848cbec",
|
||||
"focused-tests.json": "sha256:8de5862a8d752dce0b3b96a9275e42952a99415a18d3f67c06bf9f5b6008d0e3",
|
||||
"focused-tests.txt": "sha256:aab46c51d87198ad4be6dd3078f61286e2faf1ef4d76fa14298698388f78ab24",
|
||||
"manifest.json": "sha256:754531fbef468bc0e432bd26d4dbed992294c34d57e23fe7c3b7f829f7a24ba4",
|
||||
"netkingdom-entry-point.conditional.patch": "sha256:6784a21fbd10bd62712be2e0f4929034601c94629aa74ccaa2e93fc815eecd61",
|
||||
"platform-candidate/docs/keycape-issuer-eso-contract.md": "sha256:7f59e59b17c58252982931ac61fe50dd7a07340add6c437fe48af36971eafe68",
|
||||
"platform-candidate/manifests/templates/keycape-issuer-eso.yaml": "sha256:e17498bd8a4c820041a4105e4efe9c60c6a50953db8f621ff54887080065c743",
|
||||
"platform-candidate/scripts/keycape_issuer_eso.py": "sha256:21c5797280c2a7825dbda8ac970d34a0cdef4c6458f68bce0b1c12407f122a87",
|
||||
"platform-candidate/tests/test_keycape_issuer_eso.py": "sha256:223d4c5b349062b9f93e6af79e8d5feda44377ba41a11726f6f2b762691e8308",
|
||||
"platform.candidate.patch": "sha256:a490df7dee41e15351da8d2906e1342edebb533984befe3d9ae74d952dbb091b",
|
||||
"review.json": "sha256:d99db9ab4f326308cde464129bbbb7573434e500fd03c130a37a590bac3643a4",
|
||||
"source-pins.json": "sha256:6e896b6196a0aca01ddaf433b4d14cc041fc0296c5dd6404c3a698b941b61bd8",
|
||||
"structural-and-patch-checks.json": "sha256:a3dc4cd405c412d4369986cc6736cd2d9eed02d4b86d95d62d5a9914106fdb14",
|
||||
"type.before.yaml": "sha256:e75fe94110ef9fb7fb18072fe2856941b33507c99cb406d36576046481485d0a",
|
||||
"type.candidate.yaml": "sha256:ef02ddae3167bdd1558193a5f6db0379fb8cc84207531706d5ef35caabc3684f"
|
||||
},
|
||||
"checks": {
|
||||
"all_source_pins_verified": true,
|
||||
"both_patches_apply_to_exact_archives": true,
|
||||
"focused_tests": "8 tests passed",
|
||||
"only_type_delta": "spec.follow_through[id=deliver-secret].entry_point",
|
||||
"independent_length_boundaries": "2,47,48 accepted; 1,49,63 refused",
|
||||
"template_hash_matches_type": true
|
||||
},
|
||||
"archive_sha256": {
|
||||
"railiance-platform": "sha256:0798af8b0171a5925a10b520269c45b83b03eaa97650831e17c2aaaeb696bbd9",
|
||||
"net-kingdom": "sha256:e2852f444ed3c1501107b3cc1aef088e7d30f953284ca310149cc46424da12b3"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
test_delivery_document_is_only_external_and_detached (test_keycape_issuer_eso.FixedIssuerContract.test_delivery_document_is_only_external_and_detached) ... ok
|
||||
test_external_drift_refuses (test_keycape_issuer_eso.FixedIssuerContract.test_external_drift_refuses) ... ok
|
||||
test_independent_forgejo_binding (test_keycape_issuer_eso.FixedIssuerContract.test_independent_forgejo_binding) ... ok
|
||||
test_missing_or_unready_refuses (test_keycape_issuer_eso.FixedIssuerContract.test_missing_or_unready_refuses) ... ok
|
||||
test_no_caller_store_or_path_override (test_keycape_issuer_eso.FixedIssuerContract.test_no_caller_store_or_path_override) ... ok
|
||||
test_store_drift_refuses (test_keycape_issuer_eso.FixedIssuerContract.test_store_drift_refuses) ... ok
|
||||
test_type_admitted_trailing_dash_is_preserved (test_keycape_issuer_eso.FixedIssuerContract.test_type_admitted_trailing_dash_is_preserved) ... ok
|
||||
test_valid_ready_metadata_allows_extra_controller_metadata (test_keycape_issuer_eso.FixedIssuerContract.test_valid_ready_metadata_allows_extra_controller_metadata) ... ok
|
||||
|
||||
----------------------------------------------------------------------
|
||||
Ran 8 tests in 0.294s
|
||||
|
||||
OK
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
"""Independent source-only review; archived trees and public synthetic fixtures."""
|
||||
import hashlib
|
||||
import importlib.util
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import tarfile
|
||||
import tempfile
|
||||
import yaml
|
||||
|
||||
OUT = Path(__file__).resolve().parent
|
||||
PACKET = OUT.parent / 'nk48-r5-f2-implementation-r1'
|
||||
BASES = {'railiance-platform': '0a9617a62d4696a8070798923b459e8405c3dbf2',
|
||||
'net-kingdom': '3236d5000e52e0643f33906a26a7825aa0b67465'}
|
||||
ENV = {'PATH': '/usr/local/bin:/usr/bin:/bin', 'HOME': '/tmp', 'PYTHONDONTWRITEBYTECODE': '1'}
|
||||
def run(args, cwd):
|
||||
return subprocess.run(args, cwd=cwd, env=ENV, capture_output=True, text=True, check=True).stdout
|
||||
def sha(data):
|
||||
return hashlib.sha256(data).hexdigest()
|
||||
|
||||
result = {'source_only': True, 'ambient_credentials_passed': False, 'native_calls': False,
|
||||
'bases': BASES, 'input_hashes': {}, 'checks': {}}
|
||||
for p in sorted(PACKET.rglob('*')):
|
||||
if p.is_file():
|
||||
result['input_hashes'][str(p.relative_to(PACKET))] = sha(p.read_bytes())
|
||||
with tempfile.TemporaryDirectory(prefix='platform-f2-independent-') as scratch:
|
||||
roots = {}
|
||||
for repo, commit in BASES.items():
|
||||
dest = Path(scratch) / repo
|
||||
dest.mkdir()
|
||||
archive = subprocess.run(['git', '-C', '/home/worsch/' + repo, 'archive', commit],
|
||||
env=ENV, capture_output=True, check=True).stdout
|
||||
with tarfile.open(fileobj=io.BytesIO(archive)) as tf:
|
||||
tf.extractall(dest, filter='data')
|
||||
roots[repo] = dest
|
||||
result.setdefault('archive_sha256', {})[repo] = sha(archive)
|
||||
for pin in json.loads((PACKET / 'source-pins.json').read_text()):
|
||||
repo = pin['repo']
|
||||
root = roots.get(repo, Path('/home/worsch/the-custodian'))
|
||||
actual = sha((root / pin['path']).read_bytes())
|
||||
assert actual == pin['sha256'], pin['path']
|
||||
result['checks']['all_source_pins_verified'] = True
|
||||
for repo, patch in [('railiance-platform', 'platform.candidate.patch'),
|
||||
('net-kingdom', 'netkingdom-entry-point.conditional.patch')]:
|
||||
run(['git', 'apply', '--check', str(PACKET / patch)], roots[repo])
|
||||
run(['git', 'apply', str(PACKET / patch)], roots[repo])
|
||||
result['checks']['both_patches_apply_to_exact_archives'] = True
|
||||
platform = roots['railiance-platform']
|
||||
tests = subprocess.run(['/usr/bin/python3', '-m', 'unittest', 'discover', '-s', 'tests',
|
||||
'-p', 'test_keycape_issuer_eso.py', '-v'], cwd=platform,
|
||||
env=ENV, capture_output=True, text=True)
|
||||
(OUT / 'focused-tests.txt').write_text(tests.stdout + tests.stderr)
|
||||
assert tests.returncode == 0
|
||||
result['checks']['focused_tests'] = '8 tests passed'
|
||||
type_path = roots['net-kingdom'] / 'security-case-type-revisions/1.3/oidc-browser-relying-party/type.yaml'
|
||||
before = yaml.safe_load((PACKET / 'type.before.yaml').read_text())
|
||||
after = yaml.safe_load(type_path.read_text())
|
||||
before_step = next(s for s in before['spec']['follow_through'] if s['id'] == 'deliver-secret')
|
||||
after_step = next(s for s in after['spec']['follow_through'] if s['id'] == 'deliver-secret')
|
||||
assert before_step['entry_point'] != after_step['entry_point']
|
||||
after_step['entry_point'] = before_step['entry_point']
|
||||
assert before == after
|
||||
result['checks']['only_type_delta'] = 'spec.follow_through[id=deliver-secret].entry_point'
|
||||
spec = importlib.util.spec_from_file_location('issuer', platform / 'scripts/keycape_issuer_eso.py')
|
||||
issuer = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(issuer)
|
||||
for n in (2, 47, 48):
|
||||
store, external = issuer.documents('a' * n)
|
||||
assert len(external['metadata']['name']) <= 63
|
||||
assert len(store['metadata']['name']) <= 253
|
||||
for n in (1, 49, 63):
|
||||
try:
|
||||
issuer.documents('a' * n)
|
||||
except issuer.Refused:
|
||||
pass
|
||||
else:
|
||||
raise AssertionError(n)
|
||||
result['checks']['independent_length_boundaries'] = '2,47,48 accepted; 1,49,63 refused'
|
||||
result['checks']['template_hash_matches_type'] = (
|
||||
sha((platform / 'manifests/templates/keycape-issuer-eso.yaml').read_bytes())
|
||||
in yaml.safe_load(type_path.read_text())['spec']['follow_through'][
|
||||
next(i for i,s in enumerate(before['spec']['follow_through']) if s['id']=='deliver-secret')]['entry_point'])
|
||||
assert result['checks']['template_hash_matches_type']
|
||||
(OUT / 'evidence.json').write_text(json.dumps(result, indent=2) + '\n')
|
||||
print(json.dumps(result['checks'], indent=2))
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"schema": "custodian.nk48-r5-f2-independent-source-review.v1",
|
||||
"date": "2026-10-17",
|
||||
"reviewer": "independent Platform-scoped Codex subagent",
|
||||
"finding": "NK48-R5-F2",
|
||||
"decision": "accept-for-reviewable-source",
|
||||
"blocking_source_findings": [],
|
||||
"source_owner_assent_received": false,
|
||||
"source_adoption_performed": false,
|
||||
"f2_closed": false,
|
||||
"f2_closure_condition": "Actual Platform adoption of the explicit source declaration followed by integration of its exact conditional entry_point into the successor candidate.",
|
||||
"platform_base": "0a9617a62d4696a8070798923b459e8405c3dbf2",
|
||||
"netkingdom_base": "3236d5000e52e0643f33906a26a7825aa0b67465",
|
||||
"accepted_platform_patch_sha256": "a490df7dee41e15351da8d2906e1342edebb533984befe3d9ae74d952dbb091b",
|
||||
"conditional_netkingdom_patch_sha256": "6784a21fbd10bd62712be2e0f4929034601c94629aa74ccaa2e93fc815eecd61",
|
||||
"template_sha256": "e17498bd8a4c820041a4105e4efe9c60c6a50953db8f621ff54887080065c743",
|
||||
"evidence": ["evidence.json", "focused-tests.txt", "reproduce.py", "REVIEW.md"],
|
||||
"next_implementation": "Existing RPF-1.3-T4 authenticated deliver/remove, trusted metadata readback and closed receipts, attempt-session revocation, created-only rollback and catalog routing; preserve preexisting/adoption guards and confirm installed ESO schema/defaulting.",
|
||||
"native_execution_performed": false,
|
||||
"canonical_edits_or_commits": false,
|
||||
"new_grants_or_workplans": false,
|
||||
"candidate_fix_needed": false
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue