Initial project snapshot
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
CREATE TABLE IF NOT EXISTS clusters (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
slug TEXT NOT NULL UNIQUE,
|
||||
name TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
region TEXT,
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT clusters_status_check
|
||||
CHECK (status IN ('active', 'disabled', 'archived', 'degraded'))
|
||||
);
|
||||
|
||||
INSERT INTO clusters (slug, name, status, region, metadata)
|
||||
VALUES ('default', 'Default Cluster', 'active', NULL, '{"bootstrap":true}'::jsonb)
|
||||
ON CONFLICT (slug) DO NOTHING;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS cluster_memberships (
|
||||
cluster_id UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE,
|
||||
node_id UUID NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,
|
||||
membership_status TEXT NOT NULL DEFAULT 'active',
|
||||
joined_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
last_seen_at TIMESTAMPTZ,
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
PRIMARY KEY (cluster_id, node_id),
|
||||
CONSTRAINT cluster_memberships_status_check
|
||||
CHECK (membership_status IN ('active', 'draining', 'disabled', 'revoked'))
|
||||
);
|
||||
|
||||
INSERT INTO cluster_memberships (cluster_id, node_id, membership_status, joined_at, last_seen_at, metadata)
|
||||
SELECT c.id, n.id, 'active', COALESCE(n.created_at, NOW()), n.last_seen_at, '{"backfilled":true}'::jsonb
|
||||
FROM clusters c
|
||||
CROSS JOIN nodes n
|
||||
WHERE c.slug = 'default'
|
||||
ON CONFLICT (cluster_id, node_id) DO NOTHING;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS node_identities (
|
||||
node_id UUID PRIMARY KEY REFERENCES nodes(id) ON DELETE CASCADE,
|
||||
public_key TEXT NOT NULL,
|
||||
certificate_serial TEXT,
|
||||
certificate_not_before TIMESTAMPTZ,
|
||||
certificate_not_after TIMESTAMPTZ,
|
||||
identity_status TEXT NOT NULL DEFAULT 'pending',
|
||||
rotated_at TIMESTAMPTZ,
|
||||
revoked_at TIMESTAMPTZ,
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT node_identities_status_check
|
||||
CHECK (identity_status IN ('pending', 'active', 'rotating', 'revoked'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS node_join_tokens (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
cluster_id UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE,
|
||||
token_hash TEXT NOT NULL UNIQUE,
|
||||
scope JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
expires_at TIMESTAMPTZ NOT NULL,
|
||||
max_uses INTEGER NOT NULL DEFAULT 1,
|
||||
used_count INTEGER NOT NULL DEFAULT 0,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
created_by_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
revoked_at TIMESTAMPTZ,
|
||||
CONSTRAINT node_join_tokens_status_check
|
||||
CHECK (status IN ('active', 'revoked', 'expired')),
|
||||
CONSTRAINT node_join_tokens_max_uses_check
|
||||
CHECK (max_uses > 0),
|
||||
CONSTRAINT node_join_tokens_used_count_check
|
||||
CHECK (used_count >= 0)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_node_join_tokens_cluster_status
|
||||
ON node_join_tokens(cluster_id, status, expires_at);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS node_join_requests (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
cluster_id UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE,
|
||||
join_token_id UUID REFERENCES node_join_tokens(id) ON DELETE SET NULL,
|
||||
node_name TEXT NOT NULL,
|
||||
node_fingerprint TEXT NOT NULL,
|
||||
public_key TEXT NOT NULL,
|
||||
reported_capabilities JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
reported_facts JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
requested_roles JSONB NOT NULL DEFAULT '[]'::JSONB,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
reviewed_by_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
reviewed_at TIMESTAMPTZ,
|
||||
approved_node_id UUID REFERENCES nodes(id) ON DELETE SET NULL,
|
||||
rejection_reason TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT node_join_requests_status_check
|
||||
CHECK (status IN ('pending', 'approved', 'rejected', 'cancelled'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_node_join_requests_cluster_status
|
||||
ON node_join_requests(cluster_id, status, created_at DESC);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_node_join_requests_pending_fingerprint
|
||||
ON node_join_requests(cluster_id, node_fingerprint)
|
||||
WHERE status = 'pending';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS node_role_assignments (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
cluster_id UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE,
|
||||
node_id UUID NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,
|
||||
organization_id UUID REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
role TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
policy JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
assigned_by_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
assigned_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
revoked_at TIMESTAMPTZ,
|
||||
CONSTRAINT node_role_assignments_status_check
|
||||
CHECK (status IN ('active', 'disabled', 'revoked')),
|
||||
CONSTRAINT node_role_assignments_role_check
|
||||
CHECK (role IN (
|
||||
'entry-node',
|
||||
'relay-node',
|
||||
'core-mesh',
|
||||
'rdp-worker',
|
||||
'vnc-worker',
|
||||
'vpn-exit',
|
||||
'vpn-connector',
|
||||
'file-storage-cache',
|
||||
'update-cache',
|
||||
'video-relay'
|
||||
))
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_node_role_assignments_unique_active
|
||||
ON node_role_assignments(cluster_id, node_id, role, COALESCE(organization_id, '00000000-0000-0000-0000-000000000000'::uuid))
|
||||
WHERE status = 'active';
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_node_role_assignments_cluster
|
||||
ON node_role_assignments(cluster_id, role, status);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS node_heartbeats (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
cluster_id UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE,
|
||||
node_id UUID NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,
|
||||
health_status TEXT NOT NULL DEFAULT 'unknown',
|
||||
reported_version TEXT,
|
||||
capabilities JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
service_states JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
observed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
CONSTRAINT node_heartbeats_health_status_check
|
||||
CHECK (health_status IN ('unknown', 'healthy', 'warning', 'critical'))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_node_heartbeats_cluster_node_observed
|
||||
ON node_heartbeats(cluster_id, node_id, observed_at DESC);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS node_latest_heartbeats (
|
||||
cluster_id UUID NOT NULL REFERENCES clusters(id) ON DELETE CASCADE,
|
||||
node_id UUID NOT NULL REFERENCES nodes(id) ON DELETE CASCADE,
|
||||
heartbeat_id UUID REFERENCES node_heartbeats(id) ON DELETE SET NULL,
|
||||
health_status TEXT NOT NULL DEFAULT 'unknown',
|
||||
reported_version TEXT,
|
||||
capabilities JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
service_states JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
metadata JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
observed_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
PRIMARY KEY (cluster_id, node_id),
|
||||
CONSTRAINT node_latest_heartbeats_health_status_check
|
||||
CHECK (health_status IN ('unknown', 'healthy', 'warning', 'critical'))
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS cluster_audit_events (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
cluster_id UUID REFERENCES clusters(id) ON DELETE SET NULL,
|
||||
actor_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
event_type TEXT NOT NULL,
|
||||
target_type TEXT NOT NULL,
|
||||
target_id TEXT,
|
||||
payload JSONB NOT NULL DEFAULT '{}'::JSONB,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_cluster_audit_events_cluster_created
|
||||
ON cluster_audit_events(cluster_id, created_at DESC);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_cluster_audit_events_type_created
|
||||
ON cluster_audit_events(event_type, created_at DESC);
|
||||
Reference in New Issue
Block a user