Files
oikos/seeds/policy.yaml
dtoro 18cb79caf9 oikos phase 0: ontology + inventory + policy seeds, OpenAPI contract, ADRs
- seeds/ontology.yaml: 59 entity types (5 abstract, is-a hierarchy), 46
  relationship types with cardinality, 6 lifecycles with terminal states
  and named precondition checks
- seeds/inventory.yaml: 110 entities / 142 relationships translated from
  legacy inventory.yaml (fleet, services, ingress, storage, governance,
  archaeology); thin spots marked for backfill
- seeds/policy.yaml: 4 risk classes, 27 approval rules (hierarchy-aware,
  per-entity overrides), autonomy kill-switch off (cold start)
- api/openapi.yaml: full v1 REST contract (40 paths), RFC 9457 errors,
  cursor pagination, idempotency, ETag/If-Match, scopes; redocly-clean
- docs/adr/0001-0010: initial architecture decision records
- scripts/validate-seeds.py: Phase 0 gate — hierarchy, lifecycles,
  endpoints, cardinality, policy cross-refs (0 errors)
- plan: layer CHECK gains 'meta' (root type), cardinality gains
  'many-to-one'

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 00:17:15 +02:00

104 lines
5.8 KiB
YAML

# Oikos policy seed — risk classes, approval rules, autonomy settings.
#
# Bootstraps risk_classes / approval_rules / autonomy_settings (migration
# 005). After ingest the DB is authoritative; runtime policy changes go
# through the dual-control meta-approval flow (plan S3) and are exported
# back here via `GET /api/v1/export`.
#
# Adapted from legacy oikos/policy.yaml (2026-07-07):
# - `commands:`/`mcp_tools:` maps are gone — read endpoints and MCP read
# tools are read_only by construction and never classified; mutating
# API calls classify via approval_rules below.
# - `actions:` map became approval_rules keyed on (entity_type, action);
# entity types may be abstract (rule inherits down the hierarchy,
# most-specific match wins: scope_entity > concrete type > ancestor).
# - `service_overrides:` became scope_entity rules.
# - `lifecycle_overrides:` became autonomy_settings keys read by the
# classifier.
version: 1
risk_classes:
read_only:
description: Observes state; cannot change anything.
approval_required: none
autonomy_allowed: true
reversible_low:
description: >-
Changes runtime state in a way a single follow-up command undoes
(restart, cache clear, sync pull). No config or data changes.
approval_required: none # still subject to global.auto_act + rules below
autonomy_allowed: true
config_mutation:
description: >-
Changes tracked configuration or deployed software: repo edit + push,
deploy trigger, Caddy/Gitea/app config, package upgrades. Reversible
via git, but affects other consumers.
approval_required: operator # Matrix ✅/❌ (single-use HMAC token)
autonomy_allowed: false
destructive:
description: >-
Destroys or irreversibly alters data/entities: container destroy,
disk format, DB wipe, secret rotation, client revocation.
approval_required: operator_confirmed
autonomy_allowed: false
approval_rules:
# ── Generic rules on (possibly abstract) types ──
- {entity_type: service, action: restart, risk_class: reversible_low, autonomy_level: auto}
- {entity_type: service, action: cache-clear, risk_class: reversible_low, autonomy_level: auto}
- {entity_type: service, action: sync-pull, risk_class: reversible_low, autonomy_level: auto}
- {entity_type: service, action: db-wipe, risk_class: destructive, autonomy_level: never}
- {entity_type: compose-stack, action: restart, risk_class: reversible_low, autonomy_level: auto}
- {entity_type: docker-container, action: restart, risk_class: reversible_low, autonomy_level: auto}
- {entity_type: machine, action: apt-upgrade, risk_class: config_mutation, autonomy_level: escalate}
- {entity_type: machine, action: reboot, risk_class: config_mutation, autonomy_level: escalate}
- {entity_type: machine, action: format-disk, risk_class: destructive, autonomy_level: never}
- {entity_type: config-repo, action: edit, risk_class: config_mutation, autonomy_level: escalate}
- {entity_type: deploy-pipeline, action: trigger, risk_class: config_mutation, autonomy_level: escalate}
- {entity_type: lxc, action: create, risk_class: config_mutation, autonomy_level: escalate}
- {entity_type: lxc, action: migrate, risk_class: config_mutation, autonomy_level: escalate}
- {entity_type: lxc, action: restart, risk_class: reversible_low, autonomy_level: auto}
- {entity_type: lxc, action: destroy, risk_class: destructive, autonomy_level: never}
- {entity_type: vm, action: restart, risk_class: reversible_low, autonomy_level: auto}
- {entity_type: vm, action: destroy, risk_class: destructive, autonomy_level: never}
- {entity_type: dns-record, action: change, risk_class: config_mutation, autonomy_level: escalate}
- {entity_type: ingress-route, action: change, risk_class: config_mutation, autonomy_level: escalate}
- {entity_type: storage-pool, action: change, risk_class: destructive, autonomy_level: never}
- {entity_type: secret, action: rotate, risk_class: destructive, autonomy_level: never}
- {entity_type: key, action: revoke, risk_class: destructive, autonomy_level: never}
# ── Governance objects (the OS's own levers — always operator-gated) ──
- {entity_type: pattern, action: activate, risk_class: config_mutation, autonomy_level: never}
- {entity_type: skill, action: activate, risk_class: config_mutation, autonomy_level: never}
# ── Per-entity overrides (wide blast radius) ──
- {entity_type: service, action: restart, scope_entity: "service:caddy",
risk_class: config_mutation, autonomy_level: escalate}
# everything *.hubris.network rides on caddy
- {entity_type: service, action: restart, scope_entity: "service:dns",
risk_class: config_mutation, autonomy_level: escalate}
# LAN-wide resolver
- {entity_type: service, action: restart, scope_entity: "service:authentik",
risk_class: config_mutation, autonomy_level: escalate}
# SSO provider — restart locks logins fleet-wide
autonomy_settings:
# Global kill-switch. Cold start = off: the agent escalates everything
# until patterns validate and the operator raises this (plan: trust is earned).
global.auto_act: "off" # off | reversible_low
# Per-entity hard blocks (checked even when global.auto_act is on)
never_auto_act.service:caddy: "true"
never_auto_act.service:dns: "true"
never_auto_act.service:authentik: "true"
never_auto_act.host:hubris: "true"
never_auto_act.host:strong: "true"
# Lifecycle-state classifier overrides (from legacy lifecycle_overrides)
lifecycle_override.provisioning.config_mutation: reversible_low
# no dependents yet — config changes are cheap
lifecycle_override.deprecated.refuse: new-inbound-edges
lifecycle_override.destroyed.refuse: all
# any action targeting a destroyed entity raises a drift signal instead