@integsec/agentic-pentest-proxy 0.2.8 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +2 -0
  2. package/cloudflare/package-lock.json +1553 -0
  3. package/cloudflare/package.json +15 -0
  4. package/cloudflare/src/worker.mjs +126 -0
  5. package/cloudflare/wrangler.jsonc +26 -0
  6. package/dist/bin/integsec-agentic-pentest-bridge.d.ts +3 -0
  7. package/dist/bin/integsec-agentic-pentest-bridge.d.ts.map +1 -0
  8. package/dist/bin/integsec-agentic-pentest-bridge.js +23 -0
  9. package/dist/bin/integsec-agentic-pentest-bridge.js.map +1 -0
  10. package/dist/bin/integsec-agentic-pentest-gateway.d.ts +3 -0
  11. package/dist/bin/integsec-agentic-pentest-gateway.d.ts.map +1 -0
  12. package/dist/bin/integsec-agentic-pentest-gateway.js +42 -0
  13. package/dist/bin/integsec-agentic-pentest-gateway.js.map +1 -0
  14. package/dist/bin/integsec-agentic-pentest-proxy.js +6 -0
  15. package/dist/bin/integsec-agentic-pentest-proxy.js.map +1 -1
  16. package/dist/src/config.js +1 -1
  17. package/dist/src/gateway/admin.html +21 -0
  18. package/dist/src/gateway/admin.js +78 -0
  19. package/dist/src/gateway/auth.d.ts +18 -0
  20. package/dist/src/gateway/auth.d.ts.map +1 -0
  21. package/dist/src/gateway/auth.js +112 -0
  22. package/dist/src/gateway/auth.js.map +1 -0
  23. package/dist/src/gateway/runtime.d.ts +20 -0
  24. package/dist/src/gateway/runtime.d.ts.map +1 -0
  25. package/dist/src/gateway/runtime.js +167 -0
  26. package/dist/src/gateway/runtime.js.map +1 -0
  27. package/dist/src/gateway/server.d.ts +27 -0
  28. package/dist/src/gateway/server.d.ts.map +1 -0
  29. package/dist/src/gateway/server.js +232 -0
  30. package/dist/src/gateway/server.js.map +1 -0
  31. package/dist/src/gateway/state.d.ts +64 -0
  32. package/dist/src/gateway/state.d.ts.map +1 -0
  33. package/dist/src/gateway/state.js +126 -0
  34. package/dist/src/gateway/state.js.map +1 -0
  35. package/dist/src/index.d.ts +1 -1
  36. package/dist/src/index.js +1 -1
  37. package/dist/src/proxy.d.ts +4 -3
  38. package/dist/src/proxy.d.ts.map +1 -1
  39. package/dist/src/proxy.js +22 -9
  40. package/dist/src/proxy.js.map +1 -1
  41. package/dist/src/types.d.ts +2 -0
  42. package/dist/src/types.d.ts.map +1 -1
  43. package/docs/managed-gateway.md +90 -0
  44. package/package.json +11 -3
