Native Rust and PyO3 Boundary¶
ZapTrace's zaptrace_core crate accelerates placement and routing and is loaded by Python as zaptrace._core. The crate and its PyO3 interface are supported security-sensitive code. This document defines the tested boundary, mandatory evidence, limits, and non-claims.
Supported native targets¶
The release workflow currently builds and tests these wheel targets. The authoritative support levels, source fallback, and unsupported guidance are in the distribution support matrix:
| Runner | Rust target | Python ABI |
|---|---|---|
| Ubuntu latest | x86_64-unknown-linux-gnu |
CPython 3.13 |
| macOS 15 Intel | x86_64-apple-darwin |
CPython 3.13 |
| macOS latest Apple Silicon | aarch64-apple-darwin |
CPython 3.13 |
A wheel is not eligible for upload merely because it compiled. The exact built wheel must be installed into a clean virtual environment, pass the mandatory native boundary verifier, and pass the broader distribution smoke contract before the wheel upload step runs.
Boundary architecture¶
The native code is divided into:
- pure Rust placement/routing kernels;
- shared validation and typed native errors;
- thin PyO3 wrappers that convert valid results and controlled failures into Python values/exceptions.
Public PyO3 collection parameters accept concrete Python list values. Their lengths are checked against the documented limits before PyO3 converts any element into a Rust Vec, so an oversized list cannot force a second native allocation or trigger element conversion first. Kernel working buffers are allocated only after the remaining finite-value, geometry, and index validation succeeds. Unexpected Rust panics are caught at the wrapper boundary and converted to a fixed RuntimeError rather than unwinding through Python. Expected invalid inputs become ValueError.
Explicit resource limits¶
| Resource | Maximum |
|---|---|
| Components per placement call | 1,000 |
| Placement connections | 10,000 |
| MST points | 2,000 |
| Shove connections | 10,000 |
| Shove obstacles | 2,000 |
Inputs above these limits are rejected before PyO3 element extraction and before the corresponding result/working buffers are allocated. Floating-point coordinates, board dimensions, spacing, and clearance must be finite. Dimensions must be positive, spacing/clearance must be non-negative, and connection indices must refer to existing components. Derived routing values are checked again so arithmetic overflow from extreme but finite inputs cannot produce NaN or infinity in native outputs.
Mandatory verification¶
Direct Rust tests¶
The crate test suite covers:
- deterministic placement, MST routing, and shove routing;
- finite outputs and board-bound invariants;
- invalid indices and degenerate geometry;
- NaN/infinity rejection and derived-value overflow rejection;
- empty/single-item behavior;
- exact resource-limit boundaries;
- panic containment in the shared boundary guard.
The required commands are:
cargo fmt --manifest-path zaptrace_core/Cargo.toml --check
cargo clippy --manifest-path zaptrace_core/Cargo.toml --all-targets -- -D warnings
cargo test --manifest-path zaptrace_core/Cargo.toml
Installed-wheel boundary evidence¶
scripts/ci_native_boundary.py must run against the installed extension from a clean environment. When a wheel is supplied, the verifier rejects an extension loaded from the source tree. It records:
- source commit/ref/dirty state, with dirty source rejected;
- wheel filename, size, and SHA-256;
- actual extension path;
- configured limits;
- valid/deterministic placement and routing checks;
- negative-input exception checks;
- pre-extraction resource-limit rejection for concrete Python lists;
- same-process survival after rejected calls;
- deterministic evidence digest and explicit non-claims.
ZAPTRACE_REQUIRE_NATIVE=1 marks native verification as mandatory. A missing extension is a failure, not a skip.
Cargo advisory evidence¶
The Security workflow installs cargo-audit at the pinned version declared in .github/workflows/security-scan.yml, scans zaptrace_core/Cargo.lock, and retains:
- raw
cargo-audit.json; - normalized
cargo-audit-evidence.json; - a human-readable Markdown summary.
The normalized evidence binds the result to the Cargo.lock SHA-256 and tool version. Vulnerabilities fail strict mode. Warnings are counted and remain visible for maintainer triage.
Failure semantics¶
| Condition | Result |
|---|---|
| Expected invalid input | Python ValueError |
| Unexpected caught native panic | Python RuntimeError with fixed non-sensitive message |
| Missing required extension | CI failure |
| Dirty source tree while binding evidence to a commit | CI failure |
| Source-tree extension used while claiming wheel verification | CI failure |
| Wheel verification check fails | CI failure; wheel is not uploaded |
| Cargo advisory found | Security workflow failure with retained evidence |
Reproducing locally¶
cargo test --manifest-path zaptrace_core/Cargo.toml
maturin build --manifest-path zaptrace_core/Cargo.toml --out /tmp/zaptrace-native-dist
uv lock --check
UV_PROJECT_ENVIRONMENT=/tmp/zaptrace-native-smoke \
uv sync --locked --all-extras --all-groups --no-install-project --no-build \
--python 3.12
wheel="$(realpath /tmp/zaptrace-native-dist/*.whl)"
wheel_hash="$(sha256sum "$wheel" | awk '{print $1}')"
printf 'zaptrace @ file://%s --hash=sha256:%s\n' "$wheel" "$wheel_hash" \
> /tmp/zaptrace-native.requirements.txt
uv pip install \
--python /tmp/zaptrace-native-smoke/bin/python \
--no-deps \
--require-hashes \
-r /tmp/zaptrace-native.requirements.txt
cd /tmp
ZAPTRACE_REQUIRE_NATIVE=1 /tmp/zaptrace-native-smoke/bin/python \
/path/to/zaptrace/scripts/ci_native_boundary.py \
--wheel "$wheel" \
--source-root /path/to/zaptrace \
--target x86_64-unknown-linux-gnu \
--output /tmp/native-boundary-evidence.json \
--markdown /tmp/native-boundary-evidence.md \
--strict
Non-claims¶
This boundary does not establish formal verification, constant-time behavior, real-time guarantees, qualified safety, or immunity from denial-of-service. It does not prove that all platform/toolchain combinations are safe. Native evidence is one layer alongside code review, SAST, dependency review, fuzzing, release provenance, and human engineering review.