Files
oikos/seeds/ontology.yaml
dtoro 0920c4cb6d
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
0.25.0 — DNS resolution check kind (KindDNS) + VPS monitoring fix
Adds a new 'dns' semantic monitoring kind that probes whether a DNS name
resolves. Uses net.LookupNS (NS records) with fallback to net.LookupHost
(A/AAAA). Supports an explicit server config for split-horizon resolution.

Changes:
- seeds/ontology.yaml: dns-zone monitoring: none → [dns] (was deferred
  since 2026-06 with a comment 'no dns checker exists yet')
- seeds/inventory.yaml: host:netbird-vps monitoring: [http] (was none;
  VPS was invisible for 7 days during the 2026-07-29 outage)
- internal/checkdefaults/defaults.go: add KindDNS, buildKind case for 'dns'
  that creates a check_def at 5-minute intervals
- internal/scheduler/scheduler.go: add checkDNS probe + wire in executeCheck

The DNS checker catches stale/unreachable zones (e.g. matrix.hubris.network
pointing to a dead VPS IP). The VPS HTTP check probes the public endpoint
every 60s, closing the 7-day monitoring gap.
2026-08-05 15:31:50 +02:00

1035 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).
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.