@jimhoyd/urlcode 0.3.0

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 (254) hide show
  1. package/CONTRIBUTING.md +80 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +20 -0
  4. package/README.md +342 -0
  5. package/ROADMAP.md +248 -0
  6. package/SECURITY.md +40 -0
  7. package/data/agents/LICENSES/ai-robots-txt.txt +24 -0
  8. package/data/agents/LICENSES/crawler-user-agents.txt +23 -0
  9. package/data/agents/ai-crawlers.json +1240 -0
  10. package/data/agents/crawlers.json +10515 -0
  11. package/data/agents/index.d.ts +3 -0
  12. package/data/agents/index.js +2453 -0
  13. package/data/agents/monitoring.json +1520 -0
  14. package/data/agents/seo.json +3865 -0
  15. package/dist/BUILD-MANIFEST.json +60 -0
  16. package/dist/adapters.js +59 -0
  17. package/dist/agent-lists.js +59 -0
  18. package/dist/assets.js +129 -0
  19. package/dist/authoring.js +68 -0
  20. package/dist/aws.js +110 -0
  21. package/dist/build-cloudflare.js +164 -0
  22. package/dist/cli.js +185 -0
  23. package/dist/client-address.js +85 -0
  24. package/dist/cloudflare.js +165 -0
  25. package/dist/compliance-rules/baseline.js +98 -0
  26. package/dist/compliance-rules/privacy.js +38 -0
  27. package/dist/compliance-rules/shared.js +62 -0
  28. package/dist/compliance-rules/strict.js +61 -0
  29. package/dist/compliance.js +219 -0
  30. package/dist/config-worker.js +9 -0
  31. package/dist/config.js +172 -0
  32. package/dist/errors.js +8 -0
  33. package/dist/function-sources.js +54 -0
  34. package/dist/function-worker.js +105 -0
  35. package/dist/functions.js +174 -0
  36. package/dist/guest-api.js +114 -0
  37. package/dist/header-validation.js +18 -0
  38. package/dist/http-policy.js +74 -0
  39. package/dist/http-response.js +84 -0
  40. package/dist/index.js +11 -0
  41. package/dist/link-api.js +136 -0
  42. package/dist/link-cli.js +141 -0
  43. package/dist/link-events.js +76 -0
  44. package/dist/link-records.js +31 -0
  45. package/dist/link-store-worker.js +150 -0
  46. package/dist/link-store.js +250 -0
  47. package/dist/logging.js +22 -0
  48. package/dist/management-policy.js +41 -0
  49. package/dist/match.js +124 -0
  50. package/dist/observability.js +242 -0
  51. package/dist/plugins.js +74 -0
  52. package/dist/policies/agents.js +248 -0
  53. package/dist/policies/cache.js +297 -0
  54. package/dist/policies/compression.js +187 -0
  55. package/dist/policies/security.js +0 -0
  56. package/dist/policies/throttle.js +131 -0
  57. package/dist/policies.js +142 -0
  58. package/dist/policy.js +55 -0
  59. package/dist/prerender.js +165 -0
  60. package/dist/project-tests.js +23 -0
  61. package/dist/readiness.js +216 -0
  62. package/dist/router.js +166 -0
  63. package/dist/runtime.js +244 -0
  64. package/dist/scaffold.js +0 -0
  65. package/dist/scripts/operational-drills.js +75 -0
  66. package/dist/server.js +270 -0
  67. package/dist/site.js +0 -0
  68. package/dist/sqlite-version.js +6 -0
  69. package/dist/types/adapters.d.ts +12 -0
  70. package/dist/types/agent-lists.d.ts +5 -0
  71. package/dist/types/assets.d.ts +13 -0
  72. package/dist/types/authoring.d.ts +2 -0
  73. package/dist/types/aws.d.ts +35 -0
  74. package/dist/types/build-cloudflare.d.ts +14 -0
  75. package/dist/types/cli.d.ts +2 -0
  76. package/dist/types/client-address.d.ts +9 -0
  77. package/dist/types/cloudflare.d.ts +75 -0
  78. package/dist/types/compliance-rules/baseline.d.ts +12 -0
  79. package/dist/types/compliance-rules/privacy.d.ts +6 -0
  80. package/dist/types/compliance-rules/shared.d.ts +24 -0
  81. package/dist/types/compliance-rules/strict.d.ts +9 -0
  82. package/dist/types/compliance.d.ts +119 -0
  83. package/dist/types/config-worker.d.ts +1 -0
  84. package/dist/types/config.d.ts +21 -0
  85. package/dist/types/errors.d.ts +7 -0
  86. package/dist/types/function-sources.d.ts +21 -0
  87. package/dist/types/function-worker.d.ts +1 -0
  88. package/dist/types/functions.d.ts +92 -0
  89. package/dist/types/guest-api.d.ts +16 -0
  90. package/dist/types/header-validation.d.ts +2 -0
  91. package/dist/types/http-policy.d.ts +39 -0
  92. package/dist/types/http-response.d.ts +43 -0
  93. package/dist/types/index.d.ts +11 -0
  94. package/dist/types/link-api.d.ts +30 -0
  95. package/dist/types/link-cli.d.ts +36 -0
  96. package/dist/types/link-events.d.ts +27 -0
  97. package/dist/types/link-records.d.ts +11 -0
  98. package/dist/types/link-store-worker.d.ts +1 -0
  99. package/dist/types/link-store.d.ts +130 -0
  100. package/dist/types/logging.d.ts +9 -0
  101. package/dist/types/management-policy.d.ts +9 -0
  102. package/dist/types/match.d.ts +81 -0
  103. package/dist/types/observability.d.ts +104 -0
  104. package/dist/types/plugins.d.ts +27 -0
  105. package/dist/types/policies/agents.d.ts +86 -0
  106. package/dist/types/policies/cache.d.ts +82 -0
  107. package/dist/types/policies/compression.d.ts +41 -0
  108. package/dist/types/policies/security.d.ts +37 -0
  109. package/dist/types/policies/throttle.d.ts +55 -0
  110. package/dist/types/policies.d.ts +36 -0
  111. package/dist/types/policy.d.ts +21 -0
  112. package/dist/types/prerender.d.ts +31 -0
  113. package/dist/types/project-tests.d.ts +13 -0
  114. package/dist/types/readiness.d.ts +121 -0
  115. package/dist/types/router.d.ts +11 -0
  116. package/dist/types/runtime.d.ts +91 -0
  117. package/dist/types/scaffold.d.ts +17 -0
  118. package/dist/types/server.d.ts +37 -0
  119. package/dist/types/site.d.ts +12 -0
  120. package/dist/types/sqlite-version.d.ts +1 -0
  121. package/dist/types/types.d.ts +332 -0
  122. package/dist/types/vercel.d.ts +12 -0
  123. package/dist/types.js +177 -0
  124. package/dist/vercel.js +65 -0
  125. package/docs/AI-AUTHORING.md +113 -0
  126. package/docs/ASSETS.md +106 -0
  127. package/docs/AWS.md +77 -0
  128. package/docs/BEST-PRACTICES.md +267 -0
  129. package/docs/CAPACITY.md +208 -0
  130. package/docs/CLOUDFLARE.md +110 -0
  131. package/docs/COMPLIANCE.md +242 -0
  132. package/docs/DYNAMIC-LINKS.md +561 -0
  133. package/docs/FUNCTION-SECURITY.md +113 -0
  134. package/docs/HTTP.md +129 -0
  135. package/docs/INSTALL.md +90 -0
  136. package/docs/LOAD-TESTING.md +91 -0
  137. package/docs/LOCAL-DEVELOPMENT.md +99 -0
  138. package/docs/MANAGEMENT-SECURITY.md +82 -0
  139. package/docs/MIDDLEWARE.md +83 -0
  140. package/docs/MONITORING.md +132 -0
  141. package/docs/OBSERVABILITY.md +229 -0
  142. package/docs/OPERATIONAL-PROOF.md +42 -0
  143. package/docs/OPERATIONS.md +207 -0
  144. package/docs/ORGANIZATION.md +135 -0
  145. package/docs/PERFORMANCE.md +72 -0
  146. package/docs/PLUGINS.md +234 -0
  147. package/docs/POLICIES.md +489 -0
  148. package/docs/PRERENDER.md +193 -0
  149. package/docs/PROJECT-DIRECTION.md +51 -0
  150. package/docs/READINESS.md +125 -0
  151. package/docs/README.md +58 -0
  152. package/docs/RELEASE-READINESS.md +95 -0
  153. package/docs/RELEASE-SECURITY.md +72 -0
  154. package/docs/RESILIENCE.md +160 -0
  155. package/docs/ROUTING.md +95 -0
  156. package/docs/SANDBOX-REVIEW.md +59 -0
  157. package/docs/SCAFFOLDING.md +72 -0
  158. package/docs/SECURITY-AUDIT.md +124 -0
  159. package/docs/SITE.md +150 -0
  160. package/docs/SPECIFICATION.md +232 -0
  161. package/docs/SPIKE-EXTENSIONS.md +475 -0
  162. package/docs/STANDARDS.md +303 -0
  163. package/docs/STARTERS.md +51 -0
  164. package/docs/TUNNELS.md +75 -0
  165. package/docs/TYPESCRIPT.md +102 -0
  166. package/docs/VERCEL.md +107 -0
  167. package/docs/YAML-GUIDE.md +521 -0
  168. package/docs/YAML-REFERENCE.md +328 -0
  169. package/docs/policies/agents.md +182 -0
  170. package/docs/policies/cache.md +139 -0
  171. package/docs/policies/compression.md +168 -0
  172. package/docs/policies/security.md +160 -0
  173. package/docs/policies/throttle.md +103 -0
  174. package/examples/assets/.env.example +1 -0
  175. package/examples/assets/.gitattributes +2 -0
  176. package/examples/assets/Makefile +30 -0
  177. package/examples/assets/README.md +18 -0
  178. package/examples/assets/functions/hello.mjs +3 -0
  179. package/examples/assets/gitignore.template +7 -0
  180. package/examples/assets/public/about.html +2 -0
  181. package/examples/assets/public/assets/example.txt +1 -0
  182. package/examples/assets/public/guide.txt +1 -0
  183. package/examples/assets/tests/requests.json +44 -0
  184. package/examples/assets/urlcode.yaml +27 -0
  185. package/examples/aws/README.md +13 -0
  186. package/examples/aws/handler.mjs +5 -0
  187. package/examples/aws/public/index.html +3 -0
  188. package/examples/aws/public/notes.txt +1 -0
  189. package/examples/aws/template.yaml +33 -0
  190. package/examples/aws/tests/requests.json +9 -0
  191. package/examples/aws/urlcode.yaml +19 -0
  192. package/examples/cloudflare/README.md +18 -0
  193. package/examples/cloudflare/package.json +14 -0
  194. package/examples/cloudflare/tests/requests.json +9 -0
  195. package/examples/cloudflare/urlcode.yaml +24 -0
  196. package/examples/cloudflare/wrangler.toml +5 -0
  197. package/examples/compliance/README.md +20 -0
  198. package/examples/compliance/rules.mjs +65 -0
  199. package/examples/cookbook/README.md +21 -0
  200. package/examples/cookbook/functions/choice.mjs +4 -0
  201. package/examples/cookbook/functions/echo.mjs +3 -0
  202. package/examples/cookbook/functions/hello.mjs +3 -0
  203. package/examples/cookbook/functions/text.mjs +3 -0
  204. package/examples/cookbook/middleware/headers.mjs +6 -0
  205. package/examples/cookbook/public/about.html +1 -0
  206. package/examples/cookbook/public/assets/index.html +1 -0
  207. package/examples/cookbook/public/assets/site.css +1 -0
  208. package/examples/cookbook/public/favicon.svg +1 -0
  209. package/examples/cookbook/public/guide.txt +1 -0
  210. package/examples/cookbook/public/llms.txt +6 -0
  211. package/examples/cookbook/routes/code.yaml +55 -0
  212. package/examples/cookbook/routes/files.yaml +17 -0
  213. package/examples/cookbook/routes/policies.yaml +28 -0
  214. package/examples/cookbook/routes/redirects.yaml +38 -0
  215. package/examples/cookbook/routes/responses.yaml +26 -0
  216. package/examples/cookbook/tests/requests.json +254 -0
  217. package/examples/cookbook/urlcode.yaml +22 -0
  218. package/examples/live-links/README.md +11 -0
  219. package/examples/live-links/tests/requests.json +6 -0
  220. package/examples/live-links/urlcode.yaml +16 -0
  221. package/examples/monitoring/blackbox-jobs.yaml +37 -0
  222. package/examples/monitoring/prometheus-rules.yaml +88 -0
  223. package/examples/monitoring/prometheus-scrape.yaml +20 -0
  224. package/examples/monitoring/vector.toml +65 -0
  225. package/examples/prerender/README.md +48 -0
  226. package/examples/prerender/functions/page.mjs +6 -0
  227. package/examples/prerender/middleware/template.mjs +29 -0
  228. package/examples/prerender/prerender.d.mts +4 -0
  229. package/examples/prerender/prerender.mjs +63 -0
  230. package/examples/prerender/tests/requests.json +39 -0
  231. package/examples/prerender/urlcode.yaml +50 -0
  232. package/examples/tunnel/dev-with-ngrok.sh +61 -0
  233. package/examples/vercel/README.md +13 -0
  234. package/examples/vercel/api/index.js +5 -0
  235. package/examples/vercel/package.json +8 -0
  236. package/examples/vercel/public/index.html +3 -0
  237. package/examples/vercel/public/notes.txt +1 -0
  238. package/examples/vercel/tests/requests.json +48 -0
  239. package/examples/vercel/urlcode.yaml +19 -0
  240. package/examples/vercel/vercel.json +10 -0
  241. package/llms.txt +46 -0
  242. package/package.json +123 -0
  243. package/schemas/urlcode.schema.json +1230 -0
  244. package/starters/default/.gitattributes +1 -0
  245. package/starters/default/Makefile +30 -0
  246. package/starters/default/README.md +34 -0
  247. package/starters/default/functions/hello.mjs +3 -0
  248. package/starters/default/gitignore.template +8 -0
  249. package/starters/default/middleware/headers.mjs +6 -0
  250. package/starters/default/routes/functions.yaml +20 -0
  251. package/starters/default/routes/marketing/links.yaml +7 -0
  252. package/starters/default/starter.json +5 -0
  253. package/starters/default/tests/requests.json +56 -0
  254. package/starters/default/urlcode.yaml +8 -0
@@ -0,0 +1,1230 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://raw.githubusercontent.com/jimhoyd-com/urlcode/main/schemas/urlcode.schema.json",
4
+ "type": "object",
5
+ "properties": {
6
+ "version": {
7
+ "const": "1"
8
+ },
9
+ "routes": {
10
+ "type": "object",
11
+ "maxProperties": 100000,
12
+ "additionalProperties": {
13
+ "$ref": "#/$defs/route"
14
+ }
15
+ },
16
+ "includes": {
17
+ "type": "array",
18
+ "items": {
19
+ "type": "string",
20
+ "maxLength": 1024
21
+ },
22
+ "uniqueItems": true,
23
+ "maxItems": 256
24
+ },
25
+ "dynamicLinks": {
26
+ "type": "boolean",
27
+ "default": false,
28
+ "description": "Entry-point opt-in for live stored-link routes. Does not enable guest storage or management access."
29
+ },
30
+ "policies": {
31
+ "$ref": "#/$defs/policies"
32
+ },
33
+ "profiles": {
34
+ "type": "object",
35
+ "description": "Reusable named policy sets selectable with policies.profile. A name shadows a built-in profile of the same name.",
36
+ "maxProperties": 32,
37
+ "propertyNames": {
38
+ "pattern": "^[a-z][a-z0-9-]{0,63}$"
39
+ },
40
+ "additionalProperties": {
41
+ "type": "object",
42
+ "properties": {
43
+ "throttle": {
44
+ "oneOf": [
45
+ {
46
+ "const": false
47
+ },
48
+ {
49
+ "$ref": "#/$defs/policyThrottle"
50
+ }
51
+ ]
52
+ },
53
+ "agents": {
54
+ "oneOf": [
55
+ {
56
+ "const": false
57
+ },
58
+ {
59
+ "$ref": "#/$defs/policyAgents"
60
+ }
61
+ ]
62
+ },
63
+ "security": {
64
+ "oneOf": [
65
+ {
66
+ "const": false
67
+ },
68
+ {
69
+ "$ref": "#/$defs/policySecurity"
70
+ }
71
+ ]
72
+ },
73
+ "compression": {
74
+ "oneOf": [
75
+ {
76
+ "const": false
77
+ },
78
+ {
79
+ "$ref": "#/$defs/policyCompression"
80
+ }
81
+ ]
82
+ },
83
+ "cache": {
84
+ "oneOf": [
85
+ {
86
+ "const": false
87
+ },
88
+ {
89
+ "$ref": "#/$defs/policyCache"
90
+ }
91
+ ]
92
+ }
93
+ },
94
+ "additionalProperties": false
95
+ }
96
+ },
97
+ "site": {
98
+ "type": "object",
99
+ "description": "Site conventions. Each declared key generates one native route (robots.txt, sitemap.xml, favicon.ico, .well-known/security.txt, llms.txt); a declared route at the same path wins. Entry urlcode.yaml only.",
100
+ "properties": {
101
+ "robots": {
102
+ "type": "object",
103
+ "description": "Generates /robots.txt (RFC 9309). List entries are bundled agent list names or paths starting with /.",
104
+ "properties": {
105
+ "disallow": {
106
+ "type": "array",
107
+ "items": {
108
+ "type": "string",
109
+ "minLength": 1,
110
+ "maxLength": 2048
111
+ },
112
+ "maxItems": 1024,
113
+ "uniqueItems": true
114
+ },
115
+ "allow": {
116
+ "type": "array",
117
+ "items": {
118
+ "type": "string",
119
+ "minLength": 1,
120
+ "maxLength": 2048
121
+ },
122
+ "maxItems": 1024,
123
+ "uniqueItems": true
124
+ },
125
+ "sitemap": {
126
+ "type": "boolean",
127
+ "description": "Append a Sitemap line built from the public origin (--origin); omitted when no origin is known."
128
+ },
129
+ "extra": {
130
+ "type": "array",
131
+ "items": {
132
+ "type": "string",
133
+ "maxLength": 2048
134
+ },
135
+ "maxItems": 1024
136
+ }
137
+ },
138
+ "additionalProperties": false
139
+ },
140
+ "sitemap": {
141
+ "oneOf": [
142
+ {
143
+ "const": true
144
+ },
145
+ {
146
+ "type": "object",
147
+ "properties": {
148
+ "exclude": {
149
+ "type": "array",
150
+ "items": {
151
+ "type": "string",
152
+ "minLength": 1,
153
+ "maxLength": 2048
154
+ },
155
+ "maxItems": 1024,
156
+ "uniqueItems": true
157
+ },
158
+ "changefreq": {
159
+ "enum": [
160
+ "always",
161
+ "hourly",
162
+ "daily",
163
+ "weekly",
164
+ "monthly",
165
+ "yearly",
166
+ "never"
167
+ ]
168
+ },
169
+ "priority": {
170
+ "type": "number",
171
+ "minimum": 0,
172
+ "maximum": 1
173
+ }
174
+ },
175
+ "additionalProperties": false
176
+ }
177
+ ],
178
+ "description": "Generates /sitemap.xml (sitemaps.org 0.9) from active literal GET routes serving HTML. Requires --origin."
179
+ },
180
+ "favicon": {
181
+ "type": "string",
182
+ "minLength": 1,
183
+ "maxLength": 1024,
184
+ "description": "Project-relative .ico, .svg or .png served at /favicon.ico."
185
+ },
186
+ "securityTxt": {
187
+ "type": "object",
188
+ "description": "Generates /.well-known/security.txt (RFC 9116).",
189
+ "properties": {
190
+ "contact": {
191
+ "type": "array",
192
+ "items": {
193
+ "type": "string",
194
+ "minLength": 1,
195
+ "maxLength": 2048
196
+ },
197
+ "minItems": 1,
198
+ "maxItems": 64
199
+ },
200
+ "expires": {
201
+ "type": "string",
202
+ "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z$"
203
+ },
204
+ "policy": {
205
+ "type": "array",
206
+ "items": {
207
+ "type": "string",
208
+ "pattern": "^https://",
209
+ "maxLength": 2048
210
+ },
211
+ "maxItems": 64
212
+ },
213
+ "acknowledgments": {
214
+ "type": "array",
215
+ "items": {
216
+ "type": "string",
217
+ "pattern": "^https://",
218
+ "maxLength": 2048
219
+ },
220
+ "maxItems": 64
221
+ },
222
+ "preferredLanguages": {
223
+ "type": "array",
224
+ "items": {
225
+ "type": "string",
226
+ "minLength": 2,
227
+ "maxLength": 35
228
+ },
229
+ "minItems": 1,
230
+ "maxItems": 64
231
+ },
232
+ "canonical": {
233
+ "type": "array",
234
+ "items": {
235
+ "type": "string",
236
+ "pattern": "^https://",
237
+ "maxLength": 2048
238
+ },
239
+ "maxItems": 64
240
+ },
241
+ "encryption": {
242
+ "type": "array",
243
+ "items": {
244
+ "type": "string",
245
+ "minLength": 1,
246
+ "maxLength": 2048
247
+ },
248
+ "maxItems": 64
249
+ }
250
+ },
251
+ "required": [
252
+ "contact",
253
+ "expires"
254
+ ],
255
+ "additionalProperties": false
256
+ },
257
+ "llms": {
258
+ "type": "string",
259
+ "minLength": 1,
260
+ "maxLength": 1024,
261
+ "description": "Project-relative text file served at /llms.txt."
262
+ }
263
+ },
264
+ "additionalProperties": false
265
+ }
266
+ },
267
+ "required": [
268
+ "version",
269
+ "routes"
270
+ ],
271
+ "additionalProperties": false,
272
+ "$defs": {
273
+ "route": {
274
+ "type": "object",
275
+ "properties": {
276
+ "methods": {
277
+ "type": "array",
278
+ "items": {
279
+ "enum": [
280
+ "GET",
281
+ "HEAD",
282
+ "POST",
283
+ "PUT",
284
+ "PATCH",
285
+ "DELETE",
286
+ "OPTIONS"
287
+ ]
288
+ },
289
+ "minItems": 1,
290
+ "uniqueItems": true,
291
+ "default": [
292
+ "GET",
293
+ "HEAD"
294
+ ]
295
+ },
296
+ "enabled": {
297
+ "type": "boolean"
298
+ },
299
+ "expires": {
300
+ "type": "string"
301
+ },
302
+ "description": {
303
+ "type": "string",
304
+ "maxLength": 1024
305
+ },
306
+ "parameters": {
307
+ "type": "array",
308
+ "items": {
309
+ "type": "object",
310
+ "properties": {
311
+ "name": {
312
+ "type": "string",
313
+ "pattern": "^[A-Za-z_][A-Za-z0-9_-]*$"
314
+ },
315
+ "in": {
316
+ "enum": [
317
+ "path",
318
+ "query",
319
+ "header"
320
+ ]
321
+ },
322
+ "required": {
323
+ "type": "boolean"
324
+ },
325
+ "schema": {
326
+ "type": "object",
327
+ "properties": {
328
+ "type": {
329
+ "enum": [
330
+ "string",
331
+ "integer",
332
+ "number",
333
+ "boolean",
334
+ "array"
335
+ ]
336
+ },
337
+ "enum": {
338
+ "type": "array",
339
+ "items": {
340
+ "type": [
341
+ "string",
342
+ "number",
343
+ "boolean"
344
+ ]
345
+ },
346
+ "minItems": 1,
347
+ "uniqueItems": true
348
+ },
349
+ "default": {
350
+ "type": [
351
+ "string",
352
+ "number",
353
+ "boolean",
354
+ "array"
355
+ ],
356
+ "items": {
357
+ "type": [
358
+ "string",
359
+ "number",
360
+ "boolean"
361
+ ]
362
+ }
363
+ },
364
+ "minLength": {
365
+ "type": "integer",
366
+ "minimum": 0,
367
+ "maximum": 8192
368
+ },
369
+ "maxLength": {
370
+ "type": "integer",
371
+ "minimum": 0,
372
+ "maximum": 8192
373
+ },
374
+ "minimum": {
375
+ "type": "number"
376
+ },
377
+ "maximum": {
378
+ "type": "number"
379
+ },
380
+ "items": {
381
+ "type": "object",
382
+ "properties": {
383
+ "type": {
384
+ "enum": [
385
+ "string",
386
+ "integer",
387
+ "number",
388
+ "boolean"
389
+ ]
390
+ }
391
+ },
392
+ "required": [
393
+ "type"
394
+ ],
395
+ "additionalProperties": false
396
+ },
397
+ "maxItems": {
398
+ "type": "integer",
399
+ "minimum": 0,
400
+ "maximum": 100
401
+ }
402
+ },
403
+ "required": [
404
+ "type"
405
+ ],
406
+ "additionalProperties": false
407
+ }
408
+ },
409
+ "required": [
410
+ "name",
411
+ "in",
412
+ "schema"
413
+ ],
414
+ "additionalProperties": false
415
+ },
416
+ "maxItems": 64
417
+ },
418
+ "redirect": {
419
+ "type": "object",
420
+ "properties": {
421
+ "url": {
422
+ "type": "string",
423
+ "maxLength": 8192
424
+ },
425
+ "status": {
426
+ "enum": [
427
+ 301,
428
+ 302,
429
+ 303,
430
+ 307,
431
+ 308
432
+ ]
433
+ },
434
+ "query": {
435
+ "type": "object",
436
+ "properties": {
437
+ "pass": {
438
+ "oneOf": [
439
+ {
440
+ "const": false
441
+ },
442
+ {
443
+ "type": "array",
444
+ "items": {
445
+ "type": "string"
446
+ },
447
+ "uniqueItems": true
448
+ }
449
+ ]
450
+ },
451
+ "map": {
452
+ "type": "object",
453
+ "additionalProperties": {
454
+ "type": "object",
455
+ "properties": {
456
+ "from": {
457
+ "enum": [
458
+ "path",
459
+ "query",
460
+ "header"
461
+ ]
462
+ },
463
+ "name": {
464
+ "type": "string"
465
+ }
466
+ },
467
+ "required": [
468
+ "from",
469
+ "name"
470
+ ],
471
+ "additionalProperties": false
472
+ }
473
+ }
474
+ },
475
+ "required": [],
476
+ "additionalProperties": false
477
+ }
478
+ },
479
+ "required": [
480
+ "url"
481
+ ],
482
+ "additionalProperties": false
483
+ },
484
+ "function": {
485
+ "type": "object",
486
+ "properties": {
487
+ "source": {
488
+ "type": "string",
489
+ "maxLength": 1024
490
+ },
491
+ "export": {
492
+ "type": "string",
493
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
494
+ },
495
+ "args": {
496
+ "type": "object",
497
+ "propertyNames": {
498
+ "type": "string",
499
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
500
+ },
501
+ "additionalProperties": {
502
+ "oneOf": [
503
+ {
504
+ "type": [
505
+ "string",
506
+ "number",
507
+ "boolean"
508
+ ]
509
+ },
510
+ {
511
+ "type": "object",
512
+ "properties": {
513
+ "from": {
514
+ "enum": [
515
+ "path",
516
+ "query",
517
+ "header"
518
+ ]
519
+ },
520
+ "name": {
521
+ "type": "string"
522
+ }
523
+ },
524
+ "required": [
525
+ "from",
526
+ "name"
527
+ ],
528
+ "additionalProperties": false
529
+ },
530
+ {
531
+ "type": "object",
532
+ "properties": {
533
+ "env": {
534
+ "type": "string",
535
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
536
+ }
537
+ },
538
+ "required": [
539
+ "env"
540
+ ],
541
+ "additionalProperties": false
542
+ },
543
+ {
544
+ "type": "object",
545
+ "properties": {
546
+ "secret": {
547
+ "type": "string",
548
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
549
+ }
550
+ },
551
+ "required": [
552
+ "secret"
553
+ ],
554
+ "additionalProperties": false
555
+ }
556
+ ]
557
+ }
558
+ }
559
+ },
560
+ "required": [
561
+ "source"
562
+ ],
563
+ "additionalProperties": false
564
+ },
565
+ "env": {
566
+ "type": "object",
567
+ "propertyNames": {
568
+ "type": "string",
569
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
570
+ },
571
+ "additionalProperties": {
572
+ "oneOf": [
573
+ {
574
+ "type": "object",
575
+ "properties": {
576
+ "value": {
577
+ "type": "string"
578
+ }
579
+ },
580
+ "required": [
581
+ "value"
582
+ ],
583
+ "additionalProperties": false
584
+ },
585
+ {
586
+ "type": "object",
587
+ "properties": {
588
+ "env": {
589
+ "type": "string",
590
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
591
+ }
592
+ },
593
+ "required": [
594
+ "env"
595
+ ],
596
+ "additionalProperties": false
597
+ }
598
+ ]
599
+ }
600
+ },
601
+ "secrets": {
602
+ "type": "object",
603
+ "propertyNames": {
604
+ "type": "string",
605
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
606
+ },
607
+ "additionalProperties": {
608
+ "type": "object",
609
+ "properties": {
610
+ "secret": {
611
+ "type": "string",
612
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
613
+ }
614
+ },
615
+ "required": [
616
+ "secret"
617
+ ],
618
+ "additionalProperties": false
619
+ }
620
+ },
621
+ "page": {
622
+ "type": "object",
623
+ "properties": {
624
+ "file": {
625
+ "type": "string",
626
+ "minLength": 1,
627
+ "maxLength": 1024
628
+ },
629
+ "contentType": {
630
+ "type": "string",
631
+ "pattern": "^[A-Za-z0-9!#$&^_.+-]+/[A-Za-z0-9!#$&^_.+-]+$",
632
+ "maxLength": 128
633
+ },
634
+ "cacheControl": {
635
+ "enum": [
636
+ "no-cache",
637
+ "no-store",
638
+ "public, max-age=3600",
639
+ "public, max-age=31536000, immutable"
640
+ ]
641
+ }
642
+ },
643
+ "required": [
644
+ "file"
645
+ ],
646
+ "additionalProperties": false
647
+ },
648
+ "download": {
649
+ "type": "object",
650
+ "properties": {
651
+ "file": {
652
+ "type": "string",
653
+ "minLength": 1,
654
+ "maxLength": 1024
655
+ },
656
+ "contentType": {
657
+ "type": "string",
658
+ "pattern": "^[A-Za-z0-9!#$&^_.+-]+/[A-Za-z0-9!#$&^_.+-]+$",
659
+ "maxLength": 128
660
+ },
661
+ "cacheControl": {
662
+ "enum": [
663
+ "no-cache",
664
+ "no-store",
665
+ "public, max-age=3600",
666
+ "public, max-age=31536000, immutable"
667
+ ]
668
+ },
669
+ "filename": {
670
+ "type": "string",
671
+ "minLength": 1,
672
+ "maxLength": 255
673
+ }
674
+ },
675
+ "required": [
676
+ "file"
677
+ ],
678
+ "additionalProperties": false
679
+ },
680
+ "static": {
681
+ "type": "object",
682
+ "properties": {
683
+ "directory": {
684
+ "type": "string",
685
+ "minLength": 1,
686
+ "maxLength": 1024
687
+ },
688
+ "contentType": {
689
+ "type": "string",
690
+ "pattern": "^[A-Za-z0-9!#$&^_.+-]+/[A-Za-z0-9!#$&^_.+-]+$",
691
+ "maxLength": 128
692
+ },
693
+ "cacheControl": {
694
+ "enum": [
695
+ "no-cache",
696
+ "no-store",
697
+ "public, max-age=3600",
698
+ "public, max-age=31536000, immutable"
699
+ ]
700
+ },
701
+ "index": {
702
+ "type": "string",
703
+ "pattern": "^[A-Za-z0-9_-]+\\.html$"
704
+ }
705
+ },
706
+ "required": [
707
+ "directory"
708
+ ],
709
+ "additionalProperties": false
710
+ },
711
+ "request": {
712
+ "type": "object",
713
+ "properties": {
714
+ "body": {
715
+ "type": "object",
716
+ "properties": {
717
+ "required": {
718
+ "type": "boolean"
719
+ },
720
+ "maxBytes": {
721
+ "type": "integer",
722
+ "minimum": 0,
723
+ "maximum": 1048576
724
+ },
725
+ "contentTypes": {
726
+ "type": "array",
727
+ "minItems": 1,
728
+ "maxItems": 16,
729
+ "uniqueItems": true,
730
+ "items": {
731
+ "type": "string",
732
+ "pattern": "^[a-z0-9!#$&^_.+-]+/[a-z0-9!#$&^_.+-]+$"
733
+ }
734
+ },
735
+ "format": {
736
+ "enum": [
737
+ "text",
738
+ "json"
739
+ ]
740
+ }
741
+ },
742
+ "additionalProperties": false
743
+ }
744
+ },
745
+ "additionalProperties": false
746
+ },
747
+ "response": {
748
+ "type": "object",
749
+ "properties": {
750
+ "headers": {
751
+ "type": "object",
752
+ "maxProperties": 64,
753
+ "additionalProperties": {
754
+ "oneOf": [
755
+ {
756
+ "type": "string",
757
+ "maxLength": 4096
758
+ },
759
+ {
760
+ "type": "array",
761
+ "minItems": 1,
762
+ "maxItems": 16,
763
+ "items": {
764
+ "type": "string",
765
+ "maxLength": 4096
766
+ }
767
+ }
768
+ ]
769
+ }
770
+ }
771
+ },
772
+ "additionalProperties": false
773
+ },
774
+ "respond": {
775
+ "type": "object",
776
+ "properties": {
777
+ "status": {
778
+ "type": "integer",
779
+ "minimum": 200,
780
+ "maximum": 599
781
+ },
782
+ "text": {
783
+ "type": "string",
784
+ "maxLength": 1048576
785
+ },
786
+ "json": {}
787
+ },
788
+ "additionalProperties": false,
789
+ "not": {
790
+ "required": [
791
+ "text",
792
+ "json"
793
+ ]
794
+ }
795
+ },
796
+ "middleware": {
797
+ "type": "array",
798
+ "maxItems": 16,
799
+ "items": {
800
+ "type": "object",
801
+ "properties": {
802
+ "source": {
803
+ "type": "string",
804
+ "maxLength": 1024
805
+ },
806
+ "export": {
807
+ "type": "string",
808
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
809
+ }
810
+ },
811
+ "required": [
812
+ "source"
813
+ ],
814
+ "additionalProperties": false
815
+ }
816
+ },
817
+ "link": {
818
+ "type": "object",
819
+ "properties": {
820
+ "collection": {
821
+ "type": "string",
822
+ "pattern": "^[A-Za-z][A-Za-z0-9_-]{0,63}$"
823
+ },
824
+ "code": {
825
+ "type": "object",
826
+ "properties": {
827
+ "from": {
828
+ "const": "path"
829
+ },
830
+ "name": {
831
+ "type": "string",
832
+ "pattern": "^[A-Za-z_][A-Za-z0-9_]*$"
833
+ }
834
+ },
835
+ "required": [
836
+ "from",
837
+ "name"
838
+ ],
839
+ "additionalProperties": false
840
+ }
841
+ },
842
+ "required": [
843
+ "collection",
844
+ "code"
845
+ ],
846
+ "additionalProperties": false
847
+ },
848
+ "policies": {
849
+ "$ref": "#/$defs/policies"
850
+ }
851
+ },
852
+ "required": [],
853
+ "additionalProperties": false,
854
+ "oneOf": [
855
+ {
856
+ "required": [
857
+ "redirect"
858
+ ]
859
+ },
860
+ {
861
+ "required": [
862
+ "function"
863
+ ]
864
+ },
865
+ {
866
+ "required": [
867
+ "page"
868
+ ]
869
+ },
870
+ {
871
+ "required": [
872
+ "download"
873
+ ]
874
+ },
875
+ {
876
+ "required": [
877
+ "static"
878
+ ]
879
+ },
880
+ {
881
+ "required": [
882
+ "respond"
883
+ ]
884
+ },
885
+ {
886
+ "required": [
887
+ "link"
888
+ ]
889
+ }
890
+ ]
891
+ },
892
+ "policyThrottle": {
893
+ "type": "object",
894
+ "description": "Per-client request budget expressed like the IETF RateLimit-Policy field: quota requests per window seconds. quota and window are required once project and route layers are merged.",
895
+ "properties": {
896
+ "quota": {
897
+ "type": "integer",
898
+ "minimum": 1,
899
+ "maximum": 1000000
900
+ },
901
+ "window": {
902
+ "type": "integer",
903
+ "minimum": 1,
904
+ "maximum": 86400,
905
+ "description": "Seconds"
906
+ },
907
+ "partition": {
908
+ "enum": [
909
+ "client",
910
+ "route",
911
+ "client-route"
912
+ ],
913
+ "default": "client"
914
+ },
915
+ "status": {
916
+ "type": "integer",
917
+ "minimum": 400,
918
+ "maximum": 599,
919
+ "default": 429
920
+ },
921
+ "mode": {
922
+ "enum": [
923
+ "enforce",
924
+ "report"
925
+ ],
926
+ "default": "enforce"
927
+ },
928
+ "maxKeys": {
929
+ "type": "integer",
930
+ "minimum": 1000,
931
+ "maximum": 10000000,
932
+ "default": 100000
933
+ }
934
+ },
935
+ "additionalProperties": false
936
+ },
937
+ "policyAgents": {
938
+ "type": "object",
939
+ "description": "User-Agent policy. Named lists ship with the runtime; project-relative .json files in the same schema supply your own.",
940
+ "properties": {
941
+ "deny": {
942
+ "type": "array",
943
+ "items": {
944
+ "type": "string",
945
+ "minLength": 1,
946
+ "maxLength": 1024
947
+ },
948
+ "uniqueItems": true,
949
+ "maxItems": 32
950
+ },
951
+ "allow": {
952
+ "type": "array",
953
+ "items": {
954
+ "type": "string",
955
+ "minLength": 1,
956
+ "maxLength": 1024
957
+ },
958
+ "uniqueItems": true,
959
+ "maxItems": 32
960
+ },
961
+ "denyPatterns": {
962
+ "type": "array",
963
+ "items": {
964
+ "type": "string",
965
+ "minLength": 1,
966
+ "maxLength": 256
967
+ },
968
+ "uniqueItems": true,
969
+ "maxItems": 256
970
+ },
971
+ "allowPatterns": {
972
+ "type": "array",
973
+ "items": {
974
+ "type": "string",
975
+ "minLength": 1,
976
+ "maxLength": 256
977
+ },
978
+ "uniqueItems": true,
979
+ "maxItems": 256
980
+ },
981
+ "denyEmpty": {
982
+ "type": "boolean",
983
+ "default": false,
984
+ "description": "Deny requests that send no User-Agent"
985
+ },
986
+ "status": {
987
+ "type": "integer",
988
+ "minimum": 400,
989
+ "maximum": 599,
990
+ "default": 403
991
+ },
992
+ "mode": {
993
+ "enum": [
994
+ "enforce",
995
+ "report"
996
+ ],
997
+ "default": "enforce"
998
+ }
999
+ },
1000
+ "additionalProperties": false
1001
+ },
1002
+ "policySecurity": {
1003
+ "type": "object",
1004
+ "description": "Response security headers. Profiles follow the OWASP Secure Headers Project; set overrides or adds individual headers; unset removes one from the profile.",
1005
+ "properties": {
1006
+ "headers": {
1007
+ "enum": [
1008
+ "oshp",
1009
+ "oshp-no-csp",
1010
+ "off"
1011
+ ],
1012
+ "default": "oshp"
1013
+ },
1014
+ "set": {
1015
+ "type": "object",
1016
+ "maxProperties": 32,
1017
+ "additionalProperties": {
1018
+ "type": "string",
1019
+ "maxLength": 4096
1020
+ }
1021
+ },
1022
+ "unset": {
1023
+ "type": "array",
1024
+ "items": {
1025
+ "type": "string",
1026
+ "minLength": 1,
1027
+ "maxLength": 128
1028
+ },
1029
+ "uniqueItems": true,
1030
+ "maxItems": 32
1031
+ }
1032
+ },
1033
+ "additionalProperties": false
1034
+ },
1035
+ "policyCompression": {
1036
+ "type": "object",
1037
+ "description": "Content-coding negotiation per RFC 9110. Assets are precompressed at snapshot time; other bodies compress on the request path.",
1038
+ "properties": {
1039
+ "encodings": {
1040
+ "type": "array",
1041
+ "items": {
1042
+ "enum": [
1043
+ "br",
1044
+ "gzip",
1045
+ "deflate",
1046
+ "zstd"
1047
+ ]
1048
+ },
1049
+ "minItems": 1,
1050
+ "uniqueItems": true,
1051
+ "default": [
1052
+ "br",
1053
+ "gzip"
1054
+ ]
1055
+ },
1056
+ "minBytes": {
1057
+ "type": "integer",
1058
+ "minimum": 0,
1059
+ "maximum": 1048576,
1060
+ "default": 1024
1061
+ },
1062
+ "types": {
1063
+ "type": "array",
1064
+ "items": {
1065
+ "type": "string",
1066
+ "minLength": 1,
1067
+ "maxLength": 128
1068
+ },
1069
+ "uniqueItems": true,
1070
+ "maxItems": 64
1071
+ },
1072
+ "level": {
1073
+ "type": "integer",
1074
+ "minimum": 1,
1075
+ "maximum": 11
1076
+ },
1077
+ "allowWithSecrets": {
1078
+ "type": "boolean",
1079
+ "default": false
1080
+ }
1081
+ },
1082
+ "additionalProperties": false
1083
+ },
1084
+ "policyCache": {
1085
+ "type": "object",
1086
+ "description": "Named HTTP caching strategy per RFC 9111/5861/8246/9213; explicit fields override what the strategy implies. strategy is required once project and route layers are merged.",
1087
+ "properties": {
1088
+ "strategy": {
1089
+ "enum": [
1090
+ "no-store",
1091
+ "revalidate",
1092
+ "public",
1093
+ "immutable",
1094
+ "swr",
1095
+ "sie",
1096
+ "micro",
1097
+ "cdn-only",
1098
+ "private"
1099
+ ]
1100
+ },
1101
+ "maxAge": {
1102
+ "type": "integer",
1103
+ "minimum": 0,
1104
+ "maximum": 31536000,
1105
+ "description": "Seconds"
1106
+ },
1107
+ "staleWhileRevalidate": {
1108
+ "type": "integer",
1109
+ "minimum": 0,
1110
+ "maximum": 31536000
1111
+ },
1112
+ "staleIfError": {
1113
+ "type": "integer",
1114
+ "minimum": 0,
1115
+ "maximum": 31536000
1116
+ },
1117
+ "cdnMaxAge": {
1118
+ "type": "integer",
1119
+ "minimum": 0,
1120
+ "maximum": 31536000
1121
+ },
1122
+ "originTtl": {
1123
+ "type": "integer",
1124
+ "minimum": 0,
1125
+ "maximum": 86400,
1126
+ "description": "Seconds an origin memory cache may serve a stored response"
1127
+ },
1128
+ "vary": {
1129
+ "type": "array",
1130
+ "items": {
1131
+ "type": "string",
1132
+ "minLength": 1,
1133
+ "maxLength": 128
1134
+ },
1135
+ "uniqueItems": true,
1136
+ "maxItems": 8
1137
+ },
1138
+ "statuses": {
1139
+ "type": "array",
1140
+ "items": {
1141
+ "type": "integer",
1142
+ "minimum": 200,
1143
+ "maximum": 599
1144
+ },
1145
+ "uniqueItems": true,
1146
+ "maxItems": 16
1147
+ },
1148
+ "maxBytes": {
1149
+ "type": "integer",
1150
+ "minimum": 0,
1151
+ "maximum": 16777216,
1152
+ "description": "Largest body the origin cache stores"
1153
+ },
1154
+ "maxEntries": {
1155
+ "type": "integer",
1156
+ "minimum": 1,
1157
+ "maximum": 1000000
1158
+ },
1159
+ "force": {
1160
+ "type": "boolean",
1161
+ "default": false,
1162
+ "description": "Allow immutable on a path without a content hash"
1163
+ }
1164
+ },
1165
+ "additionalProperties": false
1166
+ },
1167
+ "policies": {
1168
+ "type": "object",
1169
+ "description": "Optional host-enforced behavior around routes. Every key is off unless declared. Route policies merge over project policies; false disables one.",
1170
+ "properties": {
1171
+ "profile": {
1172
+ "type": "string",
1173
+ "pattern": "^[a-z][a-z0-9-]{0,63}$",
1174
+ "description": "Built-in (hardened) or a name under top-level profiles"
1175
+ },
1176
+ "throttle": {
1177
+ "oneOf": [
1178
+ {
1179
+ "const": false
1180
+ },
1181
+ {
1182
+ "$ref": "#/$defs/policyThrottle"
1183
+ }
1184
+ ]
1185
+ },
1186
+ "agents": {
1187
+ "oneOf": [
1188
+ {
1189
+ "const": false
1190
+ },
1191
+ {
1192
+ "$ref": "#/$defs/policyAgents"
1193
+ }
1194
+ ]
1195
+ },
1196
+ "security": {
1197
+ "oneOf": [
1198
+ {
1199
+ "const": false
1200
+ },
1201
+ {
1202
+ "$ref": "#/$defs/policySecurity"
1203
+ }
1204
+ ]
1205
+ },
1206
+ "compression": {
1207
+ "oneOf": [
1208
+ {
1209
+ "const": false
1210
+ },
1211
+ {
1212
+ "$ref": "#/$defs/policyCompression"
1213
+ }
1214
+ ]
1215
+ },
1216
+ "cache": {
1217
+ "oneOf": [
1218
+ {
1219
+ "const": false
1220
+ },
1221
+ {
1222
+ "$ref": "#/$defs/policyCache"
1223
+ }
1224
+ ]
1225
+ }
1226
+ },
1227
+ "additionalProperties": false
1228
+ }
1229
+ }
1230
+ }