Aplicar el sufijo de borrado_en en las 12 vistas, PROD y despues DEV, sin carve-out para tipo_asociacion
Vehiculo de ship para el DDL que salio del spike MOVILBA-123, que esta CERRADO y no puede llevar un apply. El archivo vive untracked en docs/migrations/2026-10-08-movilba-123-sufijo-borrado-vistas-PROD-Y-DEV.sql, sha256 dad14cbd (git hash-object 324bceac), 912 lineas, NO aplicado. DECISION TOMADA, revierte mi linea de las 14:00: el carve-out de tipo_asociacion NO se aplica. Lo habia concedido sobre la premisa '3/3 muertos, mismo caso que categoria_regulatoria' y la medicion de db03 la falsea - filas apuntando a cada catalogo en las dos bases: categoria_regulatoria 5558/5560 (ahi el carve-out SI corresponde y queda), tipo_asociacion 0/0, marca_motor 0/0. Sufijar tipo_asociacion marca CERO filas, asi que el carve-out no ahorra nada. Y lo decisivo: v_personas_completas YA sufija ese campo, asi que carvear solo las 3 nuevas deja 1 superficie sufijada contra 3 peladas, que es exactamente lo que prohibe la segunda regla del 2026-09-24 - un campo, una etiqueta de catalogo, todas las superficies. Mantener el carve-out costaria ADEMAS sacar ese CASE ya instalado. Se sufijan las cuatro. Controles A-E verdes PROD+DEV bajo ROLLBACK. El control F queda SIN EJERCITAR en las dos bases (PROD 0 filas; DEV 2 filas pero sobre una opcion viva) y avisa en vez de pasar - eso se reporta como tal, no como verde. Orden: PROD primero con sus gates verdes, recien DEV. Audit verdictea dad14cbd antes del apply.
Activity
-
audit pass: MOVILBA-737, archivo dad14cbd, 912 lineas, NO aplicado. Verifique los 3 pedidos por medicion: cuerpos contra lo instalado en PROD y DEV, tipos de las 29 columnas destino, las 23 autofiltrantes, relacl. SIN EJERCITAR por mi: el ensayo -v ensayo=1 (gate del carril db), los controles A-F, el apply.
payload
{"scope":"MOVILBA-737, archivo dad14cbd, 912 lineas, NO aplicado. Verifique los 3 pedidos por medicion: cuerpos contra lo instalado en PROD y DEV, tipos de las 29 columnas destino, las 23 autofiltrantes, relacl. SIN EJERCITAR por mi: el ensayo -v ensayo=1 (gate del carril db), los controles A-F, el apply.","outcome":"pass","evidence":"PASS sobre los bytes, tres hallazgos, ninguno bloqueante. Detalle largo en el audit-finding.\nCUERPOS. Control propio: extraje los 12 cuerpos del archivo, baje pg_get_viewdef de PROD y DEV, normalice las dos formas de sufijo a la etiqueta pelada y compare. Las 24 parejas vista/base dan SAME - el archivo es identico al cuerpo instalado salvo el sufijo. Total exacto 29 forma-cast + 12 forma-texto = 41, igual que el encabezado. Ninguna deriva se pega a PROD y los 12 cuerpos coinciden entre bases. El unico delta aparente era el ::text obligado en el ELSE para igualar el THEN, que dentro de jsonb_build_object serializa igual.\n1) TRUNCA, pero el MARCADOR nunca. left(,40)+10 da 50 exactos y las 29 destino son character varying(50) en las dos bases, 27 directas y 2 por alias anidado. Lo que si cede un caracter en silencio: opcion 52 entidades/tipo_entidad, 41 caracteres, VIVA en las dos bases y alcanzada por 6 de las 41 expresiones. El renglon 76 mide solo etiquetas BORRADAS (max 37) y ese denominador esconde la unica que importa. Exposicion hoy CERO filas: 0 entidades con tipo_entidad_id=52.\n2) LAS 23. Nombradas una por una, 13 matviews + 10 vistas = 23. Medido: 23 de 23 traen borrado_en IS NULL en el cuerpo instalado en las dos bases, asi que \"el CASE seria inalcanzable\" es medicion y no afirmacion. El archivo no toca ninguna.\n3) GRANTS. PROD tiene relacl NO NULA en 12 de 12: el riesgo del DROP es real ahi y el REPLACE en el lugar es correcto. En DEV solo 1 de 12 la tiene, asi que el control E compara NULL con NULL en 11 vistas y escribe su NOTICE verde igual. En PROD tampoco se lo vio fallar porque CREATE OR REPLACE no toca relacl por construccion: E es un alambre de tropiezo, no un control ejercitado.\nCORRIJO una contradiccion mia: la premisa de coder03 es CIERTA, v_personas_completas YA sufija tipo_asociacion (linea 63 del viewdef instalado, las dos bases). Mi primera medicion dio 0 porque mi regex solo matcheaba la forma nueva. 18:02Z / 15:02 ART.","reportRef":null} -
MOVILBA-737 / MOVILBA-123 - detalle residual del PASS de 18:07Z (15:07 ART). audit-mba-l-cc. METODO del control de equivalencia de cuerpos (instrumento propio, no reutilizado del carril db). Extraje los 12 cuerpos del archivo con un regex anclado en CREATE OR REPLACE VIEW public.<v> AS hasta el ; seguido de un comentario, otro CREATE o un DO $$; baje pg_get_viewdef(oid, true) de las 12 vistas en PROD y en DEV; reescribi las DOS formas de sufijo a la etiqueta pelada contando cada reescritura y abortando si los tres alias de una misma expresion no coinciden; y compare insensible a espacios y al punto y coma. Resultado: 24 de 24 parejas vista/base SAME. Conteo: cast=29, text=12, suma=41, exactamente lo que dice el encabezado. Ningun alias desalineado. LAS DOS FORMAS, y por que no es deriva. Forma cast, columna proyectada: (left(x.nombre_mostrable::text, 40) || ' (borrado)'::text)::character varying(50). Forma texto, etiqueta dentro de jsonb_build_object: sin el cast final. El ::text del ELSE es obligatorio para igualar el tipo del THEN; varchar y text serializan al mismo string JSON, asi que es neutral en la salida. Mi primera corrida marco v_entidades_detalle y _all como DIFFERS por esto; relaje la normalizacion con el comentario que lo justifica y las 24 quedaron SAME. HALLAZGO 1 - el caracter que se pierde. Las 29 columnas destino de la forma cast son character varying(50) en las DOS bases: 27 directas y 2 por alias anidado, v_personas_completas.current_licencia_clase_nombre y v_vehiculo_cadena.eslabon_estado_nombre. 40 + 10 = 50 exactos, asi que el marcador " (borrado)" nunca puede perderse: lo que cede es el nombre. Hoy eso no se ve porque el renglon 76 del encabezado mide la etiqueta BORRADA mas larga (37, 47 con sufijo) - denominador equivocado. La etiqueta mas larga del catalogo relevante esta VIVA: opcion 52, entidades/tipo_entidad, "Sociedad Anonima c/ Participacion Estatal", 41 caracteres, presente en PROD y DEV, alcanzada por 6 de las 41 expresiones. El dia que se la borre, la ficha va a mostrar 40 caracteres + " (borrado)" y el ultimo caracter del nombre desaparece sin aviso. Exposicion actual CERO: 0 entidades con tipo_entidad_id=52 en las dos bases. Latente, no vivo; no bloquea. HALLAZGO 1b - inconsistencia intra-vista ya instalada. Las 8 sedes preexistentes usan el idiom viejo sin cap: x.nombre_mostrable::text || ' (borrado)'::text, con un cast a character varying SIN longitud. Efecto: en la misma vista conviven un campo sin truncar y uno truncado a 40 - estado_actual junto a estado_actual_nombre, y tipo_persona junto al tipoPersonaNombre del jsonb. El archivo no las toca, lo cual es coherente con no pegar deriva en PROD, pero deja dos reglas de truncado en la misma superficie. Nombro la asimetria, no pido el cambio. HALLAZGO 2 - las 23 autofiltrantes. El encabezado las nombra una por una: 13 matviews + 10 vistas = 23. Medido contra el cuerpo instalado en las dos bases: 23 de 23 contienen borrado_en IS NULL, asi que la afirmacion "el CASE seria inalcanzable ahi" es medicion y no criterio. El archivo no toca ninguna de las 23. HALLAZGO 3 - el control E es un alambre de tropiezo. relacl NO NULA en PROD: 12 de 12 vistas, asi que el riesgo del DROP VIEW es real y el CREATE OR REPLACE en el lugar es la decision correcta. En DEV solo 1 de 12 tiene relacl, asi que E compara NULL con NULL en 11 vistas y escribe su NOTICE verde igual - ahi es una linea verde. En PROD tampoco se lo puede ver fallar: CREATE OR REPLACE no toca relacl por construccion. E detecta un DROP inesperado, no un REPLACE mal hecho. CORRECCION DE UNA MEDICION MIA. Mi primer censo dio already_installed=0 y casi presente una contradiccion a la premisa de coder03. Era artefacto de regex: mis patrones solo matcheaban el idiom nuevo. v_personas_completas YA sufija tipo_asociacion, linea 63 del viewdef instalado, en las DOS bases. La premisa es CIERTA y el carve-out apagado es correcto. SIN EJERCITAR por mi, explicito: el ensayo con -v ensayo=1 bajo ROLLBACK (gate del carril db, no mio); los controles A, B, C, D y F del propio archivo; el apply. El control B (truncado sintetico de 45 caracteres) no se corrio, asi que el truncado esta verificado por tipo de columna y aritmetica, no observado.
-
APPLIED. db03, 2026-10-08. PROD movilba 21:46:42Z first, DEV movilba_dev 21:47:05Z, from docs/migrations/2026-10-08-movilba-123-sufijo-borrado-vistas-PROD-Y-DEV.sql with sha256 dad14cbd3d2416db7843accf1d4559268274898f34f25792fc5eebccb79cb0fb verified against the tree before the run, byte-identical to the audited artifact. Under hub lock mb123-sufijo-borrado-12-vistas-public. Both runs rc=0 and COMMIT. REHEARSAL FIRST, both bases, -v ensayo=1, both rc=0 with ROLLBACK printed. Controls A/B/C/D/E green in both. Apply output matched the rehearsal number for number: PROD A/B/D 2028 rows and C 1 entidad; DEV A/B/D 2045 rows and C 3 entidades. POST-APPLY, measured OUTSIDE the file so it is not the migration grading itself: the 12 named views carry the suffix 12 of 12 in each base, with 49 occurrences each - 41 new plus the 8 that already existed inside those 12 (6 in v_personas_completas, 1 in v_vehiculos_detalle, 1 in v_vehiculos_export). public went from 6 to 15 views carrying the marker, identically in both bases; 15 = the 12 plus the 3 pre-existing ones outside the set. PROD's 12 hold 48 aclitem entries after the apply. NOT EXERCISED, stated as such and not as a green line: - Control F warns instead of passing in BOTH bases - PROD has 0 tipo_asociacion labels in v_entidades_detalle, DEV has 2 but none pointing at a deleted option, so the CASE is never reached. The tipo_asociacion suffix is INSTALLED and UNOBSERVED in both bases. That is the field the carve-out argument was about, so it is the one place the decision is not backed by a seen result. - The truncation is verified by column type and arithmetic (40 + 10 = 50 exactly) and NOT observed against a label long enough to overflow. Control B used the synthetic 50-length case, not a 45-character real label. - Control E cannot be made to fail: CREATE OR REPLACE does not touch relacl by construction, so E catches an unexpected DROP, not a bad REPLACE. I did not take an independent pre-apply grant count outside the transaction - E's before/after comparison inside it is the whole control. - No app surface was opened after the apply. Nobody has SEEN a '(borrado)' label render in the ficha, the PDF, an export or the API. - Latent and measured at 0 today: the longest LIVE label in the relevant catalog is 41 characters (option 52, entidades/tipo_entidad, 'Sociedad Anonima c/ Participacion Estatal'), reached by 6 of the 41 expressions. The day it is deleted the last character of the name disappears without notice. 0 entidades reference it in either base, so exposure is zero now, which is why it does not block. DOCUMENTED: docs/migrations/README.md gained the applied entry at the top of the 2026-10-08 section, carrying the sha, both timestamps, the no-DROP reasoning and the same unexercised list. The SQL file and that README hunk are both UNTRACKED/uncommitted - coder03 needs them on the park list and in the next commit. Two things this does NOT close, both already reported in MOVILBA-123 and neither affected by this apply: asociaciones_entidad_persona.tipo_asociacion_id has a bare FOREIGN KEY to opciones(id) with no catalog restriction, so DEV's 2 live rows store option 113, which belongs to personas/tipo_persona - the field shows a live label from a DIFFERENT catalog, and that needs its own item. And the 8 pre-existing suffix sites use the older idiom with no cap, so the same view now carries two truncation rules side by side; the file deliberately does not touch them.