chore(db): archive legacy migrations, stop gitignoring drizzle/

The drizzle/ folder was in .gitignore (line 34) — likely confused with
the build 'out/' dir. Effect: migration SQL never reached the server on
deploy, so the migration pipeline could never have worked. Only 7 of 18
files were ever force-tracked; 0000-0010 + most of manual/ were untracked.

- Remove drizzle/ from .gitignore; document why it must be tracked
- Archive legacy hand-rolled migrations 0000-0015 + manual/ to
  _archived_pre_baseline_2026-05-19/ (kept on disk; history retains old copies)
- Archive stale meta/ (knew of only 3 of 16 migrations)
- Baseline regeneration follows in subsequent commits
This commit is contained in:
Manohar Gupta 2026-05-23 12:05:50 +05:30
parent 5fe24b8c59
commit e7d68c2fc6
8 changed files with 7 additions and 163 deletions

8
.gitignore vendored
View file

@ -31,4 +31,10 @@ yarn-error.log*
# docker
.docker/
data/
drizzle/
# NOTE: drizzle/ is intentionally NOT ignored.
# It holds migration SQL + meta snapshots — these are SOURCE CODE and
# MUST be committed so the deploy pipeline can apply them on the server.
# Only transient introspection scratch output is ignored:
drizzle/_introspected/
drizzle/_archived_pre_baseline_2026-05-19/

View file

@ -1,45 +0,0 @@
-- Enable pgvector if not already
CREATE EXTENSION IF NOT EXISTS vector;
-- Memories table (photos with vision metadata)
CREATE TABLE IF NOT EXISTS memories (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
family_id UUID NOT NULL,
child_id UUID,
title TEXT,
description TEXT,
taken_at TIMESTAMPTZ,
r2_key TEXT NOT NULL,
r2_thumbnail_key TEXT,
mime_type TEXT,
size_bytes INTEGER,
width INTEGER,
height INTEGER,
vision_caption TEXT,
vision_tags TEXT[],
vision_embedding VECTOR(1536),
is_private BOOLEAN NOT NULL DEFAULT FALSE,
processing_status TEXT NOT NULL DEFAULT 'uploading'
CHECK (processing_status IN ('uploading', 'processing', 'ready', 'failed')),
uploaded_by UUID,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS memories_family_idx ON memories (family_id);
CREATE INDEX IF NOT EXISTS memories_child_idx ON memories (child_id);
-- Attachments table (files linked to log entries, no vision)
CREATE TABLE IF NOT EXISTS attachments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
family_id UUID NOT NULL,
log_entry_id UUID,
r2_key TEXT NOT NULL,
r2_thumbnail_key TEXT,
mime_type TEXT,
size_bytes INTEGER,
uploaded_by UUID,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS attachments_family_idx ON attachments (family_id);

View file

@ -1,28 +0,0 @@
-- G3.2: Medication dose log
CREATE TABLE IF NOT EXISTS medication_doses (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
medicine_id UUID NOT NULL,
family_id UUID NOT NULL,
administered_at TIMESTAMPTZ NOT NULL DEFAULT now(),
administered_by UUID,
amount_given TEXT,
notes TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS medication_doses_medicine_idx ON medication_doses (medicine_id);
CREATE INDEX IF NOT EXISTS medication_doses_family_idx ON medication_doses (family_id);
-- G3.4: Log corrections (audit trail for edited doses)
CREATE TABLE IF NOT EXISTS log_corrections (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
family_id UUID NOT NULL,
dose_id UUID NOT NULL REFERENCES medication_doses(id) ON DELETE CASCADE,
original_value JSONB NOT NULL,
corrected_value JSONB NOT NULL,
reason TEXT,
corrected_by UUID,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS log_corrections_dose_idx ON log_corrections (dose_id);

View file

@ -1,16 +0,0 @@
CREATE TABLE IF NOT EXISTS ai_usage (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
family_id UUID,
user_id UUID,
intent TEXT, -- structured_query | memory_search | general_parenting | medical_redirect
model_used TEXT,
prompt_tokens INTEGER,
completion_tokens INTEGER,
total_tokens INTEGER,
cost_estimate_paise NUMERIC(10,4), -- rough estimate for monitoring
duration_ms INTEGER,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX IF NOT EXISTS ai_usage_family_idx ON ai_usage (family_id);
CREATE INDEX IF NOT EXISTS ai_usage_created_idx ON ai_usage (created_at DESC);

View file

@ -1,11 +0,0 @@
CREATE TABLE IF NOT EXISTS milestone_achievements (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
child_id UUID NOT NULL REFERENCES children(id) ON DELETE CASCADE,
family_id UUID NOT NULL,
milestone_key TEXT NOT NULL,
achieved_at DATE NOT NULL,
notes TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
UNIQUE(child_id, milestone_key)
);
CREATE INDEX IF NOT EXISTS milestone_child_idx ON milestone_achievements (child_id);

View file

@ -1,37 +0,0 @@
CREATE TABLE IF NOT EXISTS member_profiles (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL UNIQUE REFERENCES users(id) ON DELETE CASCADE,
family_id UUID NOT NULL REFERENCES families(id) ON DELETE CASCADE,
slug TEXT NOT NULL UNIQUE,
display_name TEXT NOT NULL,
bio TEXT,
avatar_url TEXT,
is_public BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS recommended_products (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
profile_id UUID NOT NULL REFERENCES member_profiles(id) ON DELETE CASCADE,
title TEXT NOT NULL,
description TEXT,
url TEXT NOT NULL,
image_url TEXT,
category TEXT NOT NULL DEFAULT 'general',
display_order INTEGER NOT NULL DEFAULT 0,
is_active BOOLEAN NOT NULL DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE TABLE IF NOT EXISTS product_clicks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
product_id UUID NOT NULL REFERENCES recommended_products(id) ON DELETE CASCADE,
clicked_at TIMESTAMPTZ NOT NULL DEFAULT now(),
referrer TEXT,
ip_hash TEXT
);
CREATE INDEX IF NOT EXISTS member_profiles_slug_idx ON member_profiles (slug);
CREATE INDEX IF NOT EXISTS recommended_products_profile_idx ON recommended_products (profile_id, display_order);
CREATE INDEX IF NOT EXISTS product_clicks_product_idx ON product_clicks (product_id, clicked_at DESC);

View file

@ -1,17 +0,0 @@
-- Create audit_log table
CREATE TABLE IF NOT EXISTS audit_log (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID,
family_id UUID,
action TEXT NOT NULL,
metadata JSONB,
ip_address TEXT,
user_agent TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create index for queries
CREATE INDEX IF NOT EXISTS idx_audit_log_user ON audit_log(user_id);
CREATE INDEX IF NOT EXISTS idx_audit_log_family ON audit_log(family_id);
CREATE INDEX IF NOT EXISTS idx_audit_log_action ON audit_log(action);
CREATE INDEX IF NOT EXISTS idx_audit_log_created ON audit_log(created_at DESC);

View file

@ -1,8 +0,0 @@
-- Create password_resets table
CREATE TABLE IF NOT EXISTS password_resets (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id),
token TEXT UNIQUE NOT NULL,
expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
used_at TIMESTAMP WITH TIME ZONE
);