{
  "schema_version": 1,
  "diagram_type": "architecture",
  "meta": {
    "title": "Compass / NHS school service",
    "output": "architecture-map.html",
    "quality_profile": "showcase",
    "viewBox": [
      1180,
      610
    ],
    "views": [
      {
        "id": "morning-run",
        "label": "Morning run",
        "focus": [
          "n8n",
          "service",
          "patchright",
          "compass",
          "apprise",
          "family"
        ],
        "note": "n8n runs the scan and the sends at 06:00 every day."
      },
      {
        "id": "read-path",
        "label": "Read path",
        "focus": [
          "sam",
          "caddy",
          "service",
          "hub"
        ],
        "note": "Sam and the Hub both read the same Go service over HTTP."
      },
      {
        "id": "writes",
        "label": "Writes outside the school",
        "focus": [
          "service",
          "ha",
          "apprise",
          "omni"
        ],
        "note": "The calendar write and the briefs are the only writes."
      }
    ]
  },
  "components": [
    {
      "id": "n8n",
      "type": "external",
      "label": "n8n (.13)",
      "sublabel": "06:00 daily trigger",
      "pos": [
        40,
        200
      ],
      "size": [
        150,
        60
      ]
    },
    {
      "id": "sam",
      "type": "external",
      "label": "Sam",
      "sublabel": "browser dashboard",
      "pos": [
        40,
        430
      ],
      "size": [
        150,
        60
      ]
    },
    {
      "id": "caddy",
      "type": "security",
      "label": "Caddy (.35)",
      "sublabel": "session login",
      "pos": [
        250,
        315
      ],
      "size": [
        150,
        60
      ],
      "tag": "school.lab"
    },
    {
      "id": "service",
      "type": "backend",
      "label": "Compass / NHS service",
      "sublabel": "Go + SQLite :8792",
      "pos": [
        470,
        310
      ],
      "size": [
        165,
        70
      ],
      "tag": "source of truth"
    },
    {
      "id": "patchright",
      "type": "backend",
      "label": "patchright scraper",
      "sublabel": "headless Playwright",
      "pos": [
        700,
        315
      ],
      "size": [
        150,
        60
      ]
    },
    {
      "id": "compass",
      "type": "external",
      "label": "Compass NHS",
      "sublabel": "read-only login + pages",
      "pos": [
        920,
        315
      ],
      "size": [
        160,
        60
      ]
    },
    {
      "id": "omni",
      "type": "cloud",
      "label": "OmniRoute",
      "sublabel": "importance only",
      "pos": [
        470,
        120
      ],
      "size": [
        160,
        60
      ]
    },
    {
      "id": "ha",
      "type": "cloud",
      "label": "Home Assistant",
      "sublabel": "calendar.school",
      "pos": [
        700,
        120
      ],
      "size": [
        160,
        60
      ]
    },
    {
      "id": "hub",
      "type": "external",
      "label": "Hub",
      "sublabel": "read-only /ask :8788",
      "pos": [
        250,
        500
      ],
      "size": [
        150,
        60
      ]
    },
    {
      "id": "apprise",
      "type": "cloud",
      "label": "Apprise (.35)",
      "sublabel": "Email + WhatsApp :8210",
      "pos": [
        470,
        500
      ],
      "size": [
        160,
        60
      ]
    },
    {
      "id": "family",
      "type": "external",
      "label": "Family briefs",
      "sublabel": "per-boy + combined",
      "pos": [
        790,
        500
      ],
      "size": [
        160,
        60
      ]
    }
  ],
  "boundaries": [
    {
      "kind": "region",
      "label": "Home lab - Docker on .13, Caddy and Apprise on .35",
      "wraps": [
        "caddy",
        "service",
        "patchright",
        "omni",
        "ha",
        "apprise",
        "hub"
      ]
    }
  ],
  "connections": [
    {
      "id": "n8n-to-service",
      "from": "n8n",
      "to": "service",
      "label": "scripts/morning-brief.sh",
      "variant": "dashed"
    },
    {
      "id": "sam-to-caddy",
      "from": "sam",
      "to": "caddy",
      "label": "HTTPS",
      "variant": "emphasis",
      "fromSide": "top",
      "toSide": "bottom"
    },
    {
      "id": "caddy-to-service",
      "from": "caddy",
      "to": "service"
    },
    {
      "id": "service-to-patchright",
      "from": "service",
      "to": "patchright",
      "label": "scan",
      "labelDy": 30
    },
    {
      "id": "patchright-to-compass",
      "from": "patchright",
      "to": "compass",
      "label": "login + fetch"
    },
    {
      "id": "service-to-omni",
      "from": "service",
      "to": "omni",
      "label": "importance",
      "variant": "dashed",
      "fromSide": "top",
      "toSide": "bottom"
    },
    {
      "id": "service-to-ha",
      "from": "service",
      "to": "ha",
      "label": "create event",
      "fromSide": "right",
      "toSide": "left"
    },
    {
      "id": "service-to-apprise",
      "from": "service",
      "to": "apprise",
      "label": "briefs",
      "fromSide": "bottom",
      "toSide": "top"
    },
    {
      "id": "apprise-to-family",
      "from": "apprise",
      "to": "family",
      "label": "email + WhatsApp"
    },
    {
      "id": "hub-to-service",
      "from": "hub",
      "to": "service",
      "label": "Bearer /ask",
      "variant": "dashed"
    }
  ],
  "cards": [
    {
      "dot": "cyan",
      "title": "Compass / NHS service",
      "items": [
        "Go and SQLite are the source of truth",
        "Go stores items, scans and the send log",
        "Serves the dashboard, the Hub API and the briefs"
      ]
    },
    {
      "dot": "amber",
      "title": "Read-only against the school",
      "items": [
        "patchright logs in and fetches pages only",
        "The Cloudflare login POST needs a real browser",
        "No post, message or submit ever runs"
      ]
    },
    {
      "dot": "rose",
      "title": "Deferred: Teams (FR-15)",
      "items": [
        "Teams homework is DEFERRED and not built",
        "Compass answers what is due and overdue",
        "No Teams section is scanned"
      ]
    }
  ]
}