@pyric/cli 0.1.0-alpha.20 → 0.1.0-alpha.22

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 (502) hide show
  1. package/README.md +64 -89
  2. package/dist/assurance/.generated/conformance-verdicts.d.ts +238 -1
  3. package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
  4. package/dist/assurance/.generated/conformance-verdicts.js +238 -1
  5. package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
  6. package/dist/bridge/client/dispatch.d.ts +25 -19
  7. package/dist/bridge/client/dispatch.d.ts.map +1 -1
  8. package/dist/bridge/client/dispatch.js +41 -48
  9. package/dist/bridge/client/dispatch.js.map +1 -1
  10. package/dist/bridge/client/tool-family-factories.d.ts +26 -0
  11. package/dist/bridge/client/tool-family-factories.d.ts.map +1 -0
  12. package/dist/bridge/client/tool-family-factories.js +10 -0
  13. package/dist/bridge/client/tool-family-factories.js.map +1 -0
  14. package/dist/bridge/server/mcp-contract.d.ts +7 -6
  15. package/dist/bridge/server/mcp-contract.d.ts.map +1 -1
  16. package/dist/bridge/server/mcp-contract.js +9 -48
  17. package/dist/bridge/server/mcp-contract.js.map +1 -1
  18. package/dist/bridge/server/peer.d.ts +11 -1
  19. package/dist/bridge/server/peer.d.ts.map +1 -1
  20. package/dist/bridge/server/peer.js +22 -1
  21. package/dist/bridge/server/peer.js.map +1 -1
  22. package/dist/bridge/server/tool-family-factories.d.ts +30 -0
  23. package/dist/bridge/server/tool-family-factories.d.ts.map +1 -0
  24. package/dist/bridge/server/tool-family-factories.js +22 -0
  25. package/dist/bridge/server/tool-family-factories.js.map +1 -0
  26. package/dist/bridge/server/tool-metadata.d.ts +17 -18
  27. package/dist/bridge/server/tool-metadata.d.ts.map +1 -1
  28. package/dist/bridge/server/tool-metadata.js +24 -59
  29. package/dist/bridge/server/tool-metadata.js.map +1 -1
  30. package/dist/bridge/tool-families.d.ts +48 -0
  31. package/dist/bridge/tool-families.d.ts.map +1 -0
  32. package/dist/bridge/tool-families.generated.d.ts +32 -0
  33. package/dist/bridge/tool-families.generated.d.ts.map +1 -0
  34. package/dist/bridge/tool-families.generated.js +15 -0
  35. package/dist/bridge/tool-families.generated.js.map +1 -0
  36. package/dist/bridge/tool-families.js +51 -0
  37. package/dist/bridge/tool-families.js.map +1 -0
  38. package/dist/bridge/tool-family-records/conformance.d.ts +7 -0
  39. package/dist/bridge/tool-family-records/conformance.d.ts.map +1 -0
  40. package/dist/bridge/tool-family-records/conformance.js +6 -0
  41. package/dist/bridge/tool-family-records/conformance.js.map +1 -0
  42. package/dist/bridge/tool-family-records/firestore-data.d.ts +7 -0
  43. package/dist/bridge/tool-family-records/firestore-data.d.ts.map +1 -0
  44. package/dist/bridge/tool-family-records/firestore-data.js +15 -0
  45. package/dist/bridge/tool-family-records/firestore-data.js.map +1 -0
  46. package/dist/bridge/tool-family-records/firestore-inspect.d.ts +7 -0
  47. package/dist/bridge/tool-family-records/firestore-inspect.d.ts.map +1 -0
  48. package/dist/bridge/tool-family-records/firestore-inspect.js +6 -0
  49. package/dist/bridge/tool-family-records/firestore-inspect.js.map +1 -0
  50. package/dist/bridge/tool-family-records/firestore-rules.d.ts +7 -0
  51. package/dist/bridge/tool-family-records/firestore-rules.d.ts.map +1 -0
  52. package/dist/bridge/tool-family-records/firestore-rules.js +15 -0
  53. package/dist/bridge/tool-family-records/firestore-rules.js.map +1 -0
  54. package/dist/bridge/tool-family-records/firestore-simulator.d.ts +7 -0
  55. package/dist/bridge/tool-family-records/firestore-simulator.d.ts.map +1 -0
  56. package/dist/bridge/tool-family-records/firestore-simulator.js +16 -0
  57. package/dist/bridge/tool-family-records/firestore-simulator.js.map +1 -0
  58. package/dist/bridge/tool-family-records/rtdb-inspection.d.ts +7 -0
  59. package/dist/bridge/tool-family-records/rtdb-inspection.d.ts.map +1 -0
  60. package/dist/bridge/tool-family-records/rtdb-inspection.js +6 -0
  61. package/dist/bridge/tool-family-records/rtdb-inspection.js.map +1 -0
  62. package/dist/bundler/externals.d.ts +37 -0
  63. package/dist/bundler/externals.d.ts.map +1 -0
  64. package/dist/bundler/externals.js +52 -0
  65. package/dist/bundler/externals.js.map +1 -0
  66. package/dist/bundler/index.d.ts +17 -0
  67. package/dist/bundler/index.d.ts.map +1 -0
  68. package/dist/bundler/index.js +17 -0
  69. package/dist/bundler/index.js.map +1 -0
  70. package/dist/cli/inlined-sdk-scanner.d.ts +6 -0
  71. package/dist/cli/inlined-sdk-scanner.d.ts.map +1 -0
  72. package/dist/cli/inlined-sdk-scanner.js +82 -0
  73. package/dist/cli/inlined-sdk-scanner.js.map +1 -0
  74. package/dist/cli/sandbox-interlock.d.ts +97 -0
  75. package/dist/cli/sandbox-interlock.d.ts.map +1 -0
  76. package/dist/cli/sandbox-interlock.js +112 -0
  77. package/dist/cli/sandbox-interlock.js.map +1 -0
  78. package/dist/cli/sandbox-runner.d.ts +20 -12
  79. package/dist/cli/sandbox-runner.d.ts.map +1 -1
  80. package/dist/cli/sandbox-runner.js +24 -21
  81. package/dist/cli/sandbox-runner.js.map +1 -1
  82. package/dist/cli/serve.d.ts +6 -10
  83. package/dist/cli/serve.d.ts.map +1 -1
  84. package/dist/cli/serve.js +57 -77
  85. package/dist/cli/serve.js.map +1 -1
  86. package/dist/cli/unsupported-runtime.d.ts +27 -0
  87. package/dist/cli/unsupported-runtime.d.ts.map +1 -0
  88. package/dist/cli/unsupported-runtime.js +63 -0
  89. package/dist/cli/unsupported-runtime.js.map +1 -0
  90. package/dist/conformance/.generated/can-i-use-browser.d.ts +1 -1
  91. package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
  92. package/dist/conformance/.generated/can-i-use-browser.js +1 -1
  93. package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
  94. package/dist/conformance/.generated/can-i-use.d.ts +1 -1
  95. package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
  96. package/dist/conformance/.generated/can-i-use.js +1 -1
  97. package/dist/conformance/.generated/can-i-use.js.map +1 -1
  98. package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
  99. package/dist/conformance/.generated/conformance-docs.js +1 -1
  100. package/dist/conformance/.generated/conformance-docs.js.map +1 -1
  101. package/dist/functions-rtdb/child.d.ts +37 -0
  102. package/dist/functions-rtdb/child.d.ts.map +1 -1
  103. package/dist/functions-rtdb/child.js +90 -21
  104. package/dist/functions-rtdb/child.js.map +1 -1
  105. package/dist/functions-rtdb/development-runtime.d.ts +3 -0
  106. package/dist/functions-rtdb/development-runtime.d.ts.map +1 -1
  107. package/dist/functions-rtdb/development-runtime.js +1 -0
  108. package/dist/functions-rtdb/development-runtime.js.map +1 -1
  109. package/dist/google-endpoints.d.ts +67 -0
  110. package/dist/google-endpoints.d.ts.map +1 -0
  111. package/dist/google-endpoints.js +119 -0
  112. package/dist/google-endpoints.js.map +1 -0
  113. package/dist/next/runtime-env.d.ts.map +1 -1
  114. package/dist/next/runtime-env.js +5 -0
  115. package/dist/next/runtime-env.js.map +1 -1
  116. package/dist/next/with-pyric.d.ts +1 -1
  117. package/dist/next/with-pyric.js +1 -1
  118. package/dist/register/beacon.d.ts +69 -0
  119. package/dist/register/beacon.d.ts.map +1 -0
  120. package/dist/register/beacon.js +199 -0
  121. package/dist/register/beacon.js.map +1 -0
  122. package/dist/register/index.d.ts.map +1 -1
  123. package/dist/register/index.js +65 -6
  124. package/dist/register/index.js.map +1 -1
  125. package/dist/register/net-guard.d.ts +110 -0
  126. package/dist/register/net-guard.d.ts.map +1 -0
  127. package/dist/register/net-guard.js +462 -0
  128. package/dist/register/net-guard.js.map +1 -0
  129. package/dist/serve/ai-diagnostics-relay.d.ts +63 -0
  130. package/dist/serve/ai-diagnostics-relay.d.ts.map +1 -0
  131. package/dist/serve/ai-diagnostics-relay.js +125 -0
  132. package/dist/serve/ai-diagnostics-relay.js.map +1 -0
  133. package/dist/serve/ai-proxy.d.ts +92 -0
  134. package/dist/serve/ai-proxy.d.ts.map +1 -0
  135. package/dist/serve/ai-proxy.js +269 -0
  136. package/dist/serve/ai-proxy.js.map +1 -0
  137. package/dist/serve/ai-status.d.ts +44 -0
  138. package/dist/serve/ai-status.d.ts.map +1 -0
  139. package/dist/serve/ai-status.js +77 -0
  140. package/dist/serve/ai-status.js.map +1 -0
  141. package/dist/serve/ai-terminal-blocks.d.ts +97 -0
  142. package/dist/serve/ai-terminal-blocks.d.ts.map +1 -0
  143. package/dist/serve/ai-terminal-blocks.js +128 -0
  144. package/dist/serve/ai-terminal-blocks.js.map +1 -0
  145. package/dist/serve/ai-terminal-text.d.ts +36 -0
  146. package/dist/serve/ai-terminal-text.d.ts.map +1 -0
  147. package/dist/serve/ai-terminal-text.js +48 -0
  148. package/dist/serve/ai-terminal-text.js.map +1 -0
  149. package/dist/serve/beacon-route.d.ts +53 -0
  150. package/dist/serve/beacon-route.d.ts.map +1 -0
  151. package/dist/serve/beacon-route.js +101 -0
  152. package/dist/serve/beacon-route.js.map +1 -0
  153. package/dist/serve/entries/active-auth-registry.d.ts +16 -0
  154. package/dist/serve/entries/active-auth-registry.d.ts.map +1 -0
  155. package/dist/serve/entries/active-auth-registry.js +48 -0
  156. package/dist/serve/entries/active-auth-registry.js.map +1 -0
  157. package/dist/serve/entries/active-auth.d.ts +18 -0
  158. package/dist/serve/entries/active-auth.d.ts.map +1 -0
  159. package/dist/serve/entries/active-auth.js +84 -0
  160. package/dist/serve/entries/active-auth.js.map +1 -0
  161. package/dist/serve/entries/auth-helper-core.d.ts +1 -0
  162. package/dist/serve/entries/auth-helper-core.d.ts.map +1 -1
  163. package/dist/serve/entries/auth-helper-core.js +4 -0
  164. package/dist/serve/entries/auth-helper-core.js.map +1 -1
  165. package/dist/serve/entries/auth-helper-dom.d.ts.map +1 -1
  166. package/dist/serve/entries/auth-helper-dom.js +28 -2
  167. package/dist/serve/entries/auth-helper-dom.js.map +1 -1
  168. package/dist/serve/entries/auth.d.ts.map +1 -1
  169. package/dist/serve/entries/auth.js +8 -0
  170. package/dist/serve/entries/auth.js.map +1 -1
  171. package/dist/serve/entries/bridge-url.d.ts +1 -1
  172. package/dist/serve/entries/bridge-url.js +1 -1
  173. package/dist/serve/entries/init.d.ts.map +1 -1
  174. package/dist/serve/entries/init.js +70 -4
  175. package/dist/serve/entries/init.js.map +1 -1
  176. package/dist/serve/entries/runtime.d.ts.map +1 -1
  177. package/dist/serve/entries/runtime.js +9 -0
  178. package/dist/serve/entries/runtime.js.map +1 -1
  179. package/dist/serve/namespace.d.ts +14 -5
  180. package/dist/serve/namespace.d.ts.map +1 -1
  181. package/dist/serve/namespace.js +57 -124
  182. package/dist/serve/namespace.js.map +1 -1
  183. package/dist/serve/runtime/chip-config.d.ts.map +1 -1
  184. package/dist/serve/runtime/chip-config.js +16 -2
  185. package/dist/serve/runtime/chip-config.js.map +1 -1
  186. package/dist/serve/runtime/chip-dialog.d.ts +18 -0
  187. package/dist/serve/runtime/chip-dialog.d.ts.map +1 -0
  188. package/dist/serve/runtime/chip-dialog.js +315 -0
  189. package/dist/serve/runtime/chip-dialog.js.map +1 -0
  190. package/dist/serve/runtime/chip-install.d.ts +2 -0
  191. package/dist/serve/runtime/chip-install.d.ts.map +1 -1
  192. package/dist/serve/runtime/chip-install.js +9 -4
  193. package/dist/serve/runtime/chip-install.js.map +1 -1
  194. package/dist/serve/runtime/chip-user-search.d.ts +16 -0
  195. package/dist/serve/runtime/chip-user-search.d.ts.map +1 -0
  196. package/dist/serve/runtime/chip-user-search.js +354 -0
  197. package/dist/serve/runtime/chip-user-search.js.map +1 -0
  198. package/dist/serve/runtime/chip.d.ts +10 -0
  199. package/dist/serve/runtime/chip.d.ts.map +1 -1
  200. package/dist/serve/runtime/chip.js +118 -15
  201. package/dist/serve/runtime/chip.js.map +1 -1
  202. package/dist/serve/runtime/identity.d.ts +17 -0
  203. package/dist/serve/runtime/identity.d.ts.map +1 -0
  204. package/dist/serve/runtime/identity.js +10 -0
  205. package/dist/serve/runtime/identity.js.map +1 -0
  206. package/dist/serve/sandbox-session.d.ts +7 -0
  207. package/dist/serve/sandbox-session.d.ts.map +1 -1
  208. package/dist/serve/sandbox-session.js +2 -0
  209. package/dist/serve/sandbox-session.js.map +1 -1
  210. package/dist/serve/site-ui/_astro/{RulesCodeEditor.XtDmHOlN.js → RulesCodeEditor.DsTAsKIa.js} +1 -1
  211. package/dist/serve/site-ui/_astro/app.CMmTxyhL.js +1 -0
  212. package/dist/serve/site-ui/_astro/app.DhALsVii.js +115 -0
  213. package/dist/serve/site-ui/_astro/{chess-showcase.B72XYeoh.js → chess-showcase.Bn_pP6UJ.js} +2 -2
  214. package/dist/serve/site-ui/_astro/{example-runtime.C25_lx6Z.js → example-runtime.CXopTGv7.js} +1 -1
  215. package/dist/serve/site-ui/_astro/sandbox-controls.rOuZTOUG.js +510 -0
  216. package/dist/serve/site-ui/_astro/{seed.Co0yUJY5.js → seed.lywYbXZ0.js} +2 -2
  217. package/dist/serve/site-ui/_astro/writes.BsPBG3dp.js +653 -0
  218. package/dist/serve/site-ui/auth/index.html +1 -1
  219. package/dist/serve/site-ui/docs/_rhythm/index.html +1 -1
  220. package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +1 -1
  221. package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +1 -1
  222. package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +1 -1
  223. package/dist/serve/site-ui/docs/ai-compat/index.html +1 -1
  224. package/dist/serve/site-ui/docs/api-reference/index.html +8 -1
  225. package/dist/serve/site-ui/docs/api-reference.md +7 -0
  226. package/dist/serve/site-ui/docs/app-compat/index.html +1 -1
  227. package/dist/serve/site-ui/docs/auth-compat/index.html +3 -3
  228. package/dist/serve/site-ui/docs/auth-compat.md +2 -2
  229. package/dist/serve/site-ui/docs/build/ai-logic/index.html +6 -1
  230. package/dist/serve/site-ui/docs/build/ai-logic.md +6 -0
  231. package/dist/serve/site-ui/docs/build/authentication/index.html +2 -2
  232. package/dist/serve/site-ui/docs/build/authentication.md +1 -1
  233. package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +4 -2
  234. package/dist/serve/site-ui/docs/build/cloud-firestore.md +4 -0
  235. package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +1 -1
  236. package/dist/serve/site-ui/docs/build/cloud-storage/index.html +1 -1
  237. package/dist/serve/site-ui/docs/build/realtime-database/index.html +1 -1
  238. package/dist/serve/site-ui/docs/conformance-scores/index.html +14 -2
  239. package/dist/serve/site-ui/docs/conformance-scores.md +13 -1
  240. package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +1 -1
  241. package/dist/serve/site-ui/docs/database-compat/index.html +44 -44
  242. package/dist/serve/site-ui/docs/database-compat.md +43 -43
  243. package/dist/serve/site-ui/docs/examples/chess/index.html +1 -1
  244. package/dist/serve/site-ui/docs/examples/index.html +1 -1
  245. package/dist/serve/site-ui/docs/firestore-compat/index.html +4 -4
  246. package/dist/serve/site-ui/docs/firestore-compat.md +3 -3
  247. package/dist/serve/site-ui/docs/firestore-flutter-compat/index.html +319 -0
  248. package/dist/serve/site-ui/docs/firestore-flutter-compat.md +344 -0
  249. package/dist/serve/site-ui/docs/firestore-kotlin-compat/index.html +319 -0
  250. package/dist/serve/site-ui/docs/firestore-kotlin-compat.md +344 -0
  251. package/dist/serve/site-ui/docs/firestore-swift-compat/index.html +490 -0
  252. package/dist/serve/site-ui/docs/firestore-swift-compat.md +517 -0
  253. package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +1 -1
  254. package/dist/serve/site-ui/docs/get-started/backend-bundlers/index.html +105 -0
  255. package/dist/serve/site-ui/docs/get-started/backend-bundlers.md +165 -0
  256. package/dist/serve/site-ui/docs/get-started/flutter/index.html +98 -0
  257. package/dist/serve/site-ui/docs/get-started/flutter.md +105 -0
  258. package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +1 -1
  259. package/dist/serve/site-ui/docs/get-started/nextjs/index.html +1 -1
  260. package/dist/serve/site-ui/docs/get-started/start-building/index.html +1 -1
  261. package/dist/serve/site-ui/docs/get-started/vite/index.html +1 -1
  262. package/dist/serve/site-ui/docs/index.json +3211 -1471
  263. package/dist/serve/site-ui/docs/messaging-compat/index.html +1 -1
  264. package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +4 -3
  265. package/dist/serve/site-ui/docs/observe/resolve-runtime-status.md +3 -1
  266. package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +1 -1
  267. package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +1 -1
  268. package/dist/serve/site-ui/docs/observe/switch-and-impersonate-identities/index.html +110 -0
  269. package/dist/serve/site-ui/docs/observe/switch-and-impersonate-identities.md +134 -0
  270. package/dist/serve/site-ui/docs/overview/index.html +1 -1
  271. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +1 -1
  272. package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +1 -1
  273. package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +1 -1
  274. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +1 -1
  275. package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +1 -1
  276. package/dist/serve/site-ui/docs/pyric-admin-reference-api/index.html +1 -1
  277. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +1 -1
  278. package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +1 -1
  279. package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +1 -1
  280. package/dist/serve/site-ui/docs/pyric-analytics-reference-api/index.html +124 -0
  281. package/dist/serve/site-ui/docs/pyric-analytics-reference-api.md +287 -0
  282. package/dist/serve/site-ui/docs/pyric-app-check-reference-api/index.html +87 -0
  283. package/dist/serve/site-ui/docs/pyric-app-check-reference-api.md +199 -0
  284. package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +1 -1
  285. package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +6 -2
  286. package/dist/serve/site-ui/docs/pyric-auth-reference-api.md +2 -1
  287. package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +1 -1
  288. package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +1 -1
  289. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +2 -2
  290. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api.md +1 -1
  291. package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +1 -1
  292. package/dist/serve/site-ui/docs/pyric-cli-bundler-reference-api/index.html +56 -0
  293. package/dist/serve/site-ui/docs/pyric-cli-bundler-reference-api.md +72 -0
  294. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +4 -1
  295. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api.md +3 -0
  296. package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +1 -1
  297. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +4 -1
  298. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api.md +3 -0
  299. package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +1 -1
  300. package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +1 -1
  301. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +2 -2
  302. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api.md +1 -1
  303. package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +1 -1
  304. package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +1 -1
  305. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +34 -9
  306. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api.md +16 -8
  307. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +133 -93
  308. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api.md +61 -1
  309. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +2 -2
  310. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api.md +1 -1
  311. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +2 -2
  312. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api.md +2 -2
  313. package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +2 -2
  314. package/dist/serve/site-ui/docs/pyric-database-reference-api.md +1 -1
  315. package/dist/serve/site-ui/docs/pyric-firestore-lite-reference-api/index.html +559 -0
  316. package/dist/serve/site-ui/docs/pyric-firestore-lite-reference-api.md +1240 -0
  317. package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +40 -11
  318. package/dist/serve/site-ui/docs/pyric-firestore-reference-api.md +18 -8
  319. package/dist/serve/site-ui/docs/pyric-functions-reference-api/index.html +67 -0
  320. package/dist/serve/site-ui/docs/pyric-functions-reference-api.md +149 -0
  321. package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +1 -1
  322. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +1 -1
  323. package/dist/serve/site-ui/docs/pyric-performance-reference-api/index.html +35 -0
  324. package/dist/serve/site-ui/docs/pyric-performance-reference-api.md +69 -0
  325. package/dist/serve/site-ui/docs/pyric-remote-config-reference-api/index.html +132 -0
  326. package/dist/serve/site-ui/docs/pyric-remote-config-reference-api.md +307 -0
  327. package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +1 -1
  328. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +52 -17
  329. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api.md +48 -9
  330. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +1 -1
  331. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +239 -49
  332. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api.md +148 -31
  333. package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +22 -4
  334. package/dist/serve/site-ui/docs/pyric-storage-reference-api.md +25 -3
  335. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +26 -96
  336. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api.md +20 -51
  337. package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +1 -1
  338. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +2 -2
  339. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api.md +1 -1
  340. package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +1 -1
  341. package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +1 -1
  342. package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +1 -1
  343. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +2 -2
  344. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api.md +1 -1
  345. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +124 -26
  346. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api.md +58 -5
  347. package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +1 -1
  348. package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +1 -1
  349. package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +1 -1
  350. package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +1 -1
  351. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +4 -5
  352. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api.md +3 -4
  353. package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +1 -1
  354. package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +1 -1
  355. package/dist/serve/site-ui/docs/reference/cli/index.html +6 -3
  356. package/dist/serve/site-ui/docs/reference/cli.md +8 -2
  357. package/dist/serve/site-ui/docs/rules-compat/index.html +10 -2
  358. package/dist/serve/site-ui/docs/rules-compat.md +9 -1
  359. package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +1 -1
  360. package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +1 -1
  361. package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +1 -1
  362. package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +1 -1
  363. package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +1 -1
  364. package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +1 -1
  365. package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +1 -1
  366. package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +1 -1
  367. package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +1 -1
  368. package/dist/serve/site-ui/docs/ship/test-in-node/index.html +1 -1
  369. package/dist/serve/site-ui/docs/storage-compat/index.html +13 -13
  370. package/dist/serve/site-ui/docs/storage-compat.md +12 -12
  371. package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +1 -1
  372. package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +1 -1
  373. package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +1 -1
  374. package/dist/serve/site-ui/docs/tutorial/index.html +1 -1
  375. package/dist/serve/site-ui/examples/chess/index.html +1 -1
  376. package/dist/serve/site-ui/firestore/index.html +1 -1
  377. package/dist/serve/site-ui/llms.txt +13 -0
  378. package/dist/serve/site-ui/rtdb/index.html +1 -1
  379. package/dist/serve/site-ui/settings/index.html +1 -1
  380. package/dist/serve/site-ui/storage/index.html +1 -1
  381. package/dist/serve/site-ui/studio/index.html +1 -1
  382. package/dist/serve/site-ui/traffic/index.html +1 -1
  383. package/dist/serve/studio/disk-workspace.d.ts.map +1 -1
  384. package/dist/serve/studio/disk-workspace.js +64 -2
  385. package/dist/serve/studio/disk-workspace.js.map +1 -1
  386. package/dist/serve/vite-plugin.d.ts +7 -7
  387. package/dist/serve/vite-plugin.js +1 -1
  388. package/dist/serve/vite-plugin.js.map +1 -1
  389. package/dist/serve/vite-sandbox-generation.d.ts.map +1 -1
  390. package/dist/serve/vite-sandbox-generation.js +12 -0
  391. package/dist/serve/vite-sandbox-generation.js.map +1 -1
  392. package/dist/serve/worker/client/auth.js +1 -2
  393. package/dist/serve/worker/client/auth.js.map +1 -1
  394. package/dist/serve/worker/client/core.d.ts +21 -1
  395. package/dist/serve/worker/client/core.d.ts.map +1 -1
  396. package/dist/serve/worker/client/core.js +79 -3
  397. package/dist/serve/worker/client/core.js.map +1 -1
  398. package/dist/serve/worker/client.d.ts +1 -1
  399. package/dist/serve/worker/client.d.ts.map +1 -1
  400. package/dist/serve/worker/client.js +1 -1
  401. package/dist/serve/worker/client.js.map +1 -1
  402. package/dist/serve/worker/context-resolver.d.ts +30 -0
  403. package/dist/serve/worker/context-resolver.d.ts.map +1 -0
  404. package/dist/serve/worker/context-resolver.js +44 -0
  405. package/dist/serve/worker/context-resolver.js.map +1 -0
  406. package/dist/serve/worker/entry.js +23 -19
  407. package/dist/serve/worker/entry.js.map +1 -1
  408. package/dist/serve/worker/host/core.d.ts +1 -0
  409. package/dist/serve/worker/host/core.d.ts.map +1 -1
  410. package/dist/serve/worker/host/core.js +12 -6
  411. package/dist/serve/worker/host/core.js.map +1 -1
  412. package/dist/serve/worker/host/storage.js +2 -2
  413. package/dist/serve/worker/host-auth.js +1 -2
  414. package/dist/serve/worker/host-auth.js.map +1 -1
  415. package/dist/serve/worker/index.d.ts +1 -1
  416. package/dist/serve/worker/index.d.ts.map +1 -1
  417. package/dist/serve/worker/index.js +2 -2
  418. package/dist/serve/worker/index.js.map +1 -1
  419. package/dist/serve/worker/port-lifecycle.d.ts +18 -0
  420. package/dist/serve/worker/port-lifecycle.d.ts.map +1 -0
  421. package/dist/serve/worker/port-lifecycle.js +28 -0
  422. package/dist/serve/worker/port-lifecycle.js.map +1 -0
  423. package/dist/serve/worker/serve-init.d.ts.map +1 -1
  424. package/dist/serve/worker/serve-init.js +8 -2
  425. package/dist/serve/worker/serve-init.js.map +1 -1
  426. package/dist/verify/fixture.d.ts +1 -1
  427. package/package.json +16 -5
  428. package/src/assurance/.generated/conformance-verdicts.ts +238 -1
  429. package/src/bridge/client/dispatch.ts +52 -56
  430. package/src/bridge/client/tool-family-factories.ts +34 -0
  431. package/src/bridge/server/mcp-contract.ts +15 -59
  432. package/src/bridge/server/peer.ts +24 -1
  433. package/src/bridge/server/tool-family-factories.ts +40 -0
  434. package/src/bridge/server/tool-metadata.ts +29 -61
  435. package/src/bridge/tool-families.generated.ts +17 -0
  436. package/src/bridge/tool-families.ts +87 -0
  437. package/src/bridge/tool-family-records/conformance.ts +6 -0
  438. package/src/bridge/tool-family-records/firestore-data.ts +15 -0
  439. package/src/bridge/tool-family-records/firestore-inspect.ts +6 -0
  440. package/src/bridge/tool-family-records/firestore-rules.ts +15 -0
  441. package/src/bridge/tool-family-records/firestore-simulator.ts +16 -0
  442. package/src/bridge/tool-family-records/rtdb-inspection.ts +6 -0
  443. package/src/bundler/externals.ts +55 -0
  444. package/src/bundler/index.ts +21 -0
  445. package/src/cli/cli.test.ts +0 -44
  446. package/src/cli/inlined-sdk-scanner.ts +77 -0
  447. package/src/cli/sandbox-interlock.ts +167 -0
  448. package/src/cli/sandbox-runner.ts +37 -26
  449. package/src/cli/serve.ts +68 -69
  450. package/src/cli/unsupported-runtime.ts +68 -0
  451. package/src/conformance/.generated/can-i-use-browser.ts +2 -2
  452. package/src/conformance/.generated/can-i-use.ts +2 -2
  453. package/src/conformance/.generated/conformance-docs.ts +1 -1
  454. package/src/functions-rtdb/child.ts +115 -21
  455. package/src/functions-rtdb/development-runtime.ts +4 -0
  456. package/src/google-endpoints.ts +155 -0
  457. package/src/next/runtime-env.ts +5 -0
  458. package/src/next/with-pyric.ts +1 -1
  459. package/src/register/beacon.ts +232 -0
  460. package/src/register/index.ts +68 -6
  461. package/src/register/net-guard.ts +567 -0
  462. package/src/serve/ai-diagnostics-relay.ts +243 -0
  463. package/src/serve/ai-proxy.ts +327 -0
  464. package/src/serve/ai-status.ts +109 -0
  465. package/src/serve/ai-terminal-blocks.ts +210 -0
  466. package/src/serve/ai-terminal-text.ts +52 -0
  467. package/src/serve/beacon-route.ts +141 -0
  468. package/src/serve/entries/active-auth-registry.ts +56 -0
  469. package/src/serve/entries/active-auth.ts +100 -0
  470. package/src/serve/entries/auth-helper-core.ts +5 -0
  471. package/src/serve/entries/auth-helper-dom.ts +26 -2
  472. package/src/serve/entries/auth.ts +8 -0
  473. package/src/serve/entries/bridge-url.ts +1 -1
  474. package/src/serve/entries/init.ts +78 -3
  475. package/src/serve/entries/runtime.ts +10 -0
  476. package/src/serve/namespace.ts +73 -140
  477. package/src/serve/runtime/chip-config.ts +16 -2
  478. package/src/serve/runtime/chip-dialog.ts +366 -0
  479. package/src/serve/runtime/chip-install.ts +10 -4
  480. package/src/serve/runtime/chip-user-search.ts +391 -0
  481. package/src/serve/runtime/chip.ts +140 -15
  482. package/src/serve/runtime/identity.ts +26 -0
  483. package/src/serve/sandbox-session.ts +9 -0
  484. package/src/serve/studio/disk-workspace.ts +76 -2
  485. package/src/serve/vite-plugin.ts +8 -8
  486. package/src/serve/vite-sandbox-generation.ts +15 -0
  487. package/src/serve/worker/client/auth.ts +1 -1
  488. package/src/serve/worker/client/core.ts +80 -3
  489. package/src/serve/worker/client.ts +1 -1
  490. package/src/serve/worker/context-resolver.ts +60 -0
  491. package/src/serve/worker/entry.ts +22 -18
  492. package/src/serve/worker/host/core.ts +9 -7
  493. package/src/serve/worker/host/storage.ts +2 -2
  494. package/src/serve/worker/host-auth.ts +1 -1
  495. package/src/serve/worker/index.ts +4 -1
  496. package/src/serve/worker/port-lifecycle.ts +45 -0
  497. package/src/serve/worker/serve-init.ts +9 -2
  498. package/src/verify/fixture.ts +1 -1
  499. package/dist/serve/site-ui/_astro/app.B52xr-DK.js +0 -1
  500. package/dist/serve/site-ui/_astro/app.DWBraPUw.js +0 -12
  501. package/dist/serve/site-ui/_astro/sandbox-controls.DEpnKg-O.js +0 -1169
  502. package/dist/serve/site-ui/_astro/writes.rpjrFzmu.js +0 -102
