Ir al contenido

El portal en la nube: misiones, ciclo de vida y aprobaciones

🟡 Parcial — El portal descrito es el que corre hoy en platformpre (org NovaCredit), recorrido en vivo de extremo a extremo. El ciclo de vida de 8 estados, las misiones, las dos vías de alta y el flujo de aprobación con registro en git están construidos. El portal lee el veredicto de apetito firmado (overall_residual.evaluation) y lo HACE CUMPLIR: si el residual agregado supera el apetito, aprobar exige una aceptación consciente (override con motivo). El motor es la autoridad; el portal lo proyecta y lo enforcea. La supervisión humana (HOTL) y la conformidad dual se detallan en [git cierra el bucle](/metodologia/git-cierra-el-bucle/).

Bucle de colaboración de NovaCredit: Diego identifica el riesgo en el portal y se lo pasa a Marta, Marta lo trata y firma con la CLI froga, git lleva la evidencia firmada al portal, y Diego revisa y aprueba la liberación; el ciclo vuelve a empezar.

El recorrido del Nivel 1 atraviesa el bucle de punta a punta; esta guía lo mira desde el lado de Diego, con detalle. El portal no es un visor pasivo: es donde el Quality Manager declara, clasifica, sigue el estado, revisa la evidencia y aprueba la puesta en mercado. El reparto se mantiene: Diego conduce el portal y aprueba; Marta aporta y firma la evidencia desde la CLI y git. Maximizamos a ambos —cada misión del portal espera una evidencia que Marta empuja, y cada aprobación de Diego deja un commit que Marta ve en su repo.


Cuando Diego entra en el portal de NovaCredit aterriza en el panel de la organización (/[org]): un checklist de activación de cinco pasos (instala froga · conecta un repo · registra la clave del firmante · crea o explora un sistema · genera el bundle), el recuento de sistemas gobernados y el plan vigente. Es el «hogar de bienvenida» que orienta a quien acaba de dar de alta la organización.

De ahí, el trabajo de Diego vive en dos sitios: el catálogo de sistemas (/[org]/systems) y, dentro de cada sistema, su detalle (/[org]/systems/[slug]). El catálogo es la vista de cartera; el detalle es donde se conduce un sistema concreto por su ciclo de vida.

La pieza que cose todo el portal es el sistema de misiones: en cada momento, el portal deriva del estado del sistema la siguiente acción accionable y la muestra como una tarjeta. Diego no tiene que recordar el proceso ISO 23894 / EU AI Act de memoria: el portal le dice qué toca ahora.


2. El sistema de misiones: el estado propone la acción

Sección titulada «2. El sistema de misiones: el estado propone la acción»

Una misión es una tarea accionable que el portal deriva del estado del sistema —no una lista fija escrita a mano—. La regla es: cada estado del ciclo de vida tiene su misión (o misiones), y el portal solo muestra la que de verdad toca ahora.

El catálogo de misiones, en castellano llano (las del estado declared van en orden, las demás son del estado correspondiente):

EstadoMisión(es)Qué pide
IndeclaradoDeclarar el sistema (froga.yaml)Aún no hay manifiesto; el dev debe commitearlo
DeclaradoDeclarar estándares → Clasificar (Anexo III) → Identificar riesgos (ISO 23894 §6.4) → Justificar el hueco de datosCuatro sub-pasos secuenciados
AseguradoEsperando evidencia del equipo devMarta debe entrenar y empujar el bundle
Evaluado (barrera roja)Planificar tratamiento del riesgoEl residual excede el apetito; hay que tratar
Evaluado (barrera verde, owner)Revisar y aprobar el sistemaDiego es la autoridad: aprueba directamente
Evaluado (barrera verde, maintainer)Solicitar aprobaciónMarta pide; no aprueba
En tratamientoEsperando evidencia del equipo devYa hay plan; Marta re-entrena y empuja V2
AprobadoDescargar Anexo IV · Descargar Declaración (DoC)Entregables universales (+ DORA RoI si aplica)
Comercializable(sin misiones)Ciclo cerrado

El orden de las cuatro sub-misiones de Declarado no es estético: es una dependencia normativa. No puedes clasificar el sistema como Anexo III §X sin haber declarado antes qué marcos regulatorios aplican; no puedes identificar riesgos significativos sin saber a qué categoría de alto riesgo pertenece; y el catálogo de variables protegidas (el hueco de datos) se acota por los riesgos ya identificados. Por eso el portal muestra el siguiente sub-paso accionable y deja los posteriores bloqueados con un tooltip hasta que su prerrequisito esté hecho.

