Repository navigation
Conversation
Remove retired reward consumers and capital-action callers, use the shared gross return minimum, and align native Andon permissions and retained flows with the current SDK. Verify raw fallback for removed reward and reserve-creation wire values without blocking active attestation decoding.
…onds and settles The batch operator plugin's underwriter role bonds sysio.synd's envelope requests itself: it checks each statement against the outpost's record of the envelope, accepts the remainder, cranks sysio.synd, and approves and claims after the challenge window. A flow can now run its bonder as that daemon instead of pushing those actions. OperatorDaemonTool.planDaemonStart now starts an underwriter's daemon as well as a batch operator's. It dispatches on the operator's type, and a role's own inputs ride a StartDaemonOptions argument: the underwriter's exposure caps. The underwriter's arguments are the batch operator daemon's with --batch-underwriter-account and one --batch-underwriter-max-exposure per token in place of --batch-operator-account, so both roles build the shared part in one place. WireSyndicationTool.planAwaitRequestBonded waits until an envelope's request is fully bonded with a bond of the bonder's on it, and planAwaitRequestSettled until the request is APPROVED and the bonder's bonds on it are paid. Neither pushes anything. Their budgets come from the daemon's poll interval and the cluster's irreversibility budget. readIssuedEnvelope finds an envelope by its epoch and syndicated total, which outlive its release. SyndicationScenario.planUnderwriterStart materializes the bonder's underwriter identity (the account's key and the imported position's outpost keys) and starts its daemon. It fails when the flow is planned, instead of when the daemon starts, if the scenario reserved no ad-hoc port pair for the daemon or the cluster's signature provider is not KEY. planVerifyIssuedIntake verifies an intake while the daemon runs: the daemon can bond and release an envelope before a read sees it held. Constants.DEV_K1_KEY_PAIR is the development key as a WIRE key pair; the bios operator and the bonder's identity both use it.
…riter daemon The flow pushed every bond, crank, approval and claim itself. It now starts the underwriter daemon for its bonder where it used to push the first bond, after the checks that need unbonded state, and waits on what the daemon does. The daemon's exposure cap is the first request's covered amount, so it bonds the second request only once the first bond is paid back and the flow keeps its order: bond, release, settle, then the next request. The release checks poll for the daemon's crank, the claim check counts a stake the daemon has already placed on the next request as the bonder's, and the third intake no longer needs to be seen held.
valthon
force-pushed
the
fix/sysio-670-consumers
branch
from
October 10, 2026 22:44
f258cc5 to
e3d76da
Compare
valthon
added a commit
that referenced
this pull request
Oct 14, 2026
The flow proves the batch_operator_plugin underwriter role enforces its exposure cap and recovers once a bond is paid back. Every batch operator runs the role, but batchOperatorUnderwriting funds only batchop.a, with a cap of exactly the first request's coverage. It brings the cap-exhaustion case of the standalone-daemon change to flow-syndication-underwriting (wire-tools-ts #120) onto the operators' own nodes. flow-syndication-plugin-underwriting keeps the case of three funded operators racing. Setup sets the pair rules with a 240 s challenge window. After that the flow writes only what users do (syndications and the unlinked recipient's createlink); a unit test pins the list. Its Plan, pair rules and shared tail phases come from BatchOperatorUnderwritingSteps (createPlan, configOf, planUnlinkedIntake, planParkAndLink, planSettle). Its first-released check requires the held second envelope to have released nothing. It adds two checks of its own: - second-held-by-cap, last in ExhaustCap: polls the first bond until it reads paid, for at most the window plus two plugin passes. On every reading before that, taken between two unpaid readings of the first bond, the second request must be OPEN with nothing bonded and no bond row. The first bond must equal the cap, at least one held reading must exist, and the first bond row must not vanish before it reads paid. The Report row records the held-reading count, its wall-clock span and the first request's resolved_at at the paid reading. - second-bonded-after-recovery: the first request is APPROVED and its bond paid, and the funded operator's liquid LIQSOL plus its unpaid stake on the second request equals its funded balance from setup (bounty 0), the approved-and-returned check of #120. As a secondary check, the second request's bonded_at is no earlier than the first request's resolved_at. The shared Steps also assert: - every bond is the funded operator's, within the cap; - unfunded operators hold nothing throughout; - exact fees and exact custody; - approvals no earlier than the window, and every bond claimed; - the funded operator's credit returns, and every operator stays ACTIVE. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01PPcjf9SpvBzUMjiuGoKZt6
valthon
added a commit
that referenced
this pull request
Oct 15, 2026
Prove the batch_operator_plugin underwriter role enforces its exposure cap and recovers once a bond is paid back. Every batch operator runs the role, but batchOperatorUnderwriting funds only batchop.a, with a cap of exactly the first request's coverage. This brings the cap case of the standalone-daemon change in wire-tools-ts #120 onto operators' own nodes; the companion flow covers three funded operators racing. The first request has a 589 s challenge window, covering submission, one busy hop, governance finality, two active plugin passes and one observation gap. Later requests use 60 s windows. Timeout scaling raises ceilings without lengthening the on-chain windows. After setup, the flow configures later request governance and performs user writes; it never bonds, cranks, approves or claims on an underwriter's behalf. Start the second-intake observer before submitting the syndication, retaining its OPEN, zero-bonded snapshot through the first payment. Bracket ordinary observations with unpaid first-bond readings. When payment races discovery or reads, require request creation strictly before the first approval to establish the earlier held state, even if atomic accepts advance the second bond before its rows are read. The first bond must equal the cap and cannot disappear before payment. Record the held-reading count, span and first approval in the Report. The shared initial evidence lives in orchestration/outputs. After recovery, require the first request approved and its bond paid. The funded operator's liquid balance plus unpaid second-request stake must equal its original funding. Accept an already-paid second bond and reread liquid balance once if its claim races the snapshot. Require the second bond timestamp no earlier than the first approval. Custody persistence can lag releases, so first-release verification accounts for either no second release or its full release, with exact fees. Shared Steps check funded ownership, exposure caps, unfunded operators' empty holdings, exact custody, challenge-window approvals and claims, returned credit, ACTIVE operators and the parked recipient's one-time delivery. Controlled-clock tests cover delayed intake, payment races, missing ordering evidence and claim races. The Plan, pair rules and shared tail phases come from BatchOperatorUnderwritingSteps. Claude-Session: https://claude.ai/code/session_01PPcjf9SpvBzUMjiuGoKZt6 Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_019LgGtRheR6Hac9WHX739y3
Contributor
|
This PR is superseded by #127 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
flow-syndication-underwritingpushed every bond, crank, approval and claim itself. It now starts the batch operator plugin's underwriter role for its bonder and waits on what the daemon does, so the flow exercises the daemon against live outposts: each request is bonded only after the Solana outpost's own record of the envelope confirms it.Related PRs:
nodeopbuilt with it.cluster-tool
OperatorDaemonTool.planDaemonStartnow starts an underwriter's daemon as well as a batch operator's. It dispatches on the operator's type; a role's own inputs ride aStartDaemonOptionsargument, here the underwriter's exposure caps. The underwriter's arguments are the batch operator daemon's with--batch-underwriter-accountand one--batch-underwriter-max-exposureper token in place of--batch-operator-account; both roles build the shared part in one place.WireSyndicationTool.planAwaitRequestBondedwaits until an envelope's request is fully bonded with a bond of the bonder's on it.planAwaitRequestSettledwaits until the request is APPROVED and the bonder's bonds on it are paid. Neither pushes anything. Their budgets come from the daemon's poll interval and the cluster's irreversibility budget.WireSyndicationTool.readIssuedEnvelopefinds an envelope by its epoch and syndicated total, which outlive its release.SyndicationScenario.planUnderwriterStartmaterializes the bonder's underwriter identity (the account's key and the imported position's outpost keys) and starts its daemon. A scenario that plans it reserves the daemon's ports withadHocCount: SyndicationScenario.AdHocDaemonCount. Without that, or under a signature provider other thanKEY, planning fails at once rather than when the daemon starts.SyndicationScenario.planVerifyIssuedIntakeverifies an intake while the daemon runs. The daemon can bond and release an envelope before a read sees it held, so the envelope is found withreadIssuedEnvelope.Constants.DEV_K1_KEY_PAIRis the development key as a WIRE key pair; the bios operator and the bonder's identity both use it.flow-syndication-underwriting
The daemon starts where the flow used to push its first bond, after the checks that need unbonded state. Its exposure cap is the first request's covered amount, so it bonds the second request only once the first bond is paid back, and the flow keeps its order: bond, release, settle, then the next request. The release checks poll for the daemon's crank, the claim check counts a stake the daemon has already placed on the next request as the bonder's, and the third intake, which arrives with the daemon running, is no longer required to be seen held.
Notes