ProofedMesh/db/trust/migrations/0002_agents.up.sql
CTO (Paperclip) 51733d8b36
Some checks failed
build-images / signing-service image (push) Failing after 14s
validate / JSON Schema (ajv) (push) Successful in 19s
validate / Rego (opa fmt + opa test) (push) Successful in 14s
validate / DB (migrate up/down dry-run) (push) Failing after 18s
validate / Go (vet + test) (push) Successful in 34s
db+ci: Agent Registry schema (agents + agent_keys), Phase-1 seed, migrate up/down CI (DEV-607)
- 0002_agents / 0003_agent_keys migrations per architecture v1.1 §4.4
  (incl. (k8s_namespace, k8s_service_account) uniqueness for the signing
  service's dual identity check and an agent_id, valid_from index for the
  verification lookup path)
- idempotent seed db/trust/seeds/0001_phase1_agents.sql with the three
  Phase-1 identities: agent-approval-service, agent-testagent-transform,
  agent-dummy-sink (namespace agent-trust)
- new db CI job in validate.yml: runs postgres:16-alpine, migrate up ->
  down 2 -> up, applies the seed twice, verifies three agents

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-10-25 19:23:20 +00:00

33 lines
1.7 KiB
SQL

-- Migration: 0002_agents
-- Agent Registry (Identitäten) gemäß docs/architecture/v1.1.md §4.4.
--
-- Phase 1 nutzt diese Tabelle rein lesend (SELECT) aus Signing Service und
-- Verification Service, um Pocket-ID-Client-IDs und K8s-ServiceAccount-Paare
-- auf stabile agent_ids zu mappen. Eine HTTP-API-Schale folgt in Phase 2.
--
-- Design-Entscheidungen:
-- * agent_id ist ein stabiler, lesbarer Slug (`agent-<rolle>`), kein UUID.
-- Er taucht in Attestations (`actor`, `issuer`), DSSE-key_ids,
-- Policy-Dateien und Audit-Logs auf — Lesbarkeit zählt.
-- * (k8s_namespace, k8s_service_account) ist zusätzlich UNIQUE: die
-- doppelte Identitätsprüfung im Signing Service (Pocket-ID + K8s
-- TokenReview) MUSS auf genau einen Agenten mappen.
-- * allowed_actions ist NOT NULL, darf aber eine leere Liste sein; die
-- effektive Autorisierung macht OPA im Signing / Verification Service.
CREATE TABLE IF NOT EXISTS agents (
agent_id TEXT PRIMARY KEY
CHECK (agent_id ~ '^[a-z0-9][a-z0-9-]{0,126}[a-z0-9]$'),
pocket_id_client TEXT UNIQUE NOT NULL
CHECK (length(pocket_id_client) BETWEEN 1 AND 256),
k8s_namespace TEXT NOT NULL
CHECK (k8s_namespace ~ '^[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$'),
k8s_service_account TEXT NOT NULL
CHECK (k8s_service_account ~ '^[a-z0-9][a-z0-9.-]{0,251}[a-z0-9]$'),
display_name TEXT NOT NULL
CHECK (length(display_name) BETWEEN 1 AND 200),
allowed_actions TEXT[] NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT agents_k8s_identity_unique
UNIQUE (k8s_namespace, k8s_service_account)
);