chore: import DH V2 D5.6.4 production baseline
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
# Punto de retorno — INVENTARIO A REVISAR
|
||||
|
||||
Antes de introducir la interpretación flexible de inventarios técnicos se crea un backup fuerte con la palabra clave exacta **INVENTARIO A REVISAR**.
|
||||
|
||||
Su finalidad es conservar un punto de retorno anterior a la decisión conceptual de tratar la jerarquía posterior a Área/Yacimiento como nomenclatura local de cada operadora, por si esa decisión debe modificarse después de la reunión.
|
||||
|
||||
El backup se guarda en:
|
||||
|
||||
`/root/DH_V2_BACKUPS/INVENTARIO_A_REVISAR_YYYYMMDD_HHMMSS/`
|
||||
|
||||
Incluye dump PostgreSQL custom validado, source, `.env`, `docker-compose.yml`, volumen `dhv2_asset_media`, imágenes Docker exactas de API/Web/Migrate, health, estado de migraciones, snapshot legible del Maestro/importaciones y hashes SHA-256. El directorio y los archivos sensibles quedan restringidos a root.
|
||||
|
||||
El deploy D5.3.8 ejecuta este backup **después de compilar y testear en staging y antes de modificar source, base de datos o contenedores de producción**. Si el backup falla, el deploy se detiene.
|
||||
@@ -0,0 +1,69 @@
|
||||
# Referencia de datos — Hidrocarburos Mendoza
|
||||
|
||||
Fecha de relevamiento de referencia: 2026-08-16.
|
||||
|
||||
Fuente pública principal:
|
||||
|
||||
- https://www.mendoza.gob.ar/energiayambiente/hidrocarburos/
|
||||
- versión indexada equivalente: https://sitios.mendoza.gob.ar/energiayambiente/hidrocarburos/
|
||||
|
||||
## Qué confirma la fuente para el modelo DH
|
||||
|
||||
La publicación oficial organiza la gestión de inspecciones de campo por dos ejes que
|
||||
coinciden con el modelo D5.3:
|
||||
|
||||
1. **operadora**;
|
||||
2. **área operativa**.
|
||||
|
||||
La misma fuente publica informes de inspección por inspector/mes y viajes de campo
|
||||
por operadora y área. Esto refuerza que el contexto obligatorio de una futura
|
||||
planificación sea `Área → Empresa` y no una jerarquía donde la empresa sea padre
|
||||
físico del activo.
|
||||
|
||||
Las publicaciones oficiales de Hidrocarburos también describen como datos de interés:
|
||||
|
||||
- áreas y yacimientos;
|
||||
- geolocalización e identificación de pozos;
|
||||
- operadores;
|
||||
- profundidad y tipo de pozo;
|
||||
- situación legal y estado actual;
|
||||
- fechas de intervención;
|
||||
- plazos de concesión;
|
||||
- instalaciones de superficie;
|
||||
- producción e inspecciones.
|
||||
|
||||
## Política de precarga de DH
|
||||
|
||||
D5.3.1 **no precarga empresas, áreas, yacimientos ni pozos reales** desde una página
|
||||
web. Esos registros pueden cambiar por cesiones de concesión, nuevas licitaciones,
|
||||
renovaciones o cambios de operador.
|
||||
|
||||
En cambio, la configuración inicial instala solamente una taxonomía estable:
|
||||
|
||||
- Área / Concesión;
|
||||
- Empresa / Operadora;
|
||||
- Yacimiento;
|
||||
- Instalación de superficie;
|
||||
- Estación;
|
||||
- Subestación;
|
||||
- Pozo;
|
||||
- Equipo;
|
||||
- Ducto / Cañería.
|
||||
|
||||
Además crea atributos opcionales que permiten recibir datos oficiales sin obligar a
|
||||
completarlos cuando no estén disponibles.
|
||||
|
||||
## Futuro importador de datos oficiales
|
||||
|
||||
Cuando se incorpore una fuente oficial descargable/API, la importación deberá:
|
||||
|
||||
- identificar la fuente y fecha de extracción;
|
||||
- conservar el identificador oficial cuando exista;
|
||||
- no sobrescribir silenciosamente datos validados en campo;
|
||||
- detectar duplicados por código/nombre/ubicación;
|
||||
- registrar alta, modificación o finalización de relaciones Área–Empresa con vigencia;
|
||||
- importar activos como `IMPORT` y conservar procedencia;
|
||||
- permitir revisión humana antes de fusionar datos contradictorios.
|
||||
|
||||
Los valores de tableros públicos (cantidad de informes, viajes, operadoras, etc.) son
|
||||
métricas temporales y no deben almacenarse como datos maestros fijos.
|
||||
@@ -0,0 +1,84 @@
|
||||
# DH V2 · Datos de desarrollo y limpieza controlada
|
||||
|
||||
## Objetivo
|
||||
|
||||
Durante el desarrollo se necesita poder probar el sistema con datos representativos sin confundirlos con el futuro padrón real. D5.3.2 incorpora un caso demostrativo identificado de forma inequívoca y un limpiador seguro.
|
||||
|
||||
## Caso demostrativo
|
||||
|
||||
El seed usa el Informe Técnico Nº 124/2026 exclusivamente como referencia de nomenclatura y estructura:
|
||||
|
||||
```text
|
||||
[PRUEBA] Atamisqui Área
|
||||
└── [PRUEBA] Planta de Entrega 3 PB Planta
|
||||
├── [PRUEBA] Tanque TK-57 Tanque · 480 m³
|
||||
└── [PRUEBA] Tanque TK-58 Tanque · 320 m³
|
||||
|
||||
[PRUEBA] Petróleos Sudamericanos Energy S.A. Empresa/Operadora
|
||||
↕ relación operativa
|
||||
[PRUEBA] Atamisqui
|
||||
```
|
||||
|
||||
Todos los activos creados por el seed tienen:
|
||||
|
||||
- código `DEV-DEMO-*`;
|
||||
- nombre visible con prefijo `[PRUEBA]`;
|
||||
- procedencia `PROVIDED_DOCUMENT`;
|
||||
- referencia `DH-DEV-DEMO:ITN124/2026`;
|
||||
- estado de información `DRAFT`;
|
||||
- nota expresa de que no son carga maestra real ni validación de vigencia.
|
||||
|
||||
## Crear o reconstruir el ejemplo
|
||||
|
||||
Primero debe haberse completado el catálogo técnico desde `Maestro > Tipos y atributos`.
|
||||
|
||||
```bash
|
||||
cd /var/www/dhv2.korexlabs.com
|
||||
bash scripts/dev-seed-mendoza-demo.sh
|
||||
```
|
||||
|
||||
El seed rechaza una segunda ejecución mientras existan registros `DEV-DEMO`.
|
||||
|
||||
## Simular limpieza
|
||||
|
||||
Este comando es el recomendado durante el desarrollo. **No elimina nada.**
|
||||
|
||||
```bash
|
||||
cd /var/www/dhv2.korexlabs.com
|
||||
bash scripts/dev-clean-demo.sh
|
||||
```
|
||||
|
||||
Informa cuántos activos, visitas, actas y relevamientos quedarían afectados.
|
||||
|
||||
## Limpieza real
|
||||
|
||||
Sólo usar cuando se quiera reconstruir el demo o preparar una futura entrega limpia:
|
||||
|
||||
```bash
|
||||
cd /var/www/dhv2.korexlabs.com
|
||||
bash scripts/dev-clean-demo.sh --apply DH-DEV-DEMO
|
||||
```
|
||||
|
||||
Antes de borrar, el script crea obligatoriamente un `pg_dump` en `/root/DH_V2_BACKUPS/DEV_CLEAN_PRE_*`.
|
||||
|
||||
## Protección contra mezcla PRUEBA / REAL
|
||||
|
||||
El script aborta si detecta que un activo no marcado como demo depende física u operativamente de un activo demo, o si una visita, acta, hallazgo o relevamiento mezcla activos demo con activos no demo. Nunca amplía silenciosamente el conjunto a borrar.
|
||||
|
||||
## Qué se elimina
|
||||
|
||||
Se eliminan los activos `DEV-DEMO` y, cuando son exclusivamente de prueba, sus relaciones, relevamientos, visitas, actas, hallazgos, comunicaciones, evidencias, firmas, versiones y eventos de auditoría asociados. También se retiran los archivos físicos vinculados.
|
||||
|
||||
## Qué se conserva
|
||||
|
||||
Se conservan expresamente:
|
||||
|
||||
- tipos de activo;
|
||||
- atributos y reglas padre/hijo;
|
||||
- relaciones/configuración estructural que no sean del demo;
|
||||
- usuarios;
|
||||
- roles y permisos;
|
||||
- catálogo/modelos de hallazgo;
|
||||
- configuración general del sistema.
|
||||
|
||||
La limpieza de desarrollo no equivale a “vaciar la base”.
|
||||
@@ -0,0 +1,86 @@
|
||||
# DH V2 · Investigación de nomenclatura hidrocarburífera de Mendoza
|
||||
|
||||
Fecha de trabajo: 16/08/2026
|
||||
Estado: referencia funcional para desarrollo. No constituye padrón oficial ni validación jurídica.
|
||||
|
||||
## 1. Criterio principal
|
||||
|
||||
La información analizada converge en un orden operativo estable:
|
||||
|
||||
1. **Área operativa / Área-Concesión**: contexto territorial de la inspección.
|
||||
2. **Operadora / Empresa inspeccionada**: responsable operativo dentro de esa área.
|
||||
3. **Yacimiento / Locación**: nivel territorial intermedio cuando existe y aporta valor.
|
||||
4. **Instalación**: planta, batería, estación, subestación, cargadero, etc.
|
||||
5. **Sistema**: drenaje, eléctrico/iluminación, defensa contra incendios, zona de bombas, cuando necesita identidad e historial propios.
|
||||
6. **Equipo / activo físico**: tanque, separador, bomba, caldera, antorcha, filtro, FWKO, tratador, calentador, pozo, etc.
|
||||
7. **Componente o punto de control**: baranda, escalera, válvula, brida, cartel, manómetro, guardacorrea, etc. No debe convertirse automáticamente en activo.
|
||||
|
||||
DH mantiene separadas dos dimensiones:
|
||||
|
||||
- la **jerarquía física**, representada por `parent_id`;
|
||||
- el **contexto operativo**, representado por `Área + Empresa`.
|
||||
|
||||
Esto permite que una empresa opere más de un área y que un área tenga más de una empresa a lo largo de su historia, sin mezclar esa relación con la contención física.
|
||||
|
||||
## 2. Nomenclatura observada en fuentes de la Dirección
|
||||
|
||||
La página pública de Hidrocarburos de Mendoza organiza las salidas a campo por **operadora** y por **área operativa**. Ese par se toma como contexto primario para planificación y consulta.
|
||||
|
||||
Los Informes Técnicos recibidos utilizan los campos **Área/Yacimiento**, **Empresa Inspeccionada**, **Ref.** de la instalación, **Acta N°** e **Informe Técnico N°**. Por lo tanto, `Yacimiento` es un nivel opcional: el sistema no debe exigirlo cuando el documento o la operación sólo identifica un área.
|
||||
|
||||
Las notas de inventario relacionan operadoras con áreas y, luego, con inventarios de instalaciones. Las notas no reemplazan las planillas técnicas de inventario: sirven como fuente de procedencia y relación administrativa.
|
||||
|
||||
## 3. Familias técnicas de la planilla de hallazgos
|
||||
|
||||
La lista de hallazgos recibida está organizada por familias técnicas, no por un único concepto genérico de “Equipo”. Entre las familias observadas aparecen:
|
||||
|
||||
- Tanques
|
||||
- Separadores
|
||||
- Bomba / Zona de bombas
|
||||
- Calderas
|
||||
- Drenaje
|
||||
- Antorcha
|
||||
- Colectores
|
||||
- Sistema eléctrico / iluminación
|
||||
- Defensa contra incendios
|
||||
- Cargadero / descargadero de camiones
|
||||
- Filtros
|
||||
- Equipo de flotación
|
||||
- Baterías y plantas
|
||||
- FWKO / Tratadores / Calentadores
|
||||
- Pozos por método o función operativa
|
||||
|
||||
Por esa razón D5.3.2 agrega tipos técnicos específicos. `Equipo` se conserva solamente como clasificación genérica cuando el inventario todavía no permite una clasificación mejor.
|
||||
|
||||
## 4. Pozos
|
||||
|
||||
Se mantiene **un solo tipo de activo Pozo**. El bloque de inspección se seleccionará por un atributo de método/función operativa:
|
||||
|
||||
- Bombeo mecánico
|
||||
- Bombeo electrosumergible
|
||||
- Bombeo de cavidad progresiva (PCP)
|
||||
- Surgente / productor de gas
|
||||
- Inyector de agua
|
||||
- Otro / a validar
|
||||
|
||||
Así se evita crear cinco árboles de activos distintos para el mismo concepto físico.
|
||||
|
||||
## 5. Activo vs. componente
|
||||
|
||||
Debe ser activo cuando necesita al menos una de estas capacidades: identidad, código, ubicación propia, estado, historial, relaciones, documentación o inspección independiente.
|
||||
|
||||
Debe permanecer como componente/punto de control cuando sólo describe una parte o condición del activo superior y no requiere gestión individual.
|
||||
|
||||
Ejemplo: `Tanque TK-57` es activo. Su `baranda`, `escalera`, `válvula`, `cartelería` o `guardacorrea` pueden ser puntos de control, salvo que la Dirección decida en el futuro administrarlos individualmente.
|
||||
|
||||
## 6. Fuentes de referencia utilizadas
|
||||
|
||||
- Portal oficial: https://sitios.mendoza.gob.ar/energiayambiente/hidrocarburos/
|
||||
- Informe Técnico Nº 124/2026, Acta Nº 105/2026.
|
||||
- Modelo de Informe Técnico suministrado por la Dirección.
|
||||
- Notas de inventario de CPESA, EMESA, Phoenix, Quintana, Petróleos Sudamericanos, CGC, GyG y PCR recibidas durante el desarrollo.
|
||||
- Lista de hallazgos suministrada en formato XLSX.
|
||||
|
||||
## 7. Datos cambiantes
|
||||
|
||||
Operadoras, concesiones, denominaciones de áreas y vigencias pueden cambiar. Por eso no se hardcodean como configuración estructural. Cuando se carguen datos reales, deben guardar fuente, fecha observada, usuario, procedencia y, cuando corresponda, vigencia histórica.
|
||||
@@ -0,0 +1,7 @@
|
||||
# Hotfix DH V2 v0.2.1
|
||||
|
||||
Corrige el arranque de la API en producción al cargar `cookie-parser` desde
|
||||
CommonJS. No agrega ni modifica migraciones de base de datos.
|
||||
|
||||
También actualiza la versión visible del footer y del endpoint de salud a
|
||||
`0.2.1`.
|
||||
@@ -0,0 +1,96 @@
|
||||
# Modelo documental de inspecciones
|
||||
|
||||
Este documento fija el modelo funcional validado a partir del Informe Técnico
|
||||
Nº 124/2026, el acta manuscrita adjunta y la planilla de hallazgos entregada.
|
||||
|
||||
## Canales de operación
|
||||
|
||||
| Función | APK móvil | Dashboard web |
|
||||
|---|---:|---:|
|
||||
| Planificar visita, activos y equipo | Consulta | Administra |
|
||||
| Administrar activos y catálogo de hallazgos | Consulta | Administra |
|
||||
| Iniciar y ejecutar la visita | Inspector | No |
|
||||
| Crear o modificar el acta y sus hallazgos | Inspector | Sólo consulta |
|
||||
| Incorporar evidencia de campo y GPS | Inspector | Sólo consulta |
|
||||
| Identificar responsable, firmar y cerrar | Inspector | Sólo consulta |
|
||||
| Registrar respuesta empresarial, PDF y próximo control | Consulta | Administra |
|
||||
| Consultar acta, hallazgos e informe sincronizados | Sí | Sí |
|
||||
|
||||
La API aplica esta separación además de la interfaz: las escrituras operativas
|
||||
requieren autenticación bearer de la aplicación móvil y el rol `inspector`.
|
||||
Una sesión web no puede eludir la restricción llamando directamente al endpoint.
|
||||
|
||||
## Cardinalidades
|
||||
|
||||
| Origen | Relación | Destino |
|
||||
|---|---:|---|
|
||||
| Inspección o visita | 1 a 1 | Acta de inspección |
|
||||
| Acta | 1 a muchos | Hallazgos |
|
||||
| Hallazgo | muchos a 1 | Activo o equipo del Maestro |
|
||||
| Hallazgo | muchos a 1 | Ítem del catálogo configurable |
|
||||
| Hallazgo | 1 a muchos | Evidencias, principalmente fotografías |
|
||||
| Acta | 1 a muchos | Firmas de inspectores |
|
||||
| Acta | 1 a 1 | Firma del responsable que atendió la visita |
|
||||
| Inspección o visita | 1 a 1 | Informe técnico |
|
||||
| Informe técnico | incorpora | Acta, hallazgos y evidencias congelados |
|
||||
|
||||
## Acta digital
|
||||
|
||||
El acta debe reunir como mínimo:
|
||||
|
||||
- número anual oficial, fecha, hora y ubicación;
|
||||
- empresa, área, yacimiento o instalación inspeccionada;
|
||||
- objeto y resultado de la inspección;
|
||||
- todos los hallazgos de la visita y sus plazos de corrección;
|
||||
- inspectores intervinientes;
|
||||
- identidad, DNI, cargo y correo del responsable de la empresa que recibió al
|
||||
equipo;
|
||||
- firmas manuscritas capturadas en pantalla de inspectores y responsable;
|
||||
- versión inmutable, hash, sello de tiempo y token de verificación.
|
||||
|
||||
Al finalizar la visita, el acta se cierra y ya no admite edición. Se genera el
|
||||
PDF verificable y se envía al correo del responsable de la empresa y a una
|
||||
dirección interna de Hidrocarburos definida por configuración. Cada intento y
|
||||
resultado de entrega debe quedar auditado.
|
||||
|
||||
Si se requiere corregir un acta cerrada, se emitirá una rectificativa vinculada
|
||||
sin reemplazar ni borrar el documento original.
|
||||
|
||||
## Hallazgos
|
||||
|
||||
La planilla entregada contiene 170 modelos de hallazgo agrupados en 19
|
||||
categorías de equipos, con descripción, normativa y glosario. Se implementará
|
||||
como catálogo administrable, importable y versionado. No se copiarán esas
|
||||
opciones como constantes en la interfaz.
|
||||
|
||||
Cada hallazgo operativo conservará una instantánea de su descripción y base
|
||||
legal para que posteriores cambios del catálogo no alteren documentos ya
|
||||
emitidos. También podrá registrar estado, observación específica, activo,
|
||||
ubicación/GPS, plazo y evidencias.
|
||||
|
||||
Cada hallazgo nace abierto. Se distinguen el plazo exigido, la respuesta y
|
||||
fecha comprometida por la empresa, y la fecha de próximo control fijada por el
|
||||
organismo. La respuesta empresarial no cierra el hallazgo: sólo una verificación
|
||||
posterior autorizada puede hacerlo.
|
||||
|
||||
## Informe técnico
|
||||
|
||||
El informe se genera después del cierre del acta, con numeración anual global
|
||||
independiente. Siguiendo el modelo entregado, contempla:
|
||||
|
||||
- título, número, acta referenciada, empresa, área/yacimiento y autores;
|
||||
- objetivos;
|
||||
- antecedentes;
|
||||
- marco legal;
|
||||
- resumen ejecutivo;
|
||||
- descripción de la inspección y de todos los hallazgos;
|
||||
- registro fotográfico;
|
||||
- conclusión;
|
||||
- acta digital completa como anexo final.
|
||||
|
||||
El informe congela las versiones exactas del acta, hallazgos, activos,
|
||||
evidencias y normativa que incorpora.
|
||||
|
||||
La solicitud de creación del informe corresponde al flujo del inspector en la
|
||||
APK después de cerrar la visita. El backend numera, compone y sella el PDF; el
|
||||
dashboard sólo lo consulta, descarga y administra su seguimiento documental.
|
||||
@@ -0,0 +1,14 @@
|
||||
# Instalación resumida
|
||||
|
||||
1. Crear `/var/www/dhv2.korexlabs.com`.
|
||||
2. Copiar este proyecto dentro.
|
||||
3. Generar `.env` con contraseñas aleatorias.
|
||||
4. Generar `package-lock.json` para api y web con Node 24.
|
||||
5. `docker compose config`.
|
||||
6. `docker compose build --pull`.
|
||||
7. `docker compose up -d`.
|
||||
8. Verificar health local.
|
||||
9. Instalar Nginx host.
|
||||
10. Verificar HTTP.
|
||||
11. Emitir certificado con Certbot.
|
||||
12. Verificar HTTPS.
|
||||
@@ -0,0 +1,40 @@
|
||||
# DH Inspección V2 — Revisión A0
|
||||
|
||||
Fecha de revisión: 12/08/2026.
|
||||
|
||||
## Backend
|
||||
|
||||
- NestJS 11 con TypeScript estricto.
|
||||
- `ValidationPipe` usa `whitelist`, `forbidNonWhitelisted` y `transform`.
|
||||
- Helmet está activo y `x-powered-by` deshabilitado.
|
||||
- La API está prefijada con `/api/v3`.
|
||||
- TypeORM usa `synchronize: false` y `migrationsRun: false`.
|
||||
- El runtime se conecta con `DB_APP_USER`; no recibe credenciales del owner.
|
||||
- Antes de A1 no había entidades, migraciones, usuarios ni autorización.
|
||||
|
||||
## Base de datos e infraestructura
|
||||
|
||||
- PostgreSQL 16 con PostGIS 3.5.
|
||||
- La base no publica puertos al host.
|
||||
- `dhv2_app` ya se crea como rol sin privilegios administrativos.
|
||||
- Los default privileges estaban previstos en la inicialización de bases nuevas.
|
||||
- Faltaba una vía controlada para ejecutar migraciones como `dhv2_owner` sobre
|
||||
la base existente; A1 incorpora el servicio temporal `migrate`.
|
||||
|
||||
## Frontend
|
||||
|
||||
- React 19, Vite y React Router.
|
||||
- Sólo existe el skeleton de navegación y el health check.
|
||||
- No hay autenticación ni persistencia de tokens.
|
||||
- No se modificó el frontend durante A0/A1.
|
||||
|
||||
## Observaciones resueltas
|
||||
|
||||
- El README indicaba PostGIS 3.6; se corrigió a 3.5.
|
||||
- Se mantuvo `synchronize: false` en runtime y migraciones.
|
||||
- Las credenciales del owner quedan fuera del contenedor permanente de la API.
|
||||
|
||||
## Próximo bloque
|
||||
|
||||
A2 implementará autenticación, Argon2id, cookies seguras, sesiones rotativas,
|
||||
lockout, rate limiting y bootstrap seguro del primer administrador.
|
||||
@@ -0,0 +1,46 @@
|
||||
# DH Inspección V2 — Fase A1
|
||||
|
||||
## Alcance implementado
|
||||
|
||||
- entidades TypeORM para usuarios, roles, permisos, sesiones y auditoría;
|
||||
- cinco migraciones controladas e independientes de `synchronize`;
|
||||
- seed idempotente de roles, permisos y matriz inicial;
|
||||
- grants explícitos y default privileges para `dhv2_app`;
|
||||
- repositorios base para A2, A4 y A5;
|
||||
- servicio Docker temporal para ejecutar migraciones como owner.
|
||||
|
||||
No se agregaron endpoints públicos ni autenticación incompleta. El único
|
||||
endpoint disponible continúa siendo `/api/v3/health`.
|
||||
|
||||
## Migraciones
|
||||
|
||||
1. `PhaseAUsersRolesPermissions1786548000000`
|
||||
2. `PhaseAAuthSessions1786548001000`
|
||||
3. `PhaseAAuditEvents1786548002000`
|
||||
4. `PhaseASeedRolesPermissions1786548003000`
|
||||
5. `PhaseARuntimeGrants1786548004000`
|
||||
|
||||
## Ejecución
|
||||
|
||||
```bash
|
||||
docker compose --profile tools build api migrate
|
||||
docker compose up -d db
|
||||
docker compose --profile tools run --rm migrate
|
||||
docker compose up -d --no-deps api
|
||||
```
|
||||
|
||||
## Verificación
|
||||
|
||||
```bash
|
||||
docker compose --profile tools run --rm migrate npm run migration:show
|
||||
docker compose ps
|
||||
curl -fsS http://127.0.0.1:3101/api/v3/health
|
||||
```
|
||||
|
||||
El resultado esperado de `migration:show` es `Pending migrations: no`.
|
||||
|
||||
## Reversión inmediata
|
||||
|
||||
`migration:revert` revierte una sola migración por ejecución. Sólo debe usarse
|
||||
antes de crear usuarios o sesiones reales. Si ya existe actividad, restaurar el
|
||||
backup previo en lugar de ejecutar reversiones parciales.
|
||||
@@ -0,0 +1,165 @@
|
||||
# DH Inspección V2 — Despliegue A1
|
||||
|
||||
Estos comandos se ejecutan únicamente en `dhv2.korexlabs.com`.
|
||||
|
||||
## 1. Verificación previa
|
||||
|
||||
```bash
|
||||
cd /var/www/dhv2.korexlabs.com
|
||||
|
||||
docker compose ps
|
||||
docker compose config >/dev/null && echo "Compose actual OK"
|
||||
curl -fsS http://127.0.0.1:3101/api/v3/health
|
||||
```
|
||||
|
||||
## 2. Backup previo
|
||||
|
||||
```bash
|
||||
cd /var/www/dhv2.korexlabs.com
|
||||
|
||||
PHASEA1_STAMP="$(date +%Y%m%d_%H%M%S)"
|
||||
PHASEA1_BACKUP_DIR="/var/www/dh-backup/dhv2-pre-phase-a1-${PHASEA1_STAMP}"
|
||||
|
||||
mkdir -p "$PHASEA1_BACKUP_DIR"
|
||||
|
||||
docker compose exec -T db sh -lc \
|
||||
'pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' \
|
||||
> "$PHASEA1_BACKUP_DIR/database.dump"
|
||||
|
||||
tar -czf "$PHASEA1_BACKUP_DIR/source.tar.gz" \
|
||||
--exclude='./api-v3/node_modules' \
|
||||
--exclude='./api-v3/dist' \
|
||||
--exclude='./web-v2/node_modules' \
|
||||
--exclude='./web-v2/dist' \
|
||||
.
|
||||
|
||||
install -m 600 .env "$PHASEA1_BACKUP_DIR/.env"
|
||||
cp /etc/nginx/sites-available/dhv2.korexlabs.com \
|
||||
"$PHASEA1_BACKUP_DIR/nginx-site.conf"
|
||||
|
||||
cd "$PHASEA1_BACKUP_DIR"
|
||||
sha256sum database.dump source.tar.gz .env nginx-site.conf > SHA256SUMS
|
||||
```
|
||||
|
||||
Conservar el valor mostrado por:
|
||||
|
||||
```bash
|
||||
echo "$PHASEA1_BACKUP_DIR"
|
||||
```
|
||||
|
||||
## 3. Reemplazo de archivos
|
||||
|
||||
Subir `DH_V2_FASE_A1_SOURCE.zip` a:
|
||||
|
||||
```text
|
||||
/var/www/dhv2.korexlabs.com
|
||||
```
|
||||
|
||||
Después:
|
||||
|
||||
```bash
|
||||
cd /var/www/dhv2.korexlabs.com
|
||||
unzip -oq DH_V2_FASE_A1_SOURCE.zip
|
||||
chmod 600 .env
|
||||
docker compose config >/dev/null && echo "Compose A1 OK"
|
||||
```
|
||||
|
||||
## 4. Build y migraciones
|
||||
|
||||
```bash
|
||||
cd /var/www/dhv2.korexlabs.com
|
||||
|
||||
docker compose --profile tools build api migrate
|
||||
docker compose up -d db
|
||||
docker compose --profile tools run --rm migrate
|
||||
docker compose --profile tools run --rm migrate npm run migration:show
|
||||
docker compose up -d --no-deps api
|
||||
```
|
||||
|
||||
La migración debe informar cinco migraciones aplicadas y luego:
|
||||
|
||||
```text
|
||||
Pending migrations: no
|
||||
```
|
||||
|
||||
## 5. Verificación de esquema y seeds
|
||||
|
||||
```bash
|
||||
cd /var/www/dhv2.korexlabs.com
|
||||
|
||||
docker compose exec -T db sh -lc \
|
||||
'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -v ON_ERROR_STOP=1' <<'SQL'
|
||||
SELECT table_name
|
||||
FROM information_schema.tables
|
||||
WHERE table_schema = 'public'
|
||||
AND table_name IN (
|
||||
'users', 'roles', 'permissions', 'user_roles',
|
||||
'role_permissions', 'auth_sessions', 'audit_events'
|
||||
)
|
||||
ORDER BY table_name;
|
||||
|
||||
SELECT
|
||||
(SELECT count(*) FROM roles) AS roles,
|
||||
(SELECT count(*) FROM permissions) AS permissions,
|
||||
(SELECT count(*) FROM role_permissions) AS role_permissions;
|
||||
|
||||
SELECT role.code, array_agg(permission.code ORDER BY permission.code) AS permissions
|
||||
FROM roles role
|
||||
LEFT JOIN role_permissions mapping ON mapping.role_id = role.id
|
||||
LEFT JOIN permissions permission ON permission.id = mapping.permission_id
|
||||
GROUP BY role.code
|
||||
ORDER BY role.code;
|
||||
SQL
|
||||
```
|
||||
|
||||
Valores iniciales esperados:
|
||||
|
||||
```text
|
||||
roles = 5
|
||||
permissions = 9
|
||||
role_permissions = 21
|
||||
```
|
||||
|
||||
## 6. Verificación del usuario runtime
|
||||
|
||||
```bash
|
||||
cd /var/www/dhv2.korexlabs.com
|
||||
|
||||
docker compose exec -T db sh -lc \
|
||||
'PGPASSWORD="$APP_DB_PASSWORD" psql -U "$APP_DB_USER" -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -c "SELECT count(*) FROM roles"'
|
||||
```
|
||||
|
||||
Este comando debe funcionar sin convertir a `dhv2_app` en owner o superusuario.
|
||||
|
||||
## 7. Verificación final
|
||||
|
||||
```bash
|
||||
cd /var/www/dhv2.korexlabs.com
|
||||
|
||||
docker compose ps
|
||||
docker compose logs --tail=100 api
|
||||
curl -fsS http://127.0.0.1:3101/api/v3/health
|
||||
curl -fsS https://dhv2.korexlabs.com/api/v3/health
|
||||
```
|
||||
|
||||
## 8. Rollback seguro del código
|
||||
|
||||
Si el build o el arranque de la API falla, se puede restaurar el código anterior
|
||||
sin eliminar las tablas nuevas:
|
||||
|
||||
```bash
|
||||
cd /var/www/dhv2.korexlabs.com
|
||||
|
||||
tar -xzf "$PHASEA1_BACKUP_DIR/source.tar.gz" \
|
||||
-C /var/www/dhv2.korexlabs.com
|
||||
|
||||
install -m 600 "$PHASEA1_BACKUP_DIR/.env" \
|
||||
/var/www/dhv2.korexlabs.com/.env
|
||||
|
||||
docker compose build api
|
||||
docker compose up -d --no-deps api
|
||||
curl -fsS http://127.0.0.1:3101/api/v3/health
|
||||
```
|
||||
|
||||
No revertir migraciones ni restaurar la base si ya se crearon usuarios o
|
||||
sesiones. Ese rollback de datos debe decidirse usando el backup previo.
|
||||
@@ -0,0 +1,79 @@
|
||||
# DH Inspección V2 — Fase A2
|
||||
|
||||
## Versión
|
||||
|
||||
```text
|
||||
v0.2.1 · Fase A2 · Autenticación y sesiones
|
||||
```
|
||||
|
||||
La leyenda se muestra en el footer del frontend. El health de la API también
|
||||
informa `version: 0.2.1` y `phase: A2`.
|
||||
|
||||
## Endpoints
|
||||
|
||||
```text
|
||||
POST /api/v3/auth/login
|
||||
POST /api/v3/auth/refresh
|
||||
POST /api/v3/auth/logout
|
||||
GET /api/v3/auth/me
|
||||
POST /api/v3/auth/change-password
|
||||
```
|
||||
|
||||
`GET /api/v3/health` continúa siendo el único endpoint público sin datos de
|
||||
negocio.
|
||||
|
||||
## Seguridad
|
||||
|
||||
- passwords con Argon2id;
|
||||
- respuesta genérica para credenciales inválidas;
|
||||
- 5 intentos fallidos y 15 minutos de bloqueo por defecto;
|
||||
- rate limiting por IP;
|
||||
- access token JWT HS256 corto;
|
||||
- refresh token opaco, rotativo y persistido únicamente como HMAC-SHA256;
|
||||
- cookies `HttpOnly`, `Secure` y `SameSite=Strict`;
|
||||
- defensa CSRF de doble envío para operaciones mutables con cookies;
|
||||
- validación estricta del origen web configurado;
|
||||
- sesiones revocables y detección de reutilización;
|
||||
- sanitización de passwords, hashes, tokens, cookies y secretos en auditoría;
|
||||
- `X-Request-ID` en respuestas y eventos de auditoría.
|
||||
|
||||
El navegador no utiliza `localStorage` ni `sessionStorage` para tokens.
|
||||
|
||||
## Migración A2
|
||||
|
||||
```text
|
||||
PhaseA2SessionSecurityIndexes1786548005000
|
||||
```
|
||||
|
||||
Agrega índices para `users.locked_until` y
|
||||
`auth_sessions.replaced_by_session_id`. No elimina ni transforma datos A1.
|
||||
|
||||
## Primer administrador
|
||||
|
||||
La CLI `npm run bootstrap:admin`:
|
||||
|
||||
- funciona únicamente en una terminal interactiva;
|
||||
- oculta la contraseña mientras se escribe;
|
||||
- exige entre 12 y 128 caracteres;
|
||||
- evita crear un segundo administrador por bootstrap;
|
||||
- usa una transacción y un advisory lock para impedir ejecuciones simultáneas;
|
||||
- asigna el rol `admin` sembrado en A1;
|
||||
- registra el evento `SYSTEM_BOOTSTRAP_ADMIN_CREATED`;
|
||||
- nunca imprime la contraseña ni su hash.
|
||||
|
||||
## Variables nuevas
|
||||
|
||||
```text
|
||||
WEB_ORIGIN
|
||||
JWT_ACCESS_SECRET
|
||||
REFRESH_TOKEN_PEPPER
|
||||
ACCESS_TOKEN_TTL_SECONDS
|
||||
REFRESH_TOKEN_TTL_SECONDS
|
||||
AUTH_MAX_LOGIN_ATTEMPTS
|
||||
AUTH_LOCKOUT_SECONDS
|
||||
ACCESS_COOKIE_NAME
|
||||
REFRESH_COOKIE_NAME
|
||||
CSRF_COOKIE_NAME
|
||||
```
|
||||
|
||||
Los dos secretos deben ser diferentes y tener al menos 64 caracteres.
|
||||
@@ -0,0 +1,53 @@
|
||||
# Despliegue DH V2 — Fase A2
|
||||
|
||||
## Precondiciones
|
||||
|
||||
- A1 desplegada y validada;
|
||||
- backup posterior a A1 conservado;
|
||||
- ZIP A2 subido manualmente a `/var/www/dhv2.korexlabs.com`;
|
||||
- no modificar `dh.korexlabs.com`;
|
||||
- no reemplazar el `.env` existente.
|
||||
|
||||
## Orden
|
||||
|
||||
1. validar el ZIP;
|
||||
2. extraer el código sin `.env`;
|
||||
3. agregar las variables A2 faltantes;
|
||||
4. validar Compose;
|
||||
5. compilar API, migrador y Web;
|
||||
6. ejecutar la migración A2;
|
||||
7. recrear API y Web;
|
||||
8. validar health, protección y footer;
|
||||
9. crear el primer administrador mediante CLI interactiva;
|
||||
10. generar backup posterior a A2.
|
||||
|
||||
## Resultados esperados
|
||||
|
||||
Después de migrar:
|
||||
|
||||
```text
|
||||
Applied migrations: 1
|
||||
- PhaseA2SessionSecurityIndexes1786548005000
|
||||
```
|
||||
|
||||
Después de reiniciar:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"service": "dhv2-api",
|
||||
"api": "v3",
|
||||
"version": "0.2.1",
|
||||
"phase": "A2",
|
||||
"database": "ok"
|
||||
}
|
||||
```
|
||||
|
||||
`GET /api/v3/auth/me` sin cookies debe responder `401 UNAUTHORIZED` con un
|
||||
`requestId` y nunca devolver datos internos.
|
||||
|
||||
## Rollback
|
||||
|
||||
Si la API nueva no inicia, restaurar el código y `.env` del backup A1 y recrear
|
||||
API/Web con esas fuentes. La migración A2 sólo agrega dos índices, por lo que no
|
||||
es necesario revertirla para volver temporalmente al código A1.
|
||||
@@ -0,0 +1,41 @@
|
||||
# DH Inspección V2 — Fase A3
|
||||
|
||||
## Versión
|
||||
|
||||
```text
|
||||
v0.3.0 · Fase A3 · Guards y autorización
|
||||
```
|
||||
|
||||
## Alcance
|
||||
|
||||
A3 agrega autorización declarativa y reutilizable al backend:
|
||||
|
||||
```ts
|
||||
@RequirePermissions('users.create')
|
||||
```
|
||||
|
||||
`PermissionsGuard` se registra globalmente después de `AccessTokenGuard`. Los
|
||||
permisos se resuelven desde las relaciones `user_roles` y `role_permissions`
|
||||
en cada request autenticado, por lo que los cambios futuros de A4 no dependen
|
||||
de regenerar el access token.
|
||||
|
||||
Reglas:
|
||||
|
||||
- endpoint sin sesión: `401 UNAUTHORIZED`;
|
||||
- sesión válida sin todos los permisos requeridos: `403 FORBIDDEN`;
|
||||
- sesión con todos los permisos requeridos: acceso permitido;
|
||||
- permisos de controller y handler se acumulan;
|
||||
- endpoints marcados con `@Public()` no requieren permisos;
|
||||
- el frontend podrá ocultar acciones, pero la autorización definitiva siempre
|
||||
queda en el backend.
|
||||
|
||||
## Migraciones
|
||||
|
||||
A3 no modifica el esquema y no incluye migraciones. Utiliza la matriz de roles
|
||||
y permisos creada en A1.
|
||||
|
||||
## Exclusiones
|
||||
|
||||
- endpoints administrativos de usuarios y roles: A4;
|
||||
- consultas administrativas de auditoría: A5;
|
||||
- login y panel web autenticado: A6.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Despliegue DH V2 — Fase A3
|
||||
|
||||
## Precondiciones
|
||||
|
||||
- A2 `v0.2.1` desplegada y operativa;
|
||||
- ZIP A3 subido manualmente a `/var/www/dhv2.korexlabs.com`;
|
||||
- conservar el `.env` existente;
|
||||
- no modificar `dh.korexlabs.com`.
|
||||
|
||||
## Orden
|
||||
|
||||
1. validar y extraer el ZIP;
|
||||
2. validar Compose;
|
||||
3. compilar API y Web;
|
||||
4. recrear API y Web;
|
||||
5. validar health, protección de autenticación y footer.
|
||||
|
||||
No se ejecutan migraciones porque A3 no cambia la base de datos.
|
||||
|
||||
## Resultado esperado
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"service": "dhv2-api",
|
||||
"api": "v3",
|
||||
"version": "0.3.0",
|
||||
"phase": "A3",
|
||||
"database": "ok"
|
||||
}
|
||||
```
|
||||
|
||||
`GET /api/v3/auth/me` sin sesión debe continuar respondiendo `401`.
|
||||
@@ -0,0 +1,72 @@
|
||||
# DH Inspección V2 — Fase A4
|
||||
|
||||
## Versión
|
||||
|
||||
```text
|
||||
v0.4.0 · Fase A4 · Administración de usuarios y roles
|
||||
```
|
||||
|
||||
## Usuarios
|
||||
|
||||
```text
|
||||
GET /api/v3/users
|
||||
POST /api/v3/users
|
||||
GET /api/v3/users/:id
|
||||
PATCH /api/v3/users/:id
|
||||
PATCH /api/v3/users/:id/status
|
||||
PUT /api/v3/users/:id/roles
|
||||
```
|
||||
|
||||
El listado acepta `page`, `pageSize`, `search` y `status`. No existe endpoint de
|
||||
borrado físico. La desactivación revoca todas las sesiones del usuario.
|
||||
|
||||
Los usuarios se crean con una contraseña temporal de al menos 12 caracteres.
|
||||
El password se transforma a Argon2id antes de persistir y nunca aparece en la
|
||||
respuesta ni en auditoría. Cuando `mustChangePassword` está activo, los guards
|
||||
bloquean endpoints administrativos hasta completar el cambio de contraseña.
|
||||
|
||||
## Roles
|
||||
|
||||
```text
|
||||
GET /api/v3/roles
|
||||
GET /api/v3/roles/permissions
|
||||
GET /api/v3/roles/:id
|
||||
POST /api/v3/roles
|
||||
PATCH /api/v3/roles/:id
|
||||
PUT /api/v3/roles/:id/permissions
|
||||
```
|
||||
|
||||
Los códigos de rol son inmutables después de su creación. Los nombres,
|
||||
descripciones y permisos se administran por API. No existe borrado de roles en
|
||||
A4.
|
||||
|
||||
## Permisos requeridos
|
||||
|
||||
```text
|
||||
users.read
|
||||
users.create
|
||||
users.update
|
||||
users.change_status
|
||||
users.assign_roles
|
||||
roles.read
|
||||
roles.manage
|
||||
```
|
||||
|
||||
Cada endpoint usa `@RequirePermissions(...)` y el backend siempre valida la
|
||||
matriz actual almacenada en PostgreSQL.
|
||||
|
||||
## Integridad y auditoría
|
||||
|
||||
- todas las mutaciones son transaccionales;
|
||||
- se registran `USER_CREATED`, `USER_UPDATED`, `USER_STATUS_CHANGED`,
|
||||
`USER_ROLES_CHANGED`, `ROLE_CREATED`, `ROLE_UPDATED` y
|
||||
`ROLE_PERMISSIONS_CHANGED`;
|
||||
- no se auditan passwords, hashes, tokens ni cookies;
|
||||
- no se permite la autodesactivación;
|
||||
- no se puede dejar el sistema sin al menos un usuario activo con
|
||||
`roles.manage` y `users.assign_roles`;
|
||||
- cambios de roles y permisos tienen efecto en el siguiente request.
|
||||
|
||||
## Migraciones
|
||||
|
||||
A4 no modifica el esquema y no incluye migraciones.
|
||||
@@ -0,0 +1,34 @@
|
||||
# Despliegue DH V2 — Fase A4
|
||||
|
||||
## Precondiciones
|
||||
|
||||
- A3 `v0.3.0` desplegada;
|
||||
- ZIP A4 subido a `/var/www/dhv2.korexlabs.com`;
|
||||
- conservar el `.env` existente;
|
||||
- no modificar `dh.korexlabs.com`.
|
||||
|
||||
## Orden
|
||||
|
||||
1. crear backup previo;
|
||||
2. validar y extraer el ZIP;
|
||||
3. validar Compose;
|
||||
4. compilar API y Web;
|
||||
5. recrear API y Web;
|
||||
6. validar health, rutas protegidas y footer.
|
||||
|
||||
No se ejecutan migraciones porque A4 utiliza el esquema existente.
|
||||
|
||||
## Resultado esperado
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"service": "dhv2-api",
|
||||
"api": "v3",
|
||||
"version": "0.4.0",
|
||||
"phase": "A4",
|
||||
"database": "ok"
|
||||
}
|
||||
```
|
||||
|
||||
Sin sesión, `/api/v3/users` y `/api/v3/roles` deben responder `401`.
|
||||
@@ -0,0 +1,90 @@
|
||||
# DH Inspección V2 — Fase A5
|
||||
|
||||
## Versión
|
||||
|
||||
```text
|
||||
v0.5.0 · Fase A5 · Auditoría, filtros y trazabilidad
|
||||
```
|
||||
|
||||
## Endpoints
|
||||
|
||||
```text
|
||||
GET /api/v3/audit
|
||||
GET /api/v3/audit/:id
|
||||
```
|
||||
|
||||
Ambos requieren:
|
||||
|
||||
```text
|
||||
audit.read
|
||||
```
|
||||
|
||||
## Listado
|
||||
|
||||
El listado devuelve únicamente la información necesaria para una grilla:
|
||||
|
||||
```text
|
||||
fecha/hora
|
||||
usuario
|
||||
acción
|
||||
entidad
|
||||
request ID
|
||||
origen
|
||||
IP
|
||||
indicador de detalle
|
||||
```
|
||||
|
||||
Los objetos `beforeData`, `afterData` y `metadata` se reservan para la consulta
|
||||
individual, evitando respuestas innecesariamente pesadas.
|
||||
|
||||
## Filtros
|
||||
|
||||
```text
|
||||
page
|
||||
pageSize
|
||||
actorUserId
|
||||
actorUsername
|
||||
action
|
||||
source
|
||||
entityType
|
||||
entityId
|
||||
requestId
|
||||
from
|
||||
to
|
||||
search
|
||||
```
|
||||
|
||||
`pageSize` admite hasta 100 resultados. `from` y `to` usan ISO 8601 y se
|
||||
rechaza un rango en el que la fecha inicial sea posterior a la final.
|
||||
|
||||
La respuesta paginada conserva el contrato:
|
||||
|
||||
```json
|
||||
{
|
||||
"data": [],
|
||||
"meta": {
|
||||
"page": 1,
|
||||
"pageSize": 25,
|
||||
"total": 0,
|
||||
"totalPages": 0
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Detalle
|
||||
|
||||
Además de los campos del listado devuelve:
|
||||
|
||||
```text
|
||||
userAgent
|
||||
beforeData
|
||||
afterData
|
||||
metadata
|
||||
```
|
||||
|
||||
La escritura continúa pasando por `sanitizeAuditData`, que elimina passwords,
|
||||
hashes, JWT, refresh tokens, cookies, encabezados de autorización y secretos.
|
||||
|
||||
## Migraciones
|
||||
|
||||
A5 no cambia el esquema y no incluye migraciones.
|
||||
@@ -0,0 +1,34 @@
|
||||
# Despliegue DH V2 — Fase A5
|
||||
|
||||
## Precondiciones
|
||||
|
||||
- A4 `v0.4.0` desplegada;
|
||||
- ZIP A5 subido a `/var/www/dhv2.korexlabs.com`;
|
||||
- conservar el `.env` existente;
|
||||
- no modificar `dh.korexlabs.com`.
|
||||
|
||||
## Orden
|
||||
|
||||
1. crear backup previo;
|
||||
2. validar y extraer el ZIP;
|
||||
3. validar Compose;
|
||||
4. compilar API y Web;
|
||||
5. recrear API y Web;
|
||||
6. validar health, endpoint protegido y footer.
|
||||
|
||||
No se ejecutan migraciones.
|
||||
|
||||
## Resultado esperado
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"service": "dhv2-api",
|
||||
"api": "v3",
|
||||
"version": "0.5.0",
|
||||
"phase": "A5",
|
||||
"database": "ok"
|
||||
}
|
||||
```
|
||||
|
||||
Sin sesión, `/api/v3/audit` debe responder `401`.
|
||||
@@ -0,0 +1,93 @@
|
||||
# DH Inspección V2 — Fase A6
|
||||
|
||||
## Versión
|
||||
|
||||
```text
|
||||
v0.6.0 · Fase A6 · Panel web administrativo
|
||||
```
|
||||
|
||||
## Rutas web
|
||||
|
||||
```text
|
||||
/login
|
||||
/
|
||||
/change-password
|
||||
/admin/users
|
||||
/admin/users/new
|
||||
/admin/users/:id
|
||||
/admin/roles
|
||||
/admin/audit
|
||||
```
|
||||
|
||||
## Autenticación web
|
||||
|
||||
- el JWT de acceso y el token de renovación permanecen en cookies seguras;
|
||||
- el frontend no almacena JWT en `localStorage` ni `sessionStorage`;
|
||||
- las escrituras envían `x-csrf-token`;
|
||||
- un acceso vencido intenta una única renovación y repite el request original;
|
||||
- una sesión inválida vuelve al login;
|
||||
- la contraseña temporal bloquea todos los módulos hasta ser cambiada;
|
||||
- el cierre de sesión revoca la sesión actual.
|
||||
|
||||
## Autorización visible
|
||||
|
||||
La navegación y las acciones se ocultan cuando el usuario no dispone del
|
||||
permiso correspondiente. El backend continúa siendo la autoridad definitiva.
|
||||
|
||||
| Área | Permiso |
|
||||
|---|---|
|
||||
| Dashboard | `dashboard.read` |
|
||||
| Usuarios | `users.read`, `users.create`, `users.update`, `users.change_status`, `users.assign_roles` |
|
||||
| Roles | `roles.read`, `roles.manage` |
|
||||
| Auditoría | `audit.read` |
|
||||
|
||||
## Resumen administrativo
|
||||
|
||||
A6 agrega:
|
||||
|
||||
```text
|
||||
GET /api/v3/dashboard/summary
|
||||
```
|
||||
|
||||
Requiere `dashboard.read` y devuelve:
|
||||
|
||||
- usuarios activos;
|
||||
- usuarios inactivos;
|
||||
- sesiones vigentes;
|
||||
- seis eventos recientes de auditoría;
|
||||
- fecha de generación.
|
||||
|
||||
La lectura se ejecuta dentro de una transacción `REPEATABLE READ`.
|
||||
|
||||
## Usuarios
|
||||
|
||||
- búsqueda y filtro por estado;
|
||||
- paginación;
|
||||
- alta con contraseña temporal y roles;
|
||||
- edición de datos personales;
|
||||
- activación y desactivación;
|
||||
- asignación múltiple de roles;
|
||||
- información de último acceso, bloqueo y cambio de contraseña.
|
||||
|
||||
Se mantienen las protecciones de A4: no es posible desactivar la propia cuenta,
|
||||
quitar el último administrador de recuperación ni dejar el sistema sin acceso
|
||||
administrativo.
|
||||
|
||||
## Roles y permisos
|
||||
|
||||
- listado de roles del sistema y personalizados;
|
||||
- alta de roles personalizados;
|
||||
- edición de nombre y descripción;
|
||||
- matriz dinámica de permisos;
|
||||
- cantidad de usuarios por rol.
|
||||
|
||||
## Auditoría
|
||||
|
||||
- filtros por texto, acción, origen y fechas;
|
||||
- paginación;
|
||||
- detalle técnico en panel lateral;
|
||||
- visualización de `beforeData`, `afterData` y `metadata` ya sanitizados.
|
||||
|
||||
## Migraciones
|
||||
|
||||
A6 no cambia el esquema y no incluye migraciones.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Deploy A6
|
||||
|
||||
## Archivo
|
||||
|
||||
```text
|
||||
DH_V2_FASE_A6_SOURCE.zip
|
||||
```
|
||||
|
||||
El archivo se sube por FTP a:
|
||||
|
||||
```text
|
||||
/var/www/dhv2.korexlabs.com/
|
||||
```
|
||||
|
||||
Antes de reemplazar los fuentes se guarda un backup de archivos, `.env` y base
|
||||
de datos en `/var/www/dh-backup/`.
|
||||
|
||||
El despliegue reconstruye únicamente `api` y `web`; la base no se recrea y A6
|
||||
no requiere migraciones. Al finalizar deben verificarse:
|
||||
|
||||
```text
|
||||
health interno: version 0.6.0, phase A6, database ok
|
||||
health externo: version 0.6.0, phase A6, database ok
|
||||
/api/v3/dashboard/summary sin sesión: HTTP 401
|
||||
/api/v3/users sin sesión: HTTP 401
|
||||
/api/v3/roles sin sesión: HTTP 401
|
||||
/api/v3/audit sin sesión: HTTP 401
|
||||
login compilado: OK
|
||||
footer v0.6.0: OK
|
||||
api, db y web: Up
|
||||
```
|
||||
|
||||
El bloque único de comandos y el SHA-256 se entregan junto con el ZIP final.
|
||||
@@ -0,0 +1,69 @@
|
||||
# DH Inspección V2 — Fase A7
|
||||
|
||||
## Versión
|
||||
|
||||
```text
|
||||
v0.7.0 · Fase A7 · Integración y cierre de Fase A
|
||||
```
|
||||
|
||||
## Objetivo
|
||||
|
||||
A7 no agrega módulos funcionales ni modifica tablas. Cierra la Fase A mediante
|
||||
pruebas integradas sobre el despliegue real, controles de seguridad y un backup
|
||||
post-fase verificable.
|
||||
|
||||
## Aceptación autenticada
|
||||
|
||||
`scripts/phase-a-acceptance.sh` solicita usuario y contraseña en la terminal.
|
||||
La contraseña se ingresa sin mostrarse, se utiliza para un único login y no se
|
||||
escribe en logs ni archivos persistentes.
|
||||
|
||||
La prueba valida:
|
||||
|
||||
1. `401` sin sesión en dashboard, usuarios, roles y auditoría;
|
||||
2. respuesta genérica ante un usuario inexistente;
|
||||
3. login administrativo válido;
|
||||
4. tres cookies con `Secure` y `SameSite=Strict`;
|
||||
5. dos cookies de autenticación con `HttpOnly`;
|
||||
6. `200` autenticado en `/auth/me`, dashboard, usuarios, roles y auditoría;
|
||||
7. `403 CSRF_INVALID` en una escritura sin token CSRF;
|
||||
8. logout válido con CSRF;
|
||||
9. `401` después de revocar la sesión.
|
||||
|
||||
La prueba no crea, edita ni elimina usuarios o roles. Sólo genera los eventos
|
||||
de autenticación y seguridad esperables en auditoría.
|
||||
|
||||
## Backup post-fase
|
||||
|
||||
`scripts/backup-phase-a.sh` crea una carpeta privada bajo
|
||||
`/var/www/dh-backup/` con:
|
||||
|
||||
```text
|
||||
source.tar.gz
|
||||
database.dump
|
||||
.env
|
||||
nginx-site.conf o NGINX_CONFIG_NOT_FOUND.txt
|
||||
MANIFEST.txt
|
||||
SHA256SUMS
|
||||
```
|
||||
|
||||
El TAR excluye `.env`, ZIP, `node_modules`, `dist` y archivos incrementales de
|
||||
TypeScript. El dump usa formato custom de PostgreSQL.
|
||||
|
||||
## Verificación
|
||||
|
||||
`scripts/verify-backup.sh` es no destructivo y comprueba:
|
||||
|
||||
- archivos obligatorios;
|
||||
- permisos `600` del `.env` respaldado;
|
||||
- todos los SHA-256;
|
||||
- integridad y exclusiones del TAR;
|
||||
- legibilidad del catálogo de `database.dump` mediante `pg_restore --list`.
|
||||
|
||||
## Migraciones
|
||||
|
||||
A7 no incluye migraciones. El despliegue debe confirmar:
|
||||
|
||||
```text
|
||||
Pending migrations: no
|
||||
```
|
||||
@@ -0,0 +1,30 @@
|
||||
# Deploy A7
|
||||
|
||||
## Archivo
|
||||
|
||||
```text
|
||||
DH_V2_FASE_A7_SOURCE.zip
|
||||
```
|
||||
|
||||
Se sube por FTP a:
|
||||
|
||||
```text
|
||||
/var/www/dhv2.korexlabs.com/
|
||||
```
|
||||
|
||||
El bloque de deploy realiza, en orden:
|
||||
|
||||
1. checksum e integridad del ZIP;
|
||||
2. backup pre-A7;
|
||||
3. reemplazo de fuentes;
|
||||
4. build de API, web y herramienta de migraciones;
|
||||
5. confirmación de que no existen migraciones pendientes;
|
||||
6. recreación controlada de API y web;
|
||||
7. health interno y externo;
|
||||
8. aceptación autenticada interactiva;
|
||||
9. backup post-A7;
|
||||
10. verificación no destructiva del backup;
|
||||
11. estado y logs finales.
|
||||
|
||||
A7 no agrega migraciones ni variables de entorno. El SHA-256 y el bloque único
|
||||
se entregan junto con el ZIP final.
|
||||
@@ -0,0 +1,49 @@
|
||||
# Cierre de Fase A — Matriz de aceptación
|
||||
|
||||
## Backend
|
||||
|
||||
| Criterio | Evidencia |
|
||||
|---|---|
|
||||
| Migraciones controladas | TypeORM con `synchronize: false` y `migration:show` sin pendientes |
|
||||
| Tablas, índices y seeds | Migraciones A1/A2 aplicadas y 26 índices verificados en producción |
|
||||
| Bootstrap seguro | CLI interactiva, contraseña oculta y bloqueo si ya existe admin |
|
||||
| Auth completa | login, refresh, logout, me y change-password |
|
||||
| Sesiones | hash del refresh, rotación, revocación y detección de reutilización |
|
||||
| Autorización | guard global y permisos resueltos desde base |
|
||||
| Usuarios y roles | endpoints administrativos protegidos y auditados |
|
||||
| Auditoría | filtros, paginación, detalle, request ID y sanitización |
|
||||
| Dashboard | resumen protegido por `dashboard.read` |
|
||||
| Rate limiting | throttling global y límites reforzados en autenticación |
|
||||
| Usuario DB runtime | API configurada con `DB_APP_USER`, separada del owner |
|
||||
|
||||
## Frontend
|
||||
|
||||
| Criterio | Evidencia |
|
||||
|---|---|
|
||||
| Login y sesión | AuthContext con cookies y renovación controlada |
|
||||
| Tokens | ningún JWT en `localStorage` o `sessionStorage` |
|
||||
| Rutas | protección por sesión y redirección al login |
|
||||
| Contraseña temporal | bloqueo de módulos hasta completar el cambio |
|
||||
| Permisos visibles | navegación y acciones mediante `PermissionGate` |
|
||||
| Administración | dashboard, usuarios, roles y auditoría |
|
||||
| Cierre de sesión | revocación backend y limpieza local |
|
||||
| Identificación | footer visible `v0.7.0 · Fase A7` |
|
||||
|
||||
## Seguridad e infraestructura
|
||||
|
||||
| Criterio | Evidencia |
|
||||
|---|---|
|
||||
| HTTPS | login y API externa accesibles únicamente mediante el proxy configurado |
|
||||
| Cookies | `HttpOnly` para acceso/refresh; `Secure` y `SameSite=Strict` |
|
||||
| CSRF | escritura con cookie rechazada sin `x-csrf-token` |
|
||||
| Acceso anónimo | sólo `/api/v3/health` es público |
|
||||
| Secretos | sanitización de auditoría y ninguna credencial en artefactos fuente |
|
||||
| Docker | DB saludable, API y web en ejecución |
|
||||
| Backup | fuentes, base, `.env`, Nginx, manifiesto y checksums |
|
||||
| Recuperación | dump y TAR verificables sin modificar producción |
|
||||
|
||||
## Resultado
|
||||
|
||||
Cuando el deploy A7, la aceptación autenticada y la verificación del backup
|
||||
finalizan sin errores, la Fase A queda formalmente cerrada y puede comenzar la
|
||||
Fase B — Maestro de Activos.
|
||||
@@ -0,0 +1,106 @@
|
||||
# Fase B1 — Base del Maestro de Activos
|
||||
|
||||
Versión: `0.8.0`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Reemplazar el placeholder de Activos por el primer núcleo funcional del Maestro
|
||||
de Activos, sin fijar niveles como Empresa, Área, Yacimiento o Pozo.
|
||||
|
||||
## Modelo incorporado
|
||||
|
||||
- `asset_types`: tipos configurables y activables/desactivables;
|
||||
- `asset_type_parent_rules`: múltiples tipos padre permitidos por tipo hijo;
|
||||
- `asset_attribute_definitions`: atributos configurables por tipo;
|
||||
- `assets`: entidades administrables con identidad y padre opcional;
|
||||
- `asset_attribute_values`: valores tipados de cada activo.
|
||||
|
||||
La jerarquía se controla con dos reglas:
|
||||
|
||||
1. un tipo puede o no permitir activos raíz;
|
||||
2. un tipo puede aceptar cero, uno o varios tipos padre.
|
||||
|
||||
La API también evita ciclos en la jerarquía real de activos.
|
||||
|
||||
## Atributos dinámicos
|
||||
|
||||
Tipos iniciales de dato:
|
||||
|
||||
- texto;
|
||||
- número;
|
||||
- verdadero/falso;
|
||||
- fecha;
|
||||
- fecha y hora;
|
||||
- selección con opciones configurables.
|
||||
|
||||
Los atributos pueden ser obligatorios, tener unidad, orden e inactivarse sin
|
||||
borrar valores existentes.
|
||||
|
||||
## Estados de información
|
||||
|
||||
- `DRAFT`;
|
||||
- `PENDING_SURVEY`;
|
||||
- `SURVEYED`;
|
||||
- `VALIDATED`;
|
||||
- `OBSERVED`;
|
||||
- `OUTDATED`;
|
||||
- `INACTIVE`.
|
||||
|
||||
Estos estados describen la calidad o vigencia de la información. No representan
|
||||
el estado operativo o mecánico del activo.
|
||||
|
||||
## API
|
||||
|
||||
Tipos y atributos:
|
||||
|
||||
- `GET /api/v3/asset-types`;
|
||||
- `GET /api/v3/asset-types/:id`;
|
||||
- `POST /api/v3/asset-types`;
|
||||
- `PATCH /api/v3/asset-types/:id`;
|
||||
- `POST /api/v3/asset-types/:id/attributes`;
|
||||
- `PATCH /api/v3/asset-types/:id/attributes/:attributeId`.
|
||||
|
||||
Activos:
|
||||
|
||||
- `GET /api/v3/assets`;
|
||||
- `GET /api/v3/assets/parent-options`;
|
||||
- `GET /api/v3/assets/:id`;
|
||||
- `POST /api/v3/assets`;
|
||||
- `PATCH /api/v3/assets/:id`;
|
||||
- `PATCH /api/v3/assets/:id/information-status`.
|
||||
|
||||
No se implementa borrado físico.
|
||||
|
||||
## Permisos
|
||||
|
||||
- `asset_types.read`;
|
||||
- `asset_types.manage`;
|
||||
- `assets.read`;
|
||||
- `assets.create`;
|
||||
- `assets.update`;
|
||||
- `assets.change_status`.
|
||||
|
||||
La migración los asigna a los roles de sistema según su alcance y entrega todos
|
||||
al rol `admin`.
|
||||
|
||||
## Interfaz web
|
||||
|
||||
- `/activos`: búsqueda, filtros, tabla y jerarquía visible;
|
||||
- `/activos/nuevo`: alta con atributos dinámicos;
|
||||
- `/activos/:id`: consulta/edición y cambio de estado según permiso;
|
||||
- `/admin/asset-types`: configuración de tipos, padres y atributos.
|
||||
|
||||
## Trazabilidad
|
||||
|
||||
Se auditan altas y cambios de tipos, atributos, activos y estado de información.
|
||||
Los valores dinámicos quedan incluidos en el antes/después sanitizado.
|
||||
|
||||
## Fuera de B1
|
||||
|
||||
Quedan para próximas subfases:
|
||||
|
||||
- geometrías PostGIS y edición en mapa;
|
||||
- fotografías y media versionada;
|
||||
- versiones históricas y consulta temporal;
|
||||
- importaciones/procedencia avanzada;
|
||||
- relevamiento de campo.
|
||||
@@ -0,0 +1,42 @@
|
||||
# Deploy B1
|
||||
|
||||
## Archivo
|
||||
|
||||
```text
|
||||
DH_V2_FASE_B1_SOURCE.zip
|
||||
```
|
||||
|
||||
Subir por FTP a:
|
||||
|
||||
```text
|
||||
/var/www/dhv2.korexlabs.com/
|
||||
```
|
||||
|
||||
## Cambios de base
|
||||
|
||||
B1 incorpora una migración controlada:
|
||||
|
||||
```text
|
||||
PhaseB1AssetMaster1786636800000
|
||||
```
|
||||
|
||||
La migración crea cinco tablas, dos enums, índices, permisos y grants para el
|
||||
usuario runtime. TypeORM permanece con `synchronize: false`.
|
||||
|
||||
No se agregan variables de entorno.
|
||||
|
||||
## Orden del bloque único
|
||||
|
||||
1. verificar checksum e integridad del ZIP;
|
||||
2. crear backup previo de fuentes, `.env` y base;
|
||||
3. extraer el código;
|
||||
4. validar Compose;
|
||||
5. construir API, migrador y web;
|
||||
6. aplicar la migración como owner;
|
||||
7. confirmar que no quedan migraciones pendientes;
|
||||
8. recrear únicamente API y web;
|
||||
9. esperar health interno;
|
||||
10. ejecutar `scripts/phase-b1-acceptance.sh`;
|
||||
11. mostrar contenedores, logs y ubicación del backup.
|
||||
|
||||
El checksum definitivo y el bloque completo se entregan junto al ZIP.
|
||||
@@ -0,0 +1,80 @@
|
||||
# Fase B2 — Geometrías PostGIS y mapa operativo
|
||||
|
||||
Versión: `0.9.0`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Incorporar ubicación geográfica real al Maestro de Activos y reemplazar el
|
||||
mapa demostrativo por una consulta territorial conectada a PostGIS.
|
||||
|
||||
## Modelo
|
||||
|
||||
La tabla `asset_geometries` mantiene la geometría actual de cada activo:
|
||||
|
||||
- `POINT`, `LINESTRING` o `POLYGON`;
|
||||
- SRID `4326`;
|
||||
- fuente `WEB`, `ANDROID`, `IMPORT` o `SURVEY`;
|
||||
- precisión en metros;
|
||||
- fecha/hora de captura;
|
||||
- dispositivo;
|
||||
- usuario y fechas de actualización.
|
||||
|
||||
PostgreSQL valida tipo, rango, validez geométrica y relación con el activo. La
|
||||
columna posee un índice espacial `GIST`.
|
||||
|
||||
## API
|
||||
|
||||
- `GET /api/v3/map/assets` devuelve un `FeatureCollection` GeoJSON;
|
||||
- `GET /api/v3/assets/:id/geometry` consulta la geometría actual;
|
||||
- `PUT /api/v3/assets/:id/geometry` crea o actualiza ubicación y metadatos;
|
||||
- `DELETE /api/v3/assets/:id/geometry` retira la geometría actual.
|
||||
|
||||
El mapa admite filtros por tipo de activo, estado de información, tipo de
|
||||
geometría y área visible mediante `bbox`. La respuesta se limita a 5000
|
||||
features e informa si fue truncada.
|
||||
|
||||
## Seguridad
|
||||
|
||||
- lectura y mapa: `assets.read`;
|
||||
- escritura geográfica: `assets.update_geometry`.
|
||||
|
||||
La migración asigna escritura a `admin`, `supervisor` e `inspector`. Director y
|
||||
auditor conservan lectura territorial.
|
||||
|
||||
## Interfaz
|
||||
|
||||
### Mapa
|
||||
|
||||
`/mapa` muestra puntos, líneas y polígonos con:
|
||||
|
||||
- filtros reales;
|
||||
- selección visual;
|
||||
- datos básicos, jerarquía y estado;
|
||||
- acceso directo al detalle del activo;
|
||||
- aviso de resultados truncados o sin ubicación.
|
||||
|
||||
### Editor del activo
|
||||
|
||||
El detalle del activo permite:
|
||||
|
||||
- elegir punto, línea o polígono;
|
||||
- marcar vértices sobre el mapa;
|
||||
- deshacer y limpiar;
|
||||
- usar explícitamente la geolocalización del navegador;
|
||||
- registrar precisión, timestamp y dispositivo;
|
||||
- retirar una geometría dejando auditoría.
|
||||
|
||||
La captura GPS sólo ocurre cuando el usuario presiona “Usar mi ubicación”.
|
||||
|
||||
## Trazabilidad
|
||||
|
||||
Cada creación, reemplazo o retiro genera un evento de auditoría con geometría y
|
||||
metadatos antes/después. El versionado temporal formal de activos se incorpora
|
||||
en una subfase posterior.
|
||||
|
||||
## Fuera de B2
|
||||
|
||||
- versiones históricas completas y consulta temporal;
|
||||
- media/fotografías;
|
||||
- importaciones masivas;
|
||||
- relevamiento de campo y sincronización Android.
|
||||
@@ -0,0 +1,28 @@
|
||||
# Deploy B2
|
||||
|
||||
## Archivo
|
||||
|
||||
```text
|
||||
DH_V2_FASE_B2_SOURCE.zip
|
||||
```
|
||||
|
||||
Subir por FTP a:
|
||||
|
||||
```text
|
||||
/var/www/dhv2.korexlabs.com/
|
||||
```
|
||||
|
||||
## Migración
|
||||
|
||||
```text
|
||||
PhaseB2AssetGeometries1786723200000
|
||||
```
|
||||
|
||||
Crea la tabla espacial, enum de fuente, índices, permiso y grants runtime. La
|
||||
extensión PostGIS ya existente no se modifica. TypeORM continúa con
|
||||
`synchronize: false`.
|
||||
|
||||
No se agregan variables de entorno.
|
||||
|
||||
El bloque único de deploy realiza backup, verifica el ZIP, construye API,
|
||||
migrador y web, aplica la migración, recrea API/web y ejecuta la aceptación B2.
|
||||
@@ -0,0 +1,62 @@
|
||||
# Fase B3 — Historial y versiones de activos
|
||||
|
||||
Versión: `0.10.0`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Conservar el estado exacto de cada activo a través del tiempo, sin depender de
|
||||
la auditoría general para reconstruirlo.
|
||||
|
||||
## Modelo
|
||||
|
||||
La tabla append-only `asset_versions` registra una versión completa cuando:
|
||||
|
||||
- se crea un activo;
|
||||
- cambian su identificación, jerarquía o atributos;
|
||||
- cambia su estado de información;
|
||||
- se crea, reemplaza o retira su geometría.
|
||||
|
||||
Cada snapshot incluye datos principales, tipo y padre, atributos configurables,
|
||||
geometría GeoJSON, metadatos de captura, actor, origen, request ID y fecha.
|
||||
El evento de auditoría correspondiente conserva además el número de versión
|
||||
generado, permitiendo relacionar ambos registros.
|
||||
|
||||
La columna `assets.current_version` identifica la versión vigente. La migración
|
||||
genera automáticamente una versión `BASELINE` para cada activo que ya existía
|
||||
al desplegar B3.
|
||||
|
||||
## Inmutabilidad
|
||||
|
||||
El usuario runtime de la API recibe solamente `SELECT` e `INSERT` sobre
|
||||
`asset_versions`. No recibe `UPDATE` ni `DELETE`. Una versión guardada no puede
|
||||
ser reescrita por la aplicación.
|
||||
|
||||
## API
|
||||
|
||||
- `GET /api/v3/asset-versions`: historial global paginado y filtrable;
|
||||
- `GET /api/v3/assets/:id/versions`: línea de tiempo de un activo;
|
||||
- `GET /api/v3/assets/:id/versions/:versionNumber`: snapshot exacto.
|
||||
|
||||
Los filtros globales incluyen búsqueda, tipo, estado, clase de cambio y rango
|
||||
de fechas.
|
||||
|
||||
## Seguridad
|
||||
|
||||
Todas las rutas requieren `assets.read_history`. La migración asigna lectura
|
||||
histórica a `admin`, `director`, `supervisor`, `inspector` y `auditor`.
|
||||
|
||||
## Interfaz
|
||||
|
||||
- la sección **Historial** reemplaza el placeholder y muestra las versiones de
|
||||
todos los activos;
|
||||
- cada activo incluye su propia línea de tiempo;
|
||||
- el visor distingue la versión vigente y muestra datos, atributos, ubicación
|
||||
y el snapshot técnico exacto;
|
||||
- la lista maestra muestra el número de versión vigente.
|
||||
|
||||
## Fuera de B3
|
||||
|
||||
- restauración automática de versiones anteriores;
|
||||
- fotografías, documentos y evidencias;
|
||||
- importaciones masivas;
|
||||
- relevamiento Android y sincronización offline.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Deploy B3
|
||||
|
||||
## Archivo
|
||||
|
||||
```text
|
||||
DH_V2_FASE_B3_SOURCE.zip
|
||||
```
|
||||
|
||||
Subir por FTP a:
|
||||
|
||||
```text
|
||||
/var/www/dhv2.korexlabs.com/
|
||||
```
|
||||
|
||||
## Migración
|
||||
|
||||
```text
|
||||
PhaseB3AssetVersions1786723201000
|
||||
```
|
||||
|
||||
Crea `asset_versions`, agrega `assets.current_version`, genera las versiones
|
||||
base de los activos existentes, incorpora el permiso y configura grants
|
||||
append-only para el usuario runtime.
|
||||
|
||||
TypeORM continúa con `synchronize: false`. No se agregan variables de entorno.
|
||||
|
||||
El bloque único de deploy realiza backup, valida el ZIP, construye API,
|
||||
migrador y web, aplica la migración, recrea los servicios y ejecuta la
|
||||
aceptación B3.
|
||||
@@ -0,0 +1,73 @@
|
||||
# Fase B4 — Fotografías y documentos de activos
|
||||
|
||||
Versión: `0.11.0`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Adjuntar evidencia visual y documental a cada activo, conservando el archivo
|
||||
original en almacenamiento privado y relacionando toda operación con el
|
||||
historial inmutable y la auditoría.
|
||||
|
||||
## Modelo y almacenamiento
|
||||
|
||||
La tabla `asset_media` guarda los metadatos, el hash SHA-256 y el vínculo con
|
||||
el activo. Los binarios se almacenan fuera de la imagen de la API, en el
|
||||
volumen Docker persistente `dhv2_asset_media`.
|
||||
|
||||
Formatos permitidos:
|
||||
|
||||
- fotografías JPEG, PNG y WebP;
|
||||
- documentos PDF;
|
||||
- tamaño máximo de 15 MB por archivo.
|
||||
|
||||
La API inspecciona la firma real del contenido y no confía en la extensión ni
|
||||
en el MIME informado por el navegador. Cada original recibe un nombre interno
|
||||
aleatorio y permisos de archivo restringidos.
|
||||
|
||||
## API
|
||||
|
||||
- `GET /api/v3/assets/:assetId/media`: lista archivos activos;
|
||||
- `POST /api/v3/assets/:assetId/media`: incorpora un archivo multipart;
|
||||
- `PATCH /api/v3/asset-media/:mediaId`: actualiza metadatos;
|
||||
- `DELETE /api/v3/asset-media/:mediaId`: retiro lógico;
|
||||
- `GET /api/v3/asset-media/:mediaId/content`: visualización o descarga protegida.
|
||||
|
||||
Los archivos no se publican desde Nginx. Toda lectura atraviesa autenticación y
|
||||
autorización en la API.
|
||||
|
||||
## Seguridad y permisos
|
||||
|
||||
- `assets.read_media`: admin, director, supervisor, inspector y auditor;
|
||||
- `assets.manage_media`: admin, supervisor e inspector.
|
||||
|
||||
El usuario runtime puede consultar, insertar y actualizar `asset_media`, pero
|
||||
no recibe `DELETE`. Retirar un archivo es una baja lógica: el registro y el
|
||||
original físico se conservan.
|
||||
|
||||
## Trazabilidad
|
||||
|
||||
Incorporar, editar o retirar un archivo:
|
||||
|
||||
- genera un evento específico en `audit_events`;
|
||||
- incrementa `assets.current_version`;
|
||||
- produce un snapshot B3 con los metadatos vigentes de fotografías y
|
||||
documentos, sin duplicar los binarios dentro de PostgreSQL.
|
||||
|
||||
## Interfaz
|
||||
|
||||
Cada activo incluye una sección de fotografías y documentos con:
|
||||
|
||||
- captura desde la cámara o selección de archivo;
|
||||
- fecha, título y descripción opcionales;
|
||||
- captura GPS explícita con precisión;
|
||||
- previsualización autenticada de fotografías;
|
||||
- descarga protegida;
|
||||
- edición de metadatos y retiro lógico;
|
||||
- cantidad de archivos en el listado maestro.
|
||||
|
||||
## Fuera de B4
|
||||
|
||||
- miniaturas y transformaciones derivadas;
|
||||
- antivirus externo;
|
||||
- importación masiva de archivos;
|
||||
- sincronización Android offline.
|
||||
@@ -0,0 +1,30 @@
|
||||
# Deploy B4
|
||||
|
||||
## Archivo
|
||||
|
||||
```text
|
||||
DH_V2_FASE_B4_SOURCE.zip
|
||||
```
|
||||
|
||||
Subir por FTP a:
|
||||
|
||||
```text
|
||||
/var/www/dhv2.korexlabs.com/
|
||||
```
|
||||
|
||||
## Migración
|
||||
|
||||
```text
|
||||
PhaseB4AssetMedia1786723202000
|
||||
```
|
||||
|
||||
Crea `asset_media`, amplía los tipos del historial, incorpora dos permisos y
|
||||
configura los grants runtime sin borrado físico.
|
||||
|
||||
TypeORM continúa con `synchronize: false`. No se agregan variables al `.env`.
|
||||
El volumen persistente `dhv2_asset_media` es creado por Docker Compose y queda
|
||||
montado únicamente en la API.
|
||||
|
||||
El bloque único de deploy respalda fuentes, base, `.env` y —cuando ya existe—
|
||||
el volumen de archivos; valida el ZIP, construye los tres artefactos, aplica la
|
||||
migración, recrea API y web y ejecuta la aceptación B4.
|
||||
@@ -0,0 +1,64 @@
|
||||
# Fase B5 — Procedencia de datos y consulta temporal
|
||||
|
||||
Versión: `0.12.0`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Completar el Maestro de Activos con dos capacidades previstas desde su diseño:
|
||||
|
||||
- identificar de dónde proviene la información principal de cada activo;
|
||||
- reconstruir cómo se encontraba el maestro en una fecha y hora determinada.
|
||||
|
||||
## Procedencia
|
||||
|
||||
Cada activo registra:
|
||||
|
||||
- origen controlado: carga manual, relevamiento de campo, documentación
|
||||
recibida, importación o sistema;
|
||||
- nombre de la fuente y referencia;
|
||||
- fecha y hora observada;
|
||||
- notas de procedencia;
|
||||
- usuario y fecha de la última actualización;
|
||||
- usuario y fecha de verificación.
|
||||
|
||||
Actualizar la procedencia reinicia cualquier verificación previa. Las fuentes
|
||||
documentales e importaciones requieren identificar la fuente.
|
||||
|
||||
## Permisos
|
||||
|
||||
- `assets.read_provenance`: cinco roles base;
|
||||
- `assets.manage_provenance`: admin, supervisor e inspector;
|
||||
- `assets.verify_provenance`: admin, director y supervisor;
|
||||
- `assets.read_temporal`: cinco roles base.
|
||||
|
||||
## Versionado y auditoría
|
||||
|
||||
La migración incorpora una versión inicial de procedencia a todos los activos
|
||||
existentes. Las actualizaciones y verificaciones posteriores:
|
||||
|
||||
- incrementan `assets.current_version`;
|
||||
- generan un snapshot inmutable completo;
|
||||
- registran actor, origen, request ID y evento de auditoría;
|
||||
- no permiten al usuario runtime modificar ni borrar versiones anteriores.
|
||||
|
||||
## Consulta temporal
|
||||
|
||||
La API selecciona la última versión de cada activo cuya fecha sea menor o igual
|
||||
al instante solicitado. Así reconstruye sólo los activos que ya existían en ese
|
||||
momento y conserva sus códigos, nombres, tipos, jerarquías, estados, atributos,
|
||||
geometrías, archivos y procedencia histórica.
|
||||
|
||||
Rutas:
|
||||
|
||||
- `GET /api/v3/temporal-assets?at=...`: maestro histórico paginado y filtrable;
|
||||
- `GET /api/v3/temporal-assets/:assetId?at=...`: snapshot exacto de un activo.
|
||||
|
||||
Las consultas son de sólo lectura y no modifican el estado actual.
|
||||
|
||||
## Interfaz
|
||||
|
||||
- panel de procedencia dentro de cada activo;
|
||||
- estado pendiente o verificado en el listado maestro;
|
||||
- sección **Consulta temporal** con fecha, hora y filtros;
|
||||
- vigencia desde/hasta de cada snapshot;
|
||||
- visor semántico y snapshot técnico exacto.
|
||||
@@ -0,0 +1,30 @@
|
||||
# Deploy B5
|
||||
|
||||
## Archivo
|
||||
|
||||
```text
|
||||
DH_V2_FASE_B5_SOURCE.zip
|
||||
```
|
||||
|
||||
Subir por FTP a:
|
||||
|
||||
```text
|
||||
/var/www/dhv2.korexlabs.com/
|
||||
```
|
||||
|
||||
## Migración
|
||||
|
||||
```text
|
||||
PhaseB5ProvenanceTemporal1786723203000
|
||||
```
|
||||
|
||||
Agrega nueve campos de procedencia en `assets`, cuatro permisos y tres tipos de
|
||||
cambio histórico. También genera una versión de procedencia inicial para cada
|
||||
activo existente, sin modificar versiones previas.
|
||||
|
||||
TypeORM continúa con `synchronize: false`. No se agregan variables al `.env` ni
|
||||
volúmenes nuevos.
|
||||
|
||||
El bloque único de deploy respalda fuentes, base, `.env` y el volumen de
|
||||
archivos, valida el ZIP, construye los tres artefactos, aplica la migración,
|
||||
recrea API y web y ejecuta la aceptación B5.
|
||||
@@ -0,0 +1,67 @@
|
||||
# Fase C1 — Planificación de relevamientos
|
||||
|
||||
Versión: `0.13.0`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Iniciar el ciclo operativo de relevamiento planificando trabajo sobre el único
|
||||
Maestro de Activos. La fase no crea inventarios ni copias paralelas.
|
||||
|
||||
## Campañas
|
||||
|
||||
Cada campaña define código, nombre, descripción, fechas previstas, coordinación
|
||||
y un alcance opcional. El alcance referencia cualquier activo del árbol
|
||||
configurable y comprende ese activo y sus descendientes, sin niveles fijos.
|
||||
|
||||
Estados controlados:
|
||||
|
||||
- borrador;
|
||||
- planificada;
|
||||
- en curso;
|
||||
- completada;
|
||||
- cancelada.
|
||||
|
||||
Una campaña sólo puede iniciarse si contiene objetivos. Sólo puede completarse
|
||||
cuando todos están completados u omitidos. Completadas y canceladas quedan
|
||||
cerradas.
|
||||
|
||||
## Objetivos
|
||||
|
||||
Cada objetivo referencia exactamente un activo existente y registra responsable,
|
||||
vencimiento, instrucciones y avance. La restricción campaña-activo impide
|
||||
duplicados. Si existe alcance, la API verifica la jerarquía antes de agregar el
|
||||
activo.
|
||||
|
||||
Los inspectores sólo pueden avanzar objetivos que tengan asignados. La base no
|
||||
concede `DELETE` al usuario runtime: la omisión es un estado trazable, no un
|
||||
borrado físico.
|
||||
|
||||
## Permisos
|
||||
|
||||
- `surveys.read`: admin, director, supervisor, inspector y auditor;
|
||||
- `surveys.manage`: admin y supervisor;
|
||||
- `surveys.assign`: admin y supervisor;
|
||||
- `surveys.execute`: admin, supervisor e inspector.
|
||||
|
||||
## Auditoría
|
||||
|
||||
Se registran creación, actualización y cambio de estado de campañas, además de
|
||||
alta, actualización, asignación y cambio de avance de objetivos.
|
||||
|
||||
## Interfaz y API
|
||||
|
||||
La sección **Relevamientos** incluye listado, filtros, alta, edición, flujo de
|
||||
estados, incorporación de activos existentes, asignaciones y avance.
|
||||
|
||||
Rutas principales:
|
||||
|
||||
- `GET|POST /api/v3/survey-campaigns`;
|
||||
- `GET|PATCH /api/v3/survey-campaigns/:id`;
|
||||
- `PUT /api/v3/survey-campaigns/:id/status`;
|
||||
- `POST /api/v3/survey-campaigns/:id/targets`;
|
||||
- `PATCH /api/v3/survey-campaign-targets/:id`;
|
||||
- `PUT /api/v3/survey-campaign-targets/:id/assignment`;
|
||||
- `PUT /api/v3/survey-campaign-targets/:id/status`.
|
||||
|
||||
La captura de datos de campo y la consolidación de relevamientos continúan en
|
||||
las fases siguientes.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Deploy C1
|
||||
|
||||
## Archivo
|
||||
|
||||
```text
|
||||
DH_V2_FASE_C1_SOURCE.zip
|
||||
```
|
||||
|
||||
Subir por FTP a:
|
||||
|
||||
```text
|
||||
/var/www/dhv2.korexlabs.com/
|
||||
```
|
||||
|
||||
## Migración
|
||||
|
||||
```text
|
||||
PhaseC1SurveyPlanning1786809600000
|
||||
```
|
||||
|
||||
Crea `survey_campaigns` y `survey_campaign_targets`, cuatro permisos, índices,
|
||||
restricciones y privilegios runtime sin borrado físico.
|
||||
|
||||
TypeORM continúa con `synchronize: false`. C1 no agrega variables al `.env` ni
|
||||
volúmenes nuevos.
|
||||
|
||||
El bloque único de deploy respalda fuentes, base, `.env` y archivos, valida el
|
||||
ZIP, construye API, migraciones y web, aplica la migración, recrea servicios y
|
||||
ejecuta `scripts/phase-c1-acceptance.sh`.
|
||||
@@ -0,0 +1,65 @@
|
||||
# Fase C2 — Ejecución y validación de relevamientos
|
||||
|
||||
Versión: `0.14.0`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Ejecutar en campo los objetivos planificados en C1 y consolidar su resultado en
|
||||
el único Maestro de Activos. C2 no crea una segunda ficha ni un inventario
|
||||
paralelo: el informe referencia al objetivo y al activo originales.
|
||||
|
||||
## Flujo operativo
|
||||
|
||||
1. El responsable inicia un objetivo asignado.
|
||||
2. Guarda un borrador con resultado, fecha observada, GPS, precisión, notas y
|
||||
fotografías protegidas.
|
||||
3. Si detecta diferencias, actualiza el activo original desde el Maestro.
|
||||
4. Envía el informe. C2 actualiza la procedencia del activo, crea una versión de
|
||||
activo y congela una versión inmutable del informe con los hashes de evidencia.
|
||||
5. Un revisor aprueba o rechaza. La aprobación sólo continúa si el activo conserva
|
||||
exactamente la versión enviada.
|
||||
6. Al aprobar, el activo queda validado y el objetivo completado. Al rechazar,
|
||||
vuelve a ejecución con el motivo registrado.
|
||||
|
||||
Los resultados admitidos son activo confirmado, cambios registrados y no
|
||||
localizado. GPS con precisión y al menos una fotografía son obligatorios para el
|
||||
envío. Cambios registrados y no localizado requieren una explicación.
|
||||
|
||||
## Inmutabilidad y Maestro único
|
||||
|
||||
- `survey_target_reports` conserva el estado actual del informe;
|
||||
- `survey_target_report_media` vincula evidencia existente del activo;
|
||||
- `survey_target_report_versions` conserva cada envío y decisión como JSON
|
||||
inmutable, incluyendo identificación, versión del activo y hash SHA-256 de cada
|
||||
evidencia;
|
||||
- las tres tablas revocan `DELETE` al usuario runtime;
|
||||
- las versiones congeladas revocan también `UPDATE`;
|
||||
- el envío actualiza procedencia y estado del activo original mediante el historial
|
||||
ya existente del Maestro.
|
||||
|
||||
Un informe enviado no puede editarse. Las correcciones requieren rechazo,
|
||||
nuevo borrador y un nuevo envío; las versiones anteriores permanecen disponibles.
|
||||
|
||||
## Permisos
|
||||
|
||||
- `surveys.read_reports`: admin, director, supervisor, inspector y auditor;
|
||||
- `surveys.capture`: admin, supervisor e inspector;
|
||||
- `surveys.review`: admin, director y supervisor.
|
||||
|
||||
Además se conservan los permisos de C1 para planificación y avance y los de B4
|
||||
para cargar fotografías protegidas.
|
||||
|
||||
## API e interfaz
|
||||
|
||||
Rutas nuevas:
|
||||
|
||||
- `GET|PUT /api/v3/survey-campaign-targets/:targetId/report`;
|
||||
- `POST /api/v3/survey-campaign-targets/:targetId/report/submit`;
|
||||
- `POST /api/v3/survey-campaign-targets/:targetId/report/review`.
|
||||
|
||||
La pantalla de campaña abre cada objetivo en una vista de ejecución con captura
|
||||
GPS, carga y selección de evidencia, envío, control de calidad y consulta de todas
|
||||
las versiones inmutables.
|
||||
|
||||
Las inspecciones, visitas, actas y hallazgos continúan siendo un dominio separado
|
||||
para una fase posterior.
|
||||
@@ -0,0 +1,30 @@
|
||||
# Deploy C2
|
||||
|
||||
## Archivo
|
||||
|
||||
```text
|
||||
DH_V2_FASE_C2_SOURCE.zip
|
||||
```
|
||||
|
||||
Subir por FTP a:
|
||||
|
||||
```text
|
||||
/var/www/dhv2.korexlabs.com/
|
||||
```
|
||||
|
||||
## Migración
|
||||
|
||||
```text
|
||||
PhaseC2SurveyExecution1786896000000
|
||||
```
|
||||
|
||||
Crea informes, vínculos de evidencia y versiones inmutables, agrega el estado de
|
||||
objetivo `SUBMITTED`, tres permisos específicos, índices, restricciones y
|
||||
privilegios runtime sin borrado físico.
|
||||
|
||||
TypeORM continúa con `synchronize: false`. C2 no agrega variables al `.env` ni
|
||||
volúmenes nuevos.
|
||||
|
||||
El bloque único de deploy respalda fuentes, base, `.env` y archivos, valida el
|
||||
ZIP, construye API, migraciones y web, aplica la migración, recrea servicios y
|
||||
ejecuta `scripts/phase-c2-acceptance.sh`.
|
||||
@@ -0,0 +1,69 @@
|
||||
# Fase D1 — Planificación y apertura de visitas
|
||||
|
||||
Versión: `0.15.0`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Iniciar el dominio de inspecciones con la regla funcional acordada: una
|
||||
inspección representa una visita. D1 planifica y abre esa visita; no incorpora
|
||||
todavía actas, hallazgos ni el informe consolidado.
|
||||
|
||||
## Modelo
|
||||
|
||||
`inspection_visits` conserva identidad, título, objetivo, estado, fechas,
|
||||
ubicación o alcance principal, responsable, instrucciones y trazabilidad.
|
||||
|
||||
La visita utiliza el Maestro de Activos de dos maneras:
|
||||
|
||||
- `scope_asset_id` referencia cualquier activo que represente su ubicación o
|
||||
alcance principal;
|
||||
- `inspection_visit_assets` vincula los activos concretos a inspeccionar.
|
||||
|
||||
No se copian nombres, ubicaciones ni atributos. Todos los vínculos apuntan a los
|
||||
activos originales y respetan la jerarquía dinámica: si se define un alcance,
|
||||
los activos seleccionados deben pertenecer a esa rama.
|
||||
|
||||
`inspection_visit_members` vincula usuarios activos con permiso de ejecución.
|
||||
Un integrante se designa como inspector responsable y debe pertenecer al equipo.
|
||||
|
||||
## Flujo controlado
|
||||
|
||||
- `DRAFT`: admite cambios generales, activos y equipo;
|
||||
- `PLANNED`: el plan está confirmado, pero aún puede volver a borrador;
|
||||
- `IN_PROGRESS`: la visita fue iniciada y su planificación queda congelada;
|
||||
- `CANCELLED`: estado terminal con motivo obligatorio;
|
||||
- `CLOSED`: reservado para la futura operación de cierre e informe consolidado.
|
||||
|
||||
Antes de confirmar o iniciar se exige ubicación, fecha de inicio, al menos un
|
||||
activo, un equipo válido y un responsable incluido. Sólo un integrante asignado
|
||||
o un usuario con gestión puede iniciar la visita.
|
||||
|
||||
## Permisos
|
||||
|
||||
- `inspections.read`: admin, director, supervisor, inspector y auditor;
|
||||
- `inspections.manage`: admin y supervisor;
|
||||
- `inspections.assign`: admin y supervisor;
|
||||
- `inspections.execute`: admin, supervisor e inspector.
|
||||
|
||||
Las tres tablas conceden al usuario runtime lectura, inserción y actualización,
|
||||
pero revocan borrado físico.
|
||||
|
||||
## API e interfaz
|
||||
|
||||
Rutas principales:
|
||||
|
||||
- `GET|POST /api/v3/inspection-visits`;
|
||||
- `GET|PATCH /api/v3/inspection-visits/:id`;
|
||||
- `PUT /api/v3/inspection-visits/:id/assets`;
|
||||
- `PUT /api/v3/inspection-visits/:id/team`;
|
||||
- `PUT /api/v3/inspection-visits/:id/status`;
|
||||
- `POST /api/v3/inspection-visits/:id/start`.
|
||||
|
||||
La sección **Inspecciones** reemplaza el placeholder por un listado y un editor
|
||||
completo de visita.
|
||||
|
||||
## Continuidad
|
||||
|
||||
La próxima subfase agregará el acta única de cada visita. Después se
|
||||
incorporarán hallazgos y evidencias, y finalmente firmas, rectificativas y el
|
||||
informe técnico que incorporará el acta y sus hallazgos.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Deploy D1
|
||||
|
||||
## Archivo
|
||||
|
||||
```text
|
||||
DH_V2_FASE_D1_SOURCE.zip
|
||||
```
|
||||
|
||||
Subir por FTP a:
|
||||
|
||||
```text
|
||||
/var/www/dhv2.korexlabs.com/
|
||||
```
|
||||
|
||||
## Migración
|
||||
|
||||
```text
|
||||
PhaseD1InspectionVisits1786982400000
|
||||
```
|
||||
|
||||
Crea visitas, vínculos a activos y equipos, cuatro permisos, índices,
|
||||
restricciones y privilegios runtime sin borrado físico.
|
||||
|
||||
TypeORM continúa con `synchronize: false`. D1 no agrega variables al `.env` ni
|
||||
volúmenes nuevos.
|
||||
|
||||
El bloque único de deploy respalda fuentes, base, `.env` y archivos, valida el
|
||||
ZIP, construye API, migraciones y web, aplica la migración, recrea servicios y
|
||||
ejecuta `scripts/phase-d1-acceptance.sh`.
|
||||
@@ -0,0 +1,64 @@
|
||||
# Fase D2 — Base de actas y versiones
|
||||
|
||||
Versión: `0.16.0`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Crear la base documental de las actas. D2.1 corrige posteriormente la
|
||||
cardinalidad para que cada visita contenga una única acta. El acta conserva
|
||||
identidad oficial, activos vinculados y todas sus versiones, sin duplicar
|
||||
información del Maestro de Activos.
|
||||
|
||||
## Numeración oficial
|
||||
|
||||
Al crear un acta el servidor asigna `ACTA-AAAA-NNNNNN`. El contador es global
|
||||
para todas las actas del año y se incrementa dentro de la misma transacción que
|
||||
crea el documento. Los números cancelados no se reutilizan.
|
||||
|
||||
`document_annual_sequences` reserva también la serie `REPORT` para el futuro
|
||||
informe consolidado, pero D2 sólo emite números de tipo `ACT`.
|
||||
|
||||
## Modelo e integridad
|
||||
|
||||
- `inspection_acts`: identidad, visita, número, estado y contenido actual;
|
||||
- `inspection_act_assets`: referencias a activos incluidos en la visita;
|
||||
- `inspection_act_versions`: snapshots inmutables de cada guardado;
|
||||
- `document_annual_sequences`: contadores transaccionales por tipo y año.
|
||||
|
||||
Los snapshots congelan el contenido del acta, el contexto de la visita y la
|
||||
identidad y versión actual de cada activo seleccionado. La API runtime no tiene
|
||||
permisos para borrar estas tablas ni para modificar versiones históricas.
|
||||
|
||||
## Flujo D2
|
||||
|
||||
- la visita debe estar `IN_PROGRESS`;
|
||||
- un integrante asignado, o gestión, puede crear y editar el acta;
|
||||
- cada acta nace `DRAFT` y recibe número oficial inmediatamente;
|
||||
- sólo un borrador puede editarse;
|
||||
- admin o supervisor pueden cancelar un borrador con motivo obligatorio;
|
||||
- la cancelación agrega una versión y conserva el número y todo el historial.
|
||||
|
||||
Los estados `READY`, `CLOSED` y `RECTIFIED` quedan reservados. D2 no implementa
|
||||
todavía cierre, firma, PDF, hash, token público ni rectificación.
|
||||
|
||||
## Permisos y rutas
|
||||
|
||||
- `inspection_acts.read`: consultar actas y versiones;
|
||||
- `inspection_acts.create`: crear actas en visitas asignadas;
|
||||
- `inspection_acts.update`: actualizar borradores;
|
||||
- `inspection_acts.cancel`: cancelar borradores.
|
||||
|
||||
Rutas:
|
||||
|
||||
- `GET|POST /api/v3/inspection-visits/:visitId/acts`;
|
||||
- `GET|PATCH /api/v3/inspection-acts/:id`;
|
||||
- `POST /api/v3/inspection-acts/:id/cancel`.
|
||||
|
||||
La pantalla de visita contiene su acta. El editor permite elegir los activos de
|
||||
esa visita y consultar las versiones inmutables.
|
||||
|
||||
## Continuidad
|
||||
|
||||
D2.1 garantiza un acta por visita. La siguiente subfase incorporará múltiples
|
||||
hallazgos dentro de esa acta. Luego se agregarán cierre y firma, documentos
|
||||
verificables, rectificativas e informe técnico de la visita.
|
||||
@@ -0,0 +1,40 @@
|
||||
# Fase D2.1 — Un acta por visita
|
||||
|
||||
Versión: `0.16.1`
|
||||
|
||||
## Corrección conceptual
|
||||
|
||||
El dominio queda definido así:
|
||||
|
||||
1. una inspección es una visita;
|
||||
2. cada visita genera una única acta;
|
||||
3. el acta contiene múltiples hallazgos;
|
||||
4. cada hallazgo puede vincular activos, normativa y evidencias;
|
||||
5. al finalizar la visita, el acta se cierra, se firma y se distribuye;
|
||||
6. después se genera un informe técnico que incorpora el acta y todos sus
|
||||
hallazgos.
|
||||
|
||||
El Informe Técnico Nº 124/2026 y su Acta Nº 105/2026 se usaron como referencia
|
||||
funcional. La planilla de hallazgos se interpreta como catálogo configurable de
|
||||
hallazgos por tipo de equipo y normativa, no como texto fijo de la interfaz.
|
||||
|
||||
## Alcance de D2.1
|
||||
|
||||
- agrega una restricción única sobre `inspection_acts.visit_id`;
|
||||
- bloquea en la API un segundo intento de creación con código
|
||||
`INSPECTION_VISIT_ACT_ALREADY_EXISTS`;
|
||||
- adapta la interfaz y el footer al concepto de acta única;
|
||||
- mantiene numeración anual global, versiones, activos y auditoría de D2;
|
||||
- no elimina ni transforma actas existentes.
|
||||
|
||||
Antes de crear la restricción, la migración verifica que no existan visitas con
|
||||
más de un acta. Si encuentra alguna, falla de forma segura y no modifica los
|
||||
datos para que la situación se resuelva explícitamente.
|
||||
|
||||
## Próximas fases
|
||||
|
||||
D3 incorporará múltiples hallazgos dentro del acta y el catálogo configurable
|
||||
derivado de la planilla entregada. Más adelante se implementarán cierre,
|
||||
firmas de inspectores y responsable de empresa, PDF verificable, envío al
|
||||
responsable y al correo interno configurable de Hidrocarburos, y el informe
|
||||
técnico con numeración anual propia.
|
||||
@@ -0,0 +1,19 @@
|
||||
# Deploy D2.1
|
||||
|
||||
## Archivo
|
||||
|
||||
`DH_V2_FASE_D2_1_SOURCE.zip`
|
||||
|
||||
Subir por FTP a `/var/www/dhv2.korexlabs.com/`.
|
||||
|
||||
## Migración
|
||||
|
||||
`PhaseD21SingleActPerVisit1787072400000`
|
||||
|
||||
La migración agrega la unicidad de `inspection_acts.visit_id`. No borra ni
|
||||
combina datos. Si detecta más de un acta en alguna visita, interrumpe el deploy
|
||||
antes de crear la restricción.
|
||||
|
||||
D2.1 no agrega variables al `.env` ni volúmenes. El bloque único de despliegue
|
||||
respalda fuentes, base, `.env` y archivos, valida el ZIP, construye servicios,
|
||||
aplica la migración y ejecuta `scripts/phase-d2-1-acceptance.sh`.
|
||||
@@ -0,0 +1,30 @@
|
||||
# Deploy D2
|
||||
|
||||
## Archivo
|
||||
|
||||
```text
|
||||
DH_V2_FASE_D2_SOURCE.zip
|
||||
```
|
||||
|
||||
Subir por FTP a:
|
||||
|
||||
```text
|
||||
/var/www/dhv2.korexlabs.com/
|
||||
```
|
||||
|
||||
## Migración
|
||||
|
||||
```text
|
||||
PhaseD2InspectionActs1787068800000
|
||||
```
|
||||
|
||||
Crea el contador anual, actas, referencias a activos, versiones inmutables,
|
||||
cuatro permisos, restricciones, índices y privilegios runtime mínimos.
|
||||
|
||||
TypeORM continúa con `synchronize: false`. D2 no agrega variables al `.env` ni
|
||||
volúmenes nuevos. El ZIP también contiene D1; si D1 aún estuviera pendiente, el
|
||||
comando de migración aplica ambas en orden.
|
||||
|
||||
El bloque único de deploy respalda fuentes, base, `.env` y archivos, valida el
|
||||
ZIP, construye API, migraciones y web, aplica migraciones, recrea servicios y
|
||||
ejecuta `scripts/phase-d2-acceptance.sh`.
|
||||
@@ -0,0 +1,78 @@
|
||||
# Fase D3 — Hallazgos y seguimiento
|
||||
|
||||
Versión: `0.17.0`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Permitir que el acta única de una visita contenga múltiples hallazgos y que
|
||||
cada hallazgo permanezca abierto después de recibir la respuesta de la empresa,
|
||||
hasta que el organismo verifique efectivamente la corrección.
|
||||
|
||||
## Catálogo importado
|
||||
|
||||
La fuente es `Lista de hallazgos (1).xlsx`, con SHA-256
|
||||
`a49e5d8627b3d43490b43b90d4a7efde6fd88f76cdc1c29fbb8906012e13587d`.
|
||||
|
||||
La importación contiene:
|
||||
|
||||
- 19 categorías;
|
||||
- 170 modelos de hallazgo;
|
||||
- descripción, normativa y glosario cuando la planilla los informa;
|
||||
- códigos estables por categoría y número de origen;
|
||||
- revisión e indicador de actividad para administración futura.
|
||||
|
||||
La celda correspondiente a `BOMBAS-003` contenía solamente el número `4` en la
|
||||
columna del título. Se normalizó como `PUESTA A TIERRA` por la normativa de la
|
||||
misma fila y su repetición exacta en la categoría Defensa contra incendios. La
|
||||
corrección queda registrada en `import_note`.
|
||||
|
||||
## Ciclo operativo
|
||||
|
||||
1. El inspector selecciona un modelo del catálogo o crea uno personalizado.
|
||||
2. Vincula el hallazgo con un activo incluido en el acta.
|
||||
3. Registra la descripción concreta y, si corresponde, el plazo exigido.
|
||||
4. El hallazgo nace con estado `OPEN`.
|
||||
5. Después de notificar a la empresa, se registra su respuesta y fecha.
|
||||
6. Se registra por separado la fecha en que la empresa promete corregir.
|
||||
7. El organismo define la fecha del próximo control.
|
||||
8. La respuesta no cierra el hallazgo.
|
||||
9. Una fase posterior permitirá cerrarlo únicamente después de verificar la
|
||||
corrección en campo o mediante el procedimiento autorizado.
|
||||
|
||||
## Fechas separadas
|
||||
|
||||
- `correction_due_on`: plazo exigido por el organismo;
|
||||
- `company_response_received_on`: recepción de la respuesta empresarial;
|
||||
- `company_committed_correction_on`: compromiso declarado por la empresa;
|
||||
- `next_control_on`: fecha programada por el organismo para volver a controlar.
|
||||
|
||||
Estas fechas no se reemplazan entre sí. El dashboard usa `next_control_on` para
|
||||
detectar controles vencidos y los próximos 30 días.
|
||||
|
||||
## Integridad y trazabilidad
|
||||
|
||||
- todo hallazgo referencia un activo incluido en el acta;
|
||||
- el contenido del catálogo se copia al hallazgo como snapshot;
|
||||
- cada alta, edición y seguimiento genera una versión inmutable;
|
||||
- la API runtime no puede borrar hallazgos ni versiones;
|
||||
- los cambios generan auditoría;
|
||||
- editar el contenido requiere acta en borrador, visita en curso y asignación;
|
||||
- registrar seguimiento requiere permiso específico y puede continuar después
|
||||
del cierre documental del acta;
|
||||
- sólo los estados futuros de verificación podrán pasar un hallazgo a cerrado.
|
||||
|
||||
## Dashboard
|
||||
|
||||
El panel muestra:
|
||||
|
||||
- hallazgos abiertos;
|
||||
- hallazgos todavía sin respuesta empresarial;
|
||||
- controles cuya fecha ya venció;
|
||||
- controles programados en los próximos 30 días;
|
||||
- agenda de los ocho próximos controles con acceso al acta correspondiente.
|
||||
|
||||
## Límites de D3
|
||||
|
||||
D3 no cierra hallazgos, actas ni visitas. Tampoco adjunta todavía el PDF de la
|
||||
respuesta empresarial. D4 agregará fotografías, GPS y documentos protegidos,
|
||||
incluido ese PDF. D5 implementará responsables, cierre y firmas.
|
||||
@@ -0,0 +1,19 @@
|
||||
# Deploy D3
|
||||
|
||||
## Archivo
|
||||
|
||||
`DH_V2_FASE_D3_SOURCE.zip`
|
||||
|
||||
Subir por FTP a `/var/www/dhv2.korexlabs.com/`.
|
||||
|
||||
## Migración
|
||||
|
||||
`PhaseD3InspectionFindings1787155200000`
|
||||
|
||||
Crea categorías, catálogo, hallazgos y versiones inmutables; importa 19
|
||||
categorías y 170 modelos; agrega seis permisos, asignaciones de roles,
|
||||
restricciones, índices y privilegios runtime mínimos.
|
||||
|
||||
D3 no agrega variables al `.env` ni volúmenes. El bloque único de despliegue
|
||||
respalda fuentes, base, `.env` y archivos, valida el ZIP, construye los tres
|
||||
servicios, aplica la migración y ejecuta `scripts/phase-d3-acceptance.sh`.
|
||||
@@ -0,0 +1,62 @@
|
||||
# Fase D4 — Evidencias y comunicaciones
|
||||
|
||||
Versión: `0.18.0`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Incorporar fotografías, documentos y comunicaciones a cada hallazgo sin
|
||||
alterar el modelo definitivo:
|
||||
|
||||
`visita → acta única → múltiples hallazgos → evidencias → firma y envío → informe`.
|
||||
|
||||
## Evidencias
|
||||
|
||||
- múltiples fotografías JPG, PNG o WebP por hallazgo;
|
||||
- documentos PDF de campo, respuesta empresarial u otras comunicaciones;
|
||||
- archivo original, autor, fecha, dispositivo, origen y SHA-256;
|
||||
- GPS WGS84 y precisión opcionales;
|
||||
- almacenamiento autenticado dentro del volumen persistente existente;
|
||||
- vista y descarga sin exponer rutas físicas ni URL públicas.
|
||||
|
||||
Las evidencias son inmutables. La API runtime solamente puede leerlas e
|
||||
insertarlas: no puede modificarlas ni borrarlas.
|
||||
|
||||
## Comunicaciones
|
||||
|
||||
Cada hallazgo abierto admite un historial cronológico con:
|
||||
|
||||
- sentido recibido, enviado o interno;
|
||||
- medio email, presencial, teléfono, nota formal, sistema u otro;
|
||||
- tipo respuesta empresarial, notificación, seguimiento u otro;
|
||||
- fecha y hora, asunto, detalle y contacto;
|
||||
- uno o más documentos vinculados.
|
||||
|
||||
Una respuesta empresarial debe ser recibida. Su PDF sólo se acepta como
|
||||
documento válido y vinculado a esa comunicación. Registrar la respuesta o su
|
||||
PDF no cierra el hallazgo.
|
||||
|
||||
## Reglas de campo
|
||||
|
||||
- fotografías y documentos de observación sólo durante la visita en curso,
|
||||
con acta en borrador y usuario asignado o con gestión general;
|
||||
- comunicaciones y documentos posteriores pueden incorporarse mientras el
|
||||
hallazgo permanezca abierto;
|
||||
- auditor conserva acceso de sólo lectura;
|
||||
- cada alta genera un evento de auditoría con el vínculo acta/visita/hallazgo.
|
||||
|
||||
## Seguridad
|
||||
|
||||
- validación por bytes mágicos, no por extensión declarada;
|
||||
- límite de 15 MB;
|
||||
- nombres físicos aleatorios y permisos `0600`;
|
||||
- coordenadas completas y precisión controlada;
|
||||
- vínculo compuesto que impide adjuntar un documento a una comunicación de
|
||||
otro hallazgo;
|
||||
- respuestas empresariales restringidas a PDF;
|
||||
- `Cache-Control: private, no-store`, `nosniff` y sandbox para el contenido.
|
||||
|
||||
## Límites de D4
|
||||
|
||||
D4 no cierra el acta ni genera firmas. D5 incorporará responsable empresarial,
|
||||
firmas manuscritas, negativa o ausencia de firma y congelamiento coordinado de
|
||||
la visita, el acta, los hallazgos y sus evidencias.
|
||||
@@ -0,0 +1,19 @@
|
||||
# Deploy D4
|
||||
|
||||
## Archivo
|
||||
|
||||
`DH_V2_FASE_D4_SOURCE.zip`
|
||||
|
||||
Subir por FTP a `/var/www/dhv2.korexlabs.com/`.
|
||||
|
||||
## Migración
|
||||
|
||||
`PhaseD4FindingEvidenceCommunications1787241600000`
|
||||
|
||||
Crea dos tablas inmutables, cuatro permisos, asignaciones de roles,
|
||||
restricciones, índices y privilegios runtime mínimos. Reutiliza el volumen
|
||||
`dhv2_asset_media`; no agrega volúmenes ni exige cambios manuales en `.env`.
|
||||
|
||||
El bloque único entregado junto con el ZIP valida el checksum, realiza backup,
|
||||
construye API/migraciones/web, aplica la migración, recrea servicios y ejecuta
|
||||
`scripts/phase-d4-acceptance.sh`.
|
||||
@@ -0,0 +1,73 @@
|
||||
# Fase D5 — Cierre y firmas
|
||||
|
||||
Versión: `0.19.0`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Cerrar la inspección conservando una constancia exacta e inmutable de lo
|
||||
observado. El cierre del acta no cierra los hallazgos: cada hallazgo continúa
|
||||
abierto hasta su verificación posterior.
|
||||
|
||||
## Flujo
|
||||
|
||||
1. El acta sigue en `DRAFT` durante la visita.
|
||||
2. Se identifica al responsable de la empresa o se documenta su ausencia.
|
||||
3. `Preparar para firmas` cambia el acta a `READY`, congela el contenido y
|
||||
genera una huella SHA-256 canónica.
|
||||
4. Firma al menos un inspector asignado.
|
||||
5. La empresa firma la recepción o se registra una negativa/ausencia motivada.
|
||||
6. `Cerrar y sellar` cierra atómicamente el acta y la visita.
|
||||
7. Los hallazgos permanecen `OPEN`, admitiendo respuestas, PDFs, comunicaciones
|
||||
y fecha del próximo control.
|
||||
|
||||
Antes de la primera firma, un acta `READY` puede volver a `DRAFT`. Después de
|
||||
registrar una firma o constancia ya no puede reabrirse ni modificarse.
|
||||
|
||||
## Constancia manuscrita
|
||||
|
||||
La captura en pantalla se denomina firma manuscrita o constancia de recepción.
|
||||
No se presenta como firma digital certificada. Cada registro conserva:
|
||||
|
||||
- identidad y rol del firmante;
|
||||
- declaración aceptada y su versión;
|
||||
- fecha del dispositivo y fecha del servidor;
|
||||
- origen web/Android, dispositivo y GPS opcional;
|
||||
- hash de la imagen y hash del payload de firma;
|
||||
- vínculo con la huella exacta del contenido preparado.
|
||||
|
||||
Las firmas sólo admiten `SELECT` e `INSERT` para el usuario runtime de la API.
|
||||
No pueden actualizarse ni borrarse.
|
||||
|
||||
## Congelado canónico
|
||||
|
||||
El snapshot preparado usa el esquema `DH-ACT-CLOSURE-V1` e incluye:
|
||||
|
||||
- acta y visita;
|
||||
- responsable empresarial y equipo inspector;
|
||||
- activos, atributos y geometrías vigentes;
|
||||
- hallazgos, texto constatado, catálogo y base legal copiada;
|
||||
- evidencias con metadatos y SHA-256;
|
||||
- comunicaciones existentes al momento de preparar.
|
||||
|
||||
Los objetos se serializan con claves ordenadas y fechas ISO-8601 antes de
|
||||
calcular SHA-256. El cierre final agrega las firmas y las fechas de cierre, y
|
||||
genera una segunda huella almacenada en el acta.
|
||||
|
||||
## Persistencia y permisos
|
||||
|
||||
La migración `PhaseD5ActClosingSignatures1787328000000` crea:
|
||||
|
||||
- `inspection_act_responsibles`;
|
||||
- `inspection_act_closures`;
|
||||
- `inspection_act_signatures`;
|
||||
- cuatro permisos `inspection_closure.*`;
|
||||
- restricciones, índices y triggers de inmutabilidad.
|
||||
|
||||
Las imágenes se guardan bajo
|
||||
`/app/storage/asset-media/inspection-signatures`, dentro del volumen existente
|
||||
`dhv2_asset_media`. No hay variables obligatorias nuevas.
|
||||
|
||||
## Fuera de alcance
|
||||
|
||||
El PDF oficial, QR/token de verificación y envío por correo corresponden a D6.
|
||||
El informe técnico y su aprobación corresponden a D7.
|
||||
@@ -0,0 +1,46 @@
|
||||
# Fase D5.1 — Operación exclusiva desde APK
|
||||
|
||||
Versión: `0.19.1`
|
||||
|
||||
## Regla funcional
|
||||
|
||||
La visita se planifica en el dashboard, pero su ejecución documental pertenece
|
||||
al inspector en campo. Sólo la APK puede iniciar una visita, crear o modificar
|
||||
el acta única, registrar hallazgos y evidencias de observación, identificar al
|
||||
responsable, capturar firmas y cerrar el acta y la visita.
|
||||
|
||||
No alcanza con ocultar botones. Cada servicio operativo exige simultáneamente:
|
||||
|
||||
- transporte bearer, utilizado por la aplicación móvil;
|
||||
- rol `inspector`;
|
||||
- permiso específico y asignación a la visita cuando corresponda.
|
||||
|
||||
Las sesiones web usan cookie y reciben `403 INSPECTION_MOBILE_APP_REQUIRED` si
|
||||
intentan invocar una operación de campo directamente.
|
||||
|
||||
## Dashboard
|
||||
|
||||
El dashboard conserva:
|
||||
|
||||
- Maestro de Activos y tipos configurables;
|
||||
- consulta del catálogo de hallazgos; su administración completa se incorpora
|
||||
en D5.2;
|
||||
- planificación de visita, selección de activos y asignación de inspectores;
|
||||
- consulta de acta, hallazgos, evidencias, firmas e informe sincronizados;
|
||||
- respuesta de la empresa, comunicación/PDF y fecha del próximo control;
|
||||
- auditoría y administración de seguridad.
|
||||
|
||||
La respuesta empresarial no altera el acta cerrada ni cierra el hallazgo.
|
||||
|
||||
## Base de datos
|
||||
|
||||
La migración `PhaseD51MobileInspectionPolicy1787331600000` no crea tablas.
|
||||
Retira de roles no inspectores nueve permisos operativos y garantiza esos nueve
|
||||
permisos al rol `inspector`. Los permisos de lectura, catálogos, planificación y
|
||||
seguimiento posterior no cambian.
|
||||
|
||||
## Alcance técnico
|
||||
|
||||
Esta entrega fija el contrato y protege la API que consumirá la APK. El código
|
||||
fuente Android no forma parte de este repositorio actual (`api-v3` + `web-v2`);
|
||||
su cliente debe usar estos endpoints con bearer respetando la misma política.
|
||||
@@ -0,0 +1,18 @@
|
||||
# Deploy D5.1
|
||||
|
||||
## Archivo
|
||||
|
||||
`DH_V2_FASE_D5_1_SOURCE.zip`
|
||||
|
||||
Subir por FTP a `/var/www/dhv2.korexlabs.com/`.
|
||||
|
||||
## Migración
|
||||
|
||||
`PhaseD51MobileInspectionPolicy1787331600000`
|
||||
|
||||
Es una migración aditiva de permisos. No modifica `.env`, no agrega tablas ni
|
||||
volúmenes y no reescribe las migraciones D1–D5 ya instaladas.
|
||||
|
||||
El bloque único entregado junto con el ZIP valida el checksum, hace backup de
|
||||
código/base/.env/archivos protegidos, extrae, compila, migra, recrea API/web y
|
||||
ejecuta `scripts/phase-d5-1-acceptance.sh`.
|
||||
@@ -0,0 +1,42 @@
|
||||
# Fase D5.2 — Catálogo administrable de hallazgos
|
||||
|
||||
Versión: `0.19.2`
|
||||
|
||||
## Objetivo
|
||||
|
||||
El dashboard permite administrar las categorías y los tipos de hallazgo que
|
||||
consume la APK durante una inspección. Esta configuración no habilita crear
|
||||
visitas operativas, actas, hallazgos ni informes desde la web.
|
||||
|
||||
## Alcance funcional
|
||||
|
||||
- listado completo de categorías y tipos activos e inactivos;
|
||||
- alta y edición de categorías, con orden y estado;
|
||||
- alta y edición de tipos, con número, título, fundamento legal, glosario y
|
||||
nota de origen;
|
||||
- búsqueda y conteo de uso en hallazgos reales;
|
||||
- desactivación sin borrado físico;
|
||||
- permisos `finding_catalog.manage` para admin y supervisor.
|
||||
|
||||
Los inspectores siguen siendo los únicos que pueden registrar hallazgos,
|
||||
crear el acta y solicitar el informe desde la APK. El dashboard configura el
|
||||
catálogo y consulta o gestiona el seguimiento posterior.
|
||||
|
||||
## Integridad histórica
|
||||
|
||||
Cada tipo comienza en revisión 1. Una edición incrementa la revisión y crea un
|
||||
snapshot en `finding_catalog_item_versions`. La tabla es append-only para el
|
||||
usuario de runtime: puede leer e insertar, pero no actualizar ni borrar.
|
||||
|
||||
Los hallazgos ya existentes conservan el título, fundamento, glosario y
|
||||
revisión que fueron copiados al momento de la inspección. Cambiar el catálogo
|
||||
no altera un acta cerrada ni un informe histórico.
|
||||
|
||||
## Auditoría
|
||||
|
||||
Se registran altas y cambios de categorías y tipos mediante:
|
||||
|
||||
- `FINDING_CATEGORY_CREATED`;
|
||||
- `FINDING_CATEGORY_UPDATED`;
|
||||
- `FINDING_CATALOG_ITEM_CREATED`;
|
||||
- `FINDING_CATALOG_ITEM_UPDATED`.
|
||||
@@ -0,0 +1,19 @@
|
||||
# Deploy D5.2
|
||||
|
||||
## Archivo
|
||||
|
||||
`DH_V2_FASE_D5_2_SOURCE.zip`
|
||||
|
||||
Subir por FTP a `/var/www/dhv2.korexlabs.com/` y ejecutar el bloque único
|
||||
entregado junto con el archivo.
|
||||
|
||||
## Migración
|
||||
|
||||
`PhaseD52FindingCatalogAdministration1787335200000`
|
||||
|
||||
Es aditiva: crea y completa `finding_catalog_item_versions`. No modifica
|
||||
`.env`, no agrega volúmenes y no reescribe las migraciones ya aplicadas.
|
||||
|
||||
El despliegue valida checksum y ZIP, realiza backup, compila API/migrador/web,
|
||||
aplica la migración, recrea API/web y ejecuta
|
||||
`scripts/phase-d5-2-acceptance.sh`.
|
||||
@@ -0,0 +1,173 @@
|
||||
# Fase D5.3 — Contexto operativo Área–Empresa
|
||||
|
||||
Versión: `0.19.3`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Separar definitivamente la **jerarquía física** del Maestro de Activos de las
|
||||
**relaciones operativas** que determinan qué empresa explota activos dentro de
|
||||
un área.
|
||||
|
||||
D5.3 prepara el contrato de datos que después utilizarán la planificación web
|
||||
(D5.5) y la APK. No modifica todavía el flujo de inicio de inspecciones.
|
||||
|
||||
## Modelo funcional
|
||||
|
||||
La jerarquía física existente continúa usando `assets.parent_id`:
|
||||
|
||||
```text
|
||||
Área
|
||||
└── Instalación
|
||||
└── Estación
|
||||
└── Equipo
|
||||
```
|
||||
|
||||
Sobre esa jerarquía se agrega el contexto operativo:
|
||||
|
||||
```text
|
||||
Área ↔ Empresa
|
||||
└── activos explotados por esa empresa dentro de esa área
|
||||
```
|
||||
|
||||
Reglas:
|
||||
|
||||
- una empresa puede explotar varias áreas;
|
||||
- un área puede estar explotada por varias empresas;
|
||||
- un activo operativo tiene como máximo una combinación activa
|
||||
`Área + Empresa`;
|
||||
- el área asignada debe ser ancestro físico del activo;
|
||||
- el activo sólo puede asignarse a una empresa con vínculo activo con el área;
|
||||
- Área y Empresa son roles configurables del **tipo de activo**;
|
||||
- un activo Área o Empresa no recibe a su vez una asignación operativa;
|
||||
- la relación Área–Empresa no se borra físicamente: se finaliza y conserva
|
||||
vigencia, motivo y auditoría.
|
||||
|
||||
## Cambios de datos
|
||||
|
||||
### `asset_types`
|
||||
|
||||
Se agrega `operational_role`:
|
||||
|
||||
- `GENERIC`: instalación, estación, equipo u otro activo operativo;
|
||||
- `AREA`: activo que funciona como área/concesión;
|
||||
- `COMPANY`: activo que funciona como empresa explotadora.
|
||||
|
||||
La migración deja todos los tipos existentes en `GENERIC`. No intenta deducir
|
||||
roles por nombre o código, para evitar clasificaciones automáticas erróneas.
|
||||
|
||||
### `area_company_relations`
|
||||
|
||||
Nueva tabla histórica con:
|
||||
|
||||
- área;
|
||||
- empresa;
|
||||
- fecha de inicio;
|
||||
- fecha de finalización;
|
||||
- motivo de alta;
|
||||
- motivo de finalización;
|
||||
- usuario que creó el vínculo;
|
||||
- usuario que lo finalizó;
|
||||
- timestamps de auditoría.
|
||||
|
||||
Sólo puede existir un vínculo activo por cada par Área–Empresa.
|
||||
|
||||
### `assets`
|
||||
|
||||
Se agregan:
|
||||
|
||||
- `operational_area_id`;
|
||||
- `operator_company_id`.
|
||||
|
||||
Ambos campos son nulos o están completos juntos. La pareja representa la
|
||||
asignación operativa exclusiva del activo.
|
||||
|
||||
## Integridad
|
||||
|
||||
La API y PostgreSQL validan que:
|
||||
|
||||
1. el Área y la Empresa existan y estén activos;
|
||||
2. sus tipos tengan roles `AREA` y `COMPANY` respectivamente;
|
||||
3. exista un vínculo Área–Empresa activo;
|
||||
4. el activo asignado sea de un tipo `GENERIC`;
|
||||
5. el Área pertenezca a la cadena de ancestros físicos del activo;
|
||||
6. mover una rama de la jerarquía no deje descendientes fuera de su Área;
|
||||
7. no se pueda finalizar una relación mientras existan activos asignados;
|
||||
8. no se pueda inactivar un Área o Empresa mientras siga en uso.
|
||||
|
||||
## Dashboard
|
||||
|
||||
### Tipos de activo
|
||||
|
||||
El administrador puede indicar el rol operativo de cada tipo:
|
||||
|
||||
- Genérico;
|
||||
- Área;
|
||||
- Empresa.
|
||||
|
||||
No se permite cambiar un rol si eso rompería relaciones o asignaciones ya
|
||||
existentes.
|
||||
|
||||
### Activos Área / Empresa
|
||||
|
||||
En la ficha se muestra **Relaciones operativas**:
|
||||
|
||||
- vincular Área ↔ Empresa;
|
||||
- indicar motivo;
|
||||
- consultar vínculos vigentes e históricos;
|
||||
- ver cuántos activos dependen del vínculo;
|
||||
- finalizar el vínculo con motivo, sólo cuando ya no tenga activos asignados.
|
||||
|
||||
### Activos operativos
|
||||
|
||||
En activos de tipo `GENERIC` aparece **Contexto operativo**:
|
||||
|
||||
1. se selecciona Área;
|
||||
2. se muestran sólo Empresas con vínculo activo en esa Área;
|
||||
3. se selecciona la Empresa explotadora.
|
||||
|
||||
La asignación es opcional durante la transición de datos, para que la migración
|
||||
no invalide el Maestro ya existente. Antes de D5.5 deberán quedar configurados
|
||||
los activos que participen en inspecciones.
|
||||
|
||||
### Listado
|
||||
|
||||
El Maestro incorpora filtros por:
|
||||
|
||||
- Área operativa;
|
||||
- Empresa explotadora.
|
||||
|
||||
También muestra el contexto operativo actual de cada activo.
|
||||
|
||||
## Permisos
|
||||
|
||||
- `asset_relations.read`: admin, director, supervisor, inspector y auditor;
|
||||
- `asset_relations.manage`: admin y supervisor.
|
||||
|
||||
## Auditoría e historial
|
||||
|
||||
Las altas y finalizaciones generan:
|
||||
|
||||
- `ASSET_AREA_COMPANY_RELATION_CREATED`;
|
||||
- `ASSET_AREA_COMPANY_RELATION_ENDED`.
|
||||
|
||||
Los snapshots históricos de activos incorporan:
|
||||
|
||||
- rol operativo del tipo;
|
||||
- Área operativa;
|
||||
- Empresa explotadora.
|
||||
|
||||
La migración completa las versiones anteriores con valores neutros para evitar
|
||||
falsos cambios históricos.
|
||||
|
||||
## Fuera de alcance de D5.3
|
||||
|
||||
No se implementa todavía:
|
||||
|
||||
- selección Área → Empresa en una planificación;
|
||||
- generación automática de checklist;
|
||||
- modelos de hallazgo por tipo/activo;
|
||||
- gravedad 1–10;
|
||||
- opción `OTROS`;
|
||||
- cambios de APK.
|
||||
|
||||
Esos puntos pertenecen a D5.4, D5.5 y E1.
|
||||
@@ -0,0 +1,60 @@
|
||||
# Fase D5.3.1 — Configuración inicial del Maestro
|
||||
|
||||
Versión de paquete: `0.19.3-1`
|
||||
Fase visible: `D5.3.1`
|
||||
|
||||
> Se usa `0.19.3-1` porque `0.19.3.1` no es una versión SemVer válida para los
|
||||
> paquetes npm. Funcionalmente corresponde a la corrección D5.3.1.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Evitar que una instalación nueva de DH comience con un Maestro totalmente vacío y
|
||||
obligue a recrear manualmente la taxonomía hidrocarburífera básica.
|
||||
|
||||
## Configuración inicial
|
||||
|
||||
Desde `Maestro → Tipos y atributos`, cuando no existe ningún tipo, un administrador
|
||||
puede ejecutar **Instalar configuración base**.
|
||||
|
||||
La operación se ejecuta en una sola transacción y crea:
|
||||
|
||||
- Área / Concesión (`AREA`);
|
||||
- Empresa / Operadora (`COMPANY`);
|
||||
- Yacimiento;
|
||||
- Instalación de superficie;
|
||||
- Estación;
|
||||
- Subestación;
|
||||
- Pozo;
|
||||
- Equipo;
|
||||
- Ducto / Cañería.
|
||||
|
||||
También crea sus reglas padre/hijo y atributos opcionales iniciales.
|
||||
|
||||
## Seguridad
|
||||
|
||||
- requiere `asset_types.manage`;
|
||||
- sólo puede ejecutarse con `asset_types = 0`;
|
||||
- bloquea intentos concurrentes;
|
||||
- no reemplaza ni modifica configuraciones existentes;
|
||||
- no crea datos operativos reales;
|
||||
- registra `ASSET_MASTER_BOOTSTRAPPED` en auditoría.
|
||||
|
||||
## Fuente de dominio
|
||||
|
||||
La taxonomía se alineó con la terminología que usa la Dirección de Hidrocarburos de
|
||||
Mendoza y con la estructura funcional acordada para DH. Ver:
|
||||
|
||||
`docs/DATA_REFERENCE_MENDOZA_HYDROCARBONS.md`.
|
||||
|
||||
## Alcance excluido
|
||||
|
||||
D5.3.1 no importa automáticamente:
|
||||
|
||||
- operadoras actuales;
|
||||
- concesiones o áreas actuales;
|
||||
- yacimientos;
|
||||
- pozos;
|
||||
- instalaciones;
|
||||
- métricas públicas de inspección.
|
||||
|
||||
Esos datos necesitan una fuente versionada/importable y trazabilidad de vigencia.
|
||||
@@ -0,0 +1,28 @@
|
||||
# Fase D5.3.11 · Importación parcial y revisiones
|
||||
|
||||
## Objetivo
|
||||
|
||||
Permitir que un lote avance con las ramas independientes aunque existan decisiones pendientes, manteniendo protegidos los registros que dependen de esas decisiones.
|
||||
|
||||
## Reglas
|
||||
|
||||
1. Una revisión abierta no habilita escrituras sobre su propia rama ni sobre entidades dependientes.
|
||||
2. Las ramas sin dependencia de una revisión pueden aplicarse mediante `asset_imports.apply`.
|
||||
3. La aplicación parcial valida el hash del plan y la huella vigente del Maestro antes de escribir.
|
||||
4. Cada aplicación se ejecuta dentro de una transacción.
|
||||
5. Las revisiones permanecen asociadas al plan activo y se consultan desde una bandeja general de Importaciones.
|
||||
6. Una nueva revisión del plan puede reconocer como existentes los registros incorporados anteriormente.
|
||||
7. El rollback lógico contempla registros creados por todas las revisiones del mismo lote.
|
||||
8. Un lote con aplicación parcial no puede cancelarse ni volver a conciliación preliminar sin revertir; sí puede regenerar su plan.
|
||||
|
||||
## Estados visibles
|
||||
|
||||
- Pendiente de aplicar.
|
||||
- Importado parcialmente.
|
||||
- Revisiones pendientes.
|
||||
- Importado completo.
|
||||
- Revertido.
|
||||
|
||||
## Base de datos
|
||||
|
||||
La fase no agrega migraciones. Utiliza las tablas de lotes, planes e ítems existentes y conserva el progreso en `application_summary` y `analysis.importExecution`.
|
||||
@@ -0,0 +1,14 @@
|
||||
# Fase D5.3.11.1 · Navegación de importados
|
||||
|
||||
## Objetivo
|
||||
|
||||
Hacer visibles en el Maestro los activos incorporados por importación parcial cuando la fuente identifica Área y Operadora, sin convertir esa asignación de inventario en una relación formal `area_company_relations`.
|
||||
|
||||
## Comportamiento
|
||||
|
||||
- La navegación Empresa → Área considera relaciones operativas vigentes registradas y también Áreas usadas por activos no inactivos asignados a esa empresa.
|
||||
- El filtro Área → Operadora aplica el mismo criterio.
|
||||
- No se crean ni modifican relaciones legales u operativas formales.
|
||||
- La jerarquía física continúa usando `parent_id`.
|
||||
- Se conserva la importación parcial y la bandeja de revisiones de D5.3.11.
|
||||
- No requiere migración de base de datos.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Fase D5.3.14 · Expediente técnico
|
||||
|
||||
## Objetivo
|
||||
|
||||
Convertir cada elemento del Inventario en un punto de acceso a su historia operativa y documental.
|
||||
|
||||
## Alcance
|
||||
|
||||
- Nueva pestaña **Expediente** en la ficha de Inventarios.
|
||||
- Resumen de inspecciones, actas, hallazgos, fotografías y documentos.
|
||||
- Línea de tiempo unificada del elemento.
|
||||
- Acceso directo desde el expediente a inspecciones, actas y hallazgos.
|
||||
- Consulta de evidencias y comunicaciones vinculadas a hallazgos del elemento.
|
||||
- Consulta de documentos fuente e informes técnicos vinculados al registro.
|
||||
- Preservación del historial de versiones del Inventario.
|
||||
|
||||
## Criterio de datos
|
||||
|
||||
El expediente no copia información ni crea estructuras paralelas. Consulta las entidades existentes y presenta una vista cronológica común.
|
||||
|
||||
Los informes consolidados de inspección continúan fuera de esta fase y se incorporarán al centro documental general en una etapa posterior.
|
||||
|
||||
## Seguridad
|
||||
|
||||
El endpoint de expediente exige permisos de lectura de Inventarios, inspecciones, actas, hallazgos, evidencias y comunicaciones.
|
||||
|
||||
## Base de datos
|
||||
|
||||
No requiere migraciones.
|
||||
@@ -0,0 +1,56 @@
|
||||
# D5.3.15.1 · Centro documental
|
||||
|
||||
## Objetivo
|
||||
|
||||
Concentrar la consulta de actas e informes de inspección sin duplicar el contenido operativo que ya existe en visitas, hallazgos e Inventarios.
|
||||
|
||||
## Actas
|
||||
|
||||
El dashboard incorpora una vista global de actas con búsqueda y filtros por estado y año. Cada fila mantiene acceso directo a la inspección, los hallazgos y el informe relacionado cuando exista.
|
||||
|
||||
La API incorpora `GET /inspection-acts` para consulta paginada global. El endpoint por visita permanece disponible y conserva su comportamiento.
|
||||
|
||||
## Informes
|
||||
|
||||
Se incorpora el registro `inspection_reports` con numeración anual independiente mediante la secuencia `REPORT` ya prevista en el modelo documental.
|
||||
|
||||
Un informe sólo puede solicitarse sobre un acta cerrada. La solicitud se realiza mediante una operación autenticada de inspector desde la aplicación de campo. El backend:
|
||||
|
||||
- valida que el acta esté cerrada y sellada;
|
||||
- valida que el inspector esté asignado a la visita;
|
||||
- asigna un número anual global de informe;
|
||||
- congela la instantánea final del cierre del acta;
|
||||
- conserva versión del acta y hashes de integridad;
|
||||
- deja la composición PDF en estado pendiente para la etapa documental posterior.
|
||||
|
||||
El dashboard no numera ni genera informes manualmente. Muestra dos vistas: informes emitidos y actas cerradas pendientes de emisión.
|
||||
|
||||
## Navegación
|
||||
|
||||
Se agregan accesos globales:
|
||||
|
||||
- `/actas`
|
||||
- `/informes`
|
||||
- `/informes/:id`
|
||||
|
||||
Desde estas vistas se puede navegar a la inspección, acta y hallazgos relacionados.
|
||||
|
||||
## Seguridad
|
||||
|
||||
Permisos incorporados:
|
||||
|
||||
- `inspection_reports.read`
|
||||
- `inspection_reports.generate`
|
||||
|
||||
La lectura se concede a perfiles de consulta operativa. La generación queda reservada al inspector y además requiere autenticación de campo mediante la política móvil existente.
|
||||
|
||||
El contenido congelado del informe está protegido a nivel de base de datos. La tabla no admite eliminación mediante el rol de aplicación y un trigger impide alterar la identidad, numeración, snapshot y hashes una vez emitidos.
|
||||
|
||||
## Base de datos
|
||||
|
||||
La fase incorpora una migración para crear `inspection_reports`, permisos, índices y protección de inmutabilidad.
|
||||
|
||||
|
||||
## Corrección 15.1
|
||||
|
||||
Ajuste de tipado estricto en los rótulos de contexto de las bandejas globales de Actas e Informes. No modifica el modelo documental ni la migración de D5.3.15.
|
||||
@@ -0,0 +1,47 @@
|
||||
# D5.3.16 · Planificación de verificaciones
|
||||
|
||||
## Objetivo
|
||||
|
||||
Transformar la segunda fecha del seguimiento de un hallazgo en trabajo operativo planificable desde oficina, sin confundirla con el vencimiento administrativo de respuesta de la empresa.
|
||||
|
||||
## Regla funcional
|
||||
|
||||
- `correction_due_on`: vencimiento administrativo para recibir la respuesta de la empresa.
|
||||
- `next_control_on`: fecha objetivo para verificar en campo la resolución del hallazgo.
|
||||
- Una verificación sólo entra en la bandeja operativa cuando el hallazgo sigue abierto, la empresa ya respondió y `next_control_on` está definido.
|
||||
- La planificación no modifica ninguna de esas fechas.
|
||||
|
||||
## Bandeja de planificación
|
||||
|
||||
Ruta: `/hallazgos/planificacion`.
|
||||
|
||||
La pantalla separa:
|
||||
|
||||
- hallazgos verificables sin visita;
|
||||
- verificaciones vencidas sin planificar;
|
||||
- verificaciones próximas;
|
||||
- hallazgos que ya tienen una visita activa asociada.
|
||||
|
||||
Los hallazgos se seleccionan por empresa y área. No se permite mezclar contextos operativos distintos dentro de una misma visita.
|
||||
|
||||
## Creación de visita
|
||||
|
||||
La acción de oficina crea una visita de verificación en estado `DRAFT` con:
|
||||
|
||||
- área como alcance principal;
|
||||
- elementos del Inventario afectados;
|
||||
- fecha y hora previstas;
|
||||
- referencias explícitas a los hallazgos;
|
||||
- trazabilidad entre hallazgo y visita.
|
||||
|
||||
La visita se completa después con inspector y equipo y se marca `PLANNED` usando el flujo existente de Inspecciones.
|
||||
|
||||
## Trazabilidad
|
||||
|
||||
La tabla `inspection_finding_verification_visits` conserva el vínculo histórico entre hallazgo y visita. Un hallazgo no puede incorporarse simultáneamente a dos visitas activas (`DRAFT`, `PLANNED` o `IN_PROGRESS`). Si una visita se cancela o termina y el hallazgo continúa abierto, puede planificarse una nueva verificación sin perder el vínculo anterior.
|
||||
|
||||
## Permisos
|
||||
|
||||
`inspection_verifications.plan` se asigna inicialmente a admin, director y supervisor.
|
||||
|
||||
La consulta de la bandeja conserva `inspection_findings.read`.
|
||||
@@ -0,0 +1,7 @@
|
||||
# Deploy D5.3.16
|
||||
|
||||
Origen requerido: D5.3.15.1 / `0.19.3-15.1`.
|
||||
|
||||
El deploy compila API, ejecuta tests y compila Web en staging antes de modificar producción. Luego crea backup PRE, instala el source, construye las imágenes, ejecuta la migración, recrea API/Web, corre aceptación y genera backup POST.
|
||||
|
||||
La migración crea `inspection_finding_verification_visits` y el permiso `inspection_verifications.plan`.
|
||||
@@ -0,0 +1,31 @@
|
||||
# D5.3.17 · Verificación de campo
|
||||
|
||||
## Objetivo
|
||||
|
||||
Cerrar el circuito iniciado por la planificación de verificaciones, manteniendo separadas la gestión administrativa del hallazgo y la constatación en campo.
|
||||
|
||||
## Resultado de campo
|
||||
|
||||
Cada hallazgo vinculado a una visita de verificación en curso admite un resultado:
|
||||
|
||||
- `RESOLVED`: la condición fue verificada como solucionada; queda disponible para revisión y cierre administrativo cuando finaliza la visita.
|
||||
- `NOT_RESOLVED`: el hallazgo continúa abierto y vuelve a oficina sin una nueva fecha automática.
|
||||
- `REQUIRES_NEW_DATE`: el hallazgo continúa abierto y el inspector propone una nueva fecha de control posterior a la verificación.
|
||||
|
||||
La captura requiere sesión móvil del inspector asignado y permiso `inspections.execute`.
|
||||
|
||||
## Evidencia
|
||||
|
||||
Las fotografías de verificación usan la finalidad `VERIFICATION` y quedan asociadas al hallazgo y a la visita de verificación. No reemplazan la evidencia original ni la documentación presentada por la empresa.
|
||||
|
||||
## Cierre documental
|
||||
|
||||
Una visita de verificación puede preparar su acta aunque no se hayan creado hallazgos nuevos, siempre que tenga hallazgos de verificación vinculados y todos posean un resultado. El snapshot de cierre incorpora resultados y fotografías de verificación y utiliza el esquema `DH-ACT-CLOSURE-V2`.
|
||||
|
||||
## Trabajo de oficina
|
||||
|
||||
Los hallazgos cuyo último resultado sea `RESOLVED` y cuya visita ya esté cerrada aparecen en `Hallazgos → Listos para cerrar`. Los resultados resueltos dejan de aparecer en la cola de nuevas verificaciones mientras el hallazgo siga abierto administrativamente.
|
||||
|
||||
## Expediente del Inventario
|
||||
|
||||
La cronología del elemento registra cada verificación y conserva el vínculo hacia la visita y el hallazgo correspondiente.
|
||||
@@ -0,0 +1,11 @@
|
||||
# D5.3.17.1 · Verificación de campo
|
||||
|
||||
## Corrección
|
||||
|
||||
Esta entrega corrige la validación de D5.3.17 antes de producción. La versión anterior se detuvo en staging y no modificó la base de datos ni los servicios productivos.
|
||||
|
||||
El resultado `RESOLVED` queda tratado explícitamente en el servicio de verificaciones. Al verificarse un hallazgo como solucionado, se elimina su próxima fecha operativa de control y queda disponible para revisión y cierre administrativo una vez finalizada la visita.
|
||||
|
||||
Se conserva sin cambios el modelo funcional de D5.3.17: resultados `RESOLVED`, `NOT_RESOLVED` y `REQUIRES_NEW_DATE`, evidencia de verificación, cierre documental de la visita, bandeja de hallazgos listos para cerrar y cronología del Inventario.
|
||||
|
||||
La migración de D5.3.17 se mantiene sin cambios porque la entrega anterior no llegó a ejecutarla en producción.
|
||||
@@ -0,0 +1,35 @@
|
||||
# D5.3.18 · Expediente operativo de hallazgos
|
||||
|
||||
## Objetivo
|
||||
|
||||
Convertir la ficha del hallazgo en una mesa de trabajo única para oficina, evitando saltos innecesarios entre seguimiento, comunicaciones, documentos, planificación y cierre.
|
||||
|
||||
## Flujo operativo
|
||||
|
||||
La ficha muestra cuatro etapas visibles: hallazgo, respuesta de empresa, verificación y cierre. El backend expone una recomendación de trabajo según el estado real del hallazgo y sus dos fechas operativas.
|
||||
|
||||
El vencimiento administrativo permanece en `correction_due_on` y representa el plazo de la empresa para responder. La fecha `next_control_on` continúa siendo independiente y alimenta la planificación de verificaciones. `company_committed_correction_on` se conserva como fecha informada por la empresa y no reemplaza a ninguna de las dos anteriores.
|
||||
|
||||
## Respuesta de empresa
|
||||
|
||||
La primera respuesta puede registrarse desde una sola sección. El operador carga el resumen recibido, fecha y hora, medio, contacto opcional, fecha informada por la empresa, fecha de verificación opcional y un PDF opcional.
|
||||
|
||||
El resumen actualiza el seguimiento versionado. La comunicación queda registrada en el historial inmutable y, cuando se adjunta un PDF, se vincula a esa comunicación usando el almacenamiento protegido y el hash SHA-256 existente.
|
||||
|
||||
## Verificación
|
||||
|
||||
Con respuesta recibida, la misma ficha permite definir o modificar la fecha operativa de verificación. Cuando corresponde planificar una visita, se ofrece acceso directo a la bandeja de planificación. Si ya existe una visita activa, se abre directamente desde el expediente.
|
||||
|
||||
El último resultado de campo se muestra dentro del mismo circuito y conserva los estados Solucionado, No solucionado y Requiere nueva fecha.
|
||||
|
||||
## Cierre
|
||||
|
||||
El cierre administrativo se ejecuta desde la misma ficha. Si existe una visita de verificación activa, permanece bloqueado. Cuando la última verificación está resuelta y la visita cerrada, el expediente destaca que el hallazgo está listo para cierre.
|
||||
|
||||
## Documentos y trazabilidad
|
||||
|
||||
La respuesta principal se gestiona en el expediente operativo. El panel inferior queda como centro de documentos adicionales, adjuntos de comunicaciones y trazabilidad histórica. Se mantiene disponible la carga de un PDF de respuesta para completar o reintentar un adjunto vinculado.
|
||||
|
||||
## Base de datos
|
||||
|
||||
D5.3.18 no agrega migraciones. Reutiliza los campos, comunicaciones, evidencias, verificaciones, auditoría y versionado ya existentes.
|
||||
@@ -0,0 +1,30 @@
|
||||
# D5.3.18.2 · Expediente operativo de Hallazgos
|
||||
|
||||
Esta fase es un hotfix acumulativo sobre D5.3.18 ya desplegada y parte directamente de D5.3.18.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Concentrar en una sola ficha el trabajo de oficina sobre un hallazgo y alinear el seguimiento con las definiciones funcionales confirmadas:
|
||||
|
||||
- la primera respuesta registrada de la empresa no se modifica;
|
||||
- las presentaciones posteriores son históricas y append-only;
|
||||
- documentos y evidencias quedan vinculados a cada presentación;
|
||||
- el vencimiento administrativo y la fecha de verificación siguen separados;
|
||||
- el cierre administrativo queda reservado a Inspector, Supervisor y Director;
|
||||
- una verificación resuelta habilita el cierre, pero no lo ejecuta automáticamente.
|
||||
|
||||
## Alcance
|
||||
|
||||
La ficha muestra una acción recomendada según el estado del hallazgo, integra respuesta de empresa, documentos, fechas de seguimiento, planificación/resultado de verificación y cierre.
|
||||
|
||||
Las comunicaciones existentes siguen siendo la fuente histórica para múltiples presentaciones sucesivas. El resumen de la primera respuesta en `inspection_findings` queda protegido contra sobrescritura accidental una vez registrada su fecha de recepción.
|
||||
|
||||
## Migración
|
||||
|
||||
La fase agrega el permiso `inspection_findings.close` y lo asigna exclusivamente a los roles `inspector`, `supervisor` y `director`.
|
||||
|
||||
No modifica la estructura de los hallazgos ni borra información existente.
|
||||
|
||||
## Fuera de alcance
|
||||
|
||||
La relación contextual Tipo de elemento ↔ Catálogo de Hallazgos se mantiene pendiente de definición fina con Hidrocarburos. Se recomienda que sea sugerida, no restrictiva, con `OTROS` siempre disponible y versionada.
|
||||
@@ -0,0 +1,7 @@
|
||||
# D5.3.18.3 · Expediente operativo de Hallazgos
|
||||
|
||||
Corrección de consistencia de pruebas sobre D5.3.18.2.
|
||||
|
||||
El endpoint de cierre usa el permiso específico `inspection_findings.close`. La prueba heredada que todavía esperaba `inspection_findings.follow_up` fue actualizada para representar la regla funcional vigente.
|
||||
|
||||
La fase parte de producción D5.3.18 / 0.19.3-18. D5.3.18.2 no fue desplegada: su ejecución se detuvo en staging antes de modificar producción.
|
||||
@@ -0,0 +1,36 @@
|
||||
# D5.3.19 · Inventarios y filtros operativos
|
||||
|
||||
## Objetivo
|
||||
|
||||
Mejorar la identificación cotidiana de los elementos del Inventario y hacer más ágil la consulta de la operación anual, sin modificar las reglas documentales ya confirmadas.
|
||||
|
||||
## Nombre habitual / sobrenombre
|
||||
|
||||
Todos los elementos pueden guardar un `common_name` opcional. El dato se muestra como **Nombre habitual / sobrenombre** y no reemplaza al nombre técnico ni al código. La búsqueda de Inventarios contempla los tres valores y el historial/versionado captura sus cambios.
|
||||
|
||||
## Filtros operativos
|
||||
|
||||
Las bandejas globales de Inspecciones, Actas, Informes y Hallazgos aceptan Empresa, Área, Inspector, Desde y Hasta. Los filtros se aplican en servidor y se conservan en la URL para permitir volver a la misma consulta.
|
||||
|
||||
## Vencimiento administrativo de respuesta
|
||||
|
||||
El hallazgo conserva `correction_due_on` como vencimiento efectivo y agrega metadatos para explicar cómo se calculó:
|
||||
|
||||
- `FINDING_DATE`: X días desde la fecha del hallazgo/acta;
|
||||
- `REPORT_NOTIFICATION`: X días desde la fecha de notificación del informe.
|
||||
|
||||
Se guardan la regla, la cantidad de días, la fecha base y, cuando corresponde, la fecha de notificación. Una vez registrada la primera respuesta de la empresa, esa regla administrativa queda bloqueada junto con la respuesta original.
|
||||
|
||||
La fecha informada por la empresa y la fecha operativa de verificación continúan siendo conceptos independientes.
|
||||
|
||||
## Reglas preservadas
|
||||
|
||||
- una visita genera una sola acta con múltiples hallazgos;
|
||||
- acta cerrada y hallazgo original no se reescriben;
|
||||
- respuestas posteriores y verificaciones son históricas;
|
||||
- cierre de hallazgo reservado a Inspector, Supervisor y Director;
|
||||
- no se implementa en esta fase la relación contextual Tipo de elemento ↔ Catálogo de Hallazgos.
|
||||
|
||||
## Nota de integración futura
|
||||
|
||||
Mientras no esté automatizado el envío/notificación del Informe Word, la fecha de notificación puede ser registrada desde el seguimiento administrativo. Cuando se implemente el envío automático, esa fecha deberá alimentarse desde el evento real de notificación y no duplicarse manualmente.
|
||||
@@ -0,0 +1,7 @@
|
||||
# D5.3.19.1 · Inventarios y filtros operativos
|
||||
|
||||
Patch de D5.3.19 detenido en staging antes de producción.
|
||||
|
||||
Corrige el contrato TypeScript de `createAsset` en Web para aceptar `commonName?: string | null`, alineándolo con el DTO/API y con `updateAsset`. No altera la migración funcional D5.3.19 ni los datos.
|
||||
|
||||
Mantiene como origen productivo D5.3.18.3 (`0.19.3-18.3`) porque D5.3.19 falló durante el build Web, antes del backup PRE y antes de instalar source.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Deploy D5.3.1
|
||||
|
||||
## Particularidad
|
||||
|
||||
D5.3.1 no agrega migraciones. El deploy debe:
|
||||
|
||||
1. respaldar base y código;
|
||||
2. reemplazar source;
|
||||
3. compilar API y web;
|
||||
4. ejecutar tests API;
|
||||
5. confirmar `Pending migrations: no`;
|
||||
6. recrear API y web;
|
||||
7. ejecutar `scripts/phase-d5-3-1-acceptance.sh`.
|
||||
|
||||
El bootstrap del Maestro **no se ejecuta durante el deploy**. Después de validar la
|
||||
versión, un administrador entra a `Maestro → Tipos y atributos` y elige
|
||||
`Instalar configuración base`.
|
||||
|
||||
## Resultado esperado
|
||||
|
||||
- API `0.19.3-1`, fase `D5.3.1`;
|
||||
- WEB `0.19.3-1`;
|
||||
- base sin migraciones pendientes;
|
||||
- Maestro vacío hasta que el administrador confirme la configuración inicial;
|
||||
- rutas de bootstrap protegidas por autenticación y permisos.
|
||||
@@ -0,0 +1,32 @@
|
||||
# Fase D5.3.2 · Nomenclatura técnica y datos de desarrollo
|
||||
|
||||
Versión: `0.19.3-2`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Alinear el Maestro con la nomenclatura observada en la operatoria de Hidrocarburos de Mendoza y disponer de un caso demostrativo seguro antes de avanzar con D5.4.
|
||||
|
||||
## Alcance
|
||||
|
||||
- ampliación aditiva del preset de Maestro ya instalado en D5.3.1;
|
||||
- tipos de instalación, sistema y equipo específicos;
|
||||
- un único tipo Pozo con método/función configurable;
|
||||
- endpoints protegidos para consultar y aplicar el enriquecimiento;
|
||||
- acción visible en dashboard `Completar catálogo técnico`;
|
||||
- seed de desarrollo basado en ITN 124/2026;
|
||||
- limpiador controlado con dry-run, backup y protección contra mezcla demo/real;
|
||||
- documentación de nomenclatura y criterio activo vs componente.
|
||||
|
||||
## Compatibilidad
|
||||
|
||||
D5.3.2 no agrega migraciones de esquema. Conserva la migración D5.3 y no modifica los activos reales existentes. La ampliación sólo crea tipos, atributos y reglas faltantes; no reemplaza configuraciones ya existentes.
|
||||
|
||||
## Tipos técnicos incorporados
|
||||
|
||||
Además de los tipos base se contemplan, entre otros: Locación, Planta, Batería, Zona de bombas, Sistema de drenaje, Sistema eléctrico/iluminación, Defensa contra incendios, Cargadero/descargadero, Pileta API, Tanque, Separador, Bomba, Caldera, Antorcha, Colector, Filtro, Equipo de flotación, FWKO, Tratador y Calentador.
|
||||
|
||||
`Equipo` continúa disponible como tipo genérico para inventarios incompletos.
|
||||
|
||||
## Siguiente fase
|
||||
|
||||
Con la taxonomía probada, D5.4 podrá relacionar el catálogo de hallazgos con tipos técnicos y activos concretos, agregar gravedad 1–10 y soportar `OTROS` como propuesta de catálogo.
|
||||
@@ -0,0 +1,9 @@
|
||||
# D5.3.20 · Informe Word automático
|
||||
|
||||
D5.3.20 alinea el cierre documental con la regla funcional vigente: una visita produce una sola acta con múltiples hallazgos y, al cerrarse definitivamente esa acta, el sistema crea automáticamente el registro congelado del informe y genera un archivo Word para revisión manual del Director de Hidrocarburos.
|
||||
|
||||
El Word se construye exclusivamente desde la instantánea congelada del acta. El archivo posee SHA-256 propio, metadatos de almacenamiento y estado PENDING/READY/FAILED. La pantalla de Informes muestra el estado del Word y permite descargarlo cuando está disponible.
|
||||
|
||||
El diseño institucional definitivo y la firma final del Director siguen pendientes de definición. Esta fase no activa correo electrónico: el envío automático del acta a empresa/oficina y del Word al Director requiere definir y administrar destinatarios institucionales antes de conectar SMTP.
|
||||
|
||||
Se preservan una visita = una acta, hallazgos inmutables con seguimiento append-only y la numeración anual independiente del informe.
|
||||
@@ -0,0 +1,5 @@
|
||||
# Fase D5.3.21 · Entrega documental
|
||||
|
||||
La fase incorpora destinatarios institucionales configurables, email oficial por empresa, PDF automático provisional del Acta, cola auditable de entregas, reintentos y transporte SMTP opcional. El cierre documental nunca depende de que el correo esté disponible: si falta destinatario, SMTP o artefacto, la entrega queda pendiente con un estado explícito.
|
||||
|
||||
Reglas: Acta cerrada e inmutable → PDF automático → empresa + oficina. Informe Word congelado → Director de Hidrocarburos. Las direcciones no se codifican en source y los secretos SMTP permanecen en `.env`.
|
||||
@@ -0,0 +1,18 @@
|
||||
# Fase D5.3.21.1 · Entrega documental
|
||||
|
||||
Parche de compilación de D5.3.21 sobre producción D5.3.20.
|
||||
|
||||
D5.3.21 no llegó a producción: el build de API se detuvo en staging por TS4053 porque el método público `retry` exponía por inferencia el tipo interno `DeliveryRow`.
|
||||
|
||||
D5.3.21.1 exporta el contrato `DeliveryRow` y tipa de forma explícita el retorno público del endpoint de reintento. No cambia la lógica de negocio, el esquema previsto ni la migración funcional de entrega documental.
|
||||
|
||||
La fase mantiene:
|
||||
- Acta PDF para empresa y oficina.
|
||||
- Informe Word para Director de Hidrocarburos.
|
||||
- Entrega no bloqueante, auditable y reintentable.
|
||||
- Destinatarios configurables sin direcciones hardcodeadas.
|
||||
- Credenciales SMTP únicamente por entorno.
|
||||
- Una visita = una acta.
|
||||
- Actas cerradas y hallazgos originales inmutables.
|
||||
|
||||
El deploy exige como origen API/Web `0.19.3-20` porque D5.3.21 falló antes de instalar source o ejecutar migraciones.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Fase D5.3.22 · Revisión directiva de Informes
|
||||
|
||||
D5.3.22 incorpora el circuito posterior a la generación automática del Informe Word.
|
||||
|
||||
## Flujo
|
||||
|
||||
1. El cierre del Acta conserva la generación automática del Informe y del Word inicial.
|
||||
2. El Word automático pasa a ser la Versión 1 del Informe.
|
||||
3. El Director puede descargarlo, revisarlo en Word y cargar una nueva versión corregida con un resumen obligatorio de cambios.
|
||||
4. Cada corrección crea una revisión nueva e inmutable. Nunca reemplaza ni borra una versión anterior.
|
||||
5. El Director aprueba explícitamente la versión vigente.
|
||||
6. Sólo después de esa aprobación puede registrar la firma electrónica final.
|
||||
7. La firma final vincula el Informe congelado, la revisión aprobada, ambos hashes, el usuario Director y la fecha de firma.
|
||||
8. Después de la firma no se admiten nuevas revisiones.
|
||||
|
||||
## Permisos
|
||||
|
||||
- `inspection_reports.revise`: cargar versiones corregidas.
|
||||
- `inspection_reports.review`: aprobar la versión vigente.
|
||||
- `inspection_reports.sign_final`: firma electrónica final.
|
||||
|
||||
Los tres permisos se asignan inicialmente únicamente al rol `director`. El backend además exige que el usuario tenga efectivamente el rol Director para revisar, aprobar o firmar.
|
||||
|
||||
## Integridad documental
|
||||
|
||||
La revisión no modifica el Acta, los Hallazgos ni el `frozen_snapshot` del Informe. La Versión 1 automática se conserva. Las versiones corregidas se almacenan como documentos DOCX separados, con número, autor, fecha, resumen de cambios, tamaño y SHA-256.
|
||||
|
||||
Los DOCX cargados tienen un límite de 15 MB, deben contener la estructura mínima OOXML y no pueden contener macros VBA ni objetos embebidos.
|
||||
|
||||
## Firma
|
||||
|
||||
La fase implementa una firma electrónica de aprobación trazable y exclusiva del Director. Se almacena un payload canónico con el hash del Informe y el hash de la revisión aprobada, y se calcula un SHA-256 de firma.
|
||||
|
||||
La ubicación visual de una rúbrica o sello dentro del documento final no se fija todavía porque la plantilla institucional definitiva continúa pendiente de definición.
|
||||
|
||||
## Correo
|
||||
|
||||
D5.3.22 no exige SMTP y no modifica el alcance de D5.3.21.1. El envío inicial del Word al Director permanece preparado pero puede seguir en estado pendiente mientras no exista una cuenta institucional definida.
|
||||
@@ -0,0 +1,40 @@
|
||||
# D5.3.23.1 · Altas de campo y revisión de Inventarios
|
||||
|
||||
## Objetivo
|
||||
|
||||
Permitir que un inspector registre durante una inspección un elemento que no existe todavía en el Inventario, siga trabajando con ese registro provisional y deje la decisión definitiva para oficina.
|
||||
|
||||
## Flujo
|
||||
|
||||
1. Sólo un inspector autenticado desde la aplicación móvil puede generar un alta de campo.
|
||||
2. La visita debe estar `IN_PROGRESS` y el inspector debe integrar el equipo asignado.
|
||||
3. El elemento se crea como `DRAFT`, con origen `FIELD_SURVEY`, referencia a la visita y trazabilidad completa.
|
||||
4. El elemento se incorpora inmediatamente a la visita y, si el Acta ya existe y sigue abierta, también al Acta para poder registrar Hallazgos sobre él.
|
||||
5. En oficina, la bandeja **Inventarios → Altas de campo** permite:
|
||||
- abrir y corregir la ficha;
|
||||
- aprobarla, pasando a `VALIDATED`;
|
||||
- conciliarla con un registro existente de la misma Empresa y Área;
|
||||
- rechazarla.
|
||||
6. Conciliar o rechazar nunca elimina el registro provisional: se archiva como `INACTIVE` para conservar las referencias históricas.
|
||||
7. Actas y Hallazgos ya emitidos no cambian de `asset_id`; el vínculo con un registro existente se registra aparte mediante `matched_asset_id`.
|
||||
|
||||
## Validación mínima al aprobar
|
||||
|
||||
La ficha debe mantener como mínimo Empresa, Área, Tipo de elemento y Nombre/código. El esquema ya exige Nombre y Código; la aprobación agrega el control explícito de Empresa y Área.
|
||||
|
||||
## Seguridad
|
||||
|
||||
- Creación en campo: permiso `assets.create` + política de inspector móvil.
|
||||
- Bandeja: `assets.read`.
|
||||
- Aprobar, conciliar y rechazar: `assets.change_status`.
|
||||
- No se agregan permisos nuevos ni se amplían roles en esta fase.
|
||||
|
||||
## Persistencia
|
||||
|
||||
Nueva tabla `asset_field_discoveries`, append-preserving, con estado `PENDING | APPROVED | MATCHED | REJECTED`, visita, inspector, decisión de oficina y eventual coincidencia.
|
||||
|
||||
SMTP no forma parte de esta fase y puede continuar sin configurar.
|
||||
|
||||
|
||||
## Parche 23.1
|
||||
El enlace del objeto provisional con `inspection_visit_assets` y `inspection_act_assets` se aisló en `FieldDiscoveryInspectionLinkService`, manteniendo `AssetsService` libre de escrituras directas sobre tablas de inspección y conservando el test arquitectónico de D5.3.14.
|
||||
@@ -0,0 +1,75 @@
|
||||
# Fase D5.3.24 · Historial de contexto operativo
|
||||
|
||||
## Objetivo
|
||||
|
||||
Preservar de forma explícita la evolución de la ubicación jerárquica y del contexto operativo de cada elemento del Inventario: padre físico, Área y Operadora.
|
||||
|
||||
## Regla funcional
|
||||
|
||||
Un cambio actual de jerarquía, Área u Operadora nunca elimina la relación anterior. La relación vigente se cierra con una fecha de fin y se agrega una nueva relación con fecha de inicio, motivo, usuario, request y versión del Inventario.
|
||||
|
||||
Los cambios ordinarios de nombre, código, atributos o descripción siguen usando la edición normal. Los registros consolidados no pueden cambiar `parentId`, `operationalAreaId` ni `operatorCompanyId` por el endpoint general: deben usar el cambio de contexto auditado. La única excepción es una alta de campo todavía DRAFT y pendiente de revisión, porque en ese momento oficina está corrigiendo el registro provisional antes de validarlo.
|
||||
|
||||
## Persistencia
|
||||
|
||||
Nueva tabla `asset_context_history` con un único registro activo por elemento. Guarda:
|
||||
|
||||
- `parent_id`
|
||||
- `operational_area_id`
|
||||
- `operator_company_id`
|
||||
- `valid_from`
|
||||
- `valid_until`
|
||||
- `change_reason`
|
||||
- `end_reason`
|
||||
- `asset_version_number`
|
||||
- `source`
|
||||
- `request_id`
|
||||
- usuario creador/finalizador
|
||||
|
||||
No existe eliminación de historial para el rol de aplicación.
|
||||
|
||||
## Reconstrucción de antecedentes
|
||||
|
||||
La migración analiza `asset_versions` y detecta sólo los puntos donde cambió alguno de estos tres valores. Esos puntos se convierten en intervalos históricos. Así se aprovecha el versionado ya existente y no se presupone que la relación actual existió desde el alta del elemento.
|
||||
|
||||
Para activos sin versiones recuperables se crea una línea base a partir del contexto vigente.
|
||||
|
||||
## Cambio de contexto
|
||||
|
||||
Nuevo endpoint:
|
||||
|
||||
`POST /api/v3/assets/:id/context`
|
||||
|
||||
Requiere `assets.manage_context` y un motivo obligatorio. Puede indicar una fecha efectiva pasada siempre que sea posterior al inicio del contexto vigente y no esté en el futuro.
|
||||
|
||||
La operación es transaccional:
|
||||
|
||||
1. valida padre y reglas de jerarquía;
|
||||
2. valida Área–Operadora;
|
||||
3. cierra el contexto anterior;
|
||||
4. actualiza el contexto actual de `assets`;
|
||||
5. captura una nueva `asset_version` tipo `CONTEXT_CHANGED`;
|
||||
6. inserta el nuevo intervalo;
|
||||
7. registra auditoría `ASSET_CONTEXT_CHANGED`.
|
||||
|
||||
## Consulta histórica
|
||||
|
||||
Nuevo endpoint:
|
||||
|
||||
`GET /api/v3/assets/:id/context-history`
|
||||
|
||||
El panel de Inventarios muestra contexto vigente e intervalos anteriores con motivo y vigencia.
|
||||
|
||||
`AssetTemporalService` también consulta `asset_context_history`, por lo que al pedir un activo a una fecha determinada reemplaza padre, Área y Operadora por los que estaban vigentes en ese instante.
|
||||
|
||||
## Permisos iniciales
|
||||
|
||||
`assets.manage_context` queda asignado por defecto a `admin` y `supervisor`. El Inspector conserva las altas de campo y las correcciones provisionales, pero no puede transferir un Inventario consolidado.
|
||||
|
||||
## Reglas preservadas
|
||||
|
||||
- Una visita = una Acta.
|
||||
- Actas cerradas no se modifican.
|
||||
- Hallazgos originales no se reescriben.
|
||||
- Una conciliación de alta de campo no sustituye referencias históricas.
|
||||
- SMTP puede continuar sin configurar.
|
||||
@@ -0,0 +1,89 @@
|
||||
# Fase D5.3.25 · Historial de verificaciones de hallazgos
|
||||
|
||||
## Objetivo
|
||||
|
||||
Convertir el seguimiento de verificaciones en una historia explícita de eventos. `nextControlOn` continúa siendo la proyección vigente usada por colas y planificación, pero deja de ser la única evidencia de lo ocurrido.
|
||||
|
||||
## Regla funcional
|
||||
|
||||
Cada hallazgo conserva todas las decisiones de control y todas las verificaciones sucesivas. Una nueva fecha nunca elimina la anterior y un resultado de campo ya registrado no puede sustituirse.
|
||||
|
||||
La secuencia puede contener tantas iteraciones como sean necesarias:
|
||||
|
||||
1. fecha de verificación definida por oficina;
|
||||
2. visita de verificación planificada;
|
||||
3. resultado de campo;
|
||||
4. nueva fecha si el hallazgo continúa abierto;
|
||||
5. nueva visita;
|
||||
6. nuevo resultado;
|
||||
7. cierre administrativo cuando corresponda.
|
||||
|
||||
## Ledger append-only
|
||||
|
||||
Nueva tabla `inspection_finding_verification_events`.
|
||||
|
||||
Registra eventos:
|
||||
|
||||
- `CONTROL_DATE_DEFINED`
|
||||
- `CONTROL_DATE_CHANGED`
|
||||
- `CONTROL_DATE_CLEARED`
|
||||
- `VISIT_PLANNED`
|
||||
- `RESULT_RECORDED`
|
||||
|
||||
Cada evento conserva fecha de ocurrencia, fecha anterior, fecha nueva, visita vinculada, resultado, observaciones, usuario y evidencia relacionada.
|
||||
|
||||
El rol de aplicación sólo tiene `SELECT` e `INSERT`. No puede actualizar ni borrar eventos.
|
||||
|
||||
## Antecedentes
|
||||
|
||||
La migración reconstruye eventos existentes desde:
|
||||
|
||||
- `inspection_finding_versions`, para cambios de `nextControlOn` realizados por oficina;
|
||||
- `inspection_finding_verification_visits`, para visitas y resultados ya registrados.
|
||||
|
||||
No se inventan eventos que no puedan deducirse de los antecedentes persistidos.
|
||||
|
||||
## Resultado de campo inmutable
|
||||
|
||||
Una fila `inspection_finding_verification_visits` representa un intento concreto dentro de una visita concreta. D5.3.25 impide registrar dos veces el resultado del mismo intento.
|
||||
|
||||
La protección existe en dos niveles:
|
||||
|
||||
- servicio: devuelve `VERIFICATION_RESULT_IMMUTABLE` si ya existe resultado;
|
||||
- base de datos: un trigger impide modificar los campos del resultado una vez que `result_recorded_at` quedó definido.
|
||||
|
||||
Una verificación posterior se realiza en una nueva visita y genera nuevos eventos, sin tocar la anterior.
|
||||
|
||||
## Proyección vigente
|
||||
|
||||
`inspection_findings.next_control_on` se conserva para búsquedas, dashboard y planificación. Cada cambio de ese campo se acompaña de un evento histórico dentro de la misma transacción.
|
||||
|
||||
Cuando un resultado:
|
||||
|
||||
- es `RESOLVED`, la proyección se limpia y el historial conserva el control realizado;
|
||||
- es `NOT_RESOLVED`, la proyección se limpia y oficina debe definir el siguiente control;
|
||||
- es `REQUIRES_NEW_DATE`, la nueva fecha se convierte en la proyección vigente y también queda registrada en el ledger.
|
||||
|
||||
## Consulta y web
|
||||
|
||||
`GET /api/v3/inspection-findings/:id/verification-history`
|
||||
|
||||
La ficha de Hallazgos incorpora “Historial completo de verificaciones” con:
|
||||
|
||||
- cambios de fecha;
|
||||
- visitas planificadas;
|
||||
- resultados sucesivos;
|
||||
- observaciones;
|
||||
- usuario;
|
||||
- enlace a cada visita;
|
||||
- cantidad de evidencias vinculadas.
|
||||
|
||||
## Reglas preservadas
|
||||
|
||||
- Una visita = una Acta.
|
||||
- Actas cerradas no se modifican.
|
||||
- El hallazgo original no se reescribe.
|
||||
- La primera respuesta de empresa continúa inmutable.
|
||||
- Las presentaciones posteriores siguen siendo append-only.
|
||||
- El cierre del hallazgo continúa siendo una decisión administrativa.
|
||||
- SMTP puede continuar pendiente sin bloquear esta fase.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Fase D5.3.2.1 · Hotfix de versionado de activos
|
||||
|
||||
Versión: `0.19.3-2.1`
|
||||
|
||||
## Motivo
|
||||
|
||||
Durante la creación del caso de desarrollo Mendoza, el primer alta de activo falló al insertar su revisión en `asset_versions` porque `version_number` llegó como `NULL` desde la ruta de captura de historial.
|
||||
|
||||
## Corrección
|
||||
|
||||
`AssetHistoryService.capture()` ya no depende del valor retornado por un `UPDATE ... RETURNING` para alimentar `version_number`. Ahora:
|
||||
|
||||
1. incrementa `assets.current_version` de forma atómica;
|
||||
2. lee explícitamente `current_version` dentro de la misma transacción;
|
||||
3. valida que sea un entero mayor o igual a 1;
|
||||
4. recién entonces crea la fila de `asset_versions`.
|
||||
|
||||
Se agregó un test de regresión específico para esta secuencia.
|
||||
|
||||
## Alcance
|
||||
|
||||
- No agrega migraciones.
|
||||
- No cambia el modelo funcional D5.3.2.
|
||||
- Conserva catálogo técnico, demo y limpiador.
|
||||
- Corrige una ruta transversal usada por altas y modificaciones de activos, no sólo el seed de desarrollo.
|
||||
@@ -0,0 +1,12 @@
|
||||
# Deploy D5.3.2
|
||||
|
||||
1. Subir `DH_V2_FASE_D5_3_2_SOURCE.zip` a `/var/www/dhv2.korexlabs.com/`.
|
||||
2. Extraer `scripts/deploy-phase-d5-3-2.sh` a `/root/deploy-dhv2-d532.sh`.
|
||||
3. Ejecutar preferentemente dentro de `tmux`.
|
||||
4. El deploy compila API, ejecuta tests, compila web y crea backup PRE antes de reemplazar producción.
|
||||
5. No hay migración nueva; `migration:show` debe terminar en `Pending migrations: no`.
|
||||
6. La aceptación debe finalizar con `ACEPTACIÓN DE FASE D5.3.2: OK`.
|
||||
7. Después del deploy, completar el catálogo técnico desde el dashboard.
|
||||
8. Crear el demo sólo si se desea validar visualmente el Maestro y las relaciones.
|
||||
|
||||
La limpieza real del demo no debe ejecutarse por rutina. El modo por defecto de `scripts/dev-clean-demo.sh` es simulación.
|
||||
@@ -0,0 +1,82 @@
|
||||
# D5.3.3 · Modelo operativo definitivo
|
||||
|
||||
Versión: `0.19.3-3`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Cerrar el modelo de Maestro antes de implementar hallazgos por activo y antes del rediseño UX.
|
||||
La fase mantiene la jerarquía padre/hijo como contención física y separa explícitamente:
|
||||
|
||||
- Área territorial;
|
||||
- Organización (empresa, UTE u otra figura);
|
||||
- rol operativo de una organización sobre un Área;
|
||||
- permiso/concesión/derecho legal sobre un Área;
|
||||
- estado de calidad del dato;
|
||||
- estado operativo del activo;
|
||||
- identificadores oficiales/externos;
|
||||
- documentos fuente;
|
||||
- composición histórica de una UTE.
|
||||
|
||||
## Compatibilidad
|
||||
|
||||
No se renombran columnas históricas como `operator_company_id` ni se reemplaza la tabla
|
||||
`area_company_relations`. Se amplían para conservar compatibilidad con D5.3–D5.3.2.1.
|
||||
La API incorpora alias semánticos de Organización sin romper las rutas existentes de Empresa.
|
||||
|
||||
## Reglas centrales
|
||||
|
||||
1. `parent_id` representa sólo jerarquía física.
|
||||
2. El tipo `Área / Concesión` pasa a mostrarse como `Área`.
|
||||
3. El tipo `Empresa / Operadora` pasa a mostrarse como `Organización`.
|
||||
4. Una Organización puede perfilarse como Empresa, UTE, entidad pública u otra figura.
|
||||
5. Una UTE conserva participantes, porcentaje, vigencia y documento fuente de forma histórica.
|
||||
6. Una relación Área–Organización tiene rol (`OPERATOR`, `CONCESSIONAIRE`, etc.).
|
||||
7. Sólo una relación activa con rol `OPERATOR` habilita la asignación exclusiva de activos.
|
||||
8. Las concesiones/permisos se registran como derechos legales separados del Área.
|
||||
9. `information_status` sigue indicando calidad/validación del registro.
|
||||
10. `operational_status` indica situación física/operativa y no reemplaza la calidad del dato.
|
||||
11. Un activo puede tener múltiples identificadores externos y múltiples documentos fuente.
|
||||
12. Cuenca y Departamento son clasificaciones del Área, no niveles obligatorios del árbol.
|
||||
|
||||
## Estado operativo
|
||||
|
||||
- `UNKNOWN`
|
||||
- `IN_SERVICE`
|
||||
- `TEMPORARILY_OUT_OF_SERVICE`
|
||||
- `OUT_OF_SERVICE`
|
||||
- `DECOMMISSIONED`
|
||||
- `ABANDONED`
|
||||
|
||||
## Registro documental
|
||||
|
||||
Se agregan:
|
||||
|
||||
- `source_documents`
|
||||
- `asset_source_documents`
|
||||
- `asset_external_identifiers`
|
||||
- `organization_profiles`
|
||||
- `organization_memberships`
|
||||
- `area_legal_rights`
|
||||
- `area_legal_right_organizations`
|
||||
|
||||
Todas las relaciones sensibles conservan vigencia histórica y no dependen de borrado físico en
|
||||
operación normal.
|
||||
|
||||
## UI de esta fase
|
||||
|
||||
D5.3.3 sólo expone el estado operativo y actualiza la semántica Área/Organización en las pantallas
|
||||
existentes. La administración intuitiva de documentos, UTE, derechos e identificadores se realizará
|
||||
en D5.3.4 dentro del nuevo Asset Center, para no agregar una pantalla técnica temporal que luego
|
||||
haya que descartar.
|
||||
|
||||
## Datos de desarrollo
|
||||
|
||||
El caso `DH-DEV-DEMO` se actualiza para:
|
||||
|
||||
- registrar el Informe Técnico 124/2026 como documento fuente de prueba;
|
||||
- vincular ese documento con Área, Organización, Planta y Tanques;
|
||||
- registrar la Organización de prueba con perfil `COMPANY`;
|
||||
- utilizar una relación Área–Organización con rol `OPERATOR`;
|
||||
- marcar TK-57 y TK-58 como `OUT_OF_SERVICE`, según el caso de prueba.
|
||||
|
||||
El limpiador protegido incorpora las nuevas tablas y sigue siendo dry-run por defecto.
|
||||
@@ -0,0 +1,19 @@
|
||||
# Deploy D5.3.3
|
||||
|
||||
La entrega incluye `scripts/deploy-phase-d5-3-3.sh`.
|
||||
|
||||
El deploy:
|
||||
|
||||
1. descomprime la entrega en staging;
|
||||
2. compila API y ejecuta tests antes de tocar producción;
|
||||
3. compila el frontend en staging;
|
||||
4. genera backup PRE de base y source;
|
||||
5. instala el source;
|
||||
6. construye imágenes finales;
|
||||
7. muestra y aplica la migración D5.3.3 sólo si está pendiente;
|
||||
8. verifica que no queden migraciones pendientes;
|
||||
9. recrea API/web y espera health;
|
||||
10. ejecuta aceptación automática y genera backup POST.
|
||||
|
||||
Ejecutar el script dentro de `tmux`. El `set -Eeuo pipefail` vive dentro del script y no se pega
|
||||
en la shell SSH interactiva.
|
||||
@@ -0,0 +1,66 @@
|
||||
# D5.3.4 · Asset Center y administración intuitiva
|
||||
|
||||
Versión: `0.19.3-4`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Reducir la complejidad visible del Maestro y de la administración sin simplificar el modelo de datos definido en D5.3.3.
|
||||
La regla de diseño de esta fase es: **modelo completo, interfaz simple**.
|
||||
|
||||
## Asset Center
|
||||
|
||||
`Activos` pasa a ser el punto de entrada único al Maestro y ofrece:
|
||||
|
||||
- búsqueda por nombre, código DH e identificadores externos vigentes;
|
||||
- vistas Lista, Jerarquía, Mapa, Historial y Consulta temporal;
|
||||
- filtros Área → Operadora, tipo, estado del dato y estado operativo;
|
||||
- vistas rápidas para pendientes de validar, sin ubicación y fuera de servicio;
|
||||
- tabla compacta orientada al uso cotidiano;
|
||||
- jerarquía física navegable conservando `parent_id` como única relación de contención.
|
||||
|
||||
La API agrega `GET /api/v3/assets/tree`, protegido con `assets.read`, que devuelve los activos coincidentes junto con sus ancestros físicos. La respuesta se limita a 5.000 nodos y avisa si fue truncada.
|
||||
|
||||
## Alta y detalle de activos
|
||||
|
||||
- alta contextual desde cualquier activo con `Agregar activo aquí`;
|
||||
- herencia del padre y, cuando corresponde, del contexto Área–Operadora;
|
||||
- búsqueda de padre compatible en lugar de depender de un listado fijo;
|
||||
- detalle organizado por pestañas: Resumen, Ubicación, Documentos y registro, Archivos e Historial;
|
||||
- estado del dato y estado operativo mostrados como conceptos separados.
|
||||
|
||||
## Registro documental e institucional
|
||||
|
||||
El modelo D5.3.3 se expone en una interfaz administrable desde el detalle del activo:
|
||||
|
||||
- identificadores externos;
|
||||
- documentos fuente;
|
||||
- perfil de Organización;
|
||||
- composición histórica de UTE;
|
||||
- permisos y concesiones del Área;
|
||||
- participantes de los derechos legales.
|
||||
|
||||
## Configuración del Maestro
|
||||
|
||||
La pantalla de tipos prioriza nombre, descripción y comportamiento comprensible.
|
||||
Código interno, rol operativo, posibilidad de raíz y matriz de padres permitidos quedan dentro de `Configuración avanzada`.
|
||||
|
||||
## Roles y permisos
|
||||
|
||||
Los permisos se presentan primero con nombres funcionales en castellano y el código técnico queda como referencia secundaria.
|
||||
|
||||
## Dashboard y navegación
|
||||
|
||||
El Inicio prioriza operación:
|
||||
|
||||
- inspecciones planificadas;
|
||||
- controles vencidos;
|
||||
- hallazgos abiertos;
|
||||
- activos pendientes de validar;
|
||||
- activos sin ubicación;
|
||||
- respuestas pendientes y próximos controles.
|
||||
|
||||
La navegación lateral se agrupa en Operación, Seguimiento, Maestro, Administración y Sistema. Mapa/Historial/Consulta temporal dejan de competir como módulos principales y pasan a ser vistas del Asset Center.
|
||||
|
||||
## Compatibilidad
|
||||
|
||||
D5.3.4 no agrega una migración propia. Si D5.3.3 aún estuviera pendiente, el deploy aplica las migraciones incluidas en la entrega antes de levantar la nueva versión.
|
||||
@@ -0,0 +1,19 @@
|
||||
# Deploy D5.3.4
|
||||
|
||||
La entrega incluye `scripts/deploy-phase-d5-3-4.sh`.
|
||||
|
||||
El deploy trabaja en staging antes de modificar producción:
|
||||
|
||||
1. descomprime la entrega;
|
||||
2. compila API;
|
||||
3. ejecuta todos los tests de API;
|
||||
4. compila el frontend;
|
||||
5. genera backup PRE de base y source;
|
||||
6. instala el source validado;
|
||||
7. construye imágenes finales;
|
||||
8. aplica cualquier migración pendiente incluida en la línea D5.3;
|
||||
9. recrea API/web y espera health;
|
||||
10. ejecuta aceptación D5.3.4;
|
||||
11. genera backup POST.
|
||||
|
||||
Ejecutar dentro de `tmux`. No pegar `set -Eeuo pipefail` en la shell SSH interactiva; el modo estricto vive dentro del script.
|
||||
@@ -0,0 +1,110 @@
|
||||
# DH V2 · Fase D5.3.5 — Centro de Importaciones y escalabilidad
|
||||
|
||||
Versión: `0.19.3-5`
|
||||
|
||||
## Objetivo
|
||||
|
||||
D5.3.5 parte de D5.3.4 ya desplegada y adapta el Maestro a volúmenes y formatos reales recibidos por la Dirección de Hidrocarburos.
|
||||
|
||||
La fase tiene dos objetivos:
|
||||
|
||||
1. evitar que el Asset Center intente cargar árboles completos de miles de activos;
|
||||
2. incorporar un Centro de Importaciones que permita analizar XLSX/CSV de forma trazable antes de decidir qué registros se incorporan al Maestro.
|
||||
|
||||
## Regla de seguridad de esta fase
|
||||
|
||||
**D5.3.5 NO crea ni modifica activos desde una importación.**
|
||||
|
||||
Un archivo subido:
|
||||
|
||||
1. se conserva con SHA-256;
|
||||
2. se registra como documento fuente;
|
||||
3. se inspecciona y detecta el formato;
|
||||
4. se normalizan las filas en una capa de staging;
|
||||
5. se detectan advertencias y conflictos;
|
||||
6. se muestra una vista previa en el dashboard.
|
||||
|
||||
La aplicación efectiva al Maestro queda deliberadamente fuera de esta fase.
|
||||
|
||||
## Perfiles iniciales
|
||||
|
||||
### `MENDOZA_INVENTORY_V1`
|
||||
|
||||
Reconoce el esquema general utilizado en inventarios de instalaciones con campos equivalentes a:
|
||||
|
||||
- Item;
|
||||
- Área / Yacimiento;
|
||||
- Instalación;
|
||||
- Sub instalación;
|
||||
- Equipo;
|
||||
- Denominación;
|
||||
- Ubicación;
|
||||
- N° ID / Inventario;
|
||||
- Cantidad;
|
||||
- Especificaciones técnicas;
|
||||
- Estado.
|
||||
|
||||
El análisis conserva el valor original y propone, cuando es seguro, normalizaciones auxiliares para:
|
||||
|
||||
- familia técnica;
|
||||
- clase/tipo de fuente;
|
||||
- fabricante/modelo;
|
||||
- estado operativo sugerido;
|
||||
- condición sugerida.
|
||||
|
||||
Los valores ambiguos (`SI/NO`, `S/N`, `Bueno`, etc.) no se transforman automáticamente en un estado operativo definitivo.
|
||||
|
||||
### `MENDOZA_YACIMIENTOS_V1`
|
||||
|
||||
Reconoce tablas de referencia con Yacimiento, Área, Departamento, tipo de derecho y Operadora.
|
||||
|
||||
## Conflictos detectables
|
||||
|
||||
Entre otros:
|
||||
|
||||
- campos estructurales faltantes;
|
||||
- cantidad inválida;
|
||||
- cantidad agrupada mayor a uno;
|
||||
- estado fuente que requiere mapeo;
|
||||
- ID de inventario repetido;
|
||||
- mismo ID de inventario en ubicaciones diferentes;
|
||||
- formato no reconocido.
|
||||
|
||||
La repetición de un ID no se interpreta automáticamente como duplicado real, traslado o error: se deriva a revisión.
|
||||
|
||||
## Persistencia
|
||||
|
||||
Se incorporan:
|
||||
|
||||
- `asset_import_batches`;
|
||||
- `asset_import_rows`;
|
||||
- permisos `asset_imports.read` y `asset_imports.manage`;
|
||||
- índices trigram para búsqueda del Maestro.
|
||||
|
||||
Los lotes no tienen DELETE para el rol de ejecución de la aplicación. Cancelar un lote cambia su estado y conserva evidencia y archivo para auditoría.
|
||||
|
||||
## Asset Center escalable
|
||||
|
||||
D5.3.4 incluía un árbol completo con límite de seguridad. D5.3.5 mantiene ese endpoint por compatibilidad, pero el dashboard utiliza ahora `GET /assets/tree-children`.
|
||||
|
||||
La jerarquía:
|
||||
|
||||
- carga sólo el primer nivel;
|
||||
- consulta hijos al expandir;
|
||||
- limita cada nivel a 200 filas;
|
||||
- usa filtros y búsqueda del servidor;
|
||||
- no intenta renderizar miles de nodos simultáneamente.
|
||||
|
||||
La búsqueda del Maestro se amplía a datos relevantes como identificadores externos y ciertos atributos configurables (fabricante, modelo, número de serie y ubicación fuente).
|
||||
|
||||
## Fuera de alcance
|
||||
|
||||
D5.3.5 no:
|
||||
|
||||
- crea activos desde filas de importación;
|
||||
- decide automáticamente jerarquías ambiguas por empresa;
|
||||
- crea 70+ tipos de activo a partir de denominaciones crudas;
|
||||
- modifica hallazgos/checklists;
|
||||
- reemplaza el valor original de una fuente.
|
||||
|
||||
Estos puntos se resolverán progresivamente con perfiles específicos y taxonomía normalizada antes de D5.4.
|
||||
@@ -0,0 +1,13 @@
|
||||
# DH V2 · Fase D5.3.5.1 — Hotfix compilación Centro de Importaciones
|
||||
|
||||
Versión: `0.19.3-5.1`
|
||||
|
||||
## Motivo
|
||||
|
||||
El build de D5.3.5 fallaba con `TS4053` en `AssetImportsController.list`, `upload` y `cancel` porque el tipo inferido de retorno incluía `ImportBatchRow`, declarado como interfaz privada dentro de `asset-imports.service.ts`.
|
||||
|
||||
## Corrección
|
||||
|
||||
`ImportBatchRow` pasa a ser un contrato exportado. Esto permite a TypeScript nombrarlo al emitir archivos `.d.ts` con `declaration: true`.
|
||||
|
||||
No se altera el esquema ni el comportamiento funcional del Centro de Importaciones. La migración de D5.3.5 continúa siendo la misma y se aplicará al desplegar este paquete si sigue pendiente.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Deploy D5.3.5 · v0.19.3-5
|
||||
|
||||
Prerequisito: D5.3.4 instalada o source compatible con su esquema.
|
||||
|
||||
## Entrega
|
||||
|
||||
`DH_V2_FASE_D5_3_5_SOURCE.zip`
|
||||
|
||||
## Despliegue recomendado
|
||||
|
||||
El ZIP incluye `scripts/deploy-phase-d5-3-5.sh`.
|
||||
|
||||
Extraer sólo ese script y ejecutarlo dentro de `tmux`. El script:
|
||||
|
||||
1. descomprime en staging;
|
||||
2. compila API;
|
||||
3. ejecuta tests;
|
||||
4. compila web;
|
||||
5. crea backup PRE;
|
||||
6. instala source;
|
||||
7. construye imágenes finales;
|
||||
8. aplica migraciones pendientes;
|
||||
9. recrea API/web;
|
||||
10. ejecuta aceptación D5.3.5;
|
||||
11. crea backup POST.
|
||||
|
||||
## Aceptación esperada
|
||||
|
||||
```text
|
||||
ACEPTACIÓN DE FASE D5.3.5: OK
|
||||
```
|
||||
|
||||
Y health con:
|
||||
|
||||
```text
|
||||
version: 0.19.3-5
|
||||
phase: D5.3.5
|
||||
```
|
||||
@@ -0,0 +1,32 @@
|
||||
# DH V2 · D5.3.6 · Normalización, matching y preview
|
||||
|
||||
## Objetivo
|
||||
|
||||
Convertir el Centro de Importaciones de D5.3.5 en una herramienta de conciliación segura antes de habilitar escrituras al Maestro.
|
||||
|
||||
## Reglas funcionales
|
||||
|
||||
1. Ningún análisis o conciliación de D5.3.6 crea, actualiza ni elimina activos.
|
||||
2. La clasificación original de cada empresa se conserva en `raw_data` y `normalized_data`.
|
||||
3. La normalización técnica es una sugerencia controlada: familia + subtipo.
|
||||
4. El estado informado por la fuente no se pisa: se conserva y, cuando es inequívoco, se propone estado operativo o condición.
|
||||
5. El matching inicial es deliberadamente conservador:
|
||||
- ID de inventario contra identificadores externos activos;
|
||||
- ID de inventario contra código DH;
|
||||
- Área + Yacimiento exactos para la tabla territorial;
|
||||
- nombre legal/nombre del activo exacto para Organización.
|
||||
6. Más de una coincidencia exacta genera revisión, nunca una fusión automática.
|
||||
7. La importación real al Maestro queda para D5.3.7.
|
||||
|
||||
## UX
|
||||
|
||||
El Centro muestra cuatro pasos: Análisis → Normalización → Conciliación → Importación.
|
||||
|
||||
- `MENDOZA_YACIMIENTOS_V1`: Área, Yacimiento, Departamento, Derecho, Operadora.
|
||||
- `MENDOZA_INVENTORY_V1`: estructura fuente, equipo, familia/subtipo normalizados, ID, cantidad y estados.
|
||||
|
||||
`Listas` pasa a llamarse `Analizables` para no implicar que la fila ya está autorizada para importar.
|
||||
|
||||
## Sin migración
|
||||
|
||||
La fase reutiliza `asset_import_batches.analysis`, `asset_import_rows.matched_asset_id`, `suggested_action`, `status` y `normalized_data` creados en D5.3.5.
|
||||
@@ -0,0 +1,19 @@
|
||||
# DH V2 · D5.3.6.3 · Hotfix de renderizado de conciliación
|
||||
|
||||
Hotfix acumulativo sobre D5.3.6.
|
||||
|
||||
## Corrección
|
||||
|
||||
El resumen tipado `ImportReconciliationSummary` no era asignable directamente a `Record<string, unknown>` exigido por `AuditService`. La conciliación ahora entrega una copia como objeto plano (`afterData: { ...summary }`), conservando exactamente los mismos campos y sin modificar la lógica de matching.
|
||||
|
||||
## Alcance
|
||||
|
||||
- Sin migraciones nuevas.
|
||||
- Sin cambios en el modelo de datos.
|
||||
- Sin escrituras al Maestro durante análisis/conciliación.
|
||||
- Agrega una prueba de regresión para este contrato.
|
||||
|
||||
|
||||
## Hotfix D5.3.6.3
|
||||
|
||||
Corrige TS2322 en `AssetImportsPage.tsx`: el valor `analysis.reconciliation` tiene tipo `unknown` y no debe renderizarse directamente mediante `&&`. Se convierte explícitamente a booleano para que el resultado JSX sea `ReactNode` válido. No cambia la lógica de conciliación ni escribe en el Maestro.
|
||||
@@ -0,0 +1,125 @@
|
||||
# Fase D5.3.7 — Plan e importación transaccional
|
||||
|
||||
Versión: `0.19.3-7.1`
|
||||
|
||||
## Objetivo
|
||||
|
||||
D5.3.7 agrega la capa de seguridad que faltaba entre la conciliación fila-a-fila de D5.3.6 y la escritura del Maestro. Un archivo analizado ya no se interpreta como una colección directa de `INSERT`: primero se transforma en un **plan de entidades únicas y relaciones**, se resuelven revisiones obligatorias y recién entonces un usuario con permiso explícito puede aplicar el lote en una sola transacción.
|
||||
|
||||
El flujo queda:
|
||||
|
||||
1. Análisis.
|
||||
2. Normalización.
|
||||
3. Conciliación preliminar contra Maestro.
|
||||
4. Plan de importación por entidad.
|
||||
5. Confirmación explícita.
|
||||
6. Aplicación transaccional.
|
||||
|
||||
## Principios de seguridad
|
||||
|
||||
- `WARNING` y `CONFLICT` nunca se convierten silenciosamente en altas automáticas.
|
||||
- Un plan con cualquier ítem `REVIEW` queda bloqueado.
|
||||
- La confirmación utiliza el `plan_hash`; si el plan cambió, la aplicación se rechaza como obsoleta.
|
||||
- La aplicación completa corre dentro de una única transacción PostgreSQL.
|
||||
- Los identificadores externos se vuelven a validar justo antes de insertar para reducir carreras entre planificación y aplicación.
|
||||
- Una coincidencia exacta no se acepta si el activo existente pertenece a otra Área/Operadora; D5.3.7 no reubica ni reasigna activos existentes silenciosamente.
|
||||
- Las reglas de jerarquía y el contexto Área + Operadora se vuelven a verificar antes de escribir activos.
|
||||
- La API separa `asset_imports.manage` de `asset_imports.apply`. Aplicar/revertir queda reservado inicialmente a Admin y Director.
|
||||
- La reversión es lógica: no borra activos del Maestro.
|
||||
|
||||
## Plan territorial Área / Yacimiento
|
||||
|
||||
El perfil `MENDOZA_YACIMIENTOS_V1` deduplica las filas en entidades y relaciones reales:
|
||||
|
||||
- Organizaciones.
|
||||
- Áreas.
|
||||
- Yacimientos.
|
||||
- Relaciones Área ↔ Operadora.
|
||||
|
||||
Por eso 230 filas no significan 230 altas. El mismo Área u Operadora puede participar en muchas filas y se representa una sola vez dentro del plan.
|
||||
|
||||
La coincidencia sigue siendo conservadora y normalizada para mayúsculas, signos y acentos. El nombre de Yacimiento no se trata como clave global: se evalúa dentro del Área.
|
||||
|
||||
`Tipo Concesión` y Departamento se preservan en el payload del plan y en la trazabilidad, pero D5.3.7 **no crea derechos legales automáticamente** porque el padrón no aporta por sí solo instrumento, vigencia y evidencia suficientes para construir esa capa con seguridad.
|
||||
|
||||
Cuando una organización comienza por `UTE`, el plan propone perfil de organización `UTE`; la composición interna y porcentajes de participación no se infieren de un nombre concatenado.
|
||||
|
||||
|
||||
El valor fuente `Sin Empresa Operadora` se interpreta como **ausencia explícita de operadora**, no como una empresa. Esos Yacimientos pueden quedar registrados en `DRAFT` dentro de su Área, sin contexto operativo Área + Operadora, preservando el literal fuente para una asignación posterior. Nunca se crea una organización ficticia con ese nombre.
|
||||
|
||||
Como referencia de validación del archivo real recibido (sin considerar coincidencias ya existentes en el Maestro), las 230 filas se descomponen en 64 Áreas, 230 pares Área/Yacimiento, 12 Organizaciones reales y 47 relaciones Área↔Operadora: 353 ítems de entidad/relación. Además, 26 Yacimientos traen explícitamente `Sin Empresa Operadora`. Los conteos que muestre producción pueden ser menores en `CREATE` si existen coincidencias válidas.
|
||||
|
||||
## Plan de inventario técnico
|
||||
|
||||
El perfil `MENDOZA_INVENTORY_V1` exige antes de planificar:
|
||||
|
||||
- seleccionar la Organización operadora existente;
|
||||
- confirmar/definir un namespace de identificadores externos, por ejemplo `PSENERGY`.
|
||||
|
||||
El plan usa ese namespace para distinguir inventarios que pueden reutilizar el mismo número de identificación en fuentes distintas.
|
||||
|
||||
Los contenedores físicos se crean sólo cuando la fuente permite identificar una instancia concreta. Por ejemplo, de una ubicación como:
|
||||
|
||||
`MENDOZA / VIZCACHERAS / PTC / PTCVIZ01`
|
||||
|
||||
se puede proponer `PTCVIZ01`. En cambio categorías genéricas como `SET`, `EM`, `TRANSPORTE`, `OFICINA` o `ALMACEN` no se convierten silenciosamente en un activo por cada fila. Se agrupan en un único ítem estructural `[A VALIDAR] ...` por contexto, que requiere decidir si corresponde crear o vincular un contenedor real.
|
||||
|
||||
Las cantidades agrupadas, estados ambiguos y conflictos de fuente quedan en revisión obligatoria.
|
||||
|
||||
## Acciones del plan
|
||||
|
||||
Cada ítem puede quedar en:
|
||||
|
||||
- `CREATE`: crear una entidad nueva.
|
||||
- `MATCH`: reutilizar una entidad existente del mismo tipo.
|
||||
- `REVIEW`: requiere intervención antes de aplicar.
|
||||
- `IGNORE`: sólo permitido para activos técnicos; no se permite romper la estructura ignorando Áreas, Organizaciones, Yacimientos o contenedores estructurales.
|
||||
|
||||
Las resoluciones manuales quedan registradas con usuario, fecha y motivo.
|
||||
|
||||
## Aplicación
|
||||
|
||||
El endpoint de aplicación exige:
|
||||
|
||||
- plan activo;
|
||||
- estado `READY`;
|
||||
- mismo `plan_hash` confirmado en pantalla;
|
||||
- permiso `asset_imports.apply`;
|
||||
- coincidencias todavía activas;
|
||||
- Operadora todavía activa;
|
||||
- IDs externos todavía disponibles;
|
||||
- tipos y reglas padre/hijo vigentes;
|
||||
- contexto operativo completo.
|
||||
|
||||
La aplicación crea en orden las entidades raíz, relaciones operativas, Yacimientos, instalaciones y activos técnicos. Las altas quedan en estado de información `DRAFT`, origen `IMPORT`, con documento fuente, procedencia e historial inicial.
|
||||
|
||||
Los ítems que ya coinciden con Maestro **no son modificados** por esta fase.
|
||||
|
||||
## Reversión
|
||||
|
||||
`Revertir lote` funciona sólo sobre el plan aplicado activo y dentro de una transacción.
|
||||
|
||||
La reversión:
|
||||
|
||||
- cierra identificadores externos creados por el lote;
|
||||
- inactiva lógicamente los activos creados por el lote;
|
||||
- retira su contexto operativo antes de inactivarlos;
|
||||
- cierra las relaciones Área ↔ Operadora creadas por el lote;
|
||||
- registra nuevas versiones de estado;
|
||||
- limpia la referencia `imported_asset_id` de las filas del lote;
|
||||
- conserva toda la trazabilidad del plan.
|
||||
|
||||
La reversión se bloquea si activos posteriores, relaciones externas, relevamientos o inspecciones ya dependen de entidades creadas por el lote.
|
||||
|
||||
## Limitaciones deliberadas
|
||||
|
||||
D5.3.7 no intenta todavía:
|
||||
|
||||
- interpretar automáticamente integrantes y porcentajes de una UTE a partir del nombre;
|
||||
- crear concesiones/permisos legales sin instrumento y vigencia verificables;
|
||||
- modificar activos existentes que hagan `MATCH`;
|
||||
- resolver de forma probabilística alias o nombres parecidos;
|
||||
- convertir todos los términos del inventario fuente en niveles de jerarquía;
|
||||
- persistir una taxonomía completa de condición técnica cuando la fuente sólo trae textos ambiguos.
|
||||
|
||||
Estas restricciones son intencionales para evitar contaminación masiva del Maestro.
|
||||
@@ -0,0 +1,60 @@
|
||||
# Fase D5.3.7.2 — Plan relacional normalizado
|
||||
|
||||
Versión: `0.19.3-7.2`
|
||||
|
||||
## Objetivo
|
||||
|
||||
Evitar que una importación replique como texto datos maestros que se repiten en cientos de filas. El perfil territorial de Mendoza pasa de una lectura por fila a un plan compuesto por entidades únicas y relaciones explícitas.
|
||||
|
||||
## Modelo aplicado a `Tablas de yacimiento.xlsx`
|
||||
|
||||
Cada fila fuente conserva su trazabilidad, pero el plan deduplica y separa:
|
||||
|
||||
- **Departamentos**: catálogo normalizado `administrative_departments`; un Departamento se crea una sola vez.
|
||||
- **Organizaciones / Operadoras**: activos de rol COMPANY, con clave canónica que normaliza siglas con puntos (`E.M.E.S.A.` → `emesa`, `S.R.L.` → `srl`) sin fusionar nombres jurídicos semánticamente distintos.
|
||||
- **Áreas**: una entidad por Área.
|
||||
- **Yacimientos**: una entidad contextual por `Área + Yacimiento`; el nombre de Yacimiento no es clave global.
|
||||
- **Área ↔ Departamento**: relación histórica explícita en `area_department_relations`.
|
||||
- **Área ↔ Operadora**: relación histórica existente `area_company_relations`, rol `OPERATOR`.
|
||||
- **Tipo de derecho**: se normaliza al enum jurídico ya existente (`EXPLOITATION_CONCESSION`, `EXPLORATION_PERMIT`, `TRANSPORT_CONCESSION`, `OTHER`), sin duplicar un catálogo paralelo.
|
||||
- **Derecho / concesión**: entidad jurídica `area_legal_rights`, inicialmente `PENDING` cuando la fuente sólo informa tipo y Área pero no instrumento o vigencia.
|
||||
- **Derecho ↔ Organización**: relación `area_legal_right_organizations` con rol `OPERATOR`. No se infiere titularidad, participación ni tenencia.
|
||||
|
||||
`Sin Empresa Operadora` sigue representando ausencia explícita y nunca se convierte en una Organización.
|
||||
|
||||
## Referencia sobre el archivo real
|
||||
|
||||
Sobre un Maestro vacío, el archivo de 230 filas produce conceptualmente:
|
||||
|
||||
- 7 Departamentos únicos;
|
||||
- 12 Organizaciones reales (13 valores fuente menos `Sin Empresa Operadora`);
|
||||
- 64 Áreas;
|
||||
- 64 relaciones Área ↔ Departamento;
|
||||
- 230 pares contextuales Área + Yacimiento;
|
||||
- 47 relaciones Área ↔ Operadora;
|
||||
- 64 derechos normalizados por Área + tipo;
|
||||
- 47 relaciones Derecho ↔ Organización.
|
||||
|
||||
Total de referencia: **535 operaciones de plan**, antes de descontar coincidencias que ya existan en el Maestro.
|
||||
|
||||
El archivo contiene 26 filas con `Sin Empresa Operadora`; esas filas no generan una empresa ficticia.
|
||||
|
||||
## Vista del plan
|
||||
|
||||
El frontend agrupa las operaciones en:
|
||||
|
||||
1. Territorio.
|
||||
2. Organizaciones.
|
||||
3. Marco jurídico.
|
||||
4. Inventario técnico.
|
||||
|
||||
Cada clase de entidad muestra Crear / Coincidir / Revisar / Ignorar / Total y dispone de `Ver detalle`, paginado, para revisar las entidades únicas y sus filas fuente antes de aplicar.
|
||||
|
||||
## Seguridad
|
||||
|
||||
- El plan se calcula antes de escribir el Maestro.
|
||||
- Las revisiones bloquean la aplicación.
|
||||
- La aplicación sigue siendo transaccional y validada por hash.
|
||||
- Los objetos relacionales se revalidan antes de aplicar.
|
||||
- El rollback es lógico: finaliza relaciones, revoca derechos creados por el lote, inactiva Departamentos creados por el lote y no ejecuta `DELETE FROM assets`.
|
||||
- El usuario debe validar visualmente el plan real antes de pulsar `APLICAR`.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Fase D5.3.7.2.1 — Hotfix de regresión del plan relacional
|
||||
|
||||
Versión: `0.19.3-7.2.1`
|
||||
|
||||
Hotfix acumulativo sobre D5.3.7.2. No cambia el modelo relacional ni la migración.
|
||||
|
||||
## Corrección
|
||||
|
||||
El test heredado `D5.3.7 keeps the explicit no-operator sentinel...` todavía esperaba que la clave de organización usara `plainImportKey(operator)`. D5.3.7.2 reemplazó deliberadamente esa clave por `organizationImportKey(operator)` para deduplicar variantes de siglas y puntuación (`E.M.E.S.A.` / `EMESA`, `S.R.L.` / `SRL`) sin crear una organización ficticia para el sentinel `Sin Empresa Operadora`.
|
||||
|
||||
La implementación era correcta; se actualiza únicamente la expectativa de regresión y el versionado del hotfix.
|
||||
|
||||
La migración sigue siendo `PhaseD5372RelationalTerritoryPlan1787767200000`.
|
||||
@@ -0,0 +1,21 @@
|
||||
# D5.3.7.2.2 — Hotfix de aplicación del plan relacional
|
||||
|
||||
## Problema corregido
|
||||
|
||||
Durante `POST /api/v3/asset-imports/:id/apply`, el UPDATE por lote de `asset_import_rows.imported_asset_id` construía `VALUES` con `row_number` sin casteo explícito. PostgreSQL podía inferir esa columna como `text` y fallaba al compararla con `asset_import_rows.row_number` (`integer`):
|
||||
|
||||
`operator does not exist: integer = text`
|
||||
|
||||
## Corrección
|
||||
|
||||
Cada número de fila del `VALUES` se tipa explícitamente como `integer`:
|
||||
|
||||
```sql
|
||||
($n::integer, $m::uuid)
|
||||
```
|
||||
|
||||
La operación sigue dentro de la misma transacción de importación. No cambia el modelo relacional ni requiere migración nueva.
|
||||
|
||||
## Regresión
|
||||
|
||||
Se agregó una prueba que exige el casteo `::integer` en `updateImportedRows`.
|
||||
@@ -0,0 +1,25 @@
|
||||
# D5.3.7.2.3 — Hotfix de persistencia del plan aplicado
|
||||
|
||||
## Problema corregido
|
||||
|
||||
La aplicación relacional ya superaba la actualización de `asset_import_rows`, pero al marcar un activo creado como aplicado se reutilizaba el mismo parámetro SQL para dos columnas de tipos distintos:
|
||||
|
||||
- `applied_asset_id`: `uuid`
|
||||
- `applied_object_id`: `varchar(255)`
|
||||
|
||||
PostgreSQL rechazaba la sentencia con `inconsistent types deduced for parameter $2` (`uuid versus character varying`).
|
||||
|
||||
## Corrección
|
||||
|
||||
El parámetro se tipa una sola vez como UUID y su representación textual se deriva explícitamente para `applied_object_id`:
|
||||
|
||||
```sql
|
||||
applied_asset_id = $2::uuid,
|
||||
applied_object_id = ($2::uuid)::text
|
||||
```
|
||||
|
||||
La operación continúa dentro de la misma transacción. El fallo previo no dejó datos parciales y esta fase no requiere migración nueva.
|
||||
|
||||
## Regresión
|
||||
|
||||
Se agregó una prueba que impide volver a usar el mismo parámetro sin casteos compatibles en ambas columnas.
|
||||
@@ -0,0 +1,24 @@
|
||||
# D5.3.7.2.4 — Protección de planes obsoletos e idempotencia
|
||||
|
||||
Versión: `0.19.3-7.2.4`.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Evitar que un plan READY generado contra un estado anterior del Maestro pueda aplicarse después de que otro lote o una edición administrativa haya modificado los datos maestros.
|
||||
|
||||
## Cambios
|
||||
|
||||
- El plan guarda `masterStateHash` dentro de su resumen.
|
||||
- El hash representa el estado relevante de activos, organizaciones, Departamentos, relaciones operativas, derechos y IDs externos.
|
||||
- La generación toma una huella antes y después de construir el plan; si el Maestro cambia durante la generación, se aborta.
|
||||
- La aplicación compara la huella actual contra la guardada **antes de cualquier escritura**.
|
||||
- Los planes READY de versiones anteriores, que no tienen huella, se consideran obsoletos y deben regenerarse.
|
||||
- El frontend muestra `Plan obsoleto` y deshabilita `Confirmar y aplicar` hasta regenerar.
|
||||
|
||||
## Caso real cubierto
|
||||
|
||||
Si un lote A aplica 64 Áreas, 12 Organizaciones, 230 Yacimientos y sus relaciones mientras existe un lote B con un plan READY anterior, el lote B ya no puede volver a crear esas entidades. Debe conciliar y regenerar; el nuevo plan debe resolverlas como coincidencias.
|
||||
|
||||
## Migraciones
|
||||
|
||||
No agrega migraciones. La huella se almacena en el JSON `summary` ya existente del plan.
|
||||
@@ -0,0 +1,35 @@
|
||||
# D5.3.7.2.5 — Conciliación y revisión más claras
|
||||
|
||||
Versión: `0.19.3-7.2.5`.
|
||||
|
||||
## Objetivo
|
||||
|
||||
Hacer que el Centro de Importaciones explique en lenguaje administrativo qué se va a crear, qué registro existente se reutiliza y por qué un elemento requiere intervención humana antes de aplicar.
|
||||
|
||||
## Cambios de interfaz
|
||||
|
||||
- `Coincidir` pasa a **Usar existentes** y explica que esos objetos ya están en el Maestro y no se duplican.
|
||||
- Los cuatro KPI del plan son accionables: **Crear nuevos**, **Usar existentes**, **Requieren revisión** e **Ignorar**.
|
||||
- Al abrir **Usar existentes** se lista la entidad, el criterio seguro utilizado por el motor de conciliación y el identificador del objeto encontrado.
|
||||
- El desglose relacional usa la misma terminología clara.
|
||||
- La conciliación preliminar por filas habla de **Nuevas** y **Ya existentes**.
|
||||
|
||||
## Revisión obligatoria
|
||||
|
||||
La sección se renombra **Decisiones pendientes antes de importar** y distingue:
|
||||
|
||||
- **Decisiones directas**: requieren una decisión humana real.
|
||||
- **Dependencias**: no deben forzarse; normalmente se recalculan después de resolver un padre o contexto y regenerar el plan.
|
||||
|
||||
Cada tarjeta muestra:
|
||||
|
||||
- tipo de entidad y filas fuente;
|
||||
- nombre provisional sin ocultar que `[A VALIDAR]` no es un nombre confirmado;
|
||||
- datos fuente relevantes (Área/Yacimiento, instalación, sector, equipo, familia, ID, cantidad, estado);
|
||||
- explicación del motivo;
|
||||
- qué debe revisar la persona;
|
||||
- acciones con nombres explícitos: **Vincular con existente**, **Crear como nuevo** o **Excluir de esta importación**, únicamente cuando la lógica ya las permite.
|
||||
|
||||
## Seguridad
|
||||
|
||||
No cambia la lógica de aplicación, matching, transacciones, permisos ni base de datos. No agrega migraciones. D5.3.7.2.4 sigue protegiendo contra planes obsoletos y duplicación.
|
||||
@@ -0,0 +1,21 @@
|
||||
# Deploy D5.3.7.2
|
||||
|
||||
Artefacto esperado: `DH_V2_FASE_D5_3_7_2_SOURCE.zip`
|
||||
|
||||
La fase es acumulativa sobre D5.3.7.1. El deploy:
|
||||
|
||||
1. verifica PostgreSQL healthy y espacio libre;
|
||||
2. descomprime a staging;
|
||||
3. compila API;
|
||||
4. ejecuta todos los tests API;
|
||||
5. compila web;
|
||||
6. crea backup PRE;
|
||||
7. instala source;
|
||||
8. construye imágenes finales;
|
||||
9. aplica la migración D5.3.7.2;
|
||||
10. recrea API/Web;
|
||||
11. ejecuta aceptación automática y backup POST.
|
||||
|
||||
La migración `PhaseD5372RelationalTerritoryPlan1787767200000` agrega el catálogo de Departamentos y su relación con Áreas, y extiende los tipos permitidos de ítems del plan.
|
||||
|
||||
Después del deploy no se debe pulsar `APLICAR` hasta regenerar y revisar el plan de `Tablas de yacimiento.xlsx`.
|
||||
@@ -0,0 +1,59 @@
|
||||
# Deploy D5.3.7
|
||||
|
||||
Artefacto esperado:
|
||||
|
||||
`DH_V2_FASE_D5_3_7_1_SOURCE.zip`
|
||||
|
||||
Ruta de producción:
|
||||
|
||||
`/var/www/dhv2.korexlabs.com`
|
||||
|
||||
## Seguridad del deploy
|
||||
|
||||
El script `scripts/deploy-phase-d5-3-7-1.sh` valida antes de modificar producción:
|
||||
|
||||
- espacio libre suficiente;
|
||||
- PostgreSQL `healthy` y aceptando conexiones;
|
||||
- ZIP y versiones esperadas;
|
||||
- build real de API en staging;
|
||||
- suite completa de tests API en staging;
|
||||
- build real del frontend en staging.
|
||||
|
||||
Sólo después crea backup PRE, instala el source, reconstruye imágenes y aplica la migración.
|
||||
|
||||
El chequeo de migraciones se imprime directamente; no se oculta dentro de una sustitución de shell. Esto facilita diagnosticar errores del contenedor `migrate`.
|
||||
|
||||
## Ejecución
|
||||
|
||||
Desde el directorio del sitio, extraer el script del ZIP y ejecutarlo preferentemente dentro de `tmux`:
|
||||
|
||||
```bash
|
||||
unzip -p DH_V2_FASE_D5_3_7_1_SOURCE.zip scripts/deploy-phase-d5-3-7-1.sh > /root/deploy-dhv2-d537.sh
|
||||
chmod +x /root/deploy-dhv2-d537.sh
|
||||
bash /root/deploy-dhv2-d537.sh 2>&1 | tee /root/deploy-dhv2-d537.log
|
||||
```
|
||||
|
||||
Resultado esperado:
|
||||
|
||||
`ACEPTACIÓN DE FASE D5.3.7: OK`
|
||||
|
||||
Health esperado:
|
||||
|
||||
- version `0.19.3-7.1`
|
||||
- phase `D5.3.7`
|
||||
- database `ok`
|
||||
|
||||
## Validación funcional posterior
|
||||
|
||||
No aplicar masivamente un lote apenas termina el deploy.
|
||||
|
||||
Orden recomendado:
|
||||
|
||||
1. Abrir `Tablas de yacimiento.xlsx`.
|
||||
2. Ejecutar nuevamente Conciliación.
|
||||
3. Generar Plan.
|
||||
4. Revisar el desglose por Organizaciones / Áreas / Yacimientos / Relaciones y enviar captura para validar.
|
||||
5. Sólo después de validar el plan territorial, confirmar su aplicación.
|
||||
6. Reconciliar nuevamente PSEnergy, porque el Maestro ya habrá cambiado.
|
||||
7. Seleccionar la operadora correcta y namespace `PSENERGY`.
|
||||
8. Generar y resolver el plan técnico antes de cualquier aplicación.
|
||||
@@ -0,0 +1,47 @@
|
||||
# D5.3.8 — Estructura local de inventario según la fuente
|
||||
|
||||
Versión: `0.19.3-8`.
|
||||
|
||||
## Motivo
|
||||
|
||||
Los inventarios reales muestran que, después del contexto territorial Área/Yacimiento, cada operadora puede usar su propia nomenclatura para instalaciones, sectores, baterías, plantas, SET, PTC, PTA y otros agrupadores. Esa terminología no debe convertirse automáticamente en una jerarquía universal de DH.
|
||||
|
||||
D5.3.8 preserva la estructura local declarada por la fuente y separa **identidad/nomenclatura de origen** de una futura **clasificación normalizada por DH**.
|
||||
|
||||
## Modelo
|
||||
|
||||
Se incorpora el tipo provisional `estructura_local` / **Estructura local (fuente)**. Es un activo estructural GENERIC y en DRAFT que puede colgar de Área, Yacimiento o Locación y actuar como padre de activos técnicos compatibles.
|
||||
|
||||
Sus atributos conservan:
|
||||
|
||||
- nivel informado por la fuente;
|
||||
- clasificación local informada;
|
||||
- ruta/nomenclatura de origen.
|
||||
|
||||
La identidad nunca es global por nombre: se concilia dentro del contexto Área/Yacimiento + Operadora + padre.
|
||||
|
||||
## Importador de inventarios
|
||||
|
||||
Para PSEnergy y perfiles equivalentes:
|
||||
|
||||
- si la ubicación contiene una instancia local concreta (`BATATA01`, `PTCVIZ01`, etc.), se conserva esa denominación;
|
||||
- si sólo existen categorías locales (`ENERGIA / SET`, `YACIMIENTO / BATERIA`), se conserva el grupo provisional sin afirmar que sea una instalación física universal;
|
||||
- `pozo`, `ducto` y `colector` continúan anclándose directamente al contexto territorial para evitar inferir una jerarquía física incorrecta;
|
||||
- ya no se generan nombres `[A VALIDAR]` para inventar instalaciones;
|
||||
- la clasificación posterior puede cambiar sin perder el literal ni la ruta original.
|
||||
|
||||
## Ambigüedad territorial
|
||||
|
||||
Si un nombre como Atamisqui puede corresponder a más de un Área/Yacimiento válido, el plan genera **una sola decisión raíz por contexto**, no decenas de conflictos derivados.
|
||||
|
||||
La UI muestra las alternativas con su Área padre. La selección se guarda únicamente para ese lote. Al regenerar el plan se recalculan automáticamente estructura local, padres y activos dependientes.
|
||||
|
||||
Así, “falta instalación” o “padre sin resolver” dejan de presentarse como decisiones independientes cuando son sólo consecuencia de un Área/Yacimiento todavía ambiguo.
|
||||
|
||||
## Seguridad
|
||||
|
||||
La fase mantiene plan previo, huella de Maestro, protección contra plan obsoleto, aplicación transaccional, idempotencia, procedencia, reversión lógica y reglas de contexto operativo.
|
||||
|
||||
Agrega una migración para `LOCAL_STRUCTURE`, el tipo `estructura_local`, sus atributos y reglas de padres.
|
||||
|
||||
Antes de tocar producción el deploy crea el backup fuerte **INVENTARIO A REVISAR**.
|
||||
@@ -0,0 +1,64 @@
|
||||
# D5.3.9 — Revisión obligatoria clara
|
||||
|
||||
Versión: `0.19.3-9`.
|
||||
|
||||
## Motivo
|
||||
|
||||
D5.3.8 corrigió el modelo conceptual del inventario: la ambigüedad territorial se resuelve como una causa raíz y la nomenclatura propia de cada operadora se preserva como estructura local. Sin embargo, la interfaz todavía mostraba las decisiones humanas y sus consecuencias técnicas en una misma lista, lo que podía hacer pensar que cada instalación, padre o equipo debía resolverse manualmente.
|
||||
|
||||
D5.3.9 separa explícitamente **lo que una persona debe decidir** de **lo que el sistema recalcula automáticamente**.
|
||||
|
||||
## Cambios
|
||||
|
||||
### 1. Decisiones humanas vs. dependencias automáticas
|
||||
|
||||
El resumen del plan incorpora dos contadores adicionales:
|
||||
|
||||
- `directReviewItems`: decisiones que requieren intervención humana;
|
||||
- `dependencyReviewItems`: elementos bloqueados únicamente porque dependen de una decisión raíz.
|
||||
|
||||
El plan continúa bloqueado mientras exista cualquier `REVIEW`, por lo que no se debilita ninguna protección de aplicación.
|
||||
|
||||
### 2. Nueva pantalla de revisión obligatoria
|
||||
|
||||
La UI muestra tres pasos claros:
|
||||
|
||||
1. resolver decisiones humanas;
|
||||
2. recalcular dependencias;
|
||||
3. confirmar la importación.
|
||||
|
||||
Las decisiones reales aparecen como tarjetas de acción. Las dependencias se muestran en un bloque secundario desplegable y se etiquetan expresamente como automáticas.
|
||||
|
||||
Cada tarjeta explica:
|
||||
|
||||
- qué informa el archivo;
|
||||
- por qué el sistema no decide solo;
|
||||
- qué debe decidir la persona.
|
||||
|
||||
### 3. Contexto territorial con regeneración automática
|
||||
|
||||
Cuando el usuario elige un Área/Yacimiento entre alternativas seguras:
|
||||
|
||||
1. la elección queda guardada sólo para ese lote;
|
||||
2. el sistema regenera inmediatamente el plan;
|
||||
3. se recalculan estructura local, padres y activos dependientes;
|
||||
4. la persona no tiene que recordar un segundo botón de “Regenerar plan”.
|
||||
|
||||
La elección territorial sigue validándose en backend contra las alternativas seguras detectadas.
|
||||
|
||||
### 4. Seguridad preservada
|
||||
|
||||
No se agregan migraciones en D5.3.9.
|
||||
|
||||
Se mantienen:
|
||||
|
||||
- huella del Maestro y bloqueo de planes obsoletos;
|
||||
- plan previo a cualquier escritura;
|
||||
- aplicación transaccional;
|
||||
- idempotencia;
|
||||
- procedencia;
|
||||
- reversión lógica;
|
||||
- validación de contexto operativo;
|
||||
- backup fuerte `INVENTARIO A REVISAR` creado antes de D5.3.8.
|
||||
|
||||
El deploy D5.3.9 crea además un backup PRE liviano de código + DB antes de reemplazar producción.
|
||||
@@ -0,0 +1,39 @@
|
||||
# Deploy D5.3
|
||||
|
||||
## Archivo
|
||||
|
||||
`DH_V2_FASE_D5_3_SOURCE.zip`
|
||||
|
||||
Subir manualmente a `/var/www/dhv2.korexlabs.com/`, reemplazando el código del
|
||||
proyecto según el procedimiento habitual, y ejecutar el bloque único de deploy
|
||||
entregado junto con el archivo.
|
||||
|
||||
## Migración
|
||||
|
||||
`PhaseD53OperationalContext1787421600000`
|
||||
|
||||
La migración es aditiva y preserva los datos existentes:
|
||||
|
||||
- agrega el rol operativo de tipos;
|
||||
- crea `area_company_relations`;
|
||||
- agrega Área y Empresa operativas a `assets`;
|
||||
- amplía snapshots históricos;
|
||||
- incorpora restricciones y triggers de integridad;
|
||||
- agrega permisos de lectura/gestión de relaciones.
|
||||
|
||||
No modifica `.env` ni volúmenes.
|
||||
|
||||
## Configuración posterior obligatoria
|
||||
|
||||
La migración **no adivina** qué tipos existentes son Área o Empresa. Después
|
||||
del deploy:
|
||||
|
||||
1. ir a **Configuración → Tipos de activo**;
|
||||
2. marcar el/los tipos correspondientes como `Área`;
|
||||
3. marcar el/los tipos correspondientes como `Empresa`;
|
||||
4. abrir activos Área/Empresa y crear los vínculos operativos necesarios;
|
||||
5. editar instalaciones/estaciones/equipos y seleccionar `Área → Empresa`;
|
||||
6. comprobar el Maestro usando los nuevos filtros.
|
||||
|
||||
Esta carga se realiza antes de D5.5, donde la planificación pasará a depender
|
||||
obligatoriamente del contexto Área–Empresa.
|
||||
@@ -0,0 +1,134 @@
|
||||
# Fase D5.4 · Hallazgos aplicables al Inventario
|
||||
|
||||
## Objetivo
|
||||
|
||||
Hacer que el catálogo de hallazgos deje de ser una lista universal y pase a responder al elemento concreto que se inspecciona, sin perder compatibilidad con el funcionamiento actual ni alterar hallazgos históricos.
|
||||
|
||||
D5.4 incorpora tres niveles separados:
|
||||
|
||||
1. catálogo institucional de hallazgos;
|
||||
2. aplicabilidad por tipo técnico de Inventario;
|
||||
3. excepción explícita por registro concreto del Inventario.
|
||||
|
||||
También separa la gravedad sugerida por catálogo de la gravedad real observada en una inspección y formaliza `OTROS` como propuesta administrable desde oficina.
|
||||
|
||||
## Compatibilidad controlada
|
||||
|
||||
Un tipo técnico que todavía no tenga una configuración explícita continúa viendo todos los ítems activos del catálogo. El API informa que ese tipo está `configured: false` para que oficina pueda distinguir el estado transitorio.
|
||||
|
||||
En cuanto oficina guarda la primera configuración del tipo, sólo quedan habilitados los ítems seleccionados para ese tipo. Las excepciones por registro concreto se aplican encima de esa selección.
|
||||
|
||||
De este modo el despliegue no deja a la APK o a la web sin catálogo mientras Hidrocarburos completa la parametrización inicial.
|
||||
|
||||
## Aplicabilidad por tipo técnico
|
||||
|
||||
Nuevas estructuras:
|
||||
|
||||
- `finding_catalog_asset_type_profiles`: marca que un tipo técnico ya fue configurado y conserva el motivo de la última decisión;
|
||||
- `finding_catalog_item_asset_types`: relación entre cada ítem de catálogo y los tipos técnicos para los que resulta aplicable.
|
||||
|
||||
Administración:
|
||||
|
||||
- `GET /api/v3/finding-catalog/asset-types/:assetTypeId/selection`
|
||||
- `PUT /api/v3/finding-catalog/asset-types/:assetTypeId/selection`
|
||||
|
||||
El cambio requiere `finding_catalog.manage` y queda auditado.
|
||||
|
||||
## Excepciones por objeto concreto
|
||||
|
||||
Nueva tabla `finding_catalog_asset_overrides`.
|
||||
|
||||
Sólo guarda diferencias respecto de la regla del tipo técnico. Un registro concreto puede habilitar un hallazgo normalmente deshabilitado para su tipo o excluir uno normalmente habilitado.
|
||||
|
||||
Administración:
|
||||
|
||||
- `GET /api/v3/finding-catalog/assets/:assetId/selection`
|
||||
- `PUT /api/v3/finding-catalog/assets/:assetId/selection`
|
||||
|
||||
La ficha de Inventario incorpora la pestaña **Hallazgos aplicables** con la regla heredada del tipo y las excepciones del objeto.
|
||||
|
||||
## Catálogo aplicable en campo
|
||||
|
||||
Nuevo endpoint:
|
||||
|
||||
- `GET /api/v3/finding-catalog/applicable/:assetId`
|
||||
|
||||
Devuelve solamente categorías e ítems habilitados para el objeto concreto, junto con el estado de configuración del tipo y la opción `OTROS`.
|
||||
|
||||
La misma regla se valida al crear el hallazgo. Aunque un cliente antiguo intente enviar manualmente un `catalogItemId` no habilitado para ese objeto, el servidor responde `FINDING_CATALOG_ITEM_NOT_APPLICABLE`.
|
||||
|
||||
Si durante la edición de un hallazgo abierto se cambia el objeto inspeccionado, el servidor vuelve a validar la aplicabilidad del ítem de catálogo para el nuevo objeto.
|
||||
|
||||
## Gravedad sugerida y gravedad real
|
||||
|
||||
`finding_catalog_items.suggested_severity` define una recomendación opcional de 1 a 10.
|
||||
|
||||
Cada `inspection_findings` conserva dos valores independientes:
|
||||
|
||||
- `suggested_severity`: copia congelada de la sugerencia vigente al momento de crear el hallazgo;
|
||||
- `severity`: gravedad real asignada al hallazgo, también entre 1 y 10.
|
||||
|
||||
Si el inspector no indica una gravedad real al crear un hallazgo de catálogo, se usa la sugerida como valor inicial. El inspector puede corregirla mientras el acta siga editable.
|
||||
|
||||
Cambios posteriores en la gravedad sugerida del catálogo no modifican hallazgos anteriores. La gravedad queda incluida en las versiones del hallazgo, la instantánea congelada del acta y el Word automático del informe.
|
||||
|
||||
## OTROS y propuestas de catálogo
|
||||
|
||||
Un hallazgo personalizado continúa permitido cuando el inspector encuentra una situación que no existe en el catálogo.
|
||||
|
||||
D5.4 crea automáticamente una fila en `finding_catalog_proposals` vinculada al hallazgo original, al objeto y al tipo técnico. La propuesta conserva:
|
||||
|
||||
- título propuesto;
|
||||
- fundamento legal informado;
|
||||
- gravedad propuesta;
|
||||
- descripción;
|
||||
- estado de revisión;
|
||||
- decisión y usuario de oficina.
|
||||
|
||||
Estados:
|
||||
|
||||
- `PENDING`
|
||||
- `MATCHED`
|
||||
- `REJECTED`
|
||||
|
||||
Administración:
|
||||
|
||||
- `GET /api/v3/finding-catalog/proposals`
|
||||
- `PATCH /api/v3/finding-catalog/proposals/:id/review`
|
||||
|
||||
Al marcar una propuesta como `MATCHED`, oficina la vincula a un ítem existente del catálogo. Si el tipo técnico ya estaba configurado, ese ítem se habilita para el tipo hacia adelante.
|
||||
|
||||
La decisión nunca modifica `inspection_findings.catalog_item_id` del hallazgo histórico que originó la propuesta. Ese hallazgo conserva exactamente la identidad con la que fue registrado en campo.
|
||||
|
||||
## Backfill
|
||||
|
||||
La migración crea propuestas `PENDING` para hallazgos personalizados existentes que no tenían `catalog_item_id`.
|
||||
|
||||
No se infiere gravedad ni aplicabilidad histórica cuando no existe evidencia persistida para hacerlo.
|
||||
|
||||
## Web de oficina
|
||||
|
||||
El Catálogo de Hallazgos incorpora:
|
||||
|
||||
- gravedad sugerida por ítem;
|
||||
- configuración de aplicabilidad por tipo técnico;
|
||||
- bandeja de propuestas `OTROS` pendientes.
|
||||
|
||||
El Maestro de Inventario incorpora:
|
||||
|
||||
- pestaña **Hallazgos aplicables**;
|
||||
- visualización del default del tipo;
|
||||
- excepción del objeto;
|
||||
- motivo obligatorio para guardar cambios.
|
||||
|
||||
La ficha del hallazgo muestra gravedad real y gravedad sugerida.
|
||||
|
||||
## Reglas preservadas
|
||||
|
||||
- Una visita = una Acta.
|
||||
- El catálogo sigue versionado por revisiones.
|
||||
- Hallazgos históricos no se reescriben por cambios de catálogo.
|
||||
- Actas cerradas e informes congelados conservan su snapshot.
|
||||
- Las verificaciones de D5.3.25 siguen siendo append-only.
|
||||
- La primera respuesta de empresa continúa inmutable.
|
||||
- SMTP puede continuar pendiente sin bloquear esta fase.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user