@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 +127 -14
- package/dist/egress.d.ts +97 -2
- package/dist/egress.d.ts.map +1 -1
- package/dist/egress.js +166 -6
- package/dist/flycast.d.ts +18 -7
- package/dist/flycast.d.ts.map +1 -1
- package/dist/flycast.js +18 -7
- package/dist/provider.d.ts.map +1 -1
- package/dist/provider.js +80 -3
- package/dist/storage.d.ts +8 -0
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +17 -0
- package/dist/types.d.ts +17 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -6
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-
|
|
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
|
|
98
|
-
*
|
|
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.
|
|
597
|
-
|
|
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
|
-
|
|
1392
|
-
policies only apply to traffic directly to and from Machines. They do
|
|
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
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
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
|
|
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
|
|
87
|
-
*
|
|
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
|
package/dist/egress.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"egress.d.ts","sourceRoot":"","sources":["../src/egress.ts"],"names":[],"mappings":"AAAA
|
|
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
|
-
|
|
187
|
-
|
|
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
|
|
279
|
-
return entry
|
|
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
|
-
*
|
|
119
|
-
* policies only apply to traffic directly to and from Machines. They do
|
|
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
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
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`.
|
package/dist/flycast.d.ts.map
CHANGED
|
@@ -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
|
|
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
|
-
*
|
|
151
|
-
* policies only apply to traffic directly to and from Machines. They do
|
|
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
|
|
155
|
-
*
|
|
156
|
-
*
|
|
157
|
-
*
|
|
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`.
|
package/dist/provider.d.ts.map
CHANGED
|
@@ -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;
|
|
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', {
|
|
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
|
-
|
|
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';
|
package/dist/storage.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../src/storage.ts"],"names":[],"mappings":"AAAA
|
|
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.
|
|
420
|
-
*
|
|
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. */
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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
|
|
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
|
|
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.
|
|
34
|
-
"@molecule/api-code-sandbox": "1.2.
|
|
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.
|
|
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://
|
|
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
|
}
|