@@ -2,7 +2,7 @@
2
2
  <link rel="stylesheet" href="/__pyric/ui/_astro/_slug_.Da5VLhW1.css">
3
3
  <style>:root{--rhythm-para: .875rem;--rhythm-group: 1.5rem;--rhythm-subsection: 2.25rem;--rhythm-section: 3.25rem;--rhythm-list: calc(var(--rhythm-para) * .75)}.prose>*,.prose blockquote>*,.prose li>*,.prose .compat-stat>*{margin-block:0}.prose>*+*{margin-block-start:var(--rhythm-group)}.prose>*+h2{margin-block-start:var(--rhythm-section)}.prose>*+h3,.prose>*+h4{margin-block-start:var(--rhythm-subsection)}.prose>h1+*,.prose>h2+*,.prose>h3+*,.prose>h4+*{margin-block-start:var(--rhythm-para)}.prose>p+p{margin-block-start:var(--rhythm-para)}.prose>p+ul,.prose>p+ol,.prose>p+blockquote{margin-block-start:var(--rhythm-para)}.prose li+li{margin-block-start:var(--rhythm-list)}.prose li>ul,.prose li>ol{margin-block-start:var(--rhythm-list)}.prose li>*+*,.prose blockquote>*+*{margin-block-start:var(--rhythm-para)}
4
4
  html{scrollbar-gutter:stable}
5
- </style></head> <body> <header class="studio__chrome"> <div class="studio__bar"> <div class="studio__chrome-inner"> <nav class="studio__nav" aria-label="Site"> <a class="studio__brand" href="/__pyric/ui/" aria-label="Pyric">pyric</a> <a class="studio__nav-tab" href="/__pyric/ui/"> Home </a><a class="studio__nav-tab" href="/__pyric/ui/docs" aria-current="page"> Docs </a><a class="studio__nav-tab" href="/__pyric/ui/studio"> Studio </a> </nav> </div> </div> </header> <div class="docs-shell" data-astro-cid-mw7aashj> <details class="docs-nav-drawer" data-astro-cid-mw7aashj> <summary data-astro-cid-mw7aashj>Navigate</summary> <nav class="docs-nav" aria-label="Documentation"> <div class="docs-search" data-index-url="/__pyric/ui/docs/index.json"> <div class="docs-search-field"> <svg class="docs-search-icon" viewBox="0 0 16 16" width="14" height="14" aria-hidden="true"> <path d="M11.5 11.5 15 15M13 7A6 6 0 1 1 1 7a6 6 0 0 1 12 0Z" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></path> </svg> <input type="text" class="docs-search-input" placeholder="Search docs" aria-label="Search docs" autocomplete="off" spellcheck="false"> <kbd class="docs-search-kbd">⌘K</kbd> </div> <ul class="docs-search-results" hidden></ul> </div> <script type="module">let i=null;function d(t){return i||(i=fetch(t).then(e=>e.json())),i}function l(t,e){return t.title.toLowerCase().includes(e)||t.excerpt.toLowerCase().includes(e)?!0:t.headings.some(r=>r.text.toLowerCase().includes(e))}function u(t,e,r){if(e.innerHTML="",t.length===0){e.hidden=!1;{const n=document.createElement("li");n.className="docs-search-empty",n.textContent="No matches",e.appendChild(n)}return}e.hidden=!1;for(const n of t.slice(0,8)){const s=document.createElement("li"),c=document.createElement("a");c.href=n.path;const o=document.createElement("span");o.className="docs-search-result-title",o.textContent=n.title;const a=document.createElement("span");a.className="docs-search-result-meta",a.textContent=[n.group,n.section].filter(Boolean).join(" / "),c.append(o,a),s.appendChild(c),e.appendChild(s)}}document.querySelectorAll(".docs-search").forEach(t=>{const e=t.dataset.indexUrl,r=t.querySelector(".docs-search-input"),n=t.querySelector(".docs-search-results");r.addEventListener("input",async()=>{const s=r.value.trim().toLowerCase();if(!s){n.hidden=!0,n.innerHTML="";return}const{pages:c}=await d(e);r.value.trim().toLowerCase()===s&&u(c.filter(o=>l(o,s)),n)}),r.addEventListener("focus",()=>{d(e),n.childElementCount>0&&(n.hidden=!1)}),r.addEventListener("keydown",s=>{s.key==="Escape"&&(r.value="",n.hidden=!0,n.innerHTML="",r.blur())}),r.addEventListener("blur",()=>{window.setTimeout(()=>{n.hidden=!0},150)})});document.addEventListener("keydown",t=>{if(!(t.metaKey||t.ctrlKey)||t.key.toLowerCase()!=="k")return;const e=[...document.querySelectorAll(".docs-search-input")].find(r=>r.offsetParent!==null);e&&(t.preventDefault(),e.focus(),e.select())});</script> <details class="docs-nav-group"> <summary>Overview</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/overview/"> Overview </a> </li><li> <a href="/__pyric/ui/docs/tutorial/"> Tutorial </a> </li><li> <a href="/__pyric/ui/docs/examples/"> Examples </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Get started</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/get-started/start-building/"> Quickstart </a> </li><li> <a href="/__pyric/ui/docs/get-started/vite/"> Vite </a> </li><li> <a href="/__pyric/ui/docs/get-started/nextjs/"> Next.js </a> </li><li> <a href="/__pyric/ui/docs/get-started/how-the-swap-works/"> How the swap works </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Build</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/build/authentication/"> Authentication </a> </li><li> <a href="/__pyric/ui/docs/build/cloud-firestore/"> Cloud Firestore </a> </li><li> <a href="/__pyric/ui/docs/build/realtime-database/"> Realtime Database </a> </li><li> <a href="/__pyric/ui/docs/build/cloud-storage/"> Cloud Storage </a> </li><li> <a href="/__pyric/ui/docs/build/cloud-messaging/"> Cloud Messaging </a> </li><li> <a href="/__pyric/ui/docs/build/ai-logic/"> AI Logic </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Secure &amp; debug</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/secure/secure-it-with-rules/"> Security Rules </a> </li><li> <a href="/__pyric/ui/docs/secure/simulate-and-lint/"> Simulate and lint before you deploy </a> </li><li> <a href="/__pyric/ui/docs/secure/write-a-rules-test-suite/"> Write a rules test suite </a> </li><li> <a href="/__pyric/ui/docs/secure/read-a-denial/"> Read a denial and understand it </a> </li><li> <a href="/__pyric/ui/docs/secure/rules-standard-library/"> The rules standard library </a> </li><li> <a href="/__pyric/ui/docs/secure/rtdb-rules-in-typescript/"> RTDB rules in TypeScript </a> </li><li> <a href="/__pyric/ui/docs/secure/firestore-rules-limits/"> Rules limits </a> </li><li> <a href="/__pyric/ui/docs/secure/audit-your-rules/"> Audit rules and data </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading"> Examples </h2> <ul> <li> <a href="/__pyric/ui/docs/examples/chess/"> Chess showcase </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Observe &amp; shape</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/observe/see-whats-happening/"> Traffic &amp; rule verdicts </a> </li><li> <a href="/__pyric/ui/docs/observe/resolve-runtime-status/"> Runtime status </a> </li><li> <a href="/__pyric/ui/docs/observe/shape-your-data/"> Seed, snapshot, replay </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Ship &amp; test</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/ship/ship-to-production/"> Ship to production </a> </li><li> <a href="/__pyric/ui/docs/ship/test-in-node/"> Test in Node </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Work with an agent</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/agent/set-up-your-agent/"> Connect an agent </a> </li><li> <a href="/__pyric/ui/docs/agent/work-with-an-agent/"> Use the MCP tools </a> </li><li> <a href="/__pyric/ui/docs/agent/watch-and-review/"> Watch in Pyric Studio </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Trust</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/trust/versioning-and-compatibility/"> Versioning and the fb tag </a> </li><li> <a href="/__pyric/ui/docs/trust/rules-standard-library/"> Rules standard library reference </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Conformance</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/conformance-scores/"> Conformance scores </a> </li><li> <a href="/__pyric/ui/docs/trust/how-we-know-it-matches-firebase/"> How we know it matches Firebase </a> </li><li> <a href="/__pyric/ui/docs/app-compat/"> App </a> </li><li> <a href="/__pyric/ui/docs/ai-compat/"> AI Logic </a> </li><li> <a href="/__pyric/ui/docs/auth-compat/"> Auth </a> </li><li> <a href="/__pyric/ui/docs/firestore-compat/"> Firestore </a> </li><li> <a href="/__pyric/ui/docs/database-compat/"> Realtime Database </a> </li><li> <a href="/__pyric/ui/docs/storage-compat/"> Storage </a> </li><li> <a href="/__pyric/ui/docs/messaging-compat/"> Messaging </a> </li><li> <a href="/__pyric/ui/docs/functions-rtdb-compat/"> Functions · RTDB </a> </li><li> <a href="/__pyric/ui/docs/rules-compat/"> Rules </a> </li> </ul> </div> </div> </details> <details class="docs-nav-group" open> <summary>Reference</summary> <div class="docs-nav-group-body docs-nav-group-body--reference"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/api-reference/"> API reference </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">pyric</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-app-reference-api/"> pyric/app </a> </li><li> <a href="/__pyric/ui/docs/pyric-firestore-reference-api/"> pyric/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-auth-reference-api/"> pyric/auth </a> </li><li> <a href="/__pyric/ui/docs/pyric-ai-reference-api/"> pyric/ai </a> </li><li> <a href="/__pyric/ui/docs/pyric-ai-scripting-reference-api/"> pyric/ai/scripting </a> </li><li> <a href="/__pyric/ui/docs/pyric-database-reference-api/"> pyric/database </a> </li><li> <a href="/__pyric/ui/docs/pyric-storage-reference-api/"> pyric/storage </a> </li><li> <a href="/__pyric/ui/docs/pyric-messaging-reference-api/"> pyric/messaging </a> </li><li> <a href="/__pyric/ui/docs/pyric-messaging-sw-reference-api/"> pyric/messaging/sw </a> </li><li> <a href="/__pyric/ui/docs/pyric-rules-reference-api/"> pyric/rules </a> </li><li> <a href="/__pyric/ui/docs/pyric-sandbox-reference-api/" aria-current="page"> pyric/sandbox </a> </li><li> <a href="/__pyric/ui/docs/pyric-sandbox-firestore-reference-api/"> pyric/sandbox/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-sandbox-database-reference-api/"> pyric/sandbox/database </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">pyric-admin</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-admin-reference-api/"> pyric-admin </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-app-reference-api/"> pyric-admin/app </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-firestore-reference-api/"> pyric-admin/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-auth-reference-api/"> pyric-admin/auth </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-database-reference-api/"> pyric-admin/database </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-storage-reference-api/"> pyric-admin/storage </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-messaging-reference-api/"> pyric-admin/messaging </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">create-pyric</h2> <ul> <li> <a href="/__pyric/ui/docs/create-pyric-reference-api/"> create-pyric </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">@pyric/cli</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-cli-credentials-node-reference-api/"> @pyric/cli/credentials/node </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-verify-reference-api/"> @pyric/cli/verify </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-conformance-reference-api/"> @pyric/cli/conformance </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-conformance-browser-reference-api/"> @pyric/cli/conformance/browser </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-conformance-docs-reference-api/"> @pyric/cli/conformance/docs </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-assurance-reference-api/"> @pyric/cli/assurance </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-assurance-browser-reference-api/"> @pyric/cli/assurance/browser </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-bridge-reference-api/"> @pyric/cli/bridge </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-bridge-client-reference-api/"> @pyric/cli/bridge/client </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-discover-reference-api/"> @pyric/cli/discover </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-vite-reference-api/"> @pyric/cli/vite </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-next-reference-api/"> @pyric/cli/next </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-serve-worker-reference-api/"> @pyric/cli/serve/worker </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-remote-reference-api/"> @pyric/cli/remote </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-register-reference-api/"> @pyric/cli/register </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-register-app-bridge-reference-api/"> @pyric/cli/register/app-bridge </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">@pyric/ui</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-ui-auth-reference-api/"> @pyric/ui/auth </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-auth-hooks-reference-api/"> @pyric/ui/auth/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-primitives-reference-api/"> @pyric/ui/primitives </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-firestore-reference-api/"> @pyric/ui/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-firestore-hooks-reference-api/"> @pyric/ui/firestore/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-rtdb-reference-api/"> @pyric/ui/rtdb </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-storage-reference-api/"> @pyric/ui/storage </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-storage-hooks-reference-api/"> @pyric/ui/storage/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-traffic-reference-api/"> @pyric/ui/traffic </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-traffic-hooks-reference-api/"> @pyric/ui/traffic/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-events-reference-api/"> @pyric/ui/events </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-events-hooks-reference-api/"> @pyric/ui/events/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-agents-reference-api/"> @pyric/ui/agents </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-rules-reference-api/"> @pyric/ui/rules </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-rules-hooks-reference-api/"> @pyric/ui/rules/hooks </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">@pyric/cli</h2> <ul> <li> <a href="/__pyric/ui/docs/reference/cli/"> CLI </a> </li> </ul> </div> </div> </details> </nav> </details> <nav class="docs-nav" aria-label="Documentation"> <div class="docs-search" data-index-url="/__pyric/ui/docs/index.json"> <div class="docs-search-field"> <svg class="docs-search-icon" viewBox="0 0 16 16" width="14" height="14" aria-hidden="true"> <path d="M11.5 11.5 15 15M13 7A6 6 0 1 1 1 7a6 6 0 0 1 12 0Z" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></path> </svg> <input type="text" class="docs-search-input" placeholder="Search docs" aria-label="Search docs" autocomplete="off" spellcheck="false"> <kbd class="docs-search-kbd">⌘K</kbd> </div> <ul class="docs-search-results" hidden></ul> </div> <details class="docs-nav-group" id="nav-group-overview"> <summary>Overview</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/overview/"> Overview </a> </li><li> <a href="/__pyric/ui/docs/tutorial/"> Tutorial </a> </li><li> <a href="/__pyric/ui/docs/examples/"> Examples </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-get-started"> <summary>Get started</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/get-started/start-building/"> Quickstart </a> </li><li> <a href="/__pyric/ui/docs/get-started/vite/"> Vite </a> </li><li> <a href="/__pyric/ui/docs/get-started/nextjs/"> Next.js </a> </li><li> <a href="/__pyric/ui/docs/get-started/how-the-swap-works/"> How the swap works </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-build"> <summary>Build</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/build/authentication/"> Authentication </a> </li><li> <a href="/__pyric/ui/docs/build/cloud-firestore/"> Cloud Firestore </a> </li><li> <a href="/__pyric/ui/docs/build/realtime-database/"> Realtime Database </a> </li><li> <a href="/__pyric/ui/docs/build/cloud-storage/"> Cloud Storage </a> </li><li> <a href="/__pyric/ui/docs/build/cloud-messaging/"> Cloud Messaging </a> </li><li> <a href="/__pyric/ui/docs/build/ai-logic/"> AI Logic </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-secure-debug"> <summary>Secure &amp; debug</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/secure/secure-it-with-rules/"> Security Rules </a> </li><li> <a href="/__pyric/ui/docs/secure/simulate-and-lint/"> Simulate and lint before you deploy </a> </li><li> <a href="/__pyric/ui/docs/secure/write-a-rules-test-suite/"> Write a rules test suite </a> </li><li> <a href="/__pyric/ui/docs/secure/read-a-denial/"> Read a denial and understand it </a> </li><li> <a href="/__pyric/ui/docs/secure/rules-standard-library/"> The rules standard library </a> </li><li> <a href="/__pyric/ui/docs/secure/rtdb-rules-in-typescript/"> RTDB rules in TypeScript </a> </li><li> <a href="/__pyric/ui/docs/secure/firestore-rules-limits/"> Rules limits </a> </li><li> <a href="/__pyric/ui/docs/secure/audit-your-rules/"> Audit rules and data </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading" id="nav-section-secure-debug-examples"> Examples </h2> <ul> <li> <a href="/__pyric/ui/docs/examples/chess/"> Chess showcase </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-observe-shape"> <summary>Observe &amp; shape</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/observe/see-whats-happening/"> Traffic &amp; rule verdicts </a> </li><li> <a href="/__pyric/ui/docs/observe/resolve-runtime-status/"> Runtime status </a> </li><li> <a href="/__pyric/ui/docs/observe/shape-your-data/"> Seed, snapshot, replay </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-ship-test"> <summary>Ship &amp; test</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/ship/ship-to-production/"> Ship to production </a> </li><li> <a href="/__pyric/ui/docs/ship/test-in-node/"> Test in Node </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-work-with-an-agent"> <summary>Work with an agent</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/agent/set-up-your-agent/"> Connect an agent </a> </li><li> <a href="/__pyric/ui/docs/agent/work-with-an-agent/"> Use the MCP tools </a> </li><li> <a href="/__pyric/ui/docs/agent/watch-and-review/"> Watch in Pyric Studio </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-trust"> <summary>Trust</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/trust/versioning-and-compatibility/"> Versioning and the fb tag </a> </li><li> <a href="/__pyric/ui/docs/trust/rules-standard-library/"> Rules standard library reference </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-conformance"> <summary>Conformance</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/conformance-scores/"> Conformance scores </a> </li><li> <a href="/__pyric/ui/docs/trust/how-we-know-it-matches-firebase/"> How we know it matches Firebase </a> </li><li> <a href="/__pyric/ui/docs/app-compat/"> App </a> </li><li> <a href="/__pyric/ui/docs/ai-compat/"> AI Logic </a> </li><li> <a href="/__pyric/ui/docs/auth-compat/"> Auth </a> </li><li> <a href="/__pyric/ui/docs/firestore-compat/"> Firestore </a> </li><li> <a href="/__pyric/ui/docs/database-compat/"> Realtime Database </a> </li><li> <a href="/__pyric/ui/docs/storage-compat/"> Storage </a> </li><li> <a href="/__pyric/ui/docs/messaging-compat/"> Messaging </a> </li><li> <a href="/__pyric/ui/docs/functions-rtdb-compat/"> Functions · RTDB </a> </li><li> <a href="/__pyric/ui/docs/rules-compat/"> Rules </a> </li> </ul> </div> </div> </details> <details class="docs-nav-group" id="nav-group-reference" open> <summary>Reference</summary> <div class="docs-nav-group-body docs-nav-group-body--reference"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/api-reference/"> API reference </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">pyric</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-app-reference-api/"> pyric/app </a> </li><li> <a href="/__pyric/ui/docs/pyric-firestore-reference-api/"> pyric/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-auth-reference-api/"> pyric/auth </a> </li><li> <a href="/__pyric/ui/docs/pyric-ai-reference-api/"> pyric/ai </a> </li><li> <a href="/__pyric/ui/docs/pyric-ai-scripting-reference-api/"> pyric/ai/scripting </a> </li><li> <a href="/__pyric/ui/docs/pyric-database-reference-api/"> pyric/database </a> </li><li> <a href="/__pyric/ui/docs/pyric-storage-reference-api/"> pyric/storage </a> </li><li> <a href="/__pyric/ui/docs/pyric-messaging-reference-api/"> pyric/messaging </a> </li><li> <a href="/__pyric/ui/docs/pyric-messaging-sw-reference-api/"> pyric/messaging/sw </a> </li><li> <a href="/__pyric/ui/docs/pyric-rules-reference-api/"> pyric/rules </a> </li><li> <a href="/__pyric/ui/docs/pyric-sandbox-reference-api/" aria-current="page"> pyric/sandbox </a> </li><li> <a href="/__pyric/ui/docs/pyric-sandbox-firestore-reference-api/"> pyric/sandbox/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-sandbox-database-reference-api/"> pyric/sandbox/database </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">pyric-admin</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-admin-reference-api/"> pyric-admin </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-app-reference-api/"> pyric-admin/app </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-firestore-reference-api/"> pyric-admin/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-auth-reference-api/"> pyric-admin/auth </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-database-reference-api/"> pyric-admin/database </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-storage-reference-api/"> pyric-admin/storage </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-messaging-reference-api/"> pyric-admin/messaging </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">create-pyric</h2> <ul> <li> <a href="/__pyric/ui/docs/create-pyric-reference-api/"> create-pyric </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">@pyric/cli</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-cli-credentials-node-reference-api/"> @pyric/cli/credentials/node </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-verify-reference-api/"> @pyric/cli/verify </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-conformance-reference-api/"> @pyric/cli/conformance </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-conformance-browser-reference-api/"> @pyric/cli/conformance/browser </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-conformance-docs-reference-api/"> @pyric/cli/conformance/docs </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-assurance-reference-api/"> @pyric/cli/assurance </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-assurance-browser-reference-api/"> @pyric/cli/assurance/browser </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-bridge-reference-api/"> @pyric/cli/bridge </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-bridge-client-reference-api/"> @pyric/cli/bridge/client </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-discover-reference-api/"> @pyric/cli/discover </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-vite-reference-api/"> @pyric/cli/vite </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-next-reference-api/"> @pyric/cli/next </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-serve-worker-reference-api/"> @pyric/cli/serve/worker </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-remote-reference-api/"> @pyric/cli/remote </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-register-reference-api/"> @pyric/cli/register </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-register-app-bridge-reference-api/"> @pyric/cli/register/app-bridge </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">@pyric/ui</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-ui-auth-reference-api/"> @pyric/ui/auth </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-auth-hooks-reference-api/"> @pyric/ui/auth/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-primitives-reference-api/"> @pyric/ui/primitives </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-firestore-reference-api/"> @pyric/ui/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-firestore-hooks-reference-api/"> @pyric/ui/firestore/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-rtdb-reference-api/"> @pyric/ui/rtdb </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-storage-reference-api/"> @pyric/ui/storage </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-storage-hooks-reference-api/"> @pyric/ui/storage/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-traffic-reference-api/"> @pyric/ui/traffic </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-traffic-hooks-reference-api/"> @pyric/ui/traffic/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-events-reference-api/"> @pyric/ui/events </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-events-hooks-reference-api/"> @pyric/ui/events/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-agents-reference-api/"> @pyric/ui/agents </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-rules-reference-api/"> @pyric/ui/rules </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-rules-hooks-reference-api/"> @pyric/ui/rules/hooks </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">@pyric/cli</h2> <ul> <li> <a href="/__pyric/ui/docs/reference/cli/"> CLI </a> </li> </ul> </div> </div> </details> </nav> <main class="doc-main" data-astro-cid-mw7aashj> <nav class="docs-breadcrumbs" aria-label="Breadcrumb"> <ol> <li> <a href="/__pyric/ui/docs/api-reference/">API reference</a> </li><li> <span class="docs-breadcrumbs-sep" aria-hidden="true">/</span> <span>pyric</span> </li><li> <span class="docs-breadcrumbs-sep" aria-hidden="true">/</span> <span aria-current="page">pyric/sandbox</span> </li> </ol> </nav> <header class="api-reference-header" data-astro-cid-mw7aashj> <p class="api-reference-kicker" data-astro-cid-mw7aashj>API reference</p> <h1 data-astro-cid-mw7aashj><code data-astro-cid-mw7aashj>pyric/sandbox</code></h1> <p class="api-reference-meta" data-astro-cid-mw7aashj> 73 published symbols from <code data-astro-cid-mw7aashj>pyric</code> </p> <p class="api-reference-source" data-astro-cid-mw7aashj>
5
+ </style></head> <body> <header class="studio__chrome"> <div class="studio__bar"> <div class="studio__chrome-inner"> <nav class="studio__nav" aria-label="Site"> <a class="studio__brand" href="/__pyric/ui/" aria-label="Pyric">pyric</a> <a class="studio__nav-tab" href="/__pyric/ui/"> Home </a><a class="studio__nav-tab" href="/__pyric/ui/docs" aria-current="page"> Docs </a><a class="studio__nav-tab" href="/__pyric/ui/studio"> Studio </a> </nav> </div> </div> </header> <div class="docs-shell" data-astro-cid-mw7aashj> <details class="docs-nav-drawer" data-astro-cid-mw7aashj> <summary data-astro-cid-mw7aashj>Navigate</summary> <nav class="docs-nav" aria-label="Documentation"> <div class="docs-search" data-index-url="/__pyric/ui/docs/index.json"> <div class="docs-search-field"> <svg class="docs-search-icon" viewBox="0 0 16 16" width="14" height="14" aria-hidden="true"> <path d="M11.5 11.5 15 15M13 7A6 6 0 1 1 1 7a6 6 0 0 1 12 0Z" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></path> </svg> <input type="text" class="docs-search-input" placeholder="Search docs" aria-label="Search docs" autocomplete="off" spellcheck="false"> <kbd class="docs-search-kbd">⌘K</kbd> </div> <ul class="docs-search-results" hidden></ul> </div> <script type="module">let i=null;function d(t){return i||(i=fetch(t).then(e=>e.json())),i}function l(t,e){return t.title.toLowerCase().includes(e)||t.excerpt.toLowerCase().includes(e)?!0:t.headings.some(r=>r.text.toLowerCase().includes(e))}function u(t,e,r){if(e.innerHTML="",t.length===0){e.hidden=!1;{const n=document.createElement("li");n.className="docs-search-empty",n.textContent="No matches",e.appendChild(n)}return}e.hidden=!1;for(const n of t.slice(0,8)){const s=document.createElement("li"),c=document.createElement("a");c.href=n.path;const o=document.createElement("span");o.className="docs-search-result-title",o.textContent=n.title;const a=document.createElement("span");a.className="docs-search-result-meta",a.textContent=[n.group,n.section].filter(Boolean).join(" / "),c.append(o,a),s.appendChild(c),e.appendChild(s)}}document.querySelectorAll(".docs-search").forEach(t=>{const e=t.dataset.indexUrl,r=t.querySelector(".docs-search-input"),n=t.querySelector(".docs-search-results");r.addEventListener("input",async()=>{const s=r.value.trim().toLowerCase();if(!s){n.hidden=!0,n.innerHTML="";return}const{pages:c}=await d(e);r.value.trim().toLowerCase()===s&&u(c.filter(o=>l(o,s)),n)}),r.addEventListener("focus",()=>{d(e),n.childElementCount>0&&(n.hidden=!1)}),r.addEventListener("keydown",s=>{s.key==="Escape"&&(r.value="",n.hidden=!0,n.innerHTML="",r.blur())}),r.addEventListener("blur",()=>{window.setTimeout(()=>{n.hidden=!0},150)})});document.addEventListener("keydown",t=>{if(!(t.metaKey||t.ctrlKey)||t.key.toLowerCase()!=="k")return;const e=[...document.querySelectorAll(".docs-search-input")].find(r=>r.offsetParent!==null);e&&(t.preventDefault(),e.focus(),e.select())});</script> <details class="docs-nav-group"> <summary>Overview</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/overview/"> Overview </a> </li><li> <a href="/__pyric/ui/docs/tutorial/"> Tutorial </a> </li><li> <a href="/__pyric/ui/docs/examples/"> Examples </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Get started</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/get-started/start-building/"> Quickstart </a> </li><li> <a href="/__pyric/ui/docs/get-started/vite/"> Vite </a> </li><li> <a href="/__pyric/ui/docs/get-started/nextjs/"> Next.js </a> </li><li> <a href="/__pyric/ui/docs/get-started/backend-bundlers/"> Backend bundlers </a> </li><li> <a href="/__pyric/ui/docs/get-started/flutter/"> Flutter </a> </li><li> <a href="/__pyric/ui/docs/get-started/how-the-swap-works/"> How the swap works </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Build</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/build/authentication/"> Authentication </a> </li><li> <a href="/__pyric/ui/docs/build/cloud-firestore/"> Cloud Firestore </a> </li><li> <a href="/__pyric/ui/docs/build/realtime-database/"> Realtime Database </a> </li><li> <a href="/__pyric/ui/docs/build/cloud-storage/"> Cloud Storage </a> </li><li> <a href="/__pyric/ui/docs/build/cloud-messaging/"> Cloud Messaging </a> </li><li> <a href="/__pyric/ui/docs/build/ai-logic/"> AI Logic </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Secure &amp; debug</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/secure/secure-it-with-rules/"> Security Rules </a> </li><li> <a href="/__pyric/ui/docs/secure/simulate-and-lint/"> Simulate and lint before you deploy </a> </li><li> <a href="/__pyric/ui/docs/secure/write-a-rules-test-suite/"> Write a rules test suite </a> </li><li> <a href="/__pyric/ui/docs/secure/read-a-denial/"> Read a denial and understand it </a> </li><li> <a href="/__pyric/ui/docs/secure/rules-standard-library/"> The rules standard library </a> </li><li> <a href="/__pyric/ui/docs/secure/rtdb-rules-in-typescript/"> RTDB rules in TypeScript </a> </li><li> <a href="/__pyric/ui/docs/secure/firestore-rules-limits/"> Rules limits </a> </li><li> <a href="/__pyric/ui/docs/secure/audit-your-rules/"> Audit rules and data </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading"> Examples </h2> <ul> <li> <a href="/__pyric/ui/docs/examples/chess/"> Chess showcase </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Observe &amp; shape</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/observe/see-whats-happening/"> Traffic &amp; rule verdicts </a> </li><li> <a href="/__pyric/ui/docs/observe/resolve-runtime-status/"> Runtime status </a> </li><li> <a href="/__pyric/ui/docs/observe/switch-and-impersonate-identities/"> Impersonate &amp; tenants </a> </li><li> <a href="/__pyric/ui/docs/observe/shape-your-data/"> Seed, snapshot, replay </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Ship &amp; test</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/ship/ship-to-production/"> Ship to production </a> </li><li> <a href="/__pyric/ui/docs/ship/test-in-node/"> Test in Node </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Work with an agent</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/agent/set-up-your-agent/"> Connect an agent </a> </li><li> <a href="/__pyric/ui/docs/agent/work-with-an-agent/"> Use the MCP tools </a> </li><li> <a href="/__pyric/ui/docs/agent/watch-and-review/"> Watch in Pyric Studio </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Trust</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/trust/versioning-and-compatibility/"> Versioning and the fb tag </a> </li><li> <a href="/__pyric/ui/docs/trust/rules-standard-library/"> Rules standard library reference </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Conformance</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/conformance-scores/"> Conformance scores </a> </li><li> <a href="/__pyric/ui/docs/trust/how-we-know-it-matches-firebase/"> How we know it matches Firebase </a> </li><li> <a href="/__pyric/ui/docs/app-compat/"> App </a> </li><li> <a href="/__pyric/ui/docs/ai-compat/"> AI Logic </a> </li><li> <a href="/__pyric/ui/docs/auth-compat/"> Auth </a> </li><li> <a href="/__pyric/ui/docs/firestore-compat/"> Firestore </a> </li><li> <a href="/__pyric/ui/docs/database-compat/"> Realtime Database </a> </li><li> <a href="/__pyric/ui/docs/storage-compat/"> Storage </a> </li><li> <a href="/__pyric/ui/docs/messaging-compat/"> Messaging </a> </li><li> <a href="/__pyric/ui/docs/functions-rtdb-compat/"> Functions · RTDB </a> </li><li> <a href="/__pyric/ui/docs/rules-compat/"> Rules </a> </li><li> <a href="/__pyric/ui/docs/firestore-flutter-compat/"> Firestore · Flutter </a> </li><li> <a href="/__pyric/ui/docs/firestore-kotlin-compat/"> Firestore · Kotlin </a> </li><li> <a href="/__pyric/ui/docs/firestore-swift-compat/"> Firestore · Swift </a> </li> </ul> </div> </div> </details> <details class="docs-nav-group" open> <summary>Reference</summary> <div class="docs-nav-group-body docs-nav-group-body--reference"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/api-reference/"> API reference </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">pyric</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-app-reference-api/"> pyric/app </a> </li><li> <a href="/__pyric/ui/docs/pyric-firestore-reference-api/"> pyric/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-firestore-lite-reference-api/"> pyric/firestore/lite </a> </li><li> <a href="/__pyric/ui/docs/pyric-auth-reference-api/"> pyric/auth </a> </li><li> <a href="/__pyric/ui/docs/pyric-ai-reference-api/"> pyric/ai </a> </li><li> <a href="/__pyric/ui/docs/pyric-ai-scripting-reference-api/"> pyric/ai/scripting </a> </li><li> <a href="/__pyric/ui/docs/pyric-database-reference-api/"> pyric/database </a> </li><li> <a href="/__pyric/ui/docs/pyric-storage-reference-api/"> pyric/storage </a> </li><li> <a href="/__pyric/ui/docs/pyric-messaging-reference-api/"> pyric/messaging </a> </li><li> <a href="/__pyric/ui/docs/pyric-messaging-sw-reference-api/"> pyric/messaging/sw </a> </li><li> <a href="/__pyric/ui/docs/pyric-rules-reference-api/"> pyric/rules </a> </li><li> <a href="/__pyric/ui/docs/pyric-sandbox-reference-api/" aria-current="page"> pyric/sandbox </a> </li><li> <a href="/__pyric/ui/docs/pyric-sandbox-firestore-reference-api/"> pyric/sandbox/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-sandbox-database-reference-api/"> pyric/sandbox/database </a> </li><li> <a href="/__pyric/ui/docs/pyric-app-check-reference-api/"> pyric/app-check </a> </li><li> <a href="/__pyric/ui/docs/pyric-functions-reference-api/"> pyric/functions </a> </li><li> <a href="/__pyric/ui/docs/pyric-analytics-reference-api/"> pyric/analytics </a> </li><li> <a href="/__pyric/ui/docs/pyric-performance-reference-api/"> pyric/performance </a> </li><li> <a href="/__pyric/ui/docs/pyric-remote-config-reference-api/"> pyric/remote-config </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">pyric-admin</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-admin-reference-api/"> pyric-admin </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-app-reference-api/"> pyric-admin/app </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-firestore-reference-api/"> pyric-admin/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-auth-reference-api/"> pyric-admin/auth </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-database-reference-api/"> pyric-admin/database </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-storage-reference-api/"> pyric-admin/storage </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-messaging-reference-api/"> pyric-admin/messaging </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">create-pyric</h2> <ul> <li> <a href="/__pyric/ui/docs/create-pyric-reference-api/"> create-pyric </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">@pyric/cli</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-cli-credentials-node-reference-api/"> @pyric/cli/credentials/node </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-verify-reference-api/"> @pyric/cli/verify </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-conformance-reference-api/"> @pyric/cli/conformance </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-conformance-browser-reference-api/"> @pyric/cli/conformance/browser </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-conformance-docs-reference-api/"> @pyric/cli/conformance/docs </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-assurance-reference-api/"> @pyric/cli/assurance </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-assurance-browser-reference-api/"> @pyric/cli/assurance/browser </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-bridge-reference-api/"> @pyric/cli/bridge </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-bridge-client-reference-api/"> @pyric/cli/bridge/client </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-discover-reference-api/"> @pyric/cli/discover </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-vite-reference-api/"> @pyric/cli/vite </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-next-reference-api/"> @pyric/cli/next </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-bundler-reference-api/"> @pyric/cli/bundler </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-serve-worker-reference-api/"> @pyric/cli/serve/worker </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-remote-reference-api/"> @pyric/cli/remote </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-register-reference-api/"> @pyric/cli/register </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-register-app-bridge-reference-api/"> @pyric/cli/register/app-bridge </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">@pyric/ui</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-ui-auth-reference-api/"> @pyric/ui/auth </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-auth-hooks-reference-api/"> @pyric/ui/auth/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-primitives-reference-api/"> @pyric/ui/primitives </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-firestore-reference-api/"> @pyric/ui/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-firestore-hooks-reference-api/"> @pyric/ui/firestore/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-rtdb-reference-api/"> @pyric/ui/rtdb </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-storage-reference-api/"> @pyric/ui/storage </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-storage-hooks-reference-api/"> @pyric/ui/storage/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-traffic-reference-api/"> @pyric/ui/traffic </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-traffic-hooks-reference-api/"> @pyric/ui/traffic/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-events-reference-api/"> @pyric/ui/events </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-events-hooks-reference-api/"> @pyric/ui/events/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-agents-reference-api/"> @pyric/ui/agents </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-rules-reference-api/"> @pyric/ui/rules </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-rules-hooks-reference-api/"> @pyric/ui/rules/hooks </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">@pyric/cli</h2> <ul> <li> <a href="/__pyric/ui/docs/reference/cli/"> CLI </a> </li> </ul> </div> </div> </details> </nav> </details> <nav class="docs-nav" aria-label="Documentation"> <div class="docs-search" data-index-url="/__pyric/ui/docs/index.json"> <div class="docs-search-field"> <svg class="docs-search-icon" viewBox="0 0 16 16" width="14" height="14" aria-hidden="true"> <path d="M11.5 11.5 15 15M13 7A6 6 0 1 1 1 7a6 6 0 0 1 12 0Z" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></path> </svg> <input type="text" class="docs-search-input" placeholder="Search docs" aria-label="Search docs" autocomplete="off" spellcheck="false"> <kbd class="docs-search-kbd">⌘K</kbd> </div> <ul class="docs-search-results" hidden></ul> </div> <details class="docs-nav-group" id="nav-group-overview"> <summary>Overview</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/overview/"> Overview </a> </li><li> <a href="/__pyric/ui/docs/tutorial/"> Tutorial </a> </li><li> <a href="/__pyric/ui/docs/examples/"> Examples </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-get-started"> <summary>Get started</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/get-started/start-building/"> Quickstart </a> </li><li> <a href="/__pyric/ui/docs/get-started/vite/"> Vite </a> </li><li> <a href="/__pyric/ui/docs/get-started/nextjs/"> Next.js </a> </li><li> <a href="/__pyric/ui/docs/get-started/backend-bundlers/"> Backend bundlers </a> </li><li> <a href="/__pyric/ui/docs/get-started/flutter/"> Flutter </a> </li><li> <a href="/__pyric/ui/docs/get-started/how-the-swap-works/"> How the swap works </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-build"> <summary>Build</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/build/authentication/"> Authentication </a> </li><li> <a href="/__pyric/ui/docs/build/cloud-firestore/"> Cloud Firestore </a> </li><li> <a href="/__pyric/ui/docs/build/realtime-database/"> Realtime Database </a> </li><li> <a href="/__pyric/ui/docs/build/cloud-storage/"> Cloud Storage </a> </li><li> <a href="/__pyric/ui/docs/build/cloud-messaging/"> Cloud Messaging </a> </li><li> <a href="/__pyric/ui/docs/build/ai-logic/"> AI Logic </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-secure-debug"> <summary>Secure &amp; debug</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/secure/secure-it-with-rules/"> Security Rules </a> </li><li> <a href="/__pyric/ui/docs/secure/simulate-and-lint/"> Simulate and lint before you deploy </a> </li><li> <a href="/__pyric/ui/docs/secure/write-a-rules-test-suite/"> Write a rules test suite </a> </li><li> <a href="/__pyric/ui/docs/secure/read-a-denial/"> Read a denial and understand it </a> </li><li> <a href="/__pyric/ui/docs/secure/rules-standard-library/"> The rules standard library </a> </li><li> <a href="/__pyric/ui/docs/secure/rtdb-rules-in-typescript/"> RTDB rules in TypeScript </a> </li><li> <a href="/__pyric/ui/docs/secure/firestore-rules-limits/"> Rules limits </a> </li><li> <a href="/__pyric/ui/docs/secure/audit-your-rules/"> Audit rules and data </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading" id="nav-section-secure-debug-examples"> Examples </h2> <ul> <li> <a href="/__pyric/ui/docs/examples/chess/"> Chess showcase </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-observe-shape"> <summary>Observe &amp; shape</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/observe/see-whats-happening/"> Traffic &amp; rule verdicts </a> </li><li> <a href="/__pyric/ui/docs/observe/resolve-runtime-status/"> Runtime status </a> </li><li> <a href="/__pyric/ui/docs/observe/switch-and-impersonate-identities/"> Impersonate &amp; tenants </a> </li><li> <a href="/__pyric/ui/docs/observe/shape-your-data/"> Seed, snapshot, replay </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-ship-test"> <summary>Ship &amp; test</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/ship/ship-to-production/"> Ship to production </a> </li><li> <a href="/__pyric/ui/docs/ship/test-in-node/"> Test in Node </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-work-with-an-agent"> <summary>Work with an agent</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/agent/set-up-your-agent/"> Connect an agent </a> </li><li> <a href="/__pyric/ui/docs/agent/work-with-an-agent/"> Use the MCP tools </a> </li><li> <a href="/__pyric/ui/docs/agent/watch-and-review/"> Watch in Pyric Studio </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-trust"> <summary>Trust</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/trust/versioning-and-compatibility/"> Versioning and the fb tag </a> </li><li> <a href="/__pyric/ui/docs/trust/rules-standard-library/"> Rules standard library reference </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-conformance"> <summary>Conformance</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/conformance-scores/"> Conformance scores </a> </li><li> <a href="/__pyric/ui/docs/trust/how-we-know-it-matches-firebase/"> How we know it matches Firebase </a> </li><li> <a href="/__pyric/ui/docs/app-compat/"> App </a> </li><li> <a href="/__pyric/ui/docs/ai-compat/"> AI Logic </a> </li><li> <a href="/__pyric/ui/docs/auth-compat/"> Auth </a> </li><li> <a href="/__pyric/ui/docs/firestore-compat/"> Firestore </a> </li><li> <a href="/__pyric/ui/docs/database-compat/"> Realtime Database </a> </li><li> <a href="/__pyric/ui/docs/storage-compat/"> Storage </a> </li><li> <a href="/__pyric/ui/docs/messaging-compat/"> Messaging </a> </li><li> <a href="/__pyric/ui/docs/functions-rtdb-compat/"> Functions · RTDB </a> </li><li> <a href="/__pyric/ui/docs/rules-compat/"> Rules </a> </li><li> <a href="/__pyric/ui/docs/firestore-flutter-compat/"> Firestore · Flutter </a> </li><li> <a href="/__pyric/ui/docs/firestore-kotlin-compat/"> Firestore · Kotlin </a> </li><li> <a href="/__pyric/ui/docs/firestore-swift-compat/"> Firestore · Swift </a> </li> </ul> </div> </div> </details> <details class="docs-nav-group" id="nav-group-reference" open> <summary>Reference</summary> <div class="docs-nav-group-body docs-nav-group-body--reference"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/api-reference/"> API reference </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">pyric</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-app-reference-api/"> pyric/app </a> </li><li> <a href="/__pyric/ui/docs/pyric-firestore-reference-api/"> pyric/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-firestore-lite-reference-api/"> pyric/firestore/lite </a> </li><li> <a href="/__pyric/ui/docs/pyric-auth-reference-api/"> pyric/auth </a> </li><li> <a href="/__pyric/ui/docs/pyric-ai-reference-api/"> pyric/ai </a> </li><li> <a href="/__pyric/ui/docs/pyric-ai-scripting-reference-api/"> pyric/ai/scripting </a> </li><li> <a href="/__pyric/ui/docs/pyric-database-reference-api/"> pyric/database </a> </li><li> <a href="/__pyric/ui/docs/pyric-storage-reference-api/"> pyric/storage </a> </li><li> <a href="/__pyric/ui/docs/pyric-messaging-reference-api/"> pyric/messaging </a> </li><li> <a href="/__pyric/ui/docs/pyric-messaging-sw-reference-api/"> pyric/messaging/sw </a> </li><li> <a href="/__pyric/ui/docs/pyric-rules-reference-api/"> pyric/rules </a> </li><li> <a href="/__pyric/ui/docs/pyric-sandbox-reference-api/" aria-current="page"> pyric/sandbox </a> </li><li> <a href="/__pyric/ui/docs/pyric-sandbox-firestore-reference-api/"> pyric/sandbox/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-sandbox-database-reference-api/"> pyric/sandbox/database </a> </li><li> <a href="/__pyric/ui/docs/pyric-app-check-reference-api/"> pyric/app-check </a> </li><li> <a href="/__pyric/ui/docs/pyric-functions-reference-api/"> pyric/functions </a> </li><li> <a href="/__pyric/ui/docs/pyric-analytics-reference-api/"> pyric/analytics </a> </li><li> <a href="/__pyric/ui/docs/pyric-performance-reference-api/"> pyric/performance </a> </li><li> <a href="/__pyric/ui/docs/pyric-remote-config-reference-api/"> pyric/remote-config </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">pyric-admin</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-admin-reference-api/"> pyric-admin </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-app-reference-api/"> pyric-admin/app </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-firestore-reference-api/"> pyric-admin/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-auth-reference-api/"> pyric-admin/auth </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-database-reference-api/"> pyric-admin/database </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-storage-reference-api/"> pyric-admin/storage </a> </li><li> <a href="/__pyric/ui/docs/pyric-admin-messaging-reference-api/"> pyric-admin/messaging </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">create-pyric</h2> <ul> <li> <a href="/__pyric/ui/docs/create-pyric-reference-api/"> create-pyric </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">@pyric/cli</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-cli-credentials-node-reference-api/"> @pyric/cli/credentials/node </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-verify-reference-api/"> @pyric/cli/verify </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-conformance-reference-api/"> @pyric/cli/conformance </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-conformance-browser-reference-api/"> @pyric/cli/conformance/browser </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-conformance-docs-reference-api/"> @pyric/cli/conformance/docs </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-assurance-reference-api/"> @pyric/cli/assurance </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-assurance-browser-reference-api/"> @pyric/cli/assurance/browser </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-bridge-reference-api/"> @pyric/cli/bridge </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-bridge-client-reference-api/"> @pyric/cli/bridge/client </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-discover-reference-api/"> @pyric/cli/discover </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-vite-reference-api/"> @pyric/cli/vite </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-next-reference-api/"> @pyric/cli/next </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-bundler-reference-api/"> @pyric/cli/bundler </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-serve-worker-reference-api/"> @pyric/cli/serve/worker </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-remote-reference-api/"> @pyric/cli/remote </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-register-reference-api/"> @pyric/cli/register </a> </li><li> <a href="/__pyric/ui/docs/pyric-cli-register-app-bridge-reference-api/"> @pyric/cli/register/app-bridge </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">@pyric/ui</h2> <ul> <li> <a href="/__pyric/ui/docs/pyric-ui-auth-reference-api/"> @pyric/ui/auth </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-auth-hooks-reference-api/"> @pyric/ui/auth/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-primitives-reference-api/"> @pyric/ui/primitives </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-firestore-reference-api/"> @pyric/ui/firestore </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-firestore-hooks-reference-api/"> @pyric/ui/firestore/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-rtdb-reference-api/"> @pyric/ui/rtdb </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-storage-reference-api/"> @pyric/ui/storage </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-storage-hooks-reference-api/"> @pyric/ui/storage/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-traffic-reference-api/"> @pyric/ui/traffic </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-traffic-hooks-reference-api/"> @pyric/ui/traffic/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-events-reference-api/"> @pyric/ui/events </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-events-hooks-reference-api/"> @pyric/ui/events/hooks </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-agents-reference-api/"> @pyric/ui/agents </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-rules-reference-api/"> @pyric/ui/rules </a> </li><li> <a href="/__pyric/ui/docs/pyric-ui-rules-hooks-reference-api/"> @pyric/ui/rules/hooks </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading">@pyric/cli</h2> <ul> <li> <a href="/__pyric/ui/docs/reference/cli/"> CLI </a> </li> </ul> </div> </div> </details> </nav> <main class="doc-main" data-astro-cid-mw7aashj> <nav class="docs-breadcrumbs" aria-label="Breadcrumb"> <ol> <li> <a href="/__pyric/ui/docs/api-reference/">API reference</a> </li><li> <span class="docs-breadcrumbs-sep" aria-hidden="true">/</span> <span>pyric</span> </li><li> <span class="docs-breadcrumbs-sep" aria-hidden="true">/</span> <span aria-current="page">pyric/sandbox</span> </li> </ol> </nav> <header class="api-reference-header" data-astro-cid-mw7aashj> <p class="api-reference-kicker" data-astro-cid-mw7aashj>API reference</p> <h1 data-astro-cid-mw7aashj><code data-astro-cid-mw7aashj>pyric/sandbox</code></h1> <p class="api-reference-meta" data-astro-cid-mw7aashj> 75 published symbols from <code data-astro-cid-mw7aashj>pyric</code> </p> <p class="api-reference-source" data-astro-cid-mw7aashj>
6
6
  Generated from the TypeScript declarations shipped at this import path.
