@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
@@ -1,8 +1,20 @@
1
+ import type { AuthLens } from 'pyric/sandbox';
1
2
  import type {
2
3
  PyricRuntimeError,
3
4
  PyricRuntimeSnapshot,
4
5
  PyricRuntimeStatus,
5
6
  } from './status.js';
7
+ import {
8
+ createChipDialogController,
9
+ DIALOG_STYLES,
10
+ type ChipDialogController,
11
+ } from './chip-dialog.js';
12
+ import type { RuntimeIdentity, RuntimeIdentityBindings } from './identity.js';
13
+ import {
14
+ getLens as defaultGetLens,
15
+ setLens as defaultSetLens,
16
+ subscribeLens as defaultSubscribeLens,
17
+ } from '../worker/client/core.js';
6
18
 
7
19
  export interface PyricRuntimeChipOptions {
8
20
  runtime: PyricRuntimeStatus;
@@ -11,6 +23,14 @@ export interface PyricRuntimeChipOptions {
11
23
  initiallyOpen?: boolean;
12
24
  /** Override Studio availability. Omitted uses the runtime manifest URL. */
13
25
  studioUrl?: string | null;
26
+ /** Optional identity integration. Missing operations use lens/no-op fallbacks. */
27
+ identity?: Partial<RuntimeIdentityBindings>;
28
+ /** Injectable lens getter (defaults to worker client getLens). */
29
+ getLens?: () => AuthLens | undefined;
30
+ /** Injectable lens setter (defaults to worker client setLens). */
31
+ setLens?: (lens: AuthLens | undefined) => void;
32
+ /** Injectable lens subscription (defaults to worker client subscribeLens). */
33
+ subscribeLens?: (listener: (lens: AuthLens | undefined) => void) => () => void;
14
34
  }
15
35
 
16
36
  export interface PyricRuntimeChip {
@@ -18,6 +38,32 @@ export interface PyricRuntimeChip {
18
38
  dispose(): void;
19
39
  }
20
40
 
41
+ interface AiEngineDisplay {
42
+ primary: string;
43
+ subline: string | null;
44
+ }
45
+
46
+ function aiEngineState(): AiEngineDisplay {
47
+ const engine = (globalThis as { __PYRIC_AI_ENGINE__?: { kind?: string; model?: string } }).__PYRIC_AI_ENGINE__;
48
+ if (engine?.kind === 'gemini') {
49
+ return {
50
+ primary: 'gemini (production)',
51
+ subline: 'gemini-3.5-flash-lite → gemini-flash-lite-latest',
52
+ };
53
+ }
54
+ if (engine?.kind === 'openai') {
55
+ const modelLabel = engine.model ? ` (${engine.model})` : '';
56
+ return {
57
+ primary: `openai (proxy${modelLabel})`,
58
+ subline: null,
59
+ };
60
+ }
61
+ return {
62
+ primary: 'sandbox (scripted)',
63
+ subline: null,
64
+ };
65
+ }
66
+
21
67
  const styles = `
22
68
  :host {
23
69
  --pyric-bg: #1e1e24;
@@ -63,9 +109,14 @@ const styles = `
63
109
  .brand-label { font-size: 11px; }
64
110
  .signals { color: var(--pyric-muted); font-size: 10px; gap: 8px; }
65
111
  .signal { gap: 4px; white-space: nowrap; }
112
+ .signal[data-identity-badge] {
113
+ max-width: 140px;
114
+ overflow: hidden;
115
+ text-overflow: ellipsis;
116
+ }
66
117
  .dot { background: var(--pyric-accent); border-radius: 50%; height: 8px; width: 8px; }
67
- .dot.error { background: var(--pyric-error); box-shadow: 0 0 0 3px rgba(240,160,160,.12); }
68
118
  .signal.update { color: var(--pyric-warning); }
119
+ .signal.bypass { color: #8f7fe8; font-weight: 500; }
69
120
  .chevron { color: var(--pyric-muted); height: 14px; width: 14px; }
70
121
  .panel {
71
122
  background: var(--pyric-bg);
@@ -86,8 +137,11 @@ const styles = `
86
137
  .icon-button[data-copy-failed] { color: var(--pyric-error); }
87
138
  .icon { height: 15px; width: 15px; }
88
139
  .worker-state { border-top: 1px solid var(--pyric-border-soft); color: var(--pyric-muted); font-size: 10px; justify-content: space-between; min-height: 34px; padding: 7px 12px; }
140
+ .worker-state-col { border-top: 1px solid var(--pyric-border-soft); color: var(--pyric-muted); font-size: 10px; display: flex; flex-direction: column; min-height: 34px; padding: 7px 12px; }
141
+ .worker-state-row { align-items: center; display: flex; justify-content: space-between; width: 100%; }
142
+ .worker-state-subline { color: #89899f; font: 9px/1.4 ui-monospace, monospace; margin-top: 4px; overflow-wrap: anywhere; text-align: right; width: 100%; }
89
143
  .worker-state .available { color: var(--pyric-warning); }
90
- .worker-state .state-label { align-items: center; display: flex; gap: 7px; }
144
+ .worker-state .state-label, .worker-state-col .state-label { align-items: center; display: flex; gap: 7px; white-space: nowrap; }
91
145
  .mini-dot { background: var(--pyric-accent); border-radius: 50%; height: 6px; width: 6px; }
92
146
  .available .mini-dot { background: var(--pyric-warning); }
93
147
  .epochs { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@@ -104,7 +158,7 @@ const styles = `
104
158
  .error-body code { color: #d7d7df; display: block; font-size: 11px; line-height: 1.55; overflow-wrap: anywhere; white-space: pre-wrap; }
105
159
  .error-meta { color: var(--pyric-muted); font: 9px/1.4 ui-monospace, monospace; margin-top: 4px; overflow-wrap: anywhere; }
106
160
  .empty { align-items: center; color: var(--pyric-muted); display: flex; font: 11px/1.5 ui-monospace, monospace; min-height: 57px; padding: 12px; }
107
- .actions { display: grid; gap: 8px; grid-template-columns: 1fr 1fr; min-height: 56px; padding: 10px 12px; }
161
+ .actions { display: grid; gap: 8px; grid-template-columns: repeat(3, 1fr); min-height: 56px; padding: 10px 12px; }
108
162
  .button { align-items: center; background: transparent; border: 1px solid var(--pyric-border-soft); border-radius: 4px; color: var(--pyric-muted); display: inline-flex; font-size: 10px; justify-content: center; letter-spacing: .06em; min-height: 34px; padding: 6px 8px; text-decoration: none; text-transform: uppercase; }
109
163
  button.button { cursor: pointer; }
110
164
  .button:hover:not(:disabled):not([aria-disabled="true"]), a.button:hover { border-color: #3a3a48; color: var(--pyric-text); }
@@ -121,6 +175,8 @@ const styles = `
121
175
  .chip, .panel { animation: pyric-enter 120ms ease-out; transform-origin: bottom right; }
122
176
  @keyframes pyric-enter { from { opacity: 0; transform: translateY(4px) scale(.98); } }
123
177
  }
178
+
179
+ ${DIALOG_STYLES}
124
180
  `;
125
181
 
126
182
  const icons = {
@@ -132,7 +188,7 @@ const icons = {
132
188
  };
133
189
 
134
190
  function escapeAttribute(value: string): string {
135
- return value.replaceAll('&', '&amp;').replaceAll('"', '&quot;').replaceAll('<', '&lt;');
191
+ return value.replaceAll('&', '&amp;').replaceAll('"', '&quot;').replaceAll('<', '&lt;').replaceAll('>', '&gt;');
136
192
  }
137
193
 
138
194
  export function formatPyricRuntimeError(error: PyricRuntimeError): string {
@@ -160,7 +216,19 @@ function renderErrors(snapshot: PyricRuntimeSnapshot, canCopy: boolean): string
160
216
  /** Mount the framework-independent runtime chip in an isolated shadow root. */
161
217
  export function mountPyricRuntimeChip(options: PyricRuntimeChipOptions): PyricRuntimeChip {
162
218
  const documentLike = options.document ?? document;
163
- const host = documentLike.createElement('div');
219
+ const existingHost = documentLike.querySelector<HTMLElement>(
220
+ '[data-pyric-runtime-chip-host], pyric-runtime-chip',
221
+ );
222
+ if (existingHost) {
223
+ existingHost.remove();
224
+ }
225
+
226
+ let host: HTMLElement;
227
+ try {
228
+ host = documentLike.createElement('pyric-runtime-chip');
229
+ } catch {
230
+ host = documentLike.createElement('div');
231
+ }
164
232
  host.setAttribute('data-pyric-runtime-chip-host', '');
165
233
  const root = host.attachShadow({ mode: 'open' });
166
234
  root.innerHTML = `<style>${styles}</style><div class="announcer" role="status" aria-live="polite" aria-atomic="true"></div><div data-view></div>`;
@@ -174,6 +242,50 @@ export function mountPyricRuntimeChip(options: PyricRuntimeChipOptions): PyricRu
174
242
  let open = options.initiallyOpen ?? false;
175
243
  let snapshot = options.runtime.getSnapshot();
176
244
 
245
+ const getLensFn = options.getLens ?? defaultGetLens;
246
+ const setLensFn = options.setLens ?? defaultSetLens;
247
+ const subscribeLensFn = options.subscribeLens ?? defaultSubscribeLens;
248
+ const providedIdentity = options.identity;
249
+ let clientUser: RuntimeIdentity | null = null;
250
+ const readCurrentUser = (): RuntimeIdentity | null => {
251
+ if (providedIdentity?.getCurrentUser) return providedIdentity.getCurrentUser();
252
+ return clientUser;
253
+ };
254
+ clientUser = readCurrentUser();
255
+
256
+ const identity: RuntimeIdentityBindings = {
257
+ listUsers: providedIdentity?.listUsers ?? (() => []),
258
+ switchUser: async (uid) => {
259
+ if (providedIdentity?.switchUser) await providedIdentity.switchUser(uid);
260
+ else setLensFn({ mode: 'as', uid });
261
+ clientUser = readCurrentUser();
262
+ render();
263
+ },
264
+ signOut: async () => {
265
+ if (providedIdentity?.signOut) await providedIdentity.signOut();
266
+ else setLensFn(undefined);
267
+ clientUser = null;
268
+ render();
269
+ },
270
+ openCreateUser: providedIdentity?.openCreateUser ?? (() => {}),
271
+ getCurrentUser: readCurrentUser,
272
+ subscribeAuth: providedIdentity?.subscribeAuth ?? (() => () => {}),
273
+ };
274
+
275
+ const dialogController: ChipDialogController = createChipDialogController({
276
+ shadowRoot: root,
277
+ identity,
278
+ onToggleAdminBypass: (enable) => {
279
+ if (enable) {
280
+ setLensFn({ mode: 'admin' });
281
+ } else {
282
+ setLensFn(undefined);
283
+ }
284
+ render();
285
+ },
286
+ getLens: () => getLensFn(),
287
+ });
288
+
177
289
  const render = (next = snapshot): void => {
178
290
  const active = root.activeElement;
179
291
  const oldViewport = view.querySelector<HTMLElement>('[data-error-viewport]');
@@ -184,7 +296,7 @@ export function mountPyricRuntimeChip(options: PyricRuntimeChipOptions): PyricRu
184
296
  }
185
297
  : null;
186
298
  const activeCopyId = active?.getAttribute('data-copy-error');
187
- const activeControl = ['data-expand', 'data-collapse', 'data-update-worker', 'data-open-studio']
299
+ const activeControl = ['data-expand', 'data-collapse', 'data-update-worker', 'data-open-studio', 'data-open-impersonate']
188
300
  .find((attribute) => active?.hasAttribute(attribute));
189
301
  const focusToken = activeCopyId !== null && activeCopyId !== undefined
190
302
  ? { attribute: 'data-copy-error', value: activeCopyId }
@@ -199,33 +311,60 @@ export function mountPyricRuntimeChip(options: PyricRuntimeChipOptions): PyricRu
199
311
  ? 'Sandbox starting'
200
312
  : snapshot.mode === 'in-page'
201
313
  ? 'In-page sandbox'
202
- : 'Worker current';
314
+ : 'Worker version';
203
315
  const epochs = snapshot.updateAvailable
204
316
  ? `${snapshot.runningEpoch?.slice(0, 8) ?? 'unknown'} → ${snapshot.servedEpoch?.slice(0, 8) ?? 'unknown'}`
205
317
  : snapshot.runningEpoch?.slice(0, 8) ?? '';
318
+ const aiState = aiEngineState();
319
+
320
+ const lens = getLensFn();
321
+ const user = readCurrentUser();
322
+ const isAdmin = lens?.mode === 'admin';
323
+ const activeUid = lens?.mode === 'as' ? lens.uid : user?.uid;
324
+
325
+ const identitySignals: string[] = [];
326
+ let identityStateHtml = '<span class="epochs" data-identity-state>App session</span>';
327
+ if (activeUid) {
328
+ identitySignals.push(`<span class="signal" data-identity-badge title="as: ${escapeAttribute(activeUid)}">as: ${escapeAttribute(activeUid)}</span>`);
329
+ identityStateHtml = `<span class="epochs" data-identity-state data-identity-badge title="as: ${escapeAttribute(activeUid)}">as: ${escapeAttribute(activeUid)}</span>`;
330
+ }
331
+ if (isAdmin) {
332
+ identitySignals.push('<span class="signal bypass" data-identity-badge>bypass rules</span>');
333
+ }
334
+ const identitySignalHtml = identitySignals.join('');
206
335
 
207
336
  view.innerHTML = `${open ? `
208
- <section class="panel" role="dialog" aria-label="Pyric runtime">
337
+ <section class="panel" role="dialog" aria-label="pyric">
209
338
  <header class="panel-header">
210
- <div class="panel-title"><span class="brand-mark">&gt;_</span><strong>Pyric runtime</strong>${errorCount > 0 ? `<span class="count">${errorCount} ${errorCount === 1 ? 'error' : 'errors'}</span><button class="clear-button" type="button" data-clear-errors aria-label="Clear all errors">Clear</button>` : ''}</div>
339
+ <div class="panel-title"><span class="brand-mark">&gt;_</span><strong>pyric</strong>${errorCount > 0 ? `<span class="count">${errorCount} ${errorCount === 1 ? 'error' : 'errors'}</span><button class="clear-button" type="button" data-clear-errors aria-label="Clear all errors">Clear</button>` : ''}</div>
211
340
  <div class="panel-controls">
212
- <button class="icon-button" type="button" data-collapse aria-label="Minimize Pyric runtime">${icons.minimize}</button>
213
- <button class="icon-button" type="button" data-dismiss-chip aria-label="Dismiss Pyric runtime from page">${icons.close}</button>
341
+ <button class="icon-button" type="button" data-collapse aria-label="Minimize pyric">${icons.minimize}</button>
342
+ <button class="icon-button" type="button" data-dismiss-chip aria-label="Dismiss pyric from page">${icons.close}</button>
214
343
  </div>
215
344
  </header>
216
- <div class="worker-state"><span class="state-label${snapshot.updateAvailable ? ' available' : ''}"><span class="mini-dot"></span>${workerLabel}</span><span class="epochs">${epochs}</span></div>
345
+ <div class="worker-state"><span class="state-label${snapshot.updateAvailable ? ' available' : ''}">${workerLabel}</span><span class="epochs">${epochs}</span></div>
346
+ <div class="worker-state-col" data-ai-status>
347
+ <div class="worker-state-row">
348
+ <span class="state-label">AI engine</span>
349
+ <span class="epochs">${aiState.primary}</span>
350
+ </div>
351
+ ${aiState.subline ? `<div class="worker-state-subline">${aiState.subline}</div>` : ''}
352
+ </div>
353
+ <div class="worker-state"><span class="state-label">Rules</span><span class="epochs" style="${isAdmin ? 'color: #8f7fe8; font-weight: 500;' : ''}">${isAdmin ? 'bypassed' : 'enforced'}</span></div>
354
+ <div class="worker-state"><span class="state-label">Identity</span>${identityStateHtml}</div>
217
355
  <div class="errors" data-error-viewport>${renderErrors(snapshot, Boolean(clipboard))}</div>
218
356
  <div class="actions">
219
357
  <button class="button update" type="button" data-update-worker ${snapshot.updateAvailable ? '' : 'disabled'} aria-disabled="${snapshot.updateAvailable && !snapshot.updatingWorker ? 'false' : 'true'}">${snapshot.updatingWorker ? 'Updating…' : 'Update worker'}</button>
358
+ <button class="button" type="button" data-open-impersonate>Identity</button>
220
359
  ${studioUrl
221
360
  ? `<a class="button" data-open-studio href="${escapeAttribute(studioUrl)}" target="_blank" rel="noopener noreferrer">Studio${icons.external}</a>`
222
361
  : `<span class="button" data-open-studio aria-disabled="true" title="Pyric Studio is disabled">Studio${icons.external}</span>`}
223
362
  </div>
224
363
  </section>
225
364
  ` : `
226
- <button class="chip" type="button" data-expand aria-label="Open Pyric runtime" aria-expanded="false">
227
- <span class="brand"><span class="dot${errorCount > 0 ? ' error' : ''}"></span><span class="brand-label">Pyric</span></span>
228
- <span class="signals">${snapshot.updateAvailable ? '<span class="signal update">update</span>' : ''}${errorCount > 0 ? `<span class="signal">${errorCount} ${errorCount === 1 ? 'error' : 'errors'}</span>` : '<span class="signal">ready</span>'}${icons.chevron}</span>
365
+ <button class="chip" type="button" data-expand aria-label="Open pyric" aria-expanded="false">
366
+ <span class="brand"><span class="dot${errorCount > 0 ? ' error' : ''}"></span><span class="brand-label">pyric</span></span>
367
+ <span class="signals">${identitySignalHtml}${snapshot.updateAvailable ? '<span class="signal update">update</span>' : ''}${errorCount > 0 ? `<span class="signal">${errorCount} ${errorCount === 1 ? 'error' : 'errors'}</span>` : ''}${icons.chevron}</span>
229
368
  </button>
230
369
  `}`;
231
370
 
@@ -265,6 +404,9 @@ export function mountPyricRuntimeChip(options: PyricRuntimeChipOptions): PyricRu
265
404
  if (!snapshot.updateAvailable || snapshot.updatingWorker) return;
266
405
  void options.runtime.updateWorker().catch(() => { /* status records and renders the failure */ });
267
406
  });
407
+ root.querySelector('[data-open-impersonate]')?.addEventListener('click', (e) => {
408
+ void dialogController.open(e.currentTarget as HTMLElement);
409
+ });
268
410
  for (const button of root.querySelectorAll<HTMLButtonElement>('[data-copy-error]')) {
269
411
  button.addEventListener('click', () => {
270
412
  const error = snapshot.errors.find((item) => item.id === button.dataset.copyError);
@@ -292,11 +434,31 @@ export function mountPyricRuntimeChip(options: PyricRuntimeChipOptions): PyricRu
292
434
  };
293
435
 
294
436
  documentLike.body.append(host);
437
+ const reattachAfterAstroSwap = (): void => {
438
+ if (!host.isConnected) documentLike.body.append(host);
439
+ };
440
+ documentLike.addEventListener('astro:after-swap', reattachAfterAstroSwap);
295
441
  const unsubscribe = options.runtime.subscribe(render);
442
+
443
+ const unsubLens = subscribeLensFn(() => {
444
+ render();
445
+ });
446
+
447
+ const unsubAuth = identity.subscribeAuth((user) => {
448
+ clientUser = user;
449
+ render();
450
+ });
451
+
452
+ render();
453
+
296
454
  return {
297
455
  element: host,
298
456
  dispose() {
299
457
  unsubscribe();
458
+ unsubLens();
459
+ unsubAuth();
460
+ documentLike.removeEventListener('astro:after-swap', reattachAfterAstroSwap);
461
+ dialogController.dispose();
300
462
  host.remove();
301
463
  },
302
464
  };
@@ -0,0 +1,26 @@
1
+ import type { AuthUserRecord } from 'pyric/auth';
2
+
3
+ export interface RuntimeIdentity {
4
+ uid: string;
5
+ email?: string | null;
6
+ displayName?: string | null;
7
+ }
8
+
9
+ /** The chip's complete identity integration seam, passed intact through mounting. */
10
+ export interface RuntimeIdentityBindings {
11
+ listUsers(): Promise<AuthUserRecord[]> | AuthUserRecord[];
12
+ switchUser(uid: string): Promise<void> | void;
13
+ signOut(): Promise<void> | void;
14
+ openCreateUser(): void;
15
+ getCurrentUser(): RuntimeIdentity | null;
16
+ subscribeAuth(listener: (user: RuntimeIdentity | null) => void): () => void;
17
+ }
18
+
19
+ export function projectRuntimeIdentity(user: RuntimeIdentity | null | undefined): RuntimeIdentity | null {
20
+ if (!user) return null;
21
+ return {
22
+ uid: user.uid,
23
+ email: user.email,
24
+ displayName: user.displayName,
25
+ };
26
+ }
@@ -1,7 +1,7 @@
1
1
  /** Stable routes and identity used by the served runtime and its UI. */
2
2
  export const PYRIC_WORKER_URL = '/__pyric/sdk/worker.js';
3
3
  export const PYRIC_WORKER_NAME = 'pyric-shared-worker';
4
- export const PYRIC_STUDIO_URL = '/__pyric/ui/';
4
+ export const PYRIC_STUDIO_URL = '/__pyric/ui/studio';
5
5
 
6
6
  export interface PyricRuntimeManifest {
7
7
  studioUrl: string;
@@ -108,6 +108,13 @@ function isListenerPhaseErroredEvent(event: SandboxEvent): boolean {
108
108
  return isListenerKind && isErroredPhase && hasErrorPayload;
109
109
  }
110
110
 
111
+ function isAiRejectedEvent(event: SandboxEvent): boolean {
112
+ const isServiceMutationKind = event.kind === 'service_mutation';
113
+ const isAiService = event.service === 'ai';
114
+ const isRejectedOp = 'op' in event && event.op === 'request_rejected';
115
+ return isServiceMutationKind && isAiService && isRejectedOp;
116
+ }
117
+
111
118
  function sandboxError(event: SandboxEvent): PyricRuntimeError | null {
112
119
  if (isRuntimeErrorEvent(event)) {
113
120
  const hasPathProperty = 'path' in event && typeof event.path === 'string';
@@ -127,6 +134,23 @@ function sandboxError(event: SandboxEvent): PyricRuntimeError | null {
127
134
  message: errorPayload?.message ? errorPayload.message : 'Sandbox runtime error',
128
135
  };
129
136
  }
137
+ if (isAiRejectedEvent(event)) {
138
+ const detail = 'detail' in event ? (event.detail as Record<string, unknown> | undefined) : undefined;
139
+ const code = typeof detail?.code === 'string' ? detail.code : 'AI_ERROR';
140
+ const message = typeof detail?.message === 'string' ? detail.message : 'AI request rejected';
141
+ const hasPathProperty = 'path' in event && typeof event.path === 'string';
142
+ const targetPath = hasPathProperty ? event.path : '(ai)';
143
+ return {
144
+ id: event.id,
145
+ source: 'sandbox',
146
+ at: event.at,
147
+ service: 'ai',
148
+ method: 'generateContent',
149
+ path: targetPath,
150
+ code,
151
+ message: `AI_ERROR: ${message}`,
152
+ };
153
+ }
130
154
  if (isListenerErroredEvent(event)) {
131
155
  const errorPayload = (event as { error: { code?: string; message: string } }).error;
132
156
  return {
@@ -14,6 +14,7 @@ import {
14
14
  rulesHashOf,
15
15
  } from './rules.js';
16
16
  import { createEventHub, createPyricNamespace } from './namespace.js';
17
+ import type { BeaconReport } from '../register/beacon.js';
17
18
  import { diskProjectStore, diskWorkspace } from './studio/index.js';
18
19
  import type { ServeLogger } from './server.js';
19
20
  import {
@@ -35,8 +36,15 @@ export interface SandboxSessionOptions {
35
36
  bridgeUrl?: () => string | null;
36
37
  ai?: InitPayload['ai'];
37
38
  aiProxyUpstream?: string;
39
+ permissive?: boolean;
38
40
  logger?: ServeLogger;
39
41
  activity?: (incident: ActivityIncident) => void;
42
+ /** Receives one handshake beacon per pyric-launched child, the dev
43
+ * server's only positive proof that the register module reached it. */
44
+ beacon?: (report: BeaconReport) => void;
45
+ /** The per-launch secret a beacon must present, also placed in the child's
46
+ * `PYRIC_BEACON_TOKEN`. */
47
+ beaconToken?: string;
40
48
  }
41
49
 
42
50
  export interface SandboxSessionSummary {
@@ -97,6 +105,13 @@ export async function createSandboxSession(
97
105
  databaseRules: database.rules,
98
106
  databaseRulesHash: database.rulesHash,
99
107
  };
108
+ if (!database.sourcePath) {
109
+ if (options.permissive) {
110
+ options.logger?.note(' ⓘ RTDB permissive mode active — client reads/writes are open by default.');
111
+ } else {
112
+ options.logger?.note(' ⚠ no database.rules.json found — client RTDB reads/writes default to DENY (matching production Firebase). Use --permissive for open prototyping.');
113
+ }
114
+ }
100
115
  const events = createEventHub();
101
116
  const capture: CaptureStore | undefined = (options.capture ?? true)
102
117
  ? createCaptureStore(options.projectDir)
@@ -164,6 +179,7 @@ export async function createSandboxSession(
164
179
  : seedUsers,
165
180
  messaging: true,
166
181
  ai: options.ai ?? null,
182
+ permissive: Boolean(options.permissive),
167
183
  });
168
184
 
169
185
  const summary: SandboxSessionSummary = {
@@ -203,6 +219,8 @@ export async function createSandboxSession(
203
219
  workerVersion: options.sdk.workerVersion,
204
220
  aiProxyUpstream: options.aiProxyUpstream,
205
221
  activity: options.activity,
222
+ beacon: options.beacon,
223
+ beaconToken: options.beaconToken,
206
224
  logger: options.logger,
207
225
  });
208
226
 
@@ -221,16 +239,13 @@ export async function createSandboxSession(
221
239
  }
222
240
  };
223
241
  const reloadDatabaseRules = async (): Promise<RulesReloadResult> => {
224
- const isMissingDatabaseRules = database.sourcePath === null;
225
- if (isMissingDatabaseRules) {
226
- return { kind: 'not-configured' };
227
- }
228
242
  try {
229
243
  const updated = await loadProjectDatabaseRules(options.projectDir, options.firebaseConfig);
230
244
  const isMissingUpdatedRules = updated.rules === null || updated.rulesHash === null;
231
245
  if (isMissingUpdatedRules) {
232
246
  return { kind: 'not-configured' };
233
247
  }
248
+ database.sourcePath = updated.sourcePath;
234
249
  live.databaseRules = updated.rules;
235
250
  live.databaseRulesHash = updated.rulesHash;
236
251
  events.broadcast('rtdb-rules-update', { rules: updated.rules, rulesHash: updated.rulesHash });
@@ -134,6 +134,23 @@ export function isAllowedUpgrade(
134
134
  );
135
135
  }
136
136
 
137
+ /**
138
+ * Extract a header value case-insensitively from either Node's IncomingMessage headers
139
+ * or Fetch API Headers object.
140
+ */
141
+ export function getHeader(
142
+ req: { headers?: Record<string, string | string[] | undefined> | Headers },
143
+ name: string,
144
+ ): string | undefined {
145
+ const headers = req?.headers;
146
+ if (!headers) return undefined;
147
+ if (typeof (headers as Headers).get === 'function') {
148
+ return (headers as Headers).get(name) ?? undefined;
149
+ }
150
+ const val = (headers as Record<string, string | string[] | undefined>)[name.toLowerCase()];
151
+ return Array.isArray(val) ? val.join(', ') : val;
152
+ }
153
+
137
154
  export interface ServeHandle {
138
155
  port: number;
139
156
  host: string;
@@ -249,7 +266,7 @@ async function handleRequest(
249
266
  if (!isAllowedHost(req.headers.host, opts.host ?? 'localhost', opts.allowedHosts)) {
250
267
  logger.note(` ✖ 403 blocked Host '${req.headers.host}' (DNS-rebinding guard)`);
251
268
  res.writeHead(403, { 'content-type': 'text/plain' }).end(
252
- `pyric dev: refused request for Host '${req.headers.host ?? ''}'. ` +
269
+ `pyric sandbox: refused request for Host '${req.headers.host ?? ''}'. ` +
253
270
  'Only localhost is allowed; use --allowed-host to add one.',
254
271
  );
255
272
  return;
@@ -17,8 +17,16 @@ import {
17
17
  stat,
18
18
  writeFile,
19
19
  } from 'node:fs/promises';
20
- import { existsSync, mkdirSync, watch as fsWatch, type FSWatcher } from 'node:fs';
21
- import { dirname, join, posix, relative, resolve, sep } from 'node:path';
20
+ import {
21
+ existsSync,
22
+ lstatSync,
23
+ mkdirSync,
24
+ readlinkSync,
25
+ realpathSync,
26
+ watch as fsWatch,
27
+ type FSWatcher,
28
+ } from 'node:fs';
29
+ import { basename, dirname, join, posix, relative, resolve, sep } from 'node:path';
22
30
 
23
31
  import type {
24
32
  WorkspaceChange,
@@ -34,6 +42,54 @@ export class WorkspacePathError extends Error {
34
42
  }
35
43
  }
36
44
 
45
+ /**
46
+ * Resolves the canonical realpath of a path, handling symlinks and non-existent
47
+ * terminal segments by resolving the nearest existing ancestor.
48
+ */
49
+ function getCanonicalPath(targetPath: string, seen = new Set<string>()): string {
50
+ const abs = resolve(targetPath);
51
+ if (seen.has(abs)) {
52
+ throw new WorkspacePathError(targetPath);
53
+ }
54
+ seen.add(abs);
55
+
56
+ try {
57
+ return realpathSync(abs);
58
+ } catch (err: any) {
59
+ if (err?.code === 'ELOOP') {
60
+ throw new WorkspacePathError(targetPath);
61
+ }
62
+ if (err?.code !== 'ENOENT' && err?.code !== 'ENOTDIR') {
63
+ throw err;
64
+ }
65
+ }
66
+
67
+ try {
68
+ const st = lstatSync(abs);
69
+ if (st.isSymbolicLink()) {
70
+ const linkTarget = readlinkSync(abs);
71
+ const nextTarget = resolve(dirname(abs), linkTarget);
72
+ return getCanonicalPath(nextTarget, seen);
73
+ }
74
+ } catch {
75
+ // abs does not exist as a directory entry
76
+ }
77
+
78
+ const parent = dirname(abs);
79
+ if (parent === abs) {
80
+ return abs;
81
+ }
82
+ const canonicalParent = getCanonicalPath(parent, seen);
83
+ return join(canonicalParent, basename(abs));
84
+ }
85
+
86
+ /** Check whether canonical target is contained within canonical root. */
87
+ function isContained(root: string, target: string): boolean {
88
+ if (target === root) return true;
89
+ const prefix = root.endsWith(sep) ? root : root + sep;
90
+ return target.startsWith(prefix);
91
+ }
92
+
37
93
  /**
38
94
  * Resolve a project-relative POSIX path to an absolute OS path inside `root`,
39
95
  * or throw {@link WorkspacePathError} if it would escape. Leading slashes are
@@ -52,6 +108,24 @@ export function resolveWorkspacePath(root: string, rel: string): string {
52
108
  if (abs !== root && !abs.startsWith(root + sep)) {
53
109
  throw new WorkspacePathError(rel);
54
110
  }
111
+
112
+ // Canonical realpath containment check:
113
+ // Reject symlinks that escape the workspace root.
114
+ const canonicalRoot = getCanonicalPath(root);
115
+ let canonicalTarget: string;
116
+ try {
117
+ canonicalTarget = getCanonicalPath(abs);
118
+ } catch (err) {
119
+ if (err instanceof WorkspacePathError) {
120
+ throw new WorkspacePathError(rel);
121
+ }
122
+ throw err;
123
+ }
124
+
125
+ if (!isContained(canonicalRoot, canonicalTarget)) {
126
+ throw new WorkspacePathError(rel);
127
+ }
128
+
55
129
  return abs;
56
130
  }
57
131