Identificar riesgos no es solo enumerar fallos del modelo. El EU AI Act Art. 9(2)(b) y la ISO/IEC 42001 §6.1.4 exigen también analizar el mal uso razonablemente previsible: los escenarios en que el sistema se usa de forma distinta a su finalidad y pueden derivar en daño. En froga.yaml, esto vive en system.potential_misuses (id, description, addressed_by), donde addressed_by enlaza los riesgos que lo atienden. Un mal uso sin ningún riesgo que lo cubra es un hueco de identificación (§6.1.4) que el programa de aseguramiento no ha cerrado. El comando froga impact cruza esa lista con el registro de riesgos y señala los mal usos sin cobertura (advisory).

flowchart LR
  s1["Declarar<br/>estándares"] --> s2["Clasificar<br/>(Anexo III)"]
  s2 --> s3["Identificar riesgos<br/>(ISO 23894 §6.4)"]
  s3 --> s4["Justificar el<br/>hueco de datos"]

Hay además dos misiones normativas que el portal emite cuando hay riesgos modelados: «Completa el tratamiento del riesgo X» (un riesgo declarado sin tratamiento, enlaza a su ficha) y «El riesgo residual agregado supera el apetito» (si la coherencia lo detecta). Estas derivan de la proyección del bundle: la nube no recomputa el riesgo, solo lo superficia.

1El portal me dice «Esperando evidencia del equipo dev». ¿Qué hago yo, y qué hace Marta?
🛡️ Diego

«El sistema está en “Asegurado” y la misión dice “Esperando evidencia del equipo dev”, sin botón. Como conduzco el portal, ¿esto es un callejón sin salida o una señal de que la pelota está en otro tejado?»

🧑‍💻 Marta

«Es lo segundo, a propósito. Hay estados que el motor avanza por evidencia, no el portal por un trailer humano: assured y treated son dos de ellos. La misión sin acción es informativa —te dice qué se está esperando— mientras yo entreno y hago froga run + git push. En cuanto el bundle firmado llegue al repo, la nube recalcula el estado a “Evaluado” y tu misión cambiará sola a “Revisar y aprobar” (si la barrera sale verde) o “Planificar tratamiento” (si sale roja). No tienes que refrescar nada conceptual: el estado lo deriva del log de git.»


3. Las dos vías de alta: crear frente a explorar

Sección titulada «3. Las dos vías de alta: crear frente a explorar»

Hay dos formas de meter un sistema en el portal, y elegir la correcta evita el error más común del taller.

  • «Crear sistema» (/[org]/systems/new). La nube crea un repositorio nuevo en tu proveedor y siembra un froga.yaml inicial (finalidad prevista y malos usos previsibles) y registra el sistema. Pide: Nombre, Finalidad prevista, Organización (opcional), Malos usos (opcional), Conexión, y si el repo es privado. Es para empezar de cero.
  • «Explorar un sistema existente» (/[org]/systems/explore). Atas un repositorio que ya expone artefactos .froga/ (de cualquier proveedor). La nube lo lee para validar el acceso antes de registrarlo; no escribe nada. Pide: Nombre, Conexión, Repositorio (propietario/repositorio), Referencia (rama o etiqueta, opcional) y Ruta (subcarpeta, opcional). Es para incorporar trabajo que ya existe —atar un repo que Marta ya había empujado con su evidencia firmada—.

Ambas vías terminan igual: un sistema en el catálogo, con su conexión, listo para que el ciclo de vida lo conduzca. La diferencia es quién pone el froga.yaml: la nube (crear) o Marta, antes, desde su repo (explorar).


El catálogo (/[org]/systems) sigue el patrón de un catálogo de servicios: una tabla universal a la derecha y filtros a la izquierda.

La tabla muestra, por sistema: Nombre, Estado del ciclo de vida (el badge —«Evaluado», «Aprobado», «Comercializable»…), Marco aplicable (los estándares derivados del bundle: eu/pren-18228, iso/23894, eu/ai-act…), Veredicto y Última evidencia. Arriba, un panel de Incorporación con las misiones de arranque (Crea un sistema nuevo · Explora un repositorio existente · Invita a tu equipo) que se oculta cuando ya no hay nada pendiente.

