@leed-ai/cli 0.0.0 → 6.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (263) hide show
  1. package/LICENSE.md +57 -0
  2. package/README.md +120 -3
  3. package/dist/LICENSE.md +57 -0
  4. package/dist/acorn-DAgDT1om.js +5087 -0
  5. package/dist/angular-l0_4PK8N.js +3598 -0
  6. package/dist/authShared-Dray38Ls.js +1161 -0
  7. package/dist/babel-CJeRQd5u.js +10038 -0
  8. package/dist/buildResults-tiq1nugP.js +21180 -0
  9. package/dist/chunk-1VJ9lAw7.js +42 -0
  10. package/dist/cliAuth-38JjD6hw.js +15 -0
  11. package/dist/env-B0bHiXJJ.js +29 -0
  12. package/dist/errors-CqKamGCu.js +481 -0
  13. package/dist/estree-E8WG8UHj.js +6930 -0
  14. package/dist/flow-6xaRIbPQ.js +52255 -0
  15. package/dist/glimmer-aJPjsfbT.js +7272 -0
  16. package/dist/graphql-mcgtPEiZ.js +1901 -0
  17. package/dist/html--eeea3Kl.js +6553 -0
  18. package/dist/leed.eleventy.mjs +6525 -0
  19. package/dist/leed.mjs +88952 -0
  20. package/dist/leed.sources.json +798 -0
  21. package/dist/leedLogger-Zkada5aO.js +78 -0
  22. package/dist/markdown-D73jNKwx.js +6836 -0
  23. package/dist/meriyah-CMp1nDDW.js +8932 -0
  24. package/dist/package.json +101 -0
  25. package/dist/postcss-h4fBr2Fn.js +6760 -0
  26. package/dist/prettier-CwFSKxfN.js +16821 -0
  27. package/dist/static/customer-site-worker/package.json +9 -0
  28. package/dist/static/customer-site-worker/src/assetsHydration.ts +55 -0
  29. package/dist/static/customer-site-worker/src/constants.ts +20 -0
  30. package/dist/static/customer-site-worker/src/cors.ts +120 -0
  31. package/dist/static/customer-site-worker/src/index.ts +242 -0
  32. package/dist/static/customer-site-worker/src/mcp-proxy.ts +98 -0
  33. package/dist/static/customer-site-worker/src/proxy.ts +92 -0
  34. package/dist/static/customer-site-worker/src/proxyHeaders.ts +47 -0
  35. package/dist/static/customer-site-worker/src/tier.ts +40 -0
  36. package/dist/static/customer-site-worker/src/types.ts +82 -0
  37. package/dist/static/customer-site-worker/test/functions-mock.worker.js +50 -0
  38. package/dist/static/customer-site-worker/tsconfig.json +19 -0
  39. package/dist/static/customer-site-worker/vitest.workers.config.ts +61 -0
  40. package/dist/static/install/husky/colors.mjs +5 -0
  41. package/dist/static/install/husky/hooks/commit-msg +1 -0
  42. package/dist/static/install/husky/hooks/pre-commit +1 -0
  43. package/dist/static/install/husky/hooks/pre-push +1 -0
  44. package/dist/static/install/husky/valid-command.mjs +29 -0
  45. package/dist/static/install/husky/valid-commit-msg.mjs +20 -0
  46. package/dist/static/install/package.json +10 -0
  47. package/dist/static/install/packages.txt +4 -0
  48. package/dist/static/install/tasks.json +111 -0
  49. package/dist/static/javascript/detectIncognito.js +195 -0
  50. package/dist/static/javascript/documentation.js +2781 -0
  51. package/dist/static/javascript/fp/fp.esm.js +2896 -0
  52. package/dist/static/javascript/fp/fp.js +3067 -0
  53. package/dist/static/javascript/live-search.js +986 -0
  54. package/dist/static/javascript/lunr-search.js +843 -0
  55. package/dist/static/javascript/timeme.js +451 -0
  56. package/dist/static/javascript/tracker/webmcp.js +67 -0
  57. package/dist/static/javascript/tracker/whisper.js +1 -0
  58. package/dist/static/javascript/utilities.js +819 -0
  59. package/dist/static/javascript/versions.json +74 -0
  60. package/dist/static/javascript/zoomable.js +488 -0
  61. package/dist/static/site/_data/eleventyComputed.js +228 -0
  62. package/dist/static/site/_data/leed-form-data.json +253 -0
  63. package/dist/static/site/_includes/leed/api/bits/array-type.hbs +24 -0
  64. package/dist/static/site/_includes/leed/api/bits/badges.hbs +9 -0
  65. package/dist/static/site/_includes/leed/api/bits/description.hbs +9 -0
  66. package/dist/static/site/_includes/leed/api/bits/examples.hbs +42 -0
  67. package/dist/static/site/_includes/leed/api/bits/scopes.hbs +28 -0
  68. package/dist/static/site/_includes/leed/api/object.hbs +110 -0
  69. package/dist/static/site/_includes/leed/api/parameters.hbs +11 -0
  70. package/dist/static/site/_includes/leed/api/property.hbs +153 -0
  71. package/dist/static/site/_includes/leed/api/request-body.hbs +51 -0
  72. package/dist/static/site/_includes/leed/api/responses.hbs +89 -0
  73. package/dist/static/site/_includes/leed/api/security-constraints.hbs +59 -0
  74. package/dist/static/site/_includes/leed/api/security.hbs +75 -0
  75. package/dist/static/site/_includes/leed/components/pagination.hbs +45 -0
  76. package/dist/static/site/_includes/leed/components/scroll-status-indicator-horizontal.hbs +22 -0
  77. package/dist/static/site/_includes/leed/docs/alpha/api.hbs +6 -0
  78. package/dist/static/site/_includes/leed/docs/alpha/base.hbs +26 -0
  79. package/dist/static/site/_includes/leed/docs/alpha/documentation.hbs +7 -0
  80. package/dist/static/site/_includes/leed/docs/api-article.hbs +75 -0
  81. package/dist/static/site/_includes/leed/docs/bravo/api.hbs +5 -0
  82. package/dist/static/site/_includes/leed/docs/bravo/base.hbs +31 -0
  83. package/dist/static/site/_includes/leed/docs/bravo/documentation.hbs +7 -0
  84. package/dist/static/site/_includes/leed/docs/charlie/api.hbs +6 -0
  85. package/dist/static/site/_includes/leed/docs/charlie/base.hbs +27 -0
  86. package/dist/static/site/_includes/leed/docs/charlie/documentation.hbs +10 -0
  87. package/dist/static/site/_includes/leed/docs/doc-article.hbs +40 -0
  88. package/dist/static/site/_includes/leed/docs/docs-footer.hbs +35 -0
  89. package/dist/static/site/_includes/leed/docs/docs-header.hbs +59 -0
  90. package/dist/static/site/_includes/leed/docs/document-search-modal.hbs +36 -0
  91. package/dist/static/site/_includes/leed/docs/document-search.hbs +23 -0
  92. package/dist/static/site/_includes/leed/docs/footer.hbs +12 -0
  93. package/dist/static/site/_includes/leed/docs/header/brand.hbs +19 -0
  94. package/dist/static/site/_includes/leed/docs/header/chrome.hbs +33 -0
  95. package/dist/static/site/_includes/leed/docs/header/compact.hbs +19 -0
  96. package/dist/static/site/_includes/leed/docs/header/cta.hbs +15 -0
  97. package/dist/static/site/_includes/leed/docs/header/nav.hbs +18 -0
  98. package/dist/static/site/_includes/leed/docs/header/top-search.hbs +15 -0
  99. package/dist/static/site/_includes/leed/docs/mini-bar.hbs +53 -0
  100. package/dist/static/site/_includes/leed/docs/pagination.hbs +19 -0
  101. package/dist/static/site/_includes/leed/docs/shell.hbs +56 -0
  102. package/dist/static/site/_includes/leed/docs/sidebar.hbs +52 -0
  103. package/dist/static/site/_includes/leed/docs/social-icons.hbs +81 -0
  104. package/dist/static/site/_includes/leed/docs/style.hbs +17 -0
  105. package/dist/static/site/_includes/leed/docs/toc.hbs +7 -0
  106. package/dist/static/site/_includes/leed/form.hbs +266 -0
  107. package/dist/static/site/_includes/leed/head.hbs +67 -0
  108. package/dist/static/site/_includes/leed/menu/builder.hbs +35 -0
  109. package/dist/static/site/_includes/leed/menu/item.hbs +67 -0
  110. package/dist/static/site/_includes/leed/menu/link.hbs +59 -0
  111. package/dist/static/site/_includes/leed/metadata/ogCard.hbs +40 -0
  112. package/dist/static/site/_includes/leed/metadata/siteMetadata.hbs +24 -0
  113. package/dist/static/site/_includes/leed/metadata/twitterCard.hbs +34 -0
  114. package/dist/static/site/_includes/leed/popup-video.hbs +21 -0
  115. package/dist/static/site/_includes/leed/stub-template.hbs +17 -0
  116. package/dist/static/site/_includes/leed/unsubscribe-form.hbs +30 -0
  117. package/dist/static/site/_layouts/leed-documentation.hbs +12 -0
  118. package/dist/static/site/leed-feed-atom.hbs +42 -0
  119. package/dist/static/site/leed-feed-json.hbs +56 -0
  120. package/dist/static/site/leed-feed-rss.hbs +39 -0
  121. package/dist/static/site/leed-headers.hbs +38 -0
  122. package/dist/static/site/leed-redirects.hbs +10 -0
  123. package/dist/static/site/leed-sitemap-pageType.hbs +28 -0
  124. package/dist/static/site/leed-sitemap.hbs +19 -0
  125. package/dist/static/site/leed-unsubscribe.hbs +44 -0
  126. package/dist/static/site/leed-unsubscribed.hbs +40 -0
  127. package/dist/static/tailwind/components/alerts.css +132 -0
  128. package/dist/static/tailwind/components/api-methods.css +39 -0
  129. package/dist/static/tailwind/components/breadcrumbs.css +31 -0
  130. package/dist/static/tailwind/components/code.css +88 -0
  131. package/dist/static/tailwind/components/collapsible.css +38 -0
  132. package/dist/static/tailwind/components/document-search.css +222 -0
  133. package/dist/static/tailwind/components/form.css +185 -0
  134. package/dist/static/tailwind/components/kbd.css +7 -0
  135. package/dist/static/tailwind/components/pagination.css +81 -0
  136. package/dist/static/tailwind/components/scroll-status-indicator.css +5 -0
  137. package/dist/static/tailwind/components/tab-groups.css +117 -0
  138. package/dist/static/tailwind/components/tables.css +0 -0
  139. package/dist/static/tailwind/components/toc.css +60 -0
  140. package/dist/static/tailwind/components.css +248 -0
  141. package/dist/static/tailwind/defaults.css +260 -0
  142. package/dist/static/tailwind/docs/api.css +701 -0
  143. package/dist/static/tailwind/docs/components/blockquote.css +5 -0
  144. package/dist/static/tailwind/docs/components/button.css +11 -0
  145. package/dist/static/tailwind/docs/components/docs-pagination.css +71 -0
  146. package/dist/static/tailwind/docs/components/mobile-bar.css +83 -0
  147. package/dist/static/tailwind/docs/components/navigation.css +279 -0
  148. package/dist/static/tailwind/docs/components/table.css +54 -0
  149. package/dist/static/tailwind/docs/components.css +6 -0
  150. package/dist/static/tailwind/docs/docs.css +427 -0
  151. package/dist/static/tailwind/docs/layouts/alpha.css +108 -0
  152. package/dist/static/tailwind/docs/layouts/bravo.css +218 -0
  153. package/dist/static/tailwind/docs/layouts/charlie.css +105 -0
  154. package/dist/static/tailwind/docs/layouts.css +3 -0
  155. package/dist/static/tailwind/docs/themes/amber.css +113 -0
  156. package/dist/static/tailwind/docs/themes/blue.css +94 -0
  157. package/dist/static/tailwind/docs/themes/cyan.css +111 -0
  158. package/dist/static/tailwind/docs/themes/emerald.css +111 -0
  159. package/dist/static/tailwind/docs/themes/fuchsia.css +111 -0
  160. package/dist/static/tailwind/docs/themes/green.css +95 -0
  161. package/dist/static/tailwind/docs/themes/indigo.css +111 -0
  162. package/dist/static/tailwind/docs/themes/lime.css +111 -0
  163. package/dist/static/tailwind/docs/themes/orange.css +111 -0
  164. package/dist/static/tailwind/docs/themes/pink.css +111 -0
  165. package/dist/static/tailwind/docs/themes/purple.css +111 -0
  166. package/dist/static/tailwind/docs/themes/red.css +111 -0
  167. package/dist/static/tailwind/docs/themes/rose.css +111 -0
  168. package/dist/static/tailwind/docs/themes/sky.css +111 -0
  169. package/dist/static/tailwind/docs/themes/teal.css +111 -0
  170. package/dist/static/tailwind/docs/themes/violet.css +111 -0
  171. package/dist/static/tailwind/docs/themes/yellow.css +111 -0
  172. package/dist/static/tailwind/docs/themes.css +84 -0
  173. package/dist/static/tailwind/font-awesome/free-7.3.1/brands.css +2455 -0
  174. package/dist/static/tailwind/font-awesome/free-7.3.1/fontawesome.css +8997 -0
  175. package/dist/static/tailwind/font-awesome/free-7.3.1/fonts.css +45 -0
  176. package/dist/static/tailwind/font-awesome/free-7.3.1/icons.json +2608 -0
  177. package/dist/static/tailwind/font-awesome/free-7.3.1.css +3 -0
  178. package/dist/static/tailwind/font-awesome/pro-7.0.0/brands.css +2215 -0
  179. package/dist/static/tailwind/font-awesome/pro-7.0.0/fontawesome.css +19281 -0
  180. package/dist/static/tailwind/font-awesome/pro-7.0.0/fonts.css +445 -0
  181. package/dist/static/tailwind/font-awesome/pro-7.0.0.css +3 -0
  182. package/dist/static/tailwind/font-awesome/pro-7.3.1/brands.css +2455 -0
  183. package/dist/static/tailwind/font-awesome/pro-7.3.1/fontawesome.css +20365 -0
  184. package/dist/static/tailwind/font-awesome/pro-7.3.1/fonts.css +589 -0
  185. package/dist/static/tailwind/font-awesome/pro-7.3.1.css +3 -0
  186. package/dist/static/tailwind/fonts/all.css +6 -0
  187. package/dist/static/tailwind/fonts/config.jsonc +31 -0
  188. package/dist/static/tailwind/fonts/geist-mono.css +142 -0
  189. package/dist/static/tailwind/fonts/geist.css +142 -0
  190. package/dist/static/tailwind/fonts/inter.css +215 -0
  191. package/dist/static/tailwind/fonts/jetbrains-mono.css +126 -0
  192. package/dist/static/tailwind/fonts/noto-sans.css +134 -0
  193. package/dist/static/tailwind/fonts/open-sans.css +89 -0
  194. package/dist/static/tailwind/highlighters.css +14 -0
  195. package/dist/static/tailwind/hljs/README.md +53 -0
  196. package/dist/static/tailwind/hljs/a11y.css +96 -0
  197. package/dist/static/tailwind/hljs/atom-fruit.css +90 -0
  198. package/dist/static/tailwind/hljs/atom-one.css +164 -0
  199. package/dist/static/tailwind/hljs/default.css +164 -0
  200. package/dist/static/tailwind/hljs/github.css +101 -0
  201. package/dist/static/tailwind/hljs/google-code.css +112 -0
  202. package/dist/static/tailwind/hljs/grayscale.css +115 -0
  203. package/dist/static/tailwind/hljs/gruvbox-hard.css +115 -0
  204. package/dist/static/tailwind/hljs/gruvbox-medium.css +115 -0
  205. package/dist/static/tailwind/hljs/gruvbox-soft.css +115 -0
  206. package/dist/static/tailwind/hljs/papercolor.css +120 -0
  207. package/dist/static/tailwind/hljs/qt-creator.css +91 -0
  208. package/dist/static/tailwind/hljs/summerfruit.css +115 -0
  209. package/dist/static/tailwind/hljs/tomorrow.css +115 -0
  210. package/dist/static/tailwind/leed.css +170 -0
  211. package/dist/static/tailwind/site-tokens.reference.css +105 -0
  212. package/dist/static/tailwind/utils/icons.css +102 -0
  213. package/dist/static/tailwind/utils/utilities.css +105 -0
  214. package/dist/static/templates/pages/PAGE.hbs +27 -0
  215. package/dist/static/templates/pages/PAGE_LAYOUT.hbs +19 -0
  216. package/dist/static/templates/pages/PAGE_TYPE_INDEX.hbs +89 -0
  217. package/dist/static/templates/pages/PAGINATED_PAGE_TYPE_ITEM.hbs +52 -0
  218. package/dist/static/templates/pages/PAGINATED_PAGE_TYPE_LIST.hbs +39 -0
  219. package/dist/static/templates/pages/PAGINATED_PAGE_TYPE_PAGINATION.hbs +11 -0
  220. package/dist/static/templates/raw-content/.ci/build.sh +58 -0
  221. package/dist/static/templates/raw-content/README.md +179 -0
  222. package/dist/static/templates/raw-content/_gitignore +50 -0
  223. package/dist/static/templates/raw-content/src/404.hbs +21 -0
  224. package/dist/static/templates/raw-content/src/_data/autolink.json +1 -0
  225. package/dist/static/templates/raw-content/src/_data/ctaList.json +1 -0
  226. package/dist/static/templates/raw-content/src/_data/leedForms.json +1 -0
  227. package/dist/static/templates/raw-content/src/_data/menu.json +1 -0
  228. package/dist/static/templates/raw-content/src/_includes/footer.hbs +18 -0
  229. package/dist/static/templates/raw-content/src/_includes/header-includes.hbs +25 -0
  230. package/dist/static/templates/raw-content/src/_includes/header.hbs +5 -0
  231. package/dist/static/templates/raw-content/src/_includes/site-template.hbs +23 -0
  232. package/dist/static/templates/raw-content/src/_includes/unsubscribe-DISABLED.hbs +17 -0
  233. package/dist/static/templates/raw-content/src/_includes/unsubscribed-DISABLED.hbs +13 -0
  234. package/dist/static/templates/raw-content/src/_layouts/empty.hbs +2 -0
  235. package/dist/static/templates/raw-content/src/index.hbs +21 -0
  236. package/dist/static/templates/raw-content/src/robots.hbs +9 -0
  237. package/dist/static/templates/raw-content/tailwind/site/base.css +44 -0
  238. package/dist/static/templates/raw-content/tailwind/site.config.css +3 -0
  239. package/dist/static/templates/sandbox/_gitignore +50 -0
  240. package/dist/static/templates/sandbox/identity.json +1 -0
  241. package/dist/static/templates/sandbox/src/404.hbs +21 -0
  242. package/dist/static/templates/sandbox/src/_data/autolink.json +1 -0
  243. package/dist/static/templates/sandbox/src/_data/ctaList.json +1 -0
  244. package/dist/static/templates/sandbox/src/_data/labelList.json +9 -0
  245. package/dist/static/templates/sandbox/src/_data/leedForms.json +20 -0
  246. package/dist/static/templates/sandbox/src/_data/menu.json +19 -0
  247. package/dist/static/templates/sandbox/src/_data/pageTypeList.json +14 -0
  248. package/dist/static/templates/sandbox/src/_data/searchIndexList.json +1 -0
  249. package/dist/static/templates/sandbox/src/_data/userList.json +11 -0
  250. package/dist/static/templates/sandbox/src/_includes/footer.hbs +18 -0
  251. package/dist/static/templates/sandbox/src/_includes/header-includes.hbs +25 -0
  252. package/dist/static/templates/sandbox/src/_includes/header.hbs +5 -0
  253. package/dist/static/templates/sandbox/src/_includes/site-template.hbs +23 -0
  254. package/dist/static/templates/sandbox/src/_layouts/empty.hbs +2 -0
  255. package/dist/static/templates/sandbox/src/index.hbs +20 -0
  256. package/dist/static/templates/sandbox/src/robots.hbs +9 -0
  257. package/dist/static/templates/sandbox/src/src.11tydata.json +39 -0
  258. package/dist/static/templates/sandbox/tailwind/site/base.css +44 -0
  259. package/dist/static/templates/sandbox/tailwind/site.config.css +3 -0
  260. package/dist/thrown-sukVkp_1.js +113 -0
  261. package/dist/typescript-D4T0V_Hn.js +23004 -0
  262. package/dist/yaml-9wR8GxF_.js +5236 -0
  263. package/package.json +152 -10
@@ -0,0 +1,47 @@
1
+ import type { Context } from "hono";
2
+ import type { Env } from "./types";
3
+
4
+ /**
5
+ * Build the header set the customer-functions service binding expects on every
6
+ * proxied request. Shared by `proxyToFunctions` (proxy.ts) and `proxyMcp`
7
+ * (mcp-proxy.ts), which inject the identical trusted context.
8
+ *
9
+ * Clones the inbound request headers (so the visitor's `Cookie` — including the
10
+ * Docs MCP `__lid`/`__sid` set during the OAuth authorize flow — round-trips to
11
+ * the origin), then stamps the trusted values the origin relies on:
12
+ * - `companyId` — the per-site tenant id (trusted; baked into this worker).
13
+ * - `preview` — whether this is a preview build.
14
+ * - `turnstileSecretKey` — forwarded for the origin's Turnstile checks.
15
+ * - `originUrl` — the visitor-facing request URL.
16
+ * - `x-real-ip` — the client IP. Cloudflare delivers it to this Worker as
17
+ * `cf-connecting-ip` (Miniflare sets `127.0.0.1` for local `wrangler dev`);
18
+ * customer-functions' middleware reads it under the `x-real-ip` name.
19
+ * `Headers.set` overwrites any client-supplied value, so it is not spoofable.
20
+ */
21
+ export function buildProxyHeaders(c: Context<{ Bindings: Env }>): Headers {
22
+ const headers = new Headers(c.req.raw.headers);
23
+ headers.set("companyId", c.env.COMPANY_ID);
24
+ headers.set("preview", String(c.env.PREVIEW_SITE));
25
+ headers.set("turnstileSecretKey", c.env.TURNSTILE_SECRET_KEY);
26
+ headers.set("originUrl", c.req.url);
27
+ headers.set("x-real-ip", c.req.header("cf-connecting-ip") ?? "");
28
+ return headers;
29
+ }
30
+
31
+ /**
32
+ * Dispatch a proxied request to customer-functions (#284).
33
+ *
34
+ * Production path: the `FUNCTIONS` service binding. Local-dev override: when
35
+ * `FUNCTIONS_ORIGIN` is set, the request is re-targeted at that origin (keeping
36
+ * the inbound path + query) and sent via global `fetch`, bypassing wrangler's
37
+ * cross-`wrangler dev` registry. Both branches are identical except the target —
38
+ * same `init` (method/headers/body/redirect), so callers share one request shape.
39
+ */
40
+ export function fetchFunctions(c: Context<{ Bindings: Env }>, init: RequestInit): Promise<Response> {
41
+ if (c.env.FUNCTIONS_ORIGIN) {
42
+ const inbound = new URL(c.req.url);
43
+ const target = new URL(inbound.pathname + inbound.search, c.env.FUNCTIONS_ORIGIN);
44
+ return fetch(new Request(target, init));
45
+ }
46
+ return c.env.FUNCTIONS.fetch(new Request(c.req.url, init));
47
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Entitlement tier ladder for edge gating (#329).
3
+ *
4
+ * Lives in the worker because the worker is the constrained side: it is a
5
+ * standalone hono-only bundle (the build copies its `src/` + an isolated
6
+ * package.json with only `hono` into the customer site repo) and so CANNOT
7
+ * import `@leed/*` — `hasFeature` and `FEATURE_MIN_TIER` are unreachable here.
8
+ * The same reason `constants.ts` and the `DocResource` mirror live in this
9
+ * directory.
10
+ *
11
+ * So the tier is baked into the worker as `ENTITLEMENT_TIER` and compared here.
12
+ * The ladder itself is duplicated, which is safe — it is four values that define
13
+ * the pricing model — but the per-feature MINIMUM below is exactly the kind of
14
+ * value that moves. `tierDrift.test.ts` on the site-management side (which CAN
15
+ * import both) asserts these constants still match `FEATURE_MIN_TIER`, so a
16
+ * change to the catalog fails a test instead of silently un-gating a customer.
17
+ */
18
+
19
+ /** Ordered low → high. Mirrors `TIER_RANK` in `@leed/data-types` featureCatalog. */
20
+ export const TIER_RANK: Record<string, number> = {
21
+ free: 0,
22
+ starter: 1,
23
+ growth: 2,
24
+ enterprise: 3,
25
+ };
26
+
27
+ /** Minimum tier for live docs search — mirrors `FEATURE_MIN_TIER.docsLiveSearch`. */
28
+ export const DOCS_LIVE_SEARCH_MIN_TIER = "starter";
29
+
30
+ /**
31
+ * Whether `tier` reaches `minimum` on the ladder.
32
+ *
33
+ * FAIL-CLOSED on anything unrecognized, matching `hasFeature`: an unknown or
34
+ * missing tier meets no paid minimum. The one caller compensates for the
35
+ * "missing" case deliberately — see the guard in `index.ts`.
36
+ */
37
+ export function meetsTier(tier: string | undefined, minimum: string): boolean {
38
+ if (!tier || !Object.hasOwn(TIER_RANK, tier)) return false;
39
+ return TIER_RANK[tier] >= TIER_RANK[minimum];
40
+ }
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Vendored mirror of the Docs MCP `DocResource` (#284).
3
+ *
4
+ * The canonical Zod schema lives with the Docs MCP server at
5
+ * `apps/customer-functions/src/mcp/docResource.ts`. This worker is a standalone
6
+ * hono-only bundle — the build copies its `src/` + an isolated package.json
7
+ * (only `hono`) into the customer site repo, and wrangler runs `bun install`
8
+ * against that package.json — so it CANNOT import any `@leed/*` workspace
9
+ * package. The Docs MCP hydration only needs the shape to fill `content`, so this
10
+ * hand-written interface is kept intentionally in sync with the canonical Zod
11
+ * schema. Keep the two structurally compatible.
12
+ */
13
+ export interface DocResource {
14
+ pageId?: string;
15
+ path: string;
16
+ url: string;
17
+ title?: string;
18
+ setId?: string;
19
+ content?: string;
20
+ error?: string;
21
+ }
22
+
23
+ /** The content-bearing tool-response envelope the site-worker hydrates. */
24
+ export interface DocResourcesPayload {
25
+ resources: DocResource[];
26
+ }
27
+
28
+ export interface Env {
29
+ ASSETS: Fetcher;
30
+ FUNCTIONS: Fetcher;
31
+ /**
32
+ * Local-dev override (#284). When set (only in devMode wrangler configs),
33
+ * proxied requests go to this origin via global `fetch` instead of the
34
+ * `FUNCTIONS` service binding. Works around wrangler's cross-`wrangler dev`
35
+ * registry not reliably linking `customer-functions-dev` locally. Never
36
+ * emitted for public/preview builds — production keeps the service binding.
37
+ */
38
+ FUNCTIONS_ORIGIN?: string;
39
+ COMPANY_ID: string;
40
+ VALID_ORIGINS: string;
41
+ PREVIEW_SITE: boolean;
42
+ TURNSTILE_SECRET_KEY: string;
43
+ /**
44
+ * Per-customer MCP entitlement (#284, #294). Boolean wrangler var, baked
45
+ * into the generated wrangler config from the company's `entitlements.mcp`.
46
+ * When false the site-worker short-circuits AT THE EDGE both the `/mcp` +
47
+ * OAuth surface (the request never reaches customer-functions; customer-
48
+ * functions keeps its own `entitlements.mcp` check as defense-in-depth) and
49
+ * the `/.well-known/webmcp` + `/.well-known/agent.json` surfaces (404).
50
+ */
51
+ MCP_ENABLED: boolean;
52
+ /**
53
+ * The company's entitlement tier (#329) — `free` | `starter` | `growth` |
54
+ * `enterprise`. Baked so the edge can gate on the SAME tier ladder the rest of
55
+ * the platform uses, rather than a per-feature boolean per gate.
56
+ *
57
+ * Optional: a worker generated before this var existed carries no tier, and
58
+ * must DEFER to customer-functions rather than 404 its own search — so the
59
+ * guard checks for absence explicitly instead of relying on fail-closed
60
+ * `meetsTier`.
61
+ */
62
+ ENTITLEMENT_TIER?: string;
63
+ /**
64
+ * Commit SHA baked into this worker version at build time. Emitted on
65
+ * every response as `X-Site-Version` so `curl -I` against a customer
66
+ * site reveals which commit is currently live.
67
+ */
68
+ SITE_VERSION: string;
69
+ /**
70
+ * Plaintext "true"/"false" — when "true" the workers.dev hostname is
71
+ * gated and any request hitting it without the CMS proxy header is 301'd
72
+ * to PRIMARY_DOMAIN. Emitted as "true" on public builds once the custom
73
+ * domain becomes active (preview builds always emit "false" — they
74
+ * disable workers.dev outright instead). #266
75
+ */
76
+ REDIRECT_TO_PRIMARY_DOMAIN: string;
77
+ /**
78
+ * Canonical custom domain — destination for the workers.dev redirect.
79
+ * Same value as the route hostname in wrangler.jsonc for this Worker.
80
+ */
81
+ PRIMARY_DOMAIN: string;
82
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Auxiliary worker standing in for the `customer-functions` service binding in
3
+ * the customer-site-worker workerd integration test (#284). Plain JS because the
4
+ * workers-pool loads auxiliary `scriptPath` modules without TS transformation.
5
+ *
6
+ * Routes:
7
+ * - `/mcp/oauth/authorize` — mirrors the production OAuth authorize grant:
8
+ * reads the forwarded body and answers with a 302 → client `redirect_uri`,
9
+ * echoing the body back on `X-Forwarded-Body` so the proxy test can confirm
10
+ * it forwarded the body intact.
11
+ * - `/__302` / `/__follow_target` — a real redirect boundary used by the
12
+ * mechanism test to prove WHY the proxy must buffer the request body: a
13
+ * `fetch(..., { redirect: "follow" })` whose body is a one-time-use stream
14
+ * throws "encountered a redirect requiring the body to be retransmitted" on
15
+ * the 302, while a buffered (ArrayBuffer) body replays cleanly.
16
+ *
17
+ * Reached through the customer-site-worker's real `FUNCTIONS` service binding,
18
+ * so the proxy's `FUNCTIONS.fetch(... redirect: "manual")` call crosses the
19
+ * genuine workerd subrequest boundary the node-pool unit tests mock away.
20
+ */
21
+ export default {
22
+ async fetch(request) {
23
+ const url = new URL(request.url);
24
+
25
+ if (url.pathname === "/mcp/oauth/authorize") {
26
+ const forwarded = await request.text();
27
+ return new Response(null, {
28
+ status: 302,
29
+ headers: {
30
+ Location: "https://client.example.com/cb?code=abc&state=xyz",
31
+ "X-Forwarded-Body": forwarded,
32
+ },
33
+ });
34
+ }
35
+
36
+ if (url.pathname === "/__302") {
37
+ return new Response(null, { status: 302, headers: { Location: "/__follow_target" } });
38
+ }
39
+ if (url.pathname === "/__follow_target") {
40
+ // Reached only after workerd follows the 302 above (a 302 of a POST
41
+ // becomes a bodyless GET per the fetch spec). Its presence proves the
42
+ // followed-redirect path completed without the body-retransmit throw.
43
+ return new Response("ok", { headers: { "X-Replayed": "1" } });
44
+ }
45
+
46
+ return new Response(JSON.stringify({ jsonrpc: "2.0", id: 1, result: { ok: true } }), {
47
+ headers: { "content-type": "application/json" },
48
+ });
49
+ },
50
+ };
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "lib": ["ESNext"],
7
+ "types": ["@cloudflare/workers-types"],
8
+ "strict": true,
9
+ "skipLibCheck": true,
10
+ "esModuleInterop": true,
11
+ "forceConsistentCasingInFileNames": true
12
+ },
13
+ "include": ["src/**/*.ts"],
14
+ // Co-located tests (run by vitest, excluded from the customer bundle by the
15
+ // build's copy filter) pull in test-only virtual modules like `cloudflare:test`
16
+ // that this production-bundle tsconfig has no types for. Keep them out of this
17
+ // project's typecheck — the test suites are typechecked by vitest. (#284)
18
+ "exclude": ["src/**/*.test.ts", "src/**/*.spec.ts"]
19
+ }
@@ -0,0 +1,61 @@
1
+ import { cloudflareTest } from "@cloudflare/vitest-plugin";
2
+ import { defineConfig } from "vitest/config";
3
+
4
+ /**
5
+ * Workers-pool (Miniflare / workerd) config for the customer-site-worker (#284).
6
+ *
7
+ * The existing `mcp-proxy.test.ts` unit tests run in the NODE pool with a
8
+ * hand-built `env` whose `FUNCTIONS.fetch` is a plain `vi.fn()` — so they never
9
+ * exercise workerd's real subrequest machinery and PASSED even while the live
10
+ * proxy threw the "one-time-use body … requiring the body to be retransmitted"
11
+ * error on the OAuth-302. This config boots the actual worker (`src/index.ts`)
12
+ * in workerd; the `FUNCTIONS` binding is a real auxiliary mock worker
13
+ * (`test/functions-mock.worker.js`) that answers the OAuth authorize grant with
14
+ * the 302 → client `redirect_uri`, so the `.worker.test` suite drives the proxy
15
+ * across the genuine service-binding boundary. The node-pool tests are
16
+ * untouched: the site-management root config excludes the `.worker.test` glob.
17
+ */
18
+ export default defineConfig({
19
+ plugins: [
20
+ cloudflareTest({
21
+ main: "./src/index.ts",
22
+ // No wrangler.jsonc lives in this dir (the production config is generated
23
+ // per-customer by the wrangler generator at build time), so the worker is
24
+ // configured inline here.
25
+ miniflare: {
26
+ compatibilityDate: "2026-04-07",
27
+ serviceBindings: {
28
+ // The customer-functions stand-in (see test/functions-mock.worker.js).
29
+ FUNCTIONS: "functions-mock",
30
+ // ASSETS is only consulted on page-resources hydration, never on a 302.
31
+ ASSETS: async () => new Response("should-not-be-called", { status: 404 }),
32
+ },
33
+ bindings: {
34
+ COMPANY_ID: "co-test",
35
+ VALID_ORIGINS: JSON.stringify(["https://docs.example.com"]),
36
+ PREVIEW_SITE: false,
37
+ TURNSTILE_SECRET_KEY: "ts-test",
38
+ SITE_VERSION: "abcdef0",
39
+ REDIRECT_TO_PRIMARY_DOMAIN: "false",
40
+ PRIMARY_DOMAIN: "docs.example.com",
41
+ MCP_ENABLED: true,
42
+ },
43
+ workers: [
44
+ {
45
+ name: "functions-mock",
46
+ modules: true,
47
+ scriptPath: "./test/functions-mock.worker.js",
48
+ compatibilityDate: "2026-04-07",
49
+ },
50
+ ],
51
+ },
52
+ }),
53
+ ],
54
+ test: {
55
+ name: "customer-site-worker-workers",
56
+ include: ["src/**/*.worker.test.ts"],
57
+ globals: true,
58
+ testTimeout: 30000,
59
+ teardownTimeout: 5000,
60
+ },
61
+ });
@@ -0,0 +1,5 @@
1
+ const tty = process.stderr.isTTY;
2
+ const wrap = (code) => (s) => (tty ? `\x1b[${code}m${s}\x1b[0m` : s);
3
+
4
+ export const red = wrap("1;31");
5
+ export const yellow = wrap("33");
@@ -0,0 +1 @@
1
+ node .husky/valid-commit-msg.mjs "$1"
@@ -0,0 +1 @@
1
+ node .husky/valid-command.mjs "commit"
@@ -0,0 +1 @@
1
+ node .husky/valid-command.mjs "push"
@@ -0,0 +1,29 @@
1
+ import { execSync as shell } from "node:child_process";
2
+ import { red, yellow } from "./colors.mjs";
3
+
4
+ const args = process.argv.slice(2);
5
+ const [command] = args;
6
+
7
+ /**
8
+ * We use git to see if the leed.invoked flag was set.
9
+ */
10
+ let invokedByScript = false;
11
+ try {
12
+ invokedByScript = shell("git config --get leed.invoked").toString().trim();
13
+ } catch (_e) {
14
+ // any exit code other than zero is caught
15
+ }
16
+
17
+ /**
18
+ * If it was not invoked by our application, we spit out an error
19
+ * and the application help command.
20
+ */
21
+ if (invokedByScript !== "true") {
22
+ console.error(red(`\n\tYou cannot '${command}' directly, please use:\n`));
23
+ if (command === "commit") {
24
+ console.error(yellow(`\t\tleed site commit -m "update details"\n`));
25
+ } else if (command === "push") {
26
+ console.error(yellow(`\t\tleed site push\n`));
27
+ }
28
+ process.exit(18); // Exit with error code to block the commit
29
+ }
@@ -0,0 +1,20 @@
1
+ import fs from "node:fs";
2
+ import { red, yellow } from "./colors.mjs";
3
+
4
+ // Read the commit message from the file passed by Git
5
+ const commitMessageFile = process.argv[2];
6
+ const commitMessage = fs.readFileSync(commitMessageFile, "utf-8").trim();
7
+
8
+ const startMsg = "@leed/site-management=>";
9
+ const pos = commitMessage.indexOf(startMsg);
10
+ if (pos > -1) {
11
+ const data = commitMessage.substring(startMsg.length);
12
+ const json = JSON.parse(data);
13
+ if (json.userId && json.version && json.message) {
14
+ process.exit(0);
15
+ }
16
+ }
17
+
18
+ console.error(red("\n\tYou cannot commit directly to this repo, please use:\n"));
19
+ console.error(yellow(`\t\tleed site commit -m "reason for update"\n`));
20
+ process.exit(18); // Exit with error code to block the commit
@@ -0,0 +1,10 @@
1
+ {
2
+ "name": "@leed/site",
3
+ "version": "1.0.0",
4
+ "description": "Website being built by Leed",
5
+ "type": "module",
6
+ "author": "Leed AI",
7
+ "scripts": {},
8
+ "devDependencies": {
9
+ }
10
+ }
@@ -0,0 +1,4 @@
1
+ @tailwindcss/forms@0.5.11
2
+ @tailwindcss/typography@0.5.19
3
+ tailwindcss@4.2.4
4
+ husky@9.1.7
@@ -0,0 +1,111 @@
1
+ {
2
+ "version": "2.0.0",
3
+ "_description": "VS Code Tasks to simplify execution of the application",
4
+ "command": "leed",
5
+ "tasks": [
6
+ {
7
+ "label": "Run Webserver",
8
+ "type": "shell",
9
+ "args": ["site", "build", "--serve"],
10
+ "problemMatcher": [],
11
+ "group": {
12
+ "kind": "build",
13
+ "isDefault": true
14
+ }
15
+ },
16
+ {
17
+ "label": "Build",
18
+ "type": "shell",
19
+ "args": ["site", "build"],
20
+ "problemMatcher": [],
21
+ "group": {
22
+ "kind": "build",
23
+ "isDefault": true
24
+ }
25
+ },
26
+ {
27
+ "label": "Build (debug)",
28
+ "type": "shell",
29
+ "args": ["site", "build", "-d"],
30
+ "problemMatcher": [],
31
+ "group": {
32
+ "kind": "build",
33
+ "isDefault": true
34
+ }
35
+ },
36
+ {
37
+ "label": "Site Validation",
38
+ "type": "shell",
39
+ "args": ["site", "validate"],
40
+ "problemMatcher": [],
41
+ "group": {
42
+ "kind": "build",
43
+ "isDefault": true
44
+ }
45
+ },
46
+ {
47
+ "label": "Site Validation - Reset (Dry-Run)",
48
+ "type": "shell",
49
+ "args": ["site", "validate", "-r", "--dry-run"],
50
+ "problemMatcher": [],
51
+ "group": {
52
+ "kind": "build",
53
+ "isDefault": true
54
+ }
55
+ },
56
+ {
57
+ "label": "Site Validation - Reset",
58
+ "type": "shell",
59
+ "args": ["site", "validate", "-r"],
60
+ "problemMatcher": [],
61
+ "group": {
62
+ "kind": "build",
63
+ "isDefault": true
64
+ }
65
+ },
66
+ {
67
+ "label": "Commit Changes",
68
+ "type": "shell",
69
+ "args": ["site", "commit", "-m ${input:commitMsg}"],
70
+ "problemMatcher": []
71
+ },
72
+ {
73
+ "label": "Push to Staging",
74
+ "type": "shell",
75
+ "args": ["site", "push"],
76
+ "problemMatcher": []
77
+ },
78
+ {
79
+ "label": "Pull Latest from Staging",
80
+ "type": "shell",
81
+ "command": "git pull",
82
+ "problemMatcher": []
83
+ },
84
+ {
85
+ "label": "Login",
86
+ "type": "shell",
87
+ "args": ["auth", "login", "--browser"],
88
+ "problemMatcher": []
89
+ },
90
+ {
91
+ "label": "Logout",
92
+ "type": "shell",
93
+ "args": ["auth", "logout"],
94
+ "problemMatcher": []
95
+ },
96
+ {
97
+ "label": "Auth Status",
98
+ "type": "shell",
99
+ "args": ["auth", "status"],
100
+ "problemMatcher": []
101
+ }
102
+ ],
103
+ "inputs": [
104
+ {
105
+ "id": "commitMsg",
106
+ "type": "promptString",
107
+ "description": "Enter a commit message",
108
+ "default": "update site content"
109
+ }
110
+ ]
111
+ }