BEGIN; ALTER TABLE apps ADD COLUMN IF NOT EXISTS app_type VARCHAR(50) NOT NULL DEFAULT 'generic', ADD COLUMN IF NOT EXISTS owner VARCHAR(100), ADD COLUMN IF NOT EXISTS owner_user_id UUID, ADD COLUMN IF NOT EXISTS updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(); UPDATE apps SET updated_at = COALESCE(updated_at, created_at, NOW()); CREATE INDEX IF NOT EXISTS idx_apps_status ON apps(status); CREATE INDEX IF NOT EXISTS idx_apps_app_type ON apps(app_type); CREATE INDEX IF NOT EXISTS idx_apps_created_at ON apps(created_at); CREATE TABLE IF NOT EXISTS app_change_logs ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), app_id VARCHAR(32) NOT NULL REFERENCES apps(id) ON DELETE CASCADE, action VARCHAR(50) NOT NULL, actor_user_id UUID, before JSONB, after JSONB, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_app_change_logs_app_id ON app_change_logs(app_id); CREATE INDEX IF NOT EXISTS idx_app_change_logs_created_at ON app_change_logs(created_at); CREATE TABLE IF NOT EXISTS app_status_change_requests ( id UUID PRIMARY KEY DEFAULT uuid_generate_v4(), app_id VARCHAR(32) NOT NULL REFERENCES apps(id) ON DELETE CASCADE, from_status VARCHAR(20) NOT NULL, to_status VARCHAR(20) NOT NULL, requested_by UUID, requested_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), effective_at TIMESTAMP WITH TIME ZONE, status VARCHAR(20) NOT NULL DEFAULT 'pending', approved_by UUID, approved_at TIMESTAMP WITH TIME ZONE, rejected_by UUID, rejected_at TIMESTAMP WITH TIME ZONE, reason TEXT ); CREATE INDEX IF NOT EXISTS idx_app_status_change_requests_status ON app_status_change_requests(status); CREATE INDEX IF NOT EXISTS idx_app_status_change_requests_app_id ON app_status_change_requests(app_id); CREATE INDEX IF NOT EXISTS idx_app_status_change_requests_effective_at ON app_status_change_requests(effective_at); INSERT INTO permissions (code, description, resource, action) VALUES ('iam:app:read', 'Read apps registry', 'app', 'read'), ('iam:app:write', 'Manage apps registry', 'app', 'write'), ('iam:app:approve', 'Approve app status change', 'app_status_change', 'approve'), ('iam:app:delete', 'Delete apps registry', 'app', 'delete') ON CONFLICT (code) DO NOTHING; INSERT INTO role_permissions (role_id, permission_id) SELECT r.id, p.id FROM roles r, permissions p WHERE r.name = 'SuperAdmin' AND r.tenant_id = '00000000-0000-0000-0000-000000000001' AND p.code IN ('iam:app:read', 'iam:app:write', 'iam:app:approve', 'iam:app:delete') ON CONFLICT DO NOTHING; COMMIT;