Skip to content

ADR-068: Régimen archivístico privado, corte real de la baja, plantillas y metadatos en el MCP, y compuerta de vencimiento en transferencias

Estado: Aceptado (implementado salvo D19, que no se construye). El encuadre normativo de D1 a D4 y la excepción de D19 son decisión del usuario pendiente de concepto de asesor. Fecha: 2026-11-06 Autores: Giampiero (mantenedor principal) Relacionados: ADR-025 (instrumento que gobierna), ADR-035 (estado de la entidad), ADR-044 (search_path), ADR-048 (acto de la plataforma), ADR-054 (certificado), ADR-065 (nada se borra), ADR-067 (enmendado)


Contexto

Cuatro decisiones del usuario que se diseñan juntas porque tocan los mismos actos:

  1. «Crea un régimen especial para entidades privadas, ya que estas no necesitan estar inscritas» en el RUSD. Hoy cuatro compuertas exigen el certificado (archive_service.py:2301, :6298, :7638; transferencia_service.py:294) y excribe, privada, no podría ejecutar nunca un lote ni transferir.
  2. La baja y el alta de una persona necesitan pantalla, y hoy is_active=false no corta nada: AuthService.validate (auth_service.py:285-296) resuelve la fila de auth_users sin mirar is_active; solo la credencial de asistente lo exige (auth_service.py:377).
  3. Las plantillas y los metadatos se abren al MCP.
  4. Las transferencias no revisan el vencimiento; la eliminación sí, en capas (migración 098).

El Acuerdo AGN 001/2024 (documentos/AGN_Acuerdo001_2024_firmado.pdf) define su ámbito en el art. 1.1.2: administración pública y «entidades privadas que cumplen funciones públicas», y llama a ambas sujetos obligados. El art. 4.5.4 (num. 1 RUSD, num. 2 sesenta días hábiles) y el art. 5.1.5.1 hablan de sujetos obligados. Una privada sin funciones públicas queda fuera de ese ámbito, y esa lectura es la base de D1. El dictamen es del asesor.

Parte 1. Régimen archivístico

D1. Un atributo de la entidad, fijado solo por la plataforma. Migración global services/tenant-service/migrations/global/010_tenants_regimen_archivistico.sql:

ALTER TABLE public.tenants
    ADD COLUMN IF NOT EXISTS regimen_archivistico TEXT NOT NULL DEFAULT 'publica',
    ADD COLUMN IF NOT EXISTS regimen_fijado_at TIMESTAMPTZ,
    ADD COLUMN IF NOT EXISTS regimen_motivo TEXT,
    ADD COLUMN IF NOT EXISTS regimen_operador TEXT;
-- CHECK tenants_regimen_forma: valor en ('publica','privada'); los tres de procedencia van juntos,
-- motivo >= 10 y operador 3..200 (forma de tenants_asistente_bloqueo_forma, global 006).

El acto es PUT /api/v1/tenants/{id}/regimen-archivistico en tenants.py: token interno de router y sin ruta en el gateway, igual que ADR-048. El admin de la entidad no tiene ninguna vía: si la tuviera, una entidad pública se saltaría el RUSD a sí misma. TenantUpdate no lleva el campo. Motivo y operador obligatorios; asiento tenant.regimen_archivistico_cambiado con antes, despues, motivo y operador en la cadena de la entidad, en la misma transacción. Mismo valor: 200 cambiado=false sin asiento. El operador usa scripts/regimen-archivistico.sh {publica|privada} --slug S --motivo … --operador …, que corre dentro de tenant-service como asistente-plataforma.sh, y su ayuda y su salida dicen el texto de D2.

D2. La privada con funciones públicas sigue en publica. Ley 594 art. 2 y Ac. 001/2024 art. 1.1.2. Quien fija el régimen lo lee antes de confirmar: «privada es solo para entidades privadas que NO cumplen funciones públicas. Una privada que ejerce funciones públicas es sujeto obligado y sigue en publica».

D3. Efecto: no se exige certificado RUSD, en un solo sitio. ArchiveRepository.instrumentos_sin_certificado_rusd (archive_repository.py:1803) es el único punto que leen las cuatro compuertas, y el gate va en el WHERE, sin viaje adicional y calificado public.:

AND NOT EXISTS (SELECT 1 FROM public.tenants t
                 WHERE t.slug = $2 AND t.regimen_archivistico = 'privada')

Fila ausente o valor distinto de privada: se exige el certificado (fail-closed). Ningún trigger condiciona por RUSD: en las migraciones solo hay inmutabilidad y forma del dato (083, 082, 080), así que no se toca el motor. La TVD va por la misma consulta (e.trd_serie_id sobre trd_series). Los endpoints registrar-rusd y certificado-rusd siguen funcionando; la pantalla los oculta en privada. Un certificado ya registrado se sigue mostrando porque es cierto.

D4. Efecto: plazo de publicidad de 0 a 60 días hábiles.

  • Dónde. Parámetro de tenant eliminacion_plazo_publicidad_dias_habiles en sgd_param_admin, sembrado en JSON null por la migración de tenant de tenant-service 018_param_plazo_publicidad.sql y listado en PARAMS_ADMITIDOS. null, ausente o fuera de rango valen 60.
  • Quién. El admin de la entidad, USUA_PERM_ADMIN nivel 3, por PUT /config/params/{key} y /admin/parametros. El freno a la autoexención es D1, no este valor. Bajarlo exige motivo y asienta relaja_politica (relaja_politica se extiende con un mapa PARAMS_ENTERO_ACOTADO). En publica responde 409 plazo_solo_regimen_privado. Sigue excluido del MCP.
  • Cómo lo lee archive. Una sola consulta, plazo_publicidad_vigente(): public.tenants con LEFT JOIN sgd_param_admin. regimen <> 'privada' da 60 aunque el parámetro diga otra cosa. PLAZO_PUBLICIDAD_DIAS_HABILES = 60 (archive_service.py:149) queda como plazo público y como valor por omisión.
  • El cálculo. _fecha_minima_de_publicacion (:6534) recibe los días. Con 0 no mide calendario y la mínima es hoy; con más de 0 sigue fail-closed calendario_sin_festivos.
  • El validador. LotePublicar._plazo_util (schemas/archive.py:1034) rechaza publicado_hasta <= hoy y haría imposible el 0: se retira, y plazo_publicacion_insuficiente del servicio cubre el pasado. En publica la mínima es 60 días hábiles, así que no se relaja nada.
  • El aval no cambia. publicado_hasta < CURRENT_DATE sigue en el WHERE (archive_repository.py:2876). Un plazo 0 se avala desde el día siguiente. No se abre un camino especial.
  • Se congela en el lote. Migración de tenant archive 099_regimen_en_el_lote.sql: eliminacion_lotes.regimen_al_publicar TEXT y plazo_dias_habiles INT (CHECK 0..60), fijados en publicar en el mismo UPDATE y en el asiento.
  • Cambio de régimen con un lote en curso. Si el lote se publicó en privada y la entidad pasa a publica, avalar y ejecutar lo rechazan con 409 lote_publicado_en_otro_regimen: se anula y se publica de nuevo. La condición va en el WHERE del aval y al inicio de _ejecutar_lote_bajo_candado. El sentido contrario no afecta.
  • Plazo 0 no es público. Sin plazo no hay a quién oírle, y decir «puede oponerse» sería falso. Un lote con plazo_dias_habiles = 0 no sale en /api/v1/public/archive/eliminacion/{tenant}/lotes (404 idéntico al de un lote inexistente). Con plazo mayor a 0 se publica como siempre.
  • Lectura nueva. GET /api/v1/eliminacion/plazo-publicidad (USUA_PERM_TRD): {regimen, dias_habiles, fecha_minima}, para el aviso de pantalla y la tool consultar_plazo_publicidad.

D5. Convalidación: se conserva el estado, cambia la palabra. La convalidación no bloquea mecánicamente a una privada y no se abre excepción:

  • disposicion_final_autorizada (trd_disposition.py:78) pide convalidada, o derogada con acto.
  • POST .../convalidar exige acto, fecha e instancia como texto libre; el CHECK trd_series_convalidada_acto_check (037) solo exige que no sean nulos, y nada verifica que la instancia sea un Consejo.
  • Una privada adopta su TRD por borrador → aprobar → convalidar con su instancia interna («Gerencia General») y su acto interno. Una migrada se ratifica por la misma ruta (_TRD_CONVALIDAR_DESDE, archive_service.py:4494).

Es lo mínimo y conserva instrumento_no_gobierna: un instrumento sin acto de adopción sigue sin gobernar una eliminación, en cualquier régimen. Lo que cambia es el vocabulario: en privada la pantalla dice «Adoptada por» e «Instancia que adopta». Límite: el snapshot se congela al cerrar, así que un expediente cerrado bajo una migrada conserva serie_estado='migrada' y da instrumento_no_gobierna aunque la serie se ratifique después. Si excribe tiene de esos, necesita una decisión aparte; no se pudo comprobar (ver Pendientes).

D6. Lo que dicen el acta y lo público.

  • Acta. En privada, publicidadPrevia añade regimenArchivistico=privada y plazoDiasHabiles, y con plazo 0 sinPublicidadExterna=true. Son elementos opcionales: el acta de una entidad pública sigue byte a byte igual, como plazoOposicionEfectivoHasta (eliminacion_acta.py:155). Los nombres técnicos actoConvalidacionTrd y actaAprobacionTrd no se cambian: no citan norma y romperían la verificación.
  • API pública. LoteEliminacionPublico.regimen_al_publicar y un campo regimen en el cuadro público. El CSV del cuadro (public_cuadro.py:58-59) omite las columnas rusd_* en privada; en publica no cambia un byte.
  • Sin citar norma que no aplica, en privada:
  • (public)/eliminacion/+page.svelte:61 deja de citar la Ley 594 art. 24 y «convalidada»;
  • (public)/eliminacion/[id]/+page.svelte:93 deja de citar la Ley 1712 como obligación;
  • (public)/cuadro-clasificacion/historial/+page.svelte:36 no dice «el Consejo»;
  • (app)/admin/eliminacion/+page.svelte:333-337 y :977 no citan el Acuerdo, y el aviso usa el plazo real;
  • apiError.js:740 no afirma 60 días.
  • Mensajes del backend. plazo_publicacion_insuficiente (archive_service.py:6465) y los de retención (:8822, :9161) citan el Acuerdo solo en publica. Un helper core/regimen.py::cita(regimen, texto) evita copiar la condición. Los comentarios de código no se tocan.
  • MCP. procedures.py:956 y catalog.py:4809 dicen «como mínimo el plazo de publicidad de la entidad (60 días hábiles en régimen público)». registrar_rusd_* y registrar_certificado_rusd_* advierten que no aplican en régimen privado. trd_sin_certificado_rusd entra a ERRORES_CONOCIDOS.

D7. Provisión y marcado. scripts/init_tenant.py --regimen-archivistico {publica,privada}, por omisión publica, en register_tenant (:216). TenantCreate admite el campo con el mismo valor por omisión, y el asiento de alta lo dice. Sin backfill: DEFAULT 'publica' deja a toda entidad como hoy. /auth/me publica regimen_archivistico para la pantalla (orpycamcp_common.tenant.regimen_archivistico: solo 'privada' literal; lo demás es publica). En el V330: orpyca dc exec -T tenant-service … por el script de D1, o un subcomando orpyca regimen en ~/codigo/infraTorre/v330/orpyca/orpyca, que es de otro repo.

D8. Lo que este ADR no cambia. Una privada sigue con cuadro público, índice de clasificados, OAI y ventanilla tal como están. Si le aplican o no lo dirá el asesor. Las fases del lote (proponer, publicar, avalar, ejecutar) y la separación de funciones tampoco cambian.

Parte 2. Baja y alta de personas

D9. El corte va en validate. Toda petición de usuario pasa por el gateway, y este por GET /auth/validate (api-gateway/app/middleware/auth.py:275). Ahí ya se tiene la fila. ValidateResponse gana cuenta_estado: Literal["activa","inactiva"] | None, leído de user["is_active"]. El gateway responde 403 cuenta_inactiva junto al veredicto de la entidad (auth.py:395-417), también con validación cacheada, y no cachea el inactiva, para que un alta sea inmediata. Efecto: una sesión abierta se corta en 15 s como máximo (AUTH_CACHE_TTL, una entrada ya cacheada), y un login nuevo obtiene token de Keycloak pero ninguna petición pasa.

D10. Por qué 403 y no 401. valid=false daría 401: el front renueva, redirige a login, Keycloak reentra por SSO y se forma un bucle. El 403 con código propio se clasifica como tenant_inactivo (estadoEntidad.js:54, (app)/+layout.server.js:155): pantalla «Su cuenta fue dada de baja en esta entidad» con salir, sin reintentos.

D11. Se descarta deshabilitar en Keycloak. No hay cliente de administración ni cuenta de servicio en el repo: exigiría un secreto nuevo con poder sobre el realm y una escritura entre dos sistemas sin transacción, para ganar poco frente a D9. Incremento aditivo si un día se pide. Lo que no cubre D9: una respuesta en curso (SSE del asistente) termina su turno, y los trabajos de fondo ya encolados siguen.

D12. Pantalla. En /admin/usuarios: «Dar de baja» y «Reactivar» por fila, motivo 10..500, espejo de USUA_PERM_ADMIN nivel 3, deshabilitado sobre uno mismo y para una cuenta ROOT si quien opera no es ROOT. Filtro activos/inactivos sobre el listado, que ya trae a todos. Texto del modal: «La persona deja de poder entrar y operar en esta entidad en menos de un minuto, también con una sesión abierta. Se revocan sus credenciales de asistente y no vuelven al reactivar. No se borra nada. Sus trámites asignados no se reasignan solos». Proxy nuevo en api/[id]/baja y api/[id]/alta. Se corrige el comentario falso de +page.svelte:22-23.

D13. Nada en el perfil. Nadie se da de baja a sí mismo (rbac_service.py:300). /perfil no gana nada.

Parte 3. Plantillas y metadatos en el MCP

D14. Dos defectos previos que abrir sin corregir sería peor.

  • Sin asiento y a nivel 1. crear_plantilla, fijar_alcance y borrar_plantilla (borrador_service.py:152-166, :202-217, :248-250) no asientan nada, y sus rutas exigen USUA_PERM_ADMIN sin min_crud (borradores.py:125, :185, :263; lista de excepciones en test_escritura_exige_nivel.py:120,129,130). Suben a nivel 3 y salen de esa lista, con asientos document.plantilla_creada|alcance_cambiado|retirada|reactivada atómicos.
  • DELETE físico. delete_plantilla (borrador_repository.py:197) y metadata_repository.py:157 hacen DELETE FROM. ADR-065 lo dejó como deuda de catálogos, y esto lo cierra en estas dos tablas: DELETE pasa a activo=false conservando el 204. POST /api/v1/plantillas/{id}/reactivar es nuevo; un elemento se reactiva con PATCH activo=true. combinar y crear borrador desde una plantilla inactiva: 409 plantilla_inactiva.

D15. Lo que se abre. Todas write=True, con operacion, ejemplo y destructive=False (se revierte).

