gentyr 1.3.0
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/.claude/agents/antipattern-hunter.md +176 -0
- package/.claude/agents/code-reviewer.md +205 -0
- package/.claude/agents/code-writer.md +154 -0
- package/.claude/agents/deputy-cto.md +309 -0
- package/.claude/agents/feedback-agent.md +101 -0
- package/.claude/agents/investigator.md +136 -0
- package/.claude/agents/product-manager.md +97 -0
- package/.claude/agents/project-manager.md +116 -0
- package/.claude/agents/repo-hygiene-expert.md +626 -0
- package/.claude/agents/secret-manager.md +324 -0
- package/.claude/agents/test-writer.md +354 -0
- package/.claude/commands/configure-personas.md +144 -0
- package/.claude/commands/cto-report.md +36 -0
- package/.claude/commands/demo.md +89 -0
- package/.claude/commands/deputy-cto.md +345 -0
- package/.claude/commands/hotfix.md +31 -0
- package/.claude/commands/overdrive-gentyr.md +167 -0
- package/.claude/commands/product-manager.md +32 -0
- package/.claude/commands/push-migrations.md +86 -0
- package/.claude/commands/push-secrets.md +97 -0
- package/.claude/commands/services.json.example +30 -0
- package/.claude/commands/setup-gentyr.md +396 -0
- package/.claude/commands/show.md +42 -0
- package/.claude/commands/spawn-tasks.md +79 -0
- package/.claude/commands/toggle-automation-gentyr.md +75 -0
- package/.claude/commands/toggle-product-manager.md +19 -0
- package/.claude/commands/triage.md +69 -0
- package/.claude/hooks/README.md +686 -0
- package/.claude/hooks/__tests__/README.md +129 -0
- package/.claude/hooks/agent-tracker.js +434 -0
- package/.claude/hooks/antipattern-hunter-hook.js +401 -0
- package/.claude/hooks/api-key-watcher.js +289 -0
- package/.claude/hooks/block-no-verify.js +301 -0
- package/.claude/hooks/bypass-approval-hook.js +313 -0
- package/.claude/hooks/compliance-checker.js +1309 -0
- package/.claude/hooks/config-reader.js +143 -0
- package/.claude/hooks/credential-file-guard.js +1139 -0
- package/.claude/hooks/credential-health-check.js +168 -0
- package/.claude/hooks/credential-sync-hook.js +79 -0
- package/.claude/hooks/cto-notification-hook.js +656 -0
- package/.claude/hooks/feedback-launcher.js +424 -0
- package/.claude/hooks/feedback-orchestrator.js +367 -0
- package/.claude/hooks/gentyr-splash.js +47 -0
- package/.claude/hooks/gentyr-sync.js +389 -0
- package/.claude/hooks/hourly-automation.js +3340 -0
- package/.claude/hooks/key-sync.js +899 -0
- package/.claude/hooks/lib/approval-utils.js +731 -0
- package/.claude/hooks/lib/feature-branch-helper.js +102 -0
- package/.claude/hooks/lib/worktree-manager.js +330 -0
- package/.claude/hooks/mapping-validator.js +285 -0
- package/.claude/hooks/plan-executor.js +398 -0
- package/.claude/hooks/playwright-cli-guard.js +104 -0
- package/.claude/hooks/playwright-health-check.js +71 -0
- package/.claude/hooks/pre-commit-review.js +725 -0
- package/.claude/hooks/prompts/local-spec-enforcement.md +310 -0
- package/.claude/hooks/prompts/mapping-fix.md +92 -0
- package/.claude/hooks/prompts/mapping-review.md +140 -0
- package/.claude/hooks/prompts/schema-mapper.md +185 -0
- package/.claude/hooks/prompts/spec-enforcement.md +233 -0
- package/.claude/hooks/protected-action-approval-hook.js +336 -0
- package/.claude/hooks/protected-action-gate.js +562 -0
- package/.claude/hooks/protected-actions.json +208 -0
- package/.claude/hooks/protected-actions.json.template +122 -0
- package/.claude/hooks/quota-monitor.js +490 -0
- package/.claude/hooks/reporters/jest-failure-reporter.js +401 -0
- package/.claude/hooks/reporters/playwright-failure-reporter.js +446 -0
- package/.claude/hooks/reporters/vitest-failure-reporter.js +443 -0
- package/.claude/hooks/schema-mapper-hook.js +544 -0
- package/.claude/hooks/secret-leak-detector.js +216 -0
- package/.claude/hooks/session-reviver.js +514 -0
- package/.claude/hooks/slash-command-prefetch.js +1145 -0
- package/.claude/hooks/stale-work-detector.js +205 -0
- package/.claude/hooks/stop-continue-hook.js +414 -0
- package/.claude/hooks/todo-maintenance.js +522 -0
- package/.claude/hooks/todo-processing-prompt.md +75 -0
- package/.claude/hooks/usage-optimizer.js +791 -0
- package/.claude/mcp/README.md +246 -0
- package/.claude/settings.json.template +168 -0
- package/.mcp.json.template +207 -0
- package/CLAUDE.md +340 -0
- package/CLAUDE.md.gentyr-section +89 -0
- package/LICENSE +21 -0
- package/README.md +297 -0
- package/cli/commands/init.js +471 -0
- package/cli/commands/migrate.js +132 -0
- package/cli/commands/protect.js +271 -0
- package/cli/commands/scaffold.js +48 -0
- package/cli/commands/status.js +133 -0
- package/cli/commands/sync.js +101 -0
- package/cli/commands/uninstall.js +207 -0
- package/cli/index.js +111 -0
- package/cli/lib/config-gen.js +214 -0
- package/cli/lib/resolve-framework.js +97 -0
- package/cli/lib/state.js +140 -0
- package/cli/lib/symlinks.js +260 -0
- package/docs/AUTOMATION-SYSTEMS.md +484 -0
- package/docs/BINARY-PATCHING.md +212 -0
- package/docs/CHANGELOG.md +2830 -0
- package/docs/CREDENTIAL-DETECTION.md +151 -0
- package/docs/CTO-DASHBOARD.md +476 -0
- package/docs/DEPLOYMENT-FLOW.md +477 -0
- package/docs/DEVELOPER.md +116 -0
- package/docs/Executive.md +372 -0
- package/docs/SECRET-PATHS.md +77 -0
- package/docs/SETUP-GUIDE.md +419 -0
- package/docs/STACK.md +109 -0
- package/docs/TESTING.md +440 -0
- package/docs/assets/claude-logo.svg +3 -0
- package/docs/sessions/2026-01-24-spec-suite-implementation.md +190 -0
- package/docs/sessions/2026-02-15-feedback-e2e-audit.md +484 -0
- package/docs/sessions/2026-02-20-credential-rotation-experiments.md +340 -0
- package/docs/sessions/TEST-COVERAGE-REPORT-2026-02-20.md +168 -0
- package/docs/shared/EPHEMERAL-STATE-FILES.md +115 -0
- package/docs/shared/PROTECTION-SYSTEM.md +341 -0
- package/husky/post-commit +10 -0
- package/husky/pre-commit +40 -0
- package/husky/pre-push +94 -0
- package/package.json +43 -0
- package/packages/cto-dashboard/package-lock.json +3510 -0
- package/packages/cto-dashboard/package.json +41 -0
- package/packages/cto-dashboard/pnpm-lock.yaml +2168 -0
- package/packages/mcp-servers/dist/__testUtils__/fixtures.d.ts +220 -0
- package/packages/mcp-servers/dist/__testUtils__/fixtures.d.ts.map +1 -0
- package/packages/mcp-servers/dist/__testUtils__/fixtures.js +376 -0
- package/packages/mcp-servers/dist/__testUtils__/fixtures.js.map +1 -0
- package/packages/mcp-servers/dist/__testUtils__/index.d.ts +121 -0
- package/packages/mcp-servers/dist/__testUtils__/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/__testUtils__/index.js +180 -0
- package/packages/mcp-servers/dist/__testUtils__/index.js.map +1 -0
- package/packages/mcp-servers/dist/__testUtils__/schemas.d.ts +84 -0
- package/packages/mcp-servers/dist/__testUtils__/schemas.d.ts.map +1 -0
- package/packages/mcp-servers/dist/__testUtils__/schemas.js +309 -0
- package/packages/mcp-servers/dist/__testUtils__/schemas.js.map +1 -0
- package/packages/mcp-servers/dist/agent-reports/index.d.ts +7 -0
- package/packages/mcp-servers/dist/agent-reports/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/agent-reports/index.js +8 -0
- package/packages/mcp-servers/dist/agent-reports/index.js.map +1 -0
- package/packages/mcp-servers/dist/agent-reports/server.d.ts +22 -0
- package/packages/mcp-servers/dist/agent-reports/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/agent-reports/server.js +535 -0
- package/packages/mcp-servers/dist/agent-reports/server.js.map +1 -0
- package/packages/mcp-servers/dist/agent-reports/types.d.ts +258 -0
- package/packages/mcp-servers/dist/agent-reports/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/agent-reports/types.js +81 -0
- package/packages/mcp-servers/dist/agent-reports/types.js.map +1 -0
- package/packages/mcp-servers/dist/agent-tracker/index.d.ts +5 -0
- package/packages/mcp-servers/dist/agent-tracker/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/agent-tracker/index.js +5 -0
- package/packages/mcp-servers/dist/agent-tracker/index.js.map +1 -0
- package/packages/mcp-servers/dist/agent-tracker/server.d.ts +12 -0
- package/packages/mcp-servers/dist/agent-tracker/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/agent-tracker/server.js +919 -0
- package/packages/mcp-servers/dist/agent-tracker/server.js.map +1 -0
- package/packages/mcp-servers/dist/agent-tracker/types.d.ts +328 -0
- package/packages/mcp-servers/dist/agent-tracker/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/agent-tracker/types.js +128 -0
- package/packages/mcp-servers/dist/agent-tracker/types.js.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/browser-tips.d.ts +27 -0
- package/packages/mcp-servers/dist/chrome-bridge/browser-tips.d.ts.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/browser-tips.js +167 -0
- package/packages/mcp-servers/dist/chrome-bridge/browser-tips.js.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/index.d.ts +6 -0
- package/packages/mcp-servers/dist/chrome-bridge/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/index.js +6 -0
- package/packages/mcp-servers/dist/chrome-bridge/index.js.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/server.d.ts +13 -0
- package/packages/mcp-servers/dist/chrome-bridge/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/server.js +959 -0
- package/packages/mcp-servers/dist/chrome-bridge/server.js.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/types.d.ts +41 -0
- package/packages/mcp-servers/dist/chrome-bridge/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/chrome-bridge/types.js +8 -0
- package/packages/mcp-servers/dist/chrome-bridge/types.js.map +1 -0
- package/packages/mcp-servers/dist/cloudflare/index.d.ts +8 -0
- package/packages/mcp-servers/dist/cloudflare/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cloudflare/index.js +8 -0
- package/packages/mcp-servers/dist/cloudflare/index.js.map +1 -0
- package/packages/mcp-servers/dist/cloudflare/server.d.ts +16 -0
- package/packages/mcp-servers/dist/cloudflare/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cloudflare/server.js +253 -0
- package/packages/mcp-servers/dist/cloudflare/server.js.map +1 -0
- package/packages/mcp-servers/dist/cloudflare/types.d.ts +141 -0
- package/packages/mcp-servers/dist/cloudflare/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cloudflare/types.js +53 -0
- package/packages/mcp-servers/dist/cloudflare/types.js.map +1 -0
- package/packages/mcp-servers/dist/codecov/index.d.ts +7 -0
- package/packages/mcp-servers/dist/codecov/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/codecov/index.js +7 -0
- package/packages/mcp-servers/dist/codecov/index.js.map +1 -0
- package/packages/mcp-servers/dist/codecov/server.d.ts +21 -0
- package/packages/mcp-servers/dist/codecov/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/codecov/server.js +376 -0
- package/packages/mcp-servers/dist/codecov/server.js.map +1 -0
- package/packages/mcp-servers/dist/codecov/types.d.ts +269 -0
- package/packages/mcp-servers/dist/codecov/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/codecov/types.js +128 -0
- package/packages/mcp-servers/dist/codecov/types.js.map +1 -0
- package/packages/mcp-servers/dist/cto-report/index.d.ts +9 -0
- package/packages/mcp-servers/dist/cto-report/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cto-report/index.js +9 -0
- package/packages/mcp-servers/dist/cto-report/index.js.map +1 -0
- package/packages/mcp-servers/dist/cto-report/server.d.ts +14 -0
- package/packages/mcp-servers/dist/cto-report/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cto-report/server.js +859 -0
- package/packages/mcp-servers/dist/cto-report/server.js.map +1 -0
- package/packages/mcp-servers/dist/cto-report/types.d.ts +213 -0
- package/packages/mcp-servers/dist/cto-report/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cto-report/types.js +29 -0
- package/packages/mcp-servers/dist/cto-report/types.js.map +1 -0
- package/packages/mcp-servers/dist/cto-reports/index.d.ts +7 -0
- package/packages/mcp-servers/dist/cto-reports/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cto-reports/index.js +8 -0
- package/packages/mcp-servers/dist/cto-reports/index.js.map +1 -0
- package/packages/mcp-servers/dist/cto-reports/server.d.ts +20 -0
- package/packages/mcp-servers/dist/cto-reports/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cto-reports/server.js +538 -0
- package/packages/mcp-servers/dist/cto-reports/server.js.map +1 -0
- package/packages/mcp-servers/dist/cto-reports/types.d.ts +236 -0
- package/packages/mcp-servers/dist/cto-reports/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/cto-reports/types.js +77 -0
- package/packages/mcp-servers/dist/cto-reports/types.js.map +1 -0
- package/packages/mcp-servers/dist/deputy-cto/index.d.ts +7 -0
- package/packages/mcp-servers/dist/deputy-cto/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/deputy-cto/index.js +8 -0
- package/packages/mcp-servers/dist/deputy-cto/index.js.map +1 -0
- package/packages/mcp-servers/dist/deputy-cto/server.d.ts +23 -0
- package/packages/mcp-servers/dist/deputy-cto/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/deputy-cto/server.js +1700 -0
- package/packages/mcp-servers/dist/deputy-cto/server.js.map +1 -0
- package/packages/mcp-servers/dist/deputy-cto/types.d.ts +439 -0
- package/packages/mcp-servers/dist/deputy-cto/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/deputy-cto/types.js +102 -0
- package/packages/mcp-servers/dist/deputy-cto/types.js.map +1 -0
- package/packages/mcp-servers/dist/elastic-logs/index.d.ts +5 -0
- package/packages/mcp-servers/dist/elastic-logs/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/elastic-logs/index.js +5 -0
- package/packages/mcp-servers/dist/elastic-logs/index.js.map +1 -0
- package/packages/mcp-servers/dist/elastic-logs/server.d.ts +18 -0
- package/packages/mcp-servers/dist/elastic-logs/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/elastic-logs/server.js +259 -0
- package/packages/mcp-servers/dist/elastic-logs/server.js.map +1 -0
- package/packages/mcp-servers/dist/elastic-logs/types.d.ts +107 -0
- package/packages/mcp-servers/dist/elastic-logs/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/elastic-logs/types.js +31 -0
- package/packages/mcp-servers/dist/elastic-logs/types.js.map +1 -0
- package/packages/mcp-servers/dist/feedback-explorer/index.d.ts +2 -0
- package/packages/mcp-servers/dist/feedback-explorer/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/feedback-explorer/index.js +2 -0
- package/packages/mcp-servers/dist/feedback-explorer/index.js.map +1 -0
- package/packages/mcp-servers/dist/feedback-explorer/server.d.ts +21 -0
- package/packages/mcp-servers/dist/feedback-explorer/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/feedback-explorer/server.js +580 -0
- package/packages/mcp-servers/dist/feedback-explorer/server.js.map +1 -0
- package/packages/mcp-servers/dist/feedback-explorer/types.d.ts +331 -0
- package/packages/mcp-servers/dist/feedback-explorer/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/feedback-explorer/types.js +40 -0
- package/packages/mcp-servers/dist/feedback-explorer/types.js.map +1 -0
- package/packages/mcp-servers/dist/feedback-reporter/index.d.ts +9 -0
- package/packages/mcp-servers/dist/feedback-reporter/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/feedback-reporter/index.js +9 -0
- package/packages/mcp-servers/dist/feedback-reporter/index.js.map +1 -0
- package/packages/mcp-servers/dist/feedback-reporter/server.d.ts +36 -0
- package/packages/mcp-servers/dist/feedback-reporter/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/feedback-reporter/server.js +392 -0
- package/packages/mcp-servers/dist/feedback-reporter/server.js.map +1 -0
- package/packages/mcp-servers/dist/feedback-reporter/types.d.ts +152 -0
- package/packages/mcp-servers/dist/feedback-reporter/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/feedback-reporter/types.js +67 -0
- package/packages/mcp-servers/dist/feedback-reporter/types.js.map +1 -0
- package/packages/mcp-servers/dist/github/index.d.ts +7 -0
- package/packages/mcp-servers/dist/github/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/github/index.js +7 -0
- package/packages/mcp-servers/dist/github/index.js.map +1 -0
- package/packages/mcp-servers/dist/github/server.d.ts +15 -0
- package/packages/mcp-servers/dist/github/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/github/server.js +686 -0
- package/packages/mcp-servers/dist/github/server.js.map +1 -0
- package/packages/mcp-servers/dist/github/types.d.ts +660 -0
- package/packages/mcp-servers/dist/github/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/github/types.js +209 -0
- package/packages/mcp-servers/dist/github/types.js.map +1 -0
- package/packages/mcp-servers/dist/index.d.ts +30 -0
- package/packages/mcp-servers/dist/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/index.js +32 -0
- package/packages/mcp-servers/dist/index.js.map +1 -0
- package/packages/mcp-servers/dist/makerkit-docs/index.d.ts +5 -0
- package/packages/mcp-servers/dist/makerkit-docs/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/makerkit-docs/index.js +5 -0
- package/packages/mcp-servers/dist/makerkit-docs/index.js.map +1 -0
- package/packages/mcp-servers/dist/makerkit-docs/server.d.ts +15 -0
- package/packages/mcp-servers/dist/makerkit-docs/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/makerkit-docs/server.js +252 -0
- package/packages/mcp-servers/dist/makerkit-docs/server.js.map +1 -0
- package/packages/mcp-servers/dist/makerkit-docs/types.d.ts +74 -0
- package/packages/mcp-servers/dist/makerkit-docs/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/makerkit-docs/types.js +20 -0
- package/packages/mcp-servers/dist/makerkit-docs/types.js.map +1 -0
- package/packages/mcp-servers/dist/onepassword/index.d.ts +2 -0
- package/packages/mcp-servers/dist/onepassword/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/onepassword/index.js +2 -0
- package/packages/mcp-servers/dist/onepassword/index.js.map +1 -0
- package/packages/mcp-servers/dist/onepassword/server.d.ts +2 -0
- package/packages/mcp-servers/dist/onepassword/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/onepassword/server.js +159 -0
- package/packages/mcp-servers/dist/onepassword/server.js.map +1 -0
- package/packages/mcp-servers/dist/onepassword/types.d.ts +55 -0
- package/packages/mcp-servers/dist/onepassword/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/onepassword/types.js +22 -0
- package/packages/mcp-servers/dist/onepassword/types.js.map +1 -0
- package/packages/mcp-servers/dist/playwright/helpers.d.ts +20 -0
- package/packages/mcp-servers/dist/playwright/helpers.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright/helpers.js +31 -0
- package/packages/mcp-servers/dist/playwright/helpers.js.map +1 -0
- package/packages/mcp-servers/dist/playwright/index.d.ts +5 -0
- package/packages/mcp-servers/dist/playwright/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright/index.js +5 -0
- package/packages/mcp-servers/dist/playwright/index.js.map +1 -0
- package/packages/mcp-servers/dist/playwright/server.d.ts +13 -0
- package/packages/mcp-servers/dist/playwright/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright/server.js +1201 -0
- package/packages/mcp-servers/dist/playwright/server.js.map +1 -0
- package/packages/mcp-servers/dist/playwright/types.d.ts +216 -0
- package/packages/mcp-servers/dist/playwright/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright/types.js +172 -0
- package/packages/mcp-servers/dist/playwright/types.js.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/browser-manager.d.ts +39 -0
- package/packages/mcp-servers/dist/playwright-feedback/browser-manager.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/browser-manager.js +71 -0
- package/packages/mcp-servers/dist/playwright-feedback/browser-manager.js.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/index.d.ts +5 -0
- package/packages/mcp-servers/dist/playwright-feedback/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/index.js +5 -0
- package/packages/mcp-servers/dist/playwright-feedback/index.js.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/server.d.ts +34 -0
- package/packages/mcp-servers/dist/playwright-feedback/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/server.js +538 -0
- package/packages/mcp-servers/dist/playwright-feedback/server.js.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/types.d.ts +305 -0
- package/packages/mcp-servers/dist/playwright-feedback/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/playwright-feedback/types.js +123 -0
- package/packages/mcp-servers/dist/playwright-feedback/types.js.map +1 -0
- package/packages/mcp-servers/dist/product-manager/server.d.ts +17 -0
- package/packages/mcp-servers/dist/product-manager/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/product-manager/server.js +690 -0
- package/packages/mcp-servers/dist/product-manager/server.js.map +1 -0
- package/packages/mcp-servers/dist/product-manager/types.d.ts +286 -0
- package/packages/mcp-servers/dist/product-manager/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/product-manager/types.js +99 -0
- package/packages/mcp-servers/dist/product-manager/types.js.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/index.d.ts +7 -0
- package/packages/mcp-servers/dist/programmatic-feedback/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/index.js +7 -0
- package/packages/mcp-servers/dist/programmatic-feedback/index.js.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/sandbox.d.ts +19 -0
- package/packages/mcp-servers/dist/programmatic-feedback/sandbox.d.ts.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/sandbox.js +174 -0
- package/packages/mcp-servers/dist/programmatic-feedback/sandbox.js.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/server.d.ts +35 -0
- package/packages/mcp-servers/dist/programmatic-feedback/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/server.js +465 -0
- package/packages/mcp-servers/dist/programmatic-feedback/server.js.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/types.d.ts +127 -0
- package/packages/mcp-servers/dist/programmatic-feedback/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/programmatic-feedback/types.js +80 -0
- package/packages/mcp-servers/dist/programmatic-feedback/types.js.map +1 -0
- package/packages/mcp-servers/dist/render/index.d.ts +8 -0
- package/packages/mcp-servers/dist/render/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/render/index.js +8 -0
- package/packages/mcp-servers/dist/render/index.js.map +1 -0
- package/packages/mcp-servers/dist/render/server.d.ts +15 -0
- package/packages/mcp-servers/dist/render/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/render/server.js +428 -0
- package/packages/mcp-servers/dist/render/server.js.map +1 -0
- package/packages/mcp-servers/dist/render/types.d.ts +273 -0
- package/packages/mcp-servers/dist/render/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/render/types.js +102 -0
- package/packages/mcp-servers/dist/render/types.js.map +1 -0
- package/packages/mcp-servers/dist/resend/index.d.ts +7 -0
- package/packages/mcp-servers/dist/resend/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/resend/index.js +7 -0
- package/packages/mcp-servers/dist/resend/index.js.map +1 -0
- package/packages/mcp-servers/dist/resend/server.d.ts +15 -0
- package/packages/mcp-servers/dist/resend/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/resend/server.js +298 -0
- package/packages/mcp-servers/dist/resend/server.js.map +1 -0
- package/packages/mcp-servers/dist/resend/types.d.ts +222 -0
- package/packages/mcp-servers/dist/resend/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/resend/types.js +58 -0
- package/packages/mcp-servers/dist/resend/types.js.map +1 -0
- package/packages/mcp-servers/dist/review-queue/index.d.ts +6 -0
- package/packages/mcp-servers/dist/review-queue/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/review-queue/index.js +6 -0
- package/packages/mcp-servers/dist/review-queue/index.js.map +1 -0
- package/packages/mcp-servers/dist/review-queue/server.d.ts +17 -0
- package/packages/mcp-servers/dist/review-queue/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/review-queue/server.js +348 -0
- package/packages/mcp-servers/dist/review-queue/server.js.map +1 -0
- package/packages/mcp-servers/dist/review-queue/types.d.ts +162 -0
- package/packages/mcp-servers/dist/review-queue/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/review-queue/types.js +56 -0
- package/packages/mcp-servers/dist/review-queue/types.js.map +1 -0
- package/packages/mcp-servers/dist/secret-sync/server.d.ts +19 -0
- package/packages/mcp-servers/dist/secret-sync/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/secret-sync/server.js +1139 -0
- package/packages/mcp-servers/dist/secret-sync/server.js.map +1 -0
- package/packages/mcp-servers/dist/secret-sync/types.d.ts +442 -0
- package/packages/mcp-servers/dist/secret-sync/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/secret-sync/types.js +113 -0
- package/packages/mcp-servers/dist/secret-sync/types.js.map +1 -0
- package/packages/mcp-servers/dist/session-events/index.d.ts +5 -0
- package/packages/mcp-servers/dist/session-events/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/session-events/index.js +5 -0
- package/packages/mcp-servers/dist/session-events/index.js.map +1 -0
- package/packages/mcp-servers/dist/session-events/server.d.ts +11 -0
- package/packages/mcp-servers/dist/session-events/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/session-events/server.js +290 -0
- package/packages/mcp-servers/dist/session-events/server.js.map +1 -0
- package/packages/mcp-servers/dist/session-events/types.d.ts +213 -0
- package/packages/mcp-servers/dist/session-events/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/session-events/types.js +69 -0
- package/packages/mcp-servers/dist/session-events/types.js.map +1 -0
- package/packages/mcp-servers/dist/session-restart/index.d.ts +9 -0
- package/packages/mcp-servers/dist/session-restart/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/session-restart/index.js +9 -0
- package/packages/mcp-servers/dist/session-restart/index.js.map +1 -0
- package/packages/mcp-servers/dist/session-restart/server.d.ts +20 -0
- package/packages/mcp-servers/dist/session-restart/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/session-restart/server.js +411 -0
- package/packages/mcp-servers/dist/session-restart/server.js.map +1 -0
- package/packages/mcp-servers/dist/session-restart/types.d.ts +26 -0
- package/packages/mcp-servers/dist/session-restart/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/session-restart/types.js +16 -0
- package/packages/mcp-servers/dist/session-restart/types.js.map +1 -0
- package/packages/mcp-servers/dist/setup-helper/index.d.ts +5 -0
- package/packages/mcp-servers/dist/setup-helper/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/setup-helper/index.js +5 -0
- package/packages/mcp-servers/dist/setup-helper/index.js.map +1 -0
- package/packages/mcp-servers/dist/setup-helper/server.d.ts +14 -0
- package/packages/mcp-servers/dist/setup-helper/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/setup-helper/server.js +454 -0
- package/packages/mcp-servers/dist/setup-helper/server.js.map +1 -0
- package/packages/mcp-servers/dist/setup-helper/types.d.ts +81 -0
- package/packages/mcp-servers/dist/setup-helper/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/setup-helper/types.js +41 -0
- package/packages/mcp-servers/dist/setup-helper/types.js.map +1 -0
- package/packages/mcp-servers/dist/shared/audited-server.d.ts +31 -0
- package/packages/mcp-servers/dist/shared/audited-server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/shared/audited-server.js +126 -0
- package/packages/mcp-servers/dist/shared/audited-server.js.map +1 -0
- package/packages/mcp-servers/dist/shared/constants.d.ts +26 -0
- package/packages/mcp-servers/dist/shared/constants.d.ts.map +1 -0
- package/packages/mcp-servers/dist/shared/constants.js +41 -0
- package/packages/mcp-servers/dist/shared/constants.js.map +1 -0
- package/packages/mcp-servers/dist/shared/index.d.ts +6 -0
- package/packages/mcp-servers/dist/shared/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/shared/index.js +6 -0
- package/packages/mcp-servers/dist/shared/index.js.map +1 -0
- package/packages/mcp-servers/dist/shared/readonly-db.d.ts +11 -0
- package/packages/mcp-servers/dist/shared/readonly-db.d.ts.map +1 -0
- package/packages/mcp-servers/dist/shared/readonly-db.js +47 -0
- package/packages/mcp-servers/dist/shared/readonly-db.js.map +1 -0
- package/packages/mcp-servers/dist/shared/resolve-framework.d.ts +20 -0
- package/packages/mcp-servers/dist/shared/resolve-framework.d.ts.map +1 -0
- package/packages/mcp-servers/dist/shared/resolve-framework.js +65 -0
- package/packages/mcp-servers/dist/shared/resolve-framework.js.map +1 -0
- package/packages/mcp-servers/dist/shared/server.d.ts +86 -0
- package/packages/mcp-servers/dist/shared/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/shared/server.js +291 -0
- package/packages/mcp-servers/dist/shared/server.js.map +1 -0
- package/packages/mcp-servers/dist/shared/types.d.ts +113 -0
- package/packages/mcp-servers/dist/shared/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/shared/types.js +36 -0
- package/packages/mcp-servers/dist/shared/types.js.map +1 -0
- package/packages/mcp-servers/dist/show/server.d.ts +12 -0
- package/packages/mcp-servers/dist/show/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/show/server.js +97 -0
- package/packages/mcp-servers/dist/show/server.js.map +1 -0
- package/packages/mcp-servers/dist/show/types.d.ts +19 -0
- package/packages/mcp-servers/dist/show/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/show/types.js +32 -0
- package/packages/mcp-servers/dist/show/types.js.map +1 -0
- package/packages/mcp-servers/dist/specs-browser/index.d.ts +5 -0
- package/packages/mcp-servers/dist/specs-browser/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/specs-browser/index.js +5 -0
- package/packages/mcp-servers/dist/specs-browser/index.js.map +1 -0
- package/packages/mcp-servers/dist/specs-browser/server.d.ts +13 -0
- package/packages/mcp-servers/dist/specs-browser/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/specs-browser/server.js +692 -0
- package/packages/mcp-servers/dist/specs-browser/server.js.map +1 -0
- package/packages/mcp-servers/dist/specs-browser/types.d.ts +337 -0
- package/packages/mcp-servers/dist/specs-browser/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/specs-browser/types.js +134 -0
- package/packages/mcp-servers/dist/specs-browser/types.js.map +1 -0
- package/packages/mcp-servers/dist/supabase/index.d.ts +10 -0
- package/packages/mcp-servers/dist/supabase/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/supabase/index.js +10 -0
- package/packages/mcp-servers/dist/supabase/index.js.map +1 -0
- package/packages/mcp-servers/dist/supabase/server.d.ts +20 -0
- package/packages/mcp-servers/dist/supabase/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/supabase/server.js +451 -0
- package/packages/mcp-servers/dist/supabase/server.js.map +1 -0
- package/packages/mcp-servers/dist/supabase/types.d.ts +196 -0
- package/packages/mcp-servers/dist/supabase/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/supabase/types.js +76 -0
- package/packages/mcp-servers/dist/supabase/types.js.map +1 -0
- package/packages/mcp-servers/dist/todo-db/index.d.ts +5 -0
- package/packages/mcp-servers/dist/todo-db/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/todo-db/index.js +5 -0
- package/packages/mcp-servers/dist/todo-db/index.js.map +1 -0
- package/packages/mcp-servers/dist/todo-db/server.d.ts +13 -0
- package/packages/mcp-servers/dist/todo-db/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/todo-db/server.js +649 -0
- package/packages/mcp-servers/dist/todo-db/server.js.map +1 -0
- package/packages/mcp-servers/dist/todo-db/types.d.ts +225 -0
- package/packages/mcp-servers/dist/todo-db/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/todo-db/types.js +69 -0
- package/packages/mcp-servers/dist/todo-db/types.js.map +1 -0
- package/packages/mcp-servers/dist/user-feedback/index.d.ts +7 -0
- package/packages/mcp-servers/dist/user-feedback/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/user-feedback/index.js +8 -0
- package/packages/mcp-servers/dist/user-feedback/index.js.map +1 -0
- package/packages/mcp-servers/dist/user-feedback/server.d.ts +25 -0
- package/packages/mcp-servers/dist/user-feedback/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/user-feedback/server.js +914 -0
- package/packages/mcp-servers/dist/user-feedback/server.js.map +1 -0
- package/packages/mcp-servers/dist/user-feedback/types.d.ts +415 -0
- package/packages/mcp-servers/dist/user-feedback/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/user-feedback/types.js +132 -0
- package/packages/mcp-servers/dist/user-feedback/types.js.map +1 -0
- package/packages/mcp-servers/dist/vercel/index.d.ts +9 -0
- package/packages/mcp-servers/dist/vercel/index.d.ts.map +1 -0
- package/packages/mcp-servers/dist/vercel/index.js +9 -0
- package/packages/mcp-servers/dist/vercel/index.js.map +1 -0
- package/packages/mcp-servers/dist/vercel/server.d.ts +17 -0
- package/packages/mcp-servers/dist/vercel/server.d.ts.map +1 -0
- package/packages/mcp-servers/dist/vercel/server.js +265 -0
- package/packages/mcp-servers/dist/vercel/server.js.map +1 -0
- package/packages/mcp-servers/dist/vercel/types.d.ts +189 -0
- package/packages/mcp-servers/dist/vercel/types.d.ts.map +1 -0
- package/packages/mcp-servers/dist/vercel/types.js +65 -0
- package/packages/mcp-servers/dist/vercel/types.js.map +1 -0
- package/packages/mcp-servers/package-lock.json +3765 -0
- package/packages/mcp-servers/package.json +64 -0
- package/packages/mcp-servers/test/reporters/test-failure-reporter.ts +372 -0
- package/packages/mcp-servers/vitest.config.ts +27 -0
- package/scripts/__tests__/README.md +163 -0
- package/scripts/apply-credential-hardening.sh +271 -0
- package/scripts/credential-providers/manual.js +56 -0
- package/scripts/credential-providers/onepassword.js +85 -0
- package/scripts/credential-providers/provider-interface.js +104 -0
- package/scripts/encrypt-credential.js +337 -0
- package/scripts/feedback-launcher.js +338 -0
- package/scripts/feedback-orchestrator.js +373 -0
- package/scripts/fix-mcp-launcher-issues.sh +97 -0
- package/scripts/force-spawn-tasks.js +651 -0
- package/scripts/force-triage-reports.js +560 -0
- package/scripts/generate-protected-actions-spec.js +142 -0
- package/scripts/generate-proxy-certs.sh +158 -0
- package/scripts/grant-chrome-ext-permissions.sh +242 -0
- package/scripts/mcp-launcher.js +125 -0
- package/scripts/merge-settings.cjs +167 -0
- package/scripts/patch-clawd.py +844 -0
- package/scripts/patch-credential-cache.py +313 -0
- package/scripts/patches/credential-file-guard-patched.mjs +573 -0
- package/scripts/patches/credential-file-guard.js.patched +573 -0
- package/scripts/patches/verify-tokenizer.mjs +132 -0
- package/scripts/protect-framework.sh +478 -0
- package/scripts/readme-chrome.template +12 -0
- package/scripts/reap-completed-agents.js +439 -0
- package/scripts/reinstall.sh +86 -0
- package/scripts/resign-node.sh +185 -0
- package/scripts/rotation-proxy.js +656 -0
- package/scripts/rotation-stress-monitor.mjs +862 -0
- package/scripts/setup-automation-service.sh +648 -0
- package/scripts/setup-check.js +251 -0
- package/scripts/watch-claude-version.js +142 -0
- package/specs/framework/CORE-INVARIANTS.md +161 -0
- package/specs/patterns/AGENT-PATTERNS.md +223 -0
- package/specs/patterns/HOOK-PATTERNS.md +242 -0
- package/specs/patterns/MCP-SERVER-PATTERNS.md +144 -0
- package/templates/config/gitignore.template +14 -0
- package/templates/config/merge-chain-check.yml.template +51 -0
- package/templates/config/package.json.template +18 -0
- package/templates/config/pnpm-workspace.yaml +5 -0
- package/templates/config/services.json.template +18 -0
- package/templates/config/tsconfig.base.json +17 -0
- package/templates/scaffold/integrations/_template/.gitkeep +0 -0
- package/templates/scaffold/packages/logger/package.json +17 -0
- package/templates/scaffold/packages/logger/src/logger.ts +44 -0
- package/templates/scaffold/packages/shared/package.json +17 -0
- package/templates/scaffold/packages/shared/src/errors.ts +43 -0
- package/templates/scaffold/products/_product/apps/backend/package.json +21 -0
- package/templates/scaffold/products/_product/apps/backend/src/index.ts +17 -0
- package/templates/scaffold/products/_product/apps/extension/.gitkeep +0 -0
- package/templates/scaffold/products/_product/apps/web/.gitkeep +0 -0
- package/templates/scaffold/specs/global/.gitkeep +0 -0
- package/templates/scaffold/specs/local/.gitkeep +0 -0
- package/templates/scaffold/specs/reference/.gitkeep +0 -0
- package/version.json +15 -0
|
@@ -0,0 +1,562 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* PreToolUse Hook: Protected Action Gate
|
|
4
|
+
*
|
|
5
|
+
* Intercepts MCP tool calls and blocks protected actions that haven't
|
|
6
|
+
* been approved by the CTO. When blocked, generates an approval code
|
|
7
|
+
* that the CTO must type to authorize the action.
|
|
8
|
+
*
|
|
9
|
+
* Security Model:
|
|
10
|
+
* - Agent cannot bypass: PreToolUse hooks run before tool execution
|
|
11
|
+
* - Agent cannot forge approval: UserPromptSubmit = human keyboard only
|
|
12
|
+
* - One-time codes: Each approval is tied to a specific request
|
|
13
|
+
* - Time-limited: Codes expire after 5 minutes
|
|
14
|
+
* - G001 Fail-Closed: If config is corrupted, all protected servers are blocked
|
|
15
|
+
*
|
|
16
|
+
* SECURITY: This file should be root-owned via protect-framework.sh
|
|
17
|
+
*
|
|
18
|
+
* @version 2.0.0
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import fs from 'fs';
|
|
22
|
+
import path from 'path';
|
|
23
|
+
import crypto from 'crypto';
|
|
24
|
+
import { fileURLToPath } from 'url';
|
|
25
|
+
|
|
26
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
27
|
+
const __dirname = path.dirname(__filename);
|
|
28
|
+
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// Configuration
|
|
31
|
+
// ============================================================================
|
|
32
|
+
|
|
33
|
+
const PROJECT_DIR = process.env.CLAUDE_PROJECT_DIR || path.resolve(__dirname, '..', '..');
|
|
34
|
+
const PROTECTED_ACTIONS_PATH = path.join(PROJECT_DIR, '.claude', 'hooks', 'protected-actions.json');
|
|
35
|
+
const PROTECTION_KEY_PATH = path.join(PROJECT_DIR, '.claude', 'protection-key');
|
|
36
|
+
|
|
37
|
+
// PreToolUse hooks receive tool info via environment variables
|
|
38
|
+
const toolName = process.env.TOOL_NAME || '';
|
|
39
|
+
const toolInput = process.env.TOOL_INPUT || '{}';
|
|
40
|
+
|
|
41
|
+
// ============================================================================
|
|
42
|
+
// HMAC Signing (Fix 2: Anti-Forgery)
|
|
43
|
+
// ============================================================================
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Load the protection key for HMAC signing.
|
|
47
|
+
* Returns null if key file doesn't exist (fail-closed handled by caller).
|
|
48
|
+
* @returns {string|null} Base64-encoded key or null
|
|
49
|
+
*/
|
|
50
|
+
function loadProtectionKey() {
|
|
51
|
+
try {
|
|
52
|
+
if (!fs.existsSync(PROTECTION_KEY_PATH)) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
return fs.readFileSync(PROTECTION_KEY_PATH, 'utf8').trim();
|
|
56
|
+
} catch (err) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Compute HMAC-SHA256 over pipe-delimited fields.
|
|
63
|
+
* @param {string} key - Base64-encoded key
|
|
64
|
+
* @param {...string} fields - Fields to include in HMAC
|
|
65
|
+
* @returns {string} Hex-encoded HMAC
|
|
66
|
+
*/
|
|
67
|
+
function computeHmac(key, ...fields) {
|
|
68
|
+
const keyBuffer = Buffer.from(key, 'base64');
|
|
69
|
+
return crypto.createHmac('sha256', keyBuffer)
|
|
70
|
+
.update(fields.join('|'))
|
|
71
|
+
.digest('hex');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ============================================================================
|
|
75
|
+
// MCP Tool Detection
|
|
76
|
+
// ============================================================================
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Parse MCP tool name into server and tool components
|
|
80
|
+
* Format: mcp__servername__toolname
|
|
81
|
+
* Server names use hyphens (not underscores), tool names use underscores.
|
|
82
|
+
* @param {string} name - Full tool name
|
|
83
|
+
* @returns {object|null} { server, tool } or null if not an MCP tool
|
|
84
|
+
*/
|
|
85
|
+
function parseMcpToolName(name) {
|
|
86
|
+
// Server name: alphanumeric + hyphens (no underscores)
|
|
87
|
+
// Tool name: alphanumeric + underscores + hyphens
|
|
88
|
+
const match = name.match(/^mcp__([a-zA-Z0-9-]+)__([a-zA-Z0-9_-]+)$/);
|
|
89
|
+
if (!match) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
return {
|
|
93
|
+
server: match[1],
|
|
94
|
+
tool: match[2],
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ============================================================================
|
|
99
|
+
// Protection Check
|
|
100
|
+
// ============================================================================
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Load protected actions configuration
|
|
104
|
+
* @returns {object} Config object with 'servers' property, or object with 'error' flag
|
|
105
|
+
*/
|
|
106
|
+
function loadProtectedActions() {
|
|
107
|
+
try {
|
|
108
|
+
if (!fs.existsSync(PROTECTED_ACTIONS_PATH)) {
|
|
109
|
+
// G001 Fail-Closed: Config missing = block all MCP actions
|
|
110
|
+
// An adversarial agent could delete this file to bypass protections (A4/C5)
|
|
111
|
+
return { servers: {}, notConfigured: true };
|
|
112
|
+
}
|
|
113
|
+
const config = JSON.parse(fs.readFileSync(PROTECTED_ACTIONS_PATH, 'utf8'));
|
|
114
|
+
if (!config.servers) {
|
|
115
|
+
config.servers = {};
|
|
116
|
+
}
|
|
117
|
+
return config;
|
|
118
|
+
} catch (err) {
|
|
119
|
+
// G001: Fail closed - if we can't read config, assume ALL MCP actions are blocked
|
|
120
|
+
// This prevents an adversary from corrupting the config to bypass protections
|
|
121
|
+
console.error(`[protected-action-gate] G001 FAIL-CLOSED: Config error, blocking all MCP actions: ${err.message}`);
|
|
122
|
+
return { error: true, message: err.message };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Check if a server:tool is protected
|
|
128
|
+
* @param {string} server - MCP server name
|
|
129
|
+
* @param {string} tool - Tool name
|
|
130
|
+
* @param {object} config - Protected actions config
|
|
131
|
+
* @returns {object|null} Protection config or null if not protected
|
|
132
|
+
*/
|
|
133
|
+
function getProtection(server, tool, config) {
|
|
134
|
+
if (!config || !config.servers || !config.servers[server]) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const serverConfig = config.servers[server];
|
|
139
|
+
|
|
140
|
+
// Check if this tool is protected
|
|
141
|
+
if (serverConfig.tools === '*') {
|
|
142
|
+
return serverConfig;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (Array.isArray(serverConfig.tools) && serverConfig.tools.includes(tool)) {
|
|
146
|
+
return serverConfig;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// ============================================================================
|
|
153
|
+
// Approval Check
|
|
154
|
+
// ============================================================================
|
|
155
|
+
|
|
156
|
+
const APPROVALS_PATH = path.join(PROJECT_DIR, '.claude', 'protected-action-approvals.json');
|
|
157
|
+
|
|
158
|
+
const LOCK_PATH = APPROVALS_PATH + '.lock';
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Acquire an advisory lock on the approvals file.
|
|
162
|
+
* Uses exclusive file creation (O_CREAT | O_EXCL) as a cross-process mutex.
|
|
163
|
+
* Retries with backoff for up to 2 seconds.
|
|
164
|
+
* @returns {boolean} true if lock acquired
|
|
165
|
+
*/
|
|
166
|
+
function acquireLock() {
|
|
167
|
+
const maxAttempts = 10;
|
|
168
|
+
const baseDelay = 50; // ms
|
|
169
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
170
|
+
try {
|
|
171
|
+
const fd = fs.openSync(LOCK_PATH, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY);
|
|
172
|
+
fs.writeSync(fd, String(process.pid));
|
|
173
|
+
fs.closeSync(fd);
|
|
174
|
+
return true;
|
|
175
|
+
} catch (err) {
|
|
176
|
+
// Check for stale lock (older than 10 seconds)
|
|
177
|
+
try {
|
|
178
|
+
const stat = fs.statSync(LOCK_PATH);
|
|
179
|
+
if (Date.now() - stat.mtimeMs > 10000) {
|
|
180
|
+
fs.unlinkSync(LOCK_PATH);
|
|
181
|
+
continue; // Retry immediately after removing stale lock
|
|
182
|
+
}
|
|
183
|
+
} catch { /* lock file gone, retry */ }
|
|
184
|
+
|
|
185
|
+
// Exponential backoff
|
|
186
|
+
const delay = baseDelay * Math.pow(2, i);
|
|
187
|
+
const start = Date.now();
|
|
188
|
+
while (Date.now() - start < delay) { /* busy wait */ }
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Release the advisory lock.
|
|
196
|
+
*/
|
|
197
|
+
function releaseLock() {
|
|
198
|
+
try {
|
|
199
|
+
fs.unlinkSync(LOCK_PATH);
|
|
200
|
+
} catch { /* already released */ }
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Load current approvals
|
|
205
|
+
* @returns {object}
|
|
206
|
+
*/
|
|
207
|
+
function loadApprovals() {
|
|
208
|
+
try {
|
|
209
|
+
if (!fs.existsSync(APPROVALS_PATH)) {
|
|
210
|
+
return { approvals: {} };
|
|
211
|
+
}
|
|
212
|
+
return JSON.parse(fs.readFileSync(APPROVALS_PATH, 'utf8'));
|
|
213
|
+
} catch (err) {
|
|
214
|
+
return { approvals: {} };
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Save approvals
|
|
220
|
+
* @param {object} approvals
|
|
221
|
+
*/
|
|
222
|
+
function saveApprovals(approvals) {
|
|
223
|
+
const dir = path.dirname(APPROVALS_PATH);
|
|
224
|
+
if (!fs.existsSync(dir)) {
|
|
225
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
226
|
+
}
|
|
227
|
+
fs.writeFileSync(APPROVALS_PATH, JSON.stringify(approvals, null, 2));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Check if there's a valid approval for this action.
|
|
232
|
+
* Verifies HMAC signatures to prevent agent forgery (Fix 2).
|
|
233
|
+
* Uses file locking to prevent TOCTOU race conditions on approval consumption.
|
|
234
|
+
* @param {string} server - MCP server name
|
|
235
|
+
* @param {string} tool - Tool name
|
|
236
|
+
* @param {object} args - Tool arguments (used to verify approval is scoped to these exact args)
|
|
237
|
+
* @returns {object|null} Approval if valid, null otherwise
|
|
238
|
+
*/
|
|
239
|
+
function checkApproval(server, tool, args) {
|
|
240
|
+
// Acquire lock to prevent TOCTOU race: two concurrent checks consuming same approval
|
|
241
|
+
if (!acquireLock()) {
|
|
242
|
+
console.error('[protected-action-gate] G001 FAIL-CLOSED: Could not acquire approvals lock. Blocking action.');
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
const approvals = loadApprovals();
|
|
248
|
+
const now = Date.now();
|
|
249
|
+
const key = loadProtectionKey();
|
|
250
|
+
let dirty = false;
|
|
251
|
+
|
|
252
|
+
// Hash the current call's arguments to verify they match the approved args
|
|
253
|
+
const argsHash = crypto.createHash('sha256')
|
|
254
|
+
.update(JSON.stringify(args || {}))
|
|
255
|
+
.digest('hex');
|
|
256
|
+
|
|
257
|
+
for (const [code, request] of Object.entries(approvals.approvals)) {
|
|
258
|
+
if (request.status !== 'approved') continue;
|
|
259
|
+
if (request.expires_timestamp < now) continue;
|
|
260
|
+
if (request.server !== server) continue;
|
|
261
|
+
if (request.tool !== tool) continue;
|
|
262
|
+
|
|
263
|
+
// Verify args match what was approved (prevents bait-and-switch attack)
|
|
264
|
+
if (request.argsHash && request.argsHash !== argsHash) {
|
|
265
|
+
continue; // Args don't match the approved request
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// HMAC verification (Fix 2): Verify signatures to prevent agent forgery
|
|
269
|
+
// argsHash is included in HMAC to bind approval to specific arguments
|
|
270
|
+
if (key) {
|
|
271
|
+
// Verify pending_hmac (was this request created by this hook with these args?)
|
|
272
|
+
const expectedPendingHmac = computeHmac(key, code, server, tool, request.argsHash || argsHash, String(request.expires_timestamp));
|
|
273
|
+
if (request.pending_hmac !== expectedPendingHmac) {
|
|
274
|
+
// Forged pending request - delete it
|
|
275
|
+
console.error(`[protected-action-gate] FORGERY DETECTED: Invalid pending_hmac for ${code}. Deleting.`);
|
|
276
|
+
delete approvals.approvals[code];
|
|
277
|
+
dirty = true;
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Verify approved_hmac (was this approval created by the approval hook?)
|
|
282
|
+
const expectedApprovedHmac = computeHmac(key, code, server, tool, 'approved', request.argsHash || argsHash, String(request.expires_timestamp));
|
|
283
|
+
if (request.approved_hmac !== expectedApprovedHmac) {
|
|
284
|
+
// Forged approval - delete it
|
|
285
|
+
console.error(`[protected-action-gate] FORGERY DETECTED: Invalid approved_hmac for ${code}. Deleting.`);
|
|
286
|
+
delete approvals.approvals[code];
|
|
287
|
+
dirty = true;
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
} else if (request.pending_hmac || request.approved_hmac) {
|
|
291
|
+
// G001 Fail-Closed: Request has HMAC fields but we can't verify them
|
|
292
|
+
// (protection key missing/unreadable). Reject rather than skip verification.
|
|
293
|
+
console.error(`[protected-action-gate] G001 FAIL-CLOSED: Cannot verify HMAC for ${code} (protection key missing). Skipping.`);
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// Found a valid, HMAC-verified approval - consume it (one-time use)
|
|
298
|
+
delete approvals.approvals[code];
|
|
299
|
+
saveApprovals(approvals);
|
|
300
|
+
|
|
301
|
+
return request;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Save if we deleted forged entries
|
|
305
|
+
if (dirty) {
|
|
306
|
+
saveApprovals(approvals);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return null;
|
|
310
|
+
} finally {
|
|
311
|
+
releaseLock();
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* Generate a 6-character alphanumeric approval code using crypto-secure randomness
|
|
317
|
+
* Excludes confusing characters: 0/O, 1/I/L
|
|
318
|
+
*/
|
|
319
|
+
function generateCode() {
|
|
320
|
+
const chars = 'ABCDEFGHJKMNPQRSTUVWXYZ23456789';
|
|
321
|
+
let code = '';
|
|
322
|
+
const randomBytes = crypto.randomBytes(6);
|
|
323
|
+
for (let i = 0; i < 6; i++) {
|
|
324
|
+
code += chars.charAt(randomBytes[i] % chars.length);
|
|
325
|
+
}
|
|
326
|
+
return code;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Create a pending approval request with HMAC signing (Fix 2).
|
|
331
|
+
* @param {string} server - MCP server name
|
|
332
|
+
* @param {string} tool - Tool name
|
|
333
|
+
* @param {object} args - Tool arguments
|
|
334
|
+
* @param {string} phrase - Approval phrase
|
|
335
|
+
* @param {object} [options] - Additional options
|
|
336
|
+
* @param {string} [options.approvalMode] - 'cto' (default) or 'deputy-cto'
|
|
337
|
+
* @returns {object} Request details
|
|
338
|
+
*/
|
|
339
|
+
function createRequest(server, tool, args, phrase, options = {}) {
|
|
340
|
+
const code = generateCode();
|
|
341
|
+
const now = Date.now();
|
|
342
|
+
const expiryMs = 5 * 60 * 1000; // 5 minutes
|
|
343
|
+
const expiresTimestamp = now + expiryMs;
|
|
344
|
+
|
|
345
|
+
// Hash the args to bind the approval to these specific arguments (prevents bait-and-switch)
|
|
346
|
+
const argsHash = crypto.createHash('sha256')
|
|
347
|
+
.update(JSON.stringify(args || {}))
|
|
348
|
+
.digest('hex');
|
|
349
|
+
|
|
350
|
+
// Compute HMAC for pending request (prevents agent forgery)
|
|
351
|
+
// Includes argsHash so approval is bound to exact arguments shown to CTO
|
|
352
|
+
const key = loadProtectionKey();
|
|
353
|
+
const pendingHmac = key ? computeHmac(key, code, server, tool, argsHash, String(expiresTimestamp)) : undefined;
|
|
354
|
+
|
|
355
|
+
// Acquire lock for atomic read-modify-write
|
|
356
|
+
if (!acquireLock()) {
|
|
357
|
+
console.error('[protected-action-gate] Warning: Could not acquire lock for createRequest. Proceeding without lock.');
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
try {
|
|
361
|
+
const approvals = loadApprovals();
|
|
362
|
+
approvals.approvals[code] = {
|
|
363
|
+
server,
|
|
364
|
+
tool,
|
|
365
|
+
args,
|
|
366
|
+
argsHash,
|
|
367
|
+
phrase,
|
|
368
|
+
code,
|
|
369
|
+
status: 'pending',
|
|
370
|
+
approval_mode: options.approvalMode || 'cto',
|
|
371
|
+
created_at: new Date(now).toISOString(),
|
|
372
|
+
created_timestamp: now,
|
|
373
|
+
expires_at: new Date(expiresTimestamp).toISOString(),
|
|
374
|
+
expires_timestamp: expiresTimestamp,
|
|
375
|
+
...(pendingHmac && { pending_hmac: pendingHmac }),
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
// Clean expired requests
|
|
379
|
+
const validApprovals = {};
|
|
380
|
+
for (const [key, val] of Object.entries(approvals.approvals)) {
|
|
381
|
+
if (val.expires_timestamp > now) {
|
|
382
|
+
validApprovals[key] = val;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
approvals.approvals = validApprovals;
|
|
386
|
+
|
|
387
|
+
saveApprovals(approvals);
|
|
388
|
+
} finally {
|
|
389
|
+
releaseLock();
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return {
|
|
393
|
+
code,
|
|
394
|
+
phrase,
|
|
395
|
+
message: `${phrase} ${code}`,
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// ============================================================================
|
|
400
|
+
// Main
|
|
401
|
+
// ============================================================================
|
|
402
|
+
|
|
403
|
+
function main() {
|
|
404
|
+
// Only check MCP tool calls
|
|
405
|
+
const mcpInfo = parseMcpToolName(toolName);
|
|
406
|
+
if (!mcpInfo) {
|
|
407
|
+
// Not an MCP tool, allow
|
|
408
|
+
process.exit(0);
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
// Load config
|
|
412
|
+
const config = loadProtectedActions();
|
|
413
|
+
|
|
414
|
+
// G001: If config is corrupted/unreadable, block ALL MCP actions
|
|
415
|
+
if (config.error) {
|
|
416
|
+
console.error('');
|
|
417
|
+
console.error('══════════════════════════════════════════════════════════════════════');
|
|
418
|
+
console.error(' G001 FAIL-CLOSED: Protected actions config is corrupted');
|
|
419
|
+
console.error('');
|
|
420
|
+
console.error(` Error: ${config.message}`);
|
|
421
|
+
console.error('');
|
|
422
|
+
console.error(' ALL MCP actions are blocked until config is fixed.');
|
|
423
|
+
console.error(' Fix the config file at: .claude/hooks/protected-actions.json');
|
|
424
|
+
console.error('══════════════════════════════════════════════════════════════════════');
|
|
425
|
+
console.error('');
|
|
426
|
+
process.exit(1);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// G001 Fail-Closed: If config file is missing, block ALL MCP actions
|
|
430
|
+
// This prevents attack A4/C5: agent deletes/moves config to bypass protections
|
|
431
|
+
if (config.notConfigured) {
|
|
432
|
+
console.error('');
|
|
433
|
+
console.error('══════════════════════════════════════════════════════════════════════');
|
|
434
|
+
console.error(' G001 FAIL-CLOSED: Protected actions config not found');
|
|
435
|
+
console.error('');
|
|
436
|
+
console.error(' File: .claude/hooks/protected-actions.json');
|
|
437
|
+
console.error(' ALL MCP actions are blocked until config is restored.');
|
|
438
|
+
console.error(' Run: setup.sh --path <project> to reinstall GENTYR');
|
|
439
|
+
console.error('══════════════════════════════════════════════════════════════════════');
|
|
440
|
+
console.error('');
|
|
441
|
+
process.exit(1);
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// Check if this action is protected
|
|
445
|
+
const protection = getProtection(mcpInfo.server, mcpInfo.tool, config);
|
|
446
|
+
if (!protection) {
|
|
447
|
+
// Not a protected tool — but is this a known server? (Fix 3: MCP Server Allowlist)
|
|
448
|
+
// 1. Server IS in config.servers but this specific tool isn't protected -> allow (unprotected tool on known server)
|
|
449
|
+
if (config.servers[mcpInfo.server]) {
|
|
450
|
+
process.exit(0);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// 2. Server IS in allowedUnprotectedServers -> allow (framework/internal server)
|
|
454
|
+
const allowedServers = config.allowedUnprotectedServers || [];
|
|
455
|
+
if (allowedServers.includes(mcpInfo.server)) {
|
|
456
|
+
process.exit(0);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// 3. Unknown server -> BLOCK (prevents MCP server aliasing attack C2)
|
|
460
|
+
console.error('');
|
|
461
|
+
console.error('══════════════════════════════════════════════════════════════════════');
|
|
462
|
+
console.error(' BLOCKED: Unrecognized MCP Server');
|
|
463
|
+
console.error('');
|
|
464
|
+
console.error(` Server: ${mcpInfo.server}`);
|
|
465
|
+
console.error(` Tool: ${mcpInfo.tool}`);
|
|
466
|
+
console.error('');
|
|
467
|
+
console.error(' This MCP server is not in the protected-actions.json config.');
|
|
468
|
+
console.error(' To allow this server, add it to "allowedUnprotectedServers"');
|
|
469
|
+
console.error(' or "servers" in .claude/hooks/protected-actions.json');
|
|
470
|
+
console.error('══════════════════════════════════════════════════════════════════════');
|
|
471
|
+
console.error('');
|
|
472
|
+
process.exit(1);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Parse tool arguments
|
|
476
|
+
let args = {};
|
|
477
|
+
try {
|
|
478
|
+
args = JSON.parse(toolInput);
|
|
479
|
+
} catch (err) {
|
|
480
|
+
// Can't parse args, but still need to check protection
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
// G001 Fail-Closed: If protection key is missing and we have protected actions,
|
|
484
|
+
// we cannot verify HMAC signatures. Block the action rather than allowing unsigned approvals.
|
|
485
|
+
const protectionKey = loadProtectionKey();
|
|
486
|
+
if (!protectionKey) {
|
|
487
|
+
console.error('');
|
|
488
|
+
console.error('══════════════════════════════════════════════════════════════════════');
|
|
489
|
+
console.error(' G001 FAIL-CLOSED: Protection key missing');
|
|
490
|
+
console.error('');
|
|
491
|
+
console.error(' File: .claude/protection-key');
|
|
492
|
+
console.error(' Cannot verify approval signatures without protection key.');
|
|
493
|
+
console.error(' Run: setup.sh --path <project> to reinstall GENTYR');
|
|
494
|
+
console.error('══════════════════════════════════════════════════════════════════════');
|
|
495
|
+
console.error('');
|
|
496
|
+
process.exit(1);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// Check for valid approval (HMAC-verified, args-scoped)
|
|
500
|
+
const approval = checkApproval(mcpInfo.server, mcpInfo.tool, args);
|
|
501
|
+
if (approval) {
|
|
502
|
+
// Has valid, HMAC-verified approval, allow
|
|
503
|
+
console.error(`[protected-action-gate] Approval verified for ${mcpInfo.server}:${mcpInfo.tool}`);
|
|
504
|
+
process.exit(0);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// Determine approval mode from protection config
|
|
508
|
+
const approvalMode = protection.protection || 'approval-only';
|
|
509
|
+
const isDeputyCtoMode = approvalMode === 'deputy-cto-approval';
|
|
510
|
+
|
|
511
|
+
// No approval - block and request one
|
|
512
|
+
const request = createRequest(mcpInfo.server, mcpInfo.tool, args, protection.phrase, {
|
|
513
|
+
approvalMode: isDeputyCtoMode ? 'deputy-cto' : 'cto',
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
// Output block message
|
|
517
|
+
console.error('');
|
|
518
|
+
console.error('══════════════════════════════════════════════════════════════════════');
|
|
519
|
+
if (isDeputyCtoMode) {
|
|
520
|
+
console.error(' PROTECTED ACTION BLOCKED: Deputy-CTO Approval Required');
|
|
521
|
+
} else {
|
|
522
|
+
console.error(' PROTECTED ACTION BLOCKED: CTO Approval Required');
|
|
523
|
+
}
|
|
524
|
+
console.error('');
|
|
525
|
+
console.error(` Server: ${mcpInfo.server}`);
|
|
526
|
+
console.error(` Tool: ${mcpInfo.tool}`);
|
|
527
|
+
console.error('');
|
|
528
|
+
if (Object.keys(args).length > 0) {
|
|
529
|
+
console.error(' Arguments:');
|
|
530
|
+
const argsStr = JSON.stringify(args, null, 2).split('\n');
|
|
531
|
+
argsStr.forEach(line => console.error(` ${line}`));
|
|
532
|
+
console.error('');
|
|
533
|
+
}
|
|
534
|
+
console.error(' ─────────────────────────────────────────────────────────────────────');
|
|
535
|
+
console.error('');
|
|
536
|
+
if (isDeputyCtoMode) {
|
|
537
|
+
console.error(` Request code: ${request.code}`);
|
|
538
|
+
console.error('');
|
|
539
|
+
console.error(' Submit a report to deputy-cto for triage:');
|
|
540
|
+
console.error(` mcp__agent-reports__report_to_deputy_cto`);
|
|
541
|
+
console.error(` title: "Protected Action Request: ${mcpInfo.server}.${mcpInfo.tool}"`);
|
|
542
|
+
console.error(` Include code ${request.code} in summary.`);
|
|
543
|
+
console.error('');
|
|
544
|
+
console.error(' Deputy-CTO can approve, deny, or escalate to CTO.');
|
|
545
|
+
console.error(' For CTO escalation, CTO must type:');
|
|
546
|
+
console.error(` ${request.message}`);
|
|
547
|
+
} else {
|
|
548
|
+
console.error(` To approve, CTO must type exactly:`);
|
|
549
|
+
console.error('');
|
|
550
|
+
console.error(` ${request.message}`);
|
|
551
|
+
}
|
|
552
|
+
console.error('');
|
|
553
|
+
console.error(' This code expires in 5 minutes.');
|
|
554
|
+
console.error(' After approval, retry this action.');
|
|
555
|
+
console.error('══════════════════════════════════════════════════════════════════════');
|
|
556
|
+
console.error('');
|
|
557
|
+
|
|
558
|
+
// Exit with error to block the tool call
|
|
559
|
+
process.exit(1);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
main();
|