-- Organization skin storage and active skin selector CREATE TABLE IF NOT EXISTS organization_skins ( id SERIAL PRIMARY KEY, organization_id INTEGER NOT NULL REFERENCES organizations(id) ON DELETE CASCADE, skin_id VARCHAR(50) NOT NULL, name VARCHAR(100) NOT NULL, description TEXT, tokens JSONB NOT NULL, is_editable BOOLEAN DEFAULT true, is_active BOOLEAN DEFAULT false, created_by INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE, created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW(), UNIQUE(organization_id, skin_id) ); CREATE INDEX IF NOT EXISTS organization_skins_org_idx ON organization_skins(organization_id); ALTER TABLE organizations ADD COLUMN IF NOT EXISTS active_skin_id VARCHAR(50) DEFAULT 'iistwin'; -- Tenant isolation ALTER TABLE organization_skins ENABLE ROW LEVEL SECURITY; DROP POLICY IF EXISTS tenant_iso ON organization_skins; CREATE POLICY tenant_iso ON organization_skins USING ( current_setting('app.is_superadmin', true) = 'true' OR organization_id = NULLIF(current_setting('app.current_org_id', true), '')::int );