Skip to content

feat: complete security, retry, proxy, and metrics fixes - #1

Open
Roseline-d wants to merge 236 commits into
mainfrom
fix/completed-security-and-observability-issues
Open

Roseline-d wants to merge 236 commits into
mainfrom
fix/completed-security-and-observability-issues

Conversation

@Roseline-d

@Roseline-d Roseline-d commented Aug 30, 2026 •

Copy link
Copy Markdown
Owner

Summary

This PR bundles the completed fixes for the linked security and reliability issues:

Changes

EF-CHAIN#272 persistent PIN lockout

  • Added persistent failed-attempt tracking and lockout state for user PIN verification.
  • Enforced active lock checks before payment confirmation.
  • Added lock reset and audit-friendly verification flow.

EF-CHAIN#273 queued WhatsApp retry worker

  • Registered the WhatsApp outbound retry processor.
  • Added transient Meta failure handling with bounded retry/dead-letter behavior.
  • Recorded notification state reliably for failed outbound sends.

EF-CHAIN#275 trusted proxy handling

  • Added explicit TRUST_PROXY configuration with safe defaults.
  • Sanitized forwarded headers for untrusted requests.
  • Ensured audit and rate-limit IP attribution uses trusted proxy-aware client IPs.

EF-CHAIN#276 route metric labels and cardinality

  • Captured stable mounted route templates after matching.
  • Normalized method, status, and route labels.
  • Bounded unknown routes to unmatched to prevent cardinality growth.
  • Added regression tests covering parameterized, nested, health, metrics, webhook, and unknown routes.

Validation

  • Focused tests for PIN lockout, retry handling, trusted proxy validation, and metric cardinality were added and validated.

Closes EF-CHAIN#272
Closes EF-CHAIN#273
Closes EF-CHAIN#275
Closes EF-CHAIN#276

ezedike-evan and others added 30 commits July 25, 2026 09:15
Backend lint has been red on main since the chat-sim gate landed:
app.js requires requireChatSimEnabled but gates /api/sim on
config.features.chatSim directly, and the middleware's test file
imports beforeEach/afterEach it never uses.
CI runs npm ci then npm test and never generates the Prisma client, so
any test that transitively requires @prisma/client dies with
"Cannot find module '.prisma/client/default'". A postinstall hook is
Prisma's documented fix and also covers fresh local clones.
npm ci never generated the client, so any test requiring a module that
imports src/common/prisma.js failed with "Cannot find module
'.prisma/client/default'". prisma.config.ts resolves DATABASE_URL, so
the step passes a throwaway URL — no database is contacted.
Co-authored-by: Roseline-d <Roseline-d@users.noreply.github.com>
Co-authored-by: That guy <120946193+ezedike-evan@users.noreply.github.com>
Co-authored-by: Roseline-d <Roseline-d@users.noreply.github.com>
Co-authored-by: That guy <120946193+ezedike-evan@users.noreply.github.com>
* feat: add phone number recipient resolution

- Add fourth precedence level: phone numbers resolve to wallet addresses
- Phone-shaped input triggers createOrGetWallet for wallet lookup/creation
- Maintains existing precedence: saved contacts > phone numbers > raw addresses
- Inject walletService into recipientResolver for wallet operations
- Add comprehensive test coverage: new user, existing user, and precedence cases
- All existing tests remain green

Done when:
- Phone-shaped recipient → wallet created/fetched, its address used as destination ✓
- All existing resolver behavior unchanged ✓
- New tests for new-number, existing-number, and precedence cases ✓

* feat: wire poller into app lifecycle with startup and shutdown hooks

* fix: inject walletService into assistant service, resolve linter warnings, update docs

---------

Co-authored-by: Goldy <iyiegbuogechukwu@gmail.com>
…F-CHAIN#66)

Replace the adapted code of conduct with the full verbatim text of
Contributor Covenant 2.1. The placeholder [INSERT CONTACT METHOD] is
filled with the maintainer's GitHub profile (https://github.com/Gozirimdev)
as the real contact method for conduct reports.

CONTRIBUTING.md already links to CODE_OF_CONDUCT.md — no change needed there.
…over-eager phone match

EF-CHAIN#88 landed pasted pseudo-code into requestConfirmation, leaving an unclosed
createAssistantService() wrapper and `await` outside an async function. eslint
and `node --test` both fail on main as a result.

- assistant.service.js: drop the pasted block and the stray wrapper, restore
  the address-validity guard; keep the walletService injection EF-CHAIN#88 intended.
- recipientResolver.js: gate the phone branch on an actual phone shape.
  isValidPhoneNumber() only checks "longer than 5 chars", so every G... address
  and most contact names were routed through createOrGetWallet, breaking the
  send-to-address flow (webhook integration tests hit an unmocked wallet path).
- recipientResolver.test.js: walletServiceMock was an object but called as a
  factory; make it a factory that accepts pre-existing wallets.
- server.js: restore the drain backstop EF-CHAIN#88 deleted, fix the stray indentation.
Block Friendbot funding when STELLAR_NETWORK is not testnet.
Reject startup if the Testnet USDC issuer is configured on mainnet.
Document mainnet environment variables, rollback, and operational notes.
Add automated tests for both success and failure paths.

Co-authored-by: That guy <120946193+ezedike-evan@users.noreply.github.com>
…#138)

Co-authored-by: Stellar Intel Dev <dev@stellar-intel.dev>
Co-authored-by: That guy <120946193+ezedike-evan@users.noreply.github.com>
…F-CHAIN#87)

- Add paymentCursor column to Wallet (migration 20260724000000)
- New jobs/deposits.jobs.js: setInterval poller over all Stellar wallets
  - Calls Horizon GET /accounts/{pk}/payments?cursor={cursor}&order=asc
  - Inbound-only filter (type=payment, to===publicKey)
  - Writes DB cursor before sending notification (rule 5)
  - Null-cursor first poll: initialise cursor, no notification (rule 6)
  - Per-wallet errors logged and skipped; loop never stalls (rule 4)
  - formatDepositMessage: 'You received 20 USDC (~₦31,000).'
  - All deps injected for testability; timer unref'd for clean shutdown
- Wire startDepositPoller() into jobs/index.js
- 13 unit tests (node:test, no network/DB) covering all four spec rules
  plus cursor-before-notify ordering and formatDepositMessage edge cases

Closes EF-CHAIN#31

Co-authored-by: That guy <120946193+ezedike-evan@users.noreply.github.com>
…mport

EF-CHAIN#87 merged with the artefacts of its merges from main: EF-CHAIN#86 had already added
`paymentCursor` to `model Wallet` and the 20260724163000_add_wallet_payment_cursor
migration, so main ended up with the field declared twice (prisma generate:
'Field "paymentCursor" is already defined on model "Wallet"') and a second
migration re-adding an existing column.

Keep EF-CHAIN#86's field and migration; drop EF-CHAIN#87's copies. Also drop the unused
startDepositPoller import from deposits.jobs.test.js (no-unused-vars).
…liation, auth & admin RBAC (EF-CHAIN#134)

- Add missing migration for User.welcomeSentAt to eliminate schema drift and configure CI Postgres service for migration validation (closes EF-CHAIN#89)
- Implement user authentication, SEP-10 support guidelines & admin RBAC capabilities (closes EF-CHAIN#90, closes EF-CHAIN#96)
- Implement payment settlement reconciler to check stale transactions against Horizon (closes EF-CHAIN#95)

Co-authored-by: ayomideadeniran <ayomideadeniran@users.noreply.github.com>
Co-authored-by: That guy <120946193+ezedike-evan@users.noreply.github.com>
…s config

EF-CHAIN#134 added the migration-validation step as `npx prisma migrate deploy
--schema=apps/api/prisma/schema.prisma` from the repo root. --schema points at
the schema, but datasource.url lives in apps/api/prisma.config.ts, which prisma
only discovers from that directory — so the step failed with "The
datasource.url property is required in your Prisma config file when using
prisma migrate deploy". Use the workspace script instead.
…ability (EF-CHAIN#135) (EF-CHAIN#139)

* feat: resolve issues EF-CHAIN#91, EF-CHAIN#92, EF-CHAIN#93, and EF-CHAIN#94

- Issue EF-CHAIN#91: Add versioned encryption headers (v1:), key rotation helper, and backward-compatibility for legacy ciphertexts in crypto.service. Update SECURITY.md.
- Issue EF-CHAIN#92: Require PIN_PEPPER in production in validateEnv.js and test coverage.
- Issue EF-CHAIN#93: Enforce atomic transaction limit checks using transaction contexts in compliance.service and payment.orchestrator.
- Issue EF-CHAIN#94: Use stable WhatsApp message IDs as queue job IDs in webhook controller for durable deduplicated job enqueuing. Fix test mocks.

* fix: reconcile EF-CHAIN#135 with main — mock factory, unused destructure, lockfile

Merge fallout from landing EF-CHAIN#135 on top of EF-CHAIN#138 and 3d01656:

- recipientResolver.test.js: main defines walletServiceMock as a factory;
  this branch changed the call sites to pass the object. Call the factory.
- compliance.service.js: keep main's screenSanctions helpers and this
  branch's tx = prisma parameter (EF-CHAIN#93 reads the 24h window inside the
  transaction).
- payment.orchestrator.js: drop the unused `compliance` destructure
  (no-unused-vars).
- package-lock.json: restore main's version — the only change was
  @types/react-dom flipping dev -> devOptional, install churn.

---------

Co-authored-by: adeniran19-maker <adeniran19-maker@users.noreply.github.com>
Co-authored-by: carlos cienfuegos <cienfuegossilvacarlos@gmail.com>
…e-97-production-kyc-lifecycle

integrate production Smile ID KYC lifecycle
…e-101-production-postgresql

provision and validate production PostgreSQL
…e-102-separate-background-workers

deploy background workers separately
…e-compliance-enforcement

fix: enforce payment compliance once
Gozirimdev and others added 30 commits August 29, 2026 23:05
feat(frontend): add recoverable route error boundaries
…6-209-288-289

feat: harden funding, validation, PIN security, and erasure retention
…-279-282-security-reliability

Fix admin data exposure and payment reliability safeguards
…tency-retention-health

feat: per-category messaging consent, callback idempotency, retention sweep and dependency health
…pagination

feat: cursor pagination, filters, and UI refresh for KYC and audit logs
…let limits, and add statement exports

- Fix EF-CHAIN#195: Coordinate Stellar account sequences across concurrent payments
  - Introduce withAccountLock per-account submission queue to serialize transaction preparation and Horizon submissions per source key.
  - Safely reconcile uncertain submissions and bad-sequence failures by checking transaction hashes against Horizon before retrying or rebuilding envelopes.

- Fix EF-CHAIN#307: Standardize KYC decisioning and risk-score evaluations across all pathways
  - Define unified KYC decision lifecycle (not_started, pending, review, approved, rejected, escalated) and risk score classification thresholds (low, medium, high, critical).
  - Centralize state updates via syncKycAndRiskState to ensure User and KycProfile states remain consistent across API, admin, and background flows.

- Fix EF-CHAIN#309: Enforce wallet activity limits based on verified customer tier and risk state
  - Define tiered single, daily, and monthly limits for send, receive, and withdraw operations.
  - Adjust effective limits dynamically based on risk-score penalties and session trust, rejecting violations before funds move with audit log emission.

- Fix EF-CHAIN#308: Add customer-facing balance and transaction export for account statements
  - Add statement.service.js with structured statement generation supporting CSV, PDF, and JSON formats.
  - Include full ledger history, metadata, live on-chain balances, and fee breakdowns, accessible via customer wallet and admin endpoints with audit trails.

Closes EF-CHAIN#195
Closes EF-CHAIN#307
Closes EF-CHAIN#308
Closes EF-CHAIN#309
…s-statements

feat: coordinate Stellar sequences, standardize KYC/risk, enforce wal…
…-287

feat(api): network-scoped wallets, validated network config, durable outbox and webhook inbox
…rdize-receipt-confirmation-ux

feat(receipt): standardize receipt generation and confirmation UX across channels
…-wallet-recovery-key-rotation

feat(wallet): harden wallet recovery and escrow key rotation for customer funds
…backlog-service-alerting

feat(observability): add service-level alerting for failed background jobs and queue backlogs
…er-identity-migration-tooling

feat(migration): customer identity migration tooling and rollback plan for legacy records
Fix payment lifecycle cancellation and reversal states
fix: Create incident runbooks and exercise them
…t-state-transitions

feat(EF-CHAIN#200): enforce payment-state transitions in database with Compar…
…ar-wave-issues-325-328

feat: Stellar Wave issues EF-CHAIN#325-328 — deployment manifests, secret rotation, wallet summaries, recoverable errors
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet