101 lines
5.6 KiB
Python
101 lines
5.6 KiB
Python
"""Prepare or apply the verified producer source without changing live admission."""
|
|
from pathlib import Path
|
|
import argparse
|
|
import hashlib
|
|
import json
|
|
import re
|
|
import subprocess
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
PACKET = HERE.parents[1] / 'netkingdom-target-2026-10-17/apps-access-engine-integration-r2'
|
|
OWNER = Path('/home/worsch/access-engine')
|
|
BASE = 'd328a2601095686f74376d87791bff01e2a3a2a3'
|
|
PLAN = 'workplans/FLEX-WP-0024-decision-envelope-authenticity.md'
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('action', choices=['prepare', 'apply'])
|
|
args = parser.parse_args()
|
|
|
|
|
|
def sha(raw):
|
|
return hashlib.sha256(raw).hexdigest()
|
|
|
|
|
|
def git(*argv):
|
|
return subprocess.check_output(['git', '-C', str(OWNER), *argv], stderr=subprocess.PIPE).decode().strip()
|
|
|
|
|
|
assert git('rev-parse', 'HEAD') == BASE
|
|
files = []
|
|
for item in sorted((PACKET / 'access-engine-source').rglob('*')):
|
|
if not item.is_file():
|
|
continue
|
|
name = str(item.relative_to(PACKET / 'access-engine-source'))
|
|
if name == 'examples/forgejo-application-access/registry.synthetic.json':
|
|
continue # Only the recognized, tested registry snapshot is shipped.
|
|
target = OWNER / name
|
|
preimage = PACKET / 'preimages/access-engine' / name
|
|
if target.exists():
|
|
assert preimage.is_file() and target.read_bytes() == preimage.read_bytes(), name
|
|
assert git('diff', 'HEAD', '--', name) == '', name
|
|
files.append({'path': name, 'source': str(item), 'before_sha256': sha(target.read_bytes()) if target.exists() else None,
|
|
'sha256': sha(item.read_bytes())})
|
|
plan_before = (OWNER / PLAN).read_bytes()
|
|
plan_after = plan_before.decode().replace('updated: "2026-10-16"', 'updated: "2026-10-18"', 1)
|
|
plan_after += '''
|
|
|
|
2026-10-18 source implementation under CUST-WP-0080 / NK-WP-0048-T43:
|
|
the producer-owned normal Check client now authenticates exact policy/registry/
|
|
caller/request/lifetime bindings with a nonce and the optional lossless JSON
|
|
profile. The default legacy decoder and unchanged signature/API contract remain
|
|
intact. Root pkg/decisionpep is the source of truth; its Go1.24 consumer slice is
|
|
generated by tools/export_decisionpep_adapter.py and checked by ordinary tests.
|
|
The Forgejo example uses authoritative registry tenant/issuer facts and verified
|
|
runtime identity in the admitted caller's request context. Actual producer
|
|
regressions reproduce/refuse object-shaped group inputs; policy fixtures and
|
|
Rego tests validate the original three-group contract. Full isolated root race
|
|
suite: 494 test/subtest passes, three existing optional/fixture skips. Export
|
|
parity and final group-shape regressions pass. Detailed source pins and retained
|
|
failures are in Custodian apps-access-engine-integration-r2.
|
|
|
|
This is source delivery, not owner assent or native admission. Synthetic keys,
|
|
registry and local callback proof establish no live signer/caller/policy grant.
|
|
Existing rollout R2/image84 and their approvals remain frozen; they do not admit
|
|
this source or a new image. T06 and all native custody/trust/rollout/recovery gates
|
|
remain open. Forgejo's complete resource/operation/inverse and session-revocation
|
|
coverage remains NK48-T43 / RAPPS16-T09 work.
|
|
'''
|
|
assert re.findall(r'```task\n.*?```', plan_before.decode(), re.S) == re.findall(r'```task\n.*?```', plan_after, re.S)
|
|
files.append({'path': PLAN, 'source': str(HERE / 'workplan.postimage.md'), 'before_sha256': sha(plan_before), 'sha256': sha(plan_after.encode())})
|
|
protected = []
|
|
for name in ['.custodian-brief.md', 'WORK-RECORDS.md']:
|
|
protected.append({'path': name, 'sha256': sha((OWNER / name).read_bytes()), 'index': git('ls-files', '--stage', '--', name)})
|
|
|
|
if args.action == 'prepare':
|
|
assert not (HERE / 'source-manifest.json').exists()
|
|
race = json.loads((PACKET / 'producer-race-result.json').read_text())
|
|
assert race['returncode'] == 0
|
|
assert json.loads((PACKET / 'shapes-after.json').read_text())['returncode'] == 0
|
|
assert json.loads((PACKET / 'producer-layer-check.json').read_text())['returncode'] == 0
|
|
(HERE / 'workplan.preimage.md').write_bytes(plan_before)
|
|
(HERE / 'workplan.postimage.md').write_text(plan_after)
|
|
(HERE / 'source-manifest.json').write_text(json.dumps({'base': BASE, 'files': files, 'protected': protected,
|
|
'native_changes': False, 'formal_owner_assent': False}, indent=2) + '\n')
|
|
(HERE / 'publication-inputs.json').write_text(json.dumps({'owner': 'access-engine', 'base_revision': BASE,
|
|
'message': 'Add producer-owned authenticated Go decision client and validated Forgejo profile',
|
|
'files': [{'path': row['path'], 'sha256': row['sha256']} for row in files]}, indent=2) + '\n')
|
|
print(json.dumps({'status': 'prepared', 'files': len(files), 'native_changes': False}))
|
|
else:
|
|
manifest = json.loads((HERE / 'source-manifest.json').read_text())
|
|
assert files == manifest['files'] and protected == manifest['protected']
|
|
for row in files:
|
|
assert sha(Path(row['source']).read_bytes()) == row['sha256'], row['path']
|
|
for row in files:
|
|
target = OWNER / row['path']
|
|
target.parent.mkdir(parents=True, exist_ok=True)
|
|
target.write_bytes(Path(row['source']).read_bytes())
|
|
for row in protected:
|
|
assert sha((OWNER / row['path']).read_bytes()) == row['sha256']
|
|
assert git('ls-files', '--stage', '--', row['path']) == row['index']
|
|
(HERE / 'source-application.json').write_text(json.dumps({'status': 'applied', 'files': len(files), 'base': BASE,
|
|
'native_changes': False, 'protected_worktree_and_index_preserved': True, 'formal_owner_assent': False}, indent=2) + '\n')
|
|
print(json.dumps({'status': 'applied', 'files': len(files), 'native_changes': False}))
|