# Oikos ontology — the systems model of the homelab. # # This file defines the closed vocabulary Oikos reasons with: entity # types (grouped into eight domains), typed relationships (with inverses), # and the node lifecycle. inventory.yaml holds the *instances*; this file # defines what those instances and their fields MEAN, so agents, the # decision classifier, and the topology generator interpret them # identically. See OIKOS.md for the operating model. # # Rule of completeness: if something can break, be changed, or hold data, # it has an entity type here and edges to the things it touches. domains: physical: description: Hardware and environment. entity_types: [site, machine, ups, sensor, peripheral] compute: description: Things that execute workloads. entity_types: [proxmox-host, lxc, vm, workstation, external-host, device] network: description: How things reach each other. entity_types: [lan, mesh, dns-zone, dns-record, ingress-route, certificate, firewall-rule] storage: description: Where data lives and how it survives. entity_types: [storage-pool, volume, mount, backup-target, dataset] software: description: What runs and how it is configured and shipped. entity_types: [service, application, config-repo, package-set, deploy-pipeline] identity_access: description: Who and what may do which things. entity_types: [person, identity-provider, account, secret, key, access-grant] operations: description: The OS's own working objects. entity_types: [agent, runbook, plan, change, incident, signal, approval, report] external: description: Dependencies outside the lab's control. entity_types: [domain-registration, cloud-service, isp-link, vendor-dependency] # Relationships. `source:` says which inventory/repo data expresses the edge # today (thin = not yet structured, derive from docs until backfilled). relationships: hosts: inverse: runs-on example: hubris hosts lxc:apps source: hosts..host + pve_id provides: inverse: provided-by example: lxc:apps provides service:homelab_mcp source: hosts..runs + services..backend mounts: inverse: mounted-by example: lxc:jellyfin mounts /mnt/media_local from strong source: hosts..mounts (extend with from:) stores-on: inverse: stores-for example: lxc:jellyfin rootfs stores-on storage-pool:ludo-lvm source: hosts..storage (new field) routes-to: inverse: routed-via example: ingress-route:media.hubris.network routes-to service:jellyfin source: services..url/public_host + dtoro/caddy-conf resolves-to: inverse: resolved-from example: dns-record:media.hubris.network resolves-to caddy lan_ip source: Technitium split-horizon zone (LXC 107) + dns-sync job secured-by: inverse: secures example: ingress-route:paperless secured-by identity-provider:authentik source: caddy-conf forward-auth blocks + service auth notes authenticates-via: inverse: authenticates example: service:jellyfin authenticates-via authentik (native OIDC) source: services..auth (new field, from risk_notes/docs) connects-via: inverse: connects example: workstation:mac-mini connects-via mesh:netbird source: hosts..mesh can-decrypt: inverse: readable-by example: lxc:apps can-decrypt secret:gitea-pat source: .sops.yaml path rules + hosts..age_pubkey configured-by: inverse: configures example: lxc:caddy configured-by config-repo:dtoro/caddy-conf source: services..config_repo (new field) deploys-to: inverse: deployed-from example: deploy-pipeline:webhook-10 deploys-to /opt/homelab-mcp on lxc:apps source: infrastructure/auto-deploy.md table monitors: inverse: monitored-by example: agent:scheduler monitors service:* (Week 3) source: oikos/scheduler config depends-on: inverse: dependency-of example: service:paperless depends-on service:authentik source: hosts/services depends_on (new field) backs-up-to: inverse: backup-of example: dataset:nextcloud-data backs-up-to backup-target:proton-drive source: infrastructure backups docs → structured field (thin) documents: inverse: documented-by example: containers/101-jellyfin.md documents lxc:jellyfin source: generated see_also / services..doc_page powered-by: inverse: powers example: machine:hubris powered-by ups (future, thin record) source: physical domain (thin) registered-with: inverse: registrar-of example: domain-registration:hubris.network registered-with registrar source: external domain (thin) # Node lifecycle. Stored as `state:` on each inventory host entry # (absent = active, for backward compatibility). Transitions are runbooks # (Week 2); drift detectors (Week 3) verify declared state matches reality. lifecycle: states: [planned, provisioning, active, migrating, deprecated, destroyed] default: active transitions: planned->provisioning: requires: [inventory-entry, ip-reserved, storage-pool-chosen, doc-page-stub] provisioning->active: requires: [age-key-enrolled-if-needed, mesh-joined-if-needed, ingress-live-if-public, health-check-answering, doc-page-complete, ledger-entry] active->migrating: requires: [preflight, backup-verified] migrating->active: requires: [post-verify, caddy-backends-checked, mounts-checked, docs-updated] active->deprecated: requires: [replacement-live-or-role-retired] complete_when: no inbound depends-on / routes-to edges remain deprecated->destroyed: requires: [backups-verified, secrets-revoked-and-rekeyed, ingress-and-dns-removed, archaeology-entry, ledger-entry]