@ebowwa/coder 0.7.63 → 0.7.65
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/dist/core/__tests__/permissions.test.d.ts +12 -0
- package/dist/core/__tests__/permissions.test.d.ts.map +1 -0
- package/dist/core/__tests__/permissions.test.js +851 -0
- package/dist/core/agent-loop/__tests__/compaction.test.d.ts +5 -0
- package/dist/core/agent-loop/__tests__/compaction.test.d.ts.map +1 -0
- package/dist/core/agent-loop/__tests__/compaction.test.js +209 -0
- package/dist/core/agent-loop/__tests__/formatters.test.d.ts +5 -0
- package/dist/core/agent-loop/__tests__/formatters.test.d.ts.map +1 -0
- package/dist/core/agent-loop/__tests__/formatters.test.js +195 -0
- package/dist/core/agent-loop/__tests__/index.test.d.ts +5 -0
- package/dist/core/agent-loop/__tests__/index.test.d.ts.map +1 -0
- package/dist/core/agent-loop/__tests__/index.test.js +121 -0
- package/dist/core/agent-loop/__tests__/loop-state.test.d.ts +5 -0
- package/dist/core/agent-loop/__tests__/loop-state.test.d.ts.map +1 -0
- package/dist/core/agent-loop/__tests__/loop-state.test.js +340 -0
- package/dist/core/agent-loop/__tests__/message-builder.test.d.ts +5 -0
- package/dist/core/agent-loop/__tests__/message-builder.test.d.ts.map +1 -0
- package/dist/core/agent-loop/__tests__/message-builder.test.js +178 -0
- package/dist/core/agent-loop/__tests__/tool-executor.test.d.ts +5 -0
- package/dist/core/agent-loop/__tests__/tool-executor.test.d.ts.map +1 -0
- package/dist/core/agent-loop/__tests__/tool-executor.test.js +331 -0
- package/dist/core/agent-loop/compaction.d.ts +39 -0
- package/dist/core/agent-loop/compaction.d.ts.map +1 -0
- package/dist/core/agent-loop/compaction.js +51 -0
- package/dist/core/agent-loop/formatters.d.ts +21 -0
- package/dist/core/agent-loop/formatters.d.ts.map +1 -0
- package/dist/core/agent-loop/formatters.js +42 -0
- package/dist/core/agent-loop/index.d.ts +25 -0
- package/dist/core/agent-loop/index.d.ts.map +1 -0
- package/dist/core/agent-loop/index.js +83 -0
- package/dist/core/agent-loop/loop-state.d.ts +74 -0
- package/dist/core/agent-loop/loop-state.d.ts.map +1 -0
- package/dist/core/agent-loop/loop-state.js +147 -0
- package/dist/core/agent-loop/message-builder.d.ts +13 -0
- package/dist/core/agent-loop/message-builder.d.ts.map +1 -0
- package/dist/core/agent-loop/message-builder.js +49 -0
- package/dist/core/agent-loop/tool-executor.d.ts +23 -0
- package/dist/core/agent-loop/tool-executor.d.ts.map +1 -0
- package/dist/core/agent-loop/tool-executor.js +152 -0
- package/dist/core/agent-loop/turn-executor.d.ts +57 -0
- package/dist/core/agent-loop/turn-executor.d.ts.map +1 -0
- package/dist/core/agent-loop/turn-executor.js +124 -0
- package/dist/core/agent-loop/types.d.ts +141 -0
- package/dist/core/agent-loop/types.d.ts.map +1 -0
- package/dist/core/agent-loop/types.js +4 -0
- package/dist/core/agent-loop.d.ts +17 -0
- package/dist/core/agent-loop.d.ts.map +1 -0
- package/dist/core/agent-loop.js +16 -0
- package/dist/core/api-client-impl.d.ts +62 -0
- package/dist/core/api-client-impl.d.ts.map +1 -0
- package/dist/core/api-client-impl.js +479 -0
- package/dist/core/api-client.d.ts +6 -0
- package/dist/core/api-client.d.ts.map +1 -0
- package/dist/core/api-client.js +5 -0
- package/dist/core/checkpoints.d.ts +128 -0
- package/dist/core/checkpoints.d.ts.map +1 -0
- package/dist/core/checkpoints.js +438 -0
- package/dist/core/claude-md.d.ts +71 -0
- package/dist/core/claude-md.d.ts.map +1 -0
- package/dist/core/claude-md.js +198 -0
- package/dist/core/cognitive-security/hooks.d.ts +138 -0
- package/dist/core/cognitive-security/hooks.d.ts.map +1 -0
- package/dist/core/cognitive-security/hooks.js +389 -0
- package/dist/core/cognitive-security/index.d.ts +751 -0
- package/dist/core/cognitive-security/index.d.ts.map +1 -0
- package/dist/core/cognitive-security/index.js +1123 -0
- package/dist/core/cognitive-security/middleware.d.ts +136 -0
- package/dist/core/cognitive-security/middleware.d.ts.map +1 -0
- package/dist/core/cognitive-security/middleware.js +376 -0
- package/dist/core/config-loader.d.ts +127 -0
- package/dist/core/config-loader.d.ts.map +1 -0
- package/dist/core/config-loader.js +219 -0
- package/dist/core/context-compaction.d.ts +87 -0
- package/dist/core/context-compaction.d.ts.map +1 -0
- package/dist/core/context-compaction.js +428 -0
- package/dist/core/git-status.d.ts +25 -0
- package/dist/core/git-status.d.ts.map +1 -0
- package/dist/core/git-status.js +204 -0
- package/dist/core/image.d.ts +69 -0
- package/dist/core/image.d.ts.map +1 -0
- package/dist/core/image.js +290 -0
- package/dist/core/image.test.d.ts +2 -0
- package/dist/core/image.test.d.ts.map +1 -0
- package/dist/core/image.test.js +149 -0
- package/dist/core/models.d.ts +123 -0
- package/dist/core/models.d.ts.map +1 -0
- package/dist/core/models.js +325 -0
- package/dist/core/permissions.d.ts +81 -0
- package/dist/core/permissions.d.ts.map +1 -0
- package/dist/core/permissions.js +327 -0
- package/dist/core/retry.d.ts +25 -0
- package/dist/core/retry.d.ts.map +1 -0
- package/dist/core/retry.js +121 -0
- package/dist/core/session-store.d.ts +9 -0
- package/dist/core/session-store.d.ts.map +1 -0
- package/dist/core/session-store.js +10 -0
- package/dist/core/sessions/export.d.ts +47 -0
- package/dist/core/sessions/export.d.ts.map +1 -0
- package/dist/core/sessions/export.js +256 -0
- package/dist/core/sessions/index.d.ts +132 -0
- package/dist/core/sessions/index.d.ts.map +1 -0
- package/dist/core/sessions/index.js +442 -0
- package/dist/core/sessions/metadata.d.ts +77 -0
- package/dist/core/sessions/metadata.d.ts.map +1 -0
- package/dist/core/sessions/metadata.js +233 -0
- package/dist/core/sessions/persistence.d.ts +72 -0
- package/dist/core/sessions/persistence.d.ts.map +1 -0
- package/dist/core/sessions/persistence.js +201 -0
- package/dist/core/sessions/types.d.ts +110 -0
- package/dist/core/sessions/types.d.ts.map +1 -0
- package/dist/core/sessions/types.js +4 -0
- package/dist/core/stream-highlighter.d.ts +18 -0
- package/dist/core/stream-highlighter.d.ts.map +1 -0
- package/dist/core/stream-highlighter.js +916 -0
- package/dist/core/system-reminders.d.ts +89 -0
- package/dist/core/system-reminders.d.ts.map +1 -0
- package/dist/core/system-reminders.js +285 -0
- package/dist/ecosystem/hooks/__tests__/index.test.d.ts +5 -0
- package/dist/ecosystem/hooks/__tests__/index.test.d.ts.map +1 -0
- package/dist/ecosystem/hooks/__tests__/index.test.js +458 -0
- package/dist/ecosystem/hooks/index.d.ts +59 -0
- package/dist/ecosystem/hooks/index.d.ts.map +1 -0
- package/dist/ecosystem/hooks/index.js +294 -0
- package/dist/ecosystem/hooks/prompt-evaluator.d.ts +32 -0
- package/dist/ecosystem/hooks/prompt-evaluator.d.ts.map +1 -0
- package/dist/ecosystem/hooks/prompt-evaluator.js +229 -0
- package/dist/ecosystem/skills/index.d.ts +55 -0
- package/dist/ecosystem/skills/index.d.ts.map +1 -0
- package/dist/ecosystem/skills/index.js +258 -0
- package/dist/ecosystem/tools/__tests__/index.test.d.ts +7 -0
- package/dist/ecosystem/tools/__tests__/index.test.d.ts.map +1 -0
- package/dist/ecosystem/tools/__tests__/index.test.js +856 -0
- package/dist/ecosystem/tools/index.d.ts +24 -0
- package/dist/ecosystem/tools/index.d.ts.map +1 -0
- package/dist/ecosystem/tools/index.js +1709 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33688 -49712
- package/dist/interfaces/mcp/client.d.ts +40 -0
- package/dist/interfaces/mcp/client.d.ts.map +1 -0
- package/dist/interfaces/mcp/client.js +309 -0
- package/dist/interfaces/ui/index.d.ts +36 -0
- package/dist/interfaces/ui/index.d.ts.map +1 -0
- package/dist/interfaces/ui/index.js +61 -0
- package/dist/interfaces/ui/spinner.d.ts +140 -0
- package/dist/interfaces/ui/spinner.d.ts.map +1 -0
- package/dist/interfaces/ui/spinner.js +342 -0
- package/dist/interfaces/ui/terminal/cli/index.d.ts +12 -0
- package/dist/interfaces/ui/terminal/cli/index.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/cli/index.js +32012 -50526
- package/dist/interfaces/ui/terminal/native/README.md +53 -0
- package/dist/interfaces/ui/terminal/native/claude_code_native.darwin-x64.node +0 -0
- package/dist/interfaces/ui/terminal/native/claude_code_native.dylib +0 -0
- package/dist/interfaces/ui/terminal/native/index.d.ts +0 -0
- package/dist/interfaces/ui/terminal/native/index.darwin-arm64.node +0 -0
- package/dist/interfaces/ui/terminal/native/index.js +43 -0
- package/dist/interfaces/ui/terminal/native/index.node +0 -0
- package/dist/interfaces/ui/terminal/native/package.json +34 -0
- package/dist/interfaces/ui/terminal/shared/args.d.ts +39 -0
- package/dist/interfaces/ui/terminal/shared/args.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/shared/args.js +176 -0
- package/dist/interfaces/ui/terminal/shared/index.d.ts +11 -0
- package/dist/interfaces/ui/terminal/shared/index.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/shared/index.js +16 -0
- package/dist/interfaces/ui/terminal/shared/loading-state.d.ts +124 -0
- package/dist/interfaces/ui/terminal/shared/loading-state.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/shared/loading-state.js +246 -0
- package/dist/interfaces/ui/terminal/shared/query.d.ts +22 -0
- package/dist/interfaces/ui/terminal/shared/query.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/shared/query.js +100 -0
- package/dist/interfaces/ui/terminal/shared/setup.d.ts +33 -0
- package/dist/interfaces/ui/terminal/shared/setup.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/shared/setup.js +226 -0
- package/dist/interfaces/ui/terminal/shared/status-line.d.ts +117 -0
- package/dist/interfaces/ui/terminal/shared/status-line.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/shared/status-line.js +267 -0
- package/dist/interfaces/ui/terminal/shared/system-prompt.d.ts +38 -0
- package/dist/interfaces/ui/terminal/shared/system-prompt.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/shared/system-prompt.js +102 -0
- package/dist/interfaces/ui/terminal/tui/HelpPanel.d.ts +39 -0
- package/dist/interfaces/ui/terminal/tui/HelpPanel.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/HelpPanel.js +215 -0
- package/dist/interfaces/ui/terminal/tui/InputContext.d.ts +91 -0
- package/dist/interfaces/ui/terminal/tui/InputContext.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/InputContext.js +154 -0
- package/dist/interfaces/ui/terminal/tui/InputField.d.ts +18 -0
- package/dist/interfaces/ui/terminal/tui/InputField.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/InputField.js +41 -0
- package/dist/interfaces/ui/terminal/tui/InteractiveTUI.d.ts +16 -0
- package/dist/interfaces/ui/terminal/tui/InteractiveTUI.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/InteractiveTUI.js +451 -0
- package/dist/interfaces/ui/terminal/tui/MessageArea.d.ts +10 -0
- package/dist/interfaces/ui/terminal/tui/MessageArea.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/MessageArea.js +91 -0
- package/dist/interfaces/ui/terminal/tui/MessageStore.d.ts +48 -0
- package/dist/interfaces/ui/terminal/tui/MessageStore.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/MessageStore.js +151 -0
- package/dist/interfaces/ui/terminal/tui/StatusBar.d.ts +9 -0
- package/dist/interfaces/ui/terminal/tui/StatusBar.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/StatusBar.js +36 -0
- package/dist/interfaces/ui/terminal/tui/commands.d.ts +21 -0
- package/dist/interfaces/ui/terminal/tui/commands.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/commands.js +359 -0
- package/dist/interfaces/ui/terminal/tui/components/InteractiveElements.d.ts +115 -0
- package/dist/interfaces/ui/terminal/tui/components/InteractiveElements.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/components/InteractiveElements.js +306 -0
- package/dist/interfaces/ui/terminal/tui/components/MultilineInput.d.ts +92 -0
- package/dist/interfaces/ui/terminal/tui/components/MultilineInput.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/components/MultilineInput.js +399 -0
- package/dist/interfaces/ui/terminal/tui/components/PaneManager.d.ts +59 -0
- package/dist/interfaces/ui/terminal/tui/components/PaneManager.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/components/PaneManager.js +139 -0
- package/dist/interfaces/ui/terminal/tui/components/Sidebar.d.ts +68 -0
- package/dist/interfaces/ui/terminal/tui/components/Sidebar.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/components/Sidebar.js +340 -0
- package/dist/interfaces/ui/terminal/tui/components/index.d.ts +23 -0
- package/dist/interfaces/ui/terminal/tui/components/index.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/components/index.js +51 -0
- package/dist/interfaces/ui/terminal/tui/console.d.ts +20 -0
- package/dist/interfaces/ui/terminal/tui/console.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/console.js +46 -0
- package/dist/interfaces/ui/terminal/tui/index.d.ts +20 -0
- package/dist/interfaces/ui/terminal/tui/index.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/index.js +28 -0
- package/dist/interfaces/ui/terminal/tui/run.d.ts +13 -0
- package/dist/interfaces/ui/terminal/tui/run.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/run.js +31 -0
- package/dist/interfaces/ui/terminal/tui/spinner.d.ts +44 -0
- package/dist/interfaces/ui/terminal/tui/spinner.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/spinner.js +59 -0
- package/dist/interfaces/ui/terminal/tui/tui-app.d.ts +39 -0
- package/dist/interfaces/ui/terminal/tui/tui-app.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/tui-app.js +198 -0
- package/dist/interfaces/ui/terminal/tui/tui-footer.d.ts +167 -0
- package/dist/interfaces/ui/terminal/tui/tui-footer.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/tui-footer.js +330 -0
- package/dist/interfaces/ui/terminal/tui/types.d.ts +165 -0
- package/dist/interfaces/ui/terminal/tui/types.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/types.js +5 -0
- package/dist/interfaces/ui/terminal/tui/useInputHandler.d.ts +23 -0
- package/dist/interfaces/ui/terminal/tui/useInputHandler.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/useInputHandler.js +72 -0
- package/dist/interfaces/ui/terminal/tui/useNativeInput.d.ts +90 -0
- package/dist/interfaces/ui/terminal/tui/useNativeInput.d.ts.map +1 -0
- package/dist/interfaces/ui/terminal/tui/useNativeInput.js +188 -0
- package/dist/native/README.md +53 -0
- package/dist/native/claude_code_native.darwin-x64.node +0 -0
- package/dist/native/claude_code_native.dylib +0 -0
- package/dist/native/index.d.ts +0 -0
- package/dist/native/index.d.ts.map +1 -0
- package/dist/native/index.darwin-arm64.node +0 -0
- package/dist/native/index.js +43 -0
- package/dist/native/index.node +0 -0
- package/dist/native/package.json +34 -0
- package/dist/teammates/index.d.ts +161 -0
- package/dist/teammates/index.d.ts.map +1 -0
- package/dist/teammates/index.js +827 -0
- package/dist/types/index.d.ts +482 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +52 -0
- package/native/index.darwin-arm64.node +0 -0
- package/native/index.js +33 -19
- package/package.json +6 -3
- package/packages/src/core/__tests__/permissions.test.ts +1091 -0
- package/packages/src/core/agent-loop/__tests__/compaction.test.ts +283 -0
- package/packages/src/core/agent-loop/__tests__/formatters.test.ts +234 -0
- package/packages/src/core/agent-loop/__tests__/index.test.ts +162 -0
- package/packages/src/core/agent-loop/__tests__/loop-state.test.ts +413 -0
- package/packages/src/core/agent-loop/__tests__/message-builder.test.ts +229 -0
- package/packages/src/core/agent-loop/__tests__/tool-executor.test.ts +457 -0
- package/packages/src/core/agent-loop/compaction.ts +92 -0
- package/packages/src/core/agent-loop/formatters.ts +50 -0
- package/packages/src/core/agent-loop/index.ts +137 -0
- package/packages/src/core/agent-loop/loop-state.ts +187 -0
- package/packages/src/core/agent-loop/message-builder.ts +62 -0
- package/packages/src/core/agent-loop/tool-executor.ts +211 -0
- package/packages/src/core/agent-loop/turn-executor.ts +226 -0
- package/packages/src/core/agent-loop/types.ts +152 -0
- package/packages/src/core/agent-loop.ts +18 -0
- package/packages/src/core/api-client-impl.ts +729 -0
- package/packages/src/core/api-client.ts +6 -0
- package/packages/src/core/checkpoints.ts +606 -0
- package/packages/src/core/claude-md.ts +272 -0
- package/packages/src/core/cognitive-security/hooks.ts +591 -0
- package/packages/src/core/cognitive-security/index.ts +2041 -0
- package/packages/src/core/cognitive-security/middleware.ts +536 -0
- package/packages/src/core/config/todo +7 -0
- package/packages/src/core/config-loader.ts +324 -0
- package/packages/src/core/context/__tests__/integration.test.ts +334 -0
- package/packages/src/core/context/compaction.ts +170 -0
- package/packages/src/core/context/constants.ts +58 -0
- package/packages/src/core/context/extraction.ts +85 -0
- package/packages/src/core/context/index.ts +66 -0
- package/packages/src/core/context/summarization.ts +251 -0
- package/packages/src/core/context/token-estimation.ts +98 -0
- package/packages/src/core/context/types.ts +59 -0
- package/packages/src/core/git-status.ts +262 -0
- package/packages/src/core/image.test.ts +180 -0
- package/packages/src/core/image.ts +350 -0
- package/packages/src/core/lmdb.db +0 -0
- package/packages/src/core/lmdb.db-lock +0 -0
- package/packages/src/core/models.ts +507 -0
- package/packages/src/core/normalizers/todo +8 -0
- package/packages/src/core/permissions.ts +431 -0
- package/packages/src/core/providers/README.md +230 -0
- package/packages/src/core/providers/__tests__/providers.test.ts +135 -0
- package/packages/src/core/providers/index.ts +419 -0
- package/packages/src/core/providers/types.ts +132 -0
- package/packages/src/core/retry.ts +180 -0
- package/packages/src/core/session-store.ts +36 -0
- package/packages/src/core/sessions/export.ts +329 -0
- package/packages/src/core/sessions/index.ts +587 -0
- package/packages/src/core/sessions/metadata.ts +309 -0
- package/packages/src/core/sessions/persistence.ts +244 -0
- package/packages/src/core/sessions/types.ts +169 -0
- package/packages/src/core/stream-highlighter.ts +1123 -0
- package/packages/src/core/system-reminders.ts +402 -0
- package/packages/src/core/todo +8 -0
- package/packages/src/ecosystem/hooks/__tests__/index.test.ts +561 -0
- package/packages/src/ecosystem/hooks/index.ts +341 -0
- package/packages/src/ecosystem/hooks/prompt-evaluator.ts +300 -0
- package/packages/src/ecosystem/skills/index.ts +295 -0
- package/packages/src/ecosystem/tools/__tests__/index.test.ts +1335 -0
- package/packages/src/ecosystem/tools/index.ts +2051 -0
- package/packages/src/index.ts +141 -0
- package/packages/src/interfaces/mcp/client.ts +389 -0
- package/packages/src/interfaces/ui/index.ts +158 -0
- package/packages/src/interfaces/ui/lmdb.db +0 -0
- package/packages/src/interfaces/ui/lmdb.db-lock +0 -0
- package/packages/src/interfaces/ui/spinner.ts +451 -0
- package/packages/src/interfaces/ui/terminal/bridge/index.ts +370 -0
- package/packages/src/interfaces/ui/terminal/bridge/ipc.ts +829 -0
- package/packages/src/interfaces/ui/terminal/bridge/screen-export.ts +968 -0
- package/packages/src/interfaces/ui/terminal/bridge/types.ts +226 -0
- package/packages/src/interfaces/ui/terminal/bridge/useBridge.ts +210 -0
- package/packages/src/interfaces/ui/terminal/cli/bootstrap.ts +132 -0
- package/packages/src/interfaces/ui/terminal/cli/index.ts +415 -0
- package/packages/src/interfaces/ui/terminal/cli/interactive/index.ts +110 -0
- package/packages/src/interfaces/ui/terminal/cli/interactive/input-handler.ts +393 -0
- package/packages/src/interfaces/ui/terminal/cli/interactive/interactive-runner.ts +820 -0
- package/packages/src/interfaces/ui/terminal/cli/interactive/message-store.ts +299 -0
- package/packages/src/interfaces/ui/terminal/cli/interactive/types.ts +274 -0
- package/packages/src/interfaces/ui/terminal/lmdb.db +0 -0
- package/packages/src/interfaces/ui/terminal/lmdb.db-lock +0 -0
- package/packages/src/interfaces/ui/terminal/shared/args.ts +222 -0
- package/packages/src/interfaces/ui/terminal/shared/index.ts +84 -0
- package/packages/src/interfaces/ui/terminal/shared/loading-state.ts +322 -0
- package/packages/src/interfaces/ui/terminal/shared/query.ts +152 -0
- package/packages/src/interfaces/ui/terminal/shared/setup.ts +299 -0
- package/packages/src/interfaces/ui/terminal/shared/spinner-frames.ts +73 -0
- package/packages/src/interfaces/ui/terminal/shared/status-line.ts +366 -0
- package/packages/src/interfaces/ui/terminal/shared/system-prompt.ts +146 -0
- package/packages/src/lmdb.db +0 -0
- package/packages/src/lmdb.db-lock +0 -0
- package/packages/src/native/index.ts +2722 -0
- package/packages/src/native/tui_v2_types.ts +39 -0
- package/packages/src/teammates/coordination.test.ts +279 -0
- package/packages/src/teammates/coordination.ts +646 -0
- package/packages/src/teammates/index.ts +1052 -0
- package/packages/src/teammates/integration.test.ts +272 -0
- package/packages/src/teammates/runner.test.ts +235 -0
- package/packages/src/teammates/runner.ts +750 -0
- package/packages/src/teammates/schemas.ts +673 -0
- package/packages/src/types/index.ts +723 -0
|
@@ -0,0 +1,2041 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cognitive Security - Intent Module
|
|
3
|
+
*
|
|
4
|
+
* TypeScript bindings for the Rust cognitive security module.
|
|
5
|
+
* Provides intent preservation, alignment scoring, and corruption detection.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ===== Types =====
|
|
9
|
+
|
|
10
|
+
export interface AgentIntent {
|
|
11
|
+
id: string;
|
|
12
|
+
version: number;
|
|
13
|
+
identity: AgentIdentity;
|
|
14
|
+
purpose: AgentPurpose;
|
|
15
|
+
principles: AgentPrinciples;
|
|
16
|
+
signature?: string;
|
|
17
|
+
createdAt: number;
|
|
18
|
+
signedBy?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface AgentIdentity {
|
|
22
|
+
name: string;
|
|
23
|
+
description: string;
|
|
24
|
+
capabilities: string[];
|
|
25
|
+
constraints: string[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface AgentPurpose {
|
|
29
|
+
goals: Goal[];
|
|
30
|
+
nonGoals: string[];
|
|
31
|
+
boundaries: Boundary[];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface AgentPrinciples {
|
|
35
|
+
values: string[];
|
|
36
|
+
priorities: string[];
|
|
37
|
+
forbidden: string[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface Goal {
|
|
41
|
+
id: string;
|
|
42
|
+
description: string;
|
|
43
|
+
priority: "critical" | "high" | "medium" | "low";
|
|
44
|
+
measurable: boolean;
|
|
45
|
+
successCriteria?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export interface Boundary {
|
|
49
|
+
id: string;
|
|
50
|
+
description: string;
|
|
51
|
+
enforcement: "never" | "require_approval" | "log_only";
|
|
52
|
+
domain: string;
|
|
53
|
+
pattern?: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface ActionContext {
|
|
57
|
+
actionType: string;
|
|
58
|
+
domain: string;
|
|
59
|
+
operation: string;
|
|
60
|
+
target?: string;
|
|
61
|
+
params?: Record<string, unknown>;
|
|
62
|
+
reasoning?: string;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface AlignmentResult {
|
|
66
|
+
score: number;
|
|
67
|
+
reasoning: string;
|
|
68
|
+
servesGoals: string[];
|
|
69
|
+
hindersGoals: string[];
|
|
70
|
+
boundaryConcerns: string[];
|
|
71
|
+
confidence: number;
|
|
72
|
+
shouldBlock: boolean;
|
|
73
|
+
requiresReview: boolean;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface IntegrityResult {
|
|
77
|
+
valid: boolean;
|
|
78
|
+
error?: string;
|
|
79
|
+
signatureValid: boolean;
|
|
80
|
+
contentIntact: boolean;
|
|
81
|
+
expired: boolean;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface IntentKeypair {
|
|
85
|
+
privateKey: string;
|
|
86
|
+
publicKey: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface ValidationResult {
|
|
90
|
+
valid: boolean;
|
|
91
|
+
errors: string[];
|
|
92
|
+
warnings: string[];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ===== Behavior Tracking =====
|
|
96
|
+
|
|
97
|
+
export interface BehaviorSnapshot {
|
|
98
|
+
timestamp: number;
|
|
99
|
+
actionCount: number;
|
|
100
|
+
alignmentDistribution: AlignmentDistribution;
|
|
101
|
+
actionsByDomain: DomainCount[];
|
|
102
|
+
actionsByType: TypeCount[];
|
|
103
|
+
boundaryViolations: number;
|
|
104
|
+
actionsBlocked: number;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export interface AlignmentDistribution {
|
|
108
|
+
mean: number;
|
|
109
|
+
variance: number;
|
|
110
|
+
min: number;
|
|
111
|
+
max: number;
|
|
112
|
+
belowThresholdCount: number;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface DomainCount {
|
|
116
|
+
domain: string;
|
|
117
|
+
count: number;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface TypeCount {
|
|
121
|
+
actionType: string;
|
|
122
|
+
count: number;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface CorruptionAnalysis {
|
|
126
|
+
riskScore: number;
|
|
127
|
+
indicators: CorruptionIndicator[];
|
|
128
|
+
recommendation: "continue" | "monitor" | "alert" | "pause" | "reset" | "investigate";
|
|
129
|
+
explanation: string;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export interface CorruptionIndicator {
|
|
133
|
+
indicatorType: string;
|
|
134
|
+
severity: string;
|
|
135
|
+
description: string;
|
|
136
|
+
evidence: string;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export interface DriftResult {
|
|
140
|
+
overallDrift: number;
|
|
141
|
+
driftFactors: DriftFactor[];
|
|
142
|
+
concernLevel: "none" | "low" | "medium" | "high" | "critical";
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export interface DriftFactor {
|
|
146
|
+
factorType: string;
|
|
147
|
+
drift: number;
|
|
148
|
+
description: string;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ===== Native Bindings =====
|
|
152
|
+
|
|
153
|
+
import { native } from "../../native/index.js";
|
|
154
|
+
|
|
155
|
+
let nativeModule: any = null;
|
|
156
|
+
|
|
157
|
+
async function getNative() {
|
|
158
|
+
if (!nativeModule) {
|
|
159
|
+
// Use the already-loaded native module from src/native/index.ts
|
|
160
|
+
// which properly maps all functions including cognitive security
|
|
161
|
+
nativeModule = native;
|
|
162
|
+
}
|
|
163
|
+
return nativeModule;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// ===== Key Management =====
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Generate a new Ed25519 keypair for signing intents
|
|
170
|
+
*/
|
|
171
|
+
export async function generateKeypair(): Promise<IntentKeypair> {
|
|
172
|
+
const native = await getNative();
|
|
173
|
+
return native.cs_generate_keypair();
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ===== Signing & Verification =====
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Sign an agent intent with a private key
|
|
180
|
+
*/
|
|
181
|
+
export async function signIntent(
|
|
182
|
+
intent: AgentIntent,
|
|
183
|
+
privateKey: string
|
|
184
|
+
): Promise<AgentIntent> {
|
|
185
|
+
const native = await getNative();
|
|
186
|
+
return native.cs_sign_intent(intent, privateKey);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Verify an intent's signature
|
|
191
|
+
*/
|
|
192
|
+
export async function verifyIntent(intent: AgentIntent): Promise<IntegrityResult> {
|
|
193
|
+
const native = await getNative();
|
|
194
|
+
return native.cs_verify_intent(intent);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Hash an intent for comparison
|
|
199
|
+
*/
|
|
200
|
+
export async function hashIntent(intent: AgentIntent): Promise<string> {
|
|
201
|
+
const native = await getNative();
|
|
202
|
+
return native.cs_hash_intent(intent);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Check if two intents are equivalent (ignoring signatures)
|
|
207
|
+
*/
|
|
208
|
+
export async function intentsEquivalent(
|
|
209
|
+
intent1: AgentIntent,
|
|
210
|
+
intent2: AgentIntent
|
|
211
|
+
): Promise<boolean> {
|
|
212
|
+
const native = await getNative();
|
|
213
|
+
return native.cs_intents_equivalent(intent1, intent2);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// ===== Alignment Scoring =====
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Score how well an action aligns with an intent
|
|
220
|
+
*/
|
|
221
|
+
export async function scoreAlignment(
|
|
222
|
+
action: ActionContext,
|
|
223
|
+
intent: AgentIntent
|
|
224
|
+
): Promise<AlignmentResult> {
|
|
225
|
+
const native = await getNative();
|
|
226
|
+
return native.cs_score_alignment(action, intent);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Batch score multiple actions against an intent
|
|
231
|
+
*/
|
|
232
|
+
export async function batchScoreAlignment(
|
|
233
|
+
actions: ActionContext[],
|
|
234
|
+
intent: AgentIntent
|
|
235
|
+
): Promise<AlignmentResult[]> {
|
|
236
|
+
const native = await getNative();
|
|
237
|
+
return native.cs_batch_score_alignment(actions, intent);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Check if any action in a sequence would violate intent
|
|
242
|
+
*/
|
|
243
|
+
export async function checkSequenceViolations(
|
|
244
|
+
actions: ActionContext[],
|
|
245
|
+
intent: AgentIntent
|
|
246
|
+
): Promise<number[]> {
|
|
247
|
+
const native = await getNative();
|
|
248
|
+
return native.cs_check_sequence_violations(actions, intent);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// ===== Intent Management =====
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Load intent from a JSON file
|
|
255
|
+
*/
|
|
256
|
+
export async function loadIntent(path: string): Promise<AgentIntent> {
|
|
257
|
+
const native = await getNative();
|
|
258
|
+
return native.cs_load_intent(path);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Save intent to a JSON file
|
|
263
|
+
*/
|
|
264
|
+
export async function saveIntent(intent: AgentIntent, path: string): Promise<void> {
|
|
265
|
+
const native = await getNative();
|
|
266
|
+
return native.cs_save_intent(intent, path);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Parse intent from JSON string
|
|
271
|
+
*/
|
|
272
|
+
export async function parseIntent(json: string): Promise<AgentIntent> {
|
|
273
|
+
const native = await getNative();
|
|
274
|
+
return native.cs_parse_intent(json);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Serialize intent to JSON string
|
|
279
|
+
*/
|
|
280
|
+
export async function serializeIntent(intent: AgentIntent): Promise<string> {
|
|
281
|
+
const native = await getNative();
|
|
282
|
+
return native.cs_serialize_intent(intent);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Validate intent structure
|
|
287
|
+
*/
|
|
288
|
+
export async function validateIntent(intent: AgentIntent): Promise<ValidationResult> {
|
|
289
|
+
const native = await getNative();
|
|
290
|
+
return native.cs_validate_intent(intent);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Create a default data collector intent
|
|
295
|
+
*/
|
|
296
|
+
export async function createDataCollectorIntent(
|
|
297
|
+
name: string,
|
|
298
|
+
description: string
|
|
299
|
+
): Promise<AgentIntent> {
|
|
300
|
+
const native = await getNative();
|
|
301
|
+
return native.cs_create_data_collector_intent(name, description);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Merge two intents (child overrides parent)
|
|
306
|
+
*/
|
|
307
|
+
export async function mergeIntents(
|
|
308
|
+
base: AgentIntent,
|
|
309
|
+
override: AgentIntent
|
|
310
|
+
): Promise<AgentIntent> {
|
|
311
|
+
const native = await getNative();
|
|
312
|
+
return native.cs_merge_intents(base, override);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// ===== Corruption Detection =====
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Analyze behavior for signs of intent corruption
|
|
319
|
+
*/
|
|
320
|
+
export async function analyzeCorruption(
|
|
321
|
+
snapshot: BehaviorSnapshot,
|
|
322
|
+
intent: AgentIntent
|
|
323
|
+
): Promise<CorruptionAnalysis> {
|
|
324
|
+
const native = await getNative();
|
|
325
|
+
return native.cs_analyze_corruption(snapshot, intent);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Detect behavioral drift between two snapshots
|
|
330
|
+
*/
|
|
331
|
+
export async function detectDrift(
|
|
332
|
+
baseline: BehaviorSnapshot,
|
|
333
|
+
current: BehaviorSnapshot
|
|
334
|
+
): Promise<DriftResult> {
|
|
335
|
+
const native = await getNative();
|
|
336
|
+
return native.cs_detect_drift(baseline, current);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Create an empty behavior snapshot
|
|
341
|
+
*/
|
|
342
|
+
export async function createEmptySnapshot(): Promise<BehaviorSnapshot> {
|
|
343
|
+
const native = await getNative();
|
|
344
|
+
return native.cs_create_empty_snapshot();
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Update a snapshot with a new action result
|
|
349
|
+
*/
|
|
350
|
+
export async function updateSnapshot(
|
|
351
|
+
snapshot: BehaviorSnapshot,
|
|
352
|
+
action: ActionContext,
|
|
353
|
+
alignment: AlignmentResult
|
|
354
|
+
): Promise<BehaviorSnapshot> {
|
|
355
|
+
const native = await getNative();
|
|
356
|
+
return native.cs_update_snapshot(snapshot, action, alignment);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// ===== Action Module Types =====
|
|
360
|
+
|
|
361
|
+
export type ActionType =
|
|
362
|
+
| "modify"
|
|
363
|
+
| "execute"
|
|
364
|
+
| "communicate"
|
|
365
|
+
| "transfer"
|
|
366
|
+
| "observe"
|
|
367
|
+
| "create"
|
|
368
|
+
| "delete";
|
|
369
|
+
|
|
370
|
+
export type FlowDirection = "inbound" | "outbound" | "bidirectional";
|
|
371
|
+
|
|
372
|
+
export interface ClassifiedAction {
|
|
373
|
+
id: string;
|
|
374
|
+
actionType: string;
|
|
375
|
+
domain: string;
|
|
376
|
+
operation: string;
|
|
377
|
+
target?: string;
|
|
378
|
+
flowDirection: string;
|
|
379
|
+
riskLevel: number;
|
|
380
|
+
hasSideEffects: boolean;
|
|
381
|
+
requiresApproval: boolean;
|
|
382
|
+
reasoning?: string;
|
|
383
|
+
timestamp: number;
|
|
384
|
+
metadata?: string;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export interface ActionValidationResult {
|
|
388
|
+
allowed: boolean;
|
|
389
|
+
classification?: ClassifiedAction;
|
|
390
|
+
reason: string;
|
|
391
|
+
violatedPolicy?: string;
|
|
392
|
+
approvalRequired: boolean;
|
|
393
|
+
approvalToken?: string;
|
|
394
|
+
alternatives: string[];
|
|
395
|
+
confidence: number;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
export interface ActionPolicy {
|
|
399
|
+
id: string;
|
|
400
|
+
description: string;
|
|
401
|
+
actionTypes: string[];
|
|
402
|
+
domains: string[];
|
|
403
|
+
operations: string[];
|
|
404
|
+
effect: "allow" | "deny" | "require_approval";
|
|
405
|
+
priority: number;
|
|
406
|
+
conditions?: string;
|
|
407
|
+
enabled: boolean;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export interface ActionContextForValidation {
|
|
411
|
+
actionType: string;
|
|
412
|
+
domain: string;
|
|
413
|
+
operation: string;
|
|
414
|
+
target?: string;
|
|
415
|
+
params?: string;
|
|
416
|
+
reasoning?: string;
|
|
417
|
+
sessionId?: string;
|
|
418
|
+
parentActionId?: string;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
export interface ApprovalRequest {
|
|
422
|
+
id: string;
|
|
423
|
+
actionId: string;
|
|
424
|
+
classification: ClassifiedAction;
|
|
425
|
+
context: ActionContextForValidation;
|
|
426
|
+
createdAt: number;
|
|
427
|
+
expiresAt: number;
|
|
428
|
+
status: "pending" | "approved" | "denied" | "cancelled";
|
|
429
|
+
decidedBy?: string;
|
|
430
|
+
decidedAt?: number;
|
|
431
|
+
reason?: string;
|
|
432
|
+
priority: number;
|
|
433
|
+
escalationLevel: number;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
export interface ApprovalStats {
|
|
437
|
+
pendingCount: number;
|
|
438
|
+
approvedCount: number;
|
|
439
|
+
deniedCount: number;
|
|
440
|
+
cancelledCount: number;
|
|
441
|
+
totalProcessed: number;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
export interface AuditEntry {
|
|
445
|
+
id: string;
|
|
446
|
+
sequence: number;
|
|
447
|
+
timestamp: number;
|
|
448
|
+
action: ClassifiedAction;
|
|
449
|
+
validation: ActionValidationResult;
|
|
450
|
+
executed: boolean;
|
|
451
|
+
executionResult?: string;
|
|
452
|
+
sessionId?: string;
|
|
453
|
+
agentId?: string;
|
|
454
|
+
correlationId?: string;
|
|
455
|
+
metadata?: string;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
export interface AuditStats {
|
|
459
|
+
totalEntries: number;
|
|
460
|
+
blockedCount: number;
|
|
461
|
+
executedCount: number;
|
|
462
|
+
byActionType: { actionType: string; count: number }[];
|
|
463
|
+
byDomain: { domain: string; count: number }[];
|
|
464
|
+
firstTimestamp: number;
|
|
465
|
+
lastTimestamp: number;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export interface ActionRiskInfo {
|
|
469
|
+
actionType: string;
|
|
470
|
+
riskLevel: number;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// ===== Domain Configs =====
|
|
474
|
+
|
|
475
|
+
export interface FileDomainConfig {
|
|
476
|
+
protectedPaths: string[];
|
|
477
|
+
readOnlyPaths: string[];
|
|
478
|
+
largeFileThreshold: number;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
export interface NetworkDomainConfig {
|
|
482
|
+
allowedHosts: string[];
|
|
483
|
+
blockedHosts: string[];
|
|
484
|
+
requireApprovalExternal: boolean;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
export interface ShellDomainConfig {
|
|
488
|
+
allowedCommands: string[];
|
|
489
|
+
blockedCommands: string[];
|
|
490
|
+
requireApproval: boolean;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// ===== Action Classification =====
|
|
494
|
+
|
|
495
|
+
/**
|
|
496
|
+
* Classify an operation into an action type
|
|
497
|
+
*/
|
|
498
|
+
export async function classifyOperation(
|
|
499
|
+
operation: string,
|
|
500
|
+
domain: string,
|
|
501
|
+
target?: string,
|
|
502
|
+
reasoning?: string
|
|
503
|
+
): Promise<ClassifiedAction> {
|
|
504
|
+
const native = await getNative();
|
|
505
|
+
return native.classify_operation(operation, domain, target, reasoning);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Get all supported action types
|
|
510
|
+
*/
|
|
511
|
+
export async function getActionTypes(): Promise<string[]> {
|
|
512
|
+
const native = await getNative();
|
|
513
|
+
return native.get_action_types();
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* Get risk levels for all action types
|
|
518
|
+
*/
|
|
519
|
+
export async function getActionRiskLevels(): Promise<ActionRiskInfo[]> {
|
|
520
|
+
const native = await getNative();
|
|
521
|
+
return native.get_action_risk_levels();
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// ===== Action Validation =====
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* Create a deny-all policy
|
|
528
|
+
*/
|
|
529
|
+
export async function createDenyAllPolicy(): Promise<ActionPolicy> {
|
|
530
|
+
const native = await getNative();
|
|
531
|
+
return native.create_deny_all_policy();
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Create an observe-only policy
|
|
536
|
+
*/
|
|
537
|
+
export async function createObserveOnlyPolicy(): Promise<ActionPolicy> {
|
|
538
|
+
const native = await getNative();
|
|
539
|
+
return native.create_observe_only_policy();
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Create a transfer approval policy
|
|
544
|
+
*/
|
|
545
|
+
export async function createTransferApprovalPolicy(): Promise<ActionPolicy> {
|
|
546
|
+
const native = await getNative();
|
|
547
|
+
return native.create_transfer_approval_policy();
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
// ===== Domain Configs =====
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Create file domain configuration
|
|
554
|
+
*/
|
|
555
|
+
export async function createFileDomainConfig(): Promise<FileDomainConfig> {
|
|
556
|
+
const native = await getNative();
|
|
557
|
+
return native.create_file_domain_config();
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
/**
|
|
561
|
+
* Create network domain configuration
|
|
562
|
+
*/
|
|
563
|
+
export async function createNetworkDomainConfig(): Promise<NetworkDomainConfig> {
|
|
564
|
+
const native = await getNative();
|
|
565
|
+
return native.create_network_domain_config();
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Create shell domain configuration
|
|
570
|
+
*/
|
|
571
|
+
export async function createShellDomainConfig(): Promise<ShellDomainConfig> {
|
|
572
|
+
const native = await getNative();
|
|
573
|
+
return native.create_shell_domain_config();
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
// ===== Flow Control Types =====
|
|
577
|
+
|
|
578
|
+
export type SensitivityLevelType = "public" | "internal" | "confidential" | "secret" | "top_secret";
|
|
579
|
+
|
|
580
|
+
export type DataCategoryType =
|
|
581
|
+
| "pii"
|
|
582
|
+
| "financial"
|
|
583
|
+
| "credentials"
|
|
584
|
+
| "secrets"
|
|
585
|
+
| "source_code"
|
|
586
|
+
| "configuration"
|
|
587
|
+
| "logs"
|
|
588
|
+
| "user_content"
|
|
589
|
+
| "system_data"
|
|
590
|
+
| "network_data"
|
|
591
|
+
| "generic";
|
|
592
|
+
|
|
593
|
+
export interface ClassifiedData {
|
|
594
|
+
id: string;
|
|
595
|
+
sensitivity: string;
|
|
596
|
+
category: string;
|
|
597
|
+
source: string;
|
|
598
|
+
tags: string[];
|
|
599
|
+
can_log: boolean;
|
|
600
|
+
can_transmit: boolean;
|
|
601
|
+
can_store: boolean;
|
|
602
|
+
expires_at: number | null;
|
|
603
|
+
created_at: number;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
export interface FlowRecord {
|
|
607
|
+
id: string;
|
|
608
|
+
data_id: string;
|
|
609
|
+
source_domain: string;
|
|
610
|
+
target_domain: string;
|
|
611
|
+
direction: string;
|
|
612
|
+
allowed: boolean;
|
|
613
|
+
reason: string;
|
|
614
|
+
policy_id: string | null;
|
|
615
|
+
session_id: string | null;
|
|
616
|
+
action_id: string | null;
|
|
617
|
+
timestamp: number;
|
|
618
|
+
data_hash: string;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
export interface FlowValidationResult {
|
|
622
|
+
allowed: boolean;
|
|
623
|
+
reason: string;
|
|
624
|
+
applied_policy: string | null;
|
|
625
|
+
can_log: boolean;
|
|
626
|
+
can_transmit: boolean;
|
|
627
|
+
can_store: boolean;
|
|
628
|
+
transformations: string[];
|
|
629
|
+
confidence: number;
|
|
630
|
+
warnings: string[];
|
|
631
|
+
requireApproval?: boolean;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
export interface FlowPolicy {
|
|
635
|
+
id: string;
|
|
636
|
+
description: string;
|
|
637
|
+
source_pattern: string;
|
|
638
|
+
target_pattern: string;
|
|
639
|
+
min_source_sensitivity: string | null;
|
|
640
|
+
max_target_sensitivity: string | null;
|
|
641
|
+
categories: string[];
|
|
642
|
+
effect: "allow" | "deny" | "transform" | "audit_only";
|
|
643
|
+
priority: number;
|
|
644
|
+
required_transforms: string[];
|
|
645
|
+
log_flow: boolean;
|
|
646
|
+
require_approval: boolean;
|
|
647
|
+
conditions: string | null;
|
|
648
|
+
enabled: boolean;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
export interface FlowTrackerStats {
|
|
652
|
+
total_flows: number;
|
|
653
|
+
allowed_count: number;
|
|
654
|
+
blocked_count: number;
|
|
655
|
+
by_direction: { direction: string; count: number }[];
|
|
656
|
+
by_source_domain: { domain: string; count: number }[];
|
|
657
|
+
by_target_domain: { domain: string; count: number }[];
|
|
658
|
+
first_timestamp: number;
|
|
659
|
+
last_timestamp: number;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
export interface DomainStats {
|
|
663
|
+
domain: string;
|
|
664
|
+
inbound_count: number;
|
|
665
|
+
outbound_count: number;
|
|
666
|
+
blocked_count: number;
|
|
667
|
+
by_sensitivity: Record<string, number>;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
// ===== Leak Prevention Types =====
|
|
671
|
+
|
|
672
|
+
export type LeakType =
|
|
673
|
+
| "credential_exposure"
|
|
674
|
+
| "pii_exposure"
|
|
675
|
+
| "secret_key_exposure"
|
|
676
|
+
| "internal_url_exposure"
|
|
677
|
+
| "debug_info_leak"
|
|
678
|
+
| "stack_trace_exposure"
|
|
679
|
+
| "config_exposure"
|
|
680
|
+
| "source_code_leak"
|
|
681
|
+
| "encoded_smuggling"
|
|
682
|
+
| "timing_channel"
|
|
683
|
+
| "covert_channel";
|
|
684
|
+
|
|
685
|
+
export type PreventionActionType = "allow" | "alert" | "block";
|
|
686
|
+
|
|
687
|
+
export interface LeakDetection {
|
|
688
|
+
pattern_name: string;
|
|
689
|
+
leak_type: LeakType;
|
|
690
|
+
severity: number;
|
|
691
|
+
match_found: boolean;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
export interface LeakCheckResult {
|
|
695
|
+
action: PreventionActionType;
|
|
696
|
+
detections: LeakDetection[];
|
|
697
|
+
channel_allowed: boolean;
|
|
698
|
+
checked_at: number;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
export interface PreventionStatsResult {
|
|
702
|
+
total_checks: number;
|
|
703
|
+
blocked_count: number;
|
|
704
|
+
alert_count: number;
|
|
705
|
+
by_leak_type: Record<string, number>;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// ===== Taint Tracking Types =====
|
|
709
|
+
|
|
710
|
+
export type TaintSourceType =
|
|
711
|
+
| "user_input"
|
|
712
|
+
| "file_system"
|
|
713
|
+
| "network"
|
|
714
|
+
| "environment"
|
|
715
|
+
| "secrets"
|
|
716
|
+
| "database"
|
|
717
|
+
| "agent_generated"
|
|
718
|
+
| "tool_output"
|
|
719
|
+
| "memory"
|
|
720
|
+
| "external";
|
|
721
|
+
|
|
722
|
+
export type PropagationType =
|
|
723
|
+
| "assignment"
|
|
724
|
+
| "parameter"
|
|
725
|
+
| "return"
|
|
726
|
+
| "concatenation"
|
|
727
|
+
| "collection_inclusion"
|
|
728
|
+
| "property"
|
|
729
|
+
| "transformation"
|
|
730
|
+
| "aggregation";
|
|
731
|
+
|
|
732
|
+
export interface TaintSource {
|
|
733
|
+
id: string;
|
|
734
|
+
source_type: string;
|
|
735
|
+
sensitivity: string;
|
|
736
|
+
registered_at: number;
|
|
737
|
+
tags: string[];
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
export interface TaintedData {
|
|
741
|
+
id: string;
|
|
742
|
+
source_id: string;
|
|
743
|
+
data_hash: string;
|
|
744
|
+
sensitivity: string;
|
|
745
|
+
location: DataLocation;
|
|
746
|
+
propagated_from: string[];
|
|
747
|
+
tainted_at: number;
|
|
748
|
+
can_sanitize: boolean;
|
|
749
|
+
last_accessed: number;
|
|
750
|
+
access_count: number;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
export interface DataLocation {
|
|
754
|
+
location_type: string;
|
|
755
|
+
identifier: string;
|
|
756
|
+
context: string | null;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
export interface TaintPropagation {
|
|
760
|
+
id: string;
|
|
761
|
+
source_id: string;
|
|
762
|
+
target_id: string;
|
|
763
|
+
propagation_type: string;
|
|
764
|
+
operation: string;
|
|
765
|
+
timestamp: number;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
export interface FlowDecision {
|
|
769
|
+
allowed: boolean;
|
|
770
|
+
reason: string;
|
|
771
|
+
requires_sanitization: boolean;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
export interface TaintStatsResult {
|
|
775
|
+
total_sources: number;
|
|
776
|
+
total_tainted: number;
|
|
777
|
+
total_propagations: number;
|
|
778
|
+
by_source_type: Record<string, number>;
|
|
779
|
+
by_sensitivity: Record<string, number>;
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
// ===== Flow Classification =====
|
|
783
|
+
|
|
784
|
+
/**
|
|
785
|
+
* Classify data based on content and source
|
|
786
|
+
*/
|
|
787
|
+
export async function classifyData(
|
|
788
|
+
content: string,
|
|
789
|
+
source: string,
|
|
790
|
+
tags: string[]
|
|
791
|
+
): Promise<ClassifiedData> {
|
|
792
|
+
const native = await getNative();
|
|
793
|
+
return native.classify_data(content, source, tags);
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
/**
|
|
797
|
+
* Check if content contains sensitive data
|
|
798
|
+
*/
|
|
799
|
+
export async function containsSensitiveData(content: string): Promise<boolean> {
|
|
800
|
+
const native = await getNative();
|
|
801
|
+
return native.contains_sensitive_data(content);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/**
|
|
805
|
+
* Redact sensitive content
|
|
806
|
+
*/
|
|
807
|
+
export async function redactSensitive(
|
|
808
|
+
content: string,
|
|
809
|
+
replacement?: string
|
|
810
|
+
): Promise<string> {
|
|
811
|
+
const native = await getNative();
|
|
812
|
+
return native.redact_sensitive(content, replacement ?? null);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* Get sensitivity levels
|
|
817
|
+
*/
|
|
818
|
+
export async function getSensitivityLevels(): Promise<SensitivityLevelInfo[]> {
|
|
819
|
+
const native = await getNative();
|
|
820
|
+
return native.get_sensitivity_levels();
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Get data categories
|
|
825
|
+
*/
|
|
826
|
+
export async function getDataCategories(): Promise<DataCategoryInfo[]> {
|
|
827
|
+
const native = await getNative();
|
|
828
|
+
return native.get_data_categories();
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
export interface SensitivityLevelInfo {
|
|
832
|
+
name: string;
|
|
833
|
+
value: number;
|
|
834
|
+
description: string;
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
export interface DataCategoryInfo {
|
|
838
|
+
name: string;
|
|
839
|
+
description: string;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
// ===== Flow Policy Engine =====
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Create a flow policy engine
|
|
846
|
+
*/
|
|
847
|
+
export async function createFlowPolicyEngine(): Promise<FlowPolicyEngineHandle> {
|
|
848
|
+
const native = await getNative();
|
|
849
|
+
if (typeof native.create_flow_policy_engine === 'function') {
|
|
850
|
+
return native.create_flow_policy_engine();
|
|
851
|
+
}
|
|
852
|
+
// Return JS fallback handle
|
|
853
|
+
return createFallbackFlowPolicyEngine();
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
function createFallbackFlowPolicyEngine(): FlowPolicyEngineHandle {
|
|
857
|
+
const policies: Map<string, FlowPolicy> = new Map();
|
|
858
|
+
let defaultAction = "allow";
|
|
859
|
+
let blpMode = "disabled";
|
|
860
|
+
|
|
861
|
+
return {
|
|
862
|
+
addPolicy(policy: FlowPolicy): void {
|
|
863
|
+
policies.set(policy.id, policy);
|
|
864
|
+
},
|
|
865
|
+
removePolicy(policyId: string): boolean {
|
|
866
|
+
return policies.delete(policyId);
|
|
867
|
+
},
|
|
868
|
+
evaluate(
|
|
869
|
+
data: ClassifiedData,
|
|
870
|
+
sourceDomain: string,
|
|
871
|
+
targetDomain: string
|
|
872
|
+
): FlowValidationResult {
|
|
873
|
+
// Simple fallback: allow if sensitivity allows
|
|
874
|
+
const sensitivityOrder: Record<string, number> = {
|
|
875
|
+
public: 1, internal: 2, confidential: 3, secret: 4, top_secret: 5,
|
|
876
|
+
};
|
|
877
|
+
const sourceLevel = sensitivityOrder[data.sensitivity] || 2;
|
|
878
|
+
const targetLevel = sensitivityOrder[targetDomain] || 1;
|
|
879
|
+
|
|
880
|
+
// Bell-LaPadula: can't write up (no read up, no write down)
|
|
881
|
+
if (blpMode === "enabled") {
|
|
882
|
+
if (sourceLevel > targetLevel) {
|
|
883
|
+
return {
|
|
884
|
+
allowed: false,
|
|
885
|
+
reason: `BLP violation: cannot flow from ${data.sensitivity} to ${targetDomain}`,
|
|
886
|
+
applied_policy: "blp_default",
|
|
887
|
+
can_log: true,
|
|
888
|
+
can_transmit: false,
|
|
889
|
+
can_store: true,
|
|
890
|
+
transformations: [],
|
|
891
|
+
confidence: 1.0,
|
|
892
|
+
warnings: [],
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
return {
|
|
898
|
+
allowed: defaultAction === "allow",
|
|
899
|
+
reason: `Allowed by default (${defaultAction})`,
|
|
900
|
+
applied_policy: null,
|
|
901
|
+
can_log: true,
|
|
902
|
+
can_transmit: true,
|
|
903
|
+
can_store: true,
|
|
904
|
+
transformations: [],
|
|
905
|
+
confidence: 0.5,
|
|
906
|
+
warnings: [],
|
|
907
|
+
};
|
|
908
|
+
},
|
|
909
|
+
listPolicies(): FlowPolicy[] {
|
|
910
|
+
return Array.from(policies.values());
|
|
911
|
+
},
|
|
912
|
+
setDefaultAction(action: string): void {
|
|
913
|
+
defaultAction = action;
|
|
914
|
+
},
|
|
915
|
+
setBlpMode(mode: string): void {
|
|
916
|
+
blpMode = mode;
|
|
917
|
+
},
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
export interface FlowPolicyEngineHandle {
|
|
922
|
+
addPolicy(policy: FlowPolicy): void;
|
|
923
|
+
removePolicy(policyId: string): boolean;
|
|
924
|
+
evaluate(
|
|
925
|
+
data: ClassifiedData,
|
|
926
|
+
sourceDomain: string,
|
|
927
|
+
targetDomain: string
|
|
928
|
+
): FlowValidationResult;
|
|
929
|
+
listPolicies(): FlowPolicy[];
|
|
930
|
+
setDefaultAction(action: string): void;
|
|
931
|
+
setBlpMode(mode: string): void;
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
/**
|
|
935
|
+
* Create an allow-all flow policy
|
|
936
|
+
*/
|
|
937
|
+
export async function createAllowAllFlowPolicy(): Promise<FlowPolicy> {
|
|
938
|
+
const native = await getNative();
|
|
939
|
+
if (typeof native.create_allow_all_flow_policy === 'function') {
|
|
940
|
+
return native.create_allow_all_flow_policy();
|
|
941
|
+
}
|
|
942
|
+
return {
|
|
943
|
+
id: "allow_all",
|
|
944
|
+
description: "Allow all flows",
|
|
945
|
+
source_pattern: "*",
|
|
946
|
+
target_pattern: "*",
|
|
947
|
+
min_source_sensitivity: null,
|
|
948
|
+
max_target_sensitivity: null,
|
|
949
|
+
categories: [],
|
|
950
|
+
effect: "allow",
|
|
951
|
+
priority: 0,
|
|
952
|
+
required_transforms: [],
|
|
953
|
+
log_flow: false,
|
|
954
|
+
require_approval: false,
|
|
955
|
+
conditions: null,
|
|
956
|
+
enabled: true,
|
|
957
|
+
};
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/**
|
|
961
|
+
* Create a deny-all flow policy
|
|
962
|
+
*/
|
|
963
|
+
export async function createDenyAllFlowPolicy(): Promise<FlowPolicy> {
|
|
964
|
+
const native = await getNative();
|
|
965
|
+
if (typeof native.create_deny_all_flow_policy === 'function') {
|
|
966
|
+
return native.create_deny_all_flow_policy();
|
|
967
|
+
}
|
|
968
|
+
return {
|
|
969
|
+
id: "deny_all",
|
|
970
|
+
description: "Deny all flows",
|
|
971
|
+
source_pattern: "*",
|
|
972
|
+
target_pattern: "*",
|
|
973
|
+
min_source_sensitivity: null,
|
|
974
|
+
max_target_sensitivity: null,
|
|
975
|
+
categories: [],
|
|
976
|
+
effect: "deny",
|
|
977
|
+
priority: 1000,
|
|
978
|
+
required_transforms: [],
|
|
979
|
+
log_flow: false,
|
|
980
|
+
require_approval: false,
|
|
981
|
+
conditions: null,
|
|
982
|
+
enabled: true,
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
/**
|
|
987
|
+
* Create a strict flow policy
|
|
988
|
+
*/
|
|
989
|
+
export async function createStrictFlowPolicy(): Promise<FlowPolicy> {
|
|
990
|
+
const native = await getNative();
|
|
991
|
+
if (typeof native.create_strict_flow_policy === 'function') {
|
|
992
|
+
return native.create_strict_flow_policy();
|
|
993
|
+
}
|
|
994
|
+
return {
|
|
995
|
+
id: "strict",
|
|
996
|
+
description: "Strict flow policy",
|
|
997
|
+
source_pattern: "*",
|
|
998
|
+
target_pattern: "*",
|
|
999
|
+
min_source_sensitivity: "internal",
|
|
1000
|
+
max_target_sensitivity: null,
|
|
1001
|
+
categories: [],
|
|
1002
|
+
effect: "transform",
|
|
1003
|
+
priority: 500,
|
|
1004
|
+
required_transforms: ["redact_sensitive"],
|
|
1005
|
+
log_flow: true,
|
|
1006
|
+
require_approval: true,
|
|
1007
|
+
conditions: null,
|
|
1008
|
+
enabled: true,
|
|
1009
|
+
};
|
|
1010
|
+
}
|
|
1011
|
+
|
|
1012
|
+
// ===== Flow Tracker =====
|
|
1013
|
+
|
|
1014
|
+
/**
|
|
1015
|
+
* Create a flow tracker
|
|
1016
|
+
*/
|
|
1017
|
+
export async function createFlowTracker(): Promise<FlowTrackerHandle> {
|
|
1018
|
+
const native = await getNative();
|
|
1019
|
+
if (typeof native.create_flow_tracker === 'function') {
|
|
1020
|
+
return native.create_flow_tracker();
|
|
1021
|
+
}
|
|
1022
|
+
// Return JS fallback handle
|
|
1023
|
+
return createFallbackFlowTracker();
|
|
1024
|
+
}
|
|
1025
|
+
|
|
1026
|
+
function createFallbackFlowTracker(): FlowTrackerHandle {
|
|
1027
|
+
const flows: FlowRecord[] = [];
|
|
1028
|
+
let maxFlows = 10000;
|
|
1029
|
+
|
|
1030
|
+
return {
|
|
1031
|
+
record(
|
|
1032
|
+
data: ClassifiedData,
|
|
1033
|
+
sourceDomain: string,
|
|
1034
|
+
targetDomain: string,
|
|
1035
|
+
direction: string,
|
|
1036
|
+
validation: FlowValidationResult,
|
|
1037
|
+
sessionId: string | null,
|
|
1038
|
+
actionId: string | null
|
|
1039
|
+
): FlowRecord {
|
|
1040
|
+
const record: FlowRecord = {
|
|
1041
|
+
id: `flow_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`,
|
|
1042
|
+
data_id: data.id,
|
|
1043
|
+
source_domain: sourceDomain,
|
|
1044
|
+
target_domain: targetDomain,
|
|
1045
|
+
direction,
|
|
1046
|
+
allowed: validation.allowed,
|
|
1047
|
+
reason: validation.reason,
|
|
1048
|
+
policy_id: validation.applied_policy,
|
|
1049
|
+
session_id: sessionId,
|
|
1050
|
+
action_id: actionId,
|
|
1051
|
+
timestamp: Date.now(),
|
|
1052
|
+
data_hash: "",
|
|
1053
|
+
};
|
|
1054
|
+
if (flows.length >= maxFlows) {
|
|
1055
|
+
flows.shift();
|
|
1056
|
+
}
|
|
1057
|
+
flows.push(record);
|
|
1058
|
+
return record;
|
|
1059
|
+
},
|
|
1060
|
+
getFlow(flowId: string): FlowRecord | null {
|
|
1061
|
+
return flows.find(f => f.id === flowId) || null;
|
|
1062
|
+
},
|
|
1063
|
+
getLineage(dataId: string): FlowRecord[] {
|
|
1064
|
+
return flows.filter(f => f.data_id === dataId);
|
|
1065
|
+
},
|
|
1066
|
+
bySource(domain: string): FlowRecord[] {
|
|
1067
|
+
return flows.filter(f => f.source_domain === domain);
|
|
1068
|
+
},
|
|
1069
|
+
byTarget(domain: string): FlowRecord[] {
|
|
1070
|
+
return flows.filter(f => f.target_domain === domain);
|
|
1071
|
+
},
|
|
1072
|
+
bySession(sessionId: string): FlowRecord[] {
|
|
1073
|
+
return flows.filter(f => f.session_id === sessionId);
|
|
1074
|
+
},
|
|
1075
|
+
blocked(): FlowRecord[] {
|
|
1076
|
+
return flows.filter(f => !f.allowed);
|
|
1077
|
+
},
|
|
1078
|
+
allowed(): FlowRecord[] {
|
|
1079
|
+
return flows.filter(f => f.allowed);
|
|
1080
|
+
},
|
|
1081
|
+
recent(limit: number): FlowRecord[] {
|
|
1082
|
+
return flows.slice(-limit);
|
|
1083
|
+
},
|
|
1084
|
+
stats(): FlowTrackerStats {
|
|
1085
|
+
return {
|
|
1086
|
+
total_flows: flows.length,
|
|
1087
|
+
allowed_count: flows.filter(f => f.allowed).length,
|
|
1088
|
+
blocked_count: flows.filter(f => !f.allowed).length,
|
|
1089
|
+
by_direction: [],
|
|
1090
|
+
by_source_domain: [],
|
|
1091
|
+
by_target_domain: [],
|
|
1092
|
+
first_timestamp: flows[0]?.timestamp || Date.now(),
|
|
1093
|
+
last_timestamp: flows[flows.length - 1]?.timestamp || Date.now(),
|
|
1094
|
+
};
|
|
1095
|
+
},
|
|
1096
|
+
domainStats(domain: string): DomainStats | null {
|
|
1097
|
+
const domainFlows = flows.filter(
|
|
1098
|
+
f => f.source_domain === domain || f.target_domain === domain
|
|
1099
|
+
);
|
|
1100
|
+
if (domainFlows.length === 0) return null;
|
|
1101
|
+
return {
|
|
1102
|
+
domain,
|
|
1103
|
+
inbound_count: domainFlows.filter(f => f.target_domain === domain).length,
|
|
1104
|
+
outbound_count: domainFlows.filter(f => f.source_domain === domain).length,
|
|
1105
|
+
blocked_count: domainFlows.filter(f => !f.allowed).length,
|
|
1106
|
+
by_sensitivity: {},
|
|
1107
|
+
};
|
|
1108
|
+
},
|
|
1109
|
+
count(): number {
|
|
1110
|
+
return flows.length;
|
|
1111
|
+
},
|
|
1112
|
+
clear(): void {
|
|
1113
|
+
flows.length = 0;
|
|
1114
|
+
},
|
|
1115
|
+
setMaxFlows(max: number): void {
|
|
1116
|
+
maxFlows = max;
|
|
1117
|
+
},
|
|
1118
|
+
exportJsonl(): string {
|
|
1119
|
+
return flows.map(f => JSON.stringify(f)).join("\n");
|
|
1120
|
+
},
|
|
1121
|
+
};
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
export interface FlowTrackerHandle {
|
|
1125
|
+
record(
|
|
1126
|
+
data: ClassifiedData,
|
|
1127
|
+
sourceDomain: string,
|
|
1128
|
+
targetDomain: string,
|
|
1129
|
+
direction: string,
|
|
1130
|
+
validation: FlowValidationResult,
|
|
1131
|
+
sessionId: string | null,
|
|
1132
|
+
actionId: string | null
|
|
1133
|
+
): FlowRecord;
|
|
1134
|
+
getFlow(flowId: string): FlowRecord | null;
|
|
1135
|
+
getLineage(dataId: string): FlowRecord[];
|
|
1136
|
+
bySource(domain: string): FlowRecord[];
|
|
1137
|
+
byTarget(domain: string): FlowRecord[];
|
|
1138
|
+
bySession(sessionId: string): FlowRecord[];
|
|
1139
|
+
blocked(): FlowRecord[];
|
|
1140
|
+
allowed(): FlowRecord[];
|
|
1141
|
+
recent(limit: number): FlowRecord[];
|
|
1142
|
+
stats(): FlowTrackerStats;
|
|
1143
|
+
domainStats(domain: string): DomainStats | null;
|
|
1144
|
+
count(): number;
|
|
1145
|
+
clear(): void;
|
|
1146
|
+
setMaxFlows(max: number): void;
|
|
1147
|
+
exportJsonl(): string;
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
// ===== Leak Prevention =====
|
|
1151
|
+
|
|
1152
|
+
/**
|
|
1153
|
+
* Create a leak prevention engine
|
|
1154
|
+
*/
|
|
1155
|
+
export async function createLeakPrevention(): Promise<LeakPreventionHandle> {
|
|
1156
|
+
const native = await getNative();
|
|
1157
|
+
if (typeof native.create_leak_prevention === 'function') {
|
|
1158
|
+
return native.create_leak_prevention();
|
|
1159
|
+
}
|
|
1160
|
+
// Return JS fallback handle
|
|
1161
|
+
return createFallbackLeakPrevention();
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
function createFallbackLeakPrevention(): LeakPreventionHandle {
|
|
1165
|
+
const sensitivePatterns: string[] = [];
|
|
1166
|
+
const channels: Set<string> = new Set(["stdout", "stderr", "network", "file"]);
|
|
1167
|
+
let mode: "alert" | "block" = "alert";
|
|
1168
|
+
let checkCount = 0;
|
|
1169
|
+
let blockedCount = 0;
|
|
1170
|
+
let alertCount = 0;
|
|
1171
|
+
|
|
1172
|
+
const leakPatterns: { pattern: RegExp; type: LeakType }[] = [
|
|
1173
|
+
{ pattern: /password[=:]\s*\S+/gi, type: "credential_exposure" },
|
|
1174
|
+
{ pattern: /api[_-]?key[=:]\s*\S+/gi, type: "credential_exposure" },
|
|
1175
|
+
{ pattern: /token[=:]\s*\S+/gi, type: "credential_exposure" },
|
|
1176
|
+
{ pattern: /secret[=:]\s*\S+/gi, type: "credential_exposure" },
|
|
1177
|
+
{ pattern: /\b[A-Za-z0-9._%+-]{20,}@\b/g, type: "pii_exposure" },
|
|
1178
|
+
{ pattern: /\b\d{4}[- ]?\d{4}[- ]?\d{4}\b/g, type: "pii_exposure" },
|
|
1179
|
+
{ pattern: /-----BEGIN.*KEY-----/g, type: "secret_key_exposure" },
|
|
1180
|
+
{ pattern: /-----BEGIN.*PRIVATE KEY-----/g, type: "secret_key_exposure" },
|
|
1181
|
+
{ pattern: /mongodb:\/\/.+/gi, type: "internal_url_exposure" },
|
|
1182
|
+
{ pattern: /redis:\/\/.+/gi, type: "internal_url_exposure" },
|
|
1183
|
+
];
|
|
1184
|
+
|
|
1185
|
+
return {
|
|
1186
|
+
check(content: string, channel: string): LeakCheckResult {
|
|
1187
|
+
checkCount++;
|
|
1188
|
+
const detections: LeakDetection[] = [];
|
|
1189
|
+
|
|
1190
|
+
for (const { pattern, type } of leakPatterns) {
|
|
1191
|
+
if (pattern.test(content)) {
|
|
1192
|
+
detections.push({
|
|
1193
|
+
pattern_name: pattern.source,
|
|
1194
|
+
leak_type: type,
|
|
1195
|
+
severity: type === "credential_exposure" ? 5 : type === "secret_key_exposure" ? 5 : 3,
|
|
1196
|
+
match_found: true,
|
|
1197
|
+
});
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
for (const sensitive of sensitivePatterns) {
|
|
1202
|
+
if (content.includes(sensitive)) {
|
|
1203
|
+
detections.push({
|
|
1204
|
+
pattern_name: "registered_sensitive",
|
|
1205
|
+
leak_type: "credential_exposure",
|
|
1206
|
+
severity: 4,
|
|
1207
|
+
match_found: true,
|
|
1208
|
+
});
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
const channelAllowed = channels.has(channel);
|
|
1213
|
+
const shouldBlock = detections.length > 0 && mode === "block";
|
|
1214
|
+
const action = shouldBlock ? "block" : detections.length > 0 ? "alert" : "allow";
|
|
1215
|
+
|
|
1216
|
+
if (action === "block") blockedCount++;
|
|
1217
|
+
else if (action === "alert") alertCount++;
|
|
1218
|
+
|
|
1219
|
+
return {
|
|
1220
|
+
action,
|
|
1221
|
+
detections,
|
|
1222
|
+
channel_allowed: channelAllowed,
|
|
1223
|
+
checked_at: Date.now(),
|
|
1224
|
+
};
|
|
1225
|
+
},
|
|
1226
|
+
sanitize(content: string): string {
|
|
1227
|
+
let sanitized = content;
|
|
1228
|
+
for (const { pattern } of leakPatterns) {
|
|
1229
|
+
sanitized = sanitized.replace(pattern, "[REDACTED]");
|
|
1230
|
+
}
|
|
1231
|
+
for (const sensitive of sensitivePatterns) {
|
|
1232
|
+
sanitized = sanitized.replace(sensitive, "[REDACTED]");
|
|
1233
|
+
}
|
|
1234
|
+
return sanitized;
|
|
1235
|
+
},
|
|
1236
|
+
registerSensitive(data: string): void {
|
|
1237
|
+
sensitivePatterns.push(data);
|
|
1238
|
+
},
|
|
1239
|
+
addChannel(channel: string): void {
|
|
1240
|
+
channels.add(channel);
|
|
1241
|
+
},
|
|
1242
|
+
removeChannel(channel: string): void {
|
|
1243
|
+
channels.delete(channel);
|
|
1244
|
+
},
|
|
1245
|
+
setMode(newMode: string): void {
|
|
1246
|
+
if (newMode === "alert" || newMode === "block") {
|
|
1247
|
+
mode = newMode;
|
|
1248
|
+
}
|
|
1249
|
+
},
|
|
1250
|
+
stats(): PreventionStatsResult {
|
|
1251
|
+
return {
|
|
1252
|
+
total_checks: checkCount,
|
|
1253
|
+
blocked_count: blockedCount,
|
|
1254
|
+
alert_count: alertCount,
|
|
1255
|
+
by_leak_type: {},
|
|
1256
|
+
};
|
|
1257
|
+
},
|
|
1258
|
+
clearSensitive(): void {
|
|
1259
|
+
sensitivePatterns.length = 0;
|
|
1260
|
+
},
|
|
1261
|
+
};
|
|
1262
|
+
}
|
|
1263
|
+
|
|
1264
|
+
export interface LeakPreventionHandle {
|
|
1265
|
+
check(content: string, channel: string): LeakCheckResult;
|
|
1266
|
+
sanitize(content: string): string;
|
|
1267
|
+
registerSensitive(data: string): void;
|
|
1268
|
+
addChannel(channel: string): void;
|
|
1269
|
+
removeChannel(channel: string): void;
|
|
1270
|
+
setMode(mode: string): void;
|
|
1271
|
+
stats(): PreventionStatsResult;
|
|
1272
|
+
clearSensitive(): void;
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
/**
|
|
1276
|
+
* Quick check content for leaks
|
|
1277
|
+
*/
|
|
1278
|
+
export async function checkForLeaks(
|
|
1279
|
+
content: string,
|
|
1280
|
+
channel: string
|
|
1281
|
+
): Promise<LeakCheckResult> {
|
|
1282
|
+
const native = await getNative();
|
|
1283
|
+
if (typeof native.check_for_leaks === 'function') {
|
|
1284
|
+
return native.check_for_leaks(content, channel);
|
|
1285
|
+
}
|
|
1286
|
+
// Use fallback implementation
|
|
1287
|
+
const engine = createFallbackLeakPrevention();
|
|
1288
|
+
return engine.check(content, channel);
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
/**
|
|
1292
|
+
* Quick sanitize content
|
|
1293
|
+
*/
|
|
1294
|
+
export async function sanitizeContent(content: string): Promise<string> {
|
|
1295
|
+
const native = await getNative();
|
|
1296
|
+
if (typeof native.sanitizeContent === 'function') {
|
|
1297
|
+
return native.sanitizeContent(content);
|
|
1298
|
+
}
|
|
1299
|
+
// Use fallback implementation
|
|
1300
|
+
const engine = createFallbackLeakPrevention();
|
|
1301
|
+
return engine.sanitize(content);
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
// ===== Taint Tracking =====
|
|
1305
|
+
|
|
1306
|
+
/**
|
|
1307
|
+
* Create a taint tracker
|
|
1308
|
+
*/
|
|
1309
|
+
export async function createTaintTracker(): Promise<TaintTrackerHandle> {
|
|
1310
|
+
const native = await getNative();
|
|
1311
|
+
if (typeof native.createTaintTracker === 'function') {
|
|
1312
|
+
return native.createTaintTracker();
|
|
1313
|
+
}
|
|
1314
|
+
// Return JS fallback handle
|
|
1315
|
+
return createFallbackTaintTracker();
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
function createFallbackTaintTracker(): TaintTrackerHandle {
|
|
1319
|
+
const sources: Map<string, TaintSource> = new Map();
|
|
1320
|
+
const taintedData: Map<string, TaintedData> = new Map();
|
|
1321
|
+
const propagations: TaintPropagation[] = [];
|
|
1322
|
+
|
|
1323
|
+
return {
|
|
1324
|
+
registerSource(sourceType: string, sensitivity: string, tags: string[]): string {
|
|
1325
|
+
const id = `source_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
1326
|
+
sources.set(id, {
|
|
1327
|
+
id,
|
|
1328
|
+
source_type: sourceType,
|
|
1329
|
+
sensitivity,
|
|
1330
|
+
registered_at: Date.now(),
|
|
1331
|
+
tags,
|
|
1332
|
+
});
|
|
1333
|
+
return id;
|
|
1334
|
+
},
|
|
1335
|
+
taint(
|
|
1336
|
+
sourceId: string,
|
|
1337
|
+
data: string,
|
|
1338
|
+
locationType: string,
|
|
1339
|
+
identifier: string
|
|
1340
|
+
): string | null {
|
|
1341
|
+
const source = sources.get(sourceId);
|
|
1342
|
+
if (!source) return null;
|
|
1343
|
+
|
|
1344
|
+
const taintId = `taint_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
1345
|
+
const tainted: TaintedData = {
|
|
1346
|
+
id: taintId,
|
|
1347
|
+
source_id: sourceId,
|
|
1348
|
+
data_hash: data.substring(0, 32),
|
|
1349
|
+
sensitivity: source.sensitivity,
|
|
1350
|
+
location: {
|
|
1351
|
+
location_type: locationType,
|
|
1352
|
+
identifier,
|
|
1353
|
+
context: null,
|
|
1354
|
+
},
|
|
1355
|
+
propagated_from: [],
|
|
1356
|
+
tainted_at: Date.now(),
|
|
1357
|
+
can_sanitize: true,
|
|
1358
|
+
last_accessed: Date.now(),
|
|
1359
|
+
access_count: 0,
|
|
1360
|
+
};
|
|
1361
|
+
taintedData.set(taintId, tainted);
|
|
1362
|
+
return taintId;
|
|
1363
|
+
},
|
|
1364
|
+
propagate(
|
|
1365
|
+
sourceTaintId: string,
|
|
1366
|
+
newData: string,
|
|
1367
|
+
locationType: string,
|
|
1368
|
+
identifier: string,
|
|
1369
|
+
propagationType: string,
|
|
1370
|
+
operation: string
|
|
1371
|
+
): string | null {
|
|
1372
|
+
const sourceTaint = taintedData.get(sourceTaintId);
|
|
1373
|
+
if (!sourceTaint) return null;
|
|
1374
|
+
|
|
1375
|
+
const newTaintId = `taint_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;
|
|
1376
|
+
const newTaint: TaintedData = {
|
|
1377
|
+
id: newTaintId,
|
|
1378
|
+
source_id: sourceTaint.source_id,
|
|
1379
|
+
data_hash: newData.substring(0, 32),
|
|
1380
|
+
sensitivity: sourceTaint.sensitivity,
|
|
1381
|
+
location: {
|
|
1382
|
+
location_type: locationType,
|
|
1383
|
+
identifier,
|
|
1384
|
+
context: null,
|
|
1385
|
+
},
|
|
1386
|
+
propagated_from: [sourceTaintId],
|
|
1387
|
+
tainted_at: Date.now(),
|
|
1388
|
+
can_sanitize: true,
|
|
1389
|
+
last_accessed: Date.now(),
|
|
1390
|
+
access_count: 0,
|
|
1391
|
+
};
|
|
1392
|
+
taintedData.set(newTaintId, newTaint);
|
|
1393
|
+
|
|
1394
|
+
propagations.push({
|
|
1395
|
+
id: `prop_${Date.now()}`,
|
|
1396
|
+
source_id: sourceTaintId,
|
|
1397
|
+
target_id: newTaintId,
|
|
1398
|
+
propagation_type: propagationType,
|
|
1399
|
+
operation,
|
|
1400
|
+
timestamp: Date.now(),
|
|
1401
|
+
});
|
|
1402
|
+
|
|
1403
|
+
return newTaintId;
|
|
1404
|
+
},
|
|
1405
|
+
canFlow(taintId: string, sink: string): FlowDecision {
|
|
1406
|
+
const taint = taintedData.get(taintId);
|
|
1407
|
+
if (!taint) {
|
|
1408
|
+
return { allowed: true, reason: "No taint found", requires_sanitization: false };
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
// Check sensitivity-based flow
|
|
1412
|
+
const sensitivityOrder = ["public", "internal", "confidential", "secret", "top_secret"];
|
|
1413
|
+
const taintLevel = sensitivityOrder.indexOf(taint.sensitivity);
|
|
1414
|
+
|
|
1415
|
+
if (taintLevel >= 3) {
|
|
1416
|
+
// High sensitivity data
|
|
1417
|
+
if (sink === "external" || sink === "network") {
|
|
1418
|
+
return {
|
|
1419
|
+
allowed: false,
|
|
1420
|
+
reason: `Cannot flow ${taint.sensitivity} data to ${sink}`,
|
|
1421
|
+
requires_sanitization: true,
|
|
1422
|
+
};
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
return { allowed: true, reason: "Flow allowed", requires_sanitization: false };
|
|
1427
|
+
},
|
|
1428
|
+
isTainted(data: string): boolean {
|
|
1429
|
+
for (const taint of taintedData.values()) {
|
|
1430
|
+
if (data.includes(taint.data_hash)) {
|
|
1431
|
+
return true;
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
return false;
|
|
1435
|
+
},
|
|
1436
|
+
getTaint(taintId: string): TaintedData | null {
|
|
1437
|
+
return taintedData.get(taintId) || null;
|
|
1438
|
+
},
|
|
1439
|
+
stats(): TaintStatsResult {
|
|
1440
|
+
return {
|
|
1441
|
+
total_sources: sources.size,
|
|
1442
|
+
total_tainted: taintedData.size,
|
|
1443
|
+
total_propagations: propagations.length,
|
|
1444
|
+
by_source_type: {},
|
|
1445
|
+
by_sensitivity: {},
|
|
1446
|
+
};
|
|
1447
|
+
},
|
|
1448
|
+
clear(taintId: string): boolean {
|
|
1449
|
+
return taintedData.delete(taintId);
|
|
1450
|
+
},
|
|
1451
|
+
clearAll(): void {
|
|
1452
|
+
sources.clear();
|
|
1453
|
+
taintedData.clear();
|
|
1454
|
+
propagations.length = 0;
|
|
1455
|
+
},
|
|
1456
|
+
};
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
export interface TaintTrackerHandle {
|
|
1460
|
+
registerSource(
|
|
1461
|
+
sourceType: string,
|
|
1462
|
+
sensitivity: string,
|
|
1463
|
+
tags: string[]
|
|
1464
|
+
): string;
|
|
1465
|
+
taint(
|
|
1466
|
+
sourceId: string,
|
|
1467
|
+
data: string,
|
|
1468
|
+
locationType: string,
|
|
1469
|
+
identifier: string
|
|
1470
|
+
): string | null;
|
|
1471
|
+
propagate(
|
|
1472
|
+
sourceTaintId: string,
|
|
1473
|
+
newData: string,
|
|
1474
|
+
locationType: string,
|
|
1475
|
+
identifier: string,
|
|
1476
|
+
propagationType: string,
|
|
1477
|
+
operation: string
|
|
1478
|
+
): string | null;
|
|
1479
|
+
canFlow(taintId: string, sink: string): FlowDecision;
|
|
1480
|
+
isTainted(data: string): boolean;
|
|
1481
|
+
getTaint(taintId: string): TaintedData | null;
|
|
1482
|
+
stats(): TaintStatsResult;
|
|
1483
|
+
clear(taintId: string): boolean;
|
|
1484
|
+
clearAll(): void;
|
|
1485
|
+
}
|
|
1486
|
+
|
|
1487
|
+
// ===== Immutable Directives =====
|
|
1488
|
+
// Cryptographically signed rules that cannot be modified by AI
|
|
1489
|
+
|
|
1490
|
+
export interface ImmutableDirective {
|
|
1491
|
+
id: string;
|
|
1492
|
+
directiveType: string;
|
|
1493
|
+
rule: string;
|
|
1494
|
+
domain: string;
|
|
1495
|
+
priority: number;
|
|
1496
|
+
overridable: boolean;
|
|
1497
|
+
createdAt: number;
|
|
1498
|
+
expiresAt?: number;
|
|
1499
|
+
createdBy: string;
|
|
1500
|
+
signature?: string;
|
|
1501
|
+
signedBy?: string;
|
|
1502
|
+
ruleHash: string;
|
|
1503
|
+
}
|
|
1504
|
+
|
|
1505
|
+
export interface DirectiveResult {
|
|
1506
|
+
allowed: boolean;
|
|
1507
|
+
requiresApproval: boolean;
|
|
1508
|
+
violations: DirectiveViolation[];
|
|
1509
|
+
approvalDirectives: string[];
|
|
1510
|
+
denialReason?: string;
|
|
1511
|
+
}
|
|
1512
|
+
|
|
1513
|
+
export interface DirectiveViolation {
|
|
1514
|
+
directiveId: string;
|
|
1515
|
+
directiveType: string;
|
|
1516
|
+
reason: string;
|
|
1517
|
+
severity: string;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
// ===== Signed Actions =====
|
|
1521
|
+
// Every action cryptographically signed before execution
|
|
1522
|
+
|
|
1523
|
+
export interface SignedAction {
|
|
1524
|
+
id: string;
|
|
1525
|
+
sequence: number;
|
|
1526
|
+
sessionId: string;
|
|
1527
|
+
tool: string;
|
|
1528
|
+
domain: string;
|
|
1529
|
+
actionType: string;
|
|
1530
|
+
target?: string;
|
|
1531
|
+
paramsHash: string;
|
|
1532
|
+
timestamp: number;
|
|
1533
|
+
intentId?: string;
|
|
1534
|
+
signature: string;
|
|
1535
|
+
signedBy: string;
|
|
1536
|
+
prevHash?: string;
|
|
1537
|
+
hash: string;
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
export interface ActionVerification {
|
|
1541
|
+
signatureValid: boolean;
|
|
1542
|
+
chainIntact: boolean;
|
|
1543
|
+
hashValid: boolean;
|
|
1544
|
+
intentVerified: boolean;
|
|
1545
|
+
valid: boolean;
|
|
1546
|
+
error?: string;
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
// ===== Drift Detection =====
|
|
1550
|
+
// Behavioral analytics to detect deviation from intent
|
|
1551
|
+
|
|
1552
|
+
export interface BehavioralProfile {
|
|
1553
|
+
agentId: string;
|
|
1554
|
+
intentId?: string;
|
|
1555
|
+
createdAt: number;
|
|
1556
|
+
updatedAt: number;
|
|
1557
|
+
totalActions: number;
|
|
1558
|
+
actionTypes: Record<string, number>;
|
|
1559
|
+
domains: Record<string, number>;
|
|
1560
|
+
tools: Record<string, number>;
|
|
1561
|
+
actionsPerMinute: number;
|
|
1562
|
+
rateWindow: number;
|
|
1563
|
+
commonSequences: SequencePattern[];
|
|
1564
|
+
forbiddenAttempts: number;
|
|
1565
|
+
approvalRequests: number;
|
|
1566
|
+
}
|
|
1567
|
+
|
|
1568
|
+
export interface SequencePattern {
|
|
1569
|
+
sequence: string[];
|
|
1570
|
+
count: number;
|
|
1571
|
+
lastSeen: number;
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
export interface DriftIndicator {
|
|
1575
|
+
indicatorType: string;
|
|
1576
|
+
severity: number;
|
|
1577
|
+
description: string;
|
|
1578
|
+
factor: string;
|
|
1579
|
+
evidence: string[];
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
// ===== Native Module Bindings =====
|
|
1583
|
+
// These will be populated when the native module is built
|
|
1584
|
+
|
|
1585
|
+
import type { SystemSignature } from "../claude-md.js";
|
|
1586
|
+
|
|
1587
|
+
let directiveStoreHandle: any = null;
|
|
1588
|
+
let actionSignerHandle: any = null;
|
|
1589
|
+
let driftDetectorHandle: any = null;
|
|
1590
|
+
|
|
1591
|
+
/**
|
|
1592
|
+
* Create a directive store for immutable directives
|
|
1593
|
+
*/
|
|
1594
|
+
export async function createDirectiveStore(): Promise<DirectiveStoreHandle> {
|
|
1595
|
+
const native = await getNative();
|
|
1596
|
+
if (native.create_directive_store) {
|
|
1597
|
+
return native.create_directive_store();
|
|
1598
|
+
}
|
|
1599
|
+
// Fallback to JS implementation
|
|
1600
|
+
return new DirectiveStoreHandle();
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
/**
|
|
1604
|
+
* Create an action signer for cryptographic action signing
|
|
1605
|
+
*/
|
|
1606
|
+
export async function createActionSigner(
|
|
1607
|
+
privateKeyHex: string,
|
|
1608
|
+
sessionId: string
|
|
1609
|
+
): Promise<ActionSignerHandle> {
|
|
1610
|
+
const native = await getNative();
|
|
1611
|
+
if (native.create_action_signer) {
|
|
1612
|
+
return native.create_action_signer(privateKeyHex, sessionId);
|
|
1613
|
+
}
|
|
1614
|
+
// Fallback to JS implementation
|
|
1615
|
+
return new ActionSignerHandle(privateKeyHex, sessionId);
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
/**
|
|
1619
|
+
* Create a drift detector for behavioral analytics
|
|
1620
|
+
*/
|
|
1621
|
+
export async function createDriftDetector(
|
|
1622
|
+
agentId: string,
|
|
1623
|
+
intentId?: string
|
|
1624
|
+
): Promise<DriftDetectorHandle> {
|
|
1625
|
+
const native = await getNative();
|
|
1626
|
+
if (native.create_drift_detector) {
|
|
1627
|
+
return native.create_drift_detector(agentId, intentId);
|
|
1628
|
+
}
|
|
1629
|
+
// Fallback to JS implementation
|
|
1630
|
+
return new DriftDetectorHandle(agentId, intentId);
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
/**
|
|
1634
|
+
* Create default financial protection directives
|
|
1635
|
+
*/
|
|
1636
|
+
export async function createDefaultFinancialDirectives(
|
|
1637
|
+
store: DirectiveStoreHandle
|
|
1638
|
+
): Promise<ImmutableDirective[]> {
|
|
1639
|
+
const native = await getNative();
|
|
1640
|
+
if (native.create_default_financial_directives) {
|
|
1641
|
+
return native.create_default_financial_directives(store);
|
|
1642
|
+
}
|
|
1643
|
+
// JS fallback - create basic directives
|
|
1644
|
+
return [
|
|
1645
|
+
await store.createDirective(
|
|
1646
|
+
"forbidden_action",
|
|
1647
|
+
JSON.stringify({
|
|
1648
|
+
actions: ["*"],
|
|
1649
|
+
paramPatterns: ["send.*eth", "send.*btc", "transfer.*crypto", "wallet.*address"]
|
|
1650
|
+
}),
|
|
1651
|
+
"financial",
|
|
1652
|
+
1,
|
|
1653
|
+
false,
|
|
1654
|
+
"system"
|
|
1655
|
+
),
|
|
1656
|
+
await store.createDirective(
|
|
1657
|
+
"forbidden_action",
|
|
1658
|
+
JSON.stringify({
|
|
1659
|
+
actions: ["mcp__telegram__telegram_send_message"],
|
|
1660
|
+
paramPatterns: ["password", "secret", "api_key", "private_key"]
|
|
1661
|
+
}),
|
|
1662
|
+
"credentials",
|
|
1663
|
+
1,
|
|
1664
|
+
false,
|
|
1665
|
+
"system"
|
|
1666
|
+
),
|
|
1667
|
+
];
|
|
1668
|
+
}
|
|
1669
|
+
|
|
1670
|
+
// ===== JS Fallback Implementations =====
|
|
1671
|
+
|
|
1672
|
+
class DirectiveStoreHandle {
|
|
1673
|
+
private directives: Map<string, ImmutableDirective> = new Map();
|
|
1674
|
+
|
|
1675
|
+
async setSigningKey(privateKeyHex: string): Promise<void> {
|
|
1676
|
+
// JS fallback - no actual signing
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
async createDirective(
|
|
1680
|
+
directiveType: string,
|
|
1681
|
+
rule: string,
|
|
1682
|
+
domain: string,
|
|
1683
|
+
priority: number = 5,
|
|
1684
|
+
overridable: boolean = false,
|
|
1685
|
+
createdBy: string = "user"
|
|
1686
|
+
): Promise<ImmutableDirective> {
|
|
1687
|
+
const id = `directive-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
1688
|
+
const directive: ImmutableDirective = {
|
|
1689
|
+
id,
|
|
1690
|
+
directiveType,
|
|
1691
|
+
rule,
|
|
1692
|
+
domain,
|
|
1693
|
+
priority,
|
|
1694
|
+
overridable,
|
|
1695
|
+
createdAt: Date.now(),
|
|
1696
|
+
createdBy,
|
|
1697
|
+
ruleHash: await this.hashRule(rule),
|
|
1698
|
+
};
|
|
1699
|
+
this.directives.set(id, directive);
|
|
1700
|
+
return directive;
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
async addDirective(directive: ImmutableDirective): Promise<void> {
|
|
1704
|
+
this.directives.set(directive.id, directive);
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
async evaluate(
|
|
1708
|
+
actionType: string,
|
|
1709
|
+
domain: string,
|
|
1710
|
+
target: string | null,
|
|
1711
|
+
params: string
|
|
1712
|
+
): Promise<DirectiveResult> {
|
|
1713
|
+
const violations: DirectiveViolation[] = [];
|
|
1714
|
+
const approvalDirectives: string[] = [];
|
|
1715
|
+
|
|
1716
|
+
for (const directive of this.directives.values()) {
|
|
1717
|
+
if (directive.domain !== "*" && directive.domain !== domain) continue;
|
|
1718
|
+
|
|
1719
|
+
const matches = this.evaluateRule(directive.rule, actionType, domain, target, params);
|
|
1720
|
+
|
|
1721
|
+
if (matches) {
|
|
1722
|
+
if (directive.directiveType === "forbidden_action") {
|
|
1723
|
+
violations.push({
|
|
1724
|
+
directiveId: directive.id,
|
|
1725
|
+
directiveType: directive.directiveType,
|
|
1726
|
+
reason: `Matched forbidden pattern in ${directive.domain}`,
|
|
1727
|
+
severity: directive.priority === 1 ? "critical" : "high",
|
|
1728
|
+
});
|
|
1729
|
+
} else if (directive.directiveType === "required_approval") {
|
|
1730
|
+
approvalDirectives.push(directive.id);
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
const hasCritical = violations.some(v => v.severity === "critical");
|
|
1736
|
+
|
|
1737
|
+
return {
|
|
1738
|
+
allowed: !hasCritical,
|
|
1739
|
+
requiresApproval: approvalDirectives.length > 0,
|
|
1740
|
+
violations,
|
|
1741
|
+
approvalDirectives,
|
|
1742
|
+
denialReason: hasCritical ? "Critical directive violation" : undefined,
|
|
1743
|
+
};
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
private evaluateRule(
|
|
1747
|
+
rule: string,
|
|
1748
|
+
actionType: string,
|
|
1749
|
+
domain: string,
|
|
1750
|
+
target: string | null,
|
|
1751
|
+
params: string
|
|
1752
|
+
): boolean {
|
|
1753
|
+
try {
|
|
1754
|
+
const ruleJson = JSON.parse(rule);
|
|
1755
|
+
// Check action patterns
|
|
1756
|
+
if (ruleJson.actions) {
|
|
1757
|
+
for (const action of ruleJson.actions) {
|
|
1758
|
+
if (action === "*" || action === actionType) return true;
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
// Check param patterns
|
|
1762
|
+
if (ruleJson.paramPatterns || ruleJson.param_patterns) {
|
|
1763
|
+
const patterns = ruleJson.paramPatterns || ruleJson.param_patterns;
|
|
1764
|
+
for (const pattern of patterns) {
|
|
1765
|
+
if (params.toLowerCase().includes(pattern.toLowerCase())) return true;
|
|
1766
|
+
}
|
|
1767
|
+
}
|
|
1768
|
+
return false;
|
|
1769
|
+
} catch {
|
|
1770
|
+
// Simple string match
|
|
1771
|
+
return rule.includes(actionType) || rule.includes(domain);
|
|
1772
|
+
}
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
private async hashRule(rule: string): Promise<string> {
|
|
1776
|
+
const encoder = new TextEncoder();
|
|
1777
|
+
const data = encoder.encode(rule);
|
|
1778
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
1779
|
+
const hashArray = Array.from(new Uint8Array(hashBuffer));
|
|
1780
|
+
return hashArray.map(b => b.toString(16).padStart(2, "0")).join("");
|
|
1781
|
+
}
|
|
1782
|
+
}
|
|
1783
|
+
|
|
1784
|
+
class ActionSignerHandle {
|
|
1785
|
+
private privateKey: string;
|
|
1786
|
+
private _sessionId: string;
|
|
1787
|
+
private _sequence: number = 0;
|
|
1788
|
+
private _lastHash: string | null = null;
|
|
1789
|
+
private _intentId: string | null = null;
|
|
1790
|
+
|
|
1791
|
+
constructor(privateKey: string, sessionId: string) {
|
|
1792
|
+
this.privateKey = privateKey;
|
|
1793
|
+
this._sessionId = sessionId;
|
|
1794
|
+
}
|
|
1795
|
+
|
|
1796
|
+
setIntent(intentId: string): void {
|
|
1797
|
+
this._intentId = intentId;
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
async sign(
|
|
1801
|
+
tool: string,
|
|
1802
|
+
domain: string,
|
|
1803
|
+
actionType: string,
|
|
1804
|
+
target: string | null,
|
|
1805
|
+
params: string
|
|
1806
|
+
): Promise<SignedAction> {
|
|
1807
|
+
this._sequence++;
|
|
1808
|
+
const timestamp = Date.now();
|
|
1809
|
+
const id = `action-${this._sessionId}-${this._sequence}`;
|
|
1810
|
+
|
|
1811
|
+
// Hash params
|
|
1812
|
+
const encoder = new TextEncoder();
|
|
1813
|
+
const paramsData = encoder.encode(params);
|
|
1814
|
+
const paramsHashBuffer = await crypto.subtle.digest("SHA-256", paramsData);
|
|
1815
|
+
const paramsHash = Array.from(new Uint8Array(paramsHashBuffer))
|
|
1816
|
+
.map(b => b.toString(16).padStart(2, "0"))
|
|
1817
|
+
.join("");
|
|
1818
|
+
|
|
1819
|
+
// Create action (without signature for hash computation)
|
|
1820
|
+
const action: SignedAction = {
|
|
1821
|
+
id,
|
|
1822
|
+
sequence: this._sequence,
|
|
1823
|
+
sessionId: this._sessionId,
|
|
1824
|
+
tool,
|
|
1825
|
+
domain,
|
|
1826
|
+
actionType,
|
|
1827
|
+
target: target || undefined,
|
|
1828
|
+
paramsHash,
|
|
1829
|
+
timestamp,
|
|
1830
|
+
intentId: this._intentId ?? undefined,
|
|
1831
|
+
signature: "",
|
|
1832
|
+
signedBy: this.privateKey.substring(0, 16), // Placeholder
|
|
1833
|
+
prevHash: this._lastHash ?? undefined,
|
|
1834
|
+
hash: "",
|
|
1835
|
+
};
|
|
1836
|
+
|
|
1837
|
+
// Compute hash
|
|
1838
|
+
const hashInput = `${action.id}:${action.sequence}:${action.tool}:${action.domain}:${action.paramsHash}:${action.timestamp}`;
|
|
1839
|
+
const hashData = encoder.encode(hashInput);
|
|
1840
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", hashData);
|
|
1841
|
+
action.hash = Array.from(new Uint8Array(hashBuffer))
|
|
1842
|
+
.map(b => b.toString(16).padStart(2, "0"))
|
|
1843
|
+
.join("");
|
|
1844
|
+
|
|
1845
|
+
// Sign (simplified - in production use Ed25519)
|
|
1846
|
+
action.signature = `sig-${action.hash.substring(0, 32)}`;
|
|
1847
|
+
|
|
1848
|
+
this._lastHash = action.hash;
|
|
1849
|
+
|
|
1850
|
+
return action;
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
async verify(action: SignedAction): Promise<ActionVerification> {
|
|
1854
|
+
// Simplified verification
|
|
1855
|
+
const valid = action.signature === `sig-${action.hash.substring(0, 32)}`;
|
|
1856
|
+
return {
|
|
1857
|
+
signatureValid: valid,
|
|
1858
|
+
chainIntact: action.prevHash === this._lastHash || action.sequence === 1,
|
|
1859
|
+
hashValid: true,
|
|
1860
|
+
intentVerified: !this._intentId || action.intentId === this._intentId,
|
|
1861
|
+
valid,
|
|
1862
|
+
error: valid ? undefined : "Signature verification failed",
|
|
1863
|
+
};
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
getSequence(): number {
|
|
1867
|
+
return this._sequence;
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
getSessionId(): string {
|
|
1871
|
+
return this._sessionId;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
get publicKey(): string {
|
|
1875
|
+
return this.privateKey.substring(0, 16) + "...";
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
/**
|
|
1880
|
+
* Verify a signed action without needing a signer handle
|
|
1881
|
+
*/
|
|
1882
|
+
export async function verifySignedAction(
|
|
1883
|
+
action: SignedAction,
|
|
1884
|
+
publicKeyHex: string
|
|
1885
|
+
): Promise<ActionVerification> {
|
|
1886
|
+
const native = await getNative();
|
|
1887
|
+
if (native.verify_signed_action) {
|
|
1888
|
+
return native.verify_signed_action(action, publicKeyHex);
|
|
1889
|
+
}
|
|
1890
|
+
// JS fallback - simplified verification
|
|
1891
|
+
const expectedSig = `sig-${action.hash.substring(0, 32)}`;
|
|
1892
|
+
const valid = action.signature === expectedSig;
|
|
1893
|
+
return {
|
|
1894
|
+
signatureValid: valid,
|
|
1895
|
+
chainIntact: action.prevHash !== null || action.sequence === 1,
|
|
1896
|
+
hashValid: true,
|
|
1897
|
+
intentVerified: true, // Can't verify intent without context
|
|
1898
|
+
valid,
|
|
1899
|
+
error: valid ? undefined : "Signature verification failed",
|
|
1900
|
+
};
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
class DriftDetectorHandle {
|
|
1904
|
+
private agentId: string;
|
|
1905
|
+
private intentId: string | null;
|
|
1906
|
+
private profile: BehavioralProfile;
|
|
1907
|
+
private recentActions: SignedAction[] = [];
|
|
1908
|
+
private actionTimes: number[] = [];
|
|
1909
|
+
private threshold: number = 0.3;
|
|
1910
|
+
|
|
1911
|
+
constructor(agentId: string, intentId?: string) {
|
|
1912
|
+
this.agentId = agentId;
|
|
1913
|
+
this.intentId = intentId || null;
|
|
1914
|
+
this.profile = {
|
|
1915
|
+
agentId,
|
|
1916
|
+
intentId: intentId || undefined,
|
|
1917
|
+
createdAt: Date.now(),
|
|
1918
|
+
updatedAt: Date.now(),
|
|
1919
|
+
totalActions: 0,
|
|
1920
|
+
actionTypes: {},
|
|
1921
|
+
domains: {},
|
|
1922
|
+
tools: {},
|
|
1923
|
+
actionsPerMinute: 0,
|
|
1924
|
+
rateWindow: 60,
|
|
1925
|
+
commonSequences: [],
|
|
1926
|
+
forbiddenAttempts: 0,
|
|
1927
|
+
approvalRequests: 0,
|
|
1928
|
+
};
|
|
1929
|
+
}
|
|
1930
|
+
|
|
1931
|
+
record(action: SignedAction): void {
|
|
1932
|
+
this.profile.totalActions++;
|
|
1933
|
+
this.profile.updatedAt = Date.now();
|
|
1934
|
+
|
|
1935
|
+
// Update distributions
|
|
1936
|
+
this.profile.actionTypes[action.actionType] = (this.profile.actionTypes[action.actionType] || 0) + 1;
|
|
1937
|
+
this.profile.domains[action.domain] = (this.profile.domains[action.domain] || 0) + 1;
|
|
1938
|
+
this.profile.tools[action.tool] = (this.profile.tools[action.tool] || 0) + 1;
|
|
1939
|
+
|
|
1940
|
+
// Track recent actions
|
|
1941
|
+
this.recentActions.push(action);
|
|
1942
|
+
if (this.recentActions.length > 100) {
|
|
1943
|
+
this.recentActions.shift();
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
// Track times for rate calculation
|
|
1947
|
+
this.actionTimes.push(action.timestamp);
|
|
1948
|
+
const cutoff = Date.now() - this.profile.rateWindow * 1000;
|
|
1949
|
+
this.actionTimes = this.actionTimes.filter(t => t > cutoff);
|
|
1950
|
+
|
|
1951
|
+
// Calculate rate
|
|
1952
|
+
if (this.actionTimes.length > 1) {
|
|
1953
|
+
const lastTime = this.actionTimes[this.actionTimes.length - 1];
|
|
1954
|
+
const firstTime = this.actionTimes[0];
|
|
1955
|
+
if (lastTime !== undefined && firstTime !== undefined) {
|
|
1956
|
+
const timeSpan = (lastTime - firstTime) / 1000;
|
|
1957
|
+
if (timeSpan > 0) {
|
|
1958
|
+
this.profile.actionsPerMinute = (this.actionTimes.length / timeSpan) * 60;
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
recordForbidden(): void {
|
|
1965
|
+
this.profile.forbiddenAttempts++;
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
recordApproval(): void {
|
|
1969
|
+
this.profile.approvalRequests++;
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1972
|
+
detect(): DriftResult {
|
|
1973
|
+
const indicators: DriftIndicator[] = [];
|
|
1974
|
+
|
|
1975
|
+
// Check for too many forbidden attempts
|
|
1976
|
+
if (this.profile.forbiddenAttempts > 0) {
|
|
1977
|
+
const forbiddenRatio = this.profile.forbiddenAttempts / this.profile.totalActions;
|
|
1978
|
+
if (forbiddenRatio > 0.1) {
|
|
1979
|
+
indicators.push({
|
|
1980
|
+
indicatorType: "forbidden-pattern",
|
|
1981
|
+
severity: Math.min(forbiddenRatio, 1),
|
|
1982
|
+
description: `${this.profile.forbiddenAttempts} forbidden attempts (${(forbiddenRatio * 100).toFixed(1)}%)`,
|
|
1983
|
+
factor: "security_violations",
|
|
1984
|
+
evidence: [`${this.profile.forbiddenAttempts} forbidden attempts`],
|
|
1985
|
+
});
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
// Check rate anomaly
|
|
1990
|
+
if (this.profile.actionsPerMinute > 30) {
|
|
1991
|
+
indicators.push({
|
|
1992
|
+
indicatorType: "rate-anomaly",
|
|
1993
|
+
severity: Math.min(this.profile.actionsPerMinute / 60, 1),
|
|
1994
|
+
description: `High action rate: ${this.profile.actionsPerMinute.toFixed(1)}/min`,
|
|
1995
|
+
factor: "action_rate",
|
|
1996
|
+
evidence: [`${this.profile.actionsPerMinute.toFixed(1)} actions/min`],
|
|
1997
|
+
});
|
|
1998
|
+
}
|
|
1999
|
+
|
|
2000
|
+
// Calculate drift score
|
|
2001
|
+
const overallDrift = indicators.length > 0
|
|
2002
|
+
? indicators.reduce((sum, i) => sum + i.severity, 0) / indicators.length
|
|
2003
|
+
: 0;
|
|
2004
|
+
|
|
2005
|
+
const concernLevel = overallDrift > 0.7
|
|
2006
|
+
? "critical" as const
|
|
2007
|
+
: overallDrift > 0.5
|
|
2008
|
+
? "high" as const
|
|
2009
|
+
: overallDrift > this.threshold
|
|
2010
|
+
? "medium" as const
|
|
2011
|
+
: overallDrift > 0.1
|
|
2012
|
+
? "low" as const
|
|
2013
|
+
: "none" as const;
|
|
2014
|
+
|
|
2015
|
+
return {
|
|
2016
|
+
overallDrift,
|
|
2017
|
+
driftFactors: indicators.map(i => ({
|
|
2018
|
+
factorType: i.factor,
|
|
2019
|
+
drift: i.severity,
|
|
2020
|
+
description: i.description,
|
|
2021
|
+
})),
|
|
2022
|
+
concernLevel,
|
|
2023
|
+
};
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
getProfile(): BehavioralProfile {
|
|
2027
|
+
return { ...this.profile };
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
setThreshold(threshold: number): void {
|
|
2031
|
+
this.threshold = threshold;
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
getRecentActions(): SignedAction[] {
|
|
2035
|
+
return [...this.recentActions];
|
|
2036
|
+
}
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
// ===== Automatic Security Hooks =====
|
|
2040
|
+
|
|
2041
|
+
export * from "./hooks.js";
|