@pyric/cli 0.1.0-alpha.10 → 0.1.0-alpha.12

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 (498) hide show
  1. package/README.md.orig +2 -2
  2. package/dist/assurance/.generated/conformance-verdicts.d.ts +16 -0
  3. package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
  4. package/dist/assurance/.generated/conformance-verdicts.js +16 -0
  5. package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
  6. package/dist/bridge/server/peer.d.ts +1 -1
  7. package/dist/bridge/server.d.ts +1 -1
  8. package/dist/bridge/server.js +1 -1
  9. package/dist/cli/index.d.ts +11 -0
  10. package/dist/cli/index.d.ts.map +1 -1
  11. package/dist/cli/index.js +13 -1
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/cli/init.d.ts +3 -3
  14. package/dist/cli/init.d.ts.map +1 -1
  15. package/dist/cli/init.js +5 -5
  16. package/dist/cli/init.js.map +1 -1
  17. package/dist/cli/serve.d.ts.map +1 -1
  18. package/dist/cli/serve.js +8 -2
  19. package/dist/cli/serve.js.map +1 -1
  20. package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
  21. package/dist/conformance/.generated/can-i-use-browser.js +1 -1
  22. package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
  23. package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
  24. package/dist/conformance/.generated/can-i-use.js +2 -2
  25. package/dist/conformance/.generated/can-i-use.js.map +1 -1
  26. package/dist/conformance/.generated/conformance-docs.d.ts +12 -0
  27. package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -0
  28. package/dist/conformance/.generated/conformance-docs.js +2 -0
  29. package/dist/conformance/.generated/conformance-docs.js.map +1 -0
  30. package/dist/conformance/docs.d.ts +6 -0
  31. package/dist/conformance/docs.d.ts.map +1 -0
  32. package/dist/conformance/docs.js +6 -0
  33. package/dist/conformance/docs.js.map +1 -0
  34. package/dist/remote/index.d.ts.map +1 -1
  35. package/dist/remote/index.js +1 -0
  36. package/dist/remote/index.js.map +1 -1
  37. package/dist/serve/activity-guard.d.ts +4 -0
  38. package/dist/serve/activity-guard.d.ts.map +1 -0
  39. package/dist/serve/activity-guard.js +22 -0
  40. package/dist/serve/activity-guard.js.map +1 -0
  41. package/dist/serve/activity-route.d.ts +4 -0
  42. package/dist/serve/activity-route.d.ts.map +1 -0
  43. package/dist/serve/activity-route.js +157 -0
  44. package/dist/serve/activity-route.js.map +1 -0
  45. package/dist/serve/activity-warning.d.ts +4 -0
  46. package/dist/serve/activity-warning.d.ts.map +1 -0
  47. package/dist/serve/activity-warning.js +21 -0
  48. package/dist/serve/activity-warning.js.map +1 -0
  49. package/dist/serve/bridge-mount.d.ts +5 -0
  50. package/dist/serve/bridge-mount.d.ts.map +1 -1
  51. package/dist/serve/bridge-mount.js +1 -0
  52. package/dist/serve/bridge-mount.js.map +1 -1
  53. package/dist/serve/docs-ui/404.html +3 -0
  54. package/dist/serve/docs-ui/_astro/{_slug_.DPUwShm2.css → _slug_.CXh9yTP1.css} +1 -1
  55. package/dist/serve/docs-ui/_astro/_slug_.DUci-duz.css +1 -0
  56. package/dist/serve/docs-ui/docs/_rhythm/index.html +2 -1
  57. package/dist/serve/docs-ui/docs/agent/set-up-your-agent/index.html +3 -2
  58. package/dist/serve/docs-ui/docs/agent/set-up-your-agent.md +1 -1
  59. package/dist/serve/docs-ui/docs/agent/watch-and-review/index.html +2 -1
  60. package/dist/serve/docs-ui/docs/agent/work-with-an-agent/index.html +2 -1
  61. package/dist/serve/docs-ui/docs/ai-compat/index.html +2 -1
  62. package/dist/serve/docs-ui/docs/api-reference/index.html +51 -49
  63. package/dist/serve/docs-ui/docs/api-reference.md +3 -3
  64. package/dist/serve/docs-ui/docs/app-compat/index.html +2 -1
  65. package/dist/serve/docs-ui/docs/auth-compat/index.html +2 -1
  66. package/dist/serve/docs-ui/docs/build/ai-logic/index.html +18 -3
  67. package/dist/serve/docs-ui/docs/build/ai-logic.md +30 -2
  68. package/dist/serve/docs-ui/docs/build/authentication/index.html +2 -1
  69. package/dist/serve/docs-ui/docs/build/authentication.md +1 -1
  70. package/dist/serve/docs-ui/docs/build/cloud-firestore/index.html +2 -1
  71. package/dist/serve/docs-ui/docs/build/cloud-messaging/index.html +46 -2
  72. package/dist/serve/docs-ui/docs/build/cloud-messaging.md +56 -1
  73. package/dist/serve/docs-ui/docs/build/cloud-storage/index.html +2 -1
  74. package/dist/serve/docs-ui/docs/build/cloud-storage.md +1 -1
  75. package/dist/serve/docs-ui/docs/build/realtime-database/index.html +21 -3
  76. package/dist/serve/docs-ui/docs/build/realtime-database.md +25 -1
  77. package/dist/serve/docs-ui/docs/conformance-scores/index.html +2 -1
  78. package/dist/serve/docs-ui/docs/create-pyric-reference-api/index.html +61 -28
  79. package/dist/serve/docs-ui/docs/create-pyric-reference-api.md +65 -20
  80. package/dist/serve/docs-ui/docs/database-compat/index.html +2 -1
  81. package/dist/serve/docs-ui/docs/firestore-compat/index.html +6 -5
  82. package/dist/serve/docs-ui/docs/firestore-compat.md +4 -4
  83. package/dist/serve/docs-ui/docs/functions-rtdb-compat/index.html +2 -1
  84. package/dist/serve/docs-ui/docs/get-started/how-the-swap-works/index.html +2 -1
  85. package/dist/serve/docs-ui/docs/get-started/start-building/index.html +4 -3
  86. package/dist/serve/docs-ui/docs/get-started/start-building.md +2 -2
  87. package/dist/serve/docs-ui/docs/index.json +979 -579
  88. package/dist/serve/docs-ui/docs/messaging-compat/index.html +2 -1
  89. package/dist/serve/docs-ui/docs/observe/see-whats-happening/index.html +2 -1
  90. package/dist/serve/docs-ui/docs/observe/shape-your-data/index.html +2 -1
  91. package/dist/serve/docs-ui/docs/overview/index.html +2 -1
  92. package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api/index.html +5 -4
  93. package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api.md +3 -4
  94. package/dist/serve/docs-ui/docs/pyric-admin-auth-reference-api/index.html +5 -4
  95. package/dist/serve/docs-ui/docs/pyric-admin-auth-reference-api.md +3 -4
  96. package/dist/serve/docs-ui/docs/pyric-admin-database-reference-api/index.html +5 -4
  97. package/dist/serve/docs-ui/docs/pyric-admin-database-reference-api.md +3 -4
  98. package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-api/index.html +2503 -12
  99. package/dist/serve/docs-ui/docs/pyric-admin-firestore-reference-api.md +2219 -8
  100. package/dist/serve/docs-ui/docs/pyric-admin-messaging-reference-api/index.html +916 -0
  101. package/dist/serve/docs-ui/docs/pyric-admin-messaging-reference-api.md +706 -0
  102. package/dist/serve/docs-ui/docs/pyric-admin-storage-reference-api/index.html +4 -3
  103. package/dist/serve/docs-ui/docs/pyric-admin-storage-reference-api.md +2 -3
  104. package/dist/serve/docs-ui/docs/pyric-ai-reference-api/index.html +16 -11
  105. package/dist/serve/docs-ui/docs/pyric-ai-reference-api.md +14 -13
  106. package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api/index.html +4 -3
  107. package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api.md +2 -3
  108. package/dist/serve/docs-ui/docs/pyric-app-reference-api/index.html +7 -2
  109. package/dist/serve/docs-ui/docs/pyric-app-reference-api.md +5 -2
  110. package/dist/serve/docs-ui/docs/pyric-auth-reference-api/index.html +23 -12
  111. package/dist/serve/docs-ui/docs/pyric-auth-reference-api.md +15 -12
  112. package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +10 -48
  113. package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api.md +11 -24
  114. package/dist/serve/docs-ui/docs/pyric-cli-assurance-reference-api/index.html +87 -97
  115. package/dist/serve/docs-ui/docs/pyric-cli-assurance-reference-api.md +53 -65
  116. package/dist/serve/docs-ui/docs/pyric-cli-bridge-client-reference-api/index.html +14 -15
  117. package/dist/serve/docs-ui/docs/pyric-cli-bridge-client-reference-api.md +19 -28
  118. package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api/index.html +4 -3
  119. package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api.md +2 -3
  120. package/dist/serve/docs-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +3 -2
  121. package/dist/serve/docs-ui/docs/pyric-cli-conformance-browser-reference-api.md +1 -2
  122. package/dist/serve/docs-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +51 -0
  123. package/dist/serve/docs-ui/docs/pyric-cli-conformance-docs-reference-api.md +36 -0
  124. package/dist/serve/docs-ui/docs/pyric-cli-conformance-reference-api/index.html +3 -2
  125. package/dist/serve/docs-ui/docs/pyric-cli-conformance-reference-api.md +1 -2
  126. package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api/index.html +3 -2
  127. package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api.md +1 -2
  128. package/dist/serve/docs-ui/docs/pyric-cli-discover-reference-api/index.html +3 -2
  129. package/dist/serve/docs-ui/docs/pyric-cli-discover-reference-api.md +1 -2
  130. package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api/index.html +3 -2
  131. package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api.md +1 -2
  132. package/dist/serve/docs-ui/docs/pyric-cli-remote-reference-api/index.html +1067 -83
  133. package/dist/serve/docs-ui/docs/pyric-cli-remote-reference-api.md +1291 -160
  134. package/dist/serve/docs-ui/docs/pyric-cli-serve-worker-reference-api/index.html +253 -157
  135. package/dist/serve/docs-ui/docs/pyric-cli-serve-worker-reference-api.md +179 -85
  136. package/dist/serve/docs-ui/docs/pyric-cli-verify-reference-api/index.html +72 -7
  137. package/dist/serve/docs-ui/docs/pyric-cli-verify-reference-api.md +22 -7
  138. package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api/index.html +33 -12
  139. package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api.md +15 -12
  140. package/dist/serve/docs-ui/docs/pyric-database-reference-api/index.html +18 -17
  141. package/dist/serve/docs-ui/docs/pyric-database-reference-api.md +19 -22
  142. package/dist/serve/docs-ui/docs/pyric-firestore-reference-api/index.html +1512 -545
  143. package/dist/serve/docs-ui/docs/pyric-firestore-reference-api.md +1311 -316
  144. package/dist/serve/docs-ui/docs/pyric-messaging-reference-api/index.html +5 -4
  145. package/dist/serve/docs-ui/docs/pyric-messaging-reference-api.md +3 -4
  146. package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api/index.html +69 -369
  147. package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api.md +103 -216
  148. package/dist/serve/docs-ui/docs/pyric-rules-reference-api/index.html +10 -9
  149. package/dist/serve/docs-ui/docs/pyric-rules-reference-api.md +9 -10
  150. package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api/index.html +8 -7
  151. package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api.md +6 -7
  152. package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api/index.html +10 -9
  153. package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api.md +9 -10
  154. package/dist/serve/docs-ui/docs/pyric-sandbox-reference-api/index.html +371 -884
  155. package/dist/serve/docs-ui/docs/pyric-sandbox-reference-api.md +369 -883
  156. package/dist/serve/docs-ui/docs/pyric-storage-reference-api/index.html +25 -17
  157. package/dist/serve/docs-ui/docs/pyric-storage-reference-api.md +21 -19
  158. package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api/index.html +3 -2
  159. package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api.md +1 -2
  160. package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +63 -776
  161. package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api.md +69 -510
  162. package/dist/serve/docs-ui/docs/pyric-ui-auth-reference-api/index.html +22 -21
  163. package/dist/serve/docs-ui/docs/pyric-ui-auth-reference-api.md +29 -30
  164. package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api/index.html +15 -168
  165. package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api.md +17 -87
  166. package/dist/serve/docs-ui/docs/pyric-ui-events-reference-api/index.html +6 -5
  167. package/dist/serve/docs-ui/docs/pyric-ui-events-reference-api.md +5 -6
  168. package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +82 -970
  169. package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api.md +104 -479
  170. package/dist/serve/docs-ui/docs/pyric-ui-firestore-reference-api/index.html +30 -29
  171. package/dist/serve/docs-ui/docs/pyric-ui-firestore-reference-api.md +54 -55
  172. package/dist/serve/docs-ui/docs/pyric-ui-primitives-reference-api/index.html +3 -2
  173. package/dist/serve/docs-ui/docs/pyric-ui-primitives-reference-api.md +1 -2
  174. package/dist/serve/docs-ui/docs/pyric-ui-rtdb-reference-api/index.html +5 -4
  175. package/dist/serve/docs-ui/docs/pyric-ui-rtdb-reference-api.md +3 -4
  176. package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +9 -124
  177. package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api.md +7 -58
  178. package/dist/serve/docs-ui/docs/pyric-ui-rules-reference-api/index.html +24 -23
  179. package/dist/serve/docs-ui/docs/pyric-ui-rules-reference-api.md +31 -34
  180. package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +104 -1385
  181. package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api.md +133 -817
  182. package/dist/serve/docs-ui/docs/pyric-ui-storage-reference-api/index.html +34 -33
  183. package/dist/serve/docs-ui/docs/pyric-ui-storage-reference-api.md +37 -38
  184. package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +116 -1169
  185. package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api.md +142 -590
  186. package/dist/serve/docs-ui/docs/pyric-ui-traffic-reference-api/index.html +4 -3
  187. package/dist/serve/docs-ui/docs/pyric-ui-traffic-reference-api.md +3 -4
  188. package/dist/serve/docs-ui/docs/rules-compat/index.html +34 -1
  189. package/dist/serve/docs-ui/docs/rules-compat.md +32 -0
  190. package/dist/serve/docs-ui/docs/secure/audit-your-rules/index.html +19 -2
  191. package/dist/serve/docs-ui/docs/secure/audit-your-rules.md +32 -0
  192. package/dist/serve/docs-ui/docs/secure/firestore-rules-limits/index.html +2 -1
  193. package/dist/serve/docs-ui/docs/secure/read-a-denial/index.html +2 -1
  194. package/dist/serve/docs-ui/docs/secure/rtdb-rules-in-typescript/index.html +2 -1
  195. package/dist/serve/docs-ui/docs/secure/rtdb-rules-in-typescript.md +1 -1
  196. package/dist/serve/docs-ui/docs/secure/rules-standard-library/index.html +2 -1
  197. package/dist/serve/docs-ui/docs/secure/secure-it-with-rules/index.html +2 -1
  198. package/dist/serve/docs-ui/docs/secure/simulate-and-lint/index.html +2 -1
  199. package/dist/serve/docs-ui/docs/secure/write-a-rules-test-suite/index.html +2 -1
  200. package/dist/serve/docs-ui/docs/ship/ship-to-production/index.html +2 -1
  201. package/dist/serve/docs-ui/docs/ship/test-in-node/index.html +2 -1
  202. package/dist/serve/docs-ui/docs/storage-compat/index.html +2 -1
  203. package/dist/serve/docs-ui/docs/trust/how-we-know-it-matches-firebase/index.html +2 -1
  204. package/dist/serve/docs-ui/docs/trust/versioning-and-compatibility/index.html +2 -1
  205. package/dist/serve/docs-ui/llms.txt +2 -1
  206. package/dist/serve/entries/ai.d.ts.map +1 -1
  207. package/dist/serve/entries/ai.js +39 -1
  208. package/dist/serve/entries/ai.js.map +1 -1
  209. package/dist/serve/entries/messaging-sw.d.ts.map +1 -1
  210. package/dist/serve/entries/messaging-sw.js +5 -1
  211. package/dist/serve/entries/messaging-sw.js.map +1 -1
  212. package/dist/serve/entries/messaging.d.ts.map +1 -1
  213. package/dist/serve/entries/messaging.js +7 -1
  214. package/dist/serve/entries/messaging.js.map +1 -1
  215. package/dist/serve/entries/runtime.d.ts.map +1 -1
  216. package/dist/serve/entries/runtime.js +20 -1
  217. package/dist/serve/entries/runtime.js.map +1 -1
  218. package/dist/serve/init-payload.d.ts +25 -0
  219. package/dist/serve/init-payload.d.ts.map +1 -1
  220. package/dist/serve/namespace.d.ts +39 -0
  221. package/dist/serve/namespace.d.ts.map +1 -1
  222. package/dist/serve/namespace.js +80 -1
  223. package/dist/serve/namespace.js.map +1 -1
  224. package/dist/serve/standalone-assets.d.ts +11 -9
  225. package/dist/serve/standalone-assets.d.ts.map +1 -1
  226. package/dist/serve/standalone-assets.js +6 -5
  227. package/dist/serve/standalone-assets.js.map +1 -1
  228. package/dist/serve/studio-ui/assets/{RulesCodeEditor-CXdSLKhO.js → RulesCodeEditor-CxVYcZXw.js} +1 -1
  229. package/dist/serve/studio-ui/assets/index-cpSfgQ7H.js +1218 -0
  230. package/dist/serve/studio-ui/assets/seed-DeuFKi4J.js +20 -0
  231. package/dist/serve/studio-ui/index.html +1 -1
  232. package/dist/serve/vite-plugin.d.ts +92 -15
  233. package/dist/serve/vite-plugin.d.ts.map +1 -1
  234. package/dist/serve/vite-plugin.js +281 -11
  235. package/dist/serve/vite-plugin.js.map +1 -1
  236. package/dist/serve/worker/activity-bootstrap.d.ts +8 -0
  237. package/dist/serve/worker/activity-bootstrap.d.ts.map +1 -0
  238. package/dist/serve/worker/activity-bootstrap.js +11 -0
  239. package/dist/serve/worker/activity-bootstrap.js.map +1 -0
  240. package/dist/serve/worker/client/connection.d.ts.map +1 -1
  241. package/dist/serve/worker/client/connection.js +17 -5
  242. package/dist/serve/worker/client/connection.js.map +1 -1
  243. package/dist/serve/worker/client/core.d.ts +2 -2
  244. package/dist/serve/worker/client/core.d.ts.map +1 -1
  245. package/dist/serve/worker/client/core.js +33 -5
  246. package/dist/serve/worker/client/core.js.map +1 -1
  247. package/dist/serve/worker/client/firestore-writes.d.ts.map +1 -1
  248. package/dist/serve/worker/client/firestore-writes.js +1 -0
  249. package/dist/serve/worker/client/firestore-writes.js.map +1 -1
  250. package/dist/serve/worker/client/messaging.d.ts +9 -1
  251. package/dist/serve/worker/client/messaging.d.ts.map +1 -1
  252. package/dist/serve/worker/client/messaging.js +15 -0
  253. package/dist/serve/worker/client/messaging.js.map +1 -1
  254. package/dist/serve/worker/client/studio.d.ts +10 -0
  255. package/dist/serve/worker/client/studio.d.ts.map +1 -1
  256. package/dist/serve/worker/client/studio.js +11 -0
  257. package/dist/serve/worker/client/studio.js.map +1 -1
  258. package/dist/serve/worker/durable-persistence.d.ts +12 -0
  259. package/dist/serve/worker/durable-persistence.d.ts.map +1 -0
  260. package/dist/serve/worker/durable-persistence.js +118 -0
  261. package/dist/serve/worker/durable-persistence.js.map +1 -0
  262. package/dist/serve/worker/entry.d.ts +7 -3
  263. package/dist/serve/worker/entry.d.ts.map +1 -1
  264. package/dist/serve/worker/entry.js +7 -3
  265. package/dist/serve/worker/entry.js.map +1 -1
  266. package/dist/serve/worker/host/core.d.ts +9 -5
  267. package/dist/serve/worker/host/core.d.ts.map +1 -1
  268. package/dist/serve/worker/host/core.js +34 -9
  269. package/dist/serve/worker/host/core.js.map +1 -1
  270. package/dist/serve/worker/host/dispatch.d.ts.map +1 -1
  271. package/dist/serve/worker/host/dispatch.js +9 -2
  272. package/dist/serve/worker/host/dispatch.js.map +1 -1
  273. package/dist/serve/worker/host/firestore-writes.d.ts.map +1 -1
  274. package/dist/serve/worker/host/firestore-writes.js +3 -2
  275. package/dist/serve/worker/host/firestore-writes.js.map +1 -1
  276. package/dist/serve/worker/host/studio.d.ts +1 -1
  277. package/dist/serve/worker/host/studio.d.ts.map +1 -1
  278. package/dist/serve/worker/host/studio.js +36 -1
  279. package/dist/serve/worker/host/studio.js.map +1 -1
  280. package/dist/serve/worker/host/subscriptions.d.ts.map +1 -1
  281. package/dist/serve/worker/host/subscriptions.js +27 -7
  282. package/dist/serve/worker/host/subscriptions.js.map +1 -1
  283. package/dist/serve/worker/host-context.d.ts +15 -0
  284. package/dist/serve/worker/host-context.d.ts.map +1 -1
  285. package/dist/serve/worker/host-context.js +10 -0
  286. package/dist/serve/worker/host-context.js.map +1 -1
  287. package/dist/serve/worker/host-messaging.d.ts.map +1 -1
  288. package/dist/serve/worker/host-messaging.js +9 -2
  289. package/dist/serve/worker/host-messaging.js.map +1 -1
  290. package/dist/serve/worker/index.d.ts +3 -2
  291. package/dist/serve/worker/index.d.ts.map +1 -1
  292. package/dist/serve/worker/index.js +4 -1
  293. package/dist/serve/worker/index.js.map +1 -1
  294. package/dist/serve/worker/protocol.d.ts +25 -3
  295. package/dist/serve/worker/protocol.d.ts.map +1 -1
  296. package/dist/serve/worker/protocol.js +2 -2
  297. package/dist/serve/worker/protocol.js.map +1 -1
  298. package/dist/serve/worker/serve-init.d.ts +23 -37
  299. package/dist/serve/worker/serve-init.d.ts.map +1 -1
  300. package/dist/serve/worker/serve-init.js +95 -172
  301. package/dist/serve/worker/serve-init.js.map +1 -1
  302. package/dist/vite.d.ts +4 -4
  303. package/dist/vite.d.ts.map +1 -1
  304. package/dist/vite.js +3 -3
  305. package/dist/vite.js.map +1 -1
  306. package/package.json +9 -4
  307. package/src/assurance/.generated/conformance-verdicts.ts +1090 -0
  308. package/src/assurance/attachment.ts +211 -0
  309. package/src/assurance/browser.ts +80 -0
  310. package/src/assurance/campaign.ts +496 -0
  311. package/src/assurance/capabilities.ts +446 -0
  312. package/src/assurance/cases.ts +43 -0
  313. package/src/assurance/index.ts +75 -0
  314. package/src/assurance/runner.ts +885 -0
  315. package/src/assurance/tool-names.ts +15 -0
  316. package/src/assurance/tools.ts +830 -0
  317. package/src/assurance/types.ts +352 -0
  318. package/src/assurance/validation.ts +434 -0
  319. package/src/bridge/client/bridge.ts +550 -0
  320. package/src/bridge/client/dispatch.ts +137 -0
  321. package/src/bridge/client.ts +45 -0
  322. package/src/bridge/protocol.ts +351 -0
  323. package/src/bridge/server/audit.ts +53 -0
  324. package/src/bridge/server/bridge.ts +597 -0
  325. package/src/bridge/server/headless.ts +160 -0
  326. package/src/bridge/server/json-schema-to-zod.ts +108 -0
  327. package/src/bridge/server/local-bridge.ts +66 -0
  328. package/src/bridge/server/logger.ts +50 -0
  329. package/src/bridge/server/mcp-contract.ts +93 -0
  330. package/src/bridge/server/mcp.ts +129 -0
  331. package/src/bridge/server/peer.ts +232 -0
  332. package/src/bridge/server/standalone.ts +347 -0
  333. package/src/bridge/server/tool-metadata.ts +99 -0
  334. package/src/bridge/server.ts +28 -0
  335. package/src/cli/can-i-use.ts +50 -0
  336. package/src/cli/cli.test.ts +493 -0
  337. package/src/cli/database-rules.ts +329 -0
  338. package/src/cli/dev-runner.ts +282 -0
  339. package/src/cli/firebase-json.ts +100 -0
  340. package/src/cli/firestore-indexes.ts +70 -0
  341. package/src/cli/index.ts +425 -0
  342. package/src/cli/init.ts +260 -0
  343. package/src/cli/mcp-proxy.ts +196 -0
  344. package/src/cli/parse-args.ts +80 -0
  345. package/src/cli/rules.ts +259 -0
  346. package/src/cli/scope.ts +67 -0
  347. package/src/cli/serve.ts +996 -0
  348. package/src/cli/service-commands.ts +73 -0
  349. package/src/cli/snapshot.ts +164 -0
  350. package/src/cli/storage-rules.ts +172 -0
  351. package/src/cli/verify.ts +416 -0
  352. package/src/conformance/.generated/can-i-use-browser.ts +113 -0
  353. package/src/conformance/.generated/can-i-use.ts +117 -0
  354. package/src/conformance/.generated/conformance-docs.ts +14 -0
  355. package/src/conformance/browser.ts +24 -0
  356. package/src/conformance/can-i-use-tool.ts +51 -0
  357. package/src/conformance/can-i-use.ts +18 -0
  358. package/src/conformance/docs.ts +8 -0
  359. package/src/conformance/index.ts +20 -0
  360. package/src/conformance/tools.ts +16 -0
  361. package/src/credentials/core/memoize-ttl.ts +142 -0
  362. package/src/credentials/core/types.ts +10 -0
  363. package/src/credentials/node/from-adc.ts +96 -0
  364. package/src/credentials/node/from-service-account.ts +133 -0
  365. package/src/credentials/node/index.ts +6 -0
  366. package/src/discover/concurrency.ts +127 -0
  367. package/src/discover/crawler-adapter.ts +142 -0
  368. package/src/discover/crawler.ts +1127 -0
  369. package/src/discover/credential-free.ts +27 -0
  370. package/src/discover/findCollectionGroup.ts +131 -0
  371. package/src/discover/firestore-source.ts +59 -0
  372. package/src/discover/index.ts +5 -0
  373. package/src/discover/merge.ts +523 -0
  374. package/src/discover/session.ts +402 -0
  375. package/src/discover/tools.ts +201 -0
  376. package/src/discover/types.ts +187 -0
  377. package/src/discover/wire.ts +324 -0
  378. package/src/functions-rtdb/child.ts +382 -0
  379. package/src/functions-rtdb/delivery.ts +7 -0
  380. package/src/functions-rtdb/discovery.ts +136 -0
  381. package/src/functions-rtdb/event.ts +64 -0
  382. package/src/functions-rtdb/execution.ts +111 -0
  383. package/src/functions-rtdb/in-memory-delivery.ts +40 -0
  384. package/src/functions-rtdb/project.ts +74 -0
  385. package/src/functions-rtdb/projection.ts +104 -0
  386. package/src/functions-rtdb/reference-pattern.ts +20 -0
  387. package/src/functions-rtdb/remote-delivery.ts +23 -0
  388. package/src/pkg-version.ts +49 -0
  389. package/src/register/esm-exports.ts +63 -0
  390. package/src/register/hooks.ts +30 -0
  391. package/src/register/index.ts +150 -0
  392. package/src/register/mapping.ts +33 -0
  393. package/src/remote/index.ts +1050 -0
  394. package/src/rtdb/crawl-snapshot.ts +118 -0
  395. package/src/rtdb/inspection.ts +137 -0
  396. package/src/rtdb/load-rules-document.ts +56 -0
  397. package/src/rtdb/rules-generation-tool.ts +38 -0
  398. package/src/rtdb/rules-json.ts +29 -0
  399. package/src/serve/activity-guard.ts +29 -0
  400. package/src/serve/activity-route.ts +164 -0
  401. package/src/serve/activity-warning.ts +26 -0
  402. package/src/serve/bridge-mount.ts +200 -0
  403. package/src/serve/bundler.ts +493 -0
  404. package/src/serve/capture-store.ts +65 -0
  405. package/src/serve/discovery.ts +199 -0
  406. package/src/serve/entries/ai.ts +292 -0
  407. package/src/serve/entries/app-backend.ts +4 -0
  408. package/src/serve/entries/app-client.ts +26 -0
  409. package/src/serve/entries/app-session-store.ts +47 -0
  410. package/src/serve/entries/app.ts +11 -0
  411. package/src/serve/entries/auth-helper-core.ts +181 -0
  412. package/src/serve/entries/auth-helper-dom.ts +134 -0
  413. package/src/serve/entries/auth-helper-runtime.ts +20 -0
  414. package/src/serve/entries/auth.ts +255 -0
  415. package/src/serve/entries/bridge-url.ts +31 -0
  416. package/src/serve/entries/database.ts +129 -0
  417. package/src/serve/entries/firestore.ts +232 -0
  418. package/src/serve/entries/init.ts +46 -0
  419. package/src/serve/entries/keepalive.ts +46 -0
  420. package/src/serve/entries/messaging-sw.ts +75 -0
  421. package/src/serve/entries/messaging.ts +96 -0
  422. package/src/serve/entries/runtime.ts +540 -0
  423. package/src/serve/entries/session-store.ts +97 -0
  424. package/src/serve/entries/storage.ts +92 -0
  425. package/src/serve/entries/tab-sync-wiring.ts +274 -0
  426. package/src/serve/entries/worker-runtime.ts +75 -0
  427. package/src/serve/init-payload.ts +42 -0
  428. package/src/serve/namespace.ts +675 -0
  429. package/src/serve/open-browser.ts +68 -0
  430. package/src/serve/rules.ts +272 -0
  431. package/src/serve/sandbox-marker.ts +31 -0
  432. package/src/serve/server.ts +428 -0
  433. package/src/serve/standalone-assets.ts +180 -0
  434. package/src/serve/state-store.ts +166 -0
  435. package/src/serve/studio/disk-project-store.ts +185 -0
  436. package/src/serve/studio/disk-workspace.ts +162 -0
  437. package/src/serve/studio/index.ts +20 -0
  438. package/src/serve/studio/routes.ts +237 -0
  439. package/src/serve/studio/store-types.ts +48 -0
  440. package/src/serve/studio/studio-storage.test.ts +289 -0
  441. package/src/serve/vite-plugin.ts +1102 -0
  442. package/src/serve/worker/activity-bootstrap.ts +24 -0
  443. package/src/serve/worker/client/admin-firestore.ts +38 -0
  444. package/src/serve/worker/client/ai.ts +124 -0
  445. package/src/serve/worker/client/auth.ts +489 -0
  446. package/src/serve/worker/client/connection.ts +202 -0
  447. package/src/serve/worker/client/core.ts +350 -0
  448. package/src/serve/worker/client/disconnect.ts +45 -0
  449. package/src/serve/worker/client/firestore-reads.ts +181 -0
  450. package/src/serve/worker/client/firestore-refs.ts +226 -0
  451. package/src/serve/worker/client/firestore-writes.ts +232 -0
  452. package/src/serve/worker/client/handles.ts +91 -0
  453. package/src/serve/worker/client/messaging.ts +119 -0
  454. package/src/serve/worker/client/presence.ts +174 -0
  455. package/src/serve/worker/client/rtdb.ts +311 -0
  456. package/src/serve/worker/client/rules.ts +63 -0
  457. package/src/serve/worker/client/service-worker-connection.ts +59 -0
  458. package/src/serve/worker/client/snapshots.ts +86 -0
  459. package/src/serve/worker/client/storage.ts +195 -0
  460. package/src/serve/worker/client/studio.ts +88 -0
  461. package/src/serve/worker/client.ts +57 -0
  462. package/src/serve/worker/durable-persistence.ts +137 -0
  463. package/src/serve/worker/entry.ts +179 -0
  464. package/src/serve/worker/host/admin-firestore.ts +88 -0
  465. package/src/serve/worker/host/connection.ts +179 -0
  466. package/src/serve/worker/host/core.ts +387 -0
  467. package/src/serve/worker/host/dispatch.ts +316 -0
  468. package/src/serve/worker/host/firestore-reads.ts +117 -0
  469. package/src/serve/worker/host/firestore-writes.ts +456 -0
  470. package/src/serve/worker/host/presence.ts +312 -0
  471. package/src/serve/worker/host/rtdb.ts +136 -0
  472. package/src/serve/worker/host/rules.ts +128 -0
  473. package/src/serve/worker/host/storage.ts +312 -0
  474. package/src/serve/worker/host/studio.ts +75 -0
  475. package/src/serve/worker/host/subscriptions.ts +238 -0
  476. package/src/serve/worker/host-ai.ts +165 -0
  477. package/src/serve/worker/host-auth.ts +469 -0
  478. package/src/serve/worker/host-context.ts +273 -0
  479. package/src/serve/worker/host-events.ts +94 -0
  480. package/src/serve/worker/host-messaging.ts +240 -0
  481. package/src/serve/worker/host.ts +47 -0
  482. package/src/serve/worker/index.ts +196 -0
  483. package/src/serve/worker/presence-timing.ts +15 -0
  484. package/src/serve/worker/protocol.ts +1112 -0
  485. package/src/serve/worker/serve-init.ts +606 -0
  486. package/src/serve/worker/service-worker-channel.ts +33 -0
  487. package/src/serve/worker/service-worker-relay.ts +86 -0
  488. package/src/serve/writer-lock.ts +53 -0
  489. package/src/verify/cases.ts +233 -0
  490. package/src/verify/fixture.ts +258 -0
  491. package/src/verify/index.ts +519 -0
  492. package/src/verify/tools.ts +108 -0
  493. package/src/version/compat-target.ts +17 -0
  494. package/src/vite.ts +17 -0
  495. package/dist/serve/docs-ui/docs/pyric-firestore-values-reference-api/index.html +0 -30
  496. package/dist/serve/docs-ui/docs/pyric-firestore-values-reference-api.md +0 -30
  497. package/dist/serve/studio-ui/assets/index-BvtQIpGn.js +0 -1211
  498. package/dist/serve/studio-ui/assets/seed-3DMedLL3.js +0 -2
@@ -1,5 +1,4 @@
1
-
2
- <!-- Generated from published package declarations via TypeDoc. Do not edit by hand; run bun run docs:api:generate. -->
1
+ <!-- Generated from published package declarations via TypeDoc. Rendered by the api-reference content loader. -->
3
2
 
4
3
  ## Interfaces
5
4
 
@@ -26,23 +25,929 @@ eager checkers. `ready` kicks off the connection when first accessed and
26
25
  settles with the same fail-fast errors [connectRemoteSandbox](#connectremotesandbox) throws
27
26
  (no serve discovered / no browser tab connected).
28
27
 
29
- #### Extends
28
+ #### Extends
29
+
30
+ - [`RemoteSandbox`](#remotesandbox)
31
+
32
+ #### Properties
33
+
34
+ | Property | Modifier | Type | Description |
35
+ | :------ | :------ | :------ | :------ |
36
+ | <a id="remote_sandbox"></a> `[REMOTE_SANDBOX]` | `readonly` | `true` | - |
37
+ | <a id="admin"></a> `admin` | `readonly` | `SandboxAdmin` | Admin-plane access (rule-bypass reads). Identity-agnostic by design — admin reads aren't gated on auth, so they live on the sandbox, not on a context. See SandboxAdmin. |
38
+ | <a id="auth"></a> `auth` | `readonly` | [`RemoteAuthAdmin`](#remoteauthadmin) | Admin auth user CRUD. |
39
+ | <a id="channel"></a> `channel` | `readonly` | [`RemoteSandboxChannel`](#remotesandboxchannel-1) | The raw worker op/sub relay channel (narrowed to the wire payload types). |
40
+ | <a id="currentuser"></a> `currentUser` | `public` | \{ `token?`: `Record`\<`string`, `unknown`\>; `uid`: `string`; \} | Current authenticated user across the sandbox. Mutated by `pyric/auth`'s `signInAnonymously` / `signInWithEmailAndPassword` / `signOut` / `sandbox.setUser`. Read per-call by service factories (e.g. a future `getFirestore(sandbox)` overload) so they see auth state changes without re-binding handles. Defaults to `null` (anonymous / signed out). **Independent of `withAuth({uid})`** — `withAuth` still produces a frozen [SandboxContext](pyric-firestore-reference-api.md#sandboxcontext) that carries its own identity for the runner's test code (the existing pattern: explicit identity per service call). `currentUser` exists for the `pyric/auth` mirror, where consumer app code drives identity through a stateful `Auth` handle rather than naming it per call. |
41
+ | `currentUser.token?` | `public` | `Record`\<`string`, `unknown`\> | - |
42
+ | `currentUser.uid` | `public` | `string` | - |
43
+ | <a id="ready"></a> `ready` | `readonly` | `Promise`\<`void`\> | - |
44
+ | <a id="rtdb"></a> `rtdb` | `readonly` | [`RemoteRtdb`](#remotertdb) | RTDB conveniences (admin lens pinned). |
45
+ | <a id="serveurl"></a> `serveUrl` | `readonly` | `string` | Base URL of the `pyric dev` this handle is attached to (used in error guidance: "open <serveUrl> in a browser and retry"). |
46
+ | <a id="storage"></a> `storage` | `readonly` | [`RemoteStorage`](#remotestorage) | Storage conveniences (admin lens pinned; 8 MiB per-op byte cap). |
47
+
48
+ #### Methods
49
+
50
+ <a id="clearpersistence"></a>
51
+
52
+ ##### clearPersistence()
53
+
54
+ ```ts
55
+ clearPersistence(): Promise<void>;
56
+ ```
57
+
58
+ Wipe the persisted blob for this sandbox's `key`. In-memory state
59
+ is left intact — call `reset()` if you want both. Useful for
60
+ "sign out and forget" flows.
61
+
62
+ No-op when persistence is not enabled.
63
+
64
+ ###### Returns
65
+
66
+ `Promise`\<`void`\>
67
+
68
+ ###### Inherited from
69
+
70
+ [`RemoteSandbox`](#remotesandbox).[`clearPersistence`](#clearpersistence-2)
71
+
72
+ <a id="close"></a>
73
+
74
+ ##### close()
75
+
76
+ ```ts
77
+ close(): void;
78
+ ```
79
+
80
+ Close the connection. In-flight ops reject; subscriptions stop.
81
+
82
+ ###### Returns
83
+
84
+ `void`
85
+
86
+ ###### Inherited from
87
+
88
+ [`RemoteSandbox`](#remotesandbox).[`close`](#close-2)
89
+
90
+ <a id="dispose"></a>
91
+
92
+ ##### dispose()
93
+
94
+ ```ts
95
+ dispose(): void;
96
+ ```
97
+
98
+ Tear down listener registries on this sandbox's environment without
99
+ replacing it. Use this when you're about to discard the sandbox
100
+ itself (e.g. `runner.reseed()` builds a fresh sandbox rather than
101
+ calling `reset()`) and want to drop callback references on the
102
+ outgoing instance defensively. Idempotent. Does not touch data.
103
+
104
+ ###### Returns
105
+
106
+ `void`
107
+
108
+ ###### Inherited from
109
+
110
+ [`RemoteSandbox`](#remotesandbox).[`dispose`](#dispose-2)
111
+
112
+ <a id="enablepersistence"></a>
113
+
114
+ ##### enablePersistence()
115
+
116
+ ```ts
117
+ enablePersistence(options: SandboxPersistenceOptions): Promise<void>;
118
+ ```
119
+
120
+ Persist the sandbox's data to a backend and restore it on next
121
+ `enablePersistence` call. The default `'indexedDB'` backend turns
122
+ the sandbox into the host page's local Firestore — writes flush
123
+ automatically and a fresh `initializeSandbox()` rehydrates from
124
+ the prior session.
125
+
126
+ Restoration happens before the promise resolves; awaiting this
127
+ call is sufficient to guarantee in-memory state matches the
128
+ persisted blob.
129
+
130
+ Idempotent across the same `key` — calling twice in one process
131
+ is a no-op on the second call. Different keys are rejected as an
132
+ error (a sandbox can persist to at most one backend at a time).
133
+
134
+ Listener semantics: every write event the sandbox emits triggers
135
+ a debounced flush (default 250ms). Browser hosts additionally
136
+ flush on `beforeunload` so a page navigation doesn't lose the
137
+ tail of the debounce window.
138
+
139
+ See [SandboxPersistenceOptions](pyric-sandbox-reference-api.md#sandboxpersistenceoptions) for backend selection and
140
+ tuning.
141
+
142
+ ###### Parameters
143
+
144
+ | Parameter | Type |
145
+ | :------ | :------ |
146
+ | `options` | [`SandboxPersistenceOptions`](pyric-sandbox-reference-api.md#sandboxpersistenceoptions) |
147
+
148
+ ###### Returns
149
+
150
+ `Promise`\<`void`\>
151
+
152
+ ###### Inherited from
153
+
154
+ [`RemoteSandbox`](#remotesandbox).[`enablePersistence`](#enablepersistence-2)
155
+
156
+ <a id="enabletabsync"></a>
157
+
158
+ ##### enableTabSync()
159
+
160
+ ```ts
161
+ enableTabSync(options?: TabSyncOptions): () => void;
162
+ ```
163
+
164
+ Enable cross-tab realtime sync via `BroadcastChannel`. A write in
165
+ this tab will propagate to every OTHER tab of the same origin that
166
+ also called `enableTabSync`, causing their `onSnapshot` listeners to
167
+ re-evaluate — restoring production's cross-client realtime behavior.
168
+
169
+ **Opt-in, OFF by default.** Firestore only (RTDB is a follow-on).
170
+
171
+ Returns a disable function. Calling it removes the `onEvent`
172
+ subscription, the channel message listener, and closes the channel
173
+ (when it was created internally). After disable, no further propagation
174
+ occurs in either direction.
175
+
176
+ **Multi-writer note:** concurrent writes from two tabs to the same doc
177
+ produce last-write-wins divergence — there is no conflict resolution.
178
+ The intended model is one active writer (one user, one tab) with
179
+ observers in other tabs; this covers the overwhelming majority of
180
+ local development scenarios.
181
+
182
+ ###### Parameters
183
+
184
+ | Parameter | Type |
185
+ | :------ | :------ |
186
+ | `options?` | [`TabSyncOptions`](pyric-sandbox-reference-api.md#tabsyncoptions) |
187
+
188
+ ###### Returns
189
+
190
+ ```ts
191
+ (): void;
192
+ ```
193
+
194
+ ###### Returns
195
+
196
+ `void`
197
+
198
+ ###### See
199
+
200
+ [TabSyncOptions](pyric-sandbox-reference-api.md#tabsyncoptions) for channel injection (tests) and originId.
201
+
202
+ ###### Example
203
+
204
+ ```ts
205
+ // In every tab that should participate in realtime:
206
+ const sandbox = initializeSandbox();
207
+ const disableSync = sandbox.enableTabSync();
208
+ // Later, to stop syncing:
209
+ disableSync();
210
+ ```
211
+
212
+ ###### Inherited from
213
+
214
+ [`RemoteSandbox`](#remotesandbox).[`enableTabSync`](#enabletabsync-2)
215
+
216
+ <a id="flush"></a>
217
+
218
+ ##### flush()
219
+
220
+ ```ts
221
+ flush(): Promise<void>;
222
+ ```
223
+
224
+ Force a snapshot to the configured persistence backend right now.
225
+ Useful before a manual navigation, or in tests that need
226
+ deterministic ordering against the debounce window. Resolves once
227
+ the write hits the backend.
228
+
229
+ Throws if persistence is not enabled.
230
+
231
+ ###### Returns
232
+
233
+ `Promise`\<`void`\>
234
+
235
+ ###### Inherited from
236
+
237
+ [`RemoteSandbox`](#remotesandbox).[`flush`](#flush-2)
238
+
239
+ <a id="history"></a>
240
+
241
+ ##### history()
242
+
243
+ ```ts
244
+ history(): SandboxEvent[];
245
+ ```
246
+
247
+ Every [SandboxEvent](pyric-sandbox-reference-api.md#sandboxevent) this sandbox has emitted since init or
248
+ the last `reset()`. Returns a defensive copy.
249
+
250
+ Use this for replay: hand the array to `replay(events, rules)`
251
+ from `pyric/sandbox` and the engine re-issues every
252
+ captured write against a fresh sandbox.
253
+
254
+ Unlike [onEvent](pyric-firestore-reference-api.md#onevent) (live stream from the moment of subscribe),
255
+ `history()` returns *every* event the sandbox has seen — useful
256
+ for consumers that attach late (e.g., loading a saved session
257
+ before subscribing) or that need a snapshot at a particular moment.
258
+
259
+ `reset()` and `dispose()` each append a closing `session_boundary`
260
+ event; `reset()` then clears the history. Consumers that took a
261
+ snapshot *before* reset retain the boundary in their copy.
262
+
263
+ ###### Returns
264
+
265
+ [`SandboxEvent`](pyric-sandbox-reference-api.md#sandboxevent)[]
266
+
267
+ ###### Inherited from
268
+
269
+ [`RemoteSandbox`](#remotesandbox).[`history`](#history-2)
270
+
271
+ <a id="loadsnapshot"></a>
272
+
273
+ ##### loadSnapshot()
274
+
275
+ ```ts
276
+ loadSnapshot(data: SandboxSnapshot): void;
277
+ ```
278
+
279
+ CLOBBER-restore the sandbox's entire state from a prior [snapshot](pyric-firestore-reference-api.md#snapshot):
280
+ `reset()` (clears firestore + the signed-in session), then rebuild firestore
281
+ from `data` and restore each registered service. This is a TOTAL replace —
282
+ documents absent from `data` do NOT survive — and is the counterpart to
283
+ [snapshot](pyric-firestore-reference-api.md#snapshot). It is what makes "transfer (clobber) one instance's data
284
+ into another" and named-branch switching possible.
285
+
286
+ Fires a `session_boundary` (reset phase), re-evaluates live listeners against
287
+ the loaded state, and the next persistence flush writes the loaded state.
288
+ Services present in `data` but not currently registered are skipped (a
289
+ snapshot taken via [snapshot](pyric-firestore-reference-api.md#snapshot) always includes every registered
290
+ service, so this only affects cross-instance imports from a sandbox that had
291
+ a service this one lacks).
292
+
293
+ ###### Parameters
294
+
295
+ | Parameter | Type |
296
+ | :------ | :------ |
297
+ | `data` | [`SandboxSnapshot`](pyric-sandbox-reference-api.md#sandboxsnapshot) |
298
+
299
+ ###### Returns
300
+
301
+ `void`
302
+
303
+ ###### Inherited from
304
+
305
+ [`RemoteSandbox`](#remotesandbox).[`loadSnapshot`](#loadsnapshot-2)
306
+
307
+ <a id="oncurrentuserchanged"></a>
308
+
309
+ ##### onCurrentUserChanged()
310
+
311
+ ```ts
312
+ onCurrentUserChanged(cb: (user: {
313
+ token?: Record<string, unknown>;
314
+ uid: string;
315
+ }) => void): () => void;
316
+ ```
317
+
318
+ Subscribe to `currentUser` changes. Fires on every mutation —
319
+ sign-in, sign-out, user swap. Does NOT fire on subscribe.
320
+
321
+ Survives `reset()` and `dispose()` only as a no-op: a disposed
322
+ sandbox emits nothing further; a reset sandbox clears
323
+ `currentUser` to `null` (and fires the change) before swapping
324
+ the env.
325
+
326
+ Returns an unsubscribe function. Listener errors are swallowed —
327
+ subscribers are observational, the sandbox does not propagate
328
+ their errors.
329
+
330
+ ###### Parameters
331
+
332
+ | Parameter | Type |
333
+ | :------ | :------ |
334
+ | `cb` | (`user`: \{ `token?`: `Record`\<`string`, `unknown`\>; `uid`: `string`; \}) => `void` |
335
+
336
+ ###### Returns
337
+
338
+ ```ts
339
+ (): void;
340
+ ```
341
+
342
+ ###### Returns
343
+
344
+ `void`
345
+
346
+ ###### Inherited from
347
+
348
+ [`RemoteSandbox`](#remotesandbox).[`onCurrentUserChanged`](#oncurrentuserchanged-2)
349
+
350
+ <a id="onevent"></a>
351
+
352
+ ##### onEvent()
353
+
354
+ ```ts
355
+ onEvent(cb: (event: SandboxEvent) => void): () => void;
356
+ ```
357
+
358
+ Subscribe to every event the sandbox emits — see [SandboxEvent](pyric-sandbox-reference-api.md#sandboxevent)
359
+ for the discriminated-union shape. One subscription covers
360
+ request/denial/snapshot-error/listener-lifecycle/session-boundary;
361
+ filter on `event.kind` to recover individual streams.
362
+
363
+ Replaces the prior three-channel surface (`onRequest` / `onDenial`
364
+ / `onSnapshotError`) — see issue #307. Filter cookbook:
365
+ - All denials: `event.kind === 'request' && event.result === 'deny'`
366
+ - Stream errors: `event.kind === 'listener_errored'`
367
+ - Per-op traffic: `event.kind === 'request'`
368
+
369
+ Survives `sandbox.reset()` — the subscription is held on the
370
+ sandbox, not on the underlying environment. A `session_boundary`
371
+ event with `phase: 'reset'` fires before the env swap so consumers
372
+ can segment their stream.
373
+
374
+ Returns an unsubscribe function. Listener errors are swallowed so a
375
+ faulty subscriber can't change rule semantics or hide other events.
376
+ Both synchronous throws and rejected Promises from async callbacks
377
+ are silently discarded — subscribers are **observational**, the
378
+ sandbox doesn't await them and doesn't propagate their errors.
379
+
380
+ ###### Parameters
381
+
382
+ | Parameter | Type |
383
+ | :------ | :------ |
384
+ | `cb` | (`event`: [`SandboxEvent`](pyric-sandbox-reference-api.md#sandboxevent)) => `void` |
385
+
386
+ ###### Returns
387
+
388
+ ```ts
389
+ (): void;
390
+ ```
391
+
392
+ ###### Returns
393
+
394
+ `void`
395
+
396
+ ###### Inherited from
397
+
398
+ [`RemoteSandbox`](#remotesandbox).[`onEvent`](#onevent-2)
399
+
400
+ <a id="registerpersistableservice"></a>
401
+
402
+ ##### registerPersistableService()
403
+
404
+ ```ts
405
+ registerPersistableService(name: string, hooks: PersistableService): () => void;
406
+ ```
407
+
408
+ Register a service (auth, storage, …) as a persistence participant.
409
+ The sandbox calls `hooks.snapshot()` on every flush and
410
+ `hooks.restore(data)` on restore. If `hooks.subscribe` is provided,
411
+ the persistence controller subscribes and schedules a debounced
412
+ flush on each change — so auth-user edits flush promptly, not only
413
+ on the next Firestore write.
414
+
415
+ Returns an unregister function — call it if the service is torn
416
+ down before the sandbox is disposed (uncommon in practice; the
417
+ sandbox's `dispose()` clears the registry anyway).
418
+
419
+ Throws `failed-precondition` when a service with the same `name` is
420
+ already registered — the auth package registers `'auth'` once when
421
+ `getAuth(sandbox)` first creates a backend, so accidental double-
422
+ registration is a caller bug, not a no-op.
423
+
424
+ **Advanced / internal API.** Service packages (auth, storage) call
425
+ this when they first attach to a sandbox. Consumer app code should
426
+ not need to call this directly.
427
+
428
+ ###### Parameters
429
+
430
+ | Parameter | Type |
431
+ | :------ | :------ |
432
+ | `name` | `string` |
433
+ | `hooks` | [`PersistableService`](pyric-sandbox-reference-api.md#persistableservice) |
434
+
435
+ ###### Returns
436
+
437
+ ```ts
438
+ (): void;
439
+ ```
440
+
441
+ ###### Returns
442
+
443
+ `void`
444
+
445
+ ###### Inherited from
446
+
447
+ [`RemoteSandbox`](#remotesandbox).[`registerPersistableService`](#registerpersistableservice-2)
448
+
449
+ <a id="reset"></a>
450
+
451
+ ##### reset()
452
+
453
+ ```ts
454
+ reset(): void;
455
+ ```
456
+
457
+ Reset the underlying environment to a fresh state — wipes data,
458
+ rules, and any service-specific configuration.
459
+
460
+ Snapshot listeners attached to the OLD environment are dropped at
461
+ the swap — they can't survive because their target docs have been
462
+ wiped. `onEvent` subscribers DO survive — the registry lives on
463
+ the sandbox, and a `session_boundary` event with `phase: 'reset'`
464
+ fires before the swap so subscribers know the rollover happened.
465
+ Existing [SandboxContext](pyric-firestore-reference-api.md#sandboxcontext)s continue to work — their sandbox
466
+ reference is stable; subsequent operations resolve to the new env.
467
+
468
+ ###### Returns
469
+
470
+ `void`
471
+
472
+ ###### Inherited from
473
+
474
+ [`RemoteSandbox`](#remotesandbox).[`reset`](#reset-2)
475
+
476
+ <a id="resetall"></a>
477
+
478
+ ##### resetAll()
479
+
480
+ ```ts
481
+ resetAll(): Promise<{
482
+ errors: string[];
483
+ }>;
484
+ ```
485
+
486
+ Reset the WHOLE sandbox: [reset](pyric-firestore-reference-api.md#reset) (Firestore env + signed-in
487
+ session), then clear every registered persistable service that
488
+ provides a [PersistableService.reset](pyric-sandbox-reference-api.md#reset-2) hook — auth users, the
489
+ RTDB tree, storage objects. This is the one sandbox-owned "wipe
490
+ everything" path: because it iterates the service registry, a new
491
+ service that registers with a `reset` hook is cleared automatically,
492
+ and a consumer (Pyric Studio's reset) cannot forget one.
493
+
494
+ Service resets may be async (storage clears IndexedDB stores); the
495
+ returned promise resolves when every service has finished clearing.
496
+ A service whose `reset` throws is isolated (others still clear) and
497
+ REPORTED in the returned `errors` (as `name: message`) — a reset that
498
+ leaves data behind must never look successful to the caller.
499
+
500
+ ###### Returns
501
+
502
+ `Promise`\<\{
503
+ `errors`: `string`[];
504
+ \}\>
505
+
506
+ ###### Inherited from
507
+
508
+ [`RemoteSandbox`](#remotesandbox).[`resetAll`](#resetall-2)
509
+
510
+ <a id="runwithprovenance"></a>
511
+
512
+ ##### runWithProvenance()?
513
+
514
+ ```ts
515
+ optional runWithProvenance<T>(provenance: EventProvenance, fn: () => T): T;
516
+ ```
517
+
518
+ Run `fn` with ambient [EventProvenance](pyric-sandbox-reference-api.md#eventprovenance) defaults: every event
519
+ emitted SYNCHRONOUSLY during `fn` that doesn't already carry a
520
+ provenance field (on the event itself or via an explicit per-emit
521
+ override) is stamped with these values instead of the global
522
+ defaults. This is the mechanical "who issued this op" seam the
523
+ serve worker uses to tag Studio-issued ops (`actor: { kind:
524
+ 'studio' }`) and to stamp the auth lens an op ran under
525
+ (`authLens`) — declared by the caller that issues the op, never
526
+ inferred from the op's shape.
527
+
528
+ SYNCHRONOUS WINDOW: the ambient values apply only until `fn`
529
+ returns (for an async `fn`, its synchronous prefix — which covers
530
+ the local environment's rules eval + event emission, since those
531
+ run before the op's promise is handed back). Work an op DEFERS
532
+ (snapshot-listener deliveries and re-evals drain on a microtask,
533
+ off-stack) is intentionally OUTSIDE the window: a listener re-eval
534
+ belongs to the listener's owner, not to whoever's write triggered
535
+ it. Nested calls stack — the innermost window wins per field, and
536
+ each window restores the previous one on exit (including on throw).
537
+
538
+ OPTIONAL because remote sandbox proxies can't provide an ambient
539
+ emit window (events are emitted in the worker they front). Callers
540
+ spell `sandbox.runWithProvenance?.(prov, fn) ?? fn()`.
541
+
542
+ ###### Type Parameters
543
+
544
+ | Type Parameter |
545
+ | :------ |
546
+ | `T` |
547
+
548
+ ###### Parameters
549
+
550
+ | Parameter | Type |
551
+ | :------ | :------ |
552
+ | `provenance` | [`EventProvenance`](pyric-sandbox-reference-api.md#eventprovenance) |
553
+ | `fn` | () => `T` |
554
+
555
+ ###### Returns
556
+
557
+ `T`
558
+
559
+ ###### Inherited from
560
+
561
+ [`RemoteSandbox`](#remotesandbox).[`runWithProvenance`](#runwithprovenance-2)
562
+
563
+ <a id="snapshot"></a>
564
+
565
+ ##### snapshot()
566
+
567
+ ```ts
568
+ snapshot(): SandboxSnapshot;
569
+ ```
570
+
571
+ Capture a snapshot of every service's state. For v1 with only
572
+ Firestore, the return value carries a `firestore` key mapping doc
573
+ paths to data. Future services will add their own keys.
574
+
575
+ ###### Returns
576
+
577
+ [`SandboxSnapshot`](pyric-sandbox-reference-api.md#sandboxsnapshot)
578
+
579
+ ###### Inherited from
580
+
581
+ [`RemoteSandbox`](#remotesandbox).[`snapshot`](#snapshot-2)
582
+
583
+ <a id="withauth"></a>
584
+
585
+ ##### withAuth()
586
+
587
+ ```ts
588
+ withAuth(auth: {
589
+ token?: Record<string, unknown>;
590
+ uid: string;
591
+ }): SandboxContext;
592
+ ```
593
+
594
+ Derive a context bound to this sandbox under the given auth
595
+ identity. Operations through services attached to the returned
596
+ context evaluate rules under that identity. Many contexts can
597
+ coexist for one sandbox; data is shared.
598
+
599
+ `null` is anonymous; an `AuthState` object names the user (and
600
+ optional custom claims). Passing `undefined` is a deliberate
601
+ error — say `withAuth(null)` for anonymous so the call site is
602
+ unambiguous.
603
+
604
+ ###### Parameters
605
+
606
+ | Parameter | Type |
607
+ | :------ | :------ |
608
+ | `auth` | \{ `token?`: `Record`\<`string`, `unknown`\>; `uid`: `string`; \} |
609
+ | `auth.token?` | `Record`\<`string`, `unknown`\> |
610
+ | `auth.uid` | `string` |
611
+
612
+ ###### Returns
613
+
614
+ [`SandboxContext`](pyric-firestore-reference-api.md#sandboxcontext)
615
+
616
+ ###### Example
617
+
618
+ ```ts
619
+ const sandbox = initializeSandbox();
620
+ const dbAlice = getFirestore(sandbox.withAuth({ uid: 'alice' }));
621
+ const dbAnon = getFirestore(sandbox.withAuth(null));
622
+ ```
623
+
624
+ ###### Inherited from
625
+
626
+ [`RemoteSandbox`](#remotesandbox).[`withAuth`](#withauth-2)
627
+
628
+ ***
629
+
630
+ <a id="remoteauthadmin"></a>
631
+
632
+ ### RemoteAuthAdmin
633
+
634
+ Admin auth user-CRUD passthrough (never lensed — auth ops operate the
635
+ worker's user pool directly, mirroring `pyric/auth`'s sandbox ops).
636
+
637
+ #### Methods
638
+
639
+ <a id="clearusers"></a>
640
+
641
+ ##### clearUsers()
642
+
643
+ ```ts
644
+ clearUsers(): Promise<void>;
645
+ ```
646
+
647
+ ###### Returns
648
+
649
+ `Promise`\<`void`\>
650
+
651
+ <a id="createuser"></a>
652
+
653
+ ##### createUser()
654
+
655
+ ```ts
656
+ createUser(request: CreateUserRequest): Promise<AuthUserRecord>;
657
+ ```
658
+
659
+ ###### Parameters
660
+
661
+ | Parameter | Type |
662
+ | :------ | :------ |
663
+ | `request` | [`CreateUserRequest`](pyric-auth-reference-api.md#createuserrequest) |
664
+
665
+ ###### Returns
666
+
667
+ `Promise`\<[`AuthUserRecord`](pyric-auth-reference-api.md#authuserrecord)\>
668
+
669
+ <a id="deleteuser"></a>
670
+
671
+ ##### deleteUser()
672
+
673
+ ```ts
674
+ deleteUser(uid: string): Promise<void>;
675
+ ```
676
+
677
+ ###### Parameters
678
+
679
+ | Parameter | Type |
680
+ | :------ | :------ |
681
+ | `uid` | `string` |
682
+
683
+ ###### Returns
684
+
685
+ `Promise`\<`void`\>
686
+
687
+ <a id="listusers"></a>
688
+
689
+ ##### listUsers()
690
+
691
+ ```ts
692
+ listUsers(): Promise<AuthUserRecord[]>;
693
+ ```
694
+
695
+ ###### Returns
696
+
697
+ `Promise`\<[`AuthUserRecord`](pyric-auth-reference-api.md#authuserrecord)[]\>
698
+
699
+ <a id="updateuser"></a>
700
+
701
+ ##### updateUser()
702
+
703
+ ```ts
704
+ updateUser(uid: string, request: UpdateUserRequest): Promise<AuthUserRecord>;
705
+ ```
706
+
707
+ ###### Parameters
708
+
709
+ | Parameter | Type |
710
+ | :------ | :------ |
711
+ | `uid` | `string` |
712
+ | `request` | [`UpdateUserRequest`](pyric-auth-reference-api.md#updateuserrequest) |
713
+
714
+ ###### Returns
715
+
716
+ `Promise`\<[`AuthUserRecord`](pyric-auth-reference-api.md#authuserrecord)\>
717
+
718
+ ***
719
+
720
+ <a id="remotertdb"></a>
721
+
722
+ ### RemoteRtdb
723
+
724
+ Thin RTDB conveniences over the channel. Every call pins
725
+ `actAs: { mode: 'admin' }` — firebase-admin's rules-bypass semantics,
726
+ matching what `pyric-admin`'s database backend needs. Use the raw
727
+ `channel` for lensed (rules-evaluated) access.
728
+
729
+ #### Methods
730
+
731
+ <a id="get"></a>
732
+
733
+ ##### get()
734
+
735
+ ```ts
736
+ get(path: string): Promise<unknown>;
737
+ ```
738
+
739
+ Read the value at `path` (null when absent).
740
+
741
+ ###### Parameters
742
+
743
+ | Parameter | Type |
744
+ | :------ | :------ |
745
+ | `path` | `string` |
746
+
747
+ ###### Returns
748
+
749
+ `Promise`\<`unknown`\>
750
+
751
+ <a id="onvalue"></a>
752
+
753
+ ##### onValue()
754
+
755
+ ```ts
756
+ onValue(
757
+ path: string,
758
+ callback: (snapshot: RemoteRtdbSnapshot) => void,
759
+ onError?: (err: Error & {
760
+ code: string;
761
+ }) => void): () => void;
762
+ ```
763
+
764
+ Subscribe to the value at `path` (initial snapshot + every change).
765
+
766
+ ###### Parameters
767
+
768
+ | Parameter | Type |
769
+ | :------ | :------ |
770
+ | `path` | `string` |
771
+ | `callback` | (`snapshot`: [`RemoteRtdbSnapshot`](#remotertdbsnapshot)) => `void` |
772
+ | `onError?` | (`err`: `Error` & \{ `code`: `string`; \}) => `void` |
773
+
774
+ ###### Returns
775
+
776
+ ```ts
777
+ (): void;
778
+ ```
779
+
780
+ ###### Returns
781
+
782
+ `void`
783
+
784
+ <a id="push"></a>
785
+
786
+ ##### push()
787
+
788
+ ```ts
789
+ push(path: string, value?: unknown): Promise<{
790
+ key: string;
791
+ path: string;
792
+ }>;
793
+ ```
794
+
795
+ Push `value` under a CLIENT-minted 20-char push id (the worker-protocol
796
+ contract: `rtdb.push` carries the key, so `.key` is known synchronously
797
+ on the pyric-admin side). Resolves with the minted key + full path.
798
+
799
+ ###### Parameters
800
+
801
+ | Parameter | Type |
802
+ | :------ | :------ |
803
+ | `path` | `string` |
804
+ | `value?` | `unknown` |
805
+
806
+ ###### Returns
807
+
808
+ `Promise`\<\{
809
+ `key`: `string`;
810
+ `path`: `string`;
811
+ \}\>
812
+
813
+ <a id="remove"></a>
814
+
815
+ ##### remove()
816
+
817
+ ```ts
818
+ remove(path: string): Promise<void>;
819
+ ```
820
+
821
+ ###### Parameters
822
+
823
+ | Parameter | Type |
824
+ | :------ | :------ |
825
+ | `path` | `string` |
826
+
827
+ ###### Returns
828
+
829
+ `Promise`\<`void`\>
830
+
831
+ <a id="set"></a>
832
+
833
+ ##### set()
834
+
835
+ ```ts
836
+ set(path: string, value: unknown): Promise<void>;
837
+ ```
838
+
839
+ ###### Parameters
840
+
841
+ | Parameter | Type |
842
+ | :------ | :------ |
843
+ | `path` | `string` |
844
+ | `value` | `unknown` |
845
+
846
+ ###### Returns
847
+
848
+ `Promise`\<`void`\>
849
+
850
+ <a id="update"></a>
851
+
852
+ ##### update()
853
+
854
+ ```ts
855
+ update(path: string, values: Record<string, unknown>): Promise<void>;
856
+ ```
857
+
858
+ ###### Parameters
859
+
860
+ | Parameter | Type |
861
+ | :------ | :------ |
862
+ | `path` | `string` |
863
+ | `values` | `Record`\<`string`, `unknown`\> |
864
+
865
+ ###### Returns
866
+
867
+ `Promise`\<`void`\>
868
+
869
+ ***
870
+
871
+ <a id="remotertdbsnapshot"></a>
872
+
873
+ ### RemoteRtdbSnapshot
874
+
875
+ Wire shape of an RTDB snapshot as the worker host serializes it.
876
+
877
+ #### Properties
878
+
879
+ | Property | Type |
880
+ | :------ | :------ |
881
+ | <a id="exists"></a> `exists` | `boolean` |
882
+ | <a id="key"></a> `key` | `string` |
883
+ | <a id="size"></a> `size` | `number` |
884
+ | <a id="value"></a> `value` | `unknown` |
885
+
886
+ ***
887
+
888
+ <a id="remotesandbox"></a>
889
+
890
+ ### RemoteSandbox
891
+
892
+ The Node-side remote sandbox handle. Extends `pyric/sandbox`'s branded
893
+ [RemoteSandboxBase](pyric-sandbox-reference-api.md#remotesandbox) — structurally a full `Sandbox`, so it can be
894
+ passed to `pyric-admin/app`'s `initializeApp({ sandbox })`, whose RTDB and
895
+ Auth backends dispatch on the brand and route through [channel](#channel-1).
896
+
897
+ Sandbox members that are genuinely sync-only (`admin`, `snapshot()`,
898
+ `history()`, `onEvent`, `currentUser`, …) cannot be mirrored over the
899
+ wire in slice 1 and throw a remediating `unimplemented` error naming
900
+ what to do instead. Implemented members: `withAuth` (pure local pair
901
+ construction) and `dispose` (aliases [close](#close-2)).
902
+
903
+ #### Extends
904
+
905
+ - [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox)
906
+
907
+ #### Extended by
908
+
909
+ - [`LazyRemoteSandbox`](#lazyremotesandbox)
910
+
911
+ #### Properties
912
+
913
+ | Property | Modifier | Type | Description | Overrides |
914
+ | :------ | :------ | :------ | :------ | :------ |
915
+ | <a id="remote_sandbox-1"></a> `[REMOTE_SANDBOX]` | `readonly` | `true` | - | - |
916
+ | <a id="admin-1"></a> `admin` | `readonly` | `SandboxAdmin` | Admin-plane access (rule-bypass reads). Identity-agnostic by design — admin reads aren't gated on auth, so they live on the sandbox, not on a context. See SandboxAdmin. | - |
917
+ | <a id="auth-1"></a> `auth` | `readonly` | [`RemoteAuthAdmin`](#remoteauthadmin) | Admin auth user CRUD. | - |
918
+ | <a id="channel-1"></a> `channel` | `readonly` | [`RemoteSandboxChannel`](#remotesandboxchannel-1) | The raw worker op/sub relay channel (narrowed to the wire payload types). | [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`channel`](pyric-sandbox-reference-api.md#channel) |
919
+ | <a id="currentuser-1"></a> `currentUser` | `public` | \{ `token?`: `Record`\<`string`, `unknown`\>; `uid`: `string`; \} | Current authenticated user across the sandbox. Mutated by `pyric/auth`'s `signInAnonymously` / `signInWithEmailAndPassword` / `signOut` / `sandbox.setUser`. Read per-call by service factories (e.g. a future `getFirestore(sandbox)` overload) so they see auth state changes without re-binding handles. Defaults to `null` (anonymous / signed out). **Independent of `withAuth({uid})`** — `withAuth` still produces a frozen [SandboxContext](pyric-firestore-reference-api.md#sandboxcontext) that carries its own identity for the runner's test code (the existing pattern: explicit identity per service call). `currentUser` exists for the `pyric/auth` mirror, where consumer app code drives identity through a stateful `Auth` handle rather than naming it per call. | - |
920
+ | `currentUser.token?` | `public` | `Record`\<`string`, `unknown`\> | - | - |
921
+ | `currentUser.uid` | `public` | `string` | - | - |
922
+ | <a id="rtdb-1"></a> `rtdb` | `readonly` | [`RemoteRtdb`](#remotertdb) | RTDB conveniences (admin lens pinned). | - |
923
+ | <a id="serveurl-1"></a> `serveUrl` | `readonly` | `string` | Base URL of the `pyric dev` this handle is attached to (used in error guidance: "open <serveUrl> in a browser and retry"). | - |
924
+ | <a id="storage-1"></a> `storage` | `readonly` | [`RemoteStorage`](#remotestorage) | Storage conveniences (admin lens pinned; 8 MiB per-op byte cap). | - |
925
+
926
+ #### Methods
927
+
928
+ <a id="clearpersistence-2"></a>
929
+
930
+ ##### clearPersistence()
931
+
932
+ ```ts
933
+ clearPersistence(): Promise<void>;
934
+ ```
935
+
936
+ Wipe the persisted blob for this sandbox's `key`. In-memory state
937
+ is left intact — call `reset()` if you want both. Useful for
938
+ "sign out and forget" flows.
30
939
 
31
- - [`RemoteSandbox`](#remotesandbox)
940
+ No-op when persistence is not enabled.
32
941
 
33
- #### Properties
942
+ ###### Returns
34
943
 
35
- | Property | Modifier | Type | Description |
36
- | :------ | :------ | :------ | :------ |
37
- | <a id="auth"></a> `auth` | `readonly` | [`RemoteAuthAdmin`](#remoteauthadmin) | Admin auth user CRUD. |
38
- | <a id="channel"></a> `channel` | `readonly` | [`RemoteSandboxChannel`](#remotesandboxchannel-1) | The raw worker op/sub relay channel (narrowed to the wire payload types). |
39
- | <a id="ready"></a> `ready` | `readonly` | `Promise`\<`void`\> | - |
40
- | <a id="rtdb"></a> `rtdb` | `readonly` | [`RemoteRtdb`](#remotertdb) | RTDB conveniences (admin lens pinned). |
41
- | <a id="storage"></a> `storage` | `readonly` | [`RemoteStorage`](#remotestorage) | Storage conveniences (admin lens pinned; 8 MiB per-op byte cap). |
944
+ `Promise`\<`void`\>
42
945
 
43
- #### Methods
946
+ ###### Inherited from
44
947
 
45
- <a id="close"></a>
948
+ [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`clearPersistence`](pyric-sandbox-reference-api.md#clearpersistence-2)
949
+
950
+ <a id="close-2"></a>
46
951
 
47
952
  ##### close()
48
953
 
@@ -56,155 +961,251 @@ Close the connection. In-flight ops reject; subscriptions stop.
56
961
 
57
962
  `void`
58
963
 
59
- ###### Inherited from
964
+ <a id="dispose-2"></a>
60
965
 
61
- [`RemoteSandbox`](#remotesandbox).[`close`](#close-2)
966
+ ##### dispose()
62
967
 
63
- ***
968
+ ```ts
969
+ dispose(): void;
970
+ ```
64
971
 
65
- <a id="remoteauthadmin"></a>
972
+ Tear down listener registries on this sandbox's environment without
973
+ replacing it. Use this when you're about to discard the sandbox
974
+ itself (e.g. `runner.reseed()` builds a fresh sandbox rather than
975
+ calling `reset()`) and want to drop callback references on the
976
+ outgoing instance defensively. Idempotent. Does not touch data.
66
977
 
67
- ### RemoteAuthAdmin
978
+ ###### Returns
68
979
 
69
- Admin auth user-CRUD passthrough (never lensed — auth ops operate the
70
- worker's user pool directly, mirroring `pyric/auth`'s sandbox ops).
980
+ `void`
71
981
 
72
- #### Methods
982
+ ###### Inherited from
73
983
 
74
- <a id="clearusers"></a>
984
+ [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`dispose`](pyric-sandbox-reference-api.md#dispose-4)
75
985
 
76
- ##### clearUsers()
986
+ <a id="enablepersistence-2"></a>
987
+
988
+ ##### enablePersistence()
77
989
 
78
990
  ```ts
79
- clearUsers(): Promise<void>;
991
+ enablePersistence(options: SandboxPersistenceOptions): Promise<void>;
80
992
  ```
81
993
 
82
- ###### Returns
994
+ Persist the sandbox's data to a backend and restore it on next
995
+ `enablePersistence` call. The default `'indexedDB'` backend turns
996
+ the sandbox into the host page's local Firestore — writes flush
997
+ automatically and a fresh `initializeSandbox()` rehydrates from
998
+ the prior session.
83
999
 
84
- `Promise`\<`void`\>
1000
+ Restoration happens before the promise resolves; awaiting this
1001
+ call is sufficient to guarantee in-memory state matches the
1002
+ persisted blob.
85
1003
 
86
- <a id="createuser"></a>
1004
+ Idempotent across the same `key` — calling twice in one process
1005
+ is a no-op on the second call. Different keys are rejected as an
1006
+ error (a sandbox can persist to at most one backend at a time).
87
1007
 
88
- ##### createUser()
1008
+ Listener semantics: every write event the sandbox emits triggers
1009
+ a debounced flush (default 250ms). Browser hosts additionally
1010
+ flush on `beforeunload` so a page navigation doesn't lose the
1011
+ tail of the debounce window.
89
1012
 
90
- ```ts
91
- createUser(request: CreateUserRequest): Promise<AuthUserRecord>;
92
- ```
1013
+ See [SandboxPersistenceOptions](pyric-sandbox-reference-api.md#sandboxpersistenceoptions) for backend selection and
1014
+ tuning.
93
1015
 
94
1016
  ###### Parameters
95
1017
 
96
1018
  | Parameter | Type |
97
1019
  | :------ | :------ |
98
- | `request` | `CreateUserRequest` |
1020
+ | `options` | [`SandboxPersistenceOptions`](pyric-sandbox-reference-api.md#sandboxpersistenceoptions) |
99
1021
 
100
1022
  ###### Returns
101
1023
 
102
- `Promise`\<`AuthUserRecord`\>
1024
+ `Promise`\<`void`\>
103
1025
 
104
- <a id="deleteuser"></a>
1026
+ ###### Inherited from
105
1027
 
106
- ##### deleteUser()
1028
+ [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`enablePersistence`](pyric-sandbox-reference-api.md#enablepersistence-2)
1029
+
1030
+ <a id="enabletabsync-2"></a>
1031
+
1032
+ ##### enableTabSync()
107
1033
 
108
1034
  ```ts
109
- deleteUser(uid: string): Promise<void>;
1035
+ enableTabSync(options?: TabSyncOptions): () => void;
110
1036
  ```
111
1037
 
1038
+ Enable cross-tab realtime sync via `BroadcastChannel`. A write in
1039
+ this tab will propagate to every OTHER tab of the same origin that
1040
+ also called `enableTabSync`, causing their `onSnapshot` listeners to
1041
+ re-evaluate — restoring production's cross-client realtime behavior.
1042
+
1043
+ **Opt-in, OFF by default.** Firestore only (RTDB is a follow-on).
1044
+
1045
+ Returns a disable function. Calling it removes the `onEvent`
1046
+ subscription, the channel message listener, and closes the channel
1047
+ (when it was created internally). After disable, no further propagation
1048
+ occurs in either direction.
1049
+
1050
+ **Multi-writer note:** concurrent writes from two tabs to the same doc
1051
+ produce last-write-wins divergence — there is no conflict resolution.
1052
+ The intended model is one active writer (one user, one tab) with
1053
+ observers in other tabs; this covers the overwhelming majority of
1054
+ local development scenarios.
1055
+
112
1056
  ###### Parameters
113
1057
 
114
1058
  | Parameter | Type |
115
1059
  | :------ | :------ |
116
- | `uid` | `string` |
1060
+ | `options?` | [`TabSyncOptions`](pyric-sandbox-reference-api.md#tabsyncoptions) |
117
1061
 
118
1062
  ###### Returns
119
1063
 
120
- `Promise`\<`void`\>
1064
+ ```ts
1065
+ (): void;
1066
+ ```
121
1067
 
122
- <a id="listusers"></a>
1068
+ ###### Returns
123
1069
 
124
- ##### listUsers()
1070
+ `void`
1071
+
1072
+ ###### See
1073
+
1074
+ [TabSyncOptions](pyric-sandbox-reference-api.md#tabsyncoptions) for channel injection (tests) and originId.
1075
+
1076
+ ###### Example
125
1077
 
126
1078
  ```ts
127
- listUsers(): Promise<AuthUserRecord[]>;
1079
+ // In every tab that should participate in realtime:
1080
+ const sandbox = initializeSandbox();
1081
+ const disableSync = sandbox.enableTabSync();
1082
+ // Later, to stop syncing:
1083
+ disableSync();
128
1084
  ```
129
1085
 
130
- ###### Returns
1086
+ ###### Inherited from
131
1087
 
132
- `Promise`\<`AuthUserRecord`[]\>
1088
+ [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`enableTabSync`](pyric-sandbox-reference-api.md#enabletabsync-2)
133
1089
 
134
- <a id="updateuser"></a>
1090
+ <a id="flush-2"></a>
135
1091
 
136
- ##### updateUser()
1092
+ ##### flush()
137
1093
 
138
1094
  ```ts
139
- updateUser(uid: string, request: UpdateUserRequest): Promise<AuthUserRecord>;
1095
+ flush(): Promise<void>;
140
1096
  ```
141
1097
 
142
- ###### Parameters
1098
+ Force a snapshot to the configured persistence backend right now.
1099
+ Useful before a manual navigation, or in tests that need
1100
+ deterministic ordering against the debounce window. Resolves once
1101
+ the write hits the backend.
143
1102
 
144
- | Parameter | Type |
145
- | :------ | :------ |
146
- | `uid` | `string` |
147
- | `request` | `UpdateUserRequest` |
1103
+ Throws if persistence is not enabled.
148
1104
 
149
1105
  ###### Returns
150
1106
 
151
- `Promise`\<`AuthUserRecord`\>
1107
+ `Promise`\<`void`\>
152
1108
 
153
- ***
1109
+ ###### Inherited from
154
1110
 
155
- <a id="remotertdb"></a>
1111
+ [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`flush`](pyric-sandbox-reference-api.md#flush-4)
156
1112
 
157
- ### RemoteRtdb
1113
+ <a id="history-2"></a>
158
1114
 
159
- Thin RTDB conveniences over the channel. Every call pins
160
- `actAs: { mode: 'admin' }` — firebase-admin's rules-bypass semantics,
161
- matching what `pyric-admin`'s database backend needs. Use the raw
162
- `channel` for lensed (rules-evaluated) access.
1115
+ ##### history()
163
1116
 
164
- #### Methods
1117
+ ```ts
1118
+ history(): SandboxEvent[];
1119
+ ```
165
1120
 
166
- <a id="get"></a>
1121
+ Every [SandboxEvent](pyric-sandbox-reference-api.md#sandboxevent) this sandbox has emitted since init or
1122
+ the last `reset()`. Returns a defensive copy.
167
1123
 
168
- ##### get()
1124
+ Use this for replay: hand the array to `replay(events, rules)`
1125
+ from `pyric/sandbox` and the engine re-issues every
1126
+ captured write against a fresh sandbox.
1127
+
1128
+ Unlike [onEvent](pyric-firestore-reference-api.md#onevent) (live stream from the moment of subscribe),
1129
+ `history()` returns *every* event the sandbox has seen — useful
1130
+ for consumers that attach late (e.g., loading a saved session
1131
+ before subscribing) or that need a snapshot at a particular moment.
1132
+
1133
+ `reset()` and `dispose()` each append a closing `session_boundary`
1134
+ event; `reset()` then clears the history. Consumers that took a
1135
+ snapshot *before* reset retain the boundary in their copy.
1136
+
1137
+ ###### Returns
1138
+
1139
+ [`SandboxEvent`](pyric-sandbox-reference-api.md#sandboxevent)[]
1140
+
1141
+ ###### Inherited from
1142
+
1143
+ [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`history`](pyric-sandbox-reference-api.md#history-2)
1144
+
1145
+ <a id="loadsnapshot-2"></a>
1146
+
1147
+ ##### loadSnapshot()
169
1148
 
170
1149
  ```ts
171
- get(path: string): Promise<unknown>;
1150
+ loadSnapshot(data: SandboxSnapshot): void;
172
1151
  ```
173
1152
 
174
- Read the value at `path` (null when absent).
1153
+ CLOBBER-restore the sandbox's entire state from a prior [snapshot](pyric-firestore-reference-api.md#snapshot):
1154
+ `reset()` (clears firestore + the signed-in session), then rebuild firestore
1155
+ from `data` and restore each registered service. This is a TOTAL replace —
1156
+ documents absent from `data` do NOT survive — and is the counterpart to
1157
+ [snapshot](pyric-firestore-reference-api.md#snapshot). It is what makes "transfer (clobber) one instance's data
1158
+ into another" and named-branch switching possible.
1159
+
1160
+ Fires a `session_boundary` (reset phase), re-evaluates live listeners against
1161
+ the loaded state, and the next persistence flush writes the loaded state.
1162
+ Services present in `data` but not currently registered are skipped (a
1163
+ snapshot taken via [snapshot](pyric-firestore-reference-api.md#snapshot) always includes every registered
1164
+ service, so this only affects cross-instance imports from a sandbox that had
1165
+ a service this one lacks).
175
1166
 
176
1167
  ###### Parameters
177
1168
 
178
1169
  | Parameter | Type |
179
1170
  | :------ | :------ |
180
- | `path` | `string` |
1171
+ | `data` | [`SandboxSnapshot`](pyric-sandbox-reference-api.md#sandboxsnapshot) |
181
1172
 
182
1173
  ###### Returns
183
1174
 
184
- `Promise`\<`unknown`\>
1175
+ `void`
185
1176
 
186
- <a id="onvalue"></a>
1177
+ ###### Inherited from
187
1178
 
188
- ##### onValue()
1179
+ [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`loadSnapshot`](pyric-sandbox-reference-api.md#loadsnapshot-2)
1180
+
1181
+ <a id="oncurrentuserchanged-2"></a>
1182
+
1183
+ ##### onCurrentUserChanged()
189
1184
 
190
1185
  ```ts
191
- onValue(
192
- path: string,
193
- callback: (snapshot: RemoteRtdbSnapshot) => void,
194
- onError?: (err: Error & {
195
- code: string;
1186
+ onCurrentUserChanged(cb: (user: {
1187
+ token?: Record<string, unknown>;
1188
+ uid: string;
196
1189
  }) => void): () => void;
197
1190
  ```
198
1191
 
199
- Subscribe to the value at `path` (initial snapshot + every change).
1192
+ Subscribe to `currentUser` changes. Fires on every mutation —
1193
+ sign-in, sign-out, user swap. Does NOT fire on subscribe.
1194
+
1195
+ Survives `reset()` and `dispose()` only as a no-op: a disposed
1196
+ sandbox emits nothing further; a reset sandbox clears
1197
+ `currentUser` to `null` (and fires the change) before swapping
1198
+ the env.
1199
+
1200
+ Returns an unsubscribe function. Listener errors are swallowed —
1201
+ subscribers are observational, the sandbox does not propagate
1202
+ their errors.
200
1203
 
201
1204
  ###### Parameters
202
1205
 
203
1206
  | Parameter | Type |
204
1207
  | :------ | :------ |
205
- | `path` | `string` |
206
- | `callback` | (`snapshot`: [`RemoteRtdbSnapshot`](#remotertdbsnapshot)) => `void` |
207
- | `onError?` | (`err`: `Error` & \{ `code`: `string`; \}) => `void` |
1208
+ | `cb` | (`user`: \{ `token?`: `Record`\<`string`, `unknown`\>; `uid`: `string`; \}) => `void` |
208
1209
 
209
1210
  ###### Returns
210
1211
 
@@ -216,157 +1217,287 @@ Subscribe to the value at `path` (initial snapshot + every change).
216
1217
 
217
1218
  `void`
218
1219
 
219
- <a id="push"></a>
1220
+ ###### Inherited from
220
1221
 
221
- ##### push()
1222
+ [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`onCurrentUserChanged`](pyric-sandbox-reference-api.md#oncurrentuserchanged-2)
1223
+
1224
+ <a id="onevent-2"></a>
1225
+
1226
+ ##### onEvent()
222
1227
 
223
1228
  ```ts
224
- push(path: string, value?: unknown): Promise<{
225
- key: string;
226
- path: string;
227
- }>;
1229
+ onEvent(cb: (event: SandboxEvent) => void): () => void;
228
1230
  ```
229
1231
 
230
- Push `value` under a CLIENT-minted 20-char push id (the worker-protocol
231
- contract: `rtdb.push` carries the key, so `.key` is known synchronously
232
- on the pyric-admin side). Resolves with the minted key + full path.
1232
+ Subscribe to every event the sandbox emits see [SandboxEvent](pyric-sandbox-reference-api.md#sandboxevent)
1233
+ for the discriminated-union shape. One subscription covers
1234
+ request/denial/snapshot-error/listener-lifecycle/session-boundary;
1235
+ filter on `event.kind` to recover individual streams.
1236
+
1237
+ Replaces the prior three-channel surface (`onRequest` / `onDenial`
1238
+ / `onSnapshotError`) — see issue #307. Filter cookbook:
1239
+ - All denials: `event.kind === 'request' && event.result === 'deny'`
1240
+ - Stream errors: `event.kind === 'listener_errored'`
1241
+ - Per-op traffic: `event.kind === 'request'`
1242
+
1243
+ Survives `sandbox.reset()` — the subscription is held on the
1244
+ sandbox, not on the underlying environment. A `session_boundary`
1245
+ event with `phase: 'reset'` fires before the env swap so consumers
1246
+ can segment their stream.
1247
+
1248
+ Returns an unsubscribe function. Listener errors are swallowed so a
1249
+ faulty subscriber can't change rule semantics or hide other events.
1250
+ Both synchronous throws and rejected Promises from async callbacks
1251
+ are silently discarded — subscribers are **observational**, the
1252
+ sandbox doesn't await them and doesn't propagate their errors.
233
1253
 
234
1254
  ###### Parameters
235
1255
 
236
1256
  | Parameter | Type |
237
1257
  | :------ | :------ |
238
- | `path` | `string` |
239
- | `value?` | `unknown` |
1258
+ | `cb` | (`event`: [`SandboxEvent`](pyric-sandbox-reference-api.md#sandboxevent)) => `void` |
240
1259
 
241
1260
  ###### Returns
242
1261
 
243
- `Promise`\<\{
244
- `key`: `string`;
245
- `path`: `string`;
246
- \}\>
1262
+ ```ts
1263
+ (): void;
1264
+ ```
247
1265
 
248
- <a id="remove"></a>
1266
+ ###### Returns
249
1267
 
250
- ##### remove()
1268
+ `void`
1269
+
1270
+ ###### Inherited from
1271
+
1272
+ [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`onEvent`](pyric-sandbox-reference-api.md#onevent-2)
1273
+
1274
+ <a id="registerpersistableservice-2"></a>
1275
+
1276
+ ##### registerPersistableService()
251
1277
 
252
1278
  ```ts
253
- remove(path: string): Promise<void>;
1279
+ registerPersistableService(name: string, hooks: PersistableService): () => void;
254
1280
  ```
255
1281
 
1282
+ Register a service (auth, storage, …) as a persistence participant.
1283
+ The sandbox calls `hooks.snapshot()` on every flush and
1284
+ `hooks.restore(data)` on restore. If `hooks.subscribe` is provided,
1285
+ the persistence controller subscribes and schedules a debounced
1286
+ flush on each change — so auth-user edits flush promptly, not only
1287
+ on the next Firestore write.
1288
+
1289
+ Returns an unregister function — call it if the service is torn
1290
+ down before the sandbox is disposed (uncommon in practice; the
1291
+ sandbox's `dispose()` clears the registry anyway).
1292
+
1293
+ Throws `failed-precondition` when a service with the same `name` is
1294
+ already registered — the auth package registers `'auth'` once when
1295
+ `getAuth(sandbox)` first creates a backend, so accidental double-
1296
+ registration is a caller bug, not a no-op.
1297
+
1298
+ **Advanced / internal API.** Service packages (auth, storage) call
1299
+ this when they first attach to a sandbox. Consumer app code should
1300
+ not need to call this directly.
1301
+
256
1302
  ###### Parameters
257
1303
 
258
1304
  | Parameter | Type |
259
1305
  | :------ | :------ |
260
- | `path` | `string` |
1306
+ | `name` | `string` |
1307
+ | `hooks` | [`PersistableService`](pyric-sandbox-reference-api.md#persistableservice) |
261
1308
 
262
1309
  ###### Returns
263
1310
 
264
- `Promise`\<`void`\>
1311
+ ```ts
1312
+ (): void;
1313
+ ```
265
1314
 
266
- <a id="set"></a>
1315
+ ###### Returns
267
1316
 
268
- ##### set()
1317
+ `void`
1318
+
1319
+ ###### Inherited from
1320
+
1321
+ [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`registerPersistableService`](pyric-sandbox-reference-api.md#registerpersistableservice-2)
1322
+
1323
+ <a id="reset-2"></a>
1324
+
1325
+ ##### reset()
269
1326
 
270
1327
  ```ts
271
- set(path: string, value: unknown): Promise<void>;
1328
+ reset(): void;
272
1329
  ```
273
1330
 
274
- ###### Parameters
1331
+ Reset the underlying environment to a fresh state — wipes data,
1332
+ rules, and any service-specific configuration.
275
1333
 
276
- | Parameter | Type |
277
- | :------ | :------ |
278
- | `path` | `string` |
279
- | `value` | `unknown` |
1334
+ Snapshot listeners attached to the OLD environment are dropped at
1335
+ the swap they can't survive because their target docs have been
1336
+ wiped. `onEvent` subscribers DO survive — the registry lives on
1337
+ the sandbox, and a `session_boundary` event with `phase: 'reset'`
1338
+ fires before the swap so subscribers know the rollover happened.
1339
+ Existing [SandboxContext](pyric-firestore-reference-api.md#sandboxcontext)s continue to work — their sandbox
1340
+ reference is stable; subsequent operations resolve to the new env.
280
1341
 
281
1342
  ###### Returns
282
1343
 
283
- `Promise`\<`void`\>
1344
+ `void`
284
1345
 
285
- <a id="update"></a>
1346
+ ###### Inherited from
286
1347
 
287
- ##### update()
1348
+ [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`reset`](pyric-sandbox-reference-api.md#reset-4)
1349
+
1350
+ <a id="resetall-2"></a>
1351
+
1352
+ ##### resetAll()
288
1353
 
289
1354
  ```ts
290
- update(path: string, values: Record<string, unknown>): Promise<void>;
1355
+ resetAll(): Promise<{
1356
+ errors: string[];
1357
+ }>;
291
1358
  ```
292
1359
 
293
- ###### Parameters
1360
+ Reset the WHOLE sandbox: [reset](pyric-firestore-reference-api.md#reset) (Firestore env + signed-in
1361
+ session), then clear every registered persistable service that
1362
+ provides a [PersistableService.reset](pyric-sandbox-reference-api.md#reset-2) hook — auth users, the
1363
+ RTDB tree, storage objects. This is the one sandbox-owned "wipe
1364
+ everything" path: because it iterates the service registry, a new
1365
+ service that registers with a `reset` hook is cleared automatically,
1366
+ and a consumer (Pyric Studio's reset) cannot forget one.
294
1367
 
295
- | Parameter | Type |
296
- | :------ | :------ |
297
- | `path` | `string` |
298
- | `values` | `Record`\<`string`, `unknown`\> |
1368
+ Service resets may be async (storage clears IndexedDB stores); the
1369
+ returned promise resolves when every service has finished clearing.
1370
+ A service whose `reset` throws is isolated (others still clear) and
1371
+ REPORTED in the returned `errors` (as `name: message`) — a reset that
1372
+ leaves data behind must never look successful to the caller.
299
1373
 
300
1374
  ###### Returns
301
1375
 
302
- `Promise`\<`void`\>
1376
+ `Promise`\<\{
1377
+ `errors`: `string`[];
1378
+ \}\>
303
1379
 
304
- ***
1380
+ ###### Inherited from
305
1381
 
306
- <a id="remotertdbsnapshot"></a>
1382
+ [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`resetAll`](pyric-sandbox-reference-api.md#resetall-2)
307
1383
 
308
- ### RemoteRtdbSnapshot
1384
+ <a id="runwithprovenance-2"></a>
309
1385
 
310
- Wire shape of an RTDB snapshot as the worker host serializes it.
1386
+ ##### runWithProvenance()?
311
1387
 
312
- #### Properties
1388
+ ```ts
1389
+ optional runWithProvenance<T>(provenance: EventProvenance, fn: () => T): T;
1390
+ ```
313
1391
 
314
- | Property | Type |
1392
+ Run `fn` with ambient [EventProvenance](pyric-sandbox-reference-api.md#eventprovenance) defaults: every event
1393
+ emitted SYNCHRONOUSLY during `fn` that doesn't already carry a
1394
+ provenance field (on the event itself or via an explicit per-emit
1395
+ override) is stamped with these values instead of the global
1396
+ defaults. This is the mechanical "who issued this op" seam the
1397
+ serve worker uses to tag Studio-issued ops (`actor: { kind:
1398
+ 'studio' }`) and to stamp the auth lens an op ran under
1399
+ (`authLens`) — declared by the caller that issues the op, never
1400
+ inferred from the op's shape.
1401
+
1402
+ SYNCHRONOUS WINDOW: the ambient values apply only until `fn`
1403
+ returns (for an async `fn`, its synchronous prefix — which covers
1404
+ the local environment's rules eval + event emission, since those
1405
+ run before the op's promise is handed back). Work an op DEFERS
1406
+ (snapshot-listener deliveries and re-evals drain on a microtask,
1407
+ off-stack) is intentionally OUTSIDE the window: a listener re-eval
1408
+ belongs to the listener's owner, not to whoever's write triggered
1409
+ it. Nested calls stack — the innermost window wins per field, and
1410
+ each window restores the previous one on exit (including on throw).
1411
+
1412
+ OPTIONAL because remote sandbox proxies can't provide an ambient
1413
+ emit window (events are emitted in the worker they front). Callers
1414
+ spell `sandbox.runWithProvenance?.(prov, fn) ?? fn()`.
1415
+
1416
+ ###### Type Parameters
1417
+
1418
+ | Type Parameter |
1419
+ | :------ |
1420
+ | `T` |
1421
+
1422
+ ###### Parameters
1423
+
1424
+ | Parameter | Type |
315
1425
  | :------ | :------ |
316
- | <a id="exists"></a> `exists` | `boolean` |
317
- | <a id="key"></a> `key` | `string` |
318
- | <a id="size"></a> `size` | `number` |
319
- | <a id="value"></a> `value` | `unknown` |
1426
+ | `provenance` | [`EventProvenance`](pyric-sandbox-reference-api.md#eventprovenance) |
1427
+ | `fn` | () => `T` |
320
1428
 
321
- ***
1429
+ ###### Returns
322
1430
 
323
- <a id="remotesandbox"></a>
1431
+ `T`
324
1432
 
325
- ### RemoteSandbox
1433
+ ###### Inherited from
326
1434
 
327
- The Node-side remote sandbox handle. Extends `pyric/sandbox`'s branded
328
- RemoteSandboxBase — structurally a full `Sandbox`, so it can be
329
- passed to `pyric-admin/app`'s `initializeApp({ sandbox })`, whose RTDB and
330
- Auth backends dispatch on the brand and route through [channel](#channel-1).
1435
+ [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`runWithProvenance`](pyric-sandbox-reference-api.md#runwithprovenance-2)
331
1436
 
332
- Sandbox members that are genuinely sync-only (`admin`, `snapshot()`,
333
- `history()`, `onEvent`, `currentUser`, …) cannot be mirrored over the
334
- wire in slice 1 and throw a remediating `unimplemented` error naming
335
- what to do instead. Implemented members: `withAuth` (pure local pair
336
- construction) and `dispose` (aliases [close](#close-2)).
1437
+ <a id="snapshot-2"></a>
337
1438
 
338
- #### Extends
1439
+ ##### snapshot()
339
1440
 
340
- - `unknown`
1441
+ ```ts
1442
+ snapshot(): SandboxSnapshot;
1443
+ ```
341
1444
 
342
- #### Extended by
1445
+ Capture a snapshot of every service's state. For v1 with only
1446
+ Firestore, the return value carries a `firestore` key mapping doc
1447
+ paths to data. Future services will add their own keys.
343
1448
 
344
- - [`LazyRemoteSandbox`](#lazyremotesandbox)
1449
+ ###### Returns
345
1450
 
346
- #### Properties
1451
+ [`SandboxSnapshot`](pyric-sandbox-reference-api.md#sandboxsnapshot)
347
1452
 
348
- | Property | Modifier | Type | Description |
349
- | :------ | :------ | :------ | :------ |
350
- | <a id="auth-1"></a> `auth` | `readonly` | [`RemoteAuthAdmin`](#remoteauthadmin) | Admin auth user CRUD. |
351
- | <a id="channel-1"></a> `channel` | `readonly` | [`RemoteSandboxChannel`](#remotesandboxchannel-1) | The raw worker op/sub relay channel (narrowed to the wire payload types). |
352
- | <a id="rtdb-1"></a> `rtdb` | `readonly` | [`RemoteRtdb`](#remotertdb) | RTDB conveniences (admin lens pinned). |
353
- | <a id="storage-1"></a> `storage` | `readonly` | [`RemoteStorage`](#remotestorage) | Storage conveniences (admin lens pinned; 8 MiB per-op byte cap). |
1453
+ ###### Inherited from
354
1454
 
355
- #### Methods
1455
+ [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`snapshot`](pyric-sandbox-reference-api.md#snapshot-4)
356
1456
 
357
- <a id="close-2"></a>
1457
+ <a id="withauth-2"></a>
358
1458
 
359
- ##### close()
1459
+ ##### withAuth()
360
1460
 
361
1461
  ```ts
362
- close(): void;
1462
+ withAuth(auth: {
1463
+ token?: Record<string, unknown>;
1464
+ uid: string;
1465
+ }): SandboxContext;
363
1466
  ```
364
1467
 
365
- Close the connection. In-flight ops reject; subscriptions stop.
1468
+ Derive a context bound to this sandbox under the given auth
1469
+ identity. Operations through services attached to the returned
1470
+ context evaluate rules under that identity. Many contexts can
1471
+ coexist for one sandbox; data is shared.
1472
+
1473
+ `null` is anonymous; an `AuthState` object names the user (and
1474
+ optional custom claims). Passing `undefined` is a deliberate
1475
+ error — say `withAuth(null)` for anonymous so the call site is
1476
+ unambiguous.
1477
+
1478
+ ###### Parameters
1479
+
1480
+ | Parameter | Type |
1481
+ | :------ | :------ |
1482
+ | `auth` | \{ `token?`: `Record`\<`string`, `unknown`\>; `uid`: `string`; \} |
1483
+ | `auth.token?` | `Record`\<`string`, `unknown`\> |
1484
+ | `auth.uid` | `string` |
366
1485
 
367
1486
  ###### Returns
368
1487
 
369
- `void`
1488
+ [`SandboxContext`](pyric-firestore-reference-api.md#sandboxcontext)
1489
+
1490
+ ###### Example
1491
+
1492
+ ```ts
1493
+ const sandbox = initializeSandbox();
1494
+ const dbAlice = getFirestore(sandbox.withAuth({ uid: 'alice' }));
1495
+ const dbAnon = getFirestore(sandbox.withAuth(null));
1496
+ ```
1497
+
1498
+ ###### Inherited from
1499
+
1500
+ [`RemoteSandbox`](pyric-sandbox-reference-api.md#remotesandbox).[`withAuth`](pyric-sandbox-reference-api.md#withauth-4)
370
1501
 
371
1502
  ***
372
1503
 
@@ -452,7 +1583,7 @@ to `onError` instead. Returns the unsubscribe function.
452
1583
 
453
1584
  #### Methods
454
1585
 
455
- <a id="dispose"></a>
1586
+ <a id="dispose-4"></a>
456
1587
 
457
1588
  ##### dispose()
458
1589
 
@@ -486,7 +1617,7 @@ Feed one parsed message from the transport into the core.
486
1617
 
487
1618
  | Parameter | Type |
488
1619
  | :------ | :------ |
489
- | `msg` | `BridgeMessage` |
1620
+ | `msg` | [`BridgeMessage`](pyric-cli-bridge-client-reference-api.md#bridgemessage) |
490
1621
 
491
1622
  ###### Returns
492
1623
 
@@ -600,7 +1731,7 @@ Read the object's `FullMetadata`.
600
1731
 
601
1732
  ###### Returns
602
1733
 
603
- `Promise`\<`FullMetadata`\>
1734
+ `Promise`\<[`FullMetadata`](pyric-storage-reference-api.md#fullmetadata)\>
604
1735
 
605
1736
  <a id="listall"></a>
606
1737
 
@@ -669,7 +1800,7 @@ Upload `data` at `path` (replaces any existing object). Resolves with
669
1800
 
670
1801
  ###### Returns
671
1802
 
672
- `Promise`\<`FullMetadata`\>
1803
+ `Promise`\<[`FullMetadata`](pyric-storage-reference-api.md#fullmetadata)\>
673
1804
 
674
1805
  ***
675
1806
 
@@ -713,7 +1844,7 @@ send(msg: BridgeMessage): void;
713
1844
 
714
1845
  | Parameter | Type |
715
1846
  | :------ | :------ |
716
- | `msg` | `BridgeMessage` |
1847
+ | `msg` | [`BridgeMessage`](pyric-cli-bridge-client-reference-api.md#bridgemessage) |
717
1848
 
718
1849
  ###### Returns
719
1850