palaryn 0.1.0 → 0.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +243 -588
- package/dist/sdk/typescript/src/client.js +2 -2
- package/dist/sdk/typescript/src/client.js.map +1 -1
- package/dist/src/anomaly/detector.d.ts +7 -4
- package/dist/src/anomaly/detector.d.ts.map +1 -1
- package/dist/src/anomaly/detector.js +22 -12
- package/dist/src/anomaly/detector.js.map +1 -1
- package/dist/src/audit/logger.d.ts +10 -0
- package/dist/src/audit/logger.d.ts.map +1 -1
- package/dist/src/audit/logger.js +52 -38
- package/dist/src/audit/logger.js.map +1 -1
- package/dist/src/auth/routes.d.ts.map +1 -1
- package/dist/src/auth/routes.js +35 -0
- package/dist/src/auth/routes.js.map +1 -1
- package/dist/src/budget/manager.d.ts +5 -0
- package/dist/src/budget/manager.d.ts.map +1 -1
- package/dist/src/budget/manager.js +32 -0
- package/dist/src/budget/manager.js.map +1 -1
- package/dist/src/budget/model-pricing.d.ts +20 -0
- package/dist/src/budget/model-pricing.d.ts.map +1 -0
- package/dist/src/budget/model-pricing.js +107 -0
- package/dist/src/budget/model-pricing.js.map +1 -0
- package/dist/src/budget/usage-extractor.d.ts +3 -1
- package/dist/src/budget/usage-extractor.d.ts.map +1 -1
- package/dist/src/budget/usage-extractor.js +47 -3
- package/dist/src/budget/usage-extractor.js.map +1 -1
- package/dist/src/config/defaults.d.ts.map +1 -1
- package/dist/src/config/defaults.js +65 -13
- package/dist/src/config/defaults.js.map +1 -1
- package/dist/src/dlp/tool-patterns.d.ts +7 -0
- package/dist/src/dlp/tool-patterns.d.ts.map +1 -0
- package/dist/src/dlp/tool-patterns.js +34 -0
- package/dist/src/dlp/tool-patterns.js.map +1 -0
- package/dist/src/executor/filesystem-executor.d.ts +28 -0
- package/dist/src/executor/filesystem-executor.d.ts.map +1 -0
- package/dist/src/executor/filesystem-executor.js +192 -0
- package/dist/src/executor/filesystem-executor.js.map +1 -0
- package/dist/src/executor/http-executor.d.ts.map +1 -1
- package/dist/src/executor/http-executor.js +22 -2
- package/dist/src/executor/http-executor.js.map +1 -1
- package/dist/src/executor/index.d.ts +4 -0
- package/dist/src/executor/index.d.ts.map +1 -1
- package/dist/src/executor/index.js +9 -1
- package/dist/src/executor/index.js.map +1 -1
- package/dist/src/executor/shell-executor.d.ts +22 -0
- package/dist/src/executor/shell-executor.d.ts.map +1 -0
- package/dist/src/executor/shell-executor.js +119 -0
- package/dist/src/executor/shell-executor.js.map +1 -0
- package/dist/src/executor/sql-executor.d.ts +29 -0
- package/dist/src/executor/sql-executor.d.ts.map +1 -0
- package/dist/src/executor/sql-executor.js +114 -0
- package/dist/src/executor/sql-executor.js.map +1 -0
- package/dist/src/executor/websocket-executor.d.ts +26 -0
- package/dist/src/executor/websocket-executor.d.ts.map +1 -0
- package/dist/src/executor/websocket-executor.js +205 -0
- package/dist/src/executor/websocket-executor.js.map +1 -0
- package/dist/src/interceptor/index.d.ts +2 -0
- package/dist/src/interceptor/index.d.ts.map +1 -0
- package/dist/src/interceptor/index.js +6 -0
- package/dist/src/interceptor/index.js.map +1 -0
- package/dist/src/interceptor/provider-interceptor.d.ts +36 -0
- package/dist/src/interceptor/provider-interceptor.d.ts.map +1 -0
- package/dist/src/interceptor/provider-interceptor.js +302 -0
- package/dist/src/interceptor/provider-interceptor.js.map +1 -0
- package/dist/src/mcp/auth-verifier.d.ts.map +1 -1
- package/dist/src/mcp/auth-verifier.js +3 -2
- package/dist/src/mcp/auth-verifier.js.map +1 -1
- package/dist/src/mcp/bridge.d.ts +14 -10
- package/dist/src/mcp/bridge.d.ts.map +1 -1
- package/dist/src/mcp/bridge.js +51 -227
- package/dist/src/mcp/bridge.js.map +1 -1
- package/dist/src/mcp/http-transport.d.ts +2 -0
- package/dist/src/mcp/http-transport.d.ts.map +1 -1
- package/dist/src/mcp/http-transport.js +117 -66
- package/dist/src/mcp/http-transport.js.map +1 -1
- package/dist/src/mcp/internal-auth.d.ts +13 -0
- package/dist/src/mcp/internal-auth.d.ts.map +1 -0
- package/dist/src/mcp/internal-auth.js +12 -0
- package/dist/src/mcp/internal-auth.js.map +1 -0
- package/dist/src/mcp/tool-definitions.d.ts +41 -0
- package/dist/src/mcp/tool-definitions.d.ts.map +1 -0
- package/dist/src/mcp/tool-definitions.js +491 -0
- package/dist/src/mcp/tool-definitions.js.map +1 -0
- package/dist/src/middleware/auth.js.map +1 -1
- package/dist/src/middleware/session.js.map +1 -1
- package/dist/src/middleware/validate.d.ts +8 -0
- package/dist/src/middleware/validate.d.ts.map +1 -1
- package/dist/src/middleware/validate.js +45 -0
- package/dist/src/middleware/validate.js.map +1 -1
- package/dist/src/policy/engine.d.ts +4 -0
- package/dist/src/policy/engine.d.ts.map +1 -1
- package/dist/src/policy/engine.js +117 -0
- package/dist/src/policy/engine.js.map +1 -1
- package/dist/src/saas/routes.d.ts.map +1 -1
- package/dist/src/saas/routes.js +355 -22
- package/dist/src/saas/routes.js.map +1 -1
- package/dist/src/server/app.d.ts.map +1 -1
- package/dist/src/server/app.js +24 -3
- package/dist/src/server/app.js.map +1 -1
- package/dist/src/server/gateway.d.ts.map +1 -1
- package/dist/src/server/gateway.js +17 -0
- package/dist/src/server/gateway.js.map +1 -1
- package/dist/src/server/index.d.ts.map +1 -1
- package/dist/src/server/index.js +18 -0
- package/dist/src/server/index.js.map +1 -1
- package/dist/src/storage/interfaces.d.ts +14 -3
- package/dist/src/storage/interfaces.d.ts.map +1 -1
- package/dist/src/storage/memory.d.ts +2 -0
- package/dist/src/storage/memory.d.ts.map +1 -1
- package/dist/src/storage/memory.js +6 -0
- package/dist/src/storage/memory.js.map +1 -1
- package/dist/src/storage/postgres.d.ts +5 -0
- package/dist/src/storage/postgres.d.ts.map +1 -1
- package/dist/src/storage/postgres.js +16 -0
- package/dist/src/storage/postgres.js.map +1 -1
- package/dist/src/storage/redis.d.ts +10 -0
- package/dist/src/storage/redis.d.ts.map +1 -1
- package/dist/src/storage/redis.js +65 -0
- package/dist/src/storage/redis.js.map +1 -1
- package/dist/src/types/budget.d.ts +4 -0
- package/dist/src/types/budget.d.ts.map +1 -1
- package/dist/src/types/config.d.ts +58 -0
- package/dist/src/types/config.d.ts.map +1 -1
- package/dist/src/types/events.d.ts +1 -0
- package/dist/src/types/events.d.ts.map +1 -1
- package/dist/src/types/policy.d.ts +11 -1
- package/dist/src/types/policy.d.ts.map +1 -1
- package/dist/src/types/tool-result.d.ts +11 -0
- package/dist/src/types/tool-result.d.ts.map +1 -1
- package/dist/tests/unit/app-routes.test.d.ts +2 -0
- package/dist/tests/unit/app-routes.test.d.ts.map +1 -0
- package/dist/tests/unit/app-routes.test.js +715 -0
- package/dist/tests/unit/app-routes.test.js.map +1 -0
- package/dist/tests/unit/audit-logger.test.js +105 -0
- package/dist/tests/unit/audit-logger.test.js.map +1 -1
- package/dist/tests/unit/auth-providers.test.d.ts +2 -0
- package/dist/tests/unit/auth-providers.test.d.ts.map +1 -0
- package/dist/tests/unit/auth-providers.test.js +279 -0
- package/dist/tests/unit/auth-providers.test.js.map +1 -0
- package/dist/tests/unit/auth-routes-extended.test.d.ts +2 -0
- package/dist/tests/unit/auth-routes-extended.test.d.ts.map +1 -0
- package/dist/tests/unit/auth-routes-extended.test.js +993 -0
- package/dist/tests/unit/auth-routes-extended.test.js.map +1 -0
- package/dist/tests/unit/auth-verifier.test.d.ts +2 -0
- package/dist/tests/unit/auth-verifier.test.d.ts.map +1 -0
- package/dist/tests/unit/auth-verifier.test.js +505 -0
- package/dist/tests/unit/auth-verifier.test.js.map +1 -0
- package/dist/tests/unit/billing-routes.test.d.ts +2 -0
- package/dist/tests/unit/billing-routes.test.d.ts.map +1 -0
- package/dist/tests/unit/billing-routes.test.js +432 -0
- package/dist/tests/unit/billing-routes.test.js.map +1 -0
- package/dist/tests/unit/config-defaults.test.d.ts +2 -0
- package/dist/tests/unit/config-defaults.test.d.ts.map +1 -0
- package/dist/tests/unit/config-defaults.test.js +119 -0
- package/dist/tests/unit/config-defaults.test.js.map +1 -0
- package/dist/tests/unit/defaults.test.js +0 -10
- package/dist/tests/unit/defaults.test.js.map +1 -1
- package/dist/tests/unit/filesystem-executor.test.d.ts +2 -0
- package/dist/tests/unit/filesystem-executor.test.d.ts.map +1 -0
- package/dist/tests/unit/filesystem-executor.test.js +280 -0
- package/dist/tests/unit/filesystem-executor.test.js.map +1 -0
- package/dist/tests/unit/gateway-branches.test.d.ts +2 -0
- package/dist/tests/unit/gateway-branches.test.d.ts.map +1 -0
- package/dist/tests/unit/gateway-branches.test.js +1039 -0
- package/dist/tests/unit/gateway-branches.test.js.map +1 -0
- package/dist/tests/unit/http-executor-branches.test.d.ts +2 -0
- package/dist/tests/unit/http-executor-branches.test.d.ts.map +1 -0
- package/dist/tests/unit/http-executor-branches.test.js +495 -0
- package/dist/tests/unit/http-executor-branches.test.js.map +1 -0
- package/dist/tests/unit/logger.test.d.ts +2 -0
- package/dist/tests/unit/logger.test.d.ts.map +1 -0
- package/dist/tests/unit/logger.test.js +97 -0
- package/dist/tests/unit/logger.test.js.map +1 -0
- package/dist/tests/unit/mcp-internal-auth.test.d.ts +2 -0
- package/dist/tests/unit/mcp-internal-auth.test.d.ts.map +1 -0
- package/dist/tests/unit/mcp-internal-auth.test.js +445 -0
- package/dist/tests/unit/mcp-internal-auth.test.js.map +1 -0
- package/dist/tests/unit/metrics.test.js +102 -0
- package/dist/tests/unit/metrics.test.js.map +1 -1
- package/dist/tests/unit/model-pricing.test.d.ts +2 -0
- package/dist/tests/unit/model-pricing.test.d.ts.map +1 -0
- package/dist/tests/unit/model-pricing.test.js +87 -0
- package/dist/tests/unit/model-pricing.test.js.map +1 -0
- package/dist/tests/unit/oauth-stores.test.d.ts +2 -0
- package/dist/tests/unit/oauth-stores.test.d.ts.map +1 -0
- package/dist/tests/unit/oauth-stores.test.js +260 -0
- package/dist/tests/unit/oauth-stores.test.js.map +1 -0
- package/dist/tests/unit/policy-engine.test.js +466 -0
- package/dist/tests/unit/policy-engine.test.js.map +1 -1
- package/dist/tests/unit/provider-interceptor.test.d.ts +2 -0
- package/dist/tests/unit/provider-interceptor.test.d.ts.map +1 -0
- package/dist/tests/unit/provider-interceptor.test.js +472 -0
- package/dist/tests/unit/provider-interceptor.test.js.map +1 -0
- package/dist/tests/unit/saas-routes-branches.test.d.ts +2 -0
- package/dist/tests/unit/saas-routes-branches.test.d.ts.map +1 -0
- package/dist/tests/unit/saas-routes-branches.test.js +2165 -0
- package/dist/tests/unit/saas-routes-branches.test.js.map +1 -0
- package/dist/tests/unit/saas-routes-crud.test.d.ts +2 -0
- package/dist/tests/unit/saas-routes-crud.test.d.ts.map +1 -0
- package/dist/tests/unit/saas-routes-crud.test.js +332 -0
- package/dist/tests/unit/saas-routes-crud.test.js.map +1 -0
- package/dist/tests/unit/saas-routes-data.test.d.ts +2 -0
- package/dist/tests/unit/saas-routes-data.test.d.ts.map +1 -0
- package/dist/tests/unit/saas-routes-data.test.js +405 -0
- package/dist/tests/unit/saas-routes-data.test.js.map +1 -0
- package/dist/tests/unit/saas-routes.test.js +3 -3
- package/dist/tests/unit/saas-routes.test.js.map +1 -1
- package/dist/tests/unit/shell-executor.test.d.ts +2 -0
- package/dist/tests/unit/shell-executor.test.d.ts.map +1 -0
- package/dist/tests/unit/shell-executor.test.js +145 -0
- package/dist/tests/unit/shell-executor.test.js.map +1 -0
- package/dist/tests/unit/sql-executor.test.d.ts +2 -0
- package/dist/tests/unit/sql-executor.test.d.ts.map +1 -0
- package/dist/tests/unit/sql-executor.test.js +177 -0
- package/dist/tests/unit/sql-executor.test.js.map +1 -0
- package/dist/tests/unit/stream-proxy.test.d.ts +2 -0
- package/dist/tests/unit/stream-proxy.test.d.ts.map +1 -0
- package/dist/tests/unit/stream-proxy.test.js +147 -0
- package/dist/tests/unit/stream-proxy.test.js.map +1 -0
- package/dist/tests/unit/tool-definitions.test.d.ts +2 -0
- package/dist/tests/unit/tool-definitions.test.d.ts.map +1 -0
- package/dist/tests/unit/tool-definitions.test.js +184 -0
- package/dist/tests/unit/tool-definitions.test.js.map +1 -0
- package/dist/tests/unit/usage-extractor.test.js +140 -0
- package/dist/tests/unit/usage-extractor.test.js.map +1 -1
- package/dist/tests/unit/webhook-handler.test.d.ts +2 -0
- package/dist/tests/unit/webhook-handler.test.d.ts.map +1 -0
- package/dist/tests/unit/webhook-handler.test.js +453 -0
- package/dist/tests/unit/webhook-handler.test.js.map +1 -0
- package/dist/tests/unit/webhook-routes.test.d.ts +2 -0
- package/dist/tests/unit/webhook-routes.test.d.ts.map +1 -0
- package/dist/tests/unit/webhook-routes.test.js +69 -0
- package/dist/tests/unit/webhook-routes.test.js.map +1 -0
- package/dist/tests/unit/websocket-executor.test.d.ts +2 -0
- package/dist/tests/unit/websocket-executor.test.d.ts.map +1 -0
- package/dist/tests/unit/websocket-executor.test.js +121 -0
- package/dist/tests/unit/websocket-executor.test.js.map +1 -0
- package/package.json +8 -2
- package/policy-packs/demo_fail.yaml +41 -0
- package/policy-packs/full_tools.yaml +136 -0
- package/src/admin/index.ts +1 -0
- package/src/admin/routes.ts +509 -0
- package/src/admin/templates.ts +572 -0
- package/src/anomaly/detector.ts +730 -0
- package/src/anomaly/index.ts +1 -0
- package/src/approval/manager.ts +569 -0
- package/src/approval/webhook.ts +133 -0
- package/src/audit/logger.ts +490 -0
- package/src/auth/index.ts +5 -0
- package/src/auth/password.ts +21 -0
- package/src/auth/pkce.ts +22 -0
- package/src/auth/providers.ts +208 -0
- package/src/auth/routes.ts +561 -0
- package/src/auth/session.ts +84 -0
- package/src/billing/index.ts +6 -0
- package/src/billing/plan-enforcer.ts +135 -0
- package/src/billing/routes.ts +229 -0
- package/src/billing/stripe-client.ts +58 -0
- package/src/billing/webhook-handler.ts +182 -0
- package/src/billing/webhook-routes.ts +28 -0
- package/src/budget/manager.ts +679 -0
- package/src/budget/model-pricing.ts +119 -0
- package/src/budget/usage-extractor.ts +214 -0
- package/src/cli.ts +91 -0
- package/src/config/defaults.ts +261 -0
- package/src/config/validate.ts +88 -0
- package/src/dlp/composite-scanner.ts +213 -0
- package/src/dlp/index.ts +9 -0
- package/src/dlp/interfaces.ts +34 -0
- package/src/dlp/patterns.ts +30 -0
- package/src/dlp/prompt-injection-backend.ts +181 -0
- package/src/dlp/prompt-injection-patterns.ts +302 -0
- package/src/dlp/regex-backend.ts +181 -0
- package/src/dlp/scanner.ts +502 -0
- package/src/dlp/text-normalizer.ts +225 -0
- package/src/dlp/tool-patterns.ts +35 -0
- package/src/dlp/trufflehog-backend.ts +190 -0
- package/src/executor/filesystem-executor.ts +196 -0
- package/src/executor/http-executor.ts +349 -0
- package/src/executor/index.ts +9 -0
- package/src/executor/interfaces.ts +11 -0
- package/src/executor/noop-executor.ts +23 -0
- package/src/executor/registry.ts +64 -0
- package/src/executor/shell-executor.ts +148 -0
- package/src/executor/slack-executor.ts +176 -0
- package/src/executor/sql-executor.ts +146 -0
- package/src/executor/websocket-executor.ts +211 -0
- package/src/index.ts +24 -0
- package/src/interceptor/index.ts +1 -0
- package/src/interceptor/provider-interceptor.ts +315 -0
- package/src/mcp/auth-verifier.ts +152 -0
- package/src/mcp/bridge.ts +703 -0
- package/src/mcp/http-transport.ts +698 -0
- package/src/mcp/index.ts +9 -0
- package/src/mcp/internal-auth.ts +14 -0
- package/src/mcp/oauth-pages.ts +139 -0
- package/src/mcp/oauth-postgres-stores.ts +278 -0
- package/src/mcp/oauth-provider.ts +536 -0
- package/src/mcp/oauth-stores.ts +202 -0
- package/src/mcp/server.ts +55 -0
- package/src/mcp/tool-definitions.ts +562 -0
- package/src/metrics/collector.ts +357 -0
- package/src/metrics/index.ts +1 -0
- package/src/middleware/auth.ts +814 -0
- package/src/middleware/session.ts +85 -0
- package/src/middleware/validate.ts +130 -0
- package/src/policy/engine.ts +815 -0
- package/src/policy/index.ts +2 -0
- package/src/policy/opa-engine.ts +829 -0
- package/src/proxy/forward-proxy.ts +649 -0
- package/src/proxy/index.ts +1 -0
- package/src/ratelimit/limiter.ts +196 -0
- package/src/replay/engine.ts +142 -0
- package/src/replay/index.ts +1 -0
- package/src/saas/index.ts +1 -0
- package/src/saas/routes.ts +2178 -0
- package/src/server/app.ts +985 -0
- package/src/server/errors.ts +49 -0
- package/src/server/gateway.ts +1130 -0
- package/src/server/index.ts +307 -0
- package/src/server/logger.ts +255 -0
- package/src/server/stream-proxy.ts +202 -0
- package/src/storage/file-persistence.ts +315 -0
- package/src/storage/index.ts +4 -0
- package/src/storage/interfaces.ts +287 -0
- package/src/storage/memory.ts +686 -0
- package/src/storage/postgres.ts +1831 -0
- package/src/storage/redis.ts +835 -0
- package/src/tracing/index.ts +1 -0
- package/src/tracing/provider.ts +100 -0
- package/src/trust/calculator.ts +141 -0
- package/src/trust/index.ts +7 -0
- package/src/types/budget.ts +36 -0
- package/src/types/config.ts +278 -0
- package/src/types/events.ts +41 -0
- package/src/types/express.d.ts +14 -0
- package/src/types/index.ts +7 -0
- package/src/types/policy.ts +83 -0
- package/src/types/stripe-config.ts +11 -0
- package/src/types/subscription.ts +59 -0
- package/src/types/tool-call.ts +47 -0
- package/src/types/tool-result.ts +82 -0
- package/src/types/user.ts +125 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import { SessionStore, UserStore, WorkspaceMemberStore } from '../storage/interfaces';
|
|
3
|
+
import { OAuthConfig } from '../types/user';
|
|
4
|
+
import { SESSION_COOKIE_NAME } from '../auth/session';
|
|
5
|
+
import { resolvePermissions } from './auth';
|
|
6
|
+
import { AuthConfig } from '../types/config';
|
|
7
|
+
|
|
8
|
+
export interface SessionMiddlewareDeps {
|
|
9
|
+
oauthConfig: OAuthConfig;
|
|
10
|
+
authConfig: AuthConfig;
|
|
11
|
+
sessionStore: SessionStore;
|
|
12
|
+
userStore: UserStore;
|
|
13
|
+
workspaceMemberStore: WorkspaceMemberStore;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Session middleware that reads the session cookie and populates req.auth
|
|
18
|
+
* if a valid session is found. This runs before the existing auth middleware
|
|
19
|
+
* so that session-authenticated requests skip API key / JWT checks.
|
|
20
|
+
*/
|
|
21
|
+
export function createSessionMiddleware(deps: SessionMiddlewareDeps) {
|
|
22
|
+
const { oauthConfig, authConfig, sessionStore, userStore, workspaceMemberStore } = deps;
|
|
23
|
+
|
|
24
|
+
return (req: Request, res: Response, next: NextFunction): void => {
|
|
25
|
+
const sessionId = req.cookies?.[SESSION_COOKIE_NAME];
|
|
26
|
+
if (!sessionId) {
|
|
27
|
+
return next();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const session = sessionStore.getById(sessionId);
|
|
31
|
+
if (!session) {
|
|
32
|
+
// Expired or invalid session - clear cookie
|
|
33
|
+
res.clearCookie(SESSION_COOKIE_NAME, { path: '/' });
|
|
34
|
+
return next();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const user = userStore.getById(session.user_id);
|
|
38
|
+
if (!user || user.status !== 'active') {
|
|
39
|
+
sessionStore.delete(sessionId);
|
|
40
|
+
res.clearCookie(SESSION_COOKIE_NAME, { path: '/' });
|
|
41
|
+
return next();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Update last_active_at (fire-and-forget)
|
|
45
|
+
sessionStore.update(sessionId, { last_active_at: new Date().toISOString() });
|
|
46
|
+
|
|
47
|
+
// Determine workspace and roles
|
|
48
|
+
const workspaceId = session.workspace_id || 'ws_default';
|
|
49
|
+
const memberships = workspaceMemberStore.getByUser(user.id);
|
|
50
|
+
const membership = memberships.find(m => m.workspace_id === workspaceId);
|
|
51
|
+
|
|
52
|
+
// Map workspace role to RBAC roles
|
|
53
|
+
let roles: string[] = [];
|
|
54
|
+
if (membership) {
|
|
55
|
+
if (membership.role === 'owner' || membership.role === 'admin') {
|
|
56
|
+
roles = ['admin'];
|
|
57
|
+
} else if (membership.role === 'member') {
|
|
58
|
+
roles = ['operator'];
|
|
59
|
+
} else {
|
|
60
|
+
roles = ['readonly'];
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const permissions = resolvePermissions(roles, authConfig.rbac);
|
|
65
|
+
|
|
66
|
+
// Set auth context (same shape as API key / JWT auth)
|
|
67
|
+
(req as any).auth = {
|
|
68
|
+
workspace_id: workspaceId,
|
|
69
|
+
actor_id: `user:${user.id}`,
|
|
70
|
+
roles,
|
|
71
|
+
permissions,
|
|
72
|
+
auth_method: 'session' as const,
|
|
73
|
+
user_id: user.id,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// Attach user and session for use in auth routes
|
|
77
|
+
(req as any).sessionUser = user;
|
|
78
|
+
(req as any).sessionData = session;
|
|
79
|
+
|
|
80
|
+
// Backward compat
|
|
81
|
+
(req as any).workspace_id = workspaceId;
|
|
82
|
+
|
|
83
|
+
return next();
|
|
84
|
+
};
|
|
85
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import { randomUUID } from 'crypto';
|
|
3
|
+
import { sendError, ErrorCode } from '../server/errors';
|
|
4
|
+
|
|
5
|
+
const TOOL_NAME_PATTERN = /^[a-zA-Z][a-zA-Z0-9_.:\-]{0,127}$/;
|
|
6
|
+
const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
7
|
+
const SAFE_ID_PATTERN = /^[a-zA-Z0-9_-]{1,64}$/;
|
|
8
|
+
|
|
9
|
+
/** Infer tool.capability from the tool name (e.g. "http.get" → "read") */
|
|
10
|
+
function inferCapability(toolName: string): 'read' | 'write' | 'delete' | 'admin' {
|
|
11
|
+
const lower = toolName.toLowerCase();
|
|
12
|
+
if (lower.includes('get') || lower.includes('read') || lower.includes('list') || lower.includes('search')) return 'read';
|
|
13
|
+
if (lower.includes('delete') || lower.includes('remove')) return 'delete';
|
|
14
|
+
return 'write';
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Normalize the simplified docs format into the full ToolCall schema.
|
|
19
|
+
* Accepts: { tool, input, taskId, actorId, platform? }
|
|
20
|
+
* Produces: { tool_call_id, task_id, actor, source, tool, args }
|
|
21
|
+
*
|
|
22
|
+
* If the body already has tool_call_id or tool.name, it's left untouched.
|
|
23
|
+
*/
|
|
24
|
+
export function normalizeToolCall(req: Request, _res: Response, next: NextFunction): void {
|
|
25
|
+
const body = req.body;
|
|
26
|
+
if (!body || typeof body !== 'object') { next(); return; }
|
|
27
|
+
|
|
28
|
+
// Detect simplified format: has "tool" as string + "input" object, lacks "tool_call_id"
|
|
29
|
+
const isSimplified = typeof body.tool === 'string' && !body.tool_call_id;
|
|
30
|
+
if (!isSimplified) { next(); return; }
|
|
31
|
+
|
|
32
|
+
const toolName: string = body.tool;
|
|
33
|
+
const input = body.input && typeof body.input === 'object' ? body.input : {};
|
|
34
|
+
|
|
35
|
+
req.body = {
|
|
36
|
+
tool_call_id: randomUUID(),
|
|
37
|
+
task_id: body.taskId || body.task_id || randomUUID(),
|
|
38
|
+
actor: body.actor || { type: 'agent' as const, id: body.actorId || 'anonymous' },
|
|
39
|
+
source: body.source || { platform: body.platform || 'rest' },
|
|
40
|
+
tool: { name: toolName, capability: inferCapability(toolName) },
|
|
41
|
+
args: { method: toolName.split('.').pop()?.toUpperCase() || 'GET', ...input },
|
|
42
|
+
...(body.workspace_id ? { workspace_id: body.workspace_id } : {}),
|
|
43
|
+
...(body.constraints ? { constraints: body.constraints } : {}),
|
|
44
|
+
...(body.context ? { context: body.context } : {}),
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
next();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function validateToolCall(req: Request, res: Response, next: NextFunction): void {
|
|
51
|
+
const body = req.body;
|
|
52
|
+
|
|
53
|
+
const errors: string[] = [];
|
|
54
|
+
|
|
55
|
+
if (!body.tool_call_id) errors.push('tool_call_id is required');
|
|
56
|
+
if (!body.task_id) errors.push('task_id is required');
|
|
57
|
+
if (!body.actor || !body.actor.type || !body.actor.id) errors.push('actor with type and id is required');
|
|
58
|
+
if (!body.source || !body.source.platform) errors.push('source with platform is required');
|
|
59
|
+
if (!body.tool || !body.tool.name || !body.tool.capability) errors.push('tool with name and capability is required');
|
|
60
|
+
if (!body.args || typeof body.args !== 'object') errors.push('args object is required');
|
|
61
|
+
|
|
62
|
+
// Validate enum values
|
|
63
|
+
if (body.actor?.type && !['agent', 'user', 'system'].includes(body.actor.type)) {
|
|
64
|
+
errors.push('actor.type must be agent, user, or system');
|
|
65
|
+
}
|
|
66
|
+
if (body.tool?.capability && !['read', 'write', 'delete', 'admin'].includes(body.tool.capability)) {
|
|
67
|
+
errors.push('tool.capability must be read, write, delete, or admin');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Validate tool name pattern
|
|
71
|
+
if (body.tool?.name && !TOOL_NAME_PATTERN.test(body.tool.name)) {
|
|
72
|
+
errors.push('tool.name must start with a letter, contain only alphanumeric characters, dots, underscores, colons, or hyphens, and be at most 128 characters');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Validate URL format in args
|
|
76
|
+
if (body.args?.url !== undefined && body.args?.url !== null) {
|
|
77
|
+
const url = String(body.args.url);
|
|
78
|
+
if (!/^https?:\/\//i.test(url)) {
|
|
79
|
+
errors.push('args.url must be a well-formed URL starting with http:// or https://');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Validate args size limit (< 1MB)
|
|
84
|
+
if (body.args && typeof body.args === 'object') {
|
|
85
|
+
const argsSize = Buffer.byteLength(JSON.stringify(body.args), 'utf8');
|
|
86
|
+
if (argsSize >= 1048576) {
|
|
87
|
+
errors.push('args must be less than 1MB when serialized');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Validate tool_call_id format: UUID or alphanumeric up to 64 chars
|
|
92
|
+
if (body.tool_call_id && typeof body.tool_call_id === 'string') {
|
|
93
|
+
if (!UUID_PATTERN.test(body.tool_call_id) && !SAFE_ID_PATTERN.test(body.tool_call_id)) {
|
|
94
|
+
errors.push('tool_call_id must be a UUID (e.g. 550e8400-e29b-41d4-a716-446655440000) or alphanumeric string up to 64 chars (a-z, A-Z, 0-9, _, -)');
|
|
95
|
+
}
|
|
96
|
+
} else if (body.tool_call_id && typeof body.tool_call_id !== 'string') {
|
|
97
|
+
errors.push('tool_call_id must be a string');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Validate task_id format: UUID or alphanumeric up to 64 chars
|
|
101
|
+
if (body.task_id && typeof body.task_id === 'string') {
|
|
102
|
+
if (!UUID_PATTERN.test(body.task_id) && !SAFE_ID_PATTERN.test(body.task_id)) {
|
|
103
|
+
errors.push('task_id must be a UUID (e.g. 550e8400-e29b-41d4-a716-446655440000) or alphanumeric string up to 64 chars (a-z, A-Z, 0-9, _, -)');
|
|
104
|
+
}
|
|
105
|
+
} else if (body.task_id && typeof body.task_id !== 'string') {
|
|
106
|
+
errors.push('task_id must be a string');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Validate workspace_id if present
|
|
110
|
+
if (body.workspace_id !== undefined && body.workspace_id !== null) {
|
|
111
|
+
if (typeof body.workspace_id !== 'string' || body.workspace_id.length === 0 || body.workspace_id.length > 128) {
|
|
112
|
+
errors.push('workspace_id must be a non-empty string with length <= 128');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Validate actor.id length
|
|
117
|
+
if (body.actor?.id && typeof body.actor.id === 'string' && body.actor.id.length > 256) {
|
|
118
|
+
errors.push('actor.id must be <= 256 characters');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (errors.length > 0) {
|
|
122
|
+
sendError(res, 400, ErrorCode.VALIDATION_FAILED, 'Invalid ToolCall', {
|
|
123
|
+
details: errors,
|
|
124
|
+
hint: 'Check the ToolCall schema: tool_call_id, task_id, actor, source, tool, and args are required',
|
|
125
|
+
});
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
next();
|
|
130
|
+
}
|