Python inter-op ports

Prove the Python backend through proven Rust.

A Python project is designed to go through the same pipeline with one extra front end: pure, fully type-hinted spans will be ported to Rust in the provable subset, called from the patched Python through a compiled extension, and proven. By design, the proven Rust runs only inside the approved precondition; outside it, the original Python runs unchanged.

01 / THE MECHANISM

Find, port, guard, prove.

From the port onward it will be the Rust pipeline: extract, spec, prove, check. The port is designed to be validated like a patch: by differential tests and by the person reading the diff.

1 · candidatesrustproof python candidatespure, type-hinted, no I/O, no globals, no exceptions crossing the boundary
2 · portport-python skillRust under .rustproof/crates/, written in the provable subset
3 · scaffoldExtension cratePyO3, built with maturin
4 · patchGuarded callprecondition generated as Python from the approved spec
5 · testDifferential, across languagesboth agree or both fail; every port timed
6 · proveTheorem about the RustLean kernel, no sorry
02 / THE EXAMPLE

A FastAPI billing handler.

before · what the handler calls
def prorate(amount_cents: int, days_used: int, days_in_period: int) -> int:
return amount_cents * days_used // days_in_period
the port · provable subset
pub fn prorate(amount_cents: u64, days_used: u64, days_in_period: u64) -> u64 {
amount_cents * days_used / days_in_period
}
the patch · guarded inter-op call
from rustproof_ext.billing import prorate as _prorate_rs
U64_MAX = 18_446_744_073_709_551_615
def _prorate_ok(a: int, u: int, d: int) -> bool: # generated from the approved spec
return (
type(a) is int and type(u) is int and type(d) is int
and 0 < d <= U64_MAX
and 0 <= u <= d
and 0 <= a <= U64_MAX
and a * u <= U64_MAX
)
def prorate(amount_cents: int, days_used: int, days_in_period: int) -> int:
if _prorate_ok(amount_cents, days_used, days_in_period):
return _prorate_rs(amount_cents, days_used, days_in_period) # proven
return amount_cents * days_used // days_in_period # original
Spec.prorateIllustrative

For integer amounts and periods that fit in 64 bits, where the period is at least one day, the days used don’t exceed it, and amount × days used fits in 64 bits, prorate returns at most the amount.

.rustproof/specs/Prorate.lean
def prorate : Prop :=
∀ a u d : U64, 0 < d.val → u.val ≤ d.val → a.val * u.val ≤ U64.max →
∃ r, Generated.prorate a u d = ok r ∧ r.val ≤ a.val
Found by the counterexample search

Found before the spec was proposed: prorate(100, 1, 0) divides by zero. A large amount over a long period overflows 64 bits. The handler checked neither, so the precondition arrives with the theorem.

The team decides: reject a zero-day period at the API boundary with a 400, or keep the guarded fallback. Either way, every call inside the precondition is designed to run proven code, and the theorem says a customer is never charged more than the full amount.

03 / WHAT COVERS THE GAP

Nothing formally relates the Python to the Rust.

Python integers are unbounded and // floors toward negative infinity; the port uses u64 and truncating division. The precondition is designed to keep the proven path on inputs where the two semantics coincide.

PythonRust portWhat covers the gap
Unbounded intFixed-width integersA precondition in the spec, and the guard
// floors toward −∞/ truncates toward zeroThey agree for non-negative operands; the precondition is designed to keep the proven path there
ExceptionsResultThe extension will raise the matching Python exception
Shared mutable lists and dictsOwned valuesOnly spans with value semantics will be candidates
str indexing by code pointUTF-8 bytesSpans that index strings won’t be candidates in v1
Duck typingStatic typesType hints will be required; the guard rejects other types
04 / GUARDS, COST, SHIPPING

By design, behavior outside the proof stays exactly as it was.

Guarded ports

The patch is designed to dispatch on the approved precondition, generated as Python from the spec. Inside it the proven Rust runs; outside it the original Python runs unchanged. The guard itself will be covered by the differential tests.

The cost of the boundary

Every call into Rust pays a crossing cost. So candidates will be whole loops rather than loop bodies, every port will be timed, and a port slower than the Python it replaces will be flagged.

What will ship

The patched Python tree plus the compiled extension, built by rustproof build with maturin and stamped with the same provenance hash as a Rust project.

Your backend, with a proof on the money.

Start with one billing rule. The port will be a diff you can read, and the guard is designed to keep everything else as it was.

Install the Claude Code plugin coming soonRequest early access coming soon