Sistema NEXUS v3.4 migrado con: Estructura principal: - core/orchestration: Sistema SIMCO + CAPVED (27 directivas, 28 perfiles) - core/catalog: Catalogo de funcionalidades reutilizables - shared/knowledge-base: Base de conocimiento compartida - devtools/scripts: Herramientas de desarrollo - control-plane/registries: Control de servicios y CI/CD - orchestration/: Configuracion de orquestacion de agentes Proyectos incluidos (11): - gamilit (submodule -> GitHub) - trading-platform (OrbiquanTIA) - erp-suite con 5 verticales: - erp-core, construccion, vidrio-templado - mecanicas-diesel, retail, clinicas - betting-analytics - inmobiliaria-analytics - platform_marketing_content - pos-micro, erp-basico Configuracion: - .gitignore completo para Node.js/Python/Docker - gamilit como submodule (git@github.com:rckrdmrd/gamilit-workspace.git) - Sistema de puertos estandarizado (3005-3199) Generated with NEXUS v3.4 Migration System EPIC-010: Configuracion Git y Repositorios
413 lines
18 KiB
SQL
413 lines
18 KiB
SQL
-- ============================================================================
|
|
-- ET-WORK: Row-Level Security (RLS) Policies
|
|
-- Módulo: MAI-005 - Control de Obra y Avances
|
|
-- Tablas: work_control schema (todas las tablas del módulo)
|
|
-- Fecha: 2025-11-20
|
|
-- Descripción: Políticas de seguridad para aislamiento multi-tenant (constructora)
|
|
-- ============================================================================
|
|
|
|
-- ============================================================================
|
|
-- HABILITAR RLS EN TODAS LAS TABLAS
|
|
-- ============================================================================
|
|
|
|
ALTER TABLE work_control.work_progress ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE work_control.daily_reports ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE work_control.work_photos ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE work_control.quality_checkpoints ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE work_control.checkpoint_inspections ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE work_control.material_consumption ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE work_control.labor_tracking ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE work_control.equipment_usage ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE work_control.weather_conditions ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE work_control.incidents ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE work_control.delays ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE work_control.rfi_requests ENABLE ROW LEVEL SECURITY;
|
|
|
|
-- ============================================================================
|
|
-- POLÍTICAS RLS: WORK_PROGRESS (Avances de Obra)
|
|
-- ============================================================================
|
|
|
|
DROP POLICY IF EXISTS "work_progress_select_own" ON work_control.work_progress;
|
|
CREATE POLICY "work_progress_select_own"
|
|
ON work_control.work_progress FOR SELECT TO authenticated
|
|
USING (constructora_id = public.get_current_constructora_id());
|
|
|
|
COMMENT ON POLICY "work_progress_select_own" ON work_control.work_progress IS
|
|
'Permite ver solo avances de obra de la constructora actual.
|
|
Usado en: Dashboard de avances, curva S, reportes de progreso.';
|
|
|
|
DROP POLICY IF EXISTS "work_progress_insert_own" ON work_control.work_progress;
|
|
CREATE POLICY "work_progress_insert_own"
|
|
ON work_control.work_progress FOR INSERT TO authenticated
|
|
WITH CHECK (
|
|
constructora_id = public.get_current_constructora_id()
|
|
AND public.get_current_user_role() IN ('director', 'admin', 'engineer', 'resident')
|
|
);
|
|
|
|
DROP POLICY IF EXISTS "work_progress_update_own" ON work_control.work_progress;
|
|
CREATE POLICY "work_progress_update_own"
|
|
ON work_control.work_progress FOR UPDATE TO authenticated
|
|
USING (
|
|
constructora_id = public.get_current_constructora_id()
|
|
AND public.get_current_user_role() IN ('director', 'admin', 'engineer', 'resident')
|
|
)
|
|
WITH CHECK (constructora_id = public.get_current_constructora_id());
|
|
|
|
DROP POLICY IF EXISTS "work_progress_delete_own" ON work_control.work_progress;
|
|
CREATE POLICY "work_progress_delete_own"
|
|
ON work_control.work_progress FOR DELETE TO authenticated
|
|
USING (
|
|
constructora_id = public.get_current_constructora_id()
|
|
AND public.get_current_user_role() IN ('director', 'admin')
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- POLÍTICAS RLS: DAILY_REPORTS (Reportes Diarios)
|
|
-- ============================================================================
|
|
|
|
DROP POLICY IF EXISTS "daily_reports_select_own" ON work_control.daily_reports;
|
|
CREATE POLICY "daily_reports_select_own"
|
|
ON work_control.daily_reports FOR SELECT TO authenticated
|
|
USING (constructora_id = public.get_current_constructora_id());
|
|
|
|
DROP POLICY IF EXISTS "daily_reports_insert_own" ON work_control.daily_reports;
|
|
CREATE POLICY "daily_reports_insert_own"
|
|
ON work_control.daily_reports FOR INSERT TO authenticated
|
|
WITH CHECK (
|
|
constructora_id = public.get_current_constructora_id()
|
|
AND public.get_current_user_role() IN ('director', 'admin', 'engineer', 'resident', 'supervisor')
|
|
);
|
|
|
|
COMMENT ON POLICY "daily_reports_insert_own" ON work_control.daily_reports IS
|
|
'Permite crear reportes diarios a personal de campo.
|
|
Roles: director, admin, engineer, resident, supervisor.';
|
|
|
|
DROP POLICY IF EXISTS "daily_reports_update_own" ON work_control.daily_reports;
|
|
CREATE POLICY "daily_reports_update_own"
|
|
ON work_control.daily_reports FOR UPDATE TO authenticated
|
|
USING (
|
|
constructora_id = public.get_current_constructora_id()
|
|
AND (
|
|
-- Creador puede editar mismo día
|
|
(created_by = public.get_current_user_id() AND created_at::date = CURRENT_DATE)
|
|
OR
|
|
-- Director/Admin siempre
|
|
public.get_current_user_role() IN ('director', 'admin')
|
|
)
|
|
)
|
|
WITH CHECK (constructora_id = public.get_current_constructora_id());
|
|
|
|
-- ============================================================================
|
|
-- POLÍTICAS RLS: WORK_PHOTOS (Fotos de Obra)
|
|
-- ============================================================================
|
|
|
|
DROP POLICY IF EXISTS "work_photos_select_own" ON work_control.work_photos;
|
|
CREATE POLICY "work_photos_select_own"
|
|
ON work_control.work_photos FOR SELECT TO authenticated
|
|
USING (constructora_id = public.get_current_constructora_id());
|
|
|
|
DROP POLICY IF EXISTS "work_photos_insert_own" ON work_control.work_photos;
|
|
CREATE POLICY "work_photos_insert_own"
|
|
ON work_control.work_photos FOR INSERT TO authenticated
|
|
WITH CHECK (
|
|
constructora_id = public.get_current_constructora_id()
|
|
);
|
|
|
|
COMMENT ON POLICY "work_photos_insert_own" ON work_control.work_photos IS
|
|
'Todos los usuarios pueden subir fotos de obra (con geolocalización).';
|
|
|
|
DROP POLICY IF EXISTS "work_photos_delete_own" ON work_control.work_photos;
|
|
CREATE POLICY "work_photos_delete_own"
|
|
ON work_control.work_photos FOR DELETE TO authenticated
|
|
USING (
|
|
constructora_id = public.get_current_constructora_id()
|
|
AND (
|
|
created_by = public.get_current_user_id()
|
|
OR public.get_current_user_role() IN ('director', 'admin')
|
|
)
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- POLÍTICAS RLS: QUALITY_CHECKPOINTS (Puntos de Control de Calidad)
|
|
-- ============================================================================
|
|
|
|
DROP POLICY IF EXISTS "checkpoints_select_own" ON work_control.quality_checkpoints;
|
|
CREATE POLICY "checkpoints_select_own"
|
|
ON work_control.quality_checkpoints FOR SELECT TO authenticated
|
|
USING (constructora_id = public.get_current_constructora_id());
|
|
|
|
DROP POLICY IF EXISTS "checkpoints_insert_own" ON work_control.quality_checkpoints;
|
|
CREATE POLICY "checkpoints_insert_own"
|
|
ON work_control.quality_checkpoints FOR INSERT TO authenticated
|
|
WITH CHECK (
|
|
constructora_id = public.get_current_constructora_id()
|
|
AND public.get_current_user_role() IN ('director', 'admin', 'engineer')
|
|
);
|
|
|
|
DROP POLICY IF EXISTS "checkpoints_update_own" ON work_control.quality_checkpoints;
|
|
CREATE POLICY "checkpoints_update_own"
|
|
ON work_control.quality_checkpoints FOR UPDATE TO authenticated
|
|
USING (
|
|
constructora_id = public.get_current_constructora_id()
|
|
AND public.get_current_user_role() IN ('director', 'admin', 'engineer')
|
|
)
|
|
WITH CHECK (constructora_id = public.get_current_constructora_id());
|
|
|
|
-- ============================================================================
|
|
-- POLÍTICAS RLS: CHECKPOINT_INSPECTIONS (Inspecciones de Calidad)
|
|
-- ============================================================================
|
|
|
|
DROP POLICY IF EXISTS "inspections_select_own" ON work_control.checkpoint_inspections;
|
|
CREATE POLICY "inspections_select_own"
|
|
ON work_control.checkpoint_inspections FOR SELECT TO authenticated
|
|
USING (
|
|
checkpoint_id IN (
|
|
SELECT id FROM work_control.quality_checkpoints
|
|
WHERE constructora_id = public.get_current_constructora_id()
|
|
)
|
|
);
|
|
|
|
DROP POLICY IF EXISTS "inspections_insert_own" ON work_control.checkpoint_inspections;
|
|
CREATE POLICY "inspections_insert_own"
|
|
ON work_control.checkpoint_inspections FOR INSERT TO authenticated
|
|
WITH CHECK (
|
|
checkpoint_id IN (
|
|
SELECT id FROM work_control.quality_checkpoints
|
|
WHERE constructora_id = public.get_current_constructora_id()
|
|
)
|
|
AND public.get_current_user_role() IN ('director', 'admin', 'engineer', 'resident', 'supervisor')
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- POLÍTICAS RLS: MATERIAL_CONSUMPTION (Consumo de Materiales)
|
|
-- ============================================================================
|
|
|
|
DROP POLICY IF EXISTS "material_consumption_select_own" ON work_control.material_consumption;
|
|
CREATE POLICY "material_consumption_select_own"
|
|
ON work_control.material_consumption FOR SELECT TO authenticated
|
|
USING (constructora_id = public.get_current_constructora_id());
|
|
|
|
DROP POLICY IF EXISTS "material_consumption_insert_own" ON work_control.material_consumption;
|
|
CREATE POLICY "material_consumption_insert_own"
|
|
ON work_control.material_consumption FOR INSERT TO authenticated
|
|
WITH CHECK (
|
|
constructora_id = public.get_current_constructora_id()
|
|
AND public.get_current_user_role() IN ('director', 'admin', 'engineer', 'resident', 'warehouse_manager')
|
|
);
|
|
|
|
COMMENT ON POLICY "material_consumption_insert_own" ON work_control.material_consumption IS
|
|
'Permite registrar consumo de materiales en obra.
|
|
Integración: Actualiza inventario y costos reales.';
|
|
|
|
-- ============================================================================
|
|
-- POLÍTICAS RLS: LABOR_TRACKING (Seguimiento de Mano de Obra)
|
|
-- ============================================================================
|
|
|
|
DROP POLICY IF EXISTS "labor_tracking_select_own" ON work_control.labor_tracking;
|
|
CREATE POLICY "labor_tracking_select_own"
|
|
ON work_control.labor_tracking FOR SELECT TO authenticated
|
|
USING (constructora_id = public.get_current_constructora_id());
|
|
|
|
DROP POLICY IF EXISTS "labor_tracking_insert_own" ON work_control.labor_tracking;
|
|
CREATE POLICY "labor_tracking_insert_own"
|
|
ON work_control.labor_tracking FOR INSERT TO authenticated
|
|
WITH CHECK (
|
|
constructora_id = public.get_current_constructora_id()
|
|
AND public.get_current_user_role() IN ('director', 'admin', 'resident', 'supervisor')
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- POLÍTICAS RLS: EQUIPMENT_USAGE (Uso de Maquinaria)
|
|
-- ============================================================================
|
|
|
|
DROP POLICY IF EXISTS "equipment_usage_select_own" ON work_control.equipment_usage;
|
|
CREATE POLICY "equipment_usage_select_own"
|
|
ON work_control.equipment_usage FOR SELECT TO authenticated
|
|
USING (constructora_id = public.get_current_constructora_id());
|
|
|
|
DROP POLICY IF EXISTS "equipment_usage_insert_own" ON work_control.equipment_usage;
|
|
CREATE POLICY "equipment_usage_insert_own"
|
|
ON work_control.equipment_usage FOR INSERT TO authenticated
|
|
WITH CHECK (
|
|
constructora_id = public.get_current_constructora_id()
|
|
AND public.get_current_user_role() IN ('director', 'admin', 'engineer', 'resident')
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- POLÍTICAS RLS: WEATHER_CONDITIONS (Condiciones Climáticas)
|
|
-- ============================================================================
|
|
|
|
DROP POLICY IF EXISTS "weather_select_own" ON work_control.weather_conditions;
|
|
CREATE POLICY "weather_select_own"
|
|
ON work_control.weather_conditions FOR SELECT TO authenticated
|
|
USING (constructora_id = public.get_current_constructora_id());
|
|
|
|
DROP POLICY IF EXISTS "weather_insert_own" ON work_control.weather_conditions;
|
|
CREATE POLICY "weather_insert_own"
|
|
ON work_control.weather_conditions FOR INSERT TO authenticated
|
|
WITH CHECK (
|
|
constructora_id = public.get_current_constructora_id()
|
|
);
|
|
|
|
COMMENT ON POLICY "weather_insert_own" ON work_control.weather_conditions IS
|
|
'Registro automático o manual de condiciones climáticas.
|
|
Usado para: Justificación de retrasos, análisis de productividad.';
|
|
|
|
-- ============================================================================
|
|
-- POLÍTICAS RLS: INCIDENTS (Incidentes)
|
|
-- ============================================================================
|
|
|
|
DROP POLICY IF EXISTS "incidents_select_own" ON work_control.incidents;
|
|
CREATE POLICY "incidents_select_own"
|
|
ON work_control.incidents FOR SELECT TO authenticated
|
|
USING (constructora_id = public.get_current_constructora_id());
|
|
|
|
DROP POLICY IF EXISTS "incidents_insert_own" ON work_control.incidents;
|
|
CREATE POLICY "incidents_insert_own"
|
|
ON work_control.incidents FOR INSERT TO authenticated
|
|
WITH CHECK (
|
|
constructora_id = public.get_current_constructora_id()
|
|
);
|
|
|
|
DROP POLICY IF EXISTS "incidents_update_own" ON work_control.incidents;
|
|
CREATE POLICY "incidents_update_own"
|
|
ON work_control.incidents FOR UPDATE TO authenticated
|
|
USING (
|
|
constructora_id = public.get_current_constructora_id()
|
|
AND public.get_current_user_role() IN ('director', 'admin', 'engineer', 'resident')
|
|
)
|
|
WITH CHECK (constructora_id = public.get_current_constructora_id());
|
|
|
|
-- ============================================================================
|
|
-- POLÍTICAS RLS: DELAYS (Retrasos)
|
|
-- ============================================================================
|
|
|
|
DROP POLICY IF EXISTS "delays_select_own" ON work_control.delays;
|
|
CREATE POLICY "delays_select_own"
|
|
ON work_control.delays FOR SELECT TO authenticated
|
|
USING (constructora_id = public.get_current_constructora_id());
|
|
|
|
DROP POLICY IF EXISTS "delays_insert_own" ON work_control.delays;
|
|
CREATE POLICY "delays_insert_own"
|
|
ON work_control.delays FOR INSERT TO authenticated
|
|
WITH CHECK (
|
|
constructora_id = public.get_current_constructora_id()
|
|
AND public.get_current_user_role() IN ('director', 'admin', 'engineer', 'resident')
|
|
);
|
|
|
|
-- ============================================================================
|
|
-- POLÍTICAS RLS: RFI_REQUESTS (Solicitudes de Información)
|
|
-- ============================================================================
|
|
|
|
DROP POLICY IF EXISTS "rfi_select_own" ON work_control.rfi_requests;
|
|
CREATE POLICY "rfi_select_own"
|
|
ON work_control.rfi_requests FOR SELECT TO authenticated
|
|
USING (constructora_id = public.get_current_constructora_id());
|
|
|
|
DROP POLICY IF EXISTS "rfi_insert_own" ON work_control.rfi_requests;
|
|
CREATE POLICY "rfi_insert_own"
|
|
ON work_control.rfi_requests FOR INSERT TO authenticated
|
|
WITH CHECK (
|
|
constructora_id = public.get_current_constructora_id()
|
|
);
|
|
|
|
DROP POLICY IF EXISTS "rfi_update_own" ON work_control.rfi_requests;
|
|
CREATE POLICY "rfi_update_own"
|
|
ON work_control.rfi_requests FOR UPDATE TO authenticated
|
|
USING (
|
|
constructora_id = public.get_current_constructora_id()
|
|
AND (
|
|
created_by = public.get_current_user_id()
|
|
OR public.get_current_user_role() IN ('director', 'admin', 'engineer')
|
|
)
|
|
)
|
|
WITH CHECK (constructora_id = public.get_current_constructora_id());
|
|
|
|
-- ============================================================================
|
|
-- POLÍTICAS SUPER ADMIN
|
|
-- ============================================================================
|
|
|
|
DO $$
|
|
DECLARE
|
|
table_name TEXT;
|
|
tables TEXT[] := ARRAY[
|
|
'work_progress', 'daily_reports', 'work_photos', 'quality_checkpoints',
|
|
'checkpoint_inspections', 'material_consumption', 'labor_tracking',
|
|
'equipment_usage', 'weather_conditions', 'incidents', 'delays', 'rfi_requests'
|
|
];
|
|
BEGIN
|
|
FOREACH table_name IN ARRAY tables
|
|
LOOP
|
|
EXECUTE format('
|
|
DROP POLICY IF EXISTS "%s_super_admin_all" ON work_control.%s;
|
|
CREATE POLICY "%s_super_admin_all" ON work_control.%s
|
|
FOR ALL TO authenticated
|
|
USING (public.get_current_user_role() = ''super_admin'')
|
|
WITH CHECK (public.get_current_user_role() = ''super_admin'');
|
|
', table_name, table_name, table_name, table_name);
|
|
END LOOP;
|
|
END $$;
|
|
|
|
-- ============================================================================
|
|
-- ÍNDICES PARA PERFORMANCE
|
|
-- ============================================================================
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_work_progress_constructora ON work_control.work_progress(constructora_id);
|
|
CREATE INDEX IF NOT EXISTS idx_work_progress_housing_unit ON work_control.work_progress(housing_unit_id);
|
|
CREATE INDEX IF NOT EXISTS idx_work_progress_date ON work_control.work_progress(progress_date);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_daily_reports_constructora ON work_control.daily_reports(constructora_id);
|
|
CREATE INDEX IF NOT EXISTS idx_daily_reports_project ON work_control.daily_reports(project_id);
|
|
CREATE INDEX IF NOT EXISTS idx_daily_reports_date ON work_control.daily_reports(report_date);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_work_photos_constructora ON work_control.work_photos(constructora_id);
|
|
CREATE INDEX IF NOT EXISTS idx_work_photos_entity ON work_control.work_photos(entity_type, entity_id);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_material_consumption_constructora ON work_control.material_consumption(constructora_id);
|
|
CREATE INDEX IF NOT EXISTS idx_material_consumption_item ON work_control.material_consumption(inventory_item_id);
|
|
CREATE INDEX IF NOT EXISTS idx_material_consumption_date ON work_control.material_consumption(consumption_date);
|
|
|
|
COMMENT ON INDEX work_control.idx_work_progress_constructora IS
|
|
'Optimiza queries RLS filtrados por constructora_id.';
|
|
|
|
-- ============================================================================
|
|
-- GRANTS
|
|
-- ============================================================================
|
|
|
|
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA work_control TO authenticated;
|
|
GRANT USAGE ON SCHEMA work_control TO authenticated;
|
|
|
|
-- ============================================================================
|
|
-- VERIFICACIÓN FINAL
|
|
-- ============================================================================
|
|
|
|
DO $$
|
|
DECLARE
|
|
v_tables TEXT[] := ARRAY[
|
|
'work_progress', 'daily_reports', 'work_photos',
|
|
'material_consumption', 'quality_checkpoints', 'incidents'
|
|
];
|
|
v_table TEXT;
|
|
v_rls_enabled BOOLEAN;
|
|
v_policy_count INTEGER;
|
|
BEGIN
|
|
FOREACH v_table IN ARRAY v_tables
|
|
LOOP
|
|
SELECT relrowsecurity INTO v_rls_enabled
|
|
FROM pg_class
|
|
WHERE relname = v_table AND relnamespace = 'work_control'::regnamespace;
|
|
|
|
SELECT COUNT(*) INTO v_policy_count
|
|
FROM pg_policies
|
|
WHERE schemaname = 'work_control' AND tablename = v_table;
|
|
|
|
IF NOT v_rls_enabled THEN
|
|
RAISE EXCEPTION 'CRITICAL: RLS no habilitado en work_control.%', v_table;
|
|
END IF;
|
|
|
|
RAISE NOTICE '✓ work_control.%: RLS habilitado con % políticas', v_table, v_policy_count;
|
|
END LOOP;
|
|
|
|
RAISE NOTICE '✓ Módulo MAI-005: Todas las tablas tienen RLS habilitado';
|
|
END $$;
|