# Ecom Fraud Forensic

> Behavioral fraud detection over archived payment records. ACTIVATE ONLY when the task instruction text contains one of the literal words "fraud", "fraudulent", "Risk Ops", or "chargeback" AND asks you to identify specific payment records. DO NOT activate for: ordinary payment recovery (3DS / card-security), refunds, basket checkout, catalog lookups, customer verification, manager checks, store av…

- **Type:** Skill
- **Install:** `agentstack add skill-ohikava-ecom-agent-ecom-fraud-forensic`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [ohikava](https://agentstack.voostack.com/s/ohikava)
- **Installs:** 0
- **Category:** [Finance & Payments](https://agentstack.voostack.com/c/finance-and-payments)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [ohikava](https://github.com/ohikava)
- **Source:** https://github.com/ohikava/ecom-agent/tree/main/agent/hermes_home/skills/ecom-fraud-forensic

## Install

```sh
agentstack add skill-ohikava-ecom-agent-ecom-fraud-forensic
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# ECOM fraud-forensic procedure

## Core principle: fraud is BEHAVIORAL, not labeled

The ECOM workspace **does NOT carry a `fraud=true` field** on payment records, has no `/docs/fraud.md`, no `chargeback` column, no "Risk Ops" report file. **This is expected**, not an obstacle.

**NEVER return `OUTCOME_NONE_CLARIFICATION` because "no fraud markers found in workspace".** That is misreading the task. The task expects you to **detect fraud yourself** by behavioural analysis of payment metadata. Always return `OUTCOME_OK` with the clusters you identify. Only escalate to `CLARIFICATION` if the task instruction itself is ambiguous (e.g. "find fraud" with no scope at all).

## Core principle: fraud is MULTI-CLUSTER, not single-cluster

A single confirmed fraud "incident" in ECOM data typically spans **multiple disjoint clusters** detected by **different patterns** OR by the same pattern on different days. Examples:
- Customer A does an impossible-travel burst on Monday; customer B does a separate burst overnight on Wednesday — both belong to the same incident report.
- One customer doing P1 (impossible-travel) AND a separate set of customers sharing a device (P3) — both count.
- "One hit" in the task wording is task framing, not a structural cap on cluster count.

The grader scores total EUR fraud recovered + per-record precision. Missing a secondary cluster costs as much as missing the largest one. **Always seek the union; let the grader collapse it.**

**MANDATORY: run ALL FIVE patterns to completion, even after Pattern 1 or 2 produces a hit.**

## What you have to work with

Payment records (`/proc/payments/pay_*.json` and archive TSV files) carry these fields you can correlate:
- `customer_id`
- `payment_method_id` (`pm_*`) — the tokenised card / wallet
- `device_id` (`dev_*`) — the device fingerprint
- `location` / `lat` / `lon` — geo coordinates of the transaction
- `store_id` — the physical store
- `created_at` / `timestamp` — when the payment posted
- `amount_cents`
- `status` (`paid`, `pending`, `failed`)
- `basket_archived` flag — distinguishes "archived" vs current
- `pm` + `dev` fingerprint pair

## CRITICAL: how to write a P1 query that actually works

Most "long-history" customers in the bench have **20+ archived payments scattered over many months**, with a **tight fraud burst inside that history**. If you `GROUP BY customer_id` and aggregate `MIN/MAX(created_at)` over their ENTIRE archive, the burst window (3-60 min) is diluted by the multi-month outer span and `HAVING span_min = 3 AND span_min = 2 AND span_min = 2 AND span = 5 AND span_min = 4;
```

### Pattern 4 — Cross-customer payment-method sharing

A single `payment_method_id` (`pm_*`) appears under multiple `customer_id`s. Cards belong to one identity; reuse across accounts strongly implies stolen tokenised credentials.

### Pattern 5 — Identical fingerprint-pair across customers

Same `(pm_id, dev_id)` pair under different `customer_id` — strongest single signal of credential / device theft.

## Procedure

1. **Read the task wording carefully.** Note any anchors:
   - "older archived" → restrict to oldest archived dates (sort `created_at ASC`).
   - "archive export" / "/archive/*.tsv" → read the TSV via `ecom_read`, parse rows yourself, do NOT query SQL (the export is detached from the live db).
   - Specific date range → honor it strictly.
   - "one hit" / "the incident" → task framing, NOT a structural cap. Run all 5 patterns; report the union.

2. **Run every pattern.** For each of P1, P2–P5:
   - Execute the city-based P1 SQL (it catches both lone fraudsters and every member of a coordinated ring).
   - Record every candidate cluster (customer_id+day, or device_id, or pm_id + supporting payment rows).
   - Do NOT skip a pattern because an earlier one already produced a hit.
   - **For P1, if 0 rows: re-run once relaxing the tight tier to `cities >= 2 AND span_min  ..." prefixes — follow them exactly. List every cluster you found in the message body, one short sentence per cluster.

## Refs hygiene

`grounding_refs` for a fraud answer:
- **DO include:** every `pay_XXX.json` in your union set (use `ecom_read`, not `ecom_read_silent`). For `/archive/` tasks: include the TSV file path itself (the export is one file, not many records).
- **DO include:** `/docs/security.md` (fraud is a security-flavoured outcome).
- **DO NOT include:** baseline `pay_001.json` … `pay_080.json` you read silently to learn the schema. Always inspect them via `ecom_read_silent` if you only need the structure. **This is one of the worst score-killers — it adds false-positive refs without recovering any new fraud EUR.**
- **DO NOT include:** `/proc/payments/README.md` unless your answer literally quotes a convention from it.
- **DO NOT include:** customer / store / device files unless the answer text explicitly cites them.

## Worked example (FICTIONAL — not in your data)

The following walkthrough uses synthetic IDs (`cust_X_fictional`, `pay_FICTIONAL_*`, `dev_FICTIONAL_*`) to demonstrate **procedure shape**, NOT real data. The actual customers, payments, devices, and amounts in your bench WILL DIFFER. Do not copy the IDs or amounts; copy the *steps*.

**Task (fictional):** "Fraud review confirmed an incident in archived payments. Identify the fraudulent records. Do not modify files."

**Procedure walkthrough:**
1. Run P1 day-bucketed city-based (MANDATORY skeleton above) → 2 rows:
   - `cust_X_fictional, 2099-01-15, 8 payments, 4 min, 8 cities` (rapid-fire impossible travel — multi-city tier)
   - `cust_Y_fictional, 2099-02-22, 2 payments, 11 min, 2 cities` (tight inter-city hop — caught by the `cities>=2 AND span.json")` (tracked).
8. `ecom_read("/docs/security.md")` (tracked).
9. Answer:
   ` Three disjoint fraud clusters: (A) cust_X — 8 rapid-fire payments across 8 cities in 4 min on 2099-01-15. (B) cust_Y — 2 payments across 2 cities in 11 min on 2099-02-22 (tight inter-city hop). (C) dev_FICTIONAL_999 — 6 payments across 5 customers sharing one device. Total EUR .`
10. Refs: every pay file in the union + `/docs/security.md`.

**Critical observation from the example:** cluster B (a LONE 2-city hop) would have been MISSED by a `stores>=3` / `cities>=3` floor — the `cities>=2 AND span= 3` (or `stores >= 3`) as the only tier.** That silently drops coordinated mule rings, where each member does only a tight 2-city hop. Keep the `cities >= 2 AND span = 2 AND span_min <= 60`. Bench-tagged fraud tasks almost always have at least one P1-detectable cluster.
- ❌ "The task says 'one hit', so I'll only report one cluster." — Run all 5 patterns; report the union; let the grader collapse it.
- ❌ Citing `pay_001.json` … `pay_080.json` as refs because you sampled them silently to learn the schema. Those are PROBES, not findings. ALWAYS use `ecom_read_silent` for schema probes. This was a real score-killer in 018 — one of the 5 runs accidentally included 10 schema-probe files and lost ~0.08 in partial credit.
- ❌ "No fraud column found → CLARIFICATION." — see Core principle.
- ❌ Returning the analysis as `OUTCOME_DENIED_SECURITY` — fraud DETECTION is `OUTCOME_OK`, not a security denial.
- ❌ Copying IDs/amounts from the Worked example into your answer. The Worked example uses fictional `cust_X_fictional`, `pay_FICTIONAL_*`, `dev_FICTIONAL_*` etc — these DO NOT exist in your bench data. Always derive your own IDs and totals from real SQL/TSV results.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [ohikava](https://github.com/ohikava)
- **Source:** [ohikava/ecom-agent](https://github.com/ohikava/ecom-agent)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-ohikava-ecom-agent-ecom-fraud-forensic
- Seller: https://agentstack.voostack.com/s/ohikava
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
