{
  "schema_version": 1,
  "diagram_type": "architecture",
  "meta": {
    "title": "Bambu Print Monitor — System Boundary",
    "quality_profile": "showcase",
    "views": [
      {
        "id": "read-only-observation",
        "label": "Read-only observation",
        "focus": ["bambu_cloud", "lifecycle_monitor", "printguard", "camera"],
        "note": "Follow Cloud lifecycle reads and local camera evidence without a printer-control path."
      },
      {
        "id": "evidence-and-status",
        "label": "Evidence + public status",
        "focus": ["lifecycle_monitor", "evidence", "status_publisher", "d1", "status_site"],
        "note": "See how bounded local evidence becomes a two-slot public status surface."
      },
      {
        "id": "failure-alert",
        "label": "Confirmed failure alert",
        "focus": ["printguard", "telegram_bridge", "telegram", "reviewer"],
        "note": "Only an exact alert with a matching snapshot can cross the Telegram boundary."
      }
    ]
  },
  "components": [
    {
      "id": "camera",
      "type": "external",
      "label": "TP-Link Tapo C210",
      "tag": "visual source",
      "pos": [40, 300],
      "size": [160, 72]
    },
    {
      "id": "bambu_cloud",
      "type": "cloud",
      "label": "Bambu Cloud",
      "sublabel": "fixed HTTPS GET",
      "tag": "lifecycle read",
      "pos": [40, 120],
      "size": [160, 72]
    },
    {
      "id": "printguard",
      "type": "backend",
      "label": "PrintGuard 2.3.12",
      "sublabel": "camera-only / alert-only",
      "tag": "loopback :8000",
      "pos": [260, 300],
      "size": [180, 76]
    },
    {
      "id": "lifecycle_monitor",
      "type": "backend",
      "label": "Lifecycle Monitor",
      "sublabel": "5s poll + 2-sample gate",
      "tag": "systemd service",
      "pos": [260, 120],
      "size": [180, 76]
    },
    {
      "id": "evidence",
      "type": "database",
      "label": "Evidence Bundle",
      "sublabel": "5s JPEG ring + NDJSON",
      "tag": "local 0700",
      "pos": [490, 300],
      "size": [180, 76]
    },
    {
      "id": "status_publisher",
      "type": "backend",
      "label": "Status Publisher",
      "sublabel": "authenticated ingest",
      "tag": "two-slot writer",
      "pos": [700, 300],
      "size": [180, 76]
    },
    {
      "id": "d1",
      "type": "database",
      "label": "Cloudflare D1",
      "sublabel": "current + last + diagnostics",
      "tag": "replace-in-place",
      "pos": [910, 300],
      "size": [190, 76]
    },
    {
      "id": "status_site",
      "type": "frontend",
      "label": "print.arrgee.org",
      "sublabel": "public read-only status",
      "tag": "Pages frontend",
      "pos": [1130, 300],
      "size": [190, 76]
    },
    {
      "id": "telegram_bridge",
      "type": "security",
      "label": "Defect-Only Bridge",
      "sublabel": "alert + matching snapshot",
      "tag": "no shell / at most once",
      "pos": [480, 500],
      "size": [190, 76]
    },
    {
      "id": "telegram",
      "type": "external",
      "label": "Rahul's Telegram",
      "sublabel": "private failure alert",
      "tag": "human review",
      "pos": [700, 500],
      "size": [180, 76]
    },
    {
      "id": "reviewer",
      "type": "external",
      "label": "Human Reviewer",
      "sublabel": "inspect snapshot",
      "tag": "no automation",
      "pos": [910, 500],
      "size": [180, 76]
    }
  ],
  "boundaries": [
    {"kind": "region", "label": "Local host / protected runtime", "wraps": ["printguard", "lifecycle_monitor", "evidence", "status_publisher", "telegram_bridge"]},
    {"kind": "region", "label": "Cloudflare public status surface", "wraps": ["d1", "status_site"]},
    {"kind": "security-group", "label": "Alert-only / no printer control", "wraps": ["camera", "bambu_cloud", "printguard", "lifecycle_monitor", "telegram_bridge"]}
  ],
  "connections": [
    {"id": "cloud-lifecycle", "from": "bambu_cloud", "to": "lifecycle_monitor", "label": "fixed HTTPS GET /v1/iot-service/api/user/bind", "variant": "emphasis", "labelDy": 64},
    {"id": "camera-printguard", "from": "camera", "to": "printguard", "label": "RTSP /stream2", "variant": "default", "labelDy": 60},
    {"id": "printguard-lifecycle", "from": "printguard", "to": "lifecycle_monitor", "label": "GET /api/health + current frame", "variant": "default", "fromSide": "top", "toSide": "bottom"},
    {"id": "lifecycle-evidence", "from": "lifecycle_monitor", "to": "evidence", "label": "5s frame + score observation", "variant": "emphasis"},
    {"id": "lifecycle-status", "from": "lifecycle_monitor", "to": "status_publisher", "label": "redacted status + frames", "variant": "dashed"},
    {"id": "evidence-status", "from": "evidence", "to": "status_publisher", "label": "sealed/selected JPEG", "variant": "dashed", "labelDy": 60},
    {"id": "publisher-d1", "from": "status_publisher", "to": "d1", "label": "bearer-authenticated ingest", "variant": "security", "labelDy": 60},
    {"id": "d1-site", "from": "d1", "to": "status_site", "label": "public GET / HEAD", "variant": "emphasis", "labelDy": 60},
    {"id": "printguard-bridge", "from": "printguard", "to": "telegram_bridge", "label": "redacted events + snapshot", "variant": "security", "fromSide": "bottom", "toSide": "top"},
    {"id": "bridge-telegram", "from": "telegram_bridge", "to": "telegram", "label": "exact alert + media", "variant": "security", "labelDy": -42},
    {"id": "telegram-review", "from": "telegram", "to": "reviewer", "label": "inspect and decide", "variant": "default", "labelDy": -42}
  ],
  "cards": [
    {"dot": "emerald", "title": "Primary contract", "items": ["Bambu Cloud remains the printing path; the monitor reads lifecycle state only.", "The C210 is an independent visual source and PrintGuard stays camera-only."]},
    {"dot": "rose", "title": "Safety boundary", "items": ["No A1 LAN credentials, MQTT, FTP, pause, stop, cancel, or G-code route exists.", "Telegram is reachable only through the confirmed-defect bridge and human review."]},
    {"dot": "cyan", "title": "Public surface", "items": ["The site exposes coarse status, privacy-cropped frames, and bounded diagnostics.", "D1 uses replace-in-place retention: current and last, with no public history."]}
  ]
}
