ADR 0014 — Aislamiento de los bytes de nivel 3 en R2 y modelo de credenciales
- Estado: aceptado (aprobado por el usuario el 2026-10-16; la reorganización del bucket y de los tokens la ejecuta el usuario siguiendo los pasos de la bitácora de la Fase 2; la regla transitoria de la decisión 6 rige hasta que
dvc remote listmuestrer2-openyr2-restricted) - Fecha: 2026-10-16
- Complementa: ADR 0007 (remote DVC en R2) y ADR 0010 (niveles de congelamiento)
- Origen: hallazgo crítico C1 de
docs/reviews/f2-adversarial.md
Contexto
El ADR 0007 creó un único bucket R2 (tinkuy-qhali-raw) como remote DVC y dejó abierto “exponer el bucket con dominio público”; el plan 3-2-1, el verificador de mirrors, la carta de espejo y run.sh (ADR 0011) usaban ese bucket como fuente compartida (dvc pull de mirrors, usuarios y CI, token de solo lectura en GitHub Actions, verificación --deep que descarga el objeto). Con 15 fuentes en nivel 3 en el mismo bucket, cualquiera de esas vías copiaría bytes de ENDES a un soporte multiusuario (runners de GitHub, máquinas de terceros), lo que la política ANDA del INEI prohíbe sin consentimiento escrito (ADR 0010). Nada en la configuración impedía que una credencial de lectura o un bucket público alcanzara objetos de nivel 3.
Alternativas
- Un bucket público para todo: descartado; viola la política del INEI para nivel 3.
- Un bucket privado único con credenciales compartidas de lectura: descartado; es el estado actual y no distingue niveles.
- Dos remotes DVC (prefijos o buckets separados por nivel) con credenciales distintas: elegido.
Decisión
- Dos remotes DVC en
.dvc/config:r2-openpara niveles 1 y 2 (prefijo o buckettinkuy-qhali-open) yr2-restrictedpara nivel 3 (prefijo o buckettinkuy-qhali-restricted). Cada.dvcderaw/declara su remote (dvc add --to-remote/remote:en el archivo) según elfreeze_leveldel manifiesto; un test rechaza un.dvcde nivel 3 apuntando ar2-open. - Credenciales: el token de escritura y lectura de
r2-restrictedexiste solo en la máquina del usuario (.dvc/config.local, nunca en secretos de GitHub ni en la imagen). Parar2-openpuede existir un token de solo lectura en CI y para mirrors. Ningún bucket que contenga nivel 3 se expone con dominio público; la frase correspondiente del ADR 0007 queda sin efecto. - Verificador de mirrors (
verify_mirrors.py) en CI: para ubicaciones de nivel 3 solo hace comprobación mínima (HEAD/listado del objeto y tamaño) con el token der2-opensi el objeto está ahí (no debería) y, si no tiene credenciales, marcaskipped; nunca--deepsobre nivel 3 fuera de la máquina del usuario. Un objeto de nivel 3 alcanzable con credenciales de CI o público espolicy-violationy falla el workflow. run.sh/run.bat: si no hay credenciales der2-restricted, el pipeline cae aTQ_SYNTHETIC=1(datos sintéticos) o a los marts de nivel 1–2 disponibles; no pide ni acepta un token compartido.- Carta de espejo e instituciones: reciben únicamente niveles 1 y 2 (por Zenodo o
r2-open); el nivel 3 no se ofrece, y una fuente de nivel 3 con consentimiento escrito pasa a nivel 2 por definición (ADR 0010, R5). - Regla transitoria mientras este ADR no se apruebe e implemente: el bucket actual se trata como
r2-restricted(contiene ENDES, nivel 3); no se crea ningún token de lectura para CI ni terceros; no se activa dominio público;mirrors-verify.ymlpermanece como placeholder. - Marts fila-nivel de nivel 3 (resuelve M3 de la revisión): no se guardan en DVC ni en R2; son regenerables desde
raw/contargetsy viven solo en el volumen local. El ADR 0010, decisión 5, se lee así en adelante.
Consecuencias
- Pasos del usuario tras aprobar: crear el bucket o prefijo
tinkuy-qhali-open, un token de solo lectura para CI limitado a él, y mover (o dejar) los objetos de nivel 3 en el actual renombrado comor2-restricted;dvc remote addde ambos;dvc pushde ENDES al restringido (ya está, basta renombrar el remote). - Fase 3: test
tests/test_freeze_remotes.sh(.dvcde nivel 3 →r2-restricted), pasopolicy-violationen el verificador,run.shcon la caída a sintéticos,MIRRORS.mdcon columnaremote. docs/preservation/*.md, ADR 0007 y ADR 0011 se corrigen en el mismo commit que este ADR para no ofrecerdvc pullcompartido de nivel 3.- Provisional: si una copia transitoria en un runner de GitHub cuenta como “soporte multiusuario” para el INEI no se resuelve: la decisión 3 lo evita por diseño; la revisión legal de la Fase 3 lo anota.