Files
dh-inspeccion-v2/scripts/phase-d5-1-acceptance.sh
T

142 lines
5.7 KiB
Bash
Executable File

#!/usr/bin/env bash
set -Eeuo pipefail
dhv2_base_url="${DHV2_BASE_URL:-https://dhv2.korexlabs.com}"
dhv2_base_url="${dhv2_base_url%/}"
dhv2_nil_uuid="00000000-0000-4000-8000-000000000000"
fail() {
echo "ERROR: $*" >&2
exit 1
}
echo "========== D5.1 · MIGRACIONES =========="
dhv2_migration_status="$(docker compose --profile tools run --rm migrate npm run migration:show 2>&1)"
grep -q 'Pending migrations: no' <<<"$dhv2_migration_status" \
|| fail "Quedaron migraciones pendientes"
echo "Migraciones pendientes: no"
echo
echo "========== D5.1 · HEALTH =========="
dhv2_internal="$(curl -fsS --connect-timeout 10 --max-time 30 http://127.0.0.1:3101/api/v3/health)"
dhv2_external="$(curl -fsS --connect-timeout 10 --max-time 30 "$dhv2_base_url/api/v3/health")"
grep -q '"version":"0.19.1"' <<<"$dhv2_internal" || fail "Health interno no informa v0.19.1"
grep -q '"phase":"D5.1"' <<<"$dhv2_internal" || fail "Health interno no informa D5.1"
grep -q '"version":"0.19.1"' <<<"$dhv2_external" || fail "Health externo no informa v0.19.1"
grep -q '"database":"ok"' <<<"$dhv2_external" || fail "La base no está saludable"
echo "$dhv2_external"
echo
echo "========== D5.1 · RUTAS PROTEGIDAS =========="
dhv2_post_paths=(
"inspection-visits/$dhv2_nil_uuid/start"
"inspection-visits/$dhv2_nil_uuid/acts"
"inspection-acts/$dhv2_nil_uuid/findings"
"inspection-acts/$dhv2_nil_uuid/ready"
"inspection-acts/$dhv2_nil_uuid/close"
)
for dhv2_path in "${dhv2_post_paths[@]}"; do
dhv2_code="$(curl -sS --connect-timeout 10 --max-time 30 \
-X POST -H 'Content-Type: application/json' -d '{}' \
-o /tmp/dhv2-d5-1-response.json -w '%{http_code}' \
"$dhv2_base_url/api/v3/$dhv2_path")"
test "$dhv2_code" = "401" \
|| fail "/api/v3/$dhv2_path devolvió HTTP $dhv2_code; se esperaba 401"
echo "/api/v3/$dhv2_path sin sesión: 401 OK"
done
rm -f /tmp/dhv2-d5-1-response.json
echo
echo "========== D5.1 · POLÍTICA DE ROLES =========="
dhv2_db_check="$(docker compose exec -T db sh -lc \
'psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -v ON_ERROR_STOP=1 -At' <<'SQL'
WITH operational(code) AS (VALUES
('inspections.execute'),
('inspection_acts.create'),
('inspection_acts.update'),
('inspection_acts.cancel'),
('inspection_findings.create'),
('inspection_findings.update'),
('inspection_closure.prepare'),
('inspection_closure.sign'),
('inspection_closure.close')
)
SELECT 'operational_permissions', COUNT(*)
FROM permissions permission
INNER JOIN operational ON operational.code = permission.code;
WITH operational(code) AS (VALUES
('inspections.execute'),
('inspection_acts.create'),
('inspection_acts.update'),
('inspection_acts.cancel'),
('inspection_findings.create'),
('inspection_findings.update'),
('inspection_closure.prepare'),
('inspection_closure.sign'),
('inspection_closure.close')
)
SELECT 'inspector_grants', COUNT(*)
FROM role_permissions role_permission
INNER JOIN roles role ON role.id = role_permission.role_id
INNER JOIN permissions permission ON permission.id = role_permission.permission_id
INNER JOIN operational ON operational.code = permission.code
WHERE role.code = 'inspector';
WITH operational(code) AS (VALUES
('inspections.execute'),
('inspection_acts.create'),
('inspection_acts.update'),
('inspection_acts.cancel'),
('inspection_findings.create'),
('inspection_findings.update'),
('inspection_closure.prepare'),
('inspection_closure.sign'),
('inspection_closure.close')
)
SELECT 'non_inspector_grants', COUNT(*)
FROM role_permissions role_permission
INNER JOIN roles role ON role.id = role_permission.role_id
INNER JOIN permissions permission ON permission.id = role_permission.permission_id
INNER JOIN operational ON operational.code = permission.code
WHERE role.code <> 'inspector';
SELECT 'follow_up_roles', COUNT(*)
FROM role_permissions role_permission
INNER JOIN roles role ON role.id = role_permission.role_id
INNER JOIN permissions permission ON permission.id = role_permission.permission_id
WHERE role.code IN ('admin', 'director', 'supervisor', 'inspector')
AND permission.code = 'inspection_findings.follow_up';
SELECT 'migration_applied', COUNT(*)
FROM typeorm_migrations
WHERE name = 'PhaseD51MobileInspectionPolicy1787331600000';
SQL
)"
grep -q 'operational_permissions|9' <<<"$dhv2_db_check" || fail "No se encontraron los nueve permisos operativos"
grep -q 'inspector_grants|9' <<<"$dhv2_db_check" || fail "El inspector no tiene los nueve permisos operativos"
grep -q 'non_inspector_grants|0' <<<"$dhv2_db_check" || fail "Un rol no inspector conserva permisos operativos"
grep -q 'follow_up_roles|4' <<<"$dhv2_db_check" || fail "Se alteró el seguimiento posterior del dashboard"
grep -q 'migration_applied|1' <<<"$dhv2_db_check" || fail "La migración D5.1 no figura aplicada"
echo "$dhv2_db_check"
echo
echo "========== D5.1 · BLOQUEO EN API =========="
docker compose exec -T api sh -lc \
'grep -R "INSPECTION_MOBILE_APP_REQUIRED" /app/dist >/dev/null && grep -R "INSPECTION_INSPECTOR_ROLE_REQUIRED" /app/dist >/dev/null'
echo "Bearer móvil + rol inspector exigidos en runtime: OK"
echo
echo "========== D5.1 · DASHBOARD =========="
docker compose exec -T web sh -lc \
'grep -R "0.19.1" /usr/share/nginx/html/assets >/dev/null && grep -R "Operación exclusiva APK" /usr/share/nginx/html/assets >/dev/null && grep -R "El inspector asignado debe iniciar la visita desde la APK" /usr/share/nginx/html/assets >/dev/null && grep -R "Actas y hallazgos se registran desde la APK" /usr/share/nginx/html/assets >/dev/null && grep -R "respuesta de la empresa, PDF y próximo control" /usr/share/nginx/html/assets >/dev/null'
echo "Dashboard administrativo y footer v0.19.1: OK"
echo
echo "========== D5.1 · CONTENEDORES =========="
docker compose ps
echo
echo "ACEPTACIÓN DE FASE D5.1: OK"