
Ed25519-signierte Belege + Cedar-Richtlinien für KI-Agenten. Finanzmandats-Gate (Legate), Nachweispakete, 3 IETF-Internetentwürfe. npx protect-mcp
Fail-Closed Cedar Policy Gate mit signierten Empfangsbestätigungen für KI-Agenten-Toolaufrufe.
protect-mcp ist ein Gate, das vor den Toolaufrufen eines KI-Agenten sitzt. Es bewertet jeden Aufruf gegen eine Cedar-Richtlinie (dieselbe Sprache, die AWS für IAM verwendet), blockiert, was die Regeln verletzt, bevor es ausgeführt wird, und signiert eine offline verifizierbare Ed25519-Empfangsbestätigung jeder Entscheidung. Es läuft lokal, sendet keine Telemetriedaten Ihrer Entscheidungen irgendwohin und ist unter MIT-Lizenz lizenziert.
would_deny: true gekennzeichnet, sodass ein Fehler nie still ist.serve --enforce und doctor führen einen Start-Selbsttest durch und weigern sich, das Gate zu aktivieren, es sei denn, sie können zeigen, dass eine bekanntermaßen verbotene Aktion tatsächlich verweigert wird. Ein Gate, das nicht beweisen kann, dass es verweigert, startet nicht.@veritasacta/verify. Kein Vertrauen in Anbieter erforderlich: Die Mathematik kümmert sich nicht darum, wer sie ausführt.npx protect-mcp init
npx protect-mcp wrap -- node your-mcp-server.js
npx protect-mcp dashboard --open
npx protect-mcp recommend --write
npx protect-mcp --policy protect-mcp.recommended.json --enforce -- node your-mcp-server.js
Führen Sie für Claude Desktop zuerst einen Dry-Run-Konfigurationspatch aus und wenden Sie ihn dann an:```bash
npx protect-mcp wrap --claude-desktop
npx protect-mcp wrap --claude-desktop --write
npx protect-mcp dashboard --open
Das Dashboard bindet an 127.0.0.1, liest nur lokale Protokoll-/Quittungsdateien und lädt nichts hoch. Verwenden Sie npx protect-mcp connect nur, wenn Sie explizit ein gehostetes ScopeBlind-Dashboard wünschen.
Wenn Sie das Gate lieber als Tools aufrufen möchten, anstatt die Claude Code-Hooks zu verdrahten, führen Sie es als MCP-Server aus:```bash npx protect-mcp mcp
Es kommuniziert via MCP über stdio und stellt vier schreibgeschützte Tools bereit, der gesamte Ablauf:
- **`evaluate_action`**: Bewertet einen vorgeschlagenen Tool-Aufruf anhand einer Inline-Cedar-Richtlinie, fail-closed (jeder Richtlinienfehler führt zu DENY). Gibt `{ allowed, decision, reason, policy_digest }` zurück.
- **`sign_decision`**: Wandelt eine Entscheidung in eine mit Ed25519 signierte Quittung um (eine Ablehnung signiert eine `gateway_restraint`, eine Erlaubnis eine `decision_receipt`). Gibt die Quittung und ihren öffentlichen Schlüssel zurück; generiert einen ephemeren Schlüssel, falls keiner bereitgestellt wird.
- **`verify_receipt`**: Überprüft eine signierte Quittung offline anhand eines öffentlichen Schlüssels. Gibt `{ valid, error, type, kid, issuer }` zurück.
- **`self_test`**: Selbsttest, keine Eingaben. Eine bekanntermaßen verbotene Aktion wird abgelehnt, dann durchläuft eine signierte Quittung den gesamten Zyklus und eine manipulierte Kopie schlägt fehl.
Richten Sie einen beliebigen MCP-Host darauf aus, z. B. Claude Desktop:```json
{
"mcpServers": {
"protect-mcp": { "command": "npx", "args": ["-y", "protect-mcp", "mcp"] }
}
}
Receipts sind byte-kompatibel mit denen, die das Gate zur Laufzeit signiert, sodass eine
hier ausgestellte Quittung mit @veritasacta/verify
und dem Browser-Verifier gleichermaßen verifiziert wird.
protect-mcp dashboard ist die Operator-Ansicht, um von Sichtbarkeit zu Durchsetzung zu gelangen:
Require approval, Block oder Observe. Starten Sie den Wrapper nach der Überprüfung der Änderungen neu.Für Live-Desktop-Fallback-Genehmigungen starten Sie das Dashboard mit dem vom Wrapper ausgegebenen lokalen Gateway-Genehmigungsendpunkt und Nonce:```bash
npx protect-mcp dashboard --open
--approval-endpoint http://127.0.0.1:9876
--approval-nonce "$PROTECT_MCP_APPROVAL_NONCE"
`Approve` leitet an das Live-Local-Gateway weiter, wenn diese Flags vorhanden sind.
`Deny`, `Edit` und `Take over` werden lokal als Genehmigungsauflösungsdatensätze erfasst; verwenden Sie sie als Operatoranweisung und führen Sie das Tool bei Bedarf erneut aus.
### Bezahltes Boundary-MVP: Digest-Verankerung, kein Daten-Upload
Lokale selbstsignierte Belege bleiben kostenlos und offline verifizierbar. Die bezahlte Grenze ist ein unabhängiger Beweis dafür, dass ScopeBlind zu einem bestimmten Zeitpunkt unter einer Organisationsidentität einen Beleg-Digest gesehen hat, ohne den rohen Prompt, die Tool-Nutzlast, die Ausgabe, den privaten Schlüssel oder den rohen Beleg zu erhalten.```bash
# Create or refresh a local org identity and public-key directory.
npx protect-mcp registry init --org "Meridian Global Macro" --billing-account acct_meridian
# Local preview: writes a digest registry and shareable static verifier page.
npx protect-mcp registry anchor
# Hosted mode: uploads receipt digests only for independent anchoring.
SCOPEBLIND_TOKEN=... npx protect-mcp registry anchor \
--hosted \
--endpoint https://api.scopeblind.com \
--verifier-base https://legate.scopeblind.com
Die lokale Vorschau ist bewusst als local-preview-not-independent gekennzeichnet.
Der gehostete Modus verankert nur Beleg-Hashes, Anfrage-IDs, öffentliche Schlüssel der Organisation und
Abrechnungsmetadaten. Es werden keine Rohbelege oder vertraulichen Kontexte hochgeladen.
protect-mcp killer-demo erzeugt ein komplettes dreiminütiges Verkaufs-/Demopaket:```bash
npx protect-mcp killer-demo --dir ./scopeblind-demo
Es erstellt simulierte Dateisystem-, GitHub-, E-Mail- und PMS-Aktivitäten; zeigt riskante Aufrufe im Shadow-Modus; wendet ein Policy-Paket an; erfordert Genehmigung für eine sensible PMS-Buchung; führt über das Gateway aus; schreibt eine signierte Quittung; beweist, dass die originale Quittung verifiziert; beweist, dass eine manipulierte Quittung fehlschlägt; und erstellt ein selektives Offenlegungspaket, das sensiblen Kontext verbirgt und den minimalen Nachweis zeigt.
Öffnen Sie zuerst die generierte `DEMO-RUNBOOK.md`. Führen Sie dann den gedruckten Dashboard-Befehl aus, um einen Kunden durch die genaue Sequenz zu führen.
### Selektive Offenlegung v0
Commitment-Modus-Quittungen können eine `committed_fields_root` anstelle der Offenlegung jedes Feldes im Klartext enthalten. Später kann der Inhaber nur ausgewählte Felder offenlegen:```bash
npx protect-mcp verify-disclosure \
--receipt ./receipts/selective-disclosure.receipt.json \
--disclosure ./receipts/selective-disclosure.tool-only.json
Der Verifizierer prüft den übergeordneten Beleg-Hash, die Ed25519-Signatur, die Commit-Wurzel und den Merkle-Beweis jedes offengelegten Feldes. Anschließend erläutert er, welche Felder offengelegt wurden und welche verborgenen Felder weiterhin nicht sichtbar sind. Dies ist eine gesalzene Commit-Offenlegung, kein vollwertiges Zero-Knowledge, aber es konkretisiert die Datenschutzbehauptung: Prüfer können ausgewählte Fakten überprüfen, ohne die vollständige Tool-Nutzlast oder den sensiblen Desk-Kontext zu erhalten.
Sie können eine BEHAUPTUNG über Ihren Datensatz beweisen, ohne ihn preiszugeben. Mint eine signierte, positionsblinde Attestierung über den gesamten Datensatz, die nur entscheidungsbezogene Kategorien offenlegt (einen Beleg-Digest, das Urteil, Fähigkeits-Tags), niemals Ihre Tool-Eingaben, -Ausgaben oder -Daten:```bash
npx protect-mcp claim --no net.egress
Jeder kann es offline überprüfen, sieht dabei nur die Kategorien, niemals den Inhalt:```bash
npx protect-mcp verify-claim claim-<id>.json
Der Verifizierer berechnet einen Merkle-Root über die offengelegte Menge neu und berechnet das Prädikat unabhängig neu, sodass der Aussteller nicht über den Anspruch lügen kann, wenn die Offenlegung erfolgt. Fügen Sie --anchor hinzu, um den Digest des Anspruchs im öffentlichen, nur-anhängbaren ScopeBlind-Transparenzlog zu erfassen, damit eine Gegenpartei, die Ihnen nicht vertraut, bestätigen kann, dass die offengelegte Menge vollständig ist und nicht stillschweigend neu zugeschnitten wurde (nur der Hash wird gesendet; der Datensatz bleibt lokal):```bash
npx protect-mcp claim --no net.egress --anchor
Dies ist eine rechenschaftspflichtige, positionsblinde Beglaubigung, kein vollständiges Zero-Knowledge: Sie gibt die Form preis, nicht den Inhalt.
## Probieren Sie es in 60 Sekunden aus (kein Agent erforderlich)
[](https://legate.scopeblind.com/record)
Schauen Sie sich den zweiminütigen Film unter [legate.scopeblind.com/record](https://legate.scopeblind.com/record) an und führen Sie ihn dann mit Ihrer eigenen Kopie aus:```bash
npx protect-mcp sample # seed a labeled sample record (8 decisions: 1 blocked, 2 payments)
npx protect-mcp record # open it: signatures verified in your browser
npx protect-mcp claim --payment-under 100 --anchor --output payments-under-100.json
npx protect-mcp verify-claim payments-under-100.json
npx protect-mcp anchor-record
Lege die generierte demo-tampered.jsonl auf der Aufzeichnungsseite ab, um zu sehen, wie eine nachträgliche Signaturänderung erkannt wird. sample weigert sich, eine vorhandene Aufzeichnung zu berühren, also führe es in einem leeren Ordner aus. Wenn du bereit für den Ernstfall bist, verdrahte das folgende Gate und die gleichen Befehle werden gegen die eigene Aufzeichnung deines Agents ausgeführt.
npx protect-mcp init-hooks
npx protect-mcp serve --enforce --cedar ./cedar
Einmalige Bewertung, so wie ein PreToolUse-Hook sie aufruft. Exit-Code 2 bedeutet Ablehnung (das Tool wird blockiert); Exit-Code 0 bedeutet Zulassung:```bash
npx protect-mcp evaluate --cedar ./cedar --tool Bash --input '{"command":"rm"}'
echo $? # 2 -> denied, fail-closed
npx protect-mcp evaluate --cedar ./cedar --tool Read --input '{"path":"README.md"}'
echo $? # 0 -> allowed
Eine fehlende oder nicht ladbare Richtlinie verweigert (exit 2), es sei denn, Sie übergeben explizit
--fail-on-missing-policy false.
protect-mcp init-hooks schreibt eine .claude/settings.json für Sie. Um das
Gate von Hand zu verdrahten, sind die beiden benötigten Verben evaluate (PreToolUse, blockiert bei exit 2)
und sign (PostToolUse, zeichnet eine Quittung auf). Fixieren Sie die Version, sodass eine Claude Code
Sitzung immer das von Ihnen getestete Gate ausführt:```json
{
"hooks": {
"PreToolUse": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "npx [email protected] evaluate --cedar ./cedar --tool "$TOOL_NAME" --input "$TOOL_INPUT""
}
]
}
],
"PostToolUse": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "npx [email protected] sign --tool "$TOOL_NAME" --receipts ./receipts --key ./keys/gateway.json"
}
]
}
]
}
}
`evaluate` exits 2 bei Ablehnung, sodass Claude Code den Werkzeugaufruf blockiert, und 0 bei Zulassung.
`sign` ist Best-Effort: es hängt eine Ed25519-signierte Quittung an, wenn ein Schlüssel konfiguriert ist, und wenn kein Signierer verfügbar ist, zeichnet es eine ehrliche unsignierte Zeile auf (`"signed": false`), anstatt das Werkzeug fehlschlagen zu lassen.
## Einsatz in anderen Agenten (Codex, Cursor, Gemini, Hermes)
Das gleiche fail-closed-Gate läuft als Tool-Hook in jedem Agenten, der diese unterstützt. Fügen Sie `--format <host>` hinzu, damit das Verb die Hook-Payload dieses Hosts von stdin liest und in seinem Contract ablehnt:```bash
# the PreToolUse / before-tool command for each host
npx -y protect-mcp@latest evaluate --format codex --cedar ./cedar # OpenAI Codex
npx -y protect-mcp@latest evaluate --format gemini --cedar ./cedar # Gemini CLI BeforeTool
npx -y protect-mcp@latest evaluate --format cursor --cedar ./cedar # Cursor beforeShellExecution
npx -y protect-mcp@latest evaluate --format hermes --cedar ./cedar # Hermes pre_tool_call
Pair each with sign --format <host> on the post-tool event for receipts. The
important case is Hermes, which ignores hook exit codes and reads the verdict
from stdout, so --format hermes denies via {"decision":"block"} rather than
exit 2 (a raw exit-2 would silently fail open there). Without --format, the
verbs read --tool/--input flags exactly as in the Claude Code section above.
Cedar policies live in a directory you point at with --cedar. A forbid rule
denies, a permit rule allows. To match against a value in the tool input, use
the .contains() idiom:```cedar
// Allow read-only tools.
permit(
principal,
action == Action::"MCP::Tool::call",
resource == Tool::"Read"
);
// Deny dangerous shell commands by matching the command against a list. forbid( principal, action == Action::"MCP::Tool::call", resource == Tool::"Bash" ) when { ["rm", "dd", "mkfs"].contains(context.command) };
// Block destructive tools outright. forbid( principal, action == Action::"MCP::Tool::call", resource == Tool::"delete_file" );
> **Gefahr:** Schreiben Sie NICHT `context.command in ["rm", "dd"]`, um einen String mit einer Liste abzugleichen. `in` ist für Entitätshierarchien, nicht für String-Zugehörigkeit. Cedar behandelt den Ausdruck als Typfehler und verwirft stillschweigend die gesamte `forbid`-Regel, was (bei einem Fail-Open-Gate) ein residuelles `permit` hinterlässt. Dies ist der genaue Defekt hinter dem untenstehenden Advisory. Verwenden Sie stattdessen `[...].contains(context.command)`. Ab Version 0.7.0 verweigert das Gate bei diesem Fehler, anstatt zu erlauben, und ein CI-Tripwire-Test schlägt fehl, wenn das Muster wieder in eine ausgelieferte Richtlinie eingeführt wird. Siehe [GHSA-hm46-7j72-rpv9](https://github.com/ScopeBlind/scopeblind-gateway/security/advisories/GHSA-hm46-7j72-rpv9).
### Starter-Richtlinienpakete
Die meisten Teams sollten Cedar nicht von Grund auf am ersten Tag schreiben. Installieren Sie ein Starter-Paket, führen Sie es im Schattenmodus aus, prüfen Sie die Quittungen und verschärfen oder erzwingen Sie dann:```bash
npx protect-mcp policy-packs list
npx protect-mcp policy-packs show secrets-safe
npx protect-mcp policy-packs install filesystem-safe --dir ./cedar
npx protect-mcp policy-packs install all --dir ./cedar
npx protect-mcp serve --cedar ./cedar
Integrierte Pakete:
filesystem-safe: zerstörerische Dateioperationen und geheimnisähnliche Pfad-Lesevorgänge.git-safe: Force-Pushes, Hard Resets, zerstörerische Bereinigung, Repo-Löschung.email-safe: Erstellen von Entwürfen erlauben, unbeaufsichtigte Sendungen blockieren.database-safe: leseorientierte DB-Haltung, Schreib-/Admin-SQL blockieren.cloud-spend-safe: offensichtliche Cloud-Ausgabenerstellung und Infrastrukturzerstörung.secrets-safe: häufige Exfiltration von Datei-, Umgebungs-, Shell- und Cloud-Geheimnissen.finance-mandate-safe: Verstöße gegen Sperrlisten und Konzentrationsverstöße in Buchungsabläufen.Quittungen sind signiert und offline von jedem mit dem öffentlichen Schlüssel überprüfbar. Kein Netzwerk, kein Anbieter, kein Vertrauen in ScopeBlind:```bash npx @veritasacta/verify ./receipts/receipts.jsonl --format jsonl
`npx protect-mcp bundle --output audit.json` exportiert ein eigenständiges, offline verifizierbares Audit-Bündel Ihrer Quittungen sowie den öffentlichen Signaturschlüssel.
## Sicherheit
`protect-mcp` 0.7.0 schlägt standardmäßig geschlossen fehl. Bei jedem Richtlinienauswertungsfehler, einer fehlenden Engine oder einer Richtlinie, die bei der Auswertung fehlerhaft war, wird die Entscheidung auf VERWEIGERN gesetzt, nicht auf ZULASSEN. `serve --enforce` und `doctor` führen einen Boot-Selbsttest durch, der beweist, dass das Gate einen bekannten verbotenen Vektor ablehnt, bevor es vertrauenswürdig ist, und verweigern die Aktivierung, wenn dies nicht möglich ist.
**Betroffene Versionen: 0.5.x und 0.6.x.** Diese Linien schlagen offen fehl (sie geben bei Auswertungsfehlern ZULASSEN zurück) und werten Cedar nicht korrekt gegen die festgelegte Engine aus, sodass eine `forbid`-Regel möglicherweise nicht blockiert. **Upgrade auf >= 0.7.0.**
Details und Behebung: [GHSA-hm46-7j72-rpv9](https://github.com/ScopeBlind/scopeblind-gateway/security/advisories/GHSA-hm46-7j72-rpv9). Um eine Schwachstelle zu melden, siehe [SECURITY.md](https://github.com/scopeblind/scopeblind-gateway/blob/HEAD/SECURITY.md).
## Befehle
| Befehl | Beschreibung |
|---------|-------------|
| `serve` | Startet den HTTP-Hook-Server für Claude Code (Port 9377). `--enforce` führt zuerst den Selbsttest der Zurückhaltung durch; `--cedar <Verzeichnis>` und `--policy <Pfad>` wählen die Richtlinie aus. |
| `init` | Generiert ein Ed25519-Schlüsselpaar (`keys/gateway.json`), eine Konfigurationsvorlage und eine Beispielrichtlinie. |
| `sample` | Befüllt einen klar gekennzeichneten Beispieldatensatz (8 Entscheidungen: ein blockierter Aufruf, zwei Zahlungen; kid `sample-demo`) plus eine manipulierte Kopie, sodass `record`, `claim`, `verify-claim` und `anchor-record` von Grund auf wiederholbar sind, bevor ein Agent angeschlossen wird. Weigert sich, einen vorhandenen Datensatz zu berühren; `--force` überschreibt. |
| `policy` | Zeigt und ändert die Cedar-Richtlinie im Terminal: `policy list` (erlauben / verbieten / Standard-Verweigern pro Werkzeug, mit der Häufigkeit, mit der das Gate es zugelassen oder verweigert hat), `policy show`, `policy allow <Werkzeug>`, `policy deny <Werkzeug>`, `policy path`. Ein laufender `serve` lädt die Änderung heiß nach. |
| `wrap` | Gibt einen geschützten MCP-Befehl aus oder patcht Claude Desktop MCP-Server. Standardmäßig Trockenlauf; verwenden Sie `--write`, um die Claude Desktop-Konfiguration zu aktualisieren. |
| `dashboard` | Startet ein nur lokales Dashboard auf `127.0.0.1`, das Werkzeugbestand, Risiko, Richtlinienabdeckung, Genehmigungen für genaue Aktionen, Quittungsketten und Audit-Export anzeigt. |
| `recommend` | Erstellt einen überprüfbaren JSON-Richtlinienentwurf aus beobachteten lokalen Aufrufen. Standardmäßig Trockenlauf; verwenden Sie `--write`, um `protect-mcp.recommended.json` zu erstellen. |
| `registry` | Erstellt eine Organisationsidentität, verankert Quittungsdigests und schreibt eine statische Verifizierungsseite. Im gehosteten Modus werden nur Digests hochgeladen. |
| `record` | Öffnet einen lokalen, durchsuchbaren Viewer über Ihre Quittungen (`--live` streamt, während der Agent läuft): Ed25519-Signaturen, die in Ihrem Browser gegen Ihren Gateway-Schlüssel verifiziert werden, Fähigkeitsmarkierungen, ein Herkunftsbaum und ein signierter Export mit einem Klick. Alles lokal, nichts hochgeladen. |
| `claim` | Erstellt eine signierte, positionsunabhängige Bestätigung eines Prädikats über den Datensatz (`--no <cap>` inkl. `--no payment`, `--only <c1,c2>`, `--no-verdict <Verdikt>`, `--count <Verdikt>`, `--payment-under <cap>`), die nur Entscheidungskategorien offenlegt. Fügen Sie `--anchor` hinzu, um den Anspruchsdigest im öffentlichen Transparenzprotokoll zu erfassen; registrierte Schlüssel werden als benannte Organisation verankert. |
| `anchor-record` | Setzt einen Checkpoint für die Merkle-Wurzel + Anzahl + Zeitbereich des Datensatzes im öffentlichen Protokoll (Heartbeat-freundlich: überspringt, wenn unverändert). Ein späterer Anspruch, dessen Verpflichtung mit einem verankerten Checkpoint übereinstimmt, ist nachweislich über den vollständigen Datensatz zu diesem Checkpoint. |
| `verify-claim` | Verifiziert ein Anspruchspaket offline: Signatur, neu berechnete Merkle-Wurzel, unabhängig neu berechnetes Prädikat und den Ankerseitenwagen, falls vorhanden (bindet den verankerten Umschlag an diesen genauen Anspruch und bestätigt dann, dass das öffentliche Protokoll ihn enthält). `--check-anchor` erfordert den Anker; `--offline` überspringt den Protokollsprung. |
| `killer-demo` | Generiert ein vollständiges Demo-Paket vom Schattenmodus über Richtlinie bis zur Genehmigung bis zur signierten Quittung. |
| `verify-disclosure` | Überprüft ein `scopeblind.selective_disclosure.v0`-Paket und erklärt offengelegte versus verborgene Felder. |
| `policy-packs` | Listet, inspiziert und installiert Starter-Cedar-Richtlinienpakete. |
| `evaluate` | Wertet einen Werkzeugaufruf gegen eine Cedar-Richtlinie aus (PreToolUse-Gate). Exit 2 = verweigern (fail-closed), Exit 0 = zulassen. |
| `sign` | Signiert einen Werkzeugaufruf in eine Quittung (PostToolUse). Nach bestem Ermessen: zeichnet eine ehrliche unsignierte Zeile auf, wenn kein Schlüssel vorhanden ist. |
| `simulate` | Führt eine Richtlinie trocken gegen ein aufgezeichnetes Entscheidungsprotokoll aus, um zu sehen, was es blockiert hätte. |
| `demo` | Startet einen integrierten Demo-Server, der mit dem Gate umschlossen ist, um Quittungen sofort zu sehen. |
| `doctor` | Überprüft Ihre Einrichtung (Schlüssel, Richtlinien, Cedar-Engine, Verifizierer) und führt den Selbsttest der Zurückhaltung durch. |
| `bundle` | Exportiert ein offline verifizierbares Audit-Bündel von Quittungen plus den öffentlichen Schlüssel. |
| `report` | Generiert einen Compliance-Bericht (Markdown oder JSON) aus dem Entscheidungsprotokoll und den Quittungen. |
Führen Sie `npx protect-mcp --help` aus, um die vollständige Flag-Referenz zu erhalten.
## Links
- Protokoll (IETF): [draft-farley-acta-signed-receipts](https://datatracker.ietf.org/doc/draft-farley-acta-signed-receipts/)
- [CHANGELOG](https://github.com/scopeblind/scopeblind-gateway/blob/HEAD/CHANGELOG.md)
- [npm](https://www.npmjs.com/package/protect-mcp)
- [scopeblind.com](https://scopeblind.com)
MIT-lizenziert. Erstellt von [ScopeBlind](https://scopeblind.com).