@carderne/sandbox-runtime 0.0.40

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 (83) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +684 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +163 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/index.d.ts +11 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +9 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/sandbox/generate-seccomp-filter.d.ts +71 -0
  12. package/dist/sandbox/generate-seccomp-filter.d.ts.map +1 -0
  13. package/dist/sandbox/generate-seccomp-filter.js +263 -0
  14. package/dist/sandbox/generate-seccomp-filter.js.map +1 -0
  15. package/dist/sandbox/http-proxy.d.ts +13 -0
  16. package/dist/sandbox/http-proxy.d.ts.map +1 -0
  17. package/dist/sandbox/http-proxy.js +217 -0
  18. package/dist/sandbox/http-proxy.js.map +1 -0
  19. package/dist/sandbox/linux-sandbox-utils.d.ts +158 -0
  20. package/dist/sandbox/linux-sandbox-utils.d.ts.map +1 -0
  21. package/dist/sandbox/linux-sandbox-utils.js +875 -0
  22. package/dist/sandbox/linux-sandbox-utils.js.map +1 -0
  23. package/dist/sandbox/macos-sandbox-utils.d.ts +40 -0
  24. package/dist/sandbox/macos-sandbox-utils.d.ts.map +1 -0
  25. package/dist/sandbox/macos-sandbox-utils.js +623 -0
  26. package/dist/sandbox/macos-sandbox-utils.js.map +1 -0
  27. package/dist/sandbox/sandbox-config.d.ts +288 -0
  28. package/dist/sandbox/sandbox-config.d.ts.map +1 -0
  29. package/dist/sandbox/sandbox-config.js +178 -0
  30. package/dist/sandbox/sandbox-config.js.map +1 -0
  31. package/dist/sandbox/sandbox-manager.d.ts +42 -0
  32. package/dist/sandbox/sandbox-manager.d.ts.map +1 -0
  33. package/dist/sandbox/sandbox-manager.js +786 -0
  34. package/dist/sandbox/sandbox-manager.js.map +1 -0
  35. package/dist/sandbox/sandbox-schemas.d.ts +57 -0
  36. package/dist/sandbox/sandbox-schemas.d.ts.map +1 -0
  37. package/dist/sandbox/sandbox-schemas.js +3 -0
  38. package/dist/sandbox/sandbox-schemas.js.map +1 -0
  39. package/dist/sandbox/sandbox-utils.d.ts +109 -0
  40. package/dist/sandbox/sandbox-utils.d.ts.map +1 -0
  41. package/dist/sandbox/sandbox-utils.js +429 -0
  42. package/dist/sandbox/sandbox-utils.js.map +1 -0
  43. package/dist/sandbox/sandbox-violation-store.d.ts +19 -0
  44. package/dist/sandbox/sandbox-violation-store.d.ts.map +1 -0
  45. package/dist/sandbox/sandbox-violation-store.js +54 -0
  46. package/dist/sandbox/sandbox-violation-store.js.map +1 -0
  47. package/dist/sandbox/socks-proxy.d.ts +13 -0
  48. package/dist/sandbox/socks-proxy.d.ts.map +1 -0
  49. package/dist/sandbox/socks-proxy.js +95 -0
  50. package/dist/sandbox/socks-proxy.js.map +1 -0
  51. package/dist/utils/config-loader.d.ts +11 -0
  52. package/dist/utils/config-loader.d.ts.map +1 -0
  53. package/dist/utils/config-loader.js +60 -0
  54. package/dist/utils/config-loader.js.map +1 -0
  55. package/dist/utils/debug.d.ts +7 -0
  56. package/dist/utils/debug.d.ts.map +1 -0
  57. package/dist/utils/debug.js +25 -0
  58. package/dist/utils/debug.js.map +1 -0
  59. package/dist/utils/platform.d.ts +15 -0
  60. package/dist/utils/platform.d.ts.map +1 -0
  61. package/dist/utils/platform.js +49 -0
  62. package/dist/utils/platform.js.map +1 -0
  63. package/dist/utils/ripgrep.d.ts +20 -0
  64. package/dist/utils/ripgrep.d.ts.map +1 -0
  65. package/dist/utils/ripgrep.js +42 -0
  66. package/dist/utils/ripgrep.js.map +1 -0
  67. package/dist/utils/which.d.ts +9 -0
  68. package/dist/utils/which.d.ts.map +1 -0
  69. package/dist/utils/which.js +25 -0
  70. package/dist/utils/which.js.map +1 -0
  71. package/dist/vendor/seccomp/arm64/apply-seccomp +0 -0
  72. package/dist/vendor/seccomp/arm64/unix-block.bpf +0 -0
  73. package/dist/vendor/seccomp/x64/apply-seccomp +0 -0
  74. package/dist/vendor/seccomp/x64/unix-block.bpf +0 -0
  75. package/dist/vendor/seccomp-src/apply-seccomp.c +98 -0
  76. package/dist/vendor/seccomp-src/seccomp-unix-block.c +97 -0
  77. package/package.json +88 -0
  78. package/vendor/seccomp/arm64/apply-seccomp +0 -0
  79. package/vendor/seccomp/arm64/unix-block.bpf +0 -0
  80. package/vendor/seccomp/x64/apply-seccomp +0 -0
  81. package/vendor/seccomp/x64/unix-block.bpf +0 -0
  82. package/vendor/seccomp-src/apply-seccomp.c +98 -0
  83. package/vendor/seccomp-src/seccomp-unix-block.c +97 -0
@@ -0,0 +1,217 @@
1
+ import { Agent, createServer } from 'node:http';
2
+ import { request as httpRequest } from 'node:http';
3
+ import { request as httpsRequest } from 'node:https';
4
+ import { connect } from 'node:net';
5
+ import { URL } from 'node:url';
6
+ import { logForDebugging } from '../utils/debug.js';
7
+ export function createHttpProxyServer(options) {
8
+ const server = createServer();
9
+ // Handle CONNECT requests for HTTPS traffic
10
+ server.on('connect', async (req, socket) => {
11
+ // Attach error handler immediately to prevent unhandled errors
12
+ socket.on('error', err => {
13
+ logForDebugging(`Client socket error: ${err.message}`, { level: 'error' });
14
+ });
15
+ try {
16
+ const [hostname, portStr] = req.url.split(':');
17
+ const port = portStr === undefined ? undefined : parseInt(portStr, 10);
18
+ if (!hostname || !port) {
19
+ logForDebugging(`Invalid CONNECT request: ${req.url}`, {
20
+ level: 'error',
21
+ });
22
+ socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
23
+ return;
24
+ }
25
+ const allowed = await options.filter(port, hostname, socket);
26
+ if (!allowed) {
27
+ logForDebugging(`Connection blocked to ${hostname}:${port}`, {
28
+ level: 'error',
29
+ });
30
+ socket.end('HTTP/1.1 403 Forbidden\r\n' +
31
+ 'Content-Type: text/plain\r\n' +
32
+ 'X-Proxy-Error: blocked-by-allowlist\r\n' +
33
+ '\r\n' +
34
+ 'Connection blocked by network allowlist');
35
+ return;
36
+ }
37
+ // Check if this host should be routed through a MITM proxy
38
+ const mitmSocketPath = options.getMitmSocketPath?.(hostname);
39
+ if (mitmSocketPath) {
40
+ // Route through MITM proxy via Unix socket
41
+ logForDebugging(`Routing CONNECT ${hostname}:${port} through MITM proxy at ${mitmSocketPath}`);
42
+ const mitmSocket = connect({ path: mitmSocketPath }, () => {
43
+ // Send CONNECT request to the MITM proxy
44
+ mitmSocket.write(`CONNECT ${hostname}:${port} HTTP/1.1\r\n` +
45
+ `Host: ${hostname}:${port}\r\n` +
46
+ '\r\n');
47
+ });
48
+ // Buffer to accumulate the MITM proxy's response
49
+ let responseBuffer = '';
50
+ const onMitmData = (chunk) => {
51
+ responseBuffer += chunk.toString();
52
+ // Check if we've received the full HTTP response headers
53
+ const headerEndIndex = responseBuffer.indexOf('\r\n\r\n');
54
+ if (headerEndIndex !== -1) {
55
+ // Remove data listener, we're done parsing the response
56
+ mitmSocket.removeListener('data', onMitmData);
57
+ // Check if MITM proxy accepted the connection
58
+ const statusLine = responseBuffer.substring(0, responseBuffer.indexOf('\r\n'));
59
+ if (statusLine.includes(' 200 ')) {
60
+ // Connection established, now pipe data between client and MITM
61
+ socket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
62
+ // If there's any data after the headers, write it to the client
63
+ const remainingData = responseBuffer.substring(headerEndIndex + 4);
64
+ if (remainingData.length > 0) {
65
+ socket.write(remainingData);
66
+ }
67
+ mitmSocket.pipe(socket);
68
+ socket.pipe(mitmSocket);
69
+ }
70
+ else {
71
+ logForDebugging(`MITM proxy rejected CONNECT: ${statusLine}`, {
72
+ level: 'error',
73
+ });
74
+ socket.end('HTTP/1.1 502 Bad Gateway\r\n\r\n');
75
+ mitmSocket.destroy();
76
+ }
77
+ }
78
+ };
79
+ mitmSocket.on('data', onMitmData);
80
+ mitmSocket.on('error', err => {
81
+ logForDebugging(`MITM proxy connection failed: ${err.message}`, {
82
+ level: 'error',
83
+ });
84
+ socket.end('HTTP/1.1 502 Bad Gateway\r\n\r\n');
85
+ });
86
+ socket.on('error', err => {
87
+ logForDebugging(`Client socket error: ${err.message}`, {
88
+ level: 'error',
89
+ });
90
+ mitmSocket.destroy();
91
+ });
92
+ socket.on('end', () => mitmSocket.end());
93
+ mitmSocket.on('end', () => socket.end());
94
+ }
95
+ else {
96
+ // Direct connection (original behavior)
97
+ const serverSocket = connect(port, hostname, () => {
98
+ socket.write('HTTP/1.1 200 Connection Established\r\n\r\n');
99
+ serverSocket.pipe(socket);
100
+ socket.pipe(serverSocket);
101
+ });
102
+ serverSocket.on('error', err => {
103
+ logForDebugging(`CONNECT tunnel failed: ${err.message}`, {
104
+ level: 'error',
105
+ });
106
+ socket.end('HTTP/1.1 502 Bad Gateway\r\n\r\n');
107
+ });
108
+ socket.on('error', err => {
109
+ logForDebugging(`Client socket error: ${err.message}`, {
110
+ level: 'error',
111
+ });
112
+ serverSocket.destroy();
113
+ });
114
+ socket.on('end', () => serverSocket.end());
115
+ serverSocket.on('end', () => socket.end());
116
+ }
117
+ }
118
+ catch (err) {
119
+ logForDebugging(`Error handling CONNECT: ${err}`, { level: 'error' });
120
+ socket.end('HTTP/1.1 500 Internal Server Error\r\n\r\n');
121
+ }
122
+ });
123
+ // Handle regular HTTP requests
124
+ server.on('request', async (req, res) => {
125
+ try {
126
+ const url = new URL(req.url);
127
+ const hostname = url.hostname;
128
+ const port = url.port
129
+ ? parseInt(url.port, 10)
130
+ : url.protocol === 'https:'
131
+ ? 443
132
+ : 80;
133
+ const allowed = await options.filter(port, hostname, req.socket);
134
+ if (!allowed) {
135
+ logForDebugging(`HTTP request blocked to ${hostname}:${port}`, {
136
+ level: 'error',
137
+ });
138
+ res.writeHead(403, {
139
+ 'Content-Type': 'text/plain',
140
+ 'X-Proxy-Error': 'blocked-by-allowlist',
141
+ });
142
+ res.end('Connection blocked by network allowlist');
143
+ return;
144
+ }
145
+ // Check if this host should be routed through a MITM proxy
146
+ const mitmSocketPath = options.getMitmSocketPath?.(hostname);
147
+ if (mitmSocketPath) {
148
+ // Route through MITM proxy via Unix socket
149
+ // Use an agent that connects via the Unix socket
150
+ logForDebugging(`Routing HTTP ${req.method} ${hostname}:${port} through MITM proxy at ${mitmSocketPath}`);
151
+ const mitmAgent = new Agent({
152
+ // @ts-expect-error - socketPath is valid but not in types
153
+ socketPath: mitmSocketPath,
154
+ });
155
+ // Send request to MITM proxy with full URL (proxy-style request)
156
+ const proxyReq = httpRequest({
157
+ agent: mitmAgent,
158
+ // For proxy requests, path should be the full URL
159
+ path: req.url,
160
+ method: req.method,
161
+ headers: {
162
+ ...req.headers,
163
+ host: url.host,
164
+ },
165
+ }, proxyRes => {
166
+ res.writeHead(proxyRes.statusCode, proxyRes.headers);
167
+ proxyRes.pipe(res);
168
+ });
169
+ proxyReq.on('error', err => {
170
+ logForDebugging(`MITM proxy request failed: ${err.message}`, {
171
+ level: 'error',
172
+ });
173
+ if (!res.headersSent) {
174
+ res.writeHead(502, { 'Content-Type': 'text/plain' });
175
+ res.end('Bad Gateway');
176
+ }
177
+ });
178
+ req.pipe(proxyReq);
179
+ }
180
+ else {
181
+ // Direct request (original behavior)
182
+ // Choose http or https module
183
+ const requestFn = url.protocol === 'https:' ? httpsRequest : httpRequest;
184
+ const proxyReq = requestFn({
185
+ hostname,
186
+ port,
187
+ path: url.pathname + url.search,
188
+ method: req.method,
189
+ headers: {
190
+ ...req.headers,
191
+ host: url.host,
192
+ },
193
+ }, proxyRes => {
194
+ res.writeHead(proxyRes.statusCode, proxyRes.headers);
195
+ proxyRes.pipe(res);
196
+ });
197
+ proxyReq.on('error', err => {
198
+ logForDebugging(`Proxy request failed: ${err.message}`, {
199
+ level: 'error',
200
+ });
201
+ if (!res.headersSent) {
202
+ res.writeHead(502, { 'Content-Type': 'text/plain' });
203
+ res.end('Bad Gateway');
204
+ }
205
+ });
206
+ req.pipe(proxyReq);
207
+ }
208
+ }
209
+ catch (err) {
210
+ logForDebugging(`Error handling HTTP request: ${err}`, { level: 'error' });
211
+ res.writeHead(500, { 'Content-Type': 'text/plain' });
212
+ res.end('Internal Server Error');
213
+ }
214
+ });
215
+ return server;
216
+ }
217
+ //# sourceMappingURL=http-proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http-proxy.js","sourceRoot":"","sources":["../../src/sandbox/http-proxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,158 @@
1
+ import type { ChildProcess } from 'node:child_process';
2
+ import type { FsReadRestrictionConfig, FsWriteRestrictionConfig } from './sandbox-schemas.js';
3
+ export interface LinuxNetworkBridgeContext {
4
+ httpSocketPath: string;
5
+ socksSocketPath: string;
6
+ httpBridgeProcess: ChildProcess;
7
+ socksBridgeProcess: ChildProcess;
8
+ httpProxyPort: number;
9
+ socksProxyPort: number;
10
+ }
11
+ export interface LinuxSandboxParams {
12
+ command: string;
13
+ needsNetworkRestriction: boolean;
14
+ httpSocketPath?: string;
15
+ socksSocketPath?: string;
16
+ httpProxyPort?: number;
17
+ socksProxyPort?: number;
18
+ readConfig?: FsReadRestrictionConfig;
19
+ writeConfig?: FsWriteRestrictionConfig;
20
+ enableWeakerNestedSandbox?: boolean;
21
+ allowAllUnixSockets?: boolean;
22
+ binShell?: string;
23
+ ripgrepConfig?: {
24
+ command: string;
25
+ args?: string[];
26
+ };
27
+ /** Maximum directory depth to search for dangerous files (default: 3) */
28
+ mandatoryDenySearchDepth?: number;
29
+ /** Allow writes to .git/config files (default: false) */
30
+ allowGitConfig?: boolean;
31
+ /** Custom seccomp binary paths */
32
+ seccompConfig?: {
33
+ bpfPath?: string;
34
+ applyPath?: string;
35
+ };
36
+ /** Abort signal to cancel the ripgrep scan */
37
+ abortSignal?: AbortSignal;
38
+ }
39
+ /**
40
+ * Clean up mount point files created by bwrap for non-existent deny paths.
41
+ *
42
+ * When protecting non-existent deny paths, bwrap creates empty files on the
43
+ * host filesystem as mount points for --ro-bind. These files persist after
44
+ * bwrap exits. This function removes them.
45
+ *
46
+ * This should be called after each sandboxed command completes to prevent
47
+ * ghost dotfiles (e.g. .bashrc, .gitconfig) from appearing in the working
48
+ * directory. It is also called automatically on process exit as a safety net.
49
+ *
50
+ * Safe to call at any time — it only removes files that were tracked during
51
+ * generateFilesystemArgs() and skips any that no longer exist.
52
+ */
53
+ export declare function cleanupBwrapMountPoints(): void;
54
+ /**
55
+ * Detailed status of Linux sandbox dependencies
56
+ */
57
+ export type LinuxDependencyStatus = {
58
+ hasBwrap: boolean;
59
+ hasSocat: boolean;
60
+ hasSeccompBpf: boolean;
61
+ hasSeccompApply: boolean;
62
+ };
63
+ /**
64
+ * Result of checking sandbox dependencies
65
+ */
66
+ export type SandboxDependencyCheck = {
67
+ warnings: string[];
68
+ errors: string[];
69
+ };
70
+ /**
71
+ * Get detailed status of Linux sandbox dependencies
72
+ */
73
+ export declare function getLinuxDependencyStatus(seccompConfig?: {
74
+ bpfPath?: string;
75
+ applyPath?: string;
76
+ }): LinuxDependencyStatus;
77
+ /**
78
+ * Check sandbox dependencies and return structured result
79
+ */
80
+ export declare function checkLinuxDependencies(seccompConfig?: {
81
+ bpfPath?: string;
82
+ applyPath?: string;
83
+ }): SandboxDependencyCheck;
84
+ /**
85
+ * Initialize the Linux network bridge for sandbox networking
86
+ *
87
+ * ARCHITECTURE NOTE:
88
+ * Linux network sandboxing uses bwrap --unshare-net which creates a completely isolated
89
+ * network namespace with NO network access. To enable network access, we:
90
+ *
91
+ * 1. Host side: Run socat bridges that listen on Unix sockets and forward to host proxy servers
92
+ * - HTTP bridge: Unix socket -> host HTTP proxy (for HTTP/HTTPS traffic)
93
+ * - SOCKS bridge: Unix socket -> host SOCKS5 proxy (for SSH/git traffic)
94
+ *
95
+ * 2. Sandbox side: Bind the Unix sockets into the isolated namespace and run socat listeners
96
+ * - HTTP listener on port 3128 -> HTTP Unix socket -> host HTTP proxy
97
+ * - SOCKS listener on port 1080 -> SOCKS Unix socket -> host SOCKS5 proxy
98
+ *
99
+ * 3. Configure environment:
100
+ * - HTTP_PROXY=http://localhost:3128 for HTTP/HTTPS tools
101
+ * - GIT_SSH_COMMAND with socat for SSH through SOCKS5
102
+ *
103
+ * LIMITATION: Unlike macOS sandbox which can enforce domain-based allowlists at the kernel level,
104
+ * Linux's --unshare-net provides only all-or-nothing network isolation. Domain filtering happens
105
+ * at the host proxy level, not the sandbox boundary. This means network restrictions on Linux
106
+ * depend on the proxy's filtering capabilities.
107
+ *
108
+ * DEPENDENCIES: Requires bwrap (bubblewrap) and socat
109
+ */
110
+ export declare function initializeLinuxNetworkBridge(httpProxyPort: number, socksProxyPort: number): Promise<LinuxNetworkBridgeContext>;
111
+ /**
112
+ * Wrap a command with sandbox restrictions on Linux
113
+ *
114
+ * UNIX SOCKET BLOCKING (APPLY-SECCOMP):
115
+ * This implementation uses a custom apply-seccomp binary to block Unix domain socket
116
+ * creation for user commands while allowing network infrastructure:
117
+ *
118
+ * Stage 1: Outer bwrap - Network and filesystem isolation (NO seccomp)
119
+ * - Bubblewrap starts with isolated network namespace (--unshare-net)
120
+ * - Bubblewrap applies PID namespace isolation (--unshare-pid and --proc)
121
+ * - Filesystem restrictions are applied (read-only mounts, bind mounts, etc.)
122
+ * - Socat processes start and connect to Unix socket bridges (can use socket(AF_UNIX, ...))
123
+ *
124
+ * Stage 2: apply-seccomp - Seccomp filter application (ONLY seccomp)
125
+ * - apply-seccomp binary applies seccomp filter via prctl(PR_SET_SECCOMP)
126
+ * - Sets PR_SET_NO_NEW_PRIVS to allow seccomp without root
127
+ * - Execs user command with seccomp active (cannot create new Unix sockets)
128
+ *
129
+ * This solves the conflict between:
130
+ * - Security: Blocking arbitrary Unix socket creation in user commands
131
+ * - Functionality: Network sandboxing requires socat to call socket(AF_UNIX, ...) for bridge connections
132
+ *
133
+ * The seccomp-bpf filter blocks socket(AF_UNIX, ...) syscalls, preventing:
134
+ * - Creating new Unix domain socket file descriptors
135
+ *
136
+ * Security limitations:
137
+ * - Does NOT block operations (bind, connect, sendto, etc.) on inherited Unix socket FDs
138
+ * - Does NOT prevent passing Unix socket FDs via SCM_RIGHTS
139
+ * - For most sandboxing use cases, blocking socket creation is sufficient
140
+ *
141
+ * The filter allows:
142
+ * - All TCP/UDP sockets (AF_INET, AF_INET6) for normal network operations
143
+ * - All other syscalls
144
+ *
145
+ * PLATFORM NOTE:
146
+ * The allowUnixSockets configuration is not path-based on Linux (unlike macOS)
147
+ * because seccomp-bpf cannot inspect user-space memory to read socket paths.
148
+ *
149
+ * Requirements for seccomp filtering:
150
+ * - Pre-built apply-seccomp binaries are included for x64 and ARM64
151
+ * - Pre-generated BPF filters are included for x64 and ARM64
152
+ * - Other architectures are not currently supported (no apply-seccomp binary available)
153
+ * - To use sandboxing without Unix socket blocking on unsupported architectures,
154
+ * set allowAllUnixSockets: true in your configuration
155
+ * Dependencies are checked by checkLinuxDependencies() before enabling the sandbox.
156
+ */
157
+ export declare function wrapCommandWithSandboxLinux(params: LinuxSandboxParams): Promise<string>;
158
+ //# sourceMappingURL=linux-sandbox-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linux-sandbox-utils.d.ts","sourceRoot":"","sources":["../../src/sandbox/linux-sandbox-utils.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAYtD,OAAO,KAAK,EACV,uBAAuB,EACvB,wBAAwB,EACzB,MAAM,sBAAsB,CAAA;AAQ7B,MAAM,WAAW,yBAAyB;IACxC,cAAc,EAAE,MAAM,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,iBAAiB,EAAE,YAAY,CAAA;IAC/B,kBAAkB,EAAE,YAAY,CAAA;IAChC,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAA;IACf,uBAAuB,EAAE,OAAO,CAAA;IAChC,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,UAAU,CAAC,EAAE,uBAAuB,CAAA;IACpC,WAAW,CAAC,EAAE,wBAAwB,CAAA;IACtC,yBAAyB,CAAC,EAAE,OAAO,CAAA;IACnC,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;IACpD,yEAAyE;IACzE,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC,yDAAyD;IACzD,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,kCAAkC;IAClC,aAAa,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACxD,8CAA8C;IAC9C,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B;AAiQD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CA2B9C;AAED;;GAEG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,OAAO,CAAA;IACjB,QAAQ,EAAE,OAAO,CAAA;IACjB,aAAa,EAAE,OAAO,CAAA;IACtB,eAAe,EAAE,OAAO,CAAA;CACzB,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,aAAa,CAAC,EAAE;IACvD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,GAAG,qBAAqB,CAQxB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,aAAa,CAAC,EAAE;IACrD,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,GAAG,sBAAsB,CAezB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,4BAA4B,CAChD,aAAa,EAAE,MAAM,EACrB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,yBAAyB,CAAC,CA2HpC;AAqUD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC,MAAM,CAAC,CAwPjB"}