Skip to content

feat: resolve issues #1260 #1261 #1262 #1264 — DB constraints, Stellar timeouts, audit logging, wallet auth UX - #1578

Merged
mimijuwonlo-commits merged 1 commit into
Split-Naira:mainfrom
Mirabel64:feat/mirabel64-1260-1261-1262-1264
Oct 22, 2026
Merged

mimijuwonlo-commits merged 1 commit into
Split-Naira:mainfrom
Mirabel64:feat/mirabel64-1260-1261-1262-1264

Conversation

@Mirabel64

Copy link
Copy Markdown
Contributor

Summary

Resolves all four issues assigned to Mirabel64. Changes span backend (DB, middleware, services) and frontend (component + i18n).


Issues closed

#1260 — DB uniqueness constraints for financial identities

Problem: Application-level uniqueness checks can race under concurrent requests.

Changes:

  • New migration 1760000000015-AddEmailUniquenessConstraint.ts: adds a partial unique index on users.email WHERE email IS NOT NULL, preventing duplicate emails at the DB level without affecting existing null-email rows.
  • middleware/error.ts: maps PostgreSQL SQLSTATE 23505 (unique violation) to a safe 409 DUPLICATE_RESOURCE response — never leaks DB internals.
  • 5 tests: 23505 → 409, wallet-address race, early application-level 409, unrelated errors fall through, response body clean.

#1261 — Transaction timeout coverage for external Stellar calls

Problem: External blockchain calls must not hold application resources indefinitely.

Changes:

  • New services/stellar-timeout.ts: exports classifyStellarFailure (timeout / permanent / transient), isStellarTimeoutFailure, and withStellarTimeoutGuard.
  • withStellarTimeoutGuard ensures DB query runners are rolled back and released when a Stellar call times out — never left open.
  • 23 tests: failure classification, guard semantics, DB-transaction-not-left-open scenario, executeWithRetry timeout via fake timers.

#1262 — Structured audit logging for privileged operations

Problem: Privileged actions need consistent, searchable audit events.

Changes:

  • entities/AuditLog.ts: add actor (wallet address) and outcome (success / failure / blocked) fields.
  • New migration 1760000000016-AddAuditLogActorOutcome.ts: adds columns and an index on actor.
  • middleware/audit-log.ts rewritten: extract actor from payload/JWT, redact known-sensitive keys (token, apiKey, secret, xdr, signature, …), derive consistent lowercase snake_case event names, record outcome.
  • 13 tests: unit tests for redactSensitivePayload and deriveEventName, HTTP integration tests for actor recording, redaction, and all three outcome values.

#1264 — Frontend wallet authentication challenge UX

Problem: The frontend needs a clear flow for signing an authentication challenge.

Changes:

  • New components/wallet/WalletAuthChallenge.tsx:
    • Explains why a signature is requested (identity proof, not payment).
    • Distinct callout: "This is not a payment. No tokens will leave your wallet.".
    • Expiry timer with near-expiry warning (≤30 s) and expired state.
    • Rejection handling (user cancelled in wallet).
    • Safe challenge refresh: never reuses expired nonce; resets state when new challenge prop arrives.
    • Full ARIA dialog semantics.
  • i18n keys added to messages/en.json and messages/fr.json (i18n check passes: 59 keys each).
  • 19 tests covering all acceptance criteria.

Test results

Suite Before After
Backend test files 37 failed / 84 passed 35 failed / 86 passed
Frontend test files 10 failed / 47 passed 10 failed / 47 passed (+1 new file)

No regressions. All pre-existing failures were present on main before this PR.

New passing tests: 41 backend (5 + 23 + 13) + 19 frontend = 60 new tests.

Closes #1260
Closes #1261
Closes #1262
Closes #1264

Split-Naira#1264 (Mirabel64)

Split-Naira#1260 — DB uniqueness constraints for financial identities
- Add partial unique index on users.email (WHERE email IS NOT NULL) via
  migration 1760000000015-AddEmailUniquenessConstraint.ts
- Map PostgreSQL SQLSTATE 23505 unique-violation to 409 DUPLICATE_RESOURCE
  in the error handler so concurrent registration races surface correctly
- Add 5 tests covering 23505 → 409 mapping, early 409 on duplicate wallet,
  and safe non-leak of DB internals in the error response

Split-Naira#1261 — Transaction timeout coverage for external Stellar calls
- Add services/stellar-timeout.ts with classifyStellarFailure (timeout /
  permanent / transient), isStellarTimeoutFailure, and withStellarTimeoutGuard
- withStellarTimeoutGuard ensures DB transactions are rolled back and
  released when a Stellar call times out, never left open
- Add 23 tests covering all classification categories, guard re-throw
  semantics, the DB-transaction-cleanup scenario, and executeWithRetry
  timeout behaviour with fake timers

Split-Naira#1262 — Structured audit logging for privileged operations
- Extend AuditLog entity with actor (wallet address) and outcome fields
- Add migration 1760000000016-AddAuditLogActorOutcome.ts
- Rewrite audit-log.ts middleware: extract actor from payload/JWT, redact
  known-sensitive keys (token, apiKey, secret, xdr, signature, …),
  derive consistent lowercase snake_case event names, record outcome as
  success / failure / blocked
- Export redactSensitivePayload and deriveEventName for unit testing
- Add 13 tests (unit + HTTP integration) covering redaction, event names,
  actor recording, and all three outcome values

Split-Naira#1264 — Frontend wallet authentication challenge UX
- Add WalletAuthChallenge component with: explanation that this is NOT a
  payment, distinction callout, expiry timer with near-expiry warning,
  rejection handling (user cancelled), safe challenge refresh that never
  reuses expired nonces, success state, ARIA dialog semantics
- Add i18n keys to en.json and fr.json (59 keys each, i18n check passes)
- Add 19 tests covering all acceptance criteria

Closes Split-Naira#1260
Closes Split-Naira#1261
Closes Split-Naira#1262
Closes Split-Naira#1264
@drips-wave

drips-wave Bot commented Oct 22, 2026

Copy link
Copy Markdown

@Mirabel64 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

for (const [key, value] of Object.entries(payload)) {
// Check the direct key
if (REDACTED_KEYS.has(key.toLowerCase())) {
redacted[key] = "[REDACTED]";
redactedNested[nk] = nv;
}
}
redacted[key] = anyRedacted ? redactedNested : value;
continue;
}

redacted[key] = value;
]);

function isRedactedKey(key: string): boolean {
return REDACTED_KEYS.has(key.toLowerCase().replace(/[-_]/g, "").replace("secret", "secret"));
@mimijuwonlo-commits
mimijuwonlo-commits merged commit 9f590ee into Split-Naira:main Oct 22, 2026
8 of 16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

3 participants