-- Phase 2: share links, resumable uploads, thumbnails ALTER TABLE files ADD COLUMN has_thumbnail BOOLEAN NOT NULL DEFAULT FALSE; -- ── Share links ─────────────────────────────────────────────────────────────── CREATE TABLE share_links ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), file_id UUID NOT NULL REFERENCES files(id) ON DELETE CASCADE, owner_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, token TEXT NOT NULL UNIQUE, password_hash TEXT, -- Argon2id, NULL = no password expires_at TIMESTAMPTZ, -- NULL = never download_count INTEGER NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); CREATE INDEX idx_share_links_token ON share_links(token); CREATE INDEX idx_share_links_owner ON share_links(owner_id); CREATE INDEX idx_share_links_file ON share_links(file_id); -- ── Resumable uploads ──────────────────────────────────────────────────────── CREATE TABLE uploads ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), owner_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, folder_id UUID REFERENCES folders(id) ON DELETE SET NULL, filename TEXT NOT NULL, mime_type TEXT NOT NULL DEFAULT 'application/octet-stream', total_size BIGINT NOT NULL, uploaded BIGINT NOT NULL DEFAULT 0, storage_key TEXT NOT NULL UNIQUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), expires_at TIMESTAMPTZ NOT NULL DEFAULT NOW() + INTERVAL '24 hours' ); CREATE INDEX idx_uploads_owner ON uploads(owner_id);