capgate 0.0.2 → 0.0.3
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 +109 -50
- package/dist/cli.js +17 -5
- package/dist/cli.js.map +1 -1
- package/dist/policy/adapters/bwrap.d.ts.map +1 -1
- package/dist/policy/adapters/bwrap.js +26 -11
- package/dist/policy/adapters/bwrap.js.map +1 -1
- package/dist/policy/adapters/egress.d.ts +24 -0
- package/dist/policy/adapters/egress.d.ts.map +1 -0
- package/dist/policy/adapters/egress.js +194 -0
- package/dist/policy/adapters/egress.js.map +1 -0
- package/dist/policy/index.d.ts +2 -0
- package/dist/policy/index.d.ts.map +1 -1
- package/dist/policy/index.js +1 -0
- package/dist/policy/index.js.map +1 -1
- package/package.json +3 -2
- package/dist/.tsbuildinfo +0 -1
package/README.md
CHANGED
|
@@ -10,11 +10,9 @@ MCP servers today either run with full host trust (Claude Desktop, most wrappers
|
|
|
10
10
|
manifest (JSON) → Capability[] → NormalizedPolicy → adapter (bwrap | docker) → argv + egress + env + assertions
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
It is a compiler
|
|
13
|
+
It is a **sandbox compiler for MCP servers**, not a runtime. It does not execute tools, resolve secrets, or speak MCP on the wire. Its job is to make the sandbox boundary **reviewable in a PR before the first agent call** — what the server is allowed to reach lives in the repo, not in someone's `docker run` muscle memory.
|
|
14
14
|
|
|
15
|
-
**
|
|
16
|
-
|
|
17
|
-
Status: **v0.0.2.** Two adapters (`bwrap`, `docker`) are golden-tested and ready to embed. Grammar may evolve through v0.1 based on design-partner feedback.
|
|
15
|
+
**For platform and security engineers** who can't ship MCP servers under blanket host trust and don't want to hand-write bwrap argv or `docker run` flags per server. **Not for** end-user agent UIs (this isn't a runtime), or for teams who want post-hoc tool-call auditing — that's a different lane (see [How capgate compares](#how-capgate-compares) below for the short version, or [A working map of MCP security tools](https://razukc.github.io/capgate/positioning/) for the full discussion).
|
|
18
16
|
|
|
19
17
|
---
|
|
20
18
|
|
|
@@ -26,11 +24,45 @@ npm install capgate
|
|
|
26
24
|
|
|
27
25
|
Requires Node.js ≥ 18.
|
|
28
26
|
|
|
29
|
-
##
|
|
27
|
+
## 30-second example
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { compile, lowerToDocker } from 'capgate';
|
|
31
|
+
|
|
32
|
+
const docker = lowerToDocker(compile({
|
|
33
|
+
name: 'my-server',
|
|
34
|
+
version: '0.1.0',
|
|
35
|
+
tools: [{ name: 'read_file', capabilities: ['fs:read:/workspace/**'] }],
|
|
36
|
+
}));
|
|
37
|
+
|
|
38
|
+
console.log(docker.argv.join(' '));
|
|
39
|
+
// → --rm --cap-drop ALL --security-opt no-new-privileges --read-only
|
|
40
|
+
// --tmpfs /tmp --network none --volume /workspace:/workspace:ro
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
One capability in, one container policy out. No declared network → `--network none`. Read-only declared → `:ro` mount. No env declared → no env crosses the boundary. The CLI prints the same artifact for `bwrap`.
|
|
30
44
|
|
|
31
|
-
|
|
45
|
+
## CLI
|
|
32
46
|
|
|
33
|
-
|
|
47
|
+
```bash
|
|
48
|
+
capgate compile manifest.json --target bwrap --pretty
|
|
49
|
+
capgate compile manifest.json --target docker --pretty
|
|
50
|
+
capgate compile manifest.json --target egress --egress-target squid --pretty
|
|
51
|
+
capgate compile manifest.json --target egress --egress-target nftables --pretty
|
|
52
|
+
cat manifest.json | capgate compile - --target docker
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
`--target egress` emits a static proxy config for a host-run proxy (`--egress-target squid|nftables`, default `squid`). Exits non-zero on parse errors (3), unknown arguments (2), or `CompilationError` (4). See `capgate --help`.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Worked example: `github` server with PAT
|
|
60
|
+
|
|
61
|
+
The 30-second example is a single tool with a single capability. A realistic MCP server has several tools, several capability kinds, and a threat model that motivates the sandbox in the first place.
|
|
62
|
+
|
|
63
|
+
**The threat.** An MCP `github` server runs with a personal access token in its environment. A tool description carrying adversarial text triggers an outbound request to attacker-controlled infrastructure, exfiltrating the PAT. A default container won't stop this — it inherits the host environment and reaches any host on the internet.
|
|
64
|
+
|
|
65
|
+
**The verdict.** capgate compiles the manifest below into a policy whose egress allowlist contains exactly one entry: `api.github.com:443`. An egress proxy honoring that allowlist refuses any outbound request that isn't api.github.com, blocking PAT exfiltration to a third party. No host env is inherited; only `GITHUB_PERSONAL_ACCESS_TOKEN` is named for the host's secret store to inject at exec time.
|
|
34
66
|
|
|
35
67
|
```ts
|
|
36
68
|
import { compile, lowerToBwrap, lowerToDocker } from 'capgate';
|
|
@@ -64,7 +96,6 @@ const manifest = {
|
|
|
64
96
|
};
|
|
65
97
|
|
|
66
98
|
const policy = compile(manifest);
|
|
67
|
-
|
|
68
99
|
const bwrap = lowerToBwrap(policy);
|
|
69
100
|
const docker = lowerToDocker(policy, { readOnlyRootfs: true });
|
|
70
101
|
|
|
@@ -76,14 +107,14 @@ const docker = lowerToDocker(policy, { readOnlyRootfs: true });
|
|
|
76
107
|
// .notes — audit-friendly diagnostics (drift, edge cases, host decisions)
|
|
77
108
|
```
|
|
78
109
|
|
|
79
|
-
The compiler unions per-tool capabilities into a server-level policy: `apply_patch` widens `/workspace` from `:ro` to `:rw`, and only one env name
|
|
110
|
+
The compiler unions per-tool capabilities into a server-level policy: `apply_patch` widens `/workspace` from `:ro` to `:rw`, and only one env name survives the merge.
|
|
80
111
|
|
|
81
112
|
```jsonc
|
|
82
113
|
// docker.egress === bwrap.egress
|
|
83
114
|
[{ "host": "api.github.com", "port": 443, "blockPrivate": true }]
|
|
84
115
|
```
|
|
85
116
|
|
|
86
|
-
|
|
117
|
+
Adapter `argv` (docker shown in full; bwrap abridged):
|
|
87
118
|
|
|
88
119
|
```
|
|
89
120
|
# docker (full)
|
|
@@ -102,34 +133,62 @@ The `argv` for each adapter (`docker` shown in full; `bwrap` abridged):
|
|
|
102
133
|
--setenv HOME /tmp
|
|
103
134
|
```
|
|
104
135
|
|
|
105
|
-
Note what's *missing* from the docker `argv`: no inherited host env, no host network, no extra capabilities, no writable rootfs.
|
|
136
|
+
Note what's *missing* from the docker `argv`: no inherited host env, no host network, no extra capabilities, no writable rootfs. capgate emits the policy; enforcement is the host's job.
|
|
106
137
|
|
|
107
138
|
Full golden outputs: [`bwrap/github.json`](tests/fixtures/policy/policies/bwrap/github.json), [`docker/github.json`](tests/fixtures/policy/policies/docker/github.json). Worked examples for `filesystem`, `fetch` (egress + assertions), and `puppeteer` (nested-sandbox edge case) live alongside them.
|
|
108
139
|
|
|
109
|
-
|
|
140
|
+
---
|
|
110
141
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
capgate
|
|
114
|
-
|
|
115
|
-
|
|
142
|
+
## What's stable, what's evolving
|
|
143
|
+
|
|
144
|
+
`v0.0.x` is published for adopters who want to pin against capgate today. Stability commitments:
|
|
145
|
+
|
|
146
|
+
| Surface | Status in v0.0.x |
|
|
147
|
+
|---|---|
|
|
148
|
+
| Capability string grammar (`fs`, `net`, `env`, `assert` kinds) | **Stable.** String form will not change; new refinements are additive. |
|
|
149
|
+
| Adapter output shape (`argv`, `egress`, `envInjections`, `assertions`, `notes`) | **Stable.** Fields are additive; existing fields keep their semantics. |
|
|
150
|
+
| `compile()` and `lowerToBwrap` / `lowerToDocker` exports | **Stable.** |
|
|
151
|
+
| `lowerToEgress(policy, { target })` (`squid` / `nftables`) | **Usable.** Artifact shape (`config`, `filename`, `unenforceable`, `notes`) is additive; more `EgressTarget` values land without breaking existing ones. |
|
|
152
|
+
| `exec`, `ipc`, `clock` capability kinds | **Usable.** May gain refinements (like `exec:?nestedSandbox=true` did); existing forms keep working. |
|
|
153
|
+
| Adapter option objects (e.g. `lowerToDocker(policy, { readOnlyRootfs })`) | **Evolving.** Will expand in v0.1 as more adapters land. |
|
|
154
|
+
| `assert:` validator hook | **Metadata-only in v0.0.x.** Runtime hook lands in v0.2. |
|
|
155
|
+
|
|
156
|
+
Pin a minor range against `v0.0.x` for production review pipelines. Grammar additions land in `v0.1`; existing strings keep parsing.
|
|
116
157
|
|
|
117
|
-
|
|
158
|
+
## How capgate compares
|
|
159
|
+
|
|
160
|
+
MCP-server security splits across three lanes. capgate is in the static-technical lane. The other two aren't competitors — most teams running MCP servers in production end up wanting more than one.
|
|
161
|
+
|
|
162
|
+
| Lane | What it does | When you'd use it |
|
|
163
|
+
|---|---|---|
|
|
164
|
+
| **Static technical** (capgate) | Reads a manifest, emits sandbox argv + egress allowlist. Static artifact, no runtime. | You want the sandbox policy reviewable in PR before the server ever runs. |
|
|
165
|
+
| **Static governance** | Reads a manifest, emits a compliance report against a threat catalog or policy framework. | You want a procedural sign-off on a server before it's adopted. |
|
|
166
|
+
| **Dynamic attestation** | Logs and cryptographically signs each tool call at runtime. | You need a tamper-evident record of what the server actually did. |
|
|
167
|
+
|
|
168
|
+
Two adjacent concerns are *not* on this map: per-request authentication (gateways / OAuth — about *who* is calling) and runtime threat detection (pattern-watching, anomaly alerts — about flagging in real time). Both are real categories; both are different conversations. See [A working map of MCP security tools](https://razukc.github.io/capgate/positioning/) for the full discussion.
|
|
169
|
+
|
|
170
|
+
If you arrived here from a comparison post and you wanted dynamic attestation or static governance, capgate isn't that — but the artifact it emits can be the input to either.
|
|
118
171
|
|
|
119
172
|
---
|
|
120
173
|
|
|
121
|
-
##
|
|
174
|
+
## Validated servers
|
|
122
175
|
|
|
123
|
-
|
|
124
|
-
- Capability grammar covering `fs`, `net`, `exec`, `env`, `ipc`, `clock`, `assert`.
|
|
125
|
-
- Lowering to three targets: `bwrap` (Linux namespace sandbox), egress-proxy rules (net allowlist), Worker `resourceLimits` (in-process JS isolation).
|
|
126
|
-
- Golden-file tests from real MCP server manifests.
|
|
176
|
+
Before committing to the capability-grammar abstraction, we ran a [go/no-go exercise](tests/fixtures/policy/GO_NO_GO.md) against 10 real MCP servers. The full inventory (capability strings, source links, lowering notes) lives in [`GO_NO_GO.md`](tests/fixtures/policy/GO_NO_GO.md); the summary:
|
|
127
177
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
178
|
+
| Server | Capabilities (excerpt) | Status | Manifest | bwrap | docker |
|
|
179
|
+
|---|---|---|---|---|---|
|
|
180
|
+
| [filesystem](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) | `fs:read,write:<roots>` | mechanical | [filesystem.json](tests/fixtures/policy/manifests/filesystem.json) | [✓](tests/fixtures/policy/policies/bwrap/filesystem.json) | [✓](tests/fixtures/policy/policies/docker/filesystem.json) |
|
|
181
|
+
| [fetch](https://github.com/modelcontextprotocol/servers/tree/main/src/fetch) | `net:connect:*`, `assert:fetch.block_rfc1918` | mechanical (assert) | [fetch.json](tests/fixtures/policy/manifests/fetch.json) | [✓](tests/fixtures/policy/policies/bwrap/fetch.json) | [✓](tests/fixtures/policy/policies/docker/fetch.json) |
|
|
182
|
+
| [git](https://github.com/modelcontextprotocol/servers/tree/main/src/git) | `fs:read,write:<repo>`, `exec:spawn:git`, `net:connect:*` | mechanical | — | — | — |
|
|
183
|
+
| [memory](https://github.com/modelcontextprotocol/servers/tree/main/src/memory) | `fs:read,write:$MEMORY_FILE_PATH` | mechanical | — | — | — |
|
|
184
|
+
| [time](https://github.com/modelcontextprotocol/servers/tree/main/src/time) | `fs:read:/usr/share/zoneinfo`, `clock:tzdata` | mechanical | — | — | — |
|
|
185
|
+
| [github](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/github) | `net:connect:api.github.com:443`, `env:inject:GITHUB_PERSONAL_ACCESS_TOKEN` | mechanical | [github.json](tests/fixtures/policy/manifests/github.json) | [✓](tests/fixtures/policy/policies/bwrap/github.json) | [✓](tests/fixtures/policy/policies/docker/github.json) |
|
|
186
|
+
| [postgres](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/postgres) | `net:connect:<db>:<port>`, `assert:postgres.read_only_txn` | mechanical (assert) | — | — | — |
|
|
187
|
+
| [sqlite](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/sqlite) | `fs:read,write:<db_path>` | mechanical | — | — | — |
|
|
188
|
+
| [brave-search](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/brave-search) | `net:connect:api.search.brave.com:443`, `env:inject:BRAVE_API_KEY` | mechanical | — | — | — |
|
|
189
|
+
| [puppeteer](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/puppeteer) | `exec:spawn:chromium?nestedSandbox=true`, `ipc:connect:x11` | nested-sandbox | [puppeteer.json](tests/fixtures/policy/manifests/puppeteer.json) | [✓](tests/fixtures/policy/policies/bwrap/puppeteer.json) | [✓](tests/fixtures/policy/policies/docker/puppeteer.json) |
|
|
190
|
+
|
|
191
|
+
Four of the ten ship as golden-file fixtures for both adapters; the rest follow one of the four shapes and are tracked in `GO_NO_GO.md` for the next grammar review. **MCP server author?** If your server isn't listed and you'd like a fixture review, [open an issue](https://github.com/razukc/capgate/issues/new) with a link to the manifest.
|
|
133
192
|
|
|
134
193
|
## Capability grammar
|
|
135
194
|
|
|
@@ -150,6 +209,19 @@ assert:postgres.read_only_txn:"all queries run in READ ONLY TRANSACTION"
|
|
|
150
209
|
|
|
151
210
|
The grammar rejects ambiguity (relative paths, bad ports, non-UPPER_SNAKE env vars) at parse time — fail-closed, always.
|
|
152
211
|
|
|
212
|
+
## Scope for v0.1
|
|
213
|
+
|
|
214
|
+
**In scope:**
|
|
215
|
+
- Capability grammar covering `fs`, `net`, `exec`, `env`, `ipc`, `clock`, `assert`.
|
|
216
|
+
- Lowering to `bwrap` (Linux namespace sandbox), `docker` (`docker run` argv), and `egress` (proxy config — `squid` / `nftables`, **shipped**). Worker `resourceLimits` (in-process JS isolation) is the next target.
|
|
217
|
+
- Golden-file tests from real MCP server manifests.
|
|
218
|
+
|
|
219
|
+
**Out of scope (deferred):**
|
|
220
|
+
- Firecracker / microVM adapter — needed for production but not for proving the abstraction.
|
|
221
|
+
- E2B / Daytona / Blaxel adapters — API stability varies; wait for a design partner.
|
|
222
|
+
- seccomp-bpf syscall filters — requires a separate IR; out of the capability model.
|
|
223
|
+
- MCP client/server implementation — this library consumes manifests, it does not speak MCP on the wire.
|
|
224
|
+
|
|
153
225
|
## Design notes
|
|
154
226
|
|
|
155
227
|
### Why capabilities are typed and discriminated
|
|
@@ -168,6 +240,12 @@ JSON-object capabilities are verbose and bury the kind under keys. The string fo
|
|
|
168
240
|
|
|
169
241
|
Chromium carries its own sandbox that fights namespace isolation. Every production sandbox tool has a special case for this. Rather than a new capability kind, `nestedSandbox=true` is a refinement on an existing `exec:` capability — the adapter sees it during lowering and emits a different bwrap profile (user/pid/ipc namespaces kept for inner-sandbox compatibility). The IR stays small; the edge case is explicit and documented.
|
|
170
242
|
|
|
243
|
+
### Why egress lowers to a proxy config, not a proxy
|
|
244
|
+
|
|
245
|
+
`egress[]` is emitted by the bwrap and docker adapters but enforced by neither — the host is told to wire a proxy. The neither-adapter-can-actually-do-net property is real: bwrap's `--unshare-net` is all-or-nothing (it always isolates now; see the net posture in `bwrap.ts`), and Docker's default bridge NATs but doesn't allowlist. Closing that gap by *running* a proxy would turn capgate into a gateway and drag a long-running, root-adjacent process into a library whose whole value is being a static compiler.
|
|
246
|
+
|
|
247
|
+
The move keeps capgate a compiler: a third lowering target, `lowerToEgress(policy, { target })`, compiles `policy.net` into a config blob for a proxy the host *already runs* — `squid` (allowlist by hostname via CONNECT, no TLS interception) and `nftables` (allowlist by IP+port in-kernel, bypass-proof, plus the `blockPrivate` drops) ship today. Both configs are fail-closed: squid ends in an unconditional `http_access deny all`, nftables defaults to `policy drop`, and an empty `policy.net` compiles to a deny-ALL config. The artifact carries an `unenforceable[]` field naming every declared rule the chosen target *cannot* honor (e.g. nftables can't express `api.github.com` — it filters IPs, not rotating hostnames), so "portable" stays honest: it compiles everywhere and tells you what each backend loses. Envoy/Cloudflare/microVM targets are later entries behind the same `EgressTarget` switch; the IR does not change. This keeps Docker MCP Gateway and Cloudflare as *targets you compile to*, not competitors — the manifest stays the single reviewable source of truth, and enforcement is borrowed, not built.
|
|
248
|
+
|
|
171
249
|
## Non-goals that matter
|
|
172
250
|
|
|
173
251
|
- **The compiler does not decide trust.** Capability declarations come from the manifest; the compiler does not infer them from tool descriptions. Inference belongs in a separate auditing tool. A manifest that under-declares is a bug in the manifest.
|
|
@@ -182,25 +260,6 @@ Chromium carries its own sandbox that fights namespace isolation. Every producti
|
|
|
182
260
|
|
|
183
261
|
All compilation errors are fatal. There is no warning mode.
|
|
184
262
|
|
|
185
|
-
## Validated servers
|
|
186
|
-
|
|
187
|
-
Before committing to the capability-grammar abstraction, we ran a [go/no-go exercise](tests/fixtures/policy/GO_NO_GO.md) against 10 real MCP servers. The full inventory (capability strings, source links, lowering notes) lives in [`GO_NO_GO.md`](tests/fixtures/policy/GO_NO_GO.md); the summary:
|
|
188
|
-
|
|
189
|
-
| Server | Capabilities (excerpt) | Status | Manifest | bwrap | docker |
|
|
190
|
-
|---|---|---|---|---|---|
|
|
191
|
-
| [filesystem](https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem) | `fs:read,write:<roots>` | mechanical | [filesystem.json](tests/fixtures/policy/manifests/filesystem.json) | [✓](tests/fixtures/policy/policies/bwrap/filesystem.json) | [✓](tests/fixtures/policy/policies/docker/filesystem.json) |
|
|
192
|
-
| [fetch](https://github.com/modelcontextprotocol/servers/tree/main/src/fetch) | `net:connect:*`, `assert:fetch.block_rfc1918` | mechanical (assert) | [fetch.json](tests/fixtures/policy/manifests/fetch.json) | [✓](tests/fixtures/policy/policies/bwrap/fetch.json) | [✓](tests/fixtures/policy/policies/docker/fetch.json) |
|
|
193
|
-
| [git](https://github.com/modelcontextprotocol/servers/tree/main/src/git) | `fs:read,write:<repo>`, `exec:spawn:git`, `net:connect:*` | mechanical | — | — | — |
|
|
194
|
-
| [memory](https://github.com/modelcontextprotocol/servers/tree/main/src/memory) | `fs:read,write:$MEMORY_FILE_PATH` | mechanical | — | — | — |
|
|
195
|
-
| [time](https://github.com/modelcontextprotocol/servers/tree/main/src/time) | `fs:read:/usr/share/zoneinfo`, `clock:tzdata` | mechanical | — | — | — |
|
|
196
|
-
| [github](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/github) | `net:connect:api.github.com:443`, `env:inject:GITHUB_PERSONAL_ACCESS_TOKEN` | mechanical | — | — | — |
|
|
197
|
-
| [postgres](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/postgres) | `net:connect:<db>:<port>`, `assert:postgres.read_only_txn` | mechanical (assert) | — | — | — |
|
|
198
|
-
| [sqlite](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/sqlite) | `fs:read,write:<db_path>` | mechanical | — | — | — |
|
|
199
|
-
| [brave-search](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/brave-search) | `net:connect:api.search.brave.com:443`, `env:inject:BRAVE_API_KEY` | mechanical | — | — | — |
|
|
200
|
-
| [puppeteer](https://github.com/modelcontextprotocol/servers-archived/tree/main/src/puppeteer) | `exec:spawn:chromium?nestedSandbox=true`, `ipc:connect:x11` | nested-sandbox | [puppeteer.json](tests/fixtures/policy/manifests/puppeteer.json) | [✓](tests/fixtures/policy/policies/bwrap/puppeteer.json) | [✓](tests/fixtures/policy/policies/docker/puppeteer.json) |
|
|
201
|
-
|
|
202
|
-
Three of the ten ship as golden-file fixtures for both adapters (representatives of the distinct shapes — pure-fs, net+assert, nested-sandbox); the remaining seven follow the filesystem or github shape and are tracked in `GO_NO_GO.md` for the next grammar review. **MCP server author?** If your server isn't listed and you'd like a fixture review, [open an issue](https://github.com/razukc/capgate/issues/new) with a link to the manifest.
|
|
203
|
-
|
|
204
263
|
## Test strategy
|
|
205
264
|
|
|
206
265
|
Golden files. One fixture manifest → one expected policy per adapter. Every PR that changes grammar, IR, or an adapter must update the golden files in the same commit. Reviewers read the diff. This is the primary correctness mechanism; unit tests on the grammar are secondary.
|
|
@@ -212,16 +271,16 @@ npm run test:update-goldens # regenerate golden files after intentional change
|
|
|
212
271
|
|
|
213
272
|
## Open questions before v0.1
|
|
214
273
|
|
|
215
|
-
1. **Egress proxy choice.** mitmproxy (great DX, slow, not prod-grade) vs nftables (hard to author, prod-grade, Linux-only) vs Envoy (prod-grade, ops-heavy).
|
|
274
|
+
1. **Egress proxy choice.** mitmproxy (great DX, slow, not prod-grade) vs nftables (hard to author, prod-grade, Linux-only) vs Envoy (prod-grade, ops-heavy). Direction settled: capgate stays a compiler and emits a config blob per target rather than running a proxy — see [Why egress lowers to a proxy config, not a proxy](#why-egress-lowers-to-a-proxy-config-not-a-proxy). Both `squid` and `nftables` now ship as reference bindings (they cover complementary cases — hostname-CONNECT vs in-kernel IP allowlist). Remaining sub-question is whether a dev-only mitmproxy emitter is worth carrying.
|
|
216
275
|
2. **Path glob semantics.** bwrap binds directories, not globs. A `fs:read:/workspace/**` capability lowers to `--ro-bind /workspace /workspace`, which is a *superset* of the declared scope. Runtime enforcement of globs is an MCP-server concern.
|
|
217
276
|
3. **Server-level vs tool-level capabilities.** v0.0 unions them. Finer-grained per-tool sandboxing (one sandbox per invocation) is possible but expensive — deferred until a user asks for it.
|
|
218
277
|
|
|
219
278
|
## Contributing
|
|
220
279
|
|
|
221
|
-
Design-partner stage. **Actively seeking feedback from teams reviewing MCP servers today** — please see [issue #1](https://github.com/razukc/capgate/issues/1) and share how your review process works (as much or as little as you can publicly). That is the single most valuable contribution right now.
|
|
222
|
-
|
|
223
280
|
If you have a concrete manifest + unexpected compiler output, file an issue with both. See [CONTRIBUTING.md](CONTRIBUTING.md) for what else is useful.
|
|
224
281
|
|
|
282
|
+
Design-partner stage: if you're already reviewing MCP servers in production and willing to share how your review process works, [issue #1](https://github.com/razukc/capgate/issues/1) has a question for you.
|
|
283
|
+
|
|
225
284
|
## Security
|
|
226
285
|
|
|
227
286
|
capgate compiles declarations into sandbox policies downstream hosts trust — bugs here can silently over-grant. Please report privately per [SECURITY.md](SECURITY.md).
|
package/dist/cli.js
CHANGED
|
@@ -10,12 +10,13 @@
|
|
|
10
10
|
// This is deliberately minimal. Anything fancier (watch mode, multi-target,
|
|
11
11
|
// YAML output) belongs behind a feature flag, not here.
|
|
12
12
|
import { readFileSync } from 'node:fs';
|
|
13
|
-
import { compile, lowerToBwrap, lowerToDocker, CompilationError } from './policy/index.js';
|
|
13
|
+
import { compile, lowerToBwrap, lowerToDocker, lowerToEgress, CompilationError } from './policy/index.js';
|
|
14
14
|
function parseArgs(argv) {
|
|
15
15
|
const args = {
|
|
16
16
|
command: undefined,
|
|
17
17
|
input: undefined,
|
|
18
18
|
target: 'bwrap',
|
|
19
|
+
egressTarget: 'squid',
|
|
19
20
|
pretty: false,
|
|
20
21
|
help: false,
|
|
21
22
|
};
|
|
@@ -28,6 +29,8 @@ function parseArgs(argv) {
|
|
|
28
29
|
args.pretty = true;
|
|
29
30
|
else if (a === '--target')
|
|
30
31
|
args.target = rest[++i];
|
|
32
|
+
else if (a === '--egress-target')
|
|
33
|
+
args.egressTarget = rest[++i];
|
|
31
34
|
else if (!args.command)
|
|
32
35
|
args.command = a;
|
|
33
36
|
else if (!args.input)
|
|
@@ -41,13 +44,15 @@ Usage:
|
|
|
41
44
|
capgate compile <manifest.json|-> [--target bwrap] [--pretty]
|
|
42
45
|
|
|
43
46
|
Options:
|
|
44
|
-
--target <name>
|
|
45
|
-
--
|
|
46
|
-
|
|
47
|
+
--target <name> Adapter to lower to. Default: bwrap. Supported: bwrap, docker, egress.
|
|
48
|
+
--egress-target <name> Egress backend when --target egress. Default: squid. Supported: squid, nftables.
|
|
49
|
+
--pretty Indent JSON output with 2 spaces.
|
|
50
|
+
-h, --help Show this message.
|
|
47
51
|
|
|
48
52
|
Examples:
|
|
49
53
|
capgate compile manifests/filesystem.json --pretty
|
|
50
54
|
cat manifest.json | capgate compile - --target bwrap
|
|
55
|
+
capgate compile manifests/github.json --target egress --egress-target nftables --pretty
|
|
51
56
|
`;
|
|
52
57
|
function readInput(path) {
|
|
53
58
|
if (path === '-')
|
|
@@ -86,8 +91,15 @@ function main() {
|
|
|
86
91
|
case 'docker':
|
|
87
92
|
output = lowerToDocker(policy);
|
|
88
93
|
break;
|
|
94
|
+
case 'egress':
|
|
95
|
+
if (args.egressTarget !== 'squid' && args.egressTarget !== 'nftables') {
|
|
96
|
+
process.stderr.write(`capgate: unsupported --egress-target "${args.egressTarget}" (supported: squid, nftables)\n`);
|
|
97
|
+
process.exit(2);
|
|
98
|
+
}
|
|
99
|
+
output = lowerToEgress(policy, { target: args.egressTarget });
|
|
100
|
+
break;
|
|
89
101
|
default:
|
|
90
|
-
process.stderr.write(`capgate: unsupported --target "${args.target}" (supported: bwrap, docker)\n`);
|
|
102
|
+
process.stderr.write(`capgate: unsupported --target "${args.target}" (supported: bwrap, docker, egress)\n`);
|
|
91
103
|
process.exit(2);
|
|
92
104
|
}
|
|
93
105
|
const indent = args.pretty ? 2 : 0;
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,wDAAwD;AACxD,EAAE;AACF,SAAS;AACT,gEAAgE;AAChE,EAAE;AACF,0EAA0E;AAC1E,2EAA2E;AAC3E,EAAE;AACF,4EAA4E;AAC5E,wDAAwD;AAExD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bwrap.d.ts","sourceRoot":"","sources":["../../../src/policy/adapters/bwrap.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bwrap.d.ts","sourceRoot":"","sources":["../../../src/policy/adapters/bwrap.ts"],"names":[],"mappings":"AA4BA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,WAAW,aAAa;IAC5B,0FAA0F;IAC1F,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,oDAAoD;IACpD,MAAM,EAAE,UAAU,EAAE,CAAC;IACrB,+EAA+E;IAC/E,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,oEAAoE;IACpE,UAAU,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAClD,6DAA6D;IAC7D,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,+EAA+E;IAC/E,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IACxB,yEAAyE;IACzE,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAID,wBAAgB,YAAY,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,GAAE,YAAiB,GAAG,aAAa,CAwH7F"}
|
|
@@ -10,6 +10,18 @@
|
|
|
10
10
|
// - seccomp syscall filters → out of scope for v0.1
|
|
11
11
|
// - secret value resolution → caller pulls from secret store
|
|
12
12
|
//
|
|
13
|
+
// Net posture (fail-closed). bwrap's --unshare-net is all-or-nothing: an
|
|
14
|
+
// unprivileged user namespace cannot mint veth pairs or routes, so bwrap can
|
|
15
|
+
// only fully isolate the net namespace or fully share the host's. Selective
|
|
16
|
+
// egress is impossible inside bwrap alone. Therefore this adapter ALWAYS emits
|
|
17
|
+
// --unshare-net — even when egress is declared — and NEVER shares the host
|
|
18
|
+
// netns. A declared net capability does not relax isolation; it only records an
|
|
19
|
+
// EgressRule[] that a privileged broker must honor by launching the bwrap
|
|
20
|
+
// process inside a pre-created, egress-constrained network namespace. If no
|
|
21
|
+
// such broker exists, the sandbox simply has no network: deny-by-default holds.
|
|
22
|
+
// (The prior behavior — sharing host netns whenever net>0 — was a silent
|
|
23
|
+
// privilege escalation that read as a constraint; it is refused by design.)
|
|
24
|
+
//
|
|
13
25
|
// This adapter emits a BwrapArtifact: argv for bwrap itself plus companion
|
|
14
26
|
// data the host must honor. The host decides how to wire EgressRule — mitmproxy,
|
|
15
27
|
// nftables, Envoy; the adapter stays policy-layer only.
|
|
@@ -20,14 +32,14 @@ export function lowerToBwrap(policy, opts = {}) {
|
|
|
20
32
|
const systemMounts = opts.systemMounts ?? DEFAULT_SYSTEM_MOUNTS;
|
|
21
33
|
const exposeDev = opts.exposeDev ?? policy.nestedSandbox;
|
|
22
34
|
// ---------- base namespaces ----------
|
|
23
|
-
// We build the unshare set explicitly instead of using --unshare-all so
|
|
24
|
-
//
|
|
25
|
-
//
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
35
|
+
// We build the unshare set explicitly instead of using --unshare-all so each
|
|
36
|
+
// namespace is an auditable decision point. Net is ALWAYS unshared: bwrap
|
|
37
|
+
// cannot do selective egress (see header), so sharing the host netns would be
|
|
38
|
+
// a silent grant of full host network access. Declared egress is carried in
|
|
39
|
+
// egress[] for an external netns broker to enforce, never by relaxing this.
|
|
40
|
+
// nestedSandbox additionally keeps user/pid/ipc for inner sandboxes
|
|
41
|
+
// (Chromium, QEMU) that re-namespace themselves.
|
|
42
|
+
argv.push('--unshare-uts', '--unshare-cgroup-try', '--unshare-net');
|
|
31
43
|
if (!policy.nestedSandbox) {
|
|
32
44
|
argv.push('--unshare-user-try', '--unshare-pid', '--unshare-ipc');
|
|
33
45
|
}
|
|
@@ -106,15 +118,18 @@ export function lowerToBwrap(policy, opts = {}) {
|
|
|
106
118
|
argv.push('--setenv', 'HOME', '/tmp');
|
|
107
119
|
// Values for envInjections are injected by the caller via --setenv at exec time.
|
|
108
120
|
// ---------- net ----------
|
|
109
|
-
//
|
|
110
|
-
//
|
|
121
|
+
// The net namespace is already unshared above, so the sandbox starts with NO
|
|
122
|
+
// network (loopback only). bwrap cannot open a constrained hole, so declared
|
|
123
|
+
// egress is NOT enforced here: we emit EgressRule[] for a privileged broker
|
|
124
|
+
// that runs this bwrap process inside a pre-created, egress-aware netns. We
|
|
125
|
+
// emit rules even for the empty case so a deny-all broker is a valid host.
|
|
111
126
|
const egress = policy.net.map((n) => ({
|
|
112
127
|
host: n.host,
|
|
113
128
|
port: n.port,
|
|
114
129
|
blockPrivate: n.blockPrivate,
|
|
115
130
|
}));
|
|
116
131
|
if (policy.net.length > 0) {
|
|
117
|
-
notes.push(`net: ${policy.net.length} endpoint(s) declared — host MUST
|
|
132
|
+
notes.push(`net: ${policy.net.length} endpoint(s) declared but NOT enforced by bwrap alone — bwrap always unshares the net namespace (no host network). To grant egress, a privileged broker MUST launch bwrap inside a pre-created network namespace whose egress honors egress[]. Absent that broker the sandbox has no network. Sharing the host netns is refused by design.`);
|
|
118
133
|
}
|
|
119
134
|
return {
|
|
120
135
|
argv,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bwrap.js","sourceRoot":"","sources":["../../../src/policy/adapters/bwrap.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,EAAE;AACF,oEAAoE;AACpE,kDAAkD;AAClD,sDAAsD;AACtD,uDAAuD;AACvD,EAAE;AACF,sBAAsB;AACtB,wEAAwE;AACxE,+DAA+D;AAC/D,wEAAwE;AACxE,EAAE;AACF,2EAA2E;AAC3E,iFAAiF;AACjF,wDAAwD;AA8BxD,MAAM,qBAAqB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,sBAAsB,CAAC,CAAC;AAE9G,MAAM,UAAU,YAAY,CAAC,MAAwB,EAAE,OAAqB,EAAE;IAC5E,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,qBAAqB,CAAC;IAChE,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,aAAa,CAAC;IAEzD,wCAAwC;IACxC,
|
|
1
|
+
{"version":3,"file":"bwrap.js","sourceRoot":"","sources":["../../../src/policy/adapters/bwrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { NormalizedPolicy } from '../ir.js';
|
|
2
|
+
import type { EgressRule } from './bwrap.js';
|
|
3
|
+
export type EgressTarget = 'squid' | 'nftables';
|
|
4
|
+
export interface EgressArtifact {
|
|
5
|
+
/** Which backend this config targets. */
|
|
6
|
+
target: EgressTarget;
|
|
7
|
+
/** The config file contents, ready to write to disk and load into the proxy. */
|
|
8
|
+
config: string;
|
|
9
|
+
/** Suggested filename, e.g. "capgate-egress.squid.conf". */
|
|
10
|
+
filename: string;
|
|
11
|
+
/** Declared rules this target CANNOT honor — surfaced, never silently dropped. */
|
|
12
|
+
unenforceable: {
|
|
13
|
+
rule: EgressRule;
|
|
14
|
+
reason: string;
|
|
15
|
+
}[];
|
|
16
|
+
/** Human-readable diagnostics for audit logs / PR review. */
|
|
17
|
+
notes: string[];
|
|
18
|
+
}
|
|
19
|
+
export interface EgressOptions {
|
|
20
|
+
/** Required — no default. The caller must pick the backend the host runs. */
|
|
21
|
+
target: EgressTarget;
|
|
22
|
+
}
|
|
23
|
+
export declare function lowerToEgress(policy: NormalizedPolicy, opts: EgressOptions): EgressArtifact;
|
|
24
|
+
//# sourceMappingURL=egress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"egress.d.ts","sourceRoot":"","sources":["../../../src/policy/adapters/egress.ts"],"names":[],"mappings":"AA0BA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,UAAU,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,MAAM,EAAE,YAAY,CAAC;IACrB,gFAAgF;IAChF,MAAM,EAAE,MAAM,CAAC;IACf,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAC;IACjB,kFAAkF;IAClF,aAAa,EAAE;QAAE,IAAI,EAAE,UAAU,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACtD,6DAA6D;IAC7D,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,6EAA6E;IAC7E,MAAM,EAAE,YAAY,CAAC;CACtB;AAQD,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,aAAa,GAAG,cAAc,CAe3F"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// Egress adapter: NormalizedPolicy → static proxy config blob.
|
|
2
|
+
//
|
|
3
|
+
// This is the third lowering lane (see README "Why egress will lower to a proxy
|
|
4
|
+
// config, not a proxy"). bwrap and docker emit argv; this adapter emits a config
|
|
5
|
+
// *file* for a proxy the HOST already runs. Same compiler-not-runtime contract:
|
|
6
|
+
// capgate compiles policy.net (+ blockPrivate) into a config, and the host wires
|
|
7
|
+
// it into squid / nftables. We never open a socket.
|
|
8
|
+
//
|
|
9
|
+
// What this lane handles:
|
|
10
|
+
// - squid: allowlist by hostname via CONNECT (no TLS interception)
|
|
11
|
+
// - nftables: allowlist by IP+port in-kernel (bypass-proof) + blockPrivate drops
|
|
12
|
+
// - the blockPrivate RFC1918/loopback deny that bwrap/docker can only assert
|
|
13
|
+
//
|
|
14
|
+
// What this lane does NOT handle:
|
|
15
|
+
// - RUNNING the proxy — the host owns the long-lived process; we emit a file.
|
|
16
|
+
// - DNS resolution — nftables filters IPs, not names; hostname rules that it
|
|
17
|
+
// cannot express are surfaced in unenforceable[], never silently dropped.
|
|
18
|
+
// - TLS interception / secret inspection — out of scope for v0.1. squid here
|
|
19
|
+
// is CONNECT-allowlist only; it sees SNI/host, never plaintext.
|
|
20
|
+
//
|
|
21
|
+
// Net posture (fail-closed). Every emitted config terminates or defaults in
|
|
22
|
+
// deny/drop: squid ends in an unconditional `http_access deny all`, nftables
|
|
23
|
+
// sets `policy drop`. No code path produces an allow-all config. An empty
|
|
24
|
+
// policy.net compiles to a deny-ALL config — mirroring how bwrap/docker treat
|
|
25
|
+
// net==0 (`--unshare-net` / `--network none`): declaring nothing grants nothing.
|
|
26
|
+
// Private-range destinations the blockPrivate flag must deny. Kept as two lists
|
|
27
|
+
// because squid and nftables spell them differently (squid uses one `dst` acl
|
|
28
|
+
// covering both families; nftables splits ip / ip6 daddr sets).
|
|
29
|
+
const PRIVATE_V4 = ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16', '127.0.0.0/8', '169.254.0.0/16'];
|
|
30
|
+
const PRIVATE_V6 = ['::1/128', 'fc00::/7', 'fe80::/10'];
|
|
31
|
+
export function lowerToEgress(policy, opts) {
|
|
32
|
+
const rules = policy.net.map((n) => ({
|
|
33
|
+
host: n.host,
|
|
34
|
+
port: n.port,
|
|
35
|
+
blockPrivate: n.blockPrivate,
|
|
36
|
+
}));
|
|
37
|
+
// blockPrivate is OR-ed across the policy: if ANY declared rule asks for the
|
|
38
|
+
// private-range block, the whole config enforces it (deny wins, so a single
|
|
39
|
+
// rule cannot opt the proxy out of a sibling rule's blockPrivate).
|
|
40
|
+
const blockPrivate = rules.some((r) => r.blockPrivate);
|
|
41
|
+
if (opts.target === 'squid')
|
|
42
|
+
return lowerToSquid(rules, blockPrivate);
|
|
43
|
+
if (opts.target === 'nftables')
|
|
44
|
+
return lowerToNftables(rules, blockPrivate);
|
|
45
|
+
// Fail-closed on an unknown target rather than emitting a permissive default.
|
|
46
|
+
throw new Error(`[EGRESS_UNKNOWN_TARGET] unsupported egress target "${opts.target}"`);
|
|
47
|
+
}
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
// squid — allowlist by hostname via CONNECT, no TLS interception
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
//
|
|
52
|
+
// squid matches on the CONNECT host, so it allowlists by DOMAIN cleanly and is
|
|
53
|
+
// the right target for rotating-CDN hostnames (api.github.com). IP-literal hosts
|
|
54
|
+
// are matched with a `dst` acl instead of `dstdomain`. The deny-all terminator
|
|
55
|
+
// is the last line, unconditional — nothing can be allowed past it.
|
|
56
|
+
function lowerToSquid(rules, blockPrivate) {
|
|
57
|
+
const notes = [];
|
|
58
|
+
const unenforceable = [];
|
|
59
|
+
const lines = ['# capgate-egress.squid.conf (generated — do not edit)'];
|
|
60
|
+
// ---------- blockPrivate (deny FIRST so it wins over the allows below) ----------
|
|
61
|
+
if (blockPrivate) {
|
|
62
|
+
lines.push(`acl to_private dst ${[...PRIVATE_V4, ...PRIVATE_V6].join(' ')}`);
|
|
63
|
+
lines.push('http_access deny to_private');
|
|
64
|
+
}
|
|
65
|
+
// ---------- allow rules ----------
|
|
66
|
+
rules.forEach((rule, i) => {
|
|
67
|
+
const dstAcl = `cg_dst_${i}`;
|
|
68
|
+
if (rule.host === '*') {
|
|
69
|
+
// squid can't allowlist "any host" as a *restriction*: `*` means the rule
|
|
70
|
+
// permits any destination. We represent it honestly as `dstdomain .`
|
|
71
|
+
// (matches every domain) and lean on blockPrivate to be the only real
|
|
72
|
+
// constraint left. Surfaced as a note so a reviewer sees the degeneracy.
|
|
73
|
+
lines.push(`acl ${dstAcl} dstdomain .`);
|
|
74
|
+
notes.push(`net[${i}]: host "*" degenerates to allow-any (dstdomain .) — squid cannot turn a wildcard into a restriction; only blockPrivate then constrains it.`);
|
|
75
|
+
}
|
|
76
|
+
else if (isIpLiteral(rule.host)) {
|
|
77
|
+
// IP literal: squid matches it with `dst`, not `dstdomain`.
|
|
78
|
+
lines.push(`acl ${dstAcl} dst ${rule.host}`);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
lines.push(`acl ${dstAcl} dstdomain ${rule.host}`);
|
|
82
|
+
}
|
|
83
|
+
const aclRefs = [dstAcl];
|
|
84
|
+
if (rule.port === null) {
|
|
85
|
+
// Any port → no port acl. Noted so the widened scope is auditable.
|
|
86
|
+
notes.push(`net[${i}]: port null (any port) — no port acl emitted for ${rule.host}.`);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
const portAcl = `cg_port_${i}`;
|
|
90
|
+
lines.push(`acl ${portAcl} port ${rule.port}`);
|
|
91
|
+
aclRefs.push(portAcl);
|
|
92
|
+
}
|
|
93
|
+
lines.push(`http_access allow ${aclRefs.join(' ')} CONNECT`);
|
|
94
|
+
});
|
|
95
|
+
if (rules.length === 0) {
|
|
96
|
+
notes.push('net: no egress declared — all outbound denied (deny-all only).');
|
|
97
|
+
}
|
|
98
|
+
// ---------- fail-closed terminator (unconditional, LAST line) ----------
|
|
99
|
+
lines.push('http_access deny all');
|
|
100
|
+
return {
|
|
101
|
+
target: 'squid',
|
|
102
|
+
config: lines.join('\n'),
|
|
103
|
+
filename: 'capgate-egress.squid.conf',
|
|
104
|
+
unenforceable,
|
|
105
|
+
notes,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
// nftables — allowlist by IP+port in-kernel, bypass-proof
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
//
|
|
112
|
+
// nftables filters packets by destination IP; it cannot resolve or track
|
|
113
|
+
// rotating hostnames in-kernel. So hostname rules are NOT lowered to a (broken)
|
|
114
|
+
// rule — they are pushed to unenforceable[] with a reason pointing at the squid
|
|
115
|
+
// target. blockPrivate drops are emitted FIRST (before accepts), and the chain
|
|
116
|
+
// defaults to `policy drop` so anything not explicitly accepted is dropped.
|
|
117
|
+
function lowerToNftables(rules, blockPrivate) {
|
|
118
|
+
const notes = [];
|
|
119
|
+
const unenforceable = [];
|
|
120
|
+
const body = [];
|
|
121
|
+
// ---------- blockPrivate (drops FIRST, before any accept) ----------
|
|
122
|
+
if (blockPrivate) {
|
|
123
|
+
body.push(` ip daddr { ${PRIVATE_V4.join(', ')} } drop`);
|
|
124
|
+
body.push(` ip6 daddr { ${PRIVATE_V6.join(', ')} } drop`);
|
|
125
|
+
}
|
|
126
|
+
// ---------- accept rules ----------
|
|
127
|
+
rules.forEach((rule, i) => {
|
|
128
|
+
if (rule.host === '*') {
|
|
129
|
+
// Can't allowlist "any host" by IP. The blockPrivate drops above still
|
|
130
|
+
// apply; the allow itself is unenforceable here.
|
|
131
|
+
unenforceable.push({
|
|
132
|
+
rule,
|
|
133
|
+
reason: 'nftables filters IPs, not hostnames; "*" cannot be expressed as an IP allowlist. Use the "squid" target for wildcard/hostname rules.',
|
|
134
|
+
});
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (!isIpLiteral(rule.host)) {
|
|
138
|
+
// Hostname (e.g. api.github.com): resolves to rotating CDN IPs that
|
|
139
|
+
// nftables can't track. Surface it; do not emit a broken rule.
|
|
140
|
+
unenforceable.push({
|
|
141
|
+
rule,
|
|
142
|
+
reason: `nftables filters IPs, not hostnames; ${rule.host} resolves to rotating IPs. Use the 'squid' target for hostname rules, or pin to resolved CIDRs.`,
|
|
143
|
+
});
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
// IP literal: pick the family by colon presence and accept it.
|
|
147
|
+
const fam = rule.host.includes(':') ? 'ip6' : 'ip';
|
|
148
|
+
const dport = rule.port === null ? '' : ` tcp dport ${rule.port}`;
|
|
149
|
+
if (rule.port === null) {
|
|
150
|
+
notes.push(`net[${i}]: port null (any port) — accept emitted without tcp dport for ${rule.host}.`);
|
|
151
|
+
}
|
|
152
|
+
body.push(` ${fam} daddr ${rule.host}${dport} accept`);
|
|
153
|
+
});
|
|
154
|
+
if (rules.length === 0) {
|
|
155
|
+
notes.push('net: no egress declared — all outbound denied (policy drop, no accepts).');
|
|
156
|
+
}
|
|
157
|
+
if (unenforceable.length > 0) {
|
|
158
|
+
notes.push(`net: ${unenforceable.length} rule(s) unenforceable by nftables (hostname/wildcard) — see unenforceable[]; compile those to the "squid" target.`);
|
|
159
|
+
}
|
|
160
|
+
// ---------- assemble table (policy drop = fail-closed default) ----------
|
|
161
|
+
const lines = [
|
|
162
|
+
'# capgate-egress.nftables (generated — do not edit)',
|
|
163
|
+
'table inet capgate {',
|
|
164
|
+
' chain egress {',
|
|
165
|
+
' type filter hook output priority 0; policy drop;',
|
|
166
|
+
...body,
|
|
167
|
+
' }',
|
|
168
|
+
'}',
|
|
169
|
+
];
|
|
170
|
+
return {
|
|
171
|
+
target: 'nftables',
|
|
172
|
+
config: lines.join('\n'),
|
|
173
|
+
filename: 'capgate-egress.nftables',
|
|
174
|
+
unenforceable,
|
|
175
|
+
notes,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* True if `host` is an IPv4 or IPv6 literal (vs a DNS name). Heuristic, kept
|
|
180
|
+
* deliberately simple: IPv4 is four dot-separated 0-255 octets; IPv6 is "has a
|
|
181
|
+
* colon" (real names never contain colons). This is enough to decide squid
|
|
182
|
+
* `dst` vs `dstdomain` and nftables accept-vs-unenforceable; we do not need a
|
|
183
|
+
* full RFC parser here, and over-classifying a name as an IP would only ever
|
|
184
|
+
* tighten matching, never loosen it.
|
|
185
|
+
*/
|
|
186
|
+
function isIpLiteral(host) {
|
|
187
|
+
if (host.includes(':'))
|
|
188
|
+
return true; // IPv6 literal (names never contain ':')
|
|
189
|
+
const octets = host.split('.');
|
|
190
|
+
if (octets.length !== 4)
|
|
191
|
+
return false;
|
|
192
|
+
return octets.every((o) => /^\d{1,3}$/.test(o) && Number(o) <= 255);
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=egress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"egress.js","sourceRoot":"","sources":["../../../src/policy/adapters/egress.ts"],"names":[],"mappings":"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"}
|
package/dist/policy/index.d.ts
CHANGED
|
@@ -8,4 +8,6 @@ export { lowerToBwrap } from './adapters/bwrap.js';
|
|
|
8
8
|
export type { BwrapArtifact, BwrapOptions, EgressRule } from './adapters/bwrap.js';
|
|
9
9
|
export { lowerToDocker } from './adapters/docker.js';
|
|
10
10
|
export type { DockerArtifact, DockerOptions } from './adapters/docker.js';
|
|
11
|
+
export { lowerToEgress } from './adapters/egress.js';
|
|
12
|
+
export type { EgressArtifact, EgressOptions, EgressTarget } from './adapters/egress.js';
|
|
11
13
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,UAAU,EACV,cAAc,EACd,QAAQ,EACR,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,cAAc,EACd,gBAAgB,GACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAChE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAClE,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAExE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEnF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAGA,YAAY,EACV,UAAU,EACV,cAAc,EACd,QAAQ,EACR,SAAS,EACT,UAAU,EACV,SAAS,EACT,SAAS,EACT,OAAO,EACP,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,WAAW,EACX,WAAW,EACX,YAAY,EACZ,cAAc,EACd,gBAAgB,GACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAChE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAClE,YAAY,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAExE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEnF,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/policy/index.js
CHANGED
|
@@ -5,4 +5,5 @@ export { parseCapability, GRAMMAR_VERSION } from './grammar.js';
|
|
|
5
5
|
export { compile, parseManifest, normalize } from './compiler.js';
|
|
6
6
|
export { lowerToBwrap } from './adapters/bwrap.js';
|
|
7
7
|
export { lowerToDocker } from './adapters/docker.js';
|
|
8
|
+
export { lowerToEgress } from './adapters/egress.js';
|
|
8
9
|
//# sourceMappingURL=index.js.map
|
package/dist/policy/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,+BAA+B;AAsB/B,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGhE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAGlE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,+BAA+B;AAsB/B,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGhE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAGlE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAGrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "capgate",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Compile MCP tool manifests into sandbox policies (bwrap, egress rules, and more).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
},
|
|
18
18
|
"files": [
|
|
19
19
|
"dist/",
|
|
20
|
+
"!dist/.tsbuildinfo",
|
|
20
21
|
"LICENSE",
|
|
21
22
|
"NOTICE",
|
|
22
23
|
"README.md"
|
|
@@ -62,4 +63,4 @@
|
|
|
62
63
|
"typescript": "^5.3.3",
|
|
63
64
|
"vitest": "^3.2.4"
|
|
64
65
|
}
|
|
65
|
-
}
|
|
66
|
+
}
|
package/dist/.tsbuildinfo
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"fileNames":["../node_modules/typescript/lib/lib.es5.d.ts","../node_modules/typescript/lib/lib.es2015.d.ts","../node_modules/typescript/lib/lib.es2016.d.ts","../node_modules/typescript/lib/lib.es2017.d.ts","../node_modules/typescript/lib/lib.es2018.d.ts","../node_modules/typescript/lib/lib.es2019.d.ts","../node_modules/typescript/lib/lib.es2020.d.ts","../node_modules/typescript/lib/lib.es2021.d.ts","../node_modules/typescript/lib/lib.es2022.d.ts","../node_modules/typescript/lib/lib.es2015.core.d.ts","../node_modules/typescript/lib/lib.es2015.collection.d.ts","../node_modules/typescript/lib/lib.es2015.generator.d.ts","../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../node_modules/typescript/lib/lib.es2015.promise.d.ts","../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../node_modules/typescript/lib/lib.es2016.intl.d.ts","../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../node_modules/typescript/lib/lib.es2017.date.d.ts","../node_modules/typescript/lib/lib.es2017.object.d.ts","../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2017.string.d.ts","../node_modules/typescript/lib/lib.es2017.intl.d.ts","../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../node_modules/typescript/lib/lib.es2018.intl.d.ts","../node_modules/typescript/lib/lib.es2018.promise.d.ts","../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../node_modules/typescript/lib/lib.es2019.array.d.ts","../node_modules/typescript/lib/lib.es2019.object.d.ts","../node_modules/typescript/lib/lib.es2019.string.d.ts","../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../node_modules/typescript/lib/lib.es2019.intl.d.ts","../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../node_modules/typescript/lib/lib.es2020.date.d.ts","../node_modules/typescript/lib/lib.es2020.promise.d.ts","../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2020.string.d.ts","../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2020.intl.d.ts","../node_modules/typescript/lib/lib.es2020.number.d.ts","../node_modules/typescript/lib/lib.es2021.promise.d.ts","../node_modules/typescript/lib/lib.es2021.string.d.ts","../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../node_modules/typescript/lib/lib.es2021.intl.d.ts","../node_modules/typescript/lib/lib.es2022.array.d.ts","../node_modules/typescript/lib/lib.es2022.error.d.ts","../node_modules/typescript/lib/lib.es2022.intl.d.ts","../node_modules/typescript/lib/lib.es2022.object.d.ts","../node_modules/typescript/lib/lib.es2022.string.d.ts","../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../node_modules/typescript/lib/lib.decorators.d.ts","../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../src/policy/ir.ts","../src/policy/grammar.ts","../src/policy/compiler.ts","../src/policy/adapters/bwrap.ts","../src/policy/adapters/docker.ts","../src/policy/index.ts","../src/cli.ts","../src/index.ts","../node_modules/@types/deep-eql/index.d.ts","../node_modules/assertion-error/index.d.ts","../node_modules/@types/chai/index.d.ts","../node_modules/@types/estree/index.d.ts","../node_modules/@types/node/compatibility/disposable.d.ts","../node_modules/@types/node/compatibility/indexable.d.ts","../node_modules/@types/node/compatibility/iterators.d.ts","../node_modules/@types/node/compatibility/index.d.ts","../node_modules/@types/node/globals.typedarray.d.ts","../node_modules/@types/node/buffer.buffer.d.ts","../node_modules/@types/node/globals.d.ts","../node_modules/@types/node/web-globals/abortcontroller.d.ts","../node_modules/@types/node/web-globals/domexception.d.ts","../node_modules/@types/node/web-globals/events.d.ts","../node_modules/undici-types/header.d.ts","../node_modules/undici-types/readable.d.ts","../node_modules/undici-types/file.d.ts","../node_modules/undici-types/fetch.d.ts","../node_modules/undici-types/formdata.d.ts","../node_modules/undici-types/connector.d.ts","../node_modules/undici-types/client.d.ts","../node_modules/undici-types/errors.d.ts","../node_modules/undici-types/dispatcher.d.ts","../node_modules/undici-types/global-dispatcher.d.ts","../node_modules/undici-types/global-origin.d.ts","../node_modules/undici-types/pool-stats.d.ts","../node_modules/undici-types/pool.d.ts","../node_modules/undici-types/handlers.d.ts","../node_modules/undici-types/balanced-pool.d.ts","../node_modules/undici-types/agent.d.ts","../node_modules/undici-types/mock-interceptor.d.ts","../node_modules/undici-types/mock-agent.d.ts","../node_modules/undici-types/mock-client.d.ts","../node_modules/undici-types/mock-pool.d.ts","../node_modules/undici-types/mock-errors.d.ts","../node_modules/undici-types/proxy-agent.d.ts","../node_modules/undici-types/env-http-proxy-agent.d.ts","../node_modules/undici-types/retry-handler.d.ts","../node_modules/undici-types/retry-agent.d.ts","../node_modules/undici-types/api.d.ts","../node_modules/undici-types/interceptors.d.ts","../node_modules/undici-types/util.d.ts","../node_modules/undici-types/cookies.d.ts","../node_modules/undici-types/patch.d.ts","../node_modules/undici-types/websocket.d.ts","../node_modules/undici-types/eventsource.d.ts","../node_modules/undici-types/filereader.d.ts","../node_modules/undici-types/diagnostics-channel.d.ts","../node_modules/undici-types/content-type.d.ts","../node_modules/undici-types/cache.d.ts","../node_modules/undici-types/index.d.ts","../node_modules/@types/node/web-globals/fetch.d.ts","../node_modules/@types/node/assert.d.ts","../node_modules/@types/node/assert/strict.d.ts","../node_modules/@types/node/async_hooks.d.ts","../node_modules/@types/node/buffer.d.ts","../node_modules/@types/node/child_process.d.ts","../node_modules/@types/node/cluster.d.ts","../node_modules/@types/node/console.d.ts","../node_modules/@types/node/constants.d.ts","../node_modules/@types/node/crypto.d.ts","../node_modules/@types/node/dgram.d.ts","../node_modules/@types/node/diagnostics_channel.d.ts","../node_modules/@types/node/dns.d.ts","../node_modules/@types/node/dns/promises.d.ts","../node_modules/@types/node/domain.d.ts","../node_modules/@types/node/events.d.ts","../node_modules/@types/node/fs.d.ts","../node_modules/@types/node/fs/promises.d.ts","../node_modules/@types/node/http.d.ts","../node_modules/@types/node/http2.d.ts","../node_modules/@types/node/https.d.ts","../node_modules/@types/node/inspector.generated.d.ts","../node_modules/@types/node/module.d.ts","../node_modules/@types/node/net.d.ts","../node_modules/@types/node/os.d.ts","../node_modules/@types/node/path.d.ts","../node_modules/@types/node/perf_hooks.d.ts","../node_modules/@types/node/process.d.ts","../node_modules/@types/node/punycode.d.ts","../node_modules/@types/node/querystring.d.ts","../node_modules/@types/node/readline.d.ts","../node_modules/@types/node/readline/promises.d.ts","../node_modules/@types/node/repl.d.ts","../node_modules/@types/node/sea.d.ts","../node_modules/@types/node/stream.d.ts","../node_modules/@types/node/stream/promises.d.ts","../node_modules/@types/node/stream/consumers.d.ts","../node_modules/@types/node/stream/web.d.ts","../node_modules/@types/node/string_decoder.d.ts","../node_modules/@types/node/test.d.ts","../node_modules/@types/node/timers.d.ts","../node_modules/@types/node/timers/promises.d.ts","../node_modules/@types/node/tls.d.ts","../node_modules/@types/node/trace_events.d.ts","../node_modules/@types/node/tty.d.ts","../node_modules/@types/node/url.d.ts","../node_modules/@types/node/util.d.ts","../node_modules/@types/node/v8.d.ts","../node_modules/@types/node/vm.d.ts","../node_modules/@types/node/wasi.d.ts","../node_modules/@types/node/worker_threads.d.ts","../node_modules/@types/node/zlib.d.ts","../node_modules/@types/node/index.d.ts"],"fileIdsList":[[66,67,75,121],[75,121],[75,118,121],[75,120,121],[121],[75,121,126,154],[75,121,122,127,132,140,151,162],[75,121,122,123,132,140],[70,71,72,75,121],[75,121,124,163],[75,121,125,126,133,141],[75,121,126,151,159],[75,121,127,129,132,140],[75,120,121,128],[75,121,129,130],[75,121,131,132],[75,120,121,132],[75,121,132,133,134,151,162],[75,121,132,133,134,147,151,154],[75,121,129,132,135,140,151,162],[75,121,132,133,135,136,140,151,159,162],[75,121,135,137,151,159,162],[73,74,75,76,77,78,79,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168],[75,121,132,138],[75,121,139,162,167],[75,121,129,132,140,151],[75,121,141],[75,121,142],[75,120,121,143],[75,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168],[75,121,145],[75,121,146],[75,121,132,147,148],[75,121,147,149,163,165],[75,121,132,151,152,154],[75,121,153,154],[75,121,151,152],[75,121,154],[75,121,155],[75,118,121,151,156],[75,121,132,157,158],[75,121,157,158],[75,121,126,140,151,159],[75,121,160],[75,121,140,161],[75,121,135,146,162],[75,121,126,163],[75,121,151,164],[75,121,139,165],[75,121,166],[75,116,121],[75,116,121,132,134,143,151,154,162,165,167],[75,121,151,168],[75,88,92,121,162],[75,88,121,151,162],[75,83,121],[75,85,88,121,159,162],[75,121,140,159],[75,121,169],[75,83,121,169],[75,85,88,121,140,162],[75,80,81,84,87,121,132,151,162],[75,88,95,121],[75,80,86,121],[75,88,109,110,121],[75,84,88,121,154,162,169],[75,109,121,169],[75,82,83,121,169],[75,88,121],[75,82,83,84,85,86,87,88,89,90,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,110,111,112,113,114,115,121],[75,88,103,121],[75,88,95,96,121],[75,86,88,96,97,121],[75,87,121],[75,80,83,88,121],[75,88,92,96,97,121],[75,92,121],[75,86,88,91,121,162],[75,80,85,88,95,121],[75,121,151],[75,83,88,109,121,167,169],[63,75,121,133],[63,75,121],[58,75,121],[58,61,75,121],[58,59,75,121],[58,59,60,61,62,75,121]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"8cdf8847677ac7d20486e54dd3fcf09eda95812ac8ace44b4418da1bbbab6eb8","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"7d8d8d1c13e8cf045b846f2260e8525934696e06b729e09ef1ccd4fa004a420c","signature":"f1f76fba70cfd9ea94050567e1679fc58f8a4042bd38f2305a31c276ee2f9bf8","impliedFormat":99},{"version":"6c5aeed665c5fed8bf25e12597faa7e959873ec5bd93cef96944db527dae2fc6","signature":"4a9e2ca3b0d8615dd9720c56105980effe87bc46bf6fb3a7fb022fdce4ced178","impliedFormat":99},{"version":"03bec921d3681af3c419b13c7a88e4238c67b585ed1e5a9b0b242fec9ebc53f4","signature":"27371969b29b1d75874dfefa176fb4975f6589772b5909ea80b8c7916f9a85c4","impliedFormat":99},{"version":"3d962b2b695509d0f1601a91f5032a1e0668c603e1155df860dc9acc7011dd74","signature":"e7dba5cc3d7ab272e89e9e8d7376368149268461ba78e807cf510cb3e0e6614c","impliedFormat":99},{"version":"744ca4ec5515e70a22db3fea372bdfc7b259d720f9fe03d83c089999200c5cf8","signature":"e6589dfbc82730a9f3c2759448b081b614f980458351f06d3d17d9b5698696f5","impliedFormat":99},{"version":"2aa9a9514c800a217560213f0d77c8f0b2aa41865477db3c68cb59f8078d1170","signature":"6c59c71a60aae051f1b3117ae395d6ebcd58fb334e76233f4847e41deac5442d","impliedFormat":99},{"version":"409795758db31a8d089c950706ee10d32f81e4690a02a3646d6f6086ac46aa08","signature":"43e818adf60173644896298637f47b01d5819b17eda46eaa32d0c7d64724d012","impliedFormat":99},{"version":"4a6bdfff32fba6a5632b3e056fdc4568625ec0b91648e40d5636e42d66e47336","signature":"044d36ac72ef84f2d3639cbc25140d355f1016706c23fe48eb7744f27479c52d","impliedFormat":99},{"version":"427fe2004642504828c1476d0af4270e6ad4db6de78c0b5da3e4c5ca95052a99","impliedFormat":1},{"version":"2eeffcee5c1661ddca53353929558037b8cf305ffb86a803512982f99bcab50d","impliedFormat":99},{"version":"9afb4cb864d297e4092a79ee2871b5d3143ea14153f62ef0bb04ede25f432030","affectsGlobalScope":true,"impliedFormat":99},{"version":"151ff381ef9ff8da2da9b9663ebf657eac35c4c9a19183420c05728f31a6761d","impliedFormat":1},{"version":"70521b6ab0dcba37539e5303104f29b721bfb2940b2776da4cc818c07e1fefc1","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"d153a11543fd884b596587ccd97aebbeed950b26933ee000f94009f1ab142848","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"98cffbf06d6bab333473c70a893770dbe990783904002c4f1a960447b4b53dca","affectsGlobalScope":true,"impliedFormat":1},{"version":"ba481bca06f37d3f2c137ce343c7d5937029b2468f8e26111f3c9d9963d6568d","affectsGlobalScope":true,"impliedFormat":1},{"version":"6d9ef24f9a22a88e3e9b3b3d8c40ab1ddb0853f1bfbd5c843c37800138437b61","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"b52476feb4a0cbcb25e5931b930fc73cb6643fb1a5060bf8a3dda0eeae5b4b68","affectsGlobalScope":true,"impliedFormat":1},{"version":"e2677634fe27e87348825bb041651e22d50a613e2fdf6a4a3ade971d71bac37e","impliedFormat":1},{"version":"7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","impliedFormat":1},{"version":"8c0bcd6c6b67b4b503c11e91a1fb91522ed585900eab2ab1f61bba7d7caa9d6f","impliedFormat":1},{"version":"8cd19276b6590b3ebbeeb030ac271871b9ed0afc3074ac88a94ed2449174b776","affectsGlobalScope":true,"impliedFormat":1},{"version":"696eb8d28f5949b87d894b26dc97318ef944c794a9a4e4f62360cd1d1958014b","impliedFormat":1},{"version":"3f8fa3061bd7402970b399300880d55257953ee6d3cd408722cb9ac20126460c","impliedFormat":1},{"version":"35ec8b6760fd7138bbf5809b84551e31028fb2ba7b6dc91d95d098bf212ca8b4","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"68bd56c92c2bd7d2339457eb84d63e7de3bd56a69b25f3576e1568d21a162398","affectsGlobalScope":true,"impliedFormat":1},{"version":"3e93b123f7c2944969d291b35fed2af79a6e9e27fdd5faa99748a51c07c02d28","impliedFormat":1},{"version":"9d19808c8c291a9010a6c788e8532a2da70f811adb431c97520803e0ec649991","impliedFormat":1},{"version":"87aad3dd9752067dc875cfaa466fc44246451c0c560b820796bdd528e29bef40","impliedFormat":1},{"version":"4aacb0dd020eeaef65426153686cc639a78ec2885dc72ad220be1d25f1a439df","impliedFormat":1},{"version":"f0bd7e6d931657b59605c44112eaf8b980ba7f957a5051ed21cb93d978cf2f45","impliedFormat":1},{"version":"8db0ae9cb14d9955b14c214f34dae1b9ef2baee2fe4ce794a4cd3ac2531e3255","affectsGlobalScope":true,"impliedFormat":1},{"version":"15fc6f7512c86810273af28f224251a5a879e4261b4d4c7e532abfbfc3983134","impliedFormat":1},{"version":"58adba1a8ab2d10b54dc1dced4e41f4e7c9772cbbac40939c0dc8ce2cdb1d442","impliedFormat":1},{"version":"641942a78f9063caa5d6b777c99304b7d1dc7328076038c6d94d8a0b81fc95c1","impliedFormat":1},{"version":"714435130b9015fae551788df2a88038471a5a11eb471f27c4ede86552842bc9","impliedFormat":1},{"version":"855cd5f7eb396f5f1ab1bc0f8580339bff77b68a770f84c6b254e319bbfd1ac7","impliedFormat":1},{"version":"5650cf3dace09e7c25d384e3e6b818b938f68f4e8de96f52d9c5a1b3db068e86","impliedFormat":1},{"version":"1354ca5c38bd3fd3836a68e0f7c9f91f172582ba30ab15bb8c075891b91502b7","affectsGlobalScope":true,"impliedFormat":1},{"version":"7e20d899c28ca26a2a7afc98beaa69e63ff7fba0a8bc47b4e3bf3ede5e09e424","impliedFormat":1},{"version":"2d2fcaab481b31a5882065c7951255703ddbe1c0e507af56ea42d79ac3911201","impliedFormat":1},{"version":"a192fe8ec33f75edbc8d8f3ed79f768dfae11ff5735e7fe52bfa69956e46d78d","impliedFormat":1},{"version":"ca867399f7db82df981d6915bcbb2d81131d7d1ef683bc782b59f71dda59bc85","affectsGlobalScope":true,"impliedFormat":1},{"version":"372413016d17d804e1d139418aca0c68e47a83fb6669490857f4b318de8cccb3","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e043a1bc8fbf2a255bccf9bf27e0f1caf916c3b0518ea34aa72357c0afd42ec","impliedFormat":1},{"version":"b4f70ec656a11d570e1a9edce07d118cd58d9760239e2ece99306ee9dfe61d02","impliedFormat":1},{"version":"3bc2f1e2c95c04048212c569ed38e338873f6a8593930cf5a7ef24ffb38fc3b6","impliedFormat":1},{"version":"6e70e9570e98aae2b825b533aa6292b6abd542e8d9f6e9475e88e1d7ba17c866","impliedFormat":1},{"version":"f9d9d753d430ed050dc1bf2667a1bab711ccbb1c1507183d794cc195a5b085cc","impliedFormat":1},{"version":"9eece5e586312581ccd106d4853e861aaaa1a39f8e3ea672b8c3847eedd12f6e","impliedFormat":1},{"version":"085f552d005479e2e6a7311cdbbe5d8c55c497b4d19274285df161ee9684cd9c","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"007faacc9268357caa21d24169f3f3f2497af3e9241308df2d89f6e6d9bb3f2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"74cf591a0f63db318651e0e04cb55f8791385f86e987a67fd4d2eaab8191f730","impliedFormat":1},{"version":"5eab9b3dc9b34f185417342436ec3f106898da5f4801992d8ff38ab3aff346b5","impliedFormat":1},{"version":"12ed4559eba17cd977aa0db658d25c4047067444b51acfdcbf38470630642b23","affectsGlobalScope":true,"impliedFormat":1},{"version":"f3ffabc95802521e1e4bcba4c88d8615176dc6e09111d920c7a213bdda6e1d65","impliedFormat":1},{"version":"809821b8a065e3234a55b3a9d7846231ed18d66dd749f2494c66288d890daf7f","impliedFormat":1},{"version":"ae56f65caf3be91108707bd8dfbccc2a57a91feb5daabf7165a06a945545ed26","impliedFormat":1},{"version":"a136d5de521da20f31631a0a96bf712370779d1c05b7015d7019a9b2a0446ca9","impliedFormat":1},{"version":"c3b41e74b9a84b88b1dca61ec39eee25c0dbc8e7d519ba11bb070918cfacf656","affectsGlobalScope":true,"impliedFormat":1},{"version":"4737a9dc24d0e68b734e6cfbcea0c15a2cfafeb493485e27905f7856988c6b29","affectsGlobalScope":true,"impliedFormat":1},{"version":"36d8d3e7506b631c9582c251a2c0b8a28855af3f76719b12b534c6edf952748d","impliedFormat":1},{"version":"1ca69210cc42729e7ca97d3a9ad48f2e9cb0042bada4075b588ae5387debd318","impliedFormat":1},{"version":"f5ebe66baaf7c552cfa59d75f2bfba679f329204847db3cec385acda245e574e","impliedFormat":1},{"version":"ed59add13139f84da271cafd32e2171876b0a0af2f798d0c663e8eeb867732cf","affectsGlobalScope":true,"impliedFormat":1},{"version":"b7c5e2ea4a9749097c347454805e933844ed207b6eefec6b7cfd418b5f5f7b28","impliedFormat":1},{"version":"b1810689b76fd473bd12cc9ee219f8e62f54a7d08019a235d07424afbf074d25","impliedFormat":1}],"root":[[58,65]],"options":{"declaration":true,"declarationMap":true,"esModuleInterop":true,"module":100,"noFallthroughCasesInSwitch":true,"noImplicitReturns":true,"noUnusedLocals":true,"noUnusedParameters":true,"outDir":"./","rootDir":"../src","skipLibCheck":true,"sourceMap":true,"strict":true,"target":9,"tsBuildInfoFile":"./.tsbuildinfo"},"referencedMap":[[68,1],[66,2],[69,2],[118,3],[119,3],[120,4],[75,5],[121,6],[122,7],[123,8],[70,2],[73,9],[71,2],[72,2],[124,10],[125,11],[126,12],[127,13],[128,14],[129,15],[130,15],[131,16],[132,17],[133,18],[134,19],[76,2],[74,2],[135,20],[136,21],[137,22],[169,23],[138,24],[139,25],[140,26],[141,27],[142,28],[143,29],[144,30],[145,31],[146,32],[147,33],[148,33],[149,34],[150,2],[151,35],[153,36],[152,37],[154,38],[155,39],[156,40],[157,41],[158,42],[159,43],[160,44],[161,45],[162,46],[163,47],[164,48],[165,49],[166,50],[77,2],[78,2],[79,2],[117,51],[167,52],[168,53],[67,2],[56,2],[57,2],[11,2],[10,2],[2,2],[12,2],[13,2],[14,2],[15,2],[16,2],[17,2],[18,2],[19,2],[3,2],[20,2],[21,2],[4,2],[22,2],[26,2],[23,2],[24,2],[25,2],[27,2],[28,2],[29,2],[5,2],[30,2],[31,2],[32,2],[33,2],[6,2],[37,2],[34,2],[35,2],[36,2],[38,2],[7,2],[39,2],[44,2],[45,2],[40,2],[41,2],[42,2],[43,2],[8,2],[49,2],[46,2],[47,2],[48,2],[50,2],[9,2],[51,2],[52,2],[53,2],[55,2],[54,2],[1,2],[95,54],[105,55],[94,54],[115,56],[86,57],[85,58],[114,59],[108,60],[113,61],[88,62],[102,63],[87,64],[111,65],[83,66],[82,59],[112,67],[84,68],[89,69],[90,2],[93,69],[80,2],[116,70],[106,71],[97,72],[98,73],[100,74],[96,75],[99,76],[109,59],[91,77],[92,78],[101,79],[81,80],[104,71],[103,69],[107,2],[110,81],[64,82],[65,83],[61,84],[62,85],[60,86],[59,84],[63,87],[58,2]],"version":"5.9.3"}
|