Skip to content

[RAI-2943] Bound the orchestrator-approve receipt wait and return the tx hash - #454

Closed
ueco-jb wants to merge 4 commits into
feature/rai-2933-add-breakglass-vers-to-the-issuance-clientfrom
feature/rai-2943-bound-the-orchestrator-approve-receipt-wait-and-return-the
Closed

ueco-jb wants to merge 4 commits into
feature/rai-2933-add-breakglass-vers-to-the-issuance-clientfrom
feature/rai-2943-bound-the-orchestrator-approve-receipt-wait-and-return-the

Conversation

@ueco-jb

@ueco-jb ueco-jb commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Bounds capital approve-orchestrator to one 18-second request deadline and returns the signed transaction hash when confirmation is still pending. This is part 3 of 5; #456 makes live external burn-excess safe for the poller. RAI-2943

Live effect: the route returns 202 with a transaction hash, 503 before broadcast, or 422 for a proven refusal instead of hanging · Risk: medium (money path and wallet signing; a sent approval is on-chain, but the route remains operator-triggered) · Blocks: #456

Decisions

  • One deadline covers the wallet lock, signing, broadcast, receipt, and allowance re-read. This keeps the bot's answer inside the load balancer's request window. src/tokenized_asset/orchestrator_ops.rs
  • The bot fills and signs before broadcast, so it knows the hash before the result can become uncertain. A signature that finishes after the deadline is not sent. src/tokenized_asset/orchestrator_ops.rs
  • A node refusal returns 422, not 502. The client reserves 502 for outcomes that may have reached the node. src/vault/onboarding.rs

Risks

  • A pending approval keeps its nonce after the wallet lock is released. Later mints and burns can wait until it mines or an operator replaces it.
  • An RPC node that lags can miss the pending hash before the deadline. Existing nonce recovery handles the next transaction if both use one nonce.

Proof

  • Rainix test and static passed. Regression tests cover an unmined approval, a refused broadcast, a late signature, and each pre-broadcast deadline.
  • Lock tests prove that approval holds the service wallet lock and checks signer intents only after it acquires that lock.
  • Not verified: a live Turnkey approval and a transport failure that happens after the node accepts the transaction.

Rollout

  1. Run the staging approval and branch on outcome, not only the exit code. Look up every 202 hash before retrying.
  2. Rollback: revert the route. A transaction already sent remains on-chain and must still be reconciled by hash.

@linear-code

linear-code Bot commented Oct 6, 2026

Copy link
Copy Markdown

RAI-2943

ueco-jb commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor Author

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more


How to use the Graphite Merge Queue

Add the label add-to-gt-merge-queue to this PR to add it to the merge queue.

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

This stack of pull requests is managed by Graphite. Learn more about stacking.

@ueco-jb ueco-jb changed the title Bound the orchestrator approval's receipt wait and answer 202 with its hash issuance: bound the orchestrator-approve receipt wait and return its tx hash Oct 6, 2026
@ueco-jb ueco-jb self-assigned this Oct 6, 2026
@ueco-jb
ueco-jb force-pushed the feature/rai-2943-bound-the-orchestrator-approve-receipt-wait-and-return-the branch 2 times, most recently from 938e8b8 to 1258b55 Compare October 7, 2026 10:09
@ueco-jb
ueco-jb force-pushed the feature/rai-2933-add-breakglass-vers-to-the-issuance-client branch from b8a5c0b to 0f81f67 Compare October 7, 2026 11:22
@ueco-jb
ueco-jb force-pushed the feature/rai-2943-bound-the-orchestrator-approve-receipt-wait-and-return-the branch from 3a0c4b3 to 83d5bed Compare October 7, 2026 11:22
@ueco-jb
ueco-jb marked this pull request as ready for review October 7, 2026 11:22

ueco-jb commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

@rain-marvin review

@rain-marvin

rain-marvin Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

🔎 Reviewing 83d5bed, started by @ueco-jb. The review will appear here when it's done.

@rain-marvin rain-marvin Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR puts a deadline on capital approve-orchestrator. The route signs the approval, broadcasts it, and waits for its receipt only until the deadline. When the receipt does not come in time, the route answers 202 submitted_unconfirmed with the transaction hash. Before this change the request could hang until a gateway cut it off, and the operator got no hash. The wallet lock is now released at the deadline. A node that refuses the broadcast gives a 422. A failure before broadcast gives a 503. The offline issuer approve-orchestrator uses a 300 s deadline and prints the hash. SPEC, the runbook and the ops-client text are updated to match.

Overall the change is sound. The deadline covers each step: the wallet lock, the fill and sign, the broadcast, the receipt wait and the allowance re-read. The bot does not broadcast a transaction that it signed after the deadline. The concurrency and the lock handling look correct. The mapping to HTTP status codes is complete. No finding blocks the merge. The main point: the 422 "refused" answer is a little too sure of itself. Some broadcast errors do not prove that the node refused the transaction, and in those cases the operator gets a 422 without the hash. Two smaller points concern log assertions in the new tests, and a single RPC error that ends the receipt wait early.

claude-opus-5-5 · high · 15 min

Comment thread src/vault/onboarding.rs
Comment thread src/vault/onboarding.rs Outdated
Comment thread src/vault/onboarding.rs
…y failed confirmation reads until the deadline

ueco-jb commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Team
  • Run ID: 3542c301-1bc4-48cf-8034-9b7bb0eb195e
