feat: client enrollment API and compute entity provisioning
Phase 1 implementation from the client-lifecycle plan.
- Migration 012: provisioning_steps table, context_version, context_files,
enrolled_at column, slug+type index for machine entities
- API endpoints (openapi.yaml + generated code):
POST /clients/enroll — age key issuance, Infisical identity, state transition
GET /clients/{slug}/context — agent file delta polling (replaces git pull)
GET /clients/{slug}/secrets — scoped secret listing
POST /entities/provision — compute entity creation with constraint validation
GET /entities/{slug}/provision/status — step-by-step provisioning progress
- Handlers in impl.go: enrollment with state validation and age key generation,
provisioning with execution tracking and relationship creation,
context endpoint with since-based delta queries
- Server struct extended with secretsBackend interface for key storage
- All tests pass, build clean
This commit is contained in:
57
migrations/012_client_enrollment.up.sql
Normal file
57
migrations/012_client_enrollment.up.sql
Normal file
@@ -0,0 +1,57 @@
|
||||
-- Migration 012: Client enrollment and compute entity provisioning
|
||||
-- Adds provisioning tracking and client-specific lookup indexes.
|
||||
|
||||
-- Provisioning step tracker for LXC/VM/container creation.
|
||||
-- Tracks individual steps within a provisioning execution so the client
|
||||
-- can poll GET /provision/status for progress.
|
||||
CREATE TABLE IF NOT EXISTS provisioning_steps (
|
||||
id UUID PRIMARY KEY,
|
||||
entity_id UUID NOT NULL REFERENCES entities(id) ON DELETE CASCADE,
|
||||
execution_id UUID NOT NULL REFERENCES executions(id) ON DELETE CASCADE,
|
||||
step_order INTEGER NOT NULL,
|
||||
step_name TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'pending'
|
||||
CHECK (status IN ('pending', 'running', 'ok', 'failed', 'skipped')),
|
||||
started_at TIMESTAMPTZ,
|
||||
finished_at TIMESTAMPTZ,
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
UNIQUE(entity_id, step_name)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_provisioning_steps_entity
|
||||
ON provisioning_steps (entity_id, step_order);
|
||||
CREATE INDEX IF NOT EXISTS idx_provisioning_steps_execution
|
||||
ON provisioning_steps (execution_id);
|
||||
|
||||
-- Fast lookup for client entities by slug prefix + type.
|
||||
-- Supports whoami(hostname) and GET /clients/{slug} lookups.
|
||||
CREATE INDEX IF NOT EXISTS idx_entities_slug_type_machine
|
||||
ON entities (slug, type)
|
||||
WHERE type IN ('workstation', 'standalone-server', 'proxmox-host');
|
||||
|
||||
-- Track client enrollment state separately from entity state.
|
||||
-- An entity may be in provisioning for infrastructure reasons while
|
||||
-- enrollment (age key, Infisical identity) is complete.
|
||||
ALTER TABLE entities ADD COLUMN IF NOT EXISTS enrolled_at TIMESTAMPTZ;
|
||||
ALTER TABLE entities ADD COLUMN IF NOT EXISTS enrolled_by UUID;
|
||||
|
||||
-- Context version tracking — incremented when agent files change,
|
||||
-- so clients can poll GET /context?since= efficiently.
|
||||
CREATE TABLE IF NOT EXISTS context_version (
|
||||
singleton BOOLEAN PRIMARY KEY DEFAULT true
|
||||
CHECK (singleton = true),
|
||||
version BIGINT NOT NULL DEFAULT 0,
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
INSERT INTO context_version (version) VALUES (0)
|
||||
ON CONFLICT (singleton) DO NOTHING;
|
||||
|
||||
-- List of files included in the agent context bundle.
|
||||
CREATE TABLE IF NOT EXISTS context_files (
|
||||
path TEXT PRIMARY KEY,
|
||||
hash TEXT NOT NULL,
|
||||
last_changed TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
Reference in New Issue
Block a user