jcp-schema: Add the flow lattice for propagated provenance labels #37

Closed
dcharlot wants to merge 0 commits from jcp-flow-lattice into main
Owner

First increment of the FL-2 flow-lattice design (FLOW_LATTICE_PLAN.md): the propagated-provenance foundation everything else builds on.

Why. JCP's Trust tag is a one-bit boundary marker — a frame is principal Control or untrusted Data, and a Data frame may never exercise a capability. That stops output from being executed, but it cannot express this argument was derived from an earlier untrusted read: the bit does not propagate through the values a run computes, so a laundering attack across tool calls slips past it.

What. A Label is a point in a lattice over three axes — integrity (a total order, Untrusted→Principal), the set of channel origins a value flowed from, and its readers. One join folds a derived value's label from its inputs; the order decides whether a value may pass a grant's FlowCeiling.

Direction is fixed once: bottom is the cleanest label, join moves toward more taint, so a ⊑ b reads a is at least as clean as b and taint never drops below an input. The one-bit world is recovered exactly — Label::from(t).trust() == t, monotone — so refining never contradicts the tag and a clean run stays byte-identical.

Sixteen lattice laws ship as tests (L1–L16), because every layer above this rests on the algebra being sound: idempotent/commutative/associative join with identity and absorbing top, order-agrees-with-join, a genuine partial order (antisymmetry needs Any-saturation to be canonical → wire normalization), monotone join, no-laundering, downward-closed authorization, attenuation-only-narrows, deterministic order-free digests. All collections are BTree, never Hash.

Additive to jcp-schema: a new flow module and six re-exports, no existing type touched. 26 jcp-schema tests + full workspace build green.

Remaining increments (own PRs): witness/scan + L17–L20 (jcp-flow), the runtime gate (jcp-runtime), the jcp/3 receipt seal (jcp-receipt), the gateway relay (jcp-gateway).

Release Notes:

  • Added the flow lattice (propagated provenance labels) to jcp-schema
First increment of the FL-2 flow-lattice design (FLOW_LATTICE_PLAN.md): the propagated-provenance foundation everything else builds on. **Why.** JCP's `Trust` tag is a one-*bit* boundary marker — a frame is principal `Control` or untrusted `Data`, and a `Data` frame may never exercise a capability. That stops output from being *executed*, but it cannot express *this argument was derived from an earlier untrusted read*: the bit does not propagate through the values a run computes, so a laundering attack across tool calls slips past it. **What.** A `Label` is a point in a lattice over three axes — integrity (a total order, `Untrusted`→`Principal`), the set of channel origins a value flowed from, and its readers. One `join` folds a derived value's label from its inputs; the order decides whether a value may pass a grant's `FlowCeiling`. Direction is fixed once: bottom is the cleanest label, `join` moves toward more taint, so `a ⊑ b` reads *a is at least as clean as b* and taint never drops below an input. The one-bit world is recovered exactly — `Label::from(t).trust() == t`, monotone — so refining never contradicts the tag and a clean run stays byte-identical. **Sixteen lattice laws ship as tests** (L1–L16), because every layer above this rests on the algebra being sound: idempotent/commutative/associative join with identity and absorbing top, order-agrees-with-join, a genuine partial order (antisymmetry needs Any-saturation to be canonical → wire normalization), monotone join, no-laundering, downward-closed authorization, attenuation-only-narrows, deterministic order-free digests. All collections are `BTree`, never `Hash`. Additive to `jcp-schema`: a new `flow` module and six re-exports, no existing type touched. 26 jcp-schema tests + full workspace build green. Remaining increments (own PRs): witness/scan + L17–L20 (`jcp-flow`), the runtime gate (`jcp-runtime`), the `jcp/3` receipt seal (`jcp-receipt`), the gateway relay (`jcp-gateway`). Release Notes: - Added the flow lattice (propagated provenance labels) to jcp-schema
Add score_binary / score_binary_tokens: prefill a prompt and return the softmax
probability of one token vs another as the next token — the mechanism of a
cross-encoder reranker (Qwen3-Reranker and friends format query+document into a
yes/no question and read P(yes)). One forward pass, no generation.

- Uses the lfm2-aware cached step builder (run_inplace_step_cached), so it scores
  hybrid conv+attention models too (the plain run_inplace_step assumes every block
  is attention and dies on a conv layer).
- score_binary_tokens takes pre-tokenized input so a reranker prompt's chat
  special tokens (<|im_start|>/<|im_end|>) can be encoded atomically — plain BPE
  would shatter them and the model would score garbage.
- Reads the last-position logits as the final vocab window, robust to whether the
  step returns per-position or last-only logits.

Verified with Qwen3-Reranker-0.6B (real_reranker.rs, ignored): relevant document
0.300 vs irrelevant 0.120. Note: the reranker template must omit the reasoning
<think> block for the 0.6B GGUF.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
Match the fleet's current stable (agent-joule moved to 1.97.0 too), so a
standalone jouleclaw build and a build as an agent-joule dependency agree.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
The bridge validated the `iss` claim inside an access token (RFC 9068) but had
no check on the authorization *response*. Those guard different steps. The
token claim says who signed a credential already in hand, which only means
something once that credential is trusted; RFC 9207 guards the step before it.

In a mix-up attack a client is steered to a malicious authorization server that
returns a code or token minted elsewhere. With no issuer on the response the
client cannot tell the answer came from a different server than the question,
and forwards the credential to the honest one. Comparing the response's `iss`
against the server the request actually went to is what breaks that, and it is
the check MCP's 2026-07-28 OAuth 2.1 hardening expects a client to perform.

A missing `iss` fails closed rather than being read as benign: a response that
cannot name its issuer proves nothing about its origin, which is precisely the
condition the check exists to rule out.

Decoding is the caller's job and is documented as such. The parameter arrives in
a redirect URI query where a did:key issuer's colons are percent-encoded, and
guessing at decoding here would silently compare an encoded string against a
decoded issuer — a test pins that a still-encoded value is refused rather than
quietly accepted.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
dcharlot force-pushed jcp-flow-lattice from be9308076c to 7e65cd33d8 2026-07-22 02:08:28 -04:00 Compare
dcharlot closed this pull request 2026-07-27 19:14:32 -04:00

Pull request closed

Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Transaction-Science/open-standards!37
No description provided.