@foro-sh/foro 0.10.0 → 0.12.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 +6 -4
- package/dist/_generated-manifest-cases.d.ts +564 -70
- package/dist/_generated-manifest-cases.d.ts.map +1 -1
- package/dist/_generated-manifest-cases.js +612 -70
- package/dist/manifest-cases.d.ts +6 -4
- package/dist/manifest-cases.d.ts.map +1 -1
- package/dist/manifest-cases.js +1 -1
- package/package.json +3 -3
|
@@ -1,219 +1,713 @@
|
|
|
1
1
|
export declare const rawManifestCases: readonly [{
|
|
2
|
-
readonly name: "minimal
|
|
3
|
-
readonly
|
|
2
|
+
readonly name: "python-minimal";
|
|
3
|
+
readonly files: {
|
|
4
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n";
|
|
5
|
+
readonly "server.py": "";
|
|
6
|
+
};
|
|
7
|
+
readonly expect: {
|
|
8
|
+
readonly ok: true;
|
|
9
|
+
};
|
|
10
|
+
}, {
|
|
11
|
+
readonly name: "python-poetry-only-name";
|
|
12
|
+
readonly files: {
|
|
13
|
+
readonly "pyproject.toml": "[tool.poetry]\nname = \"my-server\"\n";
|
|
14
|
+
readonly "main.py": "";
|
|
15
|
+
};
|
|
4
16
|
readonly expect: {
|
|
5
17
|
readonly ok: true;
|
|
6
18
|
};
|
|
7
19
|
}, {
|
|
8
|
-
readonly name: "
|
|
9
|
-
readonly
|
|
20
|
+
readonly name: "python-explicit-entrypoint";
|
|
21
|
+
readonly files: {
|
|
22
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"src/server.py\"\n";
|
|
23
|
+
};
|
|
10
24
|
readonly expect: {
|
|
11
25
|
readonly ok: true;
|
|
12
26
|
};
|
|
13
27
|
}, {
|
|
14
|
-
readonly name: "all-fields";
|
|
15
|
-
readonly
|
|
28
|
+
readonly name: "python-all-fields";
|
|
29
|
+
readonly files: {
|
|
30
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nbuild_path = \"app\"\nentrypoint = \"server.py\"\nruntime = \"python\"\nruntime_version = \"3.11\"\nport = 9000\ndependency_manager = \"poetry\"\n";
|
|
31
|
+
};
|
|
16
32
|
readonly expect: {
|
|
17
33
|
readonly ok: true;
|
|
18
34
|
};
|
|
19
35
|
}, {
|
|
20
|
-
readonly name: "
|
|
21
|
-
readonly
|
|
36
|
+
readonly name: "python-requires-python-range";
|
|
37
|
+
readonly files: {
|
|
38
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\nrequires-python = \">=3.11,<3.13\"\n";
|
|
39
|
+
readonly "server.py": "";
|
|
40
|
+
};
|
|
22
41
|
readonly expect: {
|
|
23
42
|
readonly ok: true;
|
|
24
43
|
};
|
|
25
44
|
}, {
|
|
26
|
-
readonly name: "
|
|
27
|
-
readonly
|
|
45
|
+
readonly name: "python-requires-python-exclusion";
|
|
46
|
+
readonly files: {
|
|
47
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\nrequires-python = \">=3.11,!=3.13\"\n";
|
|
48
|
+
readonly "server.py": "";
|
|
49
|
+
};
|
|
50
|
+
readonly expect: {
|
|
51
|
+
readonly ok: true;
|
|
52
|
+
};
|
|
53
|
+
}, {
|
|
54
|
+
readonly name: "python-requires-python-excludes-every-supported-version-one-by-one";
|
|
55
|
+
readonly files: {
|
|
56
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\nrequires-python = \">=3.11,!=3.11,!=3.12,!=3.13\"\n";
|
|
57
|
+
readonly "server.py": "";
|
|
58
|
+
};
|
|
28
59
|
readonly expect: {
|
|
29
60
|
readonly ok: false;
|
|
30
|
-
readonly reason: "
|
|
61
|
+
readonly reason: "invalid_runtime_version";
|
|
31
62
|
};
|
|
32
63
|
}, {
|
|
33
|
-
readonly name: "
|
|
34
|
-
readonly
|
|
64
|
+
readonly name: "python-hyphen-inside-a-path-segment-is-fine";
|
|
65
|
+
readonly files: {
|
|
66
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"my-tools/mcp-server.py\"\n";
|
|
67
|
+
};
|
|
68
|
+
readonly expect: {
|
|
69
|
+
readonly ok: true;
|
|
70
|
+
};
|
|
71
|
+
}, {
|
|
72
|
+
readonly name: "python-scoped-unspellable-name-is-normalised";
|
|
73
|
+
readonly files: {
|
|
74
|
+
readonly "pyproject.toml": "[project]\nname = \"My_Server\"\n";
|
|
75
|
+
readonly "server.py": "";
|
|
76
|
+
};
|
|
77
|
+
readonly expect: {
|
|
78
|
+
readonly ok: true;
|
|
79
|
+
};
|
|
80
|
+
}, {
|
|
81
|
+
readonly name: "python-no-entry-file";
|
|
82
|
+
readonly files: {
|
|
83
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n";
|
|
84
|
+
};
|
|
35
85
|
readonly expect: {
|
|
36
86
|
readonly ok: false;
|
|
37
|
-
readonly reason: "
|
|
87
|
+
readonly reason: "invalid_entrypoint";
|
|
38
88
|
};
|
|
39
89
|
}, {
|
|
40
|
-
readonly name: "
|
|
41
|
-
readonly
|
|
90
|
+
readonly name: "python-entrypoint-traversal";
|
|
91
|
+
readonly files: {
|
|
92
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"../server.py\"\n";
|
|
93
|
+
};
|
|
42
94
|
readonly expect: {
|
|
43
95
|
readonly ok: false;
|
|
44
|
-
readonly reason: "
|
|
96
|
+
readonly reason: "invalid_entrypoint";
|
|
45
97
|
};
|
|
46
98
|
}, {
|
|
47
|
-
readonly name: "
|
|
48
|
-
readonly
|
|
99
|
+
readonly name: "python-entrypoint-absolute";
|
|
100
|
+
readonly files: {
|
|
101
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"/server.py\"\n";
|
|
102
|
+
};
|
|
49
103
|
readonly expect: {
|
|
50
104
|
readonly ok: false;
|
|
51
105
|
readonly reason: "invalid_entrypoint";
|
|
52
106
|
};
|
|
53
107
|
}, {
|
|
54
|
-
readonly name: "
|
|
55
|
-
readonly
|
|
108
|
+
readonly name: "python-entrypoint-shell-metachar";
|
|
109
|
+
readonly files: {
|
|
110
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py; rm -rf x\"\n";
|
|
111
|
+
};
|
|
56
112
|
readonly expect: {
|
|
57
113
|
readonly ok: false;
|
|
58
114
|
readonly reason: "invalid_entrypoint";
|
|
59
115
|
};
|
|
60
116
|
}, {
|
|
61
|
-
readonly name: "
|
|
62
|
-
readonly
|
|
117
|
+
readonly name: "python-entrypoint-leading-dash";
|
|
118
|
+
readonly files: {
|
|
119
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"--isolated\"\n";
|
|
120
|
+
};
|
|
63
121
|
readonly expect: {
|
|
64
122
|
readonly ok: false;
|
|
65
123
|
readonly reason: "invalid_entrypoint";
|
|
66
124
|
};
|
|
67
125
|
}, {
|
|
68
|
-
readonly name: "
|
|
69
|
-
readonly
|
|
126
|
+
readonly name: "python-entrypoint-leading-dash-nested";
|
|
127
|
+
readonly files: {
|
|
128
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"src/-rf.py\"\n";
|
|
129
|
+
};
|
|
70
130
|
readonly expect: {
|
|
71
131
|
readonly ok: false;
|
|
72
132
|
readonly reason: "invalid_entrypoint";
|
|
73
133
|
};
|
|
74
134
|
}, {
|
|
75
|
-
readonly name: "
|
|
76
|
-
readonly
|
|
135
|
+
readonly name: "python-build-path-traversal";
|
|
136
|
+
readonly files: {
|
|
137
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nbuild_path = \"../x\"\n";
|
|
138
|
+
};
|
|
77
139
|
readonly expect: {
|
|
78
140
|
readonly ok: false;
|
|
79
141
|
readonly reason: "invalid_build_path";
|
|
80
142
|
};
|
|
81
143
|
}, {
|
|
82
|
-
readonly name: "
|
|
83
|
-
readonly
|
|
144
|
+
readonly name: "python-build-path-shell-metachar";
|
|
145
|
+
readonly files: {
|
|
146
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nbuild_path = \". && whoami\"\n";
|
|
147
|
+
};
|
|
84
148
|
readonly expect: {
|
|
85
149
|
readonly ok: false;
|
|
86
150
|
readonly reason: "invalid_build_path";
|
|
87
151
|
};
|
|
88
152
|
}, {
|
|
89
|
-
readonly name: "
|
|
90
|
-
readonly
|
|
153
|
+
readonly name: "python-build-path-space";
|
|
154
|
+
readonly files: {
|
|
155
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nbuild_path = \"my services\"\n";
|
|
156
|
+
};
|
|
91
157
|
readonly expect: {
|
|
92
158
|
readonly ok: false;
|
|
93
159
|
readonly reason: "invalid_build_path";
|
|
94
160
|
};
|
|
95
161
|
}, {
|
|
96
|
-
readonly name: "
|
|
97
|
-
readonly
|
|
162
|
+
readonly name: "python-build-path-newline";
|
|
163
|
+
readonly files: {
|
|
164
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nbuild_path = \"app\\nUSER root\"\n";
|
|
165
|
+
};
|
|
98
166
|
readonly expect: {
|
|
99
167
|
readonly ok: false;
|
|
100
168
|
readonly reason: "invalid_build_path";
|
|
101
169
|
};
|
|
102
170
|
}, {
|
|
103
|
-
readonly name: "
|
|
104
|
-
readonly
|
|
171
|
+
readonly name: "python-build-path-leading-dash";
|
|
172
|
+
readonly files: {
|
|
173
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nbuild_path = \"-rf\"\n";
|
|
174
|
+
};
|
|
175
|
+
readonly expect: {
|
|
176
|
+
readonly ok: false;
|
|
177
|
+
readonly reason: "invalid_build_path";
|
|
178
|
+
};
|
|
179
|
+
}, {
|
|
180
|
+
readonly name: "python-runtime-version-outside-allowlist";
|
|
181
|
+
readonly files: {
|
|
182
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nruntime_version = \"3.9\"\n";
|
|
183
|
+
};
|
|
105
184
|
readonly expect: {
|
|
106
185
|
readonly ok: false;
|
|
107
186
|
readonly reason: "invalid_runtime_version";
|
|
108
187
|
};
|
|
109
188
|
}, {
|
|
110
|
-
readonly name: "
|
|
111
|
-
readonly
|
|
189
|
+
readonly name: "python-requires-python-excludes-every-supported-version";
|
|
190
|
+
readonly files: {
|
|
191
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\nrequires-python = \"==3.9\"\n";
|
|
192
|
+
readonly "server.py": "";
|
|
193
|
+
};
|
|
112
194
|
readonly expect: {
|
|
113
195
|
readonly ok: false;
|
|
114
|
-
readonly reason: "
|
|
196
|
+
readonly reason: "invalid_runtime_version";
|
|
115
197
|
};
|
|
116
198
|
}, {
|
|
117
|
-
readonly name: "runtime-version-from-another-runtime";
|
|
118
|
-
readonly
|
|
199
|
+
readonly name: "python-runtime-version-from-another-runtime";
|
|
200
|
+
readonly files: {
|
|
201
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nruntime_version = \"22\"\n";
|
|
202
|
+
};
|
|
119
203
|
readonly expect: {
|
|
120
204
|
readonly ok: false;
|
|
121
205
|
readonly reason: "invalid_runtime_version";
|
|
122
206
|
};
|
|
207
|
+
}, {
|
|
208
|
+
readonly name: "runtime-outside-allowlist";
|
|
209
|
+
readonly files: {
|
|
210
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nruntime = \"ruby\"\n";
|
|
211
|
+
};
|
|
212
|
+
readonly expect: {
|
|
213
|
+
readonly ok: false;
|
|
214
|
+
readonly reason: "invalid_runtime";
|
|
215
|
+
};
|
|
216
|
+
}, {
|
|
217
|
+
readonly name: "runtime-disagrees-with-the-file-it-was-read-from";
|
|
218
|
+
readonly files: {
|
|
219
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nruntime = \"node\"\n";
|
|
220
|
+
};
|
|
221
|
+
readonly expect: {
|
|
222
|
+
readonly ok: false;
|
|
223
|
+
readonly reason: "invalid_runtime";
|
|
224
|
+
};
|
|
225
|
+
}, {
|
|
226
|
+
readonly name: "both-config-files-and-neither-claims-the-runtime";
|
|
227
|
+
readonly files: {
|
|
228
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n";
|
|
229
|
+
readonly "package.json": "{\"name\": \"my-server\", \"main\": \"index.js\"}";
|
|
230
|
+
readonly "server.py": "";
|
|
231
|
+
};
|
|
232
|
+
readonly expect: {
|
|
233
|
+
readonly ok: false;
|
|
234
|
+
readonly reason: "invalid_runtime";
|
|
235
|
+
};
|
|
236
|
+
}, {
|
|
237
|
+
readonly name: "both-config-files-and-both-claim-the-runtime";
|
|
238
|
+
readonly files: {
|
|
239
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nruntime = \"python\"\n";
|
|
240
|
+
readonly "package.json": "{\"name\": \"my-server\", \"main\": \"index.js\", \"foro\": {\"runtime\": \"node\"}}";
|
|
241
|
+
readonly "server.py": "";
|
|
242
|
+
};
|
|
243
|
+
readonly expect: {
|
|
244
|
+
readonly ok: false;
|
|
245
|
+
readonly reason: "invalid_runtime";
|
|
246
|
+
};
|
|
247
|
+
}, {
|
|
248
|
+
readonly name: "both-config-files-python-claims-the-runtime";
|
|
249
|
+
readonly files: {
|
|
250
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nruntime = \"python\"\n";
|
|
251
|
+
readonly "package.json": "{\"name\": \"tooling-only\"}";
|
|
252
|
+
readonly "server.py": "";
|
|
253
|
+
};
|
|
254
|
+
readonly expect: {
|
|
255
|
+
readonly ok: true;
|
|
256
|
+
};
|
|
257
|
+
}, {
|
|
258
|
+
readonly name: "both-config-files-node-claims-the-runtime";
|
|
259
|
+
readonly files: {
|
|
260
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n";
|
|
261
|
+
readonly "package.json": "{\"name\": \"my-server\", \"main\": \"index.js\", \"foro\": {\"runtime\": \"node\"}}";
|
|
262
|
+
readonly "server.py": "";
|
|
263
|
+
};
|
|
264
|
+
readonly expect: {
|
|
265
|
+
readonly ok: true;
|
|
266
|
+
};
|
|
267
|
+
}, {
|
|
268
|
+
readonly name: "no-config-file-only-a-legacy-manifest";
|
|
269
|
+
readonly files: {
|
|
270
|
+
readonly "foro.yaml": "name: my-server\nentrypoint: server.py\n";
|
|
271
|
+
readonly "server.py": "";
|
|
272
|
+
};
|
|
273
|
+
readonly expect: {
|
|
274
|
+
readonly ok: false;
|
|
275
|
+
readonly reason: "missing_manifest";
|
|
276
|
+
};
|
|
123
277
|
}, {
|
|
124
278
|
readonly name: "unknown-field-stale-python-version";
|
|
125
|
-
readonly
|
|
279
|
+
readonly files: {
|
|
280
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\npython_version = \"3.13\"\n";
|
|
281
|
+
};
|
|
126
282
|
readonly expect: {
|
|
127
283
|
readonly ok: false;
|
|
128
284
|
readonly reason: "unknown_field";
|
|
129
285
|
};
|
|
130
286
|
}, {
|
|
131
287
|
readonly name: "unknown-field-typo";
|
|
132
|
-
readonly
|
|
288
|
+
readonly files: {
|
|
289
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nentrypoints = \"server.py\"\n";
|
|
290
|
+
};
|
|
133
291
|
readonly expect: {
|
|
134
292
|
readonly ok: false;
|
|
135
293
|
readonly reason: "unknown_field";
|
|
136
294
|
};
|
|
137
295
|
}, {
|
|
138
|
-
readonly name: "
|
|
139
|
-
readonly
|
|
296
|
+
readonly name: "unknown-field-name-belongs-to-the-package";
|
|
297
|
+
readonly files: {
|
|
298
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nname = \"other\"\n";
|
|
299
|
+
};
|
|
300
|
+
readonly expect: {
|
|
301
|
+
readonly ok: false;
|
|
302
|
+
readonly reason: "unknown_field";
|
|
303
|
+
};
|
|
304
|
+
}, {
|
|
305
|
+
readonly name: "port-too-low";
|
|
306
|
+
readonly files: {
|
|
307
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nport = 80\n";
|
|
308
|
+
};
|
|
309
|
+
readonly expect: {
|
|
310
|
+
readonly ok: false;
|
|
311
|
+
readonly reason: "invalid_port";
|
|
312
|
+
};
|
|
313
|
+
}, {
|
|
314
|
+
readonly name: "port-too-high";
|
|
315
|
+
readonly files: {
|
|
316
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nport = 70000\n";
|
|
317
|
+
};
|
|
140
318
|
readonly expect: {
|
|
141
319
|
readonly ok: false;
|
|
142
320
|
readonly reason: "invalid_port";
|
|
143
321
|
};
|
|
144
322
|
}, {
|
|
145
|
-
readonly name: "
|
|
146
|
-
readonly
|
|
323
|
+
readonly name: "port-sidecar-reserved";
|
|
324
|
+
readonly files: {
|
|
325
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nport = 8001\n";
|
|
326
|
+
};
|
|
147
327
|
readonly expect: {
|
|
148
328
|
readonly ok: false;
|
|
149
329
|
readonly reason: "invalid_port";
|
|
150
330
|
};
|
|
151
331
|
}, {
|
|
152
|
-
readonly name: "
|
|
153
|
-
readonly
|
|
332
|
+
readonly name: "port-gate-reserved";
|
|
333
|
+
readonly files: {
|
|
334
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nport = 8002\n";
|
|
335
|
+
};
|
|
154
336
|
readonly expect: {
|
|
155
337
|
readonly ok: false;
|
|
156
338
|
readonly reason: "invalid_port";
|
|
157
339
|
};
|
|
158
340
|
}, {
|
|
159
|
-
readonly name: "
|
|
160
|
-
readonly
|
|
341
|
+
readonly name: "port-non-integer";
|
|
342
|
+
readonly files: {
|
|
343
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\nport = \"abc\"\n";
|
|
344
|
+
};
|
|
161
345
|
readonly expect: {
|
|
162
346
|
readonly ok: false;
|
|
163
347
|
readonly reason: "invalid_port";
|
|
164
348
|
};
|
|
165
349
|
}, {
|
|
166
|
-
readonly name: "
|
|
167
|
-
readonly
|
|
350
|
+
readonly name: "dependency-manager-outside-allowlist";
|
|
351
|
+
readonly files: {
|
|
352
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\ndependency_manager = \"pipx\"\n";
|
|
353
|
+
};
|
|
168
354
|
readonly expect: {
|
|
169
355
|
readonly ok: false;
|
|
170
356
|
readonly reason: "invalid_dependency_manager";
|
|
171
357
|
};
|
|
172
358
|
}, {
|
|
173
|
-
readonly name: "
|
|
174
|
-
readonly
|
|
359
|
+
readonly name: "node-dependency-manager-on-python";
|
|
360
|
+
readonly files: {
|
|
361
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\ndependency_manager = \"npm\"\n";
|
|
362
|
+
};
|
|
175
363
|
readonly expect: {
|
|
176
364
|
readonly ok: false;
|
|
177
|
-
readonly reason: "
|
|
365
|
+
readonly reason: "invalid_dependency_manager";
|
|
178
366
|
};
|
|
179
367
|
}, {
|
|
180
|
-
readonly name: "
|
|
181
|
-
readonly
|
|
368
|
+
readonly name: "unparseable-pyproject";
|
|
369
|
+
readonly files: {
|
|
370
|
+
readonly "pyproject.toml": "[project\nname = \"my-server\"\n";
|
|
371
|
+
};
|
|
182
372
|
readonly expect: {
|
|
183
373
|
readonly ok: false;
|
|
184
374
|
readonly reason: "invalid_shape";
|
|
185
375
|
};
|
|
186
376
|
}, {
|
|
187
|
-
readonly name: "
|
|
188
|
-
readonly
|
|
377
|
+
readonly name: "node-minimal";
|
|
378
|
+
readonly files: {
|
|
379
|
+
readonly "package.json": "{\"name\": \"my-server\", \"main\": \"dist/index.js\"}";
|
|
380
|
+
};
|
|
381
|
+
readonly expect: {
|
|
382
|
+
readonly ok: true;
|
|
383
|
+
};
|
|
384
|
+
}, {
|
|
385
|
+
readonly name: "node-scoped-name";
|
|
386
|
+
readonly files: {
|
|
387
|
+
readonly "package.json": "{\"name\": \"@acme/my-server\", \"main\": \"dist/index.js\"}";
|
|
388
|
+
};
|
|
389
|
+
readonly expect: {
|
|
390
|
+
readonly ok: true;
|
|
391
|
+
};
|
|
392
|
+
}, {
|
|
393
|
+
readonly name: "node-bin-map";
|
|
394
|
+
readonly files: {
|
|
395
|
+
readonly "package.json": "{\"name\": \"my-server\", \"bin\": {\"my-server\": \"dist/cli.js\"}}";
|
|
396
|
+
};
|
|
397
|
+
readonly expect: {
|
|
398
|
+
readonly ok: true;
|
|
399
|
+
};
|
|
400
|
+
}, {
|
|
401
|
+
readonly name: "node-implicit-index";
|
|
402
|
+
readonly files: {
|
|
403
|
+
readonly "package.json": "{\"name\": \"my-server\"}";
|
|
404
|
+
readonly "index.js": "";
|
|
405
|
+
};
|
|
406
|
+
readonly expect: {
|
|
407
|
+
readonly ok: true;
|
|
408
|
+
};
|
|
409
|
+
}, {
|
|
410
|
+
readonly name: "node-engines-range";
|
|
411
|
+
readonly files: {
|
|
412
|
+
readonly "package.json": "{\"name\": \"my-server\", \"main\": \"index.js\", \"engines\": {\"node\": \">=22\"}}";
|
|
413
|
+
};
|
|
414
|
+
readonly expect: {
|
|
415
|
+
readonly ok: true;
|
|
416
|
+
};
|
|
417
|
+
}, {
|
|
418
|
+
readonly name: "node-engines-union-of-every-supported-major";
|
|
419
|
+
readonly files: {
|
|
420
|
+
readonly "package.json": "{\"name\": \"my-server\", \"main\": \"index.js\", \"engines\": {\"node\": \"^22 || ^24\"}}";
|
|
421
|
+
};
|
|
422
|
+
readonly expect: {
|
|
423
|
+
readonly ok: true;
|
|
424
|
+
};
|
|
425
|
+
}, {
|
|
426
|
+
readonly name: "node-engines-union-with-one-unsupported-branch";
|
|
427
|
+
readonly files: {
|
|
428
|
+
readonly "package.json": "{\"name\": \"my-server\", \"main\": \"index.js\", \"engines\": {\"node\": \"^20 || ^22\"}}";
|
|
429
|
+
};
|
|
430
|
+
readonly expect: {
|
|
431
|
+
readonly ok: true;
|
|
432
|
+
};
|
|
433
|
+
}, {
|
|
434
|
+
readonly name: "node-all-fields";
|
|
435
|
+
readonly files: {
|
|
436
|
+
readonly "package.json": "{\"name\": \"my-server\", \"main\": \"dist/index.js\", \"foro\": {\"runtime\": \"node\", \"runtime_version\": \"22\", \"port\": 9000, \"dependency_manager\": \"pnpm\"}}";
|
|
437
|
+
};
|
|
438
|
+
readonly expect: {
|
|
439
|
+
readonly ok: true;
|
|
440
|
+
};
|
|
441
|
+
}, {
|
|
442
|
+
readonly name: "node-no-entry-file";
|
|
443
|
+
readonly files: {
|
|
444
|
+
readonly "package.json": "{\"name\": \"my-server\"}";
|
|
445
|
+
};
|
|
446
|
+
readonly expect: {
|
|
447
|
+
readonly ok: false;
|
|
448
|
+
readonly reason: "invalid_entrypoint";
|
|
449
|
+
};
|
|
450
|
+
}, {
|
|
451
|
+
readonly name: "node-engines-excludes-every-supported-version";
|
|
452
|
+
readonly files: {
|
|
453
|
+
readonly "package.json": "{\"name\": \"my-server\", \"main\": \"index.js\", \"engines\": {\"node\": \"^20\"}}";
|
|
454
|
+
};
|
|
455
|
+
readonly expect: {
|
|
456
|
+
readonly ok: false;
|
|
457
|
+
readonly reason: "invalid_runtime_version";
|
|
458
|
+
};
|
|
459
|
+
}, {
|
|
460
|
+
readonly name: "node-runtime-version-from-another-runtime";
|
|
461
|
+
readonly files: {
|
|
462
|
+
readonly "package.json": "{\"name\": \"my-server\", \"main\": \"index.js\", \"foro\": {\"runtime_version\": \"3.12\"}}";
|
|
463
|
+
};
|
|
464
|
+
readonly expect: {
|
|
465
|
+
readonly ok: false;
|
|
466
|
+
readonly reason: "invalid_runtime_version";
|
|
467
|
+
};
|
|
468
|
+
}, {
|
|
469
|
+
readonly name: "python-dependency-manager-on-node";
|
|
470
|
+
readonly files: {
|
|
471
|
+
readonly "package.json": "{\"name\": \"my-server\", \"main\": \"index.js\", \"foro\": {\"dependency_manager\": \"uv\"}}";
|
|
472
|
+
};
|
|
473
|
+
readonly expect: {
|
|
474
|
+
readonly ok: false;
|
|
475
|
+
readonly reason: "invalid_dependency_manager";
|
|
476
|
+
};
|
|
477
|
+
}, {
|
|
478
|
+
readonly name: "unparseable-package-json";
|
|
479
|
+
readonly files: {
|
|
480
|
+
readonly "package.json": "{\"name\": ";
|
|
481
|
+
};
|
|
189
482
|
readonly expect: {
|
|
190
483
|
readonly ok: false;
|
|
191
484
|
readonly reason: "invalid_shape";
|
|
192
485
|
};
|
|
193
486
|
}, {
|
|
194
|
-
readonly name: "
|
|
195
|
-
readonly
|
|
487
|
+
readonly name: "python-egress-ip-entry";
|
|
488
|
+
readonly files: {
|
|
489
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"10.20.30.40:5432\"]\n";
|
|
490
|
+
};
|
|
491
|
+
readonly expect: {
|
|
492
|
+
readonly ok: true;
|
|
493
|
+
};
|
|
494
|
+
}, {
|
|
495
|
+
readonly name: "python-egress-cidr-entry";
|
|
496
|
+
readonly files: {
|
|
497
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"10.20.0.0/16:443\"]\n";
|
|
498
|
+
};
|
|
499
|
+
readonly expect: {
|
|
500
|
+
readonly ok: true;
|
|
501
|
+
};
|
|
502
|
+
}, {
|
|
503
|
+
readonly name: "python-egress-hostname-entry";
|
|
504
|
+
readonly files: {
|
|
505
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"sql.database.windows.net:1433\"]\n";
|
|
506
|
+
};
|
|
507
|
+
readonly expect: {
|
|
508
|
+
readonly ok: true;
|
|
509
|
+
};
|
|
510
|
+
}, {
|
|
511
|
+
readonly name: "python-egress-multiple-entries";
|
|
512
|
+
readonly files: {
|
|
513
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"sql.database.windows.net:1433\", \"10.20.30.40:5432\", \"10.20.0.0/16:443\"]\n";
|
|
514
|
+
};
|
|
515
|
+
readonly expect: {
|
|
516
|
+
readonly ok: true;
|
|
517
|
+
};
|
|
518
|
+
}, {
|
|
519
|
+
readonly name: "python-egress-empty-list-denies-everything";
|
|
520
|
+
readonly files: {
|
|
521
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = []\n";
|
|
522
|
+
};
|
|
523
|
+
readonly expect: {
|
|
524
|
+
readonly ok: true;
|
|
525
|
+
};
|
|
526
|
+
}, {
|
|
527
|
+
readonly name: "python-egress-missing-port";
|
|
528
|
+
readonly files: {
|
|
529
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"example.com\"]\n";
|
|
530
|
+
};
|
|
196
531
|
readonly expect: {
|
|
197
532
|
readonly ok: false;
|
|
198
|
-
readonly reason: "
|
|
533
|
+
readonly reason: "invalid_egress";
|
|
199
534
|
};
|
|
200
535
|
}, {
|
|
201
|
-
readonly name: "
|
|
202
|
-
readonly
|
|
536
|
+
readonly name: "python-egress-port-zero";
|
|
537
|
+
readonly files: {
|
|
538
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"example.com:0\"]\n";
|
|
539
|
+
};
|
|
203
540
|
readonly expect: {
|
|
204
541
|
readonly ok: false;
|
|
205
|
-
readonly reason: "
|
|
542
|
+
readonly reason: "invalid_egress";
|
|
206
543
|
};
|
|
207
544
|
}, {
|
|
208
|
-
readonly name: "
|
|
209
|
-
readonly
|
|
545
|
+
readonly name: "python-egress-port-too-high";
|
|
546
|
+
readonly files: {
|
|
547
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"example.com:65536\"]\n";
|
|
548
|
+
};
|
|
210
549
|
readonly expect: {
|
|
211
550
|
readonly ok: false;
|
|
212
|
-
readonly reason: "
|
|
551
|
+
readonly reason: "invalid_egress";
|
|
552
|
+
};
|
|
553
|
+
}, {
|
|
554
|
+
readonly name: "python-egress-blocked-mail-port";
|
|
555
|
+
readonly files: {
|
|
556
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"smtp.example.com:25\"]\n";
|
|
557
|
+
};
|
|
558
|
+
readonly expect: {
|
|
559
|
+
readonly ok: false;
|
|
560
|
+
readonly reason: "invalid_egress";
|
|
561
|
+
};
|
|
562
|
+
}, {
|
|
563
|
+
readonly name: "python-egress-metadata-endpoint";
|
|
564
|
+
readonly files: {
|
|
565
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"169.254.169.254:80\"]\n";
|
|
566
|
+
};
|
|
567
|
+
readonly expect: {
|
|
568
|
+
readonly ok: false;
|
|
569
|
+
readonly reason: "invalid_egress";
|
|
570
|
+
};
|
|
571
|
+
}, {
|
|
572
|
+
readonly name: "python-egress-whole-internet";
|
|
573
|
+
readonly files: {
|
|
574
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"0.0.0.0/0:443\"]\n";
|
|
575
|
+
};
|
|
576
|
+
readonly expect: {
|
|
577
|
+
readonly ok: false;
|
|
578
|
+
readonly reason: "invalid_egress";
|
|
579
|
+
};
|
|
580
|
+
}, {
|
|
581
|
+
readonly name: "python-egress-wide-range-swallows-a-reserved-one";
|
|
582
|
+
readonly files: {
|
|
583
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"172.16.0.0/12:443\"]\n";
|
|
584
|
+
};
|
|
585
|
+
readonly expect: {
|
|
586
|
+
readonly ok: false;
|
|
587
|
+
readonly reason: "invalid_egress";
|
|
588
|
+
};
|
|
589
|
+
}, {
|
|
590
|
+
readonly name: "python-egress-hostname-over-253-chars";
|
|
591
|
+
readonly files: {
|
|
592
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa.aaaa:443\"]\n";
|
|
593
|
+
};
|
|
594
|
+
readonly expect: {
|
|
595
|
+
readonly ok: false;
|
|
596
|
+
readonly reason: "invalid_egress";
|
|
597
|
+
};
|
|
598
|
+
}, {
|
|
599
|
+
readonly name: "python-egress-string-instead-of-list";
|
|
600
|
+
readonly files: {
|
|
601
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = \"example.com:443\"\n";
|
|
602
|
+
};
|
|
603
|
+
readonly expect: {
|
|
604
|
+
readonly ok: false;
|
|
605
|
+
readonly reason: "invalid_egress";
|
|
606
|
+
};
|
|
607
|
+
}, {
|
|
608
|
+
readonly name: "python-egress-over-entry-cap";
|
|
609
|
+
readonly files: {
|
|
610
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"h0.example.com:443\", \"h1.example.com:443\", \"h2.example.com:443\", \"h3.example.com:443\", \"h4.example.com:443\", \"h5.example.com:443\", \"h6.example.com:443\", \"h7.example.com:443\", \"h8.example.com:443\", \"h9.example.com:443\", \"h10.example.com:443\", \"h11.example.com:443\", \"h12.example.com:443\", \"h13.example.com:443\", \"h14.example.com:443\", \"h15.example.com:443\", \"h16.example.com:443\", \"h17.example.com:443\", \"h18.example.com:443\", \"h19.example.com:443\", \"h20.example.com:443\"]\n";
|
|
611
|
+
};
|
|
612
|
+
readonly expect: {
|
|
613
|
+
readonly ok: false;
|
|
614
|
+
readonly reason: "invalid_egress";
|
|
615
|
+
};
|
|
616
|
+
}, {
|
|
617
|
+
readonly name: "node-egress-non-string-entry";
|
|
618
|
+
readonly files: {
|
|
619
|
+
readonly "package.json": "{\"name\": \"my-server\", \"main\": \"index.js\", \"foro\": {\"egress\": [443]}}";
|
|
620
|
+
};
|
|
621
|
+
readonly expect: {
|
|
622
|
+
readonly ok: false;
|
|
623
|
+
readonly reason: "invalid_egress";
|
|
624
|
+
};
|
|
625
|
+
}, {
|
|
626
|
+
readonly name: "python-egress-shell-metacharacter";
|
|
627
|
+
readonly files: {
|
|
628
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"evil.com:443; rm -rf /\"]\n";
|
|
629
|
+
};
|
|
630
|
+
readonly expect: {
|
|
631
|
+
readonly ok: false;
|
|
632
|
+
readonly reason: "invalid_egress";
|
|
633
|
+
};
|
|
634
|
+
}, {
|
|
635
|
+
readonly name: "python-egress-embedded-whitespace";
|
|
636
|
+
readonly files: {
|
|
637
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"evil .com:443\"]\n";
|
|
638
|
+
};
|
|
639
|
+
readonly expect: {
|
|
640
|
+
readonly ok: false;
|
|
641
|
+
readonly reason: "invalid_egress";
|
|
213
642
|
};
|
|
214
643
|
}, {
|
|
215
|
-
readonly name: "
|
|
216
|
-
readonly
|
|
644
|
+
readonly name: "python-egress-embedded-newline";
|
|
645
|
+
readonly files: {
|
|
646
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"evil.com:443\\nother:80\"]\n";
|
|
647
|
+
};
|
|
648
|
+
readonly expect: {
|
|
649
|
+
readonly ok: false;
|
|
650
|
+
readonly reason: "invalid_egress";
|
|
651
|
+
};
|
|
652
|
+
}, {
|
|
653
|
+
readonly name: "python-egress-ipv6-literal";
|
|
654
|
+
readonly files: {
|
|
655
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"::1:443\"]\n";
|
|
656
|
+
};
|
|
657
|
+
readonly expect: {
|
|
658
|
+
readonly ok: false;
|
|
659
|
+
readonly reason: "invalid_egress";
|
|
660
|
+
};
|
|
661
|
+
}, {
|
|
662
|
+
readonly name: "python-egress-cidr-prefix-out-of-range";
|
|
663
|
+
readonly files: {
|
|
664
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"10.0.0.0/33:443\"]\n";
|
|
665
|
+
};
|
|
666
|
+
readonly expect: {
|
|
667
|
+
readonly ok: false;
|
|
668
|
+
readonly reason: "invalid_egress";
|
|
669
|
+
};
|
|
670
|
+
}, {
|
|
671
|
+
readonly name: "python-egress-link-local-range";
|
|
672
|
+
readonly files: {
|
|
673
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"169.254.0.0/16:443\"]\n";
|
|
674
|
+
};
|
|
675
|
+
readonly expect: {
|
|
676
|
+
readonly ok: false;
|
|
677
|
+
readonly reason: "invalid_egress";
|
|
678
|
+
};
|
|
679
|
+
}, {
|
|
680
|
+
readonly name: "python-egress-loopback";
|
|
681
|
+
readonly files: {
|
|
682
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"127.0.0.1:5432\"]\n";
|
|
683
|
+
};
|
|
684
|
+
readonly expect: {
|
|
685
|
+
readonly ok: false;
|
|
686
|
+
readonly reason: "invalid_egress";
|
|
687
|
+
};
|
|
688
|
+
}, {
|
|
689
|
+
readonly name: "python-egress-platform-bridge-network";
|
|
690
|
+
readonly files: {
|
|
691
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"172.20.0.5:5432\"]\n";
|
|
692
|
+
};
|
|
693
|
+
readonly expect: {
|
|
694
|
+
readonly ok: false;
|
|
695
|
+
readonly reason: "invalid_egress";
|
|
696
|
+
};
|
|
697
|
+
}, {
|
|
698
|
+
readonly name: "python-egress-submission-port";
|
|
699
|
+
readonly files: {
|
|
700
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"smtp.example.com:587\"]\n";
|
|
701
|
+
};
|
|
702
|
+
readonly expect: {
|
|
703
|
+
readonly ok: false;
|
|
704
|
+
readonly reason: "invalid_egress";
|
|
705
|
+
};
|
|
706
|
+
}, {
|
|
707
|
+
readonly name: "python-egress-private-ranges-stay-allowlistable";
|
|
708
|
+
readonly files: {
|
|
709
|
+
readonly "pyproject.toml": "[project]\nname = \"my-server\"\n\n[tool.foro]\nentrypoint = \"server.py\"\negress = [\"10.20.30.40:5432\", \"192.168.1.0/24:443\"]\n";
|
|
710
|
+
};
|
|
217
711
|
readonly expect: {
|
|
218
712
|
readonly ok: true;
|
|
219
713
|
};
|