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.mde í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.mdcon 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.