New projects created: - michangarrito (marketplace mobile) - template-saas (SaaS template) - clinica-dental (dental ERP) - clinica-veterinaria (veterinary ERP) Architecture updates: - Move catalog from core/ to shared/ - Add MCP servers structure and templates - Add git management scripts - Update SUBREPOSITORIOS.md with 15 new repos - Update .gitignore for new projects Repository infrastructure: - 4 main repositories - 11 subrepositorios - Gitea remotes configured 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
5.4 KiB
5.4 KiB
Patron RLS Policies
Categoria: Patterns Version: 1.0.0 Origen: projects/gamilit, projects/erp-core Fecha: 2025-12-27
Descripcion
Patrones estandarizados para implementar Row-Level Security (RLS) en PostgreSQL.
Politicas Base
1. Tenant Isolation (Aislamiento por tenant)
-- Template basico
CREATE POLICY tenant_isolation ON {schema}.{table}
FOR ALL
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
2. Tenant + Owner (Aislamiento por tenant y propietario)
-- Solo el creador puede ver/modificar
CREATE POLICY owner_only ON {schema}.{table}
FOR ALL
USING (
tenant_id = current_setting('app.current_tenant_id', true)::UUID
AND created_by = current_setting('app.current_user_id', true)::UUID
);
3. Tenant + Role Based (Basado en roles)
-- Admins ven todo, usuarios ven lo suyo
CREATE POLICY role_based ON {schema}.{table}
FOR ALL
USING (
tenant_id = current_setting('app.current_tenant_id', true)::UUID
AND (
current_setting('app.current_user_role', true) = 'admin'
OR created_by = current_setting('app.current_user_id', true)::UUID
)
);
4. Soft Delete Protection
-- No mostrar registros eliminados
CREATE POLICY soft_delete ON {schema}.{table}
FOR SELECT
USING (
tenant_id = current_setting('app.current_tenant_id', true)::UUID
AND deleted_at IS NULL
);
-- Admins pueden ver eliminados
CREATE POLICY admin_see_deleted ON {schema}.{table}
FOR SELECT
USING (
tenant_id = current_setting('app.current_tenant_id', true)::UUID
AND current_setting('app.current_user_role', true) = 'admin'
);
5. Hierarchical Access (Acceso jerarquico)
-- Managers ven datos de su equipo
CREATE POLICY hierarchical ON {schema}.{table}
FOR SELECT
USING (
tenant_id = current_setting('app.current_tenant_id', true)::UUID
AND (
created_by = current_setting('app.current_user_id', true)::UUID
OR created_by IN (
SELECT id FROM auth.users
WHERE manager_id = current_setting('app.current_user_id', true)::UUID
)
)
);
Patrones por Operacion
SELECT (Lectura)
CREATE POLICY read_own ON {table}
FOR SELECT
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
INSERT (Creacion)
CREATE POLICY insert_own ON {table}
FOR INSERT
WITH CHECK (
tenant_id = current_setting('app.current_tenant_id', true)::UUID
AND created_by = current_setting('app.current_user_id', true)::UUID
);
UPDATE (Modificacion)
CREATE POLICY update_own ON {table}
FOR UPDATE
USING (
tenant_id = current_setting('app.current_tenant_id', true)::UUID
AND created_by = current_setting('app.current_user_id', true)::UUID
)
WITH CHECK (
tenant_id = current_setting('app.current_tenant_id', true)::UUID
);
DELETE (Eliminacion)
-- Solo admins pueden eliminar
CREATE POLICY delete_admin_only ON {table}
FOR DELETE
USING (
tenant_id = current_setting('app.current_tenant_id', true)::UUID
AND current_setting('app.current_user_role', true) = 'admin'
);
Casos Especiales
Tablas de Configuracion Global
-- Sin RLS, acceso publico de lectura
ALTER TABLE config.settings DISABLE ROW LEVEL SECURITY;
-- O con politica permisiva
CREATE POLICY public_read ON config.settings
FOR SELECT
USING (true);
Tablas de Audit (Solo insert)
-- Solo permitir INSERT, nunca UPDATE/DELETE
CREATE POLICY audit_insert_only ON audit.logs
FOR INSERT
WITH CHECK (true);
-- Bloquear todo lo demas
CREATE POLICY audit_no_modify ON audit.logs
FOR UPDATE
USING (false);
CREATE POLICY audit_no_delete ON audit.logs
FOR DELETE
USING (false);
Cross-Tenant Access (Super Admin)
-- Super admin puede ver todos los tenants
CREATE POLICY super_admin_access ON {table}
FOR ALL
USING (
current_setting('app.is_super_admin', true)::BOOLEAN = true
OR tenant_id = current_setting('app.current_tenant_id', true)::UUID
);
Script de Generacion
-- Funcion para aplicar politicas estandar
CREATE OR REPLACE FUNCTION apply_standard_rls(
p_schema TEXT,
p_table TEXT
) RETURNS VOID AS $$
BEGIN
-- Habilitar RLS
EXECUTE format('ALTER TABLE %I.%I ENABLE ROW LEVEL SECURITY', p_schema, p_table);
-- Politica de tenant isolation
EXECUTE format(
'CREATE POLICY tenant_isolation ON %I.%I
FOR ALL
USING (tenant_id = current_setting(''app.current_tenant_id'', true)::UUID)',
p_schema, p_table
);
RAISE NOTICE 'RLS applied to %.%', p_schema, p_table;
END;
$$ LANGUAGE plpgsql;
-- Uso:
SELECT apply_standard_rls('my_schema', 'my_table');
Validacion
-- Verificar que RLS esta activo
SELECT
schemaname,
tablename,
rowsecurity
FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY schemaname, tablename;
-- Verificar politicas existentes
SELECT
schemaname,
tablename,
policyname,
permissive,
roles,
cmd,
qual
FROM pg_policies
ORDER BY schemaname, tablename;
Referencias
architecture/PATRON-MULTI-TENANT.mdshared/catalog/multi-tenancy/- PostgreSQL RLS Documentation
Knowledge Base - Workspace v1