You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix: fail closed on contract allowlist and mark records failed on Horizon rejection (#117)
Closes#117
Addresses the audit gaps on the secured submit endpoint: the per-type
contract check no longer degrades to function-name-only matching when the
contract ID is unset or unextractable, and persisted records are marked
failed when Horizon rejects the transaction instead of lingering as stale
pending rows. Also resolves the committed merge-conflict markers in the
progress tracker.
🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
Copy file name to clipboardExpand all lines: context/progress-tracker.md
+60-7Lines changed: 60 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -6,6 +6,66 @@ pure chore/docs commits). Direct pushes to main must also be logged here.
6
6
7
7
---
8
8
9
+
## 2026-08-27
10
+
11
+
- Closed the audit gaps on `POST /transactions/submit` (#117):
12
+
-**Fail-closed contract allowlist** — the contract ID for the declared
13
+
type must be configured and the XDR must target it. Function-name-only
14
+
matching was removed: an unset contract ID now rejects with
15
+
`TRANSACTION_CONTRACT_NOT_CONFIGURED`, and an invocation whose target
16
+
contract cannot be determined from the XDR rejects with
17
+
`TRANSACTION_TYPE_MISMATCH` instead of silently skipping the check.
18
+
-**No stale pending rows on submission failure** — when Horizon rejects
19
+
the transaction (or submission fails unexpectedly), the persisted record
20
+
is marked `failed` with the mapped error message and `completed_at`, so
21
+
the row no longer lingers as `pending` attributable to the submitting
22
+
wallet. Transient network unavailability (503) leaves the row `pending`
23
+
for the status checker to reconcile, since the transaction may still be
24
+
in flight.
25
+
- Resolved the committed merge-conflict markers in this file (stale
26
+
StepFi-Contracts content from the wrong repo removed; StepFi-API history
27
+
retained).
28
+
29
+
## 2026-08-26
30
+
31
+
- Fixed registration race conditions in `AuthService.register()` by eliminating application-side pre-checks (`findByWallet`, `checkUsernameExists`) and relying directly on DB-level UNIQUE constraints (`users.wallet_address`, `users.username`).
32
+
- Added idempotent migration `20260826130000_ensure_users_unique_constraints.sql` to ensure unique indexes exist on `users.wallet_address` and `users.username`.
33
+
- Updated `UsersRepository.createProfile()` to catch PostgreSQL unique constraint violation error `23505` and map to structured 409 `ConflictException` (`AUTH_WALLET_EXISTS`, `AUTH_USERNAME_TAKEN`).
34
+
- Added cleanup handlers (`deleteAvatar`, `deleteUserById`) in `AuthService.register()` and `UsersRepository` to ensure failed registrations do not leave orphaned avatar files or partial user records.
35
+
36
+
## 2026-08-25
37
+
38
+
- Secured `POST /transactions/submit` (#117):
39
+
-**Source binding** — the authenticated wallet must be the transaction
40
+
source account (or the inner source for fee-bump transactions), or must
41
+
appear as an authorized address in the Soroban invocation auth. Third-party
42
+
XDR where the wallet is neither source nor authorizer is rejected with
43
+
`TRANSACTION_SOURCE_MISMATCH`. (Deposit/withdraw/repay/vendor XDRs built
44
+
by this API use a random source account and authorize via Soroban auth, so
45
+
the auth check keeps those flows working.)
46
+
-**Operation allowlist per type** — every operation must be a Soroban
47
+
`invokeHostFunction` whose function name matches the declared type
@@ -27,13 +87,6 @@ pure chore/docs commits). Direct pushes to main must also be logged here.
27
87
event, blocked-user denial within TTL bound, cache expiry re-query,
28
88
cleanup job deletes-only-expired.
29
89
30
-
## 2026-08-26
31
-
32
-
- Fixed registration race conditions in `AuthService.register()` by eliminating application-side pre-checks (`findByWallet`, `checkUsernameExists`) and relying directly on DB-level UNIQUE constraints (`users.wallet_address`, `users.username`).
33
-
- Added idempotent migration `20260826130000_ensure_users_unique_constraints.sql` to ensure unique indexes exist on `users.wallet_address` and `users.username`.
34
-
- Updated `UsersRepository.createProfile()` to catch PostgreSQL unique constraint violation error `23505` and map to structured 409 `ConflictException` (`AUTH_WALLET_EXISTS`, `AUTH_USERNAME_TAKEN`).
35
-
- Added cleanup handlers (`deleteAvatar`, `deleteUserById`) in `AuthService.register()` and `UsersRepository` to ensure failed registrations do not leave orphaned avatar files or partial user records.
36
-
37
90
## 2026-07-23
38
91
39
92
- Added GitHub Actions health check workflow (`health-check.yml`) to ping the Render API every 6 hours to prevent the free tier instance from sleeping. Auto-creates or comments on issues with the `incident` label if the ping fails, preventing silent outages.
@ApiResponse({status: 500,description: 'Failed to persist the transaction record locally (TRANSACTION_PERSISTENCE_FAILED) or an unexpected Stellar submission failure (STELLAR_SUBMISSION_FAILED)'})
61
+
@ApiResponse({status: 503,description: 'Stellar network temporarily unavailable, or the contract for the declared type is not configured on the server (TRANSACTION_CONTRACT_NOT_CONFIGURED)'})
0 commit comments