@pyric/cli 0.1.0-alpha.19 → 0.1.0-alpha.21

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 (642) hide show
  1. package/README.md +64 -89
  2. package/dist/assurance/.generated/conformance-verdicts.d.ts +68 -1
  3. package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
  4. package/dist/assurance/.generated/conformance-verdicts.js +68 -1
  5. package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
  6. package/dist/bridge/client/dispatch.d.ts +25 -19
  7. package/dist/bridge/client/dispatch.d.ts.map +1 -1
  8. package/dist/bridge/client/dispatch.js +41 -48
  9. package/dist/bridge/client/dispatch.js.map +1 -1
  10. package/dist/bridge/client/tool-family-factories.d.ts +26 -0
  11. package/dist/bridge/client/tool-family-factories.d.ts.map +1 -0
  12. package/dist/bridge/client/tool-family-factories.js +10 -0
  13. package/dist/bridge/client/tool-family-factories.js.map +1 -0
  14. package/dist/bridge/server/mcp-contract.d.ts +7 -6
  15. package/dist/bridge/server/mcp-contract.d.ts.map +1 -1
  16. package/dist/bridge/server/mcp-contract.js +9 -48
  17. package/dist/bridge/server/mcp-contract.js.map +1 -1
  18. package/dist/bridge/server/peer.d.ts +11 -1
  19. package/dist/bridge/server/peer.d.ts.map +1 -1
  20. package/dist/bridge/server/peer.js +22 -1
  21. package/dist/bridge/server/peer.js.map +1 -1
  22. package/dist/bridge/server/tool-family-factories.d.ts +30 -0
  23. package/dist/bridge/server/tool-family-factories.d.ts.map +1 -0
  24. package/dist/bridge/server/tool-family-factories.js +22 -0
  25. package/dist/bridge/server/tool-family-factories.js.map +1 -0
  26. package/dist/bridge/server/tool-metadata.d.ts +17 -18
  27. package/dist/bridge/server/tool-metadata.d.ts.map +1 -1
  28. package/dist/bridge/server/tool-metadata.js +24 -59
  29. package/dist/bridge/server/tool-metadata.js.map +1 -1
  30. package/dist/bridge/tool-families.d.ts +48 -0
  31. package/dist/bridge/tool-families.d.ts.map +1 -0
  32. package/dist/bridge/tool-families.generated.d.ts +32 -0
  33. package/dist/bridge/tool-families.generated.d.ts.map +1 -0
  34. package/dist/bridge/tool-families.generated.js +15 -0
  35. package/dist/bridge/tool-families.generated.js.map +1 -0
  36. package/dist/bridge/tool-families.js +51 -0
  37. package/dist/bridge/tool-families.js.map +1 -0
  38. package/dist/bridge/tool-family-records/conformance.d.ts +7 -0
  39. package/dist/bridge/tool-family-records/conformance.d.ts.map +1 -0
  40. package/dist/bridge/tool-family-records/conformance.js +6 -0
  41. package/dist/bridge/tool-family-records/conformance.js.map +1 -0
  42. package/dist/bridge/tool-family-records/firestore-data.d.ts +7 -0
  43. package/dist/bridge/tool-family-records/firestore-data.d.ts.map +1 -0
  44. package/dist/bridge/tool-family-records/firestore-data.js +15 -0
  45. package/dist/bridge/tool-family-records/firestore-data.js.map +1 -0
  46. package/dist/bridge/tool-family-records/firestore-inspect.d.ts +7 -0
  47. package/dist/bridge/tool-family-records/firestore-inspect.d.ts.map +1 -0
  48. package/dist/bridge/tool-family-records/firestore-inspect.js +6 -0
  49. package/dist/bridge/tool-family-records/firestore-inspect.js.map +1 -0
  50. package/dist/bridge/tool-family-records/firestore-rules.d.ts +7 -0
  51. package/dist/bridge/tool-family-records/firestore-rules.d.ts.map +1 -0
  52. package/dist/bridge/tool-family-records/firestore-rules.js +15 -0
  53. package/dist/bridge/tool-family-records/firestore-rules.js.map +1 -0
  54. package/dist/bridge/tool-family-records/firestore-simulator.d.ts +7 -0
  55. package/dist/bridge/tool-family-records/firestore-simulator.d.ts.map +1 -0
  56. package/dist/bridge/tool-family-records/firestore-simulator.js +16 -0
  57. package/dist/bridge/tool-family-records/firestore-simulator.js.map +1 -0
  58. package/dist/bridge/tool-family-records/rtdb-inspection.d.ts +7 -0
  59. package/dist/bridge/tool-family-records/rtdb-inspection.d.ts.map +1 -0
  60. package/dist/bridge/tool-family-records/rtdb-inspection.js +6 -0
  61. package/dist/bridge/tool-family-records/rtdb-inspection.js.map +1 -0
  62. package/dist/bundler/externals.d.ts +37 -0
  63. package/dist/bundler/externals.d.ts.map +1 -0
  64. package/dist/bundler/externals.js +52 -0
  65. package/dist/bundler/externals.js.map +1 -0
  66. package/dist/bundler/index.d.ts +17 -0
  67. package/dist/bundler/index.d.ts.map +1 -0
  68. package/dist/bundler/index.js +17 -0
  69. package/dist/bundler/index.js.map +1 -0
  70. package/dist/cli/index.d.ts +2 -2
  71. package/dist/cli/index.d.ts.map +1 -1
  72. package/dist/cli/index.js +48 -42
  73. package/dist/cli/index.js.map +1 -1
  74. package/dist/cli/inlined-sdk-scanner.d.ts +6 -0
  75. package/dist/cli/inlined-sdk-scanner.d.ts.map +1 -0
  76. package/dist/cli/inlined-sdk-scanner.js +82 -0
  77. package/dist/cli/inlined-sdk-scanner.js.map +1 -0
  78. package/dist/cli/mcp-proxy.js +3 -3
  79. package/dist/cli/mcp-proxy.js.map +1 -1
  80. package/dist/cli/parse-args.d.ts +1 -1
  81. package/dist/cli/parse-args.d.ts.map +1 -1
  82. package/dist/cli/parse-args.js +51 -15
  83. package/dist/cli/parse-args.js.map +1 -1
  84. package/dist/cli/pyric-config.d.ts +24 -0
  85. package/dist/cli/pyric-config.d.ts.map +1 -0
  86. package/dist/cli/pyric-config.js +28 -0
  87. package/dist/cli/pyric-config.js.map +1 -0
  88. package/dist/cli/sandbox-interlock.d.ts +97 -0
  89. package/dist/cli/sandbox-interlock.d.ts.map +1 -0
  90. package/dist/cli/sandbox-interlock.js +112 -0
  91. package/dist/cli/sandbox-interlock.js.map +1 -0
  92. package/dist/cli/{dev-runner.d.ts → sandbox-runner.d.ts} +53 -48
  93. package/dist/cli/sandbox-runner.d.ts.map +1 -0
  94. package/dist/cli/{dev-runner.js → sandbox-runner.js} +105 -67
  95. package/dist/cli/sandbox-runner.js.map +1 -0
  96. package/dist/cli/serve.d.ts +12 -14
  97. package/dist/cli/serve.d.ts.map +1 -1
  98. package/dist/cli/serve.js +155 -116
  99. package/dist/cli/serve.js.map +1 -1
  100. package/dist/cli/snapshot.js +5 -5
  101. package/dist/cli/snapshot.js.map +1 -1
  102. package/dist/cli/unsupported-runtime.d.ts +27 -0
  103. package/dist/cli/unsupported-runtime.d.ts.map +1 -0
  104. package/dist/cli/unsupported-runtime.js +63 -0
  105. package/dist/cli/unsupported-runtime.js.map +1 -0
  106. package/dist/cli/verify.js +1 -1
  107. package/dist/cli/verify.js.map +1 -1
  108. package/dist/conformance/.generated/can-i-use-browser.d.ts +1 -1
  109. package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
  110. package/dist/conformance/.generated/can-i-use-browser.js +1 -1
  111. package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
  112. package/dist/conformance/.generated/can-i-use.d.ts +1 -1
  113. package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
  114. package/dist/conformance/.generated/can-i-use.js +1 -1
  115. package/dist/conformance/.generated/can-i-use.js.map +1 -1
  116. package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
  117. package/dist/conformance/.generated/conformance-docs.js +1 -1
  118. package/dist/conformance/.generated/conformance-docs.js.map +1 -1
  119. package/dist/functions-rtdb/child.d.ts +37 -0
  120. package/dist/functions-rtdb/child.d.ts.map +1 -1
  121. package/dist/functions-rtdb/child.js +90 -21
  122. package/dist/functions-rtdb/child.js.map +1 -1
  123. package/dist/functions-rtdb/development-runtime.d.ts +3 -0
  124. package/dist/functions-rtdb/development-runtime.d.ts.map +1 -1
  125. package/dist/functions-rtdb/development-runtime.js +2 -1
  126. package/dist/functions-rtdb/development-runtime.js.map +1 -1
  127. package/dist/functions-rtdb/project.js +8 -8
  128. package/dist/functions-rtdb/project.js.map +1 -1
  129. package/dist/google-endpoints.d.ts +67 -0
  130. package/dist/google-endpoints.d.ts.map +1 -0
  131. package/dist/google-endpoints.js +119 -0
  132. package/dist/google-endpoints.js.map +1 -0
  133. package/dist/next/guard.js +1 -1
  134. package/dist/next/guard.js.map +1 -1
  135. package/dist/next/runtime-env.d.ts.map +1 -1
  136. package/dist/next/runtime-env.js +5 -0
  137. package/dist/next/runtime-env.js.map +1 -1
  138. package/dist/next/with-pyric.d.ts +1 -1
  139. package/dist/next/with-pyric.js +1 -1
  140. package/dist/register/beacon.d.ts +69 -0
  141. package/dist/register/beacon.d.ts.map +1 -0
  142. package/dist/register/beacon.js +199 -0
  143. package/dist/register/beacon.js.map +1 -0
  144. package/dist/register/index.d.ts.map +1 -1
  145. package/dist/register/index.js +65 -6
  146. package/dist/register/index.js.map +1 -1
  147. package/dist/register/net-guard.d.ts +110 -0
  148. package/dist/register/net-guard.d.ts.map +1 -0
  149. package/dist/register/net-guard.js +462 -0
  150. package/dist/register/net-guard.js.map +1 -0
  151. package/dist/remote/index.d.ts +1 -1
  152. package/dist/remote/index.js +9 -9
  153. package/dist/remote/index.js.map +1 -1
  154. package/dist/serve/ai-diagnostics-relay.d.ts +63 -0
  155. package/dist/serve/ai-diagnostics-relay.d.ts.map +1 -0
  156. package/dist/serve/ai-diagnostics-relay.js +125 -0
  157. package/dist/serve/ai-diagnostics-relay.js.map +1 -0
  158. package/dist/serve/ai-proxy.d.ts +92 -0
  159. package/dist/serve/ai-proxy.d.ts.map +1 -0
  160. package/dist/serve/ai-proxy.js +269 -0
  161. package/dist/serve/ai-proxy.js.map +1 -0
  162. package/dist/serve/ai-status.d.ts +44 -0
  163. package/dist/serve/ai-status.d.ts.map +1 -0
  164. package/dist/serve/ai-status.js +77 -0
  165. package/dist/serve/ai-status.js.map +1 -0
  166. package/dist/serve/ai-terminal-blocks.d.ts +97 -0
  167. package/dist/serve/ai-terminal-blocks.d.ts.map +1 -0
  168. package/dist/serve/ai-terminal-blocks.js +128 -0
  169. package/dist/serve/ai-terminal-blocks.js.map +1 -0
  170. package/dist/serve/ai-terminal-text.d.ts +36 -0
  171. package/dist/serve/ai-terminal-text.d.ts.map +1 -0
  172. package/dist/serve/ai-terminal-text.js +48 -0
  173. package/dist/serve/ai-terminal-text.js.map +1 -0
  174. package/dist/serve/beacon-route.d.ts +53 -0
  175. package/dist/serve/beacon-route.d.ts.map +1 -0
  176. package/dist/serve/beacon-route.js +101 -0
  177. package/dist/serve/beacon-route.js.map +1 -0
  178. package/dist/serve/bundler.js +10 -10
  179. package/dist/serve/bundler.js.map +1 -1
  180. package/dist/serve/entries/active-auth-registry.d.ts +16 -0
  181. package/dist/serve/entries/active-auth-registry.d.ts.map +1 -0
  182. package/dist/serve/entries/active-auth-registry.js +48 -0
  183. package/dist/serve/entries/active-auth-registry.js.map +1 -0
  184. package/dist/serve/entries/active-auth.d.ts +18 -0
  185. package/dist/serve/entries/active-auth.d.ts.map +1 -0
  186. package/dist/serve/entries/active-auth.js +84 -0
  187. package/dist/serve/entries/active-auth.js.map +1 -0
  188. package/dist/serve/entries/ai.d.ts.map +1 -1
  189. package/dist/serve/entries/ai.js +27 -1
  190. package/dist/serve/entries/ai.js.map +1 -1
  191. package/dist/serve/entries/auth-helper-core.d.ts +1 -0
  192. package/dist/serve/entries/auth-helper-core.d.ts.map +1 -1
  193. package/dist/serve/entries/auth-helper-core.js +4 -0
  194. package/dist/serve/entries/auth-helper-core.js.map +1 -1
  195. package/dist/serve/entries/auth-helper-dom.d.ts.map +1 -1
  196. package/dist/serve/entries/auth-helper-dom.js +29 -3
  197. package/dist/serve/entries/auth-helper-dom.js.map +1 -1
  198. package/dist/serve/entries/auth-helper-runtime.js +1 -1
  199. package/dist/serve/entries/auth-helper-runtime.js.map +1 -1
  200. package/dist/serve/entries/auth.d.ts.map +1 -1
  201. package/dist/serve/entries/auth.js +8 -0
  202. package/dist/serve/entries/auth.js.map +1 -1
  203. package/dist/serve/entries/bridge-url.d.ts +1 -1
  204. package/dist/serve/entries/bridge-url.js +1 -1
  205. package/dist/serve/entries/firestore.js +3 -3
  206. package/dist/serve/entries/firestore.js.map +1 -1
  207. package/dist/serve/entries/init.d.ts.map +1 -1
  208. package/dist/serve/entries/init.js +70 -4
  209. package/dist/serve/entries/init.js.map +1 -1
  210. package/dist/serve/entries/keepalive.js +1 -1
  211. package/dist/serve/entries/keepalive.js.map +1 -1
  212. package/dist/serve/entries/runtime.d.ts.map +1 -1
  213. package/dist/serve/entries/runtime.js +30 -14
  214. package/dist/serve/entries/runtime.js.map +1 -1
  215. package/dist/serve/entries/storage.js +1 -1
  216. package/dist/serve/entries/storage.js.map +1 -1
  217. package/dist/serve/entries/worker-runtime.js +1 -1
  218. package/dist/serve/entries/worker-runtime.js.map +1 -1
  219. package/dist/serve/init-payload.d.ts +4 -0
  220. package/dist/serve/init-payload.d.ts.map +1 -1
  221. package/dist/serve/namespace.d.ts +20 -5
  222. package/dist/serve/namespace.d.ts.map +1 -1
  223. package/dist/serve/namespace.js +93 -129
  224. package/dist/serve/namespace.js.map +1 -1
  225. package/dist/serve/rules.d.ts.map +1 -1
  226. package/dist/serve/rules.js +44 -21
  227. package/dist/serve/rules.js.map +1 -1
  228. package/dist/serve/runtime/chip-config.d.ts.map +1 -1
  229. package/dist/serve/runtime/chip-config.js +16 -2
  230. package/dist/serve/runtime/chip-config.js.map +1 -1
  231. package/dist/serve/runtime/chip-dialog.d.ts +18 -0
  232. package/dist/serve/runtime/chip-dialog.d.ts.map +1 -0
  233. package/dist/serve/runtime/chip-dialog.js +315 -0
  234. package/dist/serve/runtime/chip-dialog.js.map +1 -0
  235. package/dist/serve/runtime/chip-install.d.ts +2 -0
  236. package/dist/serve/runtime/chip-install.d.ts.map +1 -1
  237. package/dist/serve/runtime/chip-install.js +9 -4
  238. package/dist/serve/runtime/chip-install.js.map +1 -1
  239. package/dist/serve/runtime/chip-user-search.d.ts +16 -0
  240. package/dist/serve/runtime/chip-user-search.d.ts.map +1 -0
  241. package/dist/serve/runtime/chip-user-search.js +354 -0
  242. package/dist/serve/runtime/chip-user-search.js.map +1 -0
  243. package/dist/serve/runtime/chip.d.ts +10 -0
  244. package/dist/serve/runtime/chip.d.ts.map +1 -1
  245. package/dist/serve/runtime/chip.js +149 -15
  246. package/dist/serve/runtime/chip.js.map +1 -1
  247. package/dist/serve/runtime/identity.d.ts +17 -0
  248. package/dist/serve/runtime/identity.d.ts.map +1 -0
  249. package/dist/serve/runtime/identity.js +10 -0
  250. package/dist/serve/runtime/identity.js.map +1 -0
  251. package/dist/serve/runtime/manifest.d.ts +1 -1
  252. package/dist/serve/runtime/manifest.d.ts.map +1 -1
  253. package/dist/serve/runtime/manifest.js +1 -1
  254. package/dist/serve/runtime/manifest.js.map +1 -1
  255. package/dist/serve/runtime/status.d.ts.map +1 -1
  256. package/dist/serve/runtime/status.js +23 -0
  257. package/dist/serve/runtime/status.js.map +1 -1
  258. package/dist/serve/sandbox-session.d.ts +8 -0
  259. package/dist/serve/sandbox-session.d.ts.map +1 -1
  260. package/dist/serve/sandbox-session.js +12 -4
  261. package/dist/serve/sandbox-session.js.map +1 -1
  262. package/dist/serve/server.d.ts +7 -0
  263. package/dist/serve/server.d.ts.map +1 -1
  264. package/dist/serve/server.js +15 -1
  265. package/dist/serve/server.js.map +1 -1
  266. package/dist/serve/site-ui/404.html +1 -1
  267. package/dist/serve/site-ui/_astro/{RulesCodeEditor.Bl-XMkhD.js → RulesCodeEditor.DsTAsKIa.js} +1 -1
  268. package/dist/serve/site-ui/_astro/_slug_.Da5VLhW1.css +1 -0
  269. package/dist/serve/site-ui/_astro/_studio_.BnfYCKoI.css +1 -0
  270. package/dist/serve/site-ui/_astro/app.BOr2kwae.js +115 -0
  271. package/dist/serve/site-ui/_astro/app.DhAcImFD.js +1 -0
  272. package/dist/serve/site-ui/_astro/app.pMSnN6Qw.css +1 -0
  273. package/dist/serve/site-ui/_astro/{chess-showcase.Dh5D8kqe.js → chess-showcase.Bn_pP6UJ.js} +2 -2
  274. package/dist/serve/site-ui/_astro/{example-runtime.CuyAjjiG.js → example-runtime.CXopTGv7.js} +1 -1
  275. package/dist/serve/site-ui/_astro/index.Tb-31efc.css +1 -0
  276. package/dist/serve/site-ui/_astro/index.UkCBr-_0.css +1 -0
  277. package/dist/serve/site-ui/_astro/sandbox-controls.rOuZTOUG.js +510 -0
  278. package/dist/serve/site-ui/_astro/{seed.CSUkloMi.js → seed.03a08f9t.js} +2 -2
  279. package/dist/serve/site-ui/_astro/writes.BsPBG3dp.js +653 -0
  280. package/dist/serve/site-ui/auth/index.html +5 -3
  281. package/dist/serve/site-ui/david-east.jpg +0 -0
  282. package/dist/serve/site-ui/docs/_rhythm/index.html +6 -3
  283. package/dist/serve/site-ui/docs/_rhythm.md +1 -1
  284. package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +18 -15
  285. package/dist/serve/site-ui/docs/agent/set-up-your-agent.md +16 -16
  286. package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +6 -5
  287. package/dist/serve/site-ui/docs/agent/watch-and-review.md +1 -5
  288. package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +8 -5
  289. package/dist/serve/site-ui/docs/agent/work-with-an-agent.md +4 -4
  290. package/dist/serve/site-ui/docs/ai-compat/index.html +5 -2
  291. package/dist/serve/site-ui/docs/api-reference/index.html +13 -2
  292. package/dist/serve/site-ui/docs/api-reference.md +8 -0
  293. package/dist/serve/site-ui/docs/app-compat/index.html +5 -2
  294. package/dist/serve/site-ui/docs/auth-compat/index.html +7 -4
  295. package/dist/serve/site-ui/docs/auth-compat.md +2 -2
  296. package/dist/serve/site-ui/docs/build/ai-logic/index.html +10 -2
  297. package/dist/serve/site-ui/docs/build/ai-logic.md +6 -0
  298. package/dist/serve/site-ui/docs/build/authentication/index.html +7 -4
  299. package/dist/serve/site-ui/docs/build/authentication.md +2 -2
  300. package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +5 -2
  301. package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +5 -2
  302. package/dist/serve/site-ui/docs/build/cloud-storage/index.html +6 -3
  303. package/dist/serve/site-ui/docs/build/cloud-storage.md +1 -1
  304. package/dist/serve/site-ui/docs/build/realtime-database/index.html +9 -6
  305. package/dist/serve/site-ui/docs/build/realtime-database.md +4 -4
  306. package/dist/serve/site-ui/docs/conformance-scores/index.html +10 -3
  307. package/dist/serve/site-ui/docs/conformance-scores.md +5 -1
  308. package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +6 -3
  309. package/dist/serve/site-ui/docs/create-pyric-reference-api.md +1 -1
  310. package/dist/serve/site-ui/docs/database-compat/index.html +48 -45
  311. package/dist/serve/site-ui/docs/database-compat.md +43 -43
  312. package/dist/serve/site-ui/docs/examples/chess/index.html +5 -2
  313. package/dist/serve/site-ui/docs/examples/index.html +5 -2
  314. package/dist/serve/site-ui/docs/firestore-compat/index.html +8 -5
  315. package/dist/serve/site-ui/docs/firestore-compat.md +3 -3
  316. package/dist/serve/site-ui/docs/firestore-flutter-compat/index.html +319 -0
  317. package/dist/serve/site-ui/docs/firestore-flutter-compat.md +344 -0
  318. package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +5 -2
  319. package/dist/serve/site-ui/docs/get-started/backend-bundlers/index.html +105 -0
  320. package/dist/serve/site-ui/docs/get-started/backend-bundlers.md +165 -0
  321. package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +9 -6
  322. package/dist/serve/site-ui/docs/get-started/how-the-swap-works.md +5 -5
  323. package/dist/serve/site-ui/docs/get-started/nextjs/index.html +9 -6
  324. package/dist/serve/site-ui/docs/get-started/nextjs.md +4 -4
  325. package/dist/serve/site-ui/docs/get-started/start-building/index.html +14 -9
  326. package/dist/serve/site-ui/docs/get-started/start-building.md +16 -10
  327. package/dist/serve/site-ui/docs/get-started/vite/index.html +6 -3
  328. package/dist/serve/site-ui/docs/get-started/vite.md +1 -1
  329. package/dist/serve/site-ui/docs/index.json +3128 -1613
  330. package/dist/serve/site-ui/docs/messaging-compat/index.html +5 -2
  331. package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +5 -2
  332. package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +6 -4
  333. package/dist/serve/site-ui/docs/observe/see-whats-happening.md +2 -4
  334. package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +9 -6
  335. package/dist/serve/site-ui/docs/observe/shape-your-data.md +4 -4
  336. package/dist/serve/site-ui/docs/overview/index.html +16 -10
  337. package/dist/serve/site-ui/docs/overview.md +19 -11
  338. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +5 -2
  339. package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +5 -2
  340. package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +5 -2
  341. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +8 -5
  342. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api.md +3 -3
  343. package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +5 -2
  344. package/dist/serve/site-ui/docs/pyric-admin-reference-api/index.html +501 -0
  345. package/dist/serve/site-ui/docs/pyric-admin-reference-api.md +587 -0
  346. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +5 -2
  347. package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +5 -2
  348. package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +5 -2
  349. package/dist/serve/site-ui/docs/pyric-analytics-reference-api/index.html +124 -0
  350. package/dist/serve/site-ui/docs/pyric-analytics-reference-api.md +287 -0
  351. package/dist/serve/site-ui/docs/pyric-app-check-reference-api/index.html +87 -0
  352. package/dist/serve/site-ui/docs/pyric-app-check-reference-api.md +199 -0
  353. package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +5 -2
  354. package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +10 -3
  355. package/dist/serve/site-ui/docs/pyric-auth-reference-api.md +2 -1
  356. package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +5 -2
  357. package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +5 -2
  358. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +6 -3
  359. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api.md +1 -1
  360. package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +5 -2
  361. package/dist/serve/site-ui/docs/pyric-cli-bundler-reference-api/index.html +56 -0
  362. package/dist/serve/site-ui/docs/pyric-cli-bundler-reference-api.md +72 -0
  363. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +6 -2
  364. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api.md +1 -0
  365. package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +5 -2
  366. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +6 -2
  367. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api.md +1 -0
  368. package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +5 -2
  369. package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +5 -2
  370. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +6 -3
  371. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api.md +1 -1
  372. package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +5 -2
  373. package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +5 -2
  374. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +39 -11
  375. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api.md +17 -9
  376. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +137 -94
  377. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api.md +61 -1
  378. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +6 -3
  379. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api.md +1 -1
  380. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +6 -3
  381. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api.md +2 -2
  382. package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +167 -96
  383. package/dist/serve/site-ui/docs/pyric-database-reference-api.md +108 -2
  384. package/dist/serve/site-ui/docs/pyric-firestore-lite-reference-api/index.html +559 -0
  385. package/dist/serve/site-ui/docs/pyric-firestore-lite-reference-api.md +1240 -0
  386. package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +44 -12
  387. package/dist/serve/site-ui/docs/pyric-firestore-reference-api.md +18 -8
  388. package/dist/serve/site-ui/docs/pyric-functions-reference-api/index.html +67 -0
  389. package/dist/serve/site-ui/docs/pyric-functions-reference-api.md +149 -0
  390. package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +10 -4
  391. package/dist/serve/site-ui/docs/pyric-messaging-reference-api.md +5 -2
  392. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +10 -4
  393. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api.md +5 -2
  394. package/dist/serve/site-ui/docs/pyric-performance-reference-api/index.html +35 -0
  395. package/dist/serve/site-ui/docs/pyric-performance-reference-api.md +69 -0
  396. package/dist/serve/site-ui/docs/pyric-remote-config-reference-api/index.html +132 -0
  397. package/dist/serve/site-ui/docs/pyric-remote-config-reference-api.md +307 -0
  398. package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +5 -2
  399. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +56 -18
  400. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api.md +48 -9
  401. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +6 -3
  402. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api.md +2 -2
  403. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +243 -50
  404. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api.md +148 -31
  405. package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +26 -5
  406. package/dist/serve/site-ui/docs/pyric-storage-reference-api.md +24 -2
  407. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +30 -97
  408. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api.md +20 -51
  409. package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +5 -2
  410. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +6 -3
  411. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api.md +1 -1
  412. package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +5 -2
  413. package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +5 -2
  414. package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +5 -2
  415. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +6 -3
  416. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api.md +1 -1
  417. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +128 -27
  418. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api.md +58 -5
  419. package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +5 -2
  420. package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +5 -2
  421. package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +5 -2
  422. package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +5 -2
  423. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +8 -6
  424. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api.md +3 -4
  425. package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +5 -2
  426. package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +5 -2
  427. package/dist/serve/site-ui/docs/reference/cli/index.html +156 -0
  428. package/dist/serve/site-ui/docs/reference/cli.md +120 -0
  429. package/dist/serve/site-ui/docs/rules-compat/index.html +14 -3
  430. package/dist/serve/site-ui/docs/rules-compat.md +9 -1
  431. package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +5 -2
  432. package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +5 -2
  433. package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +6 -3
  434. package/dist/serve/site-ui/docs/secure/read-a-denial.md +1 -1
  435. package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +5 -2
  436. package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +5 -2
  437. package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +5 -2
  438. package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +5 -2
  439. package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +5 -2
  440. package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +7 -4
  441. package/dist/serve/site-ui/docs/ship/ship-to-production.md +2 -2
  442. package/dist/serve/site-ui/docs/ship/test-in-node/index.html +9 -6
  443. package/dist/serve/site-ui/docs/ship/test-in-node.md +4 -4
  444. package/dist/serve/site-ui/docs/storage-compat/index.html +17 -14
  445. package/dist/serve/site-ui/docs/storage-compat.md +12 -12
  446. package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +5 -2
  447. package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +5 -2
  448. package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +5 -2
  449. package/dist/serve/site-ui/docs/tutorial/index.html +10 -7
  450. package/dist/serve/site-ui/docs/tutorial.md +4 -4
  451. package/dist/serve/site-ui/examples/chess/index.html +4 -2
  452. package/dist/serve/site-ui/firestore/index.html +5 -3
  453. package/dist/serve/site-ui/hero-charcoal.jpg +0 -0
  454. package/dist/serve/site-ui/index.html +9 -7
  455. package/dist/serve/site-ui/llms.txt +13 -3
  456. package/dist/serve/site-ui/pyric-campfire-full.png +0 -0
  457. package/dist/serve/site-ui/pyric-campfire.png +0 -0
  458. package/dist/serve/site-ui/rtdb/index.html +5 -3
  459. package/dist/serve/site-ui/settings/index.html +5 -3
  460. package/dist/serve/site-ui/storage/index.html +5 -3
  461. package/dist/serve/site-ui/studio/index.html +13 -0
  462. package/dist/serve/site-ui/studio-routes.json +1 -1
  463. package/dist/serve/site-ui/traffic/index.html +5 -3
  464. package/dist/serve/studio/disk-workspace.d.ts.map +1 -1
  465. package/dist/serve/studio/disk-workspace.js +64 -2
  466. package/dist/serve/studio/disk-workspace.js.map +1 -1
  467. package/dist/serve/studio/routes.d.ts +9 -0
  468. package/dist/serve/studio/routes.d.ts.map +1 -1
  469. package/dist/serve/studio/routes.js +47 -7
  470. package/dist/serve/studio/routes.js.map +1 -1
  471. package/dist/serve/vite-ai-config.d.ts.map +1 -1
  472. package/dist/serve/vite-ai-config.js +38 -8
  473. package/dist/serve/vite-ai-config.js.map +1 -1
  474. package/dist/serve/vite-module-swap.d.ts.map +1 -1
  475. package/dist/serve/vite-module-swap.js +0 -28
  476. package/dist/serve/vite-module-swap.js.map +1 -1
  477. package/dist/serve/vite-plugin.d.ts +7 -7
  478. package/dist/serve/vite-plugin.js +1 -1
  479. package/dist/serve/vite-plugin.js.map +1 -1
  480. package/dist/serve/vite-sandbox-generation.d.ts +1 -1
  481. package/dist/serve/vite-sandbox-generation.d.ts.map +1 -1
  482. package/dist/serve/vite-sandbox-generation.js +13 -1
  483. package/dist/serve/vite-sandbox-generation.js.map +1 -1
  484. package/dist/serve/worker/client/auth.js +1 -2
  485. package/dist/serve/worker/client/auth.js.map +1 -1
  486. package/dist/serve/worker/client/core.d.ts +21 -1
  487. package/dist/serve/worker/client/core.d.ts.map +1 -1
  488. package/dist/serve/worker/client/core.js +79 -3
  489. package/dist/serve/worker/client/core.js.map +1 -1
  490. package/dist/serve/worker/client/disconnect.js +1 -1
  491. package/dist/serve/worker/client/disconnect.js.map +1 -1
  492. package/dist/serve/worker/client/presence.d.ts.map +1 -1
  493. package/dist/serve/worker/client/presence.js +18 -5
  494. package/dist/serve/worker/client/presence.js.map +1 -1
  495. package/dist/serve/worker/client.d.ts +1 -1
  496. package/dist/serve/worker/client.d.ts.map +1 -1
  497. package/dist/serve/worker/client.js +1 -1
  498. package/dist/serve/worker/client.js.map +1 -1
  499. package/dist/serve/worker/context-resolver.d.ts +30 -0
  500. package/dist/serve/worker/context-resolver.d.ts.map +1 -0
  501. package/dist/serve/worker/context-resolver.js +44 -0
  502. package/dist/serve/worker/context-resolver.js.map +1 -0
  503. package/dist/serve/worker/entry.js +23 -19
  504. package/dist/serve/worker/entry.js.map +1 -1
  505. package/dist/serve/worker/host/core.d.ts +1 -0
  506. package/dist/serve/worker/host/core.d.ts.map +1 -1
  507. package/dist/serve/worker/host/core.js +12 -6
  508. package/dist/serve/worker/host/core.js.map +1 -1
  509. package/dist/serve/worker/host/storage.js +2 -2
  510. package/dist/serve/worker/host-ai.d.ts.map +1 -1
  511. package/dist/serve/worker/host-ai.js +15 -0
  512. package/dist/serve/worker/host-ai.js.map +1 -1
  513. package/dist/serve/worker/host-auth.js +1 -2
  514. package/dist/serve/worker/host-auth.js.map +1 -1
  515. package/dist/serve/worker/index.d.ts +1 -1
  516. package/dist/serve/worker/index.d.ts.map +1 -1
  517. package/dist/serve/worker/index.js +2 -2
  518. package/dist/serve/worker/index.js.map +1 -1
  519. package/dist/serve/worker/port-lifecycle.d.ts +18 -0
  520. package/dist/serve/worker/port-lifecycle.d.ts.map +1 -0
  521. package/dist/serve/worker/port-lifecycle.js +28 -0
  522. package/dist/serve/worker/port-lifecycle.js.map +1 -0
  523. package/dist/serve/worker/protocol.d.ts +4 -0
  524. package/dist/serve/worker/protocol.d.ts.map +1 -1
  525. package/dist/serve/worker/protocol.js.map +1 -1
  526. package/dist/serve/worker/serve-init.d.ts.map +1 -1
  527. package/dist/serve/worker/serve-init.js +15 -3
  528. package/dist/serve/worker/serve-init.js.map +1 -1
  529. package/dist/verify/fixture.d.ts +1 -1
  530. package/package.json +17 -6
  531. package/src/assurance/.generated/conformance-verdicts.ts +68 -1
  532. package/src/bridge/client/dispatch.ts +52 -56
  533. package/src/bridge/client/tool-family-factories.ts +34 -0
  534. package/src/bridge/server/mcp-contract.ts +15 -59
  535. package/src/bridge/server/peer.ts +24 -1
  536. package/src/bridge/server/tool-family-factories.ts +40 -0
  537. package/src/bridge/server/tool-metadata.ts +29 -61
  538. package/src/bridge/tool-families.generated.ts +17 -0
  539. package/src/bridge/tool-families.ts +87 -0
  540. package/src/bridge/tool-family-records/conformance.ts +6 -0
  541. package/src/bridge/tool-family-records/firestore-data.ts +15 -0
  542. package/src/bridge/tool-family-records/firestore-inspect.ts +6 -0
  543. package/src/bridge/tool-family-records/firestore-rules.ts +15 -0
  544. package/src/bridge/tool-family-records/firestore-simulator.ts +16 -0
  545. package/src/bridge/tool-family-records/rtdb-inspection.ts +6 -0
  546. package/src/bundler/externals.ts +55 -0
  547. package/src/bundler/index.ts +21 -0
  548. package/src/cli/cli.test.ts +2 -46
  549. package/src/cli/index.ts +48 -42
  550. package/src/cli/inlined-sdk-scanner.ts +77 -0
  551. package/src/cli/mcp-proxy.ts +4 -4
  552. package/src/cli/parse-args.ts +61 -15
  553. package/src/cli/pyric-config.ts +45 -0
  554. package/src/cli/sandbox-interlock.ts +167 -0
  555. package/src/cli/{dev-runner.ts → sandbox-runner.ts} +142 -86
  556. package/src/cli/serve.ts +182 -115
  557. package/src/cli/snapshot.ts +5 -5
  558. package/src/cli/unsupported-runtime.ts +68 -0
  559. package/src/cli/verify.ts +1 -1
  560. package/src/conformance/.generated/can-i-use-browser.ts +2 -2
  561. package/src/conformance/.generated/can-i-use.ts +2 -2
  562. package/src/conformance/.generated/conformance-docs.ts +1 -1
  563. package/src/functions-rtdb/child.ts +115 -21
  564. package/src/functions-rtdb/development-runtime.ts +5 -1
  565. package/src/functions-rtdb/project.ts +8 -8
  566. package/src/google-endpoints.ts +155 -0
  567. package/src/next/guard.ts +1 -1
  568. package/src/next/runtime-env.ts +5 -0
  569. package/src/next/with-pyric.ts +1 -1
  570. package/src/register/beacon.ts +232 -0
  571. package/src/register/index.ts +68 -6
  572. package/src/register/net-guard.ts +567 -0
  573. package/src/remote/index.ts +9 -9
  574. package/src/serve/ai-diagnostics-relay.ts +243 -0
  575. package/src/serve/ai-proxy.ts +327 -0
  576. package/src/serve/ai-status.ts +109 -0
  577. package/src/serve/ai-terminal-blocks.ts +210 -0
  578. package/src/serve/ai-terminal-text.ts +52 -0
  579. package/src/serve/beacon-route.ts +141 -0
  580. package/src/serve/bundler.ts +10 -10
  581. package/src/serve/entries/active-auth-registry.ts +56 -0
  582. package/src/serve/entries/active-auth.ts +100 -0
  583. package/src/serve/entries/ai.ts +27 -1
  584. package/src/serve/entries/auth-helper-core.ts +5 -0
  585. package/src/serve/entries/auth-helper-dom.ts +27 -3
  586. package/src/serve/entries/auth-helper-runtime.ts +1 -1
  587. package/src/serve/entries/auth.ts +8 -0
  588. package/src/serve/entries/bridge-url.ts +1 -1
  589. package/src/serve/entries/firestore.ts +3 -3
  590. package/src/serve/entries/init.ts +78 -3
  591. package/src/serve/entries/keepalive.ts +1 -1
  592. package/src/serve/entries/runtime.ts +29 -14
  593. package/src/serve/entries/storage.ts +1 -1
  594. package/src/serve/entries/worker-runtime.ts +1 -1
  595. package/src/serve/init-payload.ts +4 -0
  596. package/src/serve/namespace.ts +117 -145
  597. package/src/serve/rules.ts +47 -22
  598. package/src/serve/runtime/chip-config.ts +16 -2
  599. package/src/serve/runtime/chip-dialog.ts +366 -0
  600. package/src/serve/runtime/chip-install.ts +10 -4
  601. package/src/serve/runtime/chip-user-search.ts +391 -0
  602. package/src/serve/runtime/chip.ts +177 -15
  603. package/src/serve/runtime/identity.ts +26 -0
  604. package/src/serve/runtime/manifest.ts +1 -1
  605. package/src/serve/runtime/status.ts +24 -0
  606. package/src/serve/sandbox-session.ts +19 -4
  607. package/src/serve/server.ts +18 -1
  608. package/src/serve/studio/disk-workspace.ts +76 -2
  609. package/src/serve/studio/routes.ts +63 -7
  610. package/src/serve/vite-ai-config.ts +37 -7
  611. package/src/serve/vite-module-swap.ts +0 -28
  612. package/src/serve/vite-plugin.ts +8 -8
  613. package/src/serve/vite-sandbox-generation.ts +16 -1
  614. package/src/serve/worker/client/auth.ts +1 -1
  615. package/src/serve/worker/client/core.ts +80 -3
  616. package/src/serve/worker/client/disconnect.ts +1 -1
  617. package/src/serve/worker/client/presence.ts +25 -5
  618. package/src/serve/worker/client.ts +1 -1
  619. package/src/serve/worker/context-resolver.ts +60 -0
  620. package/src/serve/worker/entry.ts +22 -18
  621. package/src/serve/worker/host/core.ts +9 -7
  622. package/src/serve/worker/host/storage.ts +2 -2
  623. package/src/serve/worker/host-ai.ts +15 -0
  624. package/src/serve/worker/host-auth.ts +1 -1
  625. package/src/serve/worker/index.ts +4 -1
  626. package/src/serve/worker/port-lifecycle.ts +45 -0
  627. package/src/serve/worker/protocol.ts +2 -1
  628. package/src/serve/worker/serve-init.ts +14 -3
  629. package/src/verify/fixture.ts +1 -1
  630. package/README.md.orig +0 -145
  631. package/dist/cli/dev-runner.d.ts.map +0 -1
  632. package/dist/cli/dev-runner.js.map +0 -1
  633. package/dist/serve/site-ui/_astro/_slug_.CXh9yTP1.css +0 -1
  634. package/dist/serve/site-ui/_astro/_slug_.CupVK4TM.css +0 -1
  635. package/dist/serve/site-ui/_astro/_studio_.CfxiQWkk.css +0 -1
  636. package/dist/serve/site-ui/_astro/app.BsFsMjn0.css +0 -1
  637. package/dist/serve/site-ui/_astro/app.Ce3MTLQm.js +0 -1
  638. package/dist/serve/site-ui/_astro/app.taqzyjD0.js +0 -11
  639. package/dist/serve/site-ui/_astro/sandbox-controls.BP4M5f1M.js +0 -1169
  640. package/dist/serve/site-ui/_astro/writes.C57paAj2.js +0 -99
  641. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +0 -582
  642. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research.md +0 -448
