This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/server/database/migrations/postgres/011_triggers.sql
Jeffrey Smith bd703b9e0d
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
Feat event bus subscriptions + trigger system (v0.2.2)
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>
2026-03-26 22:29:43 +00:00

86 lines
3.4 KiB
SQL

-- ==========================================
-- 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);