Los filtros son dos facetas, calculadas sobre la cartera completa (cada chip lleva su recuento): Estado del ciclo y Marco aplicable. El filtrado es AND entre dimensiones y OR dentro de cada una, más una búsqueda por nombre. Sirve para responder preguntas de gestión: ¿cuántos sistemas tengo en «Evaluado» esperando mi aprobación? o ¿cuáles caen bajo el EU AI Act?

Lista de Sistemas gobernados del portal de NovaCredit con el sistema clasificador-credito en estado «Evaluado» y los marcos aplicables eu/pren-18228, iso/23894 y eu/ai-act.
El catálogo de sistemas (Diego · portal): la cartera con clasificador-credito en estado «Evaluado» y sus marcos aplicables. Cada fila enlaza al detalle del sistema.

Pulsar una fila lleva al detalle del sistema (/[org]/systems/[slug]), que es donde Diego conduce un sistema concreto. La página tiene tres zonas estables alrededor del contenido.

Cabecera. El nombre, el badge de estado del ciclo, los marcos aplicables y un enlace «Ver repo». Justo debajo, el stepper del ciclo de vida (sección 6) y, cuando procede, las acciones de aprobación (sección 7).

Navegación izquierda (pestañas), agrupadas:

  • Navegación: Resumen · Riesgos (N) · Artefactos (N) · Misiones (N).
  • Documentos: Anexo IV · Declaración (DoC) · Registro DORA (solo si DORA aplica).
  • Conformidad: Estándares · Cláusulas.
  • Ajustes del sistema.

Contenido del Resumen. El Veredicto de conformidad (un eje distinto del estado del ciclo), el banner de estado «en qué paso estoy y qué hago ahora», las misiones pendientes, un resumen de riesgos con sus donuts Inherente / Residual y los Top-3 riesgos, el progreso de los Documentos regulatorios (Anexo IV %, DoC %) y la Actividad reciente (los commits de git del directorio .froga/).

Barra lateral derecha: Propietario, Ámbito EU AI Act, Marcos aplicables, Repositorio, Evidencia con el Linaje (✓ 1/1 verificados) y las Acciones (Descargar Anexo IV / bundle.json).

La pestaña de Riesgos lista cada riesgo declarado; su ficha (/risks/[riskId]) muestra el estado (Tratado/…), el grafo de control → riesgo cubierto, el plan de tratamiento (ISO 23894 §6.5), el residual, la procedencia (Origen = froga.yaml) y un enlace «Editar froga.yaml» que abre el repo. Conviene recordar un límite del modelo: no hay un botón de «asignar el riesgo a una persona». Los riesgos vienen del froga.yaml de Marta; el relevo del riesgo a quien lo trata es colaboración entre roles, no una acción del portal.

Detalle en el portal del riesgo risk.unfair-credit-exclusion «Unfair Credit Exclusion of Minorities», marcado Alto y Tratado, con su control cubierto, el plan de tratamiento ISO 23894 §6.5 y el residual MEDIUM.
La ficha de un riesgo (Diego · portal): control cubierto, plan de tratamiento ISO 23894 §6.5, residual, y el origen en froga.yaml con su enlace para editarlo en el repo.

6. El ciclo de vida de 8 estados y su stepper

Sección titulada «6. El ciclo de vida de 8 estados y su stepper»

El corazón del plano cloud es un modelo de 8 estados que cubre todo lo pre-market (antes de poder comercializar), alineado con el EU AI Act (Arts. 9-15 + Anexo IV/DoC) y con ISO 23894. El portal lo dibuja como un stepper en la cabecera (con los nodos completados, el actual y los pendientes); el banner de estado del Resumen lo resume además con una fracción ordinal (por ejemplo, «4/8»: en qué paso de ocho estás).

#Estado (badge)Qué significaQuién lo avanza
1IndeclaradoNo hay froga.yaml; sistema no gobernadoMarta (commit)
2Declaradofroga.yaml declara la finalidad (Anexo IV §1)Marta + las 4 sub-misiones
3AseguradoClasificado + estándares + hueco de datos decididoMotor (por evidencia)
4EvaluadoHay un bundle firmado; la barrera es verde o rojaMarta (froga run + push)
5En tratamientoTras una barrera roja, hay un plan de tratamientoMarta (re-entrena V2)
6AprobadoBarrera verde + trailer Froga-Approved-by posteriorDiego (acto de dirección)
7En revisión periódicaRevisión del riesgo (ISO 23894 §6.6) reabiertaDiego (revisa)
8ComercializableAprobado + todos los entregables descargadosEl proveedor (recoge la doc)

