Files
2026-08-31 13:00:49 +05:30

4.0 KiB
Raw Permalink Blame History

09 — Fraud Controls & Audit Trail

Status: Not Started Depends On: 08 — Sales Agent Controls


Goal

A dedicated, immutable audit log plus automated anomaly detection over everything built in steps 01–08. Covers mainPlan.md §18 (logAuditEvent, checkLicenseCompliance, generateComplianceReport) and the fraud-relevant piece of §15 (sendRouteDeviationAlert) and §12 (return-without-prior-sale detection).


Background / Context

Every prior step in this plan references "logged" or "flagged" behavior (override logs, loading discrepancies, reconciliation variances) — this step is where that logging actually becomes a queryable, immutable audit trail instead of scattered per-feature notes.


Data Model Changes

Audit Log Entry

UserId, Action, EntityType, EntityId, OldValue/NewValue (JSON snapshot), CreatedAt, SourceIp/RequestId if available. Append-only — no update or delete path exposed anywhere.

Anomaly Flag

Type (ReturnWithoutSale, RouteDeviation, HighVarianceRate, CashShortfall), EntityType/ EntityId, RaisedAt, Status (Open, Reviewed, Dismissed).

Return Approval Record

Reuses the approveReturn flow from 18_returns_claims.md — this step adds the automated pre-check (ReturnWithoutSale) that runs before a human approver sees it.


API Endpoints

Function reference Endpoint intent
logAuditEvent(userId, action, entityType, entityId) (§18) Internal — called by every mutating service, not directly exposed
checkLicenseCompliance(entityId, licenseType) (§18) GET /api/compliance/{entityType}/{entityId}/license-check
generateComplianceReport(period) (§18) GET /api/compliance/report?period=...
sendRouteDeviationAlert(routeId, salesRepId) (§15) Not implemented. The underlying data now exists — POST /api/routes/{id}/visits/check-in (11_route_sales_management.md) computes and stores IsDeviationFlagged on each RouteVisitLog row (Haversine distance vs. the store's registered lat/long) — but nothing reads that flag to raise an alert/anomaly flag yet.
— GET /api/audit-log?entityType=...&entityId=...
— GET /api/anomaly-flags?status=Open

Automated Checks & Flags

  • Returns without a matching prior sale (ReturnWithoutSale).
  • Sales/deliveries outside the geofenced route (RouteDeviation) — the GPS check-in/out data this depends on now exists (11_route_sales_management.md's RouteVisitLog.IsDeviationFlagged), but no anomaly flag or alert reads it yet.
  • Agents with consistently high variance rates across closed rides (HighVarianceRate) — reads Variance Record history from 07_ride_reconciliation.md.
  • Cash collected below invoiced amount (CashShortfall) — reads Payment Record from 06_sale_ride.md.

Business Rules

  • Every state-changing action across every feature must call logAuditEvent — this is the one cross-cutting requirement every other numbered step inherits once this lands.
  • Return approval requires supervisor sign-off before stock is credited back (18_returns_claims.md), regardless of whether an anomaly flag fired.

Fraud / Control Considerations

  • Anomaly reports are surfaced to area managers on a scheduled basis — batch job or on-demand endpoint, not real-time push, in v1.

Open Questions

  • Should logAuditEvent be wired in as a cross-cutting concern (e.g. an EF SaveChanges interceptor) rather than an explicit call in every service, to guarantee nothing is missed?
  • What licenses does checkLicenseCompliance actually need to validate for this business — is regulated goods handling in scope at all, or is this function speculative until a real requirement shows up?

Implementation Notes

Fill this section in during planning discussion before writing any code.