Files
oikos/seeds/ontology.yaml
dtoro c10f6920cd
Some checks failed
ci / build-test (push) Has been cancelled
ci / docker-build (push) Has been cancelled
ci / web (push) Has been cancelled
Desktop App / Build Linux (amd64) (push) Has been cancelled
Desktop App / Attach to Release (push) Has been cancelled
fix: blast radius walks dependency direction, and reachability survives no ICMP
Two things the entity window redesign surfaced but deliberately left alone.

**blast_radius answered the wrong question.** It walked source→target for every
relationship type, but which end of an edge is the dependent differs per type:
"machine hosts container" means the target breaks, while "service depends-on
service" and "ingress routes-to service" mean the SOURCE breaks. Walking
everything forwards was right for hosts/provides and backwards for everything
else — and swept in 2,800+ documents/involves/targets edges of pure bookkeeping,
so the result contained tasks and executions that cannot break.

Direction is now declared per relationship type in seeds/ontology.yaml
(blast_direction: forward | backward | none), the same shape as the entity
types' monitoring: declaration, and defaults to none so an undeclared edge
contributes nothing rather than a confidently wrong answer.

It also needed a modelling fix: `routes-to` names an ingress's BACKEND, so
nothing recorded that all 21 public hostnames are terminated by caddy. A
`served-by` edge type now says so.

  pool:ludo-lvm    2 -> 23   (every container storing on it, then their services)
  lxc:caddy        4 -> 22   (service:caddy, then all 21 ingress routes)
  service:authentik      7   (what authenticates via it)

**Every ping check was reporting down.** Not a host:strong false positive: all
seven, including ws:mac-mini — the Docker host itself. The scheduler runs in
Docker on macOS, whose VM does not route ICMP to the LAN; loopback pings succeed
and every LAN ping fails. Under health aggregation each broken probe dragged its
entity to down.

The question the check exists to answer is "is it reachable", and ICMP is only
one way to ask it. checkPing now falls back to a TCP connect before concluding
anything, which restores an honest verdict for the four hosts that are genuinely
up while leaving the genuinely unreachable ones down.

TestBlastRadiusTerminatesOnCycles asserted the old direction (caddy=1,
authentik=2 — the cycle walked the wrong way); it now asserts the corrected
depths, and its exact-node-count check is relaxed because walking the right way
also surfaces the seed's own real dependents, which are correct answers.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-29 09:44:17 +02:00

1028 lines
33 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).
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: [ping] # no guest agent assumed; reachability only
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] # NOTE: no `dns` checker exists yet — this is a
# real gap and coverageSweep will report it
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.