thumbgate 1.34.3 → 1.37.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/skills/cyberstrike-compare-not-clone/SKILL.md +36 -0
- package/.agents/skills/gitlab-sandbox-allowlist-not-trust/SKILL.md +77 -0
- package/.agents/skills/jit-harness-compare-not-clone/SKILL.md +34 -0
- package/.agents/skills/openui-catalog-compose-honesty/SKILL.md +64 -0
- package/.agents/skills/zvec-grep-compare-not-clone/SKILL.md +34 -0
- package/.claude-plugin/plugin.json +1 -1
- package/.well-known/llms.txt +1 -0
- package/.well-known/mcp/server-card.json +1 -1
- package/CONTRIBUTING.md +95 -0
- package/README.md +195 -632
- package/THIRD_PARTY_NOTICES.md +89 -0
- package/adapters/claude/.mcp.json +2 -2
- package/adapters/forge/forge.yaml +3 -3
- package/adapters/future-agi/.mcp.json +8 -0
- package/adapters/future-agi/FUTURE_AGI.md +23 -0
- package/adapters/future-agi/config.toml +3 -0
- package/adapters/future-agi/future-agi-bridge.js +9 -0
- package/adapters/future-agi/opencode.json +8 -0
- package/adapters/herdr/herdr-plugin.toml +18 -0
- package/adapters/mcp/server-stdio.js +238 -25
- package/adapters/opencode/opencode.json +1 -1
- package/adapters/workos/WORKOS.md +52 -0
- package/bin/cli.js +373 -5
- package/bin/futureagi-bridge +9 -0
- package/config/gate-templates.json +653 -4
- package/config/gates/actor-critic-audit.json +34 -0
- package/config/gates/default.json +21 -2
- package/config/gates/five-walls-governance.json +34 -0
- package/config/gates/future-agi-guardrails.json +34 -0
- package/config/gates/radware-threat-defense-2026.json +61 -0
- package/config/gates/simatree-data-governance.json +33 -0
- package/config/mcp-allowlists.json +4 -0
- package/config/merge-quality-checks.json +10 -1
- package/config/model-candidates.json +382 -24
- package/config/model-tiers.json +18 -0
- package/config/post-deploy-marketing-pages.json +10 -0
- package/config/progressive/01-wire-only.json +11 -0
- package/config/progressive/02-dashboard-empty-ok.json +10 -0
- package/config/progressive/03-one-lesson.json +10 -0
- package/config/progressive/04-warn-fires.json +11 -0
- package/config/progressive/05-strict-optional.json +11 -0
- package/config/progressive/README.md +15 -0
- package/config/schemas/broker-execution-receipt.schema.json +139 -0
- package/config/schemas/provider-execution-attestation-v1.schema.json +58 -0
- package/conformance/provider-attestation/vectors.json +320 -0
- package/docs/specs/provider-execution-attestation-v1.md +69 -0
- package/openapi/openapi.yaml +15 -0
- package/package.json +401 -147
- package/public/about.html +2 -2
- package/public/ai-malpractice-prevention.html +7 -7
- package/public/blog/a-10-dollar-vps-is-not-a-computer.html +143 -0
- package/public/blog/a-receipt-is-not-world-state.html +388 -0
- package/public/blog/git-at-agent-scale.html +374 -0
- package/public/blog/no-llm-in-the-gate.html +133 -0
- package/public/blog.html +80 -0
- package/public/case-studies.html +16 -1
- package/public/compare.html +28 -0
- package/public/diagnostic.html +216 -7
- package/public/docs/connectors.html +39 -0
- package/public/federal.html +2 -2
- package/public/founders.html +639 -0
- package/public/index.html +87 -9
- package/public/install.html +8 -8
- package/public/learn.html +39 -0
- package/public/numbers.html +2 -2
- package/public/peter.html +310 -0
- package/public/platform-partners.html +119 -0
- package/public/pricing.html +24 -3
- package/public/privacy.html +117 -0
- package/public/pro.html +17 -0
- package/public/support.html +62 -0
- package/public/terms.html +130 -0
- package/public/third-party-notices.html +95 -0
- package/public/yt.html +351 -0
- package/scripts/action-receipts.js +133 -3
- package/scripts/adaptive-governance-arena.js +349 -0
- package/scripts/admin-override.js +205 -0
- package/scripts/agent-action-inventory.js +869 -0
- package/scripts/agent-audit-trace.js +42 -2
- package/scripts/agent-egress-policy.js +1117 -0
- package/scripts/agent-memory-lifecycle.js +141 -2
- package/scripts/agent-operations-planner.js +441 -1
- package/scripts/agent-readiness.js +68 -0
- package/scripts/agent-security-central.js +647 -0
- package/scripts/allowlist-bridge-honesty.js +417 -0
- package/scripts/async-job-runner.js +102 -11
- package/scripts/audit-trail.js +212 -0
- package/scripts/auto-promote-gates.js +178 -27
- package/scripts/billing.js +1 -1
- package/scripts/broker-execution-receipts.js +719 -0
- package/scripts/budget-aware-gates-proof.js +423 -0
- package/scripts/claude-feedback-sync.js +29 -3
- package/scripts/claw-harness-production.js +237 -0
- package/scripts/cli-progress.js +111 -0
- package/scripts/cli-schema.js +163 -1
- package/scripts/codex-runbook-flywheel.js +318 -0
- package/scripts/context-footprint.js +186 -0
- package/scripts/contextfs.js +143 -61
- package/scripts/dashboard-limits.js +27 -0
- package/scripts/dashboard.js +279 -9
- package/scripts/deepseek-v4-runtime-guardrails.js +72 -6
- package/scripts/docker-sandbox-planner.js +18 -0
- package/scripts/double-blind-eval-protocol.js +252 -0
- package/scripts/edotenv-rl-gateway.js +259 -0
- package/scripts/ensure-production-search-corpus.js +162 -0
- package/scripts/eval-holdout.js +311 -0
- package/scripts/feedback-aggregate.js +21 -2
- package/scripts/feedback-loop.js +87 -5
- package/scripts/feedback-quality.js +9 -0
- package/scripts/file-ledger-lock.js +4 -1
- package/scripts/financial-control-plane.js +41 -1
- package/scripts/find-dormant-requires.js +118 -0
- package/scripts/fs-utils.js +84 -8
- package/scripts/gate-stats.js +2 -2
- package/scripts/gates-engine.js +859 -58
- package/scripts/generate-case-study-outreach.js +24 -15
- package/scripts/git-at-scale.js +628 -0
- package/scripts/governance-conflict-audit.js +1650 -0
- package/scripts/governance-difficulty-curriculum.js +328 -0
- package/scripts/graphrag-retrieval.js +275 -0
- package/scripts/gurobi-optimizer.js +324 -0
- package/scripts/gurobi_optimizer.py +485 -0
- package/scripts/harness-selector.js +82 -1
- package/scripts/hidden-entry-points.js +284 -0
- package/scripts/human-escalation.js +199 -1
- package/scripts/hybrid-feedback-context.js +152 -19
- package/scripts/intent-governed-execution.js +602 -0
- package/scripts/intervention-policy.js +123 -20
- package/scripts/jit-harness-compose.js +628 -0
- package/scripts/jsonl-watcher.js +10 -0
- package/scripts/lesson-embedding-index.js +95 -12
- package/scripts/lesson-retrieval.js +105 -19
- package/scripts/local-model-profile.js +19 -2
- package/scripts/mailer/resend-mailer.js +1 -1
- package/scripts/matryoshka-embedding.js +235 -0
- package/scripts/mcp-oauth.js +42 -4
- package/scripts/mcp-session-handles.js +1016 -0
- package/scripts/mcp-wiring-doctor.js +314 -0
- package/scripts/memory-firewall.js +115 -2
- package/scripts/memory-scope-readiness.js +299 -0
- package/scripts/memory-vs-rag-route.js +161 -0
- package/scripts/model-tier-router.js +148 -21
- package/scripts/nvidia-specdecode-al-doctor.js +536 -0
- package/scripts/openui-catalog-compose-honesty.js +593 -0
- package/scripts/operational-integrity.js +19 -1
- package/scripts/override-audit.js +213 -0
- package/scripts/package-manager-honesty-doctor.js +458 -0
- package/scripts/pr-manager.js +63 -1
- package/scripts/prove-herdr-adapter.js +52 -0
- package/scripts/prove-memory-pyramid-and-symbolic-canvas.js +95 -0
- package/scripts/prove-workos.js +73 -0
- package/scripts/provider-attestation-conformance.js +192 -0
- package/scripts/provider-receipt-contract.js +136 -0
- package/scripts/qwen38-max-cost-optimizer.js +401 -0
- package/scripts/radware-threat-defense.js +280 -0
- package/scripts/rag-embedding-identity.js +221 -0
- package/scripts/rag-precision-guardrails.js +112 -2
- package/scripts/remote-feedback-capture.js +159 -0
- package/scripts/research-agent-harness.js +256 -0
- package/scripts/rsi-safety-hillclimb.js +200 -0
- package/scripts/rule-sprawl.js +188 -0
- package/scripts/schedule-manager.js +147 -0
- package/scripts/self-heal.js +8 -0
- package/scripts/session-lease.js +415 -0
- package/scripts/simatree-data-governance.js +347 -0
- package/scripts/slo-alert-engine.js +172 -7
- package/scripts/solver-parity.js +539 -0
- package/scripts/stealth-memory-injection-gate.js +333 -0
- package/scripts/switchyard-router.js +366 -0
- package/scripts/telemetry-analytics.js +84 -27
- package/scripts/temporal-decay-weighting.js +138 -0
- package/scripts/test-all.js +165 -0
- package/scripts/token-savings.js +42 -0
- package/scripts/tool-kpi-tracker.js +108 -5
- package/scripts/tool-registry.js +193 -5
- package/scripts/universal-claim-evaluator.js +14 -2
- package/scripts/vector-store.js +279 -9
- package/scripts/workflow-notebook.js +391 -0
- package/scripts/workflow-sentinel.js +111 -12
- package/scripts/workos-production-guard.js +260 -0
- package/scripts/workspace-search-route.js +515 -0
- package/server.json +2 -2
- package/src/agent-identity-boundary.js +76 -0
- package/src/agent-retrieval-cache.js +155 -0
- package/src/alert-noise-ledger.js +502 -0
- package/src/api/server.js +802 -185
- package/src/git-fast-cache.js +220 -0
- package/src/git-wal-sync.js +156 -0
- package/src/hash-anchored-edit.js +82 -0
- package/src/hermes-platform-protocol.js +475 -0
- package/src/hermes-sync-plane.js +241 -0
- package/src/index.js +30 -1
- package/src/iso42001-compliance-guard.js +97 -0
- package/src/latency-budget.js +244 -0
- package/src/mcp-writeguard.js +316 -0
- package/src/miminions-adapter.js +106 -0
- package/src/pipeline-compass.js +104 -0
- package/src/ppl-alert-pipeline.js +284 -0
- package/src/rendezvous-router.js +90 -0
- package/src/security-questionnaire.js +195 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Third-Party Notices
|
|
2
|
+
|
|
3
|
+
This document lists the third-party open-source software and assets used in the
|
|
4
|
+
ThumbGate project (`thumbgate` npm package and related repositories).
|
|
5
|
+
|
|
6
|
+
The ThumbGate source code itself is released under the MIT License (see `LICENSE`).
|
|
7
|
+
The following notices are required by the respective upstream licenses.
|
|
8
|
+
|
|
9
|
+
## Open-Source Dependencies
|
|
10
|
+
|
|
11
|
+
The following direct dependencies are bundled or used in ThumbGate runtime
|
|
12
|
+
services:
|
|
13
|
+
|
|
14
|
+
| Package | License | Publisher / Source |
|
|
15
|
+
| --- | --- | --- |
|
|
16
|
+
| `@anthropic-ai/sdk` | MIT | Anthropic, PBC |
|
|
17
|
+
| `@google/genai` | Apache-2.0 | Google LLC |
|
|
18
|
+
| `@lancedb/lancedb` | Apache-2.0 | LanceDB.com |
|
|
19
|
+
| `apache-arrow` | Apache-2.0 | Apache Software Foundation |
|
|
20
|
+
| `better-sqlite3` | MIT | Joshua Wise |
|
|
21
|
+
| `dotenv` | BSD-2-Clause | scottmotte / Motdotla, Inc. |
|
|
22
|
+
| `js-yaml` | MIT | Vitaly Puzrin |
|
|
23
|
+
| `playwright-core` | Apache-2.0 | Microsoft Corporation |
|
|
24
|
+
| `protobufjs` | Apache-2.0 / BSD-3-Clause | Daniel Wirtz |
|
|
25
|
+
| `stripe` | MIT | Stripe, Inc. |
|
|
26
|
+
|
|
27
|
+
The following development dependencies are used to build, test, and release
|
|
28
|
+
ThumbGate:
|
|
29
|
+
|
|
30
|
+
| Package | License | Publisher / Source |
|
|
31
|
+
| --- | --- | --- |
|
|
32
|
+
| `@changesets/changelog-github` | MIT | Thinkmill |
|
|
33
|
+
| `@changesets/cli` | MIT | Thinkmill |
|
|
34
|
+
| `@playwright/test` | Apache-2.0 | Microsoft Corporation |
|
|
35
|
+
| `c8` | MIT |bcoe / c8 contributors |
|
|
36
|
+
| `undici` | MIT | Matteo Collina |
|
|
37
|
+
|
|
38
|
+
Additional transitive dependencies are installed automatically by npm. A
|
|
39
|
+
complete machine-readable dependency tree can be generated by running:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npm install -g license-checker
|
|
43
|
+
license-checker --direct 0 --out licenses.json
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Trademarks and Brand Attribution
|
|
47
|
+
|
|
48
|
+
ThumbGate® is an independent product. The following trademarks and brands are
|
|
49
|
+
owned by their respective owners and are referenced solely for compatibility
|
|
50
|
+
and nominative fair use:
|
|
51
|
+
|
|
52
|
+
- Anthropic, Claude, and Claude Code are trademarks of Anthropic, PBC.
|
|
53
|
+
- OpenAI, ChatGPT, and Codex are trademarks of OpenAI, Inc.
|
|
54
|
+
- Cursor is a trademark of Anysphere, Inc.
|
|
55
|
+
- GitHub is a trademark of GitHub, Inc.
|
|
56
|
+
- Google, Gemini, and Google Cloud Platform are trademarks of Google LLC.
|
|
57
|
+
- Perplexity is a trademark of Perplexity AI, Inc.
|
|
58
|
+
- Hermes Agent is a project by Nous Research.
|
|
59
|
+
- Model Context Protocol (MCP) is a protocol introduced by Anthropic, PBC.
|
|
60
|
+
- Nvidia is a trademark of Nvidia Corporation.
|
|
61
|
+
- Railway is a trademark of Railway Corporation.
|
|
62
|
+
- Stripe is a trademark of Stripe, Inc.
|
|
63
|
+
- Supabase is a trademark of Supabase, Inc.
|
|
64
|
+
- PostHog is a trademark of PostHog, Inc.
|
|
65
|
+
- Plausible is a trademark of Plausible Insights OÜ.
|
|
66
|
+
|
|
67
|
+
Use of any third-party mark in this documentation, marketing material, or code
|
|
68
|
+
does not imply affiliation with, endorsement by, or sponsorship from the trademark
|
|
69
|
+
owner.
|
|
70
|
+
|
|
71
|
+
## Font and Asset Attribution
|
|
72
|
+
|
|
73
|
+
ThumbGate uses system and open-source fonts where applicable. Any brand icons,
|
|
74
|
+
diagrams, or demo media that are not original to ThumbGate are credited in the
|
|
75
|
+
`public/assets/` directory or in the asset metadata file where applicable.
|
|
76
|
+
|
|
77
|
+
## Proprietary Boundary
|
|
78
|
+
|
|
79
|
+
The open-source `thumbgate` npm package (MIT licensed) covers the local CLI,
|
|
80
|
+
MCP server, and public adapters. Hosted cloud services, enterprise dashboards,
|
|
81
|
+
multi-tenant adapters, commercial policy-sync engines, and operational tooling
|
|
82
|
+
for `thumbgate.app` are proprietary and not licensed under the public repository
|
|
83
|
+
terms unless a separate written agreement is executed.
|
|
84
|
+
|
|
85
|
+
## Updates
|
|
86
|
+
|
|
87
|
+
This file is updated as part of each release. If you believe an attribution is
|
|
88
|
+
missing or incorrect, please open an issue at:
|
|
89
|
+
https://github.com/IgorGanapolsky/ThumbGate/issues
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
"mcpServers": {
|
|
3
3
|
"thumbgate": {
|
|
4
4
|
"command": "npx",
|
|
5
|
-
"args": ["--yes", "--package", "thumbgate@1.
|
|
5
|
+
"args": ["--yes", "--package", "thumbgate@1.37.1", "thumbgate", "serve"]
|
|
6
6
|
}
|
|
7
7
|
},
|
|
8
8
|
"hooks": {
|
|
9
9
|
"preToolUse": {
|
|
10
10
|
"command": "npx",
|
|
11
|
-
"args": ["--yes", "--package", "thumbgate@1.
|
|
11
|
+
"args": ["--yes", "--package", "thumbgate@1.37.1", "thumbgate", "gate-check"]
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
}
|
|
@@ -9,12 +9,12 @@ version: "1"
|
|
|
9
9
|
skills:
|
|
10
10
|
thumbgate-gate-check:
|
|
11
11
|
description: "ThumbGate PreToolUse gate — blocks known-bad tool calls"
|
|
12
|
-
command: "npx --yes --package thumbgate@1.
|
|
12
|
+
command: "npx --yes --package thumbgate@1.37.1 thumbgate gate-check"
|
|
13
13
|
trigger: pre_tool_use
|
|
14
14
|
|
|
15
15
|
thumbgate-feedback:
|
|
16
16
|
description: "ThumbGate feedback capture — logs user prompt context"
|
|
17
|
-
command: "npx --yes --package thumbgate@1.
|
|
17
|
+
command: "npx --yes --package thumbgate@1.37.1 thumbgate hook-auto-capture"
|
|
18
18
|
trigger: user_prompt
|
|
19
19
|
|
|
20
20
|
mcp:
|
|
@@ -23,6 +23,6 @@ mcp:
|
|
|
23
23
|
args:
|
|
24
24
|
- "--yes"
|
|
25
25
|
- "--package"
|
|
26
|
-
- "thumbgate@1.
|
|
26
|
+
- "thumbgate@1.37.1"
|
|
27
27
|
- "thumbgate"
|
|
28
28
|
- "serve"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Future AGI Integration Guide
|
|
2
|
+
|
|
3
|
+
> Bridging Open-Source Agent Evaluation, Simulation, and Tracing with Deterministic PreToolUse Guardrails.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
Future AGI (`future-agi/future-agi`) provides an open-source platform collapsing simulation, evals, guardrails, tracing, gateway, and optimization into a single feedback loop.
|
|
7
|
+
|
|
8
|
+
**ThumbGate** acts as the **deterministic pre-action execution firewall** at the tool-call interface. When paired together:
|
|
9
|
+
1. **Simulation to Gate Synthesis**: Adversarial test failures in Future AGI are compiled into fail-closed PreToolUse gates in ThumbGate.
|
|
10
|
+
2. **Runtime Action Receipts**: Blocked mutations, tool calls, and human approvals in ThumbGate emit OTel spans back to Future AGI for continuous model optimization.
|
|
11
|
+
|
|
12
|
+
## Model Candidates
|
|
13
|
+
- `future-agi/agentic-eval-v1`: Specialized evaluator model for multi-turn tool calling and groundedness verification.
|
|
14
|
+
- `future-agi/guardrail-scanner`: Sub-10ms scanner for prompt injection and PII detection.
|
|
15
|
+
|
|
16
|
+
## Quickstart
|
|
17
|
+
```bash
|
|
18
|
+
# Evaluate a tool call payload with the Future AGI simulation rubric:
|
|
19
|
+
npx --package=thumbgate futureagi-bridge --simulate '{"tool": "Bash", "command": "publish_release"}'
|
|
20
|
+
|
|
21
|
+
# Run the Doctor check on the Future AGI bridge:
|
|
22
|
+
npx --package=thumbgate futureagi-bridge --doctor
|
|
23
|
+
```
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
[plugin]
|
|
2
|
+
id = "thumbgate-approvals"
|
|
3
|
+
name = "ThumbGate Approvals"
|
|
4
|
+
version = "1.37.1"
|
|
5
|
+
minHerdrVersion = "0.7.0"
|
|
6
|
+
description = "Pre-action governance, spend guard, and safety approval gates for multi-agent terminal sessions in Herdr."
|
|
7
|
+
platforms = ["linux", "macos", "windows"]
|
|
8
|
+
author = "ThumbGate"
|
|
9
|
+
homepage = "https://thumbgate.ai"
|
|
10
|
+
repository = "https://github.com/IgorGanapolsky/ThumbGate"
|
|
11
|
+
category = "Security & Governance"
|
|
12
|
+
|
|
13
|
+
[mcp_server]
|
|
14
|
+
command = "npx"
|
|
15
|
+
args = ["--yes", "--package", "thumbgate@1.37.1", "thumbgate", "serve"]
|
|
16
|
+
|
|
17
|
+
[mcp_server.env]
|
|
18
|
+
THUMBGATE_ENFORCE_ENTITLEMENTS = "1"
|
|
@@ -91,6 +91,12 @@ const {
|
|
|
91
91
|
readTaskOutcomes,
|
|
92
92
|
recordTaskOutcome,
|
|
93
93
|
} = require('../../scripts/task-outcomes');
|
|
94
|
+
const {
|
|
95
|
+
appendReceiptToLedger,
|
|
96
|
+
readReceiptLedger,
|
|
97
|
+
reconcileReceiptChain,
|
|
98
|
+
verifyBrokerReceipt,
|
|
99
|
+
} = require('../../scripts/broker-execution-receipts');
|
|
94
100
|
const {
|
|
95
101
|
listEscalations,
|
|
96
102
|
requestEscalation,
|
|
@@ -328,7 +334,7 @@ const {
|
|
|
328
334
|
finalizeSession: finalizeFeedbackSession,
|
|
329
335
|
} = require('../../scripts/feedback-session');
|
|
330
336
|
|
|
331
|
-
const SERVER_INFO = { name: 'thumbgate-mcp', version: '1.
|
|
337
|
+
const SERVER_INFO = { name: 'thumbgate-mcp', version: '1.37.1' };
|
|
332
338
|
const COMMERCE_CATEGORIES = [
|
|
333
339
|
'product_recommendation',
|
|
334
340
|
'brand_compliance',
|
|
@@ -638,29 +644,37 @@ function buildContextPackResponse(args = {}) {
|
|
|
638
644
|
maxItems: Number(args.maxItems || 8),
|
|
639
645
|
maxChars: Number(args.maxChars || 6000),
|
|
640
646
|
namespaces,
|
|
647
|
+
strategy: args.strategy || null,
|
|
648
|
+
contextEnvelope: args.contextEnvelope || null,
|
|
641
649
|
});
|
|
642
|
-
// Feed outcome-paired action receipts into the pack so an action->outcome
|
|
643
|
-
// history is available alongside lessons/rules. Additive + guarded: a
|
|
644
|
-
// receipt-store failure must never break context pack construction.
|
|
645
650
|
try {
|
|
646
651
|
const receiptEntries = buildReceiptContextEntries(args.query || '', Number(args.maxItems || 8));
|
|
647
652
|
if (Array.isArray(receiptEntries) && receiptEntries.length && Array.isArray(pack.items)) {
|
|
648
653
|
for (const entry of receiptEntries) {
|
|
654
|
+
if (pack.items.length >= pack.maxItems) break;
|
|
655
|
+
const receiptText = entry && entry.text ? String(entry.text) : '';
|
|
656
|
+
const receiptChars = `Action receipt outcome\n${receiptText}`.length;
|
|
657
|
+
if (pack.usedChars + receiptChars > pack.maxChars) continue;
|
|
649
658
|
pack.items.push({
|
|
650
659
|
id: `action-receipt_${entry && entry.score != null ? entry.score : ''}_${pack.items.length}`,
|
|
651
660
|
namespace: 'action-receipts',
|
|
652
661
|
title: 'Action receipt outcome',
|
|
653
|
-
structuredContext: { rawContent:
|
|
662
|
+
structuredContext: { rawContent: receiptText },
|
|
663
|
+
provenance: { source: 'action-receipts', freshness: 'unknown' },
|
|
654
664
|
tags: ['action-receipt', 'outcome-paired'],
|
|
655
665
|
score: entry && typeof entry.score === 'number' ? entry.score : 0,
|
|
656
666
|
});
|
|
667
|
+
pack.usedChars += receiptChars;
|
|
657
668
|
}
|
|
658
669
|
if (!Array.isArray(pack.namespaces)) pack.namespaces = [];
|
|
659
670
|
if (!pack.namespaces.includes('action-receipts')) pack.namespaces.push('action-receipts');
|
|
671
|
+
if (pack.visibility) {
|
|
672
|
+
pack.visibility.itemCount = pack.items.length;
|
|
673
|
+
pack.visibility.remainingCharBudget = Math.max(pack.maxChars - pack.usedChars, 0);
|
|
674
|
+
pack.visibility.visibleTitles = pack.items.slice(0, 5).map((item) => item.title);
|
|
675
|
+
}
|
|
660
676
|
}
|
|
661
|
-
} catch {
|
|
662
|
-
// ignore receipt enrichment failures
|
|
663
|
-
}
|
|
677
|
+
} catch { /* ignore */ }
|
|
664
678
|
return toTextResult(pack);
|
|
665
679
|
}
|
|
666
680
|
|
|
@@ -772,13 +786,23 @@ function buildEstimateUncertaintyResponse(args = {}) {
|
|
|
772
786
|
});
|
|
773
787
|
}
|
|
774
788
|
|
|
775
|
-
async function callTool(name, args = {}) {
|
|
789
|
+
async function callTool(name, args = {}, options = {}) {
|
|
776
790
|
const attemptStartMs = Date.now();
|
|
777
791
|
const activeProfile = getActiveMcpProfile();
|
|
792
|
+
const attribution = {
|
|
793
|
+
clientId: options.clientId || null,
|
|
794
|
+
sessionId: options.sessionId || null,
|
|
795
|
+
agentId: options.agentId || null,
|
|
796
|
+
serverName: options.serverName || 'mcp',
|
|
797
|
+
};
|
|
798
|
+
const trace = (outcome = {}) => recordMcpToolTrace(name, args, {
|
|
799
|
+
...outcome,
|
|
800
|
+
...attribution,
|
|
801
|
+
});
|
|
778
802
|
try {
|
|
779
803
|
assertToolAllowed(name, activeProfile);
|
|
780
804
|
} catch (error) {
|
|
781
|
-
|
|
805
|
+
trace({
|
|
782
806
|
success: false,
|
|
783
807
|
category: 'profile_denied',
|
|
784
808
|
evidence: [error.message],
|
|
@@ -788,7 +812,7 @@ async function callTool(name, args = {}) {
|
|
|
788
812
|
}
|
|
789
813
|
const capability = getToolCapability(name);
|
|
790
814
|
if (!capability.available) {
|
|
791
|
-
|
|
815
|
+
trace({
|
|
792
816
|
success: false,
|
|
793
817
|
category: 'capability',
|
|
794
818
|
evidence: capability.missingModules,
|
|
@@ -806,6 +830,55 @@ async function callTool(name, args = {}) {
|
|
|
806
830
|
throw error;
|
|
807
831
|
}
|
|
808
832
|
|
|
833
|
+
// WriteGuard: pre-action MCP governance (destructive pattern + tier policy).
|
|
834
|
+
// Runs before contract validation so schema gaps cannot bypass interdiction.
|
|
835
|
+
// Covers stdio tools/call and HTTP transport (both route through callTool).
|
|
836
|
+
if (process.env.THUMBGATE_DISABLE_MCP_WRITEGUARD !== '1') {
|
|
837
|
+
const { evaluateMcpCall } = require('../../src/mcp-writeguard');
|
|
838
|
+
const writeGuardReceipt = evaluateMcpCall(
|
|
839
|
+
{
|
|
840
|
+
server: attribution.serverName || 'mcp',
|
|
841
|
+
tool: name,
|
|
842
|
+
parameters: args || {},
|
|
843
|
+
context: {
|
|
844
|
+
user: attribution.agentId || process.env.THUMBGATE_AGENT_ID || process.env.USER || 'operator',
|
|
845
|
+
client: attribution.clientId || 'mcp-client',
|
|
846
|
+
sessionId: attribution.sessionId || process.env.THUMBGATE_SESSION_AGENT || 'default-session',
|
|
847
|
+
},
|
|
848
|
+
},
|
|
849
|
+
{
|
|
850
|
+
// Existing Semantic Firewall / gates own admin escalation UX.
|
|
851
|
+
// Destructive patterns still return decision=blocked.
|
|
852
|
+
allowAdmin: options.allowAdmin !== false
|
|
853
|
+
&& process.env.THUMBGATE_WRITEGUARD_STRICT_ADMIN !== '1',
|
|
854
|
+
requireReviewForPrivileged: options.requireReviewForPrivileged === true
|
|
855
|
+
|| process.env.THUMBGATE_WRITEGUARD_REQUIRE_REVIEW === '1',
|
|
856
|
+
},
|
|
857
|
+
);
|
|
858
|
+
if (writeGuardReceipt.decision === 'blocked' || writeGuardReceipt.decision === 'escalated') {
|
|
859
|
+
const err = new Error(
|
|
860
|
+
`Action blocked by WriteGuard [${writeGuardReceipt.decision}]: ${
|
|
861
|
+
writeGuardReceipt.reasons.join('; ') || writeGuardReceipt.decision
|
|
862
|
+
}`,
|
|
863
|
+
);
|
|
864
|
+
err.errorCategory = 'permission';
|
|
865
|
+
err.code = writeGuardReceipt.decision === 'blocked'
|
|
866
|
+
? 'WRITEGUARD_BLOCKED'
|
|
867
|
+
: 'WRITEGUARD_ESCALATED';
|
|
868
|
+
err.isRetryable = false;
|
|
869
|
+
err.writeGuardReceipt = writeGuardReceipt;
|
|
870
|
+
trace({
|
|
871
|
+
success: false,
|
|
872
|
+
category: 'blocked',
|
|
873
|
+
evidence: writeGuardReceipt.reasons.length > 0
|
|
874
|
+
? writeGuardReceipt.reasons
|
|
875
|
+
: [writeGuardReceipt.decision],
|
|
876
|
+
latencyMs: Date.now() - attemptStartMs,
|
|
877
|
+
});
|
|
878
|
+
throw err;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
|
|
809
882
|
// Validate tool input contract against schema
|
|
810
883
|
const { TOOLS } = require('../../scripts/tool-registry');
|
|
811
884
|
const toolDef = TOOLS.find(t => t.name === name);
|
|
@@ -816,7 +889,7 @@ async function callTool(name, args = {}) {
|
|
|
816
889
|
const err = new Error(`Tool contract violation on '${name}': ${validation.errors.join('; ')}`);
|
|
817
890
|
err.errorCategory = 'contract';
|
|
818
891
|
err.isRetryable = false;
|
|
819
|
-
|
|
892
|
+
trace({
|
|
820
893
|
success: false,
|
|
821
894
|
category: 'contract',
|
|
822
895
|
evidence: validation.errors,
|
|
@@ -826,13 +899,41 @@ async function callTool(name, args = {}) {
|
|
|
826
899
|
}
|
|
827
900
|
}
|
|
828
901
|
|
|
902
|
+
// Model-carried MCP session handles (InfoWorld correlation controls).
|
|
903
|
+
// Authorize whenever the model re-emits a handle, or when
|
|
904
|
+
// THUMBGATE_MCP_HANDLE_REQUIRED=1 forces handles on every tools/call.
|
|
905
|
+
if (process.env.THUMBGATE_DISABLE_MCP_SESSION_HANDLES !== '1') {
|
|
906
|
+
const {
|
|
907
|
+
authorizeMcpToolCall,
|
|
908
|
+
} = require('../../scripts/mcp-session-handles');
|
|
909
|
+
const handleAuth = authorizeMcpToolCall(name, args || {}, {
|
|
910
|
+
principalId: process.env.THUMBGATE_PRINCIPAL_ID || process.env.THUMBGATE_AGENT_ID || null,
|
|
911
|
+
tenantId: process.env.THUMBGATE_TENANT_ID || 'default',
|
|
912
|
+
});
|
|
913
|
+
if (handleAuth && handleAuth.allowed === false) {
|
|
914
|
+
const err = new Error(
|
|
915
|
+
`Action blocked by MCP session handle gate [${handleAuth.code}]: ${handleAuth.reason}`
|
|
916
|
+
);
|
|
917
|
+
err.errorCategory = 'permission';
|
|
918
|
+
err.code = handleAuth.code || 'SESSION_HANDLE_DENIED';
|
|
919
|
+
err.isRetryable = false;
|
|
920
|
+
trace({
|
|
921
|
+
success: false,
|
|
922
|
+
category: 'session_handle',
|
|
923
|
+
evidence: [handleAuth.code, handleAuth.reason],
|
|
924
|
+
latencyMs: Date.now() - attemptStartMs,
|
|
925
|
+
});
|
|
926
|
+
throw err;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
|
|
829
930
|
if (name !== 'workflow_sentinel' && process.env.THUMBGATE_DISABLE_MCP_FIREWALL !== '1') {
|
|
830
931
|
const firewallResult = (await evaluateGatesAsync(name, args)) || evaluateSecretGuard({ tool_name: name, tool_input: args });
|
|
831
932
|
if (firewallResult && firewallResult.decision === 'deny') {
|
|
832
933
|
const err = new Error(`Action blocked by Semantic Firewall: ${firewallResult.message}`);
|
|
833
934
|
err.errorCategory = 'permission';
|
|
834
935
|
err.isRetryable = false;
|
|
835
|
-
|
|
936
|
+
trace({
|
|
836
937
|
success: false,
|
|
837
938
|
category: 'permission',
|
|
838
939
|
evidence: [firewallResult.message],
|
|
@@ -846,7 +947,7 @@ async function callTool(name, args = {}) {
|
|
|
846
947
|
try {
|
|
847
948
|
result = await callToolInner(name, args);
|
|
848
949
|
} catch (err) {
|
|
849
|
-
|
|
950
|
+
trace({
|
|
850
951
|
success: false,
|
|
851
952
|
category: err.errorCategory || 'execution',
|
|
852
953
|
evidence: [err.code || err.message || 'tool execution failed'],
|
|
@@ -860,7 +961,7 @@ async function callTool(name, args = {}) {
|
|
|
860
961
|
const err = new Error(`Structured output contract violation on '${name}': ${outputValidation.errors.join('; ')}`);
|
|
861
962
|
err.errorCategory = 'output_contract';
|
|
862
963
|
err.isRetryable = false;
|
|
863
|
-
|
|
964
|
+
trace({
|
|
864
965
|
success: false,
|
|
865
966
|
category: 'output_contract',
|
|
866
967
|
evidence: outputValidation.errors,
|
|
@@ -868,7 +969,7 @@ async function callTool(name, args = {}) {
|
|
|
868
969
|
});
|
|
869
970
|
throw err;
|
|
870
971
|
}
|
|
871
|
-
|
|
972
|
+
trace({
|
|
872
973
|
success: true,
|
|
873
974
|
category: 'success',
|
|
874
975
|
evidence: [`tool completed in ${latencyMs}ms`],
|
|
@@ -896,17 +997,51 @@ function validateMcpToolOutput(toolDef, result) {
|
|
|
896
997
|
return validateStructuredOutput(result.structuredContent, toolDef.outputSchema);
|
|
897
998
|
}
|
|
898
999
|
|
|
1000
|
+
function resolveWriteRiskTierForTool(name) {
|
|
1001
|
+
try {
|
|
1002
|
+
const { TOOLS, inferWriteRiskTier } = require('../../scripts/tool-registry');
|
|
1003
|
+
const tool = TOOLS.find((candidate) => candidate.name === name);
|
|
1004
|
+
return inferWriteRiskTier(name, tool?.annotations || {});
|
|
1005
|
+
} catch {
|
|
1006
|
+
return null;
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
|
|
899
1010
|
function recordMcpToolTrace(name, args, outcome = {}) {
|
|
900
1011
|
try {
|
|
1012
|
+
const category = outcome.category || 'unknown';
|
|
1013
|
+
// Policy / profile / session denials are WriteGuard "blocked"; execution
|
|
1014
|
+
// and contract failures stay "failed".
|
|
1015
|
+
const blockedCategories = new Set([
|
|
1016
|
+
'blocked',
|
|
1017
|
+
'denied',
|
|
1018
|
+
'permission',
|
|
1019
|
+
'session_handle',
|
|
1020
|
+
'profile_denied',
|
|
1021
|
+
]);
|
|
1022
|
+
const blocked = blockedCategories.has(category) || outcome.blocked === true;
|
|
1023
|
+
const kpiOutcome = blocked
|
|
1024
|
+
? 'blocked'
|
|
1025
|
+
: (outcome.success === true ? 'successful' : 'failed');
|
|
1026
|
+
const writeRiskTier = outcome.writeRiskTier || resolveWriteRiskTierForTool(name);
|
|
1027
|
+
// KPI identity must come only from trusted transport/options metadata
|
|
1028
|
+
// (HTTP OAuth session, explicit callTool options). Never trust tool args —
|
|
1029
|
+
// callers can poison clientId/sessionId via schemas that allow extras.
|
|
901
1030
|
recordToolCall({
|
|
902
1031
|
toolName: name,
|
|
903
|
-
serverName: 'mcp',
|
|
1032
|
+
serverName: outcome.serverName || 'mcp',
|
|
904
1033
|
latencyMs: Number(outcome.latencyMs || 0),
|
|
905
1034
|
success: outcome.success === true,
|
|
906
|
-
|
|
1035
|
+
outcome: kpiOutcome,
|
|
1036
|
+
blocked,
|
|
1037
|
+
agentId: outcome.agentId || process.env.THUMBGATE_AGENT_ID || process.env.THUMBGATE_SESSION_AGENT || 'unknown',
|
|
1038
|
+
clientId: outcome.clientId || null,
|
|
1039
|
+
sessionId: outcome.sessionId || null,
|
|
1040
|
+
writeRiskTier,
|
|
907
1041
|
metadata: {
|
|
908
|
-
category
|
|
1042
|
+
category,
|
|
909
1043
|
traceId: args.traceId || args.taskId || null,
|
|
1044
|
+
writeRiskTier,
|
|
910
1045
|
},
|
|
911
1046
|
});
|
|
912
1047
|
} catch {
|
|
@@ -1260,18 +1395,28 @@ async function callToolInner(name, args) {
|
|
|
1260
1395
|
return toTextResult(formatUnifiedContext(ctx));
|
|
1261
1396
|
}
|
|
1262
1397
|
case 'satisfy_gate': {
|
|
1263
|
-
|
|
1264
|
-
|
|
1398
|
+
// Accept gate | gateId | gate_id — docs/block messages historically said gateId=
|
|
1399
|
+
// while the schema only lists `gate`, which deadlocked agents (2026-08-03).
|
|
1400
|
+
const gateName = args.gate || args.gateId || args.gate_id;
|
|
1401
|
+
if (!gateName) {
|
|
1402
|
+
throw new Error('gate is required (aliases: gateId, gate_id)');
|
|
1265
1403
|
}
|
|
1266
|
-
|
|
1267
|
-
|
|
1404
|
+
// Attribute the override to the MCP surface. Omitting this defaults the
|
|
1405
|
+
// audit record to 'cli', which would misreport every agent-driven unlock.
|
|
1406
|
+
const entry = satisfyCondition(
|
|
1407
|
+
gateName,
|
|
1408
|
+
args.evidence || '',
|
|
1409
|
+
args.structuredReasoning || null,
|
|
1410
|
+
{ source: 'mcp', actor: args.actor || 'agent' },
|
|
1411
|
+
);
|
|
1412
|
+
const result = { satisfied: true, gate: gateName, ...entry };
|
|
1268
1413
|
// Log structured reasoning to audit trail for learning
|
|
1269
1414
|
if (args.structuredReasoning) {
|
|
1270
1415
|
recordAuditEvent({
|
|
1271
1416
|
toolName: 'satisfy_gate',
|
|
1272
|
-
toolInput: { gate:
|
|
1417
|
+
toolInput: { gate: gateName },
|
|
1273
1418
|
decision: 'allow',
|
|
1274
|
-
gateId:
|
|
1419
|
+
gateId: gateName,
|
|
1275
1420
|
message: `Gate satisfied with structured reasoning: ${args.structuredReasoning.conclusion || 'no conclusion'}`,
|
|
1276
1421
|
source: 'structured-reasoning',
|
|
1277
1422
|
});
|
|
@@ -1368,6 +1513,27 @@ async function callToolInner(name, args) {
|
|
|
1368
1513
|
? getReceiptForAction(args.actionId)
|
|
1369
1514
|
: getRecentReceipts(Number(args.limit || 20)),
|
|
1370
1515
|
);
|
|
1516
|
+
case 'verify_broker_execution_receipt':
|
|
1517
|
+
return toTextResult(verifyBrokerReceipt(args.receipt || args));
|
|
1518
|
+
case 'issue_broker_execution_receipt': {
|
|
1519
|
+
// Intentionally NOT on the default MCP allowlist. Even with a host key,
|
|
1520
|
+
// agent-facing sessions must not mint broker signatures. Brokers call the
|
|
1521
|
+
// library/CLI outside the agent tool surface.
|
|
1522
|
+
const error = new Error(
|
|
1523
|
+
'issue_broker_execution_receipt is not available on the agent MCP surface. '
|
|
1524
|
+
+ 'Credential-holding brokers must sign out-of-band via scripts/broker-execution-receipts.js.',
|
|
1525
|
+
);
|
|
1526
|
+
error.code = 'THUMBGATE_BROKER_ISSUE_NOT_ON_AGENT_SURFACE';
|
|
1527
|
+
throw error;
|
|
1528
|
+
}
|
|
1529
|
+
case 'record_broker_execution_receipt': {
|
|
1530
|
+
const receipt = args.receipt || args;
|
|
1531
|
+
return toTextResult(appendReceiptToLedger(receipt));
|
|
1532
|
+
}
|
|
1533
|
+
case 'get_broker_execution_receipts':
|
|
1534
|
+
return toTextResult(readReceiptLedger().slice(-Number(args.limit || 20)));
|
|
1535
|
+
case 'reconcile_broker_receipt_chain':
|
|
1536
|
+
return toTextResult(reconcileReceiptChain());
|
|
1371
1537
|
case 'record_task_outcome':
|
|
1372
1538
|
return toTextResult(recordTaskOutcome(args));
|
|
1373
1539
|
case 'get_task_outcomes': {
|
|
@@ -1597,6 +1763,8 @@ async function callToolInner(name, args) {
|
|
|
1597
1763
|
windowSize: args.windowSize,
|
|
1598
1764
|
perEntryMaxChars: args.perEntryMaxChars,
|
|
1599
1765
|
totalMaxChars: args.totalMaxChars,
|
|
1766
|
+
matryoshkaEmbedding: args.matryoshkaEmbedding !== false,
|
|
1767
|
+
matryoshkaOptions: args.matryoshkaOptions || undefined,
|
|
1600
1768
|
}));
|
|
1601
1769
|
case 'plan_agent_design_governance':
|
|
1602
1770
|
return toTextResult(buildAgentDesignGovernancePlan(args));
|
|
@@ -1815,8 +1983,52 @@ function acquireLock() {
|
|
|
1815
1983
|
return { lockFile, cleanupLock: () => {} };
|
|
1816
1984
|
}
|
|
1817
1985
|
|
|
1986
|
+
/**
|
|
1987
|
+
* Register this MCP session as a first-class agent identity at startup.
|
|
1988
|
+
* Fulfills the registry's "called on MCP server startup" contract: a session
|
|
1989
|
+
* with an attributed id gets that id registered; a session without one gets a
|
|
1990
|
+
* generated id, exported via THUMBGATE_SESSION_AGENT so every audit record and
|
|
1991
|
+
* the gates-engine identity gate can attribute its tool calls. Best-effort by
|
|
1992
|
+
* design — identity bootstrap must never block or crash server start.
|
|
1993
|
+
*/
|
|
1994
|
+
function registerSessionIdentity() {
|
|
1995
|
+
try {
|
|
1996
|
+
const { registerAgent, loadAgentRegistry, getRegistryPath } = require('../../scripts/audit-trail');
|
|
1997
|
+
const { withFileLedgerLock } = require('../../scripts/file-ledger-lock');
|
|
1998
|
+
const envId = process.env.THUMBGATE_SESSION_AGENT || process.env.THUMBGATE_AGENT_ID || null;
|
|
1999
|
+
// Check-then-append runs under the registry ledger lock: concurrent stdio
|
|
2000
|
+
// servers inheriting one session id must not both pass the existence check
|
|
2001
|
+
// and register duplicate rows. A busy lock throws into the catch below —
|
|
2002
|
+
// the session simply starts unregistered and the next startup retries.
|
|
2003
|
+
const finalId = withFileLedgerLock(`${getRegistryPath()}.lock`, () => {
|
|
2004
|
+
const alreadyRegistered = envId
|
|
2005
|
+
? loadAgentRegistry().some((agent) => agent && agent.id === envId)
|
|
2006
|
+
: false;
|
|
2007
|
+
if (alreadyRegistered) return envId;
|
|
2008
|
+
const record = registerAgent({
|
|
2009
|
+
agentId: envId || undefined,
|
|
2010
|
+
source: 'mcp',
|
|
2011
|
+
metadata: { transport: 'stdio', pid: process.pid },
|
|
2012
|
+
});
|
|
2013
|
+
return record && record.id ? record.id : envId;
|
|
2014
|
+
});
|
|
2015
|
+
if (finalId && !process.env.THUMBGATE_SESSION_AGENT) {
|
|
2016
|
+
process.env.THUMBGATE_SESSION_AGENT = finalId;
|
|
2017
|
+
}
|
|
2018
|
+
// MCP tool telemetry (recordMcpToolTrace) attributes via THUMBGATE_AGENT_ID;
|
|
2019
|
+
// without this a generated identity would trace as agentId "unknown".
|
|
2020
|
+
if (finalId && !process.env.THUMBGATE_AGENT_ID) {
|
|
2021
|
+
process.env.THUMBGATE_AGENT_ID = finalId;
|
|
2022
|
+
}
|
|
2023
|
+
return finalId;
|
|
2024
|
+
} catch {
|
|
2025
|
+
return null;
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
|
|
1818
2029
|
function startStdioServer() {
|
|
1819
2030
|
acquireLock();
|
|
2031
|
+
registerSessionIdentity();
|
|
1820
2032
|
|
|
1821
2033
|
process.stdin.resume();
|
|
1822
2034
|
|
|
@@ -1894,6 +2106,7 @@ module.exports = {
|
|
|
1894
2106
|
handleRequest,
|
|
1895
2107
|
callTool,
|
|
1896
2108
|
startStdioServer,
|
|
2109
|
+
registerSessionIdentity,
|
|
1897
2110
|
acquireLock,
|
|
1898
2111
|
toCaptureFeedbackTextResult,
|
|
1899
2112
|
formatCorrectiveActionsReminder,
|