chore: import DH V2 D5.6.4 production baseline

This commit is contained in:
DH V2
2026-09-05 10:12:35 -03:00
commit 82213e72f5
757 changed files with 84218 additions and 0 deletions
+13
View File
@@ -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 ÁreaEmpresa 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.
+84
View File
@@ -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.
+7
View File
@@ -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`.
+96
View File
@@ -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.
+14
View File
@@ -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.
+40
View File
@@ -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.
+46
View File
@@ -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.
+165
View File
@@ -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.
+79
View File
@@ -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.
+53
View File
@@ -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.
+41
View File
@@ -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.
+33
View File
@@ -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`.
+72
View File
@@ -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.
+34
View File
@@ -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`.
+90
View File
@@ -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.
+34
View File
@@ -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`.
+93
View File
@@ -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.
+33
View File
@@ -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.
+69
View File
@@ -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
```
+30
View File
@@ -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.
+49
View File
@@ -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.
+106
View File
@@ -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.
+42
View File
@@ -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.
+80
View File
@@ -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.
+28
View File
@@ -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.
+62
View File
@@ -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.
+29
View File
@@ -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.
+73
View File
@@ -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.
+30
View File
@@ -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.
+64
View File
@@ -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.
+30
View File
@@ -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.
+67
View File
@@ -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.
+29
View File
@@ -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`.
+65
View File
@@ -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.
+30
View File
@@ -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`.
+69
View File
@@ -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.
+29
View File
@@ -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`.
+64
View File
@@ -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.
+40
View File
@@ -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.
+19
View File
@@ -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`.
+30
View File
@@ -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`.
+78
View File
@@ -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.
+19
View File
@@ -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`.
+62
View File
@@ -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.
+19
View File
@@ -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`.
+73
View File
@@ -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.
+46
View File
@@ -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.
+18
View File
@@ -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 D1D5 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`.
+42
View File
@@ -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`.
+19
View File
@@ -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`.
+173
View File
@@ -0,0 +1,173 @@
# Fase D5.3 — Contexto operativo ÁreaEmpresa
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 ÁreaEmpresa 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 ÁreaEmpresa.
### `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 ÁreaEmpresa 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 110;
- opción `OTROS`;
- cambios de APK.
Esos puntos pertenecen a D5.4, D5.5 y E1.
+60
View File
@@ -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.
+28
View File
@@ -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`.
+14
View File
@@ -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.
+29
View File
@@ -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.
+56
View File
@@ -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.
+47
View File
@@ -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`.
+7
View File
@@ -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`.
+31
View File
@@ -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.
+11
View File
@@ -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.
+35
View File
@@ -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.
+30
View File
@@ -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.
+7
View File
@@ -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.
+36
View File
@@ -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.
+7
View File
@@ -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.
+25
View File
@@ -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.
+32
View File
@@ -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 110 y soportar `OTROS` como propuesta de catálogo.
+9
View File
@@ -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.
+5
View File
@@ -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`.
+18
View File
@@ -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.
+38
View File
@@ -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.
+40
View File
@@ -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.
+75
View File
@@ -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 ÁreaOperadora;
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.
+89
View File
@@ -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.
+25
View File
@@ -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.
+12
View File
@@ -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.
+82
View File
@@ -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.3D5.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 ÁreaOrganizació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 ÁreaOrganizació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.
+19
View File
@@ -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.
+66
View File
@@ -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 ÁreaOperadora;
- 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.
+19
View File
@@ -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.
+110
View File
@@ -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.
+13
View File
@@ -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.
+38
View File
@@ -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
```
+32
View File
@@ -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.
+19
View File
@@ -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.
+125
View File
@@ -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.
+60
View File
@@ -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`.
+13
View File
@@ -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`.
+21
View File
@@ -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`.
+25
View File
@@ -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.
+24
View File
@@ -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.
+35
View File
@@ -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.
+21
View File
@@ -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`.
+59
View File
@@ -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.
+47
View File
@@ -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**.
+64
View File
@@ -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.
+39
View File
@@ -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 ÁreaEmpresa.
+134
View File
@@ -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