{
  "schema_version": 1,
  "diagram_type": "architecture",
  "meta": {
    "title": "Family Home Lab",
    "quality_profile": "showcase",
    "views": [
      {
        "id": "main",
        "label": "Primary path",
        "focus": [
          "users",
          "caddy",
          "portal",
          "omni",
          "dsh"
        ],
        "note": "Browsers reach services through the lab reverse proxy."
      },
      {
        "id": "data",
        "label": "State and workers",
        "focus": [
          "portal",
          "db",
          "worker",
          "garage"
        ],
        "note": "Console state, async transcription, S3 storage."
      }
    ]
  },
  "components": [
    {
      "id": "users",
      "type": "external",
      "label": "Family",
      "sublabel": "browsers / phones",
      "pos": [
        40,
        300
      ],
      "size": [
        120,
        60
      ]
    },
    {
      "id": "caddy",
      "type": "backend",
      "label": "Caddy",
      "sublabel": "reverse proxy :35",
      "pos": [
        250,
        300
      ],
      "size": [
        130,
        60
      ]
    },
    {
      "id": "portal",
      "type": "backend",
      "label": "Console portal",
      "sublabel": "FastAPI :13:8500",
      "pos": [
        430,
        360
      ],
      "size": [
        150,
        60
      ]
    },
    {
      "id": "redis",
      "type": "database",
      "label": "Redis",
      "sublabel": "cache / broker",
      "pos": [
        620,
        300
      ],
      "size": [
        130,
        60
      ]
    },
    {
      "id": "db",
      "type": "database",
      "label": "Postgres",
      "sublabel": "users + prefs",
      "pos": [
        780,
        440
      ],
      "size": [
        130,
        60
      ]
    },
    {
      "id": "worker",
      "type": "backend",
      "label": "Transcribe",
      "sublabel": "Celery + RabbitMQ",
      "pos": [
        780,
        300
      ],
      "size": [
        140,
        60
      ]
    },
    {
      "id": "omni",
      "type": "cloud",
      "label": "OmniRoute",
      "sublabel": "LLM gateway :20129",
      "pos": [
        430,
        150
      ],
      "size": [
        140,
        60
      ]
    },
    {
      "id": "dsh",
      "type": "backend",
      "label": "dsh chat",
      "sublabel": "per-user \u00d7 4",
      "pos": [
        620,
        150
      ],
      "size": [
        130,
        60
      ]
    },
    {
      "id": "voice",
      "type": "backend",
      "label": "Jervis",
      "sublabel": "voice agent :8501",
      "pos": [
        140,
        460
      ],
      "size": [
        120,
        60
      ]
    },
    {
      "id": "garage",
      "type": "cloud",
      "label": "Garage S3",
      "sublabel": "shared-media",
      "pos": [
        320,
        460
      ],
      "size": [
        140,
        60
      ]
    },
    {
      "id": "offsite",
      "type": "cloud",
      "label": "Amazon S3",
      "sublabel": "offsite backup",
      "pos": [
        620,
        460
      ],
      "size": [
        130,
        60
      ]
    }
  ],
  "boundaries": [
    {
      "kind": "region",
      "label": "Home LAN (.13 / .35)",
      "wraps": [
        "caddy",
        "portal",
        "db",
        "redis",
        "worker",
        "omni",
        "dsh",
        "voice",
        "garage"
      ]
    }
  ],
  "connections": [
    {
      "id": "u-c",
      "from": "users",
      "to": "caddy",
      "label": "HTTPS *.lab",
      "variant": "emphasis",
      "labelDy": -20
    },
    {
      "id": "c-p",
      "from": "caddy",
      "to": "portal",
      "label": "console.lab",
      "labelAt": [
        335,
        296
      ]
    },
    {
      "id": "c-o",
      "from": "caddy",
      "to": "omni",
      "label": "omniroute.lab",
      "variant": "dashed",
      "labelDy": 28
    },
    {
      "id": "o-d",
      "from": "omni",
      "to": "dsh",
      "label": "chat models",
      "labelAt": [
        595,
        120
      ]
    },
    {
      "id": "p-r",
      "from": "portal",
      "to": "redis",
      "label": "async",
      "variant": "dashed",
      "labelDy": 22
    },
    {
      "id": "p-db",
      "from": "portal",
      "to": "db",
      "label": "SQL",
      "labelDy": 6
    },
    {
      "id": "g-o",
      "from": "garage",
      "to": "offsite",
      "label": "Borg sync",
      "variant": "dashed",
      "labelDy": -20
    }
  ],
  "cards": [
    {
      "dot": "cyan",
      "title": "Edge",
      "items": [
        "Caddy terminates HTTPS for ~50 sites (*.lab + *.home.lab)",
        "Family reaches the whole lab from one login"
      ]
    },
    {
      "dot": "emerald",
      "title": "Lab",
      "items": [
        "FastAPI console + admin + Files",
        "Celery workers transcribe audio/video",
        "Garage S3 + shared-media (portal \u2192 S3)"
      ]
    },
    {
      "dot": "rose",
      "title": "AI",
      "items": [
        "OmniRoute pins deterministic models (chat/reasoning/coding)",
        "dsh chat hardened \u2014 no shell",
        "Jervis voice agent drives Home Assistant",
        "Voice page \u2192 Jervis agent (console)"
      ]
    }
  ]
}