86 lines
3.9 KiB
Python
86 lines
3.9 KiB
Python
"""Apply exactly reviewed paired scanner and Apps source after native verification.
|
|
|
|
No Git operations or native actions. Requires founder acknowledgement of packet.
|
|
All six original hashes are checked before writing; differing owner work is refused.
|
|
"""
|
|
from pathlib import Path
|
|
import argparse
|
|
import hashlib
|
|
import importlib.util
|
|
import json
|
|
import os
|
|
import re
|
|
import tempfile
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
|
|
|
|
def sha(raw): return hashlib.sha256(raw).hexdigest()
|
|
|
|
|
|
def patched(original, diff):
|
|
before = original.decode().splitlines(keepends=True)
|
|
result = []; cursor = 0; lines = diff.splitlines(keepends=True); i = 2
|
|
while i < len(lines):
|
|
match = re.fullmatch(r'@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@[^\n]*\n?', lines[i])
|
|
if not match: raise ValueError('malformed-hunk')
|
|
start = int(match[1]) - 1
|
|
if start < cursor: raise ValueError('overlapping-hunk')
|
|
result.extend(before[cursor:start]); cursor = start; i += 1
|
|
while i < len(lines) and not lines[i].startswith('@@ '):
|
|
line = lines[i]; tag, content = line[0], line[1:]
|
|
if tag in (' ', '-'):
|
|
if cursor >= len(before) or before[cursor] != content: raise ValueError('hunk-preimage-drift')
|
|
cursor += 1
|
|
if tag in (' ', '+'): result.append(content)
|
|
elif tag != '-': raise ValueError('unsupported-patch-line')
|
|
i += 1
|
|
result.extend(before[cursor:])
|
|
return ''.join(result).encode()
|
|
|
|
|
|
def candidates():
|
|
changes = json.loads((HERE / 'scanner-source-changes.json').read_bytes())
|
|
changes += json.loads((HERE / 'apps-source-changes.json').read_bytes())
|
|
result = []
|
|
for change in changes:
|
|
target = Path(change['target']); raw = target.read_bytes()
|
|
if sha(raw) != change['original_sha256']: raise RuntimeError('owner-source-drift:' + str(target))
|
|
candidate = ((HERE / change['candidate_file']).read_bytes() if 'candidate_file' in change else patched(raw, change['patch']))
|
|
if sha(candidate) != change['candidate_sha256']: raise RuntimeError('candidate-hash-mismatch')
|
|
result.append((target, raw, candidate))
|
|
return result
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('--apply', action='store_true')
|
|
parser.add_argument('--approved-digest')
|
|
args = parser.parse_args()
|
|
spec = importlib.util.spec_from_file_location('rollout', HERE / 'rollout.py')
|
|
module = importlib.util.module_from_spec(spec); spec.loader.exec_module(module)
|
|
digest = module.verify_packet()
|
|
prepared = candidates()
|
|
if args.apply:
|
|
if args.approved_digest != digest: raise RuntimeError('exact-founder-acknowledgement-required')
|
|
receipt = json.loads(Path('/tmp/forge-scanner-rollout-receipt.json').read_bytes())
|
|
if receipt.get('packet_sha256') != digest or receipt['events'][-1]['event'] != 'activation-verified':
|
|
raise RuntimeError('native-activation-not-verified')
|
|
for target, original, candidate in prepared:
|
|
if target.read_bytes() != original: raise RuntimeError('concurrent-owner-source-drift')
|
|
mode = target.stat().st_mode & 0o777
|
|
fd, name = tempfile.mkstemp(prefix='.scanner-reviewed-', dir=target.parent)
|
|
try:
|
|
with os.fdopen(fd, 'wb') as stream: stream.write(candidate); stream.flush(); os.fsync(stream.fileno())
|
|
os.chmod(name, mode)
|
|
os.replace(name, target)
|
|
finally:
|
|
if os.path.exists(name): os.unlink(name)
|
|
print(json.dumps({'result': 'applied' if args.apply else 'preimages-and-candidates-verified', 'files': len(prepared), 'packet_sha256': digest}))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
try: main()
|
|
except Exception as error:
|
|
print(json.dumps({'result': 'refused-or-unverified', 'reason': str(error) if isinstance(error, RuntimeError) else type(error).__name__}))
|
|
raise SystemExit(1)
|