Seal Phase 4AK frozen D18 independent validation

This commit is contained in:
Digital Drosophila Archive
2026-09-30 13:18:18 +08:00
parent cb6937666f
commit c6444255fe
1313 changed files with 154250 additions and 15 deletions
@@ -0,0 +1,337 @@
"""Fetch only externally anchored Phase 4AK small evidence and model source.
No SSH connection is made at import. The API accepts an already authenticated
SFTP client; the CLI rejects unknown host keys. This is not a trajectory backup
or a local re-verification of remote bulk payloads/scientific gates.
"""
from __future__ import annotations
import argparse
import hashlib
import json
import os
from pathlib import Path, PurePosixPath
import re
import stat
REMOTE_ROOT = '/data/digital-drosophila'
MODEL_RELATIVE = 'models/male-cns-lif/apl-timing-validation-v1'
EXPERIMENT_RELATIVE = 'experiments/phase4ak-apl-timing-validation'
REGISTRY_RELATIVE = 'registry/phase4ak-apl-timing-validation'
MODEL_ROOT = REMOTE_ROOT + '/' + MODEL_RELATIVE
REGISTRY_ROOT = REMOTE_ROOT + '/' + REGISTRY_RELATIVE
DEFAULT_DESTINATION = Path(__file__).resolve().parents[2] / 'reports/phase4ak-apl-timing-validation'
MAX_FILE_BYTES = 4 * 1024**2
MAX_TOTAL_BYTES = 1024**3
EVIDENCE_SUFFIXES = frozenset(('.json', '.csv', '.md', '.log', '.sha256'))
SOURCE_SUFFIXES = frozenset(('.py', '.json', '.md', '.yaml', '.yml', '.toml', '.txt', '.sha256', '.cpp', '.cu', '.h', '.hpp'))
CONTROLS = ('manifest.json', 'checksums.sha256')
GENERATED = ('seal-verification.json', 'evidence-index.json')
SHA = re.compile(r'[0-9a-f]{64}\Z')
def require(condition, message):
if not condition:
raise ValueError(message)
def sha(data):
return hashlib.sha256(data).hexdigest()
def unique_object(pairs):
result = {}
for key, value in pairs:
require(key not in result, 'Duplicate JSON key: ' + key)
result[key] = value
return result
def json_bytes(data):
def bad(value):
raise ValueError('Nonfinite JSON constant: ' + value)
return json.loads(data.decode('utf-8'), object_pairs_hook=unique_object, parse_constant=bad)
def relative_name(value):
require(isinstance(value, str) and value and not any(c in value for c in ('\\', '\0', '\r', '\n', ':')),
'Invalid relative filename')
path = PurePosixPath(value)
require(not path.is_absolute() and path.as_posix() == value and
all(part not in ('', '.', '..', '__pycache__') and not part.endswith((' ', '.')) for part in path.parts),
'Noncanonical/escaping/cache filename: ' + value)
devices = {'CON', 'PRN', 'AUX', 'NUL', *(f'COM{i}' for i in range(1, 10)), *(f'LPT{i}' for i in range(1, 10))}
require(all(part.split('.')[0].upper() not in devices for part in path.parts), 'Reserved local filename')
return path
def file_row(row, *, small=False):
require(isinstance(row, dict) and set(row) == {'path', 'bytes', 'sha256'}, 'Invalid hash-inventory row')
relative_name(row['path'])
require(type(row['bytes']) is int and row['bytes'] >= 0 and isinstance(row['sha256'], str) and
SHA.fullmatch(row['sha256']), 'Invalid file size/SHA')
if small:
require(row['bytes'] <= MAX_FILE_BYTES, 'Receipt file exceeds 4 MiB: ' + row['path'])
return row
class BoundedSFTP:
def __init__(self, sftp):
self.sftp = sftp
self.directories = set()
def read(self, remote, size=None, checksum=None):
require(remote.startswith(REGISTRY_ROOT + '/') or remote.startswith(MODEL_ROOT + '/'),
'Remote request outside fixed AK registry/model scope')
# Never list a remote directory or discover unregistered sidecars.
parent = PurePosixPath(remote).parent
for directory in reversed((parent, *parent.parents)):
name = str(directory)
if name not in self.directories:
require(stat.S_ISDIR(self.sftp.lstat(name).st_mode), 'Remote symlink/non-directory: ' + name)
self.directories.add(name)
info = self.sftp.lstat(remote)
require(stat.S_ISREG(info.st_mode), 'Remote symlink/nonregular file: ' + remote)
require(0 <= info.st_size <= MAX_FILE_BYTES and (size is None or info.st_size == size),
'Remote size outside expected small-file limit: ' + remote)
chunks, count = [], 0
with self.sftp.open(remote, 'rb') as source:
while True:
block = source.read(min(1 << 20, MAX_FILE_BYTES + 1 - count))
if not block:
break
count += len(block)
require(count <= MAX_FILE_BYTES, 'Remote file grew beyond download limit')
chunks.append(block)
data = b''.join(chunks)
require(len(data) == info.st_size and (size is None or len(data) == size), 'Remote size changed during read')
if checksum is not None:
require(sha(data) == checksum, 'Remote file SHA mismatch: ' + remote)
return data
def validate_receipt(data, expected_sha):
require(sha(data) == expected_sha, 'External publication-receipt SHA mismatch')
receipt = json_bytes(data)
require(isinstance(receipt, dict) and receipt.get('publication_complete') is True and
receipt.get('registry') == REGISTRY_RELATIVE and receipt.get('project_root') == REMOTE_ROOT,
'Wrong/incomplete AK publication receipt')
for key in ('source_trees_verified_before_and_after_copy', 'publication_success_is_not_scientific_pass'):
require(receipt.get(key) is True, 'Missing publication qualification: ' + key)
for key in ('complete_bulk_backup', 'scientific_gate_executed_by_publisher',
'scientific_gate_certified_by_publication', 'candidate_generated', 'learning_achieved'):
require(receipt.get(key) is False, 'Unexpected publication claim: ' + key)
require(receipt.get('limits') == dict(max_selected_evidence_file_bytes=MAX_FILE_BYTES,
selected_suffixes=sorted(EVIDENCE_SUFFIXES)), 'Unexpected publication selection limits')
for key in ('model_manifest_sha256', 'experiment_manifest_sha256'):
require(isinstance(receipt.get(key), str) and SHA.fullmatch(receipt[key]), 'Missing manifest anchor: ' + key)
rows = {}
require(isinstance(receipt.get('files'), list) and receipt['files'], 'Empty receipt inventory')
for row in receipt['files']:
file_row(row, small=True)
name = row['path']
require(name not in rows, 'Duplicate receipt file: ' + name)
allowed = name in GENERATED or name in ('model/manifest.json', 'model/checksums.sha256') or (
name.startswith('evidence/') and PurePosixPath(name).suffix.lower() in EVIDENCE_SUFFIXES)
require(allowed, 'Receipt attempts a non-evidence/sidecar download: ' + name)
rows[name] = row
required = {'model/manifest.json', 'model/checksums.sha256', 'evidence/manifest.json',
'evidence/checksums.sha256', 'evidence/audit/final-status.json',
'evidence/regression/old-integrity-after.json', *GENERATED}
require(required.issubset(rows), 'Receipt omits required AK evidence/seal controls')
return receipt, rows
def validate_manifest(manifest_data, checksums_data, expected_root, expected_sha):
require(sha(manifest_data) == expected_sha, 'Receipt/manifest SHA mismatch')
manifest = json_bytes(manifest_data)
require(isinstance(manifest, dict) and set(manifest) == {'root', 'files'} and
manifest['root'] == expected_root and isinstance(manifest['files'], list) and manifest['files'],
'Wrong seal manifest schema/root')
rows = {}
for row in manifest['files']:
file_row(row)
require(row['path'] not in rows and row['path'] not in CONTROLS, 'Duplicate/control manifest payload')
rows[row['path']] = row
checksums = {}
for line in checksums_data.decode('utf-8').splitlines():
require(len(line) >= 67 and line[64:66] == ' ' and SHA.fullmatch(line[:64]), 'Invalid checksum line')
name = line[66:]
relative_name(name)
require(name not in checksums, 'Duplicate checksum filename')
checksums[name] = line[:64]
require(checksums == {**{name: row['sha256'] for name, row in rows.items()}, 'manifest.json': expected_sha},
'Manifest self-SHA/checksum inventory mismatch')
return rows
def local_name(registry_name):
if registry_name.startswith('evidence/'):
return registry_name[len('evidence/'):]
if registry_name.startswith('model/'):
return registry_name
return 'registry/' + registry_name
def _check_local_target(destination):
require(destination.is_absolute(), 'Report destination must be absolute')
for part in (destination, *destination.parents):
require(not part.is_symlink() and not getattr(part, 'is_junction', lambda: False)(),
'Local symlink/junction destination is forbidden')
require(not destination.exists(), 'Report destination exists; no overwrite/resume')
def _write(path, data):
path.parent.mkdir(parents=True, exist_ok=True)
with path.open('xb') as output:
output.write(data)
require(path.stat().st_size == len(data) and sha(path.read_bytes()) == sha(data), 'Local write verification failed')
def fetch(sftp, destination, receipt_sha256, *, max_total_bytes=MAX_TOTAL_BYTES):
"""SFTP read-only API. Destination is exclusive; receipt SHA is out-of-band.
Registry evidence/* mirrors into the report root, model/* into model/, and
receipt/generated publication metadata into registry/. Only source-whitelisted
model payloads are added; every transferred file is individually SHA checked.
"""
require(isinstance(receipt_sha256, str) and SHA.fullmatch(receipt_sha256.lower()), 'External receipt SHA256 is required')
receipt_sha256 = receipt_sha256.lower()
require(type(max_total_bytes) is int and max_total_bytes > 0, 'Invalid total download budget')
destination = Path(destination)
_check_local_target(destination)
remote = BoundedSFTP(sftp)
receipt_bytes = remote.read(REGISTRY_ROOT + '/publication-receipt.json', checksum=receipt_sha256)
receipt, rows = validate_receipt(receipt_bytes, receipt_sha256)
cached = {}
for prefix in ('model/', 'evidence/'):
for control in CONTROLS:
name = prefix + control; row = rows[name]
cached[name] = remote.read(REGISTRY_ROOT + '/' + name, row['bytes'], row['sha256'])
model_rows = validate_manifest(cached['model/manifest.json'], cached['model/checksums.sha256'],
MODEL_ROOT, receipt['model_manifest_sha256'])
experiment_rows = validate_manifest(cached['evidence/manifest.json'], cached['evidence/checksums.sha256'],
REMOTE_ROOT + '/' + EXPERIMENT_RELATIVE, receipt['experiment_manifest_sha256'])
# Model source is fetched from its sealed model path, not the registry. Bind
# its current controls to the receipt before reading any source payload.
for control in CONTROLS:
row = rows['model/' + control]
remote.read(MODEL_ROOT + '/' + control, row['bytes'], row['sha256'])
for name, row in rows.items():
if name.startswith('evidence/') and name[len('evidence/'):] not in CONTROLS:
original = experiment_rows.get(name[len('evidence/'):])
require(original is not None and all(row[key] == original[key] for key in ('bytes', 'sha256')),
'Registry evidence disagrees with experiment seal: ' + name)
for name in GENERATED:
row = rows[name]
cached[name] = remote.read(REGISTRY_ROOT + '/' + name, row['bytes'], row['sha256'])
proof = json_bytes(cached['seal-verification.json'])
for key, root, manifest_rows, prefix in (('model', MODEL_ROOT, model_rows, 'model/'),
('experiment', REMOTE_ROOT + '/' + EXPERIMENT_RELATIVE, experiment_rows, 'evidence/')):
item = proof.get(key, {})
require(item.get('pass_all') is True and item.get('root') == root and
item.get('manifest_sha256') == receipt[key + '_manifest_sha256'] and
item.get('checksums_sha256') == rows[prefix + 'checksums.sha256']['sha256'] and
item.get('payload_file_count') == len(manifest_rows) and
item.get('payload_bytes') == sum(row['bytes'] for row in manifest_rows.values()),
'Publication seal-verification disagrees with manifest: ' + key)
index = json_bytes(cached['evidence-index.json'])
require(isinstance(index, list), 'Invalid publication evidence index')
indexed = set()
for item in index:
require(isinstance(item, dict) and set(item) == {'source', 'copy', 'bytes', 'sha256'}, 'Invalid evidence-index row')
name = item['copy']
require(name in rows and name not in GENERATED and name not in indexed, 'Duplicate/unexpected evidence-index copy')
indexed.add(name)
expected_source = (EXPERIMENT_RELATIVE + '/' + name[len('evidence/'):] if name.startswith('evidence/')
else MODEL_RELATIVE + '/' + name[len('model/'):])
require(item['source'] == expected_source and all(item[key] == rows[name][key] for key in ('bytes', 'sha256')),
'Evidence-index source/hash mismatch')
require(indexed == set(rows) - set(GENERATED), 'Evidence-index coverage mismatch')
plan = [(REGISTRY_ROOT + '/' + name, local_name(name), row, cached.get(name)) for name, row in sorted(rows.items())]
omitted = []
for name, row in sorted(model_rows.items()):
if PurePosixPath(name).suffix.lower() in SOURCE_SUFFIXES and row['bytes'] <= MAX_FILE_BYTES:
plan.append((MODEL_ROOT + '/' + name, 'model/' + name, row, None))
else:
omitted.append(dict(row, reason='model_non_source_or_over_4_MiB'))
paths = ['registry/publication-receipt.json', 'fetch-verification.json', 'fetch-failure.json'] + [entry[1] for entry in plan]
lowered = [relative_name(name).as_posix().casefold() for name in paths]
require(len(set(lowered)) == len(lowered) and not any(
parent.as_posix().casefold() in set(lowered) for name in paths for parent in PurePosixPath(name).parents if str(parent) != '.'),
'Local case-insensitive/path-prefix collision')
planned_bytes = len(receipt_bytes) + sum(entry[2]['bytes'] for entry in plan)
require(planned_bytes <= max_total_bytes, 'Selected evidence exceeds total download budget')
_check_local_target(destination)
destination.mkdir(parents=True, exist_ok=False)
try:
_write(destination / 'registry/publication-receipt.json', receipt_bytes)
downloaded = []
for source, local, row, data in plan:
if data is None:
data = remote.read(source, row['bytes'], row['sha256'])
require(len(data) == row['bytes'] and sha(data) == row['sha256'], 'Cached/downloaded file hash mismatch')
_write(destination / local, data)
downloaded.append(dict(remote=source, local=local, bytes=len(data), sha256=sha(data)))
final = json_bytes((destination / 'audit/final-status.json').read_bytes())
require(final.get('status') == receipt.get('declared_audit_status'), 'Receipt/final-status declaration mismatch')
for key, value in receipt.get('declared_gate_results', {}).items():
require(final.get(key) == value and type(final.get(key)) is type(value), 'Receipt/final gate flag mismatch')
for key, value in receipt.get('declared_validation_counts', {}).items():
require(final.get(key) == value and type(final.get(key)) is type(value), 'Receipt/final coverage mismatch')
# Re-read immutable anchors, not unselected experiment payloads.
remote.read(REGISTRY_ROOT + '/publication-receipt.json', len(receipt_bytes), receipt_sha256)
for control in CONTROLS:
row = rows['model/' + control]
remote.read(MODEL_ROOT + '/' + control, row['bytes'], row['sha256'])
result = dict(fetch_complete=True, publication_receipt_sha256=receipt_sha256,
external_receipt_anchor_required=True, declared_audit_status=final['status'],
model_manifest_sha256=receipt['model_manifest_sha256'], experiment_manifest_sha256=receipt['experiment_manifest_sha256'],
both_manifest_self_checksums_verified=True, every_downloaded_file_sha256_verified=True,
files=downloaded, file_count=len(downloaded), selected_bytes=planned_bytes,
model_payload_not_downloaded=omitted, all_remote_experiment_bulk_rehashed_locally=False,
full_remote_seal_verification_is_publisher_receipt_claim=True, complete_bulk_backup=False,
scientific_gate_executed=False, scientific_pass_certified_by_fetch=False,
fetch_success_is_not_scientific_pass=True, candidate_generated=False, learning_achieved=False,
AJ_interpretation_sidecar_requested=False, existing_files_modified=False)
_write(destination / 'fetch-verification.json', (json.dumps(result, ensure_ascii=False, indent=2, allow_nan=False) + '\n').encode())
return result
except Exception as error:
failure = destination / 'fetch-failure.json'
if not failure.exists():
_write(failure, (json.dumps(dict(fetch_complete=False, type=type(error).__name__, message=str(error),
partial_outputs_preserved=True, existing_files_modified=False), allow_nan=False) + '\n').encode())
raise
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--receipt-sha256', required=True, help='Out-of-band SHA printed by the verified AK publisher')
parser.add_argument('--destination', type=Path, default=DEFAULT_DESTINATION)
parser.add_argument('--host', default='192.168.10.51')
parser.add_argument('--user', default='qishizhe')
parser.add_argument('--port', type=int, default=22)
parser.add_argument('--password-env', default='MALECNS_REMOTE_PASSWORD')
parser.add_argument('--known-hosts', type=Path, default=Path.home() / '.ssh/known_hosts',
help='Explicit existing user known_hosts; unknown hosts are always rejected')
args = parser.parse_args()
require(SHA.fullmatch(args.receipt_sha256.lower()), 'External receipt SHA256 is required')
_check_local_target(args.destination)
require(args.known_hosts.is_file(), 'Known-hosts file is missing; configure trust externally, never auto-add')
import paramiko
client = paramiko.SSHClient()
client.load_system_host_keys(str(args.known_hosts))
client.set_missing_host_key_policy(paramiko.RejectPolicy())
try:
client.connect(args.host, port=args.port, username=args.user, password=os.environ.get(args.password_env),
timeout=15, auth_timeout=15, banner_timeout=15)
with client.open_sftp() as sftp:
result = fetch(sftp, args.destination, args.receipt_sha256)
print(json.dumps({key: result[key] for key in ('fetch_complete', 'publication_receipt_sha256',
'declared_audit_status', 'file_count', 'fetch_success_is_not_scientific_pass')}), flush=True)
finally:
client.close()
if __name__ == '__main__':
main()
@@ -0,0 +1,234 @@
"""Exclusive small-evidence publication after both Phase 4AK seals verify.
Publication verifies and copies bytes. It never runs a brain, re-evaluates a
scientific gate, converts FAIL/INCOMPLETE into PASS, or changes frozen sources.
The source-pinned Phase 4AI verification/copy helpers are executed unchanged.
"""
from __future__ import annotations
import hashlib
import importlib.util
import json
from pathlib import Path, PurePosixPath
ROOT = Path('/data/digital-drosophila')
MODEL_RELATIVE = Path('models/male-cns-lif/apl-timing-validation-v1')
EXPERIMENT_RELATIVE = Path('experiments/phase4ak-apl-timing-validation')
REGISTRY_RELATIVE = Path('registry/phase4ak-apl-timing-validation')
HELPER_RELATIVE = Path('models/male-cns-lif/pn-recruitment-audit-v1/publication.py')
HELPER_SHA256 = '7a79c499098b74163e7bb16adabcbc54e7069dafa204d0b99c7f4c03d79f8016'
MAX_EVIDENCE_BYTES = 4 * 1024 ** 2
EVIDENCE_SUFFIXES = frozenset(('.json', '.csv', '.md', '.log', '.sha256'))
FINAL_STATUSES = frozenset((
'PASS-FROZEN-D18-INDEPENDENT-VALIDATION',
'FAIL-SEED-VALIDATION-REPRESENTATION',
'FAIL-NOVEL-ODOR-REPRESENTATION',
'FAIL-FROZEN-INTEGRITY-OR-REGRESSION',
'FAIL-NUMERICAL-OR-EXECUTION-POLICY',
'INCOMPLETE-VALIDATION-EXECUTION',
))
REQUIRED_EVIDENCE = ('audit/final-status.json', 'regression/old-integrity-after.json')
REFERENCE_EVIDENCE = 'regression/frozen-five.json'
GATE_FIELDS = ('numerical_gate_pass', 'seed_validation_pass', 'novel_to_aj_pass',
'novel_dynamics_executed', 'novel_unlock_policy_violation',
'old_frozen_integrity_pass', 'frozen_five_reference_pass')
COUNT_FIELDS = ('planned_primary_cases', 'actual_primary_cases',
'aggregated_valid_primary_cases', 'actual_checked_repeats')
def require(condition, message):
if not condition:
raise ValueError(message)
def load_helpers(path):
"""Instantiate the unchanged module from its exact pinned source bytes.
Using module_from_spec plus the source bytes avoids writing/importing a pyc
inside the sealed old model, even if the publisher was invoked without -B.
No old module global is redirected or modified after module initialization.
"""
path = Path(path)
require(path.is_absolute() and path.is_file() and not path.is_symlink(), 'Invalid frozen helper path')
data = path.read_bytes()
require(hashlib.sha256(data).hexdigest() == HELPER_SHA256, 'Frozen AI publication helper hash mismatch')
spec = importlib.util.spec_from_file_location('phase4ak_frozen_ai_publication_helpers', path)
require(spec is not None and spec.loader is not None, 'Unable to define frozen helper module')
module = importlib.util.module_from_spec(spec)
exec(compile(data, str(path), 'exec'), module.__dict__)
require(module._digest(path) == HELPER_SHA256, 'Helper source changed while loading')
return module
def _copy(helper, source, destination, size, checksum):
"""Separate local delegation point for interruption-only synthetic tests."""
helper._copy_verified(source, destination, size, checksum)
def _write_small_json(helper, path, value):
data = (json.dumps(value, indent=2, ensure_ascii=False, allow_nan=False) + '\n').encode('utf-8')
require(len(data) <= MAX_EVIDENCE_BYTES, 'Generated registry evidence exceeds 4 MiB: ' + str(path))
with Path(path).open('xb') as stream:
stream.write(data)
require(Path(path).stat().st_size == len(data), 'Generated registry evidence size changed')
def _status_evidence(helper, experiment, rows):
"""Check declaration consistency only, not the scientific gate itself."""
for relative in REQUIRED_EVIDENCE:
require(relative in rows, 'Required finalized evidence absent from seal: ' + relative)
require(rows[relative]['bytes'] <= MAX_EVIDENCE_BYTES, 'Required finalized evidence exceeds 4 MiB')
status, integrity = [helper._json_bytes((experiment / relative).read_bytes())
for relative in REQUIRED_EVIDENCE]
reference = None
if REFERENCE_EVIDENCE in rows:
require(rows[REFERENCE_EVIDENCE]['bytes'] <= MAX_EVIDENCE_BYTES, 'Frozen reference evidence exceeds 4 MiB')
reference = helper._json_bytes((experiment / REFERENCE_EVIDENCE).read_bytes())
require(isinstance(reference, dict) and type(reference.get('pass_all')) is bool and
isinstance(reference.get('trials'), list), 'Invalid frozen reference report')
if reference['pass_all']:
require(len(reference['trials']) == 5, 'Declared frozen-five PASS must contain five trial records')
require(isinstance(status, dict) and status.get('status') in FINAL_STATUSES,
'Unrecognized Phase 4AK final status')
for key in GATE_FIELDS:
require(type(status.get(key)) is bool, 'Missing/non-Boolean finalized result: ' + key)
for key in COUNT_FIELDS:
require(type(status.get(key)) is int and status[key] >= 0, 'Missing/invalid finalized count: ' + key)
require(status['planned_primary_cases'] == 120, 'Declared planned validation design changed')
# Preserve unexpected actual coverage in a declared failure, not censor it.
# A PASS below still requires exactly the predeclared 120 + 24 coverage.
for key in ('candidate_generated', 'learning_achieved', 'full_scientific_goal_achieved',
'dynamics_changed', 'old_heldout_dynamic_results_parsed', 'biological_delay_measured'):
require(status.get(key) is False, 'Unexpected finalized scope claim: ' + key)
require(status.get('unchanged_sealed_runtime') is True and
status.get('shared_APL_arithmetic_oracle_limitation') is True and
type(status.get('APL_nonKC_fast_edges_unreplaced')) is int and
status['APL_nonKC_fast_edges_unreplaced'] == 1212, 'Missing/changed finalized runtime limitations')
require(status.get('novel_scope') == 'Unused for AG/AJ calibration, not historically never simulated',
'Unrecognized novel-odor scope')
require(isinstance(integrity, dict) and bool(integrity) and all(
isinstance(row, dict) and type(row.get('pass')) is bool for row in integrity.values()),
'Missing/invalid frozen-integrity report')
require(status['old_frozen_integrity_pass'] == all(row['pass'] for row in integrity.values()),
'Final status contradicts its frozen-integrity report')
reference_pass = bool(reference is not None and reference['pass_all'])
require(status['frozen_five_reference_pass'] == reference_pass,
'Final status contradicts its frozen-reference report/presence')
if status['status'].startswith('PASS-'):
require(status['numerical_gate_pass'] and status['seed_validation_pass'] and
status['novel_to_aj_pass'] and status['novel_dynamics_executed'] and
not status['novel_unlock_policy_violation'] and status['old_frozen_integrity_pass'] and
reference_pass and status['actual_primary_cases'] == 120 and
status['aggregated_valid_primary_cases'] == 120 and status['actual_checked_repeats'] == 24,
'Declared PASS contradicts finalized gate/coverage flags')
return status, reference, integrity
def publish(root=ROOT, helper_path=None):
"""Publish the fixed AK registry exclusively; root override is for tests.
Only sealed small experiment evidence and the two model seal controls are
copied. Every bulk payload is nevertheless verified before and after copying.
An interrupted registry is preserved and cannot be overwritten or resumed.
"""
root = Path(root)
require(root.is_absolute() and root.is_dir() and not root.is_symlink(), 'Invalid project root')
root = root.resolve(strict=True)
model, experiment, registry = (root / part for part in
(MODEL_RELATIVE, EXPERIMENT_RELATIVE, REGISTRY_RELATIVE))
require(not registry.exists() and not registry.is_symlink(), 'Registry already exists; no overwrite/resume')
helper_path = root / HELPER_RELATIVE if helper_path is None else Path(helper_path)
helper = load_helpers(helper_path)
for path in (model, experiment, registry.parent):
current = root
for part in path.relative_to(root).parts:
current = current / part
require(not current.is_symlink(), 'Symlink in publication root path: ' + str(current))
verified = {'model': helper.verify_seal(model), 'experiment': helper.verify_seal(experiment)}
experiment_rows = {row['path']: row for row in verified['experiment']['files']}
status, reference, integrity = _status_evidence(helper, experiment, experiment_rows)
plans, omitted = [], []
for row in verified['experiment']['files'] + helper._control_rows(experiment, verified['experiment']):
if PurePosixPath(row['path']).suffix.lower() in EVIDENCE_SUFFIXES and row['bytes'] <= MAX_EVIDENCE_BYTES:
plans.append((experiment, row, 'evidence/' + row['path']))
else:
omitted.append(dict(path=row['path'], bytes=row['bytes'], sha256=row['sha256'],
reason='exceeds_4_MiB' if row['bytes'] > MAX_EVIDENCE_BYTES else 'bulk_or_non_evidence_extension'))
for row in helper._control_rows(model, verified['model']):
require(row['bytes'] <= MAX_EVIDENCE_BYTES, 'Model seal control exceeds small-evidence limit')
plans.append((model, row, 'model/' + row['path']))
destinations = {target for _, _, target in plans}
required_copies = ['manifest.json', 'checksums.sha256', *REQUIRED_EVIDENCE]
if reference is not None:
required_copies.append(REFERENCE_EVIDENCE)
for relative in required_copies:
require('evidence/' + relative in destinations, 'Required experiment evidence cannot be copied: ' + relative)
require(len(destinations) == len(plans), 'Duplicate planned evidence destination')
registry.parent.mkdir(parents=True, exist_ok=True)
registry.mkdir(exist_ok=False)
try:
records = []
for source_root, row, relative in plans:
source = helper._regular_file(source_root.resolve(), row['path'])
_copy(helper, source, registry / relative, row['bytes'], row['sha256'])
records.append(dict(source=source.relative_to(root).as_posix(), copy=relative,
bytes=row['bytes'], sha256=row['sha256']))
after = {'model': helper.verify_seal(model), 'experiment': helper.verify_seal(experiment)}
require(after == verified, 'A sealed tree changed during publication')
require(helper._digest(helper_path) == HELPER_SHA256, 'Frozen helper changed during publication')
proof = {name: {key: value for key, value in report.items() if key != 'files'}
for name, report in verified.items()}
_write_small_json(helper, registry / 'seal-verification.json', proof)
_write_small_json(helper, registry / 'evidence-index.json', records)
files = [dict(path=path.relative_to(registry).as_posix(), bytes=path.stat().st_size,
sha256=helper._digest(path)) for path in sorted(registry.rglob('*')) if path.is_file()]
receipt = dict(publication_complete=True, registry=registry.relative_to(root).as_posix(),
project_root=str(root), declared_audit_status=status['status'],
declared_gate_results={key: status[key] for key in GATE_FIELDS},
declared_validation_counts={key: status[key] for key in COUNT_FIELDS},
declared_novel_scope=status['novel_scope'],
frozen_reference_report=dict(present=reference is not None,
path='evidence/' + REFERENCE_EVIDENCE if reference is not None else None,
sha256=experiment_rows[REFERENCE_EVIDENCE]['sha256'] if reference is not None else None,
declared_pass_all=reference['pass_all'] if reference is not None else None,
reported_trial_count=len(reference['trials']) if reference is not None else None,
missing_is_not_a_success_or_fabricated_trial_failure=True),
frozen_integrity_report=dict(path='evidence/regression/old-integrity-after.json',
sha256=experiment_rows['regression/old-integrity-after.json']['sha256'],
declared_pass_by_root={name: row['pass'] for name, row in integrity.items()}),
frozen_helper_source=str(helper_path), frozen_helper_sha256=HELPER_SHA256,
publisher_sha256=helper._digest(Path(__file__)), helper_globals_redirected=False,
model_manifest_sha256=verified['model']['manifest_sha256'],
experiment_manifest_sha256=verified['experiment']['manifest_sha256'],
source_trees_verified_before_and_after_copy=True,
copied_evidence_files=len(records), copied_evidence_bytes=sum(row['bytes'] for row in records),
files=files, experiment_payload_not_copied=omitted,
model_payload_not_duplicated=True, model_payload_remains_at=MODEL_RELATIVE.as_posix(),
bulk_remains_at=EXPERIMENT_RELATIVE.as_posix(), complete_bulk_backup=False,
scientific_gate_executed_by_publisher=False, scientific_gate_certified_by_publication=False,
publication_success_is_not_scientific_pass=True, candidate_generated=False,
learning_achieved=False, full_scientific_goal_achieved=False,
old_heldout_dynamic_results_parsed=False, existing_files_modified=False,
receipt_self_hash='Not self-referential; returned by publish() and printed by main()',
limits=dict(max_selected_evidence_file_bytes=MAX_EVIDENCE_BYTES,
selected_suffixes=sorted(EVIDENCE_SUFFIXES)))
receipt_path = registry / 'publication-receipt.json'
_write_small_json(helper, receipt_path, receipt)
return dict(publication_complete=True, registry=str(registry), declared_audit_status=status['status'],
copied_evidence_files=len(records), receipt_sha256=helper._digest(receipt_path),
scientific_gate_executed_by_publisher=False, publication_success_is_not_scientific_pass=True)
except Exception as error:
failure = registry / 'publication-failure.json'
if not failure.exists():
_write_small_json(helper, failure, dict(publication_complete=False, type=type(error).__name__,
message=str(error), partial_outputs_preserved=True, existing_files_modified=False))
raise
def main():
print(json.dumps(publish(), ensure_ascii=False, allow_nan=False), flush=True)
if __name__ == '__main__':
main()
@@ -0,0 +1,239 @@
"""Pure in-memory SFTP plus temporary local destinations, never a real server."""
import io
import json
from pathlib import Path
import stat
import tempfile
import types
import unittest
import fetch_phase4ak as fetcher
def data(value):
return (json.dumps(value, sort_keys=True, allow_nan=False) + '\n').encode()
def row(name, content):
return dict(path=name, bytes=len(content), sha256=fetcher.sha(content))
def sealed(root, payload):
rows = [row(name, content) for name, content in sorted(payload.items())]
manifest = data(dict(root=root, files=rows))
checksums = '\n'.join([entry['sha256'] + ' ' + entry['path'] for entry in rows] +
[fetcher.sha(manifest) + ' manifest.json']).encode() + b'\n'
return dict(payload, **{'manifest.json': manifest, 'checksums.sha256': checksums}), dict(
pass_all=True, root=root, payload_file_count=len(rows), payload_bytes=sum(x['bytes'] for x in rows),
manifest_sha256=fetcher.sha(manifest), checksums_sha256=fetcher.sha(checksums))
class FakeSFTP:
def __init__(self, files):
self.files = files
self.opened = []
self.hook = None
self.symlinks = set()
def lstat(self, name):
if name in self.symlinks:
return types.SimpleNamespace(st_mode=stat.S_IFLNK | 0o777, st_size=1)
if name in self.files:
return types.SimpleNamespace(st_mode=stat.S_IFREG | 0o644, st_size=len(self.files[name]))
if any(path.startswith(name.rstrip('/') + '/') for path in self.files):
return types.SimpleNamespace(st_mode=stat.S_IFDIR | 0o755, st_size=0)
raise FileNotFoundError(name)
def open(self, name, mode):
if mode != 'rb':
raise AssertionError('Remote write attempted')
self.opened.append(name)
if self.hook:
self.hook(name)
return io.BytesIO(self.files[name])
def fixture(extra_experiment=None, extra_model=None):
status = dict(status='INCOMPLETE-VALIDATION-EXECUTION', numerical_gate_pass=False,
planned_primary_cases=120, candidate_generated=False, learning_achieved=False)
mp = {'module.py': b'# synthetic, not model execution\n', 'config.json': data({'synthetic': True}),
'never-download.npy': b'raw model bulk'}
mp.update(extra_model or {})
ep = {'audit/final-status.json': data(status), 'regression/old-integrity-after.json': data({'tree': {'pass': True}}),
'REPORT.md': b'Synthetic incomplete evidence.\n', 'tests.log': b'Synthetic test log.\n',
'gpu/example/state.npz': b'large trajectory placeholder not requested',
'gpu/example/tick-state-hashes.jsonl': b'non-whitelisted suffix'}
ep.update(extra_experiment or {})
model, model_proof = sealed(fetcher.MODEL_ROOT, mp)
experiment, exp_proof = sealed(fetcher.REMOTE_ROOT + '/' + fetcher.EXPERIMENT_RELATIVE, ep)
registry = {}
index = []
for name, content in experiment.items():
if Path(name).suffix.lower() in fetcher.EVIDENCE_SUFFIXES and len(content) <= fetcher.MAX_FILE_BYTES:
dest = 'evidence/' + name
registry[dest] = content
index.append(dict(source=fetcher.EXPERIMENT_RELATIVE + '/' + name,
copy=dest, bytes=len(content), sha256=fetcher.sha(content)))
for name in fetcher.CONTROLS:
dest = 'model/' + name; content = model[name]
registry[dest] = content
index.append(dict(source=fetcher.MODEL_RELATIVE + '/' + name,
copy=dest, bytes=len(content), sha256=fetcher.sha(content)))
registry['seal-verification.json'] = data(dict(model=model_proof, experiment=exp_proof))
registry['evidence-index.json'] = data(index)
receipt = dict(publication_complete=True, registry=fetcher.REGISTRY_RELATIVE, project_root=fetcher.REMOTE_ROOT,
source_trees_verified_before_and_after_copy=True, publication_success_is_not_scientific_pass=True,
complete_bulk_backup=False, scientific_gate_executed_by_publisher=False,
scientific_gate_certified_by_publication=False, candidate_generated=False, learning_achieved=False,
model_manifest_sha256=model_proof['manifest_sha256'], experiment_manifest_sha256=exp_proof['manifest_sha256'],
files=[row(name, content) for name, content in sorted(registry.items())],
limits=dict(max_selected_evidence_file_bytes=fetcher.MAX_FILE_BYTES, selected_suffixes=sorted(fetcher.EVIDENCE_SUFFIXES)),
declared_audit_status=status['status'], declared_gate_results={'numerical_gate_pass': False},
declared_validation_counts={'planned_primary_cases': 120})
registry['publication-receipt.json'] = data(receipt)
files = {fetcher.MODEL_ROOT + '/' + name: content for name, content in model.items()}
files.update({fetcher.REGISTRY_ROOT + '/' + name: content for name, content in registry.items()})
return FakeSFTP(files), fetcher.sha(registry['publication-receipt.json'])
class FetchTests(unittest.TestCase):
def setUp(self):
self.temp = tempfile.TemporaryDirectory(prefix='phase4ak-fetch-synthetic-')
self.addCleanup(self.temp.cleanup)
self.destination = Path(self.temp.name).resolve() / 'report'
self.sftp, self.receipt_sha = fixture()
def receipt(self):
return fetcher.json_bytes(self.sftp.files[fetcher.REGISTRY_ROOT + '/publication-receipt.json'])
def resign(self, receipt):
raw = data(receipt)
self.sftp.files[fetcher.REGISTRY_ROOT + '/publication-receipt.json'] = raw
self.receipt_sha = fetcher.sha(raw)
def get(self, **kwargs):
return fetcher.fetch(self.sftp, self.destination, self.receipt_sha, **kwargs)
def test_only_receipt_small_files_and_model_source_with_hashes(self):
result = self.get()
self.assertTrue(result['fetch_complete'])
self.assertTrue(result['both_manifest_self_checksums_verified'])
self.assertTrue(result['fetch_success_is_not_scientific_pass'])
self.assertFalse(result['complete_bulk_backup'])
self.assertFalse(result['all_remote_experiment_bulk_rehashed_locally'])
self.assertEqual(result['declared_audit_status'], 'INCOMPLETE-VALIDATION-EXECUTION')
self.assertTrue((self.destination / 'audit/final-status.json').is_file())
self.assertTrue((self.destination / 'model/module.py').is_file())
self.assertTrue((self.destination / 'registry/publication-receipt.json').is_file())
self.assertFalse((self.destination / 'gpu/example/state.npz').exists())
self.assertFalse((self.destination / 'model/never-download.npy').exists())
self.assertFalse(any('interpretation' in path or 'phase4aj' in path or path.endswith(('.npy', '.npz', '.jsonl'))
for path in self.sftp.opened))
for entry in result['files']:
self.assertEqual(fetcher.sha((self.destination / entry['local']).read_bytes()), entry['sha256'])
def test_out_of_band_sha_is_mandatory_and_checked_before_other_remote_reads(self):
for checksum in ('', 'g' * 64, '0' * 64):
self.sftp.opened.clear()
with self.subTest(checksum=checksum), self.assertRaises(ValueError):
fetcher.fetch(self.sftp, self.destination, checksum)
self.assertFalse(self.destination.exists())
self.assertTrue(all(path.endswith('/publication-receipt.json') for path in self.sftp.opened))
def test_no_overwrite_or_resume_even_empty_existing_directory(self):
self.destination.mkdir()
with self.assertRaisesRegex(ValueError, 'exists'):
self.get()
self.assertFalse(self.sftp.opened)
self.assertEqual(list(self.destination.iterdir()), [])
def test_malformed_or_non_small_receipt_paths_fail_without_download(self):
for name, size in (('../escape.json', 1), ('evidence/bulk.npy', 1), ('interpretation-metrics.json', 1),
('evidence/huge.json', fetcher.MAX_FILE_BYTES + 1), ('evidence/C:/escape.json', 1)):
with self.subTest(name=name):
self.sftp, self.receipt_sha = fixture()
receipt = self.receipt()
receipt['files'].append(dict(path=name, bytes=size, sha256='a' * 64))
self.resign(receipt)
with self.assertRaises(ValueError):
self.get()
self.assertFalse(self.destination.exists())
self.assertEqual(self.sftp.opened, [fetcher.REGISTRY_ROOT + '/publication-receipt.json'])
def test_manifest_self_checksum_is_not_trusted_from_receipt_alone(self):
name = 'evidence/checksums.sha256'; path = fetcher.REGISTRY_ROOT + '/' + name
lines = self.sftp.files[path].decode().splitlines()
lines[-1] = '0' * 64 + ' manifest.json'
changed = ('\n'.join(lines) + '\n').encode()
self.sftp.files[path] = changed
receipt = self.receipt()
next(entry for entry in receipt['files'] if entry['path'] == name).update(bytes=len(changed), sha256=fetcher.sha(changed))
self.resign(receipt)
with self.assertRaisesRegex(ValueError, 'self-SHA'):
self.get()
self.assertFalse(self.destination.exists())
def test_model_original_seal_must_equal_registry_anchor(self):
self.sftp.files[fetcher.MODEL_ROOT + '/manifest.json'] += b' '
with self.assertRaises(ValueError):
self.get()
self.assertFalse(self.destination.exists())
def test_corrupt_selected_payload_preserves_partial_and_blocks_resume(self):
path = fetcher.REGISTRY_ROOT + '/evidence/REPORT.md'
self.sftp.files[path] = b'x' * len(self.sftp.files[path])
with self.assertRaisesRegex(ValueError, 'SHA'):
self.get()
self.assertTrue((self.destination / 'fetch-failure.json').is_file())
self.assertFalse((self.destination / 'fetch-verification.json').exists())
with self.assertRaisesRegex(ValueError, 'exists'):
self.get()
def test_model_source_hash_is_verified_without_fetching_other_payloads(self):
path = fetcher.MODEL_ROOT + '/module.py'
self.sftp.files[path] = b'x' * len(self.sftp.files[path])
with self.assertRaisesRegex(ValueError, 'SHA'):
self.get()
self.assertTrue((self.destination / 'fetch-failure.json').is_file())
self.assertFalse(any(path.endswith('never-download.npy') for path in self.sftp.opened))
def test_local_path_collision_and_total_budget_fail_before_destination(self):
self.sftp, self.receipt_sha = fixture(extra_experiment={'model/module.py.json': data({'not_source': True}),
'model/config.json': data({'collision': True})})
with self.assertRaisesRegex(ValueError, 'collision'):
self.get()
self.assertFalse(self.destination.exists())
self.sftp, self.receipt_sha = fixture()
with self.assertRaisesRegex(ValueError, 'total download budget'):
self.get(max_total_bytes=1)
self.assertFalse(self.destination.exists())
def test_remote_symlink_rejected_without_open(self):
path = fetcher.REGISTRY_ROOT + '/publication-receipt.json'
self.sftp.symlinks.add(path)
with self.assertRaisesRegex(ValueError, 'symlink'):
self.get()
self.assertFalse(self.sftp.opened)
def test_anchor_changed_during_copy_fails_final_check(self):
receipt_path = fetcher.REGISTRY_ROOT + '/publication-receipt.json'
def change_on_source(name):
if name == fetcher.MODEL_ROOT + '/module.py':
self.sftp.files[receipt_path] += b' '
self.sftp.hook = change_on_source
with self.assertRaises(ValueError):
self.get()
self.assertTrue((self.destination / 'fetch-failure.json').is_file())
self.assertFalse((self.destination / 'fetch-verification.json').exists())
def test_no_import_network_and_cli_rejects_unknown_hosts(self):
source = Path(fetcher.__file__).read_text(encoding='utf-8')
self.assertIn('paramiko.RejectPolicy()', source)
self.assertIn('client.load_system_host_keys(str(args.known_hosts))', source)
self.assertIn("default=Path.home() / '.ssh/known_hosts'", source)
self.assertNotIn('AutoAddPolicy', source)
self.assertNotIn('interpretation-metrics.json', source)
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,260 @@
"""Temporary synthetic seals only; never publish/register any real evidence."""
import hashlib
import json
from pathlib import Path
import tempfile
import unittest
from unittest import mock
import publish_phase4ak as publication
HELPER = Path(__file__).resolve().parents[1] / 'pn-recruitment-audit-v1/publication.py'
if not HELPER.is_file():
HELPER = publication.ROOT / publication.HELPER_RELATIVE
def sha(path):
return hashlib.sha256(path.read_bytes()).hexdigest()
def write(path, value):
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps(value, indent=2), encoding='utf-8')
def seal(root):
rows = [dict(path=path.relative_to(root).as_posix(), bytes=path.stat().st_size, sha256=sha(path))
for path in sorted(root.rglob('*')) if path.is_file() and
path.name not in ('manifest.json', 'checksums.sha256') and '__pycache__' not in path.parts]
write(root / 'manifest.json', dict(root=str(root), files=rows))
lines = [row['sha256'] + ' ' + row['path'] for row in rows]
lines.append(sha(root / 'manifest.json') + ' manifest.json')
(root / 'checksums.sha256').write_text('\n'.join(lines) + '\n', encoding='utf-8')
class PublicationTests(unittest.TestCase):
def setUp(self):
temporary = tempfile.TemporaryDirectory(prefix='phase4ak-publication-synthetic-')
self.addCleanup(temporary.cleanup)
self.root = Path(temporary.name).resolve()
self.model = self.root / publication.MODEL_RELATIVE
self.experiment = self.root / publication.EXPERIMENT_RELATIVE
self.registry = self.root / publication.REGISTRY_RELATIVE
self.model.mkdir(parents=True)
self.experiment.mkdir(parents=True)
(self.model / 'module.py').write_text('# synthetic, not a model\n', encoding='utf-8')
self.status = dict(status='FAIL-SEED-VALIDATION-REPRESENTATION', numerical_gate_pass=True,
seed_validation_pass=False, novel_to_aj_pass=False, novel_dynamics_executed=False,
novel_unlock_policy_violation=False, old_frozen_integrity_pass=True, frozen_five_reference_pass=True,
planned_primary_cases=120, actual_primary_cases=60, aggregated_valid_primary_cases=60,
actual_checked_repeats=12, candidate_generated=False, learning_achieved=False,
full_scientific_goal_achieved=False, unchanged_sealed_runtime=True, dynamics_changed=False,
old_heldout_dynamic_results_parsed=False, biological_delay_measured=False,
shared_APL_arithmetic_oracle_limitation=True, APL_nonKC_fast_edges_unreplaced=1212,
novel_scope='Unused for AG/AJ calibration, not historically never simulated')
write(self.experiment / 'audit/final-status.json', self.status)
write(self.experiment / 'regression/frozen-five.json', dict(pass_all=True, trials=[{'synthetic': i} for i in range(5)]))
write(self.experiment / 'regression/old-integrity-after.json', {'synthetic-old-tree': {'pass': True}})
write(self.experiment / 'nested/case/summary.json', {'synthetic': True})
(self.experiment / 'REPORT.md').write_text('Synthetic failed hypothesis.\n', encoding='utf-8')
(self.experiment / 'tests.log').write_text('Synthetic log\n', encoding='utf-8')
(self.experiment / 'bulk.npy').write_bytes(b'synthetic bulk bytes, not an array')
seal(self.model)
seal(self.experiment)
def publish(self):
return publication.publish(self.root, HELPER)
def test_failed_hypothesis_is_published_without_scientific_pass(self):
before = {str(path): sha(path) for base in (self.model, self.experiment)
for path in base.rglob('*') if path.is_file()}
result = self.publish()
self.assertTrue(result['publication_complete'])
self.assertEqual(result['declared_audit_status'], self.status['status'])
receipt = json.loads((self.registry / 'publication-receipt.json').read_text(encoding='utf-8'))
self.assertFalse(receipt['declared_gate_results']['seed_validation_pass'])
self.assertFalse(receipt['scientific_gate_certified_by_publication'])
self.assertTrue(receipt['publication_success_is_not_scientific_pass'])
self.assertTrue((self.registry / 'evidence/nested/case/summary.json').is_file())
self.assertTrue((self.registry / 'model/checksums.sha256').is_file())
self.assertFalse((self.registry / 'model/module.py').exists())
self.assertFalse((self.registry / 'evidence/bulk.npy').exists())
for row in receipt['files']:
self.assertEqual(sha(self.registry / row['path']), row['sha256'])
self.assertEqual(before, {str(path): sha(path) for base in (self.model, self.experiment)
for path in base.rglob('*') if path.is_file()})
def test_incomplete_final_status_remains_incomplete(self):
self.status.update(status='INCOMPLETE-VALIDATION-EXECUTION', numerical_gate_pass=False)
write(self.experiment / 'audit/final-status.json', self.status)
seal(self.experiment)
self.assertEqual(self.publish()['declared_audit_status'], self.status['status'])
def test_pass_requires_consistent_declared_gate_flags_and_coverage(self):
self.status['status'] = 'PASS-FROZEN-D18-INDEPENDENT-VALIDATION'
write(self.experiment / 'audit/final-status.json', self.status)
seal(self.experiment)
with self.assertRaisesRegex(ValueError, 'Declared PASS contradicts'):
self.publish()
self.assertFalse(self.registry.exists())
self.status.update(seed_validation_pass=True, novel_to_aj_pass=True, novel_dynamics_executed=True,
actual_primary_cases=120, aggregated_valid_primary_cases=120, actual_checked_repeats=24)
write(self.experiment / 'audit/final-status.json', self.status)
seal(self.experiment)
self.assertEqual(self.publish()['declared_audit_status'], self.status['status'])
def test_explicit_frozen_failure_is_recorded_not_hidden(self):
self.status.update(status='FAIL-FROZEN-INTEGRITY-OR-REGRESSION', old_frozen_integrity_pass=False)
write(self.experiment / 'audit/final-status.json', self.status)
write(self.experiment / 'regression/old-integrity-after.json', {'synthetic-old-tree': {'pass': False}})
seal(self.experiment)
self.publish()
receipt = json.loads((self.registry / 'publication-receipt.json').read_text(encoding='utf-8'))
self.assertFalse(receipt['frozen_integrity_report']['declared_pass_by_root']['synthetic-old-tree'])
def test_existing_registry_never_overwritten_or_resumed(self):
self.registry.mkdir(parents=True)
sentinel = self.registry / 'keep.txt'
sentinel.write_bytes(b'keep these bytes')
with self.assertRaisesRegex(ValueError, 'Registry already exists'):
self.publish()
self.assertEqual(sentinel.read_bytes(), b'keep these bytes')
self.assertEqual(list(self.registry.iterdir()), [sentinel])
def test_missing_reference_preserved_as_absent_for_incomplete_not_fabricated_fail(self):
(self.experiment / 'regression/frozen-five.json').unlink()
self.status.update(status='INCOMPLETE-VALIDATION-EXECUTION', frozen_five_reference_pass=False)
write(self.experiment / 'audit/final-status.json', self.status)
seal(self.experiment)
result = self.publish()
self.assertEqual(result['declared_audit_status'], 'INCOMPLETE-VALIDATION-EXECUTION')
receipt = json.loads((self.registry / 'publication-receipt.json').read_text(encoding='utf-8'))
self.assertFalse(receipt['frozen_reference_report']['present'])
self.assertIsNone(receipt['frozen_reference_report']['declared_pass_all'])
self.assertIsNone(receipt['frozen_reference_report']['reported_trial_count'])
self.assertFalse((self.registry / 'evidence/regression/frozen-five.json').exists())
def test_missing_integrity_report_blocks_before_destination(self):
(self.experiment / 'regression/old-integrity-after.json').unlink()
seal(self.experiment)
with self.assertRaisesRegex(ValueError, 'Required finalized evidence absent'):
self.publish()
self.assertFalse(self.registry.exists())
def test_explicit_reference_failure_is_copied_without_regrading(self):
self.status.update(status='FAIL-FROZEN-INTEGRITY-OR-REGRESSION', frozen_five_reference_pass=False)
write(self.experiment / 'audit/final-status.json', self.status)
write(self.experiment / 'regression/frozen-five.json', dict(pass_all=False,
trials=[dict(synthetic=0, pass_all=False, message='retained exact diagnostic')]))
seal(self.experiment)
self.publish()
receipt = json.loads((self.registry / 'publication-receipt.json').read_text(encoding='utf-8'))
self.assertTrue(receipt['frozen_reference_report']['present'])
self.assertFalse(receipt['frozen_reference_report']['declared_pass_all'])
self.assertEqual(receipt['frozen_reference_report']['reported_trial_count'], 1)
self.assertEqual((self.registry / 'evidence/regression/frozen-five.json').read_bytes(),
(self.experiment / 'regression/frozen-five.json').read_bytes())
def test_novel_representation_failure_keeps_its_own_status(self):
self.status.update(status='FAIL-NOVEL-ODOR-REPRESENTATION', seed_validation_pass=True,
novel_dynamics_executed=True, actual_primary_cases=120, aggregated_valid_primary_cases=120,
actual_checked_repeats=24)
write(self.experiment / 'audit/final-status.json', self.status)
seal(self.experiment)
self.assertEqual(self.publish()['declared_audit_status'], self.status['status'])
def test_policy_failure_is_not_relabelled_or_hidden(self):
self.status.update(status='FAIL-NUMERICAL-OR-EXECUTION-POLICY', numerical_gate_pass=False,
novel_dynamics_executed=True, novel_unlock_policy_violation=True,
actual_primary_cases=121)
write(self.experiment / 'audit/final-status.json', self.status)
seal(self.experiment)
self.publish()
receipt = json.loads((self.registry / 'publication-receipt.json').read_text(encoding='utf-8'))
self.assertTrue(receipt['declared_gate_results']['novel_unlock_policy_violation'])
self.assertEqual(receipt['declared_validation_counts']['actual_primary_cases'], 121)
self.assertEqual(receipt['declared_audit_status'], self.status['status'])
def test_frozen_report_contradiction_and_string_boolean_fail_closed(self):
for changed in ({'frozen_five_reference_pass': False}, {'old_frozen_integrity_pass': False},
{'seed_validation_pass': 'false'}, {'learning_achieved': True}):
with self.subTest(changed=changed):
value = dict(self.status, **changed)
write(self.experiment / 'audit/final-status.json', value)
seal(self.experiment)
with self.assertRaises(ValueError):
self.publish()
self.assertFalse(self.registry.exists())
def test_bulk_corruption_blocks_even_though_bulk_is_not_copied(self):
path = self.experiment / 'bulk.npy'
path.write_bytes(b'x' * path.stat().st_size)
with self.assertRaisesRegex(ValueError, 'Payload SHA-256 mismatch'):
self.publish()
self.assertFalse(self.registry.exists())
def test_unlisted_payload_and_bad_manifest_self_hash_fail(self):
extra = self.experiment / 'unlisted.csv'
extra.write_text('unlisted\n')
with self.assertRaisesRegex(ValueError, 'unlisted/missing'):
self.publish()
extra.unlink()
controls = self.experiment / 'checksums.sha256'
lines = controls.read_text().splitlines()
lines[-1] = '0' * 64 + ' manifest.json'
controls.write_text('\n'.join(lines) + '\n')
with self.assertRaisesRegex(ValueError, 'manifest self-checksum'):
self.publish()
self.assertFalse(self.registry.exists())
def test_large_json_verified_but_not_copied(self):
path = self.experiment / 'large.json'
path.write_bytes(b' ' * (publication.MAX_EVIDENCE_BYTES + 1))
seal(self.experiment)
self.publish()
self.assertFalse((self.registry / 'evidence/large.json').exists())
receipt = json.loads((self.registry / 'publication-receipt.json').read_text(encoding='utf-8'))
self.assertEqual(next(r for r in receipt['experiment_payload_not_copied'] if r['path'] == 'large.json')['reason'],
'exceeds_4_MiB')
def test_interrupted_copy_retained_and_cannot_resume(self):
with mock.patch.object(publication, '_copy', side_effect=OSError('synthetic interrupted copy')):
with self.assertRaisesRegex(OSError, 'synthetic interrupted copy'):
self.publish()
self.assertTrue((self.registry / 'publication-failure.json').is_file())
self.assertFalse((self.registry / 'publication-receipt.json').exists())
with self.assertRaisesRegex(ValueError, 'Registry already exists'):
self.publish()
def test_after_copy_full_verification_detects_bulk_change(self):
original = publication._copy
changed = False
def copy_then_change(helper, source, destination, size, checksum):
nonlocal changed
original(helper, source, destination, size, checksum)
if not changed:
changed = True
(self.experiment / 'bulk.npy').write_bytes(b'changed after initial seal check')
with mock.patch.object(publication, '_copy', side_effect=copy_then_change):
with self.assertRaises(ValueError):
self.publish()
self.assertTrue((self.registry / 'publication-failure.json').is_file())
self.assertFalse((self.registry / 'publication-receipt.json').exists())
def test_helper_pin_checked_without_modifying_old_globals_or_cache(self):
helper = publication.load_helpers(HELPER)
self.assertEqual(helper.MODEL_RELATIVE, Path('models/male-cns-lif/pn-recruitment-audit-v1'))
self.assertEqual(helper.FINAL_STATUS, 'PASS-CONDITIONAL-PN-APL-SOURCE-AUDIT')
wrong = self.root / 'wrong-helper.py'
wrong.write_bytes(b'raise RuntimeError("must never execute")\n')
with self.assertRaisesRegex(ValueError, 'helper hash mismatch'):
publication.publish(self.root, wrong)
self.assertFalse(self.registry.exists())
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,269 @@
"""Synthetic temporary Git repositories only; no real publication or science."""
import contextlib
import io
import json
import os
from pathlib import Path
import shutil
import subprocess
import tempfile
import unittest
import verify_git_payload as verifier
def encoded(value):
return (json.dumps(value, sort_keys=True, indent=2) + '\n').encode('utf-8')
def sealed(relative, payload):
rows = [dict(path=path, bytes=len(data), sha256=verifier.sha(data)) for path, data in sorted(payload.items())]
manifest = encoded(dict(root=verifier.PROJECT + '/' + relative, files=rows))
checksums = ''.join(row['sha256'] + ' ' + row['path'] + '\n' for row in rows)
checksums += verifier.sha(manifest) + ' manifest.json\n'
controls = {'manifest.json': manifest, 'checksums.sha256': checksums.encode('utf-8')}
proof = dict(pass_all=True, root=verifier.PROJECT + '/' + relative,
payload_file_count=len(rows), payload_bytes=sum(row['bytes'] for row in rows),
manifest_sha256=verifier.sha(manifest), checksums_sha256=verifier.sha(controls['checksums.sha256']),
excluded_pycache_files=0, verification_scope='synthetic test only')
return rows, controls, proof
@unittest.skipUnless(shutil.which('git'), 'Git executable is required')
class GitPayloadTests(unittest.TestCase):
def setUp(self):
temporary = tempfile.TemporaryDirectory(prefix='phase4ak-git-payload-synthetic-')
self.addCleanup(temporary.cleanup)
self.repo = Path(temporary.name).resolve()
self.git('init', '--quiet')
self.git('config', 'user.name', 'Synthetic Test')
self.git('config', 'user.email', 'synthetic@example.invalid')
self.git('config', 'core.autocrlf', 'false')
self.git('config', 'commit.gpgsign', 'false')
self.model = {'module.py': b'# synthetic, not a brain\nx = 1\n', 'config.json': b'{"synthetic": true}\n'}
self.exp = {'audit/final-status.json': encoded(dict(status='FAIL-SEED-VALIDATION-REPRESENTATION')),
'case/summary.json': b'{"synthetic": true}\n', 'bulk.npy': b'not-a-real-array\x00'}
self.build()
def git(self, *args, data=None):
env = os.environ.copy()
for key in ('GIT_DIR', 'GIT_WORK_TREE', 'GIT_INDEX_FILE', 'GIT_COMMON_DIR',
'GIT_OBJECT_DIRECTORY', 'GIT_ALTERNATE_OBJECT_DIRECTORIES'):
env.pop(key, None)
result = subprocess.run(['git', '-C', str(self.repo), *args], input=data,
stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env, check=False)
self.assertEqual(result.returncode, 0, result.stderr.decode('utf-8', 'replace'))
return result.stdout
def write(self, path, data):
target = self.repo / path
target.parent.mkdir(parents=True, exist_ok=True)
target.write_bytes(data)
def build(self):
_, model_controls, model_proof = sealed(verifier.MODEL, self.model)
exp_rows, exp_controls, exp_proof = sealed(verifier.EXPERIMENT, self.exp)
for path, data in {**self.model, **model_controls}.items():
self.write(verifier.MODEL + '/' + path, data)
registry = {}
index = []
omitted = []
for path, data in {**self.exp, **exp_controls}.items():
row = dict(path=path, bytes=len(data), sha256=verifier.sha(data))
if Path(path).suffix in verifier.SUFFIXES and len(data) <= verifier.MAX_EVIDENCE:
registry['evidence/' + path] = data
index.append(dict(source=verifier.EXPERIMENT + '/' + path, copy='evidence/' + path,
bytes=len(data), sha256=verifier.sha(data)))
else:
omitted.append(dict(row, reason='bulk_or_non_evidence_extension'))
for path, data in model_controls.items():
registry['model/' + path] = data
index.append(dict(source=verifier.MODEL + '/' + path, copy='model/' + path,
bytes=len(data), sha256=verifier.sha(data)))
registry['evidence-index.json'] = encoded(index)
registry['seal-verification.json'] = encoded(dict(model=model_proof, experiment=exp_proof))
self.receipt = dict(publication_complete=True, registry=verifier.REGISTRY, project_root=verifier.PROJECT,
model_payload_remains_at=verifier.MODEL, bulk_remains_at=verifier.EXPERIMENT,
model_manifest_sha256=model_proof['manifest_sha256'],
experiment_manifest_sha256=exp_proof['manifest_sha256'],
copied_evidence_files=len(index), copied_evidence_bytes=sum(row['bytes'] for row in index),
files=[dict(path=path, bytes=len(data), sha256=verifier.sha(data)) for path, data in sorted(registry.items())],
experiment_payload_not_copied=omitted, declared_audit_status='FAIL-SEED-VALIDATION-REPRESENTATION')
for path, data in registry.items():
self.write(verifier.REGISTRY + '/' + path, data)
self.receipt_write()
self.git('add', '--', verifier.MODEL, verifier.REGISTRY)
def receipt_write(self):
data = encoded(self.receipt)
self.write(verifier.REGISTRY + '/publication-receipt.json', data)
self.anchor = verifier.sha(data)
def anchored_registry_change(self, relative, data):
self.write(verifier.REGISTRY + '/' + relative, data)
row = next(row for row in self.receipt['files'] if row['path'] == relative)
row.update(bytes=len(data), sha256=verifier.sha(data))
self.receipt_write()
self.git('add', '--', verifier.REGISTRY)
def verify(self, **kwargs):
return verifier.verify_git_payload(self.repo, self.anchor, **({'staged': True} if not kwargs else kwargs))
def test_staged_verifies_blob_bytes_and_leaves_index_unchanged(self):
before = (self.repo / '.git/index').read_bytes()
result = self.verify()
self.assertTrue(result['pass_all'])
self.assertEqual(result['model_payload_files'], 2)
self.assertEqual(result['declared_audit_status'], 'FAIL-SEED-VALIDATION-REPRESENTATION')
self.assertFalse(result['experiment_bulk_verified_by_this_tool'])
self.assertFalse(result['scientific_gate_executed'])
self.assertTrue(result['publication_integrity_is_not_scientific_pass'])
self.assertEqual(before, (self.repo / '.git/index').read_bytes())
self.assertFalse((self.repo / verifier.EXPERIMENT).exists())
def test_dirty_or_missing_worktree_payload_does_not_replace_good_index(self):
(self.repo / verifier.MODEL / 'module.py').write_bytes(b'working copy differs')
(self.repo / verifier.REGISTRY / 'publication-receipt.json').unlink()
self.assertTrue(self.verify()['pass_all'])
def test_correct_worktree_cannot_hide_corrupt_staged_blob(self):
relative = verifier.MODEL + '/module.py'
self.write(relative, self.model['module.py'].replace(b'x = 1', b'x = 2'))
self.git('add', '--', relative)
self.write(relative, self.model['module.py'])
with self.assertRaisesRegex(ValueError, 'Git blob SHA-256 mismatch'):
self.verify()
def test_commit_verifies_immutable_commit_not_current_index(self):
self.git('commit', '--quiet', '-m', 'synthetic only')
commit = self.git('rev-parse', 'HEAD').decode().strip()
self.write(verifier.MODEL + '/module.py', b'bad newer index')
self.git('add', '--', verifier.MODEL)
result = self.verify(commit='HEAD')
self.assertEqual(result['commit'], commit)
self.assertEqual(result['source'], 'commit')
self.assertTrue(result['pass_all'])
def test_external_receipt_anchor_is_mandatory_and_checked(self):
for anchor in (None, '', '0' * 64, self.anchor.upper()):
with self.subTest(anchor=anchor), self.assertRaises(ValueError):
verifier.verify_git_payload(self.repo, anchor, staged=True)
def test_extra_model_file_is_rejected_but_outside_scope_is_ignored(self):
self.write('unrelated/old-file.txt', b'outside audit scope')
self.git('add', '--', 'unrelated')
self.assertTrue(self.verify()['pass_all'])
self.write(verifier.MODEL + '/extra.py', b'extra')
self.git('add', '--', verifier.MODEL)
with self.assertRaisesRegex(ValueError, 'Model Git inventory'):
self.verify()
def test_extra_registry_file_is_rejected(self):
self.write(verifier.REGISTRY + '/unlisted.json', b'{}')
self.git('add', '--', verifier.REGISTRY)
with self.assertRaisesRegex(ValueError, 'Registry Git inventory'):
self.verify()
def test_missing_staged_model_file_is_rejected(self):
self.git('update-index', '--force-remove', verifier.MODEL + '/module.py')
with self.assertRaisesRegex(ValueError, 'Model Git inventory'):
self.verify()
def test_symlink_blob_mode_is_rejected_without_following_it(self):
path = verifier.MODEL + '/module.py'
oid = self.git('rev-parse', ':' + path).decode().strip()
self.git('update-index', '--cacheinfo', '120000,' + oid + ',' + path)
with self.assertRaisesRegex(ValueError, 'Symlink/gitlink/nonregular'):
self.verify()
def test_gitlink_is_rejected(self):
self.git('commit', '--quiet', '-m', 'synthetic only')
oid = self.git('rev-parse', 'HEAD').decode().strip()
self.git('update-index', '--add', '--cacheinfo', '160000,' + oid + ',' + verifier.MODEL + '/submodule')
with self.assertRaisesRegex(ValueError, 'Symlink/gitlink/nonregular'):
self.verify()
def test_unmerged_index_is_rejected(self):
path = verifier.MODEL + '/module.py'
oid = self.git('rev-parse', ':' + path).decode().strip()
self.git('update-index', '--force-remove', path)
self.git('update-index', '--index-info', data=('100644 ' + oid + ' 1\t' + path + '\n').encode())
with self.assertRaisesRegex(ValueError, 'Unmerged index'):
self.verify()
def test_anchored_index_source_escape_is_rejected(self):
data = json.loads((self.repo / verifier.REGISTRY / 'evidence-index.json').read_bytes())
data[0]['source'] = 'experiments/another-phase/audit/final-status.json'
self.anchored_registry_change('evidence-index.json', encoded(data))
with self.assertRaisesRegex(ValueError, 'Evidence index differs'):
self.verify()
def test_anchored_registry_copy_cannot_disagree_with_model(self):
data = (self.repo / verifier.REGISTRY / 'model/checksums.sha256').read_bytes()
self.anchored_registry_change('model/checksums.sha256', b'0' * 64 + data[64:])
with self.assertRaisesRegex(ValueError, 'Checksum inventory'):
self.verify()
def test_anchored_receipt_cannot_change_model_manifest_anchor(self):
self.receipt['model_manifest_sha256'] = '0' * 64
self.receipt_write(); self.git('add', '--', verifier.REGISTRY)
with self.assertRaisesRegex(ValueError, 'Receipt-bound manifest'):
self.verify()
def test_registry_payload_corruption_is_rejected(self):
path = verifier.REGISTRY + '/evidence/case/summary.json'
self.write(path, b'{"synthetic":false}\n')
self.git('add', '--', path)
with self.assertRaisesRegex(ValueError, 'Git blob (byte count|SHA-256) mismatch'):
self.verify()
def test_anchored_receipt_path_escape_and_duplicate_fail(self):
self.receipt['files'][0]['path'] = '../outside.json'
self.receipt_write(); self.git('add', '--', verifier.REGISTRY)
with self.assertRaisesRegex(ValueError, 'Noncanonical or escaping path'):
self.verify()
def test_duplicate_json_key_fails_even_with_external_anchor(self):
data = encoded(self.receipt).replace(b'{\n', b'{\n "publication_complete": true,\n', 1)
self.write(verifier.REGISTRY + '/publication-receipt.json', data)
self.anchor = verifier.sha(data)
self.git('add', '--', verifier.REGISTRY)
with self.assertRaisesRegex(ValueError, 'Duplicate JSON key'):
self.verify()
def test_incomplete_status_is_preserved_not_regraded(self):
self.receipt['declared_audit_status'] = 'INCOMPLETE-VALIDATION-EXECUTION'
self.receipt_write(); self.git('add', '--', verifier.REGISTRY)
result = self.verify()
self.assertEqual(result['declared_audit_status'], 'INCOMPLETE-VALIDATION-EXECUTION')
self.assertTrue(result['publication_integrity_is_not_scientific_pass'])
def test_anchored_bulk_omission_inventory_mismatch_fails(self):
self.receipt['experiment_payload_not_copied'] = []
self.receipt_write(); self.git('add', '--', verifier.REGISTRY)
with self.assertRaisesRegex(ValueError, 'omitted-bulk inventory mismatch'):
self.verify()
def test_anchored_seal_proof_contradiction_fails(self):
proof = json.loads((self.repo / verifier.REGISTRY / 'seal-verification.json').read_bytes())
proof['model']['payload_file_count'] += 1
self.anchored_registry_change('seal-verification.json', encoded(proof))
with self.assertRaisesRegex(ValueError, 'Seal-verification evidence contradicts'):
self.verify()
def test_both_or_neither_git_sources_fail(self):
for kwargs in ({}, {'staged': True, 'commit': 'HEAD'}):
with self.subTest(kwargs=kwargs), self.assertRaisesRegex(ValueError, 'Select exactly one'):
verifier.verify_git_payload(self.repo, self.anchor, **kwargs)
def test_cli_success_and_failure_are_json_with_exit_status(self):
for anchor, expected in ((self.anchor, 0), ('0' * 64, 1)):
with self.subTest(expected=expected), contextlib.redirect_stdout(io.StringIO()) as output:
code = verifier.main(['--repo', str(self.repo), '--staged', '--receipt-sha256', anchor])
result = json.loads(output.getvalue())
self.assertEqual(code, expected)
self.assertEqual(result['pass_all'], expected == 0)
if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,324 @@
"""Verify fixed Phase 4AK Git blobs, not working-tree files or scientific gates.
The publication receipt SHA-256 must come from an external trusted record.
Only the index or one resolved commit is read. No publish, checkout, index
mutation, network fetch, or scientific execution is performed.
"""
from __future__ import annotations
import argparse
import hashlib
import json
import os
from pathlib import Path, PurePosixPath
import re
import subprocess
import sys
PROJECT = '/data/digital-drosophila'
MODEL = 'models/male-cns-lif/apl-timing-validation-v1'
EXPERIMENT = 'experiments/phase4ak-apl-timing-validation'
REGISTRY = 'registry/phase4ak-apl-timing-validation'
CONTROLS = frozenset(('manifest.json', 'checksums.sha256'))
SHA256 = re.compile(r'[0-9a-f]{64}\Z')
OID = re.compile(r'(?:[0-9a-f]{40}|[0-9a-f]{64})\Z')
MAX_EVIDENCE = 4 * 1024 ** 2
MAX_BLOB = 64 * 1024 ** 2
SUFFIXES = frozenset(('.json', '.csv', '.md', '.log', '.sha256'))
def require(condition, message):
if not condition:
raise ValueError(message)
def sha(data):
return hashlib.sha256(data).hexdigest()
def relative(value):
require(isinstance(value, str) and bool(value) and
not any(char in value for char in '\\\x00\n\r\t'), 'Invalid relative path')
path = PurePosixPath(value)
require(not path.is_absolute() and str(path) == value and
all(part not in ('', '.', '..') and ':' not in part for part in path.parts),
'Noncanonical or escaping path: ' + value)
return value
def unique_object(pairs):
value = {}
for key, item in pairs:
require(key not in value, 'Duplicate JSON key: ' + key)
value[key] = item
return value
def json_bytes(data):
def nonfinite(value):
raise ValueError('Nonfinite JSON value: ' + value)
return json.loads(data.decode('utf-8'), object_pairs_hook=unique_object,
parse_constant=nonfinite)
def rows_by_path(rows, label):
require(isinstance(rows, list) and bool(rows), 'Missing/empty ' + label)
result = {}
for row in rows:
require(isinstance(row, dict) and set(row) == {'path', 'bytes', 'sha256'},
'Invalid ' + label + ' row schema')
path = relative(row['path'])
require(path not in result and '__pycache__' not in PurePosixPath(path).parts,
'Duplicate/cache ' + label + ' path: ' + path)
require(type(row['bytes']) is int and row['bytes'] >= 0 and
isinstance(row['sha256'], str) and SHA256.fullmatch(row['sha256']),
'Invalid bytes/SHA-256 in ' + label + ': ' + path)
result[path] = row
return result
class GitBlobs:
"""Snapshot inventory plus immutable object reads; no work-tree fallback."""
def __init__(self, repo, *, staged, commit):
require(type(staged) is bool and (staged != (commit is not None)),
'Select exactly one of staged or commit')
self.repo = Path(repo).resolve(strict=True)
require(self.repo.is_dir(), 'Repository must be a directory')
self.env = os.environ.copy()
# The explicitly supplied repo/index must not be redirected by caller env.
for key in ('GIT_DIR', 'GIT_WORK_TREE', 'GIT_INDEX_FILE', 'GIT_COMMON_DIR',
'GIT_OBJECT_DIRECTORY', 'GIT_ALTERNATE_OBJECT_DIRECTORIES'):
self.env.pop(key, None)
self.env.update(GIT_OPTIONAL_LOCKS='0', GIT_NO_REPLACE_OBJECTS='1', GIT_NO_LAZY_FETCH='1')
self.base = ['git', '--no-optional-locks', '-c', 'core.fsmonitor=false',
'-c', 'gc.auto=0', '-C', str(self.repo)]
top = self.command('rev-parse', '--show-toplevel').decode('utf-8').strip()
require(Path(top).resolve(strict=True) == self.repo, 'Supply the Git repository top-level directory')
if staged:
self.commit = None
else:
require(isinstance(commit, str) and bool(commit) and not commit.startswith('-') and
not any(c in commit for c in '\x00\n\r'), 'Invalid commit selector')
self.commit = self.command('rev-parse', '--verify', '--end-of-options',
commit + '^{commit}').decode('ascii').strip()
require(OID.fullmatch(self.commit), 'Commit did not resolve to a full object ID')
self.staged = staged
self.inventory_bytes = self.inventory()
self.entries = self.parse_inventory(self.inventory_bytes)
self.verified = {}
def command(self, *args):
result = subprocess.run(self.base + list(args), env=self.env, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, check=False)
require(result.returncode == 0, 'Git read failed: ' + result.stderr.decode('utf-8', 'replace').strip())
return result.stdout
def inventory(self):
if self.staged:
return self.command('ls-files', '--stage', '--full-name', '-z', '--', MODEL, REGISTRY)
return self.command('ls-tree', '-r', '-z', '--full-tree', self.commit, '--', MODEL, REGISTRY)
def parse_inventory(self, data):
result = {}
require(data.endswith(b'\x00'), 'Empty/malformed scoped Git inventory')
for entry in data[:-1].split(b'\x00'):
metadata, raw_path = entry.split(b'\t', 1)
fields = metadata.decode('ascii').split(' ')
require(len(fields) == 3, 'Malformed Git entry')
if self.staged:
mode, oid, stage = fields
require(stage == '0', 'Unmerged index entry is forbidden')
else:
mode, kind, oid = fields
require(kind == 'blob', 'Non-blob Git entry is forbidden')
path = relative(raw_path.decode('utf-8'))
require(path.startswith(MODEL + '/') or path.startswith(REGISTRY + '/'),
'Git entry escapes the fixed AK scopes: ' + path)
require(mode in ('100644', '100755') and OID.fullmatch(oid),
'Symlink/gitlink/nonregular Git entry is forbidden: ' + path)
require(path not in result, 'Duplicate Git path: ' + path)
result[path] = dict(mode=mode, oid=oid)
return result
def read(self, path):
relative(path)
require(path in self.entries, 'Missing Git blob: ' + path)
oid = self.entries[path]['oid']
size = int(self.command('cat-file', '-s', oid).decode('ascii').strip())
require(0 <= size <= MAX_BLOB, 'Git blob exceeds publication verifier limit: ' + path)
# cat-file blob addresses the object, so attributes/filters/autocrlf do
# not turn a corrupt staged blob into a good working-tree substitute.
data = self.command('cat-file', 'blob', oid)
require(len(data) == size, 'Git object size changed: ' + path)
self.verified[path] = dict(path=path, bytes=len(data), sha256=sha(data),
git_oid=oid, git_mode=self.entries[path]['mode'])
return data
def match(self, path, row):
data = self.read(path)
require(len(data) == row['bytes'], 'Git blob byte count mismatch: ' + path)
require(sha(data) == row['sha256'], 'Git blob SHA-256 mismatch: ' + path)
return data
def finish(self):
require(self.inventory() == self.inventory_bytes, 'Scoped Git inventory changed during verification')
def seal_controls(manifest_data, checksum_data, expected_relative, expected_sha):
"""Validate control syntax/inventory; does not claim absent bulk was read."""
require(sha(manifest_data) == expected_sha, 'Receipt-bound manifest SHA-256 mismatch')
manifest = json_bytes(manifest_data)
require(isinstance(manifest, dict) and set(manifest) == {'root', 'files'} and
manifest['root'] == PROJECT + '/' + expected_relative, 'Wrong seal manifest schema/root')
rows = rows_by_path(manifest['files'], 'manifest')
require(not (set(rows) & CONTROLS), 'Seal controls listed as payload')
checksums = {}
for line in checksum_data.decode('utf-8').splitlines():
require(len(line) >= 67 and line[64:66] == ' ' and SHA256.fullmatch(line[:64]),
'Malformed checksum line')
path = relative(line[66:])
require(path not in checksums, 'Duplicate checksum path: ' + path)
checksums[path] = line[:64]
require(checksums == {**{name: row['sha256'] for name, row in rows.items()},
'manifest.json': sha(manifest_data)},
'Checksum inventory or manifest self-checksum mismatch')
return rows
def control_rows(manifest_data, checksum_data):
return {name: dict(path=name, bytes=len(data), sha256=sha(data)) for name, data in
(('manifest.json', manifest_data), ('checksums.sha256', checksum_data))}
def verify_git_payload(repo, receipt_sha256, *, staged=False, commit=None):
require(isinstance(receipt_sha256, str) and SHA256.fullmatch(receipt_sha256),
'External publication receipt SHA-256 is required')
blobs = GitBlobs(repo, staged=staged, commit=commit)
receipt_data = blobs.read(REGISTRY + '/publication-receipt.json')
require(len(receipt_data) <= MAX_EVIDENCE and sha(receipt_data) == receipt_sha256,
'External publication receipt SHA-256 mismatch')
receipt = json_bytes(receipt_data)
require(isinstance(receipt, dict) and receipt.get('publication_complete') is True and
receipt.get('registry') == REGISTRY and receipt.get('project_root') == PROJECT and
receipt.get('model_payload_remains_at') == MODEL and receipt.get('bulk_remains_at') == EXPERIMENT,
'Wrong/incomplete AK publication receipt or fixed scope')
for key in ('model_manifest_sha256', 'experiment_manifest_sha256'):
require(isinstance(receipt.get(key), str) and SHA256.fullmatch(receipt[key]),
'Invalid receipt manifest anchor: ' + key)
registry_rows = rows_by_path(receipt.get('files'), 'receipt files')
require('publication-receipt.json' not in registry_rows, 'Receipt must not list itself')
require({'evidence-index.json', 'seal-verification.json', 'model/manifest.json',
'model/checksums.sha256', 'evidence/manifest.json', 'evidence/checksums.sha256'} <= set(registry_rows),
'Required registry evidence/control missing')
observed_registry = {path[len(REGISTRY) + 1:] for path in blobs.entries if path.startswith(REGISTRY + '/')}
require(observed_registry == set(registry_rows) | {'publication-receipt.json'},
'Registry Git inventory has unlisted/missing files: ' + repr(sorted(
observed_registry ^ (set(registry_rows) | {'publication-receipt.json'}))))
controls_data = {}
for path, row in registry_rows.items():
require(row['bytes'] <= MAX_EVIDENCE, 'Registry receipt file exceeds 4 MiB')
data = blobs.match(REGISTRY + '/' + path, row)
if path in ('evidence-index.json', 'seal-verification.json', 'model/manifest.json',
'model/checksums.sha256', 'evidence/manifest.json', 'evidence/checksums.sha256'):
controls_data[path] = data
model_manifest, model_checksums = (controls_data['model/' + name] for name in ('manifest.json', 'checksums.sha256'))
model_rows = seal_controls(model_manifest, model_checksums, MODEL, receipt['model_manifest_sha256'])
model_controls = control_rows(model_manifest, model_checksums)
observed_model = {path[len(MODEL) + 1:] for path in blobs.entries if path.startswith(MODEL + '/')}
require(observed_model == set(model_rows) | CONTROLS,
'Model Git inventory has unlisted/missing files: ' + repr(sorted(observed_model ^ (set(model_rows) | CONTROLS))))
for path, row in {**model_rows, **model_controls}.items():
blobs.match(MODEL + '/' + path, row)
exp_manifest, exp_checksums = (controls_data['evidence/' + name] for name in ('manifest.json', 'checksums.sha256'))
exp_rows = seal_controls(exp_manifest, exp_checksums, EXPERIMENT, receipt['experiment_manifest_sha256'])
exp_controls = control_rows(exp_manifest, exp_checksums)
expected_index = {}
omitted = []
for path, row in {**exp_rows, **exp_controls}.items():
if PurePosixPath(path).suffix.lower() in SUFFIXES and row['bytes'] <= MAX_EVIDENCE:
expected_index['evidence/' + path] = dict(source=EXPERIMENT + '/' + path,
copy='evidence/' + path, bytes=row['bytes'], sha256=row['sha256'])
else:
omitted.append(dict(row, reason='exceeds_4_MiB' if row['bytes'] > MAX_EVIDENCE
else 'bulk_or_non_evidence_extension'))
for path, row in model_controls.items():
expected_index['model/' + path] = dict(source=MODEL + '/' + path,
copy='model/' + path, bytes=row['bytes'], sha256=row['sha256'])
index = json_bytes(controls_data['evidence-index.json'])
require(isinstance(index, list), 'Evidence index must be a list')
actual_index = {}
for row in index:
require(isinstance(row, dict) and set(row) == {'source', 'copy', 'bytes', 'sha256'},
'Invalid evidence-index row schema')
path = relative(row['copy']); relative(row['source'])
require(path not in actual_index and type(row['bytes']) is int and row['bytes'] >= 0 and
isinstance(row['sha256'], str) and SHA256.fullmatch(row['sha256']),
'Invalid/duplicate evidence-index row')
actual_index[path] = row
require(actual_index == expected_index, 'Evidence index differs from receipt-bound seals/selection policy')
require(set(registry_rows) == set(expected_index) | {'evidence-index.json', 'seal-verification.json'},
'Receipt files disagree with copied evidence index')
for path, row in expected_index.items():
require(registry_rows[path] == dict(path=path, bytes=row['bytes'], sha256=row['sha256']),
'Evidence-index SHA/bytes disagree with receipt files: ' + path)
require(type(receipt.get('copied_evidence_files')) is int and
receipt['copied_evidence_files'] == len(expected_index) and
type(receipt.get('copied_evidence_bytes')) is int and
receipt['copied_evidence_bytes'] == sum(row['bytes'] for row in expected_index.values()),
'Receipt copied-evidence totals mismatch')
omitted_receipt = receipt.get('experiment_payload_not_copied')
require(isinstance(omitted_receipt, list) and all(isinstance(row, dict) for row in omitted_receipt) and
sorted(omitted_receipt, key=lambda row: row.get('path', '')) == sorted(omitted, key=lambda row: row['path']),
'Receipt omitted-bulk inventory mismatch')
proof = json_bytes(controls_data['seal-verification.json'])
require(isinstance(proof, dict) and set(proof) == {'model', 'experiment'}, 'Invalid seal-verification evidence')
for name, prefix, payload, controls in (('model', MODEL, model_rows, model_controls),
('experiment', EXPERIMENT, exp_rows, exp_controls)):
record = proof[name]
require(isinstance(record, dict) and record.get('pass_all') is True and
record.get('root') == PROJECT + '/' + prefix and
record.get('payload_file_count') == len(payload) and
record.get('payload_bytes') == sum(row['bytes'] for row in payload.values()) and
record.get('manifest_sha256') == controls['manifest.json']['sha256'] and
record.get('checksums_sha256') == controls['checksums.sha256']['sha256'],
'Seal-verification evidence contradicts receipt-bound ' + name + ' controls')
blobs.finish()
return dict(pass_all=True, verification='Phase 4AK actual Git blob publication integrity',
source='staged-index' if staged else 'commit', commit=blobs.commit,
fixed_scopes=[MODEL, REGISTRY], receipt_sha256=receipt_sha256,
model_manifest_sha256=receipt['model_manifest_sha256'],
experiment_manifest_sha256=receipt['experiment_manifest_sha256'],
declared_audit_status=receipt.get('declared_audit_status'),
model_payload_files=len(model_rows), registry_receipt_files=len(registry_rows),
verified_blob_count=len(blobs.verified), verified_bytes=sum(row['bytes'] for row in blobs.verified.values()),
scoped_inventory_sha256=sha(blobs.inventory_bytes),
verified_blobs=[blobs.verified[path] for path in sorted(blobs.verified)],
working_tree_payload_used=False, git_index_modified=False,
experiment_bulk_verified_by_this_tool=False, scientific_gate_executed=False,
publication_integrity_is_not_scientific_pass=True)
def main(argv=None):
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--repo', required=True, help='Git repository top-level directory')
parser.add_argument('--receipt-sha256', required=True, help='Trusted external publication-receipt.json SHA-256')
choice = parser.add_mutually_exclusive_group(required=True)
choice.add_argument('--staged', action='store_true', help='Verify the actual stage-0 index blobs')
choice.add_argument('--commit', help='Resolve and verify this commit without checking it out')
args = parser.parse_args(argv)
try:
result = verify_git_payload(args.repo, args.receipt_sha256, staged=args.staged, commit=args.commit)
except (ValueError, OSError, UnicodeError) as error:
result = dict(pass_all=False, verification='Phase 4AK actual Git blob publication integrity',
error_type=type(error).__name__, error=str(error), scientific_gate_executed=False,
publication_integrity_is_not_scientific_pass=True)
print(json.dumps(result, ensure_ascii=False, allow_nan=False))
return 1
print(json.dumps(result, ensure_ascii=False, allow_nan=False))
return 0
if __name__ == '__main__':
sys.exit(main())