clawsec 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +560 -0
- package/dist/bin/clawsec.d.ts +7 -0
- package/dist/bin/clawsec.d.ts.map +1 -0
- package/dist/bin/clawsec.js +12 -0
- package/dist/bin/clawsec.js.map +1 -0
- package/dist/src/actions/block.d.ts +22 -0
- package/dist/src/actions/block.d.ts.map +1 -0
- package/dist/src/actions/block.js +83 -0
- package/dist/src/actions/block.js.map +1 -0
- package/dist/src/actions/confirm.d.ts +35 -0
- package/dist/src/actions/confirm.d.ts.map +1 -0
- package/dist/src/actions/confirm.js +156 -0
- package/dist/src/actions/confirm.js.map +1 -0
- package/dist/src/actions/executor.d.ts +64 -0
- package/dist/src/actions/executor.d.ts.map +1 -0
- package/dist/src/actions/executor.js +114 -0
- package/dist/src/actions/executor.js.map +1 -0
- package/dist/src/actions/index.d.ts +13 -0
- package/dist/src/actions/index.d.ts.map +1 -0
- package/dist/src/actions/index.js +15 -0
- package/dist/src/actions/index.js.map +1 -0
- package/dist/src/actions/log.d.ts +19 -0
- package/dist/src/actions/log.d.ts.map +1 -0
- package/dist/src/actions/log.js +63 -0
- package/dist/src/actions/log.js.map +1 -0
- package/dist/src/actions/types.d.ts +85 -0
- package/dist/src/actions/types.d.ts.map +1 -0
- package/dist/src/actions/types.js +78 -0
- package/dist/src/actions/types.js.map +1 -0
- package/dist/src/actions/warn.d.ts +22 -0
- package/dist/src/actions/warn.d.ts.map +1 -0
- package/dist/src/actions/warn.js +84 -0
- package/dist/src/actions/warn.js.map +1 -0
- package/dist/src/approval/agent-confirm.d.ts +104 -0
- package/dist/src/approval/agent-confirm.d.ts.map +1 -0
- package/dist/src/approval/agent-confirm.js +173 -0
- package/dist/src/approval/agent-confirm.js.map +1 -0
- package/dist/src/approval/index.d.ts +14 -0
- package/dist/src/approval/index.d.ts.map +1 -0
- package/dist/src/approval/index.js +9 -0
- package/dist/src/approval/index.js.map +1 -0
- package/dist/src/approval/native.d.ts +56 -0
- package/dist/src/approval/native.d.ts.map +1 -0
- package/dist/src/approval/native.js +196 -0
- package/dist/src/approval/native.js.map +1 -0
- package/dist/src/approval/store.d.ts +88 -0
- package/dist/src/approval/store.d.ts.map +1 -0
- package/dist/src/approval/store.js +192 -0
- package/dist/src/approval/store.js.map +1 -0
- package/dist/src/approval/types.d.ts +119 -0
- package/dist/src/approval/types.d.ts.map +1 -0
- package/dist/src/approval/types.js +6 -0
- package/dist/src/approval/types.js.map +1 -0
- package/dist/src/approval/webhook.d.ts +170 -0
- package/dist/src/approval/webhook.d.ts.map +1 -0
- package/dist/src/approval/webhook.js +362 -0
- package/dist/src/approval/webhook.js.map +1 -0
- package/dist/src/cli/commands/audit.d.ts +43 -0
- package/dist/src/cli/commands/audit.d.ts.map +1 -0
- package/dist/src/cli/commands/audit.js +115 -0
- package/dist/src/cli/commands/audit.js.map +1 -0
- package/dist/src/cli/commands/feedback.d.ts +27 -0
- package/dist/src/cli/commands/feedback.d.ts.map +1 -0
- package/dist/src/cli/commands/feedback.js +228 -0
- package/dist/src/cli/commands/feedback.js.map +1 -0
- package/dist/src/cli/commands/index.d.ts +11 -0
- package/dist/src/cli/commands/index.d.ts.map +1 -0
- package/dist/src/cli/commands/index.js +13 -0
- package/dist/src/cli/commands/index.js.map +1 -0
- package/dist/src/cli/commands/status.d.ts +20 -0
- package/dist/src/cli/commands/status.d.ts.map +1 -0
- package/dist/src/cli/commands/status.js +122 -0
- package/dist/src/cli/commands/status.js.map +1 -0
- package/dist/src/cli/commands/test.d.ts +23 -0
- package/dist/src/cli/commands/test.d.ts.map +1 -0
- package/dist/src/cli/commands/test.js +134 -0
- package/dist/src/cli/commands/test.js.map +1 -0
- package/dist/src/cli/commands/types.d.ts +81 -0
- package/dist/src/cli/commands/types.d.ts.map +1 -0
- package/dist/src/cli/commands/types.js +6 -0
- package/dist/src/cli/commands/types.js.map +1 -0
- package/dist/src/cli/index.d.ts +17 -0
- package/dist/src/cli/index.d.ts.map +1 -0
- package/dist/src/cli/index.js +267 -0
- package/dist/src/cli/index.js.map +1 -0
- package/dist/src/config/defaults.d.ts +20 -0
- package/dist/src/config/defaults.d.ts.map +1 -0
- package/dist/src/config/defaults.js +123 -0
- package/dist/src/config/defaults.js.map +1 -0
- package/dist/src/config/index.d.ts +8 -0
- package/dist/src/config/index.d.ts.map +1 -0
- package/dist/src/config/index.js +41 -0
- package/dist/src/config/index.js.map +1 -0
- package/dist/src/config/loader.d.ts +99 -0
- package/dist/src/config/loader.d.ts.map +1 -0
- package/dist/src/config/loader.js +242 -0
- package/dist/src/config/loader.js.map +1 -0
- package/dist/src/config/schema.d.ts +627 -0
- package/dist/src/config/schema.d.ts.map +1 -0
- package/dist/src/config/schema.js +585 -0
- package/dist/src/config/schema.js.map +1 -0
- package/dist/src/detectors/destructive/cloud-detector.d.ts +51 -0
- package/dist/src/detectors/destructive/cloud-detector.d.ts.map +1 -0
- package/dist/src/detectors/destructive/cloud-detector.js +556 -0
- package/dist/src/detectors/destructive/cloud-detector.js.map +1 -0
- package/dist/src/detectors/destructive/code-detector.d.ts +59 -0
- package/dist/src/detectors/destructive/code-detector.d.ts.map +1 -0
- package/dist/src/detectors/destructive/code-detector.js +558 -0
- package/dist/src/detectors/destructive/code-detector.js.map +1 -0
- package/dist/src/detectors/destructive/index.d.ts +54 -0
- package/dist/src/detectors/destructive/index.d.ts.map +1 -0
- package/dist/src/detectors/destructive/index.js +168 -0
- package/dist/src/detectors/destructive/index.js.map +1 -0
- package/dist/src/detectors/destructive/shell-detector.d.ts +43 -0
- package/dist/src/detectors/destructive/shell-detector.d.ts.map +1 -0
- package/dist/src/detectors/destructive/shell-detector.js +302 -0
- package/dist/src/detectors/destructive/shell-detector.js.map +1 -0
- package/dist/src/detectors/destructive/types.d.ts +143 -0
- package/dist/src/detectors/destructive/types.d.ts.map +1 -0
- package/dist/src/detectors/destructive/types.js +6 -0
- package/dist/src/detectors/destructive/types.js.map +1 -0
- package/dist/src/detectors/exfiltration/cloud-detector.d.ts +51 -0
- package/dist/src/detectors/exfiltration/cloud-detector.d.ts.map +1 -0
- package/dist/src/detectors/exfiltration/cloud-detector.js +427 -0
- package/dist/src/detectors/exfiltration/cloud-detector.js.map +1 -0
- package/dist/src/detectors/exfiltration/http-detector.d.ts +47 -0
- package/dist/src/detectors/exfiltration/http-detector.d.ts.map +1 -0
- package/dist/src/detectors/exfiltration/http-detector.js +429 -0
- package/dist/src/detectors/exfiltration/http-detector.js.map +1 -0
- package/dist/src/detectors/exfiltration/index.d.ts +44 -0
- package/dist/src/detectors/exfiltration/index.d.ts.map +1 -0
- package/dist/src/detectors/exfiltration/index.js +118 -0
- package/dist/src/detectors/exfiltration/index.js.map +1 -0
- package/dist/src/detectors/exfiltration/network-detector.d.ts +55 -0
- package/dist/src/detectors/exfiltration/network-detector.d.ts.map +1 -0
- package/dist/src/detectors/exfiltration/network-detector.js +504 -0
- package/dist/src/detectors/exfiltration/network-detector.js.map +1 -0
- package/dist/src/detectors/exfiltration/types.d.ts +139 -0
- package/dist/src/detectors/exfiltration/types.d.ts.map +1 -0
- package/dist/src/detectors/exfiltration/types.js +6 -0
- package/dist/src/detectors/exfiltration/types.js.map +1 -0
- package/dist/src/detectors/purchase/domain-detector.d.ts +44 -0
- package/dist/src/detectors/purchase/domain-detector.d.ts.map +1 -0
- package/dist/src/detectors/purchase/domain-detector.js +296 -0
- package/dist/src/detectors/purchase/domain-detector.js.map +1 -0
- package/dist/src/detectors/purchase/form-detector.d.ts +27 -0
- package/dist/src/detectors/purchase/form-detector.d.ts.map +1 -0
- package/dist/src/detectors/purchase/form-detector.js +344 -0
- package/dist/src/detectors/purchase/form-detector.js.map +1 -0
- package/dist/src/detectors/purchase/index.d.ts +65 -0
- package/dist/src/detectors/purchase/index.d.ts.map +1 -0
- package/dist/src/detectors/purchase/index.js +216 -0
- package/dist/src/detectors/purchase/index.js.map +1 -0
- package/dist/src/detectors/purchase/spend-tracker.d.ts +132 -0
- package/dist/src/detectors/purchase/spend-tracker.d.ts.map +1 -0
- package/dist/src/detectors/purchase/spend-tracker.js +313 -0
- package/dist/src/detectors/purchase/spend-tracker.js.map +1 -0
- package/dist/src/detectors/purchase/types.d.ts +139 -0
- package/dist/src/detectors/purchase/types.d.ts.map +1 -0
- package/dist/src/detectors/purchase/types.js +6 -0
- package/dist/src/detectors/purchase/types.js.map +1 -0
- package/dist/src/detectors/purchase/url-detector.d.ts +31 -0
- package/dist/src/detectors/purchase/url-detector.d.ts.map +1 -0
- package/dist/src/detectors/purchase/url-detector.js +292 -0
- package/dist/src/detectors/purchase/url-detector.js.map +1 -0
- package/dist/src/detectors/secrets/api-key-detector.d.ts +30 -0
- package/dist/src/detectors/secrets/api-key-detector.d.ts.map +1 -0
- package/dist/src/detectors/secrets/api-key-detector.js +297 -0
- package/dist/src/detectors/secrets/api-key-detector.js.map +1 -0
- package/dist/src/detectors/secrets/index.d.ts +43 -0
- package/dist/src/detectors/secrets/index.d.ts.map +1 -0
- package/dist/src/detectors/secrets/index.js +261 -0
- package/dist/src/detectors/secrets/index.js.map +1 -0
- package/dist/src/detectors/secrets/pii-detector.d.ts +54 -0
- package/dist/src/detectors/secrets/pii-detector.d.ts.map +1 -0
- package/dist/src/detectors/secrets/pii-detector.js +286 -0
- package/dist/src/detectors/secrets/pii-detector.js.map +1 -0
- package/dist/src/detectors/secrets/token-detector.d.ts +51 -0
- package/dist/src/detectors/secrets/token-detector.d.ts.map +1 -0
- package/dist/src/detectors/secrets/token-detector.js +233 -0
- package/dist/src/detectors/secrets/token-detector.js.map +1 -0
- package/dist/src/detectors/secrets/types.d.ts +157 -0
- package/dist/src/detectors/secrets/types.d.ts.map +1 -0
- package/dist/src/detectors/secrets/types.js +6 -0
- package/dist/src/detectors/secrets/types.js.map +1 -0
- package/dist/src/detectors/website/category-detector.d.ts +22 -0
- package/dist/src/detectors/website/category-detector.d.ts.map +1 -0
- package/dist/src/detectors/website/category-detector.js +162 -0
- package/dist/src/detectors/website/category-detector.js.map +1 -0
- package/dist/src/detectors/website/index.d.ts +53 -0
- package/dist/src/detectors/website/index.d.ts.map +1 -0
- package/dist/src/detectors/website/index.js +232 -0
- package/dist/src/detectors/website/index.js.map +1 -0
- package/dist/src/detectors/website/pattern-matcher.d.ts +33 -0
- package/dist/src/detectors/website/pattern-matcher.d.ts.map +1 -0
- package/dist/src/detectors/website/pattern-matcher.js +121 -0
- package/dist/src/detectors/website/pattern-matcher.js.map +1 -0
- package/dist/src/detectors/website/types.d.ts +105 -0
- package/dist/src/detectors/website/types.d.ts.map +1 -0
- package/dist/src/detectors/website/types.js +6 -0
- package/dist/src/detectors/website/types.js.map +1 -0
- package/dist/src/engine/analyzer.d.ts +87 -0
- package/dist/src/engine/analyzer.d.ts.map +1 -0
- package/dist/src/engine/analyzer.js +427 -0
- package/dist/src/engine/analyzer.js.map +1 -0
- package/dist/src/engine/cache.d.ts +80 -0
- package/dist/src/engine/cache.d.ts.map +1 -0
- package/dist/src/engine/cache.js +167 -0
- package/dist/src/engine/cache.js.map +1 -0
- package/dist/src/engine/index.d.ts +11 -0
- package/dist/src/engine/index.d.ts.map +1 -0
- package/dist/src/engine/index.js +11 -0
- package/dist/src/engine/index.js.map +1 -0
- package/dist/src/engine/llm-client.d.ts +210 -0
- package/dist/src/engine/llm-client.d.ts.map +1 -0
- package/dist/src/engine/llm-client.js +506 -0
- package/dist/src/engine/llm-client.js.map +1 -0
- package/dist/src/engine/types.d.ts +163 -0
- package/dist/src/engine/types.d.ts.map +1 -0
- package/dist/src/engine/types.js +21 -0
- package/dist/src/engine/types.js.map +1 -0
- package/dist/src/feedback/index.d.ts +9 -0
- package/dist/src/feedback/index.d.ts.map +1 -0
- package/dist/src/feedback/index.js +8 -0
- package/dist/src/feedback/index.js.map +1 -0
- package/dist/src/feedback/learner.d.ts +222 -0
- package/dist/src/feedback/learner.d.ts.map +1 -0
- package/dist/src/feedback/learner.js +401 -0
- package/dist/src/feedback/learner.js.map +1 -0
- package/dist/src/feedback/store.d.ts +113 -0
- package/dist/src/feedback/store.d.ts.map +1 -0
- package/dist/src/feedback/store.js +228 -0
- package/dist/src/feedback/store.js.map +1 -0
- package/dist/src/feedback/types.d.ts +126 -0
- package/dist/src/feedback/types.d.ts.map +1 -0
- package/dist/src/feedback/types.js +6 -0
- package/dist/src/feedback/types.js.map +1 -0
- package/dist/src/hooks/before-agent-start/handler.d.ts +37 -0
- package/dist/src/hooks/before-agent-start/handler.d.ts.map +1 -0
- package/dist/src/hooks/before-agent-start/handler.js +109 -0
- package/dist/src/hooks/before-agent-start/handler.js.map +1 -0
- package/dist/src/hooks/before-agent-start/index.d.ts +8 -0
- package/dist/src/hooks/before-agent-start/index.d.ts.map +1 -0
- package/dist/src/hooks/before-agent-start/index.js +7 -0
- package/dist/src/hooks/before-agent-start/index.js.map +1 -0
- package/dist/src/hooks/before-agent-start/prompts.d.ts +48 -0
- package/dist/src/hooks/before-agent-start/prompts.d.ts.map +1 -0
- package/dist/src/hooks/before-agent-start/prompts.js +103 -0
- package/dist/src/hooks/before-agent-start/prompts.js.map +1 -0
- package/dist/src/hooks/before-tool-call/handler.d.ts +42 -0
- package/dist/src/hooks/before-tool-call/handler.d.ts.map +1 -0
- package/dist/src/hooks/before-tool-call/handler.js +226 -0
- package/dist/src/hooks/before-tool-call/handler.js.map +1 -0
- package/dist/src/hooks/before-tool-call/index.d.ts +7 -0
- package/dist/src/hooks/before-tool-call/index.d.ts.map +1 -0
- package/dist/src/hooks/before-tool-call/index.js +6 -0
- package/dist/src/hooks/before-tool-call/index.js.map +1 -0
- package/dist/src/hooks/tool-result-persist/filter.d.ts +72 -0
- package/dist/src/hooks/tool-result-persist/filter.d.ts.map +1 -0
- package/dist/src/hooks/tool-result-persist/filter.js +305 -0
- package/dist/src/hooks/tool-result-persist/filter.js.map +1 -0
- package/dist/src/hooks/tool-result-persist/handler.d.ts +49 -0
- package/dist/src/hooks/tool-result-persist/handler.d.ts.map +1 -0
- package/dist/src/hooks/tool-result-persist/handler.js +217 -0
- package/dist/src/hooks/tool-result-persist/handler.js.map +1 -0
- package/dist/src/hooks/tool-result-persist/index.d.ts +11 -0
- package/dist/src/hooks/tool-result-persist/index.d.ts.map +1 -0
- package/dist/src/hooks/tool-result-persist/index.js +11 -0
- package/dist/src/hooks/tool-result-persist/index.js.map +1 -0
- package/dist/src/index.d.ts +256 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +222 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/notifications/discord.d.ts +10 -0
- package/dist/src/notifications/discord.d.ts.map +1 -0
- package/dist/src/notifications/discord.js +218 -0
- package/dist/src/notifications/discord.js.map +1 -0
- package/dist/src/notifications/index.d.ts +37 -0
- package/dist/src/notifications/index.d.ts.map +1 -0
- package/dist/src/notifications/index.js +68 -0
- package/dist/src/notifications/index.js.map +1 -0
- package/dist/src/notifications/slack.d.ts +10 -0
- package/dist/src/notifications/slack.d.ts.map +1 -0
- package/dist/src/notifications/slack.js +218 -0
- package/dist/src/notifications/slack.js.map +1 -0
- package/dist/src/notifications/telegram.d.ts +10 -0
- package/dist/src/notifications/telegram.d.ts.map +1 -0
- package/dist/src/notifications/telegram.js +242 -0
- package/dist/src/notifications/telegram.js.map +1 -0
- package/dist/src/notifications/types.d.ts +119 -0
- package/dist/src/notifications/types.d.ts.map +1 -0
- package/dist/src/notifications/types.js +6 -0
- package/dist/src/notifications/types.js.map +1 -0
- package/dist/src/proxy/index.d.ts +8 -0
- package/dist/src/proxy/index.d.ts.map +1 -0
- package/dist/src/proxy/index.js +9 -0
- package/dist/src/proxy/index.js.map +1 -0
- package/dist/src/proxy/middleware.d.ts +55 -0
- package/dist/src/proxy/middleware.d.ts.map +1 -0
- package/dist/src/proxy/middleware.js +215 -0
- package/dist/src/proxy/middleware.js.map +1 -0
- package/dist/src/proxy/server.d.ts +57 -0
- package/dist/src/proxy/server.d.ts.map +1 -0
- package/dist/src/proxy/server.js +298 -0
- package/dist/src/proxy/server.js.map +1 -0
- package/dist/src/proxy/types.d.ts +136 -0
- package/dist/src/proxy/types.d.ts.map +1 -0
- package/dist/src/proxy/types.js +6 -0
- package/dist/src/proxy/types.js.map +1 -0
- package/dist/src/sanitization/index.d.ts +10 -0
- package/dist/src/sanitization/index.d.ts.map +1 -0
- package/dist/src/sanitization/index.js +9 -0
- package/dist/src/sanitization/index.js.map +1 -0
- package/dist/src/sanitization/patterns.d.ts +51 -0
- package/dist/src/sanitization/patterns.d.ts.map +1 -0
- package/dist/src/sanitization/patterns.js +266 -0
- package/dist/src/sanitization/patterns.js.map +1 -0
- package/dist/src/sanitization/scanner.d.ts +29 -0
- package/dist/src/sanitization/scanner.d.ts.map +1 -0
- package/dist/src/sanitization/scanner.js +328 -0
- package/dist/src/sanitization/scanner.js.map +1 -0
- package/dist/src/sanitization/types.d.ts +57 -0
- package/dist/src/sanitization/types.d.ts.map +1 -0
- package/dist/src/sanitization/types.js +5 -0
- package/dist/src/sanitization/types.js.map +1 -0
- package/openclaw.plugin.json +114 -0
- package/package.json +63 -0
- package/rules/builtin/README.md +139 -0
- package/rules/builtin/ai-services.yaml +70 -0
- package/rules/builtin/api-keys.yaml +64 -0
- package/rules/builtin/authentication.yaml +56 -0
- package/rules/builtin/aws-security.yaml +57 -0
- package/rules/builtin/azure-security.yaml +58 -0
- package/rules/builtin/cicd-security.yaml +64 -0
- package/rules/builtin/cloud-storage.yaml +64 -0
- package/rules/builtin/container-registry.yaml +55 -0
- package/rules/builtin/crypto-wallets.yaml +71 -0
- package/rules/builtin/database-nosql.yaml +58 -0
- package/rules/builtin/database-sql.yaml +62 -0
- package/rules/builtin/development-env.yaml +67 -0
- package/rules/builtin/docker.yaml +57 -0
- package/rules/builtin/filesystem.yaml +71 -0
- package/rules/builtin/financial-pci.yaml +61 -0
- package/rules/builtin/gcp-security.yaml +57 -0
- package/rules/builtin/git-operations.yaml +68 -0
- package/rules/builtin/healthcare-hipaa.yaml +64 -0
- package/rules/builtin/kubernetes.yaml +60 -0
- package/rules/builtin/messaging-services.yaml +53 -0
- package/rules/builtin/minimal.yaml +47 -0
- package/rules/builtin/mobile-development.yaml +61 -0
- package/rules/builtin/monitoring.yaml +63 -0
- package/rules/builtin/network-security.yaml +57 -0
- package/rules/builtin/package-managers.yaml +74 -0
- package/rules/builtin/payment-processing.yaml +66 -0
- package/rules/builtin/pii-protection.yaml +48 -0
- package/rules/builtin/production-strict.yaml +55 -0
- package/rules/builtin/secrets-management.yaml +63 -0
- package/rules/builtin/serverless.yaml +74 -0
- package/rules/builtin/ssh-security.yaml +66 -0
- package/rules/builtin/terraform.yaml +51 -0
- package/rules/builtin/web-security.yaml +62 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"learner.js","sourceRoot":"","sources":["../../../src/feedback/learner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feedback Store
|
|
3
|
+
* File-based storage for user feedback on detection accuracy
|
|
4
|
+
*/
|
|
5
|
+
import type { FeedbackEntry, FeedbackInput, FeedbackStatus, FeedbackStore, FeedbackType } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* File-based feedback storage implementation
|
|
8
|
+
*/
|
|
9
|
+
export declare class FileFeedbackStore implements FeedbackStore {
|
|
10
|
+
private entries;
|
|
11
|
+
private filePath;
|
|
12
|
+
private saveTimeout;
|
|
13
|
+
private loaded;
|
|
14
|
+
/**
|
|
15
|
+
* Create a new file-based feedback store
|
|
16
|
+
*
|
|
17
|
+
* @param projectRoot - Root directory of the project (default: current working directory)
|
|
18
|
+
* @param filename - Name of the storage file (default: feedback.json)
|
|
19
|
+
*/
|
|
20
|
+
constructor(projectRoot?: string, filename?: string);
|
|
21
|
+
/**
|
|
22
|
+
* Add a new feedback entry
|
|
23
|
+
*
|
|
24
|
+
* @param input - Feedback entry data (without id, timestamp, status)
|
|
25
|
+
* @returns The created feedback entry with generated fields
|
|
26
|
+
*/
|
|
27
|
+
add(input: FeedbackInput): FeedbackEntry;
|
|
28
|
+
/**
|
|
29
|
+
* Get a feedback entry by ID
|
|
30
|
+
*
|
|
31
|
+
* @param id - The feedback entry ID
|
|
32
|
+
* @returns The feedback entry or undefined if not found
|
|
33
|
+
*/
|
|
34
|
+
get(id: string): FeedbackEntry | undefined;
|
|
35
|
+
/**
|
|
36
|
+
* Get all feedback entries
|
|
37
|
+
*
|
|
38
|
+
* @returns Array of all feedback entries sorted by timestamp (newest first)
|
|
39
|
+
*/
|
|
40
|
+
getAll(): FeedbackEntry[];
|
|
41
|
+
/**
|
|
42
|
+
* Get feedback entries filtered by type
|
|
43
|
+
*
|
|
44
|
+
* @param type - The feedback type to filter by
|
|
45
|
+
* @returns Array of matching feedback entries sorted by timestamp (newest first)
|
|
46
|
+
*/
|
|
47
|
+
getByType(type: FeedbackType): FeedbackEntry[];
|
|
48
|
+
/**
|
|
49
|
+
* Update the status of a feedback entry
|
|
50
|
+
*
|
|
51
|
+
* @param id - The feedback entry ID
|
|
52
|
+
* @param status - The new status
|
|
53
|
+
* @param notes - Optional notes to add
|
|
54
|
+
* @returns True if the entry was updated, false if not found
|
|
55
|
+
*/
|
|
56
|
+
updateStatus(id: string, status: FeedbackStatus, notes?: string): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Remove a feedback entry
|
|
59
|
+
*
|
|
60
|
+
* @param id - The feedback entry ID
|
|
61
|
+
* @returns True if the entry was removed, false if not found
|
|
62
|
+
*/
|
|
63
|
+
remove(id: string): boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Save feedback entries to the storage file
|
|
66
|
+
*/
|
|
67
|
+
save(): Promise<void>;
|
|
68
|
+
/**
|
|
69
|
+
* Load feedback entries from the storage file
|
|
70
|
+
*/
|
|
71
|
+
load(): Promise<void>;
|
|
72
|
+
/**
|
|
73
|
+
* Check if the store has been loaded from disk
|
|
74
|
+
*/
|
|
75
|
+
isLoaded(): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Get the number of entries in the store
|
|
78
|
+
*/
|
|
79
|
+
size(): number;
|
|
80
|
+
/**
|
|
81
|
+
* Clear all entries from the store
|
|
82
|
+
* Note: Does not automatically save - call save() explicitly if needed
|
|
83
|
+
*/
|
|
84
|
+
clear(): void;
|
|
85
|
+
/**
|
|
86
|
+
* Get the storage file path
|
|
87
|
+
*/
|
|
88
|
+
getFilePath(): string;
|
|
89
|
+
/**
|
|
90
|
+
* Schedule a debounced save operation
|
|
91
|
+
*/
|
|
92
|
+
private scheduleSave;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get the global feedback store instance
|
|
96
|
+
*
|
|
97
|
+
* @param projectRoot - Optional project root to use for storage location
|
|
98
|
+
* @returns The global feedback store instance
|
|
99
|
+
*/
|
|
100
|
+
export declare function getFeedbackStore(projectRoot?: string): FileFeedbackStore;
|
|
101
|
+
/**
|
|
102
|
+
* Reset the global feedback store (primarily for testing)
|
|
103
|
+
*/
|
|
104
|
+
export declare function resetGlobalFeedbackStore(): void;
|
|
105
|
+
/**
|
|
106
|
+
* Create a new feedback store with a specific storage location
|
|
107
|
+
*
|
|
108
|
+
* @param projectRoot - Project root directory
|
|
109
|
+
* @param filename - Optional custom filename
|
|
110
|
+
* @returns A new FileFeedbackStore instance
|
|
111
|
+
*/
|
|
112
|
+
export declare function createFeedbackStore(projectRoot: string, filename?: string): FileFeedbackStore;
|
|
113
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/feedback/store.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,cAAc,EACd,aAAa,EACb,YAAY,EACb,MAAM,YAAY,CAAC;AAWpB;;GAEG;AACH,qBAAa,iBAAkB,YAAW,aAAa;IACrD,OAAO,CAAC,OAAO,CAAyC;IACxD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAA8C;IACjE,OAAO,CAAC,MAAM,CAAS;IAEvB;;;;;OAKG;gBACS,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM;IAMnD;;;;;OAKG;IACH,GAAG,CAAC,KAAK,EAAE,aAAa,GAAG,aAAa;IAcxC;;;;;OAKG;IACH,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI1C;;;;OAIG;IACH,MAAM,IAAI,aAAa,EAAE;IAKzB;;;;;OAKG;IACH,SAAS,CAAC,IAAI,EAAE,YAAY,GAAG,aAAa,EAAE;IAI9C;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO;IAezE;;;;;OAKG;IACH,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAQ3B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB3B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAqB3B;;OAEG;IACH,QAAQ,IAAI,OAAO;IAInB;;OAEG;IACH,IAAI,IAAI,MAAM;IAId;;;OAGG;IACH,KAAK,IAAI,IAAI;IAQb;;OAEG;IACH,WAAW,IAAI,MAAM;IAIrB;;OAEG;IACH,OAAO,CAAC,YAAY;CAWrB;AAQD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAKxE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAK/C;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAE7F"}
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feedback Store
|
|
3
|
+
* File-based storage for user feedback on detection accuracy
|
|
4
|
+
*/
|
|
5
|
+
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
6
|
+
import { dirname, join } from 'node:path';
|
|
7
|
+
import { randomUUID } from 'node:crypto';
|
|
8
|
+
/** Default storage directory relative to project root */
|
|
9
|
+
const DEFAULT_STORAGE_DIR = '.clawsec';
|
|
10
|
+
/** Default storage filename */
|
|
11
|
+
const DEFAULT_STORAGE_FILE = 'feedback.json';
|
|
12
|
+
/** Debounce delay for auto-save in milliseconds */
|
|
13
|
+
const SAVE_DEBOUNCE_MS = 1000;
|
|
14
|
+
/**
|
|
15
|
+
* File-based feedback storage implementation
|
|
16
|
+
*/
|
|
17
|
+
export class FileFeedbackStore {
|
|
18
|
+
entries = new Map();
|
|
19
|
+
filePath;
|
|
20
|
+
saveTimeout = null;
|
|
21
|
+
loaded = false;
|
|
22
|
+
/**
|
|
23
|
+
* Create a new file-based feedback store
|
|
24
|
+
*
|
|
25
|
+
* @param projectRoot - Root directory of the project (default: current working directory)
|
|
26
|
+
* @param filename - Name of the storage file (default: feedback.json)
|
|
27
|
+
*/
|
|
28
|
+
constructor(projectRoot, filename) {
|
|
29
|
+
const root = projectRoot ?? process.cwd();
|
|
30
|
+
const file = filename ?? DEFAULT_STORAGE_FILE;
|
|
31
|
+
this.filePath = join(root, DEFAULT_STORAGE_DIR, file);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Add a new feedback entry
|
|
35
|
+
*
|
|
36
|
+
* @param input - Feedback entry data (without id, timestamp, status)
|
|
37
|
+
* @returns The created feedback entry with generated fields
|
|
38
|
+
*/
|
|
39
|
+
add(input) {
|
|
40
|
+
const entry = {
|
|
41
|
+
...input,
|
|
42
|
+
id: randomUUID(),
|
|
43
|
+
timestamp: Date.now(),
|
|
44
|
+
status: 'pending',
|
|
45
|
+
};
|
|
46
|
+
this.entries.set(entry.id, entry);
|
|
47
|
+
this.scheduleSave();
|
|
48
|
+
return entry;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Get a feedback entry by ID
|
|
52
|
+
*
|
|
53
|
+
* @param id - The feedback entry ID
|
|
54
|
+
* @returns The feedback entry or undefined if not found
|
|
55
|
+
*/
|
|
56
|
+
get(id) {
|
|
57
|
+
return this.entries.get(id);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get all feedback entries
|
|
61
|
+
*
|
|
62
|
+
* @returns Array of all feedback entries sorted by timestamp (newest first)
|
|
63
|
+
*/
|
|
64
|
+
getAll() {
|
|
65
|
+
return Array.from(this.entries.values())
|
|
66
|
+
.sort((a, b) => b.timestamp - a.timestamp);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get feedback entries filtered by type
|
|
70
|
+
*
|
|
71
|
+
* @param type - The feedback type to filter by
|
|
72
|
+
* @returns Array of matching feedback entries sorted by timestamp (newest first)
|
|
73
|
+
*/
|
|
74
|
+
getByType(type) {
|
|
75
|
+
return this.getAll().filter(entry => entry.type === type);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Update the status of a feedback entry
|
|
79
|
+
*
|
|
80
|
+
* @param id - The feedback entry ID
|
|
81
|
+
* @param status - The new status
|
|
82
|
+
* @param notes - Optional notes to add
|
|
83
|
+
* @returns True if the entry was updated, false if not found
|
|
84
|
+
*/
|
|
85
|
+
updateStatus(id, status, notes) {
|
|
86
|
+
const entry = this.entries.get(id);
|
|
87
|
+
if (!entry) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
entry.status = status;
|
|
91
|
+
if (notes !== undefined) {
|
|
92
|
+
entry.notes = notes;
|
|
93
|
+
}
|
|
94
|
+
this.scheduleSave();
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Remove a feedback entry
|
|
99
|
+
*
|
|
100
|
+
* @param id - The feedback entry ID
|
|
101
|
+
* @returns True if the entry was removed, false if not found
|
|
102
|
+
*/
|
|
103
|
+
remove(id) {
|
|
104
|
+
const result = this.entries.delete(id);
|
|
105
|
+
if (result) {
|
|
106
|
+
this.scheduleSave();
|
|
107
|
+
}
|
|
108
|
+
return result;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Save feedback entries to the storage file
|
|
112
|
+
*/
|
|
113
|
+
async save() {
|
|
114
|
+
// Cancel any pending debounced save
|
|
115
|
+
if (this.saveTimeout) {
|
|
116
|
+
clearTimeout(this.saveTimeout);
|
|
117
|
+
this.saveTimeout = null;
|
|
118
|
+
}
|
|
119
|
+
// Ensure directory exists
|
|
120
|
+
await mkdir(dirname(this.filePath), { recursive: true });
|
|
121
|
+
// Convert entries to array for JSON serialization
|
|
122
|
+
const data = Array.from(this.entries.values());
|
|
123
|
+
const json = JSON.stringify(data, null, 2);
|
|
124
|
+
await writeFile(this.filePath, json, 'utf-8');
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Load feedback entries from the storage file
|
|
128
|
+
*/
|
|
129
|
+
async load() {
|
|
130
|
+
try {
|
|
131
|
+
const json = await readFile(this.filePath, 'utf-8');
|
|
132
|
+
const data = JSON.parse(json);
|
|
133
|
+
this.entries.clear();
|
|
134
|
+
for (const entry of data) {
|
|
135
|
+
this.entries.set(entry.id, entry);
|
|
136
|
+
}
|
|
137
|
+
this.loaded = true;
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
// File doesn't exist or is invalid - start with empty store
|
|
141
|
+
if (error.code !== 'ENOENT') {
|
|
142
|
+
// Log non-ENOENT errors for debugging
|
|
143
|
+
console.warn(`Warning: Could not load feedback store: ${error.message}`);
|
|
144
|
+
}
|
|
145
|
+
this.entries.clear();
|
|
146
|
+
this.loaded = true;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Check if the store has been loaded from disk
|
|
151
|
+
*/
|
|
152
|
+
isLoaded() {
|
|
153
|
+
return this.loaded;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Get the number of entries in the store
|
|
157
|
+
*/
|
|
158
|
+
size() {
|
|
159
|
+
return this.entries.size;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Clear all entries from the store
|
|
163
|
+
* Note: Does not automatically save - call save() explicitly if needed
|
|
164
|
+
*/
|
|
165
|
+
clear() {
|
|
166
|
+
this.entries.clear();
|
|
167
|
+
if (this.saveTimeout) {
|
|
168
|
+
clearTimeout(this.saveTimeout);
|
|
169
|
+
this.saveTimeout = null;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get the storage file path
|
|
174
|
+
*/
|
|
175
|
+
getFilePath() {
|
|
176
|
+
return this.filePath;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Schedule a debounced save operation
|
|
180
|
+
*/
|
|
181
|
+
scheduleSave() {
|
|
182
|
+
if (this.saveTimeout) {
|
|
183
|
+
clearTimeout(this.saveTimeout);
|
|
184
|
+
}
|
|
185
|
+
this.saveTimeout = setTimeout(() => {
|
|
186
|
+
this.save().catch(error => {
|
|
187
|
+
console.error(`Failed to save feedback store: ${error.message}`);
|
|
188
|
+
});
|
|
189
|
+
}, SAVE_DEBOUNCE_MS);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Global feedback store instance
|
|
194
|
+
* Lazily initialized on first access
|
|
195
|
+
*/
|
|
196
|
+
let globalStore = null;
|
|
197
|
+
/**
|
|
198
|
+
* Get the global feedback store instance
|
|
199
|
+
*
|
|
200
|
+
* @param projectRoot - Optional project root to use for storage location
|
|
201
|
+
* @returns The global feedback store instance
|
|
202
|
+
*/
|
|
203
|
+
export function getFeedbackStore(projectRoot) {
|
|
204
|
+
if (!globalStore) {
|
|
205
|
+
globalStore = new FileFeedbackStore(projectRoot);
|
|
206
|
+
}
|
|
207
|
+
return globalStore;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Reset the global feedback store (primarily for testing)
|
|
211
|
+
*/
|
|
212
|
+
export function resetGlobalFeedbackStore() {
|
|
213
|
+
if (globalStore) {
|
|
214
|
+
globalStore.clear();
|
|
215
|
+
}
|
|
216
|
+
globalStore = null;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Create a new feedback store with a specific storage location
|
|
220
|
+
*
|
|
221
|
+
* @param projectRoot - Project root directory
|
|
222
|
+
* @param filename - Optional custom filename
|
|
223
|
+
* @returns A new FileFeedbackStore instance
|
|
224
|
+
*/
|
|
225
|
+
export function createFeedbackStore(projectRoot, filename) {
|
|
226
|
+
return new FileFeedbackStore(projectRoot, filename);
|
|
227
|
+
}
|
|
228
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/feedback/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Feedback Types
|
|
3
|
+
* Type definitions for user feedback on detection accuracy
|
|
4
|
+
*/
|
|
5
|
+
import type { ThreatCategory } from '../engine/index.js';
|
|
6
|
+
import type { Severity } from '../config/index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Status of a feedback entry
|
|
9
|
+
*/
|
|
10
|
+
export type FeedbackStatus = 'pending' | 'reviewed' | 'applied';
|
|
11
|
+
/**
|
|
12
|
+
* Type of feedback
|
|
13
|
+
*/
|
|
14
|
+
export type FeedbackType = 'false-positive' | 'false-negative';
|
|
15
|
+
/**
|
|
16
|
+
* Detection context stored with false positive feedback
|
|
17
|
+
*/
|
|
18
|
+
export interface FeedbackDetectionContext {
|
|
19
|
+
/** Category of threat that was detected */
|
|
20
|
+
category: ThreatCategory;
|
|
21
|
+
/** Severity level of the detection */
|
|
22
|
+
severity: Severity;
|
|
23
|
+
/** Reason given for the detection */
|
|
24
|
+
reason: string;
|
|
25
|
+
/** Name of the tool that was blocked */
|
|
26
|
+
toolName: string;
|
|
27
|
+
/** Input parameters that triggered the detection */
|
|
28
|
+
toolInput: Record<string, unknown>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A feedback entry from a user
|
|
32
|
+
*/
|
|
33
|
+
export interface FeedbackEntry {
|
|
34
|
+
/** Unique identifier for this feedback */
|
|
35
|
+
id: string;
|
|
36
|
+
/** Type of feedback */
|
|
37
|
+
type: FeedbackType;
|
|
38
|
+
/** Unix timestamp when feedback was submitted */
|
|
39
|
+
timestamp: number;
|
|
40
|
+
/** Detection ID for false positives (links to audit log) */
|
|
41
|
+
detectionId?: string;
|
|
42
|
+
/** Full detection context for false positives */
|
|
43
|
+
detection?: FeedbackDetectionContext;
|
|
44
|
+
/** User description for false negatives */
|
|
45
|
+
description?: string;
|
|
46
|
+
/** Suggested category for false negatives */
|
|
47
|
+
suggestedCategory?: ThreatCategory;
|
|
48
|
+
/** Current status of the feedback */
|
|
49
|
+
status: FeedbackStatus;
|
|
50
|
+
/** Optional notes (e.g., from review process) */
|
|
51
|
+
notes?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Options for creating a false positive feedback entry
|
|
55
|
+
*/
|
|
56
|
+
export interface FalsePositiveOptions {
|
|
57
|
+
/** Detection ID from audit log */
|
|
58
|
+
detectionId: string;
|
|
59
|
+
/** Full detection context */
|
|
60
|
+
detection?: FeedbackDetectionContext;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Options for creating a false negative feedback entry
|
|
64
|
+
*/
|
|
65
|
+
export interface FalseNegativeOptions {
|
|
66
|
+
/** Description of what was missed */
|
|
67
|
+
description: string;
|
|
68
|
+
/** Suggested category for the missed threat */
|
|
69
|
+
suggestedCategory?: ThreatCategory;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Input for creating a new feedback entry (without auto-generated fields)
|
|
73
|
+
*/
|
|
74
|
+
export type FeedbackInput = Omit<FeedbackEntry, 'id' | 'timestamp' | 'status'>;
|
|
75
|
+
/**
|
|
76
|
+
* Interface for feedback storage operations
|
|
77
|
+
*/
|
|
78
|
+
export interface FeedbackStore {
|
|
79
|
+
/** Add a new feedback entry */
|
|
80
|
+
add(entry: FeedbackInput): FeedbackEntry;
|
|
81
|
+
/** Get a feedback entry by ID */
|
|
82
|
+
get(id: string): FeedbackEntry | undefined;
|
|
83
|
+
/** Get all feedback entries */
|
|
84
|
+
getAll(): FeedbackEntry[];
|
|
85
|
+
/** Get feedback entries by type */
|
|
86
|
+
getByType(type: FeedbackType): FeedbackEntry[];
|
|
87
|
+
/** Update the status of a feedback entry */
|
|
88
|
+
updateStatus(id: string, status: FeedbackStatus, notes?: string): boolean;
|
|
89
|
+
/** Remove a feedback entry */
|
|
90
|
+
remove(id: string): boolean;
|
|
91
|
+
/** Save feedback to persistent storage */
|
|
92
|
+
save(): Promise<void>;
|
|
93
|
+
/** Load feedback from persistent storage */
|
|
94
|
+
load(): Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Options for the feedback CLI command
|
|
98
|
+
*/
|
|
99
|
+
export interface FeedbackOptions {
|
|
100
|
+
/** Report a false positive by detection ID */
|
|
101
|
+
falsePositive?: string;
|
|
102
|
+
/** Report a false negative with description */
|
|
103
|
+
falseNegative?: string;
|
|
104
|
+
/** Suggested category for false negative */
|
|
105
|
+
category?: ThreatCategory;
|
|
106
|
+
/** List all feedback entries */
|
|
107
|
+
list?: boolean;
|
|
108
|
+
/** Filter list by type */
|
|
109
|
+
type?: FeedbackType;
|
|
110
|
+
/** Show details of a specific feedback entry */
|
|
111
|
+
show?: string;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Result of the feedback command
|
|
115
|
+
*/
|
|
116
|
+
export interface FeedbackResult {
|
|
117
|
+
/** Whether the operation was successful */
|
|
118
|
+
success: boolean;
|
|
119
|
+
/** Message to display to the user */
|
|
120
|
+
message: string;
|
|
121
|
+
/** Feedback entries (for list/show operations) */
|
|
122
|
+
entries?: FeedbackEntry[];
|
|
123
|
+
/** Single entry (for add/show operations) */
|
|
124
|
+
entry?: FeedbackEntry;
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/feedback/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/feedback/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Before Agent Start Hook Handler
|
|
3
|
+
*
|
|
4
|
+
* Hook handler that injects security context into the agent's system prompt
|
|
5
|
+
* when an agent session starts.
|
|
6
|
+
*/
|
|
7
|
+
import type { BeforeAgentStartHandler } from '../../index.js';
|
|
8
|
+
import type { ClawsecConfig } from '../../config/schema.js';
|
|
9
|
+
/**
|
|
10
|
+
* Options for creating a before-agent-start handler
|
|
11
|
+
*/
|
|
12
|
+
export interface BeforeAgentStartHandlerOptions {
|
|
13
|
+
/**
|
|
14
|
+
* Whether to inject security context into the system prompt
|
|
15
|
+
* @default true
|
|
16
|
+
*/
|
|
17
|
+
injectPrompt?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Create the before-agent-start handler
|
|
21
|
+
*
|
|
22
|
+
* This handler runs when an agent session starts and injects security context
|
|
23
|
+
* into the system prompt to help the agent understand:
|
|
24
|
+
* - What security protections are active
|
|
25
|
+
* - How to handle blocked actions
|
|
26
|
+
* - How to use agent-confirm for acknowledged risks
|
|
27
|
+
*
|
|
28
|
+
* @param config - Clawsec configuration
|
|
29
|
+
* @param options - Optional handler options
|
|
30
|
+
* @returns BeforeAgentStartHandler function
|
|
31
|
+
*/
|
|
32
|
+
export declare function createBeforeAgentStartHandler(config: ClawsecConfig, options?: BeforeAgentStartHandlerOptions): BeforeAgentStartHandler;
|
|
33
|
+
/**
|
|
34
|
+
* Create a default before-agent-start handler with default configuration
|
|
35
|
+
*/
|
|
36
|
+
export declare function createDefaultBeforeAgentStartHandler(): BeforeAgentStartHandler;
|
|
37
|
+
//# sourceMappingURL=handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../../src/hooks/before-agent-start/handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAGV,uBAAuB,EACxB,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG5D;;GAEG;AACH,MAAM,WAAW,8BAA8B;IAC7C;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,aAAa,EACrB,OAAO,CAAC,EAAE,8BAA8B,GACvC,uBAAuB,CAqBzB;AAED;;GAEG;AACH,wBAAgB,oCAAoC,IAAI,uBAAuB,CAmE9E"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Before Agent Start Hook Handler
|
|
3
|
+
*
|
|
4
|
+
* Hook handler that injects security context into the agent's system prompt
|
|
5
|
+
* when an agent session starts.
|
|
6
|
+
*/
|
|
7
|
+
import { buildSecurityContextPrompt } from './prompts.js';
|
|
8
|
+
/**
|
|
9
|
+
* Create the before-agent-start handler
|
|
10
|
+
*
|
|
11
|
+
* This handler runs when an agent session starts and injects security context
|
|
12
|
+
* into the system prompt to help the agent understand:
|
|
13
|
+
* - What security protections are active
|
|
14
|
+
* - How to handle blocked actions
|
|
15
|
+
* - How to use agent-confirm for acknowledged risks
|
|
16
|
+
*
|
|
17
|
+
* @param config - Clawsec configuration
|
|
18
|
+
* @param options - Optional handler options
|
|
19
|
+
* @returns BeforeAgentStartHandler function
|
|
20
|
+
*/
|
|
21
|
+
export function createBeforeAgentStartHandler(config, options) {
|
|
22
|
+
const injectPrompt = options?.injectPrompt ?? true;
|
|
23
|
+
return async (_context) => {
|
|
24
|
+
// If prompt injection is disabled via options, return empty result
|
|
25
|
+
if (!injectPrompt) {
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
// Build the security context prompt based on config
|
|
29
|
+
const systemPromptAddition = buildSecurityContextPrompt(config);
|
|
30
|
+
// Return the result with the prompt addition (if any)
|
|
31
|
+
if (systemPromptAddition) {
|
|
32
|
+
return {
|
|
33
|
+
systemPromptAddition,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return {};
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Create a default before-agent-start handler with default configuration
|
|
41
|
+
*/
|
|
42
|
+
export function createDefaultBeforeAgentStartHandler() {
|
|
43
|
+
const defaultConfig = {
|
|
44
|
+
version: '1.0',
|
|
45
|
+
global: {
|
|
46
|
+
enabled: true,
|
|
47
|
+
logLevel: 'info',
|
|
48
|
+
},
|
|
49
|
+
llm: {
|
|
50
|
+
enabled: true,
|
|
51
|
+
model: null,
|
|
52
|
+
},
|
|
53
|
+
rules: {
|
|
54
|
+
purchase: {
|
|
55
|
+
enabled: true,
|
|
56
|
+
severity: 'critical',
|
|
57
|
+
action: 'block',
|
|
58
|
+
spendLimits: { perTransaction: 100, daily: 500 },
|
|
59
|
+
domains: { mode: 'blocklist', blocklist: [] },
|
|
60
|
+
},
|
|
61
|
+
website: {
|
|
62
|
+
enabled: true,
|
|
63
|
+
mode: 'blocklist',
|
|
64
|
+
severity: 'high',
|
|
65
|
+
action: 'block',
|
|
66
|
+
blocklist: [],
|
|
67
|
+
allowlist: [],
|
|
68
|
+
},
|
|
69
|
+
destructive: {
|
|
70
|
+
enabled: true,
|
|
71
|
+
severity: 'critical',
|
|
72
|
+
action: 'confirm',
|
|
73
|
+
shell: { enabled: true },
|
|
74
|
+
cloud: { enabled: true },
|
|
75
|
+
code: { enabled: true },
|
|
76
|
+
},
|
|
77
|
+
secrets: {
|
|
78
|
+
enabled: true,
|
|
79
|
+
severity: 'critical',
|
|
80
|
+
action: 'block',
|
|
81
|
+
},
|
|
82
|
+
exfiltration: {
|
|
83
|
+
enabled: true,
|
|
84
|
+
severity: 'high',
|
|
85
|
+
action: 'block',
|
|
86
|
+
},
|
|
87
|
+
sanitization: {
|
|
88
|
+
enabled: true,
|
|
89
|
+
severity: 'high',
|
|
90
|
+
action: 'block',
|
|
91
|
+
minConfidence: 0.5,
|
|
92
|
+
redactMatches: false,
|
|
93
|
+
categories: {
|
|
94
|
+
instructionOverride: true,
|
|
95
|
+
systemLeak: true,
|
|
96
|
+
jailbreak: true,
|
|
97
|
+
encodedPayload: true,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
approval: {
|
|
102
|
+
native: { enabled: true, timeout: 300 },
|
|
103
|
+
agentConfirm: { enabled: true, parameterName: '_clawsec_confirm' },
|
|
104
|
+
webhook: { enabled: false, url: undefined, timeout: 30, headers: {} },
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
return createBeforeAgentStartHandler(defaultConfig);
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../../src/hooks/before-agent-start/handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAa1D;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,6BAA6B,CAC3C,MAAqB,EACrB,OAAwC;IAExC,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,IAAI,IAAI,CAAC;IAEnD,OAAO,KAAK,EAAE,QAA2B,EAAmC,EAAE;QAC5E,mEAAmE;QACnE,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,oDAAoD;QACpD,MAAM,oBAAoB,GAAG,0BAA0B,CAAC,MAAM,CAAC,CAAC;QAEhE,sDAAsD;QACtD,IAAI,oBAAoB,EAAE,CAAC;YACzB,OAAO;gBACL,oBAAoB;aACrB,CAAC;QACJ,CAAC;QAED,OAAO,EAAE,CAAC;IACZ,CAAC,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oCAAoC;IAClD,MAAM,aAAa,GAAkB;QACnC,OAAO,EAAE,KAAK;QACd,MAAM,EAAE;YACN,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,MAAM;SACjB;QACD,GAAG,EAAE;YACH,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,IAAI;SACZ;QACD,KAAK,EAAE;YACL,QAAQ,EAAE;gBACR,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,UAAU;gBACpB,MAAM,EAAE,OAAO;gBACf,WAAW,EAAE,EAAE,cAAc,EAAE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE;gBAChD,OAAO,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,SAAS,EAAE,EAAE,EAAE;aAC9C;YACD,OAAO,EAAE;gBACP,OAAO,EAAE,IAAI;gBACb,IAAI,EAAE,WAAW;gBACjB,QAAQ,EAAE,MAAM;gBAChB,MAAM,EAAE,OAAO;gBACf,SAAS,EAAE,EAAE;gBACb,SAAS,EAAE,EAAE;aACd;YACD,WAAW,EAAE;gBACX,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,UAAU;gBACpB,MAAM,EAAE,SAAS;gBACjB,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;gBACxB,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;gBACxB,IAAI,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE;aACxB;YACD,OAAO,EAAE;gBACP,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,UAAU;gBACpB,MAAM,EAAE,OAAO;aAChB;YACD,YAAY,EAAE;gBACZ,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,MAAM;gBAChB,MAAM,EAAE,OAAO;aAChB;YACD,YAAY,EAAE;gBACZ,OAAO,EAAE,IAAI;gBACb,QAAQ,EAAE,MAAM;gBAChB,MAAM,EAAE,OAAO;gBACf,aAAa,EAAE,GAAG;gBAClB,aAAa,EAAE,KAAK;gBACpB,UAAU,EAAE;oBACV,mBAAmB,EAAE,IAAI;oBACzB,UAAU,EAAE,IAAI;oBAChB,SAAS,EAAE,IAAI;oBACf,cAAc,EAAE,IAAI;iBACrB;aACF;SACF;QACD,QAAQ,EAAE;YACR,MAAM,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE;YACvC,YAAY,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,kBAAkB,EAAE;YAClE,OAAO,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE;SACtE;KACF,CAAC;IAEF,OAAO,6BAA6B,CAAC,aAAa,CAAC,CAAC;AACtD,CAAC"}
|