@@ -6,6 +6,8 @@
6
6
  * the injected init script + shared chunks)
7
7
  * /__pyric/init.json the page init payload (rules, bridge URL) —
8
8
  * fetched by the runtime chunk at module init
9
+ * /__pyric/beacon the handshake beacon a pyric-launched child
10
+ * POSTs once its interception is installed
9
11
  *
10
12
  * Bridge routes (`/__pyric/mcp`, `/__pyric/sandbox`) mount here in P2.
11
13
  */
@@ -18,10 +20,14 @@ import { collectBody } from '../bridge/server/peer.js';
18
20
  import { StateFileError, type StateSection, type StateStore } from './state-store.js';
19
21
  import { createWriterLock, type WriterLock } from './writer-lock.js';
20
22
  import { createStudioRoutes, type StudioRouteOptions } from './studio/index.js';
21
- import { pipeFileToResponse, type ServeLogger } from './server.js';
23
+ import { pipeFileToResponse, getHeader, isAllowedHost, isAllowedOrigin, type ServeLogger } from './server.js';
22
24
  import type { InitPayload } from './init-payload.js';
23
25
  import { handleActivity } from './activity-route.js';
26
+ import { handleAiProxy, AI_PROXY_ROUTE } from './ai-proxy.js';
27
+ import { aiTerminalBlockFor, type AiDiagnosticPayload } from './ai-terminal-blocks.js';
24
28
  import { createSiteTreeHandler } from './site-tree.js';
