thumbgate 1.27.8 → 1.27.10

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.
Files changed (117) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.well-known/llms.txt +1 -2
  3. package/.well-known/mcp/server-card.json +1 -1
  4. package/README.md +4 -2
  5. package/adapters/claude/.mcp.json +2 -2
  6. package/adapters/mcp/server-stdio.js +1 -1
  7. package/adapters/opencode/opencode.json +1 -1
  8. package/bin/cli.js +259 -78
  9. package/config/gate-templates.json +228 -0
  10. package/config/gates/claim-verification.json +18 -0
  11. package/package.json +14 -21
  12. package/public/blog.html +30 -0
  13. package/public/compare/adopt-ai.html +219 -0
  14. package/public/compare/agentix-labs.html +197 -0
  15. package/public/compare/ai-experience-orchestration.html +216 -0
  16. package/public/compare/anthropic-claude-for-legal.html +260 -0
  17. package/public/compare/anthropic-containment.html +280 -0
  18. package/public/compare/arcade.html +175 -0
  19. package/public/compare/arcjet.html +239 -0
  20. package/public/compare/bumblebee.html +307 -0
  21. package/public/compare/claude-code-hooks.html +294 -0
  22. package/public/compare/databricks-unity-ai-gateway.html +215 -0
  23. package/public/compare/fallow.html +351 -0
  24. package/public/compare/heidi.html +233 -0
  25. package/public/compare/mem0.html +342 -0
  26. package/public/compare/oak-and-sparrow-gatekeeper.html +289 -0
  27. package/public/compare/rein.html +236 -0
  28. package/public/compare/sigmashake.html +256 -0
  29. package/public/compare/speclock.html +342 -0
  30. package/public/compare.html +2 -0
  31. package/public/guides/agent-harness-optimization.html +342 -0
  32. package/public/guides/agentic-web-governance.html +406 -0
  33. package/public/guides/ai-agent-governance-sprint.html +415 -0
  34. package/public/guides/ai-agent-pre-action-approval-gates.html +401 -0
  35. package/public/guides/ai-agent-workflow-migration-checklist.html +392 -0
  36. package/public/guides/ai-deployment-readiness.html +415 -0
  37. package/public/guides/ai-mode-ads-agent-governance.html +401 -0
  38. package/public/guides/ai-search-topical-presence.html +342 -0
  39. package/public/guides/autoresearch-agent-safety.html +342 -0
  40. package/public/guides/background-agent-governance.html +358 -0
  41. package/public/guides/best-tools-stop-ai-agents-breaking-production.html +363 -0
  42. package/public/guides/browser-automation-safety.html +342 -0
  43. package/public/guides/chatgpt-ads-trust.html +353 -0
  44. package/public/guides/claude-code-feedback.html +339 -0
  45. package/public/guides/claude-code-prevent-repeated-mistakes.html +161 -0
  46. package/public/guides/claude-code-skills-guardrails.html +343 -0
  47. package/public/guides/claude-desktop.html +356 -0
  48. package/public/guides/code-knowledge-graph-guardrails.html +365 -0
  49. package/public/guides/codex-cli-guardrails.html +339 -0
  50. package/public/guides/cursor-agent-guardrails.html +339 -0
  51. package/public/guides/cursor-prevent-repeated-mistakes.html +161 -0
  52. package/public/guides/database-agent-safety.html +406 -0
  53. package/public/guides/deepseek-v4-runtime-guardrails.html +346 -0
  54. package/public/guides/developer-machine-supply-chain-guardrails.html +358 -0
  55. package/public/guides/gcp-mcp-guardrails.html +147 -0
  56. package/public/guides/gemini-cli-feedback-memory.html +339 -0
  57. package/public/guides/gpt-5-5-model-evaluation.html +358 -0
  58. package/public/guides/internal-ai-engineering-stack-guardrails.html +348 -0
  59. package/public/guides/long-running-agent-context-management.html +346 -0
  60. package/public/guides/mcp-tool-governance.html +401 -0
  61. package/public/guides/multica-thumbgate-setup.html +134 -0
  62. package/public/guides/native-messaging-host-security.html +342 -0
  63. package/public/guides/policy-engine-pre-action-gates.html +346 -0
  64. package/public/guides/pre-action-checks.html +342 -0
  65. package/public/guides/pretooluse-hooks-vs-advisory-prompt-rules.html +342 -0
  66. package/public/guides/prompt-tricks-to-workflow-rules.html +365 -0
  67. package/public/guides/proxy-pointer-rag-guardrails.html +352 -0
  68. package/public/guides/rag-precision-tuning-guardrails.html +352 -0
  69. package/public/guides/reasoning-compression-guardrails.html +346 -0
  70. package/public/guides/relational-knowledge-ai-recommendations.html +342 -0
  71. package/public/guides/roo-code-alternative-cline.html +339 -0
  72. package/public/guides/semantic-programmatic-seo-guardrails.html +352 -0
  73. package/public/guides/seo-agent-skills-guardrails.html +344 -0
  74. package/public/guides/stop-repeated-ai-agent-mistakes.html +342 -0
  75. package/public/index.html +192 -50
  76. package/public/learn/ac-dc-runtime-enforcement.html +277 -0
  77. package/public/learn/agent-harness-pattern.html +181 -0
  78. package/public/learn/agent-identity-connector-governance.html +146 -0
  79. package/public/learn/agent-swarms-shared-gates.html +173 -0
  80. package/public/learn/agentic-enterprise-context-brain.html +117 -0
  81. package/public/learn/agentic-os-team-governance.html +146 -0
  82. package/public/learn/ai-agent-governance.html +158 -0
  83. package/public/learn/ai-agent-persistent-memory.html +211 -0
  84. package/public/learn/anthropomorphic-claim-gates.html +180 -0
  85. package/public/learn/background-agent-control-layer.html +184 -0
  86. package/public/learn/claude-code-goal-with-rubrics.html +205 -0
  87. package/public/learn/codex-role-plugins-need-governance.html +125 -0
  88. package/public/learn/cost-aware-agent-gate-routing.html +173 -0
  89. package/public/learn/databricks-unity-ai-gateway-runtime-governance.html +157 -0
  90. package/public/learn/deterministic-agent-workflows.html +185 -0
  91. package/public/learn/feedback-loop-vs-decision-layer.html +283 -0
  92. package/public/learn/from-prototype-to-production.html +223 -0
  93. package/public/learn/learn.css +51 -0
  94. package/public/learn/mcp-pre-action-checks-explained.html +172 -0
  95. package/public/learn/pretix-stripe-connect-marketplaces.html +161 -0
  96. package/public/learn/regulated-agent-execution-boundary.html +196 -0
  97. package/public/learn/spec-driven-development.html +168 -0
  98. package/public/learn/stop-ai-agent-force-push.html +134 -0
  99. package/public/learn/vibe-coding-safety-net.html +142 -0
  100. package/public/learn.html +34 -50
  101. package/public/numbers.html +2 -2
  102. package/public/pro.html +6 -6
  103. package/scripts/cli-schema.js +10 -22
  104. package/scripts/dashboard-chat.js +1 -2
  105. package/scripts/document-intake.js +49 -1
  106. package/scripts/gemini-embedding-policy.js +1 -2
  107. package/scripts/hook-stop-anti-claim.js +103 -42
  108. package/scripts/hosted-config.js +12 -0
  109. package/scripts/plausible-domain-config.js +1 -3
  110. package/scripts/reddit-browser-notification-watch.js +230 -0
  111. package/scripts/seo-gsd.js +0 -239
  112. package/scripts/tool-registry.js +2 -2
  113. package/scripts/vector-store.js +0 -44
  114. package/scripts/workspace-evolver.js +2 -62
  115. package/src/api/server.js +126 -335
  116. package/adapters/policy-engine/ethicore-guardian-client.js +0 -68
  117. package/adapters/policy-engine/thumbgate-policy-engine-adapter.js +0 -260
@@ -1,68 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- const DEFAULT_ENDPOINT = 'https://api.oraclestechnologies.com/v1/guardian/analyze';
5
-
6
- function requireApiKey(env = process.env) {
7
- const key = env.ETHICORE_API_KEY || env.GUARDIAN_API_KEY || env.ORACLES_GUARDIAN_API_KEY;
8
- if (!key) {
9
- throw new Error('ETHICORE_API_KEY env var is required');
10
- }
11
- return key;
12
- }
13
-
14
- async function analyzeText(text, options = {}) {
15
- if (!String(text || '').trim()) {
16
- throw new Error('analyzeText requires text');
17
- }
18
-
19
- const env = options.env || process.env;
20
- const endpoint = options.endpoint || env.ETHICORE_GUARDIAN_ENDPOINT || DEFAULT_ENDPOINT;
21
- const apiKey = options.apiKey || requireApiKey(env);
22
- const fetchImpl = options.fetch || fetch;
23
-
24
- const response = await fetchImpl(endpoint, {
25
- method: 'POST',
26
- headers: {
27
- Authorization: `Bearer ${apiKey}`,
28
- 'Content-Type': 'application/json',
29
- },
30
- body: JSON.stringify({ text }),
31
- });
32
-
33
- const bodyText = await response.text();
34
- let body = bodyText;
35
- try {
36
- body = bodyText ? JSON.parse(bodyText) : {};
37
- } catch {
38
- // Keep non-JSON body for diagnostics.
39
- }
40
-
41
- if (!response.ok) {
42
- throw new Error(`Ethicore Guardian API ${response.status}: ${typeof body === 'string' ? body : JSON.stringify(body)}`);
43
- }
44
-
45
- return body;
46
- }
47
-
48
- function createEthicorePolicyCheck(options = {}) {
49
- return async function ethicorePolicyCheck(action = {}) {
50
- const toolText = [
51
- action.toolName,
52
- action.actionType,
53
- action.command,
54
- action.path,
55
- action.url,
56
- action.input ? JSON.stringify(action.input) : '',
57
- ].filter(Boolean).join('\n');
58
-
59
- return analyzeText(toolText || JSON.stringify(action), options);
60
- };
61
- }
62
-
63
- module.exports = {
64
- DEFAULT_ENDPOINT,
65
- analyzeText,
66
- createEthicorePolicyCheck,
67
- requireApiKey,
68
- };
@@ -1,260 +0,0 @@
1
- #!/usr/bin/env node
2
- 'use strict';
3
-
4
- const { normalizeProviderAction } = require('../../scripts/provider-action-normalizer');
5
-
6
- const BLOCK_DECISIONS = new Set([
7
- 'block',
8
- 'blocked',
9
- 'deny',
10
- 'denied',
11
- 'disallow',
12
- 'disallowed',
13
- 'fail',
14
- 'failed',
15
- 'forbid',
16
- 'forbidden',
17
- 'reject',
18
- 'rejected',
19
- 'unsafe',
20
- 'violation',
21
- ]);
22
-
23
- const REVIEW_DECISIONS = new Set([
24
- 'approval',
25
- 'approval-required',
26
- 'approval_required',
27
- 'approve',
28
- 'human-review',
29
- 'human_review',
30
- 'manual-review',
31
- 'manual_review',
32
- 'review',
33
- 'requires-approval',
34
- 'requires_approval',
35
- 'requires-review',
36
- 'requires_review',
37
- ]);
38
-
39
- const ALLOW_DECISIONS = new Set([
40
- 'accept',
41
- 'accepted',
42
- 'allow',
43
- 'allowed',
44
- 'ok',
45
- 'pass',
46
- 'passed',
47
- 'permit',
48
- 'permitted',
49
- 'safe',
50
- ]);
51
-
52
- function asObject(value) {
53
- return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
54
- }
55
-
56
- function asArray(value) {
57
- return Array.isArray(value) ? value : [];
58
- }
59
-
60
- function firstString(...values) {
61
- for (const value of values) {
62
- const text = String(value || '').trim();
63
- if (text) return text;
64
- }
65
- return '';
66
- }
67
-
68
- function normalizeDecisionToken(value) {
69
- return String(value || '')
70
- .trim()
71
- .toLowerCase()
72
- .replace(/\s+/g, '-');
73
- }
74
-
75
- function normalizeEvidence(value) {
76
- const direct = asArray(value.evidence);
77
- const citations = asArray(value.citations);
78
- const violations = asArray(value.violations);
79
- const reasons = asArray(value.reasons);
80
- const reasoning = asArray(value.reasoning);
81
- const threatTypes = asArray(value.threat_types || value.threatTypes)
82
- .map((threatType) => ({
83
- code: String(threatType || '').trim(),
84
- message: `Threat type: ${String(threatType || '').trim()}`,
85
- source: 'guardian',
86
- severity: firstString(value.threat_level, value.threatLevel),
87
- }));
88
- return [...direct, ...citations, ...violations, ...reasons, ...reasoning, ...threatTypes]
89
- .map((entry) => {
90
- if (typeof entry === 'string') return { text: entry };
91
- const object = asObject(entry);
92
- if (!Object.keys(object).length) return null;
93
- return {
94
- id: firstString(object.id, object.ruleId, object.rule_id, object.code),
95
- text: firstString(object.text, object.reason, object.message, object.description, object.title),
96
- source: firstString(object.source, object.provider, object.policy),
97
- severity: firstString(object.severity, object.level),
98
- raw: object,
99
- };
100
- })
101
- .filter(Boolean);
102
- }
103
-
104
- function extractPolicyDecision(input = {}) {
105
- const event = asObject(input);
106
- for (const candidate of [
107
- event.policyDecision,
108
- event.policy_decision,
109
- event.guardrailResult,
110
- event.guardrail_result,
111
- event.result,
112
- ]) {
113
- const object = asObject(candidate);
114
- if (Object.keys(object).length) return object;
115
- }
116
- return event;
117
- }
118
-
119
- function classifyPolicyDecision(input = {}) {
120
- const value = extractPolicyDecision(input);
121
- const token = normalizeDecisionToken(firstString(
122
- value.decision,
123
- value.action,
124
- value.status,
125
- value.result,
126
- value.verdict,
127
- value.outcome,
128
- value.effect,
129
- value.recommended_action,
130
- value.recommendedAction,
131
- ));
132
-
133
- if (
134
- value.allowed === false
135
- || value.is_safe === false
136
- || value.isSafe === false
137
- || value.accepted === false
138
- || value.blocked === true
139
- || value.denied === true
140
- || BLOCK_DECISIONS.has(token)
141
- ) {
142
- return 'block';
143
- }
144
- if (
145
- value.requiresApproval === true
146
- || value.requires_approval === true
147
- || value.reviewRequired === true
148
- || value.review_required === true
149
- || REVIEW_DECISIONS.has(token)
150
- ) {
151
- return 'approval_required';
152
- }
153
- if (
154
- value.allowed === true
155
- || value.is_safe === true
156
- || value.isSafe === true
157
- || value.accepted === true
158
- || ALLOW_DECISIONS.has(token)
159
- ) {
160
- return 'allow';
161
- }
162
- return 'unknown';
163
- }
164
-
165
- function normalizePolicyDecision(input = {}, options = {}) {
166
- const value = extractPolicyDecision(input);
167
- const decision = classifyPolicyDecision(value);
168
- const source = firstString(
169
- options.source,
170
- value.source,
171
- value.provider,
172
- value.engine,
173
- value.policyEngine,
174
- value.policy_engine,
175
- 'policy-engine'
176
- );
177
- const reason = firstString(
178
- value.reason,
179
- value.message,
180
- value.explanation,
181
- value.summary,
182
- asArray(value.reasoning).join('; '),
183
- asArray(value.reasons).join('; '),
184
- decision === 'unknown' ? 'Policy engine returned an unknown decision; approval required before execution.' : ''
185
- );
186
-
187
- return {
188
- allowed: decision === 'allow',
189
- blocked: decision === 'block',
190
- approvalRequired: decision === 'approval_required' || decision === 'unknown',
191
- decision,
192
- reason,
193
- source,
194
- confidence: Number.isFinite(Number(value.confidence)) ? Number(value.confidence) : null,
195
- policyId: firstString(value.policyId, value.policy_id, value.ruleId, value.rule_id, value.id),
196
- severity: firstString(value.severity, value.level, value.threat_level, value.threatLevel),
197
- score: Number.isFinite(Number(value.score))
198
- ? Number(value.score)
199
- : (Number.isFinite(Number(value.threat_score)) ? Number(value.threat_score) : null),
200
- evidence: normalizeEvidence(value),
201
- raw: value,
202
- };
203
- }
204
-
205
- function normalizePolicyAction(input = {}) {
206
- const event = asObject(input);
207
- return {
208
- ...normalizeProviderAction({
209
- ...event,
210
- provider: firstString(event.provider, event.agentRuntime, event.runtime, 'policy-engine'),
211
- toolName: firstString(event.toolName, event.tool_name, event.name),
212
- input: asObject(event.toolInput || event.input || event.arguments || event.args),
213
- }),
214
- policyContext: asObject(event.policyContext || event.policy_context),
215
- };
216
- }
217
-
218
- function createPolicyEngineGuard({
219
- policyCheck,
220
- executeTool,
221
- gateCheck,
222
- onDecision,
223
- source = 'policy-engine',
224
- } = {}) {
225
- if (typeof policyCheck !== 'function') {
226
- throw new TypeError('createPolicyEngineGuard requires a policyCheck function');
227
- }
228
- if (typeof executeTool !== 'function') {
229
- throw new TypeError('createPolicyEngineGuard requires an executeTool function');
230
- }
231
-
232
- return async function guardedPolicyTool(input = {}) {
233
- const normalizedAction = normalizePolicyAction(input);
234
- const policyDecision = normalizePolicyDecision(await policyCheck(normalizedAction), { source });
235
- const gateDecision = typeof gateCheck === 'function'
236
- ? normalizePolicyDecision(await gateCheck({ normalizedAction, policyDecision }), { source: 'thumbgate' })
237
- : null;
238
- const effectiveDecision = gateDecision && !gateDecision.allowed ? gateDecision : policyDecision;
239
-
240
- if (typeof onDecision === 'function') {
241
- await onDecision({ normalizedAction, policyDecision, gateDecision, effectiveDecision });
242
- }
243
-
244
- if (!effectiveDecision.allowed) {
245
- const error = new Error(effectiveDecision.reason || 'ThumbGate blocked this action before execution.');
246
- error.code = effectiveDecision.approvalRequired ? 'THUMBGATE_APPROVAL_REQUIRED' : 'THUMBGATE_BLOCKED';
247
- error.thumbgate = { normalizedAction, policyDecision, gateDecision, effectiveDecision };
248
- throw error;
249
- }
250
-
251
- return executeTool(input, { normalizedAction, policyDecision, gateDecision, effectiveDecision });
252
- };
253
- }
254
-
255
- module.exports = {
256
- createPolicyEngineGuard,
257
- extractPolicyDecision,
258
- normalizePolicyAction,
259
- normalizePolicyDecision,
260
- };