@@ -0,0 +1,15 @@
1
+ {
2
+ "name": "@integsec/agentic-pentest-cloudflare",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "check": "node --check src/worker.mjs && wrangler deploy --dry-run",
7
+ "deploy": "wrangler deploy"
8
+ },
9
+ "dependencies": {
10
+ "@cloudflare/containers": "^0.3.7"
11
+ },
12
+ "devDependencies": {
13
+ "wrangler": "^4.158.0"
14
+ }
15
+ }
@@ -0,0 +1,126 @@
1
+ import { Container, getContainer } from '@cloudflare/containers';
2
+
3
+ const text = (value, status = 200) => new Response(value, { status, headers: { 'Cache-Control': 'no-store' } });
4
+ const json = (value, status = 200) => new Response(JSON.stringify(value), { status, headers: { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' } });
5
+
6
+ function tokenMatches(header, expected) {
7
+ if (!expected || !header?.startsWith('Bearer ')) return false;
8
+ const value = header.slice(7);
9
+ if (value.length !== expected.length) return false;
10
+ let difference = 0;
11
+ for (let i = 0; i < expected.length; i++) difference |= value.charCodeAt(i) ^ expected.charCodeAt(i);
12
+ return difference === 0;
13
+ }
14
+
15
+ export class PentestGatewayContainer extends Container {
16
+ defaultPort = 9091;
17
+ pingEndpoint = 'localhost/healthz';
18
+ sleepAfter = '10m';
19
+ writeQueue = Promise.resolve();
20
+
21
+ constructor(ctx, env) {
22
+ super(ctx, env);
23
+ for (const name of ['GATEWAY_ADMIN_TOKEN', 'INTERNAL_TOKEN', 'CLOUDFLARE_TEAM_DOMAIN', 'CLOUDFLARE_ACCESS_AUD', 'AUDIT_WEBHOOK_URL']) {
24
+ if (!env[name]) throw new Error(`Missing required Worker secret: ${name}`);
25
+ }
26
+ this.envVars = {
27
+ GATEWAY_MODE: 'true',
28
+ GATEWAY_HOST: '0.0.0.0',
29
+ GATEWAY_PORT: '9091',
30
+ GATEWAY_PUBLIC_URL: env.GATEWAY_PUBLIC_URL,
31
+ GATEWAY_AUTH_MODE: 'cloudflare',
32
+ CLOUDFLARE_TEAM_DOMAIN: env.CLOUDFLARE_TEAM_DOMAIN,
33
+ CLOUDFLARE_ACCESS_AUD: env.CLOUDFLARE_ACCESS_AUD,
34
+ GATEWAY_ADMIN_TOKEN: env.GATEWAY_ADMIN_TOKEN,
35
+ GATEWAY_INTERNAL_TOKEN: env.INTERNAL_TOKEN,
36
+ AUDIT_WEBHOOK_URL: env.AUDIT_WEBHOOK_URL,
37
+ AUDIT_WEBHOOK_TOKEN: env.INTERNAL_TOKEN,
38
+ GATEWAY_STATE_PATH: '/app/gateway/state.json',
39
+ AUDIT_LOG_PATH: '/app/audit',
40
+ };
41
+ }
42
+
43
+ async onStart() {
44
+ const state = await this.ctx.storage.get('gateway-state');
45
+ if (state) {
46
+ const response = await this.containerFetch('http://localhost:9091/__internal/state', {
47
+ method: 'PUT',
48
+ headers: { Authorization: `Bearer ${this.env.INTERNAL_TOKEN}`, 'Content-Type': 'application/json' },
49
+ body: JSON.stringify(state),
50
+ });
51
+ await response.body?.cancel();
52
+ if (!response.ok) throw new Error(`Failed to restore gateway state: ${response.status}`);
53
+ }
54
+ }
55
+
56
+ async fetch(request) {
57
+ const url = new URL(request.url);
58
+ if (url.pathname === '/__internal/audit') return this.persistAudit(request);
59
+ if (url.hostname !== new URL(this.env.GATEWAY_PUBLIC_URL).hostname) return text('Not found', 404);
60
+ if (url.pathname === '/api/audit' && request.method === 'GET') return this.listAudit(request);
61
+ if (url.pathname.startsWith('/__internal/')) return text('Not found', 404);
62
+ const mutatesState = url.pathname.startsWith('/api/') && ['POST', 'PUT', 'PATCH', 'DELETE'].includes(request.method);
63
+ if (!mutatesState) return this.containerFetch(request);
64
+
65
+ const result = this.writeQueue.then(() => this.persistMutation(request));
66
+ this.writeQueue = result.then(() => undefined, () => undefined);
67
+ return result;
68
+ }
69
+
70
+ async persistMutation(request) {
71
+ const previous = await this.ctx.storage.get('gateway-state') ?? { version: 1, upstreams: [], scopes: [], activeScopeId: null };
72
+ const response = await this.containerFetch(request);
73
+ if (!response.ok) return response;
74
+ const currentResponse = await this.containerFetch('http://localhost:9091/__internal/state', {
75
+ headers: { Authorization: `Bearer ${this.env.INTERNAL_TOKEN}` },
76
+ });
77
+ if (!currentResponse.ok) {
78
+ await this.restoreState(previous);
79
+ return text('Unable to read updated state', 503);
80
+ }
81
+ const current = await currentResponse.json();
82
+ try {
83
+ await this.ctx.storage.put('gateway-state', current);
84
+ return response;
85
+ } catch (error) {
86
+ console.error('Durable state write failed', error);
87
+ await this.restoreState(previous);
88
+ return text('Durable state write failed; change was not acknowledged', 503);
89
+ }
90
+ }
91
+
92
+ async restoreState(state) {
93
+ const response = await this.containerFetch('http://localhost:9091/__internal/state', {
94
+ method: 'PUT', headers: { Authorization: `Bearer ${this.env.INTERNAL_TOKEN}`, 'Content-Type': 'application/json' }, body: JSON.stringify(state),
95
+ });
96
+ await response.body?.cancel();
97
+ if (!response.ok) throw new Error(`Gateway rollback failed: ${response.status}`);
98
+ }
99
+
100
+ async persistAudit(request) {
101
+ if (request.method !== 'POST' || !tokenMatches(request.headers.get('authorization'), this.env.INTERNAL_TOKEN)) return text('Forbidden', 403);
102
+ if (Number(request.headers.get('content-length') || 0) > 65_536) return text('Too large', 413);
103
+ const raw = await request.text();
104
+ if (raw.length > 65_536) return text('Too large', 413);
105
+ let entry;
106
+ try { entry = JSON.parse(raw); } catch { return text('Invalid JSON', 400); }
107
+ if (!entry || typeof entry.engagement_id !== 'string' || typeof entry.decision !== 'string' || typeof entry.timestamp !== 'string') return text('Invalid audit entry', 400);
108
+ await this.ctx.storage.put(`audit:${Date.now().toString().padStart(13, '0')}:${crypto.randomUUID()}`, entry);
109
+ return new Response(null, { status: 204, headers: { 'Cache-Control': 'no-store' } });
110
+ }
111
+
112
+ async listAudit(request) {
113
+ if (!tokenMatches(request.headers.get('authorization'), this.env.GATEWAY_ADMIN_TOKEN)) return text('Admin token required', 401);
114
+ const check = await this.containerFetch('http://localhost:9091/api/state', { headers: request.headers });
115
+ await check.body?.cancel();
116
+ if (check.status !== 200) return text('Access assertion required', 403);
117
+ const entries = await this.ctx.storage.list({ prefix: 'audit:', reverse: true, limit: 100 });
118
+ return json({ entries: [...entries.values()] });
119
+ }
120
+ }
121
+
122
+ export default {
123
+ async fetch(request, env) {
124
+ return getContainer(env.GATEWAY, 'team').fetch(request);
125
+ },
126
+ };
@@ -0,0 +1,26 @@
1
+ {
2
+ "$schema": "./node_modules/wrangler/config-schema.json",
3
+ "name": "agentic-pentest-gateway",
4
+ "main": "src/worker.mjs",
5
+ "compatibility_date": "2026-11-07",
6
+ "workers_dev": true,
7
+ "routes": [{ "pattern": "agentic-proxy.pentestprepper.com", "custom_domain": true }],
8
+ "observability": { "enabled": true },
9
+ "containers": [
10
+ {
11
+ "class_name": "PentestGatewayContainer",
12
+ "image": "docker.io/integsec/agentic-pentest-mcp-proxy:0.3.0",
13
+ "instance_type": "basic",
14
+ "max_instances": 1
15
+ }
16
+ ],
17
+ "durable_objects": {
18
+ "bindings": [{ "name": "GATEWAY", "class_name": "PentestGatewayContainer" }]
19
+ },
20
+ "exports": {
21
+ "PentestGatewayContainer": { "type": "durable-object", "storage": "sqlite" }
22
+ },
23
+ "vars": {
24
+ "GATEWAY_PUBLIC_URL": "https://agentic-proxy.pentestprepper.com"
25
+ }
26
+ }
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=integsec-agentic-pentest-bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integsec-agentic-pentest-bridge.d.ts","sourceRoot":"","sources":["../../bin/integsec-agentic-pentest-bridge.ts"],"names":[],"mappings":""}
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env node
2
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
3
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
4
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
7
+ if (process.argv.includes("--help") || process.argv.includes("-h")) {
8
+ console.log("Local MCP bridge for Claude Desktop. Set GATEWAY_URL=http://127.0.0.1:9091/mcp or pass it as the first argument.");
9
+ process.exit(0);
10
+ }
11
+ const url = new URL(process.argv[2] ?? process.env.GATEWAY_URL ?? "http://127.0.0.1:9091/mcp");
12
+ if (!["127.0.0.1", "localhost", "[::1]"].includes(url.hostname) || url.protocol !== "http:") {
13
+ throw new Error("The local bridge only accepts a loopback HTTP gateway URL");
14
+ }
15
+ const upstream = new Client({ name: "agentic-pentest-bridge", version: "0.3.0" });
16
+ await upstream.connect(new StreamableHTTPClientTransport(url));
17
+ const bridge = new Server({ name: "agentic-pentest-local", version: "0.3.0" }, { capabilities: { tools: {} } });
18
+ bridge.setRequestHandler(ListToolsRequestSchema, async (request) => upstream.listTools(request.params));
19
+ bridge.setRequestHandler(CallToolRequestSchema, async (request) => upstream.callTool(request.params));
20
+ await bridge.connect(new StdioServerTransport());
21
+ process.on("SIGINT", () => void upstream.close());
22
+ process.on("SIGTERM", () => void upstream.close());
23
+ //# sourceMappingURL=integsec-agentic-pentest-bridge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integsec-agentic-pentest-bridge.js","sourceRoot":"","sources":["../../bin/integsec-agentic-pentest-bridge.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AACnG,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAEnG,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IACnE,OAAO,CAAC,GAAG,CAAC,kHAAkH,CAAC,CAAC;IAChI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,2BAA2B,CAAC,CAAC;AAC/F,IAAI,CAAC,CAAC,WAAW,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;IAC5F,MAAM,IAAI,KAAK,CAAC,2DAA2D,CAAC,CAAC;AAC/E,CAAC;AACD,MAAM,QAAQ,GAAG,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,wBAAwB,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AAClF,MAAM,QAAQ,CAAC,OAAO,CAAC,IAAI,6BAA6B,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,IAAI,EAAE,uBAAuB,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;AAChH,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AACxG,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AACtG,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;AACjD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;AAClD,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import "dotenv/config";
3
+ //# sourceMappingURL=integsec-agentic-pentest-gateway.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integsec-agentic-pentest-gateway.d.ts","sourceRoot":"","sources":["../../bin/integsec-agentic-pentest-gateway.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC"}
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ import "dotenv/config";
3
+ import { createGateway } from "../src/gateway/server.js";
4
+ if (process.argv.includes("--help") || process.argv.includes("-h")) {
5
+ console.log(`IntegSec MCP Gateway
6
+
7
+ Manage MCP upstreams and engagement scopes in a browser, then connect an MCP client at /mcp.
8
+
9
+ Required: GATEWAY_ADMIN_TOKEN (at least 32 characters).
10
+ Optional: GATEWAY_HOST (127.0.0.1), GATEWAY_PORT (9091), GATEWAY_STATE_PATH (./gateway/state.json).
11
+ Hosted with Cloudflare Access: GATEWAY_PUBLIC_URL, GATEWAY_AUTH_MODE=cloudflare,
12
+ CLOUDFLARE_TEAM_DOMAIN, CLOUDFLARE_ACCESS_AUD.
13
+ Hosted with direct Entra: GATEWAY_PUBLIC_URL, ENTRA_TENANT, ENTRA_AUDIENCE, ENTRA_SCOPE.
14
+
15
+ Run: integsec-agentic-pentest-gateway
16
+ Open: http://127.0.0.1:9091/admin
17
+ `);
18
+ process.exit(0);
19
+ }
20
+ const gateway = createGateway({
21
+ host: process.env.GATEWAY_HOST ?? "127.0.0.1",
22
+ port: Number(process.env.GATEWAY_PORT ?? "9091"),
23
+ statePath: process.env.GATEWAY_STATE_PATH ?? "./gateway/state.json",
24
+ adminToken: process.env.GATEWAY_ADMIN_TOKEN ?? "",
25
+ publicUrl: process.env.GATEWAY_PUBLIC_URL,
26
+ entraTenant: process.env.ENTRA_TENANT,
27
+ entraAudience: process.env.ENTRA_AUDIENCE,
28
+ entraScope: process.env.ENTRA_SCOPE,
29
+ authMode: process.env.GATEWAY_AUTH_MODE === "cloudflare" ? "cloudflare" : "entra",
30
+ cloudflareTeamDomain: process.env.CLOUDFLARE_TEAM_DOMAIN,
31
+ cloudflareAccessAud: process.env.CLOUDFLARE_ACCESS_AUD,
32
+ internalToken: process.env.GATEWAY_INTERNAL_TOKEN,
33
+ auditWebhookUrl: process.env.AUDIT_WEBHOOK_URL,
34
+ auditWebhookToken: process.env.AUDIT_WEBHOOK_TOKEN,
35
+ });
36
+ await gateway.listen();
37
+ console.error(`[gateway] Listening on ${process.env.GATEWAY_HOST ?? "127.0.0.1"}:${process.env.GATEWAY_PORT ?? "9091"}`);
38
+ console.error("[gateway] Admin UI: /admin; MCP: /mcp");
39
+ const stop = async () => { await gateway.close(); process.exit(0); };
40
+ process.on("SIGINT", () => void stop());
41
+ process.on("SIGTERM", () => void stop());
42
+ //# sourceMappingURL=integsec-agentic-pentest-gateway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integsec-agentic-pentest-gateway.js","sourceRoot":"","sources":["../../bin/integsec-agentic-pentest-gateway.ts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AACvB,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAEzD,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;IACnE,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;CAYb,CAAC,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,OAAO,GAAG,aAAa,CAAC;IAC5B,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,WAAW;IAC7C,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,MAAM,CAAC;IAChD,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,sBAAsB;IACnE,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,IAAI,EAAE;IACjD,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB;IACzC,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY;IACrC,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc;IACzC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW;IACnC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO;IACjF,oBAAoB,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB;IACxD,mBAAmB,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB;IACtD,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,sBAAsB;IACjD,eAAe,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB;IAC9C,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB;CACnD,CAAC,CAAC;AAEH,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;AACvB,OAAO,CAAC,KAAK,CAAC,0BAA0B,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,WAAW,IAAI,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,MAAM,EAAE,CAAC,CAAC;AACzH,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;AACvD,MAAM,IAAI,GAAG,KAAK,IAAI,EAAE,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrE,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;AACxC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC"}
@@ -10,6 +10,10 @@ import { CloudWatchAuditLogger } from "../src/audit/cloudwatch.js";
10
10
  import { AzureMonitorAuditLogger } from "../src/audit/azure-monitor.js";
11
11
  import { GcpAuditLogger } from "../src/audit/gcp-logging.js";
12
12
  async function main() {
13
+ if (process.argv.includes("--gateway") || process.env.GATEWAY_MODE === "true") {
14
+ await import("./integsec-agentic-pentest-gateway.js");
15
+ return;
16
+ }
13
17
  if (process.argv.includes("--help") || process.argv.includes("-h")) {
14
18
  console.log(`IntegSec Agentic Pentest Proxy
15
19
 
@@ -21,6 +25,8 @@ Get started:
21
25
  3. Paste the generated mcpServers entry into your MCP client's configuration.
22
26
  4. integsec-agentic-pentest-tui --audit-path ./audit
23
27
 
28
+ Managed gateway: integsec-agentic-pentest-gateway --help
29
+
24
30
  The proxy starts when your MCP client launches its configured tool.
25
31
  Docs: https://github.com/IntegSec/agentic-pentest-proxy#quick-start
26
32
  `);
@@ -1 +1 @@
1
- {"version":3,"file":"integsec-agentic-pentest-proxy.js","sourceRoot":"","sources":["../../bin/integsec-agentic-pentest-proxy.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"integsec-agentic-pentest-proxy.js","sourceRoot":"","sources":["../../bin/integsec-agentic-pentest-proxy.ts"],"names":[],"mappings":"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"}
@@ -50,7 +50,7 @@ export function loadConfig() {
50
50
  techniqueMapPath: process.env.TECHNIQUE_MAP_PATH,
51
51
  dnsCacheTtl: parseInt(process.env.DNS_CACHE_TTL || "60", 10),
52
52
  logLevel: process.env.LOG_LEVEL || "INFO",
53
- proxyVersion: process.env.PROXY_VERSION || "0.2.7",
53
+ proxyVersion: process.env.PROXY_VERSION || "0.3.0",
54
54
  };
55
55
  }
56
56
  //# sourceMappingURL=config.js.map
@@ -0,0 +1,21 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <meta charset="utf-8">
4
+ <meta name="viewport" content="width=device-width, initial-scale=1">
5
+ <title>IntegSec MCP Gateway</title>
6
+ <style>
7
+ :root{font:15px system-ui,sans-serif;color:#e8f0f2;background:#0b1218}
8
+ *{box-sizing:border-box}body{margin:0}header{padding:22px 5vw;background:#10202b;border-bottom:1px solid #234052;display:flex;justify-content:space-between;align-items:center;gap:20px}
9
+ h1{font-size:21px;margin:0}h2{font-size:18px;margin:0 0 14px}h3{font-size:15px;margin:16px 0 6px}p{color:#a8bdc8;line-height:1.45}main{max-width:1200px;margin:30px auto;padding:0 20px;display:grid;grid-template-columns:1fr 1fr;gap:20px}.card{background:#14222c;border:1px solid #294454;border-radius:13px;padding:24px}.wide{grid-column:1/-1}
10
+ input,select,textarea,button{font:inherit}input,select,textarea{width:100%;background:#0b1720;color:#fff;border:1px solid #426073;border-radius:7px;padding:9px;margin:5px 0 12px}textarea{min-height:70px}label{display:block;color:#c1d0d8;font-weight:600;font-size:13px}button{border:0;border-radius:7px;background:#26bfa4;color:#081914;padding:9px 14px;font-weight:700;cursor:pointer;margin:4px 7px 4px 0}button.secondary{background:#304b5a;color:#e8f0f2}button.danger{background:#6d3541;color:#fff}button:disabled{opacity:.5;cursor:not-allowed}.grid{display:grid;grid-template-columns:1fr 1fr;gap:0 14px}.row{border-top:1px solid #294454;padding:12px 0;display:flex;align-items:center;justify-content:space-between;gap:12px}.muted{font-size:12px;color:#93acb9}#status{padding:8px 5vw;color:#8ee7ce;min-height:35px}#status.error{color:#ff9e9e}code{color:#a6e7db}@media(max-width:800px){main{display:block}.card{margin-bottom:20px}.grid{display:block}}
11
+ </style>
12
+ <header><h1>IntegSec MCP Gateway</h1><span class="muted">Manage tools and engagement scope</span></header>
13
+ <div id="status" role="status"></div>
14
+ <main>
15
+ <section class="card wide"><h2>Administrator access</h2><p>Enter the gateway admin token from your service environment. It stays in this browser tab only.</p><div class="grid"><label>Admin token<input id="token" type="password" autocomplete="off"></label><div><br><button id="connect">Connect</button></div></div></section>
16
+ <section class="card"><h2>MCP servers</h2><div id="upstreams"></div><h3>Add a server</h3><div class="grid"><label>Name<input id="up-name" placeholder="burp"></label><label>Transport<select id="up-transport"><option value="stdio">Local process</option><option value="http">Streamable HTTP</option><option value="sse">SSE</option></select></label></div><label>Command or URL<input id="up-target" placeholder="burp-mcp-server or https://example.com/mcp"></label><label>Arguments, one per line<textarea id="up-args" placeholder="--port\n3000"></textarea></label><button id="add-upstream">Add server</button></section>
17
+ <section class="card"><h2>Engagement scopes</h2><p>Save a draft, review it, then activate it. The active scope cannot be edited in place.</p><div id="scopes"></div><h3>Scope editor</h3><div class="grid"><label>Engagement ID<input id="engagement" placeholder="ENG-2026-001"></label><label>Client<input id="client" placeholder="Example Client"></label><label>Operator<input id="operator" placeholder="Test Team"></label><label>Starts (UTC)<input id="starts" type="datetime-local"></label><label>Ends (UTC)<input id="ends" type="datetime-local"></label><label>Execution profile<select id="profile"><option value="isolated">Isolated: local MCP only</option><option value="restricted">Restricted: approved hosts</option><option value="connected">Connected: network MCP allowed</option></select></label></div><p class="muted">Use one item per line in each field.</p><div class="grid"><label>IP ranges<textarea id="ips"></textarea></label><label>Domains<textarea id="domains"></textarea></label><label>URLs<textarea id="urls"></textarea></label><label>Cloud accounts<textarea id="cloud"></textarea></label><label>Excluded targets<textarea id="excluded-targets"></textarea></label><label>Authorized techniques<textarea id="techniques"></textarea></label><label>Excluded techniques<textarea id="excluded-techniques"></textarea></label><label>Allowed MCP hosts (restricted profile)<textarea id="hosts"></textarea></label></div><button id="save-scope">Save draft</button><button id="new-scope" class="secondary">Clear editor</button></section>
18
+ <section class="card wide"><h2>Client connection</h2><p id="connection">Connect as an administrator to see the endpoint.</p><p class="muted">Local Burp tools must run on each tester’s own gateway or local MCP connection. A public gateway cannot launch Burp on a tester’s laptop.</p></section>
19
+ </main>
20
+ <script src="/admin.js" defer></script>
21
+ </html>
@@ -0,0 +1,78 @@
1
+ const $ = (id) => document.getElementById(id);
2
+ let state = null;
3
+ let editing = null;
4
+ const token = $('token');
5
+ token.value = sessionStorage.getItem('gateway-token') || '';
6
+
7
+ function status(message, error = false) { const node = $('status'); node.textContent = message; node.classList.toggle('error', error); }
8
+ async function api(path, method = 'GET', data) {
9
+ const response = await fetch(path, { method, headers: { Authorization: `Bearer ${token.value}`, ...(data ? { 'Content-Type': 'application/json' } : {}) }, body: data ? JSON.stringify(data) : undefined });
10
+ const result = await response.json();
11
+ if (!response.ok) throw new Error(result.error || `HTTP ${response.status}`);
12
+ return result;
13
+ }
14
+ const lines = (id) => $(id).value.split(/\r?\n/).map(x => x.trim()).filter(Boolean);
15
+ const setLines = (id, values) => { $(id).value = values.join('\n'); };
16
+ const make = (tag, value) => { const node = document.createElement(tag); node.textContent = value; return node; };
17
+ const button = (label, action, style = 'secondary') => { const node = make('button', label); node.className = style; node.addEventListener('click', () => action().catch(e => status(e.message, true))); return node; };
18
+
19
+ async function refresh() {
20
+ state = await api('/api/state');
21
+ const up = $('upstreams'); up.replaceChildren();
22
+ for (const item of state.upstreams) {
23
+ const row = make('div', ''); row.className = 'row';
24
+ const label = make('div', `${item.name} · ${item.transport} · ${item.enabled ? 'Enabled' : 'Disabled'}`);
25
+ label.appendChild(make('div', item.transport === 'stdio' ? item.command : item.url));
26
+ row.append(label, button(item.enabled ? 'Disable' : 'Enable', async () => { await api(`/api/upstreams/${item.id}`, 'PATCH', { enabled: !item.enabled }); await refresh(); }));
27
+ row.append(button('Remove', async () => { if (confirm(`Remove ${item.name}?`)) { await api(`/api/upstreams/${item.id}`, 'DELETE'); await refresh(); } }, 'danger'));
28
+ up.append(row);
29
+ }
30
+ const scopes = $('scopes'); scopes.replaceChildren();
31
+ for (const item of state.scopes) {
32
+ const active = item.id === state.activeScopeId;
33
+ const row = make('div', ''); row.className = 'row';
34
+ row.append(make('div', `${item.manifest.engagement_id} · ${item.profile}${active ? ' · ACTIVE' : ''}`));
35
+ row.append(button('View', async () => loadScope(item)));
36
+ if (!active) {
37
+ row.append(button('Activate', async () => { await api(`/api/scopes/${item.id}/activate`, 'POST'); await refresh(); }));
38
+ row.append(button('Delete', async () => { if (confirm(`Delete draft ${item.manifest.engagement_id}?`)) { await api(`/api/scopes/${item.id}`, 'DELETE'); await refresh(); } }, 'danger'));
39
+ }
40
+ scopes.append(row);
41
+ }
42
+ $('connection').textContent = `MCP endpoint: ${location.origin}/mcp. ${state.activeScopeId ? 'An engagement scope is active.' : 'Activate a scope before connecting clients.'}`;
43
+ status('Gateway state loaded.');
44
+ }
45
+ function loadScope(item) {
46
+ editing = item.id === state.activeScopeId ? null : item.id;
47
+ const m = item.manifest;
48
+ $('engagement').value = m.engagement_id; $('client').value = m.client; $('operator').value = m.operator;
49
+ $('starts').value = m.engagement_window.start.slice(0,16); $('ends').value = m.engagement_window.end.slice(0,16);
50
+ $('profile').value = item.profile; setLines('ips', m.authorized_targets.ip_ranges); setLines('domains', m.authorized_targets.domains);
51
+ setLines('urls', m.authorized_targets.urls); setLines('cloud', m.authorized_targets.cloud_accounts);
52
+ setLines('excluded-targets', m.excluded_targets); setLines('techniques', m.authorized_techniques);
53
+ setLines('excluded-techniques', m.excluded_techniques); setLines('hosts', item.allowedHosts);
54
+ status(item.id === state.activeScopeId ? 'Viewing active scope. Saving creates a new draft.' : 'Draft loaded for editing.');
55
+ }
56
+ $('connect').onclick = () => { sessionStorage.setItem('gateway-token', token.value); refresh().catch(e => status(e.message, true)); };
57
+ $('add-upstream').onclick = async () => {
58
+ try {
59
+ const transport = $('up-transport').value;
60
+ await api('/api/upstreams', 'POST', { name: $('up-name').value.trim(), enabled: true, transport,
61
+ ...(transport === 'stdio' ? { command: $('up-target').value.trim(), args: lines('up-args') } : { url: $('up-target').value.trim(), args: [] }) });
62
+ $('up-name').value = ''; $('up-target').value = ''; $('up-args').value = ''; await refresh();
63
+ } catch (e) { status(e.message, true); }
64
+ };
65
+ $('new-scope').onclick = () => { editing = null; for (const id of ['engagement','client','operator','starts','ends','ips','domains','urls','cloud','excluded-targets','techniques','excluded-techniques','hosts']) $(id).value = ''; $('profile').value = 'isolated'; status('New draft.'); };
66
+ $('save-scope').onclick = async () => {
67
+ try {
68
+ const scope = { profile: $('profile').value, allowedHosts: lines('hosts'), manifest: {
69
+ engagement_id: $('engagement').value.trim(), client: $('client').value.trim(), operator: $('operator').value.trim(),
70
+ authorized_targets: { ip_ranges: lines('ips'), domains: lines('domains'), urls: lines('urls'), cloud_accounts: lines('cloud') },
71
+ excluded_targets: lines('excluded-targets'), authorized_techniques: lines('techniques'), excluded_techniques: lines('excluded-techniques'),
72
+ engagement_window: { start: new Date($('starts').value).toISOString(), end: new Date($('ends').value).toISOString() },
73
+ } };
74
+ await api(editing ? `/api/scopes/${editing}` : '/api/scopes', editing ? 'PUT' : 'POST', scope);
75
+ editing = null; await refresh(); status('Draft saved. Review it before activation.');
76
+ } catch (e) { status(e.message, true); }
77
+ };
78
+ if (token.value) refresh().catch(e => status(e.message, true));
@@ -0,0 +1,18 @@
1
+ import type { IncomingMessage, ServerResponse } from "node:http";
2
+ export declare class GatewayAuth {
3
+ readonly publicUrl: string | undefined;
4
+ private readonly tenant;
5
+ private readonly audience;
6
+ private readonly requiredScope;
7
+ private readonly mode;
8
+ private readonly teamDomain?;
9
+ private verifier?;
10
+ private accessJwks?;
11
+ constructor(publicUrl: string | undefined, tenant: string | undefined, audience: string | undefined, requiredScope: string | undefined, mode?: "entra" | "cloudflare", teamDomain?: string | undefined);
12
+ protectedResource(): Promise<Record<string, unknown>>;
13
+ authorize(req: IncomingMessage, res: ServerResponse): Promise<string | false>;
14
+ private denyAccess;
15
+ private challenge;
16
+ private getVerifier;
17
+ }
18
+ //# sourceMappingURL=auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../../src/gateway/auth.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAIjE,qBAAa,WAAW;IAKpB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAT9B,OAAO,CAAC,QAAQ,CAAC,CAA2E;IAC5F,OAAO,CAAC,UAAU,CAAC,CAAwC;gBAGhD,SAAS,EAAE,MAAM,GAAG,SAAS,EACrB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,QAAQ,EAAE,MAAM,GAAG,SAAS,EAC5B,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,IAAI,GAAE,OAAO,GAAG,YAAsB,EACtC,UAAU,CAAC,EAAE,MAAM,YAAA;IAUhC,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAYrD,SAAS,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC;IA0BnF,OAAO,CAAC,UAAU;IAKlB,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,WAAW;CAepB"}
@@ -0,0 +1,112 @@
1
+ import { createRemoteJWKSet, jwtVerify } from "jose";
2
+ export class GatewayAuth {
3
+ publicUrl;
4
+ tenant;
5
+ audience;
6
+ requiredScope;
7
+ mode;
8
+ teamDomain;
9
+ verifier;
10
+ accessJwks;
11
+ constructor(publicUrl, tenant, audience, requiredScope, mode = "entra", teamDomain) {
12
+ this.publicUrl = publicUrl;
13
+ this.tenant = tenant;
14
+ this.audience = audience;
15
+ this.requiredScope = requiredScope;
16
+ this.mode = mode;
17
+ this.teamDomain = teamDomain;
18
+ if (publicUrl) {
19
+ if (new URL(publicUrl).protocol !== "https:")
20
+ throw new Error("GATEWAY_PUBLIC_URL must be HTTPS");
21
+ if (mode === "entra" && (!tenant || !audience || !requiredScope))
22
+ throw new Error("Direct Entra mode requires ENTRA_TENANT, ENTRA_AUDIENCE and ENTRA_SCOPE");
23
+ if (mode === "cloudflare" && (!teamDomain || !audience))
24
+ throw new Error("Cloudflare mode requires CLOUDFLARE_TEAM_DOMAIN and CLOUDFLARE_ACCESS_AUD");
25
+ if (mode === "cloudflare" && (new URL(teamDomain).protocol !== "https:" || !new URL(teamDomain).hostname.endsWith(".cloudflareaccess.com")))
26
+ throw new Error("Invalid CLOUDFLARE_TEAM_DOMAIN");
27
+ }
28
+ }
29
+ async protectedResource() {
30
+ if (!this.publicUrl)
31
+ throw new Error("No public gateway URL configured");
32
+ if (this.mode === "cloudflare")
33
+ throw new Error("Cloudflare Access serves OAuth metadata at the edge");
34
+ const { issuer } = await this.getVerifier();
35
+ return {
36
+ resource: new URL("/mcp", this.publicUrl).toString(),
37
+ authorization_servers: [issuer],
38
+ scopes_supported: [this.requiredScope],
39
+ bearer_methods_supported: ["header"],
40
+ };
41
+ }
42
+ async authorize(req, res) {
43
+ if (!this.publicUrl)
44
+ return "local";
45
+ if (this.mode === "cloudflare") {
46
+ const token = req.headers["cf-access-jwt-assertion"];
47
+ if (typeof token !== "string") {
48
+ this.denyAccess(res);
49
+ return false;
50
+ }
51
+ try {
52
+ const domain = new URL(this.teamDomain);
53
+ this.accessJwks ??= createRemoteJWKSet(new URL("/cdn-cgi/access/certs", domain));
54
+ const { payload } = await jwtVerify(token, this.accessJwks, { issuer: domain.origin, audience: this.audience, algorithms: ["RS256"] });
55
+ return typeof payload.sub === "string" ? payload.sub : "cloudflare-access";
56
+ }
57
+ catch {
58
+ this.denyAccess(res);
59
+ return false;
60
+ }
61
+ }
62
+ const token = /^Bearer (\S+)$/i.exec(req.headers.authorization ?? "")?.[1];
63
+ if (!token) {
64
+ this.challenge(res);
65
+ return false;
66
+ }
67
+ try {
68
+ const { issuer, jwks } = await this.getVerifier();
69
+ const { payload } = await jwtVerify(token, jwks, { issuer, audience: this.audience, algorithms: ["RS256"] });
70
+ const scopes = typeof payload.scp === "string" ? payload.scp.split(" ") : [];
71
+ if (!scopes.includes(this.requiredScope)) {
72
+ this.challenge(res);
73
+ return false;
74
+ }
75
+ return typeof payload.oid === "string" ? payload.oid : typeof payload.sub === "string" ? payload.sub : "entra-user";
76
+ }
77
+ catch {
78
+ this.challenge(res);
79
+ return false;
80
+ }
81
+ }
82
+ denyAccess(res) {
83
+ res.writeHead(403, { "Content-Type": "application/json", "Cache-Control": "no-store" });
84
+ res.end(JSON.stringify({ error: "invalid Cloudflare Access assertion" }));
85
+ }
86
+ challenge(res) {
87
+ const metadata = new URL("/.well-known/oauth-protected-resource/mcp", this.publicUrl).toString();
88
+ res.writeHead(401, {
89
+ "WWW-Authenticate": `Bearer resource_metadata="${metadata}", scope="${this.requiredScope}"`,
90
+ "Cache-Control": "no-store",
91
+ "Content-Type": "application/json",
92
+ });
93
+ res.end(JSON.stringify({ error: "unauthorized" }));
94
+ }
95
+ getVerifier() {
96
+ this.verifier ??= (async () => {
97
+ const endpoint = `https://login.microsoftonline.com/${encodeURIComponent(this.tenant)}/v2.0/.well-known/openid-configuration`;
98
+ const response = await fetch(endpoint, { signal: AbortSignal.timeout(5000) });
99
+ if (!response.ok)
100
+ throw new Error("Entra discovery failed");
101
+ const metadata = await response.json();
102
+ const issuer = new URL(metadata.issuer);
103
+ const jwksUrl = new URL(metadata.jwks_uri);
104
+ if (issuer.protocol !== "https:" || jwksUrl.protocol !== "https:" || issuer.hostname !== "login.microsoftonline.com" || jwksUrl.hostname !== "login.microsoftonline.com") {
105
+ throw new Error("Unexpected Entra discovery endpoint");
106
+ }
107
+ return { issuer: metadata.issuer, jwks: createRemoteJWKSet(jwksUrl) };
108
+ })().catch((error) => { this.verifier = undefined; throw error; });
109
+ return this.verifier;
110
+ }
111
+ }
112
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../../src/gateway/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
2
+ import type { AuditEntry } from "../types.js";
3
+ import { GatewayStore } from "./state.js";
4
+ export declare class GatewayRuntime {
5
+ readonly store: GatewayStore;
6
+ private readonly hosted;
7
+ private readonly requiredAuditSink?;
8
+ private clients;
9
+ private pending;
10
+ private proxies;
11
+ private proxyScope?;
12
+ constructor(store: GatewayStore, hosted: boolean, requiredAuditSink?: ((entry: AuditEntry) => Promise<void>) | undefined);
13
+ sync(): Promise<void>;
14
+ private scopeProxy;
15
+ private clientFor;
16
+ private available;
17
+ createServer(actor?: string): Server;
18
+ close(): Promise<void>;
19
+ }
20
+ //# sourceMappingURL=runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/gateway/runtime.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAInE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAiE,MAAM,YAAY,CAAC;AAIzG,qBAAa,cAAc;IAMb,QAAQ,CAAC,KAAK,EAAE,YAAY;IAAE,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAW,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC;IAL/G,OAAO,CAAC,OAAO,CAA4D;IAC3E,OAAO,CAAC,OAAO,CAAsC;IACrD,OAAO,CAAC,OAAO,CAA4C;IAC3D,OAAO,CAAC,UAAU,CAAC,CAAc;gBAEZ,KAAK,EAAE,YAAY,EAAmB,MAAM,EAAE,OAAO,EAAmB,iBAAiB,CAAC,GAAE,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,aAAA;IAE/I,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAa3B,OAAO,CAAC,UAAU;YAcJ,SAAS;IA2BvB,OAAO,CAAC,SAAS;IAOjB,YAAY,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;IAgE9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAI7B"}