{
  "docVersion": 1,
  "id": "template-fraud-detection-pipeline",
  "name": "Fraud detection pipeline",
  "purpose": "Real-time fraud scoring with streaming features, champion/challenger models, rules fallback on timeout, and human review feeding retraining.",
  "nodes": {
    "txns": {
      "type": "stream",
      "label": "Transaction Stream",
      "x": 20,
      "y": 240,
      "runtime": "every card swipe"
    },
    "agg": {
      "type": "spark",
      "label": "Window Aggregator",
      "x": 280,
      "y": 100,
      "runtime": "sliding 5m / 1h / 24h",
      "notes": "Computes velocity features with watermarks for late events — the features fraudsters actually trip."
    },
    "fs": {
      "type": "featurestore",
      "label": "Feature Store",
      "x": 560,
      "y": 100,
      "runtime": "online + offline parity",
      "patterns": [
        "replicated"
      ]
    },
    "scorer": {
      "type": "worker",
      "label": "Fraud Scorer",
      "x": 560,
      "y": 340,
      "runtime": "decision ≤80ms",
      "color": "blue",
      "patterns": [
        "autoscale",
        "stateless"
      ],
      "notes": "Orchestrates: fetch features, call champion, mirror to challenger, fall back to rules on timeout."
    },
    "champ": {
      "type": "gpu",
      "label": "Champion Model",
      "x": 840,
      "y": 220,
      "runtime": "v41 — decides",
      "color": "green"
    },
    "chall": {
      "type": "gpu",
      "label": "Challenger",
      "x": 840,
      "y": 460,
      "runtime": "v42 — shadow only",
      "style": "dashed",
      "patterns": [
        "canary"
      ]
    },
    "rules": {
      "type": "worker",
      "label": "Rules Fallback",
      "x": 1110,
      "y": 340,
      "runtime": "deterministic · always answers",
      "color": "amber"
    },
    "review": {
      "type": "queue",
      "label": "Review Queue",
      "x": 560,
      "y": 570,
      "runtime": "gray-zone scores"
    },
    "analyst": {
      "type": "user",
      "label": "Analysts",
      "x": 840,
      "y": 640,
      "runtime": "label & decide"
    },
    "cases": {
      "type": "database",
      "label": "Case DB",
      "x": 1110,
      "y": 570,
      "runtime": "labels → retraining",
      "patterns": [
        "backup"
      ]
    }
  },
  "edges": {
    "e1": {
      "from": "txns",
      "to": "agg",
      "fromSide": "right",
      "toSide": "left",
      "label": "events",
      "style": "dashed",
      "patterns": [
        "ordered"
      ]
    },
    "e2": {
      "from": "agg",
      "to": "fs",
      "fromSide": "right",
      "toSide": "left",
      "label": "features"
    },
    "e3": {
      "from": "txns",
      "to": "scorer",
      "fromSide": "right",
      "toSide": "left",
      "label": "score request",
      "animated": true,
      "patterns": [
        "timeout"
      ]
    },
    "e4": {
      "from": "fs",
      "to": "scorer",
      "fromSide": "bottom",
      "toSide": "top",
      "label": "velocity features ≤10ms",
      "patterns": [
        "cache-aside"
      ]
    },
    "e5": {
      "from": "scorer",
      "to": "champ",
      "fromSide": "right",
      "toSide": "left",
      "label": "score ≤50ms",
      "animated": true,
      "patterns": [
        "timeout",
        "circuit-breaker"
      ]
    },
    "e6": {
      "from": "scorer",
      "to": "chall",
      "fromSide": "right",
      "toSide": "left",
      "label": "mirrored — result logged, ignored",
      "style": "dashed"
    },
    "e7": {
      "from": "champ",
      "to": "rules",
      "fromSide": "right",
      "toSide": "left",
      "label": "deadline miss → rules decide",
      "style": "dashed",
      "patterns": [
        "fallback"
      ]
    },
    "e8": {
      "from": "scorer",
      "to": "review",
      "fromSide": "bottom",
      "toSide": "top",
      "label": "confidence 0.4–0.7",
      "style": "dashed"
    },
    "e9": {
      "from": "review",
      "to": "analyst",
      "fromSide": "right",
      "toSide": "left"
    },
    "e10": {
      "from": "analyst",
      "to": "cases",
      "fromSide": "right",
      "toSide": "left",
      "label": "labeled outcomes"
    },
    "e11": {
      "from": "cases",
      "to": "chall",
      "fromSide": "top",
      "toSide": "bottom",
      "label": "training data for v43",
      "style": "dashed"
    }
  },
  "texts": {
    "t1": {
      "x": 20,
      "y": 450,
      "text": "the loop: challenger shadows today's traffic,\nanalysts label the gray zone, both feed the next\nchampion — the model improves without ever\nbeing trusted blindly.",
      "color": "purple",
      "size": 12
    }
  },
  "meta": {
    "createdAt": "2026-07-13T09:00:00.000Z",
    "modifiedAt": "2026-07-13T09:00:00.000Z"
  }
}