# Oikos inventory seed — entity instances + relationships.
#
# Translated from the legacy /inventory.yaml (2026-07-07). Bootstraps the
# entities/relationships tables (migration 002); after ingest the DB is
# authoritative and this file is regenerated by `GET /api/v1/export`.
#
# Slug conventions: <prefix>:<name> —
#   host: (proxmox-host, standalone-server) · ws: (workstation) · lxc: · vm:
#   service: · ingress: · repo: (config-repo) · pool: · volume: · mesh: · lan:
#   zone: (dns-zone) · idp: · person: · agent: · cluster: · backup:
#
# `state:` omitted = the type's lifecycle default (active).
# Mount details (mount_point) are attributes on `mounts` edges.
# Known thin spots are marked  # THIN: backfill later.

version: 1

entities:

  # ─── Sites, networks ───────────────────────────────────────────────
  - {slug: "site:home", type: site, name: home}
  - {slug: "site:ionos-dc", type: site, name: ionos-dc,
     attributes: {address: IONOS datacenter (VPS)}}
  - slug: "lan:lab"
    type: lan
    name: lab
    attributes: {subnet: 192.168.8.0/24}
  - slug: "lan:household"
    type: lan
    name: household
    attributes: {subnet: 192.168.178.0/24}   # Fritz LAN; static route to lab subnet
  - slug: "mesh:netbird"
    type: mesh
    name: netbird
    attributes:
      provider: netbird
      subnet: 100.122.0.0/16
      domain: netbird.selfhosted
  - slug: "mesh:tailscale"
    type: mesh
    name: tailscale
    state: deprecated          # migration to netbird in progress (infrastructure/mesh.md)
    attributes: {provider: tailscale}
  - slug: "zone:hubris.network"
    type: dns-zone
    name: hubris.network
    attributes: {zone: hubris.network, authority: "Technitium (LXC 107), split-horizon"}
  - slug: "zone:netbird.selfhosted"
    type: dns-zone
    name: netbird.selfhosted
    attributes: {zone: netbird.selfhosted, authority: netbird-mgmt}

  # ─── Machines ──────────────────────────────────────────────────────
  - slug: "cluster:homelab"
    type: cluster
    name: Homelab
    attributes: {quorum: "2-node, no QDevice tiebreaker yet"}
  - slug: "host:hubris"
    type: proxmox-host
    name: hubris
    attributes:
      os: linux
      lan_ip: 192.168.8.77
      mesh: {netbird: {ip: 100.122.38.109, fqdn: proxmox-server.netbird.selfhosted}}
      ssh: {port: 22, netbird_port: 22022, user: root}
      age_pubkey: age1xkklkvnk5z0fsnh6cfgv70hy9ksfy8rdprwerzw4yk3p4p7cxcqs2yvpz6
  - slug: "host:strong"
    type: proxmox-host
    name: strong
    attributes:
      os: linux
      lan_ip: 192.168.178.181
      ssh: {user: root}
      age_pubkey: age1rtwvdct6avjkr3cyxv3vue3vqx4d524fjfr3vk7xrnvyrylnry5sm54sn4
      note: >-
        PVE 9.2.3 since 2026-07-01 (formerly workstation ludo-mini). Joined
        Homelab cluster same day. Not yet netbird-enrolled — reachable via
        household LAN / Fritz static route only.
  - slug: "host:netbird-vps"
    type: standalone-server
    name: netbird-vps
    attributes:
      os: linux
      provider: ionos
      control_level: partial     # managed via ssh from hubris; not a homelab client
      public_ipv4: 82.165.190.79
      mesh: {netbird: {ip: 100.122.165.149, fqdn: netbird-ionos.netbird.selfhosted}}
      ssh: {user: root}
      note: netbird mgmt+signal+relay+dashboard + coturn; sshd locked to hubris pubkey
  - slug: "ws:mac-mini"
    type: workstation
    name: mac-mini
    attributes:
      os: macos
      user: dtoro
      lan_ip: 192.168.178.182
      mesh: {netbird: {fqdn: mac-mini-234-17.netbird.selfhosted}}
      age_pubkey: age169104ee1a9e1577d493820830560197f0adf56bf8f1c369d57c152c03f9437ae
      note: only macOS in fleet; Oikos Docker host. Enrolled 2026-07-08.
      enrolled_at: "2026-07-08T09:49:03Z"
      mesh_ip: 192.168.178.182
      hostname: mac-mini
  - slug: "ws:republic-laptop"
    type: workstation
    name: republic-laptop
    attributes:
      os: linux
      user: dtoro
      mesh: {netbird: {fqdn: republic-laptop.netbird.selfhosted}}

  # ─── LXCs ──────────────────────────────────────────────────────────
  - {slug: "lxc:jellyfin", type: lxc, name: jellyfin,
     attributes: {pve_id: 101, role: media-server, lan_ip: 192.168.8.246,
                  public_host: media.hubris.network,
                  note: "VAAPI transcode via Radeon 680M passthrough; migrated hubris→strong 2026-07-05"}}
  - {slug: "lxc:nfs-export", type: lxc, name: nfs-export,
     attributes: {pve_id: 102, role: storage-export, lan_ip: 192.168.8.200}}
  - {slug: "lxc:paperless", type: lxc, name: paperless,
     attributes: {pve_id: 103, role: document-archive, lan_ip: 192.168.8.130,
                  public_host: paperless.hubris.network}}
  - {slug: "lxc:gitea", type: lxc, name: gitea,
     attributes: {pve_id: 104, role: git-server, lan_ip: 192.168.8.121,
                  public_host: git.hubris.network,
                  note: "bare repos at /mnt/library/repos/dtoro/*.git"}}
  - {slug: "lxc:apps", type: lxc, name: apps,
     attributes: {pve_id: 105, role: docker-apps, lan_ip: 192.168.8.205,
                  age_pubkey: age1duyl8mkpgu80uv934dy8q7enqjms6yvdz264hme8uryuxmvvqesq6rusq0,
                  note: "legacy Oikos host; fallback during cutover (plan A6)"}}
  - {slug: "lxc:auth-outpost", type: lxc, name: auth-outpost,
     attributes: {pve_id: 106, role: authentik-gateway, lan_ip: 192.168.8.6}}
  - {slug: "lxc:dns", type: lxc, name: dns,
     attributes: {pve_id: 107, role: dns-server, lan_ip: 192.168.8.2}}
  - {slug: "lxc:nextcloud", type: lxc, name: nextcloud,
     attributes: {pve_id: 114, role: file-sync, lan_ip: 192.168.8.224,
                  public_host: cloud.hubris.network}}
  - {slug: "lxc:elementsynapse", type: lxc, name: elementsynapse,
     attributes: {pve_id: 118, role: matrix-server, lan_ip: 192.168.8.242,
                  public_host: matrix.hubris.network,
                  note: "migrated hubris→strong 2026-07-05"}}
  - {slug: "lxc:sophia", type: lxc, name: sophia,
     attributes: {pve_id: 119, role: workshop, lan_ip: 192.168.8.109}}
  - {slug: "lxc:mule-images", type: lxc, name: mule-images,
     attributes: {pve_id: 120, role: photo-management, lan_ip: 192.168.8.136,
                  public_host: photos.hubris.network}}
  - {slug: "lxc:caddy", type: lxc, name: caddy,
     attributes: {pve_id: 121, role: reverse-proxy, lan_ip: 192.168.8.175,
                  note: "terminates all *.hubris.network; /etc/caddy is a checkout of dtoro/caddy-conf"}}
  - {slug: "lxc:arriman", type: lxc, name: arriman,
     attributes: {pve_id: 122, role: arr-stack, lan_ip: 192.168.8.245,
                  public_hosts: [jellyseerr.hubris.network, qbit.hubris.network, sab.hubris.network],
                  note: "homarr/radarr/sonarr/lidarr/sab/qbit/bazarr/flaresolverr/prowlarr/jellyseerr; migrated to strong 2026-07-05"}}
  - {slug: "lxc:trmnl", type: lxc, name: trmnl,
     attributes: {pve_id: 128, role: trmnl-middleware, lan_ip: 192.168.8.211,
                  public_host: trmnl.hubris.network,
                  note: "not yet mesh/SOPS-enrolled"}}
  - {slug: "lxc:house", type: lxc, name: house,
     attributes: {pve_id: 129, role: family-planner, lan_ip: 192.168.8.244,
                  public_host: house.hubris.network,
                  age_pubkey: age1s07zs83ehtlg8jtwvr75ltc3c4cdlemfwjuxrwjtwkqxkl9tpggsyrzn2h,
                  note: "Yuvomi + WebDAV bridge to paperless; migrated to strong 2026-07-05"}}
  - {slug: "lxc:grimmory", type: lxc, name: grimmory,
     attributes: {pve_id: 130, role: book-library, lan_ip: 192.168.8.247,
                  public_host: books.hubris.network,
                  age_pubkey: age1uellsemnjrzgfg9fxw4jefpy05laxzggwnwhh6ny3wl7alyp6v8q0muxet}}
  - {slug: "lxc:teddycloud", type: lxc, name: teddycloud,
     attributes: {pve_id: 131, role: teddycloud, lan_ip: 192.168.8.150,
                  public_host: teddy.hubris.network,
                  note: "drift-caught 2026-07-06; no forward-auth gate on route; not a homelab client"}}
  - {slug: "lxc:rclone", type: lxc, name: rclone,
     attributes: {pve_id: 132, role: backup,
                  mesh: {netbird: {fqdn: rclone.netbird.selfhosted}},
                  age_pubkey: age1pwtdws2thdh7vzp2dzttl3zxgcs2tgpcsjsqgw3q04nyml4kvuqq467u4x}}
                  # verified live on hubris 2026-07-07 (pct list via MCP)
  - {slug: "lxc:seanime", type: lxc, name: seanime,
     attributes: {pve_id: 133, role: anime-media-server, lan_ip: 192.168.8.248,
                  public_host: seanime.hubris.network,
                  note: "systemd service at /opt/seanime; uses qbittorrent on arriman"}}
  - {slug: "lxc:romm", type: lxc, name: romm,
     attributes: {pve_id: 134, role: rom-manager, lan_ip: 192.168.8.249,
                  public_host: roms.hubris.network,
                  note: "docker compose + MariaDB sidecar at /opt/romm"}}

  # ─── VMs ───────────────────────────────────────────────────────────
  - {slug: "vm:zimaos", type: vm, name: zimaos,
     attributes: {pve_id: 100, role: nas-frontend-eval, lan_ip: 192.168.8.195,
                  public_host: zimaos.hubris.network}}
  - {slug: "vm:haos", type: vm, name: haos,
     attributes: {pve_id: 108, role: home-automation, lan_ip: 192.168.8.101}}

  # ─── Storage ───────────────────────────────────────────────────────
  - {slug: "pool:local-lvm-hubris", type: storage-pool, name: local-lvm (hubris),
     attributes: {type: lvm}}
  - {slug: "pool:library-hubris", type: storage-pool, name: library (hubris),
     attributes: {type: lvmthin, capacity_gb: 3700}}
     # 2nd Samsung 990 EVO Plus NVMe; backs /mnt/library ext4 via
     # /dev/mapper/library-library (knowledge/wiki/hosts/hubris.md)
  - {slug: "pool:ludo-lvm", type: storage-pool, name: ludo-lvm (strong),
     attributes: {type: lvm}}
  - {slug: "volume:library", type: volume, name: library,
     attributes: {path: /mnt/library, size_gb: 3700}}
  - {slug: "volume:media-local", type: volume, name: media-local,
     attributes: {path: /mnt/media_local}}
  - {slug: "backup:proton-drive", type: backup-target, name: proton-drive,
     attributes: {provider: proton, encrypted: true,
                  path: /mnt/backup,
                  note: "rclone stages here before pushing to Proton; freshness is checked on lxc:rclone via the backs-up-to edge"}}
  # The pre-deploy pg_dump written by scripts/deploy.sh on every push to main.
  # It was the lab's only untracked backup: its failure path is `|| echo
  # WARNING` inside the deploy script, so a broken dump was invisible until a
  # rollback needed it.
  - {slug: "backup:oikos-predeploy", type: backup-target, name: oikos-predeploy,
     attributes: {provider: local, encrypted: false,
                  path: /opt/oikos/backups,
                  note: "pre-deploy pg_dump on the mac-mini; one per deployed SHA"}}

  # ─── Services ──────────────────────────────────────────────────────
  - {slug: "service:proxmox-ui", type: service, name: proxmox_ui,
     attributes: {url: "https://proxmox.hubris.network", port: 8006,
                  doc_page: knowledge/wiki/hosts/hubris.md,
                  risk_notes: "hypervisor UI — changes affect every guest on the node"}}
  - {slug: "service:gitea", type: service, name: gitea,
     attributes: {url: "https://git.hubris.network", port: 3000,
                  doc_page: knowledge/wiki/containers/104-gitea.md,
                  risk_notes: "hosts all config repos + deploy webhooks; outage blocks auto-deploy and sync"}}
  - {slug: "service:caddy", type: service, name: caddy,
     attributes: {doc_page: knowledge/wiki/containers/121-caddy.md,
                  risk_notes: "wide blast radius — every *.hubris.network route rides on it"}}
  - {slug: "service:authentik", type: service, name: authentik,
     attributes: {url: "https://auth.hubris.network",
                  doc_page: knowledge/wiki/containers/106-auth-outpost.md,
                  note: "core on VPS since 2026-05-31; LAN outpost = auth-outpost (LXC 106) 192.168.8.6:9000",
                  risk_notes: "SSO provider — outage locks login to OIDC/forward-auth services"}}
  - {slug: "service:dns", type: service, name: dns,
     attributes: {doc_page: knowledge/wiki/containers/107-dns.md,
                  risk_notes: "LAN-wide resolver — misconfig breaks name resolution for every client"}}
  - {slug: "service:jellyfin", type: service, name: jellyfin,
     attributes: {url: "https://media.hubris.network",
                  doc_page: knowledge/wiki/containers/101-jellyfin.md,
                  risk_notes: "native Authentik OIDC (no forward-auth gate); VAAPI depends on GPU passthrough on strong"}}
  - {slug: "service:nextcloud", type: service, name: nextcloud,
     attributes: {url: "https://cloud.hubris.network",
                  doc_page: knowledge/wiki/containers/114-nextcloud.md}}
  - {slug: "service:paperless", type: service, name: paperless,
     attributes: {url: "https://paperless.hubris.network",
                  doc_page: knowledge/wiki/containers/103-paperless.md,
                  risk_notes: "document archive — data irreplaceable; DB operations are destructive-class"}}
  - {slug: "service:matrix", type: service, name: matrix,
     attributes: {url: "https://matrix.hubris.network",
                  doc_page: knowledge/wiki/containers/118-elementsynapse.md,
                  risk_notes: "alert/approval channel for Oikos — outage silences agent escalation"}}
  - {slug: "service:photos", type: service, name: photos,
     attributes: {url: "https://photos.hubris.network",
                  doc_page: knowledge/wiki/containers/120-mule-images.md}}
  - {slug: "service:arr-stack", type: service, name: arr_stack,
     attributes: {doc_page: knowledge/wiki/containers/122-arriman.md,
                  note: "jellyseerr / qbit / sab on docker compose"}}
  - {slug: "service:artifacto", type: service, name: artifacto,
     attributes: {url: "https://artifacto.hubris.network",
                  doc_page: knowledge/wiki/containers/105-apps.md}}
  - {slug: "service:trmnl", type: service, name: trmnl,
     attributes: {url: "https://trmnl.hubris.network",
                  doc_page: knowledge/wiki/containers/128-trmnl.md,
                  note: "TRMNL e-ink plugin middleware (polled by TRMNL cloud)"}}
  - {slug: "service:zimaos", type: service, name: zimaos,
     attributes: {url: "https://zimaos.hubris.network",
                  doc_page: knowledge/wiki/vms/100-zimaos.md}}
  - {slug: "service:haos", type: service, name: haos,
     attributes: {doc_page: knowledge/wiki/vms/108-haos.md}}
  - {slug: "service:teddycloud", type: service, name: teddycloud,
     attributes: {url: "https://teddy.hubris.network",
                  doc_page: knowledge/wiki/containers/131-teddycloud.md,
                  risk_notes: "no forward-auth gate — reachable by anyone on LAN/mesh"}}
  # The Go control plane itself: api/scheduler/notifier/web on the mac-mini,
  # and what mcp.hubris.network fronts since the cutover. It existed in the
  # database (created outside the seed) but was never declared here, so a
  # fresh seed could not resolve the routes-to edge below.
  - {slug: "service:oikos", type: service, name: oikos,
     attributes: {url: "https://oikos.hubris.network",
                  host: "ws:mac-mini",
                  ports: {api: 8090, web: 8091, nomos_gateway: 8092},
                  note: "homelab automation platform — api/scheduler/notifier/web on mac-mini docker compose (project name oikos)"}}
  - {slug: "service:homelab-mcp", type: service, name: homelab_mcp,
     attributes: {port: 9810, systemd_unit: homelab-mcp,
                  endpoint: "https://mcp.hubris.network/mcp",
                  doc_page: knowledge/wiki/infrastructure/homelab-context.md,
                  risk_notes: "agents' primary read surface — outage degrades every agent to grepping the clone"}}
  - {slug: "service:secrets-issuance", type: service, name: secrets_issuance,
     attributes: {port: 9820, systemd_unit: secrets-issuance,
                  endpoint: "https://secrets.hubris.network/issue",
                  doc_page: .agents/operations/agent-enrollment.md,
                  risk_notes: "identity issuance — security-sensitive; key operations are destructive-class"}}
  # Services derived from hosts.public_host (no legacy services entry):
  - {slug: "service:house", type: service, name: house,
     attributes: {url: "https://house.hubris.network", note: "Yuvomi family planner (derived)"}}
  - {slug: "service:grimmory", type: service, name: grimmory,
     attributes: {url: "https://books.hubris.network", note: derived}}
  - {slug: "service:seanime", type: service, name: seanime,
     attributes: {url: "https://seanime.hubris.network", port: 43211, note: derived}}
  - {slug: "service:romm", type: service, name: romm,
     attributes: {url: "https://roms.hubris.network", note: derived}}
  - {slug: "service:jellyseerr", type: service, name: jellyseerr,
     attributes: {url: "https://jellyseerr.hubris.network", note: derived (arriman)}}
  - {slug: "service:qbit", type: service, name: qbit,
     attributes: {url: "https://qbit.hubris.network", note: derived (arriman)}}
  - {slug: "service:sab", type: service, name: sab,
     attributes: {url: "https://sab.hubris.network", note: "derived (arriman); forward-auth gated"}}

  # ─── Config repos ──────────────────────────────────────────────────
  - {slug: "repo:caddy-conf", type: config-repo, name: dtoro/caddy-conf}
  - {slug: "repo:gitea-customizations", type: config-repo, name: dtoro/gitea-customizations}
  - {slug: "repo:mule-image", type: config-repo, name: dtoro/mule-image}
  - {slug: "repo:artifacto", type: config-repo, name: dtoro/Artifacto}
  - {slug: "repo:terminalito", type: config-repo, name: dtoro/terminalito}
  - {slug: "repo:homelab-docs", type: config-repo, name: dtoro/oikos}

  # ─── Ingress routes (Caddy, *.hubris.network) ──────────────────────
  - {slug: "ingress:proxmox.hubris.network", type: ingress-route, name: proxmox.hubris.network}
  - {slug: "ingress:git.hubris.network", type: ingress-route, name: git.hubris.network}
  - {slug: "ingress:auth.hubris.network", type: ingress-route, name: auth.hubris.network}
  - {slug: "ingress:media.hubris.network", type: ingress-route, name: media.hubris.network}
  - {slug: "ingress:cloud.hubris.network", type: ingress-route, name: cloud.hubris.network}
  - {slug: "ingress:paperless.hubris.network", type: ingress-route, name: paperless.hubris.network,
     attributes: {forward_auth: true}}
  - {slug: "ingress:matrix.hubris.network", type: ingress-route, name: matrix.hubris.network}
  - {slug: "ingress:photos.hubris.network", type: ingress-route, name: photos.hubris.network}
  - {slug: "ingress:artifacto.hubris.network", type: ingress-route, name: artifacto.hubris.network}
  - {slug: "ingress:trmnl.hubris.network", type: ingress-route, name: trmnl.hubris.network}
  - {slug: "ingress:zimaos.hubris.network", type: ingress-route, name: zimaos.hubris.network}
  - {slug: "ingress:teddy.hubris.network", type: ingress-route, name: teddy.hubris.network,
     attributes: {forward_auth: false}}
  - {slug: "ingress:mcp.hubris.network", type: ingress-route, name: mcp.hubris.network}
  - {slug: "ingress:secrets.hubris.network", type: ingress-route, name: secrets.hubris.network}
  - {slug: "ingress:house.hubris.network", type: ingress-route, name: house.hubris.network}
  - {slug: "ingress:books.hubris.network", type: ingress-route, name: books.hubris.network}
  - {slug: "ingress:seanime.hubris.network", type: ingress-route, name: seanime.hubris.network}
  - {slug: "ingress:roms.hubris.network", type: ingress-route, name: roms.hubris.network}
  - {slug: "ingress:jellyseerr.hubris.network", type: ingress-route, name: jellyseerr.hubris.network}
  - {slug: "ingress:qbit.hubris.network", type: ingress-route, name: qbit.hubris.network}
  - {slug: "ingress:sab.hubris.network", type: ingress-route, name: sab.hubris.network,
     attributes: {forward_auth: true}}

  # ─── TLS certificates (Caddy-managed, *.hubris.network) ───────────
  # Each cert's expiry is probed by dialing Caddy's lab IP (`dial`) with SNI
  # set to the hostname — the scheduler container has no mesh/split-horizon
  # DNS, so it can't resolve *.hubris.network, but it CAN reach Caddy on the
  # lab LAN.
  - {slug: "cert:proxmox.hubris.network", type: certificate, name: proxmox.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:git.hubris.network", type: certificate, name: git.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:auth.hubris.network", type: certificate, name: auth.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:media.hubris.network", type: certificate, name: media.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:cloud.hubris.network", type: certificate, name: cloud.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:paperless.hubris.network", type: certificate, name: paperless.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:matrix.hubris.network", type: certificate, name: matrix.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:photos.hubris.network", type: certificate, name: photos.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:artifacto.hubris.network", type: certificate, name: artifacto.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:trmnl.hubris.network", type: certificate, name: trmnl.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:zimaos.hubris.network", type: certificate, name: zimaos.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:teddy.hubris.network", type: certificate, name: teddy.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:mcp.hubris.network", type: certificate, name: mcp.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:house.hubris.network", type: certificate, name: house.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:books.hubris.network", type: certificate, name: books.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:seanime.hubris.network", type: certificate, name: seanime.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:roms.hubris.network", type: certificate, name: roms.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:jellyseerr.hubris.network", type: certificate, name: jellyseerr.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:qbit.hubris.network", type: certificate, name: qbit.hubris.network, attributes: {dial: "192.168.8.175"}}
  - {slug: "cert:sab.hubris.network", type: certificate, name: sab.hubris.network, attributes: {dial: "192.168.8.175"}}

  # ─── Governance ────────────────────────────────────────────────────
  - {slug: "person:dtoro", type: person, name: dtoro,
     attributes: {matrix_id: "@dtoro:avispero"}}
  - {slug: "idp:authentik", type: identity-provider, name: authentik,
     attributes: {issuer: "https://auth.hubris.network", auth_mode: both}}
  - {slug: "agent:nomos", type: agent, name: nomos,
      state: active,
      attributes: {gateway_port: 8092, session_mode: smart_approve, note: "Phase 4 — Docker gateway mode"}}
  - {slug: "agent:oikos", type: agent, name: oikos,
     state: planned,
     attributes: {note: "the OS control loop itself (scheduler/actuator) as an actor"}}

  # ─── Archaeology (state: destroyed — kept for "what happened to X?") ─
  - {slug: "lxc:claudio-bot", type: lxc, name: claudio-bot, state: destroyed,
     attributes: {pve_id: 123, destroyed: "2026-06-04", reason: "replaced by Nomos Agent on mac-mini"}}
  - {slug: "lxc:plato", type: lxc, name: plato, state: destroyed,
     attributes: {pve_id: 126, destroyed: "2026-06-28", reason: "notes workspace decommissioned; data at /mnt/library/documents/plato"}}
  - {slug: "lxc:mule-photos-new", type: lxc, name: mule-photos-new, state: destroyed,
     attributes: {pve_id: 127, destroyed: "2026-05-22", reason: "PhotoPrism test stack promoted to LXC 120"}}
  - {slug: "lxc:heaper", type: lxc, name: heaper, state: destroyed,
     attributes: {pve_id: 116, destroyed: "2026-05-14", reason: "decommissioned; data at /mnt/library/heaper"}}
  - {slug: "lxc:syncthing", type: lxc, name: syncthing, state: destroyed,
     attributes: {pve_id: 109, destroyed: "2026-05-14", reason: "decommissioned; library subtree was empty"}}
  - {slug: "lxc:seafile", type: lxc, name: seafile, state: destroyed,
     attributes: {pve_id: 125, destroyed: "2026-05-13", reason: "Seafile Pro evaluation rejected"}}
  - {slug: "lxc:arr-yunohost", type: lxc, name: arr-yunohost, state: destroyed,
     attributes: {pve_id: 100, destroyed: "2026-04-28", reason: "migrated to docker stack on arriman (LXC 122)"}}
  - {slug: "lxc:flaresolverr", type: lxc, name: flaresolverr, state: destroyed,
     attributes: {pve_id: 106, destroyed: "2026-04-28", reason: "folded into the arriman docker compose"}}
  - {slug: "lxc:marimo", type: lxc, name: marimo, state: destroyed,
     attributes: {pve_id: 107, destroyed: "2026-04-28", reason: decommissioned}}
  - {slug: "lxc:photoprism", type: lxc, name: photoprism, state: destroyed,
     attributes: {pve_id: 110, destroyed: "2026-04-28", reason: "replaced by mule-images (LXC 120)"}}
  - {slug: "lxc:karakeep", type: lxc, name: karakeep, state: destroyed,
     attributes: {pve_id: 111, destroyed: "2026-04-28", reason: decommissioned}}
  - {slug: "lxc:immich", type: lxc, name: immich, state: destroyed,
     attributes: {pve_id: 112, destroyed: "2026-04-28", reason: "replaced by mule-images (LXC 120)"}}
  - {slug: "lxc:reticulum", type: lxc, name: reticulum, state: destroyed,
     attributes: {pve_id: 115, destroyed: "2026-04-28", reason: decommissioned}}

