field_ios

In-the-field app for Radroots on iOS
git clone https://radroots.dev/git/field_ios.git
Log | Files | Refs | README | LICENSE

package_contract.py (25574B)


      1 #!/usr/bin/env python3
      2 """Structured standalone package-contract verification for the iOS capsule."""
      3 
      4 from __future__ import annotations
      5 
      6 import argparse
      7 import hashlib
      8 import json
      9 import os
     10 import plistlib
     11 import re
     12 import subprocess
     13 import sys
     14 import tempfile
     15 import tomllib
     16 from collections.abc import Mapping
     17 from pathlib import Path
     18 from typing import Any
     19 
     20 import app_dependency_graph
     21 import legacy_identifiers
     22 import package_privacy
     23 
     24 MAX_CONTRACT_BYTES = 2 * 1024 * 1024
     25 GIT_REVISION = re.compile(r"^[0-9a-f]{40}$")
     26 SHA256 = re.compile(r"^[0-9a-f]{64}$")
     27 APPLE_KIT_REMOTE = "https://github.com/radrootslabs/apple_kit.git"
     28 LIB_REMOTE = "https://github.com/radrootslabs/lib"
     29 SECP256K1_REMOTE = "https://github.com/21-DOT-DEV/swift-secp256k1.git"
     30 SECP256K1_REVISION = "e70a10e036a55fffea31568f0af92d69b6d449cd"
     31 
     32 
     33 class PackageContractError(Exception):
     34     """A stable, source-free package-contract rejection."""
     35 
     36 
     37 def _read_regular(path: Path, *, maximum: int = MAX_CONTRACT_BYTES) -> bytes:
     38     try:
     39         if path.is_symlink() or not path.is_file():
     40             raise PackageContractError("required contract input is not a regular file")
     41         size = path.stat().st_size
     42         if size < 0 or size > maximum:
     43             raise PackageContractError("required contract input exceeds its byte limit")
     44         value = path.read_bytes()
     45     except OSError as error:
     46         raise PackageContractError("required contract input cannot be read") from error
     47     if len(value) != size:
     48         raise PackageContractError("required contract input changed while reading")
     49     return value
     50 
     51 
     52 def _read_text(path: Path) -> str:
     53     try:
     54         return _read_regular(path).decode("utf-8")
     55     except UnicodeDecodeError as error:
     56         raise PackageContractError("required contract input is not UTF-8") from error
     57 
     58 
     59 def _read_toml(path: Path) -> dict[str, Any]:
     60     try:
     61         value = tomllib.loads(_read_text(path))
     62     except tomllib.TOMLDecodeError as error:
     63         raise PackageContractError("required TOML contract is malformed") from error
     64     if not isinstance(value, dict):
     65         raise PackageContractError("required TOML contract is not an object")
     66     return value
     67 
     68 
     69 def _read_json(path: Path) -> dict[str, Any]:
     70     try:
     71         value = json.loads(_read_text(path))
     72     except json.JSONDecodeError as error:
     73         raise PackageContractError("required JSON contract is malformed") from error
     74     if not isinstance(value, dict):
     75         raise PackageContractError("required JSON contract is not an object")
     76     return value
     77 
     78 
     79 def _read_plist(path: Path) -> dict[str, Any]:
     80     try:
     81         value = plistlib.loads(_read_regular(path))
     82     except (plistlib.InvalidFileException, ValueError, TypeError) as error:
     83         raise PackageContractError("required plist contract is malformed") from error
     84     if not isinstance(value, dict):
     85         raise PackageContractError("required plist contract is not a dictionary")
     86     return value
     87 
     88 
     89 def _mapping(value: object, key: str) -> Mapping[str, Any]:
     90     if not isinstance(value, Mapping):
     91         raise PackageContractError(f"structured contract field is invalid: {key}")
     92     return value
     93 
     94 
     95 def _exact(value: object, expected: object, key: str) -> None:
     96     if value != expected:
     97         raise PackageContractError(f"structured contract field differs: {key}")
     98 
     99 
    100 def parse_xcconfig_assignments(text: str) -> dict[str, str]:
    101     assignments: dict[str, str] = {}
    102     expression = re.compile(r"^([A-Z][A-Z0-9_]*)\s*=\s*(\S(?:.*\S)?)$")
    103     for raw in text.splitlines():
    104         line = raw.strip()
    105         if not line or line.startswith("//") or line.startswith("#"):
    106             continue
    107         match = expression.fullmatch(line)
    108         if match is None:
    109             raise PackageContractError("xcconfig contains an unsupported statement")
    110         key, value = match.groups()
    111         if key in assignments:
    112             raise PackageContractError("xcconfig assignment is duplicated")
    113         assignments[key] = value
    114     return assignments
    115 
    116 
    117 def parse_project_package(text: str, package_name: str) -> dict[str, str]:
    118     lines = text.splitlines()
    119     packages_line, packages_end = _project_package_bounds(lines)
    120     start = _project_package_start(lines, packages_line, packages_end, package_name)
    121     return _project_package_fields(lines[start + 1 :])
    122 
    123 
    124 def _project_package_bounds(lines: list[str]) -> tuple[int, int]:
    125     start = next(
    126         (index for index, line in enumerate(lines) if line == "packages:"), None
    127     )
    128     if start is None:
    129         raise PackageContractError("project package inventory is absent")
    130     end = next(
    131         (
    132             index
    133             for index in range(start + 1, len(lines))
    134             if lines[index] and not lines[index].startswith((" ", "#"))
    135         ),
    136         len(lines),
    137     )
    138     return start, end
    139 
    140 
    141 def _project_package_start(
    142     lines: list[str], start: int, end: int, package_name: str
    143 ) -> int:
    144     expected = f"  {package_name}:"
    145     result = next(
    146         (index for index in range(start + 1, end) if lines[index] == expected), None
    147     )
    148     if result is None:
    149         raise PackageContractError("project package entry is absent")
    150     return result
    151 
    152 
    153 def _project_package_fields(lines: list[str]) -> dict[str, str]:
    154     values: dict[str, str] = {}
    155     for line in lines:
    156         if line and not line.startswith("    "):
    157             break
    158         match = re.fullmatch(r"    ([a-z_]+): (\S+)", line)
    159         if match is None:
    160             if line.strip():
    161                 raise PackageContractError("project package entry is malformed")
    162             continue
    163         key, value = match.groups()
    164         if key in values:
    165             raise PackageContractError("project package field is duplicated")
    166         values[key] = value
    167     return values
    168 
    169 
    170 def validate_resolved(document: dict[str, Any], apple_revision: str) -> None:
    171     _exact(document.get("version"), 3, "package lock version")
    172     pins = document.get("pins")
    173     if not isinstance(pins, list) or len(pins) != 2:
    174         raise PackageContractError("package lock pin inventory differs")
    175     selected: dict[str, str] = {}
    176     for pin in pins:
    177         item = _mapping(pin, "package lock pin")
    178         _exact(item.get("kind"), "remoteSourceControl", "package lock pin kind")
    179         location = item.get("location")
    180         state = _mapping(item.get("state"), "package lock pin state")
    181         revision = state.get("revision")
    182         if not isinstance(location, str) or not location.startswith("https://"):
    183             raise PackageContractError("package lock location is invalid")
    184         if not isinstance(revision, str) or GIT_REVISION.fullmatch(revision) is None:
    185             raise PackageContractError("package lock revision is invalid")
    186         if location in selected:
    187             raise PackageContractError("package lock location is duplicated")
    188         selected[location] = revision
    189     _exact(selected.get(APPLE_KIT_REMOTE), apple_revision, "AppleKit package pin")
    190     _exact(
    191         selected.get(SECP256K1_REMOTE),
    192         SECP256K1_REVISION,
    193         "secp256k1 package pin",
    194     )
    195 
    196 
    197 def _swift_package(repo_root: Path) -> dict[str, Any]:
    198     with tempfile.TemporaryFile() as stdout, tempfile.TemporaryFile() as stderr:
    199         try:
    200             result = subprocess.run(
    201                 [
    202                     "swift",
    203                     "package",
    204                     "--package-path",
    205                     str(repo_root),
    206                     "dump-package",
    207                 ],
    208                 check=False,
    209                 stdout=stdout,
    210                 stderr=stderr,
    211                 timeout=60,
    212             )
    213         except (OSError, subprocess.TimeoutExpired) as error:
    214             raise PackageContractError(
    215                 "Swift package manifest cannot be evaluated"
    216             ) from error
    217         stdout.seek(0)
    218         output = stdout.read(MAX_CONTRACT_BYTES + 1)
    219     if result.returncode != 0 or len(output) > MAX_CONTRACT_BYTES:
    220         raise PackageContractError("Swift package manifest evaluation failed")
    221     try:
    222         value = json.loads(output)
    223     except (UnicodeDecodeError, json.JSONDecodeError) as error:
    224         raise PackageContractError(
    225             "Swift package manifest output is malformed"
    226         ) from error
    227     if not isinstance(value, dict):
    228         raise PackageContractError("Swift package manifest output is not an object")
    229     return value
    230 
    231 
    232 def _apple_revision(package: dict[str, Any]) -> str:
    233     dependencies = package.get("dependencies")
    234     if not isinstance(dependencies, list):
    235         raise PackageContractError("Swift package dependencies are absent")
    236     matches: list[str] = []
    237     for dependency in dependencies:
    238         candidate = _apple_dependency_revision(dependency)
    239         if candidate is not None:
    240             matches.append(candidate)
    241     if (
    242         len(matches) != 1
    243         or not isinstance(matches[0], str)
    244         or GIT_REVISION.fullmatch(matches[0]) is None
    245     ):
    246         raise PackageContractError("AppleKit dependency is not one exact revision")
    247     return matches[0]
    248 
    249 
    250 def _apple_dependency_revision(dependency: object) -> object | None:
    251     item = _mapping(dependency, "Swift package dependency")
    252     source = item.get("sourceControl")
    253     if not isinstance(source, list) or len(source) != 1:
    254         return None
    255     identity = _mapping(source[0], "Swift package source")
    256     remote = identity.get("location")
    257     requirement = identity.get("requirement")
    258     remote_values = remote.get("remote") if isinstance(remote, dict) else None
    259     if remote_values != [{"urlString": APPLE_KIT_REMOTE}]:
    260         return None
    261     if not isinstance(requirement, dict):
    262         return None
    263     revisions = requirement.get("revision")
    264     if not isinstance(revisions, list) or len(revisions) != 1:
    265         return None
    266     return revisions[0]
    267 
    268 
    269 def _validate_privacy(document: dict[str, Any]) -> None:
    270     try:
    271         package_privacy.validate_manifest(document)
    272     except ValueError as error:
    273         raise PackageContractError(str(error)) from error
    274 
    275 
    276 def _validate_app_plist(document: dict[str, Any]) -> None:
    277     for key in (
    278         "NSCameraUsageDescription",
    279         "NSFaceIDUsageDescription",
    280         "NSLocalNetworkUsageDescription",
    281     ):
    282         value = document.get(key)
    283         if not isinstance(value, str) or not value.strip():
    284             raise PackageContractError(f"required plist purpose is absent: {key}")
    285     try:
    286         package_privacy.validate_purposes(document)
    287     except ValueError as error:
    288         raise PackageContractError(str(error)) from error
    289     _exact(
    290         document.get("NSAppTransportSecurity"),
    291         {"NSAllowsLocalNetworking": True},
    292         "app transport security",
    293     )
    294     for forbidden in ("NSBonjourServices", "NSPhotoLibraryUsageDescription"):
    295         if forbidden in document:
    296             raise PackageContractError(f"forbidden plist field is present: {forbidden}")
    297 
    298     _exact(document.get("CFBundleDisplayName"), "Tera", "app display name")
    299     _exact(document.get("CFBundleName"), "$(PRODUCT_NAME)", "app bundle name")
    300 
    301 
    302 def _validate_ui_test_plist(document: dict[str, Any]) -> None:
    303     required = {
    304         "TERA_IOS_UI_TEST_FIXTURE_CONTROL",
    305         "TERA_IOS_UI_TEST_FIXTURE_EVIDENCE",
    306         "TERA_IOS_UI_TEST_NETWORK_PROFILE",
    307         "TERA_IOS_UI_TEST_SOURCE_COMMIT",
    308         "TERA_IOS_UI_TEST_SOURCE_TREE",
    309         "TERA_IOS_UI_TEST_APP_BUILD_SHA256",
    310         "TERA_IOS_UI_TEST_SIMULATOR_ID",
    311     }
    312     if required.difference(document):
    313         raise PackageContractError("UI test plist inventory is incomplete")
    314 
    315 
    316 def _verify_repository_layout(root: Path) -> None:
    317     for forbidden in ("docs", ".github", ".act"):
    318         path = root / forbidden
    319         if path.exists() or path.is_symlink():
    320             raise PackageContractError("forbidden public repository root exists")
    321 
    322 
    323 def _cargo_workspace(root: Path, *, resolved: bool = False) -> dict[str, Any]:
    324     with tempfile.TemporaryFile() as stdout, tempfile.TemporaryFile() as stderr:
    325         try:
    326             result = subprocess.run(
    327                 [
    328                     "cargo",
    329                     "metadata",
    330                     "--manifest-path",
    331                     str(root / "Cargo.toml"),
    332                     "--locked",
    333                     *([] if resolved else ["--no-deps"]),
    334                     "--offline",
    335                     "--format-version",
    336                     "1",
    337                 ],
    338                 check=False,
    339                 stdin=subprocess.DEVNULL,
    340                 stdout=stdout,
    341                 stderr=stderr,
    342                 timeout=60,
    343             )
    344         except (OSError, subprocess.TimeoutExpired) as error:
    345             raise PackageContractError("Cargo workspace cannot be evaluated") from error
    346         stdout.seek(0)
    347         output = stdout.read(MAX_CONTRACT_BYTES + 1)
    348     if result.returncode != 0 or len(output) > MAX_CONTRACT_BYTES:
    349         raise PackageContractError("Cargo workspace evaluation failed")
    350     try:
    351         value = json.loads(output)
    352     except (UnicodeDecodeError, json.JSONDecodeError) as error:
    353         raise PackageContractError("Cargo workspace output is malformed") from error
    354     if not isinstance(value, dict):
    355         raise PackageContractError("Cargo workspace output is not an object")
    356     return value
    357 
    358 
    359 def _local_cargo_path(value: object, root: Path) -> Path:
    360     if not isinstance(value, str) or not value:
    361         raise PackageContractError("local Cargo path is invalid")
    362     path = Path(value).resolve()
    363     if not path.is_relative_to(root.resolve()):
    364         raise PackageContractError("local Cargo path escapes the standalone repository")
    365     return path.relative_to(root.resolve())
    366 
    367 
    368 def _validate_app_workspace(document: dict[str, Any], root: Path) -> None:
    369     _exact(document.get("workspace_root"), str(root), "Cargo workspace root")
    370     packages = document.get("packages")
    371     members = document.get("workspace_members")
    372     if not isinstance(packages, list) or not packages or not isinstance(members, list):
    373         raise PackageContractError("Cargo workspace members are absent")
    374     identifiers = [
    375         package.get("id") for package in packages if isinstance(package, dict)
    376     ]
    377     if not all(isinstance(item, str) for item in identifiers + members):
    378         raise PackageContractError("Cargo workspace member identity is invalid")
    379     _exact(sorted(identifiers), sorted(members), "Cargo workspace member inventory")
    380     for package in packages:
    381         _validate_app_package(_mapping(package, "Cargo package"), root)
    382     _validate_mobile_defaults(document, packages, root)
    383 
    384 
    385 def _validate_mobile_defaults(
    386     document: Mapping[str, Any], packages: list[Any], root: Path
    387 ) -> None:
    388     owned = {
    389         _local_cargo_path(package.get("manifest_path"), root).parent.name: package["id"]
    390         for package in packages
    391     }
    392     if "tera_wasm" not in owned:
    393         return
    394     defaults = document.get("workspace_default_members")
    395     if not isinstance(defaults, list) or owned["tera_wasm"] in defaults:
    396         raise PackageContractError("non-default WASM package entered mobile defaults")
    397     for name in ("tera_core", "tera_ffi"):
    398         if name in owned and owned[name] not in defaults:
    399             raise PackageContractError("owned runtime is missing from mobile defaults")
    400 
    401 
    402 def _validate_app_package(package: Mapping[str, Any], root: Path) -> None:
    403     manifest = _local_cargo_path(package.get("manifest_path"), root)
    404     directory = manifest.parent
    405     if not directory.is_relative_to("core/crates"):
    406         raise PackageContractError("application Rust package is outside its owned root")
    407     dependencies = package.get("dependencies")
    408     if not isinstance(dependencies, list):
    409         raise PackageContractError("Cargo dependency inventory is absent")
    410     for dependency in dependencies:
    411         item = _mapping(dependency, "Cargo dependency")
    412         if "path" in item:
    413             _local_cargo_path(item["path"], root)
    414 
    415 
    416 def _verify_cargo_and_source(root: Path) -> tuple[str, str]:
    417     cargo = _read_toml(root / "Cargo.toml")
    418     workspace = _mapping(cargo.get("workspace"), "Cargo workspace")
    419     workspace_package = _mapping(workspace.get("package"), "Cargo workspace package")
    420     _exact(
    421         workspace_package.get("repository"),
    422         "https://github.com/radrootslabs/tera",
    423         "Cargo repository",
    424     )
    425     consumer = _read_toml(root / "radroots.lib.source-lock.v1.toml")
    426     _exact(consumer.get("repository"), LIB_REMOTE, "consumer Lib remote")
    427     lib_revision = consumer.get("revision")
    428     if (
    429         not isinstance(lib_revision, str)
    430         or GIT_REVISION.fullmatch(lib_revision) is None
    431     ):
    432         raise PackageContractError("consumer Lib revision is invalid")
    433     release_version = consumer.get("version")
    434     _exact(release_version, "0.1.0-alpha", "consumer Lib version")
    435     try:
    436         app_dependency_graph.validate(_cargo_workspace(root, resolved=True), consumer)
    437     except app_dependency_graph.GraphError as error:
    438         raise PackageContractError(str(error)) from error
    439     _verify_owned_source_lock(root, consumer)
    440     return release_version, lib_revision
    441 
    442 
    443 def _verify_owned_source_lock(root: Path, foundation: dict[str, Any]) -> None:
    444     lock = _read_toml(root / "TeraFFI/source.lock")
    445     _exact(
    446         set(lock),
    447         {
    448             "schema",
    449             "repository",
    450             "source_tree",
    451             "manifest_sha256",
    452             "source_date_epoch",
    453             "foundation",
    454         },
    455         "installed source fields",
    456     )
    457     _exact(lock["schema"], "tera.installed-source.v1", "installed source schema")
    458     _exact(
    459         lock["repository"], "https://github.com/radrootslabs/tera", "installed producer"
    460     )
    461     _exact(
    462         lock["foundation"],
    463         {key: foundation[key] for key in ("repository", "revision", "version")},
    464         "installed foundation",
    465     )
    466     if (
    467         not isinstance(lock["source_tree"], str)
    468         or GIT_REVISION.fullmatch(lock["source_tree"]) is None
    469     ):
    470         raise PackageContractError("installed source tree is invalid")
    471     _exact(lock["source_date_epoch"], 1787871027, "installed source epoch")
    472     _exact(
    473         lock["manifest_sha256"],
    474         hashlib.sha256(_read_regular(root / "TeraFFI/provenance.json")).hexdigest(),
    475         "installed manifest digest",
    476     )
    477 
    478 
    479 def _verify_apple_dependencies(root: Path) -> str:
    480     package = _swift_package(root)
    481     _exact(package.get("name"), "tera", "Swift package name")
    482     _exact(package.get("defaultLocalization"), "en", "Swift localization")
    483     apple_revision = _apple_revision(package)
    484     project = parse_project_package(_read_text(root / "project.yml"), "RadrootsKit")
    485     if set(project) != {"url", "revision"}:
    486         raise PackageContractError("project AppleKit field inventory differs")
    487     _exact(project.get("url"), APPLE_KIT_REMOTE, "project AppleKit remote")
    488     _exact(project.get("revision"), apple_revision, "project AppleKit revision")
    489     return apple_revision
    490 
    491 
    492 def _verify_apple_configuration(root: Path) -> None:
    493     _validate_privacy(_read_plist(root / "Tera/Resources/PrivacyInfo.xcprivacy"))
    494     _validate_app_plist(_read_plist(root / "Tera/Info.plist"))
    495     _validate_ui_test_plist(_read_plist(root / "TeraUITests/Info.plist"))
    496 
    497     base = parse_xcconfig_assignments(_read_text(root / "Tera/Config/Base.xcconfig"))
    498     debug = parse_xcconfig_assignments(_read_text(root / "Tera/Config/Debug.xcconfig"))
    499     if set(base) != {
    500         "TERA_IOS_RUNTIME_MODE",
    501         "TERA_IOS_NOSTR_RELAY_URLS",
    502         "TERA_IOS_BLOSSOM_ORIGINS",
    503         "TERA_IOS_KEYCHAIN_SERVICE_PREFIX",
    504     }:
    505         raise PackageContractError("base xcconfig field inventory differs")
    506     if set(debug) != {
    507         "TERA_IOS_RUNTIME_MODE",
    508         "PRODUCT_BUNDLE_IDENTIFIER",
    509         "TERA_IOS_NOSTR_RELAY_URLS",
    510         "TERA_IOS_BLOSSOM_ORIGINS",
    511         "TERA_IOS_KEYCHAIN_SERVICE_PREFIX",
    512     }:
    513         raise PackageContractError("debug xcconfig field inventory differs")
    514     _exact(
    515         base.get("TERA_IOS_NOSTR_RELAY_URLS"),
    516         "wss:$(SLASH)$(SLASH)radroots.org$(SLASH)",
    517         "base relay",
    518     )
    519     _exact(
    520         base.get("TERA_IOS_BLOSSOM_ORIGINS"),
    521         "https:$(SLASH)$(SLASH)blossom.radroots.org",
    522         "base Blossom origin",
    523     )
    524     _exact(
    525         debug.get("TERA_IOS_NOSTR_RELAY_URLS"),
    526         "ws:$(SLASH)$(SLASH)127.0.0.1:21000",
    527         "debug relay",
    528     )
    529     _exact(
    530         debug.get("TERA_IOS_BLOSSOM_ORIGINS"),
    531         "http:$(SLASH)$(SLASH)127.0.0.1:21100",
    532         "debug Blossom origin",
    533     )
    534     _verify_installation_compatibility(root, base, debug)
    535 
    536 
    537 def _verify_installation_compatibility(
    538     root: Path, base: dict[str, str], debug: dict[str, str]
    539 ) -> None:
    540     baseline = _read_json(root / "test-fixtures/tera-compatibility.v1.json")
    541     _exact(
    542         baseline.get("schema"), "tera.compatibility-baseline.v1", "compatibility schema"
    543     )
    544     production = parse_xcconfig_assignments(_read_text(root / "Tera/tera.xcconfig"))
    545     actual = {
    546         "production_bundle_identifier": production.get("PRODUCT_BUNDLE_IDENTIFIER"),
    547         "debug_bundle_identifier": debug.get("PRODUCT_BUNDLE_IDENTIFIER"),
    548         "production_keychain_service_prefix": base.get(
    549             "TERA_IOS_KEYCHAIN_SERVICE_PREFIX"
    550         ),
    551         "debug_keychain_service_prefix": debug.get("TERA_IOS_KEYCHAIN_SERVICE_PREFIX"),
    552     }
    553     _exact(actual, baseline.get("installation"), "installed identity compatibility")
    554 
    555 
    556 def _verify_package_locks(root: Path, apple_revision: str) -> None:
    557     resolved_paths = (
    558         root / "Package.resolved",
    559         root
    560         / "Tera.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved",
    561     )
    562     resolved = [_read_json(path) for path in resolved_paths]
    563     for document in resolved:
    564         validate_resolved(document, apple_revision)
    565     if resolved[0].get("pins") != resolved[1].get("pins"):
    566         raise PackageContractError("Swift and Xcode package locks disagree")
    567 
    568 
    569 def _verify_persona_toolchain(root: Path) -> None:
    570     verifier_project = _read_toml(root / "scripts/persona-verifier/pyproject.toml")
    571     verifier_lock = _read_toml(root / "scripts/persona-verifier/uv.lock")
    572     verifier_metadata = _mapping(verifier_project.get("project"), "verifier project")
    573     _exact(
    574         verifier_metadata.get("requires-python"),
    575         "==3.14.7",
    576         "verifier Python",
    577     )
    578     _exact(
    579         verifier_metadata.get("dependencies"),
    580         ["jsonschema==4.26.0"],
    581         "verifier dependencies",
    582     )
    583     dependency_groups = _mapping(
    584         verifier_project.get("dependency-groups"), "verifier dependency groups"
    585     )
    586     _exact(dependency_groups, {"dev": ["ruff==0.12.12"]}, "verifier dev tools")
    587     _exact(verifier_lock.get("requires-python"), "==3.14.7", "verifier lock Python")
    588     package_rows = verifier_lock.get("package")
    589     if not isinstance(package_rows, list):
    590         raise PackageContractError("verifier lock package inventory is invalid")
    591     locked_packages = {
    592         item.get("name"): item.get("version")
    593         for item in package_rows
    594         if isinstance(item, dict)
    595     }
    596     _exact(locked_packages.get("jsonschema"), "4.26.0", "verifier jsonschema lock")
    597     _exact(locked_packages.get("ruff"), "0.12.12", "verifier ruff lock")
    598 
    599 
    600 def _verify_required_files(root: Path) -> None:
    601     required_files = (
    602         ".swiftformat",
    603         ".swiftlint.yml",
    604         "scripts/maintainability_ratchet.py",
    605         "scripts/local-social-fixture.py",
    606         "scripts/swift-quality.sh",
    607         "scripts/linux-shared-rust.sh",
    608         "test-fixtures/maintainability-baseline.v1.json",
    609         "test-fixtures/swiftlint-maintainability-baseline.v1.json",
    610         "test-fixtures/bud11-upload-authorization-mutations.v1.json",
    611         "test-fixtures/bud11-upload-authorization-mutations.v1.schema.json",
    612         "test-fixtures/local-social-personas.v1.json",
    613         "test-fixtures/local-social-personas.v1.schema.json",
    614         "test-fixtures/local-social-persona-results.v1.schema.json",
    615         "test-fixtures/local-social-persona-attempt-evidence.v1.schema.json",
    616         "test-fixtures/local-social-persona-results.v2.schema.json",
    617     )
    618     for relative in required_files:
    619         _read_regular(root / relative)
    620     for relative in ("scripts/swift-quality.sh", "scripts/linux-shared-rust.sh"):
    621         if not os.access(root / relative, os.X_OK):
    622             raise PackageContractError("required package command is not executable")
    623 
    624 
    625 def verify(repo_root: Path) -> tuple[str, str]:
    626     root = repo_root.resolve()
    627     _verify_repository_layout(root)
    628     try:
    629         legacy_identifiers.verify(root)
    630     except legacy_identifiers.LegacyIdentifierError as error:
    631         raise PackageContractError(str(error)) from error
    632     _validate_app_workspace(_cargo_workspace(root), root)
    633     release_version, _ = _verify_cargo_and_source(root)
    634     apple_revision = _verify_apple_dependencies(root)
    635     _verify_apple_configuration(root)
    636     _verify_package_locks(root, apple_revision)
    637     _verify_persona_toolchain(root)
    638     _verify_required_files(root)
    639     return release_version, apple_revision
    640 
    641 
    642 def main(argv: list[str] | None = None) -> int:
    643     parser = argparse.ArgumentParser()
    644     parser.add_argument("--repo-root", type=Path, required=True)
    645     arguments = parser.parse_args(argv)
    646     try:
    647         version, apple_revision = verify(arguments.repo_root)
    648     except PackageContractError as error:
    649         print(f"package_contract: {error}", file=sys.stderr)
    650         return 1
    651     print(f"package contracts agree at {version}; apple_kit@{apple_revision}")
    652     return 0
    653 
    654 
    655 if __name__ == "__main__":
    656     raise SystemExit(main())