@pyric/cli 0.1.0-alpha.14 → 0.1.0-alpha.15

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 (599) hide show
  1. package/dist/assurance/.generated/conformance-verdicts.d.ts +120 -75
  2. package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
  3. package/dist/assurance/.generated/conformance-verdicts.js +120 -75
  4. package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
  5. package/dist/cli/serve.d.ts +1 -1
  6. package/dist/cli/serve.d.ts.map +1 -1
  7. package/dist/cli/serve.js +207 -284
  8. package/dist/cli/serve.js.map +1 -1
  9. package/dist/cli/service-command-records/database-rules-generate.d.ts +4 -0
  10. package/dist/cli/service-command-records/database-rules-generate.d.ts.map +1 -0
  11. package/dist/cli/service-command-records/database-rules-generate.js +3 -0
  12. package/dist/cli/service-command-records/database-rules-generate.js.map +1 -0
  13. package/dist/cli/service-command-records/database-rules-lint.d.ts +4 -0
  14. package/dist/cli/service-command-records/database-rules-lint.d.ts.map +1 -0
  15. package/dist/cli/service-command-records/database-rules-lint.js +3 -0
  16. package/dist/cli/service-command-records/database-rules-lint.js.map +1 -0
  17. package/dist/cli/service-command-records/database-rules-simulate.d.ts +4 -0
  18. package/dist/cli/service-command-records/database-rules-simulate.d.ts.map +1 -0
  19. package/dist/cli/service-command-records/database-rules-simulate.js +3 -0
  20. package/dist/cli/service-command-records/database-rules-simulate.js.map +1 -0
  21. package/dist/cli/service-command-records/database-rules-validate.d.ts +4 -0
  22. package/dist/cli/service-command-records/database-rules-validate.d.ts.map +1 -0
  23. package/dist/cli/service-command-records/database-rules-validate.js +3 -0
  24. package/dist/cli/service-command-records/database-rules-validate.js.map +1 -0
  25. package/dist/cli/service-command-records/firestore-indexes-generate.d.ts +4 -0
  26. package/dist/cli/service-command-records/firestore-indexes-generate.d.ts.map +1 -0
  27. package/dist/cli/service-command-records/firestore-indexes-generate.js +3 -0
  28. package/dist/cli/service-command-records/firestore-indexes-generate.js.map +1 -0
  29. package/dist/cli/service-command-records/firestore-rules-lint.d.ts +4 -0
  30. package/dist/cli/service-command-records/firestore-rules-lint.d.ts.map +1 -0
  31. package/dist/cli/service-command-records/firestore-rules-lint.js +3 -0
  32. package/dist/cli/service-command-records/firestore-rules-lint.js.map +1 -0
  33. package/dist/cli/service-command-records/firestore-rules-resolve.d.ts +4 -0
  34. package/dist/cli/service-command-records/firestore-rules-resolve.d.ts.map +1 -0
  35. package/dist/cli/service-command-records/firestore-rules-resolve.js +3 -0
  36. package/dist/cli/service-command-records/firestore-rules-resolve.js.map +1 -0
  37. package/dist/cli/service-command-records/firestore-rules-simulate.d.ts +4 -0
  38. package/dist/cli/service-command-records/firestore-rules-simulate.d.ts.map +1 -0
  39. package/dist/cli/service-command-records/firestore-rules-simulate.js +3 -0
  40. package/dist/cli/service-command-records/firestore-rules-simulate.js.map +1 -0
  41. package/dist/cli/service-command-records/firestore-rules-validate.d.ts +4 -0
  42. package/dist/cli/service-command-records/firestore-rules-validate.d.ts.map +1 -0
  43. package/dist/cli/service-command-records/firestore-rules-validate.js +3 -0
  44. package/dist/cli/service-command-records/firestore-rules-validate.js.map +1 -0
  45. package/dist/cli/service-command-records/storage-rules-lint.d.ts +4 -0
  46. package/dist/cli/service-command-records/storage-rules-lint.d.ts.map +1 -0
  47. package/dist/cli/service-command-records/storage-rules-lint.js +3 -0
  48. package/dist/cli/service-command-records/storage-rules-lint.js.map +1 -0
  49. package/dist/cli/service-command-records/storage-rules-simulate.d.ts +4 -0
  50. package/dist/cli/service-command-records/storage-rules-simulate.d.ts.map +1 -0
  51. package/dist/cli/service-command-records/storage-rules-simulate.js +3 -0
  52. package/dist/cli/service-command-records/storage-rules-simulate.js.map +1 -0
  53. package/dist/cli/service-commands.d.ts +7 -0
  54. package/dist/cli/service-commands.d.ts.map +1 -1
  55. package/dist/cli/service-commands.generated.d.ts +35 -0
  56. package/dist/cli/service-commands.generated.d.ts.map +1 -0
  57. package/dist/cli/service-commands.generated.js +25 -0
  58. package/dist/cli/service-commands.generated.js.map +1 -0
  59. package/dist/cli/service-commands.js +23 -40
  60. package/dist/cli/service-commands.js.map +1 -1
  61. package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
  62. package/dist/conformance/.generated/can-i-use-browser.js +1 -1
  63. package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
  64. package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
  65. package/dist/conformance/.generated/can-i-use.js +1 -1
  66. package/dist/conformance/.generated/can-i-use.js.map +1 -1
  67. package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
  68. package/dist/conformance/.generated/conformance-docs.js +1 -1
  69. package/dist/conformance/.generated/conformance-docs.js.map +1 -1
  70. package/dist/functions-rtdb/development-runtime.d.ts +63 -0
  71. package/dist/functions-rtdb/development-runtime.d.ts.map +1 -0
  72. package/dist/functions-rtdb/development-runtime.js +244 -0
  73. package/dist/functions-rtdb/development-runtime.js.map +1 -0
  74. package/dist/serve/bridge-mount.d.ts +32 -2
  75. package/dist/serve/bridge-mount.d.ts.map +1 -1
  76. package/dist/serve/bridge-mount.js +232 -18
  77. package/dist/serve/bridge-mount.js.map +1 -1
  78. package/dist/serve/bundler.d.ts +2 -18
  79. package/dist/serve/bundler.d.ts.map +1 -1
  80. package/dist/serve/bundler.js +7 -35
  81. package/dist/serve/bundler.js.map +1 -1
  82. package/dist/serve/entries/app-client.d.ts.map +1 -1
  83. package/dist/serve/entries/app-client.js +5 -5
  84. package/dist/serve/entries/app-client.js.map +1 -1
  85. package/dist/serve/entries/auth-helper-core.d.ts +23 -6
  86. package/dist/serve/entries/auth-helper-core.d.ts.map +1 -1
  87. package/dist/serve/entries/auth-helper-core.js +55 -24
  88. package/dist/serve/entries/auth-helper-core.js.map +1 -1
  89. package/dist/serve/entries/database.d.ts +28 -0
  90. package/dist/serve/entries/database.d.ts.map +1 -1
  91. package/dist/serve/entries/database.js +95 -26
  92. package/dist/serve/entries/database.js.map +1 -1
  93. package/dist/serve/entries/init.d.ts.map +1 -1
  94. package/dist/serve/entries/init.js +21 -12
  95. package/dist/serve/entries/init.js.map +1 -1
  96. package/dist/serve/html-injection.d.ts +5 -0
  97. package/dist/serve/html-injection.d.ts.map +1 -0
  98. package/dist/serve/html-injection.js +59 -0
  99. package/dist/serve/html-injection.js.map +1 -0
  100. package/dist/serve/namespace.d.ts +6 -22
  101. package/dist/serve/namespace.d.ts.map +1 -1
  102. package/dist/serve/namespace.js +23 -145
  103. package/dist/serve/namespace.js.map +1 -1
  104. package/dist/serve/runtime/worker-replacement.d.ts +1 -2
  105. package/dist/serve/runtime/worker-replacement.d.ts.map +1 -1
  106. package/dist/serve/sandbox-session.d.ts +78 -0
  107. package/dist/serve/sandbox-session.d.ts.map +1 -0
  108. package/dist/serve/sandbox-session.js +171 -0
  109. package/dist/serve/sandbox-session.js.map +1 -0
  110. package/dist/serve/server.d.ts +5 -2
  111. package/dist/serve/server.d.ts.map +1 -1
  112. package/dist/serve/server.js +21 -5
  113. package/dist/serve/server.js.map +1 -1
  114. package/dist/serve/site-tree.d.ts +8 -0
  115. package/dist/serve/site-tree.d.ts.map +1 -0
  116. package/dist/serve/site-tree.js +113 -0
  117. package/dist/serve/site-tree.js.map +1 -0
  118. package/dist/serve/site-ui/_astro/RulesCodeEditor.CzwHdCi9.js +23 -0
  119. package/dist/serve/site-ui/_astro/_example_.jevZ7OdV.css +1 -0
  120. package/dist/serve/site-ui/_astro/_slug_.BoKXYrnu.css +1 -0
  121. package/dist/serve/site-ui/_astro/_studio_.BtYpqe1A.css +1 -0
  122. package/dist/serve/site-ui/_astro/app.BnMC0ywl.js +109 -0
  123. package/dist/serve/site-ui/_astro/app.BsFsMjn0.css +1 -0
  124. package/dist/serve/site-ui/_astro/app.DVXXR-WI.js +1 -0
  125. package/dist/serve/site-ui/_astro/chess-showcase.DzPO6kz0.js +1 -0
  126. package/dist/serve/site-ui/_astro/chess-source-explorer.C5k9c5yK.js +1 -0
  127. package/dist/serve/site-ui/_astro/chess-v2.CFHmd3UL.js +354 -0
  128. package/dist/serve/site-ui/_astro/client.D2ORs4B-.js +25 -0
  129. package/dist/serve/site-ui/_astro/example-runtime.CM0H02rx.js +291 -0
  130. package/dist/serve/site-ui/_astro/index.B4Kh80he.js +1 -0
  131. package/dist/serve/site-ui/_astro/index.DBy5LfQW.js +9 -0
  132. package/dist/serve/site-ui/_astro/index.DNyk7q8W.js +9 -0
  133. package/dist/serve/site-ui/_astro/jsx-runtime.D_zvdyIk.js +9 -0
  134. package/dist/serve/site-ui/_astro/reads.D1exkX1-.js +1 -0
  135. package/dist/serve/site-ui/_astro/sandbox-controls.BqMePr5V.js +1153 -0
  136. package/dist/serve/site-ui/_astro/seed.BCn5DhHS.js +20 -0
  137. package/dist/serve/site-ui/auth/index.html +11 -0
  138. package/dist/serve/site-ui/docs/_rhythm/index.html +100 -0
  139. package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +43 -0
  140. package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +26 -0
  141. package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +70 -0
  142. package/dist/serve/{docs-ui → site-ui}/docs/ai-compat/index.html +3 -3
  143. package/dist/serve/site-ui/docs/api-reference/index.html +68 -0
  144. package/dist/serve/{docs-ui → site-ui}/docs/app-compat/index.html +3 -3
  145. package/dist/serve/{docs-ui → site-ui}/docs/auth-compat/index.html +3 -3
  146. package/dist/serve/site-ui/docs/build/ai-logic/index.html +64 -0
  147. package/dist/serve/site-ui/docs/build/authentication/index.html +66 -0
  148. package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +84 -0
  149. package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +71 -0
  150. package/dist/serve/site-ui/docs/build/cloud-storage/index.html +66 -0
  151. package/dist/serve/{docs-ui → site-ui}/docs/build/cloud-storage.md +2 -2
  152. package/dist/serve/site-ui/docs/build/realtime-database/index.html +67 -0
  153. package/dist/serve/site-ui/docs/conformance-scores/index.html +50 -0
  154. package/dist/serve/{docs-ui → site-ui}/docs/conformance-scores.md +3 -3
  155. package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +531 -0
  156. package/dist/serve/{docs-ui → site-ui}/docs/database-compat/index.html +211 -168
  157. package/dist/serve/{docs-ui → site-ui}/docs/database-compat.md +208 -170
  158. package/dist/serve/site-ui/docs/examples/chess/index.html +384 -0
  159. package/dist/serve/site-ui/docs/examples/chess.md +57 -0
  160. package/dist/serve/site-ui/docs/examples/index.html +3 -0
  161. package/dist/serve/site-ui/docs/examples.md +4 -0
  162. package/dist/serve/{docs-ui → site-ui}/docs/firestore-compat/index.html +55 -91
  163. package/dist/serve/{docs-ui → site-ui}/docs/firestore-compat.md +52 -88
  164. package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +73 -0
  165. package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +29 -0
  166. package/dist/serve/site-ui/docs/get-started/start-building/index.html +33 -0
  167. package/dist/serve/{docs-ui → site-ui}/docs/index.json +595 -26
  168. package/dist/serve/site-ui/docs/messaging-compat/index.html +324 -0
  169. package/dist/serve/{docs-ui → site-ui}/docs/messaging-compat.md +71 -1
  170. package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +28 -0
  171. package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +74 -0
  172. package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +45 -0
  173. package/dist/serve/site-ui/docs/overview/index.html +17 -0
  174. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +186 -0
  175. package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-auth-reference-api/index.html +4 -4
  176. package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-database-reference-api/index.html +4 -4
  177. package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-firestore-reference-api/index.html +318 -202
  178. package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-firestore-reference-api.md +154 -27
  179. package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-messaging-reference-api/index.html +5 -5
  180. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +318 -0
  181. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ai-reference-api/index.html +5 -5
  182. package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +160 -0
  183. package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +425 -0
  184. package/dist/serve/{docs-ui → site-ui}/docs/pyric-auth-reference-api/index.html +5 -5
  185. package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +60 -0
  186. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-assurance-reference-api/index.html +4 -4
  187. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-bridge-client-reference-api/index.html +4 -4
  188. package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +507 -0
  189. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +258 -0
  190. package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +51 -0
  191. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +308 -0
  192. package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +68 -0
  193. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-discover-reference-api/index.html +4 -4
  194. package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +11 -0
  195. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-remote-reference-api/index.html +4 -4
  196. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-serve-worker-reference-api/index.html +1186 -1384
  197. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-serve-worker-reference-api.md +817 -1291
  198. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-verify-reference-api/index.html +4 -4
  199. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +126 -0
  200. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-vite-reference-api.md +1 -1
  201. package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +2641 -0
  202. package/dist/serve/{docs-ui → site-ui}/docs/pyric-database-reference-api.md +1055 -158
  203. package/dist/serve/{docs-ui → site-ui}/docs/pyric-firestore-reference-api/index.html +311 -249
  204. package/dist/serve/{docs-ui → site-ui}/docs/pyric-firestore-reference-api.md +72 -54
  205. package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +509 -0
  206. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +182 -0
  207. package/dist/serve/{docs-ui → site-ui}/docs/pyric-rules-reference-api/index.html +7 -26
  208. package/dist/serve/{docs-ui → site-ui}/docs/pyric-rules-reference-api.md +13 -23
  209. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +121 -0
  210. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +203 -0
  211. package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-reference-api/index.html +26 -5
  212. package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-reference-api.md +22 -22
  213. package/dist/serve/{docs-ui → site-ui}/docs/pyric-storage-reference-api/index.html +5 -15
  214. package/dist/serve/{docs-ui → site-ui}/docs/pyric-storage-reference-api.md +0 -13
  215. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +639 -0
  216. package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +100 -0
  217. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-auth-reference-api/index.html +4 -4
  218. package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +24 -0
  219. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-events-reference-api/index.html +4 -4
  220. package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +136 -0
  221. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-firestore-reference-api/index.html +7 -7
  222. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-firestore-reference-api.md +4 -4
  223. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-primitives-reference-api/index.html +4 -4
  224. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rtdb-reference-api/index.html +4 -4
  225. package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +16 -0
  226. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rules-reference-api/index.html +4 -4
  227. package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +176 -0
  228. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-storage-reference-api/index.html +10 -11
  229. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-storage-reference-api.md +7 -8
  230. package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +188 -0
  231. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-traffic-reference-api/index.html +4 -4
  232. package/dist/serve/{docs-ui → site-ui}/docs/rules-compat/index.html +87 -57
  233. package/dist/serve/{docs-ui → site-ui}/docs/rules-compat.md +84 -54
  234. package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +51 -0
  235. package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +106 -0
  236. package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +41 -0
  237. package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +67 -0
  238. package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +159 -0
  239. package/dist/serve/{docs-ui → site-ui}/docs/secure/rules-standard-library.md +2 -2
  240. package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +47 -0
  241. package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +95 -0
  242. package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +82 -0
  243. package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +37 -0
  244. package/dist/serve/site-ui/docs/ship/test-in-node/index.html +75 -0
  245. package/dist/serve/{docs-ui → site-ui}/docs/storage-compat/index.html +8 -8
  246. package/dist/serve/{docs-ui → site-ui}/docs/storage-compat.md +5 -5
  247. package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +132 -0
  248. package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +861 -0
  249. package/dist/serve/site-ui/docs/trust/rules-standard-library.md +344 -0
  250. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +582 -0
  251. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research.md +448 -0
  252. package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +14 -0
  253. package/dist/serve/{docs-ui → site-ui}/docs/tutorial/index.html +4 -4
  254. package/dist/serve/{docs-ui → site-ui}/docs/tutorial.md +1 -1
  255. package/dist/serve/site-ui/examples/chess/index.html +2 -0
  256. package/dist/serve/site-ui/examples/firestore-first-write/index.html +2 -0
  257. package/dist/serve/site-ui/firestore/index.html +11 -0
  258. package/dist/serve/site-ui/index.html +11 -0
  259. package/dist/serve/{docs-ui → site-ui}/llms.txt +6 -2
  260. package/dist/serve/site-ui/rtdb/index.html +11 -0
  261. package/dist/serve/site-ui/settings/index.html +11 -0
  262. package/dist/serve/site-ui/storage/index.html +11 -0
  263. package/dist/serve/site-ui/studio-routes.json +1 -0
  264. package/dist/serve/site-ui/traffic/index.html +11 -0
  265. package/dist/serve/standalone-assets.d.ts +4 -10
  266. package/dist/serve/standalone-assets.d.ts.map +1 -1
  267. package/dist/serve/standalone-assets.js +8 -21
  268. package/dist/serve/standalone-assets.js.map +1 -1
  269. package/dist/serve/vite-functions-development.d.ts +29 -0
  270. package/dist/serve/vite-functions-development.d.ts.map +1 -0
  271. package/dist/serve/vite-functions-development.js +150 -0
  272. package/dist/serve/vite-functions-development.js.map +1 -0
  273. package/dist/serve/vite-generation-bridge.d.ts +17 -0
  274. package/dist/serve/vite-generation-bridge.d.ts.map +1 -0
  275. package/dist/serve/vite-generation-bridge.js +47 -0
  276. package/dist/serve/vite-generation-bridge.js.map +1 -0
  277. package/dist/serve/vite-generation-functions.d.ts +35 -0
  278. package/dist/serve/vite-generation-functions.d.ts.map +1 -0
  279. package/dist/serve/vite-generation-functions.js +46 -0
  280. package/dist/serve/vite-generation-functions.js.map +1 -0
  281. package/dist/serve/vite-generation-middleware.d.ts +10 -0
  282. package/dist/serve/vite-generation-middleware.d.ts.map +1 -0
  283. package/dist/serve/vite-generation-middleware.js +40 -0
  284. package/dist/serve/vite-generation-middleware.js.map +1 -0
  285. package/dist/serve/vite-generation-rules-watch.d.ts +8 -0
  286. package/dist/serve/vite-generation-rules-watch.d.ts.map +1 -0
  287. package/dist/serve/vite-generation-rules-watch.js +33 -0
  288. package/dist/serve/vite-generation-rules-watch.js.map +1 -0
  289. package/dist/serve/vite-module-swap.d.ts +16 -0
  290. package/dist/serve/vite-module-swap.d.ts.map +1 -0
  291. package/dist/serve/vite-module-swap.js +96 -0
  292. package/dist/serve/vite-module-swap.js.map +1 -0
  293. package/dist/serve/vite-page-runtime.d.ts +29 -0
  294. package/dist/serve/vite-page-runtime.d.ts.map +1 -0
  295. package/dist/serve/vite-page-runtime.js +71 -0
  296. package/dist/serve/vite-page-runtime.js.map +1 -0
  297. package/dist/serve/vite-plugin.d.ts +44 -4
  298. package/dist/serve/vite-plugin.d.ts.map +1 -1
  299. package/dist/serve/vite-plugin.js +62 -864
  300. package/dist/serve/vite-plugin.js.map +1 -1
  301. package/dist/serve/vite-sandbox-generation.d.ts +57 -0
  302. package/dist/serve/vite-sandbox-generation.d.ts.map +1 -0
  303. package/dist/serve/vite-sandbox-generation.js +178 -0
  304. package/dist/serve/vite-sandbox-generation.js.map +1 -0
  305. package/dist/serve/worker/client/disconnect.d.ts.map +1 -1
  306. package/dist/serve/worker/client/disconnect.js +2 -0
  307. package/dist/serve/worker/client/disconnect.js.map +1 -1
  308. package/dist/serve/worker/client/handles.d.ts +5 -0
  309. package/dist/serve/worker/client/handles.d.ts.map +1 -1
  310. package/dist/serve/worker/client/handles.js.map +1 -1
  311. package/dist/serve/worker/client/pagehide.d.ts +13 -0
  312. package/dist/serve/worker/client/pagehide.d.ts.map +1 -0
  313. package/dist/serve/worker/client/pagehide.js +19 -0
  314. package/dist/serve/worker/client/pagehide.js.map +1 -0
  315. package/dist/serve/worker/client/rtdb-admin.d.ts +8 -0
  316. package/dist/serve/worker/client/rtdb-admin.d.ts.map +1 -0
  317. package/dist/serve/worker/client/rtdb-admin.js +39 -0
  318. package/dist/serve/worker/client/rtdb-admin.js.map +1 -0
  319. package/dist/serve/worker/client/rtdb-connection-lifecycle.d.ts +15 -0
  320. package/dist/serve/worker/client/rtdb-connection-lifecycle.d.ts.map +1 -0
  321. package/dist/serve/worker/client/rtdb-connection-lifecycle.js +45 -0
  322. package/dist/serve/worker/client/rtdb-connection-lifecycle.js.map +1 -0
  323. package/dist/serve/worker/client/rtdb-controls.d.ts +6 -0
  324. package/dist/serve/worker/client/rtdb-controls.d.ts.map +1 -0
  325. package/dist/serve/worker/client/rtdb-controls.js +8 -0
  326. package/dist/serve/worker/client/rtdb-controls.js.map +1 -0
  327. package/dist/serve/worker/client/rtdb-listeners.d.ts +24 -0
  328. package/dist/serve/worker/client/rtdb-listeners.d.ts.map +1 -0
  329. package/dist/serve/worker/client/rtdb-listeners.js +262 -0
  330. package/dist/serve/worker/client/rtdb-listeners.js.map +1 -0
  331. package/dist/serve/worker/client/rtdb-reads.d.ts +4 -0
  332. package/dist/serve/worker/client/rtdb-reads.d.ts.map +1 -0
  333. package/dist/serve/worker/client/rtdb-reads.js +11 -0
  334. package/dist/serve/worker/client/rtdb-reads.js.map +1 -0
  335. package/dist/serve/worker/client/rtdb-references.d.ts +19 -0
  336. package/dist/serve/worker/client/rtdb-references.d.ts.map +1 -0
  337. package/dist/serve/worker/client/rtdb-references.js +63 -0
  338. package/dist/serve/worker/client/rtdb-references.js.map +1 -0
  339. package/dist/serve/worker/client/rtdb-snapshots.d.ts +20 -0
  340. package/dist/serve/worker/client/rtdb-snapshots.d.ts.map +1 -0
  341. package/dist/serve/worker/client/rtdb-snapshots.js +64 -0
  342. package/dist/serve/worker/client/rtdb-snapshots.js.map +1 -0
  343. package/dist/serve/worker/client/rtdb-transactions.d.ts +14 -0
  344. package/dist/serve/worker/client/rtdb-transactions.d.ts.map +1 -0
  345. package/dist/serve/worker/client/rtdb-transactions.js +34 -0
  346. package/dist/serve/worker/client/rtdb-transactions.js.map +1 -0
  347. package/dist/serve/worker/client/rtdb-writes.d.ts +8 -0
  348. package/dist/serve/worker/client/rtdb-writes.d.ts.map +1 -0
  349. package/dist/serve/worker/client/rtdb-writes.js +65 -0
  350. package/dist/serve/worker/client/rtdb-writes.js.map +1 -0
  351. package/dist/serve/worker/client.d.ts +0 -2
  352. package/dist/serve/worker/client.d.ts.map +1 -1
  353. package/dist/serve/worker/client.js +0 -2
  354. package/dist/serve/worker/client.js.map +1 -1
  355. package/dist/serve/worker/entry.js +2 -2
  356. package/dist/serve/worker/entry.js.map +1 -1
  357. package/dist/serve/worker/host/dispatch.d.ts +2 -0
  358. package/dist/serve/worker/host/dispatch.d.ts.map +1 -1
  359. package/dist/serve/worker/host/dispatch.js +24 -2
  360. package/dist/serve/worker/host/dispatch.js.map +1 -1
  361. package/dist/serve/worker/host/rtdb.d.ts +6 -2
  362. package/dist/serve/worker/host/rtdb.d.ts.map +1 -1
  363. package/dist/serve/worker/host/rtdb.js +224 -2
  364. package/dist/serve/worker/host/rtdb.js.map +1 -1
  365. package/dist/serve/worker/host/studio.d.ts.map +1 -1
  366. package/dist/serve/worker/host/studio.js +2 -0
  367. package/dist/serve/worker/host/studio.js.map +1 -1
  368. package/dist/serve/worker/host/subscriptions.d.ts.map +1 -1
  369. package/dist/serve/worker/host/subscriptions.js +3 -3
  370. package/dist/serve/worker/host/subscriptions.js.map +1 -1
  371. package/dist/serve/worker/host.d.ts +1 -1
  372. package/dist/serve/worker/host.d.ts.map +1 -1
  373. package/dist/serve/worker/host.js +1 -1
  374. package/dist/serve/worker/host.js.map +1 -1
  375. package/dist/serve/worker/index.d.ts +16 -1
  376. package/dist/serve/worker/index.d.ts.map +1 -1
  377. package/dist/serve/worker/index.js +17 -4
  378. package/dist/serve/worker/index.js.map +1 -1
  379. package/dist/serve/worker/protocol.d.ts +57 -0
  380. package/dist/serve/worker/protocol.d.ts.map +1 -1
  381. package/dist/serve/worker/protocol.js.map +1 -1
  382. package/dist/serve/worker/rtdb-value-equality.d.ts +3 -0
  383. package/dist/serve/worker/rtdb-value-equality.d.ts.map +1 -0
  384. package/dist/serve/worker/rtdb-value-equality.js +18 -0
  385. package/dist/serve/worker/rtdb-value-equality.js.map +1 -0
  386. package/dist/serve/worker/serve-init.js +2 -2
  387. package/dist/serve/worker/serve-init.js.map +1 -1
  388. package/dist/serve/worker/service-worker-relay.js +2 -2
  389. package/dist/serve/worker/service-worker-relay.js.map +1 -1
  390. package/package.json +7 -5
  391. package/src/assurance/.generated/conformance-verdicts.ts +120 -75
  392. package/src/cli/serve.ts +215 -307
  393. package/src/cli/service-command-records/database-rules-generate.ts +3 -0
  394. package/src/cli/service-command-records/database-rules-lint.ts +3 -0
  395. package/src/cli/service-command-records/database-rules-simulate.ts +3 -0
  396. package/src/cli/service-command-records/database-rules-validate.ts +3 -0
  397. package/src/cli/service-command-records/firestore-indexes-generate.ts +3 -0
  398. package/src/cli/service-command-records/firestore-rules-lint.ts +3 -0
  399. package/src/cli/service-command-records/firestore-rules-resolve.ts +3 -0
  400. package/src/cli/service-command-records/firestore-rules-simulate.ts +3 -0
  401. package/src/cli/service-command-records/firestore-rules-validate.ts +3 -0
  402. package/src/cli/service-command-records/storage-rules-lint.ts +3 -0
  403. package/src/cli/service-command-records/storage-rules-simulate.ts +3 -0
  404. package/src/cli/service-commands.generated.ts +27 -0
  405. package/src/cli/service-commands.test.ts +43 -0
  406. package/src/cli/service-commands.ts +36 -51
  407. package/src/conformance/.generated/can-i-use-browser.ts +1 -1
  408. package/src/conformance/.generated/can-i-use.ts +1 -1
  409. package/src/conformance/.generated/conformance-docs.ts +1 -1
  410. package/src/functions-rtdb/development-runtime.ts +299 -0
  411. package/src/serve/bridge-mount.ts +253 -19
  412. package/src/serve/bundler.ts +8 -34
  413. package/src/serve/entries/app-client.ts +5 -4
  414. package/src/serve/entries/auth-helper-core.ts +83 -30
  415. package/src/serve/entries/database.ts +180 -57
  416. package/src/serve/entries/init.ts +30 -20
  417. package/src/serve/html-injection.ts +65 -0
  418. package/src/serve/namespace.ts +26 -169
  419. package/src/serve/runtime/worker-replacement.ts +1 -1
  420. package/src/serve/sandbox-session.ts +233 -0
  421. package/src/serve/server.ts +20 -5
  422. package/src/serve/site-tree.ts +146 -0
  423. package/src/serve/standalone-assets.ts +9 -26
  424. package/src/serve/vite-functions-development.ts +201 -0
  425. package/src/serve/vite-generation-bridge.ts +66 -0
  426. package/src/serve/vite-generation-functions.ts +78 -0
  427. package/src/serve/vite-generation-middleware.ts +56 -0
  428. package/src/serve/vite-generation-rules-watch.ts +37 -0
  429. package/src/serve/vite-module-swap.ts +119 -0
  430. package/src/serve/vite-page-runtime.ts +100 -0
  431. package/src/serve/vite-plugin.ts +78 -883
  432. package/src/serve/vite-sandbox-generation.ts +255 -0
  433. package/src/serve/worker/client/disconnect.ts +3 -1
  434. package/src/serve/worker/client/handles.ts +5 -0
  435. package/src/serve/worker/client/pagehide.ts +31 -0
  436. package/src/serve/worker/client/rtdb-admin.ts +74 -0
  437. package/src/serve/worker/client/rtdb-connection-lifecycle.ts +52 -0
  438. package/src/serve/worker/client/rtdb-controls.ts +8 -0
  439. package/src/serve/worker/client/rtdb-listeners.ts +337 -0
  440. package/src/serve/worker/client/rtdb-reads.ts +12 -0
  441. package/src/serve/worker/client/rtdb-references.ts +85 -0
  442. package/src/serve/worker/client/rtdb-snapshots.ts +118 -0
  443. package/src/serve/worker/client/rtdb-transactions.ts +51 -0
  444. package/src/serve/worker/client/rtdb-writes.ts +74 -0
  445. package/src/serve/worker/client.ts +0 -2
  446. package/src/serve/worker/entry.ts +2 -2
  447. package/src/serve/worker/host/dispatch.ts +22 -2
  448. package/src/serve/worker/host/rtdb.ts +243 -2
  449. package/src/serve/worker/host/studio.ts +2 -0
  450. package/src/serve/worker/host/subscriptions.ts +8 -4
  451. package/src/serve/worker/host.ts +1 -1
  452. package/src/serve/worker/index.ts +58 -10
  453. package/src/serve/worker/protocol.ts +23 -2
  454. package/src/serve/worker/rtdb-value-equality.ts +17 -0
  455. package/src/serve/worker/serve-init.ts +2 -2
  456. package/src/serve/worker/service-worker-relay.ts +2 -2
  457. package/dist/serve/docs-ui/_astro/_slug_.DUci-duz.css +0 -1
  458. package/dist/serve/docs-ui/docs/_rhythm/index.html +0 -100
  459. package/dist/serve/docs-ui/docs/agent/set-up-your-agent/index.html +0 -43
  460. package/dist/serve/docs-ui/docs/agent/watch-and-review/index.html +0 -26
  461. package/dist/serve/docs-ui/docs/agent/work-with-an-agent/index.html +0 -70
  462. package/dist/serve/docs-ui/docs/api-reference/index.html +0 -68
  463. package/dist/serve/docs-ui/docs/build/ai-logic/index.html +0 -64
  464. package/dist/serve/docs-ui/docs/build/authentication/index.html +0 -66
  465. package/dist/serve/docs-ui/docs/build/cloud-firestore/index.html +0 -70
  466. package/dist/serve/docs-ui/docs/build/cloud-messaging/index.html +0 -71
  467. package/dist/serve/docs-ui/docs/build/cloud-storage/index.html +0 -66
  468. package/dist/serve/docs-ui/docs/build/realtime-database/index.html +0 -67
  469. package/dist/serve/docs-ui/docs/conformance-scores/index.html +0 -50
  470. package/dist/serve/docs-ui/docs/create-pyric-reference-api/index.html +0 -531
  471. package/dist/serve/docs-ui/docs/functions-rtdb-compat/index.html +0 -73
  472. package/dist/serve/docs-ui/docs/get-started/how-the-swap-works/index.html +0 -29
  473. package/dist/serve/docs-ui/docs/get-started/start-building/index.html +0 -33
  474. package/dist/serve/docs-ui/docs/messaging-compat/index.html +0 -265
  475. package/dist/serve/docs-ui/docs/observe/resolve-runtime-status/index.html +0 -28
  476. package/dist/serve/docs-ui/docs/observe/see-whats-happening/index.html +0 -74
  477. package/dist/serve/docs-ui/docs/observe/shape-your-data/index.html +0 -45
  478. package/dist/serve/docs-ui/docs/overview/index.html +0 -17
  479. package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api/index.html +0 -186
  480. package/dist/serve/docs-ui/docs/pyric-admin-storage-reference-api/index.html +0 -318
  481. package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api/index.html +0 -160
  482. package/dist/serve/docs-ui/docs/pyric-app-reference-api/index.html +0 -425
  483. package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +0 -60
  484. package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api/index.html +0 -507
  485. package/dist/serve/docs-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +0 -258
  486. package/dist/serve/docs-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +0 -51
  487. package/dist/serve/docs-ui/docs/pyric-cli-conformance-reference-api/index.html +0 -308
  488. package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api/index.html +0 -68
  489. package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api/index.html +0 -11
  490. package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api/index.html +0 -126
  491. package/dist/serve/docs-ui/docs/pyric-database-reference-api/index.html +0 -1852
  492. package/dist/serve/docs-ui/docs/pyric-messaging-reference-api/index.html +0 -509
  493. package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api/index.html +0 -182
  494. package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api/index.html +0 -121
  495. package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api/index.html +0 -203
  496. package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api/index.html +0 -639
  497. package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +0 -100
  498. package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api/index.html +0 -24
  499. package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +0 -136
  500. package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +0 -16
  501. package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +0 -176
  502. package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +0 -188
  503. package/dist/serve/docs-ui/docs/secure/audit-your-rules/index.html +0 -51
  504. package/dist/serve/docs-ui/docs/secure/firestore-rules-limits/index.html +0 -106
  505. package/dist/serve/docs-ui/docs/secure/read-a-denial/index.html +0 -41
  506. package/dist/serve/docs-ui/docs/secure/rtdb-rules-in-typescript/index.html +0 -67
  507. package/dist/serve/docs-ui/docs/secure/rules-standard-library/index.html +0 -159
  508. package/dist/serve/docs-ui/docs/secure/secure-it-with-rules/index.html +0 -47
  509. package/dist/serve/docs-ui/docs/secure/simulate-and-lint/index.html +0 -95
  510. package/dist/serve/docs-ui/docs/secure/write-a-rules-test-suite/index.html +0 -82
  511. package/dist/serve/docs-ui/docs/ship/ship-to-production/index.html +0 -37
  512. package/dist/serve/docs-ui/docs/ship/test-in-node/index.html +0 -75
  513. package/dist/serve/docs-ui/docs/trust/how-we-know-it-matches-firebase/index.html +0 -132
  514. package/dist/serve/docs-ui/docs/trust/versioning-and-compatibility/index.html +0 -14
  515. package/dist/serve/docs-ui/index.html +0 -1
  516. package/dist/serve/studio-ui/assets/RulesCodeEditor-BDlH-5lp.js +0 -23
  517. package/dist/serve/studio-ui/assets/index-Bf9SSE8L.js +0 -1218
  518. package/dist/serve/studio-ui/assets/index-BlSGru_r.css +0 -1
  519. package/dist/serve/studio-ui/assets/seed-D_UjxfOU.js +0 -20
  520. package/dist/serve/studio-ui/index.html +0 -32
  521. package/dist/serve/worker/client/rtdb.d.ts +0 -36
  522. package/dist/serve/worker/client/rtdb.d.ts.map +0 -1
  523. package/dist/serve/worker/client/rtdb.js +0 -241
  524. package/dist/serve/worker/client/rtdb.js.map +0 -1
  525. package/src/serve/worker/client/rtdb.ts +0 -311
  526. /package/dist/serve/{docs-ui → site-ui}/404.html +0 -0
  527. /package/dist/serve/{docs-ui → site-ui}/_astro/_slug_.CXh9yTP1.css +0 -0
  528. /package/dist/serve/{docs-ui → site-ui}/docs/_rhythm.md +0 -0
  529. /package/dist/serve/{docs-ui → site-ui}/docs/agent/set-up-your-agent.md +0 -0
  530. /package/dist/serve/{docs-ui → site-ui}/docs/agent/watch-and-review.md +0 -0
  531. /package/dist/serve/{docs-ui → site-ui}/docs/agent/work-with-an-agent.md +0 -0
  532. /package/dist/serve/{docs-ui → site-ui}/docs/ai-compat.md +0 -0
  533. /package/dist/serve/{docs-ui → site-ui}/docs/api-reference.md +0 -0
  534. /package/dist/serve/{docs-ui → site-ui}/docs/app-compat.md +0 -0
  535. /package/dist/serve/{docs-ui → site-ui}/docs/auth-compat.md +0 -0
  536. /package/dist/serve/{docs-ui → site-ui}/docs/build/ai-logic.md +0 -0
  537. /package/dist/serve/{docs-ui → site-ui}/docs/build/authentication.md +0 -0
  538. /package/dist/serve/{docs-ui → site-ui}/docs/build/cloud-firestore.md +0 -0
  539. /package/dist/serve/{docs-ui → site-ui}/docs/build/cloud-messaging.md +0 -0
  540. /package/dist/serve/{docs-ui → site-ui}/docs/build/realtime-database.md +0 -0
  541. /package/dist/serve/{docs-ui → site-ui}/docs/create-pyric-reference-api.md +0 -0
  542. /package/dist/serve/{docs-ui → site-ui}/docs/functions-rtdb-compat.md +0 -0
  543. /package/dist/serve/{docs-ui → site-ui}/docs/get-started/how-the-swap-works.md +0 -0
  544. /package/dist/serve/{docs-ui → site-ui}/docs/get-started/start-building.md +0 -0
  545. /package/dist/serve/{docs-ui → site-ui}/docs/index.html +0 -0
  546. /package/dist/serve/{docs-ui → site-ui}/docs/observe/resolve-runtime-status.md +0 -0
  547. /package/dist/serve/{docs-ui → site-ui}/docs/observe/see-whats-happening.md +0 -0
  548. /package/dist/serve/{docs-ui → site-ui}/docs/observe/shape-your-data.md +0 -0
  549. /package/dist/serve/{docs-ui → site-ui}/docs/overview.md +0 -0
  550. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-app-reference-api.md +0 -0
  551. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-auth-reference-api.md +0 -0
  552. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-database-reference-api.md +0 -0
  553. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-messaging-reference-api.md +0 -0
  554. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-storage-reference-api.md +0 -0
  555. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ai-reference-api.md +0 -0
  556. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ai-scripting-reference-api.md +0 -0
  557. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-app-reference-api.md +0 -0
  558. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-auth-reference-api.md +0 -0
  559. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-assurance-browser-reference-api.md +0 -0
  560. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-assurance-reference-api.md +0 -0
  561. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-bridge-client-reference-api.md +0 -0
  562. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-bridge-reference-api.md +0 -0
  563. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-conformance-browser-reference-api.md +0 -0
  564. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-conformance-docs-reference-api.md +0 -0
  565. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-conformance-reference-api.md +0 -0
  566. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-credentials-node-reference-api.md +0 -0
  567. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-discover-reference-api.md +0 -0
  568. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-register-reference-api.md +0 -0
  569. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-remote-reference-api.md +0 -0
  570. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-verify-reference-api.md +0 -0
  571. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-messaging-reference-api.md +0 -0
  572. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-messaging-sw-reference-api.md +0 -0
  573. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-database-reference-api.md +0 -0
  574. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-firestore-reference-api.md +0 -0
  575. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-agents-reference-api.md +0 -0
  576. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-auth-hooks-reference-api.md +0 -0
  577. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-auth-reference-api.md +0 -0
  578. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-events-hooks-reference-api.md +0 -0
  579. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-events-reference-api.md +0 -0
  580. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-firestore-hooks-reference-api.md +0 -0
  581. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-primitives-reference-api.md +0 -0
  582. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rtdb-reference-api.md +0 -0
  583. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rules-hooks-reference-api.md +0 -0
  584. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rules-reference-api.md +0 -0
  585. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-storage-hooks-reference-api.md +0 -0
  586. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-traffic-hooks-reference-api.md +0 -0
  587. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-traffic-reference-api.md +0 -0
  588. /package/dist/serve/{docs-ui → site-ui}/docs/secure/audit-your-rules.md +0 -0
  589. /package/dist/serve/{docs-ui → site-ui}/docs/secure/firestore-rules-limits.md +0 -0
  590. /package/dist/serve/{docs-ui → site-ui}/docs/secure/read-a-denial.md +0 -0
  591. /package/dist/serve/{docs-ui → site-ui}/docs/secure/rtdb-rules-in-typescript.md +0 -0
  592. /package/dist/serve/{docs-ui → site-ui}/docs/secure/secure-it-with-rules.md +0 -0
  593. /package/dist/serve/{docs-ui → site-ui}/docs/secure/simulate-and-lint.md +0 -0
  594. /package/dist/serve/{docs-ui → site-ui}/docs/secure/write-a-rules-test-suite.md +0 -0
  595. /package/dist/serve/{docs-ui → site-ui}/docs/ship/ship-to-production.md +0 -0
  596. /package/dist/serve/{docs-ui → site-ui}/docs/ship/test-in-node.md +0 -0
  597. /package/dist/serve/{docs-ui → site-ui}/docs/trust/how-we-know-it-matches-firebase.md +0 -0
  598. /package/dist/serve/{docs-ui → site-ui}/docs/trust/versioning-and-compatibility.md +0 -0
  599. /package/dist/serve/{studio-ui → site-ui}/pyric-logo.svg +0 -0
@@ -10,18 +10,18 @@
10
10
  * Bridge routes (`/__pyric/mcp`, `/__pyric/sandbox`) mount here in P2.
11
11
  */
12
12
  import { randomBytes } from 'node:crypto';
13
- import { existsSync, statSync } from 'node:fs';
14
- import { basename, extname, join } from 'node:path';
13
+ import { existsSync } from 'node:fs';
14
+ import { basename, join } from 'node:path';
15
15
  import type { IncomingMessage, ServerResponse } from 'node:http';
16
16
  import type { ActivityIncident } from 'pyric/firestore/internal';
17
17
  import { collectBody } from '../bridge/server/peer.js';
18
18
  import { StateFileError, type StateSection, type StateStore } from './state-store.js';
19
19
  import { createWriterLock, type WriterLock } from './writer-lock.js';
20
20
  import { createStudioRoutes, type StudioRouteOptions } from './studio/index.js';
21
- import { contentTypeFor, pipeFileToResponse, resolveStaticFile, type ServeLogger } from './server.js';
22
- import { SANDBOX_BUILD_MARKER } from './sandbox-marker.js';
21
+ import { pipeFileToResponse, type ServeLogger } from './server.js';
23
22
  import type { InitPayload } from './init-payload.js';
24
23
  import { handleActivity } from './activity-route.js';
24
+ import { createSiteTreeHandler } from './site-tree.js';
25
25
  export type { InitPayload } from './init-payload.js';
26
26
 
27
27
  /**
@@ -34,12 +34,19 @@ export interface ServeEventHub {
34
34
  handle(req: IncomingMessage, res: ServerResponse): void;
35
35
  broadcast(event: string, data: unknown): void;
36
36
  clientCount(): number;
37
+ /** End all open streams. Idempotent; used by host-neutral session cleanup. */
38
+ close(): void;
37
39
  }
38
40
 
39
41
  export function createEventHub(): ServeEventHub {
40
42
  const clients = new Set<ServerResponse>();
43
+ let closed = false;
41
44
  return {
42
45
  handle(req, res) {
46
+ if (closed) {
47
+ res.writeHead(503, { 'content-type': 'text/plain' }).end('sandbox session closed');
48
+ return;
49
+ }
43
50
  res.writeHead(200, {
44
51
  'content-type': 'text/event-stream',
45
52
  'cache-control': 'no-store',
@@ -53,6 +60,7 @@ export function createEventHub(): ServeEventHub {
53
60
  res.on('error', () => clients.delete(res));
54
61
  },
55
62
  broadcast(event, data) {
63
+ if (closed) return;
56
64
  const frame = `event: ${event}\ndata: ${JSON.stringify(data)}\n\n`;
57
65
  for (const res of clients) {
58
66
  try {
@@ -63,6 +71,12 @@ export function createEventHub(): ServeEventHub {
63
71
  }
64
72
  },
65
73
  clientCount: () => clients.size,
74
+ close() {
75
+ if (closed) return;
76
+ closed = true;
77
+ for (const res of clients) res.end();
78
+ clients.clear();
79
+ },
66
80
  };
67
81
  }
68
82
 
@@ -85,22 +99,14 @@ export interface NamespaceOptions {
85
99
  * current fixture JSON (200) or 404 when nothing is captured yet, so the
86
100
  * served worker can re-hydrate its event history on boot after a death. */
87
101
  capture?: { write(json: string): void; read(): string | null };
102
+ /** Unified Astro documentation + Studio tree, built for `/__pyric/ui/`. */
103
+ siteUiDir?: string;
104
+ /** Served SharedWorker epoch stamped only into Studio entry documents. */
105
+ workerVersion?: string;
88
106
  /** `--ui` (Pyric Studio): mounts `/__pyric/workspace` + `/__pyric/projects`
89
107
  * (disk-backed `WorkspaceStore`/`ProjectStore`, plus the SSE watch stream)
90
108
  * that `@pyric/studio`'s `local` mode talks to. */
91
109
  studio?: StudioRouteOptions;
92
- /** `--ui` (Pyric Studio): the dir of the built Studio app, served under
93
- * `/__pyric/ui/`. Resolved by file path in the CLI (@pyric/cli never
94
- * imports `@pyric/studio`). Absent when `--ui` is off or the build is
95
- * missing. */
96
- studioUiDir?: string;
97
- /** `--ui` (Pyric Studio): the built docs site (site-docs), served so the
98
- * Studio Docs tab has local docs without the hosted site. Built with base
99
- * `/__pyric/ui/`, so its output straddles two subtrees under the mount:
100
- * the pages/twins/index.json live under `/__pyric/ui/docs/`, but the shared
101
- * assets live at `/__pyric/ui/_astro/` (Astro's asset dir, at the base
102
- * root — NOT under `docs/`). Both are served from this one dir. */
103
- docsUiDir?: string;
104
110
  /** The OpenAI-compatible upstream `/__pyric/ai-proxy` forwards to
105
111
  * (pyric/ai — cdd-deltas #98.2). Falls back to the
106
112
  * `PYRIC_AI_PROXY_UPSTREAM` env var, then `http://localhost:11434/v1`
@@ -467,6 +473,9 @@ async function handleDenials(
467
473
  export function createPyricNamespace(opts: NamespaceOptions) {
468
474
  const writerLock = createWriterLock();
469
475
  const studioRoutes = opts.studio ? createStudioRoutes(opts.studio) : null;
476
+ const siteTree = opts.siteUiDir
477
+ ? createSiteTreeHandler(opts.siteUiDir, opts.workerVersion)
478
+ : null;
470
479
  const denialThrottle = createDenialThrottle();
471
480
  // Issued once per server boot. The outer static/Vite host guard protects
472
481
  // init.json before this capability is disclosed to the served runtime.
@@ -517,159 +526,7 @@ export function createPyricNamespace(opts: NamespaceOptions) {
517
526
  pipeFileToResponse(file, res);
518
527
  return true;
519
528
  }
520
- // Embedded docs site (site-docs). MUST run BEFORE the general
521
- // `/__pyric/ui/` studio handler below: that handler's SPA fallback answers
522
- // every miss with Studio's index.html, which would swallow docs pages and
523
- // (worse) return HTML for a missing docs asset. Built with base
524
- // `/__pyric/ui/`, the docs output lives in TWO subtrees under the mount —
525
- // pages/twins/index.json under `/__pyric/ui/docs/`, and shared assets at
526
- // `/__pyric/ui/_astro/` (Astro's asset dir sits at the base root, not under
527
- // `docs/`). We claim both; `_astro` is Astro-specific and never collides
528
- // with Studio (Vite emits `/__pyric/ui/assets/`). No SPA fallback here — a
529
- // genuinely missing docs page 404s (a broken doc link must fail loudly, not
530
- // masquerade as another page). Directory-format pages (`<slug>/index.html`)
531
- // and `bunx serve`-style extensionless→trailing-slash redirects are handled
532
- // by resolveStaticFile + the directory redirect below.
533
- if (
534
- opts.docsUiDir &&
535
- (url.pathname === '/__pyric/ui/docs' ||
536
- url.pathname.startsWith('/__pyric/ui/docs/') ||
537
- url.pathname.startsWith('/__pyric/ui/_astro/'))
538
- ) {
539
- const rel = url.pathname.slice('/__pyric/ui'.length) || '/';
540
- // `bunx serve` parity: an extensionless path that names a real directory
541
- // (e.g. `/__pyric/ui/docs` or `/__pyric/ui/docs/<slug>`) redirects to the
542
- // trailing-slash form so the directory's index.html loads with correct
543
- // relative-URL resolution.
544
- if (!rel.endsWith('/') && !extname(rel)) {
545
- const dir = join(opts.docsUiDir, decodeURIComponent(rel));
546
- if (existsSync(dir) && statSync(dir).isDirectory()) {
547
- res.writeHead(301, { location: `${url.pathname}/` }).end();
548
- return true;
549
- }
550
- }
551
- const file = resolveStaticFile(opts.docsUiDir, rel);
552
- if (!file) {
553
- res.writeHead(404).end('not found');
554
- return true;
555
- }
556
- res.writeHead(200, { 'content-type': contentTypeFor(file), 'cache-control': 'no-store' });
557
- pipeFileToResponse(file, res);
558
- return true;
559
- }
560
- if (
561
- opts.studioUiDir &&
562
- (url.pathname === '/__pyric/ui' || url.pathname.startsWith('/__pyric/ui/'))
563
- ) {
564
- // The built Pyric Studio app. Served verbatim (NOT through
565
- // injectServeTags: that import-map/init injection is for sandbox pages,
566
- // not Studio). Studio uses History-API routing under this mount, so any
567
- // path that doesn't resolve to a real file falls back to index.html —
568
- // INCLUDING paths with dots (deep links like /storage/uploads/logo.png).
569
- // Only misses under Vite's content-hashed asset dir stay hard 404s, so a
570
- // broken script/style URL fails loudly instead of returning HTML.
571
- if (url.pathname === '/__pyric/ui') {
572
- res.writeHead(301, { location: '/__pyric/ui/' }).end();
573
- return true;
574
- }
575
- const rel = url.pathname.slice('/__pyric/ui'.length) || '/';
576
- let file = resolveStaticFile(opts.studioUiDir, rel);
577
- if (!file && !rel.startsWith('/assets/')) {
578
- file = resolveStaticFile(opts.studioUiDir, '/index.html');
579
- }
580
- if (!file) {
581
- res.writeHead(404).end('not found');
582
- return true;
583
- }
584
- res.writeHead(200, { 'content-type': contentTypeFor(file), 'cache-control': 'no-store' });
585
- pipeFileToResponse(file, res);
586
- return true;
587
- }
529
+ if (siteTree?.(req, res, url)) return true;
588
530
  return false; // unknown /__pyric/* → caller 404s
589
531
  };
590
532
  }
591
-
592
- // ─── HTML injection ───────────────────────────────────────────────────
593
-
594
- /** The import-map targets. Spec → served URL. */
595
- export function sdkImportMap(): Record<string, string> {
596
- return {
597
- 'firebase/ai': '/__pyric/sdk/ai.js',
598
- 'firebase/app': '/__pyric/sdk/app.js',
599
- 'firebase/auth': '/__pyric/sdk/auth.js',
600
- 'firebase/database': '/__pyric/sdk/database.js',
601
- 'firebase/firestore': '/__pyric/sdk/firestore.js',
602
- 'firebase/messaging': '/__pyric/sdk/messaging.js',
603
- 'firebase/messaging/sw': '/__pyric/sdk/messaging-sw.js',
604
- 'firebase/storage': '/__pyric/sdk/storage.js',
605
- };
606
- }
607
-
608
- /**
609
- * Inject the import map + init script into an HTML document. The import map
610
- * MUST precede any module script that imports a mapped specifier, so both
611
- * tags go at the very start of `<head>` (fallbacks: after `<html>`, else
612
- * prepended). Idempotent — a page already carrying the marker is untouched
613
- * (matters when transformHtml runs over an SPA fallback repeatedly).
614
- */
615
- export function injectServeTags(
616
- html: string,
617
- importMap: Record<string, string> = sdkImportMap(),
618
- workerVersion?: string,
619
- forceInPage = false,
620
- ): string {
621
- const MARKER = 'data-pyric-serve';
622
- if (html.includes(MARKER)) return html;
623
- // A pyric SANDBOX BUILD (`vite build` under the pyricSandbox plugin's sandbox
624
- // mode) already BUNDLES its own runtime + init chunk — injecting the import
625
- // map + /__pyric/sdk/init.js on top would boot a SECOND runtime instance on
626
- // the page (two banners, two bridge peer registrations, races between them).
627
- // The bundle owns the sandbox for a marked page: it fetches
628
- // /__pyric/init.json itself (worker path: the SharedWorker does; in-page
629
- // path: the runtime does) and owns rules hot-reload the same way. The ONLY
630
- // serve-time contribution left is the worker-version staleness stamp, which
631
- // the bundled runtime reads from this meta to warn about a stale
632
- // still-running SharedWorker.
633
- if (html.includes(SANDBOX_BUILD_MARKER)) {
634
- if (!workerVersion || html.includes('pyric-worker-v')) return html;
635
- const meta = `<meta name="pyric-worker-v" content="${workerVersion}" ${MARKER}>`;
636
- const headTag = html.match(/<head[^>]*>/i);
637
- if (headTag && headTag.index !== undefined) {
638
- const at = headTag.index + headTag[0].length;
639
- return html.slice(0, at) + meta + html.slice(at);
640
- }
641
- return meta + html;
642
- }
643
- // Stamp the worker's content hash so the page can DETECT staleness: a live
644
- // SharedWorker survives serve restarts + reloads and can't hot-update, so it
645
- // keeps running old code until every tab of the origin closes. The worker
646
- // name is intentionally STABLE (one backend shared by all tabs), so rather
647
- // than split tabs across versions, `runtime.ts` compares this served hash to
648
- // the running worker's baked hash and warns the user to close all tabs.
649
- const versionMeta = workerVersion
650
- ? `<meta name="pyric-worker-v" content="${workerVersion}" ${MARKER}>`
651
- : '';
652
- // `--bridge`: the MCP bridge peers with the IN-PAGE sandbox, so force the page
653
- // off the default SharedWorker path. Otherwise the agent drives an empty
654
- // in-page sandbox while the app's data lives in the worker. Set before any app
655
- // code runs; mirrors the Vite plugin's transformIndexHtml.
656
- const forceTag = forceInPage
657
- ? `<script ${MARKER}>globalThis.__PYRIC_FORCE_INPAGE__=true;</script>`
658
- : '';
659
- const tags =
660
- versionMeta +
661
- forceTag +
662
- `<script type="importmap" ${MARKER}>${JSON.stringify({ imports: importMap })}</script>` +
663
- `<script type="module" src="/__pyric/sdk/init.js" ${MARKER}></script>`;
664
- const head = html.match(/<head[^>]*>/i);
665
- if (head && head.index !== undefined) {
666
- const at = head.index + head[0].length;
667
- return html.slice(0, at) + tags + html.slice(at);
668
- }
669
- const htmlTag = html.match(/<html[^>]*>/i);
670
- if (htmlTag && htmlTag.index !== undefined) {
671
- const at = htmlTag.index + htmlTag[0].length;
672
- return html.slice(0, at) + tags + html.slice(at);
673
- }
674
- return tags + html;
675
- }
@@ -1,4 +1,4 @@
1
- interface WorkerReplacementOptions {
1
+ export interface WorkerReplacementOptions {
2
2
  targetEpoch: string;
3
3
  retire(): Promise<void>;
4
4
  subscribeReload(listener: (epoch: string) => void): () => void;
@@ -0,0 +1,233 @@
1
+ import { existsSync, readFileSync, rmSync } from 'node:fs';
2
+ import { readFile } from 'node:fs/promises';
3
+ import { join, resolve } from 'node:path';
4
+ import type { IncomingMessage, ServerResponse } from 'node:http';
5
+ import type { ActivityIncident } from 'pyric/firestore/internal';
6
+ import type { FirebaseJson } from '../cli/firebase-json.js';
7
+ import { createCaptureStore, type CaptureStore } from './capture-store.js';
8
+ import type { InitPayload } from './init-payload.js';
9
+ import {
10
+ loadProjectDatabaseRules,
11
+ loadProjectRules,
12
+ loadProjectStorageRules,
13
+ prepareRulesSource,
14
+ rulesHashOf,
15
+ } from './rules.js';
16
+ import { createEventHub, createPyricNamespace } from './namespace.js';
17
+ import { diskProjectStore, diskWorkspace } from './studio/index.js';
18
+ import type { ServeLogger } from './server.js';
19
+ import {
20
+ createStateStore,
21
+ firestoreDocCount,
22
+ STATE_FILE_VERSION,
23
+ type PyricStateFile,
24
+ type StateStore,
25
+ } from './state-store.js';
26
+
27
+ export interface SandboxSessionOptions {
28
+ projectDir: string;
29
+ firebaseConfig: FirebaseJson | null;
30
+ sdk: { dir: string; workerVersion?: string };
31
+ seedFile?: string;
32
+ capture?: boolean;
33
+ persistence?: { fresh?: boolean };
34
+ studio?: false | { siteUiDir?: string };
35
+ bridgeUrl?: () => string | null;
36
+ ai?: InitPayload['ai'];
37
+ aiProxyUpstream?: string;
38
+ logger?: ServeLogger;
39
+ activity?: (incident: ActivityIncident) => void;
40
+ }
41
+
42
+ export interface SandboxSessionSummary {
43
+ rules: {
44
+ firestore: { sourcePath: string | null; hash: string | null };
45
+ database: { sourcePath: string | null; hash: string | null };
46
+ storage: { sourcePath: string | null; hash: string | null };
47
+ };
48
+ persistence: null | {
49
+ path: string;
50
+ backupPath: string;
51
+ restoredDocs: number;
52
+ restoredUsers: number;
53
+ restored: boolean;
54
+ };
55
+ capturePath: string | null;
56
+ seedLabel: string | null;
57
+ seedStaged: boolean;
58
+ studioMounted: boolean;
59
+ }
60
+
61
+ export interface SandboxSession {
62
+ readonly summary: SandboxSessionSummary;
63
+ payload(): InitPayload;
64
+ handle(req: IncomingMessage, res: ServerResponse, url: URL): boolean | Promise<boolean>;
65
+ reloadFirestoreRules(): Promise<RulesReloadResult>;
66
+ close(): Promise<void>;
67
+ }
68
+
69
+ export class SandboxSeedError extends Error {
70
+ constructor(
71
+ readonly kind: 'read' | 'shape',
72
+ readonly path: string,
73
+ readonly detail: string,
74
+ ) {
75
+ super(kind === 'read' ? `failed to read seed ${path}: ${detail}` : `seed must be a JSON object (${detail})`);
76
+ this.name = 'SandboxSeedError';
77
+ }
78
+ }
79
+
80
+ export type RulesReloadResult =
81
+ | { kind: 'not-configured' }
82
+ | { kind: 'reloaded'; rulesHash: string; clients: number }
83
+ | { kind: 'rejected'; error: Error };
84
+
85
+ export async function createSandboxSession(
86
+ options: SandboxSessionOptions,
87
+ ): Promise<SandboxSession> {
88
+ // Preserve the established fail-fast order: Firestore, then RTDB, then
89
+ // Storage. Callers historically surfaced the first error in this sequence.
90
+ const firestore = await loadProjectRules(options.projectDir, options.firebaseConfig);
91
+ const database = await loadProjectDatabaseRules(options.projectDir, options.firebaseConfig);
92
+ const storage = await loadProjectStorageRules(options.projectDir, options.firebaseConfig);
93
+ const live = {
94
+ rules: firestore.rules,
95
+ rulesHash: firestore.rulesHash,
96
+ };
97
+ const events = createEventHub();
98
+ const capture: CaptureStore | undefined = (options.capture ?? true)
99
+ ? createCaptureStore(options.projectDir)
100
+ : undefined;
101
+ const state: StateStore | undefined = options.persistence
102
+ ? createStateStore(options.projectDir)
103
+ : undefined;
104
+ if (state && options.persistence?.fresh) {
105
+ for (const file of [state.path, state.backupPath]) {
106
+ if (existsSync(file)) rmSync(file);
107
+ }
108
+ }
109
+ let persisted = state?.load() ?? null;
110
+ let seed: Record<string, Record<string, unknown>> | null = null;
111
+ let seedState: unknown | null = null;
112
+ let seedUsers: Record<string, unknown>[] | null = null;
113
+ let seedLabel: string | null = null;
114
+ if (options.seedFile) {
115
+ const seedPath = resolve(options.projectDir, options.seedFile);
116
+ let parsed: unknown;
117
+ try {
118
+ parsed = JSON.parse(readFileSync(seedPath, 'utf8')) as unknown;
119
+ } catch (error) {
120
+ throw new SandboxSeedError('read', seedPath, error instanceof Error ? error.message : String(error));
121
+ }
122
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
123
+ throw new SandboxSeedError('shape', seedPath, `got ${Array.isArray(parsed) ? 'array' : typeof parsed}`);
124
+ }
125
+ const record = parsed as Record<string, unknown>;
126
+ if (record.version === STATE_FILE_VERSION && ('firestore' in record || 'auth' in record)) {
127
+ const fixture = record as unknown as PyricStateFile;
128
+ const restoredDocs = firestoreDocCount(fixture.firestore);
129
+ const restoredUsers = fixture.auth?.users?.length ?? 0;
130
+ seedLabel = `${restoredDocs} doc(s) + ${restoredUsers} user(s) from state fixture`;
131
+ if (state && !state.exists()) {
132
+ if (fixture.firestore != null) state.writeSection('firestore', fixture.firestore);
133
+ if (fixture.auth != null) state.writeSection('auth', fixture.auth);
134
+ persisted = state.load();
135
+ } else if (!state) {
136
+ seedState = fixture.firestore ?? null;
137
+ seedUsers = (fixture.auth?.users as Record<string, unknown>[] | undefined) ?? null;
138
+ }
139
+ } else {
140
+ seed = record as Record<string, Record<string, unknown>>;
141
+ seedLabel = `${Object.keys(seed).length} document(s)`;
142
+ }
143
+ }
144
+
145
+ const payload = (): InitPayload => ({
146
+ rules: live.rules,
147
+ rulesHash: live.rulesHash,
148
+ databaseRules: database.rules,
149
+ databaseRulesHash: database.rulesHash,
150
+ databaseUrl: database.databaseUrl,
151
+ storageRules: storage.rules,
152
+ storageRulesHash: storage.rulesHash,
153
+ projectKey: options.projectDir,
154
+ bridgeUrl: options.bridgeUrl?.() ?? null,
155
+ seed: state?.exists() ? null : seed,
156
+ seedState,
157
+ persist: Boolean(state),
158
+ capture: Boolean(capture),
159
+ authUsers: state
160
+ ? ((state.readSection('auth') as { users?: Record<string, unknown>[] } | null)?.users ?? null)
161
+ : seedUsers,
162
+ messaging: true,
163
+ ai: options.ai ?? null,
164
+ });
165
+
166
+ const summary: SandboxSessionSummary = {
167
+ rules: {
168
+ firestore: { sourcePath: firestore.sourcePath, hash: firestore.rulesHash },
169
+ database: { sourcePath: database.sourcePath, hash: database.rulesHash },
170
+ storage: { sourcePath: storage.sourcePath, hash: storage.rulesHash },
171
+ },
172
+ persistence: state
173
+ ? {
174
+ path: state.path,
175
+ backupPath: state.backupPath,
176
+ restoredDocs: firestoreDocCount(persisted?.firestore),
177
+ restoredUsers: persisted?.auth?.users?.length ?? 0,
178
+ restored: persisted !== null,
179
+ }
180
+ : null,
181
+ capturePath: capture?.path ?? null,
182
+ seedLabel,
183
+ seedStaged: Boolean((seed && !state?.exists()) || seedState || seedUsers),
184
+ studioMounted: Boolean(options.studio),
185
+ };
186
+
187
+ const namespace = createPyricNamespace({
188
+ sdkDir: options.sdk.dir,
189
+ initPayload: payload,
190
+ events,
191
+ state,
192
+ capture,
193
+ studio: options.studio
194
+ ? {
195
+ workspace: diskWorkspace(options.projectDir),
196
+ projects: diskProjectStore(join(options.projectDir, '.pyric', 'projects')),
197
+ }
198
+ : undefined,
199
+ siteUiDir: options.studio ? options.studio.siteUiDir : undefined,
200
+ workerVersion: options.sdk.workerVersion,
201
+ aiProxyUpstream: options.aiProxyUpstream,
202
+ activity: options.activity,
203
+ logger: options.logger,
204
+ });
205
+
206
+ const reloadFirestoreRules = async (): Promise<RulesReloadResult> => {
207
+ if (!firestore.sourcePath) return { kind: 'not-configured' };
208
+ try {
209
+ const raw = await readFile(firestore.sourcePath, 'utf8');
210
+ const rules = prepareRulesSource(raw, firestore.sourcePath);
211
+ const rulesHash = rulesHashOf(rules);
212
+ live.rules = rules;
213
+ live.rulesHash = rulesHash;
214
+ events.broadcast('rules-changed', { rules, rulesHash });
215
+ return { kind: 'reloaded', rulesHash, clients: events.clientCount() };
216
+ } catch (error) {
217
+ return { kind: 'rejected', error: error instanceof Error ? error : new Error(String(error)) };
218
+ }
219
+ };
220
+ let closePromise: Promise<void> | null = null;
221
+ const close = (): Promise<void> => {
222
+ closePromise ??= Promise.resolve().then(() => events.close());
223
+ return closePromise;
224
+ };
225
+
226
+ return {
227
+ summary,
228
+ payload,
229
+ handle: namespace,
230
+ reloadFirestoreRules,
231
+ close,
232
+ };
233
+ }
@@ -173,14 +173,29 @@ export function contentTypeFor(path: string): string {
173
173
  return CONTENT_TYPES[extname(path).toLowerCase()] ?? 'application/octet-stream';
174
174
  }
175
175
 
176
- /** Resolve a request path inside `publicDir`, refusing traversal. Returns
177
- * null when the path escapes the root or doesn't exist as a file. */
178
- export function resolveStaticFile(publicDir: string, pathname: string): string | null {
179
- const decoded = decodeURIComponent(pathname);
176
+ /** Decode a URL pathname for static-file lookup. Malformed escapes are misses. */
177
+ export function decodeStaticPathname(pathname: string): string | null {
178
+ try {
179
+ return decodeURIComponent(pathname);
180
+ } catch {
181
+ return null;
182
+ }
183
+ }
184
+
185
+ /** Resolve a request path inside `publicDir`, refusing malformed or escaping paths. */
186
+ export function resolveStaticPath(publicDir: string, pathname: string): string | null {
187
+ const decoded = decodeStaticPathname(pathname);
188
+ if (decoded === null) return null;
180
189
  const root = resolve(publicDir);
181
190
  const candidate = normalize(join(root, decoded));
182
191
  if (candidate !== root && !candidate.startsWith(root + sep)) return null; // traversal
183
- let file = candidate;
192
+ return candidate;
193
+ }
194
+
195
+ /** Resolve an existing static file inside `publicDir`. */
196
+ export function resolveStaticFile(publicDir: string, pathname: string): string | null {
197
+ let file = resolveStaticPath(publicDir, pathname);
198
+ if (file === null) return null;
184
199
  if (existsSync(file) && statSync(file).isDirectory()) file = join(file, 'index.html');
185
200
  if (!existsSync(file) || !statSync(file).isFile()) return null;
186
201
  return file;
@@ -0,0 +1,146 @@
1
+ import { existsSync, readFileSync, statSync } from 'node:fs';
2
+ import type { IncomingMessage, ServerResponse } from 'node:http';
3
+ import { extname, join } from 'node:path';
4
+ import {
5
+ contentTypeFor,
6
+ decodeStaticPathname,
7
+ pipeFileToResponse,
8
+ resolveStaticFile,
9
+ resolveStaticPath,
10
+ } from './server.js';
11
+
12
+ interface StudioRoutesManifest {
13
+ routes: string[];
14
+ }
15
+
16
+ interface RequestWithOriginalUrl extends IncomingMessage {
17
+ originalUrl?: string;
18
+ }
19
+
20
+ const SITE_TREE_MOUNT_PATH = '/__pyric/ui';
21
+ const SITE_TREE_DESCENDANT_PREFIX = `${SITE_TREE_MOUNT_PATH}/`;
22
+
23
+ function studioRoutesFromSite(root: string): ReadonlySet<string> {
24
+ const manifestPath = join(root, 'studio-routes.json');
25
+ const parsed = JSON.parse(readFileSync(manifestPath, 'utf8')) as StudioRoutesManifest;
26
+ if (!Array.isArray(parsed.routes) || parsed.routes.some((route) => typeof route !== 'string')) {
27
+ throw new Error(`pyric: invalid Studio route manifest at ${manifestPath}`);
28
+ }
29
+ return new Set(parsed.routes);
30
+ }
31
+
32
+ function rawRequestPathname(request: RequestWithOriginalUrl, parsedUrl: URL): string {
33
+ let requestTarget = request.originalUrl;
34
+
35
+ if (requestTarget === undefined) {
36
+ requestTarget = request.url;
37
+ }
38
+
39
+ if (requestTarget === undefined) {
40
+ return parsedUrl.pathname;
41
+ }
42
+
43
+ const queryStringStart = requestTarget.indexOf('?');
44
+
45
+ if (queryStringStart === -1) {
46
+ return requestTarget;
47
+ }
48
+
49
+ return requestTarget.slice(0, queryStringStart);
50
+ }
51
+
52
+ function isSiteTreePath(pathname: string): boolean {
53
+ if (pathname === SITE_TREE_MOUNT_PATH) {
54
+ return true;
55
+ }
56
+
57
+ return pathname.startsWith(SITE_TREE_DESCENDANT_PREFIX);
58
+ }
59
+
60
+ function withWorkerVersion(html: string, workerVersion: string | undefined): string {
61
+ if (!workerVersion || html.includes('name="pyric-worker-v"')) return html;
62
+ if (!/^[a-f0-9]{16}$/.test(workerVersion)) {
63
+ throw new Error(`pyric: invalid SharedWorker epoch '${workerVersion}'`);
64
+ }
65
+ const meta = `<meta name="pyric-worker-v" content="${workerVersion}" data-pyric-serve>`;
66
+ const head = html.match(/<head[^>]*>/i);
67
+ if (!head || head.index === undefined) return meta + html;
68
+ const at = head.index + head[0].length;
69
+ return html.slice(0, at) + meta + html.slice(at);
70
+ }
71
+
72
+ /** Serve the one Astro tree with SPA fallback limited to generated Studio entries. */
73
+ export function createSiteTreeHandler(root: string, workerVersion?: string) {
74
+ const studioRoutes = studioRoutesFromSite(root);
75
+
76
+ return (
77
+ req: RequestWithOriginalUrl,
78
+ res: ServerResponse,
79
+ url: URL,
80
+ ): boolean => {
81
+ // URL parsing normalizes encoded dot segments before `url.pathname`
82
+ // reaches us. Route and validate against the raw request target so an
83
+ // encoded traversal cannot cross from Studio into docs or static assets.
84
+ // Connect preserves that target in `originalUrl` after stripping a mount
85
+ // prefix from `url`.
86
+ const rawPathname = rawRequestPathname(req, url);
87
+ if (!isSiteTreePath(rawPathname)) {
88
+ return false;
89
+ }
90
+ if (rawPathname === SITE_TREE_MOUNT_PATH) {
91
+ res.writeHead(301, { location: SITE_TREE_DESCENDANT_PREFIX }).end();
92
+ return true;
93
+ }
94
+
95
+ let relativePath = rawPathname.slice(SITE_TREE_MOUNT_PATH.length);
96
+
97
+ if (relativePath === '') {
98
+ relativePath = '/';
99
+ }
100
+
101
+ const decodedRel = decodeStaticPathname(relativePath);
102
+ if (decodedRel === null || decodedRel.includes('\\')) {
103
+ res.writeHead(404).end('not found');
104
+ return true;
105
+ }
106
+ const decodedSegments = decodedRel.split('/').filter(Boolean);
107
+ if (decodedSegments.some((segment) => segment === '.' || segment === '..')) {
108
+ res.writeHead(404).end('not found');
109
+ return true;
110
+ }
111
+ if (!relativePath.endsWith('/') && !extname(relativePath)) {
112
+ const dir = resolveStaticPath(root, relativePath);
113
+ if (dir && existsSync(dir) && statSync(dir).isDirectory()) {
114
+ res.writeHead(301, { location: `${rawPathname}/` }).end();
115
+ return true;
116
+ }
117
+ }
118
+
119
+ const first = decodedSegments[0];
120
+ const studioRequest = first === undefined || studioRoutes.has(first);
121
+ let file = resolveStaticFile(root, relativePath);
122
+ // Storage object names commonly contain extensions (logo.png), while the
123
+ // other Studio routes reserve extension-bearing misses for static assets.
124
+ const allowsDottedState = first === 'storage';
125
+ const hasDottedStateSegment = decodedSegments
126
+ .slice(1)
127
+ .some((segment) => segment.includes('.'));
128
+ if (!file && studioRequest && (allowsDottedState || !hasDottedStateSegment)) {
129
+ const entry = first === undefined ? '/index.html' : `/${first}/index.html`;
130
+ file = resolveStaticFile(root, entry);
131
+ }
132
+ if (!file) {
133
+ res.writeHead(404).end('not found');
134
+ return true;
135
+ }
136
+
137
+ const contentType = contentTypeFor(file);
138
+ res.writeHead(200, { 'content-type': contentType, 'cache-control': 'no-store' });
139
+ if (studioRequest && contentType.includes('text/html')) {
140
+ res.end(withWorkerVersion(readFileSync(file, 'utf8'), workerVersion));
141
+ } else {
142
+ pipeFileToResponse(file, res);
143
+ }
144
+ return true;
145
+ };
146
+ }