(El stepper visual dibuja los 7 nodos de mercado; «En revisión periódica» es un sub-ciclo de «Aprobado», no un nodo propio.)

stateDiagram-v2
  [*] --> Indeclarado
  Indeclarado --> Declarado: commit froga.yaml
  Declarado --> Asegurado: clasificado + estándares + hueco de datos
  Asegurado --> Evaluado: bundle firmado (froga run)
  Evaluado --> Aprobado: barrera VERDE + Froga-Approved-by (Diego)
  Evaluado --> EnTratamiento: barrera ROJA + plan de tratamiento
  EnTratamiento --> Evaluado: re-entrenar V2 (bundle nuevo)
  Aprobado --> EnRevision: Froga-Reviewed-by (ISO 23894 §6.6)
  EnRevision --> Aprobado: re-aprobación
  Aprobado --> Comercializable: todos los entregables descargados
  Comercializable --> [*]

Lo esencial para Diego: las transiciones son deterministas y derivables del log de git —no hay una base de datos de estado—. Esto es la tesis «git cierra el bucle» vista desde el portal: el plano cloud no «recuerda» el estado, lo reconstruye de los commits del bundle y de los trailers (Froga-decl-by, bundle.json, Froga-treat-by, Froga-Approved-by, Froga-Delivered-by). Por eso lo que Diego ve en el portal y lo que Marta ve en git log son la misma verdad.

2El banner de estado dice «4/8» y el sistema está en «Evaluado». ¿Por qué no salta solo a «Aprobado»?
🛡️ Diego

«Veo el sistema en “Evaluado”, barrera verde, evidencia fresca. ¿Por qué el portal no lo marca “Aprobado” automáticamente? ¿Hace falta que yo haga algo?»

🧑‍💻 Marta

«Hace falta exactamente que tú hagas algo, y eso es intencional. Los estados 1-5 los avanza el motor por evidencia (commits del bundle o del plan de tratamiento). Pero la transición a “Aprobado” requiere un acto de dirección: un trailer Froga-Approved-by posterior al bundle, que nombra a la autoridad de aprobación. El portal no puede inventarse ese acto —sería saltarse el control humano del Art. 14 y del ISO/IEC 42001 §6.1.3—. Cuando pulsas “Aprobar”, la nube escribe ese commit en el repo y entonces el estado deriva a “Aprobado”. El stepper no avanza solo porque la decisión es tuya, no del motor.»


7. Las aprobaciones: el acto de dirección que pone en mercado

Sección titulada «7. Las aprobaciones: el acto de dirección que pone en mercado»

Cuando un sistema está en Evaluado con la barrera en verde, las acciones que el portal ofrece dependen del rol:

  • owner (Diego) ve «Aprobar · poner en mercado» directamente. Es la autoridad de aprobación: no tiene sentido pedirle que «solicite» su propia aprobación.
  • maintainer (Marta) ve «Solicitar aprobación»: pide la aprobación de dirección (escribe un trailer Froga-Approval-Requested-by), pero no aprueba.
  • auditor no ve ninguna acción: es solo lectura.

Si la barrera está en rojo, no hay acción de aprobación: la misión es «Planificar tratamiento» y la pelota vuelve a Marta.

El diálogo. Al pulsar «Aprobar · poner en mercado», el portal abre el diálogo «Aprobar el sistema»: explica que «el sistema quedará aprobado para su puesta en mercado» y que «el acto queda registrado en el repositorio», con un campo de motivo. El motivo es opcional cuando no hay nada que aceptar conscientemente, pero pasa a ser obligatorio cuando el residual agregado supera el apetito o la barrera de conformidad está roja (ver abajo). Diego confirma y el sistema pasa a Aprobado.

El apetito agregado por encima. Si el residual agregado del sistema supera el apetito (overall_residual.evaluation === "exceeds", firmado por el motor), el portal muestra antes del botón un aviso de «Apetito agregado por encima» y convierte la aprobación en un override con motivo obligatorio: no bloquea automáticamente, pero exige que la dirección deje constancia explícita de que lo acepta. Es el mismo patrón que la «barrera ROJA» de conformidad. (Ejemplo: en el escenario loan del SDK el residual agregado supera el apetito porque risk.opacity —pese a su tratamiento de supervisión humana— mantiene observaciones en el residual global y no se acota dentro de su apetito; en NovaCredit el residual agregado queda within y el motivo es opcional. El detalle, en git cierra el bucle.)

