Feat event bus subscriptions + trigger system (v0.2.2)
All checks were successful
CI/CD / detect-changes (pull_request) Successful in 24s
CI/CD / test-frontend (pull_request) Has been skipped
CI/CD / test-go-pg (pull_request) Successful in 2m30s
CI/CD / test-sqlite (pull_request) Successful in 2m37s
CI/CD / build-and-deploy (pull_request) Successful in 1m30s
All checks were successful
CI/CD / detect-changes (pull_request) Successful in 24s
CI/CD / test-frontend (pull_request) Has been skipped
CI/CD / test-go-pg (pull_request) Successful in 2m30s
CI/CD / test-sqlite (pull_request) Successful in 2m37s
CI/CD / build-and-deploy (pull_request) Successful in 1m30s
Three trigger primitives replacing the old monolithic scheduler: - Event triggers: extensions subscribe to bus patterns via manifest, async handler invocation through sandbox.CallEntryPoint - Webhook triggers: inbound HTTP at /api/v1/hooks/:pkg/:slug with HMAC-SHA256 verification and synchronous Starlark response - Scheduled tasks: user-created cron scripts with restricted sandbox (no raw HTTP, no DB table creation), runs as creator identity New tables: triggers, scheduled_tasks, trigger_logs (postgres + sqlite). New permission: triggers.register. Full admin + user CRUD APIs. SyncManifestTriggers hooked into seed and install flows. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
85
server/database/migrations/postgres/011_triggers.sql
Normal file
85
server/database/migrations/postgres/011_triggers.sql
Normal file
@@ -0,0 +1,85 @@
|
||||
-- ==========================================
|
||||
-- Switchboard Core — 011 Triggers & Scheduled Tasks
|
||||
-- ==========================================
|
||||
|
||||
-- ── Extension Triggers (event + webhook) ──────
|
||||
|
||||
CREATE TABLE IF NOT EXISTS triggers (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
package_id TEXT NOT NULL REFERENCES packages(id) ON DELETE CASCADE,
|
||||
type TEXT NOT NULL CHECK (type IN ('webhook', 'event')),
|
||||
enabled BOOLEAN NOT NULL DEFAULT true,
|
||||
|
||||
-- Webhook triggers
|
||||
slug TEXT,
|
||||
secret TEXT,
|
||||
|
||||
-- Event triggers
|
||||
event_pattern TEXT,
|
||||
|
||||
-- Common
|
||||
entry_point TEXT NOT NULL,
|
||||
config JSONB NOT NULL DEFAULT '{}',
|
||||
fire_count INTEGER NOT NULL DEFAULT 0,
|
||||
last_fire_at TIMESTAMPTZ,
|
||||
last_error TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
|
||||
UNIQUE(package_id, type, slug),
|
||||
UNIQUE(package_id, type, event_pattern)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_triggers_package ON triggers(package_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_triggers_type ON triggers(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_triggers_enabled ON triggers(enabled) WHERE enabled = true;
|
||||
CREATE INDEX IF NOT EXISTS idx_triggers_webhook ON triggers(package_id, slug) WHERE type = 'webhook';
|
||||
|
||||
-- ── Scheduled Tasks (user-created cron) ───────
|
||||
|
||||
CREATE TABLE IF NOT EXISTS scheduled_tasks (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
creator_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
run_as TEXT NOT NULL DEFAULT 'creator'
|
||||
CHECK (run_as IN ('creator', 'system')),
|
||||
cron_expr TEXT NOT NULL,
|
||||
next_fire_at TIMESTAMPTZ,
|
||||
last_fire_at TIMESTAMPTZ,
|
||||
enabled BOOLEAN NOT NULL DEFAULT true,
|
||||
script TEXT NOT NULL DEFAULT '',
|
||||
template_id TEXT,
|
||||
template_params JSONB NOT NULL DEFAULT '{}',
|
||||
fire_count INTEGER NOT NULL DEFAULT 0,
|
||||
last_error TEXT,
|
||||
last_duration_ms INTEGER,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_sched_tasks_creator ON scheduled_tasks(creator_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sched_tasks_enabled ON scheduled_tasks(enabled) WHERE enabled = true;
|
||||
CREATE INDEX IF NOT EXISTS idx_sched_tasks_next_fire ON scheduled_tasks(next_fire_at) WHERE enabled = true;
|
||||
|
||||
-- ── Trigger Logs (unified execution log) ──────
|
||||
|
||||
CREATE TABLE IF NOT EXISTS trigger_logs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
trigger_id UUID REFERENCES triggers(id) ON DELETE CASCADE,
|
||||
scheduled_task_id UUID REFERENCES scheduled_tasks(id) ON DELETE CASCADE,
|
||||
fired_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
duration_ms INTEGER,
|
||||
success BOOLEAN NOT NULL DEFAULT true,
|
||||
error TEXT,
|
||||
output TEXT,
|
||||
|
||||
CHECK (
|
||||
(trigger_id IS NOT NULL AND scheduled_task_id IS NULL) OR
|
||||
(trigger_id IS NULL AND scheduled_task_id IS NOT NULL)
|
||||
)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_trigger_logs_trigger ON trigger_logs(trigger_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_trigger_logs_sched ON trigger_logs(scheduled_task_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_trigger_logs_fired ON trigger_logs(fired_at);
|
||||
80
server/database/migrations/sqlite/011_triggers.sql
Normal file
80
server/database/migrations/sqlite/011_triggers.sql
Normal file
@@ -0,0 +1,80 @@
|
||||
-- ==========================================
|
||||
-- Switchboard Core — 011 Triggers & Scheduled Tasks (SQLite)
|
||||
-- ==========================================
|
||||
|
||||
-- ── Extension Triggers (event + webhook) ──────
|
||||
|
||||
CREATE TABLE IF NOT EXISTS triggers (
|
||||
id TEXT PRIMARY KEY,
|
||||
package_id TEXT NOT NULL REFERENCES packages(id) ON DELETE CASCADE,
|
||||
type TEXT NOT NULL CHECK (type IN ('webhook', 'event')),
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
|
||||
-- Webhook triggers
|
||||
slug TEXT,
|
||||
secret TEXT,
|
||||
|
||||
-- Event triggers
|
||||
event_pattern TEXT,
|
||||
|
||||
-- Common
|
||||
entry_point TEXT NOT NULL,
|
||||
config TEXT NOT NULL DEFAULT '{}',
|
||||
fire_count INTEGER NOT NULL DEFAULT 0,
|
||||
last_fire_at TEXT,
|
||||
last_error TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
|
||||
UNIQUE(package_id, type, slug),
|
||||
UNIQUE(package_id, type, event_pattern)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_triggers_package ON triggers(package_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_triggers_type ON triggers(type);
|
||||
CREATE INDEX IF NOT EXISTS idx_triggers_enabled ON triggers(enabled);
|
||||
CREATE INDEX IF NOT EXISTS idx_triggers_webhook ON triggers(package_id, slug);
|
||||
|
||||
-- ── Scheduled Tasks (user-created cron) ───────
|
||||
|
||||
CREATE TABLE IF NOT EXISTS scheduled_tasks (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
creator_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
run_as TEXT NOT NULL DEFAULT 'creator'
|
||||
CHECK (run_as IN ('creator', 'system')),
|
||||
cron_expr TEXT NOT NULL,
|
||||
next_fire_at TEXT,
|
||||
last_fire_at TEXT,
|
||||
enabled INTEGER NOT NULL DEFAULT 1,
|
||||
script TEXT NOT NULL DEFAULT '',
|
||||
template_id TEXT,
|
||||
template_params TEXT NOT NULL DEFAULT '{}',
|
||||
fire_count INTEGER NOT NULL DEFAULT 0,
|
||||
last_error TEXT,
|
||||
last_duration_ms INTEGER,
|
||||
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_sched_tasks_creator ON scheduled_tasks(creator_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sched_tasks_enabled ON scheduled_tasks(enabled);
|
||||
CREATE INDEX IF NOT EXISTS idx_sched_tasks_next_fire ON scheduled_tasks(next_fire_at);
|
||||
|
||||
-- ── Trigger Logs (unified execution log) ──────
|
||||
|
||||
CREATE TABLE IF NOT EXISTS trigger_logs (
|
||||
id TEXT PRIMARY KEY,
|
||||
trigger_id TEXT REFERENCES triggers(id) ON DELETE CASCADE,
|
||||
scheduled_task_id TEXT REFERENCES scheduled_tasks(id) ON DELETE CASCADE,
|
||||
fired_at TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
duration_ms INTEGER,
|
||||
success INTEGER NOT NULL DEFAULT 1,
|
||||
error TEXT,
|
||||
output TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_trigger_logs_trigger ON trigger_logs(trigger_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_trigger_logs_sched ON trigger_logs(scheduled_task_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_trigger_logs_fired ON trigger_logs(fired_at);
|
||||
Reference in New Issue
Block a user