Skip to content

Release: develop -> main#3616

Open
github-actions[bot] wants to merge 17 commits intomainfrom
develop
Open

Release: develop -> main#3616
github-actions[bot] wants to merge 17 commits intomainfrom
develop

Conversation

@github-actions
Copy link
Copy Markdown

Automatic Release PR

This PR was automatically created after changes were pushed to develop.

Commits: 1 new commit(s)

Checklist

  • Review all changes
  • Verify CI passes
  • Approve and merge when ready for production

…e + IBAN) (#3615)

* feat: include BankTxReturn in compliance name search

* feat: include BankTxRepeat in compliance name search and apply to IBAN search
TaprootFreak and others added 15 commits April 23, 2026 13:35
Adds a PR check that fails when an existing migration file in
migration/ is modified, renamed or deleted. Forces corrections to be
applied as a new follow-up migration instead of editing the original,
which would create drift between environments that have already run
the old version and those that haven't.
When POST /recall is called without an explicit userId, resolve the
user via the BankTx.user getter (transaction → buyCrypto →
buyCryptoChargeback → buyFiats). Load the top-level relations so the
getter can resolve through the eager transaction.user chain.

Backward compatible: callers passing userId explicitly keep their
existing behavior.
* feat: include recall info in bank tx support responses

Compliance search and user-data detail responses now include an
optional recall object on each BankTxSupportInfo. The frontend can
render recall status inline without an additional roundtrip.

- RecallService.findByBankTxIds batches the lookup for all bankTxs of
  a response
- SupportService maps recalls by bankTx id and hands them to
  toBankTxDto

* rename: findByBankTxIds → getByBankTxIds for naming consistency
* feat: support Sepolia for faucet and use fixed ETH amount

Switch faucet blockchain based on environment (Sepolia on DEV/LOC,
Ethereum otherwise) and replace CHF-based amount conversion with a
fixed native-coin amount (0.0005 ETH).

* refactor: align faucet blockchain field with existing pattern

Match the readonly field style used in realunit.service.ts for
environment-based blockchain selection.

* feat: enable faucet by default on DEV and LOC environments

Faucet is required for the BitBox RealUnit sell flow on Sepolia
(DEV/LOC). Keep the ENV flag as an explicit override for PRD.

* chore: remove stale FAUCET_ENABLED from env examples

The flag is auto-enabled on DEV and LOC and only relevant on PRD,
where it is configured via deployment secrets.
* feat: add report fields to Mros entity

Extends the Mros entity with the core goAML SAR report-content fields
that every MROS submission needs:

- reportCode (default SAR)
- reason  (Sachverhalt long text)
- action  (Grund / Unternommen long text)
- indicators (JSON-serialised array of goAML indicator codes)

reason/action/indicators are nullable for backward compatibility with
existing rows; the DTOs mark them optional so the UI can roll the
fields out gradually.

* style: simplify indicatorCodes setter to match priceStepsObject pattern

* revert: remove hand-written migration

To be replaced by a TypeORM-generated migration via
  npm run migration AddMrosReportFields
so the DEFAULT/constraint names match TypeORM's deterministic hash
naming (learned from PR #3613 / constraint-name drift).
Documents the repo-specific rules that keep biting contributors and
AI assistants:

- Migrations must be generated via 'npm run migration', not hand-
  written (constraint-name drift, see PR #3613 / #3614).
- Migrations are immutable once merged — CI enforces it.
- Canonical JSON-column pattern (getter/setter) from
  buy-crypto.entity.ts.
- Create vs Update DTO conventions (IsOptional vs
  IsOptionalButNotNull).
- Service update pattern with Object.assign + typed setters.
- Branch / commit / release-PR workflow.
… stats single query (#3593)

* feat: support dashboard counts endpoint, configurable clerks, message stats single query

- add GET /support/issue/counts endpoint (single GROUP BY query instead of 3 list calls)
- add GET /support/issue/clerks endpoint, reads from supportClerks setting with 'Support' fallback
- register supportClerks string[] setting
- getMessageStats: collapse 2 queries into 1 via correlated subquery
- drop single state filter in favor of states list (comma-separated)
- add reusable StringToArray() DTO transform decorator
- restore original clerk assignment (last-writer-wins) on message creation

* feat: support issue activity endpoint for dashboard message polling

* refactor: extract role-department map, use typeorm subquery for message stats
Follow-up to PR #3621 — the entity columns reportCode/reason/action/
indicators were merged without a corresponding migration.

Constraint names match TypeORM's auto-generated format
(DF_ + sha1('mros_<column>').substring(0, 27)) so a future
'npm run migration' run on this schema doesn't see drift.
…3628)

Reality update from PR #3621: contributors / AI assistants without
local DB setup couldn't run 'npm run migration', so they skipped the
migration entirely (David caught it after merge). The strict ban on
hand-writing didn't survive contact with that case.

The new policy keeps 'npm run migration' as the preferred path but
adds an explicit fallback: hand-written is allowed if the constraint
names match TypeORM's deterministic algorithm. Documents the formula
(prefix + sha1 substring + length per constraint type) and the
many-to-many join-table conventions.

Verifiable: every contributor can sanity-check their hashes against
existing 'AddMros'-style constraints before pushing.
* feat: compliance pending reviews endpoint

Adds /support/pending-reviews and /support/pending-reviews/items endpoints
aggregating all kyc_step and bank_data entries in ManualReview or
InternalReview, grouped by type and name. Replaces the external
NutzerMonitoring Google Sheet for manual compliance tasks.

* refactor: simplify pending review list queries
…3629)

* feat: throw TfaRequiredException with stable code for 2FA responses

Replaces the generic ForbiddenException thrown by checkVerification with
a dedicated TfaRequiredException carrying code "2FA_REQUIRED", matching
the existing pattern of KycLevelRequiredException and
RegistrationRequiredException.

Without a stable code, clients had to fall back to a statusCode == 403
heuristic, which conflicts with all other 403 paths (account blocked,
country not allowed, permission denied, etc.). With this change, clients
can match on code instead and trigger the correct 2FA flow.

Includes the optional level field in the response payload so clients can
distinguish basic from strict 2FA where relevant.

* refactor: tighten TfaRequiredException — TfaLevel type, TFA_REQUIRED code

- Use TfaLevel enum (via import type to avoid runtime circular dep) so
  callers get type-safe level argument instead of arbitrary string.
- Switch code to TFA_REQUIRED for consistency with the alphabetic
  SCREAMING_SNAKE_CASE convention used by KYC_LEVEL_REQUIRED and
  REGISTRATION_REQUIRED. The Tfa identifier namespace is what the rest
  of the codebase uses for machine-readable references (TfaService,
  TfaLevel, TfaType); 2FA stays in user-facing strings.
- Hoist level?.toLowerCase() into a local to remove the duplicate call.
Add backend support for the new compliance call-queue feature, exposing
five queues based on AML pending transactions and unavailable/suspicious
phone-call userData.

Endpoints (all guarded by COMPLIANCE role):
- GET  support/call-queues          — counts per queue
- GET  support/call-queues/clerks   — clerk list from setting
- GET  support/call-queues/:queue/items — items per queue (limit 200)

Service layer:
- BuyCryptoService.getByAmlReason / countByAmlReason
- BuyFiatService.getByAmlReason / countByAmlReason
- UserDataService.getByPhoneCallStatuses / countByPhoneCallStatuses
  All use find() with loadEagerRelations:false (consistent with the
  pending-review query refactor in #3599).

Misc:
- Register complianceClerks string[] setting
- Extend UserDataComplianceUpdateCols with phoneCallStatus and the four
  phoneCall*CheckDate fields, so they can be set via the existing admin
  update endpoint
- Resolve usedRef -> refUserName in bulk in UserSupportInfo (one extra
  query, no N+1)
- Drop redundant 'name' field from BankDataService.getPendingReviewSummary
  return type (unused after #3599)
- ParseEnumPipe on the queue param to fail-fast on invalid values
* feat: link transactions to Mros via many-to-many

A compliance officer selects which transactions are relevant to an MROS
report — goAML XML needs these as structured transaction nodes
(t_from_my_client / t_to_my_client) at export time.

- Many-to-many relation on Mros.transactions (new join table generated
  by typeorm via migration)
- transactionIds: number[] on create/update DTO; service resolves to
  Transaction entities via the new TransactionService.getTransactionsByIds
- Update loads the existing transactions relation so replacing the
  selection works cleanly

Migration to be generated locally via
  npm run migration AddMrosTransactionsRelation
(per CONTRIBUTING.md).

* feat: add migration for mros transactions many-to-many

Join table mros_transactions_transaction with composite PK +
indices + cascading FKs on both sides.

All constraint names computed via TypeORM's DefaultNamingStrategy
(sha1(table_name + '_' + column).substring(0, N)) so future
'npm run migration' won't see drift.
davidleomay
davidleomay previously approved these changes Apr 28, 2026
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.

3 participants