La aceptación consciente del riesgo residual. Por separado, si el sistema tiene riesgos cubiertos solo por controles de auditoría (no bloqueantes) o riesgos sin tratar que quedan dentro de su apetito individual, el portal muestra además un aviso de «Aceptación consciente del riesgo residual»: la barrera de conformidad sigue verde a propósito, esos controles no bloquean, y aprobar es una decisión intencionada, no un descuido. (El recorrido del Nivel 1 ilustra esta situación —barrera verde con riesgo de solo auditoría—; el matiz fino —apetito, control audit frente a gate, supervisión humana HOTL— se ve en git cierra el bucle.)

Detalle del sistema en el portal con «Linaje: ✓ 1/1 verificados», el botón «Aprobar · poner en mercado» y el aviso de aceptación consciente del riesgo residual (residual agregado dentro del apetito).
El momento de aprobar (Diego · portal): Linaje 1/1, el botón «Aprobar · poner en mercado» y el aviso de aceptación consciente del riesgo residual; el residual agregado de NovaCredit queda dentro del apetito y el motivo es opcional.

El registro en git. Aprobar no actualiza una fila en una base de datos: escribe un commit en el repositorio con el trailer Froga-Approved-by: (la identidad de Diego), posterior al commit del bundle. Ese commit es la atestación de dirección (ISO/IEC 42001 §6.1.3), fechada y atribuible. El portal después deriva el estado «Aprobado» de ese trailer —no al revés—. Las re-aprobaciones (Froga-Reviewed-by + un nuevo Froga-Approved-by) y la entrega de documentos (Froga-Delivered-by) siguen el mismo patrón.

3Apruebo desde el portal. ¿Dónde queda la prueba, y qué ve Marta en el repo?
🛡️ Diego

«El diálogo dice que “el acto queda registrado en el repositorio”. Como soy quien responde ante el regulador, necesito saber exactamente qué queda y dónde —no me vale “el portal lo recuerda”.»

🧑‍💻 Marta

«Lo que queda es un commit firmable en mi repo, con el trailer Froga-Approved-by: <tu identidad>, fechado, justo después del commit del bundle verde. Yo lo veo en git log igual que cualquier otro commit —de hecho aparece en la pestaña “Actividad reciente” de tu propio detalle del sistema—. No hay estado oculto: el portal reconstruye “Aprobado” leyendo ese trailer. Ante un auditor, la evidencia es la cadena entera: el bundle firmado con ECDSA-P256, su Linaje 1/1, y tu commit de aprobación encima. froga reconstruct la reproduce desde git sin LLM. Tu aprobación es tan auditable como mi tratamiento: las dos son commits.»


8. Roles y ajustes: la separación de poderes

Sección titulada «8. Roles y ajustes: la separación de poderes»

El portal materializa tres roles, y la separación entre ellos es un control de conformidad:

RolPuedeNo puede
owner (Diego)Gestionar la org y los miembros, crear/editar sistemas y conexiones, aprobar / rechazar / retirar
maintainer (Marta)Crear/editar sistemas y conexiones, solicitar aprobaciónAprobar; gestionar la org
auditorLeer todo (auditoría)Cualquier escritura o aprobación

Que solo el owner apruebe no es una restricción de comodidad: es el acto de dirección que acepta el riesgo residual (ISO/IEC 42001 §6.1.3). Que el maintainer solo pueda solicitar mantiene la frontera entre quien aporta la evidencia (Marta) y quien decide liberar (Diego). Y el auditor de solo lectura es exactamente lo que un revisor externo necesita: ver sin poder alterar.

Rechazar es la otra cara de aprobar: Diego devuelve la evidencia vigente a Marta con un motivo obligatorio, que queda registrado en el repositorio como un commit con el trailer Froga-Rejected-by. El sistema queda «rechazado» hasta que Marta empuje evidencia nueva (que reabre el ciclo por sí sola).

Los Ajustes de la organización tienen cuatro secciones: Perfil (datos de la org), Miembros (invitar, cambiar rol, reenviar invitación), Conexiones (host + token + la clave pública de firma del firmante) y Plan (la matriz de capacidades, la comparativa de los cuatro planes con las normas que cada uno licencia y el CTA de upgrade por venta asistida — ver Planes y normas). Gestionar miembros y la org es poder de owner; las conexiones las puede tocar también el maintainer.

