Skip to content

fix(ri-exchange): direct execute bypasses the source-in-flight guard #1829

Closed

Description

@cristim

Found in the cold review of #1826 (the #1050 backend). The #1050 plan scoped this out; this issue tracks it.

Gap. The direct RI exchange execute path (internal/api/handler_ri_exchange.go:2013-2091) never calls the source-in-flight guard (refuseRIExchangeSourceInFlight, internal/config/store_postgres.go:3440-3461) that #1826 adds to the approve and AUTO reservations. A lost accept from a direct execute is recorded only in the direct-execution audit table, not as a processing ri_exchange_history row. So the guard doesn't work in either direction:

  • Direct after unknown: a direct execute can exchange a source RI that an approve or AUTO exchange holds in an unknown (processing) state.
  • Unknown after direct: a direct execute whose outcome is unknown never blocks a later approve or AUTO exchange of the same RI.

Repro. Leave an ri_exchange_history row processing on ri-1, then POST the direct execute endpoint with ri_ids: ["ri-1"]. The request goes to AWS with no refusal.

Suggested direction.

  • Run the direct path through the same guard, under the same advisory lock as the ceiling.
  • Make its unknown outcomes visible to the guard: either insert a processing history row, or have the guard also consult the direct-execution audit table.
  • Add tests for both directions.

Related low items from the same review. Rows whose source_ri_ids is NULL or empty skip the guard (store_postgres.go:3441), which only matters for legacy rows without source IDs. Two approvals of rows sharing an RI that both transition before either reserves can refuse each other: both fail, which is safe, and a retry works.

Activity

  1. cristim commented on Nov 6, 2026

    @cristim
    MemberAuthor

    Claimed by claude-darling: planning. Test-first: direct execute must refuse while a source RI is in flight, and the reverse direction too. Stacked on #1826's guard; local commits until #1826 merges and a platform slot frees.

  2. cristim commented on Nov 7, 2026

    @cristim
    MemberAuthor

    Claimed by claude-darling: PR #1838 is open (6 commits; plan, per-task and full-change reviews done). Follow-up for the resolve API: #1836.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions