ADR-066: Anexos de expediente sin radicado¶
Estado: Aceptado Fecha: 2026-11-05 Autores: Giampiero (mantenedor principal) Relacionados: ADR-022 (índice electrónico), ADR-058 (gate de formato), ADR-065 (nada se borra)
Contexto¶
Orfeo permite subir un anexo a un expediente sin radicarlo (anexos_expediente: tipo documental de la matriz de la serie, fecha de elaboración, folios, huella SHA-256, historial al corregir, baja como marca y no como borrado). OrpycaMCP solo admitía radicados vinculados, y los anexos colgaban de un radicado. Un archivista no tenía dónde incorporar un informe, un acta o un escaneo, y el agente de la entidad (Hermes) no podía guardar un informe en un expediente sin radicarlo.
Copiar Orfeo sin más repetiría sus defectos: SQL interpolado, autorización solo por sesión, sin clearance, y un reemplazo que pisa el archivo anterior y copia la descripción al historial.
Decisiones¶
D1. Entidad propia en archive-service, con dos tablas. expediente_anexos_todos es la identidad (número, orden documental, marca de inactivación) y expediente_anexo_version son las versiones, que solo se insertan. Los bytes siguen en storage y document-service no cambia. Se descarta un expediente_radicados con radicado_id nulo (su clave primaria y todos sus consumidores asumen un radicado) y permitir NULL en anexos_todos.radicado_id (document revisaría cada lectura). El índice se regenera dentro de la transacción del acto, bajo el mismo bloqueo de ordinal: un dueño externo metería HTTP en un tramo que está escrito para ser solo base de datos.
D2. Número y orden comunes. El número es {código del expediente}-A{orden:06d} e inmutable. El orden documental es común con los radicados: siguiente_orden_documental(expediente) toma el mismo bloqueo por expediente y devuelve el mayor de ambas tablas más uno; un disparador cruzado rechaza un ordinal repetido, porque los índices únicos de cada tabla no ven la otra. Dos documentos de un expediente no pueden compartir <orden>.
D3. Nada se borra (ADR-065). La identidad lleva inactivado_* y su vista expediente_anexos oculta lo inactivo; las dos tablas rechazan DELETE y TRUNCATE en el motor y la versión rechaza UPDATE. version_vigente y sha256_vigente solo las mueve el disparador de la versión insertada: no hay puntero que pueda quedar incoherente. Corregir añade una versión y conserva el archivo anterior.
D4. El motor guarda el estado del expediente. Adjuntar, corregir, inactivar y reactivar exigen el expediente open; el disparador toma FOR SHARE sobre el expediente, que choca con el UPDATE del cierre y cierra la carrera que una comprobación previa deja abierta. La cascada del lote de eliminación actúa sobre expedientes cerrados y no pasa por esa guarda.
D5. El nivel es del expediente. El anexo no tiene clearance propio: hereda el del expediente, que ya va en la cabecera del índice. Un nivel propio exigiría reserva motivada, vencimiento, desclasificación y entrada en el índice del art. 20 de la Ley 1712: la maquinaria de los ADR-045 y ADR-049 duplicada. Lo que necesite otro nivel se radica o va en un expediente reservado. El gate va en el WHERE de cada consulta y, a diferencia de vincular un radicado (M2), no hay modo de componer sin leer: quien aporta contenido recibe número y orden, que delatan cuántos documentos hay; quien no alcanza el nivel recibe el mismo 404 de «no existe».
D6. Tipo documental de la matriz de la serie vigente. El tipo es obligatorio y se valida contra la versión vigente del código de serie del expediente (expediente_sin_serie si no tiene serie o es una TVD; trd_version_no_vigente si no hay vigente), porque trd_serie_id flota mientras el expediente está abierto y la convalidación re-apunta los tipos. GET …/tipos-admitidos lo resuelve en el servidor.
D7. Gate de formato de ADR-058, con un solo evaluador. El evaluador puro se mueve a orpycamcp_common.conformidad_tipo y lo llaman exactamente dos módulos (document para los radicados, archive para los anexos); un guardián de shared/tests lo fija. El anexo se juzga contra el tipo exacto elegido, sin la ambigüedad que ADR-058 acepta para un radicado. El MIME y el estado PDF/A salen de files, nunca del cliente. Mismo contrato de rechazo: 422 formato_no_planeado_en_trd, 409 formato_no_verificable con Retry-After, 503 conformidad_no_verificable; el veredicto viaja en el asiento (conformidad_formato). Corregir con archivo o tipo nuevos vuelve a juzgar.
D8. Índice electrónico perfil v5. Entra como <documento clase="anexo"> con su orden. Se sube de perfil y no se añade un atributo a v4 porque un mismo espacio de nombres no puede describir dos estructuras (ADR-022): clase es obligatorio, y se suman fechaElaboracion y versionContenido opcionales. identificador es el id del anexo, titulo su número y tipologia el código del tipo; jamás el nombre ni la descripción. Un anexo inactivado sale excluido="true" conservando su orden y con una causal fija; el motivo libre puede traer datos personales y el XML queda bajo WORM. Los índices v4 ya firmados no cambian (la verificación re-hashea el XML guardado y la validación elige el XSD por el espacio de nombres). El XSD llega en el mismo cambio que el constructor: index_xsd deja pasar un espacio de nombres sin XSD, y una prueba exige schemas/indice-{XSD_VERSION}.xsd. Tres puntos asumían «documento = radicado» y se corrigen: el recorte por reserva solo consulta a document por radicados, la fixity compara también la huella vigente de los anexos (si no, ha = None rechazaría toda transferencia) y la fecha de primer uso incluye los anexos.
D9. Corregir, inactivar y reactivar. Corregir exige motivo (10 caracteres), version_esperada (409 anexo_version_desactualizada) y algún cambio (422 correccion_sin_cambios); no corrige un expediente con retención legal activa (sí se puede adjuntar, que solo añade). Los bytes de una versión no vigente exigen USUA_PERM_EXPEDIENTE nivel 3. Inactivar exige PERM_BORRAR_ANEXO nivel 3 y reactivar nivel 4 por otra persona; todas las barandillas van en el WHERE del UPDATE. El mismo archivo no puede estar vigente dos veces en un expediente (409 anexo_duplicado, por un índice único parcial), lo que además vuelve inocuo el reintento.
D10. Cascada del lote. La inactivación del expediente por un lote marca sus anexos en la misma transacción (inactivado_origen = 'expediente'), sin compensación HTTP. El recuento va a expediente_inactivacion.anexos_expediente_inactivados; reactivar el lote devuelve solo lo marcado por esa cascada. El inventario congela anexos_expediente_incluidos y el acta y el addendum lo dicen (anexosExpedienteIncluidos, anexosExpedienteInactivados); las actas firmadas no se tocan.
D11. Salidas. Entran al AIP las versiones vigentes de los anexos activos; entran a la exportación y a la descarga integral (anexos_expediente/{número}/…, y las columnas clase y numero en el manifiesto); los encuentra la búsqueda de expedientes por nombre y descripción (num_anexos); sus archivos cuentan como referencias de storage (REFERENCIAS_DE_ARCHIVO) y como archivos de un expediente reservado al publicar un radicado (vista contrato v_archivo_en_expediente_reservado); las versiones entran a los eventos de preservación. Quedan fuera, por decisión, el conocimiento (RAG), OAI/EAD, CMIS y el índice del art. 20: ninguno indexa hoy los bytes de los anexos de un radicado y el EAD para en el nivel de unidad.
D12. Trazabilidad. Cinco asientos (archive.expediente_anexo_adjuntado|corregido|inactivado|reactivado|descargado) y cuatro eventos de la hoja de ruta, en la misma transacción que el acto. Nunca el nombre ni la descripción del anexo: son contenido y viven en la versión, bajo el clearance del expediente. campos_cambiados dice qué cambió sin decir a qué. La descarga la media archive (sin URL prefirmada) y deja asiento solo con canal auditable y actor real.
D13. Subir bytes. /storage/upload y /upload/audiovisual pasan de PERM_RADI a un gate any-of con un nivel por brazo: PERM_RADI ≥ 1 o USUA_PERM_EXPEDIENTE ≥ 2. Un archivista sin permiso de radicar podría, si no, no adjuntar. Solo amplía quién sube; adjuntar sigue gateado en archive.
Qué es un anexo de expediente y qué no (U1)¶
El Acuerdo AGN 001 de 2024 manda que las comunicaciones oficiales se canalicen por la ventanilla única y se radiquen con un número único (arts. 4.2.2 y 4.2.3), distingue las comunicaciones internas (art. 4.2.4) y fija el control de las recibidas y de las enviadas (arts. 4.2.6 y 4.2.7). El Acuerdo 060 de 2001, que antes lo decía, fue derogado por el art. 10.1 del Acuerdo 001 de 2024 y no se cita. La obligación de radicar viene del Acuerdo, no se atribuye a la Ley 594.
Sin un límite, esta función sería una vía para no radicar: una petición recibida se adjuntaría a un expediente y no correría término. El texto que la pantalla, la herramienta MCP y este ADR declaran es: «Adjunte aquí documentos del trámite que no son comunicaciones oficiales: informes, actas, soportes producidos por la entidad o reproducciones de ellos. Una comunicación recibida, enviada o interna, o una petición, se radica aunque la tenga escaneada: adjuntarla no le da número ni hace correr su término. (Ac. AGN 001/2024, arts. 4.2.3, 4.2.4, 4.2.6 y 4.2.7)». Un anexo, con tipo de la TRD y lugar en el índice, es documento de archivo, no un «documento de trabajo». No hay bloqueo técnico, porque el sistema no puede saber qué es cada archivo, ni campo de declaración: la responsabilidad de radicar sigue siendo de quien adjunta.
Correcciones de la ronda de auditoría¶
- D14. El archivo no salta el nivel. Adjuntar y corregir comprueban en el motor (
archivo_supera_nivel, 097) que el archivo no sea ya el de un anexo de radicado o de expediente, activo o inactivo, de más nivel que el expediente destino: el mismo422 anexo_no_disponibleneutro. Document-service añade la misma rama a_rechazar_anexos_fuera_de_alcance. La vista de archivos de expedientes reservados cuenta también lo inactivo. - D15. U4 cambiada: un índice firmado no impide incorporar. En un expediente abierto con el índice firmado se admite adjuntar, corregir, inactivar y vincular radicados: se crea una versión nueva del índice, sin firma hasta el cierre, y la firmada se conserva sin tocar (append-only, su protección WORM intacta). Desaparece
indice_firmado_inmutable. La verificación de una versión vieja compara contra la huella que cada anexo declaraba entonces: una corrección posterior no es una alteración. - D16. U5 cambiada: sin canal de operaciones. Un anexo inactivado en un expediente que luego se cierra no se reactiva, por ninguna vía; sus bytes y su fila se conservan. Es una excepción declarada a la reversibilidad de ADR-065 D4: el índice firmado afirma
excluidoy el expediente cerrado no reabre. La pantalla y la herramienta de cierre avisan con el recuento antes de cerrar, y el asiento del cierre lleva el recuento y los números. El motor no mueve la marca enclosedotransferred(salvo la cascada del lote) y no deja cambiar su origen. La lectura controlada de lo inactivo sigue siendo una decisión pendiente del usuario (roadmap). - D17. Índice v5 antes de publicarse. Opcionales
origen(nativo|digitalizado) ymedio, ydependenciaProductora/@fuente(quien_adjunta|declarada); la productora puede declararse al adjuntar y se valida contra las dependencias activas de la entidad. - D18. El AIP lleva el historial. Solo viaja el archivo vigente, pero cada documento trae los metadatos de sus versiones y un evento PREMIS
modificationpor corrección, con la huella anterior y los nombres de los campos que cambiaron. - D19. Nombres seguros. El nombre corregido se valida (sin
./.., separadores ni caracteres de control) y en la exportación el archivo se llamav{versión}-{nombre saneado}. - Otros: la fecha de elaboración no puede ser futura; corregir solo folios o descripción no exige serie vigente; un expediente de TVD responde
expediente_de_tvdy uno con clasificación provisional usa la matriz de su versión aprobada con veredictosin_trd_vigente; el inventario cuenta lo vivo en radicados y en anexos.
Decisiones pendientes de ratificación¶
- U2. Expediente sin serie o de TVD:
409 expediente_sin_serie(«clasifique primero») y409 expediente_de_tvd(una TVD no declara tipos). No se comprobó si los expedientes de fondo acumulado abiertos necesitan esta función. - U3. Versiones corregidas en el AIP: viaja solo el archivo vigente y el historial de metadatos; los bytes anteriores quedan en el bucket y en la tabla, pero no viajan en la transferencia.
Consecuencias¶
- Migraciones de archive
095(tablas, vistas, disparadores, ordinal común) y096(clasedel ítem de índice y los recuentos), sin migración de datos. El primerregeneratede cada expediente abierto crea una versión de índice en v5, como en los saltos v2→v3→v4. Storage se despliega después de la migración:referencias()falla cerrado si falta la tabla. - El evaluador de formato pasa a la librería común: document y archive se reconstruyen juntos.
- Nuevo gate de storage para subir bytes (D13): lo revisa el auditor de seguridad.
- El MCP gana siete herramientas (
listar_,consultar_,listar_versiones_,tipos_admitidos_,adjuntar_,corregir_einactivar_anexo_expediente); reactivar, el registro de inactivados y la descarga se excluyen con su código. Quien las ofrezca por un puente (Hermes) necesitaconfirmar_accionyPERM_RADIoUSUA_PERM_EXPEDIENTEnivel 2. - Migración
097(correcciones de la ronda de auditoría): guarda sin portillo,archivo_supera_nivel, vista de reservados sobre lo inactivo,origenyfuente.