jcp-runtime: Gate a call on its argument propagated provenance #40

Closed
dcharlot wants to merge 1 commit from jcp-runtime-flow-gate into jcp-flow-lattice

2026-07-22

Transaction Science
jcp-runtime: Gate a call on its argument's propagated provenance
The lattice defines flow labels and jcp-flow computes them; this is the check
that acts on one. A new check 6c in the reference monitor tests the argument's
label against the grant's flow ceiling and the resource's taint floor, so a value
derived from an untrusted read can be refused from a capability even though its
literal bytes match no rule — the question ContentContains cannot ask.

6c sits after capability and before caveats and budget, each placement load-
bearing. After capability, because the ceiling lives inside the grant and judging
flow before the signature verifies would seal a verdict over attacker-chosen
policy. Before budget, because a tainted call must cost zero joules — the same
invariant the tool-poisoning denial already holds, now extended to derived taint.

The facts argument distinguishes three cases on purpose. Absent facts (an
un-migrated caller) under a ceiling fail closed; a ceiling-free grant with absent
facts is untouched, which is every grant that exists today; clean facts pass any
ceiling and are byte-identical to the plain path. So refinement holds — the gate
only ever denies more, never allows what JCP denies now.

Three couplings make the wedge real rather than decorative. A TaintFloor mirrors
trust roots: an operator refusal of given origins on a resource that no grant
carries and no delegated ceiling can widen. A tainted sub-budget gives work that
has touched an untrusted source a tighter wallet, pre-checked at authorize so it
denies before the tool runs and depleted by charge_flow on the allow path,
tracked apart from the main budget it never converts into. And the chain path
mirrors 6c against the attenuation-fold of every link's ceiling, so a delegated
call is at most as permissive as its strictest hop and also fails closed without
facts.

The tainted budget rides inside FlowCeiling (from the FlowBelow caveat) rather
than a new Grant field, so the grant encoding is untouched; a grant without a
flow caveat is byte-identical to one minted before the feature, its content id
and signature unchanged (pinned by a test). FlowFacts lives in jcp-schema as pure
data so the runtime need not depend on the jcp-flow scan machinery for it.

Eleven new tests: the deny-with-zero-debit core, the fail-closed law, the
ceiling-free no-op, byte-identical clean calls, the floor refusal, the tainted
sub-budget pre-check, and the chain form of each.

Increment 3 of the FL-2 plan; the jcp/3 receipt seal and the gateway relay that
computes the facts follow.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-07-22 04:03:15 -04:00