workspace-v1/shared/knowledge-base/patterns/PATRON-RLS-POLICIES.md
rckrdmrd cb4c0681d3 feat(workspace): Add new projects and update architecture
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>
2026-01-07 04:43:28 -06:00

243 lines
5.4 KiB
Markdown

# 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)
```sql
-- 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)
```sql
-- 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)
```sql
-- 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
```sql
-- 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)
```sql
-- 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)
```sql
CREATE POLICY read_own ON {table}
FOR SELECT
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
```
### INSERT (Creacion)
```sql
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)
```sql
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)
```sql
-- 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
```sql
-- 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)
```sql
-- 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)
```sql
-- 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
```sql
-- 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
```sql
-- 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.md`
- `shared/catalog/multi-tenancy/`
- PostgreSQL RLS Documentation
---
*Knowledge Base - Workspace v1*