@molecule/api-code-sandbox-flyio 1.1.0 → 1.2.1

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 CHANGED
@@ -3,7 +3,7 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
3
3
  Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
4
4
  Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
5
5
  To change this document, edit the module-level JSDoc in src/index.ts.
6
- Generated: 2026-08-16T01:24:44.152Z
6
+ Generated: 2026-08-16T14:04:35.624Z
7
7
  -->
8
8
 
9
9
  # @molecule/api-code-sandbox-flyio
@@ -75,7 +75,7 @@ const warm = await provider.create({
75
75
  ## Installation
76
76
 
77
77
  ```bash
78
- npm install @molecule/api-code-sandbox-flyio @aws-sdk/client-s3 @aws-sdk/s3-request-presigner @molecule/api-bond @molecule/api-code-sandbox @molecule/api-i18n
78
+ npm install @molecule/api-code-sandbox-flyio @aws-sdk/client-s3 @aws-sdk/s3-request-presigner @molecule/api-bond @molecule/api-code-sandbox @molecule/api-i18n @molecule/api-proxy-agent
79
79
  ```
80
80
 
81
81
  ## API
@@ -94,10 +94,24 @@ interface EgressProbeContext {
94
94
  targets: EgressProbeTarget[]
95
95
  /**
96
96
  * Ports this provider's own egress policy allows, or `undefined` when it
97
- * applies no policy at all. Used ONLY for the message and the remediation —
98
- * never to decide the verdict, which comes from the observation alone.
97
+ * applies no policy at all. Used for the message, the remediation, and as the
98
+ * INTENT half of the drift check against {@link appliedPolicyPorts} — never to
99
+ * decide `open` vs `filtered` from a probe that reached a target, which comes
100
+ * from the observation alone.
99
101
  */
100
102
  policyPorts?: FlyNetworkPolicyPort[]
103
+ /**
104
+ * Ports the policy Fly ACTUALLY holds for this app allows, read back from the
105
+ * API after the probe ran, or `undefined` when the readback failed or found no
106
+ * policy of this provider's name.
107
+ *
108
+ * This is the observation half of the only drift this module can catch: a
109
+ * policy widened outside the provider (by hand, by another tool, by an older
110
+ * build) allows ports nothing here configured, and the raw-connect probe
111
+ * cannot see it because it only attempts the targets it was given. See
112
+ * {@link unexpectedPolicyPorts}.
113
+ */
114
+ appliedPolicyPorts?: FlyNetworkPolicyPort[]
101
115
  }
102
116
  ```
103
117
 
@@ -580,6 +594,13 @@ One rule in a Fly network policy. `allow` is the only documented action:
580
594
  "Once you create a rule for a given direction, the default for that direction
581
595
  becomes drop."
582
596
 
597
+ There is no destination field, and that is measured rather than assumed
598
+ (2026-08-16, live API): `ipv6_cidrs`, `ipv4_cidrs`, `cidrs`, `destinations`,
599
+ `apps`, `app`, `to` and `dst` were each POSTed on a rule and each came back
600
+ absent — the stored rule is `{action, direction, ports}` and nothing more. An
601
+ `allow tcp/5432` rule therefore permits the Machine to reach port 5432 on
602
+ every host on the internet.
603
+
583
604
  ```typescript
584
605
  interface FlyNetworkPolicyRule {
585
606
  /** Only `allow` is supported by Fly. */
@@ -593,8 +614,16 @@ interface FlyNetworkPolicyRule {
593
614
 
594
615
  #### `FlyNetworkPolicySelector`
595
616
 
596
- Which Machines in the app a policy applies to. Documented criteria combine
597
- with AND, so this provider uses `{ all: true }` alone.
617
+ Which Machines in the app a policy applies to — the SOURCE side only. There is
618
+ no destination selector: an `apps` array is the one candidate the API answers
619
+ about, and it answers `400 {"error":"apps array not currently supported in
620
+ selectors"}` (measured 2026-08-16); every other candidate field is silently
621
+ dropped. Documented criteria combine with AND, so this provider uses
622
+ `{ all: true }` alone.
623
+
624
+ The API's LIST response returns this object under the key `netpolSelector`
625
+ while accepting it as `selector` on write — which is why nothing here reads it
626
+ back by name.
598
627
 
599
628
  ```typescript
600
629
  interface FlyNetworkPolicySelector {
@@ -1165,6 +1194,28 @@ function decodePrivateRoutes(raw: string | undefined): Record<string, string>
1165
1194
 
1166
1195
  **Returns:** Target app name → allocated private address. Unparseable entries are skipped: this value only drives cleanup and self-healing, and a malformed entry must not stop either.
1167
1196
 
1197
+ #### `describePublicReach(policyPorts)`
1198
+
1199
+ States, in the verdict itself, what an allowed port actually permits.
1200
+
1201
+ A Fly network policy has no destination (see the module description — measured
1202
+ against the live API, not inferred), so every allowed port is open to every
1203
+ host on the internet, not only to the private service it was derived for. That
1204
+ is the single most consequential thing about this mechanism and it was invisible
1205
+ everywhere it mattered: the probe attempts one port the policy denies, reports
1206
+ `filtered`, and an operator reasonably reads that as "nothing gets out".
1207
+
1208
+ Naming it here means the residual is restated on every re-probe (the consumer
1209
+ re-verifies every 15 minutes) instead of living only in a document.
1210
+
1211
+ ```typescript
1212
+ function describePublicReach(policyPorts: FlyNetworkPolicyPort[] | undefined): string
1213
+ ```
1214
+
1215
+ - `policyPorts` — Allowed ports, or `undefined` when no policy is applied.
1216
+
1217
+ **Returns:** A sentence naming the public reach, or `''` when there is nothing to say (no policy, or nothing but UDP/53 — DNS is a documented residual of its own and not a TCP channel).
1218
+
1168
1219
  #### `encodePrivateRoutes(routes)`
1169
1220
 
1170
1221
  Encodes allocated addresses for storage in Machine metadata.
@@ -1223,6 +1274,32 @@ function extractPolicyId(response: unknown, name: string): string | undefined
1223
1274
 
1224
1275
  **Returns:** The matching policy's id, or `undefined`.
1225
1276
 
1277
+ #### `extractPolicyPorts(response, name)`
1278
+
1279
+ Reads back the egress ports the policy Fly ACTUALLY holds allows.
1280
+
1281
+ The write is not the observation: this provider POSTs a policy, but what
1282
+ governs a Machine is whatever Fly has when that Machine boots — which may
1283
+ differ because a person, another tool or an older build changed it. Reading it
1284
+ back is what lets {@link unexpectedPolicyPorts} catch a policy wider than the
1285
+ one this provider configured, so `verifyEgress()` can fail on drift its raw
1286
+ connects were never going to attempt.
1287
+
1288
+ Parsed as defensively as {@link extractPolicyId}, and for the same reason:
1289
+ neither Fly document specifies the LIST response shape. The live API answers
1290
+ with a bare array whose selector key is `netpolSelector` rather than the
1291
+ `selector` it accepts (verified 2026-08-16), which is exactly why nothing here
1292
+ depends on any key but `name` and `rules`.
1293
+
1294
+ ```typescript
1295
+ function extractPolicyPorts(response: unknown, name: string): FlyNetworkPolicyPort[] | undefined
1296
+ ```
1297
+
1298
+ - `response` — The raw parsed LIST response.
1299
+ - `name` — The policy name to match.
1300
+
1301
+ **Returns:** The allowed egress ports, or `undefined` when no policy of that name is present or the shape is unrecognized. `undefined` means "nothing to compare", never "nothing is allowed".
1302
+
1226
1303
  #### `flycastHost(app)`
1227
1304
 
1228
1305
  Renders the DNS name a sandbox dials to reach an app over its Flycast address.
@@ -1388,14 +1465,25 @@ It is deliberately a UNION and never a replacement, so an operator's list is
1388
1465
  still exactly what they wrote plus the ports their own declarations require,
1389
1466
  and the applied policy is logged.
1390
1467
 
1391
- Whether the addition is even load-bearing is UNVERIFIED: Fly states "Network
1392
- policies only apply to traffic directly to and from Machines. They do not
1393
- affect traffic routed through the Fly Proxy"
1468
+ The addition is load-bearing — VERIFIED 2026-08-16, not inferred. Fly states
1469
+ "Network policies only apply to traffic directly to and from Machines. They do
1470
+ not affect traffic routed through the Fly Proxy"
1394
1471
  (https://fly.io/docs/machines/guides-examples/network-policies/), and Flycast
1395
- traffic IS routed through Fly Proxy — but Fly says that about ingress and
1396
- never addresses a Machine's egress toward a Flycast address. An inert entry
1397
- costs a port on the allow list; a missing one costs every database in the
1398
- fleet, so the port is added.
1472
+ traffic IS routed through Fly Proxy, so it was an open question whether these
1473
+ ports did anything. Measured on a throwaway app with a Flycast address into
1474
+ its own 6PN: under a policy allowing only `udp:53`, `molecule-pg-tenant.flycast`
1475
+ and `molecule-api.flycast` both RESOLVED and every TCP connect to them was
1476
+ dropped; re-applying the policy with `tcp:443` opened 443 and nothing else.
1477
+ Fly's sentence is about INGRESS — a Machine's egress TOWARD a Flycast address
1478
+ is filtered like any other. Drop a declared service's port and every database
1479
+ connection in the fleet goes with it.
1480
+
1481
+ The cost of each derived port, stated plainly because a Fly policy has no
1482
+ destination field of any kind (also measured — see the `egress.ts` module
1483
+ description): the port is opened to EVERY host on the internet, not only to
1484
+ the private service it was derived for. That residual cannot be closed at this
1485
+ layer; it is named in `verifyEgress()`'s verdict and in
1486
+ `docs/sandbox-egress-enforcement.md`.
1399
1487
 
1400
1488
  ```typescript
1401
1489
  function mergeEgressPorts(
@@ -1672,6 +1760,30 @@ function toSandboxId(app: string, machineId: string): string
1672
1760
 
1673
1761
  **Returns:** The composite sandbox id.
1674
1762
 
1763
+ #### `unexpectedPolicyPorts(applied, intended)`
1764
+
1765
+ Finds ports the policy Fly holds allows that this provider never configured.
1766
+
1767
+ The raw-connect probe can only speak for the targets it was handed, so a
1768
+ policy widened outside this provider — edited by hand to unblock something, or
1769
+ left behind by an older build — is invisible to it: the probe's own port stays
1770
+ denied and the verdict stays `filtered` while a port nothing here asked for is
1771
+ open to the whole internet. Comparing what Fly holds against what this
1772
+ provider intended is the one check that can catch that, and it is why the
1773
+ verdict reads the policy back rather than trusting the write.
1774
+
1775
+ ```typescript
1776
+ function unexpectedPolicyPorts(
1777
+ applied: FlyNetworkPolicyPort[] | undefined,
1778
+ intended: FlyNetworkPolicyPort[] | undefined,
1779
+ ): FlyNetworkPolicyPort[]
1780
+ ```
1781
+
1782
+ - `applied` — Ports in the policy Fly actually holds, or `undefined` when the readback found nothing (in which case there is nothing to compare).
1783
+ - `intended` — Ports this provider configured, or `undefined` when it applies no policy.
1784
+
1785
+ **Returns:** The applied ports with no counterpart in `intended`, in order.
1786
+
1675
1787
  #### `verdictForProbeExit(exitCode, context)`
1676
1788
 
1677
1789
  Maps a probe's exit status onto an {@link EgressVerdict}.
@@ -1961,7 +2073,7 @@ export function setupCodeSandboxFlyio(): void {
1961
2073
  Peer dependencies:
1962
2074
 
1963
2075
  - `@molecule/api-bond` ^1.0.1
1964
- - `@molecule/api-code-sandbox` ^1.0.1
2076
+ - `@molecule/api-code-sandbox` ^1.2.0
1965
2077
  - `@molecule/api-i18n` ^1.0.1
1966
2078
 
1967
2079
  ### Environment Variables
@@ -2000,6 +2112,7 @@ Peer dependencies:
2000
2112
  - `@molecule/api-bond`
2001
2113
  - `@molecule/api-code-sandbox`
2002
2114
  - `@molecule/api-i18n`
2115
+ - `@molecule/api-proxy-agent`
2003
2116
 
2004
2117
  **Sources.** Every endpoint, payload field and documented behaviour used here
2005
2118
  was checked against Fly's own material, not recalled:
package/dist/egress.d.ts CHANGED
@@ -46,6 +46,30 @@
46
46
  * and that `name` is mandatory — which is why {@link DEFAULT_EGRESS_POLICY_NAME}
47
47
  * is always sent.
48
48
  *
49
+ * **THE PORT LIST IS THE WHOLE POLICY — there is no destination, and this was
50
+ * measured rather than inferred (2026-08-16, live API, throwaway app).** Every
51
+ * plausible destination field was POSTed and read back: on a RULE,
52
+ * `ipv6_cidrs` / `ipv4_cidrs` / `cidrs` / `destinations` / `apps` / `app` / `to`
53
+ * / `dst` are all accepted by the decoder and DROPPED — the stored rule comes
54
+ * back as `{action, direction, ports}` and nothing else. On the SELECTOR (which
55
+ * chooses which Machines a policy covers, i.e. the SOURCE, never a destination)
56
+ * only `all`, `machines` and `metadata` persist; `apps` is the one field the API
57
+ * answers about, with `400 {"error":"apps array not currently supported in
58
+ * selectors"}`. So an `allow tcp/5432` rule permits that Machine to reach port
59
+ * 5432 on EVERY host on the internet, and no arrangement of this object can say
60
+ * otherwise. {@link describePublicReach} states that in the verdict rather than
61
+ * leaving an operator to deduce it.
62
+ *
63
+ * **The derived private-service ports ARE load-bearing** (the open question this
64
+ * module and FLY-OPERATOR-SETUP §9 both carried since 2026-08-05). Measured the
65
+ * same day: with a policy allowing only `udp:53`, a Machine on a custom 6PN
66
+ * could resolve `molecule-pg-tenant.flycast` and `molecule-api.flycast` but
67
+ * every TCP connect to them was dropped, and re-applying `tcp:443` re-opened
68
+ * only 443. Fly's "policies do not affect traffic routed through the Fly Proxy"
69
+ * is about INGRESS; a Machine's egress TOWARD a Flycast address is filtered like
70
+ * any other. Dropping a declared service's port would therefore take out every
71
+ * database connection in the fleet.
72
+ *
49
73
  * @module
50
74
  */
51
75
  import type { EgressVerdict } from '@molecule/api-code-sandbox';
@@ -83,10 +107,24 @@ export interface EgressProbeContext {
83
107
  targets: EgressProbeTarget[];
84
108
  /**
85
109
  * Ports this provider's own egress policy allows, or `undefined` when it
86
- * applies no policy at all. Used ONLY for the message and the remediation —
87
- * never to decide the verdict, which comes from the observation alone.
110
+ * applies no policy at all. Used for the message, the remediation, and as the
111
+ * INTENT half of the drift check against {@link appliedPolicyPorts} — never to
112
+ * decide `open` vs `filtered` from a probe that reached a target, which comes
113
+ * from the observation alone.
88
114
  */
89
115
  policyPorts?: FlyNetworkPolicyPort[];
116
+ /**
117
+ * Ports the policy Fly ACTUALLY holds for this app allows, read back from the
118
+ * API after the probe ran, or `undefined` when the readback failed or found no
119
+ * policy of this provider's name.
120
+ *
121
+ * This is the observation half of the only drift this module can catch: a
122
+ * policy widened outside the provider (by hand, by another tool, by an older
123
+ * build) allows ports nothing here configured, and the raw-connect probe
124
+ * cannot see it because it only attempts the targets it was given. See
125
+ * {@link unexpectedPolicyPorts}.
126
+ */
127
+ appliedPolicyPorts?: FlyNetworkPolicyPort[];
90
128
  }
91
129
  /**
92
130
  * Renders a target the way it is written in configuration, so an operator can
@@ -139,6 +177,41 @@ export declare function parseEgressAllowedPorts(raw: string | undefined): FlyNet
139
177
  * @returns A `sh`-safe command string.
140
178
  */
141
179
  export declare function buildEgressProbeCommand(targets: EgressProbeTarget[], timeoutMs: number): string;
180
+ /**
181
+ * States, in the verdict itself, what an allowed port actually permits.
182
+ *
183
+ * A Fly network policy has no destination (see the module description — measured
184
+ * against the live API, not inferred), so every allowed port is open to every
185
+ * host on the internet, not only to the private service it was derived for. That
186
+ * is the single most consequential thing about this mechanism and it was invisible
187
+ * everywhere it mattered: the probe attempts one port the policy denies, reports
188
+ * `filtered`, and an operator reasonably reads that as "nothing gets out".
189
+ *
190
+ * Naming it here means the residual is restated on every re-probe (the consumer
191
+ * re-verifies every 15 minutes) instead of living only in a document.
192
+ * @param policyPorts - Allowed ports, or `undefined` when no policy is applied.
193
+ * @returns A sentence naming the public reach, or `''` when there is nothing to
194
+ * say (no policy, or nothing but UDP/53 — DNS is a documented residual of its
195
+ * own and not a TCP channel).
196
+ */
197
+ export declare function describePublicReach(policyPorts: FlyNetworkPolicyPort[] | undefined): string;
198
+ /**
199
+ * Finds ports the policy Fly holds allows that this provider never configured.
200
+ *
201
+ * The raw-connect probe can only speak for the targets it was handed, so a
202
+ * policy widened outside this provider — edited by hand to unblock something, or
203
+ * left behind by an older build — is invisible to it: the probe's own port stays
204
+ * denied and the verdict stays `filtered` while a port nothing here asked for is
205
+ * open to the whole internet. Comparing what Fly holds against what this
206
+ * provider intended is the one check that can catch that, and it is why the
207
+ * verdict reads the policy back rather than trusting the write.
208
+ * @param applied - Ports in the policy Fly actually holds, or `undefined` when
209
+ * the readback found nothing (in which case there is nothing to compare).
210
+ * @param intended - Ports this provider configured, or `undefined` when it
211
+ * applies no policy.
212
+ * @returns The applied ports with no counterpart in `intended`, in order.
213
+ */
214
+ export declare function unexpectedPolicyPorts(applied: FlyNetworkPolicyPort[] | undefined, intended: FlyNetworkPolicyPort[] | undefined): FlyNetworkPolicyPort[];
142
215
  /**
143
216
  * Maps a probe's exit status onto an {@link EgressVerdict}.
144
217
  *
@@ -177,4 +250,26 @@ export declare function verdictForProbeExit(exitCode: number, context: EgressPro
177
250
  * @returns The matching policy's id, or `undefined`.
178
251
  */
179
252
  export declare function extractPolicyId(response: unknown, name: string): string | undefined;
253
+ /**
254
+ * Reads back the egress ports the policy Fly ACTUALLY holds allows.
255
+ *
256
+ * The write is not the observation: this provider POSTs a policy, but what
257
+ * governs a Machine is whatever Fly has when that Machine boots — which may
258
+ * differ because a person, another tool or an older build changed it. Reading it
259
+ * back is what lets {@link unexpectedPolicyPorts} catch a policy wider than the
260
+ * one this provider configured, so `verifyEgress()` can fail on drift its raw
261
+ * connects were never going to attempt.
262
+ *
263
+ * Parsed as defensively as {@link extractPolicyId}, and for the same reason:
264
+ * neither Fly document specifies the LIST response shape. The live API answers
265
+ * with a bare array whose selector key is `netpolSelector` rather than the
266
+ * `selector` it accepts (verified 2026-08-16), which is exactly why nothing here
267
+ * depends on any key but `name` and `rules`.
268
+ * @param response - The raw parsed LIST response.
269
+ * @param name - The policy name to match.
270
+ * @returns The allowed egress ports, or `undefined` when no policy of that name
271
+ * is present or the shape is unrecognized. `undefined` means "nothing to
272
+ * compare", never "nothing is allowed".
273
+ */
274
+ export declare function extractPolicyPorts(response: unknown, name: string): FlyNetworkPolicyPort[] | undefined;
180
275
  //# sourceMappingURL=egress.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"egress.d.ts","sourceRoot":"","sources":["../src/egress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiDG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAE/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAGtD,gFAAgF;AAChF,eAAO,MAAM,0BAA0B,4BAA4B,CAAA;AAEnE;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,IAAI,CAAA;AAE1C,uFAAuF;AACvF,eAAO,MAAM,yBAAyB,IAAI,CAAA;AAE1C;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,2CAA2C,CAAA;AAEpF,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC,8FAA8F;IAC9F,IAAI,EAAE,MAAM,CAAA;IACZ,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,qFAAqF;AACrF,MAAM,WAAW,kBAAkB;IACjC,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAA;IACX,mCAAmC;IACnC,OAAO,EAAE,iBAAiB,EAAE,CAAA;IAC5B;;;;OAIG;IACH,WAAW,CAAC,EAAE,oBAAoB,EAAE,CAAA;CACrC;AAQD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAGzE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,GAAG,iBAAiB,EAAE,CAc/F;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,GAAG,SAAS,GACtB,oBAAoB,EAAE,GAAG,SAAS,CAyBpC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAY/F;AAaD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,aAAa,CA0ChG;AAWD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAanF"}
1
+ {"version":3,"file":"egress.d.ts","sourceRoot":"","sources":["../src/egress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyEG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAE/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAGtD,gFAAgF;AAChF,eAAO,MAAM,0BAA0B,4BAA4B,CAAA;AAcnE;;;;GAIG;AACH,eAAO,MAAM,yBAAyB,IAAI,CAAA;AAE1C,uFAAuF;AACvF,eAAO,MAAM,yBAAyB,IAAI,CAAA;AAE1C;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,2CAA2C,CAAA;AAEpF,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC,8FAA8F;IAC9F,IAAI,EAAE,MAAM,CAAA;IACZ,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,qFAAqF;AACrF,MAAM,WAAW,kBAAkB;IACjC,wCAAwC;IACxC,GAAG,EAAE,MAAM,CAAA;IACX,mCAAmC;IACnC,OAAO,EAAE,iBAAiB,EAAE,CAAA;IAC5B;;;;;;OAMG;IACH,WAAW,CAAC,EAAE,oBAAoB,EAAE,CAAA;IACpC;;;;;;;;;;OAUG;IACH,kBAAkB,CAAC,EAAE,oBAAoB,EAAE,CAAA;CAC5C;AAQD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAGzE;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,GAAG,iBAAiB,EAAE,CAc/F;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,uBAAuB,CACrC,GAAG,EAAE,MAAM,GAAG,SAAS,GACtB,oBAAoB,EAAE,GAAG,SAAS,CAyBpC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,iBAAiB,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAY/F;AAqBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,oBAAoB,EAAE,GAAG,SAAS,GAAG,MAAM,CAW3F;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,oBAAoB,EAAE,GAAG,SAAS,EAC3C,QAAQ,EAAE,oBAAoB,EAAE,GAAG,SAAS,GAC3C,oBAAoB,EAAE,CAMxB;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,kBAAkB,GAAG,aAAa,CAgEhG;AAWD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGnF;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,OAAO,EACjB,IAAI,EAAE,MAAM,GACX,oBAAoB,EAAE,GAAG,SAAS,CAiBpC"}
package/dist/egress.js CHANGED
@@ -46,11 +46,46 @@
46
46
  * and that `name` is mandatory — which is why {@link DEFAULT_EGRESS_POLICY_NAME}
47
47
  * is always sent.
48
48
  *
49
+ * **THE PORT LIST IS THE WHOLE POLICY — there is no destination, and this was
50
+ * measured rather than inferred (2026-08-16, live API, throwaway app).** Every
51
+ * plausible destination field was POSTed and read back: on a RULE,
52
+ * `ipv6_cidrs` / `ipv4_cidrs` / `cidrs` / `destinations` / `apps` / `app` / `to`
53
+ * / `dst` are all accepted by the decoder and DROPPED — the stored rule comes
54
+ * back as `{action, direction, ports}` and nothing else. On the SELECTOR (which
55
+ * chooses which Machines a policy covers, i.e. the SOURCE, never a destination)
56
+ * only `all`, `machines` and `metadata` persist; `apps` is the one field the API
57
+ * answers about, with `400 {"error":"apps array not currently supported in
58
+ * selectors"}`. So an `allow tcp/5432` rule permits that Machine to reach port
59
+ * 5432 on EVERY host on the internet, and no arrangement of this object can say
60
+ * otherwise. {@link describePublicReach} states that in the verdict rather than
61
+ * leaving an operator to deduce it.
62
+ *
63
+ * **The derived private-service ports ARE load-bearing** (the open question this
64
+ * module and FLY-OPERATOR-SETUP §9 both carried since 2026-08-05). Measured the
65
+ * same day: with a policy allowing only `udp:53`, a Machine on a custom 6PN
66
+ * could resolve `molecule-pg-tenant.flycast` and `molecule-api.flycast` but
67
+ * every TCP connect to them was dropped, and re-applying `tcp:443` re-opened
68
+ * only 443. Fly's "policies do not affect traffic routed through the Fly Proxy"
69
+ * is about INGRESS; a Machine's egress TOWARD a Flycast address is filtered like
70
+ * any other. Dropping a declared service's port would therefore take out every
71
+ * database connection in the fleet.
72
+ *
49
73
  * @module
50
74
  */
51
75
  import { shellQuote } from './utilities.js';
52
76
  /** Default name of the egress policy this provider owns on each sandbox app. */
53
77
  export const DEFAULT_EGRESS_POLICY_NAME = 'molecule-sandbox-egress';
78
+ /**
79
+ * UDP port name resolution runs on.
80
+ *
81
+ * Excluded from {@link describePublicReach}'s "reachable on" list because DNS is
82
+ * not a TCP channel and is a residual of its own (a resolver forwards queries
83
+ * upstream on the platform's behalf, which is why DNS tunnelling is tracked
84
+ * separately in `docs/sandbox-egress-enforcement.md` rather than as an open
85
+ * port). It is never excluded from {@link unexpectedPolicyPorts}: a policy that
86
+ * allows DNS this provider did not configure is still drift.
87
+ */
88
+ const DNS_PORT = 53;
54
89
  /**
55
90
  * Probe exit status meaning at least one raw connection to a public IP
56
91
  * SUCCEEDED. Deliberately not 1, so an interpreter error (which exits 1) can
@@ -175,6 +210,14 @@ export function buildEgressProbeCommand(targets, timeoutMs) {
175
210
  `s.on('error',()=>done())}`;
176
211
  return `node -e ${shellQuote(script)}`;
177
212
  }
213
+ /**
214
+ * Renders a port list the way an operator reads it back.
215
+ * @param ports - The ports.
216
+ * @returns `tcp/443, udp/53`.
217
+ */
218
+ function formatPorts(ports) {
219
+ return ports.map((port) => `${port.protocol}/${port.port}`).join(', ');
220
+ }
178
221
  /**
179
222
  * Describes the policy this provider applied, for the verdict message.
180
223
  * @param policyPorts - Allowed ports, or `undefined` when no policy is applied.
@@ -183,8 +226,55 @@ export function buildEgressProbeCommand(targets, timeoutMs) {
183
226
  function describePolicy(policyPorts) {
184
227
  if (!policyPorts)
185
228
  return 'no Fly network policy applied by this provider';
186
- const ports = policyPorts.map((port) => `${port.protocol}/${port.port}`).join(', ');
187
- return `a Fly network policy allowing egress on ${ports}`;
229
+ return `a Fly network policy allowing egress on ${formatPorts(policyPorts)}`;
230
+ }
231
+ /**
232
+ * States, in the verdict itself, what an allowed port actually permits.
233
+ *
234
+ * A Fly network policy has no destination (see the module description — measured
235
+ * against the live API, not inferred), so every allowed port is open to every
236
+ * host on the internet, not only to the private service it was derived for. That
237
+ * is the single most consequential thing about this mechanism and it was invisible
238
+ * everywhere it mattered: the probe attempts one port the policy denies, reports
239
+ * `filtered`, and an operator reasonably reads that as "nothing gets out".
240
+ *
241
+ * Naming it here means the residual is restated on every re-probe (the consumer
242
+ * re-verifies every 15 minutes) instead of living only in a document.
243
+ * @param policyPorts - Allowed ports, or `undefined` when no policy is applied.
244
+ * @returns A sentence naming the public reach, or `''` when there is nothing to
245
+ * say (no policy, or nothing but UDP/53 — DNS is a documented residual of its
246
+ * own and not a TCP channel).
247
+ */
248
+ export function describePublicReach(policyPorts) {
249
+ const reachable = (policyPorts ?? []).filter((port) => port.protocol !== 'udp' || port.port !== DNS_PORT);
250
+ if (reachable.length === 0)
251
+ return '';
252
+ return (`Every allowed port is open to EVERY host, not only to the private service it exists for — ` +
253
+ `a Fly network policy matches protocol and port with no destination field of any kind — so ` +
254
+ `code in this app can still reach an arbitrary public host on ${formatPorts(reachable)}. ` +
255
+ 'Route what must be filtered by host through an egress proxy on one of those ports.');
256
+ }
257
+ /**
258
+ * Finds ports the policy Fly holds allows that this provider never configured.
259
+ *
260
+ * The raw-connect probe can only speak for the targets it was handed, so a
261
+ * policy widened outside this provider — edited by hand to unblock something, or
262
+ * left behind by an older build — is invisible to it: the probe's own port stays
263
+ * denied and the verdict stays `filtered` while a port nothing here asked for is
264
+ * open to the whole internet. Comparing what Fly holds against what this
265
+ * provider intended is the one check that can catch that, and it is why the
266
+ * verdict reads the policy back rather than trusting the write.
267
+ * @param applied - Ports in the policy Fly actually holds, or `undefined` when
268
+ * the readback found nothing (in which case there is nothing to compare).
269
+ * @param intended - Ports this provider configured, or `undefined` when it
270
+ * applies no policy.
271
+ * @returns The applied ports with no counterpart in `intended`, in order.
272
+ */
273
+ export function unexpectedPolicyPorts(applied, intended) {
274
+ if (!applied)
275
+ return [];
276
+ const wanted = intended ?? [];
277
+ return applied.filter((port) => !wanted.some((own) => own.protocol === port.protocol && own.port === port.port));
188
278
  }
189
279
  /**
190
280
  * Maps a probe's exit status onto an {@link EgressVerdict}.
@@ -211,6 +301,24 @@ function describePolicy(policyPorts) {
211
301
  export function verdictForProbeExit(exitCode, context) {
212
302
  const targets = context.targets.map(formatEgressProbeTarget).join(', ');
213
303
  const policy = describePolicy(context.policyPorts);
304
+ const reach = describePublicReach(context.appliedPolicyPorts ?? context.policyPorts);
305
+ // Drift, and it outranks a blocked probe: the probe attempts the targets it
306
+ // was handed, so a port widened outside this provider is open with nothing
307
+ // observing it. `open` is the honest state — something out there permits
308
+ // traffic this provider never configured.
309
+ const unexpected = unexpectedPolicyPorts(context.appliedPolicyPorts, context.policyPorts);
310
+ if (unexpected.length > 0) {
311
+ return {
312
+ state: 'open',
313
+ detail: (`The Fly network policy in force on app "${context.app}" allows ` +
314
+ `${formatPorts(unexpected)}, which this provider never configured (it applies ` +
315
+ `${policy}). ${describePublicReach(context.appliedPolicyPorts)}`).trim(),
316
+ remediation: 'Something outside this provider widened the policy. Inspect it with ' +
317
+ `\`GET /v1/apps/${context.app}/network_policies\`, remove the rule that does not belong, ` +
318
+ 'and restart the Machines — Fly applies a policy at boot, so an already-running Machine ' +
319
+ 'keeps the wider one until it is recreated.',
320
+ };
321
+ }
214
322
  if (exitCode === EGRESS_PROBE_EXIT_REACHED) {
215
323
  return {
216
324
  state: 'open',
@@ -231,7 +339,7 @@ export function verdictForProbeExit(exitCode, context) {
231
339
  return {
232
340
  state: 'filtered',
233
341
  detail: `Raw TCP connects to ${targets} from a Machine in Fly app "${context.app}" ` +
234
- `(${policy}) were refused or timed out.`,
342
+ `(${policy}) were refused or timed out.${reach ? ` ${reach}` : ''}`,
235
343
  };
236
344
  }
237
345
  return {
@@ -267,6 +375,59 @@ function isRecord(value) {
267
375
  * @returns The matching policy's id, or `undefined`.
268
376
  */
269
377
  export function extractPolicyId(response, name) {
378
+ const entry = findPolicy(response, name);
379
+ return entry && typeof entry.id === 'string' && entry.id ? entry.id : undefined;
380
+ }
381
+ /**
382
+ * Reads back the egress ports the policy Fly ACTUALLY holds allows.
383
+ *
384
+ * The write is not the observation: this provider POSTs a policy, but what
385
+ * governs a Machine is whatever Fly has when that Machine boots — which may
386
+ * differ because a person, another tool or an older build changed it. Reading it
387
+ * back is what lets {@link unexpectedPolicyPorts} catch a policy wider than the
388
+ * one this provider configured, so `verifyEgress()` can fail on drift its raw
389
+ * connects were never going to attempt.
390
+ *
391
+ * Parsed as defensively as {@link extractPolicyId}, and for the same reason:
392
+ * neither Fly document specifies the LIST response shape. The live API answers
393
+ * with a bare array whose selector key is `netpolSelector` rather than the
394
+ * `selector` it accepts (verified 2026-08-16), which is exactly why nothing here
395
+ * depends on any key but `name` and `rules`.
396
+ * @param response - The raw parsed LIST response.
397
+ * @param name - The policy name to match.
398
+ * @returns The allowed egress ports, or `undefined` when no policy of that name
399
+ * is present or the shape is unrecognized. `undefined` means "nothing to
400
+ * compare", never "nothing is allowed".
401
+ */
402
+ export function extractPolicyPorts(response, name) {
403
+ const entry = findPolicy(response, name);
404
+ if (!entry || !Array.isArray(entry.rules))
405
+ return undefined;
406
+ const ports = [];
407
+ for (const rule of entry.rules) {
408
+ if (!isRecord(rule) || rule.direction !== 'egress' || !Array.isArray(rule.ports))
409
+ continue;
410
+ for (const port of rule.ports) {
411
+ if (!isRecord(port))
412
+ continue;
413
+ const protocol = port.protocol;
414
+ const value = port.port;
415
+ if ((protocol !== 'tcp' && protocol !== 'udp') || typeof value !== 'number')
416
+ continue;
417
+ if (!ports.some((seen) => seen.protocol === protocol && seen.port === value)) {
418
+ ports.push({ protocol, port: value });
419
+ }
420
+ }
421
+ }
422
+ return ports;
423
+ }
424
+ /**
425
+ * Finds the named policy in a LIST response.
426
+ * @param response - The raw parsed LIST response.
427
+ * @param name - The policy name to match.
428
+ * @returns The matching entry, or `undefined`.
429
+ */
430
+ function findPolicy(response, name) {
270
431
  const list = Array.isArray(response)
271
432
  ? response
272
433
  : isRecord(response)
@@ -275,9 +436,8 @@ export function extractPolicyId(response, name) {
275
436
  if (!Array.isArray(list))
276
437
  return undefined;
277
438
  for (const entry of list) {
278
- if (isRecord(entry) && entry.name === name && typeof entry.id === 'string' && entry.id) {
279
- return entry.id;
280
- }
439
+ if (isRecord(entry) && entry.name === name)
440
+ return entry;
281
441
  }
282
442
  return undefined;
283
443
  }
package/dist/flycast.d.ts CHANGED
@@ -115,14 +115,25 @@ export declare function parsePrivateServices(raw: string | undefined): FlyPrivat
115
115
  * still exactly what they wrote plus the ports their own declarations require,
116
116
  * and the applied policy is logged.
117
117
  *
118
- * Whether the addition is even load-bearing is UNVERIFIED: Fly states "Network
119
- * policies only apply to traffic directly to and from Machines. They do not
120
- * affect traffic routed through the Fly Proxy"
118
+ * The addition is load-bearing — VERIFIED 2026-08-16, not inferred. Fly states
119
+ * "Network policies only apply to traffic directly to and from Machines. They do
120
+ * not affect traffic routed through the Fly Proxy"
121
121
  * (https://fly.io/docs/machines/guides-examples/network-policies/), and Flycast
122
- * traffic IS routed through Fly Proxy — but Fly says that about ingress and
123
- * never addresses a Machine's egress toward a Flycast address. An inert entry
124
- * costs a port on the allow list; a missing one costs every database in the
125
- * fleet, so the port is added.
122
+ * traffic IS routed through Fly Proxy, so it was an open question whether these
123
+ * ports did anything. Measured on a throwaway app with a Flycast address into
124
+ * its own 6PN: under a policy allowing only `udp:53`, `molecule-pg-tenant.flycast`
125
+ * and `molecule-api.flycast` both RESOLVED and every TCP connect to them was
126
+ * dropped; re-applying the policy with `tcp:443` opened 443 and nothing else.
127
+ * Fly's sentence is about INGRESS — a Machine's egress TOWARD a Flycast address
128
+ * is filtered like any other. Drop a declared service's port and every database
129
+ * connection in the fleet goes with it.
130
+ *
131
+ * The cost of each derived port, stated plainly because a Fly policy has no
132
+ * destination field of any kind (also measured — see the `egress.ts` module
133
+ * description): the port is opened to EVERY host on the internet, not only to
134
+ * the private service it was derived for. That residual cannot be closed at this
135
+ * layer; it is named in `verifyEgress()`'s verdict and in
136
+ * `docs/sandbox-egress-enforcement.md`.
126
137
  * @param ports - The operator's configured ports, or `undefined` when no policy
127
138
  * is being applied at all.
128
139
  * @param services - The declared private services, or `undefined`.
@@ -1 +1 @@
1
- {"version":3,"file":"flycast.d.ts","sourceRoot":"","sources":["../src/flycast.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAIH,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEzE;;;;GAIG;AACH,eAAO,MAAM,cAAc,aAAa,CAAA;AAExC;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,kBAAkB,CAAA;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,eAAe,CAAA;AAKnD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,iBAAiB,EAAE,GAAG,SAAS,CAqC7F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,oBAAoB,EAAE,GAAG,SAAS,EACzC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,SAAS,GACxC,oBAAoB,EAAE,GAAG,SAAS,CAUpC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAI1E;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUnF;AA2BD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACvC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,SAAS,GACxC,IAAI,CAwCN"}
1
+ {"version":3,"file":"flycast.d.ts","sourceRoot":"","sources":["../src/flycast.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0DG;AAIH,OAAO,KAAK,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEzE;;;;GAIG;AACH,eAAO,MAAM,cAAc,aAAa,CAAA;AAExC;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,kBAAkB,CAAA;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,eAAe,CAAA;AAKnD;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE/C;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,iBAAiB,EAAE,GAAG,SAAS,CAqC7F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,oBAAoB,EAAE,GAAG,SAAS,EACzC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,SAAS,GACxC,oBAAoB,EAAE,GAAG,SAAS,CAUpC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAI1E;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAUnF;AA2BD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,EACvC,QAAQ,EAAE,iBAAiB,EAAE,GAAG,SAAS,GACxC,IAAI,CAwCN"}
package/dist/flycast.js CHANGED
@@ -147,14 +147,25 @@ export function parsePrivateServices(raw) {
147
147
  * still exactly what they wrote plus the ports their own declarations require,
148
148
  * and the applied policy is logged.
149
149
  *
150
- * Whether the addition is even load-bearing is UNVERIFIED: Fly states "Network
151
- * policies only apply to traffic directly to and from Machines. They do not
152
- * affect traffic routed through the Fly Proxy"
150
+ * The addition is load-bearing — VERIFIED 2026-08-16, not inferred. Fly states
151
+ * "Network policies only apply to traffic directly to and from Machines. They do
152
+ * not affect traffic routed through the Fly Proxy"
153
153
  * (https://fly.io/docs/machines/guides-examples/network-policies/), and Flycast
154
- * traffic IS routed through Fly Proxy — but Fly says that about ingress and
155
- * never addresses a Machine's egress toward a Flycast address. An inert entry
156
- * costs a port on the allow list; a missing one costs every database in the
157
- * fleet, so the port is added.
154
+ * traffic IS routed through Fly Proxy, so it was an open question whether these
155
+ * ports did anything. Measured on a throwaway app with a Flycast address into
156
+ * its own 6PN: under a policy allowing only `udp:53`, `molecule-pg-tenant.flycast`
157
+ * and `molecule-api.flycast` both RESOLVED and every TCP connect to them was
158
+ * dropped; re-applying the policy with `tcp:443` opened 443 and nothing else.
159
+ * Fly's sentence is about INGRESS — a Machine's egress TOWARD a Flycast address
160
+ * is filtered like any other. Drop a declared service's port and every database
161
+ * connection in the fleet goes with it.
162
+ *
163
+ * The cost of each derived port, stated plainly because a Fly policy has no
164
+ * destination field of any kind (also measured — see the `egress.ts` module
165
+ * description): the port is opened to EVERY host on the internet, not only to
166
+ * the private service it was derived for. That residual cannot be closed at this
167
+ * layer; it is named in `verifyEgress()`'s verdict and in
168
+ * `docs/sandbox-egress-enforcement.md`.
158
169
  * @param ports - The operator's configured ports, or `undefined` when no policy
159
170
  * is being applied at all.
160
171
  * @param services - The declared private services, or `undefined`.
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAWV,eAAe,EAGhB,MAAM,4BAA4B,CAAA;AAGnC,OAAO,EAAE,YAAY,EAAgC,MAAM,UAAU,CAAA;AAsBrE,OAAO,EAAmD,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AAEhG,OAAO,KAAK,EAIV,WAAW,EAUZ,MAAM,YAAY,CAAA;AA6oEnB;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,MAAM,CAAC,EAAE,WAAW,EACpB,MAAM,CAAC,EAAE,YAAY,EACrB,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,GACzB,eAAe,CAEjB"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAMH,OAAO,KAAK,EAWV,eAAe,EAGhB,MAAM,4BAA4B,CAAA;AAGnC,OAAO,EAAE,YAAY,EAAgC,MAAM,UAAU,CAAA;AAwBrE,OAAO,EAAmD,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AAEhG,OAAO,KAAK,EAIV,WAAW,EAUZ,MAAM,YAAY,CAAA;AA0tEnB;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAC5B,MAAM,CAAC,EAAE,WAAW,EACpB,MAAM,CAAC,EAAE,YAAY,EACrB,KAAK,CAAC,EAAE,WAAW,GAAG,IAAI,GACzB,eAAe,CAEjB"}
package/dist/provider.js CHANGED
@@ -11,7 +11,7 @@ import { gzipSync } from 'node:zlib';
11
11
  import { getLogger } from '@molecule/api-bond';
12
12
  import { t } from '@molecule/api-i18n';
13
13
  import { FlyApiClient, FlyApiError, normalizeApiUrl } from './api.js';
14
- import { buildEgressProbeCommand, DEFAULT_EGRESS_POLICY_NAME, DEFAULT_EGRESS_PROBE_TARGETS, extractPolicyId, parseEgressAllowedPorts, parseEgressProbeTargets, verdictForProbeExit, } from './egress.js';
14
+ import { buildEgressProbeCommand, DEFAULT_EGRESS_POLICY_NAME, DEFAULT_EGRESS_PROBE_TARGETS, describePublicReach, extractPolicyId, extractPolicyPorts, parseEgressAllowedPorts, parseEgressProbeTargets, verdictForProbeExit, } from './egress.js';
15
15
  import { execCommand, toExecResult } from './exec.js';
16
16
  import { assertPrivateRoutesForEnv, decodePrivateRoutes, DEFAULT_PRIVATE_IP_TYPE, encodePrivateRoutes, flycastHost, mergeEgressPorts, parsePrivateServices, PRIVATE_ROUTES_METADATA_SUFFIX, } from './flycast.js';
17
17
  import { appNameForProject, mapMachineState, parseSandboxId, toSandboxId } from './ids.js';
@@ -674,7 +674,74 @@ class FlyioSandboxProvider {
674
674
  rules: [{ action: 'allow', direction: 'egress', ports }],
675
675
  };
676
676
  await this.client.request(`/apps/${app}/network_policies`, { method: 'POST', body: policy });
677
- logger.info('Applied Fly egress network policy', { app, name, ports, updated: Boolean(id) });
677
+ logger.info('Applied Fly egress network policy', {
678
+ app,
679
+ name,
680
+ ports,
681
+ updated: Boolean(id),
682
+ // A Fly policy has no destination field (measured — see the egress module
683
+ // description), so every port here is open to every host on the internet.
684
+ // Logged with the apply so the residual appears where the decision is
685
+ // recorded, not only in a document.
686
+ publicReach: describePublicReach(ports),
687
+ });
688
+ }
689
+ /**
690
+ * Re-applies this provider's egress policy to an app that ALREADY exists.
691
+ *
692
+ * `ensureApp()` applies the policy on the path to creating a Machine, so a
693
+ * change to the configured ports reaches an existing app only when something
694
+ * deploys into it again. Until then Fly still holds the older, wider policy —
695
+ * and Fly applies whatever it holds at Machine BOOT, so a host migration or a
696
+ * crash-restart brings that app back up under the policy the operator thought
697
+ * they had replaced. That window is what this closes: a consumer that knows
698
+ * which apps it created (from its own records — never by enumerating a
699
+ * provider that cannot be enumerated) can walk them at startup and put the
700
+ * current policy in place before any of them next boots.
701
+ *
702
+ * Idempotent, and it updates the policy this provider owns in place rather
703
+ * than stacking a second one.
704
+ * @param app - The Fly app name.
705
+ * @returns The ports now allowed, or `undefined` when no policy is configured
706
+ * at all — in which case nothing was written, because turning "no policy"
707
+ * into one that Fly then uses to drop everything else is not something to
708
+ * infer from a reconciliation sweep.
709
+ * @throws {Error} When the policy cannot be applied. The caller decides what a
710
+ * failed reconcile means; this never reports success for a write that did
711
+ * not happen.
712
+ */
713
+ async reconcileEgressPolicy(app) {
714
+ const ports = this.egressAllowedPorts();
715
+ if (!ports)
716
+ return undefined;
717
+ await this.applyEgressPolicy(app);
718
+ return ports;
719
+ }
720
+ /**
721
+ * Reads back the egress ports the policy Fly holds for an app allows.
722
+ *
723
+ * Best-effort by design: this feeds a DRIFT check, and a readback that failed
724
+ * proves nothing about the policy — treating "I could not look" as "there is
725
+ * no drift" is the same conflation the verdict mapping refuses, so the caller
726
+ * gets `undefined` and reports on the observation alone.
727
+ * @param app - The Fly app name.
728
+ * @returns The allowed ports, or `undefined` when nothing could be read.
729
+ */
730
+ async readAppliedPolicyPorts(app) {
731
+ const name = this.config.egressPolicyName ?? DEFAULT_EGRESS_POLICY_NAME;
732
+ try {
733
+ const listed = await this.client.request(`/apps/${app}/network_policies`, {
734
+ nullOn: [404],
735
+ });
736
+ return extractPolicyPorts(listed, name);
737
+ }
738
+ catch (error) {
739
+ logger.warn('Could not read the Fly egress policy back — reporting on the probe alone', {
740
+ app,
741
+ error,
742
+ });
743
+ return undefined;
744
+ }
678
745
  }
679
746
  /**
680
747
  * Requests a shared Anycast IPv4 for the app so `<app>.fly.dev` serves traffic.
@@ -1396,7 +1463,17 @@ class FlyioSandboxProvider {
1396
1463
  await this.waitForStarted(app, machineId);
1397
1464
  const seconds = Math.min(MAX_WAIT_SECONDS, Math.max(1, Math.ceil(timeoutMs / 1000) + PROBE_EXEC_HEADROOM_SECONDS));
1398
1465
  const result = toExecResult(await this.rawExec(app, machineId)(['sh', '-c', buildEgressProbeCommand(targets, timeoutMs)], seconds));
1399
- return verdictForProbeExit(result.exitCode, { app, targets, policyPorts });
1466
+ // Read the policy back from Fly rather than trusting the write: the probe
1467
+ // can only speak for the ports it attempted, so a policy widened outside
1468
+ // this provider is invisible to it. This is the observation that catches
1469
+ // that, and it happens before the throwaway app is destroyed.
1470
+ const appliedPolicyPorts = await this.readAppliedPolicyPorts(app);
1471
+ return verdictForProbeExit(result.exitCode, {
1472
+ app,
1473
+ targets,
1474
+ policyPorts,
1475
+ appliedPolicyPorts,
1476
+ });
1400
1477
  }
1401
1478
  catch (error) {
1402
1479
  // A probe that could not RUN proves nothing. Reporting `filtered` here is
package/dist/storage.d.ts CHANGED
@@ -24,6 +24,14 @@
24
24
  * (https://www.tigrisdata.com/docs/api/s3/): PutObject, GetObject, HeadObject,
25
25
  * ListObjectsV2, DeleteObject and DeleteObjects.
26
26
  *
27
+ * Runs behind an outbound proxy when `HTTPS_PROXY` is set: the AWS SDK v3 builds
28
+ * its own agent and reads no proxy variable, so the client is given a
29
+ * CONNECT-capable one through its `requestHandler` hook
30
+ * (`@molecule/api-proxy-agent`, resolved against the configured endpoint so a
31
+ * store listed in `NO_PROXY` keeps connecting directly). Note this covers only
32
+ * the control plane's calls — the sandbox moves the tar bytes itself over the
33
+ * presigned URLs, through whatever egress path the sandbox has.
34
+ *
27
35
  * @module
28
36
  */
29
37
  import type { FlyioConfig } from './types.js';
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAYH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,4DAA4D;AAC5D,eAAO,MAAM,uBAAuB,+BAA+B,CAAA;AAEnE;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,SAAS,CAAA;AAE7C;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,QAAmB,CAAA;AAE1D,+CAA+C;AAC/C,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAA;IACX,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,sFAAsF;IACtF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,qFAAqF;IACrF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAA;IAC7C,4FAA4F;IAC5F,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IAC/C,+FAA+F;IAC/F,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAC5C,iCAAiC;IACjC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtE,qEAAqE;IACrE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,yDAAyD;IACzD,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAClE,2DAA2D;IAC3D,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CACnE;AAED,kEAAkE;AAClE,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,cAAc,EAAE,OAAO,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;CACf;AAmBD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,GAAG,eAAe,GAAG,IAAI,CAqClF;AAmBD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,IAAI,CA6H3E"}
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAcH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAE7C,4DAA4D;AAC5D,eAAO,MAAM,uBAAuB,+BAA+B,CAAA;AAEnE;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,SAAS,CAAA;AAE7C;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,QAAmB,CAAA;AAE1D,+CAA+C;AAC/C,MAAM,WAAW,YAAY;IAC3B,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAA;IACX,qBAAqB;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,sFAAsF;IACtF,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,sEAAsE;IACtE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,qFAAqF;IACrF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,4EAA4E;IAC5E,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAA;IAC7C,4FAA4F;IAC5F,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAA;IAC/C,+FAA+F;IAC/F,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;IAC5C,iCAAiC;IACjC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtE,qEAAqE;IACrE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,yDAAyD;IACzD,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAClE,2DAA2D;IAC3D,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;CACnE;AAED,kEAAkE;AAClE,UAAU,eAAe;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,MAAM,CAAA;IACvB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,cAAc,EAAE,OAAO,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;CACf;AAmBD;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,GAAG,eAAe,GAAG,IAAI,CAqClF;AAmBD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,WAAW,GAAG,IAAI,CAsI3E"}
package/dist/storage.js CHANGED
@@ -24,10 +24,19 @@
24
24
  * (https://www.tigrisdata.com/docs/api/s3/): PutObject, GetObject, HeadObject,
25
25
  * ListObjectsV2, DeleteObject and DeleteObjects.
26
26
  *
27
+ * Runs behind an outbound proxy when `HTTPS_PROXY` is set: the AWS SDK v3 builds
28
+ * its own agent and reads no proxy variable, so the client is given a
29
+ * CONNECT-capable one through its `requestHandler` hook
30
+ * (`@molecule/api-proxy-agent`, resolved against the configured endpoint so a
31
+ * store listed in `NO_PROXY` keeps connecting directly). Note this covers only
32
+ * the control plane's calls — the sandbox moves the tar bytes itself over the
33
+ * presigned URLs, through whatever egress path the sandbox has.
34
+ *
27
35
  * @module
28
36
  */
29
37
  import { DeleteObjectsCommand, GetObjectCommand, HeadObjectCommand, ListObjectsV2Command, PutObjectCommand, S3Client, } from '@aws-sdk/client-s3';
30
38
  import { getSignedUrl } from '@aws-sdk/s3-request-presigner';
39
+ import { getProxyAgents } from '@molecule/api-proxy-agent';
31
40
  /** Default key prefix for every object this bond writes. */
32
41
  export const DEFAULT_TEMPLATE_PREFIX = 'molecule-sandbox-templates';
33
42
  /**
@@ -131,9 +140,17 @@ export function createTemplateStore(config) {
131
140
  const settings = resolveTemplateStorage(config);
132
141
  if (!settings)
133
142
  return null;
143
+ // The AWS SDK v3 builds its own `https.Agent` and reads no proxy variable, so
144
+ // on a host whose only egress path is a proxy every template read/write would
145
+ // fail with a bare connection error. `requestHandler` takes NodeHttpHandler
146
+ // OPTIONS, so the agent goes in with no `@smithy/*` dependency. Resolved
147
+ // against the endpoint actually in use, so an internal store that NO_PROXY
148
+ // exempts keeps connecting directly.
149
+ const proxy = getProxyAgents(settings.endpoint || `https://s3.${settings.region}.amazonaws.com`);
134
150
  const client = new S3Client({
135
151
  region: settings.region,
136
152
  ...(settings.endpoint ? { endpoint: settings.endpoint } : {}),
153
+ ...(proxy ? { requestHandler: proxy } : {}),
137
154
  forcePathStyle: settings.forcePathStyle,
138
155
  credentials: {
139
156
  accessKeyId: settings.accessKeyId,
package/dist/types.d.ts CHANGED
@@ -406,6 +406,13 @@ export interface FlyNetworkPolicyPort {
406
406
  * One rule in a Fly network policy. `allow` is the only documented action:
407
407
  * "Once you create a rule for a given direction, the default for that direction
408
408
  * becomes drop."
409
+ *
410
+ * There is no destination field, and that is measured rather than assumed
411
+ * (2026-08-16, live API): `ipv6_cidrs`, `ipv4_cidrs`, `cidrs`, `destinations`,
412
+ * `apps`, `app`, `to` and `dst` were each POSTed on a rule and each came back
413
+ * absent — the stored rule is `{action, direction, ports}` and nothing more. An
414
+ * `allow tcp/5432` rule therefore permits the Machine to reach port 5432 on
415
+ * every host on the internet.
409
416
  */
410
417
  export interface FlyNetworkPolicyRule {
411
418
  /** Only `allow` is supported by Fly. */
@@ -416,8 +423,16 @@ export interface FlyNetworkPolicyRule {
416
423
  ports: FlyNetworkPolicyPort[];
417
424
  }
418
425
  /**
419
- * Which Machines in the app a policy applies to. Documented criteria combine
420
- * with AND, so this provider uses `{ all: true }` alone.
426
+ * Which Machines in the app a policy applies to — the SOURCE side only. There is
427
+ * no destination selector: an `apps` array is the one candidate the API answers
428
+ * about, and it answers `400 {"error":"apps array not currently supported in
429
+ * selectors"}` (measured 2026-08-16); every other candidate field is silently
430
+ * dropped. Documented criteria combine with AND, so this provider uses
431
+ * `{ all: true }` alone.
432
+ *
433
+ * The API's LIST response returns this object under the key `netpolSelector`
434
+ * while accepting it as `selector` on write — which is why nothing here reads it
435
+ * back by name.
421
436
  */
422
437
  export interface FlyNetworkPolicySelector {
423
438
  /** Match every Machine in the app. */
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;;;;;OAQG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,gGAAgG;IAChG,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kFAAkF;IAClF,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,kEAAkE;IAClE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,6FAA6F;IAC7F,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B;;;;OAIG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB;;;;;;;;OAQG;IACH,QAAQ,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,CAAA;IACrC;;;;;OAKG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,kGAAkG;IAClG,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,+FAA+F;IAC/F,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;;;;;;OAUG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B;;;;;;;;;;;;;;;;;OAiBG;IACH,kBAAkB,CAAC,EAAE,oBAAoB,EAAE,CAAA;IAC3C,uGAAuG;IACvG,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,eAAe,CAAC,EAAE,iBAAiB,EAAE,CAAA;IACrC;;;;;;OAMG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC7B,sHAAsH;IACtH,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,mHAAmH;IACnH,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,2HAA2H;IAC3H,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,wIAAwI;IACxI,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB;;;;;OAKG;IACH,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC;;;;;;OAMG;IACH,wBAAwB,CAAC,EAAE,MAAM,CAAA;IACjC;;;;OAIG;IACH,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC;;;;;OAKG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAA;CACjC;AAED;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,0DAA0D;IAC1D,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,kFAAkF;IAClF,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,+EAA+E;IAC/E,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,0EAA0E;IAC1E,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,+EAA+E;IAC/E,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,+DAA+D;IAC/D,sBAAsB,CAAC,EAAE,MAAM,CAAA;IAC/B,iEAAiE;IACjE,2BAA2B,CAAC,EAAE,MAAM,CAAA;IACpC,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,sCAAsC;IACtC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B;;;;OAIG;IACH,gCAAgC,CAAC,EAAE,MAAM,CAAA;IACzC;;;;;OAKG;IACH,4BAA4B,CAAC,EAAE,MAAM,CAAA;IACrC;;;OAGG;IACH,4BAA4B,CAAC,EAAE,MAAM,CAAA;IACrC,yEAAyE;IACzE,+BAA+B,CAAC,EAAE,MAAM,CAAA;IACxC,+EAA+E;IAC/E,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,qGAAqG;IACrG,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oFAAoF;IACpF,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC,uGAAuG;IACvG,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,qGAAqG;IACrG,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,2FAA2F;IAC3F,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,qFAAqF;IACrF,8BAA8B,CAAC,EAAE,MAAM,CAAA;IACvC,+EAA+E;IAC/E,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,yFAAyF;IACzF,kCAAkC,CAAC,EAAE,MAAM,CAAA;IAC3C,+EAA+E;IAC/E,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,yFAAyF;IACzF,8BAA8B,CAAC,EAAE,MAAM,CAAA;IACvC,4CAA4C;IAC5C,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,8EAA8E;IAC9E,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,sFAAsF;IACtF,iCAAiC,CAAC,EAAE,MAAM,CAAA;CAC3C;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,GAAG,EAAE,MAAM,CAAA;IACX;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,eAAe;IAC9B,oFAAoF;IACpF,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,sEAAsE;IACtE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,wEAAwE;IACxE,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,mDAAmD;IACnD,QAAQ,EAAE,KAAK,GAAG,KAAK,CAAA;IACvB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAA;CACb;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,wCAAwC;IACxC,MAAM,EAAE,OAAO,CAAA;IACf,4EAA4E;IAC5E,SAAS,EAAE,SAAS,GAAG,QAAQ,CAAA;IAC/B,+BAA+B;IAC/B,KAAK,EAAE,oBAAoB,EAAE,CAAA;CAC9B;AAED;;;GAGG;AACH,MAAM,WAAW,wBAAwB;IACvC,sCAAsC;IACtC,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,kCAAkC;IAClC,QAAQ,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAChC,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAClC;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mEAAmE;IACnE,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAA;IACZ,sCAAsC;IACtC,QAAQ,EAAE,wBAAwB,CAAA;IAClC,uBAAuB;IACvB,KAAK,EAAE,oBAAoB,EAAE,CAAA;CAC9B;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GACvB,SAAS,GACT,UAAU,GACV,UAAU,GACV,SAAS,GACT,UAAU,GACV,SAAS,GACT,YAAY,GACZ,WAAW,GACX,YAAY,GACZ,UAAU,GACV,WAAW,GACX,UAAU,GACV,UAAU,GACV,YAAY,GACZ,WAAW,GACX,QAAQ,GACR,eAAe,GACf,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAEjB,mFAAmF;AACnF,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kGAAkG;IAClG,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,gBAAgB,CAAA;IACzB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;;OAIG;IACH,MAAM,CAAC,EAAE,eAAe,EAAE,CAAA;CAC3B;AAED,8CAA8C;AAC9C,MAAM,WAAW,eAAe;IAC9B,mCAAmC;IACnC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wFAAwF;AACxF,MAAM,WAAW,MAAM;IACrB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,kDAAkD;AAClD,MAAM,WAAW,UAAU;IACzB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,wFAAwF;AACxF,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC/C,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,qFAAqF;AACrF,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAChE,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAChE,QAAQ,CAAC,EAAE,iBAAiB,EAAE,CAAA;IAC9B,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,IAAI,GAAG,QAAQ,GAAG,YAAY,GAAG,YAAY,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1F,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,GAAG,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CACjF;AAED,wEAAwE;AACxE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,EAAE,MAAM,CAAA;IACrB,KAAK,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IAC1E,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,QAAQ,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,CAAA;IACrC,oBAAoB,CAAC,EAAE,MAAM,CAAA;CAC9B;AAED,iDAAiD;AACjD,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B;AAED,yFAAyF;AACzF,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/api-code-sandbox-flyio",
3
- "version": "1.1.0",
3
+ "version": "1.2.1",
4
4
  "description": "Fly.io Machines (Firecracker microVM) code sandbox provider",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -30,11 +30,11 @@
30
30
  ],
31
31
  "license": "Apache-2.0",
32
32
  "devDependencies": {
33
- "@molecule/api-bond": "1.0.1",
34
- "@molecule/api-code-sandbox": "1.2.0",
33
+ "@molecule/api-bond": "1.0.2",
34
+ "@molecule/api-code-sandbox": "1.2.1",
35
35
  "@types/node": "26.1.2",
36
36
  "typescript": "6.0.3",
37
- "vitest": "4.1.10"
37
+ "vitest": "4.1.11"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "@molecule/api-bond": "^1.0.1",
@@ -51,13 +51,14 @@
51
51
  "url": "https://github.com/molecule-dev/molecule.git",
52
52
  "directory": "packages/api/bonds/code-sandbox/flyio"
53
53
  },
54
- "homepage": "https://github.com/molecule-dev/molecule/tree/main/packages/api/bonds/code-sandbox/flyio",
54
+ "homepage": "https://www.molecule.dev/packages/api-code-sandbox-flyio",
55
55
  "bugs": "https://github.com/molecule-dev/molecule/issues",
56
56
  "publishConfig": {
57
57
  "access": "public"
58
58
  },
59
59
  "dependencies": {
60
60
  "@aws-sdk/client-s3": "3.1098.0",
61
- "@aws-sdk/s3-request-presigner": "3.1098.0"
61
+ "@aws-sdk/s3-request-presigner": "3.1098.0",
62
+ "@molecule/api-proxy-agent": "1.1.1"
62
63
  }
63
64
  }