Operación Tool Permiso min_crud Peldaño Tarjeta / confirmación obligatorios_condicionales
POST /plantillas crear_plantilla USUA_PERM_ADMIN 3 4 (enmendado en la ronda de auditoría): un confirmar_con sobre un valor que dictó el propio modelo no es un dato que el modelo no pueda adivinar Lectura("listar_plantillas", {"todas": True}, (("Plantillas ya existentes", "[]"),)); la tarjeta lleva nombre, es_global, cuerpo y dependencias enteros ninguno: dependencias vacía con es_global=false es válida (no la ve nadie) y se dice en la descripción
PUT /plantillas/{id}/alcance fijar_alcance_plantilla USUA_PERM_ADMIN 3 3: es_global=true borra la lista Lectura("listar_plantillas", {}, (("Plantilla","nombre"),("Alcance actual","es_global")), frase="nombre", en_lista=("id","@plantilla_id")) ninguno
DELETE /plantillas/{id} retirar_plantilla USUA_PERM_ADMIN 3 3: la saca de circulación para todos; reversible la misma lectura no aplica
POST /plantillas/{id}/reactivar (nueva) reactivar_plantilla USUA_PERM_ADMIN 3 3: vuelve a estar disponible la misma lectura no aplica
POST /metadata/elements crear_elemento_metadato USUA_PERM_TRD 3 4: cambia el formulario de todo radicado nuevo Lectura("listar_elementos_metadato", …): los ya definidos opciones con tipo_dato=select
PATCH /metadata/elements/{id} actualizar_elemento_metadato USUA_PERM_TRD 3 4: ídem Lectura("consultar_elemento_metadato", {"element_id":"@element_id"}, (("Elemento","etiqueta"),("Clave","clave"),("Tipo","tipo_dato"))) opciones con tipo_dato=select
DELETE /metadata/elements/{id} retirar_elemento_metadato USUA_PERM_TRD 3 4: ídem la misma lectura no aplica
POST /metadata/templates crear_plantilla_metadato USUA_PERM_TRD 3 4: json_schema valida todo documento nuevo del tipo Lectura("listar_plantillas_metadato", {"tipo_documental":"@tipo_documental"}, …): versiones ya registradas ninguno
POST /expediente-metadata/templates crear_plantilla_metadato_expediente USUA_PERM_TRD 3 4: ídem para el expediente Lectura("consultar_serie", {"serie_id":"@trd_serie_id"}, (("Serie","name"),("Código","code"))) ninguno

El peldaño 3 de plantillas responde a que una plantilla no altera lo vigente: quien redacta elige usarla. El peldaño 4 de metadatos responde a que el esquema se impone a todos los documentos nuevos, que es lo que ADR-067 D6 reserva a la sesión. La tarjeta de /aprobar debe mostrar json_schema y opciones completos, para que no se apruebe a ciegas (R6 y R7 de ADR-067).

D16. Lo que sigue fuera.

  • POST /plantillas/importar cambia de [REG] a [BIN] con su propia entrada en NO_OFRECIDAS: recibe bytes .docx/.odt y no guarda nada. La vía es dar el cuerpo a crear_plantilla.
  • DELETE /tipos-documentales/{id} sigue [REG], porque la baja es activo=false.
  • Y las [REG] que son la regla con que se cuenta y se reparte: PUT /config/mcp-externo, PUT /config/params/{key}, PUT /config/asistente, PUT /config/zona-horaria, POST /config/holidays, POST /config/holidays/seed, DELETE /config/holidays/{id}, POST /catalogos/{id}, PATCH|DELETE /catalogos/{id}/{id}, POST /dependencias, POST /dependencias/{id}/mapeos-nombre, PATCH|DELETE /dependencias/{id} y POST|PATCH|DELETE /workflow/rules.
  • Reactivar expedientes sigue en peldaño 3 por MCP: decisión del usuario, sin cambios.

