-- event CREATE TABLE event ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), slug TEXT NOT NULL UNIQUE, name TEXT NOT NULL, cover_image_path TEXT, is_active BOOLEAN NOT NULL DEFAULT TRUE, uploads_locked_at TIMESTAMPTZ, export_released_at TIMESTAMPTZ, export_zip_ready BOOLEAN NOT NULL DEFAULT FALSE, export_html_ready BOOLEAN NOT NULL DEFAULT FALSE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- user CREATE TABLE "user" ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), event_id UUID NOT NULL REFERENCES event(id) ON DELETE CASCADE, display_name TEXT NOT NULL, role user_role NOT NULL DEFAULT 'guest', is_banned BOOLEAN NOT NULL DEFAULT FALSE, uploads_hidden BOOLEAN NOT NULL DEFAULT FALSE, recovery_pin_hash TEXT NOT NULL, total_upload_bytes BIGINT NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- session CREATE TABLE session ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE, token_hash TEXT NOT NULL UNIQUE, expires_at TIMESTAMPTZ NOT NULL, last_seen_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- upload CREATE TABLE upload ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), event_id UUID NOT NULL REFERENCES event(id) ON DELETE CASCADE, user_id UUID NOT NULL REFERENCES "user"(id), original_path TEXT NOT NULL, preview_path TEXT, thumbnail_path TEXT, mime_type TEXT NOT NULL, original_size_bytes BIGINT NOT NULL, caption TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), deleted_at TIMESTAMPTZ ); -- hashtag CREATE TABLE hashtag ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), event_id UUID NOT NULL REFERENCES event(id) ON DELETE CASCADE, tag TEXT NOT NULL, UNIQUE (event_id, tag) ); -- upload_hashtag (junction) CREATE TABLE upload_hashtag ( upload_id UUID NOT NULL REFERENCES upload(id) ON DELETE CASCADE, hashtag_id UUID NOT NULL REFERENCES hashtag(id) ON DELETE CASCADE, PRIMARY KEY (upload_id, hashtag_id) ); -- comment CREATE TABLE comment ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), upload_id UUID NOT NULL REFERENCES upload(id) ON DELETE CASCADE, user_id UUID NOT NULL REFERENCES "user"(id), body TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), deleted_at TIMESTAMPTZ ); -- comment_hashtag (junction) CREATE TABLE comment_hashtag ( comment_id UUID NOT NULL REFERENCES comment(id) ON DELETE CASCADE, hashtag_id UUID NOT NULL REFERENCES hashtag(id) ON DELETE CASCADE, PRIMARY KEY (comment_id, hashtag_id) ); -- like CREATE TABLE "like" ( upload_id UUID NOT NULL REFERENCES upload(id) ON DELETE CASCADE, user_id UUID NOT NULL REFERENCES "user"(id) ON DELETE CASCADE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), PRIMARY KEY (upload_id, user_id) ); -- export_job CREATE TABLE export_job ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), event_id UUID NOT NULL REFERENCES event(id) ON DELETE CASCADE, type export_type NOT NULL, status export_status NOT NULL DEFAULT 'pending', progress_pct SMALLINT NOT NULL DEFAULT 0 CHECK (progress_pct BETWEEN 0 AND 100), file_path TEXT, error_message TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), completed_at TIMESTAMPTZ, UNIQUE (event_id, type) ); -- config (admin-configurable runtime settings) CREATE TABLE config ( key TEXT PRIMARY KEY, value TEXT NOT NULL, updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() );