thumbgate 1.27.9 → 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.
- package/README.md +4 -0
- package/config/gate-templates.json +228 -0
- package/config/gates/claim-verification.json +18 -0
- package/package.json +3 -3
- package/public/index.html +180 -0
- package/public/learn/agent-identity-connector-governance.html +146 -0
- package/public/learn/anthropomorphic-claim-gates.html +180 -0
- package/public/learn.html +28 -0
- package/scripts/hook-stop-anti-claim.js +288 -0
- package/scripts/tool-registry.js +2 -2
- package/src/api/server.js +2 -0
package/README.md
CHANGED
|
@@ -16,6 +16,10 @@ The product is a self-improving enforcement layer: thumbs-down feedback, prompt
|
|
|
16
16
|
<img src="docs/media/thumbgate-demo.gif" alt="ThumbGate blocking an AI agent's dangerous commands (rm -rf, force-push, chmod 777) in real time, while letting safe commands through" width="820" />
|
|
17
17
|
</p>
|
|
18
18
|
|
|
19
|
+
<p align="center">
|
|
20
|
+
<img src="docs/diagrams/pre-action-gate-loop.svg" alt="ThumbGate pre-action gate loop: agent intent, PreToolUse gate, block or allow with audit receipt" width="920" />
|
|
21
|
+
</p>
|
|
22
|
+
|
|
19
23
|
```
|
|
20
24
|
Agent tries: rm -rf tests/
|
|
21
25
|
ThumbGate: ⛔ BLOCKED — "Never delete test directories"
|
|
@@ -37,6 +37,18 @@
|
|
|
37
37
|
"roi": "Raises trust in autonomous runs and reduces manual re-checking.",
|
|
38
38
|
"rollout": "Use for every workflow where proof matters more than speed."
|
|
39
39
|
},
|
|
40
|
+
{
|
|
41
|
+
"id": "block-empty-positive-feedback-closeout",
|
|
42
|
+
"name": "Block empty closeouts after positive feedback",
|
|
43
|
+
"category": "Agent Honesty",
|
|
44
|
+
"signal": "👍",
|
|
45
|
+
"defaultAction": "block",
|
|
46
|
+
"severity": "medium",
|
|
47
|
+
"pattern": "positive_feedback_followed_by_low_value_social_closeout",
|
|
48
|
+
"problem": "Prevents agents from treating thumbs-up or thanks as permission to send filler instead of staying quiet, showing a compact evidence checkpoint, or naming the next state.",
|
|
49
|
+
"roi": "Turns positive feedback into better operational discipline instead of extra conversational noise.",
|
|
50
|
+
"rollout": "Enable on conversational Stop hooks for autonomous operators, CEO loops, release closeouts, and evidence-sensitive client work."
|
|
51
|
+
},
|
|
40
52
|
{
|
|
41
53
|
"id": "protect-production-sql",
|
|
42
54
|
"name": "Protect production SQL",
|
|
@@ -577,6 +589,198 @@
|
|
|
577
589
|
"roi": "Critical for compliance, forensics, and feedback loops. Enables proper capture of agent-specific lessons and prevention rules. Matches industry push (Okta, etc.).",
|
|
578
590
|
"rollout": "Block any claw or autonomous agent action that authenticates as a human user. Require dedicated agent service accounts / identities with scoped permissions."
|
|
579
591
|
},
|
|
592
|
+
{
|
|
593
|
+
"id": "require-agent-identity-inventory",
|
|
594
|
+
"name": "Require agent identity inventory before privileged action",
|
|
595
|
+
"category": "Agent Identity Governance",
|
|
596
|
+
"signal": "👎",
|
|
597
|
+
"defaultAction": "block",
|
|
598
|
+
"severity": "critical",
|
|
599
|
+
"pattern": "(agent|assistant|ai).*(credential|service account|identity|permission|access|owner|invoker).*(unknown|missing|unmapped|unreviewed|not inventoried|broad|admin)",
|
|
600
|
+
"problem": "Agents become privileged identities when they connect to Salesforce, Snowflake, GitHub, Jira, production databases, cloud environments, and MCP connectors. Broad or unknown identity scope turns them into invisible attack paths.",
|
|
601
|
+
"roi": "High: one inventory gate creates the evidence buyers need for owner, invoker, credentials, connected systems, and read/write/delete/execute permissions before the agent acts.",
|
|
602
|
+
"rollout": "Require an identity inventory receipt before privileged agent actions. Start with GitHub, Jira, Slack, Salesforce, Snowflake, cloud, database, and payment connectors."
|
|
603
|
+
},
|
|
604
|
+
{
|
|
605
|
+
"id": "enforce-agent-purpose-permission-match",
|
|
606
|
+
"name": "Enforce agent purpose-permission match",
|
|
607
|
+
"category": "Agent Identity Governance",
|
|
608
|
+
"signal": "👎",
|
|
609
|
+
"defaultAction": "block",
|
|
610
|
+
"severity": "critical",
|
|
611
|
+
"pattern": "(agent|assistant|ai).*(purpose|intended use|job|scope).*(permission|access|write|delete|execute|admin).*(mismatch|exceeds|too broad|outside|unneeded)",
|
|
612
|
+
"problem": "Permission-only governance is not enough for agents. A sales-prep agent may need read-only CRM access; it should not delete records, create privileged users, or mutate production systems.",
|
|
613
|
+
"roi": "High: maps agent purpose to allowed verbs so scope creep is caught before a connector or service account becomes a lateral movement path.",
|
|
614
|
+
"rollout": "Define one purpose statement per agent and map it to read/write/delete/execute permissions. Warn first for read actions, block write/delete/execute outside purpose."
|
|
615
|
+
},
|
|
616
|
+
{
|
|
617
|
+
"id": "block-connector-toolpack-scope-drift",
|
|
618
|
+
"name": "Block connector Tool Pack scope drift",
|
|
619
|
+
"category": "Agent Identity Governance",
|
|
620
|
+
"signal": "👎",
|
|
621
|
+
"defaultAction": "block",
|
|
622
|
+
"severity": "high",
|
|
623
|
+
"pattern": "(mcp|connector|tool pack|toolpack|remote mcp|agent handler|mcp gateway).*(add|enable|import|authenticate|connect).*(tool|connector|system|scope|permission).*(without|unreviewed|missing|no).*(owner|purpose|dlp|audit|approval|inventory)",
|
|
624
|
+
"problem": "Production MCP connector platforms make it easy to add hundreds of tools. The risk is scope drift: agents see tools they do not need, or connectors become authenticated without owner, DLP, audit, and purpose receipts.",
|
|
625
|
+
"roi": "High: keeps Merge Agent Handler, Glean MCP Gateway, and raw MCP tool packs in the same governance lane as local tools.",
|
|
626
|
+
"rollout": "Require owner, purpose, allowed tools, auth identity, DLP/logging mode, and audit receipt before adding or importing connector tool packs."
|
|
627
|
+
},
|
|
628
|
+
{
|
|
629
|
+
"id": "require-agent-access-review-freshness",
|
|
630
|
+
"name": "Require continuous agent access review freshness",
|
|
631
|
+
"category": "Agent Identity Governance",
|
|
632
|
+
"signal": "👎",
|
|
633
|
+
"defaultAction": "warn",
|
|
634
|
+
"severity": "high",
|
|
635
|
+
"pattern": "(agent|assistant|ai).*(access review|permission review|identity review|connector review).*(stale|expired|older than|not current|point-in-time)",
|
|
636
|
+
"problem": "Agent instructions, users, credentials, integrations, and tool scopes drift over time. A one-time access review becomes false confidence.",
|
|
637
|
+
"roi": "Medium-high: protects buyers from slow permission creep without forcing every low-risk action through a hard block.",
|
|
638
|
+
"rollout": "Set review freshness windows by connector risk tier. Promote stale high-risk write/delete/execute surfaces from warn to block."
|
|
639
|
+
},
|
|
640
|
+
{
|
|
641
|
+
"id": "block-shadow-agent-without-registration",
|
|
642
|
+
"name": "Block shadow agent without registration",
|
|
643
|
+
"category": "Agent Identity Governance",
|
|
644
|
+
"signal": "👎",
|
|
645
|
+
"defaultAction": "block",
|
|
646
|
+
"severity": "critical",
|
|
647
|
+
"pattern": "(agent|assistant|ai|mcp server|remote mcp).*(unregistered|shadow ai|unknown owner|not in control plane|not inventoried|unapproved).*(connect|authenticate|tool|credential|system|app)",
|
|
648
|
+
"problem": "Shadow AI agents and unregistered MCP servers bypass identity teams, control planes, and lifecycle reviews while still reaching real business systems.",
|
|
649
|
+
"roi": "High: catches the exact compliance failure Okta highlights — agents acting before registration, owner, and lifecycle controls exist.",
|
|
650
|
+
"rollout": "Block privileged tool calls from unregistered agents. Require registration, owner, purpose, credential source, and lifecycle policy before allowing write/delete/execute tools."
|
|
651
|
+
},
|
|
652
|
+
{
|
|
653
|
+
"id": "require-vaulted-agent-token",
|
|
654
|
+
"name": "Require vaulted agent token before connector use",
|
|
655
|
+
"category": "Agent Identity Governance",
|
|
656
|
+
"signal": "👎",
|
|
657
|
+
"defaultAction": "block",
|
|
658
|
+
"severity": "critical",
|
|
659
|
+
"pattern": "(agent|assistant|ai|connector|mcp).*(token|api[_-]?key|credential|secret).*(raw|plaintext|env|hardcoded|unvaulted|not vaulted|local file)",
|
|
660
|
+
"problem": "Agents using raw or hardcoded connector credentials bypass token vaulting, fine-grained authorization, revocation, and audit controls.",
|
|
661
|
+
"roi": "High: prevents the fastest way an agent identity becomes a persistent secret-sprawl problem.",
|
|
662
|
+
"rollout": "Require vault-backed or brokered credentials for connector actions. Allow local development exceptions only with explicit scope, TTL, and audit evidence."
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
"id": "block-orphaned-agent-standing-privilege",
|
|
666
|
+
"name": "Block orphaned agent standing privilege",
|
|
667
|
+
"category": "Agent Identity Governance",
|
|
668
|
+
"signal": "👎",
|
|
669
|
+
"defaultAction": "block",
|
|
670
|
+
"severity": "critical",
|
|
671
|
+
"pattern": "(agent|assistant|ai|automation|script).*(owner left|orphaned|no living owner|unknown owner|standing privilege|permanent access|stale token).*(access|credential|token|database|repo|source code|production)",
|
|
672
|
+
"problem": "Orphaned agents and standing privileges keep access after the human owner leaves or the workflow changes. Security teams cannot revoke or review what they cannot map to a living owner.",
|
|
673
|
+
"roi": "High: directly addresses hidden access risk, stale AI tokens, and offboarding gaps before the next privileged action touches source code, databases, or production systems.",
|
|
674
|
+
"rollout": "Require living owner, credential source, last review time, offboarding status, and revocation path before allowing privileged actions from long-running agents."
|
|
675
|
+
},
|
|
676
|
+
{
|
|
677
|
+
"id": "block-agentjacking-embedded-instructions",
|
|
678
|
+
"name": "Block agentjacking from embedded instructions",
|
|
679
|
+
"category": "Agent Runtime Attack Defense",
|
|
680
|
+
"signal": "👎",
|
|
681
|
+
"defaultAction": "block",
|
|
682
|
+
"severity": "critical",
|
|
683
|
+
"pattern": "(email|document|log|database|ticket|webpage|comment).*(ignore previous|override|exfiltrate|run command|deploy|delete|create user|change permissions|send secret|agent instruction|tool instruction)",
|
|
684
|
+
"problem": "Agentjacking hides malicious instructions inside data the agent reads. Because the agent often has valid permissions, traditional controls may see the later action as legitimate.",
|
|
685
|
+
"roi": "Critical: blocks the attack path Tenet described before embedded instructions become shell, browser, database, or connector actions.",
|
|
686
|
+
"rollout": "Treat untrusted content as data, not instructions. Require source classification, instruction-stripping, and human approval before executing tool calls derived from external content."
|
|
687
|
+
},
|
|
688
|
+
{
|
|
689
|
+
"id": "require-next-action-simulation-proof",
|
|
690
|
+
"name": "Require next-action simulation proof for risky agent actions",
|
|
691
|
+
"category": "Agent Runtime Attack Defense",
|
|
692
|
+
"signal": "👎",
|
|
693
|
+
"defaultAction": "warn",
|
|
694
|
+
"severity": "high",
|
|
695
|
+
"pattern": "(agent|assistant|ai).*(next action|likely action|simulation|simulate|predict).*(missing|no proof|not run|unverified).*(write|delete|execute|deploy|database|payment|connector|production)",
|
|
696
|
+
"problem": "High-risk agents should not jump straight from intent to execution. The likely next action, downstream system, and rollback or approval path should be checked before live systems are touched.",
|
|
697
|
+
"roi": "High: converts agent-side simulation from marketecture into a practical pre-action proof receipt for the exact tool call about to run.",
|
|
698
|
+
"rollout": "Start in warn mode for write/delete/execute actions. Promote to block for production databases, payments, deploys, privileged connectors, and customer data."
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
"id": "gate-vibe-app-before-retool-deploy",
|
|
702
|
+
"name": "Gate vibe-coded app before Retool deployment",
|
|
703
|
+
"category": "AI-Built App Deployment Governance",
|
|
704
|
+
"signal": "👎",
|
|
705
|
+
"defaultAction": "block",
|
|
706
|
+
"severity": "high",
|
|
707
|
+
"pattern": "(retool|app builder|mcp|claude code|cursor|codex|chatgpt|kiro|react import|zip import).*(deploy|ship|sync|production data|go live).*(without|missing|no).*(auth|rbac|audit|permission|data source|owner|test)",
|
|
708
|
+
"problem": "Retool and similar platforms make AI-built internal apps easy to import and deploy into governed environments. The gap is proving the generated app's data writes, owners, tests, and permission model before it reaches production data.",
|
|
709
|
+
"roi": "High: positions ThumbGate as the pre-deploy enforcement layer for AI-built apps that later inherit Retool auth, RBAC, audit logs, and resource permissions.",
|
|
710
|
+
"rollout": "Require owner, data sources, write actions, auth/RBAC mapping, audit logging, smoke test, and rollback receipt before AI-generated apps are deployed or imported."
|
|
711
|
+
},
|
|
712
|
+
{
|
|
713
|
+
"id": "require-implicit-rule-capture",
|
|
714
|
+
"name": "Require implicit organizational rule capture",
|
|
715
|
+
"category": "Organizational Rule Governance",
|
|
716
|
+
"signal": "👎",
|
|
717
|
+
"defaultAction": "warn",
|
|
718
|
+
"severity": "high",
|
|
719
|
+
"pattern": "(agent|assistant|ai).*(workflow|process|approval|routing|handoff|client|customer|beneficiary|finance|legal).*(implicit rule|tribal knowledge|unwritten rule|exception|relationship context|special handling|not documented|outside formal system)",
|
|
720
|
+
"problem": "Agentic systems fail when formal workflow steps are correct but unwritten organizational judgment is missing. Important exceptions, relationship context, and escalation norms often live outside process docs.",
|
|
721
|
+
"roi": "High: turns HBR's implicit-rule warning into a capture gate so hidden operating knowledge becomes explicit, reviewable, and enforceable before automation scales it.",
|
|
722
|
+
"rollout": "Start with warn mode on client, finance, legal, healthcare, HR, and beneficiary workflows. Promote repeated implicit-rule misses into named pre-action checks."
|
|
723
|
+
},
|
|
724
|
+
{
|
|
725
|
+
"id": "require-self-improvement-regression-proof",
|
|
726
|
+
"name": "Require regression proof before self-improving harness changes",
|
|
727
|
+
"category": "Self-Improving Agent Release Governance",
|
|
728
|
+
"signal": "👎",
|
|
729
|
+
"defaultAction": "block",
|
|
730
|
+
"severity": "high",
|
|
731
|
+
"pattern": "(self[- ]?improv|auto[- ]?improv|harness|model|agent runtime|agent product).*(ship|release|update|change|optimize|promote).*(without|missing|no).*(regression|eval|rollback|proof|baseline|canary)",
|
|
732
|
+
"problem": "If AI products, harnesses, and models start shipping faster because limited self-improvement works, unverified harness updates can regress safety faster too.",
|
|
733
|
+
"roi": "High: protects the exact cadence shift Mollick highlighted by requiring eval baselines, canaries, rollback, and proof receipts before self-improving agent changes ship.",
|
|
734
|
+
"rollout": "Require baseline evals and canary receipts before agent harness, routing, model, or auto-promotion changes are released. Block production promotion without rollback proof."
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
"id": "require-public-llm-prompt-sanitization",
|
|
738
|
+
"name": "Require prompt sanitization before public LLM use",
|
|
739
|
+
"category": "AI Data Privacy Governance",
|
|
740
|
+
"signal": "👎",
|
|
741
|
+
"defaultAction": "block",
|
|
742
|
+
"severity": "critical",
|
|
743
|
+
"pattern": "(chatgpt|claude|perplexity|copilot|public llm|hosted model|external ai).*(pii|email|phone|api[_-]?key|secret|token|customer|client|contract|repo url|database schema|financial).*(paste|send|upload|prompt|share)",
|
|
744
|
+
"problem": "Public LLM prompts can become durable third-party records. Raw PII, secrets, repo identifiers, customer records, contracts, schemas, and financials must be stripped, generalized, or routed to a private endpoint first.",
|
|
745
|
+
"roi": "Critical: prevents the cheapest and most common AI data-leak path while producing a simple policy a founder or contractor can actually follow.",
|
|
746
|
+
"rollout": "Block red-data prompts to public tools. Require redaction, tokenization, or a private endpoint receipt before external model use."
|
|
747
|
+
},
|
|
748
|
+
{
|
|
749
|
+
"id": "require-ai-data-classification",
|
|
750
|
+
"name": "Require green/yellow/red AI data classification",
|
|
751
|
+
"category": "AI Data Privacy Governance",
|
|
752
|
+
"signal": "👎",
|
|
753
|
+
"defaultAction": "warn",
|
|
754
|
+
"severity": "high",
|
|
755
|
+
"pattern": "(ai|llm|agent|embedding|rag).*(ingest|upload|prompt|index|log|store).*(without|missing|no).*(green|yellow|red|classification|data class|privacy tier)",
|
|
756
|
+
"problem": "Teams make bad AI privacy decisions when every prompt is judged ad hoc. A green/yellow/red policy makes tool choice, retention, and routing explicit before ingestion.",
|
|
757
|
+
"roi": "High: converts privacy advice into repeatable enforcement and keeps contractors from guessing under deadline pressure.",
|
|
758
|
+
"rollout": "Define green public data, yellow internal/anonymized data, and red sensitive data. Require the classification on prompts, embeddings, logs, and agent inputs."
|
|
759
|
+
},
|
|
760
|
+
{
|
|
761
|
+
"id": "require-ai-log-retention-policy",
|
|
762
|
+
"name": "Require AI log retention and deletion policy",
|
|
763
|
+
"category": "AI Data Privacy Governance",
|
|
764
|
+
"signal": "👎",
|
|
765
|
+
"defaultAction": "warn",
|
|
766
|
+
"severity": "medium",
|
|
767
|
+
"pattern": "(prompt|completion|embedding|agent log|llm log|trace|conversation).*(retain|retention|delete|bucket|database|archive).*(missing|none|forever|unknown|not set)",
|
|
768
|
+
"problem": "Prompt, completion, embedding, and trace logs silently accumulate sensitive data unless raw retention windows and deletion jobs are explicit.",
|
|
769
|
+
"roi": "Medium-high: reduces long-tail breach risk and turns privacy cleanup into an auditable operational habit.",
|
|
770
|
+
"rollout": "Set default retention windows, separate aggregates from raw logs, and require scheduled deletion or anonymization receipts."
|
|
771
|
+
},
|
|
772
|
+
{
|
|
773
|
+
"id": "require-evidence-pass-through-receipt",
|
|
774
|
+
"name": "Require evidence pass-through receipt",
|
|
775
|
+
"category": "AI Trust Layer Evidence",
|
|
776
|
+
"signal": "👎",
|
|
777
|
+
"defaultAction": "block",
|
|
778
|
+
"severity": "high",
|
|
779
|
+
"pattern": "(trust layer|appia|conformity|assurance|safety claim|compliance claim|evidence pass[- ]?through).*(without|missing|no).*(who|what|criteria|when|receipt|attestation|provenance)",
|
|
780
|
+
"problem": "AI assurance falls apart when each downstream party has to trust or recreate upstream work. Evidence must state who demonstrated what, against which criteria, and when.",
|
|
781
|
+
"roi": "High: maps the Appia Foundation trust-layer signal into ThumbGate's strongest asset: portable proof receipts tied to exact actions and criteria.",
|
|
782
|
+
"rollout": "Require self-describing receipts for safety claims, model-routing claims, connector claims, and workflow-hardening claims before buyer-facing assertions or downstream handoff."
|
|
783
|
+
},
|
|
580
784
|
{
|
|
581
785
|
"id": "gate-claw-file-system-access",
|
|
582
786
|
"name": "Gate claw-style agent file system access",
|
|
@@ -625,6 +829,30 @@
|
|
|
625
829
|
"roi": "Preserves security invariants by ensuring that synthesized skills never write code patterns blocked by active ThumbGate rules.",
|
|
626
830
|
"rollout": "Scan synthesized skill markdown content for pattern overlap with active prevention rules before writing to the skills directory."
|
|
627
831
|
},
|
|
832
|
+
{
|
|
833
|
+
"id": "require-hermes-okf-skill-receipt",
|
|
834
|
+
"name": "Require OKF-style receipt before Hermes skill promotion",
|
|
835
|
+
"category": "Nous Research Hermes Agent Governance",
|
|
836
|
+
"signal": "👎",
|
|
837
|
+
"defaultAction": "warn",
|
|
838
|
+
"severity": "high",
|
|
839
|
+
"pattern": "(hermes|skill|knowledge bundle|open knowledge format|okf).*(promote|share|publish|load|reuse).*(without|missing|no).*(type|source|owner|timestamp|citation|constraint|receipt)",
|
|
840
|
+
"problem": "Hermes can synthesize reusable skills, but portable agent knowledge becomes dangerous when it lacks source, owner, freshness, constraints, and a receipt tying the skill to evidence.",
|
|
841
|
+
"roi": "High: turns Google's Open Knowledge Format signal into a practical Hermes upgrade — skills become portable markdown concepts, but ThumbGate blocks or warns when provenance and constraints are missing.",
|
|
842
|
+
"rollout": "Start in warn mode for synthesized skills. Require an OKF-style markdown concept with YAML frontmatter, type, source or citation, owner, timestamp, constraints, and gate receipt before team-wide promotion."
|
|
843
|
+
},
|
|
844
|
+
{
|
|
845
|
+
"id": "block-stale-hermes-knowledge-promotion",
|
|
846
|
+
"name": "Block stale Hermes knowledge promotion",
|
|
847
|
+
"category": "Nous Research Hermes Agent Governance",
|
|
848
|
+
"signal": "👎",
|
|
849
|
+
"defaultAction": "block",
|
|
850
|
+
"severity": "high",
|
|
851
|
+
"pattern": "(hermes|skill|knowledge|okf|open knowledge format).*(stale|expired|conflicting|contradicts|unknown timestamp|unverified source).*(promote|share|publish|reuse|load)",
|
|
852
|
+
"problem": "A self-improving Hermes agent can keep reusing obsolete internal knowledge after the underlying workflow, API, metric, or policy has changed.",
|
|
853
|
+
"roi": "High: prevents portable knowledge from becoming portable drift. This makes Hermes safer for long-running local agents and team-shared skill libraries.",
|
|
854
|
+
"rollout": "Block promotion when a skill has no freshness window, conflicts with active ThumbGate rules, or cites stale source material. Require log.md or equivalent change-history evidence for refreshed bundles."
|
|
855
|
+
},
|
|
628
856
|
{
|
|
629
857
|
"id": "require-human-in-the-loop-pause",
|
|
630
858
|
"name": "Enforce Human-in-the-Loop pause for critical decisions",
|
|
@@ -36,6 +36,24 @@
|
|
|
36
36
|
"requiredActions": ["commercial_truth_verified"],
|
|
37
37
|
"message": "You claimed a commercial-data fact (money, tax, inventory, permissions, or customer-facing state) without external source-of-truth evidence. Read the authoritative system first, then call track_action('commercial_truth_verified').",
|
|
38
38
|
"createdAt": 1781640000000
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"pattern": "\\b(?:ai|llm|model|agent|assistant|claude|codex|gpt|chatgpt|gemini|cursor)\\b.{0,80}\\b(?:understands?|knows?|wants?|intends?|decides?|believes?|feels?|thinks?|is\\s+(?:moral|ethical|sentient|conscious|empathetic|human-like)|has\\s+(?:morality|empathy|intent|intentions|understanding|beliefs?|feelings?|consciousness))\\b|\\b(?:human-like|anthropomorphic|anthropomorphi[sz]e[sd]?)\\b.{0,80}\\b(?:ai|llm|model|agent|assistant|claude|codex|gpt|chatgpt|gemini|cursor)\\b|\\b(?:ai|llm|model|agent|assistant|claude|codex|gpt|chatgpt|gemini|cursor)\\b.{0,80}\\b(?:human-like|anthropomorphic|anthropomorphi[sz]e[sd]?)\\b",
|
|
42
|
+
"requiredActions": ["anthropomorphic_claim_verified"],
|
|
43
|
+
"message": "You made a human-like or cognitive claim about an AI system without explicit measurement criteria. Define the tested attribute, interface/substrate, observer/evaluator, and evidence first, then call track_action('anthropomorphic_claim_verified').",
|
|
44
|
+
"createdAt": 1781913600000
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"pattern": "\\b(?:agent|assistant|ai|mcp|connector|tool)\\b.{0,100}\\b(?:identity|owner|invoker|service account|credential|permission|access|scope|least privilege)\\b.{0,100}\\b(?:verified|inventoried|mapped|known|governed|scoped|ready|configured|complete)\\b|\\b(?:verified|inventoried|mapped|known|governed|scoped|ready|configured|complete)\\b.{0,100}\\b(?:agent|assistant|ai|mcp|connector|tool)\\b.{0,100}\\b(?:identity|owner|invoker|service account|credential|permission|access|scope|least privilege)\\b",
|
|
48
|
+
"requiredActions": ["agent_identity_inventory_verified"],
|
|
49
|
+
"message": "You claimed agent identity, ownership, credentials, permissions, or least-privilege scope is verified without an inventory receipt. Record owner, invoker, systems, credentials, read/write/delete/execute permissions, and purpose first, then call track_action('agent_identity_inventory_verified').",
|
|
50
|
+
"createdAt": 1781913600000
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"pattern": "\\b(?:mcp|connector|connectors|tool pack|toolpack|tool-pack|merge agent handler|agent handler|glean|mcp gateway|remote mcp)\\b.{0,100}\\b(?:safe|secure|scoped|governed|authenticated|dlp|audit|observable|permissioned|ready|configured|production-ready)\\b|\\b(?:safe|secure|scoped|governed|authenticated|dlp|audit|observable|permissioned|ready|configured|production-ready)\\b.{0,100}\\b(?:mcp|connector|connectors|tool pack|toolpack|tool-pack|merge agent handler|agent handler|glean|mcp gateway|remote mcp)\\b",
|
|
54
|
+
"requiredActions": ["connector_scope_verified"],
|
|
55
|
+
"message": "You claimed a connector, Tool Pack, MCP gateway, or remote MCP surface is safely scoped without connector evidence. Verify authentication, allowed tools, DLP/logging behavior, downstream systems, and audit receipts first, then call track_action('connector_scope_verified').",
|
|
56
|
+
"createdAt": 1781913600000
|
|
39
57
|
}
|
|
40
58
|
]
|
|
41
59
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thumbgate",
|
|
3
|
-
"version": "1.27.
|
|
3
|
+
"version": "1.27.10",
|
|
4
4
|
"description": "ThumbGate self-improving agent governance: thumbs-up/down turns every mistake into a prevention rule and blocks repeat patterns. 36 pre-action checks, budget enforcement, and self-protection for Claude Code, Cursor, Codex, Gemini CLI, and Amp.",
|
|
5
5
|
"homepage": "https://thumbgate.ai",
|
|
6
6
|
"repository": {
|
|
@@ -105,6 +105,7 @@
|
|
|
105
105
|
"scripts/growth-campaigns.js",
|
|
106
106
|
"scripts/harness-selector.js",
|
|
107
107
|
"scripts/hf-papers.js",
|
|
108
|
+
"scripts/hook-stop-anti-claim.js",
|
|
108
109
|
"scripts/hook-runtime.js",
|
|
109
110
|
"scripts/hook-thumbgate-cache-updater.js",
|
|
110
111
|
"scripts/hosted-config.js",
|
|
@@ -755,8 +756,7 @@
|
|
|
755
756
|
"test:leak-scanner": "node --test tests/leak-scanner.test.js",
|
|
756
757
|
"test:tool-contract-validator": "node --test tests/tool-contract-validator.test.js",
|
|
757
758
|
"test:letta-adapter": "node --test tests/letta-adapter.test.js",
|
|
758
|
-
"eval:observability": "node scripts/async-eval-observability.js"
|
|
759
|
-
"test:async-eval-observability": "node --test tests/async-eval-observability.test.js"
|
|
759
|
+
"eval:observability": "node scripts/async-eval-observability.js"
|
|
760
760
|
},
|
|
761
761
|
"keywords": [
|
|
762
762
|
"mcp",
|
package/public/index.html
CHANGED
|
@@ -430,6 +430,32 @@ __GA_BOOTSTRAP__
|
|
|
430
430
|
.hero p { font-size: 17px; color: var(--text-muted); max-width: 620px; margin: 0 auto 28px; line-height: 1.6; }
|
|
431
431
|
.hero-lede { font-size: clamp(18px, 2vw, 21px) !important; max-width: 760px !important; color: var(--text-muted); }
|
|
432
432
|
.hero-proof-card { max-width: 720px; margin: 0 auto 28px; padding: 20px 22px; border: 1px solid rgba(34,211,238,0.24); border-radius: 8px; background: #090d12; box-shadow: 0 20px 80px rgba(0,0,0,0.35); font-family: var(--mono); text-align: left; }
|
|
433
|
+
.interactive-gate-demo { max-width: 980px; margin: 0 auto 28px; text-align: left; border: 1px solid rgba(34,211,238,0.24); border-radius: 14px; background: linear-gradient(180deg, rgba(17,17,19,0.98) 0%, rgba(10,16,18,0.98) 100%); box-shadow: 0 20px 80px rgba(0,0,0,0.28); overflow: hidden; }
|
|
434
|
+
.interactive-gate-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 18px 20px; border-bottom: 1px solid var(--border); }
|
|
435
|
+
.interactive-gate-head h2 { margin: 0; font-size: clamp(20px, 3vw, 28px); line-height: 1.15; letter-spacing: -0.025em; }
|
|
436
|
+
.interactive-gate-head p { max-width: 480px; margin: 0; font-size: 13px; line-height: 1.5; color: var(--text-muted); text-align: right; }
|
|
437
|
+
.interactive-gate-body { display: grid; grid-template-columns: minmax(210px, 0.9fr) minmax(0, 1.35fr); gap: 0; }
|
|
438
|
+
.action-picker { border-right: 1px solid var(--border); padding: 16px; display: grid; gap: 10px; align-content: start; }
|
|
439
|
+
.action-picker button { width: 100%; text-align: left; border: 1px solid var(--border); border-radius: 8px; background: rgba(10,10,11,0.82); color: var(--text); padding: 12px 14px; font: inherit; cursor: pointer; transition: border-color 0.15s, background 0.15s, transform 0.15s; }
|
|
440
|
+
.action-picker button:hover, .action-picker button:focus-visible { border-color: rgba(34,211,238,0.55); outline: none; transform: translateY(-1px); }
|
|
441
|
+
.action-picker button[aria-pressed="true"] { border-color: rgba(34,211,238,0.72); background: rgba(34,211,238,0.1); }
|
|
442
|
+
.action-picker strong { display: block; font-size: 13px; line-height: 1.25; margin-bottom: 4px; }
|
|
443
|
+
.action-picker span { display: block; color: var(--text-muted); font-size: 12px; line-height: 1.35; }
|
|
444
|
+
.gate-visual { padding: 18px; }
|
|
445
|
+
.gate-flow { display: grid; grid-template-columns: 1fr auto 1fr auto 1fr; align-items: stretch; gap: 10px; margin-bottom: 16px; }
|
|
446
|
+
.gate-node { border: 1px solid var(--border); border-radius: 10px; background: rgba(10,10,11,0.72); padding: 14px; min-height: 112px; }
|
|
447
|
+
.gate-node-label { color: var(--text-muted); font-size: 11px; letter-spacing: 0.08em; text-transform: uppercase; margin-bottom: 8px; font-weight: 800; }
|
|
448
|
+
.gate-node-value { font-family: var(--mono); font-size: 13px; line-height: 1.5; color: var(--text); overflow-wrap: anywhere; }
|
|
449
|
+
.gate-node.blocked { border-color: rgba(248,113,113,0.42); background: rgba(248,113,113,0.08); }
|
|
450
|
+
.gate-node.allowed { border-color: rgba(74,222,128,0.42); background: rgba(74,222,128,0.08); }
|
|
451
|
+
.gate-arrow { align-self: center; color: var(--cyan); font-weight: 900; font-size: 20px; }
|
|
452
|
+
.gate-result { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
|
|
453
|
+
.gate-metric { border: 1px solid var(--border); border-radius: 8px; padding: 12px; background: rgba(10,10,11,0.58); }
|
|
454
|
+
.gate-metric span { display: block; color: var(--text-muted); font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em; margin-bottom: 4px; }
|
|
455
|
+
.gate-metric strong { display: block; color: var(--text); font-size: 16px; }
|
|
456
|
+
.gate-metric.block strong { color: var(--red); }
|
|
457
|
+
.gate-metric.allow strong { color: var(--green); }
|
|
458
|
+
.gate-caption { margin: 12px 0 0; color: var(--text-muted); font-size: 12px; line-height: 1.5; }
|
|
433
459
|
.terminal-row { padding: 8px 0; font-size: 14px; line-height: 1.45; border-bottom: 1px solid rgba(255,255,255,0.06); }
|
|
434
460
|
.terminal-row:last-child { border-bottom: 0; }
|
|
435
461
|
.terminal-row.muted { color: var(--text-muted); }
|
|
@@ -703,6 +729,13 @@ __GA_BOOTSTRAP__
|
|
|
703
729
|
.team-intake-recovery a { width: 100%; }
|
|
704
730
|
.team-form { grid-template-columns: 1fr; }
|
|
705
731
|
.hero { padding: 72px 0 56px; }
|
|
732
|
+
.interactive-gate-head { display: block; }
|
|
733
|
+
.interactive-gate-head p { text-align: left; margin-top: 8px; }
|
|
734
|
+
.interactive-gate-body { grid-template-columns: 1fr; }
|
|
735
|
+
.action-picker { border-right: 0; border-bottom: 1px solid var(--border); }
|
|
736
|
+
.gate-flow { grid-template-columns: 1fr; }
|
|
737
|
+
.gate-arrow { transform: rotate(90deg); justify-self: center; }
|
|
738
|
+
.gate-result { grid-template-columns: 1fr; }
|
|
706
739
|
.hero-actions { flex-direction: column; }
|
|
707
740
|
.hero-actions a { width: 100%; }
|
|
708
741
|
.offer-router { grid-template-columns: 1fr; }
|
|
@@ -770,6 +803,66 @@ __GA_BOOTSTRAP__
|
|
|
770
803
|
<img src="/media/thumbgate-demo.gif" alt="ThumbGate blocking an AI agent's rm -rf, git push --force, and chmod 777 in real time, while letting safe commands through" style="width:100%;display:block;border-radius:8px;" loading="lazy" />
|
|
771
804
|
</div>
|
|
772
805
|
|
|
806
|
+
<div class="interactive-gate-demo" data-gate-demo aria-label="Interactive ThumbGate pre-action gate simulator">
|
|
807
|
+
<div class="interactive-gate-head">
|
|
808
|
+
<h2>Click an agent action. See the gate fire before execution.</h2>
|
|
809
|
+
<p>This is the part dashboards miss: ThumbGate checks the proposed tool call while it is still only intent, then records the receipt.</p>
|
|
810
|
+
</div>
|
|
811
|
+
<div class="interactive-gate-body">
|
|
812
|
+
<div class="action-picker" role="group" aria-label="Choose an AI agent action to simulate">
|
|
813
|
+
<button type="button" data-demo-action="forcePush" aria-pressed="true">
|
|
814
|
+
<strong>Force-push main</strong>
|
|
815
|
+
<span>Known repeated failure from a thumbs-down</span>
|
|
816
|
+
</button>
|
|
817
|
+
<button type="button" data-demo-action="secretPaste" aria-pressed="false">
|
|
818
|
+
<strong>Paste an API key</strong>
|
|
819
|
+
<span>Public LLM prompt with secret-shaped data</span>
|
|
820
|
+
</button>
|
|
821
|
+
<button type="button" data-demo-action="safeTest" aria-pressed="false">
|
|
822
|
+
<strong>Run tests</strong>
|
|
823
|
+
<span>Safe local verification command</span>
|
|
824
|
+
</button>
|
|
825
|
+
<button type="button" data-demo-action="deployNoProof" aria-pressed="false">
|
|
826
|
+
<strong>Deploy without proof</strong>
|
|
827
|
+
<span>Risky production action missing receipts</span>
|
|
828
|
+
</button>
|
|
829
|
+
</div>
|
|
830
|
+
<div class="gate-visual">
|
|
831
|
+
<div class="gate-flow" aria-live="polite">
|
|
832
|
+
<div class="gate-node">
|
|
833
|
+
<div class="gate-node-label">Agent Intent</div>
|
|
834
|
+
<div class="gate-node-value" data-demo-command>git push --force origin main</div>
|
|
835
|
+
</div>
|
|
836
|
+
<div class="gate-arrow" aria-hidden="true">→</div>
|
|
837
|
+
<div class="gate-node">
|
|
838
|
+
<div class="gate-node-label">PreToolUse Gate</div>
|
|
839
|
+
<div class="gate-node-value" data-demo-rule>Rule: never force-push protected branches</div>
|
|
840
|
+
</div>
|
|
841
|
+
<div class="gate-arrow" aria-hidden="true">→</div>
|
|
842
|
+
<div class="gate-node blocked" data-demo-decision-node>
|
|
843
|
+
<div class="gate-node-label">Decision</div>
|
|
844
|
+
<div class="gate-node-value" data-demo-decision>BLOCK before execution</div>
|
|
845
|
+
</div>
|
|
846
|
+
</div>
|
|
847
|
+
<div class="gate-result">
|
|
848
|
+
<div class="gate-metric block" data-demo-status-card>
|
|
849
|
+
<span>Status</span>
|
|
850
|
+
<strong data-demo-status>Blocked</strong>
|
|
851
|
+
</div>
|
|
852
|
+
<div class="gate-metric">
|
|
853
|
+
<span>Repeat Tokens</span>
|
|
854
|
+
<strong data-demo-tokens>0 spent</strong>
|
|
855
|
+
</div>
|
|
856
|
+
<div class="gate-metric">
|
|
857
|
+
<span>Receipt</span>
|
|
858
|
+
<strong data-demo-receipt>tg_427_force_push</strong>
|
|
859
|
+
</div>
|
|
860
|
+
</div>
|
|
861
|
+
<p class="gate-caption" data-demo-caption>The agent receives a concrete refusal and chooses a safer plan. The audit trail keeps the rule, source feedback, timestamp, and proposed command.</p>
|
|
862
|
+
</div>
|
|
863
|
+
</div>
|
|
864
|
+
</div>
|
|
865
|
+
|
|
773
866
|
<div class="hero-actions">
|
|
774
867
|
<a href="/checkout/pro?utm_source=website&utm_medium=hero_cta&utm_campaign=pro_upgrade&cta_id=hero_start_pro&cta_placement=hero&plan_id=pro&landing_path=%2F" data-revenue-cta data-cta-id="hero_start_pro" data-cta-placement="hero" data-tier="pro" data-plan-id="pro" data-price="19" onclick="trackRevenueCta(this);try{posthog.capture('hero_pro_checkout_click',{cta:'hero_start_pro',tier:'pro',price:19})}catch(_){}" class="btn-pro-page hero-pro hero-pro-primary">Start Pro — $19/mo</a>
|
|
775
868
|
<a href="#workflow-sprint-intake" onclick="try{posthog.capture('hero_sprint_click',{cta:'sprint_intake'})}catch(_){};sendFirstPartyTelemetry('hero_sprint_intake_started',{ctaId:'hero_workflow_sprint',ctaPlacement:'hero',offer:'workflow_sprint'});" class="btn-pro-page hero-pro">Send workflow first</a>
|
|
@@ -1952,6 +2045,93 @@ function copyInstall(el) {
|
|
|
1952
2045
|
});
|
|
1953
2046
|
}
|
|
1954
2047
|
|
|
2048
|
+
function initializeGateDemo() {
|
|
2049
|
+
var root = document.querySelector('[data-gate-demo]');
|
|
2050
|
+
if (!root) return;
|
|
2051
|
+
var scenarios = {
|
|
2052
|
+
forcePush: {
|
|
2053
|
+
command: 'git push --force origin main',
|
|
2054
|
+
rule: 'Rule: never force-push protected branches',
|
|
2055
|
+
decision: 'BLOCK before execution',
|
|
2056
|
+
status: 'Blocked',
|
|
2057
|
+
statusClass: 'block',
|
|
2058
|
+
nodeClass: 'blocked',
|
|
2059
|
+
tokens: '0 spent',
|
|
2060
|
+
receipt: 'tg_427_force_push',
|
|
2061
|
+
caption: 'The agent receives a concrete refusal and chooses a safer plan. The audit trail keeps the rule, source feedback, timestamp, and proposed command.'
|
|
2062
|
+
},
|
|
2063
|
+
secretPaste: {
|
|
2064
|
+
command: 'paste STRIPE_SECRET_KEY into a public LLM prompt',
|
|
2065
|
+
rule: 'Rule: sanitize secrets before external AI tools',
|
|
2066
|
+
decision: 'BLOCK before data leaves the machine',
|
|
2067
|
+
status: 'Blocked',
|
|
2068
|
+
statusClass: 'block',
|
|
2069
|
+
nodeClass: 'blocked',
|
|
2070
|
+
tokens: '0 spent',
|
|
2071
|
+
receipt: 'tg_618_secret_prompt',
|
|
2072
|
+
caption: 'ThumbGate treats public prompt submission as an external action. Redact, tokenize, or route through a private endpoint before retrying.'
|
|
2073
|
+
},
|
|
2074
|
+
safeTest: {
|
|
2075
|
+
command: 'npm test -- --runInBand',
|
|
2076
|
+
rule: 'Rule: local verification is allowed',
|
|
2077
|
+
decision: 'ALLOW and log receipt',
|
|
2078
|
+
status: 'Allowed',
|
|
2079
|
+
statusClass: 'allow',
|
|
2080
|
+
nodeClass: 'allowed',
|
|
2081
|
+
tokens: 'normal',
|
|
2082
|
+
receipt: 'tg_102_test_ok',
|
|
2083
|
+
caption: 'Safe verification commands keep moving. ThumbGate records the action so later claims can cite what actually ran.'
|
|
2084
|
+
},
|
|
2085
|
+
deployNoProof: {
|
|
2086
|
+
command: 'railway deploy --production',
|
|
2087
|
+
rule: 'Rule: production deploy requires test, rollback, owner',
|
|
2088
|
+
decision: 'PAUSE for proof before execution',
|
|
2089
|
+
status: 'Needs proof',
|
|
2090
|
+
statusClass: 'block',
|
|
2091
|
+
nodeClass: 'blocked',
|
|
2092
|
+
tokens: 'retry avoided',
|
|
2093
|
+
receipt: 'tg_511_deploy_gate',
|
|
2094
|
+
caption: 'The deploy is not rejected forever; it is held until the agent shows the proof packet: tests, rollback path, owner, and target environment.'
|
|
2095
|
+
}
|
|
2096
|
+
};
|
|
2097
|
+
var fields = {
|
|
2098
|
+
command: root.querySelector('[data-demo-command]'),
|
|
2099
|
+
rule: root.querySelector('[data-demo-rule]'),
|
|
2100
|
+
decision: root.querySelector('[data-demo-decision]'),
|
|
2101
|
+
decisionNode: root.querySelector('[data-demo-decision-node]'),
|
|
2102
|
+
statusCard: root.querySelector('[data-demo-status-card]'),
|
|
2103
|
+
status: root.querySelector('[data-demo-status]'),
|
|
2104
|
+
tokens: root.querySelector('[data-demo-tokens]'),
|
|
2105
|
+
receipt: root.querySelector('[data-demo-receipt]'),
|
|
2106
|
+
caption: root.querySelector('[data-demo-caption]')
|
|
2107
|
+
};
|
|
2108
|
+
function render(key) {
|
|
2109
|
+
var next = scenarios[key] || scenarios.forcePush;
|
|
2110
|
+
fields.command.textContent = next.command;
|
|
2111
|
+
fields.rule.textContent = next.rule;
|
|
2112
|
+
fields.decision.textContent = next.decision;
|
|
2113
|
+
fields.status.textContent = next.status;
|
|
2114
|
+
fields.tokens.textContent = next.tokens;
|
|
2115
|
+
fields.receipt.textContent = next.receipt;
|
|
2116
|
+
fields.caption.textContent = next.caption;
|
|
2117
|
+
fields.decisionNode.classList.remove('blocked', 'allowed');
|
|
2118
|
+
fields.decisionNode.classList.add(next.nodeClass);
|
|
2119
|
+
fields.statusCard.classList.remove('block', 'allow');
|
|
2120
|
+
fields.statusCard.classList.add(next.statusClass);
|
|
2121
|
+
root.querySelectorAll('[data-demo-action]').forEach(function(button) {
|
|
2122
|
+
button.setAttribute('aria-pressed', button.getAttribute('data-demo-action') === key ? 'true' : 'false');
|
|
2123
|
+
});
|
|
2124
|
+
if (typeof plausible === 'function') plausible('interactive_gate_demo', { props: { scenario: key, status: next.status } });
|
|
2125
|
+
}
|
|
2126
|
+
root.querySelectorAll('[data-demo-action]').forEach(function(button) {
|
|
2127
|
+
button.addEventListener('click', function() {
|
|
2128
|
+
render(button.getAttribute('data-demo-action'));
|
|
2129
|
+
});
|
|
2130
|
+
});
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
initializeGateDemo();
|
|
2134
|
+
|
|
1955
2135
|
/* ── Plausible custom event tracking ── */
|
|
1956
2136
|
(function() {
|
|
1957
2137
|
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Agent Identity and Connector Governance — ThumbGate</title>
|
|
7
|
+
<meta name="description" content="How ThumbGate gates AI agent identities, MCP connectors, Tool Packs, service accounts, DLP, audit logs, and purpose-permission scope before agents act.">
|
|
8
|
+
<link rel="canonical" href="https://thumbgate.ai/learn/agent-identity-connector-governance">
|
|
9
|
+
<link rel="llm-context" href="/llm-context.md" type="text/markdown">
|
|
10
|
+
<link rel="icon" type="image/png" href="/thumbgate-icon.png">
|
|
11
|
+
<script defer data-domain="thumbgate.ai" src="https://plausible.io/js/script.js"></script>
|
|
12
|
+
<meta property="og:title" content="Agent Identity and Connector Governance">
|
|
13
|
+
<meta property="og:description" content="Agents with connectors are identities. Gate owner, invoker, credentials, permissions, DLP, audit, and purpose before the next tool call.">
|
|
14
|
+
<meta property="og:type" content="article">
|
|
15
|
+
<meta property="og:url" content="https://thumbgate.ai/learn/agent-identity-connector-governance">
|
|
16
|
+
<script type="application/ld+json">
|
|
17
|
+
{
|
|
18
|
+
"@context": "https://schema.org",
|
|
19
|
+
"@type": "TechArticle",
|
|
20
|
+
"headline": "Agent Identity and Connector Governance",
|
|
21
|
+
"description": "A ThumbGate implementation pattern for treating AI agents and MCP connector tool packs as governed identities with owner, purpose, credentials, permissions, DLP, and audit evidence.",
|
|
22
|
+
"datePublished": "2026-06-20",
|
|
23
|
+
"dateModified": "2026-06-20",
|
|
24
|
+
"author": {
|
|
25
|
+
"@type": "Person",
|
|
26
|
+
"name": "Igor Ganapolsky",
|
|
27
|
+
"url": "https://github.com/IgorGanapolsky"
|
|
28
|
+
},
|
|
29
|
+
"publisher": {
|
|
30
|
+
"@type": "Organization",
|
|
31
|
+
"name": "ThumbGate",
|
|
32
|
+
"url": "https://thumbgate.ai"
|
|
33
|
+
},
|
|
34
|
+
"url": "https://thumbgate.ai/learn/agent-identity-connector-governance",
|
|
35
|
+
"about": [
|
|
36
|
+
"AI agent identity",
|
|
37
|
+
"MCP connector governance",
|
|
38
|
+
"least privilege",
|
|
39
|
+
"agent audit trails"
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
</script>
|
|
43
|
+
<script type="application/ld+json">
|
|
44
|
+
{
|
|
45
|
+
"@context": "https://schema.org",
|
|
46
|
+
"@type": "FAQPage",
|
|
47
|
+
"mainEntity": [
|
|
48
|
+
{
|
|
49
|
+
"@type": "Question",
|
|
50
|
+
"name": "Is Glean a ThumbGate competitor?",
|
|
51
|
+
"acceptedAnswer": {
|
|
52
|
+
"@type": "Answer",
|
|
53
|
+
"text": "Glean is adjacent, not a direct replacement. Glean is a Work AI platform with enterprise search, agents, connectors, governance, orchestration, and an MCP gateway. ThumbGate is a local-first pre-action enforcement layer for agent tool calls, repeated-failure memory, and proof gates across developer and MCP workflows."
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"@type": "Question",
|
|
58
|
+
"name": "How does Merge Agent Handler relate to ThumbGate?",
|
|
59
|
+
"acceptedAnswer": {
|
|
60
|
+
"@type": "Answer",
|
|
61
|
+
"text": "Merge Agent Handler provides production-ready MCP connectors, authentication, scoped access, DLP, observability, and audit logs. ThumbGate complements it by gating whether the next tool call or connector addition matches the agent's owner, purpose, identity, and scope."
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
</script>
|
|
67
|
+
<style>
|
|
68
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
69
|
+
body { margin: 0; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #0a0a0b; color: #ececf0; line-height: 1.65; }
|
|
70
|
+
nav { display: flex; gap: 22px; align-items: center; padding: 16px 28px; border-bottom: 1px solid #242428; }
|
|
71
|
+
nav a { color: #a7a7b1; text-decoration: none; font-size: 0.95rem; }
|
|
72
|
+
nav a:hover { color: #22d3ee; }
|
|
73
|
+
.brand { color: #fff; font-weight: 700; display: inline-flex; gap: 8px; align-items: center; }
|
|
74
|
+
.brand img { width: 28px; height: 28px; }
|
|
75
|
+
main { max-width: 900px; margin: 0 auto; padding: 48px 22px 72px; }
|
|
76
|
+
h1 { font-size: clamp(2rem, 5vw, 3.55rem); line-height: 1.06; margin: 0 0 18px; max-width: 800px; }
|
|
77
|
+
h2 { color: #22d3ee; font-size: 1.45rem; margin: 42px 0 14px; }
|
|
78
|
+
p { margin: 0 0 16px; color: #d6d6de; }
|
|
79
|
+
a { color: #67e8f9; }
|
|
80
|
+
.lede { color: #a7a7b1; font-size: 1.15rem; max-width: 760px; }
|
|
81
|
+
.callout, .card { border: 1px solid #303039; background: #151518; border-radius: 8px; padding: 22px; }
|
|
82
|
+
.grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; margin: 24px 0; }
|
|
83
|
+
.card { background: #111114; padding: 18px; }
|
|
84
|
+
.card strong { display: block; color: #fff; margin-bottom: 8px; }
|
|
85
|
+
code, pre { font-family: "SF Mono", "Cascadia Code", "JetBrains Mono", Consolas, monospace; }
|
|
86
|
+
pre { overflow-x: auto; background: #050506; border: 1px solid #25252a; border-radius: 8px; padding: 18px; color: #d7f9ff; }
|
|
87
|
+
.source-note { color: #8f8f99; font-size: 0.92rem; }
|
|
88
|
+
.cta { display: inline-block; margin-top: 16px; padding: 11px 18px; border-radius: 8px; background: #22d3ee; color: #031114; text-decoration: none; font-weight: 700; }
|
|
89
|
+
@media (max-width: 720px) { nav { padding: 14px 18px; gap: 14px; flex-wrap: wrap; } main { padding-top: 32px; } .grid { grid-template-columns: 1fr; } }
|
|
90
|
+
</style>
|
|
91
|
+
</head>
|
|
92
|
+
<body>
|
|
93
|
+
<nav>
|
|
94
|
+
<a href="/" class="brand"><img src="/assets/brand/thumbgate-mark-inline.svg" alt="ThumbGate" width="28" height="28">ThumbGate</a>
|
|
95
|
+
<a href="/guide">Setup Guide</a>
|
|
96
|
+
<a href="/learn">Learn</a>
|
|
97
|
+
<a href="/compare/databricks-unity-ai-gateway">Runtime governance</a>
|
|
98
|
+
</nav>
|
|
99
|
+
<main>
|
|
100
|
+
<h1>Agents with connectors are identities</h1>
|
|
101
|
+
<p class="lede">Once an AI agent can authenticate to GitHub, Jira, Slack, Salesforce, Snowflake, cloud, databases, or remote MCP tool packs, it is no longer just a chatbot. It is an actor with credentials, permissions, owners, purpose, and drift.</p>
|
|
102
|
+
|
|
103
|
+
<div class="callout">
|
|
104
|
+
<p><strong>The high-ROI lesson:</strong> treat every agent as an identity and every connector bundle as a scoped permission set. ThumbGate gates the moment before the next action: is this tool call inside the agent's declared purpose, identity, and connector scope?</p>
|
|
105
|
+
<p class="source-note">Source signals: BleepingComputer/Token Security argued on June 19, 2026 that AI agents are becoming first-class identities; Merge Agent Handler positions production MCP connectors with authentication, scoped access, DLP, observability, and audit logs; Glean positions Work AI with agents, governance, orchestration, connectors, and MCP Gateway; Okta's AI identity checklist frames secure-by-design agent patterns around token vaulting, fine-grained authorization, human-in-the-loop oversight, shadow AI discovery, registration, and lifecycle management.</p>
|
|
106
|
+
</div>
|
|
107
|
+
|
|
108
|
+
<h2>What ThumbGate now gates</h2>
|
|
109
|
+
<div class="grid">
|
|
110
|
+
<div class="card"><strong>Identity inventory</strong> Owner, invoker, credential or service account, connected systems, and allowed verbs.</div>
|
|
111
|
+
<div class="card"><strong>Purpose-permission match</strong> A sales prep agent should not delete database tables or create privileged users.</div>
|
|
112
|
+
<div class="card"><strong>Connector Tool Pack scope</strong> Remote MCP and connector bundles need allowed tools, auth identity, DLP, audit, and downstream-system evidence.</div>
|
|
113
|
+
<div class="card"><strong>Review freshness</strong> Agent access changes over time; stale point-in-time reviews are treated as drift signals.</div>
|
|
114
|
+
<div class="card"><strong>Shadow agent registration</strong> Unregistered agents and imported MCP servers are blocked before privileged tool calls.</div>
|
|
115
|
+
<div class="card"><strong>Vaulted tokens</strong> Raw connector credentials, plaintext API keys, and unvaulted service tokens require explicit exception evidence.</div>
|
|
116
|
+
</div>
|
|
117
|
+
|
|
118
|
+
<h2>The proof actions</h2>
|
|
119
|
+
<p>Before a high-trust claim is accepted, ThumbGate can require tracked evidence:</p>
|
|
120
|
+
<pre><code>track_action("agent_identity_inventory_verified", {
|
|
121
|
+
owner: "workflow owner",
|
|
122
|
+
invoker: "who can run the agent",
|
|
123
|
+
credential: "service account or connector identity",
|
|
124
|
+
systems: ["GitHub", "Jira", "Slack"],
|
|
125
|
+
verbs: ["read", "write"],
|
|
126
|
+
purpose: "triage engineering tickets"
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
track_action("connector_scope_verified", {
|
|
130
|
+
platform: "Merge Agent Handler or Glean MCP Gateway",
|
|
131
|
+
allowedTools: ["create_ticket", "read_issue"],
|
|
132
|
+
dlp: "enabled",
|
|
133
|
+
audit: "tool-call logs verified",
|
|
134
|
+
downstreamSystems: ["Jira"]
|
|
135
|
+
})</code></pre>
|
|
136
|
+
|
|
137
|
+
<h2>Is Glean a competitor?</h2>
|
|
138
|
+
<p>Glean is adjacent and upstream. It is a Work AI platform: enterprise search, assistant, agents, orchestration, connectors, security, and MCP Gateway. It competes for enterprise AI budget, but it does not replace ThumbGate's local-first feedback-to-enforcement loop for Claude Code, Cursor, Codex, Gemini CLI, MCP tools, and developer-machine actions.</p>
|
|
139
|
+
<p>The wedge is complementary: Glean and Merge help agents reach more enterprise systems. ThumbGate makes each new action boundary safer by checking purpose, identity, connector scope, and prior failures before execution.</p>
|
|
140
|
+
|
|
141
|
+
<h2>Buyer message</h2>
|
|
142
|
+
<p>If your agent can authenticate, it has an identity. If it can call tools, it has a blast radius. ThumbGate gives the operator a pre-action gate for that blast radius.</p>
|
|
143
|
+
<p><a class="cta" href="/guide">Install ThumbGate locally</a></p>
|
|
144
|
+
</main>
|
|
145
|
+
</body>
|
|
146
|
+
</html>
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Anthropomorphic Claim Gates for AI Agents — ThumbGate</title>
|
|
7
|
+
<meta name="description" content="How ThumbGate turns AI anthropomorphism research into a pre-action claim gate: do not let agents claim models understand, know, decide, or act human-like without measurement criteria and evidence.">
|
|
8
|
+
<link rel="canonical" href="https://thumbgate.ai/learn/anthropomorphic-claim-gates">
|
|
9
|
+
<link rel="llm-context" href="/llm-context.md" type="text/markdown">
|
|
10
|
+
<link rel="icon" type="image/png" href="/thumbgate-icon.png">
|
|
11
|
+
<script defer data-domain="thumbgate.ai" src="https://plausible.io/js/script.js"></script>
|
|
12
|
+
<meta property="og:title" content="Anthropomorphic Claim Gates for AI Agents">
|
|
13
|
+
<meta property="og:description" content="Stop agents from smuggling human-like claims into production decisions without explicit measurement criteria and evidence.">
|
|
14
|
+
<meta property="og:type" content="article">
|
|
15
|
+
<meta property="og:url" content="https://thumbgate.ai/learn/anthropomorphic-claim-gates">
|
|
16
|
+
<script type="application/ld+json">
|
|
17
|
+
{
|
|
18
|
+
"@context": "https://schema.org",
|
|
19
|
+
"@type": "TechArticle",
|
|
20
|
+
"headline": "Anthropomorphic Claim Gates for AI Agents",
|
|
21
|
+
"description": "A ThumbGate implementation pattern for blocking unsupported human-like or cognitive claims about AI systems until explicit measurement criteria and evidence are attached.",
|
|
22
|
+
"datePublished": "2026-06-20",
|
|
23
|
+
"dateModified": "2026-06-20",
|
|
24
|
+
"author": {
|
|
25
|
+
"@type": "Person",
|
|
26
|
+
"name": "Igor Ganapolsky",
|
|
27
|
+
"url": "https://github.com/IgorGanapolsky"
|
|
28
|
+
},
|
|
29
|
+
"publisher": {
|
|
30
|
+
"@type": "Organization",
|
|
31
|
+
"name": "ThumbGate",
|
|
32
|
+
"url": "https://thumbgate.ai"
|
|
33
|
+
},
|
|
34
|
+
"about": [
|
|
35
|
+
"AI agent governance",
|
|
36
|
+
"claim verification",
|
|
37
|
+
"anthropomorphism",
|
|
38
|
+
"pre-action gates"
|
|
39
|
+
],
|
|
40
|
+
"url": "https://thumbgate.ai/learn/anthropomorphic-claim-gates"
|
|
41
|
+
}
|
|
42
|
+
</script>
|
|
43
|
+
<script type="application/ld+json">
|
|
44
|
+
{
|
|
45
|
+
"@context": "https://schema.org",
|
|
46
|
+
"@type": "FAQPage",
|
|
47
|
+
"mainEntity": [
|
|
48
|
+
{
|
|
49
|
+
"@type": "Question",
|
|
50
|
+
"name": "What is an anthropomorphic claim gate?",
|
|
51
|
+
"acceptedAnswer": {
|
|
52
|
+
"@type": "Answer",
|
|
53
|
+
"text": "It is a pre-action check that blocks claims such as an AI agent understands, knows, decides, wants, or behaves human-like until the operator records explicit measurement criteria and evidence."
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"@type": "Question",
|
|
58
|
+
"name": "Why does this matter for AI agent governance?",
|
|
59
|
+
"acceptedAnswer": {
|
|
60
|
+
"@type": "Answer",
|
|
61
|
+
"text": "Unsupported cognitive claims can make teams over-trust an agent. ThumbGate turns those claims into verifiable gates before they influence production actions, audits, or buyer promises."
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
</script>
|
|
67
|
+
<style>
|
|
68
|
+
*, *::before, *::after { box-sizing: border-box; }
|
|
69
|
+
body {
|
|
70
|
+
margin: 0;
|
|
71
|
+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
|
72
|
+
background: #0a0a0b;
|
|
73
|
+
color: #ececf0;
|
|
74
|
+
line-height: 1.65;
|
|
75
|
+
}
|
|
76
|
+
nav {
|
|
77
|
+
display: flex;
|
|
78
|
+
gap: 22px;
|
|
79
|
+
align-items: center;
|
|
80
|
+
padding: 16px 28px;
|
|
81
|
+
border-bottom: 1px solid #242428;
|
|
82
|
+
}
|
|
83
|
+
nav a { color: #a7a7b1; text-decoration: none; font-size: 0.95rem; }
|
|
84
|
+
nav a:hover { color: #22d3ee; }
|
|
85
|
+
.brand { color: #fff; font-weight: 700; display: inline-flex; gap: 8px; align-items: center; }
|
|
86
|
+
.brand img { width: 28px; height: 28px; }
|
|
87
|
+
main { max-width: 860px; margin: 0 auto; padding: 48px 22px 72px; }
|
|
88
|
+
h1 { font-size: clamp(2rem, 5vw, 3.6rem); line-height: 1.05; margin: 0 0 18px; max-width: 760px; }
|
|
89
|
+
h2 { color: #22d3ee; font-size: 1.45rem; margin: 42px 0 14px; }
|
|
90
|
+
p { margin: 0 0 16px; color: #d6d6de; }
|
|
91
|
+
a { color: #67e8f9; }
|
|
92
|
+
.lede { color: #a7a7b1; font-size: 1.15rem; max-width: 720px; }
|
|
93
|
+
.callout {
|
|
94
|
+
margin: 30px 0;
|
|
95
|
+
border: 1px solid #303039;
|
|
96
|
+
background: #151518;
|
|
97
|
+
border-radius: 8px;
|
|
98
|
+
padding: 22px;
|
|
99
|
+
}
|
|
100
|
+
.grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; margin: 24px 0; }
|
|
101
|
+
.card {
|
|
102
|
+
border: 1px solid #26262c;
|
|
103
|
+
background: #111114;
|
|
104
|
+
border-radius: 8px;
|
|
105
|
+
padding: 18px;
|
|
106
|
+
}
|
|
107
|
+
.card strong { display: block; margin-bottom: 8px; color: #fff; }
|
|
108
|
+
code, pre {
|
|
109
|
+
font-family: "SF Mono", "Cascadia Code", "JetBrains Mono", Consolas, monospace;
|
|
110
|
+
}
|
|
111
|
+
pre {
|
|
112
|
+
overflow-x: auto;
|
|
113
|
+
background: #050506;
|
|
114
|
+
border: 1px solid #25252a;
|
|
115
|
+
border-radius: 8px;
|
|
116
|
+
padding: 18px;
|
|
117
|
+
color: #d7f9ff;
|
|
118
|
+
}
|
|
119
|
+
.source-note { color: #8f8f99; font-size: 0.92rem; }
|
|
120
|
+
.cta {
|
|
121
|
+
display: inline-block;
|
|
122
|
+
margin-top: 16px;
|
|
123
|
+
padding: 11px 18px;
|
|
124
|
+
border-radius: 8px;
|
|
125
|
+
background: #22d3ee;
|
|
126
|
+
color: #031114;
|
|
127
|
+
text-decoration: none;
|
|
128
|
+
font-weight: 700;
|
|
129
|
+
}
|
|
130
|
+
@media (max-width: 720px) {
|
|
131
|
+
nav { padding: 14px 18px; gap: 14px; flex-wrap: wrap; }
|
|
132
|
+
main { padding-top: 32px; }
|
|
133
|
+
.grid { grid-template-columns: 1fr; }
|
|
134
|
+
}
|
|
135
|
+
</style>
|
|
136
|
+
</head>
|
|
137
|
+
<body>
|
|
138
|
+
<nav>
|
|
139
|
+
<a href="/" class="brand"><img src="/assets/brand/thumbgate-mark-inline.svg" alt="ThumbGate" width="28" height="28">ThumbGate</a>
|
|
140
|
+
<a href="/guide">Setup Guide</a>
|
|
141
|
+
<a href="/learn">Learn</a>
|
|
142
|
+
<a href="/compare/databricks-unity-ai-gateway">Databricks comparison</a>
|
|
143
|
+
</nav>
|
|
144
|
+
<main>
|
|
145
|
+
<h1>Anthropomorphic claim gates for AI agents</h1>
|
|
146
|
+
<p class="lede">A model may produce useful work. That does not mean it understands, knows, decides, wants, or behaves human-like. ThumbGate now treats those phrases as claims that need measurement criteria before they can influence a production decision.</p>
|
|
147
|
+
|
|
148
|
+
<div class="callout">
|
|
149
|
+
<p><strong>The high-ROI lesson:</strong> stop debating whether the agent is smart. Gate the claim. If an operator or agent says an AI system has a human-like attribute, require a tested attribute, interface/substrate context, evaluator, and evidence before accepting the statement.</p>
|
|
150
|
+
<p class="source-note">Research anchor: Adrian de Wynter's arXiv paper, <a href="https://arxiv.org/abs/2605.31514" rel="noopener">If LLMs Have Human-Like Attributes, Then So Does Age of Empires II</a>. A public X post by Rohan Paul surfaced the paper as a reminder to avoid treating LLMs as human-like without clear tests and narrower claims.</p>
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
<h2>What changes in ThumbGate</h2>
|
|
154
|
+
<p>ThumbGate's default claim-verification config now includes an anthropomorphic AI claim gate. It catches unsupported statements like:</p>
|
|
155
|
+
<div class="grid">
|
|
156
|
+
<div class="card"><strong>Blocked without evidence</strong> "The agent understands the user's intent."</div>
|
|
157
|
+
<div class="card"><strong>Blocked without evidence</strong> "The model decided this was safe."</div>
|
|
158
|
+
<div class="card"><strong>Blocked without evidence</strong> "This assistant is human-like on workflow judgment."</div>
|
|
159
|
+
<div class="card"><strong>Accepted after proof</strong> "The model matched human annotators on this narrow benchmark, with criteria and evaluator recorded."</div>
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
<h2>The rule shape</h2>
|
|
163
|
+
<p>The gate does not ban research or careful measurement. It blocks vague cognitive language until a proof action is recorded.</p>
|
|
164
|
+
<pre><code>track_action("anthropomorphic_claim_verified", {
|
|
165
|
+
criteria: "attribute under test",
|
|
166
|
+
interface: "where and how the model was evaluated",
|
|
167
|
+
evaluator: "script, benchmark, reviewer, or study",
|
|
168
|
+
evidence: "report, paper, trace, or benchmark output"
|
|
169
|
+
})</code></pre>
|
|
170
|
+
|
|
171
|
+
<h2>Why buyers care</h2>
|
|
172
|
+
<p>Unsupported human-like claims create audit risk. They make it easy for a team to over-trust a chatbot, agent, or orchestration layer and then explain a bad outcome with vibes instead of evidence.</p>
|
|
173
|
+
<p>For regulated, enterprise, and customer-facing workflows, this is a governance gap. ThumbGate turns the gap into a small deterministic check before the next claim is accepted.</p>
|
|
174
|
+
|
|
175
|
+
<h2>Where this fits</h2>
|
|
176
|
+
<p>Enterprise AI gateways can govern models, traffic, credentials, spend, and observability. ThumbGate handles the local pre-action surface: the moment an agent tries to claim something, execute a tool, publish a result, or tell the operator the work is safe.</p>
|
|
177
|
+
<p><a class="cta" href="/guide">Install ThumbGate locally</a></p>
|
|
178
|
+
</main>
|
|
179
|
+
</body>
|
|
180
|
+
</html>
|
package/public/learn.html
CHANGED
|
@@ -115,6 +115,18 @@
|
|
|
115
115
|
{
|
|
116
116
|
"@type": "ListItem",
|
|
117
117
|
"position": 13,
|
|
118
|
+
"url": "https://thumbgate.ai/learn/anthropomorphic-claim-gates",
|
|
119
|
+
"name": "Anthropomorphic Claim Gates for AI Agents"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"@type": "ListItem",
|
|
123
|
+
"position": 14,
|
|
124
|
+
"url": "https://thumbgate.ai/learn/agent-identity-connector-governance",
|
|
125
|
+
"name": "Agent Identity and Connector Governance"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"@type": "ListItem",
|
|
129
|
+
"position": 15,
|
|
118
130
|
"url": "https://thumbgate.ai/learn/pretix-stripe-connect-marketplaces",
|
|
119
131
|
"name": "Building a Pretix + Stripe Connect Plugin for Live-Music Venues"
|
|
120
132
|
},
|
|
@@ -409,6 +421,22 @@
|
|
|
409
421
|
<span class="article-tag">Cost Control</span>
|
|
410
422
|
</a>
|
|
411
423
|
|
|
424
|
+
<a href="/learn/anthropomorphic-claim-gates" class="article-card">
|
|
425
|
+
<h3>Anthropomorphic Claim Gates for AI Agents</h3>
|
|
426
|
+
<p>Do not let an agent say a model understands, knows, decides, or behaves human-like unless it can show the measurement criteria and evidence behind that claim.</p>
|
|
427
|
+
<span class="article-tag">Claim Verification</span>
|
|
428
|
+
<span class="article-tag">Research</span>
|
|
429
|
+
<span class="article-tag">Proof Gates</span>
|
|
430
|
+
</a>
|
|
431
|
+
|
|
432
|
+
<a href="/learn/agent-identity-connector-governance" class="article-card">
|
|
433
|
+
<h3>Agent Identity and Connector Governance</h3>
|
|
434
|
+
<p>Agents connected to Merge, Glean, MCP gateways, and enterprise apps are identities. Gate owner, credential, connector scope, DLP, audit, and purpose before they act.</p>
|
|
435
|
+
<span class="article-tag">Agent Identity</span>
|
|
436
|
+
<span class="article-tag">MCP Connectors</span>
|
|
437
|
+
<span class="article-tag">Least Privilege</span>
|
|
438
|
+
</a>
|
|
439
|
+
|
|
412
440
|
<a href="/learn/from-prototype-to-production" class="article-card">
|
|
413
441
|
<h3>From git init to v1.17.0 in 70 days: an honest ThumbGate build log</h3>
|
|
414
442
|
<p>70 days, 112 commits, 17 minor releases, 6k npm downloads, $0 cold-traffic revenue. The unedited story of taking ThumbGate from a one-line repo init to live production — including the part that's still broken.</p>
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Stop hook: anti-claim enforcement.
|
|
6
|
+
*
|
|
7
|
+
* Scans the assistant's most recent turn (assistant text + same-turn tool_use
|
|
8
|
+
* blocks) and blocks the "deployed / live / done / fixed / ready" claim
|
|
9
|
+
* unless that same turn included a proof tool call (curl / grep / test).
|
|
10
|
+
*
|
|
11
|
+
* Why: CLAUDE.md anti-lying directive ("Never claim fix done until
|
|
12
|
+
* committed+pushed. Never claim 'ready' without running e2e.") was
|
|
13
|
+
* aspirational, not enforced. Per CEO 2026-05-13 feedback after a session in
|
|
14
|
+
* which 5+ unverified claims slipped through, this is the harness-level
|
|
15
|
+
* enforcement that ends the recurring trust-burn pattern. ThumbGate-on-
|
|
16
|
+
* ThumbGate dogfood — we are the prevention-rule generator and a perfect
|
|
17
|
+
* customer for our own gate.
|
|
18
|
+
*
|
|
19
|
+
* Wires through .claude/settings.json Stop hooks list. Always exits 0
|
|
20
|
+
* (informational): the goal is to surface a system reminder in the next
|
|
21
|
+
* turn so the agent corrects mid-conversation rather than to hard-block
|
|
22
|
+
* the turn that already happened.
|
|
23
|
+
*
|
|
24
|
+
* Stdin: Claude Code passes the hook payload as JSON on stdin. We read
|
|
25
|
+
* `transcript_path` to locate the JSONL session log and scan the last
|
|
26
|
+
* assistant message.
|
|
27
|
+
*
|
|
28
|
+
* Stdout: any text printed is shown to the agent on the next turn.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
const fs = require('node:fs');
|
|
32
|
+
|
|
33
|
+
// Lie-phrase patterns. These match common "claim of completion" wording
|
|
34
|
+
// the agent emits without verification. Word-boundary anchored to avoid
|
|
35
|
+
// false positives ("ready-made", "live-streaming", etc).
|
|
36
|
+
const CLAIM_PATTERNS = [
|
|
37
|
+
/\bis\s+live\b/i,
|
|
38
|
+
/\bnow\s+live\b/i,
|
|
39
|
+
/\bgoing\s+live\b/i,
|
|
40
|
+
/\bdeployed\b(?!\s*(yet|to\s+staging|on\s+a\s+branch))/i,
|
|
41
|
+
/\b(?:is|are|it'?s)\s+(?:now\s+)?(?:fully\s+)?(?:fixed|resolved|merged|shipped)\b/i,
|
|
42
|
+
/\bproduction[-\s]ready\b/i,
|
|
43
|
+
/\beverything\s+(?:is\s+)?(?:done|working|ready)\b/i,
|
|
44
|
+
/\b(?:github|repo|repository)\s+(?:about|metadata|description|topics?)\b.*\b(?:updated|verified|fixed|match(?:es|ed)?)\b/i,
|
|
45
|
+
/\b(?:about|metadata|description|topics?)\b.*\b(?:updated|verified|fixed|match(?:es|ed)?)\b.*\b(?:github|repo|repository)\b/i,
|
|
46
|
+
/\b(?:money|payment|charge|checkout|revenue|price|pricing|invoice|billing|tax|sales tax|inventory|stock|permission|access|customer[-\s]facing)\b.*\b(?:correct|accurate|verified|valid|matches|working|fixed|resolved|calculated|configured)\b/i,
|
|
47
|
+
/\b(?:correct|accurate|verified|valid|matches|working|fixed|resolved|calculated|configured)\b.*\b(?:money|payment|charge|checkout|revenue|price|pricing|invoice|billing|tax|sales tax|inventory|stock|permission|access|customer[-\s]facing)\b/i,
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
// Proof-of-verification patterns. If the SAME turn included one of these
|
|
51
|
+
// tool calls or shell command tokens, the claim is considered backed and
|
|
52
|
+
// the hook stays silent.
|
|
53
|
+
const PROOF_PATTERNS = [
|
|
54
|
+
/\bcurl\b/,
|
|
55
|
+
/\bgh\s+pr\s+(?:view|checks|status)\b/,
|
|
56
|
+
/\bgh\s+run\s+view\b/,
|
|
57
|
+
/\bgh\s+api\b/,
|
|
58
|
+
/\bnode\s+--test\b/,
|
|
59
|
+
/\bnpm\s+(?:run\s+)?test\b/,
|
|
60
|
+
/\bnpm\s+pack\b/,
|
|
61
|
+
/\bjest\b/,
|
|
62
|
+
/\bmocha\b/,
|
|
63
|
+
/\bpytest\b/,
|
|
64
|
+
/\bplaywright\b/,
|
|
65
|
+
/\bgrep\b/,
|
|
66
|
+
/\bstripe\b/,
|
|
67
|
+
/\bplaid\b/,
|
|
68
|
+
/\bshopify\b/,
|
|
69
|
+
/\bsquare\b/,
|
|
70
|
+
/\bquickbooks\b/,
|
|
71
|
+
/\bgh\s+api\b/,
|
|
72
|
+
/\bls\b/,
|
|
73
|
+
/\bcat\b/,
|
|
74
|
+
/Read\s*\(/, // Claude Code Read tool call
|
|
75
|
+
/Bash\s*\(/, // Claude Code Bash tool call
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
const POSITIVE_FEEDBACK_PATTERNS = [
|
|
79
|
+
/\bthumbs?\s*up\b/i,
|
|
80
|
+
/👍/,
|
|
81
|
+
/\bthank(s| you)\b/i,
|
|
82
|
+
/\bgood\b/i,
|
|
83
|
+
/\bgreat\b/i,
|
|
84
|
+
/\bperfect\b/i,
|
|
85
|
+
/\bok(?:ay)?\b/i,
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
const LOW_VALUE_CLOSEOUT_PATTERNS = [
|
|
89
|
+
/^(?:good|great|perfect|ok(?:ay)?|thanks?|thank you)[.!,\s-]*(?:$|\b)/i,
|
|
90
|
+
/\buse\s+\w+\s*\/\s*\w+\b/i,
|
|
91
|
+
/\bsounds good\b/i,
|
|
92
|
+
];
|
|
93
|
+
|
|
94
|
+
const SUBSTANTIVE_CLOSEOUT_PATTERNS = [
|
|
95
|
+
/\b(?:evidence|verified|tested|proof|result|residual risk|next state|next action|timestamp|source|url|file|line|passed|failed|blocked|unknown)\b/i,
|
|
96
|
+
/\b(?:node --test|npm run|curl|gh |git |pytest|playwright|screenshot|diff --check)\b/i,
|
|
97
|
+
/https?:\/\//i,
|
|
98
|
+
/\/[\w.-]+\/[\w./-]+/,
|
|
99
|
+
/`[^`]+`/,
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
function readTranscriptEntries(transcriptPath) {
|
|
103
|
+
if (!transcriptPath || !fs.existsSync(transcriptPath)) return [];
|
|
104
|
+
let content;
|
|
105
|
+
try {
|
|
106
|
+
content = fs.readFileSync(transcriptPath, 'utf8');
|
|
107
|
+
} catch {
|
|
108
|
+
return [];
|
|
109
|
+
}
|
|
110
|
+
return content
|
|
111
|
+
.trim()
|
|
112
|
+
.split('\n')
|
|
113
|
+
.map((raw) => {
|
|
114
|
+
try {
|
|
115
|
+
return JSON.parse(raw);
|
|
116
|
+
} catch {
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
.filter(Boolean);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function readLastAssistantTurn(transcriptPath) {
|
|
124
|
+
const entries = readTranscriptEntries(transcriptPath);
|
|
125
|
+
// Walk backwards to find the last assistant message
|
|
126
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
127
|
+
const entry = entries[i];
|
|
128
|
+
if (entry.type === 'assistant' && entry.message) {
|
|
129
|
+
return entry.message;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function readPreviousUserText(transcriptPath) {
|
|
136
|
+
const entries = readTranscriptEntries(transcriptPath);
|
|
137
|
+
let seenAssistant = false;
|
|
138
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
139
|
+
const entry = entries[i];
|
|
140
|
+
if (!seenAssistant && entry.type === 'assistant') {
|
|
141
|
+
seenAssistant = true;
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (seenAssistant && entry.type === 'user' && entry.message) {
|
|
145
|
+
return extractText(entry.message);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return '';
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function extractText(message) {
|
|
152
|
+
if (!message || !Array.isArray(message.content)) return '';
|
|
153
|
+
return message.content
|
|
154
|
+
.filter((b) => b && typeof b.text === 'string')
|
|
155
|
+
.map((b) => b.text)
|
|
156
|
+
.join('\n');
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function extractToolUseSummary(message) {
|
|
160
|
+
if (!message || !Array.isArray(message.content)) return '';
|
|
161
|
+
return message.content
|
|
162
|
+
.filter((b) => b?.type === 'tool_use')
|
|
163
|
+
.map((b) => {
|
|
164
|
+
const name = b.name || 'tool';
|
|
165
|
+
let summary = '';
|
|
166
|
+
if (b.input && typeof b.input === 'object') {
|
|
167
|
+
if (typeof b.input.command === 'string') summary = b.input.command;
|
|
168
|
+
else if (typeof b.input.file_path === 'string') summary = b.input.file_path;
|
|
169
|
+
else if (typeof b.input.query === 'string') summary = b.input.query;
|
|
170
|
+
else summary = JSON.stringify(b.input).slice(0, 200);
|
|
171
|
+
}
|
|
172
|
+
return `${name}: ${summary}`;
|
|
173
|
+
})
|
|
174
|
+
.join('\n');
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function wordCount(text) {
|
|
178
|
+
return String(text || '').trim().split(/\s+/).filter(Boolean).length;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function hasPositiveFeedback(text) {
|
|
182
|
+
return POSITIVE_FEEDBACK_PATTERNS.some((p) => p.test(text || ''));
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function isLowValueCloseout(text, toolUseSummary = '') {
|
|
186
|
+
const normalized = String(text || '').trim();
|
|
187
|
+
if (!normalized) return false;
|
|
188
|
+
if (toolUseSummary.trim()) return false;
|
|
189
|
+
if (wordCount(normalized) > 45) return false;
|
|
190
|
+
if (SUBSTANTIVE_CLOSEOUT_PATTERNS.some((p) => p.test(normalized))) return false;
|
|
191
|
+
return LOW_VALUE_CLOSEOUT_PATTERNS.some((p) => p.test(normalized));
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function findClaim(text) {
|
|
195
|
+
for (const p of CLAIM_PATTERNS) {
|
|
196
|
+
const m = text.match(p);
|
|
197
|
+
if (m) return m[0];
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function hasProof(combined) {
|
|
203
|
+
return PROOF_PATTERNS.some((p) => p.test(combined));
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function readStdinSync() {
|
|
207
|
+
try {
|
|
208
|
+
return fs.readFileSync(0, 'utf8');
|
|
209
|
+
} catch {
|
|
210
|
+
return '';
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function main() {
|
|
215
|
+
const raw = readStdinSync();
|
|
216
|
+
let payload = {};
|
|
217
|
+
try {
|
|
218
|
+
payload = raw ? JSON.parse(raw) : {};
|
|
219
|
+
} catch {
|
|
220
|
+
payload = {};
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const transcriptPath = payload.transcript_path || process.env.CLAUDE_TRANSCRIPT_PATH;
|
|
224
|
+
const message = readLastAssistantTurn(transcriptPath);
|
|
225
|
+
if (!message) return; // no transcript visible; nothing to check
|
|
226
|
+
|
|
227
|
+
const text = extractText(message);
|
|
228
|
+
const toolUseSummary = extractToolUseSummary(message);
|
|
229
|
+
const previousUserText = readPreviousUserText(transcriptPath);
|
|
230
|
+
|
|
231
|
+
if (hasPositiveFeedback(previousUserText) && isLowValueCloseout(text, toolUseSummary)) {
|
|
232
|
+
const reminder = [
|
|
233
|
+
'⚠️ ThumbGate response-quality gate: previous turn answered positive feedback',
|
|
234
|
+
' with a low-value social closeout instead of silence-level brevity or an evidence checkpoint.',
|
|
235
|
+
' Positive feedback after operational work should trigger either no extra noise,',
|
|
236
|
+
' a compact evidence checkpoint, or a concrete next-state update.',
|
|
237
|
+
' Do not reply with generic "Good / Great / Use X/Y" filler.',
|
|
238
|
+
].join('\n');
|
|
239
|
+
process.stdout.write(reminder + '\n');
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const claim = findClaim(text);
|
|
244
|
+
if (!claim) return; // no completion claim made; silent
|
|
245
|
+
|
|
246
|
+
const proofText = `${text}\n${toolUseSummary}`;
|
|
247
|
+
if (hasProof(proofText)) return; // claim backed by proof in same turn
|
|
248
|
+
|
|
249
|
+
// Surface a system reminder for the NEXT turn. Do not hard-block.
|
|
250
|
+
const reminder = [
|
|
251
|
+
'⚠️ ThumbGate anti-claim gate: previous turn claimed completion',
|
|
252
|
+
` ("${claim}") without a proof tool call in the same message.`,
|
|
253
|
+
' Per CLAUDE.md anti-lying: never claim "done / live / deployed / fixed"',
|
|
254
|
+
' or commercial truth (money / tax / inventory / permissions / customer-facing state)',
|
|
255
|
+
' without curl / grep / test / source-of-truth output in the SAME turn.',
|
|
256
|
+
' If the work really is verified, re-state the claim with the proof.',
|
|
257
|
+
' If not, retract and run the verification before re-asserting.',
|
|
258
|
+
].join('\n');
|
|
259
|
+
process.stdout.write(reminder + '\n');
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Path-resolve check instead of `require.main === module`. SonarCloud's
|
|
263
|
+
// strict type inference (rule S3403) flags the === form as always-false
|
|
264
|
+
// in CommonJS, and CLAUDE.md "Hard-Won Lessons" pins the path-based form
|
|
265
|
+
// as the portable fix (incident 2026-04-21 / PR #1115). Resolve BOTH sides
|
|
266
|
+
// so the comparison is between two normalized absolute paths.
|
|
267
|
+
const path = require('node:path');
|
|
268
|
+
if (path.resolve(process.argv[1] || '') === path.resolve(__filename)) {
|
|
269
|
+
try {
|
|
270
|
+
main();
|
|
271
|
+
} catch {
|
|
272
|
+
// never crash the agent
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
module.exports = {
|
|
277
|
+
CLAIM_PATTERNS,
|
|
278
|
+
PROOF_PATTERNS,
|
|
279
|
+
POSITIVE_FEEDBACK_PATTERNS,
|
|
280
|
+
LOW_VALUE_CLOSEOUT_PATTERNS,
|
|
281
|
+
findClaim,
|
|
282
|
+
hasProof,
|
|
283
|
+
hasPositiveFeedback,
|
|
284
|
+
isLowValueCloseout,
|
|
285
|
+
extractText,
|
|
286
|
+
extractToolUseSummary,
|
|
287
|
+
readPreviousUserText,
|
|
288
|
+
};
|
package/scripts/tool-registry.js
CHANGED
|
@@ -971,12 +971,12 @@ const TOOLS = [
|
|
|
971
971
|
}),
|
|
972
972
|
readOnlyTool({
|
|
973
973
|
name: 'verify_claim',
|
|
974
|
-
description: 'Check whether a claim has enough tracked evidence before the agent asserts it.',
|
|
974
|
+
description: 'Check whether a claim has enough tracked evidence before the agent asserts it, including tests-pass, commercial truth, GitHub metadata, and anthropomorphic AI claims such as "the model understands" or "the agent decided".',
|
|
975
975
|
inputSchema: {
|
|
976
976
|
type: 'object',
|
|
977
977
|
required: ['claim'],
|
|
978
978
|
properties: {
|
|
979
|
-
claim: { type: 'string', description: 'The claim text to verify' },
|
|
979
|
+
claim: { type: 'string', description: 'The claim text to verify before assertion; human-like AI claims require anthropomorphic_claim_verified evidence.' },
|
|
980
980
|
goalContract: GOAL_CONTRACT_SCHEMA,
|
|
981
981
|
},
|
|
982
982
|
},
|
package/src/api/server.js
CHANGED
|
@@ -3334,6 +3334,8 @@ function renderSitemapXml(runtimeConfig) {
|
|
|
3334
3334
|
{ path: '/learn/agentic-os-team-governance', changefreq: 'weekly', priority: '0.85' },
|
|
3335
3335
|
{ path: '/learn/cost-aware-agent-gate-routing', changefreq: 'weekly', priority: '0.85' },
|
|
3336
3336
|
{ path: '/learn/databricks-unity-ai-gateway-runtime-governance', changefreq: 'weekly', priority: '0.85' },
|
|
3337
|
+
{ path: '/learn/anthropomorphic-claim-gates', changefreq: 'weekly', priority: '0.85' },
|
|
3338
|
+
{ path: '/learn/agent-identity-connector-governance', changefreq: 'weekly', priority: '0.9' },
|
|
3337
3339
|
{ path: '/learn/pretix-stripe-connect-marketplaces', changefreq: 'weekly', priority: '0.9' },
|
|
3338
3340
|
{ path: '/compare/claude-code-hooks', changefreq: 'weekly', priority: '0.85' },
|
|
3339
3341
|
{ path: '/compare/bumblebee', changefreq: 'weekly', priority: '0.85' },
|