Hybrid fraud detection system combining rule-based anomaly scoring with AI-powered explanations. Uses provider abstraction for offline development and production flexibility. Built for SMBs with explainability-first design.
You are working on **FraudShield AI**, a hybrid fraud detection system for SMBs that combines deterministic rule-based anomaly detection with AI-powered explanations. The system prioritizes explainability and uses a provider abstraction pattern for development flexibility.
FraudShield uses a layered architecture with pluggable providers:
All external services use Protocol-based abstractions to enable implementation swapping:
**Protocol Definition (app/services/):**
```python
class AnomalyDetectorProtocol(Protocol):
def calculate_risk_score(self, transaction: dict) -> tuple[float, list[str]]: ...
```
**Provider Implementations (app/providers/):**
```python
class LLMProvider(ABC):
@abstractmethod
async def generate_explanation(self, request: ExplanationRequest) -> ExplanationResponse: ...
```
**Implementation locations:**
**Why:** Enables offline development with mock providers, zero vendor lock-in, seamless production deployment.
Scoring is **deterministic and weighted** (not ML-based). Implementation: `app/services/anomaly_detector.py`.
**Risk factors** (defined in `app/config.py`):
**Risk thresholds:**
**Always cap scores at 1.0:** `min(score, 1.0)`
1. **POST /transactions** → `app/main.py:create_transaction()`
2. Calculate risk → `detector.calculate_risk_score(transaction_data)` returns `(score, factors)`
3. Map to risk level → `get_risk_level(score)` applies thresholds
4. Store → `transaction_store.add()` (in-memory dict in `app/storage.py`)
5. Return → `TransactionResponse` model (no explanation yet)
**Explanation generation is lazy** (only on GET `/transactions/{id}`):
**Always use SWR** for data fetching (see `frontend/hooks/`):
```typescript
// List view
const { transactions, stats, isLoading } = useTransactions();
// Detail view
const { transaction, isLoading, isError } = useTransaction(id);
```
**API client:** `frontend/lib/api.ts` → wraps fetch with error handling
**Base URL:** `process.env.NEXT_PUBLIC_API_URL` (defaults to `http://localhost:8000`)
**Page components** (`frontend/app/`) → use client hooks for data
**UI components** (`frontend/components/`) → organized by domain:
**Styling:** Tailwind CSS with dark mode via `next-themes` provider
```bash
source venv/bin/activate
uvicorn app.main:app --reload --port 8000
cd frontend && npm run dev
```
**Seed data:** Auto-loaded from `app/data/demo_transactions.json` on startup (see `app/main.py:lifespan()`)
Controlled via environment variables (defaults work without API keys):
```bash
LLM_PROVIDER=mock # mock | azure_openai | openai | ollama
PATTERN_PROVIDER=local_json # local_json | azure_search | mock
```
**Default (mock):** No external calls, deterministic responses, perfect for development/testing.
1. Add weight to `app/config.py:SCORING_WEIGHTS`
2. Implement detection logic in `app/services/anomaly_detector.py:calculate_risk_score()`
3. Add explanation template to `app/providers/llm/mock_provider.py:FACTOR_TEMPLATES`
4. Update `METHODOLOGY.md` with factor definition
**Production Stack:**
- Config: `render.yaml` + `Procfile`
- Command: `gunicorn --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000 -w 2 --timeout 120 app.main:app`
- Health check: `/health` endpoint
- Environment: Set `NEXT_PUBLIC_API_URL` to Render backend URL
- Auto-deploys from `main` branch
**Critical:** Frontend's `NEXT_PUBLIC_API_URL` must point to production backend, not localhost.
**Don't bypass provider abstractions** → Always use Protocol/ABC interfaces
**Don't hardcode risk thresholds** → Use `RISK_THRESHOLDS` from `app/config.py`
**Don't call explanations on POST** → Expensive operation, only generate on GET detail view
**Don't use `cache: 'force-cache'`** → Use `cache: 'no-store'` for real-time fraud data
**Don't use in-memory storage for production** → Current `TransactionStore` loses data on restart (replace with database)
1. **No persistence** - In-memory storage loses data on Render dyno restart
2. **No authentication** - API is completely open
3. **No transaction creation UI** - Users must use API directly
4. **Frontend env mismatch** - May be pointing to localhost instead of Render
See `PRODUCTION_READINESS.md` for complete assessment and roadmap.
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/fraudshield-ai-explainable-fraud-detection/raw