-- V1__init.sql — PostgreSQL schema for Cameleer Server -- PostgreSQL stores RBAC, configuration, and audit data only. -- All observability data (executions, metrics, diagrams, logs, stats) is in ClickHouse. -- ============================================================= -- RBAC -- ============================================================= CREATE TABLE users ( user_id TEXT PRIMARY KEY, provider TEXT NOT NULL, email TEXT, display_name TEXT, password_hash TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE TABLE roles ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name TEXT NOT NULL UNIQUE, description TEXT NOT NULL DEFAULT '', scope TEXT NOT NULL DEFAULT 'custom', system BOOLEAN NOT NULL DEFAULT false, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); INSERT INTO roles (id, name, description, scope, system) VALUES ('00000000-0000-0000-0000-000000000001', 'AGENT', 'Agent registration and data ingestion', 'system-wide', true), ('00000000-0000-0000-0000-000000000002', 'VIEWER', 'Read-only access to dashboards and data', 'system-wide', true), ('00000000-0000-0000-0000-000000000003', 'OPERATOR', 'Operational commands (start/stop/configure agents)', 'system-wide', true), ('00000000-0000-0000-0000-000000000004', 'ADMIN', 'Full administrative access', 'system-wide', true); CREATE TABLE groups ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), name TEXT NOT NULL UNIQUE, parent_group_id UUID REFERENCES groups(id) ON DELETE SET NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ); INSERT INTO groups (id, name) VALUES ('00000000-0000-0000-0000-000000000010', 'Admins'); CREATE TABLE group_roles ( group_id UUID NOT NULL REFERENCES groups(id) ON DELETE CASCADE, role_id UUID NOT NULL REFERENCES roles(id) ON DELETE CASCADE, PRIMARY KEY (group_id, role_id) ); INSERT INTO group_roles (group_id, role_id) VALUES ('00000000-0000-0000-0000-000000000010', '00000000-0000-0000-0000-000000000004'); CREATE TABLE user_groups ( user_id TEXT NOT NULL REFERENCES users(user_id) ON DELETE CASCADE, group_id UUID NOT NULL REFERENCES groups(id) ON DELETE CASCADE, PRIMARY KEY (user_id, group_id) ); CREATE TABLE user_roles ( user_id TEXT NOT NULL REFERENCES users(user_id) ON DELETE CASCADE, role_id UUID NOT NULL REFERENCES roles(id) ON DELETE CASCADE, PRIMARY KEY (user_id, role_id) ); CREATE INDEX idx_user_roles_user_id ON user_roles(user_id); CREATE INDEX idx_user_groups_user_id ON user_groups(user_id); CREATE INDEX idx_group_roles_group_id ON group_roles(group_id); CREATE INDEX idx_groups_parent ON groups(parent_group_id); -- ============================================================= -- Server configuration -- ============================================================= CREATE TABLE server_config ( config_key TEXT PRIMARY KEY, config_val JSONB NOT NULL, updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_by TEXT ); -- ============================================================= -- Application configuration -- ============================================================= CREATE TABLE application_config ( application TEXT NOT NULL, environment TEXT NOT NULL, config_val JSONB NOT NULL, version INTEGER NOT NULL DEFAULT 1, updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_by TEXT, PRIMARY KEY (application, environment) ); CREATE TABLE app_settings ( application_id TEXT NOT NULL, environment TEXT NOT NULL, sla_threshold_ms INTEGER NOT NULL DEFAULT 300, health_error_warn DOUBLE PRECISION NOT NULL DEFAULT 1.0, health_error_crit DOUBLE PRECISION NOT NULL DEFAULT 5.0, health_sla_warn DOUBLE PRECISION NOT NULL DEFAULT 99.0, health_sla_crit DOUBLE PRECISION NOT NULL DEFAULT 95.0, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), PRIMARY KEY (application_id, environment) ); -- ============================================================= -- Audit log -- ============================================================= CREATE TABLE audit_log ( id BIGSERIAL PRIMARY KEY, timestamp TIMESTAMPTZ NOT NULL DEFAULT now(), username TEXT NOT NULL, action TEXT NOT NULL, category TEXT NOT NULL, target TEXT, detail JSONB, result TEXT NOT NULL, ip_address TEXT, user_agent TEXT ); CREATE INDEX idx_audit_log_timestamp ON audit_log (timestamp DESC); CREATE INDEX idx_audit_log_username ON audit_log (username); CREATE INDEX idx_audit_log_category ON audit_log (category); CREATE INDEX idx_audit_log_action ON audit_log (action); CREATE INDEX idx_audit_log_target ON audit_log (target);