nxtgauge-backend-rust/crates/db/migrations/20260402030000_strict_employee_separation.up.sql
Ashwin Kumar Sivakumar dbb02e54cc
All checks were successful
build-and-release / build (catering-services) (push) Successful in 1m43s
build-and-release / build (companies) (push) Successful in 1m56s
build-and-release / build (cron) (push) Successful in 2m10s
build-and-release / build (customers) (push) Successful in 2m29s
build-and-release / build (gateway) (push) Successful in 51s
build-and-release / build (fitness-trainers) (push) Successful in 1m22s
build-and-release / build (developers) (push) Successful in 1m50s
build-and-release / build (employees) (push) Successful in 2m42s
build-and-release / build (job-seekers) (push) Successful in 2m1s
build-and-release / build (jobs) (push) Successful in 2m10s
build-and-release / build (graphic-designers) (push) Successful in 2m51s
build-and-release / build (leads) (push) Successful in 2m22s
build-and-release / build (photographers) (push) Successful in 1m42s
build-and-release / build (makeup-artists) (push) Successful in 2m49s
build-and-release / build (payments) (push) Successful in 2m11s
build-and-release / build (social-media-managers) (push) Successful in 2m33s
build-and-release / build (tutors) (push) Successful in 2m36s
build-and-release / build (ugc-content-creators) (push) Successful in 2m12s
build-and-release / build (video-editors) (push) Successful in 2m38s
build-and-release / build (users) (push) Successful in 4m29s
fix(db): stop wiping employees table on every migration run, restore phone column
CRITICAL: 20260402030000_strict_employee_separation.up.sql contained an
unconditional DROP TABLE IF EXISTS employees CASCADE followed by a bare
CREATE TABLE, written as a one-time schema transformation back when it was
authored. The db-migrate tool has no applied-migrations tracking table - it
replays every .sql file on every run - which turned that one-time DROP into
a destructive operation that wipes every employee account (including admin
accounts) on every single migration job run. This is what caused today's
"db error while logging in": the phone column (never present in any tracked
migration, added out-of-band in production at some point) was gone after the
recreate, and every employee row - including the account in use this session
- was deleted.

Fix: make the table creation a plain idempotent CREATE TABLE IF NOT EXISTS
(the standalone-schema transition it performed already happened in
production long ago, so the drop was never needed for correctness going
forward). Add a proper migration for the phone column so it's tracked
instead of relying on an undocumented manual ALTER.

Confirmed via kubectl-verified row count (0) and a pre-incident backup
(2026-07-18T21:00:03Z, predates the destructive run) that the deleted row
is recoverable; restoring it separately as a one-time data fix, not part of
this schema migration.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-19 05:40:48 +05:30

42 lines
2 KiB
SQL

-- UP: 20260402030000_strict_employee_separation.up.sql
--
-- Originally: "Drop old employees table (was linked to users - replacing with
-- standalone auth)" - a one-time schema transformation. The db-migrate tool
-- (crates/db-migrate) has no applied-migrations tracking table; it replays
-- every .sql file on every run, which turned this one-time DROP TABLE ...
-- CASCADE into a destructive operation that wiped the live employees table
-- (and every employee account, including admin accounts) on every migration
-- run. The standalone-schema transition already happened in production long
-- ago, so this is now safely a plain idempotent create.
-- 1. EMPLOYEES (Standalone Table - Not Linked to 'users')
CREATE TABLE IF NOT EXISTS employees (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
first_name VARCHAR(100) NOT NULL,
last_name VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
employee_code VARCHAR(50) UNIQUE,
department_id UUID REFERENCES departments(id) ON DELETE SET NULL,
designation_id UUID REFERENCES designations(id) ON DELETE SET NULL,
role_code VARCHAR(50) NOT NULL DEFAULT 'STAFF',
status VARCHAR(50) NOT NULL DEFAULT 'ACTIVE',
joined_at DATE NOT NULL DEFAULT CURRENT_DATE,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- 2. EMPLOYEE SESSIONS (Standalone Auth)
CREATE TABLE IF NOT EXISTS employee_sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
employee_id UUID NOT NULL REFERENCES employees(id) ON DELETE CASCADE,
token_hash VARCHAR(255) UNIQUE NOT NULL,
expires_at TIMESTAMPTZ NOT NULL,
revoked BOOLEAN NOT NULL DEFAULT false,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Indexes
CREATE INDEX IF NOT EXISTS idx_employees_email ON employees(email);
CREATE INDEX IF NOT EXISTS idx_employees_status ON employees(status);
CREATE INDEX IF NOT EXISTS idx_employee_sessions_token ON employee_sessions(token_hash);