Skip to content

refactor(auction): typed refusals across the tier contract - #411

Closed
Mathih13 wants to merge 4 commits into
fix/auction-release-listing-holdfrom
feat/auction-typed-refusals
Closed

Mathih13 wants to merge 4 commits into
fix/auction-release-listing-holdfrom
feat/auction-typed-refusals

Conversation

@Mathih13

@Mathih13 Mathih13 commented Sep 3, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #409 (fix/auction-release-listing-hold). Merge that first; this PR's base is that branch.

The Module refuses an Auction Durable Request with a Result<(), String>, because SpacetimeDB reducers return strings. The Module tagged those strings as [AUCTION_DATABASE] detail and the Gateway searched the rendered error text for the tag. Any failure without a tag, including a 10 second reducer timeout, fell through that search and reached the client as a gameplay refusal.

One shared AuctionRefusal enum in lyracore-shared now defines the contract. Each variant has a stable tag (auction:item_not_found, auction:not_enough_money, auction:invalid_terms, auction:database) with as_tag and parse_tag. The Module listing and bid cores return the enum; the reducer edge sends only the tag and keeps the human detail in the Module log. The Gateway checks ReducerCallError first and parses the tag only from a reducer the Module rejected. A timeout, transport failure, or SDK failure stays an error with an unknown outcome and ends the session, the same as the loot handler. Every substring match on auction text is gone, including the handler text classifier.

Client mapping: ItemNotFound becomes ErrItemNotFound, NotEnoughMoney becomes ErrNotEnoughMoney, and InvalidTerms plus Database become ErrDatabase because the vanilla client has no invalid-terms result. The same mapping serves Started and BidPlaced.

The reviewed Realm-core refund protocol from #409 is merged into this branch without rewriting history. Its zero-id refund receipt is also represented as InvalidTerms at the reducer edge and cannot become a successful Auction replay.

Verification:

  • Every shared refusal tag round-trips.
  • Module tests assert on the enum.
  • Gateway handler tests drive every variant to its client result and prove a timeout is not answered as a refusal.
  • The full combined stack passed 1,464 Module tests, 1,186 Gateway unit tests, 4 provisioning tests, 110 schema-parity tests, and 149 shared-crate tests.

This shape is the template for social, trainer, and item refusals.

Written by Claude Fable 5.1 through Claude Code. Review fixes by GPT-5.6 through the Codex harness in T3 Code.

Mathih13 and others added 3 commits September 3, 2026 19:19
The module tagged auction refusals as bracketed strings and the gateway
matched substrings of rendered error text. A reducer timeout or any
unrelated failure fell through that match and reached the client as a
gameplay refusal.

One shared AuctionRefusal enum now crosses the reducer edge as a tag.
The module's listing and bid cores return it directly; the gateway
classifies on ReducerCallError first and parses the tag only from a
rejected reducer, so a timeout ends the session instead of posing as a
refusal.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Mathih13
Mathih13 deleted the branch fix/auction-release-listing-hold September 3, 2026 20:27
@Mathih13 Mathih13 closed this Sep 3, 2026
@Mathih13
Mathih13 deleted the feat/auction-typed-refusals branch September 3, 2026 20:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant