Einen Security-Assurance-Case aufbauen: Aussagen, die nur durch wirklich gelaufene Prüfungen gestützt sind, in einem Hash-Ledger festgehalten und an einem Commit verifiziert.
assurance ist der Befehl hinter dem Security-Assurance-Case des Shield-Packs. Ein Case listet Aussagen über dein System auf (zum Beispiel „keine Produktionsabhängigkeit hat eine bekannte Schwachstelle hoher Schwere“), liefert zu jeder ein Argument und stützt sie mit Nachweisen. Als Nachweis akzeptiert BMAD+ nur eine Prüfung, die es selbst ausgeführt hat: ein Befehl, sein Exit-Code, ein Digest seiner Ausgabe und die Digests der geschriebenen Dateien, angehängt an ein per Hash verkettetes Ledger. Eine Behauptung, ein Dokument oder ein Link wird abgelehnt. Du brauchst es, wenn jemand, eine Prüferin, ein Kunde oder du selbst später, zeigen will, dass Kontrollen an einem bestimmten Commit greifen, und „wir glauben es“ nicht reicht.
Warnung· Was ein Urteil nicht ist
Ein „supported“-Case zeigt, dass die genannten Prüfungen an einem Commit bestanden haben. Er zertifiziert das System nicht und ist kein Prüfurteil; was die Nachweise wert sind, entscheidet eine qualifizierte Prüferin. Außerdem führt assurance run die im Case stehenden Befehle mit demselben Vertrauen aus wie deine eigenen Skripte: Lies einen fremden Case, bevor du ihn startest.
Kopiert die Shield-Vorlage in die genannte Case-Datei. Die Datei muss <id>.yaml heißen; die ID stammt aus dem Namen. Eine vorhandene Datei wird nie überschrieben.
run
Führt die Prüfungen des Case aus (alle oder die mit --check genannten) und hängt pro Prüfung einen Eintrag ans Ledger an.
verify
Bewertet jede Prüfung nach ihrem letzten Lauf und jede Aussage nach ihren Nachweisen und gibt das Urteil aus. Führt nichts aus.
Optionen von assurance
Option
Argument
Standard
Was sie tut
-d, --directory
<path>
aktueller Ordner
Projektordner.
--dir
<path>
_bmad-output/assurance
Nachweisordner im Projekt; das Ledger liegt in <dir>/<case id>/runs.jsonl. Relativer Pfad, mit / geschrieben.
--check
<id>
alle Prüfungen
Nur run: nur diese Prüfung ausführen. Die Option für mehrere wiederholen.
--ledger-head
<sha256>
keiner
Nur verify: fehlschlagen, wenn das Ledger den Eintrag mit diesem Digest nicht mehr enthält (64 hexadezimale Kleinbuchstaben).
--emit-check
<file>
keiner
Nur verify: das Urteil zusätzlich als JSON-Prüfergebnis für CI schreiben. Der Name muss auf .json enden und darf weder der Case noch sein Ledger sein.
--json
-
aus
Das Ergebnis als JSON (schemaVersion: 1) statt als Text ausgeben. Fehler werden zu { "status": "error", "message": ... }.
Üblicherweise liegt ein Case unter _bmad/assurance/<id>.yaml, aber jeder projektrelative Pfad ohne .. und ohne symbolischen Link funktioniert. init schreibt die Shield-Vorlage, ein vollständiges lauffähiges Beispiel (vier Prüfungen, eine Hauptaussage und vier Unteraussagen). Ersetze jedes Beispiel durch dein eigenes, committe die Datei und starte sie dann. So sieht die Form aus; unbekannte Schlüssel werden abgelehnt.
Form eines Case (aus der Vorlage gekürzt)
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.
Schlüssel eines Case
Schlüssel
Regel
schema
Muss bmad-plus/assurance-case/1 sein.
id
Kleinbuchstaben, Ziffern, Punkte und Bindestriche, bis zu 64 Zeichen.
title, scope
Freitext, je 1 bis 4000 Zeichen.
freshness.maxAgeDays
Ganze Tage von 1 bis 366. Standard 30. Ein älterer Lauf ist stale.
freshness.sameCommit
true (Standard) bindet die Nachweise an den ausgecheckten Commit und einen sauberen Arbeitsbaum. Nur für ein Projekt außerhalb von git auf false setzen.
checks[].id
Eindeutige ID der Prüfung.
checks[].run
Der Befehl als Liste einzelner Argumente. Keine Shell beteiligt. Unter Windows sind Programme wie npm .cmd-Dateien und brauchen [cmd, /c, npm, ...].
checks[].cwd
Projektrelativer Ordner für die Ausführung. Standard ..
checks[].env
Namen zusätzlicher Umgebungsvariablen, die die Prüfung sehen darf. Standardmäßig erbt sie nur PATH, HOME, die temporären Ordner und einige Windows-Systemvariablen. BMAD_PLUS_ASSURANCE_KEY darf nie aufgeführt werden.
checks[].timeoutSeconds
Ganze Zahl von 1 bis 21600. Standard 600.
checks[].expect.exitCode
Exit-Code, der als Erfolg gilt, 0 bis 255. Standard 0.
checks[].artifacts
Projektrelative Dateien, die der Befehl schreiben muss; jede wird mit dem Lauf gehasht. Eine vom Lauf unverändert gelassene Datei gilt nicht als erzeugt.
claims[].id, claim, argument
Pflicht. Das Argument sagt, warum eine bestandene Prüfung die Aussage zeigt.
claims[].parent
Eine früher deklarierte Aussage. Eine Aussage ohne Nachweis braucht mindestens eine Unteraussage, sonst ist sie „nur behauptet“ und der Case lädt nicht.
claims[].controls
Optionale Liste von FRAMEWORK:ID-Verweisen. Akzeptierte Rahmenwerke: ISO27001, SOC2, GDPR, EU-AI-Act, NIS2, NIST-800-53. Eine falsch geschriebene oder erfundene Kontrolle wird abgelehnt.
claims[].evidence
Liste von { check, shows }. check muss eine deklarierte Prüfung nennen.
init schreibt genau eine Datei: den Case, unter dem angegebenen Pfad (übergeordnete Ordner werden angelegt).
run liest den Case, führt jede gewählte Prüfung als Kindprozess ohne Shell aus und hängt pro Prüfung eine Zeile an <dir>/<case id>/runs.jsonl an. Währenddessen hält es runs.jsonl.lock. Es fragt git (rev-parse, status, ls-files), um den Commit und den Zustand des Arbeitsbaums festzuhalten.
verify liest Case, Ledger, git und die deklarierten Artefakte. Es schreibt nichts außer der optionalen --emit-check-Datei.
Es öffnet selbst keine Netzwerkverbindung. Die Befehle, die du deklarierst, tun, was sie tun; deshalb führt das Inventar der Datenflüsse assurance-checks als Fluss auf, der nur existiert, wenn du run aufrufst.
Überall abgelehnt: Pfade außerhalb des Projekts und jeder Pfad, der durch einen symbolischen Link führt.
Jeder Eintrag in runs.jsonl ist eine JSON-Zeile: Prüf-ID, Sequenznummer, Digest des Befehls, der Commit (revision) und dirty (ob verfolgte Änderungen oder nicht ignorierte, unverfolgte Dateien vorlagen), Start- und Endzeit, Exit-Code, ob eine Zeitüberschreitung vorlag, Größe und Digest der Ausgabe mit geschwärztem Auszug der letzten 2048 Bytes, der Digest jedes deklarierten Artefakts (oder null, wenn der Lauf es nicht schrieb), der Digest des Vorgängereintrags und der eigene sha256. Wer einen Eintrag vor dem letzten ändert, umsortiert oder entfernt, bricht die Kette, und verify bewertet dann den ganzen Case als nicht gestützt.
Die Kette allein verrät nur nachlässige Änderungen: Wer die Datei schreiben kann, kann einen gültigen Eintrag anhängen oder die letzten abschneiden. Zwei Dinge außerhalb des Ledgers schließen diese Lücke.
Der Schlüssel. Setze BMAD_PLUS_ASSURANCE_KEY (mindestens 32 Zeichen) aus einem CI-Secret. run hängt dann an jeden Eintrag einen HMAC-SHA256, und verify lehnt jeden Eintrag ab, den der Schlüssel nicht authentifiziert. Der Schlüssel wird nie an eine Prüfung weitergegeben. Nimm für run und verify denselben Schlüssel: Ein ohne Schlüssel geschriebenes Ledger wird abgelehnt, sobald der Schlüssel gesetzt ist.
Der Kopf. run gibt den Digest seines letzten Eintrags aus. Bewahre ihn dort auf, wo die Schreibenden des Ledgers ihn nicht ändern können (CI-Job-Log, Audit-Datei), und übergib ihn an verify --ledger-head. Ein Ledger, das diesen Eintrag nicht mehr enthält, wird abgelehnt, entfernte Läufe fallen also auf.
Lief, tat, was die Prüfung erwartet, und ist aktuell.
failed
Startete nicht, überschritt die Zeit, endete mit einem anderen als dem erwarteten Code, oder ein Artefakt wurde vom Lauf nicht erzeugt.
stale
Bestand, aber an einem anderen Commit, auf uncommitteten Änderungen oder unverfolgten Dateien, mit inzwischen geändertem Befehl, mit inzwischen geändertem Artefakt, älter als maxAgeDays oder mit Endzeit in der Zukunft.
missing
Lief nie.
Eine Aussage ist nur supported, wenn alle ihre Nachweisprüfungen passed und alle Unteraussagen supported sind; sonst ist sie unsupported, mit Begründung. Der Case ist nur supported, wenn jede Aussage es ist, das Ledger intakt ist, ein angegebener --ledger-head noch darin steht und bei sameCommit: true ein Commit existiert und der Arbeitsbaum weder uncommittete Änderungen noch unverfolgte Dateien hat (Ledger-Ordner und Artefakte des Case zählen nicht). Das Urteil listet außerdem controls.supported und controls.unsupported: die an Aussagen markierten Kontrollen, die ausgeführte Nachweise haben oder nicht.
Jede gewählte Prüfung endete so, wie sie es erwartet.
run
1
Mindestens eine gewählte Prüfung ist gescheitert (Start unmöglich, Zeitüberschreitung, falscher Exit-Code oder ein deklariertes Artefakt nicht erzeugt). Die Einträge werden trotzdem geschrieben.
verify
0
Der Case ist supported.
verify
1
Der Case ist unsupported.
alle
3
Der Befehl konnte seine Arbeit nicht tun: unbekannte Aktion, Case fehlt oder ist ungültig, falscher Schlüssel oder Kopf, Ledger bei run nicht intakt, Sperre gehalten, Prüfung nicht deklariert, --emit-check abgelehnt. Ausgabe als assurance: <message> auf dem Fehlerstrom.
Die drei Mitschnitte unten sind aus den Meldungsvorlagen im Quellcode zusammengesetzt, mit Beispielwerten (Pfade, Zeiten und Digests sind erfunden). Deshalb sind sie als simuliert markiert.
Einen Case starten und ausführenSimuliert
$ 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
Beispielhafter Ablauf, nicht bei einem echten Lauf aufgezeichnet. Quelle: tools/cli/commands/assurance.js (Meldungsvorlagen von initAction und runAction)
Beispielhafter Ablauf, nicht bei einem echten Lauf aufgezeichnet. Quelle: tools/cli/commands/assurance.js (Meldungsvorlage von verifyAction)
Verifizieren, nachdem sich der Code geändert hatSimuliert
$ 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# Exit-Code 1. Die veraltete Prüfung am neuen Commit erneut ausführen, dann verifizieren.
Beispielhafter Ablauf, nicht bei einem echten Lauf aufgezeichnet. Quelle: tools/cli/commands/assurance.js (verifyAction), tools/cli/lib/assurance.js (Begründungen von judgeCheck)
Mit --emit-check ist die geschriebene Datei ein JSON-Objekt mit dem Schema bmad-plus/assurance-check/1: Status, Revision, die Aussagen mit Begründungen, die Kontrollen und ein github-Eintrag (name, conclusion als success oder failure, ein Titel wie 3/5 claims supported und eine Markdown-Übersichtstabelle), den ein CI-Schritt als Check-Run veröffentlichen kann. Er enthält keinen Zeitstempel, dasselbe Urteil ergibt also dieselbe Datei.
the ledger is not intact: ... oder ... is not authenticated by BMAD_PLUS_ASSURANCE_KEY: Ein Eintrag wurde verändert oder der Schlüssel passt nicht. Das Ledger neu aufbauen, indem du die Prüfungen in ein frisches --dir erneut ausführst.
the ledger no longer holds the head ... it was anchored to: Einträge wurden entfernt oder das Ledger ausgetauscht.
the working tree has uncommitted changes or untracked files: committen, dann erneut ausführen und verifizieren. Die Nachweise beschreiben den Commit, nicht deinen Arbeitsbaum.
there is no commit to bind the evidence to: Der Ordner ist kein git-Repository mit einem Commit. freshness.sameCommit: false nur für ein Projekt außerhalb von git setzen.
Eine Prüfung ist missing, failed oder stale: Die Zeile <status> <check>: <reasons> nennt den Grund. Diese Prüfung am aktuellen Commit erneut ausführen.
Shield einen Case für ein Release bauen und ausführen lassen#
Du stehst vor einem Release, und ein Kunde hat einen Nachweis verlangt, dass die Sicherheitskontrollen an genau diesem Commit greifen. Der Arbeitsbaum ist committet.
In deinem KI-Assistenten
Shield, starte einen Assurance-Case für dieses Release. Halte jede Aussage so klein, dass ein Befehl sie zeigt, markiere sie mit den Kontrollen, die sie stützen, führe dann die Prüfungen an diesem Commit aus und verifiziere den Case. Sag mir, welche Aussagen nicht gestützt sind und warum.
Das solltest du erhalten Shield führt bmad-plus assurance init _bmad/assurance/<id>.yaml aus, ersetzt die Beispielaussagen und -prüfungen der Vorlage durch die deines Projekts (eine Hauptaussage, Unteraussagen, jede gestützt durch einen Befehl, der bei Verletzung der Aussage fehlschlägt) und bittet dich, die Datei zu committen. Danach startet es assurance run, merkt sich den ausgegebenen Ledger-Kopf und führt assurance verify --ledger-head <head> --emit-check ... aus. Es meldet jede nicht gestützte Aussage mit dem von verify genannten Grund und listet die Kontrollen mit ausgeführtem Nachweis. Es sagt, ob Schlüssel und Kopf genutzt wurden; ohne sie vermerkt es, dass die Nachweise festgehalten, aber nicht manipulationssicher sind. Eine nicht gestützte Aussage nennt es nie erfüllt.
Ein CI-Job ist an assurance verify gescheitert, obwohl der Case letzte Woche grün war.
In deinem KI-Assistenten
Shield, verifiziere den Case release-security und erkläre jede nicht gestützte Aussage. Führe nichts erneut aus, bevor du mir gesagt hast, was veraltet ist und warum.
Das solltest du erhalten Shield führt bmad-plus assurance verify _bmad/assurance/release-security.yaml aus (nur lesend) und liest die Ausgabe: die Statuszeile, jede nicht bestandene Prüfung mit Gründen (anderer Commit, uncommittete Änderungen, geänderter Befehl oder geändertes Artefakt, älter als maxAgeDays) und jede nicht gestützte Aussage. Es erklärt sie in einfachen Worten, nennt die Prüfungen, die mit assurance run --check <id> zu wiederholen sind, und wartet auf dein Okay, bevor es etwas ausführt, denn run führt die im Case stehenden Befehle aus.