relationships:

  # ─── Cluster membership ────────────────────────────────────────────
  - {source: "host:hubris", target: "cluster:homelab", type: member-of}
  - {source: "host:strong", target: "cluster:homelab", type: member-of}

  # ─── Location ──────────────────────────────────────────────────────
  - {source: "host:hubris", target: "site:home", type: located-at}
  - {source: "host:strong", target: "site:home", type: located-at}
  - {source: "ws:mac-mini", target: "site:home", type: located-at}
  - {source: "host:netbird-vps", target: "site:ionos-dc", type: located-at}

  # ─── Hosting (machine → guest) ─────────────────────────────────────
  - {source: "host:hubris", target: "lxc:nfs-export", type: hosts}
  - {source: "host:hubris", target: "lxc:paperless", type: hosts}
  - {source: "host:hubris", target: "lxc:gitea", type: hosts}
  - {source: "host:hubris", target: "lxc:apps", type: hosts}
  - {source: "host:hubris", target: "lxc:auth-outpost", type: hosts}
  - {source: "host:hubris", target: "lxc:dns", type: hosts}
  - {source: "host:hubris", target: "lxc:nextcloud", type: hosts}
  - {source: "host:hubris", target: "lxc:sophia", type: hosts}
  - {source: "host:hubris", target: "lxc:mule-images", type: hosts}
  - {source: "host:hubris", target: "lxc:caddy", type: hosts}
  - {source: "host:hubris", target: "lxc:trmnl", type: hosts}
  - {source: "host:hubris", target: "lxc:teddycloud", type: hosts}
  - {source: "host:hubris", target: "vm:zimaos", type: hosts}
  - {source: "host:hubris", target: "vm:haos", type: hosts}
  - {source: "host:strong", target: "lxc:jellyfin", type: hosts}
  - {source: "host:strong", target: "lxc:elementsynapse", type: hosts}
  - {source: "host:strong", target: "lxc:arriman", type: hosts}
  - {source: "host:strong", target: "lxc:house", type: hosts}
  - {source: "host:strong", target: "lxc:grimmory", type: hosts}
  - {source: "host:strong", target: "lxc:seanime", type: hosts}
  - {source: "host:strong", target: "lxc:romm", type: hosts}
  - {source: "host:hubris", target: "lxc:rclone", type: hosts}

  # ─── Service provision (compute → service) ─────────────────────────
  - {source: "host:hubris", target: "service:proxmox-ui", type: provides}
  - {source: "lxc:gitea", target: "service:gitea", type: provides}
  - {source: "lxc:caddy", target: "service:caddy", type: provides}
  - {source: "host:netbird-vps", target: "service:authentik", type: provides}
  - {source: "lxc:dns", target: "service:dns", type: provides}
  - {source: "lxc:jellyfin", target: "service:jellyfin", type: provides}
  - {source: "lxc:nextcloud", target: "service:nextcloud", type: provides}
  - {source: "lxc:paperless", target: "service:paperless", type: provides}
  - {source: "lxc:elementsynapse", target: "service:matrix", type: provides}
  - {source: "lxc:mule-images", target: "service:photos", type: provides}
  - {source: "lxc:arriman", target: "service:arr-stack", type: provides}
  - {source: "lxc:arriman", target: "service:jellyseerr", type: provides}
  - {source: "lxc:arriman", target: "service:qbit", type: provides}
  - {source: "lxc:arriman", target: "service:sab", type: provides}
  - {source: "lxc:apps", target: "service:artifacto", type: provides}
  - {source: "lxc:apps", target: "service:homelab-mcp", type: provides}
  - {source: "lxc:apps", target: "service:secrets-issuance", type: provides}
  - {source: "lxc:trmnl", target: "service:trmnl", type: provides}
  - {source: "vm:zimaos", target: "service:zimaos", type: provides}
  - {source: "vm:haos", target: "service:haos", type: provides}
  - {source: "lxc:teddycloud", target: "service:teddycloud", type: provides}
  - {source: "lxc:house", target: "service:house", type: provides}
  - {source: "lxc:grimmory", target: "service:grimmory", type: provides}
  - {source: "lxc:seanime", target: "service:seanime", type: provides}
  - {source: "lxc:romm", target: "service:romm", type: provides}

  # ─── Ingress → service ─────────────────────────────────────────────
  - {source: "ingress:proxmox.hubris.network", target: "service:proxmox-ui", type: routes-to}
  - {source: "ingress:git.hubris.network", target: "service:gitea", type: routes-to}
  - {source: "ingress:auth.hubris.network", target: "service:authentik", type: routes-to}
  - {source: "ingress:media.hubris.network", target: "service:jellyfin", type: routes-to}
  - {source: "ingress:cloud.hubris.network", target: "service:nextcloud", type: routes-to}
  - {source: "ingress:paperless.hubris.network", target: "service:paperless", type: routes-to}
  - {source: "ingress:matrix.hubris.network", target: "service:matrix", type: routes-to}
  - {source: "ingress:photos.hubris.network", target: "service:photos", type: routes-to}
  - {source: "ingress:artifacto.hubris.network", target: "service:artifacto", type: routes-to}
  - {source: "ingress:trmnl.hubris.network", target: "service:trmnl", type: routes-to}
  - {source: "ingress:zimaos.hubris.network", target: "service:zimaos", type: routes-to}
  - {source: "ingress:teddy.hubris.network", target: "service:teddycloud", type: routes-to}
  # Re-pointed from service:homelab-mcp, which is deprecated — the Python MCP
  # server on apps/105 was stopped at the Go cutover and mcp.hubris.network now
  # fronts the Go api. Nomos recorded this correctly on 2026-07-12; the seed
  # was the stale one, and re-asserting the old edge alongside it is what made
  # ingress:mcp a cardinality violation.
  - {source: "ws:mac-mini", target: "service:oikos", type: provides}
  - {source: "ingress:mcp.hubris.network", target: "service:oikos", type: routes-to}
  # Every public hostname is terminated by caddy. Without these the
  # reverse proxy — the single widest point of failure in the lab —
  # had a blast radius of one.
  - {source: "ingress:proxmox.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:git.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:auth.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:media.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:cloud.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:paperless.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:matrix.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:photos.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:artifacto.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:trmnl.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:zimaos.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:teddy.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:mcp.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:secrets.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:house.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:books.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:seanime.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:roms.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:jellyseerr.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:qbit.hubris.network", target: "service:caddy", type: served-by}
  - {source: "ingress:sab.hubris.network", target: "service:caddy", type: served-by}
  # Each public route is served with its TLS certificate.
  - {source: "ingress:proxmox.hubris.network", target: "cert:proxmox.hubris.network", type: uses-certificate}
  - {source: "ingress:git.hubris.network", target: "cert:git.hubris.network", type: uses-certificate}
  - {source: "ingress:auth.hubris.network", target: "cert:auth.hubris.network", type: uses-certificate}
  - {source: "ingress:media.hubris.network", target: "cert:media.hubris.network", type: uses-certificate}
  - {source: "ingress:cloud.hubris.network", target: "cert:cloud.hubris.network", type: uses-certificate}
  - {source: "ingress:paperless.hubris.network", target: "cert:paperless.hubris.network", type: uses-certificate}
  - {source: "ingress:matrix.hubris.network", target: "cert:matrix.hubris.network", type: uses-certificate}
  - {source: "ingress:photos.hubris.network", target: "cert:photos.hubris.network", type: uses-certificate}
  - {source: "ingress:artifacto.hubris.network", target: "cert:artifacto.hubris.network", type: uses-certificate}
  - {source: "ingress:trmnl.hubris.network", target: "cert:trmnl.hubris.network", type: uses-certificate}
  - {source: "ingress:zimaos.hubris.network", target: "cert:zimaos.hubris.network", type: uses-certificate}
  - {source: "ingress:teddy.hubris.network", target: "cert:teddy.hubris.network", type: uses-certificate}
  - {source: "ingress:mcp.hubris.network", target: "cert:mcp.hubris.network", type: uses-certificate}
  - {source: "ingress:house.hubris.network", target: "cert:house.hubris.network", type: uses-certificate}
  - {source: "ingress:books.hubris.network", target: "cert:books.hubris.network", type: uses-certificate}
  - {source: "ingress:seanime.hubris.network", target: "cert:seanime.hubris.network", type: uses-certificate}
  - {source: "ingress:roms.hubris.network", target: "cert:roms.hubris.network", type: uses-certificate}
  - {source: "ingress:jellyseerr.hubris.network", target: "cert:jellyseerr.hubris.network", type: uses-certificate}
  - {source: "ingress:qbit.hubris.network", target: "cert:qbit.hubris.network", type: uses-certificate}
  - {source: "ingress:sab.hubris.network", target: "cert:sab.hubris.network", type: uses-certificate}

  - {source: "ingress:secrets.hubris.network", target: "service:secrets-issuance", type: routes-to}
  - {source: "ingress:house.hubris.network", target: "service:house", type: routes-to}
  - {source: "ingress:books.hubris.network", target: "service:grimmory", type: routes-to}
  - {source: "ingress:seanime.hubris.network", target: "service:seanime", type: routes-to}
  - {source: "ingress:roms.hubris.network", target: "service:romm", type: routes-to}
  - {source: "ingress:jellyseerr.hubris.network", target: "service:jellyseerr", type: routes-to}
  - {source: "ingress:qbit.hubris.network", target: "service:qbit", type: routes-to}
  - {source: "ingress:sab.hubris.network", target: "service:sab", type: routes-to}

  # ─── Auth edges ────────────────────────────────────────────────────
  - {source: "ingress:paperless.hubris.network", target: "idp:authentik", type: secured-by}
  - {source: "ingress:sab.hubris.network", target: "idp:authentik", type: secured-by}
  - {source: "service:jellyfin", target: "idp:authentik", type: authenticates-via}
  - {source: "idp:authentik", target: "person:dtoro", type: authenticates}

  # ─── Config repos ──────────────────────────────────────────────────
  - {source: "service:caddy", target: "repo:caddy-conf", type: configured-by}
  - {source: "service:gitea", target: "repo:gitea-customizations", type: configured-by}
  - {source: "service:photos", target: "repo:mule-image", type: configured-by}
  - {source: "service:artifacto", target: "repo:artifacto", type: configured-by}
  - {source: "service:trmnl", target: "repo:terminalito", type: configured-by}
  - {source: "service:homelab-mcp", target: "repo:homelab-docs", type: configured-by}
  - {source: "service:secrets-issuance", target: "repo:homelab-docs", type: configured-by}

  # ─── Service dependencies (blast-radius edges; grow over time) ─────
  - {source: "service:paperless", target: "service:authentik", type: depends-on}
  - {source: "service:homelab-mcp", target: "service:gitea", type: depends-on}
  - {source: "service:jellyseerr", target: "service:jellyfin", type: depends-on}
  - {source: "service:seanime", target: "service:qbit", type: depends-on}
  - {source: "service:house", target: "service:paperless", type: depends-on}
  - {source: "service:sab", target: "service:authentik", type: depends-on}

  # ─── Network membership ────────────────────────────────────────────
  - {source: "host:hubris", target: "lan:lab", type: connects-via}
  - {source: "host:hubris", target: "mesh:netbird", type: connects-via}
  - {source: "host:strong", target: "lan:household", type: connects-via}
  - {source: "ws:mac-mini", target: "lan:household", type: connects-via}
  - {source: "ws:mac-mini", target: "mesh:netbird", type: connects-via}
  - {source: "ws:republic-laptop", target: "mesh:netbird", type: connects-via}
  - {source: "host:netbird-vps", target: "mesh:netbird", type: connects-via}
  - {source: "lxc:rclone", target: "mesh:netbird", type: connects-via}
  - {source: "lxc:jellyfin", target: "lan:lab", type: connects-via}
  - {source: "lxc:nfs-export", target: "lan:lab", type: connects-via}
  - {source: "lxc:paperless", target: "lan:lab", type: connects-via}
  - {source: "lxc:gitea", target: "lan:lab", type: connects-via}
  - {source: "lxc:apps", target: "lan:lab", type: connects-via}
  - {source: "lxc:apps", target: "mesh:tailscale", type: connects-via}
  - {source: "lxc:auth-outpost", target: "lan:lab", type: connects-via}
  - {source: "lxc:dns", target: "lan:lab", type: connects-via}
  - {source: "lxc:nextcloud", target: "lan:lab", type: connects-via}
  - {source: "lxc:elementsynapse", target: "lan:lab", type: connects-via}
  - {source: "lxc:sophia", target: "lan:lab", type: connects-via}
  - {source: "lxc:mule-images", target: "lan:lab", type: connects-via}
  - {source: "lxc:caddy", target: "lan:lab", type: connects-via}
  - {source: "lxc:arriman", target: "lan:lab", type: connects-via}
  - {source: "lxc:trmnl", target: "lan:lab", type: connects-via}
  - {source: "lxc:house", target: "lan:lab", type: connects-via}
  - {source: "lxc:grimmory", target: "lan:lab", type: connects-via}
  - {source: "lxc:teddycloud", target: "lan:lab", type: connects-via}
  - {source: "lxc:seanime", target: "lan:lab", type: connects-via}
  - {source: "lxc:romm", target: "lan:lab", type: connects-via}
  - {source: "vm:zimaos", target: "lan:lab", type: connects-via}
  - {source: "vm:haos", target: "lan:lab", type: connects-via}

  # ─── Storage ───────────────────────────────────────────────────────
  - {source: "pool:ludo-lvm", target: "volume:media-local", type: contains}
  - {source: "pool:library-hubris", target: "volume:library", type: contains}
  - {source: "host:hubris", target: "volume:library", type: mounts,
     attributes: {mount_point: /mnt/library}}
  - {source: "lxc:jellyfin", target: "volume:media-local", type: mounts,
     attributes: {mount_point: /mnt/media_local}}
  - {source: "lxc:paperless", target: "volume:library", type: mounts,
     attributes: {mount_point: /mnt/library}}
  - {source: "lxc:gitea", target: "volume:library", type: mounts,
     attributes: {mount_point: /mnt/library}}
  - {source: "lxc:apps", target: "volume:library", type: mounts,
     attributes: {mount_point: /mnt/library}}
  - {source: "lxc:nextcloud", target: "volume:library", type: mounts,
     attributes: {mount_point: /mnt/library}}
  - {source: "lxc:sophia", target: "volume:library", type: mounts,
     attributes: {mount_point: /mnt/library}}
  - {source: "lxc:mule-images", target: "volume:library", type: mounts,
     attributes: {mount_point: /mnt/library}}
  - {source: "lxc:arriman", target: "volume:media-local", type: mounts,
     attributes: {mount_point: /mnt/media_local}}
  - {source: "lxc:grimmory", target: "volume:media-local", type: mounts,
     attributes: {mount_point: /mnt/media_local}}
  - {source: "lxc:teddycloud", target: "volume:library", type: mounts,
     attributes: {mount_point: /mnt/library}}
  - {source: "lxc:seanime", target: "volume:media-local", type: mounts,
     attributes: {mount_point: /mnt/media_local/anime}}
  - {source: "lxc:romm", target: "volume:media-local", type: mounts,
     attributes: {mount_point: /mnt/media_local}}
  - {source: "lxc:jellyfin", target: "pool:ludo-lvm", type: stores-on}
  - {source: "lxc:arriman", target: "pool:ludo-lvm", type: stores-on}
  - {source: "lxc:grimmory", target: "pool:ludo-lvm", type: stores-on}
  - {source: "lxc:romm", target: "pool:ludo-lvm", type: stores-on}
  - {source: "lxc:teddycloud", target: "pool:local-lvm-hubris", type: stores-on}
  - {source: "lxc:rclone", target: "backup:proton-drive", type: backs-up-to}
  # The mac-mini writes the pre-deploy dumps, so it is also where the freshness
  # check runs — checkdefaults resolves a backup-target's host by walking this
  # edge backwards.
  - {source: "ws:mac-mini", target: "backup:oikos-predeploy", type: backs-up-to}

  # ─── Governance ────────────────────────────────────────────────────
  - {source: "person:dtoro", target: "agent:nomos", type: owns}
  - {source: "person:dtoro", target: "agent:oikos", type: owns}