29
+ import { BEACON_PATH, type BeaconReport } from '../register/beacon.js';
30
+ import { handleBeacon } from './beacon-route.js';
25
31
  export type { InitPayload } from './init-payload.js';
26
32
 
27
33
  /**
@@ -107,144 +113,34 @@ export interface NamespaceOptions {
107
113
  * (disk-backed `WorkspaceStore`/`ProjectStore`, plus the SSE watch stream)
108
114
  * that `@pyric/studio`'s `local` mode talks to. */
109
115
  studio?: StudioRouteOptions;
116
+ /** Per-boot session capability token required on workspace and project endpoints. */
117
+ sessionToken?: string;
118
+ /** Bound host for DNS rebinding guard. */
119
+ boundHost?: string;
120
+ /** Extra allowed hostnames. */
121
+ allowedHosts?: string[];
110
122
  /** The OpenAI-compatible upstream `/__pyric/ai-proxy` forwards to
111
123
  * (pyric/ai — cdd-deltas #98.2). Falls back to the
112
124
  * `PYRIC_AI_PROXY_UPSTREAM` env var, then `http://localhost:11434/v1`
113
125
  * (local Ollama). Always mounted — the route only touches the network
114
126
  * when a request arrives. */
115
127
  aiProxyUpstream?: string;
116
- /** Where hot-reload/diagnostic lines print (rules reload, denial relay).
117
- * Absent diagnostics are dropped (a caller that wires no logger opts out
118
- * silently rather than falling back to raw `console`). */
128
+ /** Receives one handshake beacon per pyric-launched child (`POST
129
+ * /__pyric/beacon`, sent by `@pyric/cli/register` once its hooks and
130
+ * net-guard are installed). Absent means the route still 204s; the child
131
+ * must never be able to fail on its own proof-of-life. */
132
+ beacon?: (report: BeaconReport) => void;
133
+ /** The per-launch secret a beacon must present in `x-pyric-beacon-token`,
134
+ * which the launcher puts in the child's `PYRIC_BEACON_TOKEN`. Absent means
135
+ * one is generated that nobody holds, so the route accepts nothing. */
136
+ beaconToken?: string;
137
+ /** Where hot-reload/diagnostic lines print (rules reload, denial relay,
138
+ * AI broker diagnostics, ai-proxy upstream failures). Absent ⇒ diagnostics
139
+ * are dropped (a caller that wires no logger opts out silently rather than
140
+ * falling back to raw `console`). */
119
141
  logger?: ServeLogger;
120
142
  }
121
143
 
122
- // ─── AI proxy (`/__pyric/ai-proxy` — pyric/ai, cdd-deltas #98.2) ───────────
123
-
124
- /** Default upstream: local Ollama's OpenAI-compatible endpoint. */
125
- export const AI_PROXY_DEFAULT_UPSTREAM = 'http://localhost:11434/v1';
126
-
127
- /**
128
- * Request headers that must NOT be forwarded upstream: origin-sensitive
129
- * browser context (`origin`/`referer`/`cookie` — the upstream is a different
130
- * origin and must never see the page's), hop-by-hop headers, and the two the
131
- * proxy re-derives (`host`, `content-length`). `accept-encoding` is dropped
132
- * so fetch negotiates its own compression and the streamed body needs no
133
- * length fixups.
134
- */
135
- const AI_PROXY_STRIPPED_HEADERS = new Set([
136
- 'host',
137
- 'origin',
138
- 'referer',
139
- 'cookie',
140
- 'connection',
141
- 'content-length',
142
- 'accept-encoding',
143
- 'keep-alive',
144
- 'proxy-authorization',
145
- 'te',
146
- 'trailer',
147
- 'transfer-encoding',
148
- 'upgrade',
149
- ]);
150
-
151
- /**
152
- * Handle `POST /__pyric/ai-proxy/<suffix>` — a same-origin passthrough to the
153
- * configured OpenAI-compatible upstream, so the browser openai engine
154
- * (running in the served page or the SharedWorker host) reaches a localhost
155
- * upstream like Ollama with ZERO CORS setup (no `OLLAMA_ORIGINS`, ever).
156
- *
157
- * Behavior:
158
- * - POST only (the OpenAI chat-completions surface is POST); 405 otherwise.
159
- * - the path suffix + query ride through verbatim
160
- * (`/__pyric/ai-proxy/chat/completions` → `<upstream>/chat/completions`).
161
- * - the request body is forwarded verbatim; headers minus the
162
- * origin-sensitive/hop-by-hop set above (`authorization` DOES forward —
163
- * upstreams may require a key).
164
- * - the response body is STREAMED through chunk-by-chunk — SSE passthrough
165
- * must never buffer, or `stream: true` completions would arrive all at
166
- * once at the end.
167
- * - an unreachable upstream answers 502 with a plain-text explanation.
168
- */
169
- async function handleAiProxy(
170
- configuredUpstream: string | undefined,
171
- req: IncomingMessage,
172
- res: ServerResponse,
173
- url: URL,
174
- ): Promise<void> {
175
- if (req.method !== 'POST') {
176
- res.writeHead(405, { allow: 'POST' }).end('method not allowed');
177
- return;
178
- }
179
- const upstreamBase = (
180
- configuredUpstream ??
181
- process.env.PYRIC_AI_PROXY_UPSTREAM ??
182
- AI_PROXY_DEFAULT_UPSTREAM
183
- ).replace(/\/$/, '');
184
- const suffix = url.pathname.slice('/__pyric/ai-proxy'.length);
185
- const target = `${upstreamBase}${suffix}${url.search}`;
186
-
187
- // Buffer the REQUEST body (small JSON payloads); the RESPONSE streams.
188
- const raw = await new Promise<Buffer>((resolve, reject) => {
189
- const chunks: Buffer[] = [];
190
- req.on('data', (c: Buffer) => chunks.push(c));
191
- req.on('end', () => resolve(Buffer.concat(chunks)));
192
- req.on('error', reject);
193
- });
194
- // Copy into a plain-ArrayBuffer view — fetch's BodyInit typing rejects
195
- // Buffer's ArrayBufferLike backing.
196
- const body = new Uint8Array(raw.byteLength);
197
- body.set(raw);
198
-
199
- const headers: Record<string, string> = {};
200
- for (const [key, value] of Object.entries(req.headers)) {
201
- if (value === undefined) continue;
202
- if (AI_PROXY_STRIPPED_HEADERS.has(key.toLowerCase())) continue;
203
- headers[key] = Array.isArray(value) ? value.join(', ') : value;
204
- }
205
-
206
- let upstream: Response;
207
- try {
208
- upstream = await fetch(target, { method: 'POST', headers, body });
209
- } catch (e) {
210
- res.writeHead(502, { 'content-type': 'text/plain' });
211
- res.end(
212
- `pyric dev ai-proxy: upstream ${target} unreachable: ` +
213
- `${e instanceof Error ? e.message : String(e)}\n` +
214
- 'Set PYRIC_AI_PROXY_UPSTREAM to an OpenAI-compatible base URL ' +
215
- `(default ${AI_PROXY_DEFAULT_UPSTREAM}).`,
216
- );
217
- return;
218
- }
219
-
220
- const responseHeaders: Record<string, string> = { 'cache-control': 'no-store' };
221
- const contentType = upstream.headers.get('content-type');
222
- if (contentType) responseHeaders['content-type'] = contentType;
223
- res.writeHead(upstream.status, responseHeaders);
224
- if (!upstream.body) {
225
- res.end();
226
- return;
227
- }
228
- (res as ServerResponse & { flushHeaders?: () => void }).flushHeaders?.();
229
-
230
- // Chunk-by-chunk passthrough. A dropped client cancels the upstream read
231
- // so an abandoned SSE stream doesn't keep the upstream generating.
232
- const reader = upstream.body.getReader();
233
- res.on('close', () => {
234
- void reader.cancel().catch(() => {});
235
- });
236
- try {
237
- for (;;) {
238
- const { done, value } = await reader.read();
239
- if (done) break;
240
- res.write(value);
241
- }
242
- } catch {
243
- // Upstream or client dropped mid-stream — nothing to salvage.
244
- }
245
- res.end();
246
- }
247
-
248
144
  /** The page's persistence backend speaks this route:
249
145
  * GET /__pyric/state → whole envelope (404 when absent)
250
146
  * GET /__pyric/state?section=firestore → that section (404 when null)
@@ -384,6 +280,18 @@ async function handleCapture(
384
280
  // An agent driving `pyric dev` headlessly has no browser console to watch;
385
281
  // this is that visibility, printed to the terminal instead.
386
282
  //
283
+ // The route carries the AI broker's diagnostics on the same channel, relayed
284
+ // by `serve/ai-diagnostics-relay.ts` off the sandbox event stream:
285
+ // `request_rejected` (a malformed request) and `response_blocked` (a safety
286
+ // or recitation filter withheld the answer). Same category ("the sandbox
287
+ // refused your operation"), same terminal treatment, same throttle, so they
288
+ // ride here rather than opening parallel diagnostics channels.
289
+ // `model_substituted` (an engine answered as a model the code never named)
290
+ // rides along too: not a refusal, but the same "the sandbox quietly did
291
+ // something else" category. The payload's `kind` discriminates the four, and
292
+ // `ai-terminal-blocks.ts` holds one record per AI kind so this route
293
+ // dispatches through a table instead of a cascade.
294
+ //
387
295
  // A denied listener re-fires on every auth/rules change, so printing is
388
296
  // throttled per (path, message) pair — at most one line per window, and
389
297
  // silent (no output at all) on suppression rather than a "suppressed N more"
@@ -443,9 +351,21 @@ export function formatDenialBlock(payload: DenialRelayPayload): string {
443
351
  return lines.join('\n');
444
352
  }
445
353
 
446
- /** Handle `POST /__pyric/denials`. Always 204s (best-effort diagnostics —
447
- * a malformed body or a caller with no logger wired must never fail the
448
- * page that reported the denial). */
354
+ /**
355
+ * The throttle key separator: a NUL byte, written as an escape so the file
356
+ * stays greppable. It cannot occur in a Firestore path, a model id, or a
357
+ * rejection reason, so no (target, reason) pair can be spelled two ways.
358
+ */
359
+ const THROTTLE_KEY_SEPARATOR = '\x00';
360
+
361
+ /** Handle `POST /__pyric/denials`: a rules denial, or (discriminated by
362
+ * `kind`) an AI broker rejection, blocked response, or model substitution
363
+ * relayed off the sandbox event stream. All four share the throttle map: an
364
+ * agent retry loop re-sends the SAME malformed (or filter-tripping) AI
365
+ * request exactly the way a denied listener re-fires, so one line per
366
+ * (target, reason) per window is the right volume for every one of them.
367
+ * Always 204s (best-effort diagnostics: a malformed body or a caller with no
368
+ * logger wired must never fail the page that reported the refusal). */
449
369
  async function handleDenials(
450
370
  throttle: DenialThrottle,
451
371
  logger: ServeLogger | undefined,
@@ -457,22 +377,48 @@ async function handleDenials(
457
377
  return;
458
378
  }
459
379
  try {
460
- const payload = (await collectBody(req)) as DenialRelayPayload;
461
- const message = typeof payload.message === 'string' ? payload.message : 'permission denied';
462
- const path = payload.denialContext?.request?.path ?? '';
463
- const key = `${path}${message}`;
380
+ const payload = (await collectBody(req)) as DenialRelayPayload & AiDiagnosticPayload;
381
+ const aiBlock = aiTerminalBlockFor(payload.kind);
382
+ let target: string;
383
+ let reason: string;
384
+ let render: () => string;
385
+ if (aiBlock === null) {
386
+ target = payload.denialContext?.request?.path ?? '';
387
+ reason = typeof payload.message === 'string' ? payload.message : 'permission denied';
388
+ render = () => formatDenialBlock(payload);
389
+ } else {
390
+ target = aiBlock.throttleTarget(payload);
391
+ reason = aiBlock.throttleReason(payload);
392
+ render = () => aiBlock.format(payload);
393
+ }
394
+ const key = `${target}${THROTTLE_KEY_SEPARATOR}${reason}`;
464
395
  if (logger && throttle.shouldPrint(key, Date.now())) {
465
- logger.note(formatDenialBlock(payload));
396
+ logger.note(render());
466
397
  }
467
398
  } catch {
468
- /* malformed body drop it; this is a diagnostics side channel */
399
+ /* malformed body: drop it; this is a diagnostics side channel */
469
400
  }
470
401
  res.writeHead(204).end();
471
402
  }
472
403
 
473
404
  export function createPyricNamespace(opts: NamespaceOptions) {
474
- const writerLock = createWriterLock();
475
- const studioRoutes = opts.studio ? createStudioRoutes(opts.studio) : null;
405
+ const stateWriterLock = createWriterLock();
406
+ const studioWriterLock = opts.studio?.writerLock ?? createWriterLock();
407
+ const sessionToken = opts.sessionToken ?? randomBytes(24).toString('base64url');
408
+ // Fail closed: with no launcher-supplied secret the generated one is held by
409
+ // nobody, so `/__pyric/beacon` accepts nothing rather than everything.
410
+ const beaconToken = opts.beaconToken ?? randomBytes(24).toString('base64url');
411
+ let studioRoutes: ((req: IncomingMessage, res: ServerResponse, url: URL) => Promise<boolean>) | null = null;
412
+ if (opts.studio) {
413
+ const studioOptions: StudioRouteOptions = {
414
+ ...opts.studio,
415
+ sessionToken,
416
+ writerLock: studioWriterLock,
417
+ boundHost: opts.boundHost,
418
+ allowedHosts: opts.allowedHosts,
419
+ };
420
+ studioRoutes = createStudioRoutes(studioOptions);
421
+ }
476
422
  const siteTree = opts.siteUiDir
477
423
  ? createSiteTreeHandler(opts.siteUiDir, opts.workerVersion)
478
424
  : null;
@@ -489,7 +435,7 @@ export function createPyricNamespace(opts: NamespaceOptions) {
489
435
  return studioRoutes(req, res, url);
490
436
  }
491
437
  if (opts.state && url.pathname === '/__pyric/state') {
492
- return handleState(opts.state!, writerLock, req, res, url).then(() => true);
438
+ return handleState(opts.state!, stateWriterLock, req, res, url).then(() => true);
493
439
  }
494
440
  if (opts.capture && url.pathname === '/__pyric/capture') {
495
441
  return handleCapture(opts.capture, req, res).then(() => true);
@@ -498,18 +444,44 @@ export function createPyricNamespace(opts: NamespaceOptions) {
498
444
  return handleActivity(opts.activity, req, res, activityToken!).then(() => true);
499
445
  }
500
446
  if (opts.events && url.pathname === '/__pyric/events') {
447
+ const hostHeader = getHeader(req, 'host');
448
+ const originHeader = getHeader(req, 'origin');
449
+ if (!isAllowedHost(hostHeader, opts.boundHost ?? 'localhost', opts.allowedHosts)) {
450
+ res.writeHead(403, { 'content-type': 'text/plain' }).end('Forbidden: host not allowed');
451
+ return true;
452
+ }
453
+ if (originHeader && !isAllowedOrigin(originHeader, opts.boundHost ?? 'localhost', opts.allowedHosts)) {
454
+ res.writeHead(403, { 'content-type': 'text/plain' }).end('Forbidden: origin mismatch');
455
+ return true;
456
+ }
457
+ const reqToken = getHeader(req, 'x-pyric-session-token') ?? url.searchParams.get('token');
458
+ if (sessionToken && reqToken && reqToken !== sessionToken) {
459
+ res.writeHead(401, { 'content-type': 'text/plain' }).end('Unauthorized: invalid session capability token');
460
+ return true;
461
+ }
501
462
  opts.events.handle(req, res);
502
463
  return true;
503
464
  }
504
- if (url.pathname === '/__pyric/ai-proxy' || url.pathname.startsWith('/__pyric/ai-proxy/')) {
505
- return handleAiProxy(opts.aiProxyUpstream, req, res, url).then(() => true);
465
+ if (url.pathname === AI_PROXY_ROUTE || url.pathname.startsWith(`${AI_PROXY_ROUTE}/`)) {
466
+ return handleAiProxy(opts.aiProxyUpstream, denialThrottle, req, res, url, opts.logger).then(
467
+ () => true,
468
+ );
469
+ }
470
+ if (url.pathname === BEACON_PATH) {
471
+ return handleBeacon({ token: beaconToken, onBeacon: opts.beacon }, req, res).then(() => true);
506
472
  }
507
473
  if (url.pathname === '/__pyric/denials') {
508
474
  return handleDenials(denialThrottle, opts.logger, req, res).then(() => true);
509
475
  }
510
476
  if (url.pathname === '/__pyric/init.json') {
511
477
  res.writeHead(200, { 'content-type': 'application/json; charset=utf-8', 'cache-control': 'no-store' });
512
- res.end(JSON.stringify({ ...opts.initPayload(), ...(activityToken ? { activityToken } : {}) }));
478
+ res.end(
479
+ JSON.stringify({
480
+ ...opts.initPayload(),
481
+ sessionToken,
482
+ ...(activityToken ? { activityToken } : {}),
483
+ }),
484
+ );
513
485
  return true;
514
486
  }
515
487
  if (url.pathname.startsWith('/__pyric/sdk/')) {
@@ -56,7 +56,7 @@ export function prepareRulesSource(raw: string, sourcePath: string): string {
56
56
  const resolved = resolveModulesBrowser(raw);
57
57
  if (!resolved.success) {
58
58
  throw new Error(
59
- `pyric dev: ${sourcePath} uses 2+modules but module resolution failed: ${resolved.error.message}`,
59
+ `pyric sandbox: ${sourcePath} uses 2+modules but module resolution failed: ${resolved.error.message}`,
60
60
  );
61
61
  }
62
62
  source = resolved.data.resolved;
@@ -65,13 +65,13 @@ export function prepareRulesSource(raw: string, sourcePath: string): string {
65
65
  if (lint.parseError) {
66
66
  const { line, column } = lint.parseError;
67
67
  throw new Error(
68
- `pyric dev: ${sourcePath} failed to parse (line ${line}, col ${column}) fix the rules before serving.`,
68
+ `pyric sandbox: ${sourcePath} failed to parse (line ${line}, col ${column}). Fix the rules before serving.`,
69
69
  );
70
70
  }
71
71
  const errors = lint.warnings.filter((w) => w.severity === 'error');
72
72
  if (errors.length > 0) {
73
73
  throw new Error(
74
- `pyric dev: ${sourcePath} has ${errors.length} rules error(s):\n` +
74
+ `pyric sandbox: ${sourcePath} has ${errors.length} rules error(s):\n` +
75
75
  errors.map((e) => ` - ${e.message}`).join('\n'),
76
76
  );
77
77
  }
@@ -98,7 +98,7 @@ export async function loadProjectRules(
98
98
  } catch (e) {
99
99
  if ((e as NodeJS.ErrnoException).code === 'ENOENT') {
100
100
  if (configured) {
101
- throw new Error(`pyric dev: firebase.json points firestore.rules at ${path}, but it does not exist.`);
101
+ throw new Error(`pyric sandbox: firebase.json points firestore.rules at ${path}, but it does not exist.`);
102
102
  }
103
103
  return { rules: null, rulesHash: null, sourcePath: null };
104
104
  }
@@ -119,7 +119,7 @@ export function prepareStorageRulesSource(raw: string, sourcePath: string): stri
119
119
  const resolved = resolveModulesBrowser(raw, { sourceFile: sourcePath });
120
120
  if (!resolved.success) {
121
121
  throw new Error(
122
- `pyric dev: ${sourcePath} uses 2+modules but module resolution failed: ${resolved.error.message}`,
122
+ `pyric sandbox: ${sourcePath} uses 2+modules but module resolution failed: ${resolved.error.message}`,
123
123
  );
124
124
  }
125
125
  source = resolved.data.resolved;
@@ -128,7 +128,7 @@ export function prepareStorageRulesSource(raw: string, sourcePath: string): stri
128
128
  parseStorageRules(source);
129
129
  } catch (e) {
130
130
  throw new Error(
131
- `pyric dev: ${sourcePath} failed to parse: ${e instanceof Error ? e.message : String(e)} fix the rules before serving.`,
131
+ `pyric sandbox: ${sourcePath} failed to parse: ${e instanceof Error ? e.message : String(e)}. Fix the rules before serving.`,
132
132
  );
133
133
  }
134
134
  return source;
@@ -159,7 +159,7 @@ export async function loadProjectStorageRules(
159
159
  } catch (e) {
160
160
  if ((e as NodeJS.ErrnoException).code === 'ENOENT') {
161
161
  if (configured) {
162
- throw new Error(`pyric dev: firebase.json points storage.rules at ${path}, but it does not exist.`);
162
+ throw new Error(`pyric sandbox: firebase.json points storage.rules at ${path}, but it does not exist.`);
163
163
  }
164
164
  return { rules: null, rulesHash: null, sourcePath: null };
165
165
  }
@@ -169,27 +169,52 @@ export async function loadProjectStorageRules(
169
169
  return { rules, rulesHash: rulesHashOf(rules), sourcePath: path };
170
170
  }
171
171
 
172
+ function normalizeDatabaseEntries(block: unknown): Array<Record<string, unknown>> {
173
+ if (!block) {
174
+ return [];
175
+ }
176
+ if (Array.isArray(block)) {
177
+ return block.filter((item): item is Record<string, unknown> => typeof item === 'object' && item !== null);
178
+ }
179
+ if (typeof block === 'object' && block !== null) {
180
+ return [block as Record<string, unknown>];
181
+ }
182
+ return [];
183
+ }
184
+
185
+ function hasConfiguredRules(entry: Record<string, unknown>): entry is Record<string, unknown> & { rules: string } {
186
+ return typeof entry.rules === 'string';
187
+ }
188
+
189
+ function hasConfiguredUrl(entry: Record<string, unknown>): entry is Record<string, unknown> & { url: string } {
190
+ return typeof entry.url === 'string';
191
+ }
192
+
172
193
  export async function loadProjectDatabaseRules(
173
194
  cwd: string,
174
195
  config: FirebaseJson | null,
175
196
  ): Promise<LoadedDatabaseRules> {
176
- const configured = config?.database?.rules;
177
- if (!configured) {
178
- return {
179
- rules: null,
180
- rulesHash: null,
181
- sourcePath: null,
182
- databaseUrl: config?.database?.url ?? null,
183
- };
184
- }
185
-
186
- const path = isAbsolute(configured) ? configured : join(cwd, configured);
197
+ const entries = normalizeDatabaseEntries(config?.database);
198
+ const configuredEntry = entries.find(hasConfiguredRules);
199
+ const configured = configuredEntry?.rules;
200
+ const rel = configured ?? 'database.rules.json';
201
+ const path = isAbsolute(rel) ? rel : join(cwd, rel);
202
+ const urlEntry = entries.find(hasConfiguredUrl);
203
+ const databaseUrl = urlEntry?.url ?? null;
187
204
  let raw: string;
188
205
  try {
189
206
  raw = await readFile(path, 'utf8');
190
207
  } catch (e) {
191
208
  if ((e as NodeJS.ErrnoException).code === 'ENOENT') {
192
- throw new Error(`pyric dev: firebase.json points database.rules at ${path}, but it does not exist.`);
209
+ if (configured) {
210
+ throw new Error(`pyric sandbox: firebase.json points database.rules at ${path}, but it does not exist.`);
211
+ }
212
+ return {
213
+ rules: null,
214
+ rulesHash: null,
215
+ sourcePath: null,
216
+ databaseUrl,
217
+ };
193
218
  }
194
219
  throw e;
195
220
  }
@@ -198,18 +223,18 @@ export async function loadProjectDatabaseRules(
198
223
  try {
199
224
  parsed = JSON.parse(stripJsonComments(raw));
200
225
  } catch (e) {
201
- throw new Error(`pyric dev: ${path} failed to parse as RTDB rules JSON: ${e instanceof Error ? e.message : String(e)}`);
226
+ throw new Error(`pyric sandbox: ${path} failed to parse as RTDB rules JSON: ${e instanceof Error ? e.message : String(e)}`);
202
227
  }
203
228
  const rules = parseRtdbRulesJson(
204
229
  parsed,
205
- () => new Error(`pyric dev: ${path} must contain a top-level "rules" object.`),
230
+ () => new Error(`pyric sandbox: ${path} must contain a top-level "rules" object.`),
206
231
  );
207
232
 
208
233
  return {
209
234
  rules,
210
235
  rulesHash: rulesHashOf(raw),
211
236
  sourcePath: path,
212
- databaseUrl: config?.database?.url ?? null,
237
+ databaseUrl,
213
238
  };
214
239
  }
215
240
 
@@ -17,8 +17,22 @@ interface RuntimeChipDocument {
17
17
  querySelector(selector: string): { getAttribute(name: string): string | null } | null;
18
18
  }
19
19
 
20
+ /** Read the browser-inlined chip value, preferring the `NEXT_PUBLIC_`-prefixed
21
+ * name (the only one Next.js is guaranteed to expose to client bundles) and
22
+ * falling back to the unprefixed name for other bundlers/back-compat. */
23
+ function bundlerRuntimeChipValue(): string | undefined {
24
+ if (typeof process === 'undefined' || typeof process.env === 'undefined') return undefined;
25
+ if (typeof process.env.NEXT_PUBLIC_PYRIC_RUNTIME_CHIP === 'string') {
26
+ return process.env.NEXT_PUBLIC_PYRIC_RUNTIME_CHIP;
27
+ }
28
+ if (typeof process.env.PYRIC_RUNTIME_CHIP === 'string') {
29
+ return process.env.PYRIC_RUNTIME_CHIP;
30
+ }
31
+ return undefined;
32
+ }
33
+
20
34
  function hasBundlerRuntimeChipConfig(): boolean {
21
- return typeof process !== 'undefined' && typeof process.env !== 'undefined' && typeof process.env.PYRIC_RUNTIME_CHIP === 'string';
35
+ return bundlerRuntimeChipValue() !== undefined;
22
36
  }
23
37
 
24
38
  /** Read plugin-authored values from DOM metadata or bundler environment variables, defaulting to collapsed UI when omitted. */
@@ -31,7 +45,7 @@ export function readPyricRuntimeChipConfig(
31
45
 
32
46
  const shouldFallbackToEnv = !hasMetaTag && hasBundlerRuntimeChipConfig();
33
47
  if (shouldFallbackToEnv) {
34
- value = process.env.PYRIC_RUNTIME_CHIP as string;
48
+ value = bundlerRuntimeChipValue() as string;
35
49
  }
36
50
  if (value === 'off') {
37
51
  return null;