{
  "docVersion": 1,
  "id": "template-chain-replicated-object-store",
  "name": "Chain-replicated object store",
  "purpose": "Object store with chain replication: writes enter the head and commit at the tail; CRAQ serves reads from clean replicas; a config master reconfigures the chain on failure with epoch bumps.",
  "nodes": {
    "writer": {
      "type": "user",
      "label": "Writer",
      "x": 20,
      "y": 60,
      "runtime": "put(object)"
    },
    "reader": {
      "type": "user",
      "label": "Reader",
      "x": 20,
      "y": 320,
      "runtime": "get(object)"
    },
    "head": {
      "type": "keyvalue",
      "label": "HEAD",
      "x": 330,
      "y": 60,
      "runtime": "accepts writes",
      "color": "blue",
      "notes": "Applies the write locally (dirty), forwards down the chain. A version is dirty until the tail has it — CRAQ replicas track clean/dirty per key."
    },
    "mid": {
      "type": "keyvalue",
      "label": "MIDDLE",
      "x": 620,
      "y": 60,
      "runtime": "propagates · serves clean reads"
    },
    "tail": {
      "type": "keyvalue",
      "label": "TAIL",
      "x": 910,
      "y": 60,
      "runtime": "commit point · strong reads",
      "color": "green",
      "notes": "The tail ack defines committed (the high-water mark). Strong reads always agree with it."
    },
    "cfg": {
      "type": "config",
      "label": "Chain master",
      "x": 620,
      "y": 340,
      "runtime": "membership · epoch++ on failure",
      "color": "purple",
      "patterns": [
        "leader-elected"
      ],
      "notes": "On node failure, relinks the chain and bumps the generation clock — acks from the old epoch are rejected, so a paused zombie can't corrupt the chain."
    }
  },
  "edges": {
    "e1": {
      "from": "writer",
      "to": "head",
      "fromSide": "right",
      "toSide": "left",
      "label": "write",
      "animated": true
    },
    "e2": {
      "from": "head",
      "to": "mid",
      "fromSide": "right",
      "toSide": "left",
      "label": "propagate",
      "animated": true
    },
    "e3": {
      "from": "mid",
      "to": "tail",
      "fromSide": "right",
      "toSide": "left",
      "label": "propagate → commit",
      "animated": true
    },
    "e4": {
      "from": "tail",
      "to": "writer",
      "fromSide": "bottom",
      "toSide": "bottom",
      "label": "ack (HWM advances)",
      "style": "dashed",
      "color": "green"
    },
    "e5": {
      "from": "reader",
      "to": "tail",
      "fromSide": "right",
      "toSide": "bottom",
      "label": "strong read"
    },
    "e6": {
      "from": "reader",
      "to": "mid",
      "fromSide": "right",
      "toSide": "left",
      "label": "CRAQ: read if clean",
      "style": "dashed",
      "color": "purple"
    },
    "e7": {
      "from": "cfg",
      "to": "mid",
      "fromSide": "top",
      "toSide": "bottom",
      "label": "epoch 7 · chain config",
      "style": "dashed"
    }
  },
  "boxes": {
    "b1": {
      "x": 290,
      "y": -40,
      "w": 800,
      "h": 300,
      "label": "the chain — write path is the replication path",
      "color": "blue",
      "opacity": 0.04
    }
  },
  "texts": {
    "t1": {
      "x": 330,
      "y": 500,
      "text": "segmented log per node: appends land in the\nactive segment; everything below the low-water\nmark is truncated after snapshot — cheap GC.",
      "color": "gray",
      "size": 12
    }
  },
  "meta": {
    "createdAt": "2026-07-13T09:00:00.000Z",
    "modifiedAt": "2026-07-13T09:00:00.000Z"
  }
}