tricu

An interpreted language for exploring Tree Calculus
Log | Files | Refs | README | LICENSE

bootstrap_inputs.py (2307B)


      1 """Explicit, relocatable bootstrap executables; no previous-store discovery.
      2 
      3 The caller selects/trusts the kit manifest (normally through the repository or
      4 release identity). These checks bind its named artifacts to exact bytes; they do
      5 not establish a publisher's identity. Host bundle import validates wire/ABI data.
      6 """
      7 import hashlib
      8 import json
      9 from pathlib import Path
     10 import re
     11 
     12 from generation_backend import BACKENDS
     13 
     14 SCHEMA = 'tricu.bootstrap-kit.v1'
     15 ROLES = {'compiler': 'rebuilt-compiler.arboricx', 'adapter': 'io-adapter.arboricx'}
     16 
     17 
     18 def load_kit(directory, backend):
     19     """Read and verify both artifacts before any generation output is created.
     20 
     21     Return captured bytes, not paths to reopen after verification. Fixed basenames
     22     avoid metadata-controlled path traversal; selected kit directories are trusted.
     23     """
     24     directory = Path(directory)
     25     raw = (directory / 'bootstrap-kit.json').read_bytes()
     26     record = json.loads(raw)
     27     if not isinstance(record, dict) or record.get('schema') != SCHEMA:
     28         raise ValueError('unsupported bootstrap kit schema')
     29     if backend not in BACKENDS or record.get('backend') != backend:
     30         raise ValueError('bootstrap kit backend mismatch')
     31     expected_exports = {'compiler': BACKENDS[backend][0], 'adapter': 'main'}
     32     artifacts = record.get('artifacts')
     33     if not isinstance(artifacts, dict) or set(artifacts) != set(ROLES):
     34         raise ValueError('bootstrap kit requires exactly compiler and adapter artifacts')
     35     payloads = {}
     36     for role, filename in ROLES.items():
     37         item = artifacts[role]
     38         if not isinstance(item, dict) or item.get('file') != filename:
     39             raise ValueError('invalid bootstrap kit filename: ' + role)
     40         if item.get('export') != expected_exports[role]:
     41             raise ValueError('invalid bootstrap kit export: ' + role)
     42         pin = item.get('sha256')
     43         if not isinstance(pin, str) or not re.fullmatch(r'[0-9a-f]{64}', pin):
     44             raise ValueError('invalid bootstrap kit digest: ' + role)
     45         payload = (directory / filename).read_bytes()
     46         if hashlib.sha256(payload).hexdigest() != pin:
     47             raise ValueError('bootstrap kit digest mismatch: ' + role)
     48         payloads[role] = payload
     49     return raw, payloads, hashlib.sha256(raw).hexdigest()