Skip to content

OBJ-VAULT-001: Sistema de secrets/vault del harness (humanos + agentes Hermes)

Objective ID: OBJ-VAULT-001 Project doc (PROJ-VAULT-001): the DocOps project pill for this objective is the front matter of this very document (id: PROJ-VAULT-001, objective_id: OBJ-VAULT-001). Status: Active (S0 materialización en curso; ADR-0009 ACCEPTED 2026-08-31 — despliegue in-cluster por decisión del operador) Drafted by: Architect (THINK role) — provenance: THINK handoff (comentarios 591-593 de la card t_9634d1c7) Owned by: wetopi-lead (OWN role)

Outcome

Humanos autorizados y perfiles Hermes consumen secretos desde un Infisical self-hosted IN-CLUSTER (namespace vault de wetopi3; la decisión del operador de 2026-08-31 sustituye la VM dedicada del diseño original), mediante identidades individuales, contrato ai-hub estable, mínimo privilegio, rotación verificable, auditoría sin valores y recuperación ensayada; las copias plaintext y credenciales expuestas/broad-scope del harness dejan de ser estado operativo.

Context

El estado actual duplica secretos en ocho ficheros de ops01:~/secrets/ y .env, conserva credenciales de alcance excesivo o expuestas, depende de un argocd admin estático y no atribuye lecturas. ADR-0009 (ACEPTADO 2026-08-31) fija la boundary y controles, ahora in-cluster; el Operador (decisión 2026-08-31) pidió dejar Infisical totalmente operativo internamente por el cluster service endpoint con el service provider instalado en Kubernetes, y esa materialización (vault + datastores + Operator v0.11.8 + edge UI) avanza en infra PR #27 (feat/vault-infra).

Decided architecture

Referencia normativa a ADR-0009 ACEPTADO y docs/architecture/vault-system/: despliegue IN-CLUSTER (ns vault) — decisión del operador 2026-08-31 que sustituye la VM dedicada; Infisical como runtime source of truth; SOPS+age sólo bootstrap/recovery; una machine identity por perfil, default deny; ai-hub como interfaz exclusiva; credencial bootstrap única local y access token efímero; edge TLS production con auth nativa y UI solamente (Universal Auth private-only con DENY de API en la ruta pública); Operator v0.11.8 CRDs v1beta1 AHORA; backup/export cifrado off-host; audit append-only; migración por replacement→prueba→revocación. El trade-off de fallo correlacionado con wetopi3 queda aceptado y compensado por el contrato de recovery ensayado (AC8).

Estado

Leyenda permitida sólo en esta tabla/listas de etapas: ✅ resuelto · 🔄 ongoing/running · ⏸️ gated/esperando · ⬜ pendiente · ⛔ bloqueado.

