the-custodian/docs/changes/CUST-WP-0080/probe_push_deadline.py

68 lines
3.1 KiB
Python
Raw Normal View History

#!/usr/bin/env python3
"""Real disposable receive hooks outlasting both historical client deadlines."""
from concurrent.futures import ThreadPoolExecutor
import hashlib
import importlib.util
import json
import os
from pathlib import Path
import subprocess
import tempfile
import time
SOURCES = {
'state-hub': Path('/home/worsch/state-hub/scripts/repo_sync.py'),
'repo-manager': Path('/home/worsch/repo-manager/src/repo_manager/gitops.py'),
}
def probe(item):
name, source = item
spec = importlib.util.spec_from_file_location(name, source)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
with tempfile.TemporaryDirectory(prefix='push-deadline-') as temporary:
base = Path(temporary)
remote, local = base / 'remote.git', base / 'client'
def git(*args):
p = subprocess.run(['git', *map(str, args)], capture_output=True, timeout=15)
if p.returncode:
raise ValueError('probe-git-failed')
return p.stdout.decode().strip()
git('init', '--bare', '-q', remote)
git('clone', '-q', remote, local)
git('-C', local, 'config', 'user.name', 'Deadline probe')
git('-C', local, 'config', 'user.email', 'probe@example.test')
git('-C', local, 'config', 'core.hooksPath', base / 'no-client-hooks')
git('-C', local, 'commit', '--allow-empty', '-qm', 'isolated deadline fixture')
hook = remote / 'hooks/pre-receive'
hook.write_text('#!/bin/sh\nsleep 65\nexit 0\n')
hook.chmod(0o755)
start = time.monotonic()
ok, _ = module.push_ff(local)
elapsed = time.monotonic() - start
head = git('-C', local, 'rev-parse', 'HEAD')
remote_head = git('--git-dir', remote, 'rev-parse', 'HEAD')
accepted = ok and head == remote_head and elapsed >= 65
hook.write_text('#!/bin/sh\nexit 1\n')
git('-C', local, 'commit', '--allow-empty', '-qm', 'isolated rejection fixture')
rejected, _ = module.push_ff(local)
refusal = not rejected and git('--git-dir', remote, 'rev-parse', 'HEAD') == head
return {'repo': name, 'source_sha256': hashlib.sha256(source.read_bytes()).hexdigest(),
'configured_seconds': module.PUSH_TIMEOUT_SECONDS, 'elapsed_seconds': round(elapsed, 2),
'receive_hook_65_seconds_accepted': accepted, 'refusal_preserved_ref': refusal}
if __name__ == '__main__':
os.environ.update(GIT_CONFIG_GLOBAL='/dev/null', GIT_CONFIG_NOSYSTEM='1', GIT_TERMINAL_PROMPT='0')
with ThreadPoolExecutor(max_workers=2) as pool:
results = list(pool.map(probe, SOURCES.items()))
passed = all(x['receive_hook_65_seconds_accepted'] and x['refusal_preserved_ref'] for x in results)
receipt = {'result': 'verified' if passed else 'failed', 'checks': results,
'scope': 'Disposable local Git repositories; synthetic delayed/refusing receive hooks, no production delay injected.'}
Path('docs/evidence/2026-10-13-netkingdom-security/push-deadline.json').write_text(json.dumps(receipt, indent=2) + '\n')
print(json.dumps(receipt))
assert passed