@jimhoyd/urlcode 0.4.1 → 0.4.6

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 (212) hide show
  1. package/.claude/skills/urlcode-authoring/SKILL.md +60 -7
  2. package/.claude/skills/urlcode-operations/SKILL.md +4 -0
  3. package/README.md +19 -15
  4. package/SECURITY.md +5 -3
  5. package/dist/BUILD-MANIFEST.json +31 -28
  6. package/dist/agent-context.js +82 -0
  7. package/dist/agents-guide.js +42 -42
  8. package/dist/authoring.js +12 -2
  9. package/dist/body-schema.js +159 -0
  10. package/dist/build-cloudflare.js +2 -0
  11. package/dist/capabilities.js +1 -1
  12. package/dist/cli.js +29 -12
  13. package/dist/config.js +74 -6
  14. package/dist/context.js +4 -6
  15. package/dist/errors.js +3 -1
  16. package/dist/examples.js +1 -1
  17. package/dist/extensions.js +138 -3
  18. package/dist/http-policy.js +19 -4
  19. package/dist/http-response.js +2 -2
  20. package/dist/init-with.js +71 -9
  21. package/dist/mcp.js +15 -2
  22. package/dist/pattern-guard.js +32 -0
  23. package/dist/policies/security.js +0 -0
  24. package/dist/policy.js +16 -0
  25. package/dist/project-tests.js +35 -11
  26. package/dist/readiness.js +188 -32
  27. package/dist/recipes.js +1 -1
  28. package/dist/router.js +17 -0
  29. package/dist/runtime.js +26 -3
  30. package/dist/scaffold.js +0 -0
  31. package/dist/server.js +26 -3
  32. package/dist/site.js +0 -0
  33. package/dist/tooling.js +3 -1
  34. package/dist/types/agent-context.d.ts +44 -0
  35. package/dist/types/authoring.d.ts +3 -1
  36. package/dist/types/body-schema.d.ts +58 -0
  37. package/dist/types/config.d.ts +10 -2
  38. package/dist/types/context.d.ts +1 -1
  39. package/dist/types/errors.d.ts +9 -1
  40. package/dist/types/examples.d.ts +1 -1
  41. package/dist/types/extensions.d.ts +105 -2
  42. package/dist/types/http-policy.d.ts +3 -0
  43. package/dist/types/init-with.d.ts +10 -1
  44. package/dist/types/pattern-guard.d.ts +10 -0
  45. package/dist/types/project-tests.d.ts +9 -0
  46. package/dist/types/readiness.d.ts +71 -0
  47. package/dist/types/recipes.d.ts +1 -1
  48. package/dist/types/runtime.d.ts +4 -0
  49. package/dist/types/server.d.ts +9 -1
  50. package/dist/types/tooling.d.ts +2 -0
  51. package/dist/types/types.d.ts +13 -0
  52. package/dist/types.js +10 -2
  53. package/dist/typescript-authoring.js +5 -3
  54. package/dist/verify-deployment.js +16 -10
  55. package/examples/body-validation/README.md +16 -0
  56. package/examples/body-validation/example.yaml +17 -0
  57. package/examples/body-validation/tests/requests.json +15 -0
  58. package/examples/body-validation/urlcode.yaml +34 -0
  59. package/examples/coverage-waiver/README.md +8 -0
  60. package/examples/coverage-waiver/example.yaml +16 -0
  61. package/examples/coverage-waiver/functions/notes.mjs +2 -0
  62. package/examples/coverage-waiver/tests/requests.json +3 -0
  63. package/examples/coverage-waiver/urlcode.yaml +10 -0
  64. package/examples/data-dir/README.md +39 -0
  65. package/examples/data-dir/data/welcome.txt +1 -0
  66. package/examples/data-dir/example.yaml +22 -0
  67. package/examples/data-dir/functions/note.mjs +18 -0
  68. package/examples/data-dir/tests/requests.json +6 -0
  69. package/examples/data-dir/urlcode.yaml +6 -0
  70. package/examples/lifecycle/README.md +15 -0
  71. package/examples/lifecycle/example.yaml +19 -0
  72. package/examples/lifecycle/functions/notes.mjs +29 -0
  73. package/examples/lifecycle/tests/requests.json +12 -0
  74. package/examples/lifecycle/urlcode.yaml +29 -0
  75. package/examples/not-found/README.md +10 -0
  76. package/examples/not-found/example.yaml +17 -0
  77. package/examples/not-found/public/404.html +3 -0
  78. package/examples/not-found/public/index.html +3 -0
  79. package/examples/not-found/tests/requests.json +7 -0
  80. package/examples/not-found/urlcode.yaml +7 -0
  81. package/examples/shared-blocks/README.md +11 -0
  82. package/examples/shared-blocks/example.yaml +17 -0
  83. package/examples/shared-blocks/tests/requests.json +7 -0
  84. package/examples/shared-blocks/urlcode.yaml +37 -0
  85. package/llms-full.txt +436 -149
  86. package/llms.txt +44 -6
  87. package/package.json +15 -22
  88. package/recipes/static-page/README.md +9 -0
  89. package/recipes/static-page/public/index.html +11 -0
  90. package/recipes/static-page/recipe.yaml +21 -0
  91. package/recipes/static-page/tests/requests.json +22 -0
  92. package/recipes/static-page/urlcode.yaml +7 -0
  93. package/recipes/static-plus-api/README.md +6 -0
  94. package/recipes/static-plus-api/urlcode.yaml +4 -0
  95. package/recipes/store-crud/README.md +53 -0
  96. package/recipes/store-crud/recipe.yaml +31 -0
  97. package/recipes/store-crud/tests/requests.json +18 -0
  98. package/recipes/store-crud/urlcode.yaml +18 -0
  99. package/schemas/urlcode.schema.json +125 -60
  100. package/skills/urlcode/SKILL.md +53 -26
  101. package/starters/default/AGENTS.md +43 -43
  102. package/starters/page/README.md +14 -0
  103. package/starters/page/public/index.html +12 -0
  104. package/starters/page/tests/requests.json +17 -0
  105. package/starters/page/urlcode.yaml +6 -0
  106. package/.claude-plugin/marketplace.json +0 -18
  107. package/CONTRIBUTING.md +0 -112
  108. package/ROADMAP.md +0 -66
  109. package/docs/AI-AUTHORING.md +0 -338
  110. package/docs/ASSETS.md +0 -107
  111. package/docs/AUTH-BACKUP.md +0 -32
  112. package/docs/AWS.md +0 -86
  113. package/docs/BEST-PRACTICES.md +0 -276
  114. package/docs/BULK.md +0 -79
  115. package/docs/CAPABILITIES.md +0 -192
  116. package/docs/CAPACITY.md +0 -305
  117. package/docs/CI-FOLLOWUP-2026-09-19.md +0 -97
  118. package/docs/CI-RELEASE-AUDIT-2026-09-19.md +0 -322
  119. package/docs/CI.md +0 -147
  120. package/docs/CLOUDFLARE.md +0 -109
  121. package/docs/CODEBASE-AUDIT-2026-09-20.md +0 -284
  122. package/docs/COMPLIANCE.md +0 -239
  123. package/docs/COMPOSING-A-SITE.md +0 -278
  124. package/docs/CONDITIONS.md +0 -74
  125. package/docs/DEPLOYMENT-CHECKS.md +0 -108
  126. package/docs/DEVELOPMENT-PIPELINE.md +0 -270
  127. package/docs/EGRESS.md +0 -125
  128. package/docs/EXTENSIONS.md +0 -438
  129. package/docs/FRAMEWORK.md +0 -217
  130. package/docs/FUNCTION-SECURITY.md +0 -254
  131. package/docs/HTTP.md +0 -129
  132. package/docs/INSTALL.md +0 -128
  133. package/docs/INTERCHANGE.md +0 -134
  134. package/docs/LOAD-TESTING.md +0 -91
  135. package/docs/LOCAL-DEVELOPMENT.md +0 -102
  136. package/docs/MIDDLEWARE-EXAMPLES.md +0 -75
  137. package/docs/MIDDLEWARE.md +0 -102
  138. package/docs/MONITORING.md +0 -115
  139. package/docs/OBSERVABILITY.md +0 -222
  140. package/docs/OPEN-DECISIONS.md +0 -224
  141. package/docs/OPERATIONAL-PROOF.md +0 -41
  142. package/docs/OPERATIONS.md +0 -201
  143. package/docs/ORGANIZATION.md +0 -135
  144. package/docs/PERFORMANCE.md +0 -72
  145. package/docs/PLUGINS.md +0 -271
  146. package/docs/POLICIES.md +0 -211
  147. package/docs/PRERENDER.md +0 -245
  148. package/docs/PROJECT-DIRECTION.md +0 -118
  149. package/docs/PROVIDER-VERIFICATION.md +0 -84
  150. package/docs/READINESS.md +0 -150
  151. package/docs/README.md +0 -87
  152. package/docs/RECIPES.md +0 -99
  153. package/docs/RELEASE-0.4.0-alpha.3.md +0 -50
  154. package/docs/RELEASE-0.4.1.md +0 -73
  155. package/docs/RELEASE-READINESS.md +0 -117
  156. package/docs/RELEASE-SECURITY.md +0 -96
  157. package/docs/RESILIENCE.md +0 -161
  158. package/docs/ROUTING.md +0 -92
  159. package/docs/SANDBOX-REVIEW.md +0 -72
  160. package/docs/SCAFFOLDING.md +0 -70
  161. package/docs/SECURITY-AUDIT.md +0 -164
  162. package/docs/SITE.md +0 -150
  163. package/docs/SPECIFICATION.md +0 -359
  164. package/docs/SPIKE-AI-FRAMEWORK-BENCHMARK.md +0 -288
  165. package/docs/SPIKE-BUSINESS-SUITE.md +0 -1029
  166. package/docs/SPIKE-CORE-LAYERING.md +0 -368
  167. package/docs/SPIKE-DEFAULT-TRUST-MODEL.md +0 -211
  168. package/docs/STANDARDS.md +0 -311
  169. package/docs/STARTERS.md +0 -83
  170. package/docs/STATIC.md +0 -105
  171. package/docs/TOOLING.md +0 -298
  172. package/docs/TUNNELS.md +0 -72
  173. package/docs/TYPESCRIPT-AUTHORING.md +0 -87
  174. package/docs/TYPESCRIPT.md +0 -123
  175. package/docs/VERCEL.md +0 -114
  176. package/docs/VERSION-ALIGNMENT.md +0 -80
  177. package/docs/YAML-GUIDE.md +0 -57
  178. package/docs/YAML-REFERENCE.md +0 -449
  179. package/docs/archive/2026-09-19/EXTENSION-IMPLEMENTATION.md +0 -68
  180. package/docs/archive/2026-09-19/MANAGEMENT-SECURITY.md +0 -102
  181. package/docs/archive/2026-09-19/NEXT-PHASE-PLAN.md +0 -108
  182. package/docs/archive/2026-09-19/NEXT-STEPS.md +0 -646
  183. package/docs/archive/2026-09-19/OPEN-DECISIONS.md +0 -277
  184. package/docs/archive/2026-09-19/RELEASE-SECURITY.md +0 -186
  185. package/docs/archive/2026-09-19/ROADMAP.md +0 -387
  186. package/docs/archive/2026-09-19/SPIKE-EXTENSION-MODEL.md +0 -430
  187. package/docs/archive/2026-09-19/SPIKE-EXTENSIONS.md +0 -492
  188. package/docs/archive/2026-09-19/SPIKE-LAMBDA-COMPILE.md +0 -365
  189. package/docs/archive/2026-09-19/SPIKE-MONOREPO.md +0 -778
  190. package/docs/archive/2026-09-19/USABILITY-REVIEW.md +0 -139
  191. package/docs/archive/README.md +0 -28
  192. package/docs/policies/agents.md +0 -182
  193. package/docs/policies/cache.md +0 -152
  194. package/docs/policies/compression.md +0 -169
  195. package/docs/policies/contract.md +0 -52
  196. package/docs/policies/hardened.md +0 -56
  197. package/docs/policies/interoperability.md +0 -169
  198. package/docs/policies/operations.md +0 -45
  199. package/docs/policies/security.md +0 -161
  200. package/docs/policies/throttle.md +0 -103
  201. package/docs/yaml/assets.md +0 -36
  202. package/docs/yaml/conditions.md +0 -20
  203. package/docs/yaml/functions.md +0 -168
  204. package/docs/yaml/middleware.md +0 -31
  205. package/docs/yaml/organization.md +0 -74
  206. package/docs/yaml/policies.md +0 -37
  207. package/docs/yaml/redirects.md +0 -64
  208. package/docs/yaml/responses.md +0 -57
  209. package/docs/yaml/site.md +0 -24
  210. package/packaging/claude-plugin/.claude-plugin/plugin.json +0 -19
  211. package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +0 -120
  212. package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +0 -108
@@ -1,449 +0,0 @@
1
- # YAML field reference
2
-
3
- Generated from the bundled JSON Schema by `npm run docs:reference`. Required
4
- means required within its containing object, not that the object itself must be
5
- present. `routes.*` means a route path; other `*` markers mean user-selected
6
- keys. `[]` means an array item. Option rows describe union alternatives.
7
-
8
- Read the [YAML guide](YAML-GUIDE.md) for examples and [specification](SPECIFICATION.md)
9
- for semantic validation beyond JSON Schema. Exactly one handler is required per
10
- route; respond.text/respond.json are mutually exclusive. Runtime defaults include
11
- GET/HEAD, redirect 302, respond 200, default module export, and asset no-cache.
12
- Only Set-Cookie accepts response header arrays. This table does not imply all
13
- schema-valid combinations activate successfully.
14
-
15
- | Field | Type | Required | Schema constraints |
16
- |---|---|---|---|
17
- | `version` | constant | yes | const: "1" |
18
- | `routes` | object | yes | maxProperties: 100000 |
19
- | `routes.*` | object | no | unknown keys rejected |
20
- | `routes.*.methods` | array | no | default: ["GET","HEAD"]; minItems: 1; uniqueItems: true |
21
- | `routes.*.methods[]` | string | no | enum: ["GET","HEAD","POST","PUT","PATCH","DELETE","OPTIONS"] |
22
- | `routes.*.enabled` | boolean | no | — |
23
- | `routes.*.sandbox` | boolean | no | default: false |
24
- | `routes.*.sandboxReason` | string | no | maxLength: 500 |
25
- | `routes.*.expires` | string | no | — |
26
- | `routes.*.description` | string | no | maxLength: 1024 |
27
- | `routes.*.parameters` | array | no | maxItems: 64 |
28
- | `routes.*.parameters[]` | object | no | unknown keys rejected |
29
- | `routes.*.parameters[].name` | string | yes | pattern: "^[A-Za-z_][A-Za-z0-9_-]*$" |
30
- | `routes.*.parameters[].in` | string | yes | enum: ["path","query","header"] |
31
- | `routes.*.parameters[].required` | boolean | no | — |
32
- | `routes.*.parameters[].schema` | object | yes | unknown keys rejected |
33
- | `routes.*.parameters[].schema.type` | string | yes | enum: ["string","integer","number","boolean","array"] |
34
- | `routes.*.parameters[].schema.enum` | array | no | minItems: 1; uniqueItems: true |
35
- | `routes.*.parameters[].schema.enum[]` | string / number / boolean | no | — |
36
- | `routes.*.parameters[].schema.default` | string / number / boolean / array | no | — |
37
- | `routes.*.parameters[].schema.default[]` | string / number / boolean | no | — |
38
- | `routes.*.parameters[].schema.minLength` | integer | no | minimum: 0; maximum: 8192 |
39
- | `routes.*.parameters[].schema.maxLength` | integer | no | minimum: 0; maximum: 8192 |
40
- | `routes.*.parameters[].schema.minimum` | number | no | — |
41
- | `routes.*.parameters[].schema.maximum` | number | no | — |
42
- | `routes.*.parameters[].schema.items` | object | no | unknown keys rejected |
43
- | `routes.*.parameters[].schema.items.type` | string | yes | enum: ["string","integer","number","boolean"] |
44
- | `routes.*.parameters[].schema.maxItems` | integer | no | minimum: 0; maximum: 100 |
45
- | `routes.*.redirect` | object | no | unknown keys rejected |
46
- | `routes.*.redirect.url` | string | yes | maxLength: 8192 |
47
- | `routes.*.redirect.status` | number | no | enum: [301,302,303,307,308] |
48
- | `routes.*.redirect.query` | object | no | unknown keys rejected |
49
- | `routes.*.redirect.query.pass` | one of the shapes below | no | — |
50
- | `routes.*.redirect.query.pass (option 1)` | constant | no | const: false |
51
- | `routes.*.redirect.query.pass (option 2)` | array | no | uniqueItems: true |
52
- | `routes.*.redirect.query.pass (option 2)[]` | string | no | — |
53
- | `routes.*.redirect.query.map` | object | no | — |
54
- | `routes.*.redirect.query.map.*` | object | no | unknown keys rejected |
55
- | `routes.*.redirect.query.map.*.from` | string | yes | enum: ["path","query","header"] |
56
- | `routes.*.redirect.query.map.*.name` | string | yes | — |
57
- | `routes.*.function` | one of the shapes below | no | — |
58
- | `routes.*.function (option 1)` | string | no | minLength: 1; maxLength: 1024 |
59
- | `routes.*.function (option 2)` | object | no | unknown keys rejected |
60
- | `routes.*.function (option 2).source` | string | yes | maxLength: 1024 |
61
- | `routes.*.function (option 2).export` | string | no | pattern: "^[A-Za-z_][A-Za-z0-9_]*$" |
62
- | `routes.*.function (option 2).args` | object | no | — |
63
- | `routes.*.function (option 2).args.*` | one of the shapes below | no | — |
64
- | `routes.*.function (option 2).args.* (option 1)` | string / number / boolean | no | — |
65
- | `routes.*.function (option 2).args.* (option 2)` | object | no | unknown keys rejected |
66
- | `routes.*.function (option 2).args.* (option 2).from` | string | yes | enum: ["path","query","header"] |
67
- | `routes.*.function (option 2).args.* (option 2).name` | string | yes | — |
68
- | `routes.*.function (option 2).args.* (option 3)` | object | no | unknown keys rejected |
69
- | `routes.*.function (option 2).args.* (option 3).env` | string | yes | pattern: "^[A-Za-z_][A-Za-z0-9_]*$" |
70
- | `routes.*.function (option 2).args.* (option 4)` | object | no | unknown keys rejected |
71
- | `routes.*.function (option 2).args.* (option 4).secret` | string | yes | pattern: "^[A-Za-z_][A-Za-z0-9_]*$" |
72
- | `routes.*.env` | object | no | — |
73
- | `routes.*.env.*` | one of the shapes below | no | — |
74
- | `routes.*.env.* (option 1)` | object | no | unknown keys rejected |
75
- | `routes.*.env.* (option 1).value` | string | yes | — |
76
- | `routes.*.env.* (option 2)` | object | no | unknown keys rejected |
77
- | `routes.*.env.* (option 2).env` | string | yes | pattern: "^[A-Za-z_][A-Za-z0-9_]*$" |
78
- | `routes.*.secrets` | object | no | — |
79
- | `routes.*.secrets.*` | object | no | unknown keys rejected |
80
- | `routes.*.secrets.*.secret` | string | yes | pattern: "^[A-Za-z_][A-Za-z0-9_]*$" |
81
- | `routes.*.page` | object | no | unknown keys rejected |
82
- | `routes.*.page.file` | string | yes | minLength: 1; maxLength: 1024 |
83
- | `routes.*.page.contentType` | string | no | maxLength: 128; pattern: "^[A-Za-z0-9!#$&^_.+-]+/[A-Za-z0-9!#$&^_.+-]+$" |
84
- | `routes.*.page.cacheControl` | string | no | enum: ["no-cache","no-store","public, max-age=3600","public, max-age=31536000, immutable"] |
85
- | `routes.*.download` | object | no | unknown keys rejected |
86
- | `routes.*.download.file` | string | yes | minLength: 1; maxLength: 1024 |
87
- | `routes.*.download.contentType` | string | no | maxLength: 128; pattern: "^[A-Za-z0-9!#$&^_.+-]+/[A-Za-z0-9!#$&^_.+-]+$" |
88
- | `routes.*.download.cacheControl` | string | no | enum: ["no-cache","no-store","public, max-age=3600","public, max-age=31536000, immutable"] |
89
- | `routes.*.download.filename` | string | no | minLength: 1; maxLength: 255 |
90
- | `routes.*.static` | object | no | unknown keys rejected |
91
- | `routes.*.static.directory` | string | yes | minLength: 1; maxLength: 1024 |
92
- | `routes.*.static.contentType` | string | no | maxLength: 128; pattern: "^[A-Za-z0-9!#$&^_.+-]+/[A-Za-z0-9!#$&^_.+-]+$" |
93
- | `routes.*.static.cacheControl` | string | no | enum: ["no-cache","no-store","public, max-age=3600","public, max-age=31536000, immutable"] |
94
- | `routes.*.static.index` | string | no | pattern: "^[A-Za-z0-9_-]+\\.html$" |
95
- | `routes.*.request` | object | no | unknown keys rejected |
96
- | `routes.*.request.body` | object | no | unknown keys rejected |
97
- | `routes.*.request.body.required` | boolean | no | — |
98
- | `routes.*.request.body.maxBytes` | integer | no | minimum: 0; maximum: 1048576 |
99
- | `routes.*.request.body.contentTypes` | array | no | minItems: 1; maxItems: 16; uniqueItems: true |
100
- | `routes.*.request.body.contentTypes[]` | string | no | pattern: "^[a-z0-9!#$&^_.+-]+/[a-z0-9!#$&^_.+-]+$" |
101
- | `routes.*.request.body.format` | string | no | enum: ["text","json"] |
102
- | `routes.*.response` | object | no | unknown keys rejected |
103
- | `routes.*.response.headers` | object | no | maxProperties: 64 |
104
- | `routes.*.response.headers.*` | one of the shapes below | no | — |
105
- | `routes.*.response.headers.* (option 1)` | string | no | maxLength: 4096 |
106
- | `routes.*.response.headers.* (option 2)` | array | no | minItems: 1; maxItems: 16 |
107
- | `routes.*.response.headers.* (option 2)[]` | string | no | maxLength: 4096 |
108
- | `routes.*.respond` | object | no | unknown keys rejected |
109
- | `routes.*.respond.status` | integer | no | minimum: 200; maximum: 599 |
110
- | `routes.*.respond.text` | string | no | maxLength: 1048576 |
111
- | `routes.*.respond.json` | any JSON value | no | — |
112
- | `routes.*.middleware` | array | no | maxItems: 16 |
113
- | `routes.*.middleware[]` | one of the shapes below | no | — |
114
- | `routes.*.middleware[] (option 1)` | string | no | minLength: 1; maxLength: 1024 |
115
- | `routes.*.middleware[] (option 2)` | object | no | unknown keys rejected |
116
- | `routes.*.middleware[] (option 2).source` | string | yes | maxLength: 1024 |
117
- | `routes.*.middleware[] (option 2).export` | string | no | pattern: "^[A-Za-z_][A-Za-z0-9_]*$" |
118
- | `routes.*.policies` | object | no | unknown keys rejected |
119
- | `routes.*.policies.profile` | string | no | pattern: "^[a-z][a-z0-9-]{0,63}$" |
120
- | `routes.*.policies.throttle` | one of the shapes below | no | — |
121
- | `routes.*.policies.throttle (option 1)` | constant | no | const: false |
122
- | `routes.*.policies.throttle (option 2)` | object | no | unknown keys rejected |
123
- | `routes.*.policies.throttle (option 2).quota` | integer | no | minimum: 1; maximum: 1000000 |
124
- | `routes.*.policies.throttle (option 2).window` | integer | no | minimum: 1; maximum: 86400 |
125
- | `routes.*.policies.throttle (option 2).partition` | string | no | enum: ["client","route","client-route"]; default: "client" |
126
- | `routes.*.policies.throttle (option 2).status` | integer | no | default: 429; minimum: 400; maximum: 599 |
127
- | `routes.*.policies.throttle (option 2).mode` | string | no | enum: ["enforce","report"]; default: "enforce" |
128
- | `routes.*.policies.throttle (option 2).maxKeys` | integer | no | default: 100000; minimum: 1000; maximum: 10000000 |
129
- | `routes.*.policies.agents` | one of the shapes below | no | — |
130
- | `routes.*.policies.agents (option 1)` | constant | no | const: false |
131
- | `routes.*.policies.agents (option 2)` | object | no | unknown keys rejected |
132
- | `routes.*.policies.agents (option 2).deny` | array | no | maxItems: 32; uniqueItems: true |
133
- | `routes.*.policies.agents (option 2).deny[]` | string | no | minLength: 1; maxLength: 1024 |
134
- | `routes.*.policies.agents (option 2).allow` | array | no | maxItems: 32; uniqueItems: true |
135
- | `routes.*.policies.agents (option 2).allow[]` | string | no | minLength: 1; maxLength: 1024 |
136
- | `routes.*.policies.agents (option 2).denyPatterns` | array | no | maxItems: 256; uniqueItems: true |
137
- | `routes.*.policies.agents (option 2).denyPatterns[]` | string | no | minLength: 1; maxLength: 256 |
138
- | `routes.*.policies.agents (option 2).allowPatterns` | array | no | maxItems: 256; uniqueItems: true |
139
- | `routes.*.policies.agents (option 2).allowPatterns[]` | string | no | minLength: 1; maxLength: 256 |
140
- | `routes.*.policies.agents (option 2).denyEmpty` | boolean | no | default: false |
141
- | `routes.*.policies.agents (option 2).status` | integer | no | default: 403; minimum: 400; maximum: 599 |
142
- | `routes.*.policies.agents (option 2).mode` | string | no | enum: ["enforce","report"]; default: "enforce" |
143
- | `routes.*.policies.security` | one of the shapes below | no | — |
144
- | `routes.*.policies.security (option 1)` | constant | no | const: false |
145
- | `routes.*.policies.security (option 2)` | object | no | unknown keys rejected |
146
- | `routes.*.policies.security (option 2).headers` | string | no | enum: ["oshp","oshp-no-csp","off"]; default: "oshp" |
147
- | `routes.*.policies.security (option 2).set` | object | no | maxProperties: 32 |
148
- | `routes.*.policies.security (option 2).set.*` | string | no | maxLength: 4096 |
149
- | `routes.*.policies.security (option 2).unset` | array | no | maxItems: 32; uniqueItems: true |
150
- | `routes.*.policies.security (option 2).unset[]` | string | no | minLength: 1; maxLength: 128 |
151
- | `routes.*.policies.compression` | one of the shapes below | no | — |
152
- | `routes.*.policies.compression (option 1)` | constant | no | const: false |
153
- | `routes.*.policies.compression (option 2)` | object | no | unknown keys rejected |
154
- | `routes.*.policies.compression (option 2).encodings` | array | no | default: ["br","gzip"]; minItems: 1; uniqueItems: true |
155
- | `routes.*.policies.compression (option 2).encodings[]` | string | no | enum: ["br","gzip","deflate","zstd"] |
156
- | `routes.*.policies.compression (option 2).minBytes` | integer | no | default: 1024; minimum: 0; maximum: 1048576 |
157
- | `routes.*.policies.compression (option 2).types` | array | no | maxItems: 64; uniqueItems: true |
158
- | `routes.*.policies.compression (option 2).types[]` | string | no | minLength: 1; maxLength: 128 |
159
- | `routes.*.policies.compression (option 2).level` | integer | no | minimum: 1; maximum: 11 |
160
- | `routes.*.policies.compression (option 2).allowWithSecrets` | boolean | no | default: false |
161
- | `routes.*.policies.cache` | one of the shapes below | no | — |
162
- | `routes.*.policies.cache (option 1)` | constant | no | const: false |
163
- | `routes.*.policies.cache (option 2)` | object | no | unknown keys rejected |
164
- | `routes.*.policies.cache (option 2).strategy` | string | no | enum: ["no-store","revalidate","public","immutable","swr","sie","micro","cdn-only","private"] |
165
- | `routes.*.policies.cache (option 2).maxAge` | integer | no | minimum: 0; maximum: 31536000 |
166
- | `routes.*.policies.cache (option 2).staleWhileRevalidate` | integer | no | minimum: 0; maximum: 31536000 |
167
- | `routes.*.policies.cache (option 2).staleIfError` | integer | no | minimum: 0; maximum: 31536000 |
168
- | `routes.*.policies.cache (option 2).cdnMaxAge` | integer | no | minimum: 0; maximum: 31536000 |
169
- | `routes.*.policies.cache (option 2).originTtl` | integer | no | minimum: 0; maximum: 86400 |
170
- | `routes.*.policies.cache (option 2).vary` | array | no | maxItems: 8; uniqueItems: true |
171
- | `routes.*.policies.cache (option 2).vary[]` | string | no | minLength: 1; maxLength: 128 |
172
- | `routes.*.policies.cache (option 2).statuses` | array | no | maxItems: 16; uniqueItems: true |
173
- | `routes.*.policies.cache (option 2).statuses[]` | integer | no | minimum: 200; maximum: 599 |
174
- | `routes.*.policies.cache (option 2).maxBytes` | integer | no | minimum: 0; maximum: 16777216 |
175
- | `routes.*.policies.cache (option 2).maxEntries` | integer | no | minimum: 1; maximum: 1000000 |
176
- | `routes.*.policies.cache (option 2).force` | boolean | no | default: false |
177
- | `routes.*.policies.extensions` | one of the shapes below | no | — |
178
- | `routes.*.policies.extensions (option 1)` | constant | no | const: false |
179
- | `routes.*.policies.extensions (option 2)` | object | no | maxProperties: 16 |
180
- | `routes.*.policies.extensions (option 2).*` | one of the shapes below | no | — |
181
- | `routes.*.policies.extensions (option 2).* (option 1)` | constant | no | const: false |
182
- | `routes.*.policies.extensions (option 2).* (option 2)` | object | no | — |
183
- | `routes.*.match` | object | no | minProperties: 1; unknown keys rejected |
184
- | `routes.*.match.query` | object | no | minProperties: 1; maxProperties: 16 |
185
- | `routes.*.match.query.*` | string | no | maxLength: 1024 |
186
- | `routes.*.match.headers` | object | no | minProperties: 1; maxProperties: 16 |
187
- | `routes.*.match.headers.*` | string | no | maxLength: 1024 |
188
- | `routes.*.match.cookies` | object | no | minProperties: 1; maxProperties: 16 |
189
- | `routes.*.match.cookies.*` | string | no | maxLength: 1024 |
190
- | `routes.*.match.host` | string | no | maxLength: 255 |
191
- | `routes.*.match.method` | string | no | enum: ["GET","HEAD","POST","PUT","PATCH","DELETE","OPTIONS"] |
192
- | `routes.*.conditional` | object | no | unknown keys rejected |
193
- | `routes.*.conditional.cases` | array | yes | minItems: 1; maxItems: 16 |
194
- | `routes.*.conditional.cases[]` | object | no | unknown keys rejected |
195
- | `routes.*.conditional.cases[].redirect` | object | no | unknown keys rejected |
196
- | `routes.*.conditional.cases[].redirect.url` | string | yes | maxLength: 8192 |
197
- | `routes.*.conditional.cases[].redirect.status` | number | no | enum: [301,302,303,307,308] |
198
- | `routes.*.conditional.cases[].redirect.query` | object | no | unknown keys rejected |
199
- | `routes.*.conditional.cases[].redirect.query.pass` | one of the shapes below | no | — |
200
- | `routes.*.conditional.cases[].redirect.query.pass (option 1)` | constant | no | const: false |
201
- | `routes.*.conditional.cases[].redirect.query.pass (option 2)` | array | no | uniqueItems: true |
202
- | `routes.*.conditional.cases[].redirect.query.pass (option 2)[]` | string | no | — |
203
- | `routes.*.conditional.cases[].redirect.query.map` | object | no | — |
204
- | `routes.*.conditional.cases[].redirect.query.map.*` | object | no | unknown keys rejected |
205
- | `routes.*.conditional.cases[].redirect.query.map.*.from` | string | yes | enum: ["path","query","header"] |
206
- | `routes.*.conditional.cases[].redirect.query.map.*.name` | string | yes | — |
207
- | `routes.*.conditional.cases[].respond` | object | no | unknown keys rejected |
208
- | `routes.*.conditional.cases[].respond.status` | integer | no | minimum: 200; maximum: 599 |
209
- | `routes.*.conditional.cases[].respond.text` | string | no | maxLength: 1048576 |
210
- | `routes.*.conditional.cases[].respond.json` | any JSON value | no | — |
211
- | `routes.*.conditional.cases[].match` | object | yes | minProperties: 1; unknown keys rejected |
212
- | `routes.*.conditional.cases[].match.query` | object | no | minProperties: 1; maxProperties: 16 |
213
- | `routes.*.conditional.cases[].match.query.*` | string | no | maxLength: 1024 |
214
- | `routes.*.conditional.cases[].match.headers` | object | no | minProperties: 1; maxProperties: 16 |
215
- | `routes.*.conditional.cases[].match.headers.*` | string | no | maxLength: 1024 |
216
- | `routes.*.conditional.cases[].match.cookies` | object | no | minProperties: 1; maxProperties: 16 |
217
- | `routes.*.conditional.cases[].match.cookies.*` | string | no | maxLength: 1024 |
218
- | `routes.*.conditional.cases[].match.host` | string | no | maxLength: 255 |
219
- | `routes.*.conditional.cases[].match.method` | string | no | enum: ["GET","HEAD","POST","PUT","PATCH","DELETE","OPTIONS"] |
220
- | `routes.*.conditional.fallback` | object | no | unknown keys rejected |
221
- | `routes.*.conditional.fallback.redirect` | object | no | unknown keys rejected |
222
- | `routes.*.conditional.fallback.redirect.url` | string | yes | maxLength: 8192 |
223
- | `routes.*.conditional.fallback.redirect.status` | number | no | enum: [301,302,303,307,308] |
224
- | `routes.*.conditional.fallback.redirect.query` | object | no | unknown keys rejected |
225
- | `routes.*.conditional.fallback.redirect.query.pass` | one of the shapes below | no | — |
226
- | `routes.*.conditional.fallback.redirect.query.pass (option 1)` | constant | no | const: false |
227
- | `routes.*.conditional.fallback.redirect.query.pass (option 2)` | array | no | uniqueItems: true |
228
- | `routes.*.conditional.fallback.redirect.query.pass (option 2)[]` | string | no | — |
229
- | `routes.*.conditional.fallback.redirect.query.map` | object | no | — |
230
- | `routes.*.conditional.fallback.redirect.query.map.*` | object | no | unknown keys rejected |
231
- | `routes.*.conditional.fallback.redirect.query.map.*.from` | string | yes | enum: ["path","query","header"] |
232
- | `routes.*.conditional.fallback.redirect.query.map.*.name` | string | yes | — |
233
- | `routes.*.conditional.fallback.respond` | object | no | unknown keys rejected |
234
- | `routes.*.conditional.fallback.respond.status` | integer | no | minimum: 200; maximum: 599 |
235
- | `routes.*.conditional.fallback.respond.text` | string | no | maxLength: 1048576 |
236
- | `routes.*.conditional.fallback.respond.json` | any JSON value | no | — |
237
- | `routes.*.proxy` | object | no | unknown keys rejected |
238
- | `routes.*.proxy.url` | string | yes | maxLength: 8192 |
239
- | `routes.*.proxy.headers` | object | no | maxProperties: 32 |
240
- | `routes.*.proxy.headers.*` | one of the shapes below | no | — |
241
- | `routes.*.proxy.headers.* (option 1)` | string | no | maxLength: 4096 |
242
- | `routes.*.proxy.headers.* (option 2)` | object | no | unknown keys rejected |
243
- | `routes.*.proxy.headers.* (option 2).secret` | string | yes | pattern: "^[A-Za-z_][A-Za-z0-9_]*$" |
244
- | `routes.*.proxy.query` | array | no | maxItems: 32; uniqueItems: true |
245
- | `routes.*.proxy.query[]` | string | no | minLength: 1; maxLength: 128 |
246
- | `routes.*.proxy.requestHeaders` | array | no | maxItems: 32; uniqueItems: true |
247
- | `routes.*.proxy.requestHeaders[]` | string | no | minLength: 1; maxLength: 128 |
248
- | `routes.*.proxy.responseHeaders` | array | no | maxItems: 32; uniqueItems: true |
249
- | `routes.*.proxy.responseHeaders[]` | string | no | minLength: 1; maxLength: 128 |
250
- | `routes.*.signals` | array | no | minItems: 1; maxItems: 8 |
251
- | `routes.*.signals[]` | object | no | unknown keys rejected |
252
- | `routes.*.signals[].url` | string | yes | maxLength: 8192 |
253
- | `routes.*.signals[].headers` | object | no | maxProperties: 32 |
254
- | `routes.*.signals[].headers.*` | one of the shapes below | no | — |
255
- | `routes.*.signals[].headers.* (option 1)` | string | no | maxLength: 4096 |
256
- | `routes.*.signals[].headers.* (option 2)` | object | no | unknown keys rejected |
257
- | `routes.*.signals[].headers.* (option 2).secret` | string | yes | pattern: "^[A-Za-z_][A-Za-z0-9_]*$" |
258
- | `routes.*.extension` | string | no | pattern: "^[a-z][a-z0-9-]{0,63}$" |
259
- | `routes.*.auth` | one of the shapes below | no | — |
260
- | `routes.*.auth (option 1)` | constant | no | const: true |
261
- | `routes.*.auth (option 2)` | object | no | unknown keys rejected |
262
- | `routes.*.auth (option 2).required` | boolean | no | default: true |
263
- | `routes.*.auth (option 2).role` | string | no | minLength: 1; maxLength: 64 |
264
- | `routes.*.auth (option 2).permission` | string | no | minLength: 1; maxLength: 128 |
265
- | `routes.*.auth (option 2).verified` | boolean | no | — |
266
- | `routes.*.auth (option 2).freshWithinSeconds` | integer | no | minimum: 1; maximum: 3600 |
267
- | `routes.*.auth (option 2).onDeny` | number / string | no | enum: [401,403,404,"sign-in"] |
268
- | `routes.*.cache` | object | no | unknown keys rejected |
269
- | `routes.*.cache.strategy` | string | no | enum: ["no-store","revalidate","public","immutable","swr","sie","micro","cdn-only","private"] |
270
- | `routes.*.cache.maxAge` | integer | no | minimum: 0; maximum: 31536000 |
271
- | `routes.*.cache.staleWhileRevalidate` | integer | no | minimum: 0; maximum: 31536000 |
272
- | `routes.*.cache.staleIfError` | integer | no | minimum: 0; maximum: 31536000 |
273
- | `routes.*.cache.cdnMaxAge` | integer | no | minimum: 0; maximum: 31536000 |
274
- | `routes.*.cache.originTtl` | integer | no | minimum: 0; maximum: 86400 |
275
- | `routes.*.cache.vary` | array | no | maxItems: 8; uniqueItems: true |
276
- | `routes.*.cache.vary[]` | string | no | minLength: 1; maxLength: 128 |
277
- | `routes.*.cache.statuses` | array | no | maxItems: 16; uniqueItems: true |
278
- | `routes.*.cache.statuses[]` | integer | no | minimum: 200; maximum: 599 |
279
- | `routes.*.cache.maxBytes` | integer | no | minimum: 0; maximum: 16777216 |
280
- | `routes.*.cache.maxEntries` | integer | no | minimum: 1; maximum: 1000000 |
281
- | `routes.*.cache.force` | boolean | no | default: false |
282
- | `includes` | array | no | maxItems: 256; uniqueItems: true |
283
- | `includes[]` | string | no | maxLength: 1024 |
284
- | `policies` | object | no | unknown keys rejected |
285
- | `policies.profile` | string | no | pattern: "^[a-z][a-z0-9-]{0,63}$" |
286
- | `policies.throttle` | one of the shapes below | no | — |
287
- | `policies.throttle (option 1)` | constant | no | const: false |
288
- | `policies.throttle (option 2)` | object | no | unknown keys rejected |
289
- | `policies.throttle (option 2).quota` | integer | no | minimum: 1; maximum: 1000000 |
290
- | `policies.throttle (option 2).window` | integer | no | minimum: 1; maximum: 86400 |
291
- | `policies.throttle (option 2).partition` | string | no | enum: ["client","route","client-route"]; default: "client" |
292
- | `policies.throttle (option 2).status` | integer | no | default: 429; minimum: 400; maximum: 599 |
293
- | `policies.throttle (option 2).mode` | string | no | enum: ["enforce","report"]; default: "enforce" |
294
- | `policies.throttle (option 2).maxKeys` | integer | no | default: 100000; minimum: 1000; maximum: 10000000 |
295
- | `policies.agents` | one of the shapes below | no | — |
296
- | `policies.agents (option 1)` | constant | no | const: false |
297
- | `policies.agents (option 2)` | object | no | unknown keys rejected |
298
- | `policies.agents (option 2).deny` | array | no | maxItems: 32; uniqueItems: true |
299
- | `policies.agents (option 2).deny[]` | string | no | minLength: 1; maxLength: 1024 |
300
- | `policies.agents (option 2).allow` | array | no | maxItems: 32; uniqueItems: true |
301
- | `policies.agents (option 2).allow[]` | string | no | minLength: 1; maxLength: 1024 |
302
- | `policies.agents (option 2).denyPatterns` | array | no | maxItems: 256; uniqueItems: true |
303
- | `policies.agents (option 2).denyPatterns[]` | string | no | minLength: 1; maxLength: 256 |
304
- | `policies.agents (option 2).allowPatterns` | array | no | maxItems: 256; uniqueItems: true |
305
- | `policies.agents (option 2).allowPatterns[]` | string | no | minLength: 1; maxLength: 256 |
306
- | `policies.agents (option 2).denyEmpty` | boolean | no | default: false |
307
- | `policies.agents (option 2).status` | integer | no | default: 403; minimum: 400; maximum: 599 |
308
- | `policies.agents (option 2).mode` | string | no | enum: ["enforce","report"]; default: "enforce" |
309
- | `policies.security` | one of the shapes below | no | — |
310
- | `policies.security (option 1)` | constant | no | const: false |
311
- | `policies.security (option 2)` | object | no | unknown keys rejected |
312
- | `policies.security (option 2).headers` | string | no | enum: ["oshp","oshp-no-csp","off"]; default: "oshp" |
313
- | `policies.security (option 2).set` | object | no | maxProperties: 32 |
314
- | `policies.security (option 2).set.*` | string | no | maxLength: 4096 |
315
- | `policies.security (option 2).unset` | array | no | maxItems: 32; uniqueItems: true |
316
- | `policies.security (option 2).unset[]` | string | no | minLength: 1; maxLength: 128 |
317
- | `policies.compression` | one of the shapes below | no | — |
318
- | `policies.compression (option 1)` | constant | no | const: false |
319
- | `policies.compression (option 2)` | object | no | unknown keys rejected |
320
- | `policies.compression (option 2).encodings` | array | no | default: ["br","gzip"]; minItems: 1; uniqueItems: true |
321
- | `policies.compression (option 2).encodings[]` | string | no | enum: ["br","gzip","deflate","zstd"] |
322
- | `policies.compression (option 2).minBytes` | integer | no | default: 1024; minimum: 0; maximum: 1048576 |
323
- | `policies.compression (option 2).types` | array | no | maxItems: 64; uniqueItems: true |
324
- | `policies.compression (option 2).types[]` | string | no | minLength: 1; maxLength: 128 |
325
- | `policies.compression (option 2).level` | integer | no | minimum: 1; maximum: 11 |
326
- | `policies.compression (option 2).allowWithSecrets` | boolean | no | default: false |
327
- | `policies.cache` | one of the shapes below | no | — |
328
- | `policies.cache (option 1)` | constant | no | const: false |
329
- | `policies.cache (option 2)` | object | no | unknown keys rejected |
330
- | `policies.cache (option 2).strategy` | string | no | enum: ["no-store","revalidate","public","immutable","swr","sie","micro","cdn-only","private"] |
331
- | `policies.cache (option 2).maxAge` | integer | no | minimum: 0; maximum: 31536000 |
332
- | `policies.cache (option 2).staleWhileRevalidate` | integer | no | minimum: 0; maximum: 31536000 |
333
- | `policies.cache (option 2).staleIfError` | integer | no | minimum: 0; maximum: 31536000 |
334
- | `policies.cache (option 2).cdnMaxAge` | integer | no | minimum: 0; maximum: 31536000 |
335
- | `policies.cache (option 2).originTtl` | integer | no | minimum: 0; maximum: 86400 |
336
- | `policies.cache (option 2).vary` | array | no | maxItems: 8; uniqueItems: true |
337
- | `policies.cache (option 2).vary[]` | string | no | minLength: 1; maxLength: 128 |
338
- | `policies.cache (option 2).statuses` | array | no | maxItems: 16; uniqueItems: true |
339
- | `policies.cache (option 2).statuses[]` | integer | no | minimum: 200; maximum: 599 |
340
- | `policies.cache (option 2).maxBytes` | integer | no | minimum: 0; maximum: 16777216 |
341
- | `policies.cache (option 2).maxEntries` | integer | no | minimum: 1; maximum: 1000000 |
342
- | `policies.cache (option 2).force` | boolean | no | default: false |
343
- | `policies.extensions` | one of the shapes below | no | — |
344
- | `policies.extensions (option 1)` | constant | no | const: false |
345
- | `policies.extensions (option 2)` | object | no | maxProperties: 16 |
346
- | `policies.extensions (option 2).*` | one of the shapes below | no | — |
347
- | `policies.extensions (option 2).* (option 1)` | constant | no | const: false |
348
- | `policies.extensions (option 2).* (option 2)` | object | no | — |
349
- | `profiles` | object | no | maxProperties: 32 |
350
- | `profiles.*` | object | no | unknown keys rejected |
351
- | `profiles.*.throttle` | one of the shapes below | no | — |
352
- | `profiles.*.throttle (option 1)` | constant | no | const: false |
353
- | `profiles.*.throttle (option 2)` | object | no | unknown keys rejected |
354
- | `profiles.*.throttle (option 2).quota` | integer | no | minimum: 1; maximum: 1000000 |
355
- | `profiles.*.throttle (option 2).window` | integer | no | minimum: 1; maximum: 86400 |
356
- | `profiles.*.throttle (option 2).partition` | string | no | enum: ["client","route","client-route"]; default: "client" |
357
- | `profiles.*.throttle (option 2).status` | integer | no | default: 429; minimum: 400; maximum: 599 |
358
- | `profiles.*.throttle (option 2).mode` | string | no | enum: ["enforce","report"]; default: "enforce" |
359
- | `profiles.*.throttle (option 2).maxKeys` | integer | no | default: 100000; minimum: 1000; maximum: 10000000 |
360
- | `profiles.*.agents` | one of the shapes below | no | — |
361
- | `profiles.*.agents (option 1)` | constant | no | const: false |
362
- | `profiles.*.agents (option 2)` | object | no | unknown keys rejected |
363
- | `profiles.*.agents (option 2).deny` | array | no | maxItems: 32; uniqueItems: true |
364
- | `profiles.*.agents (option 2).deny[]` | string | no | minLength: 1; maxLength: 1024 |
365
- | `profiles.*.agents (option 2).allow` | array | no | maxItems: 32; uniqueItems: true |
366
- | `profiles.*.agents (option 2).allow[]` | string | no | minLength: 1; maxLength: 1024 |
367
- | `profiles.*.agents (option 2).denyPatterns` | array | no | maxItems: 256; uniqueItems: true |
368
- | `profiles.*.agents (option 2).denyPatterns[]` | string | no | minLength: 1; maxLength: 256 |
369
- | `profiles.*.agents (option 2).allowPatterns` | array | no | maxItems: 256; uniqueItems: true |
370
- | `profiles.*.agents (option 2).allowPatterns[]` | string | no | minLength: 1; maxLength: 256 |
371
- | `profiles.*.agents (option 2).denyEmpty` | boolean | no | default: false |
372
- | `profiles.*.agents (option 2).status` | integer | no | default: 403; minimum: 400; maximum: 599 |
373
- | `profiles.*.agents (option 2).mode` | string | no | enum: ["enforce","report"]; default: "enforce" |
374
- | `profiles.*.security` | one of the shapes below | no | — |
375
- | `profiles.*.security (option 1)` | constant | no | const: false |
376
- | `profiles.*.security (option 2)` | object | no | unknown keys rejected |
377
- | `profiles.*.security (option 2).headers` | string | no | enum: ["oshp","oshp-no-csp","off"]; default: "oshp" |
378
- | `profiles.*.security (option 2).set` | object | no | maxProperties: 32 |
379
- | `profiles.*.security (option 2).set.*` | string | no | maxLength: 4096 |
380
- | `profiles.*.security (option 2).unset` | array | no | maxItems: 32; uniqueItems: true |
381
- | `profiles.*.security (option 2).unset[]` | string | no | minLength: 1; maxLength: 128 |
382
- | `profiles.*.compression` | one of the shapes below | no | — |
383
- | `profiles.*.compression (option 1)` | constant | no | const: false |
384
- | `profiles.*.compression (option 2)` | object | no | unknown keys rejected |
385
- | `profiles.*.compression (option 2).encodings` | array | no | default: ["br","gzip"]; minItems: 1; uniqueItems: true |
386
- | `profiles.*.compression (option 2).encodings[]` | string | no | enum: ["br","gzip","deflate","zstd"] |
387
- | `profiles.*.compression (option 2).minBytes` | integer | no | default: 1024; minimum: 0; maximum: 1048576 |
388
- | `profiles.*.compression (option 2).types` | array | no | maxItems: 64; uniqueItems: true |
389
- | `profiles.*.compression (option 2).types[]` | string | no | minLength: 1; maxLength: 128 |
390
- | `profiles.*.compression (option 2).level` | integer | no | minimum: 1; maximum: 11 |
391
- | `profiles.*.compression (option 2).allowWithSecrets` | boolean | no | default: false |
392
- | `profiles.*.cache` | one of the shapes below | no | — |
393
- | `profiles.*.cache (option 1)` | constant | no | const: false |
394
- | `profiles.*.cache (option 2)` | object | no | unknown keys rejected |
395
- | `profiles.*.cache (option 2).strategy` | string | no | enum: ["no-store","revalidate","public","immutable","swr","sie","micro","cdn-only","private"] |
396
- | `profiles.*.cache (option 2).maxAge` | integer | no | minimum: 0; maximum: 31536000 |
397
- | `profiles.*.cache (option 2).staleWhileRevalidate` | integer | no | minimum: 0; maximum: 31536000 |
398
- | `profiles.*.cache (option 2).staleIfError` | integer | no | minimum: 0; maximum: 31536000 |
399
- | `profiles.*.cache (option 2).cdnMaxAge` | integer | no | minimum: 0; maximum: 31536000 |
400
- | `profiles.*.cache (option 2).originTtl` | integer | no | minimum: 0; maximum: 86400 |
401
- | `profiles.*.cache (option 2).vary` | array | no | maxItems: 8; uniqueItems: true |
402
- | `profiles.*.cache (option 2).vary[]` | string | no | minLength: 1; maxLength: 128 |
403
- | `profiles.*.cache (option 2).statuses` | array | no | maxItems: 16; uniqueItems: true |
404
- | `profiles.*.cache (option 2).statuses[]` | integer | no | minimum: 200; maximum: 599 |
405
- | `profiles.*.cache (option 2).maxBytes` | integer | no | minimum: 0; maximum: 16777216 |
406
- | `profiles.*.cache (option 2).maxEntries` | integer | no | minimum: 1; maximum: 1000000 |
407
- | `profiles.*.cache (option 2).force` | boolean | no | default: false |
408
- | `profiles.*.extensions` | one of the shapes below | no | — |
409
- | `profiles.*.extensions (option 1)` | constant | no | const: false |
410
- | `profiles.*.extensions (option 2)` | object | no | maxProperties: 16 |
411
- | `profiles.*.extensions (option 2).*` | one of the shapes below | no | — |
412
- | `profiles.*.extensions (option 2).* (option 1)` | constant | no | const: false |
413
- | `profiles.*.extensions (option 2).* (option 2)` | object | no | — |
414
- | `site` | object | no | unknown keys rejected |
415
- | `site.robots` | object | no | unknown keys rejected |
416
- | `site.robots.disallow` | array | no | maxItems: 1024; uniqueItems: true |
417
- | `site.robots.disallow[]` | string | no | minLength: 1; maxLength: 2048 |
418
- | `site.robots.allow` | array | no | maxItems: 1024; uniqueItems: true |
419
- | `site.robots.allow[]` | string | no | minLength: 1; maxLength: 2048 |
420
- | `site.robots.sitemap` | boolean | no | — |
421
- | `site.robots.extra` | array | no | maxItems: 1024 |
422
- | `site.robots.extra[]` | string | no | maxLength: 2048 |
423
- | `site.sitemap` | one of the shapes below | no | — |
424
- | `site.sitemap (option 1)` | constant | no | const: true |
425
- | `site.sitemap (option 2)` | object | no | unknown keys rejected |
426
- | `site.sitemap (option 2).exclude` | array | no | maxItems: 1024; uniqueItems: true |
427
- | `site.sitemap (option 2).exclude[]` | string | no | minLength: 1; maxLength: 2048 |
428
- | `site.sitemap (option 2).changefreq` | string | no | enum: ["always","hourly","daily","weekly","monthly","yearly","never"] |
429
- | `site.sitemap (option 2).priority` | number | no | minimum: 0; maximum: 1 |
430
- | `site.favicon` | string | no | minLength: 1; maxLength: 1024 |
431
- | `site.securityTxt` | object | no | unknown keys rejected |
432
- | `site.securityTxt.contact` | array | yes | minItems: 1; maxItems: 64 |
433
- | `site.securityTxt.contact[]` | string | no | minLength: 1; maxLength: 2048 |
434
- | `site.securityTxt.expires` | string | yes | pattern: "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d{3})?Z$" |
435
- | `site.securityTxt.policy` | array | no | maxItems: 64 |
436
- | `site.securityTxt.policy[]` | string | no | maxLength: 2048; pattern: "^https://" |
437
- | `site.securityTxt.acknowledgments` | array | no | maxItems: 64 |
438
- | `site.securityTxt.acknowledgments[]` | string | no | maxLength: 2048; pattern: "^https://" |
439
- | `site.securityTxt.preferredLanguages` | array | no | minItems: 1; maxItems: 64 |
440
- | `site.securityTxt.preferredLanguages[]` | string | no | minLength: 2; maxLength: 35 |
441
- | `site.securityTxt.canonical` | array | no | maxItems: 64 |
442
- | `site.securityTxt.canonical[]` | string | no | maxLength: 2048; pattern: "^https://" |
443
- | `site.securityTxt.encryption` | array | no | maxItems: 64 |
444
- | `site.securityTxt.encryption[]` | string | no | minLength: 1; maxLength: 2048 |
445
- | `site.llms` | string | no | minLength: 1; maxLength: 1024 |
446
- | `extensions` | object | no | maxProperties: 16 |
447
- | `extensions.*` | object | no | unknown keys rejected |
448
- | `extensions.*.version` | constant | yes | const: "1" |
449
- | `extensions.*.config` | object | yes | — |
@@ -1,68 +0,0 @@
1
- # Historical record
2
-
3
- Archived 2026-09-19. This records an earlier implementation or proposal, not
4
- current instructions. See the [current roadmap](../../../ROADMAP.md),
5
- [current contract](../../SPECIFICATION.md) and [open decisions](../../OPEN-DECISIONS.md).
6
- Remaining acceptance work is not declared complete by archiving this record.
7
-
8
- <!-- trust-model-prose: historical-file -->
9
- <!-- guidance-claims: ignore-file -->
10
-
11
- # Extension implementation sequence
12
-
13
- PR #54 records the auth, admin, UI and extension direction. Implementation is
14
- incremental; the spikes are proposals, not the implemented project schema.
15
- The implemented specification remains authoritative. This sequence incorporates
16
- the architectural review rather than treating contradictory spike examples as
17
- requirements.
18
-
19
- ## Invariants
20
-
21
- - Operators explicitly install trusted host extensions; project YAML never loads
22
- host modules or chooses packages. Application code remains isolated in WASM.
23
- - Authentication credentials stay in host processing. Guest Request headers and
24
- header-derived parameters must not expose operator-declared credential headers,
25
- including on public routes receiving a session cookie.
26
- - Session and one-time-token changes have explicit concurrency semantics. Define
27
- atomic operations before selecting a database abstraction; multi-record
28
- operations cannot rely on a same-collection transaction promise.
29
- - Passwords and bearer credentials use appropriate hashes. TOTP requires protected
30
- recoverable key material and an operator key rotation/backup contract.
31
- - Authentication forms and submission destinations belong to trusted extension
32
- code. Project styling does not imply permission to replace security controls.
33
- - Administrative authorization is enforced by the API, including subject-level
34
- restrictions, self-promotion and last-administrator protections.
35
- - Unsupported target capabilities fail explicitly. Live provider deployment
36
- testing remains deferred and non-blocking; local tests do not prove deployment.
37
-
38
- ## Delivery order
39
-
40
- 1. **Credential boundary:** add an explicit host-plugin declaration for headers
41
- withheld from guest requests and parameter resolution. Preserve originals for
42
- host authentication, cache decisions and policy processing. Test functions,
43
- middleware and routes without an authentication requirement.
44
- 2. **Extension registration:** explicit operator registry, versioned configuration
45
- validation, route ownership/collision rules and capability reporting. No
46
- automatic project host-file execution. Define policy ordering before adding
47
- an auth policy.
48
- 3. **Session slice:** one supported login method, trusted login/logout forms,
49
- protected page and JSON routes, session lookup/revocation, CSRF and no-store
50
- behavior. Evaluate a maintained authentication implementation behind an
51
- adapter before writing protocol engines. Define durable atomic store methods
52
- and test concurrent redemption, expiry and interrupted operations.
53
- 4. **Administrative API and CLI:** user lookup and session revocation first;
54
- audit records and narrowly scoped permissions. Add role/recovery operations
55
- only with object-level rules and concurrency tests.
56
- 5. **UI and console:** extract components from real auth/admin flows; choose a
57
- constrained renderer and asset ownership model; verify keyboard and assistive
58
- technology behavior as well as automated accessibility checks.
59
- 6. **Additional methods and targets:** passkeys, OIDC, MFA, recovery and imports
60
- each receive state-machine, abuse-budget and portability tests. Preserve
61
- verification of existing credential formats across target migrations.
62
-
63
- ## Status
64
-
65
- PR #54 is merged. The first implementation adds the operator-only
66
- `Plugin.credentialHeaders` boundary, documented in [Plugins](../../PLUGINS.md).
67
- The remaining items are pending; none of this document declares end-user auth,
68
- admin routes, extension YAML, or a generic project store available today.
@@ -1,102 +0,0 @@
1
- # Historical record
2
-
3
- Archived 2026-09-19. This records an earlier implementation or proposal, not
4
- current instructions. See the [current roadmap](../../../ROADMAP.md),
5
- [current contract](../../SPECIFICATION.md) and [open decisions](../../OPEN-DECISIONS.md).
6
- Remaining acceptance work is not declared complete by archiving this record.
7
-
8
- <!-- trust-model-prose: historical-file -->
9
- <!-- guidance-claims: ignore-file -->
10
-
11
- # Private management and durable mutation audit
12
-
13
- > **Retired.** This page describes the management API and mutation audit of
14
- > core's native link store. That store, its `urlcode links` CLI and this
15
- > management listener were removed from core when `link` was extracted, and the
16
- > `urlcode-dynamic-link` package that received them has since been retired and
17
- > unpublished. Nothing in the current runtime exposes this surface. The page is
18
- > kept because the security reasoning — loopback-only binding, operator-owned
19
- > credential policy, transactional mutation audit — is referenced by
20
- > [security audit](../../SECURITY-AUDIT.md) and applies to any component that
21
- > reintroduces a management listener.
22
-
23
- Management binds only `127.0.0.1` or `::1`. Use an authenticated private tunnel
24
- (e.g. SSH/VPN with loopback forwarding); never publish its port through a public
25
- proxy or container port mapping. This is operator management, not an end-user
26
- account service. Browser Origin requests remain rejected.
27
-
28
- ## Individual credentials
29
-
30
- Use `urlcode links api --project ./my-links --store /operator/links.sqlite
31
- --auth-file /operator/management.json --host 127.0.0.1 --port 3001` (one line).
32
- The policy is operator-owned, outside the application, at most 64 KiB and mode
33
- 600 on POSIX. Protect its parent directory and apply equivalent Windows ACLs.
34
- It is not YAML and must never be placed in the application or Git.
35
-
36
- Generate each token with `node -e "console.log(require('node:crypto').randomBytes(32).toString('base64url'))"`
37
- on a trusted operator machine. Deliver it through your secret manager. Hash the
38
- raw token using SHA-256 without a newline; the server expects `Authorization:
39
- Bearer <token>`. Tokens must contain 43–256 base64url characters. Never use a
40
- human password as a token. This synthetic policy illustrates the shape; replace
41
- the hash with the real token hash and choose a short operational expiry:
42
-
43
- ```json
44
- {
45
- "version": 1,
46
- "credentials": [{
47
- "id": "operator-alice",
48
- "sha256": "0000000000000000000000000000000000000000000000000000000000000000",
49
- "expires": "2026-10-01T00:00:00Z",
50
- "collections": ["links"],
51
- "actions": ["get", "list", "create", "update", "delete"]
52
- }]
53
- }
54
- ```
55
-
56
- At most 128 credentials; unique IDs and hashes; explicit collection and action
57
- allowlists with no wildcards. Readers should receive only `get` and `list`.
58
- An expired, removed or `"revoked": true` credential gets 401; a valid credential
59
- outside its scope gets 403. The entire policy is validated on every authenticated
60
- request. Malformed/unreadable policy fails closed with 503, without retaining an
61
- old permissive copy. Write a replacement file with mode 600 and atomically rename
62
- it over the policy. No restart is needed. Requests already authorized may finish;
63
- revocation does not cancel an in-flight transaction. Credential administration is
64
- an operator filesystem action, never exposed through this HTTP API.
65
-
66
- Legacy `--token-file` remains available for local compatibility, with full access
67
- to that listener's collection and actor `legacy-shared`. Prefer `--auth-file` for
68
- attribution, expiry and revocation. They are mutually exclusive. These bearer
69
- credentials do not establish verified human identity, MFA, SSO or session login.
70
- Host administrators and custom embedding code remain trusted operators.
71
-
72
- ## Audit durability and recovery
73
-
74
- The built-in SQLite writer creates an additive `urlcode_link_audit` table when
75
- opening a store. Every successful create/update/delete (including CLI and embedded
76
- store calls) records revision, UTC timestamp, actor, request ID, collection,
77
- action and SHA-256 of the short code in the **same transaction** as the mutation.
78
- The default local CLI actor is `local-operator`. Scoped HTTP management requires
79
- an adapter explicitly declaring atomic audit support; the built-in store provides it.
80
-
81
- An audit insert failure rolls back both mutation and revision. Conditional-write
82
- conflicts and rejected requests produce no successful-mutation row. HTTP request
83
- logs still describe failed/aborted requests and remain best effort. A client timeout
84
- may follow a committed transaction: reconcile the revision and request ID before
85
- retrying. A lost HTTP reply is not evidence that the transaction was rolled back.
86
-
87
- Inspect the journal with an operator-only SQLite client, for example:
88
-
89
- ```sql
90
- SELECT revision, timestamp, actor, request_id, collection, action, code_sha256
91
- FROM urlcode_link_audit WHERE revision > 0 ORDER BY revision LIMIT 100;
92
- ```
93
-
94
- No token, URL, request body or raw short code is stored in the journal. Code hashes
95
- are correlatable and guessable for short codes; restrict access accordingly.
96
- This is a durable local transaction journal, **not tamper-evident external storage**.
97
- An administrator with database access can change it. Export ordered revisions to
98
- your protected collector/backup system and monitor lag, gaps and disk/WAL growth.
99
- There is no automatic pruning: define retention and verify archival before any
100
- operator purge. Keep audit records in backups. User_version remains 1 because
101
- this table is additive; older readers work, but older writers do not emit audit
102
- rows. Never roll a management writer back to an unaudited revision.