- classifyAndGate: escalate read-only commands on lxc: targets that touch /opt/, /etc/, /var/lib/ to config_mutation. The classifier scores command text only, not the SSH transport layer — SSH-ing into a container to read config is riskier than pct exec from the host. - ontology: standalone-server monitoring override from inherited [ping, resource, updates] to [http]. VPS-like machines may not be SSH/ICMP-reachable from the scheduler; HTTP is the LCD liveness signal. Entities with full SSH can override per-entity.
1040 lines
34 KiB
YAML
1040 lines
34 KiB
YAML
# Oikos ontology seed — the systems model of the homelab.
|
|
#
|
|
# Bootstraps entity_types / relationship_types / lifecycle_defs on first
|
|
# deploy (migration 001). After ingest the DB is authoritative; this file
|
|
# is regenerated by `GET /api/v1/export` for DR + version control.
|
|
#
|
|
# Conventions:
|
|
# - entity type names are kebab-case
|
|
# - `parent:` builds the is-a hierarchy; `abstract: true` types cannot be
|
|
# instantiated (validation walks the hierarchy for relationship
|
|
# endpoints and policy rules — plan R3-1)
|
|
# - `layer:` one of meta | infrastructure | governance | cognition
|
|
# - relationship `cardinality:` describes source→target multiplicity:
|
|
# one-to-one | one-to-many | many-to-one | many-to-many
|
|
# - relationship endpoints may name abstract types
|
|
# - lifecycle transition `requires:` entries are NAMED CHECKS implemented
|
|
# in Go (internal/ontology); the DB stores which checks gate a
|
|
# transition, the code implements them
|
|
# - mount details (mount_point, options) live as ATTRIBUTES on `mounts`
|
|
# edges, not as a separate entity type
|
|
#
|
|
# 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.
|
|
|
|
version: 1
|
|
|
|
# ─── Lifecycles ────────────────────────────────────────────────────────
|
|
|
|
lifecycles:
|
|
infrastructure:
|
|
states: [planned, provisioning, active, migrating, failed, deprecated, destroyed]
|
|
default_state: active # legacy inventory entries without state are active
|
|
terminal_states: [destroyed]
|
|
transitions:
|
|
planned:
|
|
provisioning: {requires: [inventory-entry, ip-reserved, storage-pool-chosen, doc-page-stub]}
|
|
destroyed: {requires: [cancelled-note]}
|
|
provisioning:
|
|
active: {requires: [age-key-enrolled-if-needed, mesh-joined-if-needed,
|
|
ingress-live-if-public, health-check-answering,
|
|
doc-page-complete]}
|
|
failed: {requires: []}
|
|
active:
|
|
migrating: {requires: [preflight, backup-verified]}
|
|
deprecated: {requires: [replacement-live-or-role-retired]}
|
|
failed: {requires: []}
|
|
migrating:
|
|
active: {requires: [post-verify, caddy-backends-checked, mounts-checked, docs-updated]}
|
|
failed: {requires: []}
|
|
failed:
|
|
active: {requires: [recovery-verified]}
|
|
deprecated: {requires: [write-off-note]}
|
|
deprecated:
|
|
active: {requires: [un-deprecate-note]}
|
|
destroyed: {requires: [backups-verified, secrets-revoked-and-rekeyed,
|
|
ingress-and-dns-removed, no-inbound-edges,
|
|
archaeology-entry]}
|
|
|
|
signal:
|
|
states: [raised, acknowledged, acting, muted, resolved, failed]
|
|
default_state: raised
|
|
terminal_states: [resolved]
|
|
transitions:
|
|
raised:
|
|
acknowledged: {requires: []}
|
|
muted: {requires: [mute-ttl-set]}
|
|
resolved: {requires: [condition-cleared]}
|
|
acknowledged:
|
|
acting: {requires: [classification-exists]}
|
|
resolved: {requires: []}
|
|
muted: {requires: [mute-ttl-set]}
|
|
acting:
|
|
resolved: {requires: [verification-passed]}
|
|
raised: {requires: [retry-budget-remaining]}
|
|
failed: {requires: []}
|
|
failed:
|
|
acknowledged: {requires: [operator-retry]}
|
|
muted:
|
|
raised: {requires: [mute-ttl-expired]}
|
|
|
|
execution:
|
|
states: [proposed, approved, auto_approved, denied, expired, executing,
|
|
verifying, verified, failed, timed_out, cancelled, rolled_back,
|
|
rollback_failed]
|
|
default_state: proposed
|
|
terminal_states: [verified, failed, denied, expired, cancelled,
|
|
rolled_back, rollback_failed]
|
|
transitions:
|
|
proposed:
|
|
approved: {requires: [operator-approval]}
|
|
auto_approved: {requires: [autonomy-allows]}
|
|
denied: {requires: []}
|
|
approved:
|
|
executing: {requires: [approval-token-valid]}
|
|
expired: {requires: [approval-ttl-elapsed]}
|
|
auto_approved:
|
|
executing: {requires: []}
|
|
executing:
|
|
verified: {requires: [verification-passed]}
|
|
failed: {requires: []}
|
|
timed_out: {requires: []}
|
|
cancelled: {requires: [operator-abort]}
|
|
timed_out:
|
|
verifying: {requires: []} # check if the command completed anyway
|
|
verifying:
|
|
verified: {requires: [verification-passed]}
|
|
failed: {requires: []}
|
|
failed:
|
|
rolled_back: {requires: [rollback-procedure-exists]}
|
|
rollback_failed: {requires: []}
|
|
|
|
approval:
|
|
states: [pending, approved, denied, expired, revoked]
|
|
default_state: pending
|
|
terminal_states: [denied, expired, revoked]
|
|
transitions:
|
|
pending:
|
|
approved: {requires: [token-verified]}
|
|
denied: {requires: []}
|
|
expired: {requires: [ttl-elapsed]}
|
|
approved:
|
|
revoked: {requires: [not-yet-executing]}
|
|
|
|
pattern:
|
|
states: [hypothesized, validated, active, deprecated, invalidated]
|
|
default_state: hypothesized
|
|
terminal_states: [deprecated, invalidated]
|
|
transitions:
|
|
hypothesized:
|
|
validated: {requires: [evidence-count-5plus, confidence-0.7plus]}
|
|
invalidated: {requires: []}
|
|
validated:
|
|
active: {requires: [operator-approval]} # S4: never automatic
|
|
invalidated: {requires: []}
|
|
active:
|
|
deprecated: {requires: []}
|
|
invalidated: {requires: [contradicting-evidence]}
|
|
|
|
skill:
|
|
states: [drafted, tested, active, refined, failed, deprecated]
|
|
default_state: drafted
|
|
terminal_states: [deprecated]
|
|
transitions:
|
|
drafted:
|
|
tested: {requires: [test-execution-recorded]}
|
|
deprecated: {requires: []}
|
|
tested:
|
|
active: {requires: [operator-approval]}
|
|
failed: {requires: []}
|
|
failed:
|
|
drafted: {requires: []}
|
|
active:
|
|
refined: {requires: [new-version-created]}
|
|
deprecated: {requires: []}
|
|
refined:
|
|
active: {requires: [operator-approval]}
|
|
|
|
# ─── Entity types ──────────────────────────────────────────────────────
|
|
# domain: physical | compute | network | storage | software | external |
|
|
# identity | cognition
|
|
|
|
entity_types:
|
|
|
|
# Root
|
|
entity:
|
|
abstract: true
|
|
domain: meta
|
|
layer: meta
|
|
description: Root abstract type. Relationship endpoints that accept any
|
|
entity (documented-by, procedure-for, checks) reference this.
|
|
|
|
# ── Infrastructure / physical ──
|
|
site:
|
|
parent: entity
|
|
domain: physical
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Physical location (home, VPS datacenter).
|
|
monitoring: none # topological — health is its members'
|
|
attributes: {type: object, properties: {address: {type: string}}}
|
|
ups:
|
|
parent: entity
|
|
domain: physical
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Uninterruptible power supply.
|
|
monitoring: none # warranted, but no SNMP/NUT checker exists yet
|
|
attributes: {type: object, properties: {vendor: {type: string}, va: {type: integer}}}
|
|
sensor:
|
|
parent: entity
|
|
domain: physical
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Environmental sensor.
|
|
monitoring: none # readings are metrics, not health
|
|
peripheral:
|
|
parent: entity
|
|
domain: physical
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Attached hardware (GPU, e-ink display, dongle).
|
|
monitoring: none # visible only through its host
|
|
|
|
# ── Infrastructure / compute ──
|
|
compute-entity:
|
|
parent: entity
|
|
abstract: true
|
|
domain: compute
|
|
layer: infrastructure
|
|
description: Anything that executes workloads (machine, VM, container).
|
|
machine:
|
|
parent: compute-entity
|
|
abstract: true
|
|
domain: compute
|
|
layer: infrastructure
|
|
description: Physical machine. Always instantiated as a subtype.
|
|
monitoring: [ping, resource, updates] # inherited by proxmox-host /
|
|
# standalone-server / workstation / appliance
|
|
attributes:
|
|
type: object
|
|
properties:
|
|
cpu_arch: {type: string}
|
|
ram_gb: {type: number}
|
|
os: {type: string, enum: [linux, macos]}
|
|
lan_ip: {type: string}
|
|
mesh: {type: object}
|
|
ssh: {type: object}
|
|
age_pubkey: {type: string}
|
|
proxmox-host:
|
|
parent: machine
|
|
domain: compute
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Machine running Proxmox VE.
|
|
attributes:
|
|
type: object
|
|
properties: {pve_version: {type: string}}
|
|
standalone-server:
|
|
parent: machine
|
|
domain: compute
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Machine outside PVE management (e.g. external VPS).
|
|
# Override inherited [ping, resource, updates] — standalone servers may
|
|
# not be SSH/ICMP-reachable from the scheduler. HTTP is the least-
|
|
# common-denominator liveness signal. Entities with full SSH access
|
|
# can override to [ping, resource, http].
|
|
monitoring: [http]
|
|
attributes:
|
|
type: object
|
|
properties:
|
|
hypervisor: {type: string}
|
|
provider: {type: string}
|
|
control_level: {type: string, enum: [full, partial, none]}
|
|
public_ipv4: {type: string}
|
|
workstation:
|
|
parent: machine
|
|
domain: compute
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Operator machine (may also host services, e.g. mac-mini).
|
|
attributes:
|
|
type: object
|
|
properties: {user: {type: string}}
|
|
appliance:
|
|
parent: machine
|
|
domain: compute
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Vendor appliance with limited management access.
|
|
attributes:
|
|
type: object
|
|
properties: {vendor: {type: string}, model: {type: string}}
|
|
vm:
|
|
parent: compute-entity
|
|
domain: compute
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Virtual machine.
|
|
monitoring: [vm-status] # `qm status` from the host: powered-on liveness
|
|
# that works even when the VM blocks ICMP and has
|
|
# no guest agent (haos). ping is unreliable for VMs.
|
|
attributes:
|
|
type: object
|
|
properties:
|
|
pve_id: {type: integer}
|
|
vcpus: {type: integer}
|
|
memory_mb: {type: integer}
|
|
lan_ip: {type: string}
|
|
public_host: {type: string}
|
|
role: {type: string}
|
|
container:
|
|
parent: compute-entity
|
|
abstract: true
|
|
domain: compute
|
|
layer: infrastructure
|
|
description: OS-level container (LXC or Docker).
|
|
monitoring: [resource] # inherited by lxc / docker-container
|
|
attributes:
|
|
type: object
|
|
properties: {runtime: {type: string}}
|
|
lxc:
|
|
parent: container
|
|
domain: compute
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Proxmox LXC container.
|
|
attributes:
|
|
type: object
|
|
properties:
|
|
pve_id: {type: integer}
|
|
lan_ip: {type: string}
|
|
public_host: {type: string}
|
|
public_hosts: {type: array, items: {type: string}}
|
|
role: {type: string}
|
|
mesh: {type: object}
|
|
age_pubkey: {type: string}
|
|
destroyed: {type: string}
|
|
reason: {type: string}
|
|
docker-container:
|
|
parent: container
|
|
domain: compute
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Docker container (the OS models its own stack with these).
|
|
attributes:
|
|
type: object
|
|
properties: {image: {type: string}}
|
|
hypervisor:
|
|
parent: entity
|
|
domain: compute
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Hypervisor software running on a machine (PVE, KVM, OrbStack).
|
|
monitoring: none # the hosting machine's checks cover it
|
|
attributes:
|
|
type: object
|
|
properties: {type: {type: string}, version: {type: string}}
|
|
|
|
# ── Infrastructure / network ──
|
|
network:
|
|
parent: entity
|
|
abstract: true
|
|
domain: network
|
|
layer: infrastructure
|
|
description: A network things connect to.
|
|
monitoring: none # inherited by lan / mesh / vlan — a network's
|
|
# reachability is a property of its members
|
|
lan:
|
|
parent: network
|
|
domain: network
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Local area network.
|
|
attributes: {type: object, properties: {subnet: {type: string}}}
|
|
mesh:
|
|
parent: network
|
|
domain: network
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Overlay mesh network (NetBird, Tailscale).
|
|
attributes:
|
|
type: object
|
|
properties:
|
|
provider: {type: string}
|
|
subnet: {type: string}
|
|
domain: {type: string}
|
|
vlan:
|
|
parent: network
|
|
domain: network
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Tagged VLAN.
|
|
attributes: {type: object, properties: {tag: {type: integer}}}
|
|
network-interface:
|
|
parent: entity
|
|
domain: network
|
|
layer: infrastructure
|
|
description: Optional per-interface refinement (mac, ip). The seed uses
|
|
coarse connects-via edges; interfaces can be backfilled later.
|
|
monitoring: none # covered by its machine's ping/resource checks
|
|
attributes: {type: object, properties: {mac: {type: string}, ip: {type: string}}}
|
|
dns-zone:
|
|
parent: entity
|
|
domain: network
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: DNS zone (e.g. split-horizon hubris.network).
|
|
monitoring: [dns] # resolves the zone's apex via the configured
|
|
# resolver, verifying the zone is authoritatively
|
|
# reachable. (2026-08-05: was `none` — the DNS layer
|
|
# had zero checks, so a stale record like
|
|
# matrix→82.165.190.79 went unnoticed. Requires
|
|
# ontology re-ingest; coverageSweep clears stale
|
|
# signals after.)
|
|
attributes: {type: object, properties: {zone: {type: string}, authority: {type: string}}}
|
|
dns-record:
|
|
parent: entity
|
|
domain: network
|
|
layer: infrastructure
|
|
description: Individual DNS record.
|
|
monitoring: none # the zone is the unit of monitoring
|
|
attributes:
|
|
type: object
|
|
properties: {name: {type: string}, record_type: {type: string}, value: {type: string}}
|
|
ingress-route:
|
|
parent: entity
|
|
domain: network
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Public hostname → upstream mapping (Caddy).
|
|
monitoring: [http] # end-to-end: exercises Caddy + DNS + TLS + upstream
|
|
attributes:
|
|
type: object
|
|
properties:
|
|
pattern: {type: string}
|
|
upstream: {type: string}
|
|
forward_auth: {type: boolean}
|
|
certificate:
|
|
parent: entity
|
|
domain: network
|
|
layer: infrastructure
|
|
description: TLS certificate.
|
|
monitoring: [cert-expiry]
|
|
attributes: {type: object, properties: {issuer: {type: string}, expires: {type: string}}}
|
|
firewall-rule:
|
|
parent: entity
|
|
domain: network
|
|
layer: infrastructure
|
|
description: Firewall / port-forward rule.
|
|
monitoring: none # declarative config, not a running thing
|
|
|
|
# ── Infrastructure / storage ──
|
|
storage-pool:
|
|
parent: entity
|
|
domain: storage
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Storage pool (LVM, ZFS, NFS).
|
|
monitoring: [capacity]
|
|
attributes:
|
|
type: object
|
|
properties:
|
|
type: {type: string}
|
|
capacity_gb: {type: number}
|
|
volume:
|
|
parent: entity
|
|
domain: storage
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Named volume / dataset within a pool. Mount details live as
|
|
attributes on `mounts` edges.
|
|
monitoring: [capacity]
|
|
attributes: {type: object, properties: {size_gb: {type: number}, path: {type: string}}}
|
|
backup-target:
|
|
parent: entity
|
|
domain: storage
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Where backups land (Proton Drive, PBS).
|
|
monitoring: [backup-freshness] # checker lands in Phase 4
|
|
attributes: {type: object, properties: {provider: {type: string}, encrypted: {type: boolean}}}
|
|
dataset:
|
|
parent: entity
|
|
domain: storage
|
|
layer: infrastructure
|
|
description: Logical data collection worth tracking independently of its
|
|
volume (e.g. paperless documents).
|
|
monitoring: none # its volume and owning service carry the checks
|
|
|
|
# ── Infrastructure / software ──
|
|
service:
|
|
parent: entity
|
|
domain: software
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: A running service with consumers.
|
|
monitoring: [http, process] # http when it has a `url`, else a process check
|
|
# on the host resolved through its hosting edge
|
|
attributes:
|
|
type: object
|
|
properties:
|
|
url: {type: string}
|
|
port: {type: integer}
|
|
health: {type: string}
|
|
endpoint: {type: string}
|
|
systemd_unit: {type: string}
|
|
doc_page: {type: string}
|
|
risk_notes: {type: string}
|
|
note: {type: string}
|
|
application:
|
|
parent: entity
|
|
domain: software
|
|
layer: infrastructure
|
|
description: Deployed application/package a service runs.
|
|
monitoring: none # the service in front of it is the probe target
|
|
attributes: {type: object, properties: {version: {type: string}}}
|
|
config-repo:
|
|
parent: entity
|
|
domain: software
|
|
layer: infrastructure
|
|
description: Git repo holding tracked configuration.
|
|
monitoring: none # its Gitea service carries the checks
|
|
attributes:
|
|
type: object
|
|
properties: {url: {type: string}, branch: {type: string}}
|
|
deploy-pipeline:
|
|
parent: entity
|
|
domain: software
|
|
layer: infrastructure
|
|
description: Automated deploy path (webhook → script).
|
|
monitoring: none # health is per-deploy, tracked as executions
|
|
attributes:
|
|
type: object
|
|
properties: {trigger: {type: string}, target_path: {type: string}}
|
|
package-set:
|
|
parent: entity
|
|
domain: software
|
|
layer: infrastructure
|
|
description: Managed package baseline for a host class.
|
|
monitoring: none # drift shows up via each host's updates check
|
|
cluster:
|
|
parent: entity
|
|
domain: software
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Proxmox cluster.
|
|
monitoring: none # topological — its member hosts carry the checks
|
|
attributes: {type: object, properties: {quorum: {type: string}}}
|
|
compose-stack:
|
|
parent: entity
|
|
domain: software
|
|
layer: infrastructure
|
|
lifecycle: infrastructure
|
|
description: Docker Compose stack (the Oikos OS itself is one).
|
|
monitoring: [process]
|
|
attributes: {type: object, properties: {path: {type: string}}}
|
|
|
|
# ── Infrastructure / external ──
|
|
domain-registration:
|
|
parent: entity
|
|
domain: external
|
|
layer: infrastructure
|
|
description: Registered public domain.
|
|
monitoring: none # expiry is a calendar concern, not a probe
|
|
attributes: {type: object, properties: {registrar: {type: string}, expires: {type: string}}}
|
|
cloud-service:
|
|
parent: entity
|
|
domain: external
|
|
layer: infrastructure
|
|
description: External SaaS/cloud dependency.
|
|
monitoring: [http] # only when the entity carries a `url`
|
|
isp-link:
|
|
parent: entity
|
|
domain: external
|
|
layer: infrastructure
|
|
description: Internet uplink.
|
|
monitoring: none # no probe target; reachability shows up fleet-wide
|
|
vendor-dependency:
|
|
parent: entity
|
|
domain: external
|
|
layer: infrastructure
|
|
description: Vendor the lab depends on (registrar, IONOS, Proton).
|
|
monitoring: none # a commercial relationship, not a running thing
|
|
|
|
# ── Governance / identity ──
|
|
person:
|
|
parent: entity
|
|
domain: identity
|
|
layer: governance
|
|
description: Human actor (operator).
|
|
attributes:
|
|
type: object
|
|
properties: {matrix_id: {type: string}, oidc_sub: {type: string}, email: {type: string}}
|
|
agent:
|
|
parent: entity
|
|
domain: identity
|
|
layer: governance
|
|
lifecycle: infrastructure # agents are deployed/retired like infrastructure
|
|
description: Software agent actor (Nomos, the Oikos control loop).
|
|
monitoring: [http] # governance layer, but genuinely probeable —
|
|
# Nomos serves a gateway on :8092
|
|
attributes:
|
|
type: object
|
|
properties:
|
|
provider: {type: string}
|
|
model: {type: string}
|
|
gateway_port: {type: integer}
|
|
identity-provider:
|
|
parent: entity
|
|
domain: identity
|
|
layer: governance
|
|
description: OIDC / forward-auth provider (Authentik).
|
|
attributes:
|
|
type: object
|
|
properties:
|
|
issuer: {type: string}
|
|
client_id: {type: string}
|
|
auth_mode: {type: string, enum: [oidc, forward-auth, both]}
|
|
account:
|
|
parent: entity
|
|
domain: identity
|
|
layer: governance
|
|
description: An account a person/agent holds on a service.
|
|
secret:
|
|
parent: entity
|
|
domain: identity
|
|
layer: governance
|
|
description: Managed secret (Infisical path).
|
|
attributes:
|
|
type: object
|
|
properties: {path: {type: string}, rotation_days: {type: integer}}
|
|
key:
|
|
parent: entity
|
|
domain: identity
|
|
layer: governance
|
|
description: Cryptographic key (SSH, age).
|
|
access-grant:
|
|
parent: entity
|
|
domain: identity
|
|
layer: governance
|
|
description: Grant of access to a secret/scope.
|
|
attributes: {type: object, properties: {scope: {type: string}, expires: {type: string}}}
|
|
|
|
# ── Cognition ──
|
|
check:
|
|
parent: entity
|
|
domain: cognition
|
|
layer: cognition
|
|
description: Probe definition (checks-as-data, R3-7). Typed row in check_defs.
|
|
signal:
|
|
parent: entity
|
|
domain: cognition
|
|
layer: cognition
|
|
lifecycle: signal
|
|
description: Something needing attention. Typed row in signals.
|
|
classification:
|
|
parent: entity
|
|
domain: cognition
|
|
layer: cognition
|
|
description: A classifier decision with full reasoning. Typed row in classifications.
|
|
execution:
|
|
parent: entity
|
|
domain: cognition
|
|
layer: cognition
|
|
lifecycle: execution
|
|
description: An action the OS performed. Typed row in executions.
|
|
feedback:
|
|
parent: entity
|
|
domain: cognition
|
|
layer: cognition
|
|
description: What was learned from an execution. Typed row in feedback.
|
|
pattern:
|
|
parent: entity
|
|
domain: cognition
|
|
layer: cognition
|
|
lifecycle: pattern
|
|
description: Generalized rule extracted from feedback. Typed row in patterns.
|
|
skill:
|
|
parent: entity
|
|
domain: cognition
|
|
layer: cognition
|
|
lifecycle: skill
|
|
description: Codified, versioned procedure. Typed rows in skills.
|
|
approval:
|
|
parent: entity
|
|
domain: cognition
|
|
layer: cognition
|
|
lifecycle: approval
|
|
description: Operator approval request/decision. Typed row in approvals.
|
|
document:
|
|
parent: entity
|
|
domain: cognition
|
|
layer: cognition
|
|
description: Knowledge document ingested from docs/.
|
|
attributes:
|
|
type: object
|
|
properties: {title: {type: string}, source_path: {type: string}, content_hash: {type: string}}
|
|
runbook:
|
|
parent: entity
|
|
domain: cognition
|
|
layer: cognition
|
|
description: Step-by-step procedure for an entity/action.
|
|
attributes:
|
|
type: object
|
|
properties: {risk_class: {type: string}, source_path: {type: string}}
|
|
investigation:
|
|
parent: entity
|
|
domain: cognition
|
|
layer: cognition
|
|
description: Recorded investigation/postmortem.
|
|
task:
|
|
parent: entity
|
|
domain: cognition
|
|
layer: cognition
|
|
description: A goal-structured unit of agent work — one chat/session elevated
|
|
to a task with a plan, lifecycle status, and outcome. Anchors the knowledge
|
|
and involved-entity relationships for the task so future tasks can learn
|
|
from it. Typed rows in agent_sessions.
|
|
|
|
# ─── Relationship types ────────────────────────────────────────────────
|
|
# cardinality is source→target: e.g. `hosts` one-to-many = one machine
|
|
# hosts many compute entities; each hosted entity has one hosting machine.
|
|
|
|
relationship_types:
|
|
|
|
# Infrastructure topology
|
|
hosts:
|
|
inverse: runs-on
|
|
source: machine
|
|
target: compute-entity
|
|
cardinality: one-to-many
|
|
description: Machine hosts a VM/container (hubris hosts lxc:apps).
|
|
blast_direction: forward
|
|
runs-hypervisor:
|
|
inverse: hypervisor-on
|
|
source: machine
|
|
target: hypervisor
|
|
cardinality: one-to-one
|
|
description: Machine runs hypervisor software.
|
|
blast_direction: forward
|
|
member-of:
|
|
inverse: has-member
|
|
source: proxmox-host
|
|
target: cluster
|
|
cardinality: many-to-one
|
|
description: PVE host belongs to a cluster.
|
|
blast_direction: backward
|
|
part-of:
|
|
inverse: comprises
|
|
source: docker-container
|
|
target: compose-stack
|
|
cardinality: many-to-one
|
|
description: Docker container belongs to a compose stack.
|
|
blast_direction: backward
|
|
provides:
|
|
inverse: provided-by
|
|
source: compute-entity
|
|
target: service
|
|
cardinality: one-to-many
|
|
description: Compute entity provides a service (lxc:gitea provides service:gitea).
|
|
blast_direction: forward
|
|
runs:
|
|
inverse: run-by
|
|
source: service
|
|
target: application
|
|
cardinality: one-to-many
|
|
description: Service runs an application.
|
|
blast_direction: backward
|
|
configured-by:
|
|
inverse: configures
|
|
source: entity
|
|
target: config-repo
|
|
cardinality: many-to-one
|
|
description: Entity's config is tracked in a repo (mutations = commit+push).
|
|
deploys-to:
|
|
inverse: deployed-by
|
|
source: deploy-pipeline
|
|
target: entity
|
|
cardinality: many-to-one
|
|
description: Pipeline deploys to a service/host.
|
|
blast_direction: forward
|
|
routes-to:
|
|
inverse: routed-via
|
|
source: ingress-route
|
|
target: service
|
|
cardinality: many-to-one
|
|
description: Public hostname routes to a service.
|
|
blast_direction: backward
|
|
served-by:
|
|
inverse: serves
|
|
source: ingress-route
|
|
target: service
|
|
cardinality: many-to-one
|
|
description: Ingress route is terminated by this reverse proxy. Distinct
|
|
from routes-to, which names the BACKEND the route forwards to — without
|
|
this edge the proxy's blast radius is invisible, and lxc:caddy reported
|
|
one affected entity despite terminating every *.hubris.network route.
|
|
blast_direction: backward
|
|
secured-by:
|
|
inverse: secures
|
|
source: ingress-route
|
|
target: identity-provider
|
|
cardinality: many-to-one
|
|
description: Route gated by forward-auth.
|
|
blast_direction: backward
|
|
uses-certificate:
|
|
inverse: certifies
|
|
source: ingress-route
|
|
target: certificate
|
|
cardinality: many-to-one
|
|
description: Route served with this certificate.
|
|
blast_direction: backward
|
|
authenticates-via:
|
|
inverse: authenticates-service
|
|
source: service
|
|
target: identity-provider
|
|
cardinality: many-to-one
|
|
description: Service uses native OIDC (jellyfin authenticates-via authentik).
|
|
blast_direction: backward
|
|
in-zone:
|
|
inverse: contains-record
|
|
source: dns-record
|
|
target: dns-zone
|
|
cardinality: many-to-one
|
|
description: Record belongs to a zone.
|
|
blast_direction: backward
|
|
resolves-to:
|
|
inverse: resolved-from
|
|
source: dns-record
|
|
target: entity
|
|
cardinality: many-to-one
|
|
description: Record points at an ingress route or host.
|
|
depends-on:
|
|
inverse: dependency-of
|
|
source: service
|
|
target: service
|
|
cardinality: many-to-many
|
|
description: Runtime dependency (blast-radius edge).
|
|
blast_direction: backward
|
|
connects-via:
|
|
inverse: connects
|
|
source: compute-entity
|
|
target: network
|
|
cardinality: many-to-many
|
|
description: Coarse network membership (host on LAN / mesh).
|
|
blast_direction: backward
|
|
has-interface:
|
|
inverse: interface-of
|
|
source: compute-entity
|
|
target: network-interface
|
|
cardinality: one-to-many
|
|
description: Optional per-interface refinement.
|
|
blast_direction: backward
|
|
interface-on:
|
|
inverse: has-endpoint
|
|
source: network-interface
|
|
target: network
|
|
cardinality: many-to-one
|
|
description: Interface attaches to a network.
|
|
blast_direction: backward
|
|
|
|
# Storage
|
|
mounts:
|
|
inverse: mounted-by
|
|
source: compute-entity
|
|
target: volume
|
|
cardinality: many-to-many
|
|
description: Compute entity mounts a volume. Edge attributes carry
|
|
mount_point and options.
|
|
blast_direction: backward
|
|
stores-on:
|
|
inverse: stores-for
|
|
source: compute-entity
|
|
target: storage-pool
|
|
cardinality: many-to-many
|
|
description: Rootfs/data lives on a pool.
|
|
blast_direction: backward
|
|
contains:
|
|
inverse: contained-in
|
|
source: storage-pool
|
|
target: volume
|
|
cardinality: one-to-many
|
|
description: Pool contains a volume.
|
|
blast_direction: forward
|
|
holds-dataset:
|
|
inverse: dataset-on
|
|
source: volume
|
|
target: dataset
|
|
cardinality: one-to-many
|
|
description: Volume holds a tracked dataset.
|
|
blast_direction: backward
|
|
backs-up-to:
|
|
inverse: backup-of
|
|
source: entity
|
|
target: backup-target
|
|
cardinality: many-to-many
|
|
description: Entity's data is backed up to a target.
|
|
|
|
# Physical / external
|
|
powered-by:
|
|
inverse: powers
|
|
source: machine
|
|
target: ups
|
|
cardinality: many-to-one
|
|
description: Machine on UPS power.
|
|
blast_direction: backward
|
|
located-at:
|
|
inverse: location-of
|
|
source: machine
|
|
target: site
|
|
cardinality: many-to-one
|
|
description: Machine's physical site.
|
|
blast_direction: backward
|
|
registered-with:
|
|
inverse: registrar-of
|
|
source: domain-registration
|
|
target: vendor-dependency
|
|
cardinality: many-to-one
|
|
description: Domain registered with a registrar.
|
|
|
|
# Governance
|
|
owns:
|
|
inverse: owned-by
|
|
source: person
|
|
target: agent
|
|
cardinality: one-to-many
|
|
description: Person owns/controls an agent.
|
|
authenticates:
|
|
inverse: authenticated-by
|
|
source: identity-provider
|
|
target: person
|
|
cardinality: one-to-many
|
|
description: IdP authenticates a person.
|
|
holds-grant:
|
|
inverse: granted-to
|
|
source: agent
|
|
target: access-grant
|
|
cardinality: one-to-many
|
|
description: Agent holds an access grant.
|
|
grants:
|
|
inverse: granted-by
|
|
source: access-grant
|
|
target: secret
|
|
cardinality: many-to-one
|
|
description: Grant covers a secret.
|
|
blast_direction: forward
|
|
can-decrypt:
|
|
inverse: readable-by
|
|
source: compute-entity
|
|
target: secret
|
|
cardinality: many-to-many
|
|
description: Host can decrypt a secret (legacy SOPS; Infisical grants later).
|
|
blast_direction: backward
|
|
|
|
# Cognition
|
|
checks:
|
|
inverse: checked-by
|
|
source: check
|
|
target: entity
|
|
cardinality: many-to-one
|
|
description: Check probes an entity.
|
|
raises:
|
|
inverse: raised-by
|
|
source: check
|
|
target: signal
|
|
cardinality: one-to-many
|
|
description: Check raised a signal.
|
|
about:
|
|
inverse: subject-of
|
|
source: entity
|
|
target: entity
|
|
cardinality: many-to-many
|
|
description: Entity concerns (or is about) another entity.
|
|
classifies:
|
|
inverse: classified-as
|
|
source: classification
|
|
target: signal
|
|
cardinality: many-to-one
|
|
description: Classification of a signal.
|
|
precedes:
|
|
inverse: follows
|
|
source: classification
|
|
target: execution
|
|
cardinality: one-to-one
|
|
description: Classification that led to an execution.
|
|
targets:
|
|
inverse: targeted-by
|
|
source: execution
|
|
target: entity
|
|
cardinality: many-to-one
|
|
description: Execution acts on an entity.
|
|
requires-approval:
|
|
inverse: approves
|
|
source: execution
|
|
target: approval
|
|
cardinality: one-to-one
|
|
description: Execution gated by an approval.
|
|
performs:
|
|
inverse: performed-by
|
|
source: agent
|
|
target: execution
|
|
cardinality: one-to-many
|
|
description: Agent performed an execution.
|
|
decides:
|
|
inverse: decided-by
|
|
source: person
|
|
target: approval
|
|
cardinality: one-to-many
|
|
description: Person decided an approval.
|
|
produces:
|
|
inverse: produced-by
|
|
source: execution
|
|
target: feedback
|
|
cardinality: one-to-one
|
|
description: Execution produced feedback.
|
|
contributes-to:
|
|
inverse: built-from
|
|
source: feedback
|
|
target: pattern
|
|
cardinality: many-to-many
|
|
description: Feedback supports a pattern.
|
|
informs:
|
|
inverse: informed-by
|
|
source: pattern
|
|
target: skill
|
|
cardinality: many-to-one
|
|
description: Pattern informs a skill.
|
|
guides:
|
|
inverse: guided-by
|
|
source: skill
|
|
target: classification
|
|
cardinality: one-to-many
|
|
description: Skill guided a classification.
|
|
documents:
|
|
inverse: documented-by
|
|
source: document
|
|
target: entity
|
|
# many-to-many, not many-to-one: a single investigation routinely covers
|
|
# several entities (a fleet-wide apt audit documents every host it
|
|
# touched), and Nomos has been writing such edges for months. The stricter
|
|
# declaration made ~40 of them cardinality violations, which only surfaced
|
|
# once the seed could complete far enough to run ValidateCardinality.
|
|
cardinality: many-to-many
|
|
description: Document describes an entity.
|
|
involves:
|
|
inverse: involved-in
|
|
source: task
|
|
target: entity
|
|
cardinality: many-to-many
|
|
description: Task explored or acted on an entity (captured from its tool
|
|
calls). A task's involved-entity set is its graph neighborhood, so future
|
|
tasks on the same entities can surface this task's knowledge and outcome.
|
|
procedure-for:
|
|
inverse: has-procedure
|
|
source: runbook
|
|
target: entity
|
|
cardinality: many-to-many
|
|
description: Runbook applies to an entity.
|