chore: remove obsolete scripts and move legacy SQL schema to archive

This commit is contained in:
2026-05-07 15:24:31 -07:00
parent 057115a9fc
commit 7610ca58ca
3 changed files with 0 additions and 37 deletions

View File

@@ -0,0 +1,496 @@
-- ==================================================
-- VIBN UNIFIED SCHEMA FOR COOLIFY
-- Combines Firebase collections + Railway PostgreSQL
-- ==================================================
-- Extensions
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- ==================================================
-- USERS (replaces Firebase Auth + Firestore users)
-- ==================================================
CREATE TABLE users (
id SERIAL PRIMARY KEY,
uid VARCHAR(255) UNIQUE NOT NULL, -- Firebase UID or generated
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255), -- For email/password auth
display_name VARCHAR(255),
photo_url VARCHAR(500),
workspace VARCHAR(255) UNIQUE NOT NULL, -- URL slug: "marks-account"
-- OAuth providers
google_id VARCHAR(255) UNIQUE,
github_id VARCHAR(255) UNIQUE,
-- Metadata
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
last_login TIMESTAMP,
settings JSONB DEFAULT '{}'::jsonb
);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_workspace ON users(workspace);
-- ==================================================
-- CLIENTS (Organizations/Companies)
-- ==================================================
CREATE TABLE clients (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
slug VARCHAR(255) UNIQUE NOT NULL, -- URL-friendly
owner_user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
-- Subscription/Billing
subscription_tier VARCHAR(50) DEFAULT 'free', -- free, starter, pro, enterprise
stripe_customer_id VARCHAR(255),
max_users INTEGER DEFAULT 5,
max_projects INTEGER DEFAULT 10,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
metadata JSONB DEFAULT '{}'::jsonb
);
CREATE INDEX idx_clients_owner ON clients(owner_user_id);
CREATE INDEX idx_clients_slug ON clients(slug);
-- ==================================================
-- PROJECTS (replaces Firebase projects collection)
-- ==================================================
CREATE TABLE projects (
id SERIAL PRIMARY KEY,
firebase_id VARCHAR(255) UNIQUE, -- For migration compatibility
client_id INTEGER REFERENCES clients(id) ON DELETE CASCADE,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, -- Owner
-- Project Identity
name VARCHAR(255) NOT NULL,
slug VARCHAR(255) NOT NULL,
workspace VARCHAR(255) NOT NULL, -- User workspace slug
-- Product Details
product_name VARCHAR(255) NOT NULL,
product_vision TEXT,
project_type VARCHAR(50) DEFAULT 'scratch', -- scratch, existing
-- Status
status VARCHAR(50) DEFAULT 'active', -- active, on_hold, completed, archived
current_phase VARCHAR(50) DEFAULT 'collection', -- collection, extraction, vision, mvp, marketing
phase_status VARCHAR(50) DEFAULT 'not_started', -- not_started, in_progress, completed
-- Integrations
workspace_path VARCHAR(500), -- Local directory path
workspace_name VARCHAR(255),
is_for_client BOOLEAN DEFAULT false,
has_logo BOOLEAN DEFAULT false,
has_domain BOOLEAN DEFAULT false,
has_website BOOLEAN DEFAULT false,
has_github BOOLEAN DEFAULT false,
has_chatgpt BOOLEAN DEFAULT false,
github_repo VARCHAR(500),
chatgpt_project_id VARCHAR(255),
-- Git/Deployment
gitea_repo_url VARCHAR(500),
coolify_app_id VARCHAR(255),
coolify_project_uuid VARCHAR(255),
deployment_url VARCHAR(500),
-- Phase Data
phase_data JSONB DEFAULT '{}'::jsonb, -- Stores all phase artifacts
phase_history JSONB DEFAULT '[]'::jsonb,
phase_scores JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
UNIQUE(client_id, slug)
);
CREATE INDEX idx_projects_client ON projects(client_id);
CREATE INDEX idx_projects_user ON projects(user_id);
CREATE INDEX idx_projects_workspace ON projects(workspace);
CREATE INDEX idx_projects_status ON projects(status);
CREATE INDEX idx_projects_firebase_id ON projects(firebase_id);
-- ==================================================
-- PROJECT_CONTRIBUTORS (Team collaboration)
-- ==================================================
CREATE TABLE project_contributors (
id SERIAL PRIMARY KEY,
project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
role VARCHAR(50) DEFAULT 'developer', -- owner, admin, developer, viewer
permissions JSONB DEFAULT '{"read":true,"write":true,"admin":false}'::jsonb,
joined_at TIMESTAMP DEFAULT NOW(),
total_time_minutes INTEGER DEFAULT 0,
UNIQUE(project_id, user_id)
);
CREATE INDEX idx_contributors_project ON project_contributors(project_id);
CREATE INDEX idx_contributors_user ON project_contributors(user_id);
-- ==================================================
-- SESSIONS (replaces both Firebase sessions + Railway logs)
-- ==================================================
CREATE TABLE sessions (
id SERIAL PRIMARY KEY,
session_id VARCHAR(255) UNIQUE NOT NULL,
firebase_id VARCHAR(255), -- For migration
project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
-- Timing
started_at TIMESTAMP NOT NULL DEFAULT NOW(),
last_updated TIMESTAMP NOT NULL DEFAULT NOW(),
ended_at TIMESTAMP,
duration_minutes INTEGER DEFAULT 0,
-- Status
status VARCHAR(50) DEFAULT 'active', -- active, idle, completed
needs_project_association BOOLEAN DEFAULT false,
-- Context
workspace_path VARCHAR(500),
workspace_name VARCHAR(255),
ide_name VARCHAR(50) DEFAULT 'Cursor', -- Cursor, VS Code, etc.
-- Content
conversation JSONB DEFAULT '[]'::jsonb, -- Full chat history
file_changes JSONB DEFAULT '[]'::jsonb, -- Files modified
files_modified TEXT[], -- Quick array for queries
-- Metrics
message_count INTEGER DEFAULT 0,
user_message_count INTEGER DEFAULT 0,
assistant_message_count INTEGER DEFAULT 0,
file_change_count INTEGER DEFAULT 0,
-- AI Usage & Cost
total_tokens INTEGER DEFAULT 0,
prompt_tokens INTEGER DEFAULT 0,
completion_tokens INTEGER DEFAULT 0,
estimated_cost_usd NUMERIC(10,6) DEFAULT 0,
model VARCHAR(100),
-- AI Insights
summary TEXT,
conversation_summary TEXT,
tasks_identified JSONB DEFAULT '[]'::jsonb,
decisions_made JSONB DEFAULT '[]'::jsonb,
technologies_used JSONB DEFAULT '[]'::jsonb,
metadata JSONB DEFAULT '{}'::jsonb
);
CREATE INDEX idx_sessions_project ON sessions(project_id);
CREATE INDEX idx_sessions_user ON sessions(user_id);
CREATE INDEX idx_sessions_status ON sessions(status);
CREATE INDEX idx_sessions_started ON sessions(started_at);
CREATE INDEX idx_sessions_session_id ON sessions(session_id);
CREATE INDEX idx_sessions_firebase_id ON sessions(firebase_id);
-- ==================================================
-- WORK_COMPLETED (AI-extracted accomplishments)
-- ==================================================
CREATE TABLE work_completed (
id SERIAL PRIMARY KEY,
session_id INTEGER REFERENCES sessions(id) ON DELETE CASCADE,
project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
title VARCHAR(500) NOT NULL,
description TEXT,
category VARCHAR(100), -- frontend, backend, database, deployment, testing, docs, bugfix
files_modified JSONB DEFAULT '[]'::jsonb,
completed_at TIMESTAMP DEFAULT NOW(),
extracted_by_ai BOOLEAN DEFAULT true
);
CREATE INDEX idx_work_completed_project ON work_completed(project_id);
CREATE INDEX idx_work_completed_session ON work_completed(session_id);
CREATE INDEX idx_work_completed_category ON work_completed(category);
-- ==================================================
-- ARCHITECTURAL_DECISIONS (Design decisions)
-- ==================================================
CREATE TABLE architectural_decisions (
id SERIAL PRIMARY KEY,
project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
identified_by_session_id INTEGER REFERENCES sessions(id) ON DELETE SET NULL,
title VARCHAR(500) NOT NULL,
context TEXT,
decision TEXT NOT NULL,
consequences TEXT,
status VARCHAR(50) DEFAULT 'accepted', -- proposed, accepted, deprecated, superseded
tags JSONB DEFAULT '[]'::jsonb,
decided_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_arch_decisions_project ON architectural_decisions(project_id);
CREATE INDEX idx_arch_decisions_status ON architectural_decisions(status);
-- ==================================================
-- ARCHITECTURE_DOCS (Auto-maintained documentation)
-- ==================================================
CREATE TABLE architecture_docs (
id SERIAL PRIMARY KEY,
project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
doc_type VARCHAR(100) NOT NULL, -- tech_stack, data_model, api_design, deployment
content TEXT NOT NULL,
version INTEGER DEFAULT 1,
last_ai_update TIMESTAMP,
last_manual_update TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
UNIQUE(project_id, doc_type)
);
CREATE INDEX idx_arch_docs_project ON architecture_docs(project_id);
CREATE INDEX idx_arch_docs_type ON architecture_docs(doc_type);
-- ==================================================
-- TASKS (Project tasks)
-- ==================================================
CREATE TABLE tasks (
id SERIAL PRIMARY KEY,
project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
title VARCHAR(500) NOT NULL,
description TEXT,
status VARCHAR(50) DEFAULT 'todo', -- todo, in_progress, review, done, blocked
priority VARCHAR(50) DEFAULT 'medium', -- low, medium, high, urgent
assigned_to INTEGER REFERENCES users(id) ON DELETE SET NULL,
created_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW(),
completed_at TIMESTAMP,
identified_by_session_id INTEGER REFERENCES sessions(id) ON DELETE SET NULL,
related_sessions JSONB DEFAULT '[]'::jsonb,
metadata JSONB DEFAULT '{}'::jsonb
);
CREATE INDEX idx_tasks_project ON tasks(project_id);
CREATE INDEX idx_tasks_status ON tasks(status);
CREATE INDEX idx_tasks_assigned ON tasks(assigned_to);
-- ==================================================
-- ANALYSES (replaces Firebase analyses collection)
-- ==================================================
CREATE TABLE analyses (
id SERIAL PRIMARY KEY,
firebase_id VARCHAR(255), -- For migration
project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
type VARCHAR(50) NOT NULL, -- code, chatgpt, github, combined
summary TEXT,
tech_stack JSONB DEFAULT '[]'::jsonb,
features JSONB DEFAULT '[]'::jsonb,
raw_data JSONB DEFAULT '{}'::jsonb,
created_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_analyses_project ON analyses(project_id);
CREATE INDEX idx_analyses_type ON analyses(type);
-- ==================================================
-- API_KEYS (User API keys for extension)
-- ==================================================
CREATE TABLE api_keys (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
key_hash VARCHAR(255) UNIQUE NOT NULL,
key_prefix VARCHAR(20), -- First few chars for display
name VARCHAR(255), -- User-friendly name
last_used TIMESTAMP,
created_at TIMESTAMP DEFAULT NOW(),
expires_at TIMESTAMP,
revoked BOOLEAN DEFAULT false
);
CREATE INDEX idx_api_keys_user ON api_keys(user_id);
CREATE INDEX idx_api_keys_hash ON api_keys(key_hash);
-- ==================================================
-- USER_SESSIONS (Authentication sessions)
-- ==================================================
CREATE TABLE user_sessions (
id SERIAL PRIMARY KEY,
user_id INTEGER REFERENCES users(id) ON DELETE CASCADE,
token VARCHAR(500) UNIQUE NOT NULL,
refresh_token VARCHAR(500),
created_at TIMESTAMP DEFAULT NOW(),
expires_at TIMESTAMP,
last_activity TIMESTAMP DEFAULT NOW(),
ip_address VARCHAR(45),
user_agent TEXT
);
CREATE INDEX idx_user_sessions_token ON user_sessions(token);
CREATE INDEX idx_user_sessions_user ON user_sessions(user_id);
CREATE INDEX idx_user_sessions_expires ON user_sessions(expires_at);
-- ==================================================
-- KNOWLEDGE_ITEMS (Chat/Code context for AI)
-- ==================================================
CREATE TABLE knowledge_items (
id SERIAL PRIMARY KEY,
project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE,
item_type VARCHAR(50) NOT NULL, -- chat_history, code_file, github_issue, documentation
source VARCHAR(100), -- cursor, chatgpt, github, manual
title VARCHAR(500),
content TEXT,
metadata JSONB DEFAULT '{}'::jsonb,
-- Status
processed BOOLEAN DEFAULT false,
chunk_count INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT NOW(),
updated_at TIMESTAMP DEFAULT NOW()
);
CREATE INDEX idx_knowledge_items_project ON knowledge_items(project_id);
CREATE INDEX idx_knowledge_items_type ON knowledge_items(item_type);
CREATE INDEX idx_knowledge_items_processed ON knowledge_items(processed);
-- ==================================================
-- ANALYTICS VIEWS
-- ==================================================
-- Project health overview
CREATE OR REPLACE VIEW project_health AS
SELECT
p.id as project_id,
p.name as project_name,
p.status,
p.current_phase,
c.name as client_name,
COUNT(DISTINCT s.id) as session_count,
COUNT(DISTINCT s.user_id) as active_users,
SUM(s.total_tokens) as total_tokens,
SUM(s.estimated_cost_usd) as total_cost,
COUNT(DISTINCT t.id) FILTER (WHERE t.status = 'done') as completed_tasks,
COUNT(DISTINCT t.id) FILTER (WHERE t.status != 'done') as pending_tasks,
MAX(s.last_updated) as last_activity
FROM projects p
LEFT JOIN clients c ON p.client_id = c.id
LEFT JOIN sessions s ON s.project_id = p.id
LEFT JOIN tasks t ON t.project_id = p.id
GROUP BY p.id, p.name, p.status, p.current_phase, c.name;
-- User activity summary
CREATE OR REPLACE VIEW user_activity AS
SELECT
u.id as user_id,
u.email,
u.display_name,
COUNT(DISTINCT s.id) as session_count,
COUNT(DISTINCT s.project_id) as projects_worked_on,
SUM(s.total_tokens) as total_tokens,
SUM(s.estimated_cost_usd) as total_cost,
MAX(s.last_updated) as last_activity
FROM users u
LEFT JOIN sessions s ON s.user_id = u.id
GROUP BY u.id, u.email, u.display_name;
-- Organization billing summary
CREATE OR REPLACE VIEW organization_billing AS
SELECT
c.id as client_id,
c.name as organization_name,
c.subscription_tier,
COUNT(DISTINCT u.id) as total_users,
COUNT(DISTINCT p.id) as total_projects,
COUNT(DISTINCT s.id) as total_sessions,
SUM(s.total_tokens) as total_tokens,
SUM(s.estimated_cost_usd) as total_cost,
SUM(s.estimated_cost_usd) FILTER (
WHERE s.started_at >= DATE_TRUNC('month', CURRENT_DATE)
) as current_month_cost
FROM clients c
LEFT JOIN projects p ON p.client_id = c.id
LEFT JOIN sessions s ON s.project_id = p.id
LEFT JOIN users u ON u.id = c.owner_user_id OR EXISTS (
SELECT 1 FROM project_contributors pc
WHERE pc.project_id = p.id AND pc.user_id = u.id
)
GROUP BY c.id, c.name, c.subscription_tier;
-- ==================================================
-- HELPER FUNCTIONS
-- ==================================================
-- Auto-update updated_at timestamps
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ language 'plpgsql';
-- Apply to tables
CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON users
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_clients_updated_at BEFORE UPDATE ON clients
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_projects_updated_at BEFORE UPDATE ON projects
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_sessions_updated_at BEFORE UPDATE ON sessions
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- ==================================================
-- SEED DATA (Optional)
-- ==================================================
-- Create default user (you)
INSERT INTO users (uid, email, display_name, workspace)
VALUES
('mark-admin-001', 'mark@getacquired.com', 'Mark Henderson', 'marks-account')
ON CONFLICT (email) DO NOTHING;
-- Create default client (your organization)
INSERT INTO clients (name, slug, owner_user_id, subscription_tier)
VALUES
('VIBN', 'vibn', 1, 'enterprise')
ON CONFLICT (slug) DO NOTHING;
COMMENT ON TABLE users IS 'VIBN users (developers, team members)';
COMMENT ON TABLE clients IS 'Organizations/Companies using VIBN';
COMMENT ON TABLE projects IS 'Development projects under organizations';
COMMENT ON TABLE sessions IS 'AI coding sessions with full conversation logs';
COMMENT ON TABLE work_completed IS 'AI-extracted accomplishments from sessions';
COMMENT ON TABLE architectural_decisions IS 'Design decisions made during development';