87 lines
3.3 KiB
SQL
87 lines
3.3 KiB
SQL
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
|
|
CREATE TABLE IF NOT EXISTS schema_migrations (
|
|
id text PRIMARY KEY,
|
|
applied_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS agents (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
owner_user_id text NOT NULL,
|
|
owner_email text,
|
|
display_name text NOT NULL,
|
|
avatar_url text,
|
|
status text NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'disabled', 'revoked')),
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS agents_owner_user_id_idx ON agents(owner_user_id);
|
|
CREATE INDEX IF NOT EXISTS agents_owner_email_idx ON agents(owner_email);
|
|
|
|
CREATE TABLE IF NOT EXISTS agent_grants (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
agent_id uuid NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
|
|
workspace_slug text NOT NULL,
|
|
project_id text NOT NULL DEFAULT '',
|
|
scopes text[] NOT NULL DEFAULT '{}',
|
|
mode text NOT NULL DEFAULT 'voluntary' CHECK (mode IN ('voluntary', 'reporting')),
|
|
created_by_user_id text NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE(agent_id, workspace_slug, project_id)
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS agent_grants_agent_id_idx ON agent_grants(agent_id);
|
|
CREATE INDEX IF NOT EXISTS agent_grants_workspace_slug_idx ON agent_grants(workspace_slug);
|
|
|
|
CREATE TABLE IF NOT EXISTS agent_tokens (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
agent_id uuid NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
|
|
token_hash text NOT NULL UNIQUE,
|
|
name text NOT NULL,
|
|
status text NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'revoked', 'expired')),
|
|
expires_at timestamptz,
|
|
last_used_at timestamptz,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS agent_tokens_agent_id_idx ON agent_tokens(agent_id);
|
|
CREATE INDEX IF NOT EXISTS agent_tokens_status_idx ON agent_tokens(status);
|
|
|
|
CREATE TABLE IF NOT EXISTS pairing_codes (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
agent_id uuid NOT NULL REFERENCES agents(id) ON DELETE CASCADE,
|
|
code_hash text NOT NULL UNIQUE,
|
|
status text NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'used', 'expired', 'revoked')),
|
|
expires_at timestamptz NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
used_at timestamptz
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS pairing_codes_agent_id_idx ON pairing_codes(agent_id);
|
|
CREATE INDEX IF NOT EXISTS pairing_codes_status_idx ON pairing_codes(status);
|
|
|
|
CREATE TABLE IF NOT EXISTS agent_audit_events (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
agent_id uuid REFERENCES agents(id) ON DELETE SET NULL,
|
|
event_type text NOT NULL,
|
|
actor_user_id text,
|
|
metadata jsonb NOT NULL DEFAULT '{}'::jsonb,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS agent_audit_events_agent_id_idx ON agent_audit_events(agent_id);
|
|
CREATE INDEX IF NOT EXISTS agent_audit_events_event_type_idx ON agent_audit_events(event_type);
|
|
|
|
CREATE TABLE IF NOT EXISTS idempotency_keys (
|
|
key text PRIMARY KEY,
|
|
agent_id uuid REFERENCES agents(id) ON DELETE CASCADE,
|
|
request_hash text NOT NULL,
|
|
response_body jsonb NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
expires_at timestamptz NOT NULL
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idempotency_keys_expires_at_idx ON idempotency_keys(expires_at);
|