What a request actually becomes
A person says something in words. Six translations later it is a transaction on a chain, and each one narrows what is possible:
The narrowing is the product. Each stage is allowed to refuse, and a refusal is
recorded as carefully as an approval, because a refusal is evidence.
See Adapters for the vocabulary that second row is written in, and
Kernel for what the last two rows mean about whose money it is.
What runs, and what each part is trusted with
The parts worth knowing are the ones that hold something.
Around those sit the console and its server side, the tool server the model
talks to, a quoting service, a simulator that runs every non-bridge step before
it is broadcast, and the durable-execution engine holding the workflow
histories. One container is reachable from outside; everything else answers only
on the internal network.
The Go services are built from one image with a variable choosing which one
runs, so they share every compiled constant: adapter addresses, the intent
schema, the chain tables. That is why they are deployed together and never
singly: two of them on different builds derive account addresses two different
ways, and every group is then refused.
Why a forked mainnet, not a testnet
Testnets lack the dependencies this system needs: CCTP, lending markets, DEX depth. So the substrate is a fork pinned to a block: a run spends fork money and settles against real mainnet state, against the same contracts and the same liquidity that production would meet.Durable waiting, and the two things it buys
Stuck transactions are replaced, never re-sent. A transaction that does not mine within its window is replaced at a higher fee reusing its nonce, up to a bump limit, and then goes to a STUCK state for a human. Reusing the nonce is the whole point: a “retry” on a fresh nonce would leave the original still valid and still pending, both could confirm, and the recipient would be paid twice. Measured on a fork with mining disabled: four broadcasts, one nonce, exactly one winner. Retries cannot double-send, because three layers have to agree: the nonce lease is keyed on the task id so a retry rebuilds an identical transaction, the submission claim returns the original hash before any broadcast, and the node’s “already known” is treated as success.Amending a plan that already moved money
Step 1 lands, step 2 fails, somebody proposes a change, steps 2 and 3 run. That is a normal outcome, not an exception. Automatic retry is deliberately minimal: a fee bump for a stuck transaction, and a couple of attempts for a revert whose cause can clear by itself. Beyond that the system stops guessing and parks, because most real failures need a decision rather than another attempt at the same thing. An amendment may change the future and never the past. Every step in the execution log must reappear, unchanged, in order. Altering or dropping an executed step is refused; so is reusing its task id, and so is resubmitting the failed step unchanged. Who proposed it is recorded for attribution after the fact, not authorisation. An owner can be socially engineered and a model can be prompt-injected, so the validation is identical either way: nothing is trusted because of who sent it. Two details that prevent surprises at approval time:- Step ids are names, not positions. If they were indices, inserting a step during an amendment would silently repoint every later reference.
- Symbolic amounts resolve to actual, not requested. Step 1 asked for 1000 and delivered 997; step 2 gets 997. A diff reports which steps a human edited and which merely followed, because “you edited one step and three others moved” is the sentence that has to be said out loud.