MVP.0 Migrations
Version: MVP.0 (Foundation + Hostaway One-Way Distribution) Timeline: Weeks 1-10 Status: Ready for Implementation
Overview
These migrations establish the foundational database schema for TVL platform MVP.0, including:
- Multi-tenant organization and account structure
- User identity and authentication
- Role-based access control
- Space and Unit supply management
- Channel distribution (Hostaway one-way sync)
- Basic audit logging
Total Tables: 14
Migration Scripts
Execute in this order:
001_initial_schema.sql
Purpose: Create all core tables for MVP.0 Tables Created:
- organizations(5 columns)
- accounts(8 columns)
- users(12 columns)
- memberships(10 columns)
- roles(5 columns)
- permissions(5 columns)
- sessions(10 columns)
- spaces(16 columns)
- units(14 columns)
- unit_snapshots(7 columns)
- channel_targets(12 columns)
- channel_listings(13 columns)
- outbound_audit(13 columns)
- audit_events(10 columns)
Dependencies: None (initial schema)
Rollback: DROP SCHEMA public CASCADE; CREATE SCHEMA public;
002_rls_policies.sql
Purpose: Enable Row-Level Security for multi-tenancy Policies Created:
- Org isolation policies (all tables)
- Account-level access policies
- User session policies
Dependencies: 001_initial_schema.sql
Rollback: DROP POLICY ... ON ... for each policy
003_seed_roles.sql
Purpose: Seed system roles and permissions Data Seeded:
- Roles: admin, ops, owner_admin, manager, viewer
- Permissions: 30+ core permissions
- RolePermission mappings
Dependencies: 001_initial_schema.sql
Rollback: DELETE FROM role_permissions; DELETE FROM permissions; DELETE FROM roles WHERE is_system=true;
Prerequisites
Database Requirements
- PostgreSQL 15+
- Extensions: citext,uuid-ossp,pgcrypto
- Superuser access (for RLS policies)
Environment Variables
DATABASE_URL=postgresql://user:pass@host:5432/tvl_mvp
DB_POOL_MIN=2
DB_POOL_MAX=10
Execution Instructions
Development Environment
cd /migrations/mvp.0
# Run all migrations
psql $DATABASE_URL -f 001_initial_schema.sql
psql $DATABASE_URL -f 002_rls_policies.sql
psql $DATABASE_URL -f 003_seed_roles.sql
# Verify
psql $DATABASE_URL -c "\dt"  # List all tables
psql $DATABASE_URL -c "SELECT COUNT(*) FROM roles;"  # Should return 5
Production Environment
# Use migration tool (e.g., Flyway, Liquibase, or custom Node script)
npm run migrate:up
# Or manually with transaction wrapper
psql $DATABASE_URL << EOF
BEGIN;
\i 001_initial_schema.sql
\i 002_rls_policies.sql
\i 003_seed_roles.sql
COMMIT;
EOF
Validation Tests
After migration, run these validation queries:
Test 1: Table Count
SELECT COUNT(*) AS table_count
FROM information_schema.tables
WHERE table_schema = 'public';
-- Expected: 14
Test 2: Role Seeding
SELECT name FROM roles ORDER BY name;
-- Expected: admin, manager, ops, owner_admin, viewer
Test 3: RLS Enabled
SELECT tablename, rowsecurity
FROM pg_tables
WHERE schemaname = 'public' AND rowsecurity = true;
-- Expected: All 14 tables
Test 4: Foreign Keys
SELECT COUNT(*)
FROM information_schema.table_constraints
WHERE constraint_type = 'FOREIGN KEY';
-- Expected: 25+ foreign keys
Rollback Procedure
WARNING: This will delete all data!
BEGIN;
-- Drop policies first
DROP POLICY IF EXISTS org_isolation ON organizations;
DROP POLICY IF EXISTS org_isolation ON accounts;
-- ... (all policies)
-- Drop tables in reverse dependency order
DROP TABLE IF EXISTS audit_events CASCADE;
DROP TABLE IF EXISTS outbound_audit CASCADE;
DROP TABLE IF EXISTS channel_listings CASCADE;
DROP TABLE IF EXISTS channel_targets CASCADE;
DROP TABLE IF EXISTS unit_snapshots CASCADE;
DROP TABLE IF EXISTS units CASCADE;
DROP TABLE IF EXISTS spaces CASCADE;
DROP TABLE IF EXISTS sessions CASCADE;
DROP TABLE IF EXISTS role_permissions CASCADE;
DROP TABLE IF EXISTS permissions CASCADE;
DROP TABLE IF EXISTS memberships CASCADE;
DROP TABLE IF EXISTS roles CASCADE;
DROP TABLE IF EXISTS users CASCADE;
DROP TABLE IF EXISTS accounts CASCADE;
DROP TABLE IF EXISTS organizations CASCADE;
COMMIT;
Known Issues
Issue 1: RLS Policy Performance
Symptom: Slow queries on large tables with RLS enabled Solution: Create partial indexes on org_id + status columns Status: Monitored
Issue 2: account_id Nullable
Symptom: Some tables missing account_id enforcement Solution: Add NOT NULL constraint in MVP.1 after data migration Status: Deferred to MVP.1
Next Steps
After successful MVP.0 migration:
- Verify data model: Create test Organization, Account, User
- Test RLS policies: Ensure users can only see their org's data
- Seed test data: Run development seed scripts
- Performance baseline: Measure query performance
- Move to MVP.1: When ready, execute migrations in /migrations/mvp.1/