En NO_OFRECIDAS (scope.py:182, :402) se retira «Crear, importar o borrar plantillas de documento» y la otra queda como «Borrar tipos documentales».

D17. La frase pública. docs/es/mcp-conectar-cliente.md:85-86 y su par en docs/en pasan a: «Por este canal no se ofrece nada que ensanche el propio alcance (grupos, permisos, clearance, credenciales), ni la regla con que se cuentan los plazos y se reparte el trabajo (calendario, parámetros, zona horaria, catálogos cerrados, dependencias, reglas de reparto). Las plantillas de documento y el esquema de metadatos sí: el esquema exige la última firma en la sesión de la persona (peldaño 4)».

Parte 4. Compuerta de vencimiento en transferencias

D18. La regla. Una transferencia primaria exige fin_archivo_gestion vencido y una secundaria fin_archivo_central, leídos de expedientes_todos.disposition, con <= CURRENT_DATE en la zona que fija la conexión (ADR-062). Son los nombres reales (archive_service.py:4108-4109, 098). NULL se rechaza. Código 409 retencion_no_vencida, el mismo de decidir, con fase y fecha_vencimiento; ERRORES_CONOCIDOS amplía su texto. El Ac. 001/2024 lo sustenta en el art. 4.4.3 par. 1 («una vez cumplidos los tiempos de retención en el archivo de gestión») y el art. 5.1.5.1.

  • Servicio. ArchiveRepository.retencion_fase_vencida(expediente_id, fase), un solo predicado, llamado dentro de la transacción y tras el bloqueo de revisión pendiente, porque un re-amarre mueve las fechas: transferencia_service.py:313 (create), :694 (enviar), :783 (recibir) y archive_service.py:2307 (transfer_expediente, que no tiene tipo y mide gestion).
  • MCP. crear_transferencia, enviar_transferencia, recibir_transferencia y preparar_transferencia pasan por esas mismas rutas: no necesitan gate propio, solo el texto. rechazar no se gatea.
  • Motor. Migración de tenant archive 100_compuerta_de_vencimiento_transferencias.sql: reutiliza retencion_vencida (098) y añade triggers BEFORE INSERT y BEFORE UPDATE OF estado hacia enviada|recibida en transferencias, más BEFORE UPDATE OF status hacia transferred en expedientes_todos (la red de la vía corta). CONSTRAINT = 'ck_transferencia_retencion_no_vencida', que el servicio traduce a 409 como ck_transferencia_unidad_prestada (072).
  • Fondo acumulado. Sin regla propia: el cálculo del calendario deja agest=0 con base_date_origen='fecha_extrema_final' (archive_service.py:4097), así que fin_archivo_gestion = fecha_extrema_final, y «calendario ya vencido es el caso normal» (archive_service.py:4073). La primaria pasa si la fecha extrema ya pasó y la secundaria mide la central.
  • En curso. Sin migración ni backfill. Lo preparada o enviada se revisa al siguiente paso; si no cumple, rechazar sigue disponible.
  • Retención legal. No hace vencer nada. Primaria: no bloquea, porque es custodia interna y la retención va con el expediente. Secundaria: 409 legal_hold_activo, porque es ejecutar la disposición final, y None del registro se trata como fallo (archive_service.py:7941 es el patrón correcto).
  • Físico. fisico_service.py no transfiere: lo que hace es prestar y bloquear préstamos en tránsito. link_expediente (fisico.py:232) vincula a una unidad de cualquier ubicación y no es un movimiento de custodia: se deja sin compuerta porque el inventario inicial lo necesita.
  • Lotes. batch_service solo crea expedientes: no hay transferencia por lote.

D19. Transferencia anticipada: propuesta separable. El Ac. 001/2024 no contempla una transferencia anticipada: el art. 4.4.3 par. 1 es incondicional. (La palabra «anticipadamente» sí aparece en el texto, pero en otro asunto, no en el de las transferencias.) Queda además por consultar al asesor si una transferencia anticipada choca con la Ley 594 art. 20 (pendiente de asesor). Solo menciona la entrega por «liquidación, fusión o supresión» como procedencia de lo que recibe un archivo territorial, y define «situación de riesgo para el material documental» en su anexo. Por eso la compuerta de D18 se implementa sin excepción, y esta se construye solo si el asesor la confirma. Forma, sin puerta trasera:

  • Causal de catálogo cerrado: supresion_fusion_liquidacion, riesgo_conservacion.
  • TransferenciaCreate.anticipada = {causal, fundamento ≥ 20, acto_administrativo} en la creación.
  • POST /api/v1/transferencias/{id}/autorizar-anticipada, USUA_PERM_TRD nivel 3, por persona distinta de creada_por (CHECK en el motor), con asiento y constancia en el FUID.
  • Los triggers de D18 solo ceden con anticipada_autorizada_por IS NOT NULL.
  • La vía corta nunca la admite, y queda fuera del MCP ([ACT]): crear_transferencia no declara el parámetro.

Enmienda a ADR-067

D6 decía que las REG «quedan sin decidir» y la ronda decía que plantillas y metadatos seguían sin abrirse. Quedan abiertas las de D15; el guardián test_el_flujo_de_administracion_no_ofrece_ninguna_escritura no se afloja, porque sus prefijos son /auth/, /config/, /catalogos y /dependencias. R2 («no toca Keycloak, la sesión interactiva se corta en el proveedor de identidad») se corrige con D9: se corta en validate, y la propuesta de esas dos rutas queda aprobada por el dueño.

Enmienda: el documento que se aprueba en /aprobar (2026-11)

Los tres actos de «lo he leído y lo apruebo» del peldaño 4 (firmar_anexo_simple, dar_visto_bueno, aprobar_version_publica) muestran ahora el documento atado (ver la enmienda de ADR-067). Efecto en este ADR: en el régimen privado la aprobación de la versión pública y de las plantillas y metadatos que se abren por MCP sigue el mismo principio de lo visto es lo firmado, y la entidad privada sin certificado RUSD no cambia: el visor no depende del régimen, solo del clearance y el permiso de quien aprueba. Nada se borra: la propuesta con un archivo cambiado no se consume, simplemente no sirve.

Consecuencias

  • Una entidad mal marcada privada se salta el RUSD y acorta su publicidad. El control es el acto de plataforma con motivo y asiento, y el encuadre queda pendiente de asesor.
  • Una privada en privada deja de dar la garantía de publicidad externa si fija plazo 0. Es la decisión de la entidad y su acta lo dice.
  • Una baja corta en 15 s sin tocar Keycloak; la persona aún ve el login del proveedor y, tras él, la pantalla de cuenta dada de baja.
  • Transferir antes de la fecha deja de ser posible en todos los caminos. Los planes de transferencia que adelantaban fechas quedan fuera del sistema hasta D19.
  • Abrir metadatos por MCP pesa por el peldaño 4: la persona aprueba en su sesión.

Pendientes y lo no verificado

  • Concepto del asesor sobre D1-D4, D8 y D19. Ley 594 art. 2 y la causal de entidades suprimidas no se cotejaron con texto oficial en este repo.
  • Estado real de excribe en el V330: qué instrumentos tiene, si están convalidada o migrada, y si tiene expedientes cerrados con snapshot migrada (D5).
  • Secundaria tras primaria: resuelta en ADR-069, que además retira la vía corta.
  • Una secundaria tampoco comprueba que la disposición sea conservación total o selección (Ac. 001/2024 art. 4.4.4). Sin tocar aquí.
  • decidir_disposicion usa if holds: y deja pasar None (archive_service.py:8833-8834), contra lo que promete holds_activos_de_expediente. Defecto aparte, de una línea.

