Skip to content

fix(contract-service): remove use-case status checks that mask domain auth checks#68

Merged
RedAvocado22 merged 1 commit into
mainfrom
fix/remove-duplicate-usecase-guards
Jul 6, 2026
Merged

fix(contract-service): remove use-case status checks that mask domain auth checks#68
RedAvocado22 merged 1 commit into
mainfrom
fix/remove-duplicate-usecase-guards

Conversation

@RedAvocado22

Copy link
Copy Markdown
Owner

No tracked GitHub issue — found and fixed directly while chasing down 23-seller-dispute-invalid's failure in the Bruno e2e suite.

Problem

SignContractUseCase/CancelContractUseCase/ConfirmDeliveryUseCase/DisputeContractUseCase each duplicated a status guard that the corresponding domain method (Contract.sign/cancel/confirmDelivery/dispute) already performs — but in the wrong order relative to the domain: the use case checks status first, the domain checks auth first then status.

This is invisible in the common case (caller is wrong about only one of {auth, status} at a time). It surfaces when both are wrong at once: 23-seller-dispute-invalid expected 403 (seller isn't the buyer) but got 400, because by the time the request landed, an async RabbitMQ consumer had already moved the contract from DELIVERED to SETTLED — the use case's own status check fired and threw 400 before ever reaching the domain's auth check.

Same root cause as the auth-check duplication fixed in PR #40 (domain as SSOT) — that pass cleaned up the auth side but left this status-check duplication in place.

Fix

Removed the redundant use-case-level guards (including SignContractUseCase's duplicate-signatory check, which the domain also already performs), so the domain's own check order — auth first, then status — is what actually runs.

Test plan

  • Full contract-service test suite passes
  • scripts/run-e2e.sh run twice back to back: 47/47 requests, 76/76 tests, fully green (previously 46/47, with 23-seller-dispute-invalid as the one known failure)

… auth checks

Sign/Cancel/ConfirmDelivery/Dispute use cases each duplicated a status guard
that the domain method (Contract.sign/cancel/confirmDelivery/dispute) already
performs, but in the wrong order relative to the domain: the use case checked
status first, while the domain checks auth first, then status.

Normally this is invisible because the caller is usually wrong about only one
of {auth, status} at a time. It surfaces when both are wrong simultaneously:
23-seller-dispute-invalid in the Bruno e2e suite expected 403 (seller isn't
the buyer) but got 400, because by the time the request landed, an async
consumer had already moved the contract from DELIVERED to SETTLED — so the
use case's own status check fired and threw 400 before ever reaching the
domain's auth check.

Same root cause as the auth-check duplication fixed in PR #40 (domain as
single source of truth) — that pass cleaned up the auth side but left the
status-check duplication in place. Removed the redundant use-case guards
(including SignContractUseCase's duplicate-signatory check, which the domain
also already performs) so the domain's check order is what actually runs.

Verified: full contract-service test suite passes, and the Bruno e2e suite
(scripts/run-e2e.sh) now passes 47/47 requests / 76/76 tests — previously
46/47 with 23-seller-dispute-invalid as the one known failure. Run twice
back to back with identical results.
@RedAvocado22 RedAvocado22 merged commit 61199ac into main Jul 6, 2026
2 checks passed
@RedAvocado22 RedAvocado22 deleted the fix/remove-duplicate-usecase-guards branch July 6, 2026 11:19
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