7
7
  </p> </header> <article class="prose api-reference-body" data-astro-cid-mw7aashj> <!-- Generated from published package declarations via TypeDoc. Rendered by the api-reference content loader. -->
8
8
  <h2 id="classes">Classes</h2>
@@ -57,7 +57,8 @@ factories; consumers don’t construct it directly.</p>
57
57
  <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#C678DD">new</span><span style="color:#61AFEF"> SandboxContextImpl</span><span style="color:#ABB2BF">(</span></span>
58
58
  <span class="line"><span style="color:#E06C75"> sandbox</span><span style="color:#ABB2BF">: </span><span style="color:#E06C75">Sandbox</span><span style="color:#ABB2BF">,</span></span>
59
59
  <span class="line"><span style="color:#E06C75"> auth</span><span style="color:#ABB2BF">: {</span></span>
60
- <span class="line"><span style="color:#ABB2BF"> token?: </span><span style="color:#E06C75">Record</span><span style="color:#56B6C2">&#x3C;</span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">, unknown>;</span></span>
60
+ <span class="line"><span style="color:#ABB2BF"> tenant?: </span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">;</span></span>
61
+ <span class="line"><span style="color:#E06C75"> token</span><span style="color:#C678DD">?:</span><span style="color:#E06C75"> Record</span><span style="color:#56B6C2">&#x3C;</span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">, unknown>;</span></span>
61
62
  <span class="line"><span style="color:#E06C75"> uid</span><span style="color:#ABB2BF">: </span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">;</span></span>
62
63
  <span class="line"><span style="color:#ABB2BF">},</span></span>
63
64
  <span class="line"><span style="color:#E06C75"> operationContext</span><span style="color:#C678DD">?:</span><span style="color:#E06C75"> OperationContext</span><span style="color:#ABB2BF">): </span><span style="color:#E06C75">SandboxContextImpl</span><span style="color:#ABB2BF">;</span></span></code></pre>
@@ -91,7 +92,11 @@ factories; consumers don’t construct it directly.</p>
91
92
 
92
93
 
93
94
 
94
- <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>sandbox</code></td><td align="left"><a href="/docs/pyric-firestore-reference-api/#sandbox"><code>Sandbox</code></a></td></tr><tr><td align="left"><code>auth</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>operationContext?</code></td><td align="left"><a href="#operationcontext-2"><code>OperationContext</code></a></td></tr></tbody></table></div>
95
+
96
+
97
+
98
+
99
+ <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>sandbox</code></td><td align="left"><a href="/docs/pyric-firestore-reference-api/#sandbox"><code>Sandbox</code></a></td></tr><tr><td align="left"><code>auth</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>operationContext?</code></td><td align="left"><a href="#operationcontext-2"><code>OperationContext</code></a></td></tr></tbody></table></div>
95
100
  <h6 id="returns-1">Returns</h6>
96
101
  <p><a href="#sandboxcontextimpl"><code>SandboxContextImpl</code></a></p>
97
102
  <h4 id="properties">Properties</h4>
@@ -136,12 +141,19 @@ factories; consumers don’t construct it directly.</p>
136
141
 
137
142
 
138
143
 
139
- <table><thead><tr><th align="left">Property</th><th align="left">Modifier</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="auth"></a> <code>auth</code></td><td align="left"><code>readonly</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">The identity rules evaluate under for operations through this context.</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>public</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="operationcontext"></a> <code>operationContext</code></td><td align="left"><code>readonly</code></td><td align="left"><a href="#operationcontext-2"><code>OperationContext</code></a></td><td align="left">Immutable provenance bound to every operation issued through this handle.</td></tr><tr><td align="left"><a id="sandbox"></a> <code>sandbox</code></td><td align="left"><code>readonly</code></td><td align="left"><a href="/docs/pyric-firestore-reference-api/#sandbox"><code>Sandbox</code></a></td><td align="left">The data foundation this context operates against.</td></tr></tbody></table></div>
144
+
145
+
146
+
147
+
148
+
149
+
150
+ <table><thead><tr><th align="left">Property</th><th align="left">Modifier</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="auth"></a> <code>auth</code></td><td align="left"><code>readonly</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">The identity rules evaluate under for operations through this context.</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>public</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="operationcontext"></a> <code>operationContext</code></td><td align="left"><code>readonly</code></td><td align="left"><a href="#operationcontext-2"><code>OperationContext</code></a></td><td align="left">Immutable provenance bound to every operation issued through this handle.</td></tr><tr><td align="left"><a id="sandbox"></a> <code>sandbox</code></td><td align="left"><code>readonly</code></td><td align="left"><a href="/docs/pyric-firestore-reference-api/#sandbox"><code>Sandbox</code></a></td><td align="left">The data foundation this context operates against.</td></tr></tbody></table></div>
140
151
  <h4 id="methods">Methods</h4>
141
152
  <p><a id="withauth"></a></p>
142
153
  <h5 id="withauth">withAuth()</h5>
143
154
  <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#61AFEF">withAuth</span><span style="color:#ABB2BF">(</span><span style="color:#E06C75">auth</span><span style="color:#ABB2BF">: {</span></span>
144
- <span class="line"><span style="color:#ABB2BF"> token?: </span><span style="color:#E06C75">Record</span><span style="color:#56B6C2">&#x3C;</span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">, unknown>;</span></span>
155
+ <span class="line"><span style="color:#ABB2BF"> tenant?: </span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">;</span></span>
156
+ <span class="line"><span style="color:#E06C75"> token</span><span style="color:#C678DD">?:</span><span style="color:#E06C75"> Record</span><span style="color:#56B6C2">&#x3C;</span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">, unknown>;</span></span>
145
157
  <span class="line"><span style="color:#E06C75"> uid</span><span style="color:#ABB2BF">: </span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">;</span></span>
146
158
  <span class="line"><span style="color:#ABB2BF">}): </span><span style="color:#E06C75">SandboxContext</span><span style="color:#ABB2BF">;</span></span></code></pre>
147
159
  <p>Derive a sibling context on the same sandbox with different auth.
@@ -169,7 +181,11 @@ optional plan identity.</p>
169
181
 
170
182
 
171
183
 
172
- <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>auth</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr></tbody></table></div>
184
+
185
+
186
+
187
+
188
+ <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>auth</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr></tbody></table></div>
173
189
  <h6 id="returns-2">Returns</h6>
174
190
  <p><a href="/docs/pyric-firestore-reference-api/#sandboxcontext"><code>SandboxContext</code></a></p>
175
191
  <h6 id="implementation-of">Implementation of</h6>
@@ -518,7 +534,13 @@ reference traces.</p>
518
534
 
519
535
 
520
536
 