📥 Commits

Reviewing files that changed from the base of the PR and between 0f81f67 and 397e13e.

📒 Files selected for processing (7)
  • SPEC.md
  • crates/ops-client/src/transport.rs
  • docs/runbooks/orchestrator-onboarding.md
  • src/tokenized_asset/cli.rs
  • src/tokenized_asset/orchestrator_ops.rs
  • src/vault/onboarding.rs
  • src/vault/service.rs

Included review availability: This review used your included allowance. 4 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 6 reviews per hour.


Walkthrough

Approval processing now uses deadlines for offline CLI and IAP requests. It distinguishes approvals that are confirmed, already unlimited, submitted but unconfirmed, or definitively refused. The IAP route applies an 18-second deadline and returns separate HTTP outcomes. The CLI waits up to five minutes and reports the transaction hash if confirmation is incomplete. Tests cover deadline handling, broadcast classification, confirmation retries, and route response mapping. Documentation describes operator actions for unconfirmed transactions.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to 397e1

The change bounds the approval route to an 18-second deadline and returns the transaction hash when an approval is submitted but unconfirmed. No concrete merge-blocking issue is identified. Live-chain validation through Turnkey has not been run.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 44 functions across 5 files. (2 skipped: … Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the main changes: limiting the orchestrator approval receipt wait and returning the transaction hash.
Description check ✅ Passed The description directly explains the 18-second deadline, response outcomes, transaction-hash handling, risks, tests, and rollout considerations for the changeset.
Full details: Docstring Coverage

Explanation

Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 44 functions across 5 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@findolor findolor left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed locally against the stack parent with two independent Codex reviewers. No blocking findings. Workspace tests, Clippy, and formatting passed.

@findolor

findolor commented Oct 7, 2026

Copy link
Copy Markdown
Collaborator

Nonblocking nit: the retry guidance in src/tokenized_asset/cli.rs:912, docs/runbooks/orchestrator-onboarding.md:232-233, and SPEC says an unknown transaction hash proves nothing was sent and a retry is safe. A broadcast can succeed while the RPC/explorer lookup still cannot see it, so a retry could queue another approval and incur extra gas.

Suggested wording: "A missing hash is inconclusive; reconcile the wallet nonce and allowance before retrying." This is an operator-guidance correction, not a merge blocker.

@ueco-jb ueco-jb changed the title issuance: bound the orchestrator-approve receipt wait and return its tx hash [RAI-2943] Bound the orchestrator-approve receipt wait and return its tx hash Oct 7, 2026
@ueco-jb ueco-jb changed the title [RAI-2943] Bound the orchestrator-approve receipt wait and return its tx hash fix: bound orchestrator approval wait Oct 8, 2026

ueco-jb commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

@rain-marvin approve

@rain-marvin

rain-marvin Bot commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

🔎 Verifying that my findings from 397e13e are addressed at 397e13e, started by @ueco-jb. The review will appear here when it's done.

@rain-marvin rain-marvin Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR bounds the orchestrator approval wait during vault onboarding. The approval is broadcast and confirmed under a deadline. A 422 BroadcastRejected is returned only when the node proves it refused the bytes. Any other outcome goes to confirm by hash and answers 202 submitted_unconfirmed with the hash.

The head is still 397e13e, the commit my last review checked, so nothing changed since then. I checked the code again at that commit, and it agrees with what I confirmed in each thread.

Earlier findings:

  • 422 for any JSON-RPC error (src/vault/onboarding.rs, broadcast_approval): resolved. BroadcastRejected now comes only from Ok(Ok(None)) after is_pool_refusal. "Already known", other server errors, transport errors, and a lookup that fails or times out all return Ok(()). The checks reuse the service.rs predicates, and the SPEC bullets match.
  • Early SubmittedUnconfirmed on one transient error (confirm_approval): resolved. The receipt poll and the allowance re-read now retry at the poll interval until the outer deadline and keep the last error. PendingTransaction is removed, and the CLI message is now accurate. A mocked-node test covers one failed read of each kind.
  • Missing log assertions and coverage (refused-broadcast test): resolved. The test now runs under #[traced_test] and asserts the WARN with the hash. A table test covers real refusals, "already known", -32603, and a failed lookup. The deadline tests have no log line to assert because that path logs nothing. One branch is still untested and does not block: a pool refusal whose lookup finds the transaction.

Threads resolved by hand: none. I resolved all three threads after I confirmed the fixes.

No new changes to review and no open findings.

claude-opus-5-5 · high · 17 min

@ueco-jb ueco-jb changed the title fix: bound orchestrator approval wait [RAI-2943] Bound the orchestrator-approve receipt wait and return the tx hash Oct 8, 2026
@graphite-app

graphite-app Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Merge activity

  • Oct 9, 8:51 AM UTC: ueco-jb added this pull request to the Graphite merge queue.
  • Oct 9, 8:51 AM UTC: CI is running for this pull request on a draft pull request (#460) due to your merge queue CI optimization settings.
  • Oct 9, 8:52 AM UTC: Merged by the Graphite merge queue via draft PR: #460.

@graphite-app graphite-app Bot closed this Oct 9, 2026
@github-actions github-actions Bot added the externally-merged Graphite MQ merged this PR; Linear should treat the close as a merge label Oct 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

externally-merged Graphite MQ merged this PR; Linear should treat the close as a merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants