-- Stonks Oracle - Initial PostgreSQL Schema -- Phase 1: Core data model -- Extensions CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; CREATE EXTENSION IF NOT EXISTS "pgcrypto"; -- ============================================================ -- Companies and Watchlists -- ============================================================ CREATE TABLE companies ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), ticker VARCHAR(20) NOT NULL, legal_name VARCHAR(500) NOT NULL, exchange VARCHAR(50), sector VARCHAR(200), industry VARCHAR(200), market_cap_bucket VARCHAR(50), active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE(ticker, exchange) ); CREATE TABLE company_aliases ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE, alias VARCHAR(500) NOT NULL, alias_type VARCHAR(50) NOT NULL DEFAULT 'brand', created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX idx_company_aliases_company ON company_aliases(company_id); CREATE INDEX idx_company_aliases_alias ON company_aliases(alias); CREATE TABLE watchlists ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), name VARCHAR(200) NOT NULL UNIQUE, description TEXT, active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE TABLE watchlist_members ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), watchlist_id UUID NOT NULL REFERENCES watchlists(id) ON DELETE CASCADE, company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE, added_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), UNIQUE(watchlist_id, company_id) ); -- ============================================================ -- Sources and Credentials -- ============================================================ CREATE TABLE sources ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE, source_type VARCHAR(50) NOT NULL, source_name VARCHAR(200) NOT NULL, config JSONB NOT NULL DEFAULT '{}', credibility_score FLOAT DEFAULT 0.5, retention_days INTEGER DEFAULT 365, access_policy VARCHAR(50) DEFAULT 'internal', active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX idx_sources_company ON sources(company_id); CREATE INDEX idx_sources_type ON sources(source_type); CREATE TABLE api_credentials_refs ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), provider VARCHAR(100) NOT NULL UNIQUE, secret_ref VARCHAR(500) NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- ============================================================ -- Ingestion Tracking -- ============================================================ CREATE TABLE ingestion_runs ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), source_id UUID REFERENCES sources(id), company_id UUID REFERENCES companies(id), source_type VARCHAR(50) NOT NULL, status VARCHAR(50) NOT NULL DEFAULT 'pending', started_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), completed_at TIMESTAMPTZ, items_fetched INTEGER DEFAULT 0, items_new INTEGER DEFAULT 0, error_message TEXT, retry_count INTEGER DEFAULT 0, next_retry_at TIMESTAMPTZ ); CREATE INDEX idx_ingestion_runs_status ON ingestion_runs(status); CREATE INDEX idx_ingestion_runs_source ON ingestion_runs(source_id);