Etapa Estado Fecha Gate Evidencia esperada
S0 Diseño ADR + Objective + pack 🔄 2026-08-31 approver + operador PR docs, validator, catalog estable, index shape, CI — ADR-0009 ACEPTADO in-cluster (decisión operador 2026-08-31); materialización infra en PR #27 bajo revisión
S1 Validación §10.6 ⏸️ 2026-08-31 approver + operador informe GO/NO-GO citado (hecho); licencia/features/API/deployment (hecho); firma del gate con versión/edición/componentes fijados y coste aceptado — PENDIENTE (ajustada a in-cluster: sin VM, la firma fija además la topología ns vault y la ruta UI-only)
S2 Inventario de perfiles y policy 🔄 ongoing 2026-08-31 approver + operador ⏸️ gated: la fila requiere matriz exhaustiva y tests deny-by-default (incluyendo las identidades del Operator v0.11.8) que aún no se han ejecutado — no está completa hasta que esa evidencia exista (approver t_0a825203 RC1)
S3 Edge/TLS + datastores hardened (in-cluster, ya sin VM) ⬜ — operador antes de provisionar; approver antes de promover evidence bundle sin secretos — sustituye "VM/edge/datastore": los datastores son los PVCs de ns vault (PR #27)
S4 Infisical piloto ⬜ — approver health/TLS/version/negative exposure tests
S5 Adaptador ai-hub vault.* ⬜ — approver contract suite de seis operaciones
S6 Identities y bootstrap ⬜ — operador una identity por perfil, positive/negative matrix
S7 Audit, backup y recovery drill ⬜ — approver + operador eventos redacted y restore aislado exitoso
S8 Migración canary ⬜ — operador para rotación/revocación consumidor sano y credencial vieja rechazada
S9 Migración total y retirada plaintext ⬜ — approver + operador reconciliación cero deuda y rollback cerrado
S10 Operación y cierre ⬜ — approver + operador SLO/runbooks, dashboard final, objetivo K8s separado

Nota de estado: S1 queda ⏸️ (gated): la discovery §10.6 (t_7459a827, 2026-08-31, informe citado en ADR-0009) produjo el veredicto GO con tres condicionales y sus decisiones (audit EE = licencia obligatoria; PIT y Trusted IPs = control compensatorio), PERO el gate S1 no está cerrado: exige firma approver+operador con versión/edición/componentes fijados y aceptación explícita de licencia/coste (licencia base + audit EE), y esa firma no ha ocurrido. La aceptación de licencia NO se traslada a S3: es condición del propio S1. Cada PR de progreso DEBE actualizar estado, fecha y enlace a evidencia de cada etapa afectada. Nunca se pega evidencia que contenga valores, tokens o auth state.

Nota de ajuste in-cluster (2026-08-31): la decisión del operador (chat 2026-08-31, registrada como transición accepted in-PR de ADR-0009) sustituyó la etapa S3 "VM dedicada" por datastores y vault in-cluster (ns vault), trajo el Operator/CRDs v1beta1 a esta fase (decisión 8 de ADR-0009) y cerró el OPEN de exposición de Universal Auth como private-network-only. Este dashboard refleja el ajuste honestamente: el cambio viene del operador, no rebaja ninguna AC.

Acceptance criteria y verification contract

AC1 — DocOps y trazabilidad

ADR-0009 está accepted (decisión del operador 2026-08-31: despliegue in-cluster + Operator/CRDs v1beta1 en este objetivo, transición aplicada en el mismo PR que la presenta); Objective y architecture pack están enlazados desde home/index y catalogados con IDs únicos. docs/decisions/ no se usa como legacy exemption para el ADR nuevo.

Verificación mínima desde root del checkout Docs:

AIHUB=/opt/data/kanban/workspaces/v31-docops-baseline-20260830/ai-hub
python3 "$AIHUB/tools/docops/wetopi-docops-validate" . --check-only \
  --legacy-exempt docs/design/,docs/platform/
# esperado: exit 0; ADR-0009/PROJ-VAULT-001/ARCH-* entre material docs

Además: ejecutar el regen-catalog canónico del repo dos veces; la segunda debe dejar git diff --exit-code en 0. Ejecutar el gate canónico verify-index-shape; exit 0 y diff byte-exacto. Ejecutar CI del PR; todos los checks requeridos verdes.

AC2 — Validación previa de producto

Existe evidencia oficial y versionada para edición/licencia self-hosted, machine identities/Universal Auth, permisos por scope, audit, CRUD API, componentes/sizing soportados, backup/export e integración K8s futura. Cada punto es GO, GO condicionado aceptado por operador o NO-GO. Ninguna producción comienza con punto requerido no verificado.

Verificación: checklist §10.6 enlazado, versión de producto fijada y gate S1 firmado por approver+operador (con edición/licencia/coste aceptados).

AC3 — Boundary independiente y acceso humano

El servicio piloto corre IN-CLUSTER en el namespace vault de wetopi3 (ADR-0009 aceptado 2026-08-31, decisión del operador; la VM dedicada quedó descartada en la transición proposed → accepted); presenta certificado válido de producción y no expone datastore/puertos administrativos a Internet. Universal Auth NO es alcanzable por el hostname público — la ruta pública sirve sólo la UI humana con enforcement verificable (DENY explícito de los endpoints de API, demostrado con login público rechazado / login interno autorizado antes del primer bootstrap). Auth nativa es obligatoria en la UI; Basic Auth UI sólo si una prueba demuestra que no interfiere con API/machine identities. Acceso admin humano usa controles fuertes disponibles en la edición aprobada.

Verificación contractual: curl --fail --silent --show-error https://vault.wetopi.net/api/status (o health endpoint oficial confirmado para la versión) desde origen autorizado; prueba desde origen no autorizado falla; inspección de certificado/DNS/firewall y workloads Infisical vivos en ns vault (prueba negativa de exposure: https://vault.wetopi.net/api/v1/auth/universal-auth/login rechazada y http://vault.vault.svc.cluster.local/api/... autorizado — sin imprimir cuerpos que puedan contener datos sensibles).

AC4 — Identidad individual y mínimo privilegio

Cada perfil activo del registro canónico tiene exactamente cero o una machine identity exclusiva según necesidad; nunca comparte bootstrap secret. Los perfiles nuevos nacen sin permisos. La matriz enumera por perfil operaciones y paths. Un perfil autorizado pasa su test positivo y falla en otro namespace y en una operación no concedida.

Verificación contractual: suite identity-policy genera tabla actor×operación×namespace usando fixtures sintéticos; esperado 100% conforme y ninguna wildcard no justificada. La suite no emite secretos.

AC5 — Contrato ai-hub completo

El adaptador implementa get/put/update/delete/list/exists con las semánticas, errores, precondiciones, paginación, idempotencia, timeouts y redaction del pack. Ningún perfil consume endpoint/SDK Infisical directamente ni puede seleccionar identity.

Verificación contractual: con fixture sintético, contract tests demuestran create-only, conflict, exact get, metadata-only list, scoped exists, conditional update/delete, deny fuera de scope, upstream timeout y ausencia de valor en stdout/stderr/logs. Búsqueda estática fuera del adaptador no encuentra imports/endpoints Infisical.

AC6 — Bootstrap sin proliferación

Por perfil, sólo persiste localmente la credencial bootstrap en path aprobado, owner/mode restrictivos y fuera de Git/.env; tokens derivados viven sólo en memoria. Modo inseguro, ausencia o identidad discordante hacen fail closed.

Verificación contractual: checker metadata-only de owner/mode/path y pruebas negativas; secret scanner sobre Git, logs y .env no encuentra fixtures ni tokens. La salida contiene nombres de controles, no valores.

AC7 — Auditoría útil y no sensible

Lecturas, escrituras, denegaciones, cambios de policy/identity, exports, delete y break-glass producen eventos atribuibles con request-id; no incluyen valores/tokens. Existe copia append-only off-host y alerta si deja de ingerir.

Verificación contractual: ejecutar una lectura permitida y otra denegada con fixture; localizar ambos request-id y comparar campos esperados; escáner canary confirma que el valor sintético no aparece. Simular caída del sink y comprobar la política fail-closed para operaciones destructivas/admin.

AC8 — Recovery demostrado

Backup consistente y export lógico SOPS+age se crean sin plaintext persistente, se almacenan off-host y permiten restaurar versión compatible en entorno aislado. El drill incluye reemisión de identities y limpieza break-glass.

Verificación contractual: restore drill desde cero con fixture sintético, comprobación funcional vía vault.*, evidencia de archivo cifrado (sops puede descifrar sólo con recipient autorizado), búsqueda de plaintext canary en staging/backup/logs = cero. No se usa un secreto real como canary.

AC9 — Migración elimina deuda

El inventario metadata-only cubre los ocho ficheros actuales y todos los K8s Secrets visibles sin volcar valores. Las dos credenciales expuestas, GHCR broad-scope y argocd admin estático se reemplazan/rotan; consumidor nuevo funciona y credencial anterior es rechazada. Se eliminan copias plaintext/ .env sólo tras rollback seguro. Cada secreto queda con owner y scope.

Verificación contractual: reconciliación devuelve conteos, no valores: unowned=0, exposed-active=0, broad-unjustified=0, shared-unjustified=0, legacy-plaintext=0 (excepto bootstrap permitido). Evidencia de prueba negativa para cada credencial revocada. Los K8s Secrets se sincronizan vía Infisical Operator v1beta1 (AC11) conforme avanza la fase migrating→operational; la migración de este AC sustituye las credenciales heredadas y el Operator materializa las nuevas.

AC10 — Operación y dashboard

Existen runbooks de alta/baja de identity, rotación, incidente, audit review, backup/restore, upgrade/rollback y outage. El Objective refleja siempre cada S0..S10 con emoji, fecha y evidencia. Alertas cubren salud, expiración, fallo de rotación, audit sink y backup/restore.

Verificación contractual: tabletop sin secretos recorre cada runbook; parser de docs confirma una fila única por etapa, estado válido y fecha/evidencia para etapas no pendientes.

AC11 — Límite K8s preservado

AJUSTADA por la decisión del operador (2026-08-31, ADR-0009 aceptado): la materialización K8s (vault in-cluster + Operator/CRDs v1beta1) YA NO está prohibida en este objetivo — avanza como trabajo de infraestructura revisado (infra PR #27) y este Objective la referencía como evidencia, sin contener ella misma manifests. Lo que sigue vedado AQUÍ es el despliegue directo desde este Objective: ningún apply/merge desde el lane docs; la materialización se revisa y aprueba en su propio PR de infra.

Verificación contractual: diff del objetivo no contiene manifests/Helm/Argo de despliegue K8s; el trabajo de plataforma vive en wetopi-platform/infrastructure (PR #27) con su propio review/approval gate.

Etapas ejecutables y gates

  • 🔄 S0: materializar ADR, Objective, pack, diagramas e índices. Gate: approver y operador; sólo docs/PR, no merge automático. Acepta AC1 y CI verde.
  • ⏸️ S1: incorporar discovery §10.6 (veredicto GO con tres condicionales, t_7459a827), fijar versión/edición/componentes y resolver OPENs. Gate: approver+operador (firma pendiente — la etapa NO está aceptada hasta que approver+operador firmen con edición/licencia/coste aceptados). Stop ante NO-GO o coste/licencia no aceptados.
  • ⬜ S2: enumerar perfiles desde registro canónico, asignar policy mínima y owners. Gate: approver+operador. Acepta AC4 en diseño y matriz exhaustiva.
  • ⬜ S3: preparar red, DNS, edge, TLS, datastores in-cluster (PVCs ns vault — ya sin VM, decisión del operador 2026-08-31), hardening y rollback. Gate operador antes de mutar infraestructura; approver antes de promoción. Acepta boundary de AC3.
  • ⬜ S4: desplegar piloto fijado por versión/digest con secretos sintéticos. Gate approver. Acepta salud y controles base; no migra credenciales.
  • ⬜ S5: implementar adaptador ai-hub y contract suite. Gate approver. Acepta AC5, incluidos tests negativos/redaction.
  • ⬜ S6: crear identities, entregar bootstrap por canal separado y ejecutar matriz. Gate operador. Acepta AC4+AC6; ninguna credencial en PR/Kanban.
  • ⬜ S7: configurar audit/alerts/backup y completar restore drill aislado. Gate approver+operador. Acepta AC7+AC8 antes de cualquier secreto real.
  • ⬜ S8: migrar un canary reversible no expuesto; después rotar primero las credenciales expuestas/broad-scope con aprobación explícita por revocación. Gate operador. Acepta prueba funcional + rechazo del antiguo.
  • ⬜ S9: migrar resto, retirar copias y reconciliar. Gate approver+operador. Acepta AC9; no toca materialización K8s.
  • ⬜ S10: aprobar SLO/runbooks, cerrar dashboard y proponer objetivo K8s independiente. Gate approver+operador. Acepta AC10+AC11.

Promotion matrix

De A Condición necesaria Autoridad
accepted approved-design S1 gate firmado (GO/condiciones aceptadas por approver+operador), DocOps+CI verdes approver + operador
approved-design pilot S2 policy aprobada, edge/datastore in-cluster plan y rollback aprobados operador; approver verifica
pilot recovery-ready AC3–AC8 con fixtures sintéticos; restore drill exitoso approver + operador
recovery-ready migrating canary reversible sano y plan de cada revocación operador
migrating operational AC9 reconciliado y monitorización/runbooks activos approver + operador
operational closed evidencia final, deuda enlazada resuelta, sync Operator v1beta1 verificado (AC11) approver + operador

Ningún estado se promueve sólo porque una card esté done; manda la evidencia L2 enlazada y el gate indicado.

Constraints

  • Cero secretos, tokens, cuerpos, auth state o valores reales en Git, PR, Kanban, comandos, capturas o evidencias.
  • Versiones/digests fijados; default deny; una identidad por perfil; sin supercredencial compartida.
  • Infisical runtime, Git L2, registro Hermes de perfiles y SOPS+age recovery mantienen autoridades separadas según ADR-0003.
  • No merge ni despliegue desde THINK. OWN compila tareas; JUDGE revisa independientemente.
  • Todo cambio destructivo tiene rollback y approval previo; delete deshabilitado por defecto.
  • Emojis sólo en dashboard/lista de etapas.

Stop conditions

Detener y marcar bloqueado si: la validación §10.6 da NO-GO a un requisito obligatorio; licencia/coste no está aprobado; faltan audit/RBAC/machine identities/export soportados; no puede restaurarse backup; TLS/DNS/firewall no cumplen; se detecta un secreto en evidencia; se requiere wildcard/ supercredencial para funcionar; un perfil puede suplantar otro; contract/ redaction test falla; la migración no tiene rollback/owner; credencial expuesta no puede revocarse; audit sink cae antes de una operación destructiva; o cualquier paso ejecuta apply/merge K8s fuera del PR de infraestructura revisado (la materialización vive en infra PR #27, no en este lane).

Review boundaries

  • Architect/THINK: WHAT/WHY, ADR, límites, ACs y verificación; no Git ni ejecución.
  • Lead/OWN: adapta al template, crea branch/PR, compila tareas y mantiene dashboard; no rebaja ACs.
  • Approver/JUDGE: revisa independiente ADR, evidencia y promociones; no acepta por estado Kanban.
  • Operador: decide licencia/coste, Basic Auth UI, infraestructura y toda rotación/revocación/destrucción.
  • Discovery: aporta hechos §10.6; un dato no verificado permanece OPEN.

Out of scope

External Secrets, HA multi-instancia, reemplazar Infisical por otro producto sin ADR, rediseñar proveedores de identidad corporativa, almacenar secretos de clientes/workloads, y automatizar rotaciones de proveedores no inventariados. (El despliegue K8s fue out-of-scope en el diseño proposed; la decisión del operador del 2026-08-31 lo trajo a este objetivo vía infra PR #27 y AC11 ajustada.)

Cambios documentales materiales

  • Nuevo docs/decisions/ADR-0009-secrets-vault-harness.md e índice ADR byte-exacto.
  • Nuevo docs/objectives/active/OBJ-VAULT-001.md (este documento).
  • Nuevo pack bajo docs/architecture/vault-system/ con overview/identity-contract/operations-recovery-migration (puede mantenerse uno o varios ficheros según convención).
  • docs/index.md con enlaces al ADR y Objective.
  • Actualizar sólo menciones normativas actuales que contradigan Infisical runtime/SOPS recovery; no tocar legacy-exempt histórico salvo necesidad material.