The engine
Not a single irreversible transfer. Both products, delivery escrow and compliance bonds, run on the same core engine: funds lock at authorization into a neutral pending account, then either release to the payee on a verified claim or return to the payer on a cancellation.
every transition → a distinct, auditable snapshot
Architecture-first, rail-agnostic
A payment is an immutable record that moves through a defined lifecycle of states, never a single irreversible transfer that can't be reasoned about after the fact.
Funds lock at authorization into a neutral pending account. They belong to neither party until terms are met, then move on a verified event.
Immediate payment versus held-in-escrow is selected per counterparty, not hardcoded. A trusted supplier and an unknown new hauler transact through the same system under different rules.
Claims and cancellations are events submitted by authorized parties. An inspector, terminal operator, or safety officer triggers an outcome within their authority, the payment layer never evaluates correctness itself.
Concurrency is handled with per-transaction row locking. A claim and a cancellation racing toward the same load resolve safely to exactly one outcome, never both.
The settlement layer records the delivery-confirmation reference without adjudicating it, keeping a clear line between what the system enforces and what an authorized inspector attests.
The model
A hold is created in the pending state. The mode, escrow, immediate, or bond, is resolved from the counterparty's policy, not baked into the call site.
const hold = await sentinel.holds.create({ load: "0x8d90", payer: buyer.id, payee: refiner.id, mode: policyFor(buyer), // per-counterparty terms: ["on_time", "full_qty", "on_spec"] }) // hold.state === "pending"
An authorized party submits a claim (release) or a cancellation (refund). The engine records the reference and transitions the record; it never judges whether the attestation is correct.
// release, submitted by an inspector await sentinel.events.claim(hold.id, { by: inspector.id, ref: "terminal-3/att-5521" }) // refund, submitted on timeout / dispute await sentinel.events.cancel(hold.id, { by: "reconciler", reason: "late" })
If a claim and a cancellation arrive at once, per-transaction row locking serializes them. The first to commit wins the transition; the second sees a settled record and is rejected cleanly.
Why it matters
Sentinel takes the silent assumptions of fuel logistics and attaches money and verification to them. Counterparties who perform well get paid faster; the ones who don't are caught before the funds move. For a refiner whose investment case rests on dependable feedstock in and product out, that's the difference between a promise and a guarantee.
Rail-agnostic, architecture-first, and modeled around the way fuel logistics actually moves. Start building against the Sentinel engine.