edgeaegis 2026.10.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.
Files changed (158) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +10 -0
  3. package/README.md +215 -0
  4. package/config.yml +29 -0
  5. package/origin/cloudflare/app/config.yml +2 -0
  6. package/origin/cloudflare/app/index.js +4 -0
  7. package/origin/edgeone/app/config.yml +2 -0
  8. package/origin/edgeone/app/index.js +4 -0
  9. package/origin/esa/app/config.yml +2 -0
  10. package/origin/esa/app/index.js +4 -0
  11. package/origin/netlify/app/config.yml +2 -0
  12. package/origin/netlify/app/index.js +4 -0
  13. package/origin/vercel/app/config.yml +2 -0
  14. package/origin/vercel/app/index.js +4 -0
  15. package/package.json +123 -0
  16. package/respond/403.html +2 -0
  17. package/respond/403.json +1 -0
  18. package/rules/allowlist.yml +2 -0
  19. package/rules/emergency.conf +4 -0
  20. package/rules/local.conf +2 -0
  21. package/rules/seclang-bundle.json +360 -0
  22. package/rules/seclang-upstreams.json +14 -0
  23. package/rules/setup.conf +15 -0
  24. package/secret/credentials.example.yml +7 -0
  25. package/secret/relay-server.example.yml +10 -0
  26. package/tools/.build/scr/adapters/cloudflare/runtime.d.ts +18 -0
  27. package/tools/.build/scr/adapters/cloudflare/runtime.js +16 -0
  28. package/tools/.build/scr/adapters/cloudflare/runtime.js.map +1 -0
  29. package/tools/.build/scr/adapters/cloudflare/worker.js +25 -0
  30. package/tools/.build/scr/adapters/edgeone/worker.js +7 -0
  31. package/tools/.build/scr/adapters/esa/worker.js +5 -0
  32. package/tools/.build/scr/adapters/forward.d.ts +4 -0
  33. package/tools/.build/scr/adapters/forward.js +25 -0
  34. package/tools/.build/scr/adapters/forward.js.map +1 -0
  35. package/tools/.build/scr/adapters/handler.js +39 -0
  36. package/tools/.build/scr/adapters/ingress.d.ts +10 -0
  37. package/tools/.build/scr/adapters/ingress.js +62 -0
  38. package/tools/.build/scr/adapters/ingress.js.map +1 -0
  39. package/tools/.build/scr/adapters/netlify/worker.js +7 -0
  40. package/tools/.build/scr/adapters/runtime.d.ts +33 -0
  41. package/tools/.build/scr/adapters/runtime.js +50 -0
  42. package/tools/.build/scr/adapters/runtime.js.map +1 -0
  43. package/tools/.build/scr/adapters/vercel/worker.js +7 -0
  44. package/tools/.build/scr/cli/config.d.ts +2 -0
  45. package/tools/.build/scr/cli/config.js +23 -0
  46. package/tools/.build/scr/cli/config.js.map +1 -0
  47. package/tools/.build/scr/cli/deployment.d.ts +15 -0
  48. package/tools/.build/scr/cli/deployment.js +108 -0
  49. package/tools/.build/scr/cli/deployment.js.map +1 -0
  50. package/tools/.build/scr/cli/init.d.ts +2 -0
  51. package/tools/.build/scr/cli/init.js +62 -0
  52. package/tools/.build/scr/cli/init.js.map +1 -0
  53. package/tools/.build/scr/cli/main.d.ts +2 -0
  54. package/tools/.build/scr/cli/main.js +99 -0
  55. package/tools/.build/scr/cli/main.js.map +1 -0
  56. package/tools/.build/scr/cli/relay-serve.d.ts +1 -0
  57. package/tools/.build/scr/cli/relay-serve.js +48 -0
  58. package/tools/.build/scr/cli/relay-serve.js.map +1 -0
  59. package/tools/.build/scr/cli/responses.d.ts +2 -0
  60. package/tools/.build/scr/cli/responses.js +31 -0
  61. package/tools/.build/scr/cli/responses.js.map +1 -0
  62. package/tools/.build/scr/cli/serve.d.ts +1 -0
  63. package/tools/.build/scr/cli/serve.js +132 -0
  64. package/tools/.build/scr/cli/serve.js.map +1 -0
  65. package/tools/.build/scr/config.d.ts +39 -0
  66. package/tools/.build/scr/config.js +89 -0
  67. package/tools/.build/scr/config.js.map +1 -0
  68. package/tools/.build/scr/core/types.d.ts +27 -0
  69. package/tools/.build/scr/core/types.js +34 -0
  70. package/tools/.build/scr/core/types.js.map +1 -0
  71. package/tools/.build/scr/core/version.d.ts +1 -0
  72. package/tools/.build/scr/core/version.js +3 -0
  73. package/tools/.build/scr/core/version.js.map +1 -0
  74. package/tools/.build/scr/http-boundary/index.d.ts +19 -0
  75. package/tools/.build/scr/http-boundary/index.js +173 -0
  76. package/tools/.build/scr/http-boundary/index.js.map +1 -0
  77. package/tools/.build/scr/http-boundary/json.d.ts +2 -0
  78. package/tools/.build/scr/http-boundary/json.js +90 -0
  79. package/tools/.build/scr/http-boundary/json.js.map +1 -0
  80. package/tools/.build/scr/origin/relay.d.ts +20 -0
  81. package/tools/.build/scr/origin/relay.js +221 -0
  82. package/tools/.build/scr/origin/relay.js.map +1 -0
  83. package/tools/.build/scr/origin/replay-node.d.ts +8 -0
  84. package/tools/.build/scr/origin/replay-node.js +36 -0
  85. package/tools/.build/scr/origin/replay-node.js.map +1 -0
  86. package/tools/.build/scr/origin/types.d.ts +18 -0
  87. package/tools/.build/scr/origin/types.js +2 -0
  88. package/tools/.build/scr/origin/types.js.map +1 -0
  89. package/tools/.build/scr/runtime/allowlist.d.ts +21 -0
  90. package/tools/.build/scr/runtime/allowlist.js +84 -0
  91. package/tools/.build/scr/runtime/allowlist.js.map +1 -0
  92. package/tools/.build/scr/runtime/browser-cache.d.ts +7 -0
  93. package/tools/.build/scr/runtime/browser-cache.js +50 -0
  94. package/tools/.build/scr/runtime/browser-cache.js.map +1 -0
  95. package/tools/.build/scr/runtime/error-pages.d.ts +10 -0
  96. package/tools/.build/scr/runtime/error-pages.js +72 -0
  97. package/tools/.build/scr/runtime/error-pages.js.map +1 -0
  98. package/tools/.build/scr/runtime/index.d.ts +54 -0
  99. package/tools/.build/scr/runtime/index.js +355 -0
  100. package/tools/.build/scr/runtime/index.js.map +1 -0
  101. package/tools/.build/scr/runtime/node.d.ts +3 -0
  102. package/tools/.build/scr/runtime/node.js +97 -0
  103. package/tools/.build/scr/runtime/node.js.map +1 -0
  104. package/tools/.build/scr/runtime/proxy.d.ts +12 -0
  105. package/tools/.build/scr/runtime/proxy.js +177 -0
  106. package/tools/.build/scr/runtime/proxy.js.map +1 -0
  107. package/tools/.build/scr/runtime/stream.d.ts +8 -0
  108. package/tools/.build/scr/runtime/stream.js +72 -0
  109. package/tools/.build/scr/runtime/stream.js.map +1 -0
  110. package/tools/.build/scr/seclang/body.d.ts +13 -0
  111. package/tools/.build/scr/seclang/body.js +109 -0
  112. package/tools/.build/scr/seclang/body.js.map +1 -0
  113. package/tools/.build/scr/seclang/bytes.d.ts +5 -0
  114. package/tools/.build/scr/seclang/bytes.js +38 -0
  115. package/tools/.build/scr/seclang/bytes.js.map +1 -0
  116. package/tools/.build/scr/seclang/index.d.ts +166 -0
  117. package/tools/.build/scr/seclang/index.js +1519 -0
  118. package/tools/.build/scr/seclang/index.js.map +1 -0
  119. package/tools/.build/scr/seclang/json.d.ts +2 -0
  120. package/tools/.build/scr/seclang/json.js +87 -0
  121. package/tools/.build/scr/seclang/json.js.map +1 -0
  122. package/tools/.build/scr/seclang/libinjection.d.ts +9 -0
  123. package/tools/.build/scr/seclang/libinjection.js +59 -0
  124. package/tools/.build/scr/seclang/libinjection.js.map +1 -0
  125. package/tools/.build/scr/seclang/node.d.ts +22 -0
  126. package/tools/.build/scr/seclang/node.js +113 -0
  127. package/tools/.build/scr/seclang/node.js.map +1 -0
  128. package/tools/.build/scr/seclang/pcre2.d.ts +23 -0
  129. package/tools/.build/scr/seclang/pcre2.js +153 -0
  130. package/tools/.build/scr/seclang/pcre2.js.map +1 -0
  131. package/tools/.build/scr/seclang/sources.d.ts +6 -0
  132. package/tools/.build/scr/seclang/sources.js +59 -0
  133. package/tools/.build/scr/seclang/sources.js.map +1 -0
  134. package/tools/.build/scr/seclang/state.d.ts +17 -0
  135. package/tools/.build/scr/seclang/state.js +53 -0
  136. package/tools/.build/scr/seclang/state.js.map +1 -0
  137. package/tools/.build/scr/seclang/syntax.d.ts +9 -0
  138. package/tools/.build/scr/seclang/syntax.js +74 -0
  139. package/tools/.build/scr/seclang/syntax.js.map +1 -0
  140. package/tools/.build/scr/seclang/transforms.d.ts +3 -0
  141. package/tools/.build/scr/seclang/transforms.js +157 -0
  142. package/tools/.build/scr/seclang/transforms.js.map +1 -0
  143. package/tools/.build/scr/seclang/unicode.d.ts +2 -0
  144. package/tools/.build/scr/seclang/unicode.js +19 -0
  145. package/tools/.build/scr/seclang/unicode.js.map +1 -0
  146. package/tools/.build/scr/seclang/vendor/LIBINJECTION-LICENSE +33 -0
  147. package/tools/.build/scr/seclang/vendor/PCRE2-NOTICE +47 -0
  148. package/tools/.build/scr/seclang/vendor/PCRE2-WRAPPER-LICENSE +21 -0
  149. package/tools/.build/scr/seclang/vendor/UNICODE-DATA-NOTICE +6 -0
  150. package/tools/.build/scr/seclang/vendor/libinjection.json +7 -0
  151. package/tools/.build/scr/seclang/vendor/libinjection.wasm +0 -0
  152. package/tools/.build/scr/seclang/vendor/pcre2.json +7 -0
  153. package/tools/.build/scr/seclang/vendor/pcre2.wasm +0 -0
  154. package/tools/.build/scr/seclang/vendor/unicode.json +378 -0
  155. package/tools/build-platform.mjs +199 -0
  156. package/tools/platform-command.mjs +59 -0
  157. package/tools/sync-native-seclang.mjs +155 -0
  158. package/tools/verify-full-crs.mjs +118 -0
@@ -0,0 +1,378 @@
1
+ {
2
+ "source": "owasp-modsecurity/ModSecurity/unicode.mapping",
3
+ "sourceBlob": "2654c4a619bd585de547d0e4eeecec5753d56eeb",
4
+ "sha256": "5e4500ef82e45c49d8edd9513648939710d6c8cc2d5997513b32866dc5d9be23",
5
+ "codepage": 20127,
6
+ "mapping": {
7
+ "160": 32,
8
+ "161": 33,
9
+ "162": 99,
10
+ "164": 36,
11
+ "165": 89,
12
+ "166": 124,
13
+ "169": 67,
14
+ "170": 97,
15
+ "171": 60,
16
+ "173": 45,
17
+ "174": 82,
18
+ "178": 50,
19
+ "179": 51,
20
+ "183": 46,
21
+ "184": 44,
22
+ "185": 49,
23
+ "186": 111,
24
+ "187": 62,
25
+ "192": 65,
26
+ "193": 65,
27
+ "194": 65,
28
+ "195": 65,
29
+ "196": 65,
30
+ "197": 65,
31
+ "198": 65,
32
+ "199": 67,
33
+ "200": 69,
34
+ "201": 69,
35
+ "202": 69,
36
+ "203": 69,
37
+ "204": 73,
38
+ "205": 73,
39
+ "206": 73,
40
+ "207": 73,
41
+ "208": 68,
42
+ "209": 78,
43
+ "210": 79,
44
+ "211": 79,
45
+ "212": 79,
46
+ "213": 79,
47
+ "214": 79,
48
+ "216": 79,
49
+ "217": 85,
50
+ "218": 85,
51
+ "219": 85,
52
+ "220": 85,
53
+ "221": 89,
54
+ "224": 97,
55
+ "225": 97,
56
+ "226": 97,
57
+ "227": 97,
58
+ "228": 97,
59
+ "229": 97,
60
+ "230": 97,
61
+ "231": 99,
62
+ "232": 101,
63
+ "233": 101,
64
+ "234": 101,
65
+ "235": 101,
66
+ "236": 105,
67
+ "237": 105,
68
+ "238": 105,
69
+ "239": 105,
70
+ "241": 110,
71
+ "242": 111,
72
+ "243": 111,
73
+ "244": 111,
74
+ "245": 111,
75
+ "246": 111,
76
+ "248": 111,
77
+ "249": 117,
78
+ "250": 117,
79
+ "251": 117,
80
+ "252": 117,
81
+ "253": 121,
82
+ "255": 121,
83
+ "256": 65,
84
+ "257": 97,
85
+ "258": 65,
86
+ "259": 97,
87
+ "260": 65,
88
+ "261": 97,
89
+ "262": 67,
90
+ "263": 99,
91
+ "264": 67,
92
+ "265": 99,
93
+ "266": 67,
94
+ "267": 99,
95
+ "268": 67,
96
+ "269": 99,
97
+ "270": 68,
98
+ "271": 100,
99
+ "272": 68,
100
+ "273": 100,
101
+ "274": 69,
102
+ "275": 101,
103
+ "276": 69,
104
+ "277": 101,
105
+ "278": 69,
106
+ "279": 101,
107
+ "280": 69,
108
+ "281": 101,
109
+ "282": 69,
110
+ "283": 101,
111
+ "284": 71,
112
+ "285": 103,
113
+ "286": 71,
114
+ "287": 103,
115
+ "288": 71,
116
+ "289": 103,
117
+ "290": 71,
118
+ "291": 103,
119
+ "292": 72,
120
+ "293": 104,
121
+ "294": 72,
122
+ "295": 104,
123
+ "296": 73,
124
+ "297": 105,
125
+ "298": 73,
126
+ "299": 105,
127
+ "300": 73,
128
+ "301": 105,
129
+ "302": 73,
130
+ "303": 105,
131
+ "304": 73,
132
+ "305": 105,
133
+ "308": 74,
134
+ "309": 106,
135
+ "310": 75,
136
+ "311": 107,
137
+ "313": 76,
138
+ "314": 108,
139
+ "315": 76,
140
+ "316": 108,
141
+ "317": 76,
142
+ "318": 108,
143
+ "321": 76,
144
+ "322": 108,
145
+ "323": 78,
146
+ "324": 110,
147
+ "325": 78,
148
+ "326": 110,
149
+ "327": 78,
150
+ "328": 110,
151
+ "332": 79,
152
+ "333": 111,
153
+ "334": 79,
154
+ "335": 111,
155
+ "336": 79,
156
+ "337": 111,
157
+ "338": 79,
158
+ "339": 111,
159
+ "340": 82,
160
+ "341": 114,
161
+ "342": 82,
162
+ "343": 114,
163
+ "344": 82,
164
+ "345": 114,
165
+ "346": 83,
166
+ "347": 115,
167
+ "348": 83,
168
+ "349": 115,
169
+ "350": 83,
170
+ "351": 115,
171
+ "352": 83,
172
+ "353": 115,
173
+ "354": 84,
174
+ "355": 116,
175
+ "356": 84,
176
+ "357": 116,
177
+ "358": 84,
178
+ "359": 116,
179
+ "360": 85,
180
+ "361": 117,
181
+ "362": 85,
182
+ "363": 117,
183
+ "364": 85,
184
+ "365": 117,
185
+ "366": 85,
186
+ "367": 117,
187
+ "368": 85,
188
+ "369": 117,
189
+ "370": 85,
190
+ "371": 117,
191
+ "372": 87,
192
+ "373": 119,
193
+ "374": 89,
194
+ "375": 121,
195
+ "376": 89,
196
+ "377": 90,
197
+ "379": 90,
198
+ "380": 122,
199
+ "381": 90,
200
+ "382": 122,
201
+ "384": 98,
202
+ "393": 68,
203
+ "401": 70,
204
+ "402": 102,
205
+ "407": 73,
206
+ "410": 108,
207
+ "415": 79,
208
+ "416": 79,
209
+ "417": 111,
210
+ "427": 116,
211
+ "430": 84,
212
+ "431": 85,
213
+ "432": 117,
214
+ "438": 122,
215
+ "461": 65,
216
+ "462": 97,
217
+ "463": 73,
218
+ "464": 105,
219
+ "465": 79,
220
+ "466": 111,
221
+ "467": 85,
222
+ "468": 117,
223
+ "469": 85,
224
+ "470": 117,
225
+ "471": 85,
226
+ "472": 117,
227
+ "473": 85,
228
+ "474": 117,
229
+ "475": 85,
230
+ "476": 117,
231
+ "478": 65,
232
+ "479": 97,
233
+ "484": 71,
234
+ "485": 103,
235
+ "486": 71,
236
+ "487": 103,
237
+ "488": 75,
238
+ "489": 107,
239
+ "490": 79,
240
+ "491": 111,
241
+ "492": 79,
242
+ "493": 111,
243
+ "496": 106,
244
+ "609": 103,
245
+ "697": 39,
246
+ "698": 34,
247
+ "700": 39,
248
+ "708": 94,
249
+ "710": 94,
250
+ "712": 39,
251
+ "715": 96,
252
+ "717": 95,
253
+ "732": 126,
254
+ "768": 96,
255
+ "770": 94,
256
+ "771": 126,
257
+ "782": 34,
258
+ "817": 95,
259
+ "818": 95,
260
+ "8192": 32,
261
+ "8193": 32,
262
+ "8194": 32,
263
+ "8195": 32,
264
+ "8196": 32,
265
+ "8197": 32,
266
+ "8198": 32,
267
+ "8208": 45,
268
+ "8209": 45,
269
+ "8211": 45,
270
+ "8212": 45,
271
+ "8216": 39,
272
+ "8217": 39,
273
+ "8218": 44,
274
+ "8220": 34,
275
+ "8221": 34,
276
+ "8222": 34,
277
+ "8226": 46,
278
+ "8230": 46,
279
+ "8242": 39,
280
+ "8245": 96,
281
+ "8249": 60,
282
+ "8250": 62,
283
+ "8482": 84,
284
+ "65281": 33,
285
+ "65282": 34,
286
+ "65283": 35,
287
+ "65284": 36,
288
+ "65285": 37,
289
+ "65286": 38,
290
+ "65287": 39,
291
+ "65288": 40,
292
+ "65289": 41,
293
+ "65290": 42,
294
+ "65291": 43,
295
+ "65292": 44,
296
+ "65293": 45,
297
+ "65294": 46,
298
+ "65295": 47,
299
+ "65296": 48,
300
+ "65297": 49,
301
+ "65298": 50,
302
+ "65299": 51,
303
+ "65300": 52,
304
+ "65301": 53,
305
+ "65302": 54,
306
+ "65303": 55,
307
+ "65304": 56,
308
+ "65305": 57,
309
+ "65306": 58,
310
+ "65307": 59,
311
+ "65308": 60,
312
+ "65309": 61,
313
+ "65310": 62,
314
+ "65312": 64,
315
+ "65313": 65,
316
+ "65314": 66,
317
+ "65315": 67,
318
+ "65316": 68,
319
+ "65317": 69,
320
+ "65318": 70,
321
+ "65319": 71,
322
+ "65320": 72,
323
+ "65321": 73,
324
+ "65322": 74,
325
+ "65323": 75,
326
+ "65324": 76,
327
+ "65325": 77,
328
+ "65326": 78,
329
+ "65327": 79,
330
+ "65328": 80,
331
+ "65329": 81,
332
+ "65330": 82,
333
+ "65331": 83,
334
+ "65332": 84,
335
+ "65333": 85,
336
+ "65334": 86,
337
+ "65335": 87,
338
+ "65336": 88,
339
+ "65337": 89,
340
+ "65338": 90,
341
+ "65339": 91,
342
+ "65340": 92,
343
+ "65341": 93,
344
+ "65342": 94,
345
+ "65343": 95,
346
+ "65344": 96,
347
+ "65345": 97,
348
+ "65346": 98,
349
+ "65347": 99,
350
+ "65348": 100,
351
+ "65349": 101,
352
+ "65350": 102,
353
+ "65351": 103,
354
+ "65352": 104,
355
+ "65353": 105,
356
+ "65354": 106,
357
+ "65355": 107,
358
+ "65356": 108,
359
+ "65357": 109,
360
+ "65358": 110,
361
+ "65359": 111,
362
+ "65360": 112,
363
+ "65361": 113,
364
+ "65362": 114,
365
+ "65363": 115,
366
+ "65364": 116,
367
+ "65365": 117,
368
+ "65366": 118,
369
+ "65367": 119,
370
+ "65368": 120,
371
+ "65369": 121,
372
+ "65370": 122,
373
+ "65371": 123,
374
+ "65372": 124,
375
+ "65373": 125,
376
+ "65374": 126
377
+ }
378
+ }
@@ -0,0 +1,199 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { dirname, isAbsolute, join, relative, resolve } from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+ import { build } from "esbuild";
5
+ import { readCredentials, readData } from "./.build/scr/cli/config.js";
6
+ import { readDeployment } from "./.build/scr/cli/deployment.js";
7
+ import { readResponsePages } from "./.build/scr/cli/responses.js";
8
+ import { compileSecLang } from "./.build/scr/seclang/index.js";
9
+ import { loadSecLangDeployment } from "./.build/scr/seclang/node.js";
10
+
11
+ const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
12
+ export async function buildPlatform(
13
+ platform,
14
+ configFile = resolve("config.yml"),
15
+ outputDirectory = resolve(dirname(configFile), "tools/.build", platform),
16
+ ) {
17
+ if (!["cloudflare", "vercel", "netlify", "esa", "edgeone"].includes(platform))
18
+ throw new Error("Unknown deployment platform");
19
+ const { config, businesses, originRoot, platformRoot } = await readDeployment(
20
+ configFile,
21
+ platform,
22
+ );
23
+ const credentials = await readCredentials(config.secretFile),
24
+ native = await loadSecLangDeployment(
25
+ config.secLangFile,
26
+ config.localRulesFile,
27
+ config.setupRulesFile,
28
+ );
29
+ const program = compileSecLang(native.secLang, { ...native.secLangOptions, strict: true });
30
+ program.dispose();
31
+ const data = {
32
+ config,
33
+ credentials,
34
+ source: native.secLang,
35
+ files: native.secLangOptions.files,
36
+ allowlist: config.allowlistFile ? await readData(config.allowlistFile) : [],
37
+ errorPages: config.responses
38
+ ? await readResponsePages(config.responses.directory, config.responses.contentSecurityPolicy)
39
+ : {},
40
+ };
41
+ // Only the selected platform's business is bundled.
42
+ const directory = resolve(outputDirectory);
43
+ await mkdir(directory, { recursive: true });
44
+ const rel = (path) => JSON.stringify(path.replaceAll("\\", "/"));
45
+ const imports = [],
46
+ transports = [];
47
+ for (const [name, { settings, businessFile }] of Object.entries(businesses)) {
48
+ const id = imports.length;
49
+ if (settings.mode === "function") {
50
+ imports.push(`import business${id} from ${rel(businessFile)};`);
51
+ transports.push(
52
+ `${JSON.stringify(name)}:(input,init)=>Promise.resolve(business${id}.fetch(new Request(input,init)))`,
53
+ );
54
+ } else if (settings.mode === "proxy")
55
+ transports.push(`${JSON.stringify(name)}:(input,init)=>fetch(input,init)`);
56
+ else {
57
+ imports.push(
58
+ `import {createRelayTransport as createRelay${id}}from ${rel(resolve(root, "tools/.build/scr/origin/relay.js"))};const transport${id}=createRelay${id}(${JSON.stringify({ endpoint: settings.endpoint, serverPublicKey: await readData(settings.publicKeyFile, 16384), authenticationKey: await readData(settings.authenticationKeyFile, 4096), maxBytes: config.limits?.maxBodyBytes ?? 8388608 })});`,
59
+ );
60
+ transports.push(
61
+ `${JSON.stringify(name)}:async(input,init)=>(await transport${id})(input,init)`,
62
+ );
63
+ }
64
+ }
65
+ const origin = `${imports.join("\n")}\nexport default {${transports.join(",")}};`;
66
+ const wasm = [];
67
+ for (const name of ["pcre2", "libinjection"])
68
+ wasm.push(await readFile(resolve(root, "tools/.build/scr/seclang/vendor", `${name}.wasm`)));
69
+ const wasmSource =
70
+ platform === "cloudflare"
71
+ ? `import PCRE2 from './pcre2.wasm';import INJECTION from './libinjection.wasm';export{PCRE2,INJECTION};`
72
+ : `const decode=s=>Uint8Array.from(atob(s),c=>c.charCodeAt(0));export const PCRE2=decode('${wasm[0].toString("base64")}'),INJECTION=decode('${wasm[1].toString("base64")}');`;
73
+ const allowed = platformRoot;
74
+ const result = await build({
75
+ entryPoints: [resolve(root, `tools/.build/scr/adapters/${platform}/worker.js`)],
76
+ bundle: true,
77
+ write: false,
78
+ metafile: true,
79
+ format: "esm",
80
+ platform: "browser",
81
+ target: "es2022",
82
+ outdir: directory,
83
+ sourcemap: false,
84
+ logLevel: "silent",
85
+ external: ["*.wasm"],
86
+ plugins: [
87
+ {
88
+ name: "private-project-assets",
89
+ setup(api) {
90
+ api.onResolve({ filter: /^edgeaegis:/ }, (args) => ({
91
+ path: args.path,
92
+ namespace: "project",
93
+ }));
94
+ api.onLoad({ filter: /.*/, namespace: "project" }, (args) => ({
95
+ contents:
96
+ args.path === "edgeaegis:deployment"
97
+ ? `export default ${JSON.stringify(data)};`
98
+ : args.path === "edgeaegis:origin"
99
+ ? origin
100
+ : wasmSource,
101
+ loader: "js",
102
+ resolveDir: directory,
103
+ }));
104
+ // Reject even transitive imports of another platform's business files.
105
+ api.onLoad({ filter: /.*/ }, (args) => {
106
+ const inside = relative(originRoot, args.path);
107
+ if (!inside.startsWith("..") && !isAbsolute(inside)) {
108
+ const own = relative(allowed, args.path);
109
+ if (own.startsWith("..") || isAbsolute(own))
110
+ throw new Error("Cross-platform origin import is forbidden");
111
+ }
112
+ return undefined;
113
+ });
114
+ },
115
+ },
116
+ ],
117
+ });
118
+ for (const output of result.outputFiles)
119
+ await writeFile(output.path, output.contents, { mode: 0o600 });
120
+ if (platform === "cloudflare")
121
+ for (let i = 0; i < wasm.length; i++)
122
+ await writeFile(join(directory, `${i ? "libinjection" : "pcre2"}.wasm`), wasm[i]);
123
+ if (Object.keys(result.metafile.inputs).some((path) => /secret\/relay\/private/.test(path)))
124
+ throw new Error("Relay private key must not enter a cloud build");
125
+ const deployDirectory = join(directory, "deploy");
126
+ await mkdir(deployDirectory, { recursive: true });
127
+ const code = result.outputFiles.find((file) => file.path.endsWith("worker.js")).contents;
128
+ const name = `edgeaegis-${config.tenant}-${config.service}`
129
+ .toLowerCase()
130
+ .replace(/[^a-z0-9-]/g, "-")
131
+ .slice(0, 63);
132
+ const put = async (path, content) => {
133
+ const file = join(deployDirectory, path);
134
+ await mkdir(dirname(file), { recursive: true });
135
+ await writeFile(file, content, { mode: 0o600 });
136
+ };
137
+ await put(
138
+ "package.json",
139
+ JSON.stringify({ private: true, type: "module", engines: { node: "24.x" } }),
140
+ );
141
+ if (platform === "cloudflare") {
142
+ await put("worker.js", code);
143
+ await put(
144
+ "wrangler.json",
145
+ JSON.stringify(
146
+ {
147
+ name,
148
+ main: "worker.js",
149
+ compatibility_date: "2026-10-01",
150
+ workers_dev: false,
151
+ preview_urls: false,
152
+ routes: [],
153
+ send_metrics: false,
154
+ no_bundle: true,
155
+ rules: [{ type: "CompiledWasm", globs: ["**/*.wasm"], fallthrough: false }],
156
+ },
157
+ null,
158
+ 2,
159
+ ),
160
+ );
161
+ for (let i = 0; i < wasm.length; i++)
162
+ await put(`${i ? "libinjection" : "pcre2"}.wasm`, wasm[i]);
163
+ } else if (platform === "vercel") {
164
+ await put("api/index.mjs", code);
165
+ await put(
166
+ "vercel.json",
167
+ JSON.stringify(
168
+ { version: 2, rewrites: [{ source: "/:path*", destination: "/api/index" }] },
169
+ null,
170
+ 2,
171
+ ),
172
+ );
173
+ } else if (platform === "netlify") {
174
+ await put("edge-functions/edgeaegis.js", code);
175
+ await mkdir(join(deployDirectory, "public"), { recursive: true });
176
+ await put("netlify.toml", '[build]\npublish = "public"\nedge_functions = "edge-functions"\n');
177
+ } else if (platform === "esa") {
178
+ await put("worker.js", code);
179
+ await put("esa.jsonc", JSON.stringify({ name, entry: "./worker.js" }, null, 2));
180
+ } else
181
+ await put(
182
+ "edge-functions/[[default]].js",
183
+ `${new TextDecoder().decode(code)}\nexport default onRequest;\n`,
184
+ );
185
+ return {
186
+ directory,
187
+ deployDirectory,
188
+ entry: join(directory, "worker.js"),
189
+ inputs: Object.keys(result.metafile.inputs),
190
+ bytes: result.outputFiles.reduce((n, file) => n + file.contents.length, 0),
191
+ };
192
+ }
193
+ if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
194
+ const result = await buildPlatform(
195
+ process.argv[2],
196
+ process.argv[3] ? resolve(process.argv[3]) : undefined,
197
+ );
198
+ console.log(JSON.stringify({ directory: result.directory, bytes: result.bytes }));
199
+ }
@@ -0,0 +1,59 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { readFile } from "node:fs/promises";
3
+ import { createRequire } from "node:module";
4
+ import { dirname, join, resolve } from "node:path";
5
+ import { fileURLToPath } from "node:url";
6
+ import { buildPlatform } from "./build-platform.mjs";
7
+ export async function platformCommand(
8
+ command,
9
+ platform,
10
+ file = "config.yml",
11
+ { plan = false } = {},
12
+ ) {
13
+ const providers = {
14
+ cloudflare: ["wrangler", "wrangler", ["dev"], ["deploy"]],
15
+ vercel: ["vercel", "vercel", ["dev"], ["deploy", "--prod"]],
16
+ netlify: ["netlify-cli", "netlify", ["dev"], ["deploy", "--prod", "--no-build"]],
17
+ esa: ["esa-cli", "esa-cli", ["dev"], ["deploy"]],
18
+ edgeone: ["edgeone", "edgeone", ["makers", "dev"], ["makers", "deploy"]],
19
+ };
20
+ if (!Object.hasOwn(providers, platform) || !["build", "start", "deploy"].includes(command))
21
+ throw Error("Unknown platform command");
22
+ const built = await buildPlatform(platform, resolve(file));
23
+ if (command === "build") return built;
24
+ const [packageName, tool, dev, deploy] = providers[platform],
25
+ args = [...(command === "start" ? dev : deploy)];
26
+ if (platform === "cloudflare") args.push("--config", "wrangler.json");
27
+ const result = { platform, tool, args, cwd: built.deployDirectory };
28
+ if (plan) return result;
29
+ let entry;
30
+ for (const location of [dirname(resolve(file)), resolve(dirname(file), "tools")])
31
+ try {
32
+ const require = createRequire(join(location, "package.json"));
33
+ const manifestFile = require.resolve(`${packageName}/package.json`),
34
+ manifest = JSON.parse(await readFile(manifestFile, "utf8"));
35
+ const bin = typeof manifest.bin === "string" ? manifest.bin : manifest.bin?.[tool];
36
+ if (bin) {
37
+ entry = resolve(dirname(manifestFile), bin);
38
+ break;
39
+ }
40
+ } catch {}
41
+ if (!entry)
42
+ throw Error(`Install ${packageName} in the deployment project before running ${tool}`);
43
+ execFileSync(process.execPath, [entry, ...args], {
44
+ cwd: result.cwd,
45
+ stdio: "inherit",
46
+ windowsHide: true,
47
+ });
48
+ return result;
49
+ }
50
+ if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) {
51
+ const [command, platform, ...rest] = process.argv.slice(2),
52
+ positional = rest.filter((v) => v !== "--plan");
53
+ if (positional.length > 1) throw Error("Unexpected command arguments");
54
+ console.log(
55
+ JSON.stringify(
56
+ await platformCommand(command, platform, positional[0], { plan: rest.includes("--plan") }),
57
+ ),
58
+ );
59
+ }