railiance-clock/tools/wheel_smoke.py
tegwick c29bf39b5d Verify reproducible release artifacts and map acceptance evidence
Assistant: codex
Assistant-Model: gpt-6-astra
Assistant-Session: 01a0e6f0-a6f6-7b93-9124-55ef584930e2
2026-09-28 10:22:52 +02:00

91 lines
4.7 KiB
Python

"""Run with an isolated interpreter containing only the installed wheel and deps."""
import importlib.metadata
import json
import os
from pathlib import Path
import subprocess
import sys
import tempfile
import threading
import time
from cryptography.hazmat.primitives import serialization
from cryptography.hazmat.primitives.asymmetric import ec
import railiance_clock
from railiance_clock.admission import admit
from railiance_clock.authority import Authority, Server
from railiance_clock.client import Clock, FileTrust
from railiance_clock.core import ClockError
def main():
installed = Path(railiance_clock.__file__).resolve()
assert installed.is_relative_to(Path(sys.prefix).resolve()), installed
schemas = installed.parent / 'schemas'
for name in ('time-request', 'time-sample', 'protected-header'):
assert json.loads((schemas / (name + '-v0.1.schema.json')).read_text())['type'] == 'object'
cli = Path(sys.executable).parent / 'railiance-clock'
help_result = subprocess.run([str(cli), '--help'], capture_output=True, text=True, check=True)
assert all(command in help_result.stdout for command in ('read', 'serve', 'health-export'))
with tempfile.TemporaryDirectory() as directory:
root = Path(directory)
key = ec.generate_private_key(ec.SECP256R1())
private = root / 'key.pem'
private.write_bytes(key.private_bytes(serialization.Encoding.PEM,
serialization.PrivateFormat.PKCS8, serialization.NoEncryption()))
private.chmod(0o600)
health = root / 'health.json'
health.write_text(json.dumps({'quality': 'bounded',
'boot_id': Path('/proc/sys/kernel/random/boot_id').read_text().strip(),
'policy_id': 'wheel-test', 'observed_monotonic_ns': time.monotonic_ns(), 'error_ns': 1000}))
config = {'private_key_file': str(private), 'health_file': str(health),
'health_owner_uid': os.getuid(), 'policy_id': 'wheel-test',
'authority_id': 'disposable', 'environment': 'test', 'kid': 'test-key',
'max_health_age_ns': 30_000_000_000, 'host_drift_ppm': 1000,
'max_error_ns': 100_000_000, 'max_continuity_error_ns': 50_000_000,
'max_sample_age_ns': 5_000_000_000}
authority = Authority(config)
server = Server(('127.0.0.1', 0), authority)
thread = threading.Thread(target=server.serve_forever)
thread.start()
try:
trust = admit(directory=root, authority_id='disposable', environment='test',
kid='test-key', epoch=authority.epoch, policy_id='wheel-test',
public_key_pem=key.public_key().public_bytes(serialization.Encoding.PEM,
serialization.PublicFormat.SubjectPublicKeyInfo).decode(),
endpoint=f'http://127.0.0.1:{server.server_port}/v1/time-samples',
admission_ref='disposable-wheel-test-only', transport='admitted-loopback',
limits={'max_age_ns': 5_000_000_000, 'max_rtt_ns': 2_000_000_000,
'max_width_ns': 3_000_000_000, 'max_server_error_ns': 100_000_000,
'timer_ppm': 1000, 'timer_resolution_ns': 5_000_000,
'suspend_tolerance_ns': 5_000_000, 'trust_session_ns': 60_000_000_000})
result = subprocess.run([str(cli), 'read', '--trust', str(trust)],
capture_output=True, text=True, check=True)
window = json.loads(result.stdout)
assert window['authority_id'] == 'disposable'
assert window['epoch'] == authority.epoch
assert window['lower_ns'] <= window['upper_ns']
bad = json.loads(trust.read_text()); bad['kid'] = 'wrong-key'
trust.write_text(json.dumps(bad))
try:
Clock(FileTrust(trust)).read()
except ClockError:
pass
else:
raise AssertionError('wrong key accepted')
bad['kid'] = 'test-key'; trust.write_text(json.dumps(bad))
health.write_text('{"quality":"unusable"}')
refused = subprocess.run([str(cli), 'read', '--trust', str(trust)],
capture_output=True, text=True)
assert refused.returncode == 1 and not refused.stdout
assert refused.stderr == 'Railiance time unavailable or untrusted.\n'
finally:
server.shutdown(); server.server_close(); thread.join()
distributions = sorted((d.metadata['Name'], d.version) for d in importlib.metadata.distributions())
print(json.dumps({'checks': ['installed_import', 'three_packaged_schemas', 'cli_help',
'signed_http_cli_read', 'wrong_key_refusal', 'unhealthy_cli_refusal'],
'distributions': distributions}, sort_keys=True))
if __name__ == '__main__':
main()