521
- <table><thead><tr><th align="left">Property</th><th align="left">Modifier</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="auth-1"></a> <code>auth?</code></td><td align="left"><code>public</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">Auth identity that was active when the denial fired.</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>public</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="failedfields"></a> <code>failedFields?</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code>[]</td><td align="left">Field paths in <code>request.resource.data</code> that the rule referenced and that failed.</td></tr><tr><td align="left"><a id="query"></a> <code>query?</code></td><td align="left"><code>public</code></td><td align="left">{ <code>limit?</code>: <code>number</code>; <code>offset?</code>: <code>number</code>; <code>orderBy?</code>: <code>string</code>; <code>where?</code>: readonly { <code>field</code>: <code>string</code>; <code>op</code>: <code>string</code>; <code>value</code>: <code>string</code> | <code>number</code> | <code>boolean</code>; }[]; }</td><td align="left">Machine-readable descriptor of the denied query’s where/orderBy/limit shape (RULES-B11). Populated when a <code>list</code>/query is denied as statically unprovable (“rules are not filters”), so consumers can render the exact query the engine rejected without re-deriving it. Absent for single-doc and non-query denials.</td></tr><tr><td align="left"><code>query.limit?</code></td><td align="left"><code>readonly</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><code>query.offset?</code></td><td align="left"><code>readonly</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><code>query.orderBy?</code></td><td align="left"><code>readonly</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>query.where?</code></td><td align="left"><code>readonly</code></td><td align="left">readonly { <code>field</code>: <code>string</code>; <code>op</code>: <code>string</code>; <code>value</code>: <code>string</code> | <code>number</code> | <code>boolean</code>; }[]</td><td align="left">-</td></tr><tr><td align="left"><a id="reasons"></a> <code>reasons?</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code>[]</td><td align="left">Raw simulator reasoning lines (the underlying engine’s <code>debugMessages</code>). Always present on <code>permission-denied</code>. Stable enough for log surfacing; not stable as machine-parseable data.</td></tr><tr><td align="left"><a id="request"></a> <code>request?</code></td><td align="left"><code>public</code></td><td align="left">{ <code>method</code>: <code>"delete"</code> | <code>"get"</code> | <code>"list"</code> | <code>"create"</code> | <code>"update"</code>; <code>path</code>: <code>string</code>; <code>resourceData?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; }</td><td align="left">Eval-time request shape — what the rule saw on <code>request.*</code>. Lets callers render a “why did this deny” frame (auth, method, path, <code>request.resource.data</code> with sentinels resolved) without re-deriving any of it from out-of-band state.</td></tr><tr><td align="left"><code>request.method</code></td><td align="left"><code>public</code></td><td align="left"><code>"delete"</code> | <code>"get"</code> | <code>"list"</code> | <code>"create"</code> | <code>"update"</code></td><td align="left">-</td></tr><tr><td align="left"><code>request.path</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>request.resourceData?</code></td><td align="left"><code>public</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">The user’s proposed <code>request.resource.data</code> — pre-resolution. <code>FieldValue.*</code> sentinels are preserved as their marker shapes (<code>{ __type: 'serverTimestamp' }</code>, etc.). The rule engine evaluated against the resolved form; what surfaces here is the caller’s INTENT so consumers see what they tried to write. Absent for reads (no proposed write) and for <code>delete</code> (no payload).</td></tr><tr><td align="left"><a id="resource"></a> <code>resource?</code></td><td align="left"><code>public</code></td><td align="left">{ <code>data</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>exists</code>: <code>boolean</code>; }</td><td align="left">Eval-time existing-document snapshot — what the rule saw on <code>resource.data</code>. <code>null</code> data with <code>exists: false</code> mirrors how the rule sees an absent doc. Absent for collection ops (<code>list</code>).</td></tr><tr><td align="left"><code>resource.data</code></td><td align="left"><code>public</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>resource.exists</code></td><td align="left"><code>public</code></td><td align="left"><code>boolean</code></td><td align="left">-</td></tr><tr><td align="left"><a id="rule"></a> <code>rule?</code></td><td align="left"><code>public</code></td><td align="left">{ <code>citation?</code>: <code>string</code>; <code>col?</code>: <code>number</code>; <code>column?</code>: <code>number</code>; <code>expression?</code>: <code>string</code>; <code>file?</code>: <code>string</code>; <code>line?</code>: <code>number</code>; }</td><td align="left">The rule whose evaluation produced the denial (#370).</td></tr><tr><td align="left"><code>rule.citation?</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>rule.col?</code></td><td align="left"><code>public</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><code>rule.column?</code></td><td align="left"><code>public</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><code>rule.expression?</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>rule.file?</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>rule.line?</code></td><td align="left"><code>public</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr></tbody></table></div>
537
+
538
+
539
+
540
+
541
+
542
+
543
+ <table><thead><tr><th align="left">Property</th><th align="left">Modifier</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="auth-1"></a> <code>auth?</code></td><td align="left"><code>public</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">Auth identity that was active when the denial fired.</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>public</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="failedfields"></a> <code>failedFields?</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code>[]</td><td align="left">Field paths in <code>request.resource.data</code> that the rule referenced and that failed.</td></tr><tr><td align="left"><a id="query"></a> <code>query?</code></td><td align="left"><code>public</code></td><td align="left">{ <code>limit?</code>: <code>number</code>; <code>offset?</code>: <code>number</code>; <code>orderBy?</code>: <code>string</code>; <code>where?</code>: readonly { <code>field</code>: <code>string</code>; <code>op</code>: <code>string</code>; <code>value</code>: <code>string</code> | <code>number</code> | <code>boolean</code>; }[]; }</td><td align="left">Machine-readable descriptor of the denied query’s where/orderBy/limit shape (RULES-B11). Populated when a <code>list</code>/query is denied as statically unprovable (“rules are not filters”), so consumers can render the exact query the engine rejected without re-deriving it. Absent for single-doc and non-query denials.</td></tr><tr><td align="left"><code>query.limit?</code></td><td align="left"><code>readonly</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><code>query.offset?</code></td><td align="left"><code>readonly</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><code>query.orderBy?</code></td><td align="left"><code>readonly</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>query.where?</code></td><td align="left"><code>readonly</code></td><td align="left">readonly { <code>field</code>: <code>string</code>; <code>op</code>: <code>string</code>; <code>value</code>: <code>string</code> | <code>number</code> | <code>boolean</code>; }[]</td><td align="left">-</td></tr><tr><td align="left"><a id="reasons"></a> <code>reasons?</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code>[]</td><td align="left">Raw simulator reasoning lines (the underlying engine’s <code>debugMessages</code>). Always present on <code>permission-denied</code>. Stable enough for log surfacing; not stable as machine-parseable data.</td></tr><tr><td align="left"><a id="request"></a> <code>request?</code></td><td align="left"><code>public</code></td><td align="left">{ <code>method</code>: <code>"delete"</code> | <code>"get"</code> | <code>"list"</code> | <code>"create"</code> | <code>"update"</code>; <code>path</code>: <code>string</code>; <code>resourceData?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; }</td><td align="left">Eval-time request shape — what the rule saw on <code>request.*</code>. Lets callers render a “why did this deny” frame (auth, method, path, <code>request.resource.data</code> with sentinels resolved) without re-deriving any of it from out-of-band state.</td></tr><tr><td align="left"><code>request.method</code></td><td align="left"><code>public</code></td><td align="left"><code>"delete"</code> | <code>"get"</code> | <code>"list"</code> | <code>"create"</code> | <code>"update"</code></td><td align="left">-</td></tr><tr><td align="left"><code>request.path</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>request.resourceData?</code></td><td align="left"><code>public</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">The user’s proposed <code>request.resource.data</code> — pre-resolution. <code>FieldValue.*</code> sentinels are preserved as their marker shapes (<code>{ __type: 'serverTimestamp' }</code>, etc.). The rule engine evaluated against the resolved form; what surfaces here is the caller’s INTENT so consumers see what they tried to write. Absent for reads (no proposed write) and for <code>delete</code> (no payload).</td></tr><tr><td align="left"><a id="resource"></a> <code>resource?</code></td><td align="left"><code>public</code></td><td align="left">{ <code>data</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>exists</code>: <code>boolean</code>; }</td><td align="left">Eval-time existing-document snapshot — what the rule saw on <code>resource.data</code>. <code>null</code> data with <code>exists: false</code> mirrors how the rule sees an absent doc. Absent for collection ops (<code>list</code>).</td></tr><tr><td align="left"><code>resource.data</code></td><td align="left"><code>public</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>resource.exists</code></td><td align="left"><code>public</code></td><td align="left"><code>boolean</code></td><td align="left">-</td></tr><tr><td align="left"><a id="rule"></a> <code>rule?</code></td><td align="left"><code>public</code></td><td align="left">{ <code>citation?</code>: <code>string</code>; <code>col?</code>: <code>number</code>; <code>column?</code>: <code>number</code>; <code>expression?</code>: <code>string</code>; <code>file?</code>: <code>string</code>; <code>line?</code>: <code>number</code>; }</td><td align="left">The rule whose evaluation produced the denial (#370).</td></tr><tr><td align="left"><code>rule.citation?</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>rule.col?</code></td><td align="left"><code>public</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><code>rule.column?</code></td><td align="left"><code>public</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><code>rule.expression?</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>rule.file?</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>rule.line?</code></td><td align="left"><code>public</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr></tbody></table></div>
522
544
  <hr>
523
545
  <p><a id="denialevent"></a></p>
524
546
  <h3 id="denialevent">DenialEvent</h3>
@@ -591,7 +613,11 @@ frame either way.</li>
591
613
 
592
614
 
593
615
 
594
- <table><thead><tr><th align="left">Property</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><a id="auth-2"></a> <code>auth?</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="code"></a> <code>code</code></td><td align="left"><code>"permission-denied"</code></td></tr><tr><td align="left"><a id="message"></a> <code>message</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="reasons-1"></a> <code>reasons?</code></td><td align="left"><code>string</code>[]</td></tr><tr><td align="left"><a id="request-1"></a> <code>request?</code></td><td align="left">{ <code>method</code>: <code>"delete"</code> | <code>"get"</code> | <code>"list"</code> | <code>"create"</code> | <code>"update"</code>; <code>path</code>: <code>string</code>; <code>resourceData?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; }</td></tr><tr><td align="left"><code>request.method</code></td><td align="left"><code>"delete"</code> | <code>"get"</code> | <code>"list"</code> | <code>"create"</code> | <code>"update"</code></td></tr><tr><td align="left"><code>request.path</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>request.resourceData?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><a id="resource-1"></a> <code>resource?</code></td><td align="left">{ <code>data</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>exists</code>: <code>boolean</code>; }</td></tr><tr><td align="left"><code>resource.data</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>resource.exists</code></td><td align="left"><code>boolean</code></td></tr></tbody></table></div>
616
+
617
+
618
+
619
+
620
+ <table><thead><tr><th align="left">Property</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><a id="auth-2"></a> <code>auth?</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="code"></a> <code>code</code></td><td align="left"><code>"permission-denied"</code></td></tr><tr><td align="left"><a id="message"></a> <code>message</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="reasons-1"></a> <code>reasons?</code></td><td align="left"><code>string</code>[]</td></tr><tr><td align="left"><a id="request-1"></a> <code>request?</code></td><td align="left">{ <code>method</code>: <code>"delete"</code> | <code>"get"</code> | <code>"list"</code> | <code>"create"</code> | <code>"update"</code>; <code>path</code>: <code>string</code>; <code>resourceData?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; }</td></tr><tr><td align="left"><code>request.method</code></td><td align="left"><code>"delete"</code> | <code>"get"</code> | <code>"list"</code> | <code>"create"</code> | <code>"update"</code></td></tr><tr><td align="left"><code>request.path</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>request.resourceData?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><a id="resource-1"></a> <code>resource?</code></td><td align="left">{ <code>data</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>exists</code>: <code>boolean</code>; }</td></tr><tr><td align="left"><code>resource.data</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>resource.exists</code></td><td align="left"><code>boolean</code></td></tr></tbody></table></div>
595
621
  <hr>
596
622
  <p><a id="eventprovenance"></a></p>
597
623
  <h3 id="eventprovenance">EventProvenance</h3>
@@ -716,7 +742,12 @@ on the errored phase only.</p>
716
742
 
717
743
 
718
744
 
719
- <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="at"></a> <code>at</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="auth-3"></a> <code>auth</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="error"></a> <code>error?</code></td><td align="left">{ <code>code</code>: <code>"permission-denied"</code>; <code>message</code>: <code>string</code>; <code>reasons?</code>: <code>string</code>[]; }</td><td align="left">Populated on <code>listener_errored</code> only.</td></tr><tr><td align="left"><code>error.code</code></td><td align="left"><code>"permission-denied"</code></td><td align="left">-</td></tr><tr><td align="left"><code>error.message</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>error.reasons?</code></td><td align="left"><code>string</code>[]</td><td align="left">-</td></tr><tr><td align="left"><a id="id"></a> <code>id</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="kind"></a> <code>kind</code></td><td align="left"><code>"listener_attach"</code> | <code>"listener_detach"</code> | <code>"listener_errored"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="listenerid-1"></a> <code>listenerId</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="target"></a> <code>target</code></td><td align="left">| { <code>kind</code>: <code>"doc"</code>; <code>path</code>: <code>string</code>; } | { <code>collection</code>: <code>string</code>; <code>kind</code>: <code>"query"</code>; <code>query?</code>: <code>unknown</code>; }</td><td align="left">-</td></tr></tbody></table></div>
745
+
746
+
747
+
748
+
749
+
750
+ <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="at"></a> <code>at</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="auth-3"></a> <code>auth</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="error"></a> <code>error?</code></td><td align="left">{ <code>code</code>: <code>"permission-denied"</code>; <code>message</code>: <code>string</code>; <code>reasons?</code>: <code>string</code>[]; }</td><td align="left">Populated on <code>listener_errored</code> only.</td></tr><tr><td align="left"><code>error.code</code></td><td align="left"><code>"permission-denied"</code></td><td align="left">-</td></tr><tr><td align="left"><code>error.message</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>error.reasons?</code></td><td align="left"><code>string</code>[]</td><td align="left">-</td></tr><tr><td align="left"><a id="id"></a> <code>id</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="kind"></a> <code>kind</code></td><td align="left"><code>"listener_attach"</code> | <code>"listener_detach"</code> | <code>"listener_errored"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="listenerid-1"></a> <code>listenerId</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="target"></a> <code>target</code></td><td align="left">| { <code>kind</code>: <code>"doc"</code>; <code>path</code>: <code>string</code>; } | { <code>collection</code>: <code>string</code>; <code>kind</code>: <code>"query"</code>; <code>query?</code>: <code>unknown</code>; }</td><td align="left">-</td></tr></tbody></table></div>
720
751
  <hr>
721
752
  <p><a id="localsandbox"></a></p>
722
753
  <h3 id="localsandbox">LocalSandbox</h3>
@@ -770,7 +801,13 @@ are deliberately not assignable to this local-only interface.</p>
770
801
 
771
802
 
772
803
 
773
- <table><thead><tr><th align="left">Property</th><th align="left">Modifier</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="local_sandbox"></a> <code>[LOCAL_SANDBOX]</code></td><td align="left"><code>readonly</code></td><td align="left"><code>true</code></td><td align="left">-</td></tr><tr><td align="left"><a id="admin"></a> <code>admin</code></td><td align="left"><code>readonly</code></td><td align="left"><code>SandboxAdmin</code></td><td align="left">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.</td></tr><tr><td align="left"><a id="currentuser"></a> <code>currentUser</code></td><td align="left"><code>public</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">Current authenticated user across the sandbox. Mutated by <code>pyric/auth</code>’s <code>signInAnonymously</code> / <code>signInWithEmailAndPassword</code> / <code>signOut</code> / <code>sandbox.setUser</code>. Read per-call by service factories (e.g. a future <code>getFirestore(sandbox)</code> overload) so they see auth state changes without re-binding handles. Defaults to <code>null</code> (anonymous / signed out). <strong>Independent of <code>withAuth({uid})</code></strong> — <code>withAuth</code> still produces a frozen <a href="/docs/pyric-firestore-reference-api/#sandboxcontext">SandboxContext</a> that carries its own identity for the runner’s test code (the existing pattern: explicit identity per service call). <code>currentUser</code> exists for the <code>pyric/auth</code> mirror, where consumer app code drives identity through a stateful <code>Auth</code> handle rather than naming it per call.</td></tr><tr><td align="left"><code>currentUser.token?</code></td><td align="left"><code>public</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>currentUser.uid</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr></tbody></table></div>
804
+
805
+
806
+
807
+
808
+
809
+
810
+ <table><thead><tr><th align="left">Property</th><th align="left">Modifier</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="local_sandbox"></a> <code>[LOCAL_SANDBOX]</code></td><td align="left"><code>readonly</code></td><td align="left"><code>true</code></td><td align="left">-</td></tr><tr><td align="left"><a id="admin"></a> <code>admin</code></td><td align="left"><code>readonly</code></td><td align="left"><code>SandboxAdmin</code></td><td align="left">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.</td></tr><tr><td align="left"><a id="currentuser"></a> <code>currentUser</code></td><td align="left"><code>public</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">Current authenticated user across the sandbox. Mutated by <code>pyric/auth</code>’s <code>signInAnonymously</code> / <code>signInWithEmailAndPassword</code> / <code>signOut</code> / <code>sandbox.setUser</code>. Read per-call by service factories (e.g. a future <code>getFirestore(sandbox)</code> overload) so they see auth state changes without re-binding handles. Defaults to <code>null</code> (anonymous / signed out). <strong>Independent of <code>withAuth({uid})</code></strong> — <code>withAuth</code> still produces a frozen <a href="/docs/pyric-firestore-reference-api/#sandboxcontext">SandboxContext</a> that carries its own identity for the runner’s test code (the existing pattern: explicit identity per service call). <code>currentUser</code> exists for the <code>pyric/auth</code> mirror, where consumer app code drives identity through a stateful <code>Auth</code> handle rather than naming it per call.</td></tr><tr><td align="left"><code>currentUser.tenant?</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>currentUser.token?</code></td><td align="left"><code>public</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>currentUser.uid</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr></tbody></table></div>
774
811
  <h4 id="methods-2">Methods</h4>
775
812
  <p><a id="clearpersistence"></a></p>
776
813
  <h5 id="clearpersistence">clearPersistence()</h5>
@@ -948,6 +985,7 @@ a service this one lacks).</p>
948
985
  <p><a id="oncurrentuserchanged"></a></p>
949
986
  <h5 id="oncurrentuserchanged">onCurrentUserChanged()</h5>
950
987
  <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#61AFEF">onCurrentUserChanged</span><span style="color:#ABB2BF">(</span><span style="color:#E06C75">cb</span><span style="color:#ABB2BF">: (</span><span style="color:#E06C75;font-style:italic">user</span><span style="color:#ABB2BF">: {</span></span>
988
+ <span class="line"><span style="color:#E06C75"> tenant</span><span style="color:#C678DD">?</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">string</span><span style="color:#ABB2BF">;</span></span>
951
989
  <span class="line"><span style="color:#E06C75"> token</span><span style="color:#C678DD">?</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">Record</span><span style="color:#ABB2BF">&#x3C;</span><span style="color:#E5C07B">string</span><span style="color:#ABB2BF">, </span><span style="color:#E5C07B">unknown</span><span style="color:#ABB2BF">>;</span></span>
952
990
  <span class="line"><span style="color:#E06C75"> uid</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">string</span><span style="color:#ABB2BF">;</span></span>
953
991
  <span class="line"><span style="color:#ABB2BF">}) </span><span style="color:#C678DD">=></span><span style="color:#C678DD"> void</span><span style="color:#ABB2BF">): () </span><span style="color:#C678DD">=></span><span style="color:#C678DD"> void</span><span style="color:#ABB2BF">;</span></span></code></pre>
@@ -974,7 +1012,7 @@ their errors.</p>
974
1012
 
975
1013
 
976
1014
 
977
- <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>cb</code></td><td align="left">(<code>user</code>: { <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }) => <code>void</code></td></tr></tbody></table></div>
1015
+ <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>cb</code></td><td align="left">(<code>user</code>: { <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }) => <code>void</code></td></tr></tbody></table></div>
978
1016
  <h6 id="returns-15">Returns</h6>
979
1017
  <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#ABB2BF">(): </span><span style="color:#E5C07B">void</span><span style="color:#ABB2BF">;</span></span></code></pre>
980
1018
  <h6 id="returns-16">Returns</h6>
@@ -1180,7 +1218,8 @@ paths to data. Future services will add their own keys.</p>
1180
1218
  <p><a id="withauth-2"></a></p>
1181
1219
  <h5 id="withauth-1">withAuth()</h5>
1182
1220
  <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#61AFEF">withAuth</span><span style="color:#ABB2BF">(</span><span style="color:#E06C75">auth</span><span style="color:#ABB2BF">: {</span></span>
1183
- <span class="line"><span style="color:#ABB2BF"> token?: </span><span style="color:#E06C75">Record</span><span style="color:#56B6C2">&#x3C;</span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">, unknown>;</span></span>
1221
+ <span class="line"><span style="color:#ABB2BF"> tenant?: </span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">;</span></span>
1222
+ <span class="line"><span style="color:#E06C75"> token</span><span style="color:#C678DD">?:</span><span style="color:#E06C75"> Record</span><span style="color:#56B6C2">&#x3C;</span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">, unknown>;</span></span>
1184
1223
  <span class="line"><span style="color:#E06C75"> uid</span><span style="color:#ABB2BF">: </span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">;</span></span>
1185
1224
  <span class="line"><span style="color:#ABB2BF">}): </span><span style="color:#E06C75">SandboxContext</span><span style="color:#ABB2BF">;</span></span></code></pre>
1186
1225
  <p>Derive a context bound to this sandbox under the given auth
@@ -1213,7 +1252,11 @@ unambiguous.</p>
1213
1252
 
1214
1253
 
1215
1254
 
1216
- <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>auth</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr></tbody></table></div>
1255
+
1256
+
1257
+
1258
+
1259
+ <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>auth</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr></tbody></table></div>
1217
1260
  <h6 id="returns-25">Returns</h6>
1218
1261
  <p><a href="/docs/pyric-firestore-reference-api/#sandboxcontext"><code>SandboxContext</code></a></p>
1219
1262
  <h6 id="example-1">Example</h6>
@@ -1329,7 +1372,12 @@ as a user, while an app or agent may use an admin lens.</p>
1329
1372
 
1330
1373
 
1331
1374
 
1332
- <table><thead><tr><th align="left">Property</th><th align="left">Modifier</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><a id="at-1"></a> <code>at</code></td><td align="left"><code>readonly</code></td><td align="left"><code>number</code></td></tr><tr><td align="left"><a id="auth-4"></a> <code>auth</code></td><td align="left"><code>readonly</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>public</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="context"></a> <code>context</code></td><td align="left"><code>readonly</code></td><td align="left"><a href="#operationcontext-2"><code>OperationContext</code></a></td></tr><tr><td align="left"><a id="eventkind"></a> <code>eventKind</code></td><td align="left"><code>readonly</code></td><td align="left"><code>"request"</code> | <code>"listener"</code> | <code>"operation"</code></td></tr><tr><td align="left"><a id="id-1"></a> <code>id</code></td><td align="left"><code>readonly</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="method"></a> <code>method</code></td><td align="left"><code>readonly</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="path"></a> <code>path?</code></td><td align="left"><code>readonly</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="result"></a> <code>result?</code></td><td align="left"><code>readonly</code></td><td align="left"><code>"unsupported"</code> | <code>"error"</code> | <code>"allow"</code> | <code>"deny"</code> | <code>"not-applicable"</code></td></tr><tr><td align="left"><a id="rules-1"></a> <code>rules</code></td><td align="left"><code>readonly</code></td><td align="left"><a href="#rulesdisposition-3"><code>RulesDisposition</code></a></td></tr><tr><td align="left"><a id="service-1"></a> <code>service</code></td><td align="left"><code>readonly</code></td><td align="left"><a href="#eventservice"><code>EventService</code></a></td></tr></tbody></table></div>
1375
+
1376
+
1377
+
1378
+
1379
+
1380
+ <table><thead><tr><th align="left">Property</th><th align="left">Modifier</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><a id="at-1"></a> <code>at</code></td><td align="left"><code>readonly</code></td><td align="left"><code>number</code></td></tr><tr><td align="left"><a id="auth-4"></a> <code>auth</code></td><td align="left"><code>readonly</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>public</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="context"></a> <code>context</code></td><td align="left"><code>readonly</code></td><td align="left"><a href="#operationcontext-2"><code>OperationContext</code></a></td></tr><tr><td align="left"><a id="eventkind"></a> <code>eventKind</code></td><td align="left"><code>readonly</code></td><td align="left"><code>"request"</code> | <code>"listener"</code> | <code>"operation"</code></td></tr><tr><td align="left"><a id="id-1"></a> <code>id</code></td><td align="left"><code>readonly</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="method"></a> <code>method</code></td><td align="left"><code>readonly</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="path"></a> <code>path?</code></td><td align="left"><code>readonly</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="result"></a> <code>result?</code></td><td align="left"><code>readonly</code></td><td align="left"><code>"allow"</code> | <code>"deny"</code> | <code>"unsupported"</code> | <code>"error"</code> | <code>"not-applicable"</code></td></tr><tr><td align="left"><a id="rules-1"></a> <code>rules</code></td><td align="left"><code>readonly</code></td><td align="left"><a href="#rulesdisposition-3"><code>RulesDisposition</code></a></td></tr><tr><td align="left"><a id="service-1"></a> <code>service</code></td><td align="left"><code>readonly</code></td><td align="left"><a href="#eventservice"><code>EventService</code></a></td></tr></tbody></table></div>
1333
1381
  <hr>
1334
1382
  <p><a id="persistableservice"></a></p>
1335
1383
  <h3 id="persistableservice">PersistableService</h3>
@@ -1685,7 +1733,13 @@ dispatch on <a href="#isremotesandbox">isRemoteSandbox</a> and use <a href="#cha
1685
1733
 
1686
1734
 
1687
1735
 
1688
- <table><thead><tr><th align="left">Property</th><th align="left">Modifier</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="remote_sandbox"></a> <code>[REMOTE_SANDBOX]</code></td><td align="left"><code>readonly</code></td><td align="left"><code>true</code></td><td align="left">-</td></tr><tr><td align="left"><a id="admin-1"></a> <code>admin</code></td><td align="left"><code>readonly</code></td><td align="left"><code>SandboxAdmin</code></td><td align="left">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.</td></tr><tr><td align="left"><a id="channel"></a> <code>channel</code></td><td align="left"><code>readonly</code></td><td align="left"><a href="#remotesandboxchannel-1"><code>RemoteSandboxChannel</code></a></td><td align="left">The raw worker op/sub relay channel.</td></tr><tr><td align="left"><a id="currentuser-1"></a> <code>currentUser</code></td><td align="left"><code>public</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">Current authenticated user across the sandbox. Mutated by <code>pyric/auth</code>’s <code>signInAnonymously</code> / <code>signInWithEmailAndPassword</code> / <code>signOut</code> / <code>sandbox.setUser</code>. Read per-call by service factories (e.g. a future <code>getFirestore(sandbox)</code> overload) so they see auth state changes without re-binding handles. Defaults to <code>null</code> (anonymous / signed out). <strong>Independent of <code>withAuth({uid})</code></strong> — <code>withAuth</code> still produces a frozen <a href="/docs/pyric-firestore-reference-api/#sandboxcontext">SandboxContext</a> that carries its own identity for the runner’s test code (the existing pattern: explicit identity per service call). <code>currentUser</code> exists for the <code>pyric/auth</code> mirror, where consumer app code drives identity through a stateful <code>Auth</code> handle rather than naming it per call.</td></tr><tr><td align="left"><code>currentUser.token?</code></td><td align="left"><code>public</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>currentUser.uid</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="serveurl"></a> <code>serveUrl</code></td><td align="left"><code>readonly</code></td><td align="left"><code>string</code></td><td align="left">Base URL of the <code>pyric dev</code> this handle is attached to (used in error guidance: “open <serveurl> in a browser and retry”).</serveurl></td></tr></tbody></table></div>
1736
+
1737
+
1738
+
1739
+
1740
+
1741
+
1742
+ <table><thead><tr><th align="left">Property</th><th align="left">Modifier</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="remote_sandbox"></a> <code>[REMOTE_SANDBOX]</code></td><td align="left"><code>readonly</code></td><td align="left"><code>true</code></td><td align="left">-</td></tr><tr><td align="left"><a id="admin-1"></a> <code>admin</code></td><td align="left"><code>readonly</code></td><td align="left"><code>SandboxAdmin</code></td><td align="left">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.</td></tr><tr><td align="left"><a id="channel"></a> <code>channel</code></td><td align="left"><code>readonly</code></td><td align="left"><a href="#remotesandboxchannel-1"><code>RemoteSandboxChannel</code></a></td><td align="left">The raw worker op/sub relay channel.</td></tr><tr><td align="left"><a id="currentuser-1"></a> <code>currentUser</code></td><td align="left"><code>public</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">Current authenticated user across the sandbox. Mutated by <code>pyric/auth</code>’s <code>signInAnonymously</code> / <code>signInWithEmailAndPassword</code> / <code>signOut</code> / <code>sandbox.setUser</code>. Read per-call by service factories (e.g. a future <code>getFirestore(sandbox)</code> overload) so they see auth state changes without re-binding handles. Defaults to <code>null</code> (anonymous / signed out). <strong>Independent of <code>withAuth({uid})</code></strong> — <code>withAuth</code> still produces a frozen <a href="/docs/pyric-firestore-reference-api/#sandboxcontext">SandboxContext</a> that carries its own identity for the runner’s test code (the existing pattern: explicit identity per service call). <code>currentUser</code> exists for the <code>pyric/auth</code> mirror, where consumer app code drives identity through a stateful <code>Auth</code> handle rather than naming it per call.</td></tr><tr><td align="left"><code>currentUser.tenant?</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>currentUser.token?</code></td><td align="left"><code>public</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>currentUser.uid</code></td><td align="left"><code>public</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="serveurl"></a> <code>serveUrl</code></td><td align="left"><code>readonly</code></td><td align="left"><code>string</code></td><td align="left">Base URL of the <code>pyric sandbox</code> this handle is attached to (used in error guidance: “open <serveurl> in a browser and retry”).</serveurl></td></tr></tbody></table></div>
1689
1743
  <h4 id="methods-6">Methods</h4>
1690
1744
  <p><a id="clearpersistence-2"></a></p>
1691
1745
  <h5 id="clearpersistence-1">clearPersistence()</h5>
@@ -1863,6 +1917,7 @@ a service this one lacks).</p>
1863
1917
  <p><a id="oncurrentuserchanged-2"></a></p>
1864
1918
  <h5 id="oncurrentuserchanged-1">onCurrentUserChanged()</h5>
1865
1919
  <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#61AFEF">onCurrentUserChanged</span><span style="color:#ABB2BF">(</span><span style="color:#E06C75">cb</span><span style="color:#ABB2BF">: (</span><span style="color:#E06C75;font-style:italic">user</span><span style="color:#ABB2BF">: {</span></span>
1920
+ <span class="line"><span style="color:#E06C75"> tenant</span><span style="color:#C678DD">?</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">string</span><span style="color:#ABB2BF">;</span></span>
1866
1921
  <span class="line"><span style="color:#E06C75"> token</span><span style="color:#C678DD">?</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">Record</span><span style="color:#ABB2BF">&#x3C;</span><span style="color:#E5C07B">string</span><span style="color:#ABB2BF">, </span><span style="color:#E5C07B">unknown</span><span style="color:#ABB2BF">>;</span></span>
1867
1922
  <span class="line"><span style="color:#E06C75"> uid</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">string</span><span style="color:#ABB2BF">;</span></span>
1868
1923
  <span class="line"><span style="color:#ABB2BF">}) </span><span style="color:#C678DD">=></span><span style="color:#C678DD"> void</span><span style="color:#ABB2BF">): () </span><span style="color:#C678DD">=></span><span style="color:#C678DD"> void</span><span style="color:#ABB2BF">;</span></span></code></pre>
@@ -1889,7 +1944,7 @@ their errors.</p>
1889
1944
 
1890
1945
 
1891
1946
 
1892
- <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>cb</code></td><td align="left">(<code>user</code>: { <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }) => <code>void</code></td></tr></tbody></table></div>
1947
+ <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>cb</code></td><td align="left">(<code>user</code>: { <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }) => <code>void</code></td></tr></tbody></table></div>
1893
1948
  <h6 id="returns-46">Returns</h6>
1894
1949
  <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#ABB2BF">(): </span><span style="color:#E5C07B">void</span><span style="color:#ABB2BF">;</span></span></code></pre>
1895
1950
  <h6 id="returns-47">Returns</h6>
@@ -2095,7 +2150,8 @@ paths to data. Future services will add their own keys.</p>
2095
2150
  <p><a id="withauth-4"></a></p>
2096
2151
  <h5 id="withauth-2">withAuth()</h5>
2097
2152
  <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#61AFEF">withAuth</span><span style="color:#ABB2BF">(</span><span style="color:#E06C75">auth</span><span style="color:#ABB2BF">: {</span></span>
2098
- <span class="line"><span style="color:#ABB2BF"> token?: </span><span style="color:#E06C75">Record</span><span style="color:#56B6C2">&#x3C;</span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">, unknown>;</span></span>
2153
+ <span class="line"><span style="color:#ABB2BF"> tenant?: </span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">;</span></span>
2154
+ <span class="line"><span style="color:#E06C75"> token</span><span style="color:#C678DD">?:</span><span style="color:#E06C75"> Record</span><span style="color:#56B6C2">&#x3C;</span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">, unknown>;</span></span>
2099
2155
  <span class="line"><span style="color:#E06C75"> uid</span><span style="color:#ABB2BF">: </span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">;</span></span>
2100
2156
  <span class="line"><span style="color:#ABB2BF">}): </span><span style="color:#E06C75">SandboxContext</span><span style="color:#ABB2BF">;</span></span></code></pre>
2101
2157
  <p>Derive a context bound to this sandbox under the given auth
@@ -2128,7 +2184,11 @@ unambiguous.</p>
2128
2184
 
2129
2185
 
2130
2186
 
2131
- <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>auth</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr></tbody></table></div>
2187
+
2188
+
2189
+
2190
+
2191
+ <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>auth</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr></tbody></table></div>
2132
2192
  <h6 id="returns-56">Returns</h6>
2133
2193
  <p><a href="/docs/pyric-firestore-reference-api/#sandboxcontext"><code>SandboxContext</code></a></p>
2134
2194
  <h6 id="example-3">Example</h6>
@@ -2236,7 +2296,7 @@ Returns the unsubscribe function.</p>
2236
2296
 
2237
2297
 
2238
2298
 
2239
- <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="url"></a> <code>url?</code></td><td align="left"><code>string</code></td><td align="left">Explicit <code>pyric dev</code> base URL (from <code>PYRIC_SANDBOX=remote:&#x3C;url></code>). When omitted the factory discovers the running host itself (the <code>.pyric/serve.json</code> locator protocol).</td></tr></tbody></table></div>
2299
+ <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="url"></a> <code>url?</code></td><td align="left"><code>string</code></td><td align="left">Explicit <code>pyric sandbox</code> base URL (from <code>PYRIC_SANDBOX=remote:&#x3C;url></code>). When omitted the factory discovers the running host itself (the <code>.pyric/serve.json</code> locator protocol).</td></tr></tbody></table></div>
2240
2300
  <hr>
2241
2301
  <p><a id="replayoptions"></a></p>
2242
2302
  <h3 id="replayoptions">ReplayOptions</h3>
@@ -2480,7 +2540,12 @@ subscriber can’t change rule semantics or hide other events.</p>
2480
2540
 
2481
2541
 
2482
2542
 
2483
- <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="at-2"></a> <code>at</code></td><td align="left"><code>number</code></td><td align="left">Wall-clock at op start, ms since epoch.</td></tr><tr><td align="left"><a id="auth-5"></a> <code>auth</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="detail"></a> <code>detail?</code></td><td align="left">{ <code>admin?</code>: <code>boolean</code>; } &#x26; <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">Free-form operation metadata. <code>admin: true</code> marks a rules-bypassing setup/admin operation so fixture tooling can exclude it from protected behavior while still preserving it as replay context.</td></tr><tr><td align="left"><a id="evalms"></a> <code>evalMs</code></td><td align="left"><code>number</code></td><td align="left">Wall-clock duration of the simulator.simulate(…) call, in ms.</td></tr><tr><td align="left"><a id="evaluatedrule"></a> <code>evaluatedRule?</code></td><td align="left"><a href="/docs/pyric-rules-reference-api/#evaluatedruleinfo"><code>EvaluatedRuleInfo</code></a></td><td align="left">The DECIDING rule’s verdict + 1-indexed source line + full sub-expression trace, projected from the simulator’s structured <code>RuleEvaluation</code> (additive: present on `result: ‘allow'</td></tr><tr><td align="left"><a id="groupid"></a> <code>groupId?</code></td><td align="left"><code>string</code></td><td align="left">Shared across ops in one batch or transaction. Opaque to consumers.</td></tr><tr><td align="left"><a id="groupkind-1"></a> <code>groupKind?</code></td><td align="left"><code>"transaction"</code> | <code>"batch"</code></td><td align="left">Disambiguates `origin: ‘transaction'</td></tr><tr><td align="left"><a id="id-2"></a> <code>id</code></td><td align="left"><code>string</code></td><td align="left">Unique within a sandbox process. Useful for React list keys.</td></tr><tr><td align="left"><a id="kind-1"></a> <code>kind</code></td><td align="left"><code>"request"</code></td><td align="left">Discriminator.</td></tr><tr><td align="left"><a id="matchedrule"></a> <code>matchedRule?</code></td><td align="left">{ <code>operations</code>: <code>string</code>[]; <code>ruleIndex</code>: <code>number</code>; }</td><td align="left">Parsed from the simulator’s “Rule #N → …” debug line. Absent when no rule matched (e.g. no allow rules at the path — implicit deny).</td></tr><tr><td align="left"><code>matchedRule.operations</code></td><td align="left"><code>string</code>[]</td><td align="left">-</td></tr><tr><td align="left"><code>matchedRule.ruleIndex</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="method-1"></a> <code>method</code></td><td align="left"><code>"delete"</code> | <code>"get"</code> | <code>"list"</code> | <code>"create"</code> | <code>"update"</code> | <code>"set"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="origin"></a> <code>origin</code></td><td align="left"><code>"user"</code> | <code>"transaction"</code> | <code>"listener"</code> | <code>"batch"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="path-1"></a> <code>path</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="reasons-2"></a> <code>reasons</code></td><td align="left"><code>string</code>[]</td><td align="left">Simulator debug messages — the per-rule trace (<code>Rule #0 (read) → ALLOW</code>). Same shape as <code>DenialEvent.reasons</code> so consumer code can share rendering.</td></tr><tr><td align="left"><a id="request-2"></a> <code>request?</code></td><td align="left">{ <code>resourceData?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; }</td><td align="left">Proposed write payload, for create/update/set. Absent on reads + delete. Pre-resolution: <code>FieldValue.*</code> sentinels are preserved as their marker shapes (<code>{ __type: 'serverTimestamp' }</code>, etc.) so the replay engine can re-resolve them. The rule engine evaluated against the resolved form internally; that resolved form lives on <a href="#nextstate-1">WriteSandboxEvent.nextState</a>, not here.</td></tr><tr><td align="left"><code>request.resourceData?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><a id="resourceafter"></a> <code>resourceAfter?</code></td><td align="left">{ <code>data</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>exists</code>: <code>boolean</code>; }</td><td align="left">Projected document state after the write. Absent on reads.</td></tr><tr><td align="left"><code>resourceAfter.data</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>resourceAfter.exists</code></td><td align="left"><code>boolean</code></td><td align="left">-</td></tr><tr><td align="left"><a id="resourcebefore"></a> <code>resourceBefore?</code></td><td align="left">{ <code>data</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>exists</code>: <code>boolean</code>; }</td><td align="left">Existing document state before the write (or read target for get).</td></tr><tr><td align="left"><code>resourceBefore.data</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>resourceBefore.exists</code></td><td align="left"><code>boolean</code></td><td align="left">-</td></tr><tr><td align="left"><a id="result-1"></a> <code>result</code></td><td align="left"><code>"unsupported"</code> | <code>"allow"</code> | <code>"deny"</code></td><td align="left"><code>'unsupported'</code> fires when the simulator hit an unmodelled feature and the sandbox upgraded it (today: thrown as SimulatorUnsupportedError, surfaced here as a discrete result so the panel can show it distinctly from a real denial).</td></tr><tr><td align="left"><a id="rulesdisposition"></a> <code>rulesDisposition?</code></td><td align="left"><a href="#rulesdisposition-3"><code>RulesDisposition</code></a></td><td align="left">Canonical statement of whether Security Rules evaluated this request. Added by the sandbox event recorder when an older emitter omits it.</td></tr><tr><td align="left"><a id="triggeredby"></a> <code>triggeredBy?</code></td><td align="left">{ <code>method</code>: <code>string</code>; <code>path</code>: <code>string</code>; }</td><td align="left">For listener re-evals: the originating user op that triggered this re-evaluation. Absent on the initial-snapshot fire.</td></tr><tr><td align="left"><code>triggeredBy.method</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>triggeredBy.path</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr></tbody></table></div>
2543
+
2544
+
2545
+
2546
+
2547
+
2548
+ <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="at-2"></a> <code>at</code></td><td align="left"><code>number</code></td><td align="left">Wall-clock at op start, ms since epoch.</td></tr><tr><td align="left"><a id="auth-5"></a> <code>auth</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="detail"></a> <code>detail?</code></td><td align="left">{ <code>admin?</code>: <code>boolean</code>; } &#x26; <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">Free-form operation metadata. <code>admin: true</code> marks a rules-bypassing setup/admin operation so fixture tooling can exclude it from protected behavior while still preserving it as replay context.</td></tr><tr><td align="left"><a id="evalms"></a> <code>evalMs</code></td><td align="left"><code>number</code></td><td align="left">Wall-clock duration of the simulator.simulate(…) call, in ms.</td></tr><tr><td align="left"><a id="evaluatedrule"></a> <code>evaluatedRule?</code></td><td align="left"><a href="/docs/pyric-rules-reference-api/#evaluatedruleinfo"><code>EvaluatedRuleInfo</code></a></td><td align="left">The DECIDING rule’s verdict + 1-indexed source line + full sub-expression trace, projected from the simulator’s structured <code>RuleEvaluation</code> (additive: present on `result: ‘allow'</td></tr><tr><td align="left"><a id="groupid"></a> <code>groupId?</code></td><td align="left"><code>string</code></td><td align="left">Shared across ops in one batch or transaction. Opaque to consumers.</td></tr><tr><td align="left"><a id="groupkind-1"></a> <code>groupKind?</code></td><td align="left"><code>"transaction"</code> | <code>"batch"</code></td><td align="left">Disambiguates `origin: ‘transaction'</td></tr><tr><td align="left"><a id="id-2"></a> <code>id</code></td><td align="left"><code>string</code></td><td align="left">Unique within a sandbox process. Useful for React list keys.</td></tr><tr><td align="left"><a id="kind-1"></a> <code>kind</code></td><td align="left"><code>"request"</code></td><td align="left">Discriminator.</td></tr><tr><td align="left"><a id="matchedrule"></a> <code>matchedRule?</code></td><td align="left">{ <code>operations</code>: <code>string</code>[]; <code>ruleIndex</code>: <code>number</code>; }</td><td align="left">Parsed from the simulator’s “Rule #N → …” debug line. Absent when no rule matched (e.g. no allow rules at the path — implicit deny).</td></tr><tr><td align="left"><code>matchedRule.operations</code></td><td align="left"><code>string</code>[]</td><td align="left">-</td></tr><tr><td align="left"><code>matchedRule.ruleIndex</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="method-1"></a> <code>method</code></td><td align="left"><code>"delete"</code> | <code>"get"</code> | <code>"list"</code> | <code>"create"</code> | <code>"update"</code> | <code>"set"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="origin"></a> <code>origin</code></td><td align="left"><code>"user"</code> | <code>"transaction"</code> | <code>"listener"</code> | <code>"batch"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="path-1"></a> <code>path</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="reasons-2"></a> <code>reasons</code></td><td align="left"><code>string</code>[]</td><td align="left">Simulator debug messages — the per-rule trace (<code>Rule #0 (read) → ALLOW</code>). Same shape as <code>DenialEvent.reasons</code> so consumer code can share rendering.</td></tr><tr><td align="left"><a id="request-2"></a> <code>request?</code></td><td align="left">{ <code>resourceData?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; }</td><td align="left">Proposed write payload, for create/update/set. Absent on reads + delete. Pre-resolution: <code>FieldValue.*</code> sentinels are preserved as their marker shapes (<code>{ __type: 'serverTimestamp' }</code>, etc.) so the replay engine can re-resolve them. The rule engine evaluated against the resolved form internally; that resolved form lives on <a href="#nextstate-1">WriteSandboxEvent.nextState</a>, not here.</td></tr><tr><td align="left"><code>request.resourceData?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><a id="resourceafter"></a> <code>resourceAfter?</code></td><td align="left">{ <code>data</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>exists</code>: <code>boolean</code>; }</td><td align="left">Projected document state after the write. Absent on reads.</td></tr><tr><td align="left"><code>resourceAfter.data</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>resourceAfter.exists</code></td><td align="left"><code>boolean</code></td><td align="left">-</td></tr><tr><td align="left"><a id="resourcebefore"></a> <code>resourceBefore?</code></td><td align="left">{ <code>data</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>exists</code>: <code>boolean</code>; }</td><td align="left">Existing document state before the write (or read target for get).</td></tr><tr><td align="left"><code>resourceBefore.data</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>resourceBefore.exists</code></td><td align="left"><code>boolean</code></td><td align="left">-</td></tr><tr><td align="left"><a id="result-1"></a> <code>result</code></td><td align="left"><code>"allow"</code> | <code>"deny"</code> | <code>"unsupported"</code></td><td align="left"><code>'unsupported'</code> fires when the simulator hit an unmodelled feature and the sandbox upgraded it (today: thrown as SimulatorUnsupportedError, surfaced here as a discrete result so the panel can show it distinctly from a real denial).</td></tr><tr><td align="left"><a id="rulesdisposition"></a> <code>rulesDisposition?</code></td><td align="left"><a href="#rulesdisposition-3"><code>RulesDisposition</code></a></td><td align="left">Canonical statement of whether Security Rules evaluated this request. Added by the sandbox event recorder when an older emitter omits it.</td></tr><tr><td align="left"><a id="triggeredby"></a> <code>triggeredBy?</code></td><td align="left">{ <code>method</code>: <code>string</code>; <code>path</code>: <code>string</code>; }</td><td align="left">For listener re-evals: the originating user op that triggered this re-evaluation. Absent on the initial-snapshot fire.</td></tr><tr><td align="left"><code>triggeredBy.method</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>triggeredBy.path</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr></tbody></table></div>
2484
2549
  <hr>
2485
2550
  <p><a id="sandboxcommitevent"></a></p>
2486
2551
  <h3 id="sandboxcommitevent">SandboxCommitEvent</h3>
@@ -2573,7 +2638,11 @@ these service adapters instead of filtering Firestore-only <code>write</code> ev
2573
2638
 
2574
2639
 
2575
2640
 
2576
- <table><thead><tr><th align="left">Property</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><a id="at-3"></a> <code>at</code></td><td align="left"><code>number</code></td></tr><tr><td align="left"><a id="auth-6"></a> <code>auth</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="data"></a> <code>data?</code></td><td align="left"><code>unknown</code></td></tr><tr><td align="left"><a id="detail-1"></a> <code>detail?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><a id="groupid-1"></a> <code>groupId?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="groupkind-2"></a> <code>groupKind?</code></td><td align="left"><code>"transaction"</code> | <code>"batch"</code></td></tr><tr><td align="left"><a id="id-3"></a> <code>id</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="kind-2"></a> <code>kind</code></td><td align="left"><code>"commit"</code></td></tr><tr><td align="left"><a id="method-2"></a> <code>method</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="nextstate"></a> <code>nextState?</code></td><td align="left"><code>unknown</code></td></tr><tr><td align="left"><a id="path-2"></a> <code>path?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="priorstate"></a> <code>priorState?</code></td><td align="left"><code>unknown</code></td></tr><tr><td align="left"><a id="replay"></a> <code>replay?</code></td><td align="left">{ <code>autoId?</code>: <code>string</code>; <code>requestTime?</code>: <code>number</code>; <code>sentinels?</code>: { <code>field</code>: <code>string</code>; <code>kind</code>: <code>string</code>; }[]; }</td></tr><tr><td align="left"><code>replay.autoId?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>replay.requestTime?</code></td><td align="left"><code>number</code></td></tr><tr><td align="left"><code>replay.sentinels?</code></td><td align="left">{ <code>field</code>: <code>string</code>; <code>kind</code>: <code>string</code>; }[]</td></tr><tr><td align="left"><a id="service-2"></a> <code>service</code></td><td align="left"><a href="#eventservice"><code>EventService</code></a></td></tr></tbody></table></div>
2641
+
2642
+
2643
+
2644
+
2645
+ <table><thead><tr><th align="left">Property</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><a id="at-3"></a> <code>at</code></td><td align="left"><code>number</code></td></tr><tr><td align="left"><a id="auth-6"></a> <code>auth</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="data"></a> <code>data?</code></td><td align="left"><code>unknown</code></td></tr><tr><td align="left"><a id="detail-1"></a> <code>detail?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><a id="groupid-1"></a> <code>groupId?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="groupkind-2"></a> <code>groupKind?</code></td><td align="left"><code>"transaction"</code> | <code>"batch"</code></td></tr><tr><td align="left"><a id="id-3"></a> <code>id</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="kind-2"></a> <code>kind</code></td><td align="left"><code>"commit"</code></td></tr><tr><td align="left"><a id="method-2"></a> <code>method</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="nextstate"></a> <code>nextState?</code></td><td align="left"><code>unknown</code></td></tr><tr><td align="left"><a id="path-2"></a> <code>path?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="priorstate"></a> <code>priorState?</code></td><td align="left"><code>unknown</code></td></tr><tr><td align="left"><a id="replay"></a> <code>replay?</code></td><td align="left">{ <code>autoId?</code>: <code>string</code>; <code>requestTime?</code>: <code>number</code>; <code>sentinels?</code>: { <code>field</code>: <code>string</code>; <code>kind</code>: <code>string</code>; }[]; }</td></tr><tr><td align="left"><code>replay.autoId?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>replay.requestTime?</code></td><td align="left"><code>number</code></td></tr><tr><td align="left"><code>replay.sentinels?</code></td><td align="left">{ <code>field</code>: <code>string</code>; <code>kind</code>: <code>string</code>; }[]</td></tr><tr><td align="left"><a id="service-2"></a> <code>service</code></td><td align="left"><a href="#eventservice"><code>EventService</code></a></td></tr></tbody></table></div>
2577
2646
  <hr>
2578
2647
  <p><a id="sandboxconfig"></a></p>
2579
2648
  <h3 id="sandboxconfig">SandboxConfig</h3>
@@ -2741,7 +2810,11 @@ service listeners the same debuggable surface.</p>
2741
2810
 
2742
2811
 
2743
2812
 
2744
- <table><thead><tr><th align="left">Property</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><a id="at-4"></a> <code>at</code></td><td align="left"><code>number</code></td></tr><tr><td align="left"><a id="auth-7"></a> <code>auth</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="detail-2"></a> <code>detail?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><a id="error-1"></a> <code>error?</code></td><td align="left">{ <code>code?</code>: <code>string</code>; <code>message</code>: <code>string</code>; <code>reasons?</code>: <code>string</code>[]; }</td></tr><tr><td align="left"><code>error.code?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>error.message</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>error.reasons?</code></td><td align="left"><code>string</code>[]</td></tr><tr><td align="left"><a id="id-4"></a> <code>id</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="kind-3"></a> <code>kind</code></td><td align="left"><code>"listener"</code></td></tr><tr><td align="left"><a id="listenerid-2"></a> <code>listenerId</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="phase"></a> <code>phase</code></td><td align="left"><code>"attach"</code> | <code>"detach"</code> | <code>"delivery"</code> | <code>"suppressed"</code> | <code>"errored"</code></td></tr><tr><td align="left"><a id="reason"></a> <code>reason?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="reasons-3"></a> <code>reasons?</code></td><td align="left"><code>string</code>[]</td></tr><tr><td align="left"><a id="result-2"></a> <code>result?</code></td><td align="left"><code>"unsupported"</code> | <code>"error"</code> | <code>"allow"</code> | <code>"deny"</code></td></tr><tr><td align="left"><a id="rules-2"></a> <code>rules?</code></td><td align="left">{ <code>engine</code>: <code>"firestore"</code> | <code>"rtdb"</code> | <code>"storage"</code>; <code>errorCode?</code>: <code>string</code>; <code>matchedPath?</code>: <code>string</code>; <code>matchedRule?</code>: <code>string</code>; <code>operations?</code>: <code>string</code>[]; <code>pathVariableBindings?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>string</code>>; <code>reason?</code>: <code>string</code>; <code>ruleIndex?</code>: <code>number</code>; }</td></tr><tr><td align="left"><code>rules.engine</code></td><td align="left"><code>"firestore"</code> | <code>"rtdb"</code> | <code>"storage"</code></td></tr><tr><td align="left"><code>rules.errorCode?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>rules.matchedPath?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>rules.matchedRule?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>rules.operations?</code></td><td align="left"><code>string</code>[]</td></tr><tr><td align="left"><code>rules.pathVariableBindings?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>string</code>></td></tr><tr><td align="left"><code>rules.reason?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>rules.ruleIndex?</code></td><td align="left"><code>number</code></td></tr><tr><td align="left"><a id="rulesdisposition-1"></a> <code>rulesDisposition?</code></td><td align="left"><a href="#rulesdisposition-3"><code>RulesDisposition</code></a></td></tr><tr><td align="left"><a id="sample"></a> <code>sample?</code></td><td align="left"><code>unknown</code></td></tr><tr><td align="left"><a id="service-3"></a> <code>service</code></td><td align="left"><a href="#eventservice"><code>EventService</code></a></td></tr><tr><td align="left"><a id="size"></a> <code>size?</code></td><td align="left"><code>number</code></td></tr><tr><td align="left"><a id="target-1"></a> <code>target</code></td><td align="left">{ <code>kind</code>: <code>string</code>; <code>path?</code>: <code>string</code>; <code>query?</code>: <code>unknown</code>; }</td></tr><tr><td align="left"><code>target.kind</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>target.path?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>target.query?</code></td><td align="left"><code>unknown</code></td></tr><tr><td align="left"><a id="triggeredby-1"></a> <code>triggeredBy?</code></td><td align="left">{ <code>method</code>: <code>string</code>; <code>path?</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>triggeredBy.method</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>triggeredBy.path?</code></td><td align="left"><code>string</code></td></tr></tbody></table></div>
2813
+
2814
+
2815
+
2816
+
2817
+ <table><thead><tr><th align="left">Property</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><a id="at-4"></a> <code>at</code></td><td align="left"><code>number</code></td></tr><tr><td align="left"><a id="auth-7"></a> <code>auth</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="detail-2"></a> <code>detail?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><a id="error-1"></a> <code>error?</code></td><td align="left">{ <code>code?</code>: <code>string</code>; <code>message</code>: <code>string</code>; <code>reasons?</code>: <code>string</code>[]; }</td></tr><tr><td align="left"><code>error.code?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>error.message</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>error.reasons?</code></td><td align="left"><code>string</code>[]</td></tr><tr><td align="left"><a id="id-4"></a> <code>id</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="kind-3"></a> <code>kind</code></td><td align="left"><code>"listener"</code></td></tr><tr><td align="left"><a id="listenerid-2"></a> <code>listenerId</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="phase"></a> <code>phase</code></td><td align="left"><code>"attach"</code> | <code>"detach"</code> | <code>"delivery"</code> | <code>"suppressed"</code> | <code>"errored"</code></td></tr><tr><td align="left"><a id="reason"></a> <code>reason?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="reasons-3"></a> <code>reasons?</code></td><td align="left"><code>string</code>[]</td></tr><tr><td align="left"><a id="result-2"></a> <code>result?</code></td><td align="left"><code>"allow"</code> | <code>"deny"</code> | <code>"unsupported"</code> | <code>"error"</code></td></tr><tr><td align="left"><a id="rules-2"></a> <code>rules?</code></td><td align="left">{ <code>engine</code>: <code>"firestore"</code> | <code>"rtdb"</code> | <code>"storage"</code>; <code>errorCode?</code>: <code>string</code>; <code>matchedPath?</code>: <code>string</code>; <code>matchedRule?</code>: <code>string</code>; <code>operations?</code>: <code>string</code>[]; <code>pathVariableBindings?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>string</code>>; <code>reason?</code>: <code>string</code>; <code>ruleIndex?</code>: <code>number</code>; }</td></tr><tr><td align="left"><code>rules.engine</code></td><td align="left"><code>"firestore"</code> | <code>"rtdb"</code> | <code>"storage"</code></td></tr><tr><td align="left"><code>rules.errorCode?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>rules.matchedPath?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>rules.matchedRule?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>rules.operations?</code></td><td align="left"><code>string</code>[]</td></tr><tr><td align="left"><code>rules.pathVariableBindings?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>string</code>></td></tr><tr><td align="left"><code>rules.reason?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>rules.ruleIndex?</code></td><td align="left"><code>number</code></td></tr><tr><td align="left"><a id="rulesdisposition-1"></a> <code>rulesDisposition?</code></td><td align="left"><a href="#rulesdisposition-3"><code>RulesDisposition</code></a></td></tr><tr><td align="left"><a id="sample"></a> <code>sample?</code></td><td align="left"><code>unknown</code></td></tr><tr><td align="left"><a id="service-3"></a> <code>service</code></td><td align="left"><a href="#eventservice"><code>EventService</code></a></td></tr><tr><td align="left"><a id="size"></a> <code>size?</code></td><td align="left"><code>number</code></td></tr><tr><td align="left"><a id="target-1"></a> <code>target</code></td><td align="left">{ <code>kind</code>: <code>string</code>; <code>path?</code>: <code>string</code>; <code>query?</code>: <code>unknown</code>; }</td></tr><tr><td align="left"><code>target.kind</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>target.path?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>target.query?</code></td><td align="left"><code>unknown</code></td></tr><tr><td align="left"><a id="triggeredby-1"></a> <code>triggeredBy?</code></td><td align="left">{ <code>method</code>: <code>string</code>; <code>path?</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>triggeredBy.method</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>triggeredBy.path?</code></td><td align="left"><code>string</code></td></tr></tbody></table></div>
2745
2818
  <hr>
2746
2819
  <p><a id="sandboxoperationevent"></a></p>
2747
2820
  <h3 id="sandboxoperationevent">SandboxOperationEvent</h3>
@@ -2959,7 +3032,12 @@ their state is a Firestore document.</p>
2959
3032
 
2960
3033
 
2961
3034
 
2962
- <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="at-5"></a> <code>at</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="auth-8"></a> <code>auth</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="detail-3"></a> <code>detail?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><a id="durationms"></a> <code>durationMs?</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="groupid-2"></a> <code>groupId?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="groupkind-3"></a> <code>groupKind?</code></td><td align="left"><code>"transaction"</code> | <code>"batch"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="id-5"></a> <code>id</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="kind-4"></a> <code>kind</code></td><td align="left"><code>"operation"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="method-3"></a> <code>method</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="origin-1"></a> <code>origin</code></td><td align="left"><code>"admin"</code> | <code>"user"</code> | <code>"system"</code> | <code>"transaction"</code> | <code>"listener"</code> | <code>"batch"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="path-3"></a> <code>path?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="reasons-4"></a> <code>reasons?</code></td><td align="left"><code>string</code>[]</td><td align="left">-</td></tr><tr><td align="left"><a id="request-3"></a> <code>request?</code></td><td align="left">{ <code>data?</code>: <code>unknown</code>; <code>query?</code>: <code>unknown</code>; <code>resourceData?</code>: <code>unknown</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>request.data?</code></td><td align="left"><code>unknown</code></td><td align="left">-</td></tr><tr><td align="left"><code>request.query?</code></td><td align="left"><code>unknown</code></td><td align="left">-</td></tr><tr><td align="left"><code>request.resourceData?</code></td><td align="left"><code>unknown</code></td><td align="left">-</td></tr><tr><td align="left"><a id="resourceafter-1"></a> <code>resourceAfter?</code></td><td align="left">{ <code>data</code>: <code>unknown</code>; <code>exists</code>: <code>boolean</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>resourceAfter.data</code></td><td align="left"><code>unknown</code></td><td align="left">-</td></tr><tr><td align="left"><code>resourceAfter.exists</code></td><td align="left"><code>boolean</code></td><td align="left">-</td></tr><tr><td align="left"><a id="resourcebefore-1"></a> <code>resourceBefore?</code></td><td align="left">{ <code>data</code>: <code>unknown</code>; <code>exists</code>: <code>boolean</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>resourceBefore.data</code></td><td align="left"><code>unknown</code></td><td align="left">-</td></tr><tr><td align="left"><code>resourceBefore.exists</code></td><td align="left"><code>boolean</code></td><td align="left">-</td></tr><tr><td align="left"><a id="result-3"></a> <code>result</code></td><td align="left"><code>"unsupported"</code> | <code>"error"</code> | <code>"allow"</code> | <code>"deny"</code> | <code>"not-applicable"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="rules-3"></a> <code>rules?</code></td><td align="left">{ <code>engine</code>: <code>"firestore"</code> | <code>"rtdb"</code> | <code>"storage"</code>; <code>errorCode?</code>: <code>string</code>; <code>matchedPath?</code>: <code>string</code>; <code>matchedRule?</code>: <code>string</code>; <code>operations?</code>: <code>string</code>[]; <code>pathVariableBindings?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>string</code>>; <code>reason?</code>: <code>string</code>; <code>ruleIndex?</code>: <code>number</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>rules.engine</code></td><td align="left"><code>"firestore"</code> | <code>"rtdb"</code> | <code>"storage"</code></td><td align="left">-</td></tr><tr><td align="left"><code>rules.errorCode?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>rules.matchedPath?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>rules.matchedRule?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>rules.operations?</code></td><td align="left"><code>string</code>[]</td><td align="left">-</td></tr><tr><td align="left"><code>rules.pathVariableBindings?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>string</code>></td><td align="left">-</td></tr><tr><td align="left"><code>rules.reason?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>rules.ruleIndex?</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="rulesdisposition-2"></a> <code>rulesDisposition?</code></td><td align="left"><a href="#rulesdisposition-3"><code>RulesDisposition</code></a></td><td align="left">Canonical statement of whether Security Rules evaluated this operation. Service emitters may provide it directly; the recorder normalizes legacy operation shapes at the unified stream seam.</td></tr><tr><td align="left"><a id="service-4"></a> <code>service</code></td><td align="left"><a href="#eventservice"><code>EventService</code></a></td><td align="left">-</td></tr><tr><td align="left"><a id="triggeredby-2"></a> <code>triggeredBy?</code></td><td align="left">{ <code>method</code>: <code>string</code>; <code>path?</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>triggeredBy.method</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>triggeredBy.path?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr></tbody></table></div>
3035
+
3036
+
3037
+
3038
+
3039
+
3040
+ <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="at-5"></a> <code>at</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="auth-8"></a> <code>auth</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="detail-3"></a> <code>detail?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><a id="durationms"></a> <code>durationMs?</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="groupid-2"></a> <code>groupId?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="groupkind-3"></a> <code>groupKind?</code></td><td align="left"><code>"transaction"</code> | <code>"batch"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="id-5"></a> <code>id</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="kind-4"></a> <code>kind</code></td><td align="left"><code>"operation"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="method-3"></a> <code>method</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="origin-1"></a> <code>origin</code></td><td align="left"><code>"admin"</code> | <code>"user"</code> | <code>"system"</code> | <code>"transaction"</code> | <code>"listener"</code> | <code>"batch"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="path-3"></a> <code>path?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="reasons-4"></a> <code>reasons?</code></td><td align="left"><code>string</code>[]</td><td align="left">-</td></tr><tr><td align="left"><a id="request-3"></a> <code>request?</code></td><td align="left">{ <code>data?</code>: <code>unknown</code>; <code>query?</code>: <code>unknown</code>; <code>resourceData?</code>: <code>unknown</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>request.data?</code></td><td align="left"><code>unknown</code></td><td align="left">-</td></tr><tr><td align="left"><code>request.query?</code></td><td align="left"><code>unknown</code></td><td align="left">-</td></tr><tr><td align="left"><code>request.resourceData?</code></td><td align="left"><code>unknown</code></td><td align="left">-</td></tr><tr><td align="left"><a id="resourceafter-1"></a> <code>resourceAfter?</code></td><td align="left">{ <code>data</code>: <code>unknown</code>; <code>exists</code>: <code>boolean</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>resourceAfter.data</code></td><td align="left"><code>unknown</code></td><td align="left">-</td></tr><tr><td align="left"><code>resourceAfter.exists</code></td><td align="left"><code>boolean</code></td><td align="left">-</td></tr><tr><td align="left"><a id="resourcebefore-1"></a> <code>resourceBefore?</code></td><td align="left">{ <code>data</code>: <code>unknown</code>; <code>exists</code>: <code>boolean</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>resourceBefore.data</code></td><td align="left"><code>unknown</code></td><td align="left">-</td></tr><tr><td align="left"><code>resourceBefore.exists</code></td><td align="left"><code>boolean</code></td><td align="left">-</td></tr><tr><td align="left"><a id="result-3"></a> <code>result</code></td><td align="left"><code>"allow"</code> | <code>"deny"</code> | <code>"unsupported"</code> | <code>"error"</code> | <code>"not-applicable"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="rules-3"></a> <code>rules?</code></td><td align="left">{ <code>engine</code>: <code>"firestore"</code> | <code>"rtdb"</code> | <code>"storage"</code>; <code>errorCode?</code>: <code>string</code>; <code>matchedPath?</code>: <code>string</code>; <code>matchedRule?</code>: <code>string</code>; <code>operations?</code>: <code>string</code>[]; <code>pathVariableBindings?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>string</code>>; <code>reason?</code>: <code>string</code>; <code>ruleIndex?</code>: <code>number</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>rules.engine</code></td><td align="left"><code>"firestore"</code> | <code>"rtdb"</code> | <code>"storage"</code></td><td align="left">-</td></tr><tr><td align="left"><code>rules.errorCode?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>rules.matchedPath?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>rules.matchedRule?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>rules.operations?</code></td><td align="left"><code>string</code>[]</td><td align="left">-</td></tr><tr><td align="left"><code>rules.pathVariableBindings?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>string</code>></td><td align="left">-</td></tr><tr><td align="left"><code>rules.reason?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>rules.ruleIndex?</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="rulesdisposition-2"></a> <code>rulesDisposition?</code></td><td align="left"><a href="#rulesdisposition-3"><code>RulesDisposition</code></a></td><td align="left">Canonical statement of whether Security Rules evaluated this operation. Service emitters may provide it directly; the recorder normalizes legacy operation shapes at the unified stream seam.</td></tr><tr><td align="left"><a id="service-4"></a> <code>service</code></td><td align="left"><a href="#eventservice"><code>EventService</code></a></td><td align="left">-</td></tr><tr><td align="left"><a id="triggeredby-2"></a> <code>triggeredBy?</code></td><td align="left">{ <code>method</code>: <code>string</code>; <code>path?</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>triggeredBy.method</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>triggeredBy.path?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr></tbody></table></div>
2963
3041
  <hr>
2964
3042
  <p><a id="sandboxpersistenceoptions"></a></p>
2965
3043
  <h3 id="sandboxpersistenceoptions">SandboxPersistenceOptions</h3>
@@ -3077,7 +3155,11 @@ their state is a Firestore document.</p>
3077
3155
 
3078
3156
 
3079
3157
 
3080
- <table><thead><tr><th align="left">Property</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><a id="at-6"></a> <code>at</code></td><td align="left"><code>number</code></td></tr><tr><td align="left"><a id="auth-9"></a> <code>auth</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="detail-4"></a> <code>detail?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><a id="error-2"></a> <code>error</code></td><td align="left">{ <code>code?</code>: <code>string</code>; <code>message</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>error.code?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>error.message</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="id-6"></a> <code>id</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="kind-5"></a> <code>kind</code></td><td align="left"><code>"runtime_error"</code></td></tr><tr><td align="left"><a id="method-4"></a> <code>method</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="path-4"></a> <code>path?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="service-5"></a> <code>service</code></td><td align="left"><a href="#eventservice"><code>EventService</code></a></td></tr></tbody></table></div>
3158
+
3159
+
3160
+
3161
+
3162
+ <table><thead><tr><th align="left">Property</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><a id="at-6"></a> <code>at</code></td><td align="left"><code>number</code></td></tr><tr><td align="left"><a id="auth-9"></a> <code>auth</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="detail-4"></a> <code>detail?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><a id="error-2"></a> <code>error</code></td><td align="left">{ <code>code?</code>: <code>string</code>; <code>message</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>error.code?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>error.message</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="id-6"></a> <code>id</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="kind-5"></a> <code>kind</code></td><td align="left"><code>"runtime_error"</code></td></tr><tr><td align="left"><a id="method-4"></a> <code>method</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="path-4"></a> <code>path?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="service-5"></a> <code>service</code></td><td align="left"><a href="#eventservice"><code>EventService</code></a></td></tr></tbody></table></div>
3081
3163
  <hr>
3082
3164
  <p><a id="sandboxsnapshot"></a></p>
3083
3165
  <h3 id="sandboxsnapshot">SandboxSnapshot</h3>
@@ -3205,7 +3287,12 @@ diff <code>before</code>→<code>after</code> when both are present.</p>
3205
3287
 
3206
3288
 
3207
3289
 
3208
- <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="after"></a> <code>after?</code></td><td align="left"><code>unknown</code></td><td align="left">Best-effort serializable snapshot of the state AFTER the mutation. Absent on deletes / sign-outs (nothing remains).</td></tr><tr><td align="left"><a id="at-7"></a> <code>at</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="auth-10"></a> <code>auth</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">Identity in effect when the op ran (the service’s <code>request.auth</code> equivalent). <code>null</code> for admin/anonymous-driven mutations (e.g. <code>sandbox.createUser</code>, an unauthenticated RTDB write).</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="before"></a> <code>before?</code></td><td align="left"><code>unknown</code></td><td align="left">Best-effort serializable snapshot of the state BEFORE the mutation. Absent when there was no prior state (a create) or it isn’t cheap to capture.</td></tr><tr><td align="left"><a id="detail-5"></a> <code>detail?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">Free-form, service-specific extras a consumer may surface without re-deriving (e.g. storage <code>{ size, contentType }</code>, rtdb <code>{ committed }</code> for a transaction). Kept loose on purpose — it’s a display hint, not a contract.</td></tr><tr><td align="left"><a id="id-7"></a> <code>id</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="kind-6"></a> <code>kind</code></td><td align="left"><code>"service_mutation"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="op-2"></a> <code>op</code></td><td align="left"><code>string</code></td><td align="left">Service-scoped operation name. Stable, lowercase, snake/kebab-free: - auth: <code>user_create</code></td></tr><tr><td align="left"><a id="path-5"></a> <code>path?</code></td><td align="left"><code>string</code></td><td align="left">The thing mutated, in the service’s own addressing scheme: - auth: the user <code>uid</code> (or <code>'*'</code> for a clear-all). Absent for a sign-out with no prior user. - storage: the object <code>fullPath</code> (e.g. <code>avatars/alice.png</code>). - rtdb: the database path (e.g. <code>/rooms/r1/messages</code>), or for a multi-path <code>update</code> the ref path the call targeted.</td></tr><tr><td align="left"><a id="service-6"></a> <code>service</code></td><td align="left"><code>"rtdb"</code> | <code>"auth"</code> | <code>"storage"</code> | <code>"messaging"</code> | <code>"ai"</code></td><td align="left">Which service performed the mutation. Always one of the non-Firestore services — Firestore rides its own <code>request</code>/<code>write</code> path. (The provenance <code>service</code> field on the stamped event mirrors this; it is set redundantly here so a consumer matching purely on <code>kind</code> still gets the discriminator without reaching into provenance.)</td></tr></tbody></table></div>
3290
+
3291
+
3292
+
3293
+
3294
+
3295
+ <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="after"></a> <code>after?</code></td><td align="left"><code>unknown</code></td><td align="left">Best-effort serializable snapshot of the state AFTER the mutation. Absent on deletes / sign-outs (nothing remains).</td></tr><tr><td align="left"><a id="at-7"></a> <code>at</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="auth-10"></a> <code>auth</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">Identity in effect when the op ran (the service’s <code>request.auth</code> equivalent). <code>null</code> for admin/anonymous-driven mutations (e.g. <code>sandbox.createUser</code>, an unauthenticated RTDB write).</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="before"></a> <code>before?</code></td><td align="left"><code>unknown</code></td><td align="left">Best-effort serializable snapshot of the state BEFORE the mutation. Absent when there was no prior state (a create) or it isn’t cheap to capture.</td></tr><tr><td align="left"><a id="detail-5"></a> <code>detail?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">Free-form, service-specific extras a consumer may surface without re-deriving (e.g. storage <code>{ size, contentType }</code>, rtdb <code>{ committed }</code> for a transaction). Kept loose on purpose — it’s a display hint, not a contract.</td></tr><tr><td align="left"><a id="id-7"></a> <code>id</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="kind-6"></a> <code>kind</code></td><td align="left"><code>"service_mutation"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="op-2"></a> <code>op</code></td><td align="left"><code>string</code></td><td align="left">Service-scoped operation name. Stable, lowercase, snake/kebab-free: - auth: <code>user_create</code></td></tr><tr><td align="left"><a id="path-5"></a> <code>path?</code></td><td align="left"><code>string</code></td><td align="left">The thing mutated, in the service’s own addressing scheme: - auth: the user <code>uid</code> (or <code>'*'</code> for a clear-all). Absent for a sign-out with no prior user. - storage: the object <code>fullPath</code> (e.g. <code>avatars/alice.png</code>). - rtdb: the database path (e.g. <code>/rooms/r1/messages</code>), or for a multi-path <code>update</code> the ref path the call targeted.</td></tr><tr><td align="left"><a id="service-6"></a> <code>service</code></td><td align="left"><code>"rtdb"</code> | <code>"auth"</code> | <code>"storage"</code> | <code>"messaging"</code> | <code>"ai"</code></td><td align="left">Which service performed the mutation. Always one of the non-Firestore services — Firestore rides its own <code>request</code>/<code>write</code> path. (The provenance <code>service</code> field on the stamped event mirrors this; it is set redundantly here so a consumer matching purely on <code>kind</code> still gets the discriminator without reaching into provenance.)</td></tr></tbody></table></div>
3209
3296
  <hr>
3210
3297
  <p><a id="sessionboundaryevent"></a></p>
3211
3298
  <h3 id="sessionboundaryevent">SessionBoundaryEvent</h3>
@@ -3357,7 +3444,12 @@ scenario produces large snapshots.</p>
3357
3444
 
3358
3445
 
3359
3446
 
3360
- <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="addedcount"></a> <code>addedCount</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="at-9"></a> <code>at</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="auth-11"></a> <code>auth</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="id-9"></a> <code>id</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="kind-8"></a> <code>kind</code></td><td align="left"><code>"snapshot_delivery"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="listenerid-3"></a> <code>listenerId</code></td><td align="left"><code>string</code></td><td align="left">Opaque listener id assigned at attach time.</td></tr><tr><td align="left"><a id="modifiedcount"></a> <code>modifiedCount</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="removedcount"></a> <code>removedCount</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="sample-1"></a> <code>sample?</code></td><td align="left">{ <code>docs</code>: { <code>data</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>path</code>: <code>string</code>; }[]; }</td><td align="left">Doc payloads, in the order the user callback saw them.</td></tr><tr><td align="left"><code>sample.docs</code></td><td align="left">{ <code>data</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>path</code>: <code>string</code>; }[]</td><td align="left">-</td></tr><tr><td align="left"><a id="size-1"></a> <code>size</code></td><td align="left"><code>number</code></td><td align="left"><code>1</code> for doc-kind (exists) / <code>0</code> (deleted), <code>n</code> for query-kind.</td></tr><tr><td align="left"><a id="target-2"></a> <code>target</code></td><td align="left">| { <code>kind</code>: <code>"doc"</code>; <code>path</code>: <code>string</code>; } | { <code>collection</code>: <code>string</code>; <code>kind</code>: <code>"query"</code>; }</td><td align="left">-</td></tr><tr><td align="left"><a id="triggeredby-3"></a> <code>triggeredBy?</code></td><td align="left">{ <code>method</code>: <code>string</code>; <code>path</code>: <code>string</code>; }</td><td align="left">The user op that triggered this re-eval. Absent on initial fire and on <code>deployRules</code>-driven re-evals.</td></tr><tr><td align="left"><code>triggeredBy.method</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>triggeredBy.path</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr></tbody></table></div>
3447
+
3448
+
3449
+
3450
+
3451
+
3452
+ <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="addedcount"></a> <code>addedCount</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="at-9"></a> <code>at</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="auth-11"></a> <code>auth</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="id-9"></a> <code>id</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="kind-8"></a> <code>kind</code></td><td align="left"><code>"snapshot_delivery"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="listenerid-3"></a> <code>listenerId</code></td><td align="left"><code>string</code></td><td align="left">Opaque listener id assigned at attach time.</td></tr><tr><td align="left"><a id="modifiedcount"></a> <code>modifiedCount</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="removedcount"></a> <code>removedCount</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="sample-1"></a> <code>sample?</code></td><td align="left">{ <code>docs</code>: { <code>data</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>path</code>: <code>string</code>; }[]; }</td><td align="left">Doc payloads, in the order the user callback saw them.</td></tr><tr><td align="left"><code>sample.docs</code></td><td align="left">{ <code>data</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>path</code>: <code>string</code>; }[]</td><td align="left">-</td></tr><tr><td align="left"><a id="size-1"></a> <code>size</code></td><td align="left"><code>number</code></td><td align="left"><code>1</code> for doc-kind (exists) / <code>0</code> (deleted), <code>n</code> for query-kind.</td></tr><tr><td align="left"><a id="target-2"></a> <code>target</code></td><td align="left">| { <code>kind</code>: <code>"doc"</code>; <code>path</code>: <code>string</code>; } | { <code>collection</code>: <code>string</code>; <code>kind</code>: <code>"query"</code>; }</td><td align="left">-</td></tr><tr><td align="left"><a id="triggeredby-3"></a> <code>triggeredBy?</code></td><td align="left">{ <code>method</code>: <code>string</code>; <code>path</code>: <code>string</code>; }</td><td align="left">The user op that triggered this re-eval. Absent on initial fire and on <code>deployRules</code>-driven re-evals.</td></tr><tr><td align="left"><code>triggeredBy.method</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>triggeredBy.path</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr></tbody></table></div>
3361
3453
  <hr>
3362
3454
  <p><a id="snapshoterrorevent"></a></p>
3363
3455
  <h3 id="snapshoterrorevent">SnapshotErrorEvent</h3>
@@ -3440,7 +3532,11 @@ scenario surfaces them.</p>
3440
3532
 
3441
3533
 
3442
3534
 
3443
- <table><thead><tr><th align="left">Property</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><a id="auth-12"></a> <code>auth?</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="code-1"></a> <code>code</code></td><td align="left"><code>"permission-denied"</code></td></tr><tr><td align="left"><a id="message-1"></a> <code>message</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="reasons-5"></a> <code>reasons?</code></td><td align="left"><code>string</code>[]</td></tr><tr><td align="left"><a id="request-4"></a> <code>request?</code></td><td align="left">{ <code>method</code>: <code>"delete"</code> | <code>"get"</code> | <code>"list"</code> | <code>"create"</code> | <code>"update"</code>; <code>path</code>: <code>string</code>; <code>resourceData?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; }</td></tr><tr><td align="left"><code>request.method</code></td><td align="left"><code>"delete"</code> | <code>"get"</code> | <code>"list"</code> | <code>"create"</code> | <code>"update"</code></td></tr><tr><td align="left"><code>request.path</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>request.resourceData?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><a id="resource-2"></a> <code>resource?</code></td><td align="left">{ <code>data</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>exists</code>: <code>boolean</code>; }</td></tr><tr><td align="left"><code>resource.data</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>resource.exists</code></td><td align="left"><code>boolean</code></td></tr><tr><td align="left"><a id="target-3"></a> <code>target</code></td><td align="left">| { <code>kind</code>: <code>"doc"</code>; <code>path</code>: <code>string</code>; } | { <code>collection</code>: <code>string</code>; <code>kind</code>: <code>"query"</code>; <code>query?</code>: <code>unknown</code>; }</td></tr></tbody></table></div>
3535
+
3536
+
3537
+
3538
+
3539
+ <table><thead><tr><th align="left">Property</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><a id="auth-12"></a> <code>auth?</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="code-1"></a> <code>code</code></td><td align="left"><code>"permission-denied"</code></td></tr><tr><td align="left"><a id="message-1"></a> <code>message</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><a id="reasons-5"></a> <code>reasons?</code></td><td align="left"><code>string</code>[]</td></tr><tr><td align="left"><a id="request-4"></a> <code>request?</code></td><td align="left">{ <code>method</code>: <code>"delete"</code> | <code>"get"</code> | <code>"list"</code> | <code>"create"</code> | <code>"update"</code>; <code>path</code>: <code>string</code>; <code>resourceData?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; }</td></tr><tr><td align="left"><code>request.method</code></td><td align="left"><code>"delete"</code> | <code>"get"</code> | <code>"list"</code> | <code>"create"</code> | <code>"update"</code></td></tr><tr><td align="left"><code>request.path</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>request.resourceData?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><a id="resource-2"></a> <code>resource?</code></td><td align="left">{ <code>data</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>exists</code>: <code>boolean</code>; }</td></tr><tr><td align="left"><code>resource.data</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>resource.exists</code></td><td align="left"><code>boolean</code></td></tr><tr><td align="left"><a id="target-3"></a> <code>target</code></td><td align="left">| { <code>kind</code>: <code>"doc"</code>; <code>path</code>: <code>string</code>; } | { <code>collection</code>: <code>string</code>; <code>kind</code>: <code>"query"</code>; <code>query?</code>: <code>unknown</code>; }</td></tr></tbody></table></div>
3444
3540
  <hr>
3445
3541
  <p><a id="snapshotsuppressedevent"></a></p>
3446
3542
  <h3 id="snapshotsuppressedevent">SnapshotSuppressedEvent</h3>
@@ -3521,7 +3617,12 @@ them.</p>
3521
3617
 
3522
3618
 
3523
3619
 
3524
- <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="at-10"></a> <code>at</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="auth-13"></a> <code>auth</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="id-10"></a> <code>id</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="kind-9"></a> <code>kind</code></td><td align="left"><code>"snapshot_suppressed"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="listenerid-4"></a> <code>listenerId</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="reason-1"></a> <code>reason</code></td><td align="left"><code>"no-op"</code></td><td align="left">Why this re-eval was suppressed. v1 only emits <code>'no-op'</code>.</td></tr><tr><td align="left"><a id="target-4"></a> <code>target</code></td><td align="left">| { <code>kind</code>: <code>"doc"</code>; <code>path</code>: <code>string</code>; } | { <code>collection</code>: <code>string</code>; <code>kind</code>: <code>"query"</code>; }</td><td align="left">-</td></tr><tr><td align="left"><a id="triggeredby-4"></a> <code>triggeredBy?</code></td><td align="left">{ <code>method</code>: <code>string</code>; <code>path</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>triggeredBy.method</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>triggeredBy.path</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr></tbody></table></div>
3620
+
3621
+
3622
+
3623
+
3624
+
3625
+ <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="at-10"></a> <code>at</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="auth-13"></a> <code>auth</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="id-10"></a> <code>id</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="kind-9"></a> <code>kind</code></td><td align="left"><code>"snapshot_suppressed"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="listenerid-4"></a> <code>listenerId</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="reason-1"></a> <code>reason</code></td><td align="left"><code>"no-op"</code></td><td align="left">Why this re-eval was suppressed. v1 only emits <code>'no-op'</code>.</td></tr><tr><td align="left"><a id="target-4"></a> <code>target</code></td><td align="left">| { <code>kind</code>: <code>"doc"</code>; <code>path</code>: <code>string</code>; } | { <code>collection</code>: <code>string</code>; <code>kind</code>: <code>"query"</code>; }</td><td align="left">-</td></tr><tr><td align="left"><a id="triggeredby-4"></a> <code>triggeredBy?</code></td><td align="left">{ <code>method</code>: <code>string</code>; <code>path</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>triggeredBy.method</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>triggeredBy.path</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr></tbody></table></div>
3525
3626
  <hr>
3526
3627
  <p><a id="tabsyncoptions"></a></p>
3527
3628
  <h3 id="tabsyncoptions">TabSyncOptions</h3>
@@ -3554,7 +3655,7 @@ the defaults provide a ready-to-use configuration for browser environments.</p>
3554
3655
  <h3 id="webstoragelike">WebStorageLike</h3>
3555
3656
  <p>Minimal web-storage-like contract the session persistence controller
3556
3657
  reads/writes. Matches the <code>localStorage</code> / <code>sessionStorage</code> browser
3557
- API subset that <code>pyric dev</code>’s <code>SessionStore</code> already uses, so
3658
+ API subset that <code>pyric sandbox</code>’s <code>SessionStore</code> already uses, so
3558
3659
  browsers pass real storages and tests pass in-memory Map-backed fakes.</p>
3559
3660
  <p>Why the minimal subset (get/set/remove) instead of the full
3560
3661
  <code>Storage</code> interface: this library targets multiple environments
@@ -3747,7 +3848,12 @@ sentinel/auto-id capture lands.</p>
3747
3848
 
3748
3849
 
3749
3850
 
3750
- <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="at-11"></a> <code>at</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="auth-14"></a> <code>auth</code></td><td align="left">{ <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="autoid"></a> <code>autoId?</code></td><td align="left"><code>string</code></td><td align="left">Minted document ID when this write came from <code>collection.add()</code> / <code>LocalEnvironment.createWithAutoId</code>. The replay engine aliases the path’s last segment to a fresh mint on replay (rather than preserving the original auto-ID).</td></tr><tr><td align="left"><a id="data-1"></a> <code>data?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">Pre-resolution write payload — <code>FieldValue.*</code> sentinels preserved as marker shapes (<code>{ __type: 'serverTimestamp' }</code>, etc.) so the replay engine can re-resolve them. The rule engine evaluated against the resolved form internally; the resolved form lives on <a href="#nextstate-1">nextState</a>. Absent on <code>delete</code>.</td></tr><tr><td align="left"><a id="detail-6"></a> <code>detail?</code></td><td align="left">{ <code>admin?</code>: <code>boolean</code>; } &#x26; <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">Free-form write metadata. <code>admin: true</code> marks a rules-bypassing setup/admin commit so replay can apply it as context without asking candidate rules to permit it.</td></tr><tr><td align="left"><a id="groupid-3"></a> <code>groupId?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="groupkind-4"></a> <code>groupKind?</code></td><td align="left"><code>"transaction"</code> | <code>"batch"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="id-11"></a> <code>id</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="kind-10"></a> <code>kind</code></td><td align="left"><code>"write"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="method-5"></a> <code>method</code></td><td align="left"><code>"delete"</code> | <code>"create"</code> | <code>"update"</code> | <code>"set"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="nextstate-1"></a> <code>nextState</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">State AFTER this write. <code>null</code> on <code>delete</code>.</td></tr><tr><td align="left"><a id="path-6"></a> <code>path</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="priorstate-1"></a> <code>priorState</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">State BEFORE this write. <code>null</code> for a non-existent doc.</td></tr><tr><td align="left"><a id="requesttime"></a> <code>requestTime</code></td><td align="left">{ <code>nanoseconds</code>: <code>number</code>; <code>seconds</code>: <code>number</code>; }</td><td align="left">Server time at which the rule engine evaluated this write — pinned per op (or shared across sub-ops in a batch / transaction). The replay engine re-issues this exact value when re-resolving <code>serverTimestamp()</code> sentinels so resolved fields are bit-identical on replay. Shape mirrors the Firestore Web SDK Timestamp (<code>{ seconds, nanoseconds }</code>).</td></tr><tr><td align="left"><code>requestTime.nanoseconds</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><code>requestTime.seconds</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="sentinels"></a> <code>sentinels?</code></td><td align="left">{ <code>field</code>: <code>string</code>; <code>kind</code>: | <code>"delete"</code> | <code>"serverTimestamp"</code> | <code>"increment"</code> | <code>"arrayUnion"</code> | <code>"arrayRemove"</code>; }[]</td><td align="left">FieldValue sentinels (serverTimestamp / increment / arrayUnion / arrayRemove / deleteField → ‘delete’) extracted from the pre-resolution write payload. The replay engine consumes this to re-issue the same sentinels at replay time without consulting resolved values that would have drifted. Path syntax: dotted with bracket-indices (‘a.b[0].c’). Absent when the write contained no sentinels.</td></tr></tbody></table></div>
3851
+
3852
+
3853
+
3854
+
3855
+
3856
+ <table><thead><tr><th align="left">Property</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><a id="at-11"></a> <code>at</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="auth-14"></a> <code>auth</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td><td align="left">-</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">-</td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="autoid"></a> <code>autoId?</code></td><td align="left"><code>string</code></td><td align="left">Minted document ID when this write came from <code>collection.add()</code> / <code>LocalEnvironment.createWithAutoId</code>. The replay engine aliases the path’s last segment to a fresh mint on replay (rather than preserving the original auto-ID).</td></tr><tr><td align="left"><a id="data-1"></a> <code>data?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">Pre-resolution write payload — <code>FieldValue.*</code> sentinels preserved as marker shapes (<code>{ __type: 'serverTimestamp' }</code>, etc.) so the replay engine can re-resolve them. The rule engine evaluated against the resolved form internally; the resolved form lives on <a href="#nextstate-1">nextState</a>. Absent on <code>delete</code>.</td></tr><tr><td align="left"><a id="detail-6"></a> <code>detail?</code></td><td align="left">{ <code>admin?</code>: <code>boolean</code>; } &#x26; <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">Free-form write metadata. <code>admin: true</code> marks a rules-bypassing setup/admin commit so replay can apply it as context without asking candidate rules to permit it.</td></tr><tr><td align="left"><a id="groupid-3"></a> <code>groupId?</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="groupkind-4"></a> <code>groupKind?</code></td><td align="left"><code>"transaction"</code> | <code>"batch"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="id-11"></a> <code>id</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="kind-10"></a> <code>kind</code></td><td align="left"><code>"write"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="method-5"></a> <code>method</code></td><td align="left"><code>"delete"</code> | <code>"create"</code> | <code>"update"</code> | <code>"set"</code></td><td align="left">-</td></tr><tr><td align="left"><a id="nextstate-1"></a> <code>nextState</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">State AFTER this write. <code>null</code> on <code>delete</code>.</td></tr><tr><td align="left"><a id="path-6"></a> <code>path</code></td><td align="left"><code>string</code></td><td align="left">-</td></tr><tr><td align="left"><a id="priorstate-1"></a> <code>priorState</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td><td align="left">State BEFORE this write. <code>null</code> for a non-existent doc.</td></tr><tr><td align="left"><a id="requesttime"></a> <code>requestTime</code></td><td align="left">{ <code>nanoseconds</code>: <code>number</code>; <code>seconds</code>: <code>number</code>; }</td><td align="left">Server time at which the rule engine evaluated this write — pinned per op (or shared across sub-ops in a batch / transaction). The replay engine re-issues this exact value when re-resolving <code>serverTimestamp()</code> sentinels so resolved fields are bit-identical on replay. Shape mirrors the Firestore Web SDK Timestamp (<code>{ seconds, nanoseconds }</code>).</td></tr><tr><td align="left"><code>requestTime.nanoseconds</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><code>requestTime.seconds</code></td><td align="left"><code>number</code></td><td align="left">-</td></tr><tr><td align="left"><a id="sentinels"></a> <code>sentinels?</code></td><td align="left">{ <code>field</code>: <code>string</code>; <code>kind</code>: | <code>"delete"</code> | <code>"serverTimestamp"</code> | <code>"increment"</code> | <code>"arrayUnion"</code> | <code>"arrayRemove"</code>; }[]</td><td align="left">FieldValue sentinels (serverTimestamp / increment / arrayUnion / arrayRemove / deleteField → ‘delete’) extracted from the pre-resolution write payload. The replay engine consumes this to re-issue the same sentinels at replay time without consulting resolved values that would have drifted. Path syntax: dotted with bracket-indices (‘a.b[0].c’). Absent when the write contained no sentinels.</td></tr></tbody></table></div>
3751
3857
  <h2 id="type-aliases">Type Aliases</h2>
3752
3858
  <p><a id="authlens-2"></a></p>
3753
3859
  <h3 id="authlens">AuthLens</h3>
@@ -3757,6 +3863,7 @@ sentinel/auto-id capture lands.</p>
3757
3863
  <span class="line"><span style="color:#ABB2BF">}</span></span>
3758
3864
  <span class="line"><span style="color:#ABB2BF"> | {</span></span>
3759
3865
  <span class="line"><span style="color:#E06C75"> mode</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">"as"</span><span style="color:#ABB2BF">;</span></span>
3866
+ <span class="line"><span style="color:#E06C75"> tenant</span><span style="color:#C678DD">?</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">string</span><span style="color:#ABB2BF">;</span></span>
3760
3867
  <span class="line"><span style="color:#E06C75"> token</span><span style="color:#C678DD">?</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">Record</span><span style="color:#ABB2BF">&#x3C;</span><span style="color:#E5C07B">string</span><span style="color:#ABB2BF">, </span><span style="color:#E5C07B">unknown</span><span style="color:#ABB2BF">>;</span></span>
3761
3868
  <span class="line"><span style="color:#E06C75"> uid</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">string</span><span style="color:#ABB2BF">;</span></span>
3762
3869
  <span class="line"><span style="color:#ABB2BF">}</span></span>
@@ -4301,12 +4408,67 @@ than into process-local state.</p>
4301
4408
  <h4 id="returns-77">Returns</h4>
4302
4409
  <p><code>sandbox is RemoteSandbox</code></p>
4303
4410
  <hr>
4411
+ <p><a id="normalizeauthstate"></a></p>
4412
+ <h3 id="normalizeauthstate">normalizeAuthState()</h3>
4413
+ <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#C678DD">function</span><span style="color:#61AFEF"> normalizeAuthState</span><span style="color:#ABB2BF">(</span><span style="color:#E06C75;font-style:italic">auth</span><span style="color:#ABB2BF">: {</span></span>
4414
+ <span class="line"><span style="color:#E06C75"> tenant</span><span style="color:#C678DD">?</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">string</span><span style="color:#ABB2BF">;</span></span>
4415
+ <span class="line"><span style="color:#E06C75"> token</span><span style="color:#C678DD">?</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">Record</span><span style="color:#ABB2BF">&#x3C;</span><span style="color:#E5C07B">string</span><span style="color:#ABB2BF">, </span><span style="color:#E5C07B">unknown</span><span style="color:#ABB2BF">>;</span></span>
4416
+ <span class="line"><span style="color:#E06C75"> uid</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">string</span><span style="color:#ABB2BF">;</span></span>
4417
+ <span class="line"><span style="color:#ABB2BF">}): {</span></span>
4418
+ <span class="line"><span style="color:#E06C75"> tenant</span><span style="color:#C678DD">?</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">string</span><span style="color:#ABB2BF">;</span></span>
4419
+ <span class="line"><span style="color:#E06C75"> token</span><span style="color:#C678DD">?</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">Record</span><span style="color:#ABB2BF">&#x3C;</span><span style="color:#E5C07B">string</span><span style="color:#ABB2BF">, </span><span style="color:#E5C07B">unknown</span><span style="color:#ABB2BF">>;</span></span>
4420
+ <span class="line"><span style="color:#E06C75"> uid</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">string</span><span style="color:#ABB2BF">;</span></span>
4421
+ <span class="line"><span style="color:#ABB2BF">};</span></span></code></pre>
4422
+ <p>Normalize AuthState during SandboxContextImpl context assembly.
4423
+ Automatically projects top-level <code>tenant</code> into <code>token.firebase.tenant</code>
4424
+ while preserving custom claims and explicit nested token overrides.
4425
+ Never mutates original input.</p>
4426
+ <h4 id="parameters-45">Parameters</h4>
4427
+ <div class="table-scroll">
4428
+
4429
+
4430
+
4431
+
4432
+
4433
+
4434
+
4435
+
4436
+
4437
+
4438
+
4439
+
4440
+
4441
+
4442
+
4443
+
4444
+
4445
+
4446
+
4447
+
4448
+
4449
+
4450
+
4451
+
4452
+ <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>auth</code></td><td align="left">{ <code>tenant?</code>: <code>string</code>; <code>token?</code>: <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>; <code>uid</code>: <code>string</code>; }</td></tr><tr><td align="left"><code>auth.tenant?</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>auth.token?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>auth.uid</code></td><td align="left"><code>string</code></td></tr></tbody></table></div>
4453
+ <h4 id="returns-78">Returns</h4>
4454
+ <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#ABB2BF">{</span></span>
4455
+ <span class="line"><span style="color:#E06C75"> tenant</span><span style="color:#C678DD">?:</span><span style="color:#E06C75"> string</span><span style="color:#ABB2BF">;</span></span>
4456
+ <span class="line"><span style="color:#E06C75"> token</span><span style="color:#C678DD">?:</span><span style="color:#E06C75"> Record</span><span style="color:#56B6C2">&#x3C;</span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">, </span><span style="color:#E06C75">unknown</span><span style="color:#56B6C2">></span><span style="color:#ABB2BF">;</span></span>
4457
+ <span class="line"><span style="color:#E06C75"> uid</span><span style="color:#ABB2BF">: </span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">;</span></span>
4458
+ <span class="line"><span style="color:#ABB2BF">}</span></span></code></pre>
4459
+ <h5 id="tenant">tenant?</h5>
4460
+ <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#E06C75">optional</span><span style="color:#E06C75"> tenant</span><span style="color:#ABB2BF">: </span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">;</span></span></code></pre>
4461
+ <h5 id="token">token?</h5>
4462
+ <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#E06C75">optional</span><span style="color:#E06C75"> token</span><span style="color:#ABB2BF">: </span><span style="color:#E06C75">Record</span><span style="color:#56B6C2">&#x3C;</span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">, </span><span style="color:#E06C75">unknown</span><span style="color:#56B6C2">></span><span style="color:#ABB2BF">;</span></span></code></pre>
4463
+ <h5 id="uid">uid</h5>
4464
+ <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#E06C75">uid</span><span style="color:#ABB2BF">: </span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">;</span></span></code></pre>
4465
+ <hr>
4304
4466
  <p><a id="operationcontextfor"></a></p>
4305
4467
  <h3 id="operationcontextfor">operationContextFor()</h3>
4306
4468
  <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#C678DD">function</span><span style="color:#61AFEF"> operationContextFor</span><span style="color:#ABB2BF">(</span><span style="color:#E06C75;font-style:italic">event</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">Pick</span><span style="color:#ABB2BF">&#x3C;</span><span style="color:#E5C07B">EventProvenance</span><span style="color:#ABB2BF">, </span><span style="color:#98C379">"operationContext"</span><span style="color:#ABB2BF"> | </span><span style="color:#98C379">"actor"</span><span style="color:#ABB2BF"> | </span><span style="color:#98C379">"authLens"</span><span style="color:#ABB2BF"> | </span><span style="color:#98C379">"planId"</span><span style="color:#ABB2BF">>): </span><span style="color:#E5C07B">OperationContext</span><span style="color:#ABB2BF">;</span></span></code></pre>
4307
4469
  <p>The canonical context on a recorded event. Old/pre-context events are
4308
4470
  explicitly unattributed rather than silently asserted to be app traffic.</p>
4309
- <h4 id="parameters-45">Parameters</h4>
4471
+ <h4 id="parameters-46">Parameters</h4>
4310
4472
  <div class="table-scroll">
4311
4473
 
4312
4474
 
@@ -4321,7 +4483,7 @@ explicitly unattributed rather than silently asserted to be app traffic.</p>
4321
4483
 
4322
4484
 
4323
4485
  <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>event</code></td><td align="left"><code>Pick</code>&#x3C;<a href="#eventprovenance"><code>EventProvenance</code></a>, <code>"operationContext"</code> | <code>"actor"</code> | <code>"authLens"</code> | <code>"planId"</code>></td></tr></tbody></table></div>
4324
- <h4 id="returns-78">Returns</h4>
4486
+ <h4 id="returns-79">Returns</h4>
4325
4487
  <p><a href="#operationcontext-2"><code>OperationContext</code></a></p>
4326
4488
  <hr>
4327
4489
  <p><a id="parsebundle"></a></p>
@@ -4330,7 +4492,7 @@ explicitly unattributed rather than silently asserted to be app traffic.</p>
4330
4492
  <p>Parse a v3 bundle blob back into records. Returns an empty map for an
4331
4493
  unrecognized blob (e.g. a legacy v2 single-blob snapshot); migrate-on-open (a
4332
4494
  later commit) handles converting a v2 blob to v3 records.</p>
4333
- <h4 id="parameters-46">Parameters</h4>
4495
+ <h4 id="parameters-47">Parameters</h4>
4334
4496
  <div class="table-scroll">
4335
4497
 
4336
4498
 
@@ -4345,7 +4507,7 @@ later commit) handles converting a v2 blob to v3 records.</p>
4345
4507
 
4346
4508
 
4347
4509
  <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>blob</code></td><td align="left"><code>string</code></td></tr></tbody></table></div>
4348
- <h4 id="returns-79">Returns</h4>
4510
+ <h4 id="returns-80">Returns</h4>
4349
4511
  <p><code>Map</code>&#x3C;<code>string</code>, <code>unknown</code>></p>
4350
4512
  <hr>
4351
4513
  <p><a id="promote"></a></p>
@@ -4364,7 +4526,7 @@ the admin plane:</p>
4364
4526
  <p>Admin-plane application fires the target’s listeners (matching how
4365
4527
  persistence restore lands docs), so live UI/handles see the promotion.</p>
4366
4528
  <p>The branch is marked discarded afterward — a promoted branch is spent.</p>
4367
- <h4 id="parameters-47">Parameters</h4>
4529
+ <h4 id="parameters-48">Parameters</h4>
4368
4530
  <div class="table-scroll">
4369
4531
 
4370
4532
 
@@ -4386,7 +4548,7 @@ persistence restore lands docs), so live UI/handles see the promotion.</p>
4386
4548
 
4387
4549
 
4388
4550
  <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th><th align="left">Description</th></tr></thead><tbody><tr><td align="left"><code>branch</code></td><td align="left"><a href="#branch"><code>Branch</code></a></td><td align="left">The experiment to land.</td></tr><tr><td align="left"><code>target</code></td><td align="left"><a href="#localsandbox"><code>LocalSandbox</code></a></td><td align="left">The live sandbox to land it on.</td></tr></tbody></table></div>
4389
- <h4 id="returns-80">Returns</h4>
4551
+ <h4 id="returns-81">Returns</h4>
4390
4552
  <p><code>void</code></p>
4391
4553
  <hr>
4392
4554
  <p><a id="recordbackendoverblob"></a></p>
@@ -4401,7 +4563,7 @@ The whole record set is bundled into that blob, for serve’s committable export
4401
4563
  file / HTTP state endpoint and any single-key store. It loses chunking’s scale
4402
4564
  benefit by design (the blob IS the single artifact). The blob is loaded once and
4403
4565
  cached, so a restore (list + per-record get) costs one read, not one per record.</p>
4404
- <h4 id="parameters-48">Parameters</h4>
4566
+ <h4 id="parameters-49">Parameters</h4>
4405
4567
  <div class="table-scroll">
4406
4568
 
4407
4569
 
@@ -4428,7 +4590,7 @@ cached, so a restore (list + per-record get) costs one read, not one per record.
4428
4590
 
4429
4591
 
4430
4592
  <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>io</code></td><td align="left">{ <code>clear</code>: <code>Promise</code>&#x3C;<code>void</code>>; <code>read</code>: <code>Promise</code>&#x3C;<code>string</code>>; <code>write</code>: <code>Promise</code>&#x3C;<code>void</code>>; }</td></tr><tr><td align="left"><code>io.clear</code></td><td align="left"></td></tr><tr><td align="left"><code>io.read</code></td><td align="left"></td></tr><tr><td align="left"><code>io.write</code></td><td align="left"></td></tr></tbody></table></div>
4431
- <h4 id="returns-81">Returns</h4>
4593
+ <h4 id="returns-82">Returns</h4>
4432
4594
  <p><a href="#persistencebackend"><code>PersistenceBackend</code></a></p>
4433
4595
  <hr>
4434
4596
  <p><a id="rehydratedocvalue"></a></p>
@@ -4440,7 +4602,7 @@ values (and plain objects without a recognized discriminator) pass through.</p>
4440
4602
  <p>This is the canonical rehydrate used by BOTH the sandbox persistence
4441
4603
  serializer and the SharedWorker wire protocol, so the IDB format and the
4442
4604
  MessagePort wire format are guaranteed identical.</p>
4443
- <h4 id="parameters-49">Parameters</h4>
4605
+ <h4 id="parameters-50">Parameters</h4>
4444
4606
  <div class="table-scroll">
4445
4607
 
4446
4608
 
@@ -4455,7 +4617,7 @@ MessagePort wire format are guaranteed identical.</p>
4455
4617
 
4456
4618
 
4457
4619
  <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>value</code></td><td align="left"><code>unknown</code></td></tr></tbody></table></div>
4458
- <h4 id="returns-82">Returns</h4>
4620
+ <h4 id="returns-83">Returns</h4>
4459
4621
  <p><code>unknown</code></p>
4460
4622
  <hr>
4461
4623
  <p><a id="replay-1"></a></p>
@@ -4470,7 +4632,7 @@ MessagePort wire format are guaranteed identical.</p>
4470
4632
  diffs the replayed sandbox’s final state against it and returns
4471
4633
  classified divergences. When omitted, divergences is <code>[]</code> (you still
4472
4634
  get the replayed sandbox; you can inspect its state manually).</p>
4473
- <h4 id="parameters-50">Parameters</h4>
4635
+ <h4 id="parameters-51">Parameters</h4>
4474
4636
  <div class="table-scroll">
4475
4637
 
4476
4638
 
@@ -4497,7 +4659,7 @@ get the replayed sandbox; you can inspect its state manually).</p>
4497
4659
 
4498
4660
 
4499
4661
  <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>events</code></td><td align="left">readonly <a href="#sandboxevent"><code>SandboxEvent</code></a>[]</td></tr><tr><td align="left"><code>rules</code></td><td align="left"><code>string</code></td></tr><tr><td align="left"><code>options?</code></td><td align="left"><a href="#replayoptions"><code>ReplayOptions</code></a></td></tr><tr><td align="left"><code>originalState?</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>DocData</code>></td></tr></tbody></table></div>
4500
- <h4 id="returns-83">Returns</h4>
4662
+ <h4 id="returns-84">Returns</h4>
4501
4663
  <p><a href="#replayresult"><code>ReplayResult</code></a></p>
4502
4664
  <hr>
4503
4665
  <p><a id="rulesdispositionfor"></a></p>
@@ -4506,7 +4668,7 @@ get the replayed sandbox; you can inspect its state manually).</p>
4506
4668
  <p>Normalize the legacy per-service markers exactly once, at the sandbox
4507
4669
  stream seam. Consumers must not inspect <code>detail.admin</code>, <code>origin</code>, or the
4508
4670
  presence of a trace themselves.</p>
4509
- <h4 id="parameters-51">Parameters</h4>
4671
+ <h4 id="parameters-52">Parameters</h4>
4510
4672
  <div class="table-scroll">
4511
4673
 
4512
4674
 
@@ -4521,7 +4683,7 @@ presence of a trace themselves.</p>
4521
4683
 
4522
4684
 
4523
4685
  <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>event</code></td><td align="left"><code>OperationEvent</code></td></tr></tbody></table></div>
4524
- <h4 id="returns-84">Returns</h4>
4686
+ <h4 id="returns-85">Returns</h4>
4525
4687
  <p><a href="#rulesdisposition-3"><code>RulesDisposition</code></a></p>
4526
4688
  <hr>
4527
4689
  <p><a id="serializetobuckets"></a></p>
@@ -4533,7 +4695,7 @@ presence of a trace themselves.</p>
4533
4695
  <p>Partition a firestore doc map into v3 records: one bucket record per occupied
4534
4696
  bucket plus the <code>meta</code> record. The returned map’s keys are record ids; values
4535
4697
  are structured-clone-safe.</p>
4536
- <h4 id="parameters-52">Parameters</h4>
4698
+ <h4 id="parameters-53">Parameters</h4>
4537
4699
  <div class="table-scroll">
4538
4700
 
4539
4701
 
@@ -4556,14 +4718,14 @@ are structured-clone-safe.</p>
4556
4718
 
4557
4719
 
4558
4720
  <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>firestore</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>>></td></tr><tr><td align="left"><code>services</code></td><td align="left"><code>Record</code>&#x3C;<code>string</code>, <code>unknown</code>></td></tr><tr><td align="left"><code>savedAt</code></td><td align="left"><code>number</code></td></tr></tbody></table></div>
4559
- <h4 id="returns-85">Returns</h4>
4721
+ <h4 id="returns-86">Returns</h4>
4560
4722
  <p><code>Map</code>&#x3C;<code>string</code>, <code>BucketRecord</code> | <code>MetaRecord</code>></p>
4561
4723
  <hr>
4562
4724
  <p><a id="tooperationrecord"></a></p>
4563
4725
  <h3 id="tooperationrecord">toOperationRecord()</h3>
4564
4726
  <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#C678DD">function</span><span style="color:#61AFEF"> toOperationRecord</span><span style="color:#ABB2BF">(</span><span style="color:#E06C75;font-style:italic">event</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">SandboxEvent</span><span style="color:#ABB2BF">): </span><span style="color:#E5C07B">OperationRecord</span><span style="color:#ABB2BF">;</span></span></code></pre>
4565
4727
  <p>Project either traffic event family into the canonical record.</p>
4566
- <h4 id="parameters-53">Parameters</h4>
4728
+ <h4 id="parameters-54">Parameters</h4>
4567
4729
  <div class="table-scroll">
4568
4730
 
4569
4731
 
@@ -4578,8 +4740,36 @@ are structured-clone-safe.</p>
4578
4740
 
4579
4741
 
4580
4742
  <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>event</code></td><td align="left"><a href="#sandboxevent"><code>SandboxEvent</code></a></td></tr></tbody></table></div>
4581
- <h4 id="returns-86">Returns</h4>
4743
+ <h4 id="returns-87">Returns</h4>
4582
4744
  <p><a href="#operationrecord"><code>OperationRecord</code></a></p>
4745
+ <hr>
4746
+ <p><a id="validateauthstate"></a></p>
4747
+ <h3 id="validateauthstate">validateAuthState()</h3>
4748
+ <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#C678DD">function</span><span style="color:#61AFEF"> validateAuthState</span><span style="color:#ABB2BF">(</span><span style="color:#E06C75;font-style:italic">auth</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">unknown</span><span style="color:#ABB2BF">): asserts </span><span style="color:#E06C75;font-style:italic">auth</span><span style="color:#C678DD"> is</span><span style="color:#ABB2BF"> { </span><span style="color:#E06C75">tenant</span><span style="color:#C678DD">?:</span><span style="color:#E06C75"> string</span><span style="color:#ABB2BF">; </span><span style="color:#E06C75">token</span><span style="color:#C678DD">?:</span><span style="color:#E06C75"> Record</span><span style="color:#56B6C2">&#x3C;</span><span style="color:#E06C75">string</span><span style="color:#ABB2BF">, </span><span style="color:#E06C75">unknown</span><span style="color:#56B6C2">></span><span style="color:#ABB2BF">; </span><span style="color:#E06C75">uid</span><span style="color:#ABB2BF">: </span><span style="color:#E06C75">string</span><span style="color:#ABB2BF"> };</span></span></code></pre>
4749
+ <p>Reject <code>undefined</code> and other clearly-malformed inputs at the
4750
+ <code>withAuth</code> call site. <code>null</code> is valid (anonymous);
4751
+ <code>{ uid: 'someUid' }</code> is valid; everything else throws so the
4752
+ mistake surfaces at the boundary instead of leaking into rule
4753
+ eval as a confusing denial.</p>
4754
+ <p>Shared between <code>Sandbox.withAuth</code> and <code>SandboxContext.withAuth</code>
4755
+ so both entries enforce the same validation.</p>
4756
+ <h4 id="parameters-55">Parameters</h4>
4757
+ <div class="table-scroll">
4758
+
4759
+
4760
+
4761
+
4762
+
4763
+
4764
+
4765
+
4766
+
4767
+
4768
+
4769
+
4770
+ <table><thead><tr><th align="left">Parameter</th><th align="left">Type</th></tr></thead><tbody><tr><td align="left"><code>auth</code></td><td align="left"><code>unknown</code></td></tr></tbody></table></div>
4771
+ <h4 id="returns-88">Returns</h4>
4772
+ <p><code>asserts auth is { tenant?: string; token?: Record&#x3C;string, unknown>; uid: string }</code></p>
4583
4773
  <h2 id="references">References</h2>
4584
4774
  <p><a id="authstate"></a></p>
4585
4775
  <h3 id="authstate">AuthState</h3>
@@ -4595,4 +4785,4 @@ are structured-clone-safe.</p>
4595
4785
  <hr>
4596
4786
  <p><a id="sandboxerror"></a></p>
4597
4787
  <h3 id="sandboxerror">SandboxError</h3>
4598
- <p>Re-exports <a href="/docs/pyric-firestore-reference-api/#sandboxerror">SandboxError</a></p> </article> </main> <aside class="doc-toc api-symbols" aria-label="API symbols" data-astro-cid-mw7aashj> <h2 class="doc-toc-heading" data-astro-cid-mw7aashj>Symbols</h2> <input class="api-symbol-filter" type="search" placeholder="Filter symbols" aria-label="Filter API symbols" data-api-symbol-filter data-astro-cid-mw7aashj> <div class="api-symbol-groups" data-api-symbol-groups data-astro-cid-mw7aashj> <section class="api-symbol-group" data-api-symbol-group data-astro-cid-mw7aashj> <a class="api-symbol-kind" href="#classes" data-astro-cid-mw7aashj> Classes </a> <ul data-astro-cid-mw7aashj> <li data-api-symbol="persistenceschemaerror" data-astro-cid-mw7aashj> <a href="#persistenceschemaerror" data-astro-cid-mw7aashj>PersistenceSchemaError</a> </li><li data-api-symbol="sandboxcontextimpl" data-astro-cid-mw7aashj> <a href="#sandboxcontextimpl" data-astro-cid-mw7aashj>SandboxContextImpl</a> </li> </ul> </section><section class="api-symbol-group" data-api-symbol-group data-astro-cid-mw7aashj> <a class="api-symbol-kind" href="#interfaces" data-astro-cid-mw7aashj> Interfaces </a> <ul data-astro-cid-mw7aashj> <li data-api-symbol="activityeventprovenance" data-astro-cid-mw7aashj> <a href="#activityeventprovenance" data-astro-cid-mw7aashj>ActivityEventProvenance</a> </li><li data-api-symbol="branch" data-astro-cid-mw7aashj> <a href="#branch" data-astro-cid-mw7aashj>Branch</a> </li><li data-api-symbol="broadcastchannellike" data-astro-cid-mw7aashj> <a href="#broadcastchannellike" data-astro-cid-mw7aashj>BroadcastChannelLike</a> </li><li data-api-symbol="denialcontext" data-astro-cid-mw7aashj> <a href="#denialcontext" data-astro-cid-mw7aashj>DenialContext</a> </li><li data-api-symbol="denialevent" data-astro-cid-mw7aashj> <a href="#denialevent" data-astro-cid-mw7aashj>DenialEvent</a> </li><li data-api-symbol="eventprovenance" data-astro-cid-mw7aashj> <a href="#eventprovenance" data-astro-cid-mw7aashj>EventProvenance</a> </li><li data-api-symbol="listenerlifecycleevent" data-astro-cid-mw7aashj> <a href="#listenerlifecycleevent" data-astro-cid-mw7aashj>ListenerLifecycleEvent</a> </li><li data-api-symbol="localsandbox" data-astro-cid-mw7aashj> <a href="#localsandbox" data-astro-cid-mw7aashj>LocalSandbox</a> </li><li data-api-symbol="operationcontext" data-astro-cid-mw7aashj> <a href="#operationcontext" data-astro-cid-mw7aashj>OperationContext</a> </li><li data-api-symbol="operationrecord" data-astro-cid-mw7aashj> <a href="#operationrecord" data-astro-cid-mw7aashj>OperationRecord</a> </li><li data-api-symbol="persistableservice" data-astro-cid-mw7aashj> <a href="#persistableservice" data-astro-cid-mw7aashj>PersistableService</a> </li><li data-api-symbol="persistencebackend" data-astro-cid-mw7aashj> <a href="#persistencebackend" data-astro-cid-mw7aashj>PersistenceBackend</a> </li><li data-api-symbol="persistencecontroller" data-astro-cid-mw7aashj> <a href="#persistencecontroller" data-astro-cid-mw7aashj>PersistenceController</a> </li><li data-api-symbol="remotesandbox" data-astro-cid-mw7aashj> <a href="#remotesandbox" data-astro-cid-mw7aashj>RemoteSandbox</a> </li><li data-api-symbol="remotesandboxchannel" data-astro-cid-mw7aashj> <a href="#remotesandboxchannel" data-astro-cid-mw7aashj>RemoteSandboxChannel</a> </li><li data-api-symbol="remotesandboxfactoryoptions" data-astro-cid-mw7aashj> <a href="#remotesandboxfactoryoptions" data-astro-cid-mw7aashj>RemoteSandboxFactoryOptions</a> </li><li data-api-symbol="replayoptions" data-astro-cid-mw7aashj> <a href="#replayoptions" data-astro-cid-mw7aashj>ReplayOptions</a> </li><li data-api-symbol="replayresult" data-astro-cid-mw7aashj> <a href="#replayresult" data-astro-cid-mw7aashj>ReplayResult</a> </li><li data-api-symbol="requestevent" data-astro-cid-mw7aashj> <a href="#requestevent" data-astro-cid-mw7aashj>RequestEvent</a> </li><li data-api-symbol="sandboxcommitevent" data-astro-cid-mw7aashj> <a href="#sandboxcommitevent" data-astro-cid-mw7aashj>SandboxCommitEvent</a> </li><li data-api-symbol="sandboxconfig" data-astro-cid-mw7aashj> <a href="#sandboxconfig" data-astro-cid-mw7aashj>SandboxConfig</a> </li><li data-api-symbol="sandboxlistenerevent" data-astro-cid-mw7aashj> <a href="#sandboxlistenerevent" data-astro-cid-mw7aashj>SandboxListenerEvent</a> </li><li data-api-symbol="sandboxoperationevent" data-astro-cid-mw7aashj> <a href="#sandboxoperationevent" data-astro-cid-mw7aashj>SandboxOperationEvent</a> </li><li data-api-symbol="sandboxpersistenceoptions" data-astro-cid-mw7aashj> <a href="#sandboxpersistenceoptions" data-astro-cid-mw7aashj>SandboxPersistenceOptions</a> </li><li data-api-symbol="sandboxruntimeerrorevent" data-astro-cid-mw7aashj> <a href="#sandboxruntimeerrorevent" data-astro-cid-mw7aashj>SandboxRuntimeErrorEvent</a> </li><li data-api-symbol="sandboxsnapshot" data-astro-cid-mw7aashj> <a href="#sandboxsnapshot" data-astro-cid-mw7aashj>SandboxSnapshot</a> </li><li data-api-symbol="servicemutationevent" data-astro-cid-mw7aashj> <a href="#servicemutationevent" data-astro-cid-mw7aashj>ServiceMutationEvent</a> </li><li data-api-symbol="sessionboundaryevent" data-astro-cid-mw7aashj> <a href="#sessionboundaryevent" data-astro-cid-mw7aashj>SessionBoundaryEvent</a> </li><li data-api-symbol="snapshotdeliveryevent" data-astro-cid-mw7aashj> <a href="#snapshotdeliveryevent" data-astro-cid-mw7aashj>SnapshotDeliveryEvent</a> </li><li data-api-symbol="snapshoterrorevent" data-astro-cid-mw7aashj> <a href="#snapshoterrorevent" data-astro-cid-mw7aashj>SnapshotErrorEvent</a> </li><li data-api-symbol="snapshotsuppressedevent" data-astro-cid-mw7aashj> <a href="#snapshotsuppressedevent" data-astro-cid-mw7aashj>SnapshotSuppressedEvent</a> </li><li data-api-symbol="tabsyncoptions" data-astro-cid-mw7aashj> <a href="#tabsyncoptions" data-astro-cid-mw7aashj>TabSyncOptions</a> </li><li data-api-symbol="webstoragelike" data-astro-cid-mw7aashj> <a href="#webstoragelike" data-astro-cid-mw7aashj>WebStorageLike</a> </li><li data-api-symbol="writesandboxevent" data-astro-cid-mw7aashj> <a href="#writesandboxevent" data-astro-cid-mw7aashj>WriteSandboxEvent</a> </li> </ul> </section><section class="api-symbol-group" data-api-symbol-group data-astro-cid-mw7aashj> <a class="api-symbol-kind" href="#type-aliases" data-astro-cid-mw7aashj> Type Aliases </a> <ul data-astro-cid-mw7aashj> <li data-api-symbol="authlens" data-astro-cid-mw7aashj> <a href="#authlens" data-astro-cid-mw7aashj>AuthLens</a> </li><li data-api-symbol="difftarget" data-astro-cid-mw7aashj> <a href="#difftarget" data-astro-cid-mw7aashj>DiffTarget</a> </li><li data-api-symbol="divergence" data-astro-cid-mw7aashj> <a href="#divergence" data-astro-cid-mw7aashj>Divergence</a> </li><li data-api-symbol="eventactor" data-astro-cid-mw7aashj> <a href="#eventactor" data-astro-cid-mw7aashj>EventActor</a> </li><li data-api-symbol="eventservice" data-astro-cid-mw7aashj> <a href="#eventservice" data-astro-cid-mw7aashj>EventService</a> </li><li data-api-symbol="remotesandboxfactory()" data-astro-cid-mw7aashj> <a href="#remotesandboxfactory" data-astro-cid-mw7aashj>RemoteSandboxFactory()</a> </li><li data-api-symbol="rulesdisposition" data-astro-cid-mw7aashj> <a href="#rulesdisposition" data-astro-cid-mw7aashj>RulesDisposition</a> </li><li data-api-symbol="sandboxerrorcode" data-astro-cid-mw7aashj> <a href="#sandboxerrorcode" data-astro-cid-mw7aashj>SandboxErrorCode</a> </li><li data-api-symbol="sandboxevent" data-astro-cid-mw7aashj> <a href="#sandboxevent" data-astro-cid-mw7aashj>SandboxEvent</a> </li> </ul> </section><section class="api-symbol-group" data-api-symbol-group data-astro-cid-mw7aashj> <a class="api-symbol-kind" href="#variables" data-astro-cid-mw7aashj> Variables </a> <ul data-astro-cid-mw7aashj> <li data-api-symbol="remote_sandbox" data-astro-cid-mw7aashj> <a href="#remote_sandbox" data-astro-cid-mw7aashj>REMOTE_SANDBOX</a> </li><li data-api-symbol="remote_sandbox_factory" data-astro-cid-mw7aashj> <a href="#remote_sandbox_factory" data-astro-cid-mw7aashj>REMOTE_SANDBOX_FACTORY</a> </li> </ul> </section><section class="api-symbol-group" data-api-symbol-group data-astro-cid-mw7aashj> <a class="api-symbol-kind" href="#functions" data-astro-cid-mw7aashj> Functions </a> <ul data-astro-cid-mw7aashj> <li data-api-symbol="apply()" data-astro-cid-mw7aashj> <a href="#apply" data-astro-cid-mw7aashj>apply()</a> </li><li data-api-symbol="attachpersistence()" data-astro-cid-mw7aashj> <a href="#attachpersistence" data-astro-cid-mw7aashj>attachPersistence()</a> </li><li data-api-symbol="attachtabsync()" data-astro-cid-mw7aashj> <a href="#attachtabsync" data-astro-cid-mw7aashj>attachTabSync()</a> </li><li data-api-symbol="bundlerecords()" data-astro-cid-mw7aashj> <a href="#bundlerecords" data-astro-cid-mw7aashj>bundleRecords()</a> </li><li data-api-symbol="createindexeddbbackend()" data-astro-cid-mw7aashj> <a href="#createindexeddbbackend" data-astro-cid-mw7aashj>createIndexedDBBackend()</a> </li><li data-api-symbol="creatememorybackend()" data-astro-cid-mw7aashj> <a href="#creatememorybackend" data-astro-cid-mw7aashj>createMemoryBackend()</a> </li><li data-api-symbol="deserializefrombuckets()" data-astro-cid-mw7aashj> <a href="#deserializefrombuckets" data-astro-cid-mw7aashj>deserializeFromBuckets()</a> </li><li data-api-symbol="diff()" data-astro-cid-mw7aashj> <a href="#diff" data-astro-cid-mw7aashj>diff()</a> </li><li data-api-symbol="discard()" data-astro-cid-mw7aashj> <a href="#discard" data-astro-cid-mw7aashj>discard()</a> </li><li data-api-symbol="fork()" data-astro-cid-mw7aashj> <a href="#fork" data-astro-cid-mw7aashj>fork()</a> </li><li data-api-symbol="initializesandbox()" data-astro-cid-mw7aashj> <a href="#initializesandbox" data-astro-cid-mw7aashj>initializeSandbox()</a> </li><li data-api-symbol="isoperationevent()" data-astro-cid-mw7aashj> <a href="#isoperationevent" data-astro-cid-mw7aashj>isOperationEvent()</a> </li><li data-api-symbol="isremotesandbox()" data-astro-cid-mw7aashj> <a href="#isremotesandbox" data-astro-cid-mw7aashj>isRemoteSandbox()</a> </li><li data-api-symbol="operationcontextfor()" data-astro-cid-mw7aashj> <a href="#operationcontextfor" data-astro-cid-mw7aashj>operationContextFor()</a> </li><li data-api-symbol="parsebundle()" data-astro-cid-mw7aashj> <a href="#parsebundle" data-astro-cid-mw7aashj>parseBundle()</a> </li><li data-api-symbol="promote()" data-astro-cid-mw7aashj> <a href="#promote" data-astro-cid-mw7aashj>promote()</a> </li><li data-api-symbol="recordbackendoverblob()" data-astro-cid-mw7aashj> <a href="#recordbackendoverblob" data-astro-cid-mw7aashj>recordBackendOverBlob()</a> </li><li data-api-symbol="rehydratedocvalue()" data-astro-cid-mw7aashj> <a href="#rehydratedocvalue" data-astro-cid-mw7aashj>rehydrateDocValue()</a> </li><li data-api-symbol="replay()" data-astro-cid-mw7aashj> <a href="#replay" data-astro-cid-mw7aashj>replay()</a> </li><li data-api-symbol="rulesdispositionfor()" data-astro-cid-mw7aashj> <a href="#rulesdispositionfor" data-astro-cid-mw7aashj>rulesDispositionFor()</a> </li><li data-api-symbol="serializetobuckets()" data-astro-cid-mw7aashj> <a href="#serializetobuckets" data-astro-cid-mw7aashj>serializeToBuckets()</a> </li><li data-api-symbol="tooperationrecord()" data-astro-cid-mw7aashj> <a href="#tooperationrecord" data-astro-cid-mw7aashj>toOperationRecord()</a> </li> </ul> </section><section class="api-symbol-group" data-api-symbol-group data-astro-cid-mw7aashj> <a class="api-symbol-kind" href="#references" data-astro-cid-mw7aashj> References </a> <ul data-astro-cid-mw7aashj> <li data-api-symbol="authstate" data-astro-cid-mw7aashj> <a href="#authstate" data-astro-cid-mw7aashj>AuthState</a> </li><li data-api-symbol="sandbox" data-astro-cid-mw7aashj> <a href="#sandbox" data-astro-cid-mw7aashj>Sandbox</a> </li><li data-api-symbol="sandboxcontext" data-astro-cid-mw7aashj> <a href="#sandboxcontext" data-astro-cid-mw7aashj>SandboxContext</a> </li><li data-api-symbol="sandboxerror" data-astro-cid-mw7aashj> <a href="#sandboxerror" data-astro-cid-mw7aashj>SandboxError</a> </li> </ul> </section> <p class="api-symbol-empty" data-api-symbol-empty hidden data-astro-cid-mw7aashj>No matching symbols</p> </div> </aside> </div> <script type="module">const a=document.querySelector("[data-api-symbol-filter]"),d=[...document.querySelectorAll("[data-api-symbol-group]")],n=document.querySelector("[data-api-symbol-empty]");a?.addEventListener("input",()=>{const t=a.value.trim().toLowerCase();let o=0;for(const i of d){let e=0;i.querySelectorAll("[data-api-symbol]").forEach(l=>{const r=!t||(l.dataset.apiSymbol??"").includes(t);l.hidden=!r,r&&e++}),i.hidden=e===0,o+=e}n&&(n.hidden=o>0)});</script> <script type="module">const s=new Map;document.querySelectorAll('.doc-toc a[href^="#"]').forEach(t=>s.set(decodeURIComponent(t.hash.slice(1)),t));if(s.size>0){const t=new Set,n=()=>{let o=null;for(const e of s.keys())if(t.has(e)){o=e;break}s.forEach((e,c)=>e.classList.toggle("active",c===o))},r=new IntersectionObserver(o=>{for(const e of o)e.isIntersecting?t.add(e.target.id):t.delete(e.target.id);n()},{rootMargin:"-72px 0px -60% 0px"});s.forEach((o,e)=>{const c=document.getElementById(e);c&&r.observe(c)})}</script> <script type="module">document.querySelector('.studio__nav [aria-current="page"]')?.scrollIntoView({block:"nearest",inline:"center"});</script> </body></html>
4788
+ <p>Re-exports <a href="/docs/pyric-firestore-reference-api/#sandboxerror">SandboxError</a></p> </article> </main> <aside class="doc-toc api-symbols" aria-label="API symbols" data-astro-cid-mw7aashj> <h2 class="doc-toc-heading" data-astro-cid-mw7aashj>Symbols</h2> <input class="api-symbol-filter" type="search" placeholder="Filter symbols" aria-label="Filter API symbols" data-api-symbol-filter data-astro-cid-mw7aashj> <div class="api-symbol-groups" data-api-symbol-groups data-astro-cid-mw7aashj> <section class="api-symbol-group" data-api-symbol-group data-astro-cid-mw7aashj> <a class="api-symbol-kind" href="#classes" data-astro-cid-mw7aashj> Classes </a> <ul data-astro-cid-mw7aashj> <li data-api-symbol="persistenceschemaerror" data-astro-cid-mw7aashj> <a href="#persistenceschemaerror" data-astro-cid-mw7aashj>PersistenceSchemaError</a> </li><li data-api-symbol="sandboxcontextimpl" data-astro-cid-mw7aashj> <a href="#sandboxcontextimpl" data-astro-cid-mw7aashj>SandboxContextImpl</a> </li> </ul> </section><section class="api-symbol-group" data-api-symbol-group data-astro-cid-mw7aashj> <a class="api-symbol-kind" href="#interfaces" data-astro-cid-mw7aashj> Interfaces </a> <ul data-astro-cid-mw7aashj> <li data-api-symbol="activityeventprovenance" data-astro-cid-mw7aashj> <a href="#activityeventprovenance" data-astro-cid-mw7aashj>ActivityEventProvenance</a> </li><li data-api-symbol="branch" data-astro-cid-mw7aashj> <a href="#branch" data-astro-cid-mw7aashj>Branch</a> </li><li data-api-symbol="broadcastchannellike" data-astro-cid-mw7aashj> <a href="#broadcastchannellike" data-astro-cid-mw7aashj>BroadcastChannelLike</a> </li><li data-api-symbol="denialcontext" data-astro-cid-mw7aashj> <a href="#denialcontext" data-astro-cid-mw7aashj>DenialContext</a> </li><li data-api-symbol="denialevent" data-astro-cid-mw7aashj> <a href="#denialevent" data-astro-cid-mw7aashj>DenialEvent</a> </li><li data-api-symbol="eventprovenance" data-astro-cid-mw7aashj> <a href="#eventprovenance" data-astro-cid-mw7aashj>EventProvenance</a> </li><li data-api-symbol="listenerlifecycleevent" data-astro-cid-mw7aashj> <a href="#listenerlifecycleevent" data-astro-cid-mw7aashj>ListenerLifecycleEvent</a> </li><li data-api-symbol="localsandbox" data-astro-cid-mw7aashj> <a href="#localsandbox" data-astro-cid-mw7aashj>LocalSandbox</a> </li><li data-api-symbol="operationcontext" data-astro-cid-mw7aashj> <a href="#operationcontext" data-astro-cid-mw7aashj>OperationContext</a> </li><li data-api-symbol="operationrecord" data-astro-cid-mw7aashj> <a href="#operationrecord" data-astro-cid-mw7aashj>OperationRecord</a> </li><li data-api-symbol="persistableservice" data-astro-cid-mw7aashj> <a href="#persistableservice" data-astro-cid-mw7aashj>PersistableService</a> </li><li data-api-symbol="persistencebackend" data-astro-cid-mw7aashj> <a href="#persistencebackend" data-astro-cid-mw7aashj>PersistenceBackend</a> </li><li data-api-symbol="persistencecontroller" data-astro-cid-mw7aashj> <a href="#persistencecontroller" data-astro-cid-mw7aashj>PersistenceController</a> </li><li data-api-symbol="remotesandbox" data-astro-cid-mw7aashj> <a href="#remotesandbox" data-astro-cid-mw7aashj>RemoteSandbox</a> </li><li data-api-symbol="remotesandboxchannel" data-astro-cid-mw7aashj> <a href="#remotesandboxchannel" data-astro-cid-mw7aashj>RemoteSandboxChannel</a> </li><li data-api-symbol="remotesandboxfactoryoptions" data-astro-cid-mw7aashj> <a href="#remotesandboxfactoryoptions" data-astro-cid-mw7aashj>RemoteSandboxFactoryOptions</a> </li><li data-api-symbol="replayoptions" data-astro-cid-mw7aashj> <a href="#replayoptions" data-astro-cid-mw7aashj>ReplayOptions</a> </li><li data-api-symbol="replayresult" data-astro-cid-mw7aashj> <a href="#replayresult" data-astro-cid-mw7aashj>ReplayResult</a> </li><li data-api-symbol="requestevent" data-astro-cid-mw7aashj> <a href="#requestevent" data-astro-cid-mw7aashj>RequestEvent</a> </li><li data-api-symbol="sandboxcommitevent" data-astro-cid-mw7aashj> <a href="#sandboxcommitevent" data-astro-cid-mw7aashj>SandboxCommitEvent</a> </li><li data-api-symbol="sandboxconfig" data-astro-cid-mw7aashj> <a href="#sandboxconfig" data-astro-cid-mw7aashj>SandboxConfig</a> </li><li data-api-symbol="sandboxlistenerevent" data-astro-cid-mw7aashj> <a href="#sandboxlistenerevent" data-astro-cid-mw7aashj>SandboxListenerEvent</a> </li><li data-api-symbol="sandboxoperationevent" data-astro-cid-mw7aashj> <a href="#sandboxoperationevent" data-astro-cid-mw7aashj>SandboxOperationEvent</a> </li><li data-api-symbol="sandboxpersistenceoptions" data-astro-cid-mw7aashj> <a href="#sandboxpersistenceoptions" data-astro-cid-mw7aashj>SandboxPersistenceOptions</a> </li><li data-api-symbol="sandboxruntimeerrorevent" data-astro-cid-mw7aashj> <a href="#sandboxruntimeerrorevent" data-astro-cid-mw7aashj>SandboxRuntimeErrorEvent</a> </li><li data-api-symbol="sandboxsnapshot" data-astro-cid-mw7aashj> <a href="#sandboxsnapshot" data-astro-cid-mw7aashj>SandboxSnapshot</a> </li><li data-api-symbol="servicemutationevent" data-astro-cid-mw7aashj> <a href="#servicemutationevent" data-astro-cid-mw7aashj>ServiceMutationEvent</a> </li><li data-api-symbol="sessionboundaryevent" data-astro-cid-mw7aashj> <a href="#sessionboundaryevent" data-astro-cid-mw7aashj>SessionBoundaryEvent</a> </li><li data-api-symbol="snapshotdeliveryevent" data-astro-cid-mw7aashj> <a href="#snapshotdeliveryevent" data-astro-cid-mw7aashj>SnapshotDeliveryEvent</a> </li><li data-api-symbol="snapshoterrorevent" data-astro-cid-mw7aashj> <a href="#snapshoterrorevent" data-astro-cid-mw7aashj>SnapshotErrorEvent</a> </li><li data-api-symbol="snapshotsuppressedevent" data-astro-cid-mw7aashj> <a href="#snapshotsuppressedevent" data-astro-cid-mw7aashj>SnapshotSuppressedEvent</a> </li><li data-api-symbol="tabsyncoptions" data-astro-cid-mw7aashj> <a href="#tabsyncoptions" data-astro-cid-mw7aashj>TabSyncOptions</a> </li><li data-api-symbol="webstoragelike" data-astro-cid-mw7aashj> <a href="#webstoragelike" data-astro-cid-mw7aashj>WebStorageLike</a> </li><li data-api-symbol="writesandboxevent" data-astro-cid-mw7aashj> <a href="#writesandboxevent" data-astro-cid-mw7aashj>WriteSandboxEvent</a> </li> </ul> </section><section class="api-symbol-group" data-api-symbol-group data-astro-cid-mw7aashj> <a class="api-symbol-kind" href="#type-aliases" data-astro-cid-mw7aashj> Type Aliases </a> <ul data-astro-cid-mw7aashj> <li data-api-symbol="authlens" data-astro-cid-mw7aashj> <a href="#authlens" data-astro-cid-mw7aashj>AuthLens</a> </li><li data-api-symbol="difftarget" data-astro-cid-mw7aashj> <a href="#difftarget" data-astro-cid-mw7aashj>DiffTarget</a> </li><li data-api-symbol="divergence" data-astro-cid-mw7aashj> <a href="#divergence" data-astro-cid-mw7aashj>Divergence</a> </li><li data-api-symbol="eventactor" data-astro-cid-mw7aashj> <a href="#eventactor" data-astro-cid-mw7aashj>EventActor</a> </li><li data-api-symbol="eventservice" data-astro-cid-mw7aashj> <a href="#eventservice" data-astro-cid-mw7aashj>EventService</a> </li><li data-api-symbol="remotesandboxfactory()" data-astro-cid-mw7aashj> <a href="#remotesandboxfactory" data-astro-cid-mw7aashj>RemoteSandboxFactory()</a> </li><li data-api-symbol="rulesdisposition" data-astro-cid-mw7aashj> <a href="#rulesdisposition" data-astro-cid-mw7aashj>RulesDisposition</a> </li><li data-api-symbol="sandboxerrorcode" data-astro-cid-mw7aashj> <a href="#sandboxerrorcode" data-astro-cid-mw7aashj>SandboxErrorCode</a> </li><li data-api-symbol="sandboxevent" data-astro-cid-mw7aashj> <a href="#sandboxevent" data-astro-cid-mw7aashj>SandboxEvent</a> </li> </ul> </section><section class="api-symbol-group" data-api-symbol-group data-astro-cid-mw7aashj> <a class="api-symbol-kind" href="#variables" data-astro-cid-mw7aashj> Variables </a> <ul data-astro-cid-mw7aashj> <li data-api-symbol="remote_sandbox" data-astro-cid-mw7aashj> <a href="#remote_sandbox" data-astro-cid-mw7aashj>REMOTE_SANDBOX</a> </li><li data-api-symbol="remote_sandbox_factory" data-astro-cid-mw7aashj> <a href="#remote_sandbox_factory" data-astro-cid-mw7aashj>REMOTE_SANDBOX_FACTORY</a> </li> </ul> </section><section class="api-symbol-group" data-api-symbol-group data-astro-cid-mw7aashj> <a class="api-symbol-kind" href="#functions" data-astro-cid-mw7aashj> Functions </a> <ul data-astro-cid-mw7aashj> <li data-api-symbol="apply()" data-astro-cid-mw7aashj> <a href="#apply" data-astro-cid-mw7aashj>apply()</a> </li><li data-api-symbol="attachpersistence()" data-astro-cid-mw7aashj> <a href="#attachpersistence" data-astro-cid-mw7aashj>attachPersistence()</a> </li><li data-api-symbol="attachtabsync()" data-astro-cid-mw7aashj> <a href="#attachtabsync" data-astro-cid-mw7aashj>attachTabSync()</a> </li><li data-api-symbol="bundlerecords()" data-astro-cid-mw7aashj> <a href="#bundlerecords" data-astro-cid-mw7aashj>bundleRecords()</a> </li><li data-api-symbol="createindexeddbbackend()" data-astro-cid-mw7aashj> <a href="#createindexeddbbackend" data-astro-cid-mw7aashj>createIndexedDBBackend()</a> </li><li data-api-symbol="creatememorybackend()" data-astro-cid-mw7aashj> <a href="#creatememorybackend" data-astro-cid-mw7aashj>createMemoryBackend()</a> </li><li data-api-symbol="deserializefrombuckets()" data-astro-cid-mw7aashj> <a href="#deserializefrombuckets" data-astro-cid-mw7aashj>deserializeFromBuckets()</a> </li><li data-api-symbol="diff()" data-astro-cid-mw7aashj> <a href="#diff" data-astro-cid-mw7aashj>diff()</a> </li><li data-api-symbol="discard()" data-astro-cid-mw7aashj> <a href="#discard" data-astro-cid-mw7aashj>discard()</a> </li><li data-api-symbol="fork()" data-astro-cid-mw7aashj> <a href="#fork" data-astro-cid-mw7aashj>fork()</a> </li><li data-api-symbol="initializesandbox()" data-astro-cid-mw7aashj> <a href="#initializesandbox" data-astro-cid-mw7aashj>initializeSandbox()</a> </li><li data-api-symbol="isoperationevent()" data-astro-cid-mw7aashj> <a href="#isoperationevent" data-astro-cid-mw7aashj>isOperationEvent()</a> </li><li data-api-symbol="isremotesandbox()" data-astro-cid-mw7aashj> <a href="#isremotesandbox" data-astro-cid-mw7aashj>isRemoteSandbox()</a> </li><li data-api-symbol="normalizeauthstate()" data-astro-cid-mw7aashj> <a href="#normalizeauthstate" data-astro-cid-mw7aashj>normalizeAuthState()</a> </li><li data-api-symbol="operationcontextfor()" data-astro-cid-mw7aashj> <a href="#operationcontextfor" data-astro-cid-mw7aashj>operationContextFor()</a> </li><li data-api-symbol="parsebundle()" data-astro-cid-mw7aashj> <a href="#parsebundle" data-astro-cid-mw7aashj>parseBundle()</a> </li><li data-api-symbol="promote()" data-astro-cid-mw7aashj> <a href="#promote" data-astro-cid-mw7aashj>promote()</a> </li><li data-api-symbol="recordbackendoverblob()" data-astro-cid-mw7aashj> <a href="#recordbackendoverblob" data-astro-cid-mw7aashj>recordBackendOverBlob()</a> </li><li data-api-symbol="rehydratedocvalue()" data-astro-cid-mw7aashj> <a href="#rehydratedocvalue" data-astro-cid-mw7aashj>rehydrateDocValue()</a> </li><li data-api-symbol="replay()" data-astro-cid-mw7aashj> <a href="#replay" data-astro-cid-mw7aashj>replay()</a> </li><li data-api-symbol="rulesdispositionfor()" data-astro-cid-mw7aashj> <a href="#rulesdispositionfor" data-astro-cid-mw7aashj>rulesDispositionFor()</a> </li><li data-api-symbol="serializetobuckets()" data-astro-cid-mw7aashj> <a href="#serializetobuckets" data-astro-cid-mw7aashj>serializeToBuckets()</a> </li><li data-api-symbol="tooperationrecord()" data-astro-cid-mw7aashj> <a href="#tooperationrecord" data-astro-cid-mw7aashj>toOperationRecord()</a> </li><li data-api-symbol="validateauthstate()" data-astro-cid-mw7aashj> <a href="#validateauthstate" data-astro-cid-mw7aashj>validateAuthState()</a> </li> </ul> </section><section class="api-symbol-group" data-api-symbol-group data-astro-cid-mw7aashj> <a class="api-symbol-kind" href="#references" data-astro-cid-mw7aashj> References </a> <ul data-astro-cid-mw7aashj> <li data-api-symbol="authstate" data-astro-cid-mw7aashj> <a href="#authstate" data-astro-cid-mw7aashj>AuthState</a> </li><li data-api-symbol="sandbox" data-astro-cid-mw7aashj> <a href="#sandbox" data-astro-cid-mw7aashj>Sandbox</a> </li><li data-api-symbol="sandboxcontext" data-astro-cid-mw7aashj> <a href="#sandboxcontext" data-astro-cid-mw7aashj>SandboxContext</a> </li><li data-api-symbol="sandboxerror" data-astro-cid-mw7aashj> <a href="#sandboxerror" data-astro-cid-mw7aashj>SandboxError</a> </li> </ul> </section> <p class="api-symbol-empty" data-api-symbol-empty hidden data-astro-cid-mw7aashj>No matching symbols</p> </div> </aside> </div> <script type="module">const a=document.querySelector("[data-api-symbol-filter]"),d=[...document.querySelectorAll("[data-api-symbol-group]")],n=document.querySelector("[data-api-symbol-empty]");a?.addEventListener("input",()=>{const t=a.value.trim().toLowerCase();let o=0;for(const i of d){let e=0;i.querySelectorAll("[data-api-symbol]").forEach(l=>{const r=!t||(l.dataset.apiSymbol??"").includes(t);l.hidden=!r,r&&e++}),i.hidden=e===0,o+=e}n&&(n.hidden=o>0)});</script> <script type="module">const s=new Map;document.querySelectorAll('.doc-toc a[href^="#"]').forEach(t=>s.set(decodeURIComponent(t.hash.slice(1)),t));if(s.size>0){const t=new Set,n=()=>{let o=null;for(const e of s.keys())if(t.has(e)){o=e;break}s.forEach((e,c)=>e.classList.toggle("active",c===o))},r=new IntersectionObserver(o=>{for(const e of o)e.isIntersecting?t.add(e.target.id):t.delete(e.target.id);n()},{rootMargin:"-72px 0px -60% 0px"});s.forEach((o,e)=>{const c=document.getElementById(e);c&&r.observe(c)})}</script> <script type="module">document.querySelector('.studio__nav [aria-current="page"]')?.scrollIntoView({block:"nearest",inline:"center"});</script> </body></html>