Fix: reset anual real del ID de negocio de instancias y recordatorios
Qué
Corrige el hallazgo #3 (Alto) de la auditoría de backend (2026-08-27):
el id de negocio de instancias y recordatorios podía exceder VARCHAR(16)
a largo plazo, porque la SEQUENCE de Postgres es global y nunca resetea
pese al formato "anual".
Por qué
Dos mitigaciones posibles: ensanchar la columna, o hacer que el contador
resetee de verdad por año. Se eligió la segunda porque es la corrección
real (el formato ya afirma ser anual) y no requiere volver a tocar el
ancho de columna nunca más — 6 dígitos por año es, para el volumen
esperado de este sistema, indefinidamente suficiente.
Cambios
- Nueva tabla
proyecto.contador_id_negocio(tipo, año, último_valor),
reemplaza aseq_instancia/seq_recordatorio. -
InstanciaIdGenerator/RecordatorioIdGenerator: UPSERT atómico
(INSERT ... ON CONFLICT DO UPDATE ... RETURNING) contra esa tabla,
en vez denextval().@Transactionalexplícito (se une a la
transacción del caller —crear()en los services ya es transaccional). -
id_neg_instancia/id_neg_recordatoriose quedan en VARCHAR(16)
(sin cambios) — con reset anual real, 6 dígitos no van a agotarse.
Acción requerida en el deploy
Nada se desplegó todavía de la iteración anterior de este fix, así que
la migración a correr en Neon antes de este deploy es simplemente:
CREATE TABLE proyecto.contador_id_negocio (
tipo VARCHAR(20) NOT NULL,
anio INT NOT NULL,
ultimo_valor INT NOT NULL DEFAULT 0,
CONSTRAINT pk_contador_id_negocio PRIMARY KEY (tipo, anio)
);
DROP SEQUENCE IF EXISTS proyecto.seq_instancia;
DROP SEQUENCE IF EXISTS proyecto.seq_recordatorio;
No hay que tocar el ancho de ninguna columna (se quedan en VARCHAR(16)
como ya estaban).
Testing
- Compila limpio. Suite completa: 522 tests, 0 failures (516 + 6 nuevos
entre los dos generadores). - Verificado contra Postgres real: dos llamadas consecutivas en el mismo
año incrementan (1, 2); una llamada en un año distinto arranca en 1 sin
importar el contador de otros años.