Enmiendas de la ronda de auditoría (2026-11-06)

Verificadas contra el código antes de corregir. Las referencias archivo:línea de este ADR describen el código al diseñarlo; ya se movieron y no se mantienen.

  • D2 y script. El aviso añade «ni presta un servicio público» (Ley 594 art. 3, pendiente de concepto de asesor).
  • D7 (enmendado). privada ya no se admite en el alta: ni POST /tenants (TenantCreate rechaza campos desconocidos) ni init_tenant.py (sin --regimen-archivistico). La única vía es el acto de D1, que deja motivo y operador. Migración global 011_tenants_privada_exige_procedencia: privada exige los tres campos de procedencia.
  • D4. El portal público no deduce el régimen de los lotes: GET /public/archive/eliminacion/{tenant}/plazo entrega {regimen, dias_habiles} (una entidad inexistente responde lo mismo que una pública). Con plazo 0 el portal dice que la entidad no publica previamente sus inventarios y no niega ejecuciones. El acta de plazo 0 omite publicadoDesde y plazoOposicionHasta. regimen_al_publicar y plazo_dias_habiles son inmutables una vez fijados (migración archive 101). Un lote ejecutado_parcial publicado en privada no se puede anular: el 409 lote_publicado_en_otro_regimen lo dice y no manda anular.
  • D6. cita() se extendió a los mensajes de índice no firmado, ubicaciones requeridas, retención y rechazos de propuesta; en privada los botones dicen «Adoptar» y «Detalle de la adopción».
  • D9. cuenta_estado admite desconocida (la entidad opera pero la fila no se pudo resolver: colisión de username con una cuenta local o error inesperado): el gateway responde 503 cuenta_estado_no_disponible y no cachea. Antes salía null y la baja no cortaba.
  • D12. La baja devuelve y asienta tramites_a_cargo (pasos activos asignados) y no los reasigna; la reasignación no admite como destino una cuenta dada de baja. Una cuenta ROOT por bandera o por permiso de grupo solo la baja o da de alta un ROOT. GET /auth/users?activo= filtra en el servidor.
  • D14. Una plantilla global con dependencias es 422. GET /plantillas sin todas devuelve solo las activas aunque se pida activo=false. PATCH y retirar un elemento asientan antes y despues; un elemento retirado es 404 para quien no administra. Un json_schema con $ref que no empiece por # se rechaza (SSRF), también al validar los ya guardados. Una versión nueva activa de una plantilla de metadatos desactiva la vigente en la misma transacción.
  • D15. crear_plantilla sube al peldaño 4. Se verificó que nada consume metadata/elements en la radicación (solo la administración de metadatos); aun así se conserva el peldaño 4, lo más restrictivo, y el motivo correcto es que el vocabulario y los esquemas son regla de la entidad, no que cambie hoy el formulario de cada radicado. Las listas (dependencias, opciones) se ven enteras en la tarjeta; es_global es obligatorio. El conteo de [REG] que da el censo ejecutado es 18, no 25.
  • D18. El trigger de expedientes_todos mide la fase central cuando hay una secundaria enviada o recibida del expediente. Los asientos de preparar y de la vía corta llevan regimen_archivistico. Límites vigentes declarados: secundaria tras primaria inalcanzable y secundaria sin comprobar CT/S; excepciones: link_expediente y el tipo_archivo de la ubicación.
  • D19. No se construye.
  • Secundaria solo con CT o S (art. 4.4.4, decisión del dueño). 409 disposicion_no_transferible_a_historico en preparar, enviar y recibir una secundaria cuya disposición (disposition_code del snapshot) no sea CT/conserve/S/select; ausente, E y M se rechazan, y la migración archive 102 lo repite en el motor. M queda pendiente de asesor (lo más restrictivo por ahora). Deja de ser una limitación vigente; sigue la de secundaria tras primaria.