4Quiero que un revisor externo audite sin riesgo de que cambie nada. ¿Qué rol le doy?
🛡️ Diego

«Un organismo notificado quiere revisar el sistema. Tengo que darle acceso a la evidencia —Anexo IV, riesgos, linaje— pero no puede aprobar, ni editar, ni tocar las conexiones. ¿Con qué rol lo invito desde Ajustes → Miembros?»

🧑‍💻 Marta

«auditor: solo lectura sobre todos los recursos. Ve los sistemas, los riesgos, el Anexo IV y el Linaje, pero no le aparece ningún botón de acción —ni “Aprobar”, ni “Crear sistema”, ni editar conexiones—. Es el mismo rol con el que entra el invitado del demo público (demo.venturalitica.ai → “Explorar el demo”): puede recorrer 7 sistemas firmados sin poder alterar ninguno. Para el revisor externo es exactamente la postura de mínimo privilegio que pide la auditoría: que pueda comprobar tu evidencia sin formar parte de la cadena de decisión.»


¿De dónde salen las misiones del portal, y por qué las cuatro sub-misiones del estado «Declarado» van en un orden fijo?

Las misiones se derivan del estado del sistema, no de una lista escrita a mano: cada estado del ciclo de vida tiene su misión accionable. Las cuatro sub-misiones de «Declarado» —declarar estándares, clasificar (Anexo III), identificar riesgos, justificar el hueco de datos— van en ese orden porque hay una dependencia normativa: no se puede clasificar sin haber declarado los marcos aplicables, ni identificar riesgos significativos sin saber la categoría de alto riesgo, ni acotar las variables protegidas sin los riesgos. El portal muestra el siguiente sub-paso accionable y deja los posteriores bloqueados con tooltip.

Tienes un repo que ya tiene evidencia `.froga/` firmada. ¿Usas «Crear sistema» o «Explorar un sistema existente»? ¿Por qué?

«Explorar un sistema existente». Esa vía ata un repo que ya expone artefactos .froga/: la nube lo lee para validar el acceso y lo registra sin escribir nada. «Crear sistema» es para empezar de cero: la nube crea un repo nuevo y vacío y siembra un froga.yaml inicial. Pulsar «Crear» cuando la evidencia ya existe en otro repo no la ataría —crearía un sistema vacío aparte—. Cuando Marta ya ha empujado el .froga/, «Explorar» es la vía que ata ese repo.

El sistema está en «Evaluado» con barrera verde y evidencia fresca. ¿Por qué el portal no lo marca «Aprobado» automáticamente?

Porque la transición a «Aprobado» requiere un acto de dirección humano, no una derivación del motor. Los estados 1-5 los avanza el motor por evidencia (commits del bundle o del plan de tratamiento), pero «Aprobado» necesita un trailer Froga-Approved-by posterior al bundle, que nombra a la autoridad de aprobación (owner). El portal no puede inventarse ese acto sin saltarse el control humano (ISO/IEC 42001 §6.1.3). Cuando Diego pulsa «Aprobar · poner en mercado», la nube escribe ese commit y entonces el estado deriva a «Aprobado».

Diego aprueba desde el portal. ¿Dónde queda la prueba de la aprobación?

En git, como un commit. Aprobar no actualiza una fila en una base de datos: escribe un commit en el repositorio con el trailer Froga-Approved-by: <identidad de Diego>, fechado y posterior al commit del bundle verde. Ese commit es la atestación de dirección (ISO/IEC 42001 §6.1.3); el portal después deriva el estado «Aprobado» leyendo ese trailer. Marta lo ve en git log y en la pestaña «Actividad reciente». No hay estado oculto: el portal y el repo cuentan la misma verdad, y froga reconstruct la reproduce desde git.

¿Qué rol das a un revisor externo que debe auditar sin poder cambiar nada, y por qué la separación de roles es conformidad?

El rol auditor: solo lectura sobre todos los recursos, sin ningún botón de acción (ni aprobar, ni crear, ni editar conexiones). Es el mismo rol del invitado del demo público. La separación de roles es conformidad —no burocracia— porque mantiene la frontera entre quien aporta la evidencia (maintainer, Marta), quien decide liberar aceptando el riesgo residual (owner, Diego, ISO/IEC 42001 §6.1.3) y quien solo comprueba (auditor). Solo el owner aprueba; el maintainer solo puede solicitar.