fraud-service - API Contract¶
| Field | Value |
|---|---|
| Port | 9013 |
| Mode | CQRS + Mediator |
| Base path | /api/v1 |
| Owning sprint | Sprint 23 |
| Build status | TODO |
| Requirements | Scope defined by ADR-029 and docs/tasks/sprint-23-sim-swap-fraud/design-note.md; no FR/AC IDs assigned in docs/product/requirements.md yet. |
Bounded context: rule-based SIM-swap / fraud detection reacting to existing subscription-service
domain events (ADR-029). Owns MsisdnLifecycleSignal, FraudRule, FraudSignal, and FraudCase
in its own fraud-db (PostgreSQL, database-per-service, ADR-006). Read-only relative to
subscription-service (ADR-029 Section 1): consumes its events via the inbox and never accesses
subscription-db directly.
Rule evaluation and the inbox consumers (23.2) and the fraud-case/rule-config API (23.3) are
implemented; the outbox event publishers land alongside 23.4. Detect-and-alert only - fraud-service
never automatically suspends a subscription (ADR-029 Section 5); resolving a CONFIRMED case is a
FraudCase status change plus an event publish only.
Authentication and Authorization¶
/api/v1/fraud-cases/**and/api/v1/fraud-rules/**require a valid JWT, like every other CQRS + Mediator domain service (Feature 23.3). RBAC reuses the platform's existing role taxonomy:SUPPORTis the agent/fraud-analyst role (the same role ticket-service gates its agent assign/resolve endpoints on) andADMINis the stricter operations role./internal/**is reserved for any future trusted system-to-system surface (tokenless, network-perimeter trust behind the gatewayinternal-deny-route). None defined yet.
All responses are wrapped in ApiResult<T> (ADR-015); list responses use PageResult<T>. A
@PreAuthorize rejection returns 403; an unknown id/rule code returns 404
(ResourceNotFoundException); resolving an already-resolved case returns 422
(BusinessRuleException).
Endpoints¶
Fraud cases (Feature 23.3.1 / 23.3.2)¶
| Method | Path | Role | Request | Response (data) |
|---|---|---|---|---|
| GET | /api/v1/fraud-cases |
SUPPORT or ADMIN |
query params: status (optional, one of OPEN/UNDER_REVIEW/CONFIRMED/DISMISSED), customerId (optional UUID), page (default 0), size (default 20) |
PageResult<FraudCaseSummaryResponse> |
| GET | /api/v1/fraud-cases/{id} |
SUPPORT or ADMIN |
path id (UUID) |
FraudCaseDetailResponse (case + linked signals, each with its contributing MsisdnLifecycleSignal sourceSignalIds) |
| POST | /api/v1/fraud-cases/{id}/resolve |
SUPPORT or ADMIN |
ResolveFraudCaseRequest |
FraudCaseSummaryResponse (resolved case) |
ResolveFraudCaseRequest:
{ "status": "CONFIRMED", "note": "optional free-text (max 1000 chars)" }
status must be CONFIRMED or DISMISSED; any other value is rejected (422). Resolving a case
sets resolvedAt/resolvedBy (the authenticated user id), transitions status, and publishes
fraud.case-resolved.v1 via the outbox. It never calls subscription-service and never suspends,
holds, or otherwise mutates a subscription (ADR-029 Section 5, hard scope boundary).
FraudCaseSummaryResponse: id, customerId, status, openedAt, resolvedAt, resolvedBy,
signalCount.
FraudCaseDetailResponse: id, customerId, status, openedAt, resolvedAt, resolvedBy,
signals (list of FraudSignalResponse).
FraudSignalResponse: id, ruleCode, customerId, msisdn, subscriptionId, severity,
triggeredAt, sourceSignalIds (contributing MsisdnLifecycleSignal ids).
Fraud rules (Feature 23.3.3)¶
| Method | Path | Role | Request | Response (data) |
|---|---|---|---|---|
| GET | /api/v1/fraud-rules |
SUPPORT or ADMIN |
- | List<FraudRuleResponse> (all three fixed rule codes) |
| PUT | /api/v1/fraud-rules/{code} |
ADMIN |
UpdateFraudRuleRequest |
FraudRuleResponse (updated rule) |
{code} is one of RAPID_SIM_SWAP, MSISDN_CHURN_VELOCITY, SUSPEND_REACTIVATE_VELOCITY; an
unknown/unparseable code returns 404 (adding a genuinely new rule type is a code change, not
config, per ADR-029 Section 4). A PUT takes effect on the next rule evaluation with no restart.
UpdateFraudRuleRequest:
{ "windowMinutes": 120, "thresholdCount": 5, "severity": "HIGH", "enabled": true }
windowMinutes and thresholdCount must be positive; severity is one of LOW/MEDIUM/HIGH.
FraudRuleResponse: code, windowMinutes, thresholdCount, severity, enabled.
Events¶
Consumed (existing, from subscription-service via inbox - wired in Feature 23.2)¶
None wired yet. Planned: msisdn.allocated.v1, msisdn.released.v1, subscription.activated.v1,
subscription.suspended.v1.
Published (new, from fraud-service via outbox - wired in Feature 23.4)¶
None wired yet. Planned: fraud.signal-raised.v1, fraud.case-opened.v1,
fraud.case-resolved.v1.