palaryn 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +716 -0
- package/dist/sdk/typescript/src/client.d.ts +71 -0
- package/dist/sdk/typescript/src/client.d.ts.map +1 -0
- package/dist/sdk/typescript/src/client.js +176 -0
- package/dist/sdk/typescript/src/client.js.map +1 -0
- package/dist/sdk/typescript/src/errors.d.ts +50 -0
- package/dist/sdk/typescript/src/errors.d.ts.map +1 -0
- package/dist/sdk/typescript/src/errors.js +103 -0
- package/dist/sdk/typescript/src/errors.js.map +1 -0
- package/dist/sdk/typescript/src/index.d.ts +4 -0
- package/dist/sdk/typescript/src/index.d.ts.map +1 -0
- package/dist/sdk/typescript/src/index.js +15 -0
- package/dist/sdk/typescript/src/index.js.map +1 -0
- package/dist/sdk/typescript/src/types.d.ts +101 -0
- package/dist/sdk/typescript/src/types.d.ts.map +1 -0
- package/dist/sdk/typescript/src/types.js +6 -0
- package/dist/sdk/typescript/src/types.js.map +1 -0
- package/dist/src/admin/index.d.ts +2 -0
- package/dist/src/admin/index.d.ts.map +1 -0
- package/dist/src/admin/index.js +6 -0
- package/dist/src/admin/index.js.map +1 -0
- package/dist/src/admin/routes.d.ts +5 -0
- package/dist/src/admin/routes.d.ts.map +1 -0
- package/dist/src/admin/routes.js +471 -0
- package/dist/src/admin/routes.js.map +1 -0
- package/dist/src/admin/templates.d.ts +51 -0
- package/dist/src/admin/templates.d.ts.map +1 -0
- package/dist/src/admin/templates.js +500 -0
- package/dist/src/admin/templates.js.map +1 -0
- package/dist/src/anomaly/detector.d.ts +141 -0
- package/dist/src/anomaly/detector.d.ts.map +1 -0
- package/dist/src/anomaly/detector.js +554 -0
- package/dist/src/anomaly/detector.js.map +1 -0
- package/dist/src/anomaly/index.d.ts +2 -0
- package/dist/src/anomaly/index.d.ts.map +1 -0
- package/dist/src/anomaly/index.js +7 -0
- package/dist/src/anomaly/index.js.map +1 -0
- package/dist/src/approval/manager.d.ts +147 -0
- package/dist/src/approval/manager.d.ts.map +1 -0
- package/dist/src/approval/manager.js +511 -0
- package/dist/src/approval/manager.js.map +1 -0
- package/dist/src/approval/webhook.d.ts +36 -0
- package/dist/src/approval/webhook.d.ts.map +1 -0
- package/dist/src/approval/webhook.js +135 -0
- package/dist/src/approval/webhook.js.map +1 -0
- package/dist/src/audit/logger.d.ts +70 -0
- package/dist/src/audit/logger.d.ts.map +1 -0
- package/dist/src/audit/logger.js +440 -0
- package/dist/src/audit/logger.js.map +1 -0
- package/dist/src/auth/index.d.ts +6 -0
- package/dist/src/auth/index.d.ts.map +1 -0
- package/dist/src/auth/index.js +22 -0
- package/dist/src/auth/index.js.map +1 -0
- package/dist/src/auth/password.d.ts +3 -0
- package/dist/src/auth/password.d.ts.map +1 -0
- package/dist/src/auth/password.js +25 -0
- package/dist/src/auth/password.js.map +1 -0
- package/dist/src/auth/pkce.d.ts +13 -0
- package/dist/src/auth/pkce.d.ts.map +1 -0
- package/dist/src/auth/pkce.js +58 -0
- package/dist/src/auth/pkce.js.map +1 -0
- package/dist/src/auth/providers.d.ts +28 -0
- package/dist/src/auth/providers.d.ts.map +1 -0
- package/dist/src/auth/providers.js +198 -0
- package/dist/src/auth/providers.js.map +1 -0
- package/dist/src/auth/routes.d.ts +14 -0
- package/dist/src/auth/routes.d.ts.map +1 -0
- package/dist/src/auth/routes.js +431 -0
- package/dist/src/auth/routes.js.map +1 -0
- package/dist/src/auth/session.d.ts +24 -0
- package/dist/src/auth/session.d.ts.map +1 -0
- package/dist/src/auth/session.js +105 -0
- package/dist/src/auth/session.js.map +1 -0
- package/dist/src/billing/index.d.ts +7 -0
- package/dist/src/billing/index.d.ts.map +1 -0
- package/dist/src/billing/index.js +14 -0
- package/dist/src/billing/index.js.map +1 -0
- package/dist/src/billing/plan-enforcer.d.ts +44 -0
- package/dist/src/billing/plan-enforcer.d.ts.map +1 -0
- package/dist/src/billing/plan-enforcer.js +110 -0
- package/dist/src/billing/plan-enforcer.js.map +1 -0
- package/dist/src/billing/routes.d.ts +15 -0
- package/dist/src/billing/routes.d.ts.map +1 -0
- package/dist/src/billing/routes.js +193 -0
- package/dist/src/billing/routes.js.map +1 -0
- package/dist/src/billing/stripe-client.d.ts +14 -0
- package/dist/src/billing/stripe-client.d.ts.map +1 -0
- package/dist/src/billing/stripe-client.js +51 -0
- package/dist/src/billing/stripe-client.js.map +1 -0
- package/dist/src/billing/webhook-handler.d.ts +19 -0
- package/dist/src/billing/webhook-handler.d.ts.map +1 -0
- package/dist/src/billing/webhook-handler.js +169 -0
- package/dist/src/billing/webhook-handler.js.map +1 -0
- package/dist/src/billing/webhook-routes.d.ts +5 -0
- package/dist/src/billing/webhook-routes.d.ts.map +1 -0
- package/dist/src/billing/webhook-routes.js +30 -0
- package/dist/src/billing/webhook-routes.js.map +1 -0
- package/dist/src/budget/manager.d.ts +95 -0
- package/dist/src/budget/manager.d.ts.map +1 -0
- package/dist/src/budget/manager.js +547 -0
- package/dist/src/budget/manager.js.map +1 -0
- package/dist/src/budget/usage-extractor.d.ts +38 -0
- package/dist/src/budget/usage-extractor.d.ts.map +1 -0
- package/dist/src/budget/usage-extractor.js +165 -0
- package/dist/src/budget/usage-extractor.js.map +1 -0
- package/dist/src/cli.d.ts +3 -0
- package/dist/src/cli.d.ts.map +1 -0
- package/dist/src/cli.js +115 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/config/defaults.d.ts +3 -0
- package/dist/src/config/defaults.d.ts.map +1 -0
- package/dist/src/config/defaults.js +243 -0
- package/dist/src/config/defaults.js.map +1 -0
- package/dist/src/config/validate.d.ts +15 -0
- package/dist/src/config/validate.d.ts.map +1 -0
- package/dist/src/config/validate.js +105 -0
- package/dist/src/config/validate.js.map +1 -0
- package/dist/src/dlp/composite-scanner.d.ts +47 -0
- package/dist/src/dlp/composite-scanner.d.ts.map +1 -0
- package/dist/src/dlp/composite-scanner.js +186 -0
- package/dist/src/dlp/composite-scanner.js.map +1 -0
- package/dist/src/dlp/index.d.ts +10 -0
- package/dist/src/dlp/index.d.ts.map +1 -0
- package/dist/src/dlp/index.js +26 -0
- package/dist/src/dlp/index.js.map +1 -0
- package/dist/src/dlp/interfaces.d.ts +33 -0
- package/dist/src/dlp/interfaces.d.ts.map +1 -0
- package/dist/src/dlp/interfaces.js +3 -0
- package/dist/src/dlp/interfaces.js.map +1 -0
- package/dist/src/dlp/patterns.d.ts +9 -0
- package/dist/src/dlp/patterns.d.ts.map +1 -0
- package/dist/src/dlp/patterns.js +25 -0
- package/dist/src/dlp/patterns.js.map +1 -0
- package/dist/src/dlp/prompt-injection-backend.d.ts +68 -0
- package/dist/src/dlp/prompt-injection-backend.d.ts.map +1 -0
- package/dist/src/dlp/prompt-injection-backend.js +148 -0
- package/dist/src/dlp/prompt-injection-backend.js.map +1 -0
- package/dist/src/dlp/prompt-injection-patterns.d.ts +32 -0
- package/dist/src/dlp/prompt-injection-patterns.d.ts.map +1 -0
- package/dist/src/dlp/prompt-injection-patterns.js +290 -0
- package/dist/src/dlp/prompt-injection-patterns.js.map +1 -0
- package/dist/src/dlp/regex-backend.d.ts +32 -0
- package/dist/src/dlp/regex-backend.d.ts.map +1 -0
- package/dist/src/dlp/regex-backend.js +153 -0
- package/dist/src/dlp/regex-backend.js.map +1 -0
- package/dist/src/dlp/scanner.d.ts +122 -0
- package/dist/src/dlp/scanner.d.ts.map +1 -0
- package/dist/src/dlp/scanner.js +444 -0
- package/dist/src/dlp/scanner.js.map +1 -0
- package/dist/src/dlp/text-normalizer.d.ts +41 -0
- package/dist/src/dlp/text-normalizer.d.ts.map +1 -0
- package/dist/src/dlp/text-normalizer.js +203 -0
- package/dist/src/dlp/text-normalizer.js.map +1 -0
- package/dist/src/dlp/trufflehog-backend.d.ts +64 -0
- package/dist/src/dlp/trufflehog-backend.d.ts.map +1 -0
- package/dist/src/dlp/trufflehog-backend.js +151 -0
- package/dist/src/dlp/trufflehog-backend.js.map +1 -0
- package/dist/src/executor/http-executor.d.ts +25 -0
- package/dist/src/executor/http-executor.d.ts.map +1 -0
- package/dist/src/executor/http-executor.js +333 -0
- package/dist/src/executor/http-executor.js.map +1 -0
- package/dist/src/executor/index.d.ts +6 -0
- package/dist/src/executor/index.d.ts.map +1 -0
- package/dist/src/executor/index.js +12 -0
- package/dist/src/executor/index.js.map +1 -0
- package/dist/src/executor/interfaces.d.ts +11 -0
- package/dist/src/executor/interfaces.d.ts.map +1 -0
- package/dist/src/executor/interfaces.js +3 -0
- package/dist/src/executor/interfaces.js.map +1 -0
- package/dist/src/executor/noop-executor.d.ts +13 -0
- package/dist/src/executor/noop-executor.d.ts.map +1 -0
- package/dist/src/executor/noop-executor.js +21 -0
- package/dist/src/executor/noop-executor.js.map +1 -0
- package/dist/src/executor/registry.d.ts +30 -0
- package/dist/src/executor/registry.d.ts.map +1 -0
- package/dist/src/executor/registry.js +62 -0
- package/dist/src/executor/registry.js.map +1 -0
- package/dist/src/executor/slack-executor.d.ts +24 -0
- package/dist/src/executor/slack-executor.d.ts.map +1 -0
- package/dist/src/executor/slack-executor.js +147 -0
- package/dist/src/executor/slack-executor.js.map +1 -0
- package/dist/src/index.d.ts +25 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +74 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/mcp/auth-verifier.d.ts +23 -0
- package/dist/src/mcp/auth-verifier.d.ts.map +1 -0
- package/dist/src/mcp/auth-verifier.js +162 -0
- package/dist/src/mcp/auth-verifier.js.map +1 -0
- package/dist/src/mcp/bridge.d.ts +132 -0
- package/dist/src/mcp/bridge.d.ts.map +1 -0
- package/dist/src/mcp/bridge.js +734 -0
- package/dist/src/mcp/bridge.js.map +1 -0
- package/dist/src/mcp/http-transport.d.ts +32 -0
- package/dist/src/mcp/http-transport.d.ts.map +1 -0
- package/dist/src/mcp/http-transport.js +538 -0
- package/dist/src/mcp/http-transport.js.map +1 -0
- package/dist/src/mcp/index.d.ts +10 -0
- package/dist/src/mcp/index.d.ts.map +1 -0
- package/dist/src/mcp/index.js +17 -0
- package/dist/src/mcp/index.js.map +1 -0
- package/dist/src/mcp/oauth-pages.d.ts +23 -0
- package/dist/src/mcp/oauth-pages.d.ts.map +1 -0
- package/dist/src/mcp/oauth-pages.js +121 -0
- package/dist/src/mcp/oauth-pages.js.map +1 -0
- package/dist/src/mcp/oauth-postgres-stores.d.ts +55 -0
- package/dist/src/mcp/oauth-postgres-stores.d.ts.map +1 -0
- package/dist/src/mcp/oauth-postgres-stores.js +226 -0
- package/dist/src/mcp/oauth-postgres-stores.js.map +1 -0
- package/dist/src/mcp/oauth-provider.d.ts +95 -0
- package/dist/src/mcp/oauth-provider.d.ts.map +1 -0
- package/dist/src/mcp/oauth-provider.js +360 -0
- package/dist/src/mcp/oauth-provider.js.map +1 -0
- package/dist/src/mcp/oauth-stores.d.ts +62 -0
- package/dist/src/mcp/oauth-stores.d.ts.map +1 -0
- package/dist/src/mcp/oauth-stores.js +154 -0
- package/dist/src/mcp/oauth-stores.js.map +1 -0
- package/dist/src/mcp/server.d.ts +18 -0
- package/dist/src/mcp/server.d.ts.map +1 -0
- package/dist/src/mcp/server.js +51 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/metrics/collector.d.ts +106 -0
- package/dist/src/metrics/collector.d.ts.map +1 -0
- package/dist/src/metrics/collector.js +311 -0
- package/dist/src/metrics/collector.js.map +1 -0
- package/dist/src/metrics/index.d.ts +2 -0
- package/dist/src/metrics/index.d.ts.map +1 -0
- package/dist/src/metrics/index.js +6 -0
- package/dist/src/metrics/index.js.map +1 -0
- package/dist/src/middleware/auth.d.ts +77 -0
- package/dist/src/middleware/auth.d.ts.map +1 -0
- package/dist/src/middleware/auth.js +720 -0
- package/dist/src/middleware/auth.js.map +1 -0
- package/dist/src/middleware/session.d.ts +18 -0
- package/dist/src/middleware/session.d.ts.map +1 -0
- package/dist/src/middleware/session.js +67 -0
- package/dist/src/middleware/session.js.map +1 -0
- package/dist/src/middleware/validate.d.ts +3 -0
- package/dist/src/middleware/validate.d.ts.map +1 -0
- package/dist/src/middleware/validate.js +85 -0
- package/dist/src/middleware/validate.js.map +1 -0
- package/dist/src/policy/engine.d.ts +107 -0
- package/dist/src/policy/engine.d.ts.map +1 -0
- package/dist/src/policy/engine.js +646 -0
- package/dist/src/policy/engine.js.map +1 -0
- package/dist/src/policy/index.d.ts +3 -0
- package/dist/src/policy/index.d.ts.map +1 -0
- package/dist/src/policy/index.js +8 -0
- package/dist/src/policy/index.js.map +1 -0
- package/dist/src/policy/opa-engine.d.ts +176 -0
- package/dist/src/policy/opa-engine.d.ts.map +1 -0
- package/dist/src/policy/opa-engine.js +790 -0
- package/dist/src/policy/opa-engine.js.map +1 -0
- package/dist/src/proxy/forward-proxy.d.ts +30 -0
- package/dist/src/proxy/forward-proxy.d.ts.map +1 -0
- package/dist/src/proxy/forward-proxy.js +580 -0
- package/dist/src/proxy/forward-proxy.js.map +1 -0
- package/dist/src/proxy/index.d.ts +2 -0
- package/dist/src/proxy/index.d.ts.map +1 -0
- package/dist/src/proxy/index.js +8 -0
- package/dist/src/proxy/index.js.map +1 -0
- package/dist/src/ratelimit/limiter.d.ts +45 -0
- package/dist/src/ratelimit/limiter.d.ts.map +1 -0
- package/dist/src/ratelimit/limiter.js +158 -0
- package/dist/src/ratelimit/limiter.js.map +1 -0
- package/dist/src/replay/engine.d.ts +40 -0
- package/dist/src/replay/engine.d.ts.map +1 -0
- package/dist/src/replay/engine.js +106 -0
- package/dist/src/replay/engine.js.map +1 -0
- package/dist/src/replay/index.d.ts +2 -0
- package/dist/src/replay/index.d.ts.map +1 -0
- package/dist/src/replay/index.js +6 -0
- package/dist/src/replay/index.js.map +1 -0
- package/dist/src/saas/index.d.ts +2 -0
- package/dist/src/saas/index.d.ts.map +1 -0
- package/dist/src/saas/index.js +18 -0
- package/dist/src/saas/index.js.map +1 -0
- package/dist/src/saas/routes.d.ts +18 -0
- package/dist/src/saas/routes.d.ts.map +1 -0
- package/dist/src/saas/routes.js +1566 -0
- package/dist/src/saas/routes.js.map +1 -0
- package/dist/src/server/app.d.ts +44 -0
- package/dist/src/server/app.d.ts.map +1 -0
- package/dist/src/server/app.js +854 -0
- package/dist/src/server/app.js.map +1 -0
- package/dist/src/server/errors.d.ts +32 -0
- package/dist/src/server/errors.d.ts.map +1 -0
- package/dist/src/server/errors.js +39 -0
- package/dist/src/server/errors.js.map +1 -0
- package/dist/src/server/gateway.d.ts +165 -0
- package/dist/src/server/gateway.d.ts.map +1 -0
- package/dist/src/server/gateway.js +964 -0
- package/dist/src/server/gateway.js.map +1 -0
- package/dist/src/server/index.d.ts +2 -0
- package/dist/src/server/index.d.ts.map +1 -0
- package/dist/src/server/index.js +295 -0
- package/dist/src/server/index.js.map +1 -0
- package/dist/src/server/logger.d.ts +33 -0
- package/dist/src/server/logger.d.ts.map +1 -0
- package/dist/src/server/logger.js +230 -0
- package/dist/src/server/logger.js.map +1 -0
- package/dist/src/server/stream-proxy.d.ts +32 -0
- package/dist/src/server/stream-proxy.d.ts.map +1 -0
- package/dist/src/server/stream-proxy.js +184 -0
- package/dist/src/server/stream-proxy.js.map +1 -0
- package/dist/src/storage/file-persistence.d.ts +48 -0
- package/dist/src/storage/file-persistence.d.ts.map +1 -0
- package/dist/src/storage/file-persistence.js +280 -0
- package/dist/src/storage/file-persistence.js.map +1 -0
- package/dist/src/storage/index.d.ts +5 -0
- package/dist/src/storage/index.d.ts.map +1 -0
- package/dist/src/storage/index.js +21 -0
- package/dist/src/storage/index.js.map +1 -0
- package/dist/src/storage/interfaces.d.ts +237 -0
- package/dist/src/storage/interfaces.d.ts.map +1 -0
- package/dist/src/storage/interfaces.js +3 -0
- package/dist/src/storage/interfaces.js.map +1 -0
- package/dist/src/storage/memory.d.ts +162 -0
- package/dist/src/storage/memory.d.ts.map +1 -0
- package/dist/src/storage/memory.js +603 -0
- package/dist/src/storage/memory.js.map +1 -0
- package/dist/src/storage/postgres.d.ts +267 -0
- package/dist/src/storage/postgres.d.ts.map +1 -0
- package/dist/src/storage/postgres.js +1555 -0
- package/dist/src/storage/postgres.js.map +1 -0
- package/dist/src/storage/redis.d.ts +202 -0
- package/dist/src/storage/redis.d.ts.map +1 -0
- package/dist/src/storage/redis.js +629 -0
- package/dist/src/storage/redis.js.map +1 -0
- package/dist/src/tracing/index.d.ts +2 -0
- package/dist/src/tracing/index.d.ts.map +1 -0
- package/dist/src/tracing/index.js +6 -0
- package/dist/src/tracing/index.js.map +1 -0
- package/dist/src/tracing/provider.d.ts +43 -0
- package/dist/src/tracing/provider.d.ts.map +1 -0
- package/dist/src/tracing/provider.js +74 -0
- package/dist/src/tracing/provider.js.map +1 -0
- package/dist/src/trust/calculator.d.ts +54 -0
- package/dist/src/trust/calculator.d.ts.map +1 -0
- package/dist/src/trust/calculator.js +102 -0
- package/dist/src/trust/calculator.js.map +1 -0
- package/dist/src/trust/index.d.ts +2 -0
- package/dist/src/trust/index.d.ts.map +1 -0
- package/dist/src/trust/index.js +7 -0
- package/dist/src/trust/index.js.map +1 -0
- package/dist/src/types/budget.d.ts +30 -0
- package/dist/src/types/budget.d.ts.map +1 -0
- package/dist/src/types/budget.js +3 -0
- package/dist/src/types/budget.js.map +1 -0
- package/dist/src/types/config.d.ts +176 -0
- package/dist/src/types/config.d.ts.map +1 -0
- package/dist/src/types/config.js +3 -0
- package/dist/src/types/config.js.map +1 -0
- package/dist/src/types/events.d.ts +24 -0
- package/dist/src/types/events.d.ts.map +1 -0
- package/dist/src/types/events.js +3 -0
- package/dist/src/types/events.js.map +1 -0
- package/dist/src/types/index.d.ts +8 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/types/index.js +24 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/types/policy.d.ts +60 -0
- package/dist/src/types/policy.d.ts.map +1 -0
- package/dist/src/types/policy.js +3 -0
- package/dist/src/types/policy.js.map +1 -0
- package/dist/src/types/stripe-config.d.ts +12 -0
- package/dist/src/types/stripe-config.d.ts.map +1 -0
- package/dist/src/types/stripe-config.js +3 -0
- package/dist/src/types/stripe-config.js.map +1 -0
- package/dist/src/types/subscription.d.ts +24 -0
- package/dist/src/types/subscription.d.ts.map +1 -0
- package/dist/src/types/subscription.js +38 -0
- package/dist/src/types/subscription.js.map +1 -0
- package/dist/src/types/tool-call.d.ts +42 -0
- package/dist/src/types/tool-call.d.ts.map +1 -0
- package/dist/src/types/tool-call.js +3 -0
- package/dist/src/types/tool-call.js.map +1 -0
- package/dist/src/types/tool-result.d.ts +58 -0
- package/dist/src/types/tool-result.d.ts.map +1 -0
- package/dist/src/types/tool-result.js +3 -0
- package/dist/src/types/tool-result.js.map +1 -0
- package/dist/src/types/user.d.ts +101 -0
- package/dist/src/types/user.d.ts.map +1 -0
- package/dist/src/types/user.js +6 -0
- package/dist/src/types/user.js.map +1 -0
- package/dist/tests/integration/api.test.d.ts +2 -0
- package/dist/tests/integration/api.test.d.ts.map +1 -0
- package/dist/tests/integration/api.test.js +1199 -0
- package/dist/tests/integration/api.test.js.map +1 -0
- package/dist/tests/integration/proxy.test.d.ts +2 -0
- package/dist/tests/integration/proxy.test.d.ts.map +1 -0
- package/dist/tests/integration/proxy.test.js +251 -0
- package/dist/tests/integration/proxy.test.js.map +1 -0
- package/dist/tests/integration/storage.test.d.ts +16 -0
- package/dist/tests/integration/storage.test.d.ts.map +1 -0
- package/dist/tests/integration/storage.test.js +826 -0
- package/dist/tests/integration/storage.test.js.map +1 -0
- package/dist/tests/unit/admin.test.d.ts +2 -0
- package/dist/tests/unit/admin.test.d.ts.map +1 -0
- package/dist/tests/unit/admin.test.js +698 -0
- package/dist/tests/unit/admin.test.js.map +1 -0
- package/dist/tests/unit/anomaly-detector.test.d.ts +2 -0
- package/dist/tests/unit/anomaly-detector.test.d.ts.map +1 -0
- package/dist/tests/unit/anomaly-detector.test.js +903 -0
- package/dist/tests/unit/anomaly-detector.test.js.map +1 -0
- package/dist/tests/unit/approval-manager.test.d.ts +2 -0
- package/dist/tests/unit/approval-manager.test.d.ts.map +1 -0
- package/dist/tests/unit/approval-manager.test.js +528 -0
- package/dist/tests/unit/approval-manager.test.js.map +1 -0
- package/dist/tests/unit/approval-webhook.test.d.ts +2 -0
- package/dist/tests/unit/approval-webhook.test.d.ts.map +1 -0
- package/dist/tests/unit/approval-webhook.test.js +355 -0
- package/dist/tests/unit/approval-webhook.test.js.map +1 -0
- package/dist/tests/unit/audit-logger.test.d.ts +2 -0
- package/dist/tests/unit/audit-logger.test.d.ts.map +1 -0
- package/dist/tests/unit/audit-logger.test.js +635 -0
- package/dist/tests/unit/audit-logger.test.js.map +1 -0
- package/dist/tests/unit/auth-routes.test.d.ts +2 -0
- package/dist/tests/unit/auth-routes.test.d.ts.map +1 -0
- package/dist/tests/unit/auth-routes.test.js +281 -0
- package/dist/tests/unit/auth-routes.test.js.map +1 -0
- package/dist/tests/unit/auth.test.d.ts +2 -0
- package/dist/tests/unit/auth.test.d.ts.map +1 -0
- package/dist/tests/unit/auth.test.js +1382 -0
- package/dist/tests/unit/auth.test.js.map +1 -0
- package/dist/tests/unit/billing.test.d.ts +2 -0
- package/dist/tests/unit/billing.test.d.ts.map +1 -0
- package/dist/tests/unit/billing.test.js +579 -0
- package/dist/tests/unit/billing.test.js.map +1 -0
- package/dist/tests/unit/budget-manager.test.d.ts +2 -0
- package/dist/tests/unit/budget-manager.test.d.ts.map +1 -0
- package/dist/tests/unit/budget-manager.test.js +778 -0
- package/dist/tests/unit/budget-manager.test.js.map +1 -0
- package/dist/tests/unit/budget-race.test.d.ts +2 -0
- package/dist/tests/unit/budget-race.test.d.ts.map +1 -0
- package/dist/tests/unit/budget-race.test.js +58 -0
- package/dist/tests/unit/budget-race.test.js.map +1 -0
- package/dist/tests/unit/cli.test.d.ts +2 -0
- package/dist/tests/unit/cli.test.d.ts.map +1 -0
- package/dist/tests/unit/cli.test.js +93 -0
- package/dist/tests/unit/cli.test.js.map +1 -0
- package/dist/tests/unit/concurrency.test.d.ts +2 -0
- package/dist/tests/unit/concurrency.test.d.ts.map +1 -0
- package/dist/tests/unit/concurrency.test.js +1270 -0
- package/dist/tests/unit/concurrency.test.js.map +1 -0
- package/dist/tests/unit/config-validate.test.d.ts +2 -0
- package/dist/tests/unit/config-validate.test.d.ts.map +1 -0
- package/dist/tests/unit/config-validate.test.js +230 -0
- package/dist/tests/unit/config-validate.test.js.map +1 -0
- package/dist/tests/unit/defaults.test.d.ts +2 -0
- package/dist/tests/unit/defaults.test.d.ts.map +1 -0
- package/dist/tests/unit/defaults.test.js +364 -0
- package/dist/tests/unit/defaults.test.js.map +1 -0
- package/dist/tests/unit/dlp-backends.test.d.ts +2 -0
- package/dist/tests/unit/dlp-backends.test.d.ts.map +1 -0
- package/dist/tests/unit/dlp-backends.test.js +563 -0
- package/dist/tests/unit/dlp-backends.test.js.map +1 -0
- package/dist/tests/unit/dlp-scanner.test.d.ts +2 -0
- package/dist/tests/unit/dlp-scanner.test.d.ts.map +1 -0
- package/dist/tests/unit/dlp-scanner.test.js +739 -0
- package/dist/tests/unit/dlp-scanner.test.js.map +1 -0
- package/dist/tests/unit/error-responses.test.d.ts +2 -0
- package/dist/tests/unit/error-responses.test.d.ts.map +1 -0
- package/dist/tests/unit/error-responses.test.js +101 -0
- package/dist/tests/unit/error-responses.test.js.map +1 -0
- package/dist/tests/unit/executor-registry.test.d.ts +2 -0
- package/dist/tests/unit/executor-registry.test.d.ts.map +1 -0
- package/dist/tests/unit/executor-registry.test.js +390 -0
- package/dist/tests/unit/executor-registry.test.js.map +1 -0
- package/dist/tests/unit/forward-proxy.test.d.ts +2 -0
- package/dist/tests/unit/forward-proxy.test.d.ts.map +1 -0
- package/dist/tests/unit/forward-proxy.test.js +621 -0
- package/dist/tests/unit/forward-proxy.test.js.map +1 -0
- package/dist/tests/unit/gateway-features.test.d.ts +2 -0
- package/dist/tests/unit/gateway-features.test.d.ts.map +1 -0
- package/dist/tests/unit/gateway-features.test.js +753 -0
- package/dist/tests/unit/gateway-features.test.js.map +1 -0
- package/dist/tests/unit/http-executor.test.d.ts +2 -0
- package/dist/tests/unit/http-executor.test.d.ts.map +1 -0
- package/dist/tests/unit/http-executor.test.js +310 -0
- package/dist/tests/unit/http-executor.test.js.map +1 -0
- package/dist/tests/unit/mcp-bridge.test.d.ts +2 -0
- package/dist/tests/unit/mcp-bridge.test.d.ts.map +1 -0
- package/dist/tests/unit/mcp-bridge.test.js +1136 -0
- package/dist/tests/unit/mcp-bridge.test.js.map +1 -0
- package/dist/tests/unit/mcp-http-transport.test.d.ts +2 -0
- package/dist/tests/unit/mcp-http-transport.test.d.ts.map +1 -0
- package/dist/tests/unit/mcp-http-transport.test.js +899 -0
- package/dist/tests/unit/mcp-http-transport.test.js.map +1 -0
- package/dist/tests/unit/mcp-oauth.test.d.ts +2 -0
- package/dist/tests/unit/mcp-oauth.test.d.ts.map +1 -0
- package/dist/tests/unit/mcp-oauth.test.js +759 -0
- package/dist/tests/unit/mcp-oauth.test.js.map +1 -0
- package/dist/tests/unit/mcp-server.test.d.ts +15 -0
- package/dist/tests/unit/mcp-server.test.d.ts.map +1 -0
- package/dist/tests/unit/mcp-server.test.js +158 -0
- package/dist/tests/unit/mcp-server.test.js.map +1 -0
- package/dist/tests/unit/metrics.test.d.ts +2 -0
- package/dist/tests/unit/metrics.test.d.ts.map +1 -0
- package/dist/tests/unit/metrics.test.js +208 -0
- package/dist/tests/unit/metrics.test.js.map +1 -0
- package/dist/tests/unit/oauth.test.d.ts +2 -0
- package/dist/tests/unit/oauth.test.d.ts.map +1 -0
- package/dist/tests/unit/oauth.test.js +281 -0
- package/dist/tests/unit/oauth.test.js.map +1 -0
- package/dist/tests/unit/opa-circuit-breaker.test.d.ts +2 -0
- package/dist/tests/unit/opa-circuit-breaker.test.d.ts.map +1 -0
- package/dist/tests/unit/opa-circuit-breaker.test.js +297 -0
- package/dist/tests/unit/opa-circuit-breaker.test.js.map +1 -0
- package/dist/tests/unit/opa-engine.test.d.ts +2 -0
- package/dist/tests/unit/opa-engine.test.d.ts.map +1 -0
- package/dist/tests/unit/opa-engine.test.js +1813 -0
- package/dist/tests/unit/opa-engine.test.js.map +1 -0
- package/dist/tests/unit/pipeline-timing.test.d.ts +2 -0
- package/dist/tests/unit/pipeline-timing.test.d.ts.map +1 -0
- package/dist/tests/unit/pipeline-timing.test.js +528 -0
- package/dist/tests/unit/pipeline-timing.test.js.map +1 -0
- package/dist/tests/unit/policy-engine.test.d.ts +2 -0
- package/dist/tests/unit/policy-engine.test.d.ts.map +1 -0
- package/dist/tests/unit/policy-engine.test.js +1345 -0
- package/dist/tests/unit/policy-engine.test.js.map +1 -0
- package/dist/tests/unit/policy-store.test.d.ts +2 -0
- package/dist/tests/unit/policy-store.test.d.ts.map +1 -0
- package/dist/tests/unit/policy-store.test.js +60 -0
- package/dist/tests/unit/policy-store.test.js.map +1 -0
- package/dist/tests/unit/postgres-storage.test.d.ts +2 -0
- package/dist/tests/unit/postgres-storage.test.d.ts.map +1 -0
- package/dist/tests/unit/postgres-storage.test.js +614 -0
- package/dist/tests/unit/postgres-storage.test.js.map +1 -0
- package/dist/tests/unit/prompt-injection-backend.test.d.ts +2 -0
- package/dist/tests/unit/prompt-injection-backend.test.d.ts.map +1 -0
- package/dist/tests/unit/prompt-injection-backend.test.js +621 -0
- package/dist/tests/unit/prompt-injection-backend.test.js.map +1 -0
- package/dist/tests/unit/proxy-hardening.test.d.ts +2 -0
- package/dist/tests/unit/proxy-hardening.test.d.ts.map +1 -0
- package/dist/tests/unit/proxy-hardening.test.js +166 -0
- package/dist/tests/unit/proxy-hardening.test.js.map +1 -0
- package/dist/tests/unit/rate-limiter.test.d.ts +2 -0
- package/dist/tests/unit/rate-limiter.test.d.ts.map +1 -0
- package/dist/tests/unit/rate-limiter.test.js +443 -0
- package/dist/tests/unit/rate-limiter.test.js.map +1 -0
- package/dist/tests/unit/redis-storage.test.d.ts +2 -0
- package/dist/tests/unit/redis-storage.test.d.ts.map +1 -0
- package/dist/tests/unit/redis-storage.test.js +766 -0
- package/dist/tests/unit/redis-storage.test.js.map +1 -0
- package/dist/tests/unit/replay-engine.test.d.ts +2 -0
- package/dist/tests/unit/replay-engine.test.d.ts.map +1 -0
- package/dist/tests/unit/replay-engine.test.js +371 -0
- package/dist/tests/unit/replay-engine.test.js.map +1 -0
- package/dist/tests/unit/saas-routes.test.d.ts +2 -0
- package/dist/tests/unit/saas-routes.test.d.ts.map +1 -0
- package/dist/tests/unit/saas-routes.test.js +1399 -0
- package/dist/tests/unit/saas-routes.test.js.map +1 -0
- package/dist/tests/unit/session.test.d.ts +2 -0
- package/dist/tests/unit/session.test.d.ts.map +1 -0
- package/dist/tests/unit/session.test.js +532 -0
- package/dist/tests/unit/session.test.js.map +1 -0
- package/dist/tests/unit/slack-executor.test.d.ts +2 -0
- package/dist/tests/unit/slack-executor.test.d.ts.map +1 -0
- package/dist/tests/unit/slack-executor.test.js +209 -0
- package/dist/tests/unit/slack-executor.test.js.map +1 -0
- package/dist/tests/unit/storage-hardening.test.d.ts +2 -0
- package/dist/tests/unit/storage-hardening.test.d.ts.map +1 -0
- package/dist/tests/unit/storage-hardening.test.js +165 -0
- package/dist/tests/unit/storage-hardening.test.js.map +1 -0
- package/dist/tests/unit/storage.test.d.ts +2 -0
- package/dist/tests/unit/storage.test.d.ts.map +1 -0
- package/dist/tests/unit/storage.test.js +698 -0
- package/dist/tests/unit/storage.test.js.map +1 -0
- package/dist/tests/unit/text-normalizer.test.d.ts +2 -0
- package/dist/tests/unit/text-normalizer.test.d.ts.map +1 -0
- package/dist/tests/unit/text-normalizer.test.js +229 -0
- package/dist/tests/unit/text-normalizer.test.js.map +1 -0
- package/dist/tests/unit/tracing.test.d.ts +2 -0
- package/dist/tests/unit/tracing.test.d.ts.map +1 -0
- package/dist/tests/unit/tracing.test.js +611 -0
- package/dist/tests/unit/tracing.test.js.map +1 -0
- package/dist/tests/unit/trust-calculator.test.d.ts +2 -0
- package/dist/tests/unit/trust-calculator.test.d.ts.map +1 -0
- package/dist/tests/unit/trust-calculator.test.js +497 -0
- package/dist/tests/unit/trust-calculator.test.js.map +1 -0
- package/dist/tests/unit/ts-sdk.test.d.ts +2 -0
- package/dist/tests/unit/ts-sdk.test.d.ts.map +1 -0
- package/dist/tests/unit/ts-sdk.test.js +421 -0
- package/dist/tests/unit/ts-sdk.test.js.map +1 -0
- package/dist/tests/unit/usage-extractor-llm.test.d.ts +2 -0
- package/dist/tests/unit/usage-extractor-llm.test.d.ts.map +1 -0
- package/dist/tests/unit/usage-extractor-llm.test.js +139 -0
- package/dist/tests/unit/usage-extractor-llm.test.js.map +1 -0
- package/dist/tests/unit/usage-extractor.test.d.ts +2 -0
- package/dist/tests/unit/usage-extractor.test.d.ts.map +1 -0
- package/dist/tests/unit/usage-extractor.test.js +271 -0
- package/dist/tests/unit/usage-extractor.test.js.map +1 -0
- package/dist/tests/unit/user-stores.test.d.ts +2 -0
- package/dist/tests/unit/user-stores.test.d.ts.map +1 -0
- package/dist/tests/unit/user-stores.test.js +687 -0
- package/dist/tests/unit/user-stores.test.js.map +1 -0
- package/dist/tests/unit/validate.test.d.ts +2 -0
- package/dist/tests/unit/validate.test.d.ts.map +1 -0
- package/dist/tests/unit/validate.test.js +545 -0
- package/dist/tests/unit/validate.test.js.map +1 -0
- package/package.json +86 -0
- package/policy-packs/README.md +42 -0
- package/policy-packs/default.yaml +46 -0
- package/policy-packs/dev_fast.yaml +54 -0
- package/policy-packs/prod_strict.yaml +83 -0
|
@@ -0,0 +1,646 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PolicyEngine = void 0;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const net = __importStar(require("net"));
|
|
39
|
+
const yaml = __importStar(require("js-yaml"));
|
|
40
|
+
/**
|
|
41
|
+
* Check if a hostname resolves to a private/internal IP address or is a
|
|
42
|
+
* well-known loopback/link-local name. Used for SSRF protection.
|
|
43
|
+
*/
|
|
44
|
+
function isPrivateTarget(hostname) {
|
|
45
|
+
const lower = hostname.toLowerCase();
|
|
46
|
+
// Well-known private hostnames
|
|
47
|
+
if (lower === 'localhost' || lower === '0.0.0.0') {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
// IPv6 loopback and link-local
|
|
51
|
+
if (lower === '::1' || lower === '[::1]') {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
// Strip square brackets for IPv6 addresses
|
|
55
|
+
const bare = lower.startsWith('[') && lower.endsWith(']') ? lower.slice(1, -1) : lower;
|
|
56
|
+
// Check for IPv6 link-local (fe80::/10)
|
|
57
|
+
if (bare.startsWith('fe80:') || bare.startsWith('fe80%')) {
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
// Check for IPv6 multicast (ff00::/8)
|
|
61
|
+
if (bare.startsWith('ff')) {
|
|
62
|
+
const secondChar = bare.charAt(2);
|
|
63
|
+
if (secondChar === '0' || secondChar === ':') {
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
// ff02::1, ff0e::, etc. — any address starting with ff is multicast
|
|
67
|
+
if (/^ff[0-9a-f]{2}:/i.test(bare)) {
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Check for Teredo tunneling (2001:0000::/32)
|
|
72
|
+
// Teredo addresses start with 2001:0000: or 2001:0:
|
|
73
|
+
if (/^2001:0{0,4}:/i.test(bare)) {
|
|
74
|
+
return true;
|
|
75
|
+
}
|
|
76
|
+
// Check for 6to4 addresses (2002::/16)
|
|
77
|
+
if (bare.startsWith('2002:')) {
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
// Check for IPv6 unique local addresses (fc00::/7 — includes fd00::/8)
|
|
81
|
+
if (/^f[cd]/i.test(bare)) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
// IPv6 unspecified address (::) - equivalent to 0.0.0.0
|
|
85
|
+
if (bare === '::' || bare === '0:0:0:0:0:0:0:0' || bare === '0000:0000:0000:0000:0000:0000:0000:0000') {
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
// IPv6 documentation range (2001:db8::/32, RFC 3849)
|
|
89
|
+
if (/^2001:0?db8:/i.test(bare) || bare.startsWith('2001:db8:')) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
// IPv4-compatible IPv6 (deprecated ::x.x.x.x format)
|
|
93
|
+
const compatMatch = bare.match(/^::(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/);
|
|
94
|
+
if (compatMatch) {
|
|
95
|
+
return isPrivateTarget(compatMatch[1]);
|
|
96
|
+
}
|
|
97
|
+
// Check if it's an IPv4 address
|
|
98
|
+
if (net.isIPv4(bare)) {
|
|
99
|
+
const parts = bare.split('.').map(Number);
|
|
100
|
+
// 127.0.0.0/8
|
|
101
|
+
if (parts[0] === 127)
|
|
102
|
+
return true;
|
|
103
|
+
// 10.0.0.0/8
|
|
104
|
+
if (parts[0] === 10)
|
|
105
|
+
return true;
|
|
106
|
+
// 172.16.0.0/12
|
|
107
|
+
if (parts[0] === 172 && parts[1] >= 16 && parts[1] <= 31)
|
|
108
|
+
return true;
|
|
109
|
+
// 192.168.0.0/16
|
|
110
|
+
if (parts[0] === 192 && parts[1] === 168)
|
|
111
|
+
return true;
|
|
112
|
+
// 169.254.0.0/16 (link-local)
|
|
113
|
+
if (parts[0] === 169 && parts[1] === 254)
|
|
114
|
+
return true;
|
|
115
|
+
// 100.64.0.0/10 (CGNAT / shared address space)
|
|
116
|
+
if (parts[0] === 100 && parts[1] >= 64 && parts[1] <= 127)
|
|
117
|
+
return true;
|
|
118
|
+
// 0.0.0.0
|
|
119
|
+
if (parts[0] === 0 && parts[1] === 0 && parts[2] === 0 && parts[3] === 0)
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
// Check for IPv6 addresses (non-specific format — net.isIPv6)
|
|
123
|
+
if (net.isIPv6(bare)) {
|
|
124
|
+
// Catch mapped IPv4 in dotted-quad form: ::ffff:127.0.0.1
|
|
125
|
+
const mappedMatch = bare.match(/::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/i);
|
|
126
|
+
if (mappedMatch) {
|
|
127
|
+
return isPrivateTarget(mappedMatch[1]);
|
|
128
|
+
}
|
|
129
|
+
// Catch mapped IPv4 in hex form (as URL parsers normalize): ::ffff:7f00:1
|
|
130
|
+
const mappedHexMatch = bare.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/i);
|
|
131
|
+
if (mappedHexMatch) {
|
|
132
|
+
const hi = parseInt(mappedHexMatch[1], 16);
|
|
133
|
+
const lo = parseInt(mappedHexMatch[2], 16);
|
|
134
|
+
const ipv4 = `${(hi >> 8) & 0xff}.${hi & 0xff}.${(lo >> 8) & 0xff}.${lo & 0xff}`;
|
|
135
|
+
return isPrivateTarget(ipv4);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return false;
|
|
139
|
+
}
|
|
140
|
+
const VALID_EFFECTS = ['ALLOW', 'DENY', 'TRANSFORM', 'REQUIRE_APPROVAL'];
|
|
141
|
+
class PolicyEngine {
|
|
142
|
+
constructor(packPath, defaultEffect = 'DENY') {
|
|
143
|
+
/** Compiled regex cache: pattern string -> RegExp */
|
|
144
|
+
this.regexCache = new Map();
|
|
145
|
+
this.packPath = packPath;
|
|
146
|
+
this.defaultEffect = defaultEffect;
|
|
147
|
+
this.pack = this.loadPack(packPath);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Create a PolicyEngine from an in-memory PolicyPack (no file I/O).
|
|
151
|
+
* Used for workspace-specific policies stored in PolicyStore.
|
|
152
|
+
*/
|
|
153
|
+
static fromPack(pack, defaultEffect = 'DENY') {
|
|
154
|
+
const engine = Object.create(PolicyEngine.prototype);
|
|
155
|
+
engine.packPath = '__in_memory__';
|
|
156
|
+
engine.defaultEffect = defaultEffect;
|
|
157
|
+
engine.regexCache = new Map();
|
|
158
|
+
// Validate
|
|
159
|
+
const validation = PolicyEngine.validate(pack);
|
|
160
|
+
if (!validation.valid) {
|
|
161
|
+
throw new Error(`Invalid policy pack: ${validation.errors.join('; ')}`);
|
|
162
|
+
}
|
|
163
|
+
// Sort rules by priority (same as loadPack does)
|
|
164
|
+
const sortedPack = { ...pack, rules: [...pack.rules] };
|
|
165
|
+
sortedPack.rules.sort((a, b) => {
|
|
166
|
+
const pa = a.priority ?? Number.MAX_SAFE_INTEGER;
|
|
167
|
+
const pb = b.priority ?? Number.MAX_SAFE_INTEGER;
|
|
168
|
+
return pa - pb;
|
|
169
|
+
});
|
|
170
|
+
engine.pack = sortedPack;
|
|
171
|
+
return engine;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Load and parse a policy pack from a YAML file on disk.
|
|
175
|
+
* Validates the structure and sorts rules by priority (ascending).
|
|
176
|
+
*/
|
|
177
|
+
loadPack(path) {
|
|
178
|
+
let content;
|
|
179
|
+
try {
|
|
180
|
+
content = fs.readFileSync(path, 'utf-8');
|
|
181
|
+
}
|
|
182
|
+
catch (err) {
|
|
183
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
184
|
+
throw new Error(`Failed to read policy pack file at "${path}": ${message}`);
|
|
185
|
+
}
|
|
186
|
+
let parsed;
|
|
187
|
+
try {
|
|
188
|
+
parsed = yaml.load(content);
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
192
|
+
throw new Error(`Failed to parse YAML in policy pack file "${path}": ${message}`);
|
|
193
|
+
}
|
|
194
|
+
if (parsed === null || parsed === undefined || typeof parsed !== 'object') {
|
|
195
|
+
throw new Error(`Policy pack file "${path}" does not contain a valid YAML object`);
|
|
196
|
+
}
|
|
197
|
+
const pack = parsed;
|
|
198
|
+
const validation = PolicyEngine.validate(pack);
|
|
199
|
+
if (!validation.valid) {
|
|
200
|
+
throw new Error(`Invalid policy pack "${path}": ${validation.errors.join('; ')}`);
|
|
201
|
+
}
|
|
202
|
+
// Sort rules by priority (lower number = higher precedence).
|
|
203
|
+
// Rules without an explicit priority are placed at the end.
|
|
204
|
+
pack.rules.sort((a, b) => {
|
|
205
|
+
const pa = a.priority ?? Number.MAX_SAFE_INTEGER;
|
|
206
|
+
const pb = b.priority ?? Number.MAX_SAFE_INTEGER;
|
|
207
|
+
return pa - pb;
|
|
208
|
+
});
|
|
209
|
+
return pack;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Reload the policy pack from disk. Useful for hot-reload scenarios
|
|
213
|
+
* where the YAML file is updated without restarting the process.
|
|
214
|
+
*/
|
|
215
|
+
reload() {
|
|
216
|
+
this.regexCache.clear();
|
|
217
|
+
this.pack = this.loadPack(this.packPath);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Check if a regex pattern is safe from catastrophic backtracking (ReDoS).
|
|
221
|
+
* Blocks nested quantifiers (e.g., `(a+)+`, `(a*)*`, `(a|b?)+`) which are
|
|
222
|
+
* the most common source of exponential-time matches.
|
|
223
|
+
*/
|
|
224
|
+
static isSafeRegex(pattern) {
|
|
225
|
+
if (pattern.length > PolicyEngine.MAX_REGEX_PATTERN_LENGTH)
|
|
226
|
+
return false;
|
|
227
|
+
// Detect nested quantifiers: a quantifier (+, *, {n}) immediately after a group
|
|
228
|
+
// that itself contains a quantifier — the classic ReDoS pattern
|
|
229
|
+
if (/([+*}])\s*\)\s*[+*{]/.test(pattern))
|
|
230
|
+
return false;
|
|
231
|
+
// Detect alternation inside repeated group: (a|a)+ style
|
|
232
|
+
if (/\([^)]*\|[^)]*\)\s*[+*{]/.test(pattern) && /\([^)]*\|[^)]*\)\s*[+*]\s*[+*{]/.test(pattern))
|
|
233
|
+
return false;
|
|
234
|
+
return true;
|
|
235
|
+
}
|
|
236
|
+
getCachedRegex(pattern) {
|
|
237
|
+
let re = this.regexCache.get(pattern);
|
|
238
|
+
if (re) {
|
|
239
|
+
// Move to end (most recently used) for LRU ordering
|
|
240
|
+
this.regexCache.delete(pattern);
|
|
241
|
+
this.regexCache.set(pattern, re);
|
|
242
|
+
return re;
|
|
243
|
+
}
|
|
244
|
+
// ReDoS protection: block patterns with nested quantifiers or excessive length
|
|
245
|
+
if (!PolicyEngine.isSafeRegex(pattern)) {
|
|
246
|
+
console.warn(`PolicyEngine: rejecting potentially unsafe regex pattern (ReDoS risk): "${pattern.slice(0, 100)}..."`);
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
try {
|
|
250
|
+
re = new RegExp(pattern);
|
|
251
|
+
}
|
|
252
|
+
catch (err) {
|
|
253
|
+
console.warn(`PolicyEngine: invalid regex pattern "${pattern}": ${err instanceof Error ? err.message : String(err)}`);
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
// Evict oldest entry if at capacity
|
|
257
|
+
if (this.regexCache.size >= PolicyEngine.MAX_REGEX_CACHE_SIZE) {
|
|
258
|
+
const oldest = this.regexCache.keys().next().value;
|
|
259
|
+
if (oldest !== undefined) {
|
|
260
|
+
this.regexCache.delete(oldest);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
this.regexCache.set(pattern, re);
|
|
264
|
+
return re;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Return the currently loaded policy pack.
|
|
268
|
+
*/
|
|
269
|
+
getPack() {
|
|
270
|
+
return this.pack;
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Validate a PolicyPack object without loading it from disk.
|
|
274
|
+
* Returns a list of validation errors (empty when the pack is valid).
|
|
275
|
+
*/
|
|
276
|
+
static validate(pack) {
|
|
277
|
+
const errors = [];
|
|
278
|
+
if (!pack.name || typeof pack.name !== 'string') {
|
|
279
|
+
errors.push('Policy pack must have a non-empty "name" string');
|
|
280
|
+
}
|
|
281
|
+
if (!pack.version || typeof pack.version !== 'string') {
|
|
282
|
+
errors.push('Policy pack must have a non-empty "version" string');
|
|
283
|
+
}
|
|
284
|
+
if (!Array.isArray(pack.rules)) {
|
|
285
|
+
errors.push('Policy pack must have a "rules" array');
|
|
286
|
+
return { valid: false, errors };
|
|
287
|
+
}
|
|
288
|
+
for (let i = 0; i < pack.rules.length; i++) {
|
|
289
|
+
const rule = pack.rules[i];
|
|
290
|
+
const prefix = `Rule[${i}]`;
|
|
291
|
+
if (!rule.name || typeof rule.name !== 'string') {
|
|
292
|
+
errors.push(`${prefix}: must have a non-empty "name" string`);
|
|
293
|
+
}
|
|
294
|
+
if (!rule.effect || typeof rule.effect !== 'string') {
|
|
295
|
+
errors.push(`${prefix} ("${rule.name || 'unnamed'}"): must have an "effect" string`);
|
|
296
|
+
}
|
|
297
|
+
else if (!VALID_EFFECTS.includes(rule.effect)) {
|
|
298
|
+
errors.push(`${prefix} ("${rule.name}"): invalid effect "${rule.effect}". ` +
|
|
299
|
+
`Must be one of: ${VALID_EFFECTS.join(', ')}`);
|
|
300
|
+
}
|
|
301
|
+
if (!rule.conditions || typeof rule.conditions !== 'object') {
|
|
302
|
+
errors.push(`${prefix} ("${rule.name || 'unnamed'}"): must have a "conditions" object`);
|
|
303
|
+
}
|
|
304
|
+
if (rule.priority !== undefined && (typeof rule.priority !== 'number' || !isFinite(rule.priority))) {
|
|
305
|
+
errors.push(`${prefix} ("${rule.name || 'unnamed'}"): "priority" must be a finite number`);
|
|
306
|
+
}
|
|
307
|
+
// Validate regex patterns are compilable and safe from ReDoS
|
|
308
|
+
if (rule.conditions) {
|
|
309
|
+
if (rule.conditions.tool_match) {
|
|
310
|
+
if (!PolicyEngine.isSafeRegex(rule.conditions.tool_match)) {
|
|
311
|
+
errors.push(`${prefix} ("${rule.name || 'unnamed'}"): "conditions.tool_match" is potentially unsafe (ReDoS risk or too long): "${rule.conditions.tool_match.slice(0, 100)}"`);
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
try {
|
|
315
|
+
new RegExp(rule.conditions.tool_match);
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
errors.push(`${prefix} ("${rule.name || 'unnamed'}"): "conditions.tool_match" is not a valid regex: "${rule.conditions.tool_match}"`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
if (rule.conditions.label_match) {
|
|
323
|
+
if (!PolicyEngine.isSafeRegex(rule.conditions.label_match)) {
|
|
324
|
+
errors.push(`${prefix} ("${rule.name || 'unnamed'}"): "conditions.label_match" is potentially unsafe (ReDoS risk or too long): "${rule.conditions.label_match.slice(0, 100)}"`);
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
try {
|
|
328
|
+
new RegExp(rule.conditions.label_match);
|
|
329
|
+
}
|
|
330
|
+
catch {
|
|
331
|
+
errors.push(`${prefix} ("${rule.name || 'unnamed'}"): "conditions.label_match" is not a valid regex: "${rule.conditions.label_match}"`);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return { valid: errors.length === 0, errors };
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Evaluate a ToolCall against the loaded policy pack.
|
|
341
|
+
*
|
|
342
|
+
* Processing order:
|
|
343
|
+
* 1. Check the pack-level domain_blocklist (instant DENY).
|
|
344
|
+
* 2. If a pack-level domain_allowlist exists and the call targets a URL,
|
|
345
|
+
* the domain must appear in the allowlist or the call is denied.
|
|
346
|
+
* 3. Iterate rules in priority order. Return the first matching rule's result.
|
|
347
|
+
* 4. If no rule matches, apply the defaultEffect.
|
|
348
|
+
*/
|
|
349
|
+
evaluate(toolCall, dlpContext) {
|
|
350
|
+
const domain = this.extractDomainFromToolCall(toolCall);
|
|
351
|
+
// --- Pack-level domain blocklist ---
|
|
352
|
+
if (domain && this.pack.domain_blocklist && this.pack.domain_blocklist.length > 0) {
|
|
353
|
+
if (this.isDomainInList(domain, this.pack.domain_blocklist)) {
|
|
354
|
+
return {
|
|
355
|
+
decision: 'deny',
|
|
356
|
+
rule_id: '__pack_domain_blocklist',
|
|
357
|
+
rule_name: '__pack_domain_blocklist',
|
|
358
|
+
reasons: [`Domain "${domain}" is in the pack-level domain blocklist`],
|
|
359
|
+
transformations: [],
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
// --- SSRF protection: block private/internal targets ---
|
|
364
|
+
// Active when a domain_allowlist is configured (non-empty), indicating the
|
|
365
|
+
// policy cares about restricting target domains. In that mode, private IPs
|
|
366
|
+
// are denied unless explicitly present in the allowlist or in a rule's
|
|
367
|
+
// domains list.
|
|
368
|
+
if (domain && isPrivateTarget(domain) && this.pack.domain_allowlist && this.pack.domain_allowlist.length > 0) {
|
|
369
|
+
// Check if the pack-level allowlist explicitly includes the private domain
|
|
370
|
+
const allowlistedPrivate = this.isDomainInList(domain, this.pack.domain_allowlist);
|
|
371
|
+
// Check if any rule explicitly allows private access via domains list
|
|
372
|
+
const explicitlyAllowed = this.pack.rules.some(rule => rule.conditions.domains && rule.conditions.domains.length > 0 &&
|
|
373
|
+
this.isDomainInList(domain, rule.conditions.domains));
|
|
374
|
+
if (!explicitlyAllowed && !allowlistedPrivate) {
|
|
375
|
+
return {
|
|
376
|
+
decision: 'deny',
|
|
377
|
+
rule_id: '__ssrf_protection',
|
|
378
|
+
rule_name: '__ssrf_protection',
|
|
379
|
+
reasons: [`Domain "${domain}" resolves to a private/internal address (SSRF protection)`],
|
|
380
|
+
transformations: [],
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
// --- Pack-level domain allowlist ---
|
|
385
|
+
if (domain && this.pack.domain_allowlist && this.pack.domain_allowlist.length > 0) {
|
|
386
|
+
if (!this.isDomainInList(domain, this.pack.domain_allowlist)) {
|
|
387
|
+
return {
|
|
388
|
+
decision: 'deny',
|
|
389
|
+
rule_id: '__pack_domain_allowlist',
|
|
390
|
+
rule_name: '__pack_domain_allowlist',
|
|
391
|
+
reasons: [`Domain "${domain}" is not in the pack-level domain allowlist`],
|
|
392
|
+
transformations: [],
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
// --- Rule evaluation (priority order, already sorted) ---
|
|
397
|
+
for (const rule of this.pack.rules) {
|
|
398
|
+
if (this.matchesConditions(rule.conditions, toolCall, dlpContext)) {
|
|
399
|
+
return this.buildResult(rule);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
// --- No rule matched: apply default effect ---
|
|
403
|
+
return {
|
|
404
|
+
decision: this.effectToDecision(this.pack.default_effect ?? this.defaultEffect),
|
|
405
|
+
rule_id: '__default',
|
|
406
|
+
rule_name: '__default',
|
|
407
|
+
reasons: ['No matching rule found; default effect applied'],
|
|
408
|
+
transformations: [],
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Evaluate a ToolCall with DLP context (phase-2 evaluation).
|
|
413
|
+
* Only called when DLP detections were found, allowing policy rules
|
|
414
|
+
* with dlp_* conditions to match.
|
|
415
|
+
*/
|
|
416
|
+
evaluateWithDLP(toolCall, dlpContext) {
|
|
417
|
+
// Only consider rules that have DLP conditions
|
|
418
|
+
for (const rule of this.pack.rules) {
|
|
419
|
+
const hasDLPConditions = rule.conditions.dlp_severity
|
|
420
|
+
|| rule.conditions.dlp_detected !== undefined
|
|
421
|
+
|| rule.conditions.dlp_pattern_names;
|
|
422
|
+
if (!hasDLPConditions)
|
|
423
|
+
continue;
|
|
424
|
+
if (this.matchesConditions(rule.conditions, toolCall, dlpContext)) {
|
|
425
|
+
return this.buildResult(rule);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
return null; // No DLP-conditioned rules matched
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Check whether a single rule's conditions match the given ToolCall.
|
|
432
|
+
* All specified conditions use AND logic: every present condition must
|
|
433
|
+
* match for the rule to apply. Conditions that are absent or empty are
|
|
434
|
+
* treated as "match everything".
|
|
435
|
+
*/
|
|
436
|
+
matchesConditions(conditions, toolCall, dlpContext) {
|
|
437
|
+
// --- tools ---
|
|
438
|
+
if (conditions.tools && conditions.tools.length > 0) {
|
|
439
|
+
if (!conditions.tools.includes(toolCall.tool.name)) {
|
|
440
|
+
return false;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
// --- tool_match (regex, cached) ---
|
|
444
|
+
if (conditions.tool_match) {
|
|
445
|
+
const re = this.getCachedRegex(conditions.tool_match);
|
|
446
|
+
if (!re || !re.test(toolCall.tool.name)) {
|
|
447
|
+
return false;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
// --- capabilities ---
|
|
451
|
+
if (conditions.capabilities && conditions.capabilities.length > 0) {
|
|
452
|
+
if (!conditions.capabilities.includes(toolCall.tool.capability)) {
|
|
453
|
+
return false;
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
// --- actors ---
|
|
457
|
+
if (conditions.actors && conditions.actors.length > 0) {
|
|
458
|
+
if (!conditions.actors.includes(toolCall.actor.id)) {
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
// --- actor_types ---
|
|
463
|
+
if (conditions.actor_types && conditions.actor_types.length > 0) {
|
|
464
|
+
if (!conditions.actor_types.includes(toolCall.actor.type)) {
|
|
465
|
+
return false;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
// --- domains (allow list at rule level) ---
|
|
469
|
+
if (conditions.domains && conditions.domains.length > 0) {
|
|
470
|
+
const domain = this.extractDomainFromToolCall(toolCall);
|
|
471
|
+
if (!domain) {
|
|
472
|
+
// Rule requires a specific domain but the call has no URL -- no match.
|
|
473
|
+
return false;
|
|
474
|
+
}
|
|
475
|
+
if (!this.isDomainInList(domain, conditions.domains)) {
|
|
476
|
+
return false;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
// --- domain_blocklist (rule level) ---
|
|
480
|
+
if (conditions.domain_blocklist && conditions.domain_blocklist.length > 0) {
|
|
481
|
+
const domain = this.extractDomainFromToolCall(toolCall);
|
|
482
|
+
if (domain && this.isDomainInList(domain, conditions.domain_blocklist)) {
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
// --- methods ---
|
|
487
|
+
if (conditions.methods && conditions.methods.length > 0) {
|
|
488
|
+
const method = toolCall.args.method;
|
|
489
|
+
if (!method) {
|
|
490
|
+
return false;
|
|
491
|
+
}
|
|
492
|
+
// Case-insensitive comparison for HTTP methods.
|
|
493
|
+
const upperMethod = method.toUpperCase();
|
|
494
|
+
const upperMethods = conditions.methods.map((m) => m.toUpperCase());
|
|
495
|
+
if (!upperMethods.includes(upperMethod)) {
|
|
496
|
+
return false;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
// --- labels ---
|
|
500
|
+
if (conditions.labels && conditions.labels.length > 0) {
|
|
501
|
+
const callLabels = toolCall.context?.labels;
|
|
502
|
+
if (!callLabels || callLabels.length === 0) {
|
|
503
|
+
return false;
|
|
504
|
+
}
|
|
505
|
+
// At least one label from the condition must appear in the call's labels.
|
|
506
|
+
const hasMatch = conditions.labels.some((label) => callLabels.includes(label));
|
|
507
|
+
if (!hasMatch) {
|
|
508
|
+
return false;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
// --- label_match (regex, cached) ---
|
|
512
|
+
if (conditions.label_match) {
|
|
513
|
+
const callLabels = toolCall.context?.labels;
|
|
514
|
+
if (!callLabels || callLabels.length === 0) {
|
|
515
|
+
return false;
|
|
516
|
+
}
|
|
517
|
+
const re = this.getCachedRegex(conditions.label_match);
|
|
518
|
+
if (!re) {
|
|
519
|
+
return false;
|
|
520
|
+
}
|
|
521
|
+
const hasMatch = callLabels.some((label) => re.test(label));
|
|
522
|
+
if (!hasMatch) {
|
|
523
|
+
return false;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
// --- platforms ---
|
|
527
|
+
if (conditions.platforms && conditions.platforms.length > 0) {
|
|
528
|
+
if (!conditions.platforms.includes(toolCall.source.platform)) {
|
|
529
|
+
return false;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
// --- workspace_ids ---
|
|
533
|
+
if (conditions.workspace_ids && conditions.workspace_ids.length > 0) {
|
|
534
|
+
if (!conditions.workspace_ids.includes(toolCall.workspace_id)) {
|
|
535
|
+
return false;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
// --- DLP conditions (only evaluated when dlpContext is provided) ---
|
|
539
|
+
if (conditions.dlp_detected !== undefined) {
|
|
540
|
+
if (!dlpContext)
|
|
541
|
+
return false; // DLP conditions require DLP context
|
|
542
|
+
const hasDetections = dlpContext.detected.length > 0;
|
|
543
|
+
if (conditions.dlp_detected !== hasDetections) {
|
|
544
|
+
return false;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
if (conditions.dlp_severity && conditions.dlp_severity.length > 0) {
|
|
548
|
+
if (!dlpContext)
|
|
549
|
+
return false;
|
|
550
|
+
if (!conditions.dlp_severity.includes(dlpContext.severity)) {
|
|
551
|
+
return false;
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
if (conditions.dlp_pattern_names && conditions.dlp_pattern_names.length > 0) {
|
|
555
|
+
if (!dlpContext)
|
|
556
|
+
return false;
|
|
557
|
+
const hasMatch = conditions.dlp_pattern_names.some(name => dlpContext.pattern_names.includes(name));
|
|
558
|
+
if (!hasMatch) {
|
|
559
|
+
return false;
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
// All specified conditions matched (or were absent).
|
|
563
|
+
return true;
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Extract the hostname from a URL string.
|
|
567
|
+
* Returns null if the string is not a valid URL.
|
|
568
|
+
*/
|
|
569
|
+
extractDomain(url) {
|
|
570
|
+
try {
|
|
571
|
+
const parsed = new URL(url);
|
|
572
|
+
return parsed.hostname.toLowerCase();
|
|
573
|
+
}
|
|
574
|
+
catch {
|
|
575
|
+
return null;
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
/**
|
|
579
|
+
* Convenience helper: pull the URL out of a ToolCall's args and extract its domain.
|
|
580
|
+
*/
|
|
581
|
+
extractDomainFromToolCall(toolCall) {
|
|
582
|
+
const url = toolCall.args.url;
|
|
583
|
+
if (!url || typeof url !== 'string') {
|
|
584
|
+
return null;
|
|
585
|
+
}
|
|
586
|
+
return this.extractDomain(url);
|
|
587
|
+
}
|
|
588
|
+
/**
|
|
589
|
+
* Check whether a domain appears in a domain list.
|
|
590
|
+
* Supports exact matches and wildcard subdomains (e.g., "*.example.com"
|
|
591
|
+
* matches "api.example.com" and "sub.api.example.com").
|
|
592
|
+
*/
|
|
593
|
+
isDomainInList(domain, list) {
|
|
594
|
+
const lowerDomain = domain.toLowerCase();
|
|
595
|
+
for (const entry of list) {
|
|
596
|
+
const lowerEntry = entry.toLowerCase();
|
|
597
|
+
if (lowerEntry === lowerDomain) {
|
|
598
|
+
return true;
|
|
599
|
+
}
|
|
600
|
+
// Wildcard matching: *.example.com matches any subdomain of example.com.
|
|
601
|
+
if (lowerEntry.startsWith('*.')) {
|
|
602
|
+
const suffix = lowerEntry.slice(1); // ".example.com"
|
|
603
|
+
if (lowerDomain.endsWith(suffix) || lowerDomain === lowerEntry.slice(2)) {
|
|
604
|
+
return true;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
return false;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Map a PolicyEffect enum value to the lowercase PolicyDecision string.
|
|
612
|
+
*/
|
|
613
|
+
effectToDecision(effect) {
|
|
614
|
+
return effect.toLowerCase();
|
|
615
|
+
}
|
|
616
|
+
/**
|
|
617
|
+
* Build a PolicyEvalResult from a matched rule.
|
|
618
|
+
*/
|
|
619
|
+
buildResult(rule) {
|
|
620
|
+
const reasons = [];
|
|
621
|
+
if (rule.description) {
|
|
622
|
+
reasons.push(rule.description);
|
|
623
|
+
}
|
|
624
|
+
reasons.push(`Matched rule "${rule.name}"`);
|
|
625
|
+
const result = {
|
|
626
|
+
decision: this.effectToDecision(rule.effect),
|
|
627
|
+
rule_id: rule.name,
|
|
628
|
+
rule_name: rule.name,
|
|
629
|
+
reasons,
|
|
630
|
+
transformations: rule.transformations,
|
|
631
|
+
};
|
|
632
|
+
if (rule.effect === 'REQUIRE_APPROVAL' && rule.approval) {
|
|
633
|
+
result.approval = rule.approval;
|
|
634
|
+
}
|
|
635
|
+
return result;
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
exports.PolicyEngine = PolicyEngine;
|
|
639
|
+
/**
|
|
640
|
+
* Get a cached compiled RegExp for a pattern string.
|
|
641
|
+
* Avoids re-compiling the same pattern on every evaluate() call.
|
|
642
|
+
*/
|
|
643
|
+
PolicyEngine.MAX_REGEX_CACHE_SIZE = 1000;
|
|
644
|
+
/** Maximum allowed regex pattern length */
|
|
645
|
+
PolicyEngine.MAX_REGEX_PATTERN_LENGTH = 500;
|
|
646
|
+
//# sourceMappingURL=engine.js.map
|