@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
@@ -0,0 +1,299 @@
1
+ import type { ChildProcess } from 'node:child_process';
2
+ import {
3
+ spawnFunctionsRtdbChild,
4
+ type FunctionsRtdbChildEvent,
5
+ type FunctionsRtdbChildHandle,
6
+ type FunctionsRtdbChildReady,
7
+ type SpawnFunctionsRtdbChildOptions,
8
+ } from './child.js';
9
+ import { buildChildEnv, createLinePrefixer } from '../cli/dev-runner.js';
10
+
11
+ const INITIAL_PEER_TIMEOUT_MS = 30_000;
12
+ const RELOAD_PEER_TIMEOUT_MS = 5_000;
13
+ const PEER_POLL_INTERVAL_MS = 250;
14
+
15
+ export interface FunctionsPeerReadiness {
16
+ wait(options: { timeoutMs: number; signal: AbortSignal }): Promise<boolean>;
17
+ }
18
+
19
+ export type FunctionsDevelopmentResult =
20
+ | { kind: 'ready'; ready: FunctionsRtdbChildReady }
21
+ | { kind: 'no-peer' }
22
+ | { kind: 'failed'; error: Error };
23
+
24
+ export type FunctionsDevelopmentEvent =
25
+ | { type: 'child-event'; event: FunctionsRtdbChildEvent }
26
+ | { type: 'output'; stream: 'stdout' | 'stderr'; line: string }
27
+ | { type: 'unexpected-exit'; code: number };
28
+
29
+ export interface FunctionsDevelopmentRuntime {
30
+ start(): Promise<FunctionsDevelopmentResult>;
31
+ reload(): Promise<FunctionsDevelopmentResult>;
32
+ close(): Promise<void>;
33
+ }
34
+
35
+ export interface FunctionsDevelopmentRuntimeOptions {
36
+ sourceDir: string;
37
+ entry: string;
38
+ baseEnv: NodeJS.ProcessEnv;
39
+ serveUrl: string;
40
+ registerUrl: string;
41
+ instance: string;
42
+ location: string;
43
+ childModuleUrl?: string | URL;
44
+ readiness: FunctionsPeerReadiness;
45
+ onEvent?(event: FunctionsDevelopmentEvent): void;
46
+ /** Internal test seam; production adapters use the real isolated child. */
47
+ spawn?(options: SpawnFunctionsRtdbChildOptions): FunctionsRtdbChildHandle;
48
+ initialPeerTimeoutMs?: number;
49
+ reloadPeerTimeoutMs?: number;
50
+ }
51
+
52
+ function abortableDelay(ms: number, signal: AbortSignal): Promise<void> {
53
+ if (signal.aborted) return Promise.resolve();
54
+ return new Promise((resolve) => {
55
+ const timer = setTimeout(done, ms);
56
+ function done(): void {
57
+ clearTimeout(timer);
58
+ signal.removeEventListener('abort', done);
59
+ resolve();
60
+ }
61
+ signal.addEventListener('abort', done, { once: true });
62
+ });
63
+ }
64
+
65
+ function settleBeforeAbort<T>(operation: Promise<T>, signal: AbortSignal): Promise<T> {
66
+ if (signal.aborted) return Promise.reject(signal.reason);
67
+ return new Promise<T>((resolve, reject) => {
68
+ const onAbort = (): void => {
69
+ cleanup();
70
+ reject(signal.reason);
71
+ };
72
+ const cleanup = (): void => signal.removeEventListener('abort', onAbort);
73
+ signal.addEventListener('abort', onAbort, { once: true });
74
+ operation.then(
75
+ (value) => { cleanup(); resolve(value); },
76
+ (error) => { cleanup(); reject(error); },
77
+ );
78
+ });
79
+ }
80
+
81
+ export function createInProcessFunctionsPeerReadiness(
82
+ connected: () => boolean,
83
+ options: { intervalMs?: number; now?: () => number; sleep?: typeof abortableDelay } = {},
84
+ ): FunctionsPeerReadiness {
85
+ const intervalMs = options.intervalMs ?? PEER_POLL_INTERVAL_MS;
86
+ const now = options.now ?? Date.now;
87
+ const sleep = options.sleep ?? abortableDelay;
88
+ return {
89
+ async wait({ timeoutMs, signal }) {
90
+ const deadline = now() + timeoutMs;
91
+ while (!signal.aborted) {
92
+ if (connected()) return true;
93
+ if (now() >= deadline) return false;
94
+ await sleep(intervalMs, signal);
95
+ }
96
+ return false;
97
+ },
98
+ };
99
+ }
100
+
101
+ export function createHttpFunctionsPeerReadiness(
102
+ serveUrl: string,
103
+ options: {
104
+ intervalMs?: number;
105
+ fetchImpl?: typeof fetch;
106
+ now?: () => number;
107
+ sleep?: typeof abortableDelay;
108
+ } = {},
109
+ ): FunctionsPeerReadiness {
110
+ const baseUrl = serveUrl.replace(/\/$/, '');
111
+ const fetchImpl = options.fetchImpl ?? fetch;
112
+ const intervalMs = options.intervalMs ?? PEER_POLL_INTERVAL_MS;
113
+ const now = options.now ?? Date.now;
114
+ const sleep = options.sleep ?? abortableDelay;
115
+ return {
116
+ async wait({ timeoutMs, signal }) {
117
+ const deadline = now() + timeoutMs;
118
+ const deadlineAbort = new AbortController();
119
+ const deadlineTimer = setTimeout(() => deadlineAbort.abort(), timeoutMs);
120
+ deadlineTimer.unref();
121
+ const waitSignal = AbortSignal.any([signal, deadlineAbort.signal]);
122
+ try {
123
+ while (!waitSignal.aborted) {
124
+ try {
125
+ const response = await settleBeforeAbort(
126
+ fetchImpl(`${baseUrl}/__pyric/health`, { signal: waitSignal }),
127
+ waitSignal,
128
+ );
129
+ if (response.ok) {
130
+ const health = await settleBeforeAbort(
131
+ response.json() as Promise<{ sandboxConnected?: boolean }>,
132
+ waitSignal,
133
+ );
134
+ if (health.sandboxConnected === true) return true;
135
+ }
136
+ } catch {
137
+ if (waitSignal.aborted) return false;
138
+ }
139
+ if (now() >= deadline) return false;
140
+ await sleep(intervalMs, waitSignal);
141
+ }
142
+ return false;
143
+ } finally {
144
+ clearTimeout(deadlineTimer);
145
+ }
146
+ },
147
+ };
148
+ }
149
+
150
+ function asError(error: unknown): Error {
151
+ return error instanceof Error ? error : new Error(String(error));
152
+ }
153
+
154
+ function attachOutput(
155
+ child: ChildProcess,
156
+ emit: (event: FunctionsDevelopmentEvent) => void,
157
+ ): void {
158
+ const attach = (stream: 'stdout' | 'stderr'): void => {
159
+ const readable = child[stream];
160
+ if (!readable) return;
161
+ const lines = createLinePrefixer('[functions] ', (line) => emit({ type: 'output', stream, line }));
162
+ readable.setEncoding('utf8');
163
+ readable.on('data', (chunk: string) => lines.push(chunk));
164
+ readable.once('end', () => lines.flush());
165
+ };
166
+ attach('stdout');
167
+ attach('stderr');
168
+ }
169
+
170
+ export function createFunctionsDevelopmentRuntime(
171
+ options: FunctionsDevelopmentRuntimeOptions,
172
+ ): FunctionsDevelopmentRuntime {
173
+ const spawn = options.spawn ?? spawnFunctionsRtdbChild;
174
+ const emit = (event: FunctionsDevelopmentEvent): void => options.onEvent?.(event);
175
+ const expectedStops = new WeakSet<FunctionsRtdbChildHandle>();
176
+ let activeChild: FunctionsRtdbChildHandle | null = null;
177
+ let activeWait: AbortController | null = null;
178
+ let closed = false;
179
+ let startPromise: Promise<FunctionsDevelopmentResult> | null = null;
180
+ let reloadPromise: Promise<FunctionsDevelopmentResult> | null = null;
181
+ let reloadQueued = false;
182
+ let closePromise: Promise<void> | null = null;
183
+
184
+ const stopChild = async (child: FunctionsRtdbChildHandle | null): Promise<void> => {
185
+ if (!child) return;
186
+ expectedStops.add(child);
187
+ if (activeChild === child) activeChild = null;
188
+ await child.stop().catch(() => undefined);
189
+ };
190
+
191
+ const launch = async (mode: 'initial' | 'reload'): Promise<FunctionsDevelopmentResult> => {
192
+ const controller = new AbortController();
193
+ activeWait = controller;
194
+ let connected: boolean;
195
+ try {
196
+ connected = await options.readiness.wait({
197
+ timeoutMs: mode === 'initial'
198
+ ? options.initialPeerTimeoutMs ?? INITIAL_PEER_TIMEOUT_MS
199
+ : options.reloadPeerTimeoutMs ?? RELOAD_PEER_TIMEOUT_MS,
200
+ signal: controller.signal,
201
+ });
202
+ } catch (error) {
203
+ if (controller.signal.aborted || closed) return { kind: 'no-peer' };
204
+ return { kind: 'failed', error: asError(error) };
205
+ } finally {
206
+ if (activeWait === controller) activeWait = null;
207
+ }
208
+ if (!connected || closed) return { kind: 'no-peer' };
209
+
210
+ let handle: FunctionsRtdbChildHandle;
211
+ try {
212
+ handle = spawn({
213
+ cwd: options.sourceDir,
214
+ entry: options.entry,
215
+ env: buildChildEnv(options.baseEnv, {
216
+ serveUrl: options.serveUrl,
217
+ registerUrl: options.registerUrl,
218
+ }),
219
+ instance: options.instance,
220
+ location: options.location,
221
+ ...(options.childModuleUrl === undefined ? {} : { childModuleUrl: options.childModuleUrl }),
222
+ onEvent: (event) => emit({ type: 'child-event', event }),
223
+ });
224
+ } catch (error) {
225
+ return { kind: 'failed', error: asError(error) };
226
+ }
227
+
228
+ activeChild = handle;
229
+ attachOutput(handle.child, emit);
230
+ let readyReached = false;
231
+ let exitBeforeReady: number | null = null;
232
+ const reportUnexpectedExit = (code: number): void => {
233
+ if (activeChild === handle && !closed && !expectedStops.has(handle)) {
234
+ activeChild = null;
235
+ emit({ type: 'unexpected-exit', code });
236
+ }
237
+ };
238
+ void handle.exited.then((code) => {
239
+ if (!readyReached) exitBeforeReady = code;
240
+ else reportUnexpectedExit(code);
241
+ });
242
+ try {
243
+ const ready = await handle.ready;
244
+ readyReached = true;
245
+ if (exitBeforeReady !== null) reportUnexpectedExit(exitBeforeReady);
246
+ if (closed) {
247
+ await stopChild(handle);
248
+ return { kind: 'no-peer' };
249
+ }
250
+ return { kind: 'ready', ready };
251
+ } catch (error) {
252
+ await stopChild(handle);
253
+ return { kind: 'failed', error: asError(error) };
254
+ }
255
+ };
256
+
257
+ const runtime: FunctionsDevelopmentRuntime = {
258
+ start() {
259
+ startPromise ??= launch('initial');
260
+ return startPromise;
261
+ },
262
+ reload() {
263
+ if (closed) return Promise.resolve({ kind: 'failed', error: new Error('Functions runtime is closed') });
264
+ reloadQueued = true;
265
+ if (!reloadPromise) {
266
+ reloadPromise = (async (): Promise<FunctionsDevelopmentResult> => {
267
+ let result: FunctionsDevelopmentResult = { kind: 'no-peer' };
268
+ if (startPromise) await startPromise;
269
+ do {
270
+ reloadQueued = false;
271
+ await stopChild(activeChild);
272
+ if (closed) return { kind: 'no-peer' };
273
+ result = await launch('reload');
274
+ } while (reloadQueued && !closed);
275
+ return result;
276
+ })().finally(() => { reloadPromise = null; });
277
+ }
278
+ return reloadPromise as Promise<FunctionsDevelopmentResult>;
279
+ },
280
+ close() {
281
+ if (closePromise) return closePromise;
282
+ closePromise = (async () => {
283
+ closed = true;
284
+ reloadQueued = false;
285
+ activeWait?.abort();
286
+ await stopChild(activeChild);
287
+ await Promise.allSettled([
288
+ ...(startPromise ? [startPromise] : []),
289
+ ...(reloadPromise ? [reloadPromise] : []),
290
+ ]);
291
+ // A transition that crossed the closed check in the same turn may have
292
+ // installed a child after the first capture. The stop is idempotent.
293
+ await stopChild(activeChild);
294
+ })();
295
+ return closePromise;
296
+ },
297
+ };
298
+ return runtime;
299
+ }
@@ -16,7 +16,10 @@
16
16
  * WS /__pyric/sandbox the in-page sandbox peer (server `upgrade`)
17
17
  */
18
18
  import { randomUUID } from 'node:crypto';
19
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
19
20
  import type { IncomingMessage, Server, ServerResponse } from 'node:http';
21
+ import { dirname, join } from 'node:path';
22
+ import type { Duplex } from 'node:stream';
20
23
  import { WebSocketServer, type WebSocket } from 'ws';
21
24
  import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
22
25
  import { createBridge, type BridgeToolEvent } from '../bridge/server/bridge.js';
@@ -48,10 +51,14 @@ export interface BridgeMount {
48
51
  * The pointer writer records this so the proxy can verify it reached this
49
52
  * exact server across a cross-family port collision. */
50
53
  readonly instanceId: string;
54
+ /** Canonical project identity used by health, audit, URLs, and discovery. */
55
+ readonly project: string;
51
56
  /** Namespace-handler tier: returns true when the request was handled. */
52
57
  handler(req: IncomingMessage, res: ServerResponse, url: URL): Promise<boolean>;
53
- /** Attach the WS upgrade listener to the serve server. */
54
- attachUpgrade(server: Server): void;
58
+ /** Attach all bridge-owned host resources and return their explicit owner. */
59
+ attachHost(options: BridgeHostOptions): BridgeHostAttachment;
60
+ /** Close every attachment, peer, and MCP session. Idempotent. */
61
+ close(): Promise<void>;
55
62
  /** Whether a sandbox peer (a browser tab / SharedWorker relay) is currently
56
63
  * connected. In-process callers (the Vite plugin's Functions start) poll
57
64
  * this instead of self-fetching `/__pyric/health`, which avoids a loopback
@@ -63,6 +70,29 @@ export interface BridgeMount {
63
70
  mcpUrl(origin: { host: string; port: number }): string;
64
71
  }
65
72
 
73
+ export interface BridgeHostOptions {
74
+ /** Every server accepting upgrades (static serve may bind both IP families). */
75
+ servers: Server[];
76
+ /** Server whose listen/close lifecycle owns discovery publication. */
77
+ lifecycleServer?: Server;
78
+ projectDir: string;
79
+ /** Returns null until a stable, externally reachable origin is known. */
80
+ origin(): { host: string; port: number } | null;
81
+ /** Defaults true. A host with a broader ordered shutdown can opt out and
82
+ * explicitly close the returned attachment from its own close listener. */
83
+ closeOnServerClose?: boolean;
84
+ /** Vite cannot dual-bind, so its adapter enables the cross-family probe. */
85
+ collision?: {
86
+ warn(message: string, options?: { timestamp?: boolean }): void;
87
+ /** Internal deterministic test seam. */
88
+ fetchImpl?: typeof fetch;
89
+ };
90
+ }
91
+
92
+ export interface BridgeHostAttachment {
93
+ close(): Promise<void>;
94
+ }
95
+
66
96
  export function createBridgeMount(opts: BridgeMountOptions = {}): BridgeMount {
67
97
  const project = opts.project ?? 'sandbox';
68
98
  const auditWriter = opts.disableAuditLog ? null : createAuditWriter(project);
@@ -87,19 +117,30 @@ export function createBridgeMount(opts: BridgeMountOptions = {}): BridgeMount {
87
117
  close: () => Promise<void>;
88
118
  idle: ReturnType<typeof setTimeout> | null;
89
119
  sessionId: string | null;
120
+ closing: Promise<void> | null;
90
121
  };
91
122
  const sessions = new Map<string, Session>();
123
+ const pendingSessions = new Set<Session>();
124
+ const attachments = new Set<BridgeHostAttachment>();
125
+ let closed = false;
126
+ let closePromise: Promise<void> | null = null;
92
127
 
93
128
  const bumpIdle = (s: Session): void => {
94
129
  if (s.idle) clearTimeout(s.idle);
95
130
  s.idle = setTimeout(() => {
96
131
  if (s.sessionId) sessions.delete(s.sessionId);
132
+ pendingSessions.delete(s);
97
133
  void s.close();
98
134
  }, SESSION_IDLE_MS);
99
135
  };
100
136
 
101
137
  const newSession = async (): Promise<Session> => {
102
- if (sessions.size >= MAX_SESSIONS) {
138
+ if (closed) {
139
+ const error = new Error('pyric bridge: mount is closed');
140
+ (error as { statusCode?: number }).statusCode = 503;
141
+ throw error;
142
+ }
143
+ if (sessions.size + pendingSessions.size >= MAX_SESSIONS) {
103
144
  const e = new Error(`pyric bridge: at session cap (${MAX_SESSIONS})`);
104
145
  (e as { statusCode?: number }).statusCode = 503;
105
146
  throw e;
@@ -109,34 +150,77 @@ export function createBridgeMount(opts: BridgeMountOptions = {}): BridgeMount {
109
150
  close: async () => {},
110
151
  idle: null,
111
152
  sessionId: null,
153
+ closing: null,
112
154
  };
113
155
  session.transport = new StreamableHTTPServerTransport({
114
156
  sessionIdGenerator: () => randomUUID(),
115
157
  onsessioninitialized: (id) => {
158
+ if (closed) {
159
+ pendingSessions.delete(session);
160
+ void session.close();
161
+ return;
162
+ }
116
163
  session.sessionId = id;
117
164
  sessions.set(id, session);
165
+ pendingSessions.delete(session);
118
166
  bumpIdle(session);
119
167
  },
120
168
  });
121
169
  session.transport.onclose = () => {
122
170
  if (session.sessionId) sessions.delete(session.sessionId);
171
+ pendingSessions.delete(session);
123
172
  };
124
173
  const surface = getDefaultMcpToolSurface();
125
174
  const server = buildMcpServer(bridge, {
126
175
  forwarded: surface.forwarded,
127
176
  inProcess: surface.inProcess,
128
177
  });
129
- session.close = async () => {
130
- if (session.idle) clearTimeout(session.idle);
131
- await server.close().catch(() => {});
132
- await session.transport.close().catch(() => {});
178
+ session.close = () => {
179
+ session.closing ??= (async () => {
180
+ if (session.idle) clearTimeout(session.idle);
181
+ session.idle = null;
182
+ await server.close().catch(() => {});
183
+ await session.transport.close().catch(() => {});
184
+ })();
185
+ return session.closing;
133
186
  };
134
- await server.connect(session.transport);
187
+ pendingSessions.add(session);
188
+ try {
189
+ await server.connect(session.transport);
190
+ } catch (error) {
191
+ pendingSessions.delete(session);
192
+ await session.close();
193
+ throw error;
194
+ }
135
195
  return session;
136
196
  };
137
197
 
138
- return {
198
+ const closeSession = async (session: Session): Promise<void> => {
199
+ if (session.sessionId) sessions.delete(session.sessionId);
200
+ pendingSessions.delete(session);
201
+ await session.close();
202
+ };
203
+
204
+ const removeOwnedPointer = (pointer: string): void => {
205
+ try {
206
+ if (!existsSync(pointer)) return;
207
+ const current = JSON.parse(readFileSync(pointer, 'utf8')) as { instanceId?: string };
208
+ if (current.instanceId === bridge.instanceId) rmSync(pointer);
209
+ } catch {
210
+ // Best effort. A malformed or concurrently replaced pointer is not ours.
211
+ }
212
+ };
213
+
214
+ const mount: BridgeMount = {
215
+ project,
216
+ instanceId: bridge.instanceId,
217
+
139
218
  async handler(req, res, url) {
219
+ if (closed && (url.pathname === HEALTH_PATH || url.pathname === MCP_PATH)) {
220
+ res.writeHead(503, { 'content-type': 'application/json' });
221
+ res.end(JSON.stringify({ error: 'pyric bridge: mount is closed' }));
222
+ return true;
223
+ }
140
224
  if (url.pathname === HEALTH_PATH) {
141
225
  res.writeHead(200, { 'content-type': 'application/json' }).end(JSON.stringify(bridge.health()));
142
226
  return true;
@@ -144,20 +228,38 @@ export function createBridgeMount(opts: BridgeMountOptions = {}): BridgeMount {
144
228
  if (url.pathname === MCP_PATH) {
145
229
  try {
146
230
  const sessionId = (req.headers['mcp-session-id'] ?? req.headers['Mcp-Session-Id']) as string | undefined;
147
- let session = sessionId ? sessions.get(sessionId) : undefined;
148
- if (session) bumpIdle(session);
149
- else session = await newSession();
231
+ let session: Session;
232
+ let created = false;
233
+ if (sessionId) {
234
+ const existing = sessions.get(sessionId);
235
+ if (!existing) {
236
+ res.writeHead(404, { 'content-type': 'application/json' });
237
+ res.end(JSON.stringify({ error: 'pyric bridge: MCP session not found' }));
238
+ return true;
239
+ }
240
+ session = existing;
241
+ bumpIdle(session);
242
+ } else {
243
+ session = await newSession();
244
+ created = true;
245
+ }
150
246
 
151
247
  if (req.method === 'DELETE' && sessionId) {
152
- await session.close();
153
- sessions.delete(sessionId);
248
+ await closeSession(session);
154
249
  res.writeHead(204).end();
155
250
  return true;
156
251
  }
157
252
  // The transport reads the raw request stream itself. Do NOT pre-parse
158
253
  // the body (the old `collectBody` path); a double read hangs the
159
254
  // initialize POST.
160
- await session.transport.handleRequest(req, res);
255
+ try {
256
+ await session.transport.handleRequest(req, res);
257
+ } finally {
258
+ // A request without a session id is allowed to allocate only while
259
+ // it attempts initialization. Invalid/non-initialize traffic must
260
+ // not strand an uninitialized transport against the session cap.
261
+ if (created && session.sessionId === null) await closeSession(session);
262
+ }
161
263
  } catch (err) {
162
264
  const statusCode = (err as { statusCode?: number })?.statusCode ?? 500;
163
265
  if (!res.headersSent) {
@@ -169,10 +271,25 @@ export function createBridgeMount(opts: BridgeMountOptions = {}): BridgeMount {
169
271
  }
170
272
  return false;
171
273
  },
172
- attachUpgrade(server) {
274
+ attachHost({
275
+ servers,
276
+ lifecycleServer = servers[0],
277
+ projectDir,
278
+ origin,
279
+ collision,
280
+ closeOnServerClose = true,
281
+ }) {
282
+ if (closed) throw new Error('pyric bridge: cannot attach a closed mount');
173
283
  const wss = new WebSocketServer({ noServer: true });
174
284
  const guard = opts.upgradeGuard;
175
- server.on('upgrade', (req, socket, head) => {
285
+ const pointer = join(projectDir, '.pyric', 'serve.json');
286
+ const upgradedSockets = new Set<Duplex>();
287
+ const collisionAbort = new AbortController();
288
+ let collisionProbe: Promise<void> | null = null;
289
+ let attachmentClosed = false;
290
+ let attachmentClosePromise: Promise<void> | null = null;
291
+
292
+ const onUpgrade = (req: IncomingMessage, socket: Duplex, head: Buffer): void => {
176
293
  if ((req.url ?? '') !== WS_PATH) return;
177
294
  // DNS-rebinding + cross-origin hijack guard. The static/dev server runs
178
295
  // isAllowedHost on the `request` event only; `upgrade` is a separate
@@ -187,14 +304,131 @@ export function createBridgeMount(opts: BridgeMountOptions = {}): BridgeMount {
187
304
  return;
188
305
  }
189
306
  }
307
+ upgradedSockets.add(socket);
308
+ socket.once('close', () => upgradedSockets.delete(socket));
190
309
  wss.handleUpgrade(req, socket as never, head, (ws: WebSocket) => {
191
310
  attachPeer(bridge, ws);
192
311
  });
193
- });
312
+ };
313
+
314
+ const publish = (): void => {
315
+ const currentOrigin = origin();
316
+ if (!currentOrigin?.port || attachmentClosed) return;
317
+ try {
318
+ mkdirSync(dirname(pointer), { recursive: true });
319
+ writeFileSync(pointer, JSON.stringify({
320
+ url: `http://${currentOrigin.host}:${currentOrigin.port}`,
321
+ mcpUrl: mount.mcpUrl(currentOrigin),
322
+ port: currentOrigin.port,
323
+ pid: process.pid,
324
+ instanceId: bridge.instanceId,
325
+ project,
326
+ }, null, 2) + '\n');
327
+ } catch {
328
+ // Discovery falls back to a port scan.
329
+ }
330
+ };
331
+
332
+ const probeCollision = async (): Promise<void> => {
333
+ const currentOrigin = origin();
334
+ if (!collision || !currentOrigin?.port || attachmentClosed) return;
335
+ for (const probe of [`http://127.0.0.1:${currentOrigin.port}`, `http://[::1]:${currentOrigin.port}`]) {
336
+ try {
337
+ const response = await (collision.fetchImpl ?? fetch)(`${probe}${HEALTH_PATH}`, {
338
+ signal: AbortSignal.any([collisionAbort.signal, AbortSignal.timeout(1000)]),
339
+ });
340
+ if (attachmentClosed) return;
341
+ if (response.status !== 200) continue;
342
+ const body = (await response.json()) as { mode?: string; instanceId?: string };
343
+ if (attachmentClosed) return;
344
+ if (body.mode === 'sandbox' && body.instanceId && body.instanceId !== bridge.instanceId) {
345
+ collision.warn(
346
+ `\n⚠ pyric: another sandbox already serves port ${currentOrigin.port} on a different loopback ` +
347
+ `family (${probe}). Two dev servers are colliding across IPv4/IPv6 — your MCP ` +
348
+ `agent and browser can land on DIFFERENT sandboxes (writes seem to vanish). ` +
349
+ `Stop the other server, or give this app a unique \`server.port\` so the two ` +
350
+ `don't share one (pinning server.host to a family the squatter holds would ` +
351
+ `just EADDRINUSE).\n`,
352
+ { timestamp: true },
353
+ );
354
+ return;
355
+ }
356
+ } catch {
357
+ if (attachmentClosed) return;
358
+ // The other loopback family is silent.
359
+ }
360
+ }
361
+ };
362
+
363
+ const announce = (): void => {
364
+ publish();
365
+ if (!collisionProbe) {
366
+ const current = probeCollision();
367
+ collisionProbe = current;
368
+ void current.finally(() => {
369
+ if (collisionProbe === current) collisionProbe = null;
370
+ });
371
+ }
372
+ };
373
+ const attachment: BridgeHostAttachment = {
374
+ close(): Promise<void> {
375
+ if (attachmentClosePromise) return attachmentClosePromise;
376
+ attachmentClosePromise = (async () => {
377
+ attachmentClosed = true;
378
+ collisionAbort.abort();
379
+ for (const server of servers) server.removeListener('upgrade', onUpgrade as never);
380
+ lifecycleServer?.removeListener('listening', announce);
381
+ lifecycleServer?.removeListener('close', onClose);
382
+ await collisionProbe;
383
+ removeOwnedPointer(pointer);
384
+ for (const client of wss.clients) client.terminate();
385
+ for (const socket of upgradedSockets) socket.destroy();
386
+ upgradedSockets.clear();
387
+ await new Promise<void>((resolve) => {
388
+ let settled = false;
389
+ const done = (): void => {
390
+ if (settled) return;
391
+ settled = true;
392
+ clearTimeout(fallback);
393
+ resolve();
394
+ };
395
+ // `noServer` owns no listener socket. Once upgrades are detached
396
+ // and clients are terminated, a missing ws `close` callback must
397
+ // not deadlock the host's ordered shutdown.
398
+ const fallback = setTimeout(done, 500);
399
+ fallback.unref();
400
+ try {
401
+ wss.close(done);
402
+ } catch {
403
+ done();
404
+ }
405
+ });
406
+ attachments.delete(attachment);
407
+ })();
408
+ return attachmentClosePromise;
409
+ },
410
+ };
411
+ const onClose = (): void => { void attachment.close(); };
412
+
413
+ for (const server of servers) server.on('upgrade', onUpgrade as never);
414
+ if (closeOnServerClose) lifecycleServer?.once('close', onClose);
415
+ if ((lifecycleServer as unknown as { listening?: boolean } | undefined)?.listening) announce();
416
+ else lifecycleServer?.once('listening', announce);
417
+ attachments.add(attachment);
418
+ return attachment;
194
419
  },
195
420
  sandboxConnected: () => bridge.health().sandboxConnected === true,
196
- instanceId: bridge.instanceId,
197
421
  wsUrl: ({ host, port }) => `ws://${host}:${port}${WS_PATH}`,
198
422
  mcpUrl: ({ host, port }) => `http://${host}:${port}${MCP_PATH}`,
423
+ close(): Promise<void> {
424
+ if (closePromise) return closePromise;
425
+ closePromise = (async () => {
426
+ closed = true;
427
+ await Promise.all([...attachments].map((attachment) => attachment.close()));
428
+ await Promise.all([...new Set([...sessions.values(), ...pendingSessions])].map(closeSession));
429
+ })();
430
+ return closePromise;
431
+ },
199
432
  };
433
+ return mount;
200
434
  }