Skip to content

fix(sofi): relaying and owning are two operations, and the build says so - #953

Merged
cryptskii merged 1 commit into
mainfrom
fix/sofi-relay-is-party-neutral
Sep 21, 2026
Merged

cryptskii merged 1 commit into
mainfrom
fix/sofi-relay-is-party-neutral

Conversation

@cryptskii

Copy link
Copy Markdown
Collaborator

Relaying and owning are two operations, and the build says so

complete_pending_fulfillment read this device's head and the admission on it, while its own doc comment said "any device may run it again". Device scenario 4 of §44.1 is "F registered, trader offline: a relayer completes the cells and the position resolves", and there was nothing a relayer could call.

Per the ruling in §44.4: any device may carry immutable signed protocol objects to storage; only the owning device may touch its own admission, fence, lineage and leaf cache. This makes that separation structural rather than a sentence.

The party-neutral half

SDK/sdk/sofi_relay.rs is new. Each entry point takes a committed set and a fulfillment id. It holds no CoreSDK, reads no device head, and writes nothing local.

  • relay_position_pair carries F in its published envelope and C_q, derived from the two verified objects, to the leader of s(q) and the other members. Idempotent, because members keep what they were given.
  • relay_fulfillment does that, then reads each leg key raw and carries the exercise it finds verbatim to every key F names.

It never builds an exercise. Building one needs the trader's own closure objects, which are not a relayer's to hold. A fulfillment whose exercise was never published has nothing to relay, and the relay reports that instead of papering over it.

Nothing re-gates on conformance. That gate is the producer's discipline before it publishes, not a second opinion at every carrier. Members keep what they are given and Core decides what counts, which is the storage contract.

The line is held by the build, not a comment

ci/sofi_relay_is_party_neutral.sh, wired into ci/production_safety_checks.sh:

  1. the relay may not name CoreSDK, device_head, pending_economic_admission, client_db or economic_lineage in production;
  2. its entry points must take exactly a committed set and a content address;
  3. complete_pending_fulfillment and resolve_pending_position must still take the owning device.

The gate strips comment lines before checking, because this file explains what it may not hold and prose naming a thing is not holding it. That is the mistake G1 made for the whole rebuild, caught here at the moment of writing rather than thirteen steps later.

Device scenario 4, executed

a_relayer_completes_the_cells_and_the_owner_later_resolves_from_its_admission: device A fulfils, then the second leg's cell refuses every member, which is what an offline trader looks like from storage. A's own completion lands one leg, the route cannot be consumed, and resolution is Pending. The members are healed. A party holding no device state relays, the exercise reaches every key, and only then does A advance its own lineage from its own durable admission.

a_relay_carries_the_pair_but_never_invents_an_exercise pins the other half: the pair is carried, and no leg is claimed.

Controls

Mutation Result
The relay imports CoreSDK gate fails, naming it
The owner-local half is given the relay's shape gate fails, naming it
The relay carries to one key only scenario 4 red
The relay reports legs it never wrote the never-invents test red

The second was first attempted by reordering the parameters, which left core: &CoreSDK present; the gate rightly passed and that mutation was discarded as non-discriminating rather than counted. The gate is a text check and was mutated as text, so that mutant does not compile, which is not what is under test: the gate runs before the compiler and must fail there.

Gates

  • SDK (release, --features test-utils): sdk::sofi_* 48/0, two tests new.
  • make lint exit 0; ci/production_safety_checks.sh passed, including the new gate; G1 unchanged at 86 reachable, 7 baselined.
  • Also adds fake_registers::heal_cell, so a stopped write is not permanent and a relay can mean something.

Spec

§33 states the two operations and what a relay may not do; §27's sofi.relay row points at the module.

complete_pending_fulfillment read this device's head and its admission
while its own doc comment said any device may run it. Device scenario 4
is "F registered, trader offline: a relayer completes the cells", and
there was nothing a relayer could call.

Owner ruling §44.4: any device may carry immutable signed protocol
objects to storage; only the owning device may touch its own admission,
fence, lineage and leaf cache. The separation is now structural.

SDK/sdk/sofi_relay.rs (new) is the party-neutral half. Each entry point
takes a committed set and a fulfillment id, holds no CoreSDK, reads no
device head and writes nothing local. From the id it fetches F and its P
by content address; relay_position_pair carries F in its published
envelope and C_q derived from the two verified objects to the leader of
s(q) and the other members; relay_fulfillment then reads each leg key
raw and carries the exercise it finds VERBATIM to every key F names.

It never builds an exercise. Building one needs the trader's own closure
objects, which are not a relayer's to hold, so a fulfillment whose
exercise was never published has nothing to relay and the relay reports
that rather than papering over it. Nothing re-gates on conformance:
that gate is the producer's discipline before it publishes, not a second
opinion at every carrier.

ci/sofi_relay_is_party_neutral.sh holds the line a comment could not:
the relay may not name CoreSDK, device_head, pending_economic_admission,
client_db or economic_lineage in production, its entry points must take
exactly a set and a content address, and complete_pending_fulfillment
and resolve_pending_position must still take the owning device.

Controls, each restored byte-identical:
  M1 the relay imports CoreSDK            -> the gate fails, naming it
  M2' the owner-local half is given the
      relay's shape                       -> the gate fails, naming it
  M3 the relay carries to one key only    -> scenario 4 red
  M4 the relay reports legs it never wrote -> the never-invents test red

M2 was first attempted by REORDERING the parameters, which left
core: &CoreSDK present; the gate rightly passed and the mutation was
discarded as non-discriminating.

Also: fake_registers::heal_cell, so a stopped write is not permanent and
a relay can mean something. Spec §33 and §27.
@cryptskii
cryptskii merged commit 498aa2c into main Sep 21, 2026
24 checks passed
@cryptskii
cryptskii deleted the fix/sofi-relay-is-party-neutral branch September 21, 2026 12:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant