@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
@@ -0,0 +1,177 @@
1
+ import type { HandlerResult } from './http-response.ts';
2
+ import type { ProjectDocument, RouteConfig, TargetName } from './types.ts';
3
+ export type { HandlerResult } from './http-response.ts';
4
+ export interface ExtensionDeclaration {
5
+ version: '1';
6
+ config: Record<string, unknown>;
7
+ }
8
+ export type ExtensionPolicies = Record<string, Record<string, unknown> | false>;
9
+ /**
10
+ * `root` is the project's resolved absolute directory (the same value
11
+ * `loadDocument()` computes and `functionFile()`/router.ts resolves
12
+ * `function`/`middleware` `source` entries against). It is not the process's
13
+ * `cwd()`: `--project`/`--host-file` are independent paths, a server can be
14
+ * started from any working directory, and the JS API can load a project
15
+ * programmatically with no relationship to `cwd()` at all. An extension that
16
+ * resolves project-relative paths of its own (for example, an alternative
17
+ * middleware source it loads by convention rather than through core's native
18
+ * `middleware:` array) must resolve them against this field, never `cwd()`.
19
+ */
20
+ export interface ExtensionActivation {
21
+ origin: string;
22
+ target: TargetName;
23
+ projectSha256: string;
24
+ mounts: readonly string[];
25
+ root: string;
26
+ }
27
+ export interface ExtensionRequest {
28
+ method: string;
29
+ target: string;
30
+ path: string;
31
+ query: URLSearchParams;
32
+ headers: Headers;
33
+ headerCounts: Record<string, number>;
34
+ body: Uint8Array;
35
+ origin: string;
36
+ route: string;
37
+ mount: string | null;
38
+ client: string | null;
39
+ }
40
+ export interface ExtensionInstance {
41
+ handle(request: ExtensionRequest): HandlerResult | Promise<HandlerResult>;
42
+ authorize?(requirement: Readonly<Record<string, unknown>>, request: ExtensionRequest): HandlerResult | undefined | Promise<HandlerResult | undefined>;
43
+ /**
44
+ * Wrap semantics, not gate semantics: attached the same way as `authorize`
45
+ * (policies.extensions.<name> on a route, `config` the same validated
46
+ * per-route value `authorize`'s `requirement` receives), but given `next`,
47
+ * a callable invoking the rest of the pipeline for this route (any other
48
+ * declared extension `middleware()` after this one, then the route's own
49
+ * native `middleware:` chain and handler) at most once. Calling it lets
50
+ * this hook run code before and after the rest of the pipeline, inspecting
51
+ * or mutating the `HandlerResult` it resolves to; skipping it short-circuits
52
+ * the rest of the pipeline entirely, the same way `authorize` can. Never
53
+ * touches the native `middleware:` array or its own sandboxed/trusted
54
+ * dispatch, and never runs before `authorize` on the same route.
55
+ */
56
+ middleware?(config: Readonly<Record<string, unknown>>, request: ExtensionRequest, next: () => Promise<HandlerResult>): HandlerResult | Promise<HandlerResult>;
57
+ close?(): void | Promise<void>;
58
+ }
59
+ /** Trusted operator code only. YAML declares names/configuration, never modules. */
60
+ /**
61
+ * Content-hashed assets under `<mount><prefix>/` may be cached publicly. The
62
+ * extension owns the hashed filename; the runtime only relaxes its no-store floor
63
+ * for a GET/HEAD 200/304 that carries a strong ETag, sets no cookie and does not
64
+ * vary on credentials. Everything else under the mount stays no-store.
65
+ */
66
+ export interface ExtensionImmutableAssets {
67
+ prefix: string;
68
+ }
69
+ export interface RuntimeExtension {
70
+ name: string;
71
+ version: '1';
72
+ projectSha256: string;
73
+ targets: TargetName[];
74
+ schema: object;
75
+ policySchema?: object;
76
+ credentialHeaders?: string[];
77
+ immutableAssets?: ExtensionImmutableAssets;
78
+ /**
79
+ * Reviewed, operator-declared cache sensitivity for `policies.extensions.<name>`
80
+ * routes (never for an `extension:` mount, which is always treated as
81
+ * sensitive). Omitted or `true`: the current, safe default — the runtime
82
+ * forces `Cache-Control: no-store`, disables compression and applies the
83
+ * extension response's header/size caps, exactly like `authorize`-gating
84
+ * auth/admin extensions. `false` is an explicit, reviewed opt-in a generic,
85
+ * cache-transparent extension (pure request/response middleware with no
86
+ * gating semantics of its own, like `urlcode-middleware`) makes to say its
87
+ * `middleware()` hook never depends on withholding the response from
88
+ * shared caches: the wrapped route's own declared cache headers pass
89
+ * through unchanged, exactly as the native `middleware:` array already
90
+ * does. A route naming more than one extension is treated as sensitive if
91
+ * any of them is (or leaves this unset) — this can only relax the no-store
92
+ * floor, never weaken it, and it never changes whether `authorize()` runs.
93
+ */
94
+ cacheSensitive?: boolean;
95
+ activate(config: Readonly<Record<string, unknown>>, context: ExtensionActivation): ExtensionInstance | Promise<ExtensionInstance>;
96
+ }
97
+ /** `urlcode init --with <name>` contract: what core hands `@jimhoyd/urlcode-<name>`'s `scaffold` export. Nothing is written by `scaffold`. */
98
+ export interface ScaffoldRequest {
99
+ /** Absolute site directory core creates; `files` paths in the result are relative to it. */
100
+ directory: string;
101
+ /** Absolute route project directory (holds urlcode.yaml), `<directory>/app`. */
102
+ project: string;
103
+ /** Absolute path of the combined host module core writes, `<directory>/host.mjs`. */
104
+ hostFile: string;
105
+ /** Every extension name being scaffolded together, in `--with` order, including this one. */
106
+ names: readonly string[];
107
+ }
108
+ export interface ScaffoldFile {
109
+ path: string;
110
+ content: string | Uint8Array;
111
+ mode?: number;
112
+ }
113
+ export interface ScaffoldResult {
114
+ /** Must equal the requested name. */
115
+ name: string;
116
+ /** Fragments merged into the project's top-level `extensions` and `routes`; duplicate keys are refused. */
117
+ extensions: Record<string, unknown>;
118
+ routes: Record<string, unknown>;
119
+ /** Host module lines: imports, then setup statements, then entries of the `extensions` array, then `close` statements. */
120
+ hostImports: string[];
121
+ hostSetup: string[];
122
+ hostEntries: string[];
123
+ hostClose?: string[];
124
+ /** Files written relative to `directory` with their modes; never inside the project, never overwriting. */
125
+ files: ScaffoldFile[];
126
+ /** Markdown appended to README.md under a heading core adds; the numbered steps merged in `--with` order. */
127
+ readme: string;
128
+ nextSteps: string[];
129
+ /** Environment variables the host reads, with one-line descriptions. */
130
+ env?: Record<string, string>;
131
+ }
132
+ export interface ActiveExtension {
133
+ instance: ExtensionInstance;
134
+ policies: Map<string, Readonly<Record<string, unknown>>>;
135
+ assetPrefixes: readonly string[];
136
+ }
137
+ /** What the runtime knows about the request when it applies the privacy floor. */
138
+ export interface ExtensionAssetContext {
139
+ method: string;
140
+ path: string;
141
+ prefixes: readonly string[];
142
+ }
143
+ export interface ExtensionRegistry {
144
+ entries: Map<string, ActiveExtension>;
145
+ credentialHeaders: string[];
146
+ close(): Promise<void>;
147
+ }
148
+ export declare const immutableCacheControl = "public, max-age=31536000, immutable";
149
+ /** Inspection alone grants nothing; operators must explicitly pin the returned revision. */
150
+ export declare function inspectExtensionRevision(project: string): Promise<string>;
151
+ export declare function effectiveExtensionPolicies(document: ProjectDocument, route: Pick<RouteConfig, 'policies'>): Record<string, Record<string, unknown>>;
152
+ export declare function hasExtensionPolicy(document: ProjectDocument, route: Pick<RouteConfig, 'policies'>): boolean;
153
+ /**
154
+ * Whether a route naming these `policies.extensions` names must be treated as
155
+ * confidential (forced no-store, no compression, extension response caps).
156
+ * `names` with no entries is never confidential. Without a `registrations`
157
+ * list to consult (a build path with no operator host loaded), every name is
158
+ * treated as sensitive: the safe default this can only relax, never weaken.
159
+ * A name whose registration is missing, or declares no `cacheSensitive` (or
160
+ * `true`), counts as sensitive; only an explicit `cacheSensitive: false`
161
+ * excuses it, and one sensitive name among several makes the whole route
162
+ * confidential.
163
+ */
164
+ export declare function isSensitiveExtensionPolicy(names: readonly string[], registrations?: readonly Pick<RuntimeExtension, 'name' | 'cacheSensitive'>[]): boolean;
165
+ export declare function prepareExtensions(document: ProjectDocument, routes: Record<string, RouteConfig>, registrations: RuntimeExtension[] | undefined, context: Omit<ExtensionActivation, 'mounts'>): {
166
+ activate(): Promise<ExtensionRegistry>;
167
+ };
168
+ /**
169
+ * The runtime decides; the extension cannot opt in from a response alone. The
170
+ * declared prefix, the GET/HEAD method, a 200/304 status, one strong ETag, no
171
+ * Set-Cookie and no Vary on Cookie/Authorization are all required. A stricter
172
+ * Cache-Control the extension set (no-store, no-cache, private or a shorter
173
+ * max-age) is preserved.
174
+ */
175
+ export declare function immutableAssetResponse(result: HandlerResult, asset: ExtensionAssetContext | undefined): boolean;
176
+ /** Mandatory privacy floor after trusted response hooks, with bounded output. */
177
+ export declare function extensionResponse(result: HandlerResult, asset?: ExtensionAssetContext): HandlerResult;
@@ -17,5 +17,14 @@ export interface FunctionSources {
17
17
  /** Absolute source path to module name. */
18
18
  names: Map<string, string>;
19
19
  }
20
+ /** Snapshot budgets: what one set of guest modules may cost. Deliberate bounds
21
+ * of the sandbox contract (docs/FUNCTION-SECURITY.md), not tuning knobs. */
22
+ export declare const MODULE_LIMIT = 128;
23
+ export declare const MODULE_BYTE_LIMIT = 1048576;
24
+ export declare const TOTAL_BYTE_LIMIT = 4194304;
20
25
  export declare function routeFunctions<D>(route: FunctionRoute<D>): D[];
26
+ export declare function collectTrustedSources(routes: FunctionRoute[], root: string): Promise<Record<string, string>>;
27
+ export declare function collectSourcesFor(definitions: FunctionDefinition[], root: string): Promise<FunctionSources>;
28
+ /** Route-shaped convenience over `collectSourcesFor`: every existing caller (policy.ts,
29
+ * prerender.ts, typescript-authoring.ts) keeps working unchanged from `FunctionRoute[]`. */
21
30
  export declare function collectFunctionSources(routes: FunctionRoute[], root: string): Promise<FunctionSources>;
@@ -1,12 +1,28 @@
1
1
  import { Worker } from 'node:worker_threads';
2
- import type { FunctionRoute, FunctionSources } from './function-sources.ts';
2
+ import type { FunctionDefinition, FunctionRoute, FunctionSources } from './function-sources.ts';
3
3
  import type { HandlerResult, HeaderPair } from './http-response.ts';
4
4
  import type { ParameterValue, RequestContext } from './match.ts';
5
5
  import type { LogFn } from './types.ts';
6
6
  import type { GuestRequestPayload } from './guest-api.ts';
7
7
  export type { FunctionDefinition, FunctionRoute } from './function-sources.ts';
8
8
  export type { GuestRequestPayload, GuestResponsePayload } from './guest-api.ts';
9
- export interface FunctionPoolOptions {
9
+ /** A module entry point the sandbox must load: an absolute source file path
10
+ * (already resolved and validated, e.g. via `functionFile()`) plus which
11
+ * export of it needs to be reachable. The same shape a `FunctionDefinition`
12
+ * already uses for `function`/`middleware` routes. */
13
+ export type SandboxEntry = FunctionDefinition;
14
+ /** What one `SandboxPool.execute()` call invokes: the same `{source, export}`
15
+ * shape as a `SandboxEntry`, naming one of the pool's declared entries. */
16
+ export type SandboxTarget = FunctionDefinition;
17
+ /** `entry` runs last (the route's `function`/handler); `chain` runs first, in
18
+ * order, each with `(request, context, next)` — the same wrap/middleware
19
+ * semantics `__invokePipeline` already gives sandboxed routes. Neither is
20
+ * required: an empty invocation with a `native` reply just returns it. */
21
+ export interface SandboxInvocation {
22
+ entry?: SandboxTarget | undefined;
23
+ chain?: SandboxTarget[] | undefined;
24
+ }
25
+ export interface SandboxPoolOptions {
10
26
  root?: string | undefined;
11
27
  snapshot?: FunctionSources | undefined;
12
28
  workers?: number | undefined;
@@ -14,6 +30,7 @@ export interface FunctionPoolOptions {
14
30
  maxBytes?: number | undefined;
15
31
  log?: LogFn | undefined;
16
32
  }
33
+ export type FunctionPoolOptions = SandboxPoolOptions;
17
34
  export interface FunctionWorkerData {
18
35
  sources: Record<string, string>;
19
36
  dependencies: Record<string, string[]>;
@@ -52,6 +69,7 @@ export type FunctionWorkerMessage = {
52
69
  headers: HeaderPair[];
53
70
  body: Uint8Array;
54
71
  nativeBody: boolean;
72
+ contentLength?: number;
55
73
  } | {
56
74
  id: string;
57
75
  error: true;
@@ -67,9 +85,9 @@ interface Slot {
67
85
  ready: boolean;
68
86
  pending: Pending | null;
69
87
  }
70
- export declare class FunctionPool {
88
+ export declare class SandboxPool {
71
89
  root: string | undefined;
72
- routes: FunctionRoute[];
90
+ entries: SandboxEntry[];
73
91
  preparedSnapshot: FunctionSources | undefined;
74
92
  snapshot: FunctionSources | undefined;
75
93
  restarts: Map<number, number>;
@@ -81,12 +99,37 @@ export declare class FunctionPool {
81
99
  size: number;
82
100
  slots: (Slot | undefined)[];
83
101
  closed: boolean;
84
- constructor(routes: FunctionRoute[], { root, snapshot, workers, timeoutMs, maxBytes, log }?: FunctionPoolOptions);
102
+ constructor(entries: SandboxEntry[], { root, snapshot, workers, timeoutMs, maxBytes, log }?: SandboxPoolOptions);
85
103
  start(): Promise<this>;
86
104
  spawn(index: number): Promise<void>;
87
105
  report(status: string, index: number, extra?: object): void;
88
106
  scheduleRespawn(index: number): void;
89
107
  get healthy(): boolean;
108
+ /** `invocation.entry` runs last (chain-wrapped), `invocation.chain` first, in
109
+ * declared order — the same `__invokePipeline` wrap/middleware discipline
110
+ * (`next()` callable at most once) the sandboxed route path already
111
+ * enforces; there is no second dispatch mechanism for this. Every entry and
112
+ * chain source named here must already be one of this pool's declared
113
+ * `entries` (constructor), or the worker's own module allowlist denies it. */
114
+ execute(invocation: SandboxInvocation, request: GuestRequestPayload, context: FunctionContext, native: HandlerResult | undefined): Promise<FunctionResult>;
115
+ close(): Promise<void>;
116
+ }
117
+ export declare class FunctionPool {
118
+ routes: FunctionRoute[];
119
+ private pool;
120
+ constructor(routes: FunctionRoute[], options?: FunctionPoolOptions);
121
+ start(): Promise<this>;
90
122
  execute(route: FunctionRoute, request: GuestRequestPayload, context: FunctionContext, native: HandlerResult | undefined): Promise<FunctionResult>;
123
+ scheduleRespawn(index: number): void;
91
124
  close(): Promise<void>;
125
+ get healthy(): boolean;
126
+ get restarts(): Map<number, number>;
127
+ get restartTimers(): Set<NodeJS.Timeout>;
128
+ get slots(): (Slot | undefined)[];
129
+ get size(): number;
130
+ get closed(): boolean;
131
+ get snapshot(): FunctionSources | undefined;
132
+ get log(): LogFn;
133
+ get timeoutMs(): number;
134
+ get maxBytes(): number;
92
135
  }
@@ -12,5 +12,6 @@ export interface GuestResponsePayload {
12
12
  headers: HeaderPair[];
13
13
  body: string;
14
14
  nativeBody?: boolean;
15
+ contentLength?: number;
15
16
  }
16
17
  export declare const guestBootstrap: string;
@@ -1,11 +1,41 @@
1
1
  export { createRuntime } from './runtime.ts';
2
- export type { Runtime, RuntimeOptions, RuntimeRequest, RequestTrace, LinkReader, LinkStoreBinding, HostPlugin, Observer, TestPlan } from './runtime.ts';
2
+ export type { Runtime, RuntimeOptions, RuntimeRequest, RequestTrace, HostPlugin, Observer, TestPlan } from './runtime.ts';
3
3
  export { startServer } from './server.ts';
4
4
  export type { Server, ServerOptions } from './server.ts';
5
5
  export { loadDocument, validateDocument, parseYaml } from './config.ts';
6
- export { openLinkStore } from './link-store.ts';
7
- export type { LinkStore, LinkRow, LinkStoreOptions } from './link-store.ts';
8
- export { startLinkApi } from './link-api.ts';
9
- export type { LinkApi, LinkApiOptions } from './link-api.ts';
10
- export type { LinkEvent, LinkObserverOptions, LinkObserverStats } from './link-events.ts';
11
6
  export { events as observabilityEvents, validateObservers, createObserverSink, createMetrics, renderPrometheus } from './observability.ts';
7
+ export { getCapabilities, routeCapabilities, analyzeProjectCapabilities, analyzeCompiledCapabilities, assertTargetCompatibility, normalizeCapabilityTarget } from './capabilities.ts';
8
+ export { capabilityDetails } from './capabilities.ts';
9
+ export type { CapabilityTarget, CapabilityName, CapabilityKind, CapabilityDetail, CapabilitySupport, CapabilityDecision, CapabilityRequirement, CapabilityCatalog, CompatibilityReport } from './capabilities.ts';
10
+ export { importRoutes, exportRoutes } from './interchange.ts';
11
+ export type { InterchangeFormat, ConversionDiagnostic, ConversionCounts, ConversionReport, ImportRoutesOptions, ExportRoutesOptions } from './interchange.ts';
12
+ export { listRecipes, searchRecipes, showRecipe, addRecipe } from './recipes.ts';
13
+ export type { RecipeSummary, Recipe, RecipeAddReport, RecipeSearchResult } from './recipes.ts';
14
+ export { listExamples, searchExamples } from './examples.ts';
15
+ export type { ExampleSummary, ExampleSearchResult, RouteIndex, RouteIndexEntry } from './examples.ts';
16
+ export type { CatalogMetadata, TargetVerdict, Complexity } from './catalog.ts';
17
+ export { buildTypeScriptProject } from './typescript-authoring.ts';
18
+ export type { TypeScriptBuildReport } from './typescript-authoring.ts';
19
+ export { importBulkProject } from './bulk.ts';
20
+ export type { BulkFormat, BulkFilePlan, BulkImportReport } from './bulk.ts';
21
+ export { inspectProject, validateProject, explainRoute, explainProject, previewImport, previewExport, getCapability, getSchemaFragment, schemaPathNames, inspectExtensions, describeExtensions, buildContext, renderContext, estimateTokens, documentationTokens } from './tooling.ts';
22
+ export type { InspectOptions, RouteExplanation, RouteMiss, ExplainedHandler, ExplainedCache, ExplainedExtensionRequirement, ExtensionProvider, TargetSupport, CapabilityEntry, CapabilityUsage, SchemaFragment, ExtensionInspection, ContextOptions, ProjectContext, ContextSection } from './tooling.ts';
23
+ export { buildManifest, renderManifest, MANIFEST_SCHEMA_VERSION } from './manifest.ts';
24
+ export type { Manifest, ManifestRoute, ManifestModule, RecipeProvenance } from './manifest.ts';
25
+ export { serveMcp } from './mcp.ts';
26
+ export type { McpOptions } from './mcp.ts';
27
+ export { providerConformanceCases, runProviderConformance, verifyProviderDeployment } from './provider-verification.ts';
28
+ export type { VerificationTarget, ProviderProbe, ProviderAnswer, ProviderTransport, ProviderVerificationOptions, ProviderFinding, ProviderVerificationReport } from './provider-verification.ts';
29
+ export { normalizeMatch, assertDisjointMatches, matchesRoute } from './conditions.ts';
30
+ export type { RouteMatch, ConditionRequest } from './conditions.ts';
31
+ export { buildCloudflare } from './build-cloudflare.ts';
32
+ export type { BuildOptions as CloudflareBuildOptions, BuildReport as CloudflareBuildReport } from './build-cloudflare.ts';
33
+ export { buildStatic } from './build-static.ts';
34
+ export type { BuildOptions as StaticBuildOptions, BuildReport as StaticBuildReport, StaticRedirect, StaticObject, RedirectManifest, ObjectManifest } from './build-static.ts';
35
+ export { runProjectTests } from './project-tests.ts';
36
+ export type { ProjectTestOptions, ProjectTestResult } from './project-tests.ts';
37
+ export { scaffoldProject } from './scaffold.ts';
38
+ export type { ScaffoldReport, Unresolved as ScaffoldUnresolved } from './scaffold.ts';
39
+ export { initProject, addRedirect } from './authoring.ts';
40
+ export { initProjectWith } from './init-with.ts';
41
+ export type { ScaffoldRequest, ScaffoldResult, ScaffoldFile } from './extensions.ts';
@@ -0,0 +1,30 @@
1
+ import type { ScaffoldRequest, ScaffoldResult } from './extensions.ts';
2
+ /** Directory names inside the generated site. The route project lives under `app/`; everything else is operator-owned. */
3
+ export declare const PROJECT_DIRECTORY = "app", HOST_FILE = "host.mjs", ROUTES_FILE = "routes/extensions.yaml";
4
+ export interface InitWithOptions {
5
+ cwd?: string | undefined;
6
+ }
7
+ export interface InitWithResult {
8
+ directory: string;
9
+ project: string;
10
+ hostFile: string;
11
+ extensions: string[];
12
+ projectSha256: string;
13
+ nextSteps: string[];
14
+ }
15
+ export declare function parseWithNames(value: string): string[];
16
+ export declare const packageName: (name: string) => string;
17
+ /**
18
+ * Resolves the extension package from the invoking directory (Node's package resolution with the default
19
+ * conditions), imports it, and calls its `scaffold` export. Nothing is bundled; core never imports these packages
20
+ * at build time. Refuses a missing package or a package without `scaffold` before anything is written.
21
+ */
22
+ export declare function loadScaffold(name: string, request: ScaffoldRequest, cwd: string): Promise<ScaffoldResult>;
23
+ export declare function renderHost(names: readonly string[], results: readonly ScaffoldResult[]): string;
24
+ export declare function renderReadme(directory: string, names: readonly string[], results: readonly ScaffoldResult[], starter: string, env: Record<string, string>, projectSha256: string): string;
25
+ /**
26
+ * `urlcode init <directory> --with a,b`: the starter under `app/`, every extension's fragments merged into one
27
+ * `urlcode.yaml`, one `host.mjs`, one `README.md` and the extensions' own files. All packages are resolved and
28
+ * their scaffolds computed before anything is written, so a refusal leaves no directory behind.
29
+ */
30
+ export declare function initProjectWith(destination: string, names: readonly string[], { cwd }?: InitWithOptions): Promise<InitWithResult>;
@@ -0,0 +1,16 @@
1
+ import type { ConversionReport } from './interchange.ts';
2
+ interface InterchangeCliOptions {
3
+ project: string;
4
+ target?: string | undefined;
5
+ format?: string | undefined;
6
+ out?: string | undefined;
7
+ report?: string | undefined;
8
+ dryRun?: boolean | undefined;
9
+ acceptProviderDifferences?: boolean | undefined;
10
+ }
11
+ export declare function readConversionInput(file: string): Promise<string>;
12
+ export declare function runInterchange(command: 'import' | 'export', args: string[], options: InterchangeCliOptions): Promise<{
13
+ report: ConversionReport;
14
+ text: string;
15
+ }>;
16
+ export {};
@@ -0,0 +1,42 @@
1
+ import type { ProjectDocument } from './types.ts';
2
+ export type InterchangeFormat = 'csv' | 'json' | 'yaml' | 'netlify' | 'cloudflare' | 'vercel' | 'netlify-toml';
3
+ export interface ConversionDiagnostic {
4
+ severity: 'error' | 'warning';
5
+ code: string;
6
+ source: string;
7
+ row?: number;
8
+ path?: string;
9
+ message: string;
10
+ }
11
+ export interface ConversionCounts {
12
+ convertedRoutes: number;
13
+ nativeEquivalentRoutes: number;
14
+ runtimeRequiredRoutes: number;
15
+ unsupportedRows: number;
16
+ providerDifferenceRoutes: number;
17
+ fullyScanned: boolean;
18
+ }
19
+ export interface ConversionReport {
20
+ counts: ConversionCounts;
21
+ ok: boolean;
22
+ lossless: boolean;
23
+ routeCount: number;
24
+ diagnostics: ConversionDiagnostic[];
25
+ document?: ProjectDocument;
26
+ output?: string;
27
+ }
28
+ export interface ImportRoutesOptions {
29
+ format: InterchangeFormat;
30
+ text: string;
31
+ source?: string;
32
+ acceptProviderDifferences?: boolean;
33
+ }
34
+ export interface ExportRoutesOptions {
35
+ format: InterchangeFormat;
36
+ document: ProjectDocument;
37
+ source?: string;
38
+ acceptProviderDifferences?: boolean;
39
+ }
40
+ /** Pure conversion: does not read projects, resolve bindings, execute guests or write files. */
41
+ export declare function importRoutes(options: ImportRoutesOptions): Promise<ConversionReport>;
42
+ export declare function exportRoutes(options: ExportRoutesOptions): Promise<ConversionReport>;
@@ -0,0 +1,79 @@
1
+ import type { CapabilityName, CapabilityTarget } from './capabilities.ts';
2
+ import type { InspectOptions } from './tooling.ts';
3
+ import type { RouteExplanation } from './explain.ts';
4
+ export declare const MANIFEST_SCHEMA_VERSION = 2;
5
+ export interface ManifestRoute {
6
+ path: string;
7
+ methods: string[];
8
+ handler: RouteExplanation['handler'];
9
+ enabled: boolean;
10
+ expires?: string;
11
+ generated?: string;
12
+ description?: string;
13
+ middleware: {
14
+ source: string;
15
+ export: string;
16
+ }[];
17
+ parameters: RouteExplanation['inputs']['parameters'];
18
+ body?: RouteExplanation['inputs']['body'];
19
+ policies: string[];
20
+ extensions: Record<string, Record<string, unknown>>;
21
+ cache: RouteExplanation['cache'];
22
+ bindings: {
23
+ env: string[];
24
+ secrets: string[];
25
+ };
26
+ egress: RouteExplanation['egress'];
27
+ capabilities: CapabilityName[];
28
+ targets: Record<CapabilityTarget, boolean>;
29
+ }
30
+ export interface ManifestModule {
31
+ source: string;
32
+ export: string;
33
+ routes: string[];
34
+ }
35
+ export interface RecipeProvenance {
36
+ id: string;
37
+ description?: string;
38
+ version?: string;
39
+ source?: string;
40
+ }
41
+ export interface Manifest {
42
+ schemaVersion: typeof MANIFEST_SCHEMA_VERSION;
43
+ urlcode: string;
44
+ entry: string;
45
+ files: string[];
46
+ revision: string;
47
+ configVersion: string;
48
+ routeCount: number;
49
+ routes: ManifestRoute[];
50
+ capabilities: CapabilityName[];
51
+ extensions: Record<string, {
52
+ version: string;
53
+ configKeys: string[];
54
+ mounts: string[];
55
+ protectedRoutes: string[];
56
+ }>;
57
+ recipes: RecipeProvenance[];
58
+ external: {
59
+ env: string[];
60
+ secrets: string[];
61
+ egress: {
62
+ proxy: string[];
63
+ signals: string[];
64
+ };
65
+ extensions: string[];
66
+ };
67
+ functions: ManifestModule[];
68
+ middleware: ManifestModule[];
69
+ targets: Record<CapabilityTarget, {
70
+ compatible: boolean;
71
+ issues: number;
72
+ }>;
73
+ }
74
+ /** Build the semantic manifest for a project from its compiled IR. Deterministic for a given project. */
75
+ export declare function buildManifest(project: string, options?: InspectOptions): Promise<Manifest>;
76
+ /** The manifest as `build` writes it: two-space JSON with a trailing newline. */
77
+ export declare function renderManifest(manifest: Manifest): string;
78
+ export declare const manifestFileName = "manifest.json";
79
+ export declare function manifestPath(out: string): string;
@@ -37,6 +37,7 @@ export interface MatchableRoute {
37
37
  pattern: string;
38
38
  parts: string[];
39
39
  prefix?: string;
40
+ extension?: string;
40
41
  parameters: CompiledParameter[];
41
42
  env: Record<string, string>;
42
43
  secrets: Record<string, string>;
@@ -0,0 +1,92 @@
1
+ export declare const authoringDefinitions: ({
2
+ name: string;
3
+ description: string;
4
+ properties: {
5
+ path: {
6
+ type: string;
7
+ maxLength: number;
8
+ };
9
+ handler: {
10
+ anyOf: ({
11
+ type: string;
12
+ maxLength: number;
13
+ } | {
14
+ type: string;
15
+ maxLength?: never;
16
+ })[];
17
+ };
18
+ middleware: {
19
+ type: string;
20
+ maxItems: number;
21
+ items: {
22
+ anyOf: ({
23
+ type: string;
24
+ maxLength: number;
25
+ } | {
26
+ type: string;
27
+ maxLength?: never;
28
+ })[];
29
+ };
30
+ };
31
+ file: {
32
+ type: string;
33
+ maxLength: number;
34
+ };
35
+ name?: never;
36
+ destination?: never;
37
+ dryRun?: never;
38
+ };
39
+ required: string[];
40
+ } | {
41
+ name: string;
42
+ description: string;
43
+ properties: {
44
+ name: {
45
+ type: string;
46
+ maxLength: number;
47
+ };
48
+ destination: {
49
+ type: string;
50
+ maxLength: number;
51
+ };
52
+ dryRun: {
53
+ type: string;
54
+ };
55
+ path?: never;
56
+ handler?: never;
57
+ middleware?: never;
58
+ file?: never;
59
+ };
60
+ required: string[];
61
+ } | {
62
+ name: string;
63
+ description: string;
64
+ properties: {
65
+ dryRun: {
66
+ type: string;
67
+ };
68
+ path?: never;
69
+ handler?: never;
70
+ middleware?: never;
71
+ file?: never;
72
+ name?: never;
73
+ destination?: never;
74
+ };
75
+ required: never[];
76
+ } | {
77
+ name: string;
78
+ description: string;
79
+ properties: {
80
+ path?: never;
81
+ handler?: never;
82
+ middleware?: never;
83
+ file?: never;
84
+ name?: never;
85
+ destination?: never;
86
+ dryRun?: never;
87
+ };
88
+ required: never[];
89
+ })[];
90
+ /** A project-relative path an authoring tool may create or replace: no absolute, `..`, hidden (`.env*`, `.git`), credential or operator names, and no symlink anywhere on the walk. */
91
+ export declare function confinedPath(root: string, path: unknown): Promise<string>;
92
+ export declare function callAuthoringTool(root: string, name: string, args: Record<string, unknown>, origin?: string): Promise<unknown>;
@@ -0,0 +1,12 @@
1
+ import type { Readable, Writable } from 'node:stream';
2
+ /** `allowAuthoring` and `hostFile` are set only by the `--allow-authoring` and `--host-file` command-line flags; tool arguments and the environment never enable them. */
3
+ export interface McpOptions {
4
+ project: string;
5
+ input?: Readable;
6
+ output?: Writable;
7
+ origin?: string;
8
+ allowAuthoring?: boolean;
9
+ hostFile?: string;
10
+ }
11
+ /** Operator selects the only project root. Read tools have no path, credential, write or execution authority; authoring tools write inside that root only. */
12
+ export declare function serveMcp(options: McpOptions): Promise<void>;