Construir un caso de aseguramiento de seguridad: afirmaciones respaldadas solo por comprobaciones realmente ejecutadas, registradas en un diario encadenado y verificadas en un commit.
assurance es el comando detrás del caso de aseguramiento de seguridad del pack Shield. Un caso enumera afirmaciones sobre tu sistema (por ejemplo «ninguna dependencia de producción tiene un aviso conocido de gravedad alta»), da un argumento para cada una y la respalda con evidencias. La única evidencia que BMAD+ acepta es una comprobación que ejecutó él mismo: un comando, su código de salida, la huella de su salida y las de los archivos que escribió, añadidos a un diario encadenado por huellas. Una declaración, un documento o un enlace se rechaza. Se usa cuando alguien, un auditor, un cliente o tú mismo más adelante, pide demostrar que unos controles se cumplen en un commit concreto y «creemos que sí» no basta.
Advertencia· Lo que un veredicto no es
Un caso «supported» demuestra que las comprobaciones nombradas pasaron en un commit. No certifica el sistema ni es una opinión de auditoría; un auditor cualificado decide cuánto valen las evidencias. Además, assurance run ejecuta los comandos escritos en el caso con la misma confianza que tus propios scripts: lee un caso ajeno antes de ejecutarlo.
Copia la plantilla de Shield al archivo de caso que indiques. El archivo debe llamarse <id>.yaml; el id sale del nombre. Nunca sobrescribe un archivo existente.
run
Ejecuta las comprobaciones del caso (todas, o las indicadas con --check) y añade un registro por comprobación al diario.
verify
Juzga cada comprobación por su última ejecución y cada afirmación por sus evidencias, y muestra el veredicto. No ejecuta nada.
Opciones de assurance
Opción
Argumento
Por defecto
Qué hace
-d, --directory
<path>
carpeta actual
Carpeta del proyecto.
--dir
<path>
_bmad-output/assurance
Carpeta de evidencias dentro del proyecto; el diario está en <dir>/<case id>/runs.jsonl. Ruta relativa escrita con /.
--check
<id>
todas las comprobaciones
Solo run: ejecutar solo esta comprobación. Repite la opción para varias.
--ledger-head
<sha256>
ninguno
Solo verify: fallar si el diario ya no contiene el registro con esta huella (64 caracteres hexadecimales en minúscula).
--emit-check
<file>
ninguno
Solo verify: escribir además el veredicto como resultado de comprobación JSON para CI. El nombre debe acabar en .json y no puede ser el caso ni su diario.
--json
-
desactivada
Imprimir el resultado en JSON (schemaVersion: 1) en lugar de texto. Los errores pasan a ser { "status": "error", "message": ... }.
Por convención un caso vive en _bmad/assurance/<id>.yaml, pero sirve cualquier ruta relativa al proyecto sin .. ni enlaces simbólicos. init escribe la plantilla de Shield, que es un ejemplo completo y funcional (cuatro comprobaciones, una afirmación principal y cuatro subafirmaciones). Sustituye cada ejemplo por el tuyo, haz commit del archivo y luego ejecútalo. Esta es la forma; las claves desconocidas se rechazan.
Forma de un caso (abreviada de la plantilla)
schema: bmad-plus/assurance-case/1
id: release-security
title: Release security case
scope: >-
The service at the commit being released.
freshness:
maxAgeDays: 30
sameCommit: true
checks:
- id: unit-tests
run: [npm, test]
timeoutSeconds: 900
- id: secret-scan
run: [gitleaks, detect, --no-banner, --redact, --report-path, reports/gitleaks.json]
artifacts: [reports/gitleaks.json]
claims:
- id: C1
claim: The release ships no committed credential and no failing control test.
argument: >-
Holds when both sub-claims hold.
- id: C1.1
parent: C1
claim: No credential is committed in the repository history.
argument: >-
The scanner reads every reachable commit and exits non-zero on a finding.
controls: [ISO27001:A.5.17, SOC2:CC6.1]
evidence:
- check: secret-scan
shows: gitleaks finds no secret and writes its report.
- id: C1.2
parent: C1
claim: The behaviour the controls rely on is covered by passing tests.
argument: >-
The suite exercises access checks and input validation.
controls: [ISO27001:A.8.29]
evidence:
- check: unit-tests
shows: The test suite passes at this commit.
Claves de un caso
Clave
Regla
schema
Debe ser bmad-plus/assurance-case/1.
id
Minúsculas, dígitos, puntos y guiones, hasta 64 caracteres.
title, scope
Texto libre, de 1 a 4000 caracteres cada uno.
freshness.maxAgeDays
Número entero de días de 1 a 366. Por defecto 30. Una ejecución más antigua es stale.
freshness.sameCommit
true (por defecto) liga las evidencias al commit activo y a un árbol de trabajo limpio. Pon false solo en un proyecto fuera de git.
checks[].id
Id único de la comprobación.
checks[].run
El comando como lista de argumentos separados. No interviene ningún shell. En Windows, programas como npm son archivos .cmd y necesitan [cmd, /c, npm, ...].
checks[].cwd
Carpeta relativa al proyecto donde ejecutar. Por defecto ..
checks[].env
Nombres de variables de entorno adicionales que la comprobación puede ver. Por defecto solo hereda PATH, HOME, las carpetas temporales y algunas variables de sistema de Windows. BMAD_PLUS_ASSURANCE_KEY nunca puede figurar.
checks[].timeoutSeconds
Número entero de 1 a 21600. Por defecto 600.
checks[].expect.exitCode
Código de salida que cuenta como éxito, de 0 a 255. Por defecto 0.
checks[].artifacts
Archivos relativos al proyecto que el comando debe escribir; cada uno se resume con la ejecución. Un archivo que la ejecución dejó igual no cuenta como producido.
claims[].id, claim, argument
Obligatorios. El argumento dice por qué una comprobación superada demuestra la afirmación.
claims[].parent
Una afirmación declarada antes. Una afirmación sin evidencia debe tener al menos una subafirmación; si no, está «solo afirmada» y el caso no carga.
claims[].controls
Lista opcional de referencias FRAMEWORK:ID. Marcos aceptados: ISO27001, SOC2, GDPR, EU-AI-Act, NIS2, NIST-800-53. Un control mal escrito o inventado se rechaza.
claims[].evidence
Lista de { check, shows }. check debe nombrar una comprobación declarada.
init escribe un solo archivo: el caso, en la ruta que indiques (se crean las carpetas padre).
run lee el caso, ejecuta cada comprobación elegida como proceso hijo sin shell y añade una línea por comprobación a <dir>/<case id>/runs.jsonl. Mientras trabaja mantiene runs.jsonl.lock. Consulta git (rev-parse, status, ls-files) para anotar el commit y si el árbol estaba limpio.
verify lee el caso, el diario, git y los artefactos declarados. No escribe nada salvo el archivo opcional de --emit-check.
No abre por sí mismo ninguna conexión de red. Los comandos que declares hacen lo que hagan; por eso el inventario de tratamiento de datos lista assurance-checks como un flujo que solo existe cuando invocas run.
Rechazado en todas partes: rutas fuera del proyecto y cualquier ruta que pase por un enlace simbólico.
Cada registro de runs.jsonl es una línea JSON: el id de la comprobación, un número de secuencia, la huella del comando, el commit (revision) y dirty (si había cambios rastreados o archivos sin rastrear no ignorados), las horas de inicio y fin, el código de salida, si superó el tiempo, el tamaño y la huella de la salida con un extracto censurado de sus últimos 2048 bytes, la huella de cada artefacto declarado (o null si la ejecución no lo escribió), la huella del registro anterior y su propio sha256. Editar, reordenar o quitar un registro antes del último rompe la cadena, y verify juzga entonces todo el caso como no respaldado.
La cadena sola solo delata ediciones descuidadas: quien pueda escribir el archivo puede añadir un registro que se verifica o cortar los últimos. Dos elementos guardados fuera del diario cierran esa brecha.
La clave. Define BMAD_PLUS_ASSURANCE_KEY (al menos 32 caracteres) desde un secreto de CI. run añade entonces un HMAC-SHA256 a cada registro y verify rechaza cualquier registro que la clave no autentique. La clave nunca se entrega a una comprobación. Usa la misma clave en run y verify: un diario escrito sin clave se rechaza en cuanto la clave está definida.
La cabeza. run imprime la huella de su último registro. Guárdala donde quienes escriben el diario no puedan cambiarla (el log del job de CI, el archivo de auditoría) y pásala a verify --ledger-head. Un diario que ya no contiene ese registro se rechaza, así que las ejecuciones retiradas se notan.
Estado de una comprobación (según su última ejecución)
Estado
Significado
passed
Se ejecutó, hizo lo que espera la comprobación y es reciente.
failed
No arrancó, superó el tiempo, salió con otro código distinto del esperado, o un artefacto no lo produjo la ejecución.
stale
Pasó, pero en otro commit, con cambios sin confirmar o archivos sin rastrear, con un comando que cambió después, con un artefacto que cambió después, más antiguo que maxAgeDays o con una hora de fin en el futuro.
missing
Nunca se ejecutó.
Una afirmación es supported solo cuando todas sus comprobaciones de evidencia son passed y todas sus subafirmaciones son supported; si no, es unsupported, con los motivos. El caso es supported solo cuando lo es cada afirmación, el diario está intacto, cualquier --ledger-head sigue en él y, con sameCommit: true, hay un commit y el árbol de trabajo no tiene cambios sin confirmar ni archivos sin rastrear (la carpeta del diario y los artefactos del caso no cuentan). El veredicto también lista controls.supported y controls.unsupported: los controles etiquetados en afirmaciones que tienen, o no, evidencia ejecutada.
Al menos una comprobación elegida falló (no arrancó, superó el tiempo, código de salida incorrecto o artefacto declarado no producido). Los registros se escriben igualmente.
verify
0
El caso es supported.
verify
1
El caso es unsupported.
cualquiera
3
El comando no pudo hacer su trabajo: acción desconocida, caso ausente o inválido, clave o cabeza incorrecta, diario no intacto en run, bloqueo retenido, comprobación no declarada, --emit-check rechazado. Se imprime assurance: <message> en el flujo de error.
Las tres transcripciones siguientes se componen a partir de las plantillas de mensajes del código fuente, con valores ilustrativos (rutas, tiempos y huellas son inventados). Por eso están marcadas como simuladas.
Iniciar un caso y ejecutarloSimulado
$ npx bmad-plus assurance init _bmad/assurance/release-security.yaml_bmad/assurance/release-security.yaml: case release-security started from the Shield template.Replace every example claim and check with those of the project, commit it, then run it.$ npx bmad-plus assurance run _bmad/assurance/release-security.yaml/home/me/app/_bmad-output/assurance/release-security/runs.jsonl passed unit-tests exit 0 in 41.3 s passed dependency-audit exit 0 in 6.8 s passed secret-scan exit 0 in 3.1 s passed review-gate exit 0 in 1.2 sRecorded 4 run(s); ledger head 3f9c1b7e5a2d4c6e8b0a1d3f5c7e9b2a4d6f8a0c1e3b5d7f9a2c4e6b8d0f1a3c.Keep the head outside the ledger and verify with bmad-plus assurance verify _bmad/assurance/release-security.yaml --ledger-head 3f9c1b7e5a2d4c6e8b0a1d3f5c7e9b2a4d6f8a0c1e3b5d7f9a2c4e6b8d0f1a3c.
npx bmad-plus assurance init _bmad/assurance/release-security.yaml
npx bmad-plus assurance run _bmad/assurance/release-security.yaml
Transcripción ilustrativa, no capturada de una ejecución real. Fuente: tools/cli/commands/assurance.js (plantillas de mensajes de initAction y runAction)
Transcripción ilustrativa, no capturada de una ejecución real. Fuente: tools/cli/commands/assurance.js (plantilla de mensaje de verifyAction)
Verificar tras un cambio de códigoSimulado
$ npx bmad-plus assurance verify _bmad/assurance/release-security.yamlrelease-security: unsupported — 3/5 claim(s) supported, 4 recorded run(s) stale unit-tests: it ran at 1a2b3c4d5e6f, not at 9f8e7d6c5b4a unsupported claim C1: sub-claim C1.4 is unsupported unsupported claim C1.4: evidence unit-tests is stale controls with executed evidence: ISO27001:A.8.8, NIST-800-53:RA-5, ISO27001:A.5.17, SOC2:CC6.1, ISO27001:A.8.32, SOC2:CC8.1# Código de salida 1. Ejecuta de nuevo la comprobación obsoleta en el nuevo commit y verifica.
Transcripción ilustrativa, no capturada de una ejecución real. Fuente: tools/cli/commands/assurance.js (verifyAction), tools/cli/lib/assurance.js (motivos de judgeCheck)
Con --emit-check, el archivo escrito es un objeto JSON con el esquema bmad-plus/assurance-check/1: el estado, la revisión, las afirmaciones con sus motivos, los controles y una entrada github (name, conclusion con valor success o failure, un título como 3/5 claims supported y una tabla resumen en Markdown) que un paso de CI puede publicar como ejecución de comprobación. No lleva marca de tiempo, así que el mismo veredicto produce el mismo archivo.
the ledger is not intact: ... o ... is not authenticated by BMAD_PLUS_ASSURANCE_KEY: se alteró un registro o la clave no coincide. Reconstruye el diario ejecutando de nuevo las comprobaciones en un --dir nuevo.
the ledger no longer holds the head ... it was anchored to: se quitaron registros o se sustituyó el diario.
the working tree has uncommitted changes or untracked files: haz commit y vuelve a ejecutar y verificar. Las evidencias describen el commit, no tu árbol de trabajo.
there is no commit to bind the evidence to: la carpeta no es un repositorio git con un commit. Pon freshness.sameCommit: false solo en un proyecto fuera de git.
Una comprobación está missing, failed o stale: la línea <status> <check>: <reasons> dice por qué. Ejecútala de nuevo en el commit actual.
Que Shield construya y ejecute un caso para una versión#
Vas a publicar una versión y un cliente pidió la prueba de que los controles de seguridad se cumplen en ese commit exacto. El árbol de trabajo está confirmado.
En tu asistente de IA
Shield, inicia un caso de aseguramiento para esta versión. Mantén cada afirmación lo bastante pequeña para que un comando la demuestre, etiquétalas con los controles que respaldan, luego ejecuta las comprobaciones en este commit y verifica el caso. Dime qué afirmaciones no están respaldadas y por qué.
Lo que deberías obtener Shield ejecuta bmad-plus assurance init _bmad/assurance/<id>.yaml, sustituye las afirmaciones y comprobaciones de ejemplo de la plantilla por las de tu proyecto (una afirmación principal, subafirmaciones cada una respaldada por un comando que sale con error cuando la afirmación falla) y te pide que hagas commit del archivo. Después ejecuta assurance run, guarda la cabeza del diario impresa y ejecuta assurance verify --ledger-head <head> --emit-check .... Informa de cada afirmación no respaldada con el motivo que imprime verify y lista los controles con evidencia ejecutada. Indica si se usaron una clave y una cabeza; sin ellas, aclara que las evidencias están registradas pero no a prueba de manipulación. Nunca da por cumplida una afirmación no respaldada.
Un job de CI falló en assurance verify, y el caso estaba en verde la semana pasada.
En tu asistente de IA
Shield, verifica el caso release-security y explica cada afirmación no respaldada. No vuelvas a ejecutar nada hasta decirme qué está obsoleto y por qué.
Lo que deberías obtener Shield ejecuta bmad-plus assurance verify _bmad/assurance/release-security.yaml (solo lectura) y lee la salida: la línea de estado, cada comprobación no superada con sus motivos (otro commit, cambios sin confirmar, comando o artefacto modificado, más antiguo que maxAgeDays) y cada afirmación no respaldada. Los explica con palabras sencillas, te dice qué comprobaciones repetir con assurance run --check <id> y espera tu visto bueno antes de ejecutar nada, porque run ejecuta los comandos escritos en el caso.