@jimhoyd/urlcode 0.3.0 → 0.4.0-alpha.2

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 (380) hide show
  1. package/.claude/skills/urlcode-authoring/SKILL.md +122 -0
  2. package/.claude/skills/urlcode-operations/SKILL.md +108 -0
  3. package/.claude-plugin/marketplace.json +18 -0
  4. package/CONTRIBUTING.md +30 -2
  5. package/README.md +195 -255
  6. package/ROADMAP.md +143 -15
  7. package/SECURITY.md +31 -9
  8. package/dist/BUILD-MANIFEST.json +72 -47
  9. package/dist/adapters.js +4 -23
  10. package/dist/agent-lists.js +1 -1
  11. package/dist/agents-guide.js +113 -0
  12. package/dist/authoring-files.js +60 -0
  13. package/dist/authoring.js +11 -1
  14. package/dist/aws.js +4 -3
  15. package/dist/build-cloudflare.js +11 -24
  16. package/dist/build-static.js +134 -0
  17. package/dist/bulk.js +37 -0
  18. package/dist/capabilities.js +262 -0
  19. package/dist/capability-query.js +71 -0
  20. package/dist/catalog.js +105 -0
  21. package/dist/cli.js +165 -34
  22. package/dist/client-address.js +1 -1
  23. package/dist/compliance-rules/baseline.js +9 -17
  24. package/dist/compliance-rules/privacy.js +7 -18
  25. package/dist/compliance-rules/shared.js +0 -2
  26. package/dist/compliance-rules/strict.js +5 -5
  27. package/dist/compliance.js +6 -8
  28. package/dist/conditions.js +88 -0
  29. package/dist/config.js +69 -6
  30. package/dist/context.js +155 -0
  31. package/dist/ecosystem-cli.js +88 -0
  32. package/dist/egress.js +98 -0
  33. package/dist/examples.js +92 -0
  34. package/dist/explain-cli.js +64 -0
  35. package/dist/explain.js +131 -0
  36. package/dist/extensions.js +231 -0
  37. package/dist/function-sources.js +49 -5
  38. package/dist/function-worker.js +3 -1
  39. package/dist/functions.js +84 -13
  40. package/dist/guest-api.js +29 -3
  41. package/dist/index.js +40 -6
  42. package/dist/init-with.js +165 -0
  43. package/dist/interchange-cli.js +42 -0
  44. package/dist/interchange.js +189 -0
  45. package/dist/manifest.js +109 -0
  46. package/dist/match.js +2 -2
  47. package/dist/mcp-authoring.js +147 -0
  48. package/dist/mcp.js +97 -0
  49. package/dist/observability.js +7 -21
  50. package/dist/operator-host.js +29 -0
  51. package/dist/plugins.js +12 -0
  52. package/dist/policies/agents.js +2 -2
  53. package/dist/policies/cache.js +8 -3
  54. package/dist/policies/compression.js +2 -1
  55. package/dist/policies/security.js +0 -0
  56. package/dist/policies.js +1 -1
  57. package/dist/policy.js +56 -15
  58. package/dist/prerender.js +100 -41
  59. package/dist/project-tests.js +3 -3
  60. package/dist/provider-verification.js +92 -0
  61. package/dist/proxy.js +44 -0
  62. package/dist/readiness.js +34 -11
  63. package/dist/recipes.js +41 -0
  64. package/dist/route-diff.js +106 -0
  65. package/dist/router.js +45 -7
  66. package/dist/runtime.js +164 -64
  67. package/dist/sandbox.js +48 -0
  68. package/dist/scaffold.js +0 -0
  69. package/dist/schema-query.js +62 -0
  70. package/dist/scripts/operational-drills.js +12 -54
  71. package/dist/server.js +3 -29
  72. package/dist/signals.js +24 -0
  73. package/dist/site.js +0 -0
  74. package/dist/tooling.js +96 -0
  75. package/dist/trusted-functions.js +210 -0
  76. package/dist/types/adapters.d.ts +7 -4
  77. package/dist/types/agent-lists.d.ts +0 -1
  78. package/dist/types/agents-guide.d.ts +17 -0
  79. package/dist/types/authoring-files.d.ts +10 -0
  80. package/dist/types/aws.d.ts +3 -1
  81. package/dist/types/build-cloudflare.d.ts +1 -0
  82. package/dist/types/build-static.d.ts +43 -0
  83. package/dist/types/bulk.d.ts +27 -0
  84. package/dist/types/capabilities.d.ts +64 -0
  85. package/dist/types/capability-query.d.ts +24 -0
  86. package/dist/types/catalog.d.ts +65 -0
  87. package/dist/types/client-address.d.ts +0 -1
  88. package/dist/types/compliance-rules/baseline.d.ts +1 -9
  89. package/dist/types/compliance-rules/privacy.d.ts +1 -4
  90. package/dist/types/compliance-rules/shared.d.ts +0 -2
  91. package/dist/types/compliance-rules/strict.d.ts +0 -5
  92. package/dist/types/compliance.d.ts +0 -3
  93. package/dist/types/conditions.d.ts +19 -0
  94. package/dist/types/config.d.ts +21 -2
  95. package/dist/types/context.d.ts +66 -0
  96. package/dist/types/ecosystem-cli.d.ts +17 -0
  97. package/dist/types/egress.d.ts +46 -0
  98. package/dist/types/examples.d.ts +50 -0
  99. package/dist/types/explain-cli.d.ts +11 -0
  100. package/dist/types/explain.d.ts +95 -0
  101. package/dist/types/extensions.d.ts +177 -0
  102. package/dist/types/function-sources.d.ts +9 -0
  103. package/dist/types/functions.d.ts +48 -5
  104. package/dist/types/guest-api.d.ts +1 -0
  105. package/dist/types/index.d.ts +36 -6
  106. package/dist/types/init-with.d.ts +30 -0
  107. package/dist/types/interchange-cli.d.ts +16 -0
  108. package/dist/types/interchange.d.ts +42 -0
  109. package/dist/types/manifest.d.ts +79 -0
  110. package/dist/types/match.d.ts +1 -0
  111. package/dist/types/mcp-authoring.d.ts +92 -0
  112. package/dist/types/mcp.d.ts +12 -0
  113. package/dist/types/observability.d.ts +3 -14
  114. package/dist/types/operator-host.d.ts +8 -0
  115. package/dist/types/plugins.d.ts +2 -0
  116. package/dist/types/policies/agents.d.ts +0 -2
  117. package/dist/types/policies/compression.d.ts +2 -0
  118. package/dist/types/policies/security.d.ts +0 -1
  119. package/dist/types/policy.d.ts +15 -4
  120. package/dist/types/project-tests.d.ts +3 -2
  121. package/dist/types/provider-verification.d.ts +53 -0
  122. package/dist/types/proxy.d.ts +21 -0
  123. package/dist/types/readiness.d.ts +10 -3
  124. package/dist/types/recipes.d.ts +30 -0
  125. package/dist/types/route-diff.d.ts +27 -0
  126. package/dist/types/router.d.ts +2 -1
  127. package/dist/types/runtime.d.ts +11 -27
  128. package/dist/types/sandbox.d.ts +12 -0
  129. package/dist/types/scaffold.d.ts +0 -2
  130. package/dist/types/schema-query.d.ts +12 -0
  131. package/dist/types/server.d.ts +1 -4
  132. package/dist/types/signals.d.ts +25 -0
  133. package/dist/types/site.d.ts +0 -1
  134. package/dist/types/tooling.d.ts +115 -0
  135. package/dist/types/trusted-functions.d.ts +29 -0
  136. package/dist/types/types.d.ts +71 -7
  137. package/dist/types/typescript-authoring.d.ts +12 -0
  138. package/dist/types/vercel.d.ts +3 -1
  139. package/dist/types/verify-deployment.d.ts +47 -0
  140. package/dist/types.js +37 -5
  141. package/dist/typescript-authoring.js +142 -0
  142. package/dist/vercel.js +4 -3
  143. package/dist/verify-deployment.js +270 -0
  144. package/docs/AI-AUTHORING.md +232 -15
  145. package/docs/AWS.md +4 -4
  146. package/docs/BEST-PRACTICES.md +3 -2
  147. package/docs/BULK.md +79 -0
  148. package/docs/CAPABILITIES.md +192 -0
  149. package/docs/CAPACITY.md +129 -32
  150. package/docs/CI.md +142 -0
  151. package/docs/CLOUDFLARE.md +1 -2
  152. package/docs/COMPLIANCE.md +6 -9
  153. package/docs/CONDITIONS.md +74 -0
  154. package/docs/DEPLOYMENT-CHECKS.md +108 -0
  155. package/docs/EGRESS.md +125 -0
  156. package/docs/EXTENSIONS.md +398 -0
  157. package/docs/FRAMEWORK.md +198 -0
  158. package/docs/FUNCTION-SECURITY.md +129 -32
  159. package/docs/INSTALL.md +45 -12
  160. package/docs/INTERCHANGE.md +134 -0
  161. package/docs/LOAD-TESTING.md +4 -4
  162. package/docs/MIDDLEWARE-EXAMPLES.md +75 -0
  163. package/docs/MIDDLEWARE.md +29 -16
  164. package/docs/MONITORING.md +2 -19
  165. package/docs/NEXT-PHASE-PLAN.md +98 -0
  166. package/docs/NEXT-STEPS.md +634 -0
  167. package/docs/OBSERVABILITY.md +11 -18
  168. package/docs/OPEN-DECISIONS.md +212 -0
  169. package/docs/OPERATIONAL-PROOF.md +30 -31
  170. package/docs/OPERATIONS.md +29 -35
  171. package/docs/PLUGINS.md +37 -0
  172. package/docs/POLICIES.md +23 -309
  173. package/docs/PRERENDER.md +41 -1
  174. package/docs/PROJECT-DIRECTION.md +75 -8
  175. package/docs/PROVIDER-VERIFICATION.md +84 -0
  176. package/docs/READINESS.md +21 -1
  177. package/docs/README.md +87 -34
  178. package/docs/RECIPES.md +99 -0
  179. package/docs/RELEASE-READINESS.md +57 -35
  180. package/docs/RELEASE-SECURITY.md +116 -7
  181. package/docs/RESILIENCE.md +16 -15
  182. package/docs/ROUTING.md +8 -10
  183. package/docs/SANDBOX-REVIEW.md +19 -6
  184. package/docs/SCAFFOLDING.md +0 -2
  185. package/docs/SECURITY-AUDIT.md +41 -1
  186. package/docs/SPECIFICATION.md +150 -29
  187. package/docs/SPIKE-AI-FRAMEWORK-BENCHMARK.md +287 -0
  188. package/docs/SPIKE-BUSINESS-SUITE.md +1021 -0
  189. package/docs/SPIKE-CORE-LAYERING.md +337 -0
  190. package/docs/SPIKE-DEFAULT-TRUST-MODEL.md +209 -0
  191. package/docs/SPIKE-EXTENSION-MODEL.md +419 -0
  192. package/docs/SPIKE-EXTENSIONS.md +6 -0
  193. package/docs/SPIKE-LAMBDA-COMPILE.md +201 -0
  194. package/docs/SPIKE-MONOREPO.md +322 -0
  195. package/docs/STANDARDS.md +150 -142
  196. package/docs/STARTERS.md +21 -1
  197. package/docs/STATIC.md +94 -0
  198. package/docs/TOOLING.md +295 -0
  199. package/docs/TUNNELS.md +0 -3
  200. package/docs/TYPESCRIPT-AUTHORING.md +82 -0
  201. package/docs/TYPESCRIPT.md +25 -4
  202. package/docs/USABILITY-REVIEW.md +129 -0
  203. package/docs/VERCEL.md +4 -5
  204. package/docs/VERSION-ALIGNMENT.md +205 -0
  205. package/docs/YAML-GUIDE.md +15 -479
  206. package/docs/YAML-REFERENCE.md +143 -22
  207. package/docs/policies/agents.md +1 -1
  208. package/docs/policies/cache.md +13 -0
  209. package/docs/policies/contract.md +52 -0
  210. package/docs/policies/hardened.md +56 -0
  211. package/docs/policies/interoperability.md +169 -0
  212. package/docs/policies/operations.md +45 -0
  213. package/docs/yaml/assets.md +36 -0
  214. package/docs/yaml/conditions.md +20 -0
  215. package/docs/yaml/functions.md +160 -0
  216. package/docs/yaml/middleware.md +29 -0
  217. package/docs/yaml/organization.md +74 -0
  218. package/docs/yaml/policies.md +37 -0
  219. package/docs/yaml/redirects.md +64 -0
  220. package/docs/yaml/responses.md +57 -0
  221. package/docs/yaml/site.md +24 -0
  222. package/examples/assets/example.yaml +17 -0
  223. package/examples/aws/example.yaml +20 -0
  224. package/examples/cloudflare/example.yaml +19 -0
  225. package/examples/compliance/example.yaml +11 -0
  226. package/examples/conditions/README.md +12 -0
  227. package/examples/conditions/example.yaml +19 -0
  228. package/examples/conditions/tests/requests.json +13 -0
  229. package/examples/conditions/urlcode.yaml +24 -0
  230. package/examples/cookbook/README.md +8 -4
  231. package/examples/cookbook/example.yaml +17 -0
  232. package/examples/cookbook/functions/catalog.mjs +3 -0
  233. package/examples/cookbook/functions/fail.mjs +4 -0
  234. package/examples/cookbook/functions/items.mjs +3 -0
  235. package/examples/cookbook/functions/profile.mjs +3 -0
  236. package/examples/cookbook/functions/resource.mjs +3 -0
  237. package/examples/cookbook/functions/status.mjs +3 -0
  238. package/examples/cookbook/middleware/auth.mjs +48 -0
  239. package/examples/cookbook/middleware/body.mjs +15 -0
  240. package/examples/cookbook/middleware/bucket.mjs +29 -0
  241. package/examples/cookbook/middleware/cors.mjs +21 -0
  242. package/examples/cookbook/middleware/debug.mjs +13 -0
  243. package/examples/cookbook/middleware/envelope.mjs +11 -0
  244. package/examples/cookbook/middleware/errors.mjs +11 -0
  245. package/examples/cookbook/middleware/etag.mjs +18 -0
  246. package/examples/cookbook/middleware/locale.mjs +20 -0
  247. package/examples/cookbook/middleware/maintenance.mjs +10 -0
  248. package/examples/cookbook/middleware/methods.mjs +15 -0
  249. package/examples/cookbook/middleware/negotiate.mjs +20 -0
  250. package/examples/cookbook/middleware/referer.mjs +12 -0
  251. package/examples/cookbook/middleware/request-id.mjs +16 -0
  252. package/examples/cookbook/route-index.json +676 -0
  253. package/examples/cookbook/routes/middleware.yaml +126 -0
  254. package/examples/cookbook/tests/requests.json +526 -0
  255. package/examples/cookbook/urlcode.yaml +1 -0
  256. package/examples/egress/README.md +22 -0
  257. package/examples/egress/example.yaml +19 -0
  258. package/examples/egress/urlcode.yaml +19 -0
  259. package/examples/extensions/README.md +7 -0
  260. package/examples/extensions/example.yaml +21 -0
  261. package/examples/extensions/urlcode.yaml +25 -0
  262. package/examples/monitoring/example.yaml +8 -0
  263. package/examples/prerender/README.md +2 -2
  264. package/examples/prerender/example.yaml +16 -0
  265. package/examples/provider-conformance/README.md +12 -0
  266. package/examples/provider-conformance/example.yaml +14 -0
  267. package/examples/provider-conformance/urlcode.yaml +34 -0
  268. package/examples/tunnel/example.yaml +8 -0
  269. package/examples/vercel/example.yaml +19 -0
  270. package/llms-full.txt +3084 -0
  271. package/llms.txt +61 -21
  272. package/package.json +36 -7
  273. package/packaging/claude-plugin/.claude-plugin/plugin.json +19 -0
  274. package/packaging/claude-plugin/skills/urlcode-authoring/SKILL.md +122 -0
  275. package/packaging/claude-plugin/skills/urlcode-operations/SKILL.md +108 -0
  276. package/recipes/authenticated-json-api/README.md +51 -0
  277. package/recipes/authenticated-json-api/functions/profile.mjs +5 -0
  278. package/recipes/authenticated-json-api/recipe.yaml +34 -0
  279. package/recipes/authenticated-json-api/tests/requests.json +39 -0
  280. package/recipes/authenticated-json-api/urlcode.yaml +12 -0
  281. package/recipes/contact-form/README.md +25 -0
  282. package/recipes/contact-form/functions/contact.mjs +17 -0
  283. package/recipes/contact-form/recipe.yaml +33 -0
  284. package/recipes/contact-form/tests/requests.json +47 -0
  285. package/recipes/contact-form/urlcode.yaml +18 -0
  286. package/recipes/cors-api/README.md +16 -0
  287. package/recipes/cors-api/functions/items.mjs +3 -0
  288. package/recipes/cors-api/middleware/cors.mjs +21 -0
  289. package/recipes/cors-api/recipe.yaml +26 -0
  290. package/recipes/cors-api/tests/requests.json +65 -0
  291. package/recipes/cors-api/urlcode.yaml +12 -0
  292. package/recipes/health-page/README.md +13 -0
  293. package/recipes/health-page/recipe.yaml +23 -0
  294. package/recipes/health-page/tests/requests.json +36 -0
  295. package/recipes/health-page/urlcode.yaml +19 -0
  296. package/recipes/json-api/README.md +6 -0
  297. package/recipes/json-api/functions/echo.mjs +3 -0
  298. package/recipes/json-api/recipe.yaml +25 -0
  299. package/recipes/json-api/tests/requests.json +34 -0
  300. package/recipes/json-api/urlcode.yaml +12 -0
  301. package/recipes/middleware/README.md +34 -0
  302. package/recipes/middleware/functions/catalog.mjs +3 -0
  303. package/recipes/middleware/functions/fail.mjs +4 -0
  304. package/recipes/middleware/functions/items.mjs +3 -0
  305. package/recipes/middleware/functions/profile.mjs +3 -0
  306. package/recipes/middleware/functions/resource.mjs +3 -0
  307. package/recipes/middleware/functions/status.mjs +3 -0
  308. package/recipes/middleware/middleware/auth.mjs +48 -0
  309. package/recipes/middleware/middleware/body.mjs +15 -0
  310. package/recipes/middleware/middleware/bucket.mjs +29 -0
  311. package/recipes/middleware/middleware/cors.mjs +21 -0
  312. package/recipes/middleware/middleware/debug.mjs +13 -0
  313. package/recipes/middleware/middleware/envelope.mjs +11 -0
  314. package/recipes/middleware/middleware/errors.mjs +11 -0
  315. package/recipes/middleware/middleware/etag.mjs +18 -0
  316. package/recipes/middleware/middleware/locale.mjs +20 -0
  317. package/recipes/middleware/middleware/maintenance.mjs +10 -0
  318. package/recipes/middleware/middleware/methods.mjs +15 -0
  319. package/recipes/middleware/middleware/negotiate.mjs +20 -0
  320. package/recipes/middleware/middleware/referer.mjs +12 -0
  321. package/recipes/middleware/middleware/request-id.mjs +16 -0
  322. package/recipes/middleware/public/guide.txt +1 -0
  323. package/recipes/middleware/recipe.yaml +50 -0
  324. package/recipes/middleware/tests/requests.json +528 -0
  325. package/recipes/middleware/urlcode.yaml +127 -0
  326. package/recipes/protected-download/README.md +22 -0
  327. package/recipes/protected-download/files/report.txt +1 -0
  328. package/recipes/protected-download/recipe.yaml +31 -0
  329. package/recipes/protected-download/tests/requests.json +32 -0
  330. package/recipes/protected-download/urlcode.yaml +15 -0
  331. package/recipes/redirect/README.md +7 -0
  332. package/recipes/redirect/recipe.yaml +25 -0
  333. package/recipes/redirect/tests/requests.json +19 -0
  334. package/recipes/redirect/urlcode.yaml +9 -0
  335. package/recipes/static-plus-api/README.md +15 -0
  336. package/recipes/static-plus-api/functions/info.mjs +3 -0
  337. package/recipes/static-plus-api/public/assets/index.html +3 -0
  338. package/recipes/static-plus-api/public/assets/site.css +1 -0
  339. package/recipes/static-plus-api/public/index.html +8 -0
  340. package/recipes/static-plus-api/recipe.yaml +29 -0
  341. package/recipes/static-plus-api/tests/requests.json +56 -0
  342. package/recipes/static-plus-api/urlcode.yaml +23 -0
  343. package/recipes/typescript/README.md +8 -0
  344. package/recipes/typescript/functions/hello.ts +5 -0
  345. package/recipes/typescript/recipe.yaml +23 -0
  346. package/recipes/typescript/tests/requests.json +18 -0
  347. package/recipes/typescript/urlcode.yaml +5 -0
  348. package/recipes/webhook-receiver/README.md +20 -0
  349. package/recipes/webhook-receiver/functions/receive.mjs +16 -0
  350. package/recipes/webhook-receiver/recipe.yaml +27 -0
  351. package/recipes/webhook-receiver/tests/requests.json +59 -0
  352. package/recipes/webhook-receiver/urlcode.yaml +23 -0
  353. package/schemas/recipe.schema.json +139 -0
  354. package/schemas/urlcode.schema.json +659 -110
  355. package/skills/urlcode/SKILL.md +119 -0
  356. package/starters/default/.github/workflows/urlcode.yml +23 -0
  357. package/starters/default/.mcp.json +12 -0
  358. package/starters/default/AGENTS.md +79 -0
  359. package/starters/default/urlcode.yaml +0 -1
  360. package/dist/link-api.js +0 -136
  361. package/dist/link-cli.js +0 -141
  362. package/dist/link-events.js +0 -76
  363. package/dist/link-records.js +0 -31
  364. package/dist/link-store-worker.js +0 -150
  365. package/dist/link-store.js +0 -250
  366. package/dist/management-policy.js +0 -41
  367. package/dist/sqlite-version.js +0 -6
  368. package/dist/types/link-api.d.ts +0 -30
  369. package/dist/types/link-cli.d.ts +0 -36
  370. package/dist/types/link-events.d.ts +0 -27
  371. package/dist/types/link-records.d.ts +0 -11
  372. package/dist/types/link-store-worker.d.ts +0 -1
  373. package/dist/types/link-store.d.ts +0 -130
  374. package/dist/types/management-policy.d.ts +0 -9
  375. package/dist/types/sqlite-version.d.ts +0 -1
  376. package/docs/DYNAMIC-LINKS.md +0 -561
  377. package/docs/MANAGEMENT-SECURITY.md +0 -82
  378. package/examples/live-links/README.md +0 -11
  379. package/examples/live-links/tests/requests.json +0 -6
  380. package/examples/live-links/urlcode.yaml +0 -16
package/ROADMAP.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # Public roadmap
2
2
 
3
3
  URLCode is a portable runtime for programmable URL behavior, not a URL
4
- shortener. Live links are one handler in the broader project contract. The
4
+ shortener. Stored short links are an operator-installed extension, not a core
5
+ handler. The
5
6
  [project direction](docs/PROJECT-DIRECTION.md) explains how application
6
7
  projects and provider adapters fit without redefining or restricting the free
7
8
  runtime.
@@ -11,6 +12,121 @@ separate late phase. The stable 0.1 self-hosted release covers much of M0/M1 plu
11
12
  process/container packaging and benchmarks. Provider adapters and the remaining
12
13
  production-readiness gates remain open.
13
14
 
15
+ ## 0.4.0-alpha.2 — current alpha
16
+
17
+ `0.4.0-alpha.2` is a behavior-changing release on top of `0.4.0-alpha.1`:
18
+ **`function` and `middleware` routes now run trusted and unsandboxed by
19
+ default** — in the host process, with full Node/filesystem/network access,
20
+ exactly like any other project code — instead of always dispatching through
21
+ the QuickJS/WebAssembly worker pool. Sandboxing is now an explicit per-route
22
+ opt-in via `sandbox: true`; a route that declares it gets exactly the
23
+ isolation every earlier alpha provided, unchanged. See
24
+ [docs/SPIKE-DEFAULT-TRUST-MODEL.md](docs/SPIKE-DEFAULT-TRUST-MODEL.md) for
25
+ the maintainer's decision and rationale, and
26
+ [docs/FUNCTION-SECURITY.md](docs/FUNCTION-SECURITY.md) for the resulting
27
+ contract of both execution modes.
28
+
29
+ **This changes existing projects with no YAML edit.** Every `function`/
30
+ `middleware` route that does not declare `sandbox` — which, before this
31
+ release, meant every such route in every existing project — now runs trusted
32
+ instead of sandboxed the moment the runtime is upgraded to `0.4.0-alpha.2` or
33
+ later. Binding grants (`env`/`secrets`) are unaffected: a route still
34
+ receives only what it declares and an operator policy pins to the project
35
+ revision, whether trusted or sandboxed. Review which of your project's
36
+ `function`/`middleware` routes handle input or code you would not otherwise
37
+ trust with full Node/filesystem/network access, and add `sandbox: true` to
38
+ those specifically (docs/AI-AUTHORING.md's "Deciding when a route needs
39
+ `sandbox: true`") before upgrading a project that relies on the old,
40
+ always-sandboxed behavior. An operator policy pinned to a project's revision
41
+ is invalidated by this upgrade regardless of whether the project's own YAML
42
+ changed, since the project hash includes the trust-model-affecting change;
43
+ re-derive and re-approve it (`urlcode permissions`) after upgrading.
44
+
45
+ ## 0.4.0-alpha.1
46
+
47
+ `0.4.0-alpha.1` is the first alpha of the extension contract and the agent
48
+ tooling on top of the `0.3.0` self-hosted release. It carries: the
49
+ revision-pinned extension contract, capabilities and provider conformance,
50
+ strict redirect interchange, bulk import, recipes and search, TypeScript
51
+ guests, conditions, bounded proxy and signals, MCP read and authoring modes,
52
+ the `context`, `explain`, `manifest` and `schema` queries, short forms,
53
+ route-level auth, `init --with`, the agent benchmark harness, `llms-full`,
54
+ and the generated `AGENTS.md` and skill. It is an alpha: provider
55
+ deployments, soak and independent security review remain open. The
56
+ extension packages declare `@jimhoyd/urlcode >=0.4.0-alpha.1 <0.5.0` and
57
+ are published after core.
58
+
59
+ ## Extensions: accounts, administration and presentation — implemented, unreleased
60
+
61
+ The runtime now carries a generic, revision-pinned extension contract
62
+ (`@jimhoyd/urlcode/extensions`, [extensions](docs/EXTENSIONS.md)): a project
63
+ declares versioned `extensions.<name>` blocks, exclusive `extension` mounts and
64
+ `policies.extensions` requirements; the operator supplies the implementations
65
+ in a host file loaded with `--host-file`, outside the project. Guest requests
66
+ never see `Cookie`, `Authorization` or declared credential headers. Cloudflare
67
+ refuses extensions until its artifact format can run them.
68
+
69
+ The implementations live in their own repositories, each with an
70
+ implementation-status file that is the authoritative feature list:
71
+ [urlcode-auth](https://github.com/jimhoyd-com/urlcode-auth) (accounts, sessions,
72
+ MFA, roles, account page, operator CLI), [urlcode-admin](https://github.com/jimhoyd-com/urlcode-admin)
73
+ (users, sessions, roles, audit, approvals, cases, impersonation) and
74
+ [urlcode-ui](https://github.com/jimhoyd-com/urlcode-ui) (escaped templates,
75
+ partials, themes, translations). All three are Apache-2.0 and published to
76
+ npm as `0.1.0-alpha.1` while first-release acceptance is reviewed; see
77
+ [issue 58](https://github.com/jimhoyd-com/urlcode/issues/58) for what remains:
78
+ browser and device WebAuthn coverage, accessibility assessment, soak, backup
79
+ and recovery drills on a deployment, live provider senders and independent
80
+ security review. [The framework](docs/FRAMEWORK.md) describes how the four
81
+ packages compose, and [next steps](docs/NEXT-STEPS.md) is the phased plan to
82
+ close the remaining gaps.
83
+
84
+ ## Capability foundation — implemented, unreleased
85
+
86
+ `urlcode capabilities [--target self-hosted|cloudflare|aws|vercel] [--json]`
87
+ and the public capability API centralize target support for handlers, bindings
88
+ and effective policies. Runtime activation and Cloudflare builds use the shared
89
+ preflight; unknown targets fail closed and unsupported requirements identify the
90
+ route and capability before resources or artifacts are created. The existing
91
+ compiled route IR is documented, not replaced. Configuration-dependent and
92
+ delegated behavior remain explicit; all provider deployments remain unverified.
93
+ See [capabilities](docs/CAPABILITIES.md) and the
94
+ [next-phase review and implementation status](docs/NEXT-PHASE-PLAN.md).
95
+
96
+ ## Portability and URL behavior — implemented, unreleased
97
+
98
+ Strict redirect interchange supports CSV/JSON/YAML, Netlify and Cloudflare
99
+ `_redirects`, a bounded Netlify TOML subset and Vercel redirects. Conversion
100
+ reports refuse unsupported semantics; provider differences require explicit
101
+ acknowledgment and are never called lossless. A synthetic conformance fixture
102
+ and bounded HTTPS runner distinguish local adapter tests from observed
103
+ provider deployments. Actual Cloudflare/AWS/Vercel deployment evidence remains
104
+ pending; this does not complete M4.
105
+
106
+ Exact query/header/cookie/origin/method conditions and disjoint conditional
107
+ redirect/response cases run in the self-hosted, AWS and Vercel runtimes.
108
+ Cloudflare refuses these until its compiler can preserve their semantics.
109
+ Self-hosted proxy and webhook signals use explicit revision-pinned operator
110
+ origin grants, connection-pinned public DNS and bounded transport. Signals
111
+ have no durable delivery or retry guarantee. Other targets refuse proxy and
112
+ signals. See [conditions](docs/CONDITIONS.md), [egress](docs/EGRESS.md),
113
+ [interchange](docs/INTERCHANGE.md) and
114
+ [provider verification](docs/PROVIDER-VERIFICATION.md).
115
+
116
+ ## Developer ecosystem — implemented, unreleased
117
+
118
+ Bundled Git-owned recipes, safe bulk imports into route includes, build-time
119
+ TypeScript guest transpilation, read-only inspection APIs and optional stdio
120
+ MCP tooling are available. The runtime still executes only JavaScript, and
121
+ TypeScript authoring adds no execution mode: transpilation happens at build
122
+ time, is not type checking, and a `sandbox: true` route's emitted JavaScript
123
+ runs inside QuickJS/WASM exactly as before. Bulk benchmarks
124
+ successfully cover 1,000, 10,000 and 100,000 routes without relaxing parser
125
+ limits. See [recipes](docs/RECIPES.md), [bulk evidence](docs/BULK.md),
126
+ [TypeScript authoring](docs/TYPESCRIPT-AUTHORING.md) and
127
+ [SDK/MCP](docs/TOOLING.md). These features do not supply durable signals,
128
+ protected downloads, a remote marketplace or provider deployment proof.
129
+
14
130
  ## TypeScript source and shipped declarations — implemented, unreleased
15
131
 
16
132
  The runtime, scripts, tests and benchmarks are TypeScript under a strict
@@ -57,9 +173,10 @@ deployment returns byte-identical status, body and headers to the self-hosted
57
173
  server. Bindings arrive through a `URLCODE_POLICY` environment variable holding
58
174
  the same revision-pinned grant document the operator policy file carries.
59
175
 
60
- Native handlers only: isolated functions, middleware and stored live links are
61
- refused at activation, because every cold start would pay worker and WASM
62
- startup and a serverless filesystem cannot hold a durable link store. The
176
+ Native handlers only: `function` and `middleware` routes are refused at
177
+ activation, trusted or sandboxed alike, because they need the self-hosted Node
178
+ lifecycle and a sandboxed one would pay worker and WASM startup on every cold
179
+ start. The
63
180
  `@jimhoyd/urlcode/aws` does the same for a Lambda Function URL or API Gateway HTTP API.
64
181
  Payload format 2.0 only: format 1.0 supplies an already-decoded path and query,
65
182
  and this runtime rejects ambiguous encoding deliberately, so rebuilding a target
@@ -78,7 +195,7 @@ generation, so it gets a compiler rather than an adapter: `urlcode build
78
195
  validators, and `@jimhoyd/urlcode/cloudflare` serves them with the same matching, request
79
196
  policy and response policy as every other host. Declarative routes only —
80
197
  redirects and declared responses with parameters, defaults, validation, response
81
- headers, `enabled` and `expires`. Functions, middleware, stored links, assets and
198
+ headers, `enabled` and `expires`. Functions, middleware, assets and
82
199
  bindings are refused at build time with the route named, so an unsupported
83
200
  project fails the build instead of the deployment. Bindings are refused even as
84
201
  literals, because a build artifact must never carry a secret.
@@ -119,18 +236,25 @@ does not cover.
119
236
 
120
237
  ## Hardening checkpoint — alpha.8
121
238
 
122
- Bound HTTP admission and inactive sockets, drain accepted link writes on shutdown,
123
- reject invalid store metadata, and correct management defaults/method responses.
239
+ Bound HTTP admission and inactive sockets, and correct management
240
+ defaults/method responses.
124
241
  The [readiness register](docs/RELEASE-READINESS.md) distinguishes tested safeguards
125
242
  from deployment and stable-release gates. Feature breadth does not imply stability.
126
243
 
127
- ## Live short links — alpha.8
244
+ ## Live short links — alpha.8 (removed from core, superseded)
128
245
 
129
246
  Implemented an optional native `link` handler, local SQLite persistence, CLI CRUD
130
- and a separate authenticated management API. Links become visible without YAML
131
- changes/reloads; versioned writes prevent silent lost updates. No guest storage
132
- or network access is added. Same-host only; distributed storage, general state,
133
- user accounts and provider adapters remain open. See [dynamic links](docs/DYNAMIC-LINKS.md).
247
+ and a separate authenticated management API. Links became visible without YAML
248
+ changes/reloads; versioned writes prevented silent lost updates. No guest storage
249
+ or network access was added. Same-host only; distributed storage, general state,
250
+ user accounts and provider adapters remained open.
251
+
252
+ This native `link` handler, its SQLite store, CLI and management API were
253
+ removed from core in the layering work that followed: stored short links are
254
+ moving to a future `urlcode-dynamic-link` extension package (mount-based, like
255
+ `auth`/`admin`, not yet published). A project that used `link`/`dynamicLinks`
256
+ needs that extension once it ships; there is no in-core replacement or
257
+ deprecation shim.
134
258
 
135
259
  ## Middleware — alpha.7
136
260
 
@@ -167,17 +291,21 @@ Implemented the page/static/download portion of M2: project-contained asset
167
291
  snapshots, automatic MIME types, attachment names, HEAD, cache validators and
168
292
  single byte ranges. Dedicated public directories, symlink/hardlink rejection and
169
293
  bounded memory are part of the contract. [Asset guide](docs/ASSETS.md).
170
- Bulk tools, templates and signals remain open; M2 is not complete.
294
+ Bulk tools, recipes and best-effort signals were added in the unreleased next-phase work above; they were not part of alpha.3.
171
295
 
172
296
  ## Security correction — 0.1.0-alpha.2
173
297
 
298
+ <!-- trust-model-prose: historical -->
174
299
  All function code is untrusted. Node host execution has been replaced by
175
300
  QuickJS/WebAssembly isolation with fresh invocation state, no ambient host or
176
301
  network APIs, bounded resources, restricted module graphs and revision-pinned
177
302
  operator binding policy. This protection is part of the free product. See the
178
303
  [security model](docs/FUNCTION-SECURITY.md). Full Fetch/Node
179
304
  API compatibility and network integrations were not part of that alpha and
180
- remain outside the 0.1 contract.
305
+ remain outside the 0.1 contract. That default was superseded in
306
+ `0.4.0-alpha.2`, which made this isolation the per-route `sandbox: true`
307
+ opt-in instead (see
308
+ [docs/SPIKE-DEFAULT-TRUST-MODEL.md](docs/SPIKE-DEFAULT-TRUST-MODEL.md)).
181
309
 
182
310
  ## Earlier implementation checkpoint — 0.1.0-alpha.1
183
311
 
@@ -190,7 +318,7 @@ CI and a non-root container build are included. See the [contract](docs/SPECIFIC
190
318
  and [operations guide](docs/OPERATIONS.md) for exact support and evidence limits.
191
319
 
192
320
  Still open in the early contract: host namespaces, stable identity beyond paths,
193
- TypeScript support, fuller parameter vocabulary and capability/artifact planning.
321
+ fuller parameter vocabulary. Build-time TypeScript authoring and capability planning are now implemented in the unreleased work above.
194
322
  No claims of complete M0/M1 or stable production readiness. M2–M4 work continues
195
323
  in the order below; a few independently useful operational foundations shipped early.
196
324
 
package/SECURITY.md CHANGED
@@ -1,13 +1,28 @@
1
1
  # Security
2
2
 
3
- Application functions are **untrusted by default**. Alpha.2 replaces direct Node
4
- execution with QuickJS/WebAssembly isolation. Worker threads alone are not the
5
- security boundary. There is no unrestricted host-execution fallback.
6
-
7
- Guests have no Node, filesystem, shell, network or ambient process-environment
8
- access. Each invocation gets fresh state and bounded resources. Imports stay
9
- inside a snapshotted project module graph. Binding grants come from operator
10
- policy outside the project and are pinned to the configuration/code revision.
3
+ Project `function`/`middleware` code is **trusted and unsandboxed by default**:
4
+ it runs directly in the host process, exactly like any other project code,
5
+ with full Node, filesystem and network access (docs/SPIKE-DEFAULT-TRUST-MODEL.md).
6
+ A route opts into isolation explicitly with `sandbox: true`, which dispatches
7
+ that route through the QuickJS/WebAssembly worker pool instead unchanged
8
+ from the isolation this project has always provided, still the boundary to
9
+ reach for when a route's code specifically warrants it (input from a source
10
+ the project doesn't fully trust, a contribution nobody has reviewed, logic
11
+ handling an especially sensitive secret).
12
+
13
+ A `sandbox: true` guest has no Node, filesystem, shell, network or ambient
14
+ process-environment access. Each invocation gets fresh state and bounded
15
+ resources. Imports stay inside a snapshotted project module graph. Binding
16
+ grants — for a trusted route as much as a sandboxed one — come from operator
17
+ policy outside the project and are pinned to the configuration/code revision;
18
+ trusting a route's code by default does not grant it any `env`/`secrets` it
19
+ was not explicitly declared and pinned to receive. This is a claim about what
20
+ URLCode injects into `context.env`/`context.secrets` for a route, not an
21
+ access-control boundary on trusted code itself: a trusted (non-`sandbox`)
22
+ route runs with full Node access by design, so its own code can read
23
+ `process.env`, the filesystem or the network independently of anything the
24
+ binding grant declared or withheld. The grant only governs what URLCode hands
25
+ that code through `context`; it is not a restriction the code is confined to.
11
26
  See the [security model and policy instructions](docs/FUNCTION-SECURITY.md).
12
27
 
13
28
  The host/runtime and sandbox engine still require patching, independent review
@@ -16,6 +31,13 @@ execution platform. Authorized inputs/secrets can be exposed
16
31
  by code receiving them; grant the minimum required authority. Do not deploy
17
32
  older snapshots for untrusted functions; review and upgrade to the current revision.
18
33
 
34
+ Declarative proxy and signal handlers run in a separate bounded host transport;
35
+ they do not grant guest networking. They require per-route, per-purpose HTTPS
36
+ origin grants pinned to the project revision. Every connection checks public
37
+ addresses and pins DNS, refuses redirects, filters headers and limits resources.
38
+ See [egress semantics and limitations](docs/EGRESS.md). Build-time TypeScript
39
+ transpilation and read-only MCP do not execute project code in the host.
40
+
19
41
  ## Report a vulnerability privately
20
42
 
21
43
  Use [GitHub private vulnerability reporting](https://github.com/jimhoyd-com/urlcode/security/advisories/new).
@@ -36,5 +58,5 @@ Bind loopback by default; protect public deployments with HTTPS, rate limits,
36
58
  network controls and restricted operational endpoints. See [operations](docs/OPERATIONS.md).
37
59
 
38
60
  See the [internal security reviews](docs/SECURITY-AUDIT.md) — most recently
39
- 2026-09-17 — for fixed findings and remaining gates. Use a current reviewed commit: the shared 0.2.0
61
+ 2026-09-17 — for fixed findings and remaining gates. Use a current reviewed commit: the shared 0.3.0
40
62
  version label alone does not identify which hardening patches are present.
@@ -1,60 +1,85 @@
1
1
  {
2
- "node": "v26.8.2",
2
+ "node": "v26.9.0",
3
3
  "files": {
4
- "dist/adapters.js": "40e5c2d0ff4be8b11752418f063a9e79e29e31b6a64c92a19a514f182268133c",
5
- "dist/agent-lists.js": "fa1e87b928bf7178d7e910584018ef330a164be834156a8728f8d33ed7353211",
4
+ "dist/adapters.js": "a7153ec52f2ed7e0cdd8ed7d433504815f402ec53b2b1c3d38d0cf0e2fcf6509",
5
+ "dist/agent-lists.js": "35ab484198897501d011cb6cc00b5a6787192e19df29c97646e8c118fcc19eef",
6
+ "dist/agents-guide.js": "a76e9818ec995a349085a53e8badd3ef49734275557b50bc7dcbe995ce3d0e9f",
6
7
  "dist/assets.js": "0833b093d2fe457ce68281110dc07d47914992753607741c13b339d92c76cf5c",
7
- "dist/authoring.js": "99c3fe70df840ccc2a57b887b6b5886998a1155e848c3b6804a89bd1e257b05b",
8
- "dist/aws.js": "1384e417de68404b5f1f35ee8a9148271b6efa0965a64e458d7bbda0234cc564",
9
- "dist/build-cloudflare.js": "65af88384795bd7a4e2374c2cd9e5be174e3ffd4142f705723a3f5115a28eb27",
10
- "dist/cli.js": "4cb9a0a6d85ac4b101b72cd71dbdb3ca17c8ab1d064986f9923e4a5254b8b7a9",
11
- "dist/client-address.js": "292b86165def33247b05ef619e15245b70765522c8d9dc0ca4fac6e22e531de8",
8
+ "dist/authoring-files.js": "ad32814f9ae9c549c6247396f982aa700d13a293cc0a589609eccc68f8965550",
9
+ "dist/authoring.js": "ec5240e8686c124f4601229b45f89ce112d9eeb9d35e3059fe55e93056c45209",
10
+ "dist/aws.js": "7d8e3a97b4f6dbefbd68da058f05192469d1efcaed5458b284863ebe462e060e",
11
+ "dist/build-cloudflare.js": "af4f49ad45287d7c4105bb84b1592b5b8e76c930f7159505338298f7c5fd5651",
12
+ "dist/build-static.js": "a2d2fcef3099805392da9140096d9843226bfb582dc046acf9a77f37b8a0d528",
13
+ "dist/bulk.js": "aac88d422bd9a7a341a421fb4e29ff5580b28d39250b7f1f5315ba20ae92da8a",
14
+ "dist/capabilities.js": "28dba05b3851b8b12b3c1b809af87b732f84d601c737afe9225abe429886e691",
15
+ "dist/capability-query.js": "ba148b27c6a60f8c895f13f26468b16c18ae0a5cddea26b602965c8efbba90ae",
16
+ "dist/catalog.js": "ab1c01c9296cc277d2bd4fd682aeb053656a7d9f91c61974f4b78feea0211de8",
17
+ "dist/cli.js": "f6097c246c6b9006df58e3463648013ec8837ab3296a8c294809313503be167a",
18
+ "dist/client-address.js": "9d0d01466aab23124330605c5a0e0f981f87c897858acfad909f546a63df165b",
12
19
  "dist/cloudflare.js": "17b43b0a6b6a0ef8a893415c989e4ae3976d97cc966adbf897b785f9adc472e3",
13
- "dist/compliance-rules/baseline.js": "6746ed9717fcbc414d4892ec54afca74496dcc725f2c80d417e382c190294811",
14
- "dist/compliance-rules/privacy.js": "fe8330fd4c5068645e5c41db389fd190d7423e822397bf3938ca48d275bd449c",
15
- "dist/compliance-rules/shared.js": "595a7ee3a5af8c52197c5c9cbf09f4289a234e52b7a198afdd498be9be8d28a1",
16
- "dist/compliance-rules/strict.js": "937b55f4574eb5ca9f238b1a9658b089d006372328da35a329e4359719e6c3d0",
17
- "dist/compliance.js": "e956dc89b0b729fed7031297b8d7554141110334e670edf5cedc3d052a8fb3e4",
20
+ "dist/compliance-rules/baseline.js": "6296dea6bcb9f9bb80ed6ed5ab2f456e7f74e6de2be5d2d98ca8c983fb4df3ab",
21
+ "dist/compliance-rules/privacy.js": "4cfb1c07d7df698c362dfc8761cd3bba893769e92d7fb0a3901e1c2d25e801f1",
22
+ "dist/compliance-rules/shared.js": "86fd6db6a93375689acc64975cbc394ce9452dea21ae5941e743f99822515995",
23
+ "dist/compliance-rules/strict.js": "73ee13c2f893acf20cc3d44bf054e58c1474dec52eafe0cf2ce7f4eb96a3bc53",
24
+ "dist/compliance.js": "29a18da3cefea94802ac7d817d1ab4e3674abd5c3ac4ef893cb8b01c6a23fb61",
25
+ "dist/conditions.js": "ff25e97da550a3bdd80af55522045669438aa31a77d2bc83ad602bcefdee0475",
18
26
  "dist/config-worker.js": "bc2170d60c35f8d5de227cbfc4c5067dc61d7cbc5b98aed88e68a11797072da5",
19
- "dist/config.js": "d0e0d100f3f97d3cefd17d898dddea463773092569a7cd7c3384bd547847659f",
27
+ "dist/config.js": "0cd82b4c407848f9c66e804a6dd4bf9a8a8503264e51584456578073e0f01921",
28
+ "dist/context.js": "549a53e4738b9c20a1ec55614027f758026fb5860bf4ac962ce22d7029e48df0",
29
+ "dist/ecosystem-cli.js": "1e71bacd53d6fa8c7857cfcce3c3012ce054771a434b78d1f39e892e32642edd",
30
+ "dist/egress.js": "2ae29fe2cb4590fd2f715abe6817db47fed2f50dd31f37946ecf42eafbb0dd9e",
20
31
  "dist/errors.js": "a908e66496afebbdd632a8c159a6e14d23f8f38798a0b4342ca122f2511c6cde",
21
- "dist/function-sources.js": "48b470fbdcef2ad2c83e61a6476d5499210d0937b72518ae01fb2b9225b0e16b",
22
- "dist/function-worker.js": "3f5bad4f1b5cb812924c2dcc73ece6f816cf6aac26cd471fd1030dcfbf009c3b",
23
- "dist/functions.js": "6b1e5d4a3f8db17d4e5df261b98ed15f5f0c5e5507a6fc0f472e9f94ed2b6090",
24
- "dist/guest-api.js": "bc2501496a6ef9fd20dddb606fbc6fd557d534dd075e7ad38406248b230013ed",
32
+ "dist/examples.js": "89ae2b764a688fe52acfb9b94d3d262d7742401ebd0ef10c9ebfc76edfa5631c",
33
+ "dist/explain-cli.js": "dd342b21a96fc97a11488ac3528793ba0f5d4744b74a1d99085e142c4737b69a",
34
+ "dist/explain.js": "9450d2699cbe65e5c078c443ba7a6cba95c748e75d455e05264083b3c93c92a2",
35
+ "dist/extensions.js": "fed2b394466a7d406f9edeaedb71d9da81e50e3150eb7d01f2e7659104afeac7",
36
+ "dist/function-sources.js": "16fad4abc81c7ee07b6cbcef2d23a9fc50e97a17cb4dde1db53469bbb555c96f",
37
+ "dist/function-worker.js": "35771790ada4e1b36d447d4967a5e6cf0b543f32944e4c904f5fbf8998e824a5",
38
+ "dist/functions.js": "0f09d1bd27eb655ceb5900a4a5e2b760d2028b02cb637a6a89a4eb5940828008",
39
+ "dist/guest-api.js": "49aec9ed72733ad119e63bcfcee18158dcc8ceb951e1823b8947f6407ff24afc",
25
40
  "dist/header-validation.js": "465181dbb08ff05f52defdd29fda025c0c64589bf319fa87fa6d3ab4b68216d5",
26
41
  "dist/http-policy.js": "4cb187642269078ddf3460a3f1813dc57878a616a6f8132ef8f8d3b4b91ebb56",
27
42
  "dist/http-response.js": "5fc3bb9eb932a3fd2fbc72c361416a5f1439b8bf45b2be37baca1c6446abf40c",
28
- "dist/index.js": "648878ef26cb3a8eb075a5ddd4d044022afe6cf5e5e38d1bd6ea418b82791371",
29
- "dist/link-api.js": "0d1f2fb5ef8cd6fda7b071d3e08c53eb4b1c01d4003167af2f400949b70dea4f",
30
- "dist/link-cli.js": "5f45e62a6b935112cabfcd12691a5ebc01d9c87f92e4befb655380d9e752323b",
31
- "dist/link-events.js": "502a6038a538fa43094a9ba9c7546f504b4a1832a1377f26ca8cb69c2326670e",
32
- "dist/link-records.js": "ef67a58cd107db0c3ac1c0ffd7b32817553606cf69bb3002da4ca0138c272f69",
33
- "dist/link-store-worker.js": "0080452bbada2154b923449cd14596579bde94ad5f8dab94ecc84aa0d59c089b",
34
- "dist/link-store.js": "526cdbe1b917cc7a74fb6edbbf13717d823ace5b5d6a5f89bc91438056a10b37",
43
+ "dist/index.js": "7e9f6ec8a125e2dfd4230b2ecd17ac513c0153d778a57bbcee7a1a9cd9681f81",
44
+ "dist/init-with.js": "8371f568867ebdc6ab8e9aa762234ae2aa015865f46aa901254528e20d69b791",
45
+ "dist/interchange-cli.js": "35bd70ba8077af5c3e39404ff0e5d28707632090a59a90645141252449fd3f04",
46
+ "dist/interchange.js": "26789420af33344d9a08c00fe6b2708aa71994224df527b3075295be2151611e",
35
47
  "dist/logging.js": "8ec57fea26983aa071b05fe15d680d6550b03488101163ed9666da674118cf31",
36
- "dist/management-policy.js": "ad573627de0e9f9b5368d701966468f391f53d64d2a82bfd8083bca412b01721",
37
- "dist/match.js": "a0935ee5a3c68d85c268abbdcecd30a7ebd68e37bbecb68136479b1f94fc3705",
38
- "dist/observability.js": "28a446ad867329e58cbccb9215a343a390e8599dad6a31c1db0e702d3df67e27",
39
- "dist/plugins.js": "c228ec42cd727f259193fe905ae247f9fba34f695dd1364d8e3ee6683262da7c",
40
- "dist/policies/agents.js": "761920214db2ada60733743541f134928ba1d2f0bc763660bd0d1112a725c887",
41
- "dist/policies/cache.js": "ef16d7e592526c29f865b2693faa2c8afbea41c6526687563dffcb13a77fc1f7",
42
- "dist/policies/compression.js": "d342c6db4a9bee63b62b35654dde28fa163bfd82510bb85331bb9b072f856781",
43
- "dist/policies/security.js": "119fb37bd0e994ddabf3feacbc52d481c8e8c65b0ac6b71c8d3533b8c3e2cedb",
48
+ "dist/manifest.js": "977f0f1cbe4466f7fbd9f2a0745e016cb9ebae640bc264fba04b4d02f4dbaca9",
49
+ "dist/match.js": "53ebcc2cda529a8d07fb83f8cb69a1446036ffc1641af3c4bd45a55851bded28",
50
+ "dist/mcp-authoring.js": "5030f52ef9c7ebc7b97305fcce687eb0a0d6164e34fda87f8278135a1e6f3d65",
51
+ "dist/mcp.js": "e2d70f63481dc40aae60f7c27128e6a09ec370b69fd68aee8890bcc990f4f304",
52
+ "dist/observability.js": "f4b1ab496f051fe3ef2ed36b2b2e469c63a8940700e2df852e6ff2d9cccdd5ae",
53
+ "dist/operator-host.js": "e3dac9d43a83beb775202b4ab9eeeba7ac63cebfc5dcc669be38d825be587bd0",
54
+ "dist/plugins.js": "a61aa933cd9e1b41020b86fae78aa3a7f45f5313124aa11b50cb57898722385e",
55
+ "dist/policies/agents.js": "c1dbc1e90339f472eeeb2372f7f4637f59a5d210797ea680ac8120a02aa20c10",
56
+ "dist/policies/cache.js": "03f79b91694bb78a98de4473384e5110e1ae1c3c83d46f929495d03af04d9da1",
57
+ "dist/policies/compression.js": "800f3ae3b1a4c1fe58c3d9908364ea9d78f655ff50c7f7589f584378e7f194b0",
58
+ "dist/policies/security.js": "2b3bfdf82140156fea4b162adc28ee43ccd85c402fb200680dbb8d8706417420",
44
59
  "dist/policies/throttle.js": "bbb0cb1c24cf70d0a1ac32fc0618efb6c44e5b5d42564842f9c585ff7e501603",
45
- "dist/policies.js": "e3f48ad730d1d7b1435bff2f2bd7091e24a0c46dd0e1393d53337d64e3a7d83d",
46
- "dist/policy.js": "280f94593c9e376726e2b3d34f4c1e9817802d67134bd6a2d1afe466244b3fdc",
47
- "dist/prerender.js": "f568e2773be6fe67b547739f609c0287f429451ab31187f48ffe4560df3f877b",
48
- "dist/project-tests.js": "91aa9c22d9f40efb0c5318b7a05b4aee753fc1ab591fe90e8d94f24fa60697f5",
49
- "dist/readiness.js": "64eedecc9405db253e2bd39819c7f5640c6017f13cf23d2a193656dda095ca45",
50
- "dist/router.js": "a102132362177bb8690bde11ce2b6ea9719a79601a25165d5d36dc736b1b888b",
51
- "dist/runtime.js": "1d22cdb83703e0fc15da63d28b02fbd419051894063cb2fde5072b186c98ec62",
52
- "dist/scaffold.js": "9dd30112e070ec554bd7cae1ca0a8b03642632be57411ba76a72972f4ba49b3e",
53
- "dist/server.js": "d8c78d1695b3c11328f3f983281fba78c2aca6a66cf755b39ecf4ec2ec4b6f29",
54
- "dist/site.js": "f34b023c9bcd403d38b8a2bf4d8ba184e0ff00cbd98405b49c68747466d995cd",
55
- "dist/sqlite-version.js": "a3a08d99064bd0f35847e288027e00a516efdd61c675bfbbe7726e3aa900f0d1",
56
- "dist/types.js": "96650efc60f2400b7b1a6622798f0f42d43f451fa5bf18a93d06482feb2e0283",
57
- "dist/vercel.js": "76092b83e4d80e29541589682e00237701a3d3f096a8045fa2cf104b6d1b6725",
58
- "dist/scripts/operational-drills.js": "b7e9448279c59ee9de62023055a9ff5c7a60bcceed4c33d023edc612f5575af9"
60
+ "dist/policies.js": "23fa019b7bf1cdedcc5f7772d2f157e4b381a554bce9e84594c2be4a0f8f76b8",
61
+ "dist/policy.js": "33c527008fafe4af18243ba668d069517c20659150f9f1d1a5a1d076e8724f89",
62
+ "dist/prerender.js": "0386ea2411e00b9563b5349133f1d723947b01f837fa92d4c61a699c9cfb5cdb",
63
+ "dist/project-tests.js": "445eaa139d2f1a2534369cfdeef081ef518de03218a467e7c5c2059caf840270",
64
+ "dist/provider-verification.js": "ffcf9f05e8cb5f71ea46a97e279e8a613fdfdf9435ab02bd57af11e2680a9107",
65
+ "dist/proxy.js": "34107e59ac0dbbea090efa3cf5badf3226c5302ba25e8f8ff9b2b5596ed80e50",
66
+ "dist/readiness.js": "6ce69a005d7c45cf0ef97fa5eaba34279d43ebf28124eca18359d9db4f599808",
67
+ "dist/recipes.js": "11853f23e63c3c65c5bed03a278cde0349d28c9fa23266c9907a2df318bb5fc3",
68
+ "dist/route-diff.js": "eebac076a886ddfb2bf5b97ea09d81f888e7bb0063d482eddb8e5fef9acea107",
69
+ "dist/router.js": "cf831025d5ed6778d1d6a0e541177799794e76766c82084ded81d3e87317ca1e",
70
+ "dist/runtime.js": "0470dcab0774d2da3336e9ce76a4853757bf96081e52bd741f6b44c1bdd4161f",
71
+ "dist/sandbox.js": "c88c5aa5dd95b4f55f1ba62da7969ad66dbd97c30f72e5b5f2817a2098ac1c65",
72
+ "dist/scaffold.js": "3ef243aceca7ddf2780aa2c8c04ae17edd07682d3a418fd5d65ba00f5c762f14",
73
+ "dist/schema-query.js": "bfd1844acd8d54ac361115191fcfbaf828a67e223b9ec6e9c22f158761af149b",
74
+ "dist/server.js": "d878bc8f0d6a05f8fd25997cace3150e2ff4d44ee9c8f4b5530e29601e164be1",
75
+ "dist/signals.js": "b55e54efc8fb6703e08f2a1e808ec8e011bda67738db8ceadf1b248f695795be",
76
+ "dist/site.js": "c40a06a6f9e2d6d3bea94727783c115fed4309bb0190787f58434eed64cbde84",
77
+ "dist/tooling.js": "7409db98422325cd4181d073d645ea57debca0e54cb151123474b85f4d4ed7dc",
78
+ "dist/trusted-functions.js": "befd256848be786f97e372c6af0e05ac08a0c93baed38bf2470ea49bc00dd3e4",
79
+ "dist/types.js": "a1213d033b6a347c63e94685ab9056d8cd7a301d9c83150142afe0f3ab2c6536",
80
+ "dist/typescript-authoring.js": "27829098603029ab565174e540fb1d5ef68c1a923272b7186f64a362f5244872",
81
+ "dist/vercel.js": "a0da20c095d0c7fa8f579ed4dd5951e7a34191f8a72a57c5e782c9eab39f6f08",
82
+ "dist/verify-deployment.js": "0c2e68f3cf258a364728c801411df5284343bc01b75a64fe275ff84e397e998b",
83
+ "dist/scripts/operational-drills.js": "c26c406d28013cc554b25a5b6bf8baf4e71d5e67e50d866fae546f538a192317"
59
84
  }
60
85
  }
package/dist/adapters.js CHANGED
@@ -1,19 +1,12 @@
1
+
1
2
  import { createRuntime } from './runtime.js';
2
3
 
3
4
  import { validatePolicy } from './policy.js';
4
5
  import { ConfigError } from './errors.js';
5
-
6
6
 
7
7
  /** The subset of process.env a hosted adapter reads. */
8
8
 
9
-
10
-
11
- // Handlers a stateless per-request invocation cannot honour. Functions and
12
- // middleware need worker threads and the WASM engine on every cold start;
13
- // stored links need a durable writable file that instances share. Adapters
14
- // refuse them identically, so a project's supported surface does not depend on
15
- // which provider is serving it.
16
- const unsupported = { function:'isolated functions', link:'stored live links' };
9
+
17
10
 
18
11
  export function readPolicyFromEnvironment(environment ) {
19
12
  if (!environment.URLCODE_POLICY) return undefined;
@@ -27,20 +20,8 @@ export function readPolicyFromEnvironment(environment )
27
20
 
28
21
  // Activates a project for a native-handler-only host, refusing the whole
29
22
  // deployment rather than letting individual routes fail at request time.
30
- export async function activateNativeOnly(project , environment , { target = 'node', plugins } = {}) {
31
- const runtime = await createRuntime(project, { permissions: readPolicyFromEnvironment(environment), environment, target, plugins });
32
- const refused = runtime.testPlan().inventory.flatMap(route => {
33
- const reason = route.handler === undefined ? undefined : unsupported[route.handler];
34
- return [
35
- ...(reason ? [`${route.path} uses ${reason}`] : []),
36
- ...(route.middleware ? [`${route.path} declares middleware`] : []),
37
- ];
38
- });
39
- if (refused.length) {
40
- await runtime.close();
41
- throw new ConfigError(`This adapter serves native handlers only: ${refused.join('; ')}`);
42
- }
43
- return runtime;
23
+ export async function activateNativeOnly(project , environment , { target, plugins, extensions, origin } ) {
24
+ return createRuntime(project, { permissions: readPolicyFromEnvironment(environment), environment, target, plugins, extensions, origin });
44
25
  }
45
26
 
46
27
  // Caches a successful activation for the life of the instance. A failure is not
@@ -10,7 +10,7 @@ import { isListFile, isBundled, validatePattern } from './policies/agents.js';
10
10
  //
11
11
  // A list file is the schema data/agents/*.json uses: either an array of
12
12
  // entries or `{ entries: [...] }`, each entry `{ name?, pattern, ... }`.
13
- export const MAX_LIST_ENTRIES = 4096;
13
+ const MAX_LIST_ENTRIES = 4096;
14
14
 
15
15
  function listPath(root , reference , routePattern ) {
16
16
  assert(isListFile(reference) && !isAbsolute(reference), `${routePattern}: policies.agents list ${JSON.stringify(reference)} must be a project-relative path ending in .json`);
@@ -0,0 +1,113 @@
1
+ import { getCapabilities } from './capabilities.js';
2
+
3
+ import { registry } from './policies.js';
4
+ import { generatedPaths } from './site.js';
5
+ import { assert } from './errors.js';
6
+
7
+ /** Where the packaged agent skill lives, relative to the installed @jimhoyd/urlcode package. */
8
+ export const skillPath = 'skills/urlcode/SKILL.md';
9
+ /** The MCP registration file `urlcode init` writes beside the project (Claude Code and Codex read this shape). */
10
+ export const mcpConfigFile = '.mcp.json';
11
+ /**
12
+ * Renders `.mcp.json` registering the read-only `urlcode mcp` server for the project at `project`, relative
13
+ * to the file. `--allow-authoring` is deliberately absent: the operator adds it by hand when they want it.
14
+ */
15
+ export function renderMcpConfig(project = '.') {
16
+ assert(/^[A-Za-z0-9_.-]+(?:\/[A-Za-z0-9_.-]+)*$/.test(project) && !project.split('/').includes('..'), 'MCP project path must be a relative path without ..');
17
+ return JSON.stringify({ mcpServers: { urlcode: { command: 'urlcode', args: ['mcp', '--project', project] } } }, null, 2) + '\n';
18
+ }
19
+ const handlerNames = ['redirect','respond','page','static','download','function','proxy','conditional','extension'];
20
+
21
+ /**
22
+ * The application-level AGENTS.md written by `urlcode init`. Built from the
23
+ * installed runtime's capability catalog, so it names only the handlers,
24
+ * policies and site keys this version implements. Under 80 lines by design.
25
+ */
26
+ export function renderAgentsGuide({ routes } ) {
27
+ assert(Number.isInteger(routes) && routes >= 0 && routes <= 100000, 'Route count must be a non-negative integer');
28
+ const catalog = getCapabilities('self-hosted');
29
+ const native = new Set(catalog.capabilities.filter(row => row.targets['self-hosted']?.support === 'native').map(row => row.capability));
30
+ const handlers = handlerNames.filter(name => native.has(name));
31
+ const policies = Object.keys(registry).filter(name => native.has(`policies.${name}` ));
32
+ const site = Object.entries(generatedPaths).map(([key, path]) => `\`${key}\` (${path})`);
33
+ return `# Working on this project
34
+
35
+ This project uses URLCode: URL behavior is declared in \`urlcode.yaml\`, and the
36
+ installed \`@jimhoyd/urlcode\` runtime serves it. There is no framework code to
37
+ write for routing, validation, middleware wiring, policies, static serving or
38
+ authentication; the runtime provides them. Read this file before changing anything.
39
+
40
+ ## Before writing code
41
+
42
+ 1. Inspect \`urlcode.yaml\` first, then every file its \`includes\` list names,
43
+ the referenced functions, middleware and \`tests/requests.json\`. Preserve the
44
+ existing organization and every route you were not asked to change.
45
+ 2. Run \`urlcode capabilities\` to see what this runtime version implements and
46
+ which targets support it; \`urlcode capabilities --target NAME\` before
47
+ promising any provider deployment.
48
+ 3. Run \`urlcode recipes list\` and \`urlcode recipes show NAME\` before writing a
49
+ route from scratch. If a recipe covers the need, add it with
50
+ \`urlcode recipes add NAME --out DIR\` and adapt the copy.
51
+ 4. Use URLCode's highest-level declarative features whenever possible. Generate custom code only when the framework cannot express the requirement. Check supported extensions and recipes first; explain any capability gap.
52
+
53
+ ## Ask the runtime through MCP first
54
+
55
+ When present, \`${mcpConfigFile}\` registers the read-only \`urlcode mcp\` server. When it is
56
+ available, prefer its tools over reading documents: \`get_context\`,
57
+ \`get_capability\`, \`get_schema\`, \`search_recipes\`, \`explain\`, \`get_manifest\`.
58
+ The CLI equivalents are the fallback: \`urlcode context\`, \`urlcode capabilities NAME\`,
59
+ \`urlcode schema PATH\`, \`urlcode recipes search TEXT\`, \`urlcode explain PATH\`,
60
+ \`urlcode manifest\`. \`--allow-authoring\` is an operator opt-in; never add it yourself.
61
+
62
+ ## What the runtime provides (this version)
63
+
64
+ - Handlers, exactly one per route: ${handlers.map(name => `\`${name}\``).join(', ')}.
65
+ - Ordered \`middleware\` around any handler, declared in YAML, trusted by default.
66
+ - Validated inputs: \`parameters\`, \`request.body\` and \`methods\` on the route;
67
+ functions receive validated \`args\`, never raw user input.
68
+ - Policies, host-enforced and off by default: ${policies.map(name => `\`${name}\``).join(', ')}.
69
+ - Site conventions under \`site\`, each generating one native route: ${site.join(', ')}.
70
+ - Bindings: named \`env\` and \`secrets\` references resolved by the operator, never values in YAML.
71
+
72
+ Never recreate any of these in a function; a missing one is a report, not an
73
+ invitation to reimplement it.
74
+
75
+ ## Functions and middleware are trusted by default; sandbox is opt-in
76
+
77
+ A route's \`function\`/\`middleware\` code runs trusted, in-process, with full
78
+ Node/filesystem/\`fetch\` access, receiving only the declared/granted \`args\`
79
+ and \`env\`/\`secrets\`. Add \`sandbox: true\` when code warrants isolation
80
+ (untrusted input, an unreviewed contribution, an especially sensitive
81
+ secret): that route then gets a text/JSON subset only, no Node/filesystem/
82
+ outside imports — use \`proxy\`/a binding instead, and say why in \`description\`.
83
+
84
+ ## Checks that count as evidence
85
+
86
+ \`\`\`sh
87
+ urlcode validate --local
88
+ urlcode test
89
+ urlcode audit --expect-routes ${routes}
90
+ \`\`\`
91
+
92
+ Run all three after every change, updating the route count deliberately and
93
+ adding \`tests/requests.json\` fixtures for every new route (positive/negative,
94
+ every active method, HEAD). No global install: use \`node /path/to/urlcode/src/cli.ts\`.
95
+
96
+ ## Rules
97
+
98
+ - Report unsupported requirements instead of inventing fields. The schema is
99
+ exact; a field the validator rejects does not exist. Say what is missing.
100
+ - Never create or approve operator grants. Request a named binding in YAML and
101
+ stop; the operator grants it outside this project, pinned to the revision.
102
+ - Secrets stay out of the project: no keys, tokens or credentials in YAML,
103
+ functions, fixtures, \`.env\` files that are not ignored, or commit messages.
104
+ - Protect a route with \`auth: true\`/\`auth: { role: admin }\` where an \`auth\`
105
+ extension is declared; \`cache\` likewise expands to \`policies.cache\`.
106
+ - Validation, tests and the audit are the evidence. Local checks are not a
107
+ deployment, a soak test or a security review; do not claim otherwise.
108
+
109
+ The installed package ships an agent skill with the same loop at
110
+ \`${skillPath}\` inside \`@jimhoyd/urlcode\` (for example
111
+ \`node_modules/@jimhoyd/urlcode/${skillPath}\`).
112
+ `;
113
+ }