app

Local-first trade for farms and co-ops
git clone https://radroots.dev/git/app.git
Log | Files | Refs | README | LICENSE

commit fecd0eea4075e718457251960df23dc6e241ac00
parent 17f95a70398f7cb85e423bb05cb6f94126ff7012
Author: triesap <tyson@radroots.org>
Date:   Fri,  4 Sep 2026 22:19:07 +0000

fix: bind Step 289 platform probe source

Diffstat:
Mcontracts/rshr-201-step-gates.v1.json | 2+-
Mtools/rshr_201_step_gate.py | 74+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 72 insertions(+), 4 deletions(-)

diff --git a/contracts/rshr-201-step-gates.v1.json b/contracts/rshr-201-step-gates.v1.json @@ -1 +1 @@ -{"gate_command_contract":[{"argv_template":["cargo","extbuild","run","--","uv","run","--offline","--no-project","python3","-B","tools/rshr_201_step_gate.py","--step={step}","--check-id={check_id}","--source-revision={source_revision}","--source-tree={source_tree}","--candidate-digest={candidate_digest}","--platform=macos_aarch64","--execution-request-sha256={execution_request_sha256}"],"assertion_id":["step_289_gate_01_ff71b7cb8259835dc66c6e65a6124e265dff667fa929e895c6556636f49c7e54"],"check_id":"gate-01-ff71b7cb8259835dc66c6e65a6124e265dff667fa929e895c6556636f49c7e54","environment_authority":{"cache_policy_id":"rshr-200-step-287-cache-policy.v1","cache_policy_sha256":"3e81d178bce97b6c349dfbb00c68fd6f620ac00b1a1c8d37b12e9998f3c9eaaa","cadence_policy_id":"rshr-200-step-287-cadence-policy.v1","cadence_policy_sha256":"d24903df8659ee3772297c84994911efe7d21cb8b988320ddc6ddce0431892a1","isolation":"extbuild_host_constrained","network":"disabled","network_policy_id":"none","network_policy_sha256":"none","resource_policy_id":"rshr-200-step-287-resource-policy.v1","resource_policy_sha256":"05d3c7a89185d3c55678d97955193fce2ed92b1eee5af99083d77ea64c98d14e"},"environment_names":["EXT_BUILD_CONFIG","EXT_BUILD_MACHINE_CONFIG","EXT_BUILD_ROOT","HOME","PATH","RUSTUP_TOOLCHAIN","TMPDIR"],"gate_definition_sha256":"ff71b7cb8259835dc66c6e65a6124e265dff667fa929e895c6556636f49c7e54","required_platforms":["macos_aarch64"],"required_tools":["uv","python3","git"],"result_schema":"radroots.services-hardening.rshr-200-step-check-result.v1","schema":"radroots.services-hardening.rshr-200-step-check-command.v1","step":289,"verifier_path":"tools/rshr_201_step_gate.py","verifier_sha256":"81d852d3f2a38339e7b273fd0315737712e4d69d90d4f163c013eb053777b416"}],"schema":"radroots.harvestcircle.rshr-201-step-gates.v1","step":[289]} +{"gate_command_contract":[{"argv_template":["cargo","extbuild","run","--","uv","run","--offline","--no-project","python3","-B","tools/rshr_201_step_gate.py","--step={step}","--check-id={check_id}","--source-revision={source_revision}","--source-tree={source_tree}","--candidate-digest={candidate_digest}","--platform=macos_aarch64","--execution-request-sha256={execution_request_sha256}"],"assertion_id":["step_289_gate_01_ff71b7cb8259835dc66c6e65a6124e265dff667fa929e895c6556636f49c7e54"],"check_id":"gate-01-ff71b7cb8259835dc66c6e65a6124e265dff667fa929e895c6556636f49c7e54","environment_authority":{"cache_policy_id":"rshr-200-step-287-cache-policy.v1","cache_policy_sha256":"3e81d178bce97b6c349dfbb00c68fd6f620ac00b1a1c8d37b12e9998f3c9eaaa","cadence_policy_id":"rshr-200-step-287-cadence-policy.v1","cadence_policy_sha256":"d24903df8659ee3772297c84994911efe7d21cb8b988320ddc6ddce0431892a1","isolation":"extbuild_host_constrained","network":"disabled","network_policy_id":"none","network_policy_sha256":"none","resource_policy_id":"rshr-200-step-287-resource-policy.v1","resource_policy_sha256":"05d3c7a89185d3c55678d97955193fce2ed92b1eee5af99083d77ea64c98d14e"},"environment_names":["EXT_BUILD_CONFIG","EXT_BUILD_MACHINE_CONFIG","EXT_BUILD_ROOT","HOME","PATH","RUSTUP_TOOLCHAIN","TMPDIR"],"gate_definition_sha256":"ff71b7cb8259835dc66c6e65a6124e265dff667fa929e895c6556636f49c7e54","required_platforms":["macos_aarch64"],"required_tools":["uv","python3","git"],"result_schema":"radroots.services-hardening.rshr-200-step-check-result.v1","schema":"radroots.services-hardening.rshr-200-step-check-command.v1","step":289,"verifier_path":"tools/rshr_201_step_gate.py","verifier_sha256":"a148c7a260330af444701492b7105b1e5c31f2fd45258e924b621a86cca90f3e"}],"schema":"radroots.harvestcircle.rshr-201-step-gates.v1","step":[289]} diff --git a/tools/rshr_201_step_gate.py b/tools/rshr_201_step_gate.py @@ -264,22 +264,84 @@ def run_step(step: int, source_revision: str) -> None: def parse_arguments() -> argparse.Namespace: parser = argparse.ArgumentParser(allow_abbrev=False) + parser.add_argument("--emit-platform-result", action="store_true") parser.add_argument("--step", type=int, required=True) - parser.add_argument("--check-id", required=True) + parser.add_argument("--check-id") parser.add_argument("--source-revision", required=True) parser.add_argument("--source-tree", required=True) - parser.add_argument("--candidate-digest", required=True) + parser.add_argument("--candidate-digest") parser.add_argument("--platform", required=True) parser.add_argument("--execution-request-sha256", required=True) return parser.parse_args() +def emit_platform_result(arguments: argparse.Namespace) -> int: + if arguments.check_id is not None or arguments.candidate_digest is not None: + raise GateError("platform probe received gate-only arguments") + require_source_state(arguments.source_revision, arguments.source_tree) + identity = os.uname() + if ( + arguments.platform != "macos_aarch64" + or identity.sysname != "Darwin" + or identity.machine not in {"arm64", "aarch64"} + ): + raise GateError("platform probe is not running on macOS aarch64") + xcode_identity = { + "xcodebuild": run(["/usr/bin/xcodebuild", "-version"]).decode( + "utf-8", "strict" + ), + "sdk": { + sdk: run( + ["/usr/bin/xcrun", "--sdk", sdk, "--show-sdk-version"] + ).decode("utf-8", "strict") + for sdk in ("iphoneos", "iphonesimulator", "macosx") + }, + } + verifier_path = Path(__file__).resolve() + result = { + "schema": "radroots.services-hardening.rshr-200-platform-result.v1", + "platform": "macos_aarch64", + "system": "aarch64-darwin", + "os_family": "macos", + "architecture": "aarch64", + "kernel_name": "Darwin", + "kernel_release": identity.release, + "os_build_sha256": sha256_bytes( + canonical( + { + "kernel_name": identity.sysname, + "kernel_release": identity.release, + "kernel_version": identity.version, + } + ) + ), + "runner_kind": "host", + "runner_image_sha256": "none", + "apple_toolchain_identity_sha256": sha256_bytes(canonical(xcode_identity)), + "probe_source_path": verifier_path.relative_to(ROOT).as_posix(), + "probe_source_sha256": sha256_bytes(read_regular(verifier_path)), + "execution_request_sha256": arguments.execution_request_sha256, + "assertion": [ + {"id": identifier, "result": "pass"} + for identifier in ( + "os_family", + "architecture", + "kernel_identity", + "runner_identity", + "apple_identity", + ) + ], + "result": "available", + } + sys.stdout.buffer.write(canonical(result)) + return 0 + + def main() -> int: arguments = parse_arguments() if arguments.step not in GATE_DEFINITIONS: raise GateError("step is outside the HarvestCircle gate authority") for value, label in ( - (arguments.check_id.removeprefix("gate-01-"), "check digest"), (arguments.source_revision, "source revision"), (arguments.source_tree, "source tree"), (arguments.execution_request_sha256, "execution request"), @@ -287,6 +349,12 @@ def main() -> int: expected_length = 40 if label in {"source revision", "source tree"} else 64 if re.fullmatch(rf"[0-9a-f]{{{expected_length}}}", value) is None: raise GateError(f"{label} is not canonical") + if arguments.emit_platform_result: + return emit_platform_result(arguments) + if arguments.check_id is None or re.fullmatch( + r"gate-01-[0-9a-f]{64}", arguments.check_id + ) is None: + raise GateError("check digest is not canonical") if arguments.candidate_digest != "none" or arguments.platform != "macos_aarch64": raise GateError("candidate or platform scope differs") authority_bytes = read_regular(AUTHORITY_PATH, 256 * 1024)