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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (642) hide show
  1. package/README.md +64 -89
  2. package/dist/assurance/.generated/conformance-verdicts.d.ts +68 -1
  3. package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
  4. package/dist/assurance/.generated/conformance-verdicts.js +68 -1
  5. package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
  6. package/dist/bridge/client/dispatch.d.ts +25 -19
  7. package/dist/bridge/client/dispatch.d.ts.map +1 -1
  8. package/dist/bridge/client/dispatch.js +41 -48
  9. package/dist/bridge/client/dispatch.js.map +1 -1
  10. package/dist/bridge/client/tool-family-factories.d.ts +26 -0
  11. package/dist/bridge/client/tool-family-factories.d.ts.map +1 -0
  12. package/dist/bridge/client/tool-family-factories.js +10 -0
  13. package/dist/bridge/client/tool-family-factories.js.map +1 -0
  14. package/dist/bridge/server/mcp-contract.d.ts +7 -6
  15. package/dist/bridge/server/mcp-contract.d.ts.map +1 -1
  16. package/dist/bridge/server/mcp-contract.js +9 -48
  17. package/dist/bridge/server/mcp-contract.js.map +1 -1
  18. package/dist/bridge/server/peer.d.ts +11 -1
  19. package/dist/bridge/server/peer.d.ts.map +1 -1
  20. package/dist/bridge/server/peer.js +22 -1
  21. package/dist/bridge/server/peer.js.map +1 -1
  22. package/dist/bridge/server/tool-family-factories.d.ts +30 -0
  23. package/dist/bridge/server/tool-family-factories.d.ts.map +1 -0
  24. package/dist/bridge/server/tool-family-factories.js +22 -0
  25. package/dist/bridge/server/tool-family-factories.js.map +1 -0
  26. package/dist/bridge/server/tool-metadata.d.ts +17 -18
  27. package/dist/bridge/server/tool-metadata.d.ts.map +1 -1
  28. package/dist/bridge/server/tool-metadata.js +24 -59
  29. package/dist/bridge/server/tool-metadata.js.map +1 -1
  30. package/dist/bridge/tool-families.d.ts +48 -0
  31. package/dist/bridge/tool-families.d.ts.map +1 -0
  32. package/dist/bridge/tool-families.generated.d.ts +32 -0
  33. package/dist/bridge/tool-families.generated.d.ts.map +1 -0
  34. package/dist/bridge/tool-families.generated.js +15 -0
  35. package/dist/bridge/tool-families.generated.js.map +1 -0
  36. package/dist/bridge/tool-families.js +51 -0
  37. package/dist/bridge/tool-families.js.map +1 -0
  38. package/dist/bridge/tool-family-records/conformance.d.ts +7 -0
  39. package/dist/bridge/tool-family-records/conformance.d.ts.map +1 -0
  40. package/dist/bridge/tool-family-records/conformance.js +6 -0
  41. package/dist/bridge/tool-family-records/conformance.js.map +1 -0
  42. package/dist/bridge/tool-family-records/firestore-data.d.ts +7 -0
  43. package/dist/bridge/tool-family-records/firestore-data.d.ts.map +1 -0
  44. package/dist/bridge/tool-family-records/firestore-data.js +15 -0
  45. package/dist/bridge/tool-family-records/firestore-data.js.map +1 -0
  46. package/dist/bridge/tool-family-records/firestore-inspect.d.ts +7 -0
  47. package/dist/bridge/tool-family-records/firestore-inspect.d.ts.map +1 -0
  48. package/dist/bridge/tool-family-records/firestore-inspect.js +6 -0
  49. package/dist/bridge/tool-family-records/firestore-inspect.js.map +1 -0
  50. package/dist/bridge/tool-family-records/firestore-rules.d.ts +7 -0
  51. package/dist/bridge/tool-family-records/firestore-rules.d.ts.map +1 -0
  52. package/dist/bridge/tool-family-records/firestore-rules.js +15 -0
  53. package/dist/bridge/tool-family-records/firestore-rules.js.map +1 -0
  54. package/dist/bridge/tool-family-records/firestore-simulator.d.ts +7 -0
  55. package/dist/bridge/tool-family-records/firestore-simulator.d.ts.map +1 -0
  56. package/dist/bridge/tool-family-records/firestore-simulator.js +16 -0
  57. package/dist/bridge/tool-family-records/firestore-simulator.js.map +1 -0
  58. package/dist/bridge/tool-family-records/rtdb-inspection.d.ts +7 -0
  59. package/dist/bridge/tool-family-records/rtdb-inspection.d.ts.map +1 -0
  60. package/dist/bridge/tool-family-records/rtdb-inspection.js +6 -0
  61. package/dist/bridge/tool-family-records/rtdb-inspection.js.map +1 -0
  62. package/dist/bundler/externals.d.ts +37 -0
  63. package/dist/bundler/externals.d.ts.map +1 -0
  64. package/dist/bundler/externals.js +52 -0
  65. package/dist/bundler/externals.js.map +1 -0
  66. package/dist/bundler/index.d.ts +17 -0
  67. package/dist/bundler/index.d.ts.map +1 -0
  68. package/dist/bundler/index.js +17 -0
  69. package/dist/bundler/index.js.map +1 -0
  70. package/dist/cli/index.d.ts +2 -2
  71. package/dist/cli/index.d.ts.map +1 -1
  72. package/dist/cli/index.js +48 -42
  73. package/dist/cli/index.js.map +1 -1
  74. package/dist/cli/inlined-sdk-scanner.d.ts +6 -0
  75. package/dist/cli/inlined-sdk-scanner.d.ts.map +1 -0
  76. package/dist/cli/inlined-sdk-scanner.js +82 -0
  77. package/dist/cli/inlined-sdk-scanner.js.map +1 -0
  78. package/dist/cli/mcp-proxy.js +3 -3
  79. package/dist/cli/mcp-proxy.js.map +1 -1
  80. package/dist/cli/parse-args.d.ts +1 -1
  81. package/dist/cli/parse-args.d.ts.map +1 -1
  82. package/dist/cli/parse-args.js +51 -15
  83. package/dist/cli/parse-args.js.map +1 -1
  84. package/dist/cli/pyric-config.d.ts +24 -0
  85. package/dist/cli/pyric-config.d.ts.map +1 -0
  86. package/dist/cli/pyric-config.js +28 -0
  87. package/dist/cli/pyric-config.js.map +1 -0
  88. package/dist/cli/sandbox-interlock.d.ts +97 -0
  89. package/dist/cli/sandbox-interlock.d.ts.map +1 -0
  90. package/dist/cli/sandbox-interlock.js +112 -0
  91. package/dist/cli/sandbox-interlock.js.map +1 -0
  92. package/dist/cli/{dev-runner.d.ts → sandbox-runner.d.ts} +53 -48
  93. package/dist/cli/sandbox-runner.d.ts.map +1 -0
  94. package/dist/cli/{dev-runner.js → sandbox-runner.js} +105 -67
  95. package/dist/cli/sandbox-runner.js.map +1 -0
  96. package/dist/cli/serve.d.ts +12 -14
  97. package/dist/cli/serve.d.ts.map +1 -1
  98. package/dist/cli/serve.js +155 -116
  99. package/dist/cli/serve.js.map +1 -1
  100. package/dist/cli/snapshot.js +5 -5
  101. package/dist/cli/snapshot.js.map +1 -1
  102. package/dist/cli/unsupported-runtime.d.ts +27 -0
  103. package/dist/cli/unsupported-runtime.d.ts.map +1 -0
  104. package/dist/cli/unsupported-runtime.js +63 -0
  105. package/dist/cli/unsupported-runtime.js.map +1 -0
  106. package/dist/cli/verify.js +1 -1
  107. package/dist/cli/verify.js.map +1 -1
  108. package/dist/conformance/.generated/can-i-use-browser.d.ts +1 -1
  109. package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
  110. package/dist/conformance/.generated/can-i-use-browser.js +1 -1
  111. package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
  112. package/dist/conformance/.generated/can-i-use.d.ts +1 -1
  113. package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
  114. package/dist/conformance/.generated/can-i-use.js +1 -1
  115. package/dist/conformance/.generated/can-i-use.js.map +1 -1
  116. package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
  117. package/dist/conformance/.generated/conformance-docs.js +1 -1
  118. package/dist/conformance/.generated/conformance-docs.js.map +1 -1
  119. package/dist/functions-rtdb/child.d.ts +37 -0
  120. package/dist/functions-rtdb/child.d.ts.map +1 -1
  121. package/dist/functions-rtdb/child.js +90 -21
  122. package/dist/functions-rtdb/child.js.map +1 -1
  123. package/dist/functions-rtdb/development-runtime.d.ts +3 -0
  124. package/dist/functions-rtdb/development-runtime.d.ts.map +1 -1
  125. package/dist/functions-rtdb/development-runtime.js +2 -1
  126. package/dist/functions-rtdb/development-runtime.js.map +1 -1
  127. package/dist/functions-rtdb/project.js +8 -8
  128. package/dist/functions-rtdb/project.js.map +1 -1
  129. package/dist/google-endpoints.d.ts +67 -0
  130. package/dist/google-endpoints.d.ts.map +1 -0
  131. package/dist/google-endpoints.js +119 -0
  132. package/dist/google-endpoints.js.map +1 -0
  133. package/dist/next/guard.js +1 -1
  134. package/dist/next/guard.js.map +1 -1
  135. package/dist/next/runtime-env.d.ts.map +1 -1
  136. package/dist/next/runtime-env.js +5 -0
  137. package/dist/next/runtime-env.js.map +1 -1
  138. package/dist/next/with-pyric.d.ts +1 -1
  139. package/dist/next/with-pyric.js +1 -1
  140. package/dist/register/beacon.d.ts +69 -0
  141. package/dist/register/beacon.d.ts.map +1 -0
  142. package/dist/register/beacon.js +199 -0
  143. package/dist/register/beacon.js.map +1 -0
  144. package/dist/register/index.d.ts.map +1 -1
  145. package/dist/register/index.js +65 -6
  146. package/dist/register/index.js.map +1 -1
  147. package/dist/register/net-guard.d.ts +110 -0
  148. package/dist/register/net-guard.d.ts.map +1 -0
  149. package/dist/register/net-guard.js +462 -0
  150. package/dist/register/net-guard.js.map +1 -0
  151. package/dist/remote/index.d.ts +1 -1
  152. package/dist/remote/index.js +9 -9
  153. package/dist/remote/index.js.map +1 -1
  154. package/dist/serve/ai-diagnostics-relay.d.ts +63 -0
  155. package/dist/serve/ai-diagnostics-relay.d.ts.map +1 -0
  156. package/dist/serve/ai-diagnostics-relay.js +125 -0
  157. package/dist/serve/ai-diagnostics-relay.js.map +1 -0
  158. package/dist/serve/ai-proxy.d.ts +92 -0
  159. package/dist/serve/ai-proxy.d.ts.map +1 -0
  160. package/dist/serve/ai-proxy.js +269 -0
  161. package/dist/serve/ai-proxy.js.map +1 -0
  162. package/dist/serve/ai-status.d.ts +44 -0
  163. package/dist/serve/ai-status.d.ts.map +1 -0
  164. package/dist/serve/ai-status.js +77 -0
  165. package/dist/serve/ai-status.js.map +1 -0
  166. package/dist/serve/ai-terminal-blocks.d.ts +97 -0
  167. package/dist/serve/ai-terminal-blocks.d.ts.map +1 -0
  168. package/dist/serve/ai-terminal-blocks.js +128 -0
  169. package/dist/serve/ai-terminal-blocks.js.map +1 -0
  170. package/dist/serve/ai-terminal-text.d.ts +36 -0
  171. package/dist/serve/ai-terminal-text.d.ts.map +1 -0
  172. package/dist/serve/ai-terminal-text.js +48 -0
  173. package/dist/serve/ai-terminal-text.js.map +1 -0
  174. package/dist/serve/beacon-route.d.ts +53 -0
  175. package/dist/serve/beacon-route.d.ts.map +1 -0
  176. package/dist/serve/beacon-route.js +101 -0
  177. package/dist/serve/beacon-route.js.map +1 -0
  178. package/dist/serve/bundler.js +10 -10
  179. package/dist/serve/bundler.js.map +1 -1
  180. package/dist/serve/entries/active-auth-registry.d.ts +16 -0
  181. package/dist/serve/entries/active-auth-registry.d.ts.map +1 -0
  182. package/dist/serve/entries/active-auth-registry.js +48 -0
  183. package/dist/serve/entries/active-auth-registry.js.map +1 -0
  184. package/dist/serve/entries/active-auth.d.ts +18 -0
  185. package/dist/serve/entries/active-auth.d.ts.map +1 -0
  186. package/dist/serve/entries/active-auth.js +84 -0
  187. package/dist/serve/entries/active-auth.js.map +1 -0
  188. package/dist/serve/entries/ai.d.ts.map +1 -1
  189. package/dist/serve/entries/ai.js +27 -1
  190. package/dist/serve/entries/ai.js.map +1 -1
  191. package/dist/serve/entries/auth-helper-core.d.ts +1 -0
  192. package/dist/serve/entries/auth-helper-core.d.ts.map +1 -1
  193. package/dist/serve/entries/auth-helper-core.js +4 -0
  194. package/dist/serve/entries/auth-helper-core.js.map +1 -1
  195. package/dist/serve/entries/auth-helper-dom.d.ts.map +1 -1
  196. package/dist/serve/entries/auth-helper-dom.js +29 -3
  197. package/dist/serve/entries/auth-helper-dom.js.map +1 -1
  198. package/dist/serve/entries/auth-helper-runtime.js +1 -1
  199. package/dist/serve/entries/auth-helper-runtime.js.map +1 -1
  200. package/dist/serve/entries/auth.d.ts.map +1 -1
  201. package/dist/serve/entries/auth.js +8 -0
  202. package/dist/serve/entries/auth.js.map +1 -1
  203. package/dist/serve/entries/bridge-url.d.ts +1 -1
  204. package/dist/serve/entries/bridge-url.js +1 -1
  205. package/dist/serve/entries/firestore.js +3 -3
  206. package/dist/serve/entries/firestore.js.map +1 -1
  207. package/dist/serve/entries/init.d.ts.map +1 -1
  208. package/dist/serve/entries/init.js +70 -4
  209. package/dist/serve/entries/init.js.map +1 -1
  210. package/dist/serve/entries/keepalive.js +1 -1
  211. package/dist/serve/entries/keepalive.js.map +1 -1
  212. package/dist/serve/entries/runtime.d.ts.map +1 -1
  213. package/dist/serve/entries/runtime.js +30 -14
  214. package/dist/serve/entries/runtime.js.map +1 -1
  215. package/dist/serve/entries/storage.js +1 -1
  216. package/dist/serve/entries/storage.js.map +1 -1
  217. package/dist/serve/entries/worker-runtime.js +1 -1
  218. package/dist/serve/entries/worker-runtime.js.map +1 -1
  219. package/dist/serve/init-payload.d.ts +4 -0
  220. package/dist/serve/init-payload.d.ts.map +1 -1
  221. package/dist/serve/namespace.d.ts +20 -5
  222. package/dist/serve/namespace.d.ts.map +1 -1
  223. package/dist/serve/namespace.js +93 -129
  224. package/dist/serve/namespace.js.map +1 -1
  225. package/dist/serve/rules.d.ts.map +1 -1
  226. package/dist/serve/rules.js +44 -21
  227. package/dist/serve/rules.js.map +1 -1
  228. package/dist/serve/runtime/chip-config.d.ts.map +1 -1
  229. package/dist/serve/runtime/chip-config.js +16 -2
  230. package/dist/serve/runtime/chip-config.js.map +1 -1
  231. package/dist/serve/runtime/chip-dialog.d.ts +18 -0
  232. package/dist/serve/runtime/chip-dialog.d.ts.map +1 -0
  233. package/dist/serve/runtime/chip-dialog.js +315 -0
  234. package/dist/serve/runtime/chip-dialog.js.map +1 -0
  235. package/dist/serve/runtime/chip-install.d.ts +2 -0
  236. package/dist/serve/runtime/chip-install.d.ts.map +1 -1
  237. package/dist/serve/runtime/chip-install.js +9 -4
  238. package/dist/serve/runtime/chip-install.js.map +1 -1
  239. package/dist/serve/runtime/chip-user-search.d.ts +16 -0
  240. package/dist/serve/runtime/chip-user-search.d.ts.map +1 -0
  241. package/dist/serve/runtime/chip-user-search.js +354 -0
  242. package/dist/serve/runtime/chip-user-search.js.map +1 -0
  243. package/dist/serve/runtime/chip.d.ts +10 -0
  244. package/dist/serve/runtime/chip.d.ts.map +1 -1
  245. package/dist/serve/runtime/chip.js +149 -15
  246. package/dist/serve/runtime/chip.js.map +1 -1
  247. package/dist/serve/runtime/identity.d.ts +17 -0
  248. package/dist/serve/runtime/identity.d.ts.map +1 -0
  249. package/dist/serve/runtime/identity.js +10 -0
  250. package/dist/serve/runtime/identity.js.map +1 -0
  251. package/dist/serve/runtime/manifest.d.ts +1 -1
  252. package/dist/serve/runtime/manifest.d.ts.map +1 -1
  253. package/dist/serve/runtime/manifest.js +1 -1
  254. package/dist/serve/runtime/manifest.js.map +1 -1
  255. package/dist/serve/runtime/status.d.ts.map +1 -1
  256. package/dist/serve/runtime/status.js +23 -0
  257. package/dist/serve/runtime/status.js.map +1 -1
  258. package/dist/serve/sandbox-session.d.ts +8 -0
  259. package/dist/serve/sandbox-session.d.ts.map +1 -1
  260. package/dist/serve/sandbox-session.js +12 -4
  261. package/dist/serve/sandbox-session.js.map +1 -1
  262. package/dist/serve/server.d.ts +7 -0
  263. package/dist/serve/server.d.ts.map +1 -1
  264. package/dist/serve/server.js +15 -1
  265. package/dist/serve/server.js.map +1 -1
  266. package/dist/serve/site-ui/404.html +1 -1
  267. package/dist/serve/site-ui/_astro/{RulesCodeEditor.Bl-XMkhD.js → RulesCodeEditor.DsTAsKIa.js} +1 -1
  268. package/dist/serve/site-ui/_astro/_slug_.Da5VLhW1.css +1 -0
  269. package/dist/serve/site-ui/_astro/_studio_.BnfYCKoI.css +1 -0
  270. package/dist/serve/site-ui/_astro/app.BOr2kwae.js +115 -0
  271. package/dist/serve/site-ui/_astro/app.DhAcImFD.js +1 -0
  272. package/dist/serve/site-ui/_astro/app.pMSnN6Qw.css +1 -0
  273. package/dist/serve/site-ui/_astro/{chess-showcase.Dh5D8kqe.js → chess-showcase.Bn_pP6UJ.js} +2 -2
  274. package/dist/serve/site-ui/_astro/{example-runtime.CuyAjjiG.js → example-runtime.CXopTGv7.js} +1 -1
  275. package/dist/serve/site-ui/_astro/index.Tb-31efc.css +1 -0
  276. package/dist/serve/site-ui/_astro/index.UkCBr-_0.css +1 -0
  277. package/dist/serve/site-ui/_astro/sandbox-controls.rOuZTOUG.js +510 -0
  278. package/dist/serve/site-ui/_astro/{seed.CSUkloMi.js → seed.03a08f9t.js} +2 -2
  279. package/dist/serve/site-ui/_astro/writes.BsPBG3dp.js +653 -0
  280. package/dist/serve/site-ui/auth/index.html +5 -3
  281. package/dist/serve/site-ui/david-east.jpg +0 -0
  282. package/dist/serve/site-ui/docs/_rhythm/index.html +6 -3
  283. package/dist/serve/site-ui/docs/_rhythm.md +1 -1
  284. package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +18 -15
  285. package/dist/serve/site-ui/docs/agent/set-up-your-agent.md +16 -16
  286. package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +6 -5
  287. package/dist/serve/site-ui/docs/agent/watch-and-review.md +1 -5
  288. package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +8 -5
  289. package/dist/serve/site-ui/docs/agent/work-with-an-agent.md +4 -4
  290. package/dist/serve/site-ui/docs/ai-compat/index.html +5 -2
  291. package/dist/serve/site-ui/docs/api-reference/index.html +13 -2
  292. package/dist/serve/site-ui/docs/api-reference.md +8 -0
  293. package/dist/serve/site-ui/docs/app-compat/index.html +5 -2
  294. package/dist/serve/site-ui/docs/auth-compat/index.html +7 -4
  295. package/dist/serve/site-ui/docs/auth-compat.md +2 -2
  296. package/dist/serve/site-ui/docs/build/ai-logic/index.html +10 -2
  297. package/dist/serve/site-ui/docs/build/ai-logic.md +6 -0
  298. package/dist/serve/site-ui/docs/build/authentication/index.html +7 -4
  299. package/dist/serve/site-ui/docs/build/authentication.md +2 -2
  300. package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +5 -2
  301. package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +5 -2
  302. package/dist/serve/site-ui/docs/build/cloud-storage/index.html +6 -3
  303. package/dist/serve/site-ui/docs/build/cloud-storage.md +1 -1
  304. package/dist/serve/site-ui/docs/build/realtime-database/index.html +9 -6
  305. package/dist/serve/site-ui/docs/build/realtime-database.md +4 -4
  306. package/dist/serve/site-ui/docs/conformance-scores/index.html +10 -3
  307. package/dist/serve/site-ui/docs/conformance-scores.md +5 -1
  308. package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +6 -3
  309. package/dist/serve/site-ui/docs/create-pyric-reference-api.md +1 -1
  310. package/dist/serve/site-ui/docs/database-compat/index.html +48 -45
  311. package/dist/serve/site-ui/docs/database-compat.md +43 -43
  312. package/dist/serve/site-ui/docs/examples/chess/index.html +5 -2
  313. package/dist/serve/site-ui/docs/examples/index.html +5 -2
  314. package/dist/serve/site-ui/docs/firestore-compat/index.html +8 -5
  315. package/dist/serve/site-ui/docs/firestore-compat.md +3 -3
  316. package/dist/serve/site-ui/docs/firestore-flutter-compat/index.html +319 -0
  317. package/dist/serve/site-ui/docs/firestore-flutter-compat.md +344 -0
  318. package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +5 -2
  319. package/dist/serve/site-ui/docs/get-started/backend-bundlers/index.html +105 -0
  320. package/dist/serve/site-ui/docs/get-started/backend-bundlers.md +165 -0
  321. package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +9 -6
  322. package/dist/serve/site-ui/docs/get-started/how-the-swap-works.md +5 -5
  323. package/dist/serve/site-ui/docs/get-started/nextjs/index.html +9 -6
  324. package/dist/serve/site-ui/docs/get-started/nextjs.md +4 -4
  325. package/dist/serve/site-ui/docs/get-started/start-building/index.html +14 -9
  326. package/dist/serve/site-ui/docs/get-started/start-building.md +16 -10
  327. package/dist/serve/site-ui/docs/get-started/vite/index.html +6 -3
  328. package/dist/serve/site-ui/docs/get-started/vite.md +1 -1
  329. package/dist/serve/site-ui/docs/index.json +3128 -1613
  330. package/dist/serve/site-ui/docs/messaging-compat/index.html +5 -2
  331. package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +5 -2
  332. package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +6 -4
  333. package/dist/serve/site-ui/docs/observe/see-whats-happening.md +2 -4
  334. package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +9 -6
  335. package/dist/serve/site-ui/docs/observe/shape-your-data.md +4 -4
  336. package/dist/serve/site-ui/docs/overview/index.html +16 -10
  337. package/dist/serve/site-ui/docs/overview.md +19 -11
  338. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +5 -2
  339. package/dist/serve/site-ui/docs/pyric-admin-auth-reference-api/index.html +5 -2
  340. package/dist/serve/site-ui/docs/pyric-admin-database-reference-api/index.html +5 -2
  341. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api/index.html +8 -5
  342. package/dist/serve/site-ui/docs/pyric-admin-firestore-reference-api.md +3 -3
  343. package/dist/serve/site-ui/docs/pyric-admin-messaging-reference-api/index.html +5 -2
  344. package/dist/serve/site-ui/docs/pyric-admin-reference-api/index.html +501 -0
  345. package/dist/serve/site-ui/docs/pyric-admin-reference-api.md +587 -0
  346. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +5 -2
  347. package/dist/serve/site-ui/docs/pyric-ai-reference-api/index.html +5 -2
  348. package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +5 -2
  349. package/dist/serve/site-ui/docs/pyric-analytics-reference-api/index.html +124 -0
  350. package/dist/serve/site-ui/docs/pyric-analytics-reference-api.md +287 -0
  351. package/dist/serve/site-ui/docs/pyric-app-check-reference-api/index.html +87 -0
  352. package/dist/serve/site-ui/docs/pyric-app-check-reference-api.md +199 -0
  353. package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +5 -2
  354. package/dist/serve/site-ui/docs/pyric-auth-reference-api/index.html +10 -3
  355. package/dist/serve/site-ui/docs/pyric-auth-reference-api.md +2 -1
  356. package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +5 -2
  357. package/dist/serve/site-ui/docs/pyric-cli-assurance-reference-api/index.html +5 -2
  358. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api/index.html +6 -3
  359. package/dist/serve/site-ui/docs/pyric-cli-bridge-client-reference-api.md +1 -1
  360. package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +5 -2
  361. package/dist/serve/site-ui/docs/pyric-cli-bundler-reference-api/index.html +56 -0
  362. package/dist/serve/site-ui/docs/pyric-cli-bundler-reference-api.md +72 -0
  363. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +6 -2
  364. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api.md +1 -0
  365. package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +5 -2
  366. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +6 -2
  367. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api.md +1 -0
  368. package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +5 -2
  369. package/dist/serve/site-ui/docs/pyric-cli-discover-reference-api/index.html +5 -2
  370. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api/index.html +6 -3
  371. package/dist/serve/site-ui/docs/pyric-cli-next-reference-api.md +1 -1
  372. package/dist/serve/site-ui/docs/pyric-cli-register-app-bridge-reference-api/index.html +5 -2
  373. package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +5 -2
  374. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api/index.html +39 -11
  375. package/dist/serve/site-ui/docs/pyric-cli-remote-reference-api.md +17 -9
  376. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api/index.html +137 -94
  377. package/dist/serve/site-ui/docs/pyric-cli-serve-worker-reference-api.md +61 -1
  378. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api/index.html +6 -3
  379. package/dist/serve/site-ui/docs/pyric-cli-verify-reference-api.md +1 -1
  380. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +6 -3
  381. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api.md +2 -2
  382. package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +167 -96
  383. package/dist/serve/site-ui/docs/pyric-database-reference-api.md +108 -2
  384. package/dist/serve/site-ui/docs/pyric-firestore-lite-reference-api/index.html +559 -0
  385. package/dist/serve/site-ui/docs/pyric-firestore-lite-reference-api.md +1240 -0
  386. package/dist/serve/site-ui/docs/pyric-firestore-reference-api/index.html +44 -12
  387. package/dist/serve/site-ui/docs/pyric-firestore-reference-api.md +18 -8
  388. package/dist/serve/site-ui/docs/pyric-functions-reference-api/index.html +67 -0
  389. package/dist/serve/site-ui/docs/pyric-functions-reference-api.md +149 -0
  390. package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +10 -4
  391. package/dist/serve/site-ui/docs/pyric-messaging-reference-api.md +5 -2
  392. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +10 -4
  393. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api.md +5 -2
  394. package/dist/serve/site-ui/docs/pyric-performance-reference-api/index.html +35 -0
  395. package/dist/serve/site-ui/docs/pyric-performance-reference-api.md +69 -0
  396. package/dist/serve/site-ui/docs/pyric-remote-config-reference-api/index.html +132 -0
  397. package/dist/serve/site-ui/docs/pyric-remote-config-reference-api.md +307 -0
  398. package/dist/serve/site-ui/docs/pyric-rules-reference-api/index.html +5 -2
  399. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +56 -18
  400. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api.md +48 -9
  401. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +6 -3
  402. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api.md +2 -2
  403. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api/index.html +243 -50
  404. package/dist/serve/site-ui/docs/pyric-sandbox-reference-api.md +148 -31
  405. package/dist/serve/site-ui/docs/pyric-storage-reference-api/index.html +26 -5
  406. package/dist/serve/site-ui/docs/pyric-storage-reference-api.md +24 -2
  407. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +30 -97
  408. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api.md +20 -51
  409. package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +5 -2
  410. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api/index.html +6 -3
  411. package/dist/serve/site-ui/docs/pyric-ui-auth-reference-api.md +1 -1
  412. package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +5 -2
  413. package/dist/serve/site-ui/docs/pyric-ui-events-reference-api/index.html +5 -2
  414. package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +5 -2
  415. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api/index.html +6 -3
  416. package/dist/serve/site-ui/docs/pyric-ui-firestore-reference-api.md +1 -1
  417. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api/index.html +128 -27
  418. package/dist/serve/site-ui/docs/pyric-ui-primitives-reference-api.md +58 -5
  419. package/dist/serve/site-ui/docs/pyric-ui-rtdb-reference-api/index.html +5 -2
  420. package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +5 -2
  421. package/dist/serve/site-ui/docs/pyric-ui-rules-reference-api/index.html +5 -2
  422. package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +5 -2
  423. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api/index.html +8 -6
  424. package/dist/serve/site-ui/docs/pyric-ui-storage-reference-api.md +3 -4
  425. package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +5 -2
  426. package/dist/serve/site-ui/docs/pyric-ui-traffic-reference-api/index.html +5 -2
  427. package/dist/serve/site-ui/docs/reference/cli/index.html +156 -0
  428. package/dist/serve/site-ui/docs/reference/cli.md +120 -0
  429. package/dist/serve/site-ui/docs/rules-compat/index.html +14 -3
  430. package/dist/serve/site-ui/docs/rules-compat.md +9 -1
  431. package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +5 -2
  432. package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +5 -2
  433. package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +6 -3
  434. package/dist/serve/site-ui/docs/secure/read-a-denial.md +1 -1
  435. package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +5 -2
  436. package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +5 -2
  437. package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +5 -2
  438. package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +5 -2
  439. package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +5 -2
  440. package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +7 -4
  441. package/dist/serve/site-ui/docs/ship/ship-to-production.md +2 -2
  442. package/dist/serve/site-ui/docs/ship/test-in-node/index.html +9 -6
  443. package/dist/serve/site-ui/docs/ship/test-in-node.md +4 -4
  444. package/dist/serve/site-ui/docs/storage-compat/index.html +17 -14
  445. package/dist/serve/site-ui/docs/storage-compat.md +12 -12
  446. package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +5 -2
  447. package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +5 -2
  448. package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +5 -2
  449. package/dist/serve/site-ui/docs/tutorial/index.html +10 -7
  450. package/dist/serve/site-ui/docs/tutorial.md +4 -4
  451. package/dist/serve/site-ui/examples/chess/index.html +4 -2
  452. package/dist/serve/site-ui/firestore/index.html +5 -3
  453. package/dist/serve/site-ui/hero-charcoal.jpg +0 -0
  454. package/dist/serve/site-ui/index.html +9 -7
  455. package/dist/serve/site-ui/llms.txt +13 -3
  456. package/dist/serve/site-ui/pyric-campfire-full.png +0 -0
  457. package/dist/serve/site-ui/pyric-campfire.png +0 -0
  458. package/dist/serve/site-ui/rtdb/index.html +5 -3
  459. package/dist/serve/site-ui/settings/index.html +5 -3
  460. package/dist/serve/site-ui/storage/index.html +5 -3
  461. package/dist/serve/site-ui/studio/index.html +13 -0
  462. package/dist/serve/site-ui/studio-routes.json +1 -1
  463. package/dist/serve/site-ui/traffic/index.html +5 -3
  464. package/dist/serve/studio/disk-workspace.d.ts.map +1 -1
  465. package/dist/serve/studio/disk-workspace.js +64 -2
  466. package/dist/serve/studio/disk-workspace.js.map +1 -1
  467. package/dist/serve/studio/routes.d.ts +9 -0
  468. package/dist/serve/studio/routes.d.ts.map +1 -1
  469. package/dist/serve/studio/routes.js +47 -7
  470. package/dist/serve/studio/routes.js.map +1 -1
  471. package/dist/serve/vite-ai-config.d.ts.map +1 -1
  472. package/dist/serve/vite-ai-config.js +38 -8
  473. package/dist/serve/vite-ai-config.js.map +1 -1
  474. package/dist/serve/vite-module-swap.d.ts.map +1 -1
  475. package/dist/serve/vite-module-swap.js +0 -28
  476. package/dist/serve/vite-module-swap.js.map +1 -1
  477. package/dist/serve/vite-plugin.d.ts +7 -7
  478. package/dist/serve/vite-plugin.js +1 -1
  479. package/dist/serve/vite-plugin.js.map +1 -1
  480. package/dist/serve/vite-sandbox-generation.d.ts +1 -1
  481. package/dist/serve/vite-sandbox-generation.d.ts.map +1 -1
  482. package/dist/serve/vite-sandbox-generation.js +13 -1
  483. package/dist/serve/vite-sandbox-generation.js.map +1 -1
  484. package/dist/serve/worker/client/auth.js +1 -2
  485. package/dist/serve/worker/client/auth.js.map +1 -1
  486. package/dist/serve/worker/client/core.d.ts +21 -1
  487. package/dist/serve/worker/client/core.d.ts.map +1 -1
  488. package/dist/serve/worker/client/core.js +79 -3
  489. package/dist/serve/worker/client/core.js.map +1 -1
  490. package/dist/serve/worker/client/disconnect.js +1 -1
  491. package/dist/serve/worker/client/disconnect.js.map +1 -1
  492. package/dist/serve/worker/client/presence.d.ts.map +1 -1
  493. package/dist/serve/worker/client/presence.js +18 -5
  494. package/dist/serve/worker/client/presence.js.map +1 -1
  495. package/dist/serve/worker/client.d.ts +1 -1
  496. package/dist/serve/worker/client.d.ts.map +1 -1
  497. package/dist/serve/worker/client.js +1 -1
  498. package/dist/serve/worker/client.js.map +1 -1
  499. package/dist/serve/worker/context-resolver.d.ts +30 -0
  500. package/dist/serve/worker/context-resolver.d.ts.map +1 -0
  501. package/dist/serve/worker/context-resolver.js +44 -0
  502. package/dist/serve/worker/context-resolver.js.map +1 -0
  503. package/dist/serve/worker/entry.js +23 -19
  504. package/dist/serve/worker/entry.js.map +1 -1
  505. package/dist/serve/worker/host/core.d.ts +1 -0
  506. package/dist/serve/worker/host/core.d.ts.map +1 -1
  507. package/dist/serve/worker/host/core.js +12 -6
  508. package/dist/serve/worker/host/core.js.map +1 -1
  509. package/dist/serve/worker/host/storage.js +2 -2
  510. package/dist/serve/worker/host-ai.d.ts.map +1 -1
  511. package/dist/serve/worker/host-ai.js +15 -0
  512. package/dist/serve/worker/host-ai.js.map +1 -1
  513. package/dist/serve/worker/host-auth.js +1 -2
  514. package/dist/serve/worker/host-auth.js.map +1 -1
  515. package/dist/serve/worker/index.d.ts +1 -1
  516. package/dist/serve/worker/index.d.ts.map +1 -1
  517. package/dist/serve/worker/index.js +2 -2
  518. package/dist/serve/worker/index.js.map +1 -1
  519. package/dist/serve/worker/port-lifecycle.d.ts +18 -0
  520. package/dist/serve/worker/port-lifecycle.d.ts.map +1 -0
  521. package/dist/serve/worker/port-lifecycle.js +28 -0
  522. package/dist/serve/worker/port-lifecycle.js.map +1 -0
  523. package/dist/serve/worker/protocol.d.ts +4 -0
  524. package/dist/serve/worker/protocol.d.ts.map +1 -1
  525. package/dist/serve/worker/protocol.js.map +1 -1
  526. package/dist/serve/worker/serve-init.d.ts.map +1 -1
  527. package/dist/serve/worker/serve-init.js +15 -3
  528. package/dist/serve/worker/serve-init.js.map +1 -1
  529. package/dist/verify/fixture.d.ts +1 -1
  530. package/package.json +17 -6
  531. package/src/assurance/.generated/conformance-verdicts.ts +68 -1
  532. package/src/bridge/client/dispatch.ts +52 -56
  533. package/src/bridge/client/tool-family-factories.ts +34 -0
  534. package/src/bridge/server/mcp-contract.ts +15 -59
  535. package/src/bridge/server/peer.ts +24 -1
  536. package/src/bridge/server/tool-family-factories.ts +40 -0
  537. package/src/bridge/server/tool-metadata.ts +29 -61
  538. package/src/bridge/tool-families.generated.ts +17 -0
  539. package/src/bridge/tool-families.ts +87 -0
  540. package/src/bridge/tool-family-records/conformance.ts +6 -0
  541. package/src/bridge/tool-family-records/firestore-data.ts +15 -0
  542. package/src/bridge/tool-family-records/firestore-inspect.ts +6 -0
  543. package/src/bridge/tool-family-records/firestore-rules.ts +15 -0
  544. package/src/bridge/tool-family-records/firestore-simulator.ts +16 -0
  545. package/src/bridge/tool-family-records/rtdb-inspection.ts +6 -0
  546. package/src/bundler/externals.ts +55 -0
  547. package/src/bundler/index.ts +21 -0
  548. package/src/cli/cli.test.ts +2 -46
  549. package/src/cli/index.ts +48 -42
  550. package/src/cli/inlined-sdk-scanner.ts +77 -0
  551. package/src/cli/mcp-proxy.ts +4 -4
  552. package/src/cli/parse-args.ts +61 -15
  553. package/src/cli/pyric-config.ts +45 -0
  554. package/src/cli/sandbox-interlock.ts +167 -0
  555. package/src/cli/{dev-runner.ts → sandbox-runner.ts} +142 -86
  556. package/src/cli/serve.ts +182 -115
  557. package/src/cli/snapshot.ts +5 -5
  558. package/src/cli/unsupported-runtime.ts +68 -0
  559. package/src/cli/verify.ts +1 -1
  560. package/src/conformance/.generated/can-i-use-browser.ts +2 -2
  561. package/src/conformance/.generated/can-i-use.ts +2 -2
  562. package/src/conformance/.generated/conformance-docs.ts +1 -1
  563. package/src/functions-rtdb/child.ts +115 -21
  564. package/src/functions-rtdb/development-runtime.ts +5 -1
  565. package/src/functions-rtdb/project.ts +8 -8
  566. package/src/google-endpoints.ts +155 -0
  567. package/src/next/guard.ts +1 -1
  568. package/src/next/runtime-env.ts +5 -0
  569. package/src/next/with-pyric.ts +1 -1
  570. package/src/register/beacon.ts +232 -0
  571. package/src/register/index.ts +68 -6
  572. package/src/register/net-guard.ts +567 -0
  573. package/src/remote/index.ts +9 -9
  574. package/src/serve/ai-diagnostics-relay.ts +243 -0
  575. package/src/serve/ai-proxy.ts +327 -0
  576. package/src/serve/ai-status.ts +109 -0
  577. package/src/serve/ai-terminal-blocks.ts +210 -0
  578. package/src/serve/ai-terminal-text.ts +52 -0
  579. package/src/serve/beacon-route.ts +141 -0
  580. package/src/serve/bundler.ts +10 -10
  581. package/src/serve/entries/active-auth-registry.ts +56 -0
  582. package/src/serve/entries/active-auth.ts +100 -0
  583. package/src/serve/entries/ai.ts +27 -1
  584. package/src/serve/entries/auth-helper-core.ts +5 -0
  585. package/src/serve/entries/auth-helper-dom.ts +27 -3
  586. package/src/serve/entries/auth-helper-runtime.ts +1 -1
  587. package/src/serve/entries/auth.ts +8 -0
  588. package/src/serve/entries/bridge-url.ts +1 -1
  589. package/src/serve/entries/firestore.ts +3 -3
  590. package/src/serve/entries/init.ts +78 -3
  591. package/src/serve/entries/keepalive.ts +1 -1
  592. package/src/serve/entries/runtime.ts +29 -14
  593. package/src/serve/entries/storage.ts +1 -1
  594. package/src/serve/entries/worker-runtime.ts +1 -1
  595. package/src/serve/init-payload.ts +4 -0
  596. package/src/serve/namespace.ts +117 -145
  597. package/src/serve/rules.ts +47 -22
  598. package/src/serve/runtime/chip-config.ts +16 -2
  599. package/src/serve/runtime/chip-dialog.ts +366 -0
  600. package/src/serve/runtime/chip-install.ts +10 -4
  601. package/src/serve/runtime/chip-user-search.ts +391 -0
  602. package/src/serve/runtime/chip.ts +177 -15
  603. package/src/serve/runtime/identity.ts +26 -0
  604. package/src/serve/runtime/manifest.ts +1 -1
  605. package/src/serve/runtime/status.ts +24 -0
  606. package/src/serve/sandbox-session.ts +19 -4
  607. package/src/serve/server.ts +18 -1
  608. package/src/serve/studio/disk-workspace.ts +76 -2
  609. package/src/serve/studio/routes.ts +63 -7
  610. package/src/serve/vite-ai-config.ts +37 -7
  611. package/src/serve/vite-module-swap.ts +0 -28
  612. package/src/serve/vite-plugin.ts +8 -8
  613. package/src/serve/vite-sandbox-generation.ts +16 -1
  614. package/src/serve/worker/client/auth.ts +1 -1
  615. package/src/serve/worker/client/core.ts +80 -3
  616. package/src/serve/worker/client/disconnect.ts +1 -1
  617. package/src/serve/worker/client/presence.ts +25 -5
  618. package/src/serve/worker/client.ts +1 -1
  619. package/src/serve/worker/context-resolver.ts +60 -0
  620. package/src/serve/worker/entry.ts +22 -18
  621. package/src/serve/worker/host/core.ts +9 -7
  622. package/src/serve/worker/host/storage.ts +2 -2
  623. package/src/serve/worker/host-ai.ts +15 -0
  624. package/src/serve/worker/host-auth.ts +1 -1
  625. package/src/serve/worker/index.ts +4 -1
  626. package/src/serve/worker/port-lifecycle.ts +45 -0
  627. package/src/serve/worker/protocol.ts +2 -1
  628. package/src/serve/worker/serve-init.ts +14 -3
  629. package/src/verify/fixture.ts +1 -1
  630. package/README.md.orig +0 -145
  631. package/dist/cli/dev-runner.d.ts.map +0 -1
  632. package/dist/cli/dev-runner.js.map +0 -1
  633. package/dist/serve/site-ui/_astro/_slug_.CXh9yTP1.css +0 -1
  634. package/dist/serve/site-ui/_astro/_slug_.CupVK4TM.css +0 -1
  635. package/dist/serve/site-ui/_astro/_studio_.CfxiQWkk.css +0 -1
  636. package/dist/serve/site-ui/_astro/app.BsFsMjn0.css +0 -1
  637. package/dist/serve/site-ui/_astro/app.Ce3MTLQm.js +0 -1
  638. package/dist/serve/site-ui/_astro/app.taqzyjD0.js +0 -11
  639. package/dist/serve/site-ui/_astro/sandbox-controls.BP4M5f1M.js +0 -1169
  640. package/dist/serve/site-ui/_astro/writes.C57paAj2.js +0 -99
  641. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +0 -582
  642. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research.md +0 -448
@@ -1,5 +1,8 @@
1
- <!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>pyric/database compatibility matrix · Pyric Studio</title><link rel="icon" type="image/svg+xml" href="/__pyric/ui/pyric-logo.svg"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet"><link rel="stylesheet" href="/__pyric/ui/_astro/_slug_.CXh9yTP1.css">
2
- <link rel="stylesheet" href="/__pyric/ui/_astro/_slug_.CupVK4TM.css"></head> <body> <header class="studio__bar" data-astro-cid-mw7aashj> <div class="studio__bar-inner" data-astro-cid-mw7aashj> <a class="studio__brand" href="/__pyric/ui/" aria-label="Pyric Studio" data-astro-cid-mw7aashj>Pyric</a> <nav class="studio__nav" aria-label="Studio tabs" data-astro-cid-mw7aashj> <a class="studio__nav-tab" href="/__pyric/ui/" data-astro-cid-mw7aashj> Home </a><a class="studio__nav-tab" href="/__pyric/ui/firestore" data-astro-cid-mw7aashj> Firestore </a><a class="studio__nav-tab" href="/__pyric/ui/auth" data-astro-cid-mw7aashj> Auth </a><a class="studio__nav-tab" href="/__pyric/ui/rtdb" data-astro-cid-mw7aashj> RTDB </a><a class="studio__nav-tab" href="/__pyric/ui/storage" data-astro-cid-mw7aashj> Storage </a><a class="studio__nav-tab" href="/__pyric/ui/traffic" data-astro-cid-mw7aashj> Traffic </a><a class="studio__nav-tab" href="/__pyric/ui/settings" data-astro-cid-mw7aashj> Settings </a><a class="studio__nav-tab" href="/__pyric/ui/docs" aria-current="page" data-astro-cid-mw7aashj> Docs </a> </nav> </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/storage-rules-stdlib-research/"> Storage Rules modules: evidence and design </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" open> <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/" aria-current="page"> 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"> <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/"> 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-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> </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/storage-rules-stdlib-research/"> Storage Rules modules: evidence and design </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" open> <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/" aria-current="page"> 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"> <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/"> 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-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> </details> </nav> <main class="doc-main" data-astro-cid-mw7aashj> <nav class="docs-breadcrumbs" aria-label="Breadcrumb"> <ol> <li> <a href="/__pyric/ui/docs/conformance-scores/">Conformance</a> </li><li> <span class="docs-breadcrumbs-sep" aria-hidden="true">/</span> <span aria-current="page">Realtime Database</span> </li> </ol> </nav> <article class="prose" data-astro-cid-mw7aashj> <!-- Generated from the conformance model (registry rows + surface contracts). Do not edit by hand; run bun run compat:generate. -->
1
+ <!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover"><title>pyric/database compatibility matrix · Pyric Studio</title><link rel="icon" type="image/svg+xml" href="/__pyric/ui/pyric-logo.svg"><link rel="preconnect" href="https://use.typekit.net" crossorigin><link rel="stylesheet" href="https://use.typekit.net/jwb3ycu.css"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet"><link rel="stylesheet" href="/__pyric/ui/_astro/index.UkCBr-_0.css">
2
+ <link rel="stylesheet" href="/__pyric/ui/_astro/_slug_.Da5VLhW1.css">
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
+ 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/backend-bundlers/"> Backend bundlers </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" open> <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/" aria-current="page"> 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> </ul> </div> </div> </details> <details class="docs-nav-group"> <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/"> 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/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" open> <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/" aria-current="page"> 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> </ul> </div> </div> </details> <details class="docs-nav-group" id="nav-group-reference"> <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/"> 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/conformance-scores/">Conformance</a> </li><li> <span class="docs-breadcrumbs-sep" aria-hidden="true">/</span> <span aria-current="page">Realtime Database</span> </li> </ol> </nav> <article class="prose" data-astro-cid-mw7aashj> <!-- Generated from the conformance model (registry rows + surface contracts). Do not edit by hand; run bun run compat:generate. -->
3
6
  <h1 id="pyricdatabase-compatibility-matrix"><code>pyric/database</code> compatibility matrix</h1>
4
7
  <div class="compat-stat">
5
8
  <p class="compat-stat-figure">
@@ -53,15 +56,15 @@
53
56
  </details>
54
57
  <details class="compat-row" data-status="ok">
55
58
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>set(ref, value)</code> replaces the value at the path</span></span></summary>
56
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L119" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("round-trips a primitive value" + "round-trips nested objects"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json</code></a> (prod observation blocked on rules; sandbox locks the contract directly)</div></div>
59
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L120" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("round-trips a primitive value" + "round-trips nested objects"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json</code></a> (prod observation blocked on rules; sandbox locks the contract directly)</div></div>
57
60
  </details>
58
61
  <details class="compat-row" data-status="ok">
59
62
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>set(ref, null)</code> deletes the subtree at the path</span></span></summary>
60
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L154" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("set(ref, null) deletes the path"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json</code></a></div></div>
63
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L155" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("set(ref, null) deletes the path"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json</code></a></div></div>
61
64
  </details>
62
65
  <details class="compat-row" data-status="ok">
63
66
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>remove(ref)</code> is equivalent to <code>set(ref, null)</code> (same end state)</span></span></summary>
64
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L154" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("remove and set(null) produce identical end-state"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json</code></a></div></div>
67
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L155" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("remove and set(null) produce identical end-state"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-remove-vs-set-null.json</code></a></div></div>
65
68
  </details>
66
69
  <details class="compat-row" data-status="ok">
67
70
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>update(ref, patch)</code> shallow-merges top-level keys at the ref's path</span></span></summary>
@@ -81,7 +84,7 @@
81
84
  </details>
82
85
  <details class="compat-row" data-status="ok">
83
86
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>push(ref)</code> mints a 20-char auto-id key starting with <code>-</code>, lexicographically sortable</span></span></summary>
84
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L340" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("mints 20-char keys starting with \"-\"" + "sequential push keys are lex-sortable"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-push-autoid-format.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-push-autoid-format.json</code></a></div></div>
87
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L341" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("mints 20-char keys starting with \"-\"" + "sequential push keys are lex-sortable"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-push-autoid-format.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-push-autoid-format.json</code></a></div></div>
85
88
  </details>
86
89
  <details class="compat-row" data-status="ok">
87
90
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>push(ref, value)</code> writes <code>value</code> at the new child path</span></span></summary>
@@ -97,7 +100,7 @@
97
100
  </details>
98
101
  <details class="compat-row" data-status="ok">
99
102
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>serverTimestamp()</code> resolves to a number (epoch ms) on read-back</span></span></summary>
100
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L376" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("resolves to a number on read-back"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-servertimestamp-resolves.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-servertimestamp-resolves.json</code></a> (prod observation blocked on rules; sandbox locks the contract directly)</div></div>
103
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L377" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("resolves to a number on read-back"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-servertimestamp-resolves.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-servertimestamp-resolves.json</code></a> (prod observation blocked on rules; sandbox locks the contract directly)</div></div>
101
104
  </details>
102
105
  <details class="compat-row" data-status="ok">
103
106
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>serverTimestamp()</code> sentinels resolve when nested inside multi-path update payloads</span></span></summary>
@@ -105,11 +108,11 @@
105
108
  </details>
106
109
  <details class="compat-row" data-status="ok">
107
110
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied write throws a plain <code>Error</code> (NOT a <code>FirebaseError</code>) with <code>.code === 'PERMISSION_DENIED'</code> (uppercase snake-case) and <code>.message === 'PERMISSION_DENIED: Permission denied'</code></span></span></summary>
108
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L407" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("rules-denied set throws a plain Error with PERMISSION_DENIED code"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json</code></a> (against blockingfun, fb-js-sdk 12.13.0)</div></div>
111
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L408" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("rules-denied set throws a plain Error with PERMISSION_DENIED code"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json</code></a> (against blockingfun, fb-js-sdk 12.13.0)</div></div>
109
112
  </details>
110
113
  <details class="compat-row" data-status="ok">
111
114
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied read throws the same plain-<code>Error</code> <code>PERMISSION_DENIED</code> shape as a denied write</span></span></summary>
112
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L407" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("rules-denied get throws the same plain Error shape"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json</code></a></div></div>
115
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L408" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("rules-denied get throws the same plain Error shape"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-rules-denied-error-code.json</code></a></div></div>
113
116
  </details>
114
117
  <details class="compat-row" data-status="ok">
115
118
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied remove throws the same plain-<code>Error</code> <code>PERMISSION_DENIED</code> shape</span></span></summary>
@@ -141,15 +144,15 @@
141
144
  </details>
142
145
  <details class="compat-row" data-status="ok">
143
146
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onChildAdded</code> replays each existing direct child of the parent ref on subscribe (one fire per existing key)</span></span></summary>
144
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-child-events.test.ts#L40" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-child-events.test.ts</code></a> ("replays existing direct children on subscribe — one fire per key"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-onchildadded-initial-replay.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchildadded-initial-replay.json</code></a> (seeded <code>{k1,k2,k3}</code>, observed <code>firedKeys: ['k1','k2','k3']</code>).</div></div>
147
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-child-events.test.ts#L41" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-child-events.test.ts</code></a> ("replays existing direct children on subscribe — one fire per key"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-onchildadded-initial-replay.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchildadded-initial-replay.json</code></a> (seeded <code>{k1,k2,k3}</code>, observed <code>firedKeys: ['k1','k2','k3']</code>).</div></div>
145
148
  </details>
146
149
  <details class="compat-row" data-status="ok">
147
150
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">After subscribe, <code>onChildAdded</code> fires exactly once per new direct child write; snapshot carries <code>{key, val}</code> of the new child</span></span></summary>
148
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-child-events.test.ts#L66" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-child-events.test.ts</code></a> ("fires exactly once per NEW direct child after subscribe"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-onchildadded-post-subscribe.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchildadded-post-subscribe.json</code></a> (<code>postSubscribeFires: 1</code>, <code>lastFire: {key:'k3', val:{v:3}}</code>).</div></div>
151
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-child-events.test.ts#L67" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-child-events.test.ts</code></a> ("fires exactly once per NEW direct child after subscribe"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-onchildadded-post-subscribe.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchildadded-post-subscribe.json</code></a> (<code>postSubscribeFires: 1</code>, <code>lastFire: {key:'k3', val:{v:3}}</code>).</div></div>
149
152
  </details>
150
153
  <details class="compat-row" data-status="ok">
151
154
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onChildChanged</code> has NO initial replay; fires once when an existing direct child's value transitions; snapshot carries the NEW value</span></span></summary>
152
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-child-events.test.ts#L99" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-child-events.test.ts</code></a> ("does NOT fire on subscribe (no initial replay)" + "fires once when an existing child transitions to a new value; snapshot carries NEW val"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-onchildchanged-fires-on-update.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchildchanged-fires-on-update.json</code></a> (<code>firedOnInitial: 0, firedOnUpdate: 1, lastFire: {key:'k1', val:{v:2}}</code>).</div></div>
155
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-child-events.test.ts#L100" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-child-events.test.ts</code></a> ("does NOT fire on subscribe (no initial replay)" + "fires once when an existing child transitions to a new value; snapshot carries NEW val"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-onchildchanged-fires-on-update.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-onchildchanged-fires-on-update.json</code></a> (<code>firedOnInitial: 0, firedOnUpdate: 1, lastFire: {key:'k1', val:{v:2}}</code>).</div></div>
153
156
  </details>
154
157
  <details class="compat-row" data-status="ok">
155
158
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onChildChanged</code> does NOT fire for added or removed children — those go to the other event listeners</span></span></summary>
@@ -157,7 +160,7 @@
157
160
  </details>
158
161
  <details class="compat-row" data-status="ok">
159
162
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onChildRemoved</code> has NO initial replay; fires once when a direct child is deleted (via <code>remove(child)</code> or <code>set(child, null)</code>); snapshot carries the PRIOR (now-removed) value</span></span></summary>
160
- <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/upstream-rtdb-probes.test.ts#L8" target="_blank" rel="noopener noreferrer"><code>unit:upstream-rtdb-probes.test.ts</code></a> (parent wipe fan-out via remove(parent) / set(parent, scalar)) + <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-child-events.test.ts#L143" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-child-events.test.ts</code></a> (single-child delete carries PRIOR val); matches oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-onchildremoved-fires-on-delete.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-onchildremoved-fires-on-delete.json</code></a></div></div>
163
+ <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/upstream-rtdb-probes.test.ts#L8" target="_blank" rel="noopener noreferrer"><code>unit:upstream-rtdb-probes.test.ts</code></a> (parent wipe fan-out via remove(parent) / set(parent, scalar)) + <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-child-events.test.ts#L144" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-child-events.test.ts</code></a> (single-child delete carries PRIOR val); matches oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-onchildremoved-fires-on-delete.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-onchildremoved-fires-on-delete.json</code></a></div></div>
161
164
  </details>
162
165
  <details class="compat-row" data-status="ok">
163
166
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">A plain-reference <code>onChildMoved</code> uses Firebase's default priority index: ordinary value changes that preserve priority do not move, while each changed child's priority emits one event even if its predecessor stays the same</span></span></summary>
@@ -165,7 +168,7 @@
165
168
  </details>
166
169
  <details class="compat-row" data-status="ok">
167
170
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>off(ref)</code> (no event type) removes ALL listeners at that ref — value + every child event variety</span></span></summary>
168
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-child-events.test.ts#L338" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-child-events.test.ts</code></a> ("off(ref) removes ALL listeners at the ref" + "off(ref) also removes value listeners at the same path"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-off-stops-child-fires.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-off-stops-child-fires.json</code></a> (<code>postOffFires: 0</code>).</div></div>
171
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-child-events.test.ts#L339" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-child-events.test.ts</code></a> ("off(ref) removes ALL listeners at the ref" + "off(ref) also removes value listeners at the same path"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-off-stops-child-fires.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-off-stops-child-fires.json</code></a> (<code>postOffFires: 0</code>).</div></div>
169
172
  </details>
170
173
  <details class="compat-row" data-status="ok">
171
174
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>off(ref, eventType?, callback?)</code> variants: <code>off(ref, 'value')</code> / <code>off(ref, 'child_added')</code> / <code>off(ref, eventType, cb)</code> remove the targeted subset; returned-unsubscribe from <code>onChild*</code> is equivalent to <code>off(ref, eventType, cb)</code></span></span></summary>
@@ -177,15 +180,15 @@
177
180
  </details>
178
181
  <details class="compat-row" data-status="ok">
179
182
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>sandbox.setRules(db, rulesJson)</code> deploys rules to the in-process simulator; <code>setRules(db, null)</code> clears rules (default-allow)</span></span></summary>
180
- <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L35" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("sandbox.setRules(db, null) clears rules")</div></div>
183
+ <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L36" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("sandbox.setRules(db, null) clears rules")</div></div>
181
184
  </details>
182
185
  <details class="compat-row" data-status="ok">
183
186
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>sandbox.setData(db, { '/path': value })</code> bulk-loads data, bypassing rules</span></span></summary>
184
- <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L585" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("sandbox.setData seeds the tree (rule-bypass)")</div></div>
187
+ <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L586" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("sandbox.setData seeds the tree (rule-bypass)")</div></div>
185
188
  </details>
186
189
  <details class="compat-row" data-status="ok">
187
190
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>sandbox.snapshotState(db)</code> dumps the full tree as a plain JSON object</span></span></summary>
188
- <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L51" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("sandbox.snapshotState dumps the full tree")</div></div>
191
+ <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/sandbox-target.test.ts#L52" target="_blank" rel="noopener noreferrer"><code>unit:modular/sandbox-target.test.ts</code></a> ("sandbox.snapshotState dumps the full tree")</div></div>
189
192
  </details>
190
193
  <details class="compat-row" data-status="ok">
191
194
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>query(ref, ...constraints)</code> + ordering/range constraints</span></span></summary>
@@ -193,15 +196,15 @@
193
196
  </details>
194
197
  <details class="compat-row" data-status="ok">
195
198
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>runTransaction(ref, fn, options?)</code> resolves to <code>{ committed: boolean, snapshot: DataSnapshot }</code> for the happy path — the update fn return value is written, committed is <code>true</code>, and <code>snapshot.val()</code> reflects the committed value</span></span></summary>
196
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/transaction.test.ts#L37" target="_blank" rel="noopener noreferrer"><code>unit:modular/transaction.test.ts</code></a> ("resolves to { committed: boolean, snapshot } with the committed value"); matches oracle observations <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-success.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-success.json</code></a> + <code>rtdb-modular-runtransaction-returns-committed-snapshot.json</code> (against blockingfun, fb-js-sdk 12.13.0) (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-warm-client-speculation.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-runtransaction-warm-client-speculation</code></a>)</div></div>
199
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/transaction.test.ts#L38" target="_blank" rel="noopener noreferrer"><code>unit:modular/transaction.test.ts</code></a> ("resolves to { committed: boolean, snapshot } with the committed value"); matches oracle observations <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-success.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-success.json</code></a> + <code>rtdb-modular-runtransaction-returns-committed-snapshot.json</code> (against blockingfun, fb-js-sdk 12.13.0) (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-warm-client-speculation.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-runtransaction-warm-client-speculation</code></a>)</div></div>
197
200
  </details>
198
201
  <details class="compat-row" data-status="ok">
199
202
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Returning <code>undefined</code> from the update fn ABORTS the transaction — resolves <code>{ committed: false, snapshot }</code>; no write performed, no listener fan-out</span></span></summary>
200
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/transaction.test.ts#L61" target="_blank" rel="noopener noreferrer"><code>unit:modular/transaction.test.ts</code></a> ("returning undefined aborts — committed: false, no write" + "aborted transaction does NOT fan out to listeners"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-abort-undefined.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-abort-undefined.json</code></a> — known divergence: prod's <code>result.snapshot.val()</code> reflects the CLIENT's pre-fetch (often <code>null</code> even when the server has a value because the speculative invocation runs before the server snap arrives); the sandbox returns the actual pre-transaction value at the path (more useful in single-client harness). The agreed-upon contract callers should rely on is <code>committed === false</code> and unchanged server-side data, NOT the snapshot's <code>.val()</code> on the abort path.</div></div>
203
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/transaction.test.ts#L62" target="_blank" rel="noopener noreferrer"><code>unit:modular/transaction.test.ts</code></a> ("returning undefined aborts — committed: false, no write" + "aborted transaction does NOT fan out to listeners"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-abort-undefined.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-abort-undefined.json</code></a> — known divergence: prod's <code>result.snapshot.val()</code> reflects the CLIENT's pre-fetch (often <code>null</code> even when the server has a value because the speculative invocation runs before the server snap arrives); the sandbox returns the actual pre-transaction value at the path (more useful in single-client harness). The agreed-upon contract callers should rely on is <code>committed === false</code> and unchanged server-side data, NOT the snapshot's <code>.val()</code> on the abort path.</div></div>
201
204
  </details>
202
205
  <details class="compat-row" data-status="diverged">
203
206
  <summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-behavior">Cold production clients may invoke the update fn first with speculative <code>null</code> and then with the current seeded value; the always-warm in-process sandbox invokes it once with the current value</span></span></summary>
204
- <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-current-value-arg.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-runtransaction-current-value-arg</code></a> captures two seeded-path production invocations (<code>null</code>, then current); <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/oracle-conformance-transactions.test.ts#L52" target="_blank" rel="noopener noreferrer"><code>unit:modular/oracle-conformance-transactions.test.ts</code></a> pins the sandbox's single current-value invocation. The separate warm-client observation matches the sandbox but does not erase the cold-client contract. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/transaction.test.ts#L93" target="_blank" rel="noopener noreferrer"><code>transaction.test.ts</code></a>)</div></div>
207
+ <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-current-value-arg.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-runtransaction-current-value-arg</code></a> captures two seeded-path production invocations (<code>null</code>, then current); <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/oracle-conformance-transactions.test.ts#L52" target="_blank" rel="noopener noreferrer"><code>unit:modular/oracle-conformance-transactions.test.ts</code></a> pins the sandbox's single current-value invocation. The separate warm-client observation matches the sandbox but does not erase the cold-client contract. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/transaction.test.ts#L94" target="_blank" rel="noopener noreferrer"><code>transaction.test.ts</code></a>)</div></div>
205
208
  </details>
206
209
  <details class="compat-row" data-status="ok">
207
210
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">The update fn arg is a defensive deep clone — mutating it does NOT corrupt the stored tree (matters for code that does <code>current.count++; return undefined</code> and expects abort to preserve state)</span></span></summary>
@@ -209,7 +212,7 @@
209
212
  </details>
210
213
  <details class="compat-row" data-status="ok">
211
214
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>options.applyLocally</code> controls whether the in-flight optimistic value fans out to <code>onValue</code> listeners — default <code>true</code> (apply locally before commit); <code>false</code> suppresses intermediate fires so listeners see only the committed value</span></span></summary>
212
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/transaction.test.ts#L175" target="_blank" rel="noopener noreferrer"><code>unit:modular/transaction.test.ts</code></a> ("applyLocally: true (default) — listener sees initial + committed value" + "applyLocally: false — listener sees only the committed value"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-options-applylocally.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-options-applylocally.json</code></a> (single-client harness: both branches produce 2 fires (initial + commit) — divergence vs prod's documented multi-client suppression would surface under contention, which the sandbox doesn't model)</div></div>
215
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/transaction.test.ts#L176" target="_blank" rel="noopener noreferrer"><code>unit:modular/transaction.test.ts</code></a> ("applyLocally: true (default) — listener sees initial + committed value" + "applyLocally: false — listener sees only the committed value"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-options-applylocally.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-options-applylocally.json</code></a> (single-client harness: both branches produce 2 fires (initial + commit) — divergence vs prod's documented multi-client suppression would surface under contention, which the sandbox doesn't model)</div></div>
213
216
  </details>
214
217
  <details class="compat-row" data-status="ok">
215
218
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied transaction rejects with a plain <code>Error</code> whose <code>message === 'permission_denied'</code> (lowercase) and NO <code>.code</code> field — DIFFERENT from <code>set</code>/<code>get</code>'s <code>'PERMISSION_DENIED: Permission denied'</code> shape with uppercase <code>.code</code>.</span></span></summary>
@@ -241,7 +244,7 @@
241
244
  </details>
242
245
  <details class="compat-row" data-status="ok">
243
246
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>query(ref, orderByChild(p), startAt(v), endAt(w))</code> window is BOTH-INCLUSIVE — children whose ordered field === <code>v</code> or === <code>w</code> are included</span></span></summary>
244
- <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/upstream-rtdb-probes.test.ts#L4" target="_blank" rel="noopener noreferrer"><code>unit:upstream-rtdb-probes.test.ts</code></a> (deep orderByChild nested path) + <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L65" target="_blank" rel="noopener noreferrer"><code>unit:modular/queries.test.ts</code></a> ("returns children whose ordered child is within [startAt, endAt] inclusive"); matches oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-orderbychild-window.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-orderbychild-window.json</code></a></div></div>
247
+ <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/upstream-rtdb-probes.test.ts#L4" target="_blank" rel="noopener noreferrer"><code>unit:upstream-rtdb-probes.test.ts</code></a> (deep orderByChild nested path) + <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L60" target="_blank" rel="noopener noreferrer"><code>unit:modular/queries.test.ts</code></a> ("returns children whose ordered child is within [startAt, endAt] inclusive"); matches oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-orderbychild-window.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-orderbychild-window.json</code></a></div></div>
245
248
  </details>
246
249
  <details class="compat-row" data-status="ok">
247
250
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>orderByKey()</code> orders children by RTDB <code>nameCompare</code> — integer-looking keys sort numerically FIRST (so <code>['1','2','10']</code>, not the lexicographic <code>['1','10','2']</code>), then non-integer keys lexicographically; <code>startAt</code>/<code>endAt</code> cursors + the optional <code>key</code> tie-breaker use the same order (DB-B4)</span></span></summary>
@@ -249,11 +252,11 @@
249
252
  </details>
250
253
  <details class="compat-row" data-status="diverged">
251
254
  <summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-behavior">Production rejects an unindexed <code>orderByValue() + limitToFirst(N)</code> query; the sandbox does not enforce <code>.indexOn</code> and returns the N smallest primitive values</span></span></summary>
252
- <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-orderbyvalue-numeric.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-orderbyvalue-numeric</code></a> captures production's <code>Index not defined</code> rejection; <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L108" target="_blank" rel="noopener noreferrer"><code>unit:modular/oracle-conformance-queries.test.ts</code></a> pins that rejection beside the sandbox's successful <code>[10,20,30]</code> window. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/oracle-conformance-queries.test.ts#L51" target="_blank" rel="noopener noreferrer"><code>oracle-conformance-queries.test.ts</code></a>)</div></div>
255
+ <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-orderbyvalue-numeric.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-orderbyvalue-numeric</code></a> captures production's <code>Index not defined</code> rejection; <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L103" target="_blank" rel="noopener noreferrer"><code>unit:modular/oracle-conformance-queries.test.ts</code></a> pins that rejection beside the sandbox's successful <code>[10,20,30]</code> window. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/oracle-conformance-queries.test.ts#L51" target="_blank" rel="noopener noreferrer"><code>oracle-conformance-queries.test.ts</code></a>)</div></div>
253
256
  </details>
254
257
  <details class="compat-row" data-status="ok">
255
258
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>orderByChild(p) + equalTo(v)</code> returns ALL children whose field at <code>p</code> === <code>v</code> — no uniqueness enforced</span></span></summary>
256
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L129" target="_blank" rel="noopener noreferrer"><code>unit:modular/queries.test.ts</code></a> ("returns ALL children whose ordered field === the supplied value"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-equalTo-filter.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-equalTo-filter.json</code></a> (both 'b'-grouped children returned).</div></div>
259
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L124" target="_blank" rel="noopener noreferrer"><code>unit:modular/queries.test.ts</code></a> ("returns ALL children whose ordered field === the supplied value"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-equalTo-filter.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-equalTo-filter.json</code></a> (both 'b'-grouped children returned).</div></div>
257
260
  </details>
258
261
  <details class="compat-row" data-status="ok">
259
262
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>equalTo</code> with no matches returns an empty snapshot (<code>exists() === false</code>, <code>size === 0</code>)</span></span></summary>
@@ -261,11 +264,11 @@
261
264
  </details>
262
265
  <details class="compat-row" data-status="ok">
263
266
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>limitToFirst(N)</code> keeps the lowest-ranked N children (post-ordering, pre-filter)</span></span></summary>
264
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L158" target="_blank" rel="noopener noreferrer"><code>unit:modular/queries.test.ts</code></a> ("limitToFirst takes the lowest-ranked window"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-limittofirst-vs-limittolast.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-limittofirst-vs-limittolast.json</code></a> (firstPositions <code>[1,2]</code>).</div></div>
267
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L153" target="_blank" rel="noopener noreferrer"><code>unit:modular/queries.test.ts</code></a> ("limitToFirst takes the lowest-ranked window"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-limittofirst-vs-limittolast.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-limittofirst-vs-limittolast.json</code></a> (firstPositions <code>[1,2]</code>).</div></div>
265
268
  </details>
266
269
  <details class="compat-row" data-status="ok">
267
270
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>limitToLast(N)</code> keeps the highest-ranked N children</span></span></summary>
268
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L158" target="_blank" rel="noopener noreferrer"><code>unit:modular/queries.test.ts</code></a> ("limitToLast takes the highest-ranked window"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-limittofirst-vs-limittolast.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-limittofirst-vs-limittolast.json</code></a> (lastPositions <code>[4,5]</code>).</div></div>
271
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L153" target="_blank" rel="noopener noreferrer"><code>unit:modular/queries.test.ts</code></a> ("limitToLast takes the highest-ranked window"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-limittofirst-vs-limittolast.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-limittofirst-vs-limittolast.json</code></a> (lastPositions <code>[4,5]</code>).</div></div>
269
272
  </details>
270
273
  <details class="compat-row" data-status="ok">
271
274
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>limitToFirst(N)</code> larger than the result returns the full window (no padding, no throw)</span></span></summary>
@@ -273,11 +276,11 @@
273
276
  </details>
274
277
  <details class="compat-row" data-status="ok">
275
278
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>startAfter(v)</code> and <code>endBefore(v)</code> are EXCLUSIVE — the boundary value is dropped from the result</span></span></summary>
276
- <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L197" target="_blank" rel="noopener noreferrer"><code>unit:modular/queries.test.ts</code></a> ("startAfter + endBefore drop the boundary values"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-startafter-endbefore-exclusive.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-startafter-endbefore-exclusive.json</code></a> (positions <code>[3,4]</code>, cursors 2 + 5 dropped).</div></div>
279
+ <div class="compat-evidence"><div class="compat-probe">Sandbox aligned: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L192" target="_blank" rel="noopener noreferrer"><code>unit:modular/queries.test.ts</code></a> ("startAfter + endBefore drop the boundary values"); matches oracle observation <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-startafter-endbefore-exclusive.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb-modular/rtdb-modular-startafter-endbefore-exclusive.json</code></a> (positions <code>[3,4]</code>, cursors 2 + 5 dropped).</div></div>
277
280
  </details>
278
281
  <details class="compat-row" data-status="ok">
279
282
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onValue(query, cb)</code> only fires when the windowed result changes — writes OUTSIDE the window don't re-fire the listener; writes that displace a member DO</span></span></summary>
280
- <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/upstream-rtdb-probes.test.ts#L4" target="_blank" rel="noopener noreferrer"><code>unit:upstream-rtdb-probes.test.ts</code></a> ("one update nulls, mutates, and displaces within a limitToFirst window") + <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L221" target="_blank" rel="noopener noreferrer"><code>unit:modular/queries.test.ts</code></a> ("fires only when the windowed result changes"); matches oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-onvalue-with-query.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-onvalue-with-query.json</code></a></div></div>
283
+ <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/upstream-rtdb-probes.test.ts#L4" target="_blank" rel="noopener noreferrer"><code>unit:upstream-rtdb-probes.test.ts</code></a> ("one update nulls, mutates, and displaces within a limitToFirst window") + <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L216" target="_blank" rel="noopener noreferrer"><code>unit:modular/queries.test.ts</code></a> ("fires only when the windowed result changes"); matches oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-onvalue-with-query.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-onvalue-with-query.json</code></a></div></div>
281
284
  </details>
282
285
  <details class="compat-row" data-status="ok">
283
286
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onValue(query)</code> initial fire delivers an empty window (<code>size === 0</code>) when the path is absent</span></span></summary>
@@ -369,31 +372,31 @@
369
372
  </details>
370
373
  <details class="compat-row" data-status="ok">
371
374
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>onDisconnect(ref)</code> returns the Firebase-shaped five-method handle; registration methods and <code>cancel()</code> return acknowledged Promises</span></span></summary>
372
- <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-ondisconnect-registration.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-ondisconnect-registration</code></a>; sandbox <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/on-disconnect.test.ts#L40" target="_blank" rel="noopener noreferrer"><code>unit:database/on-disconnect.test.ts</code></a>.</div></div>
375
+ <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-ondisconnect-registration.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-ondisconnect-registration</code></a>; sandbox <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/on-disconnect.test.ts#L41" target="_blank" rel="noopener noreferrer"><code>unit:database/on-disconnect.test.ts</code></a>.</div></div>
373
376
  </details>
374
377
  <details class="compat-row" data-status="ok">
375
378
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">An acknowledged <code>onDisconnect(ref).set(value)</code> registration does not mutate server data before the client disconnects</span></span></summary>
376
- <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-ondisconnect-registration.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-ondisconnect-registration</code></a>; sandbox registration/no-mutation test. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/on-disconnect.test.ts#L40" target="_blank" rel="noopener noreferrer"><code>on-disconnect.test.ts</code></a>)</div></div>
379
+ <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-ondisconnect-registration.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-ondisconnect-registration</code></a>; sandbox registration/no-mutation test. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/on-disconnect.test.ts#L41" target="_blank" rel="noopener noreferrer"><code>on-disconnect.test.ts</code></a>)</div></div>
377
380
  </details>
378
381
  <details class="compat-row" data-status="ok">
379
382
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>goOffline(db)</code> drains that client's queue once, listeners observe the disconnect write in server order, and <code>goOnline(db)</code> does not resurrect executed operations</span></span></summary>
380
- <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-ondisconnect-clean-set.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-ondisconnect-clean-set</code></a>; sandbox clean lifecycle test. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/on-disconnect.test.ts#L71" target="_blank" rel="noopener noreferrer"><code>on-disconnect.test.ts</code></a>)</div></div>
383
+ <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-ondisconnect-clean-set.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-ondisconnect-clean-set</code></a>; sandbox clean lifecycle test. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/on-disconnect.test.ts#L72" target="_blank" rel="noopener noreferrer"><code>on-disconnect.test.ts</code></a>)</div></div>
381
384
  </details>
382
385
  <details class="compat-row" data-status="ok">
383
386
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Disconnect queues support <code>set</code>, <code>update</code>, <code>remove</code>, exact cancellation, parent cancellation of queued descendants, and captured parent-set/child-set/child-cancel coalescing that preserves the existing canceled child</span></span></summary>
384
- <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-ondisconnect-operations-cancel.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-ondisconnect-operations-cancel</code></a>; sandbox operation/cancellation test, including the captured parent-set + child-cancel merge result. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/on-disconnect.test.ts#L96" target="_blank" rel="noopener noreferrer"><code>on-disconnect.test.ts</code></a>)</div></div>
387
+ <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-ondisconnect-operations-cancel.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-ondisconnect-operations-cancel</code></a>; sandbox operation/cancellation test, including the captured parent-set + child-cancel merge result. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/on-disconnect.test.ts#L97" target="_blank" rel="noopener noreferrer"><code>on-disconnect.test.ts</code></a>)</div></div>
385
388
  </details>
386
389
  <details class="compat-row" data-status="ok">
387
390
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules are evaluated when a disconnect operation is registered and re-evaluated when it executes; an execution-time denial leaves server state unchanged</span></span></summary>
388
- <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-ondisconnect-rules.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-ondisconnect-rules</code></a> with successful normal-write controls in both rule phases; sandbox rules-timing test. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/on-disconnect.test.ts#L174" target="_blank" rel="noopener noreferrer"><code>on-disconnect.test.ts</code></a>)</div></div>
391
+ <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-ondisconnect-rules.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-ondisconnect-rules</code></a> with successful normal-write controls in both rule phases; sandbox rules-timing test. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/on-disconnect.test.ts#L176" target="_blank" rel="noopener noreferrer"><code>on-disconnect.test.ts</code></a>)</div></div>
389
392
  </details>
390
393
  <details class="compat-row" data-status="ok">
391
394
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><strong>Local lifecycle contract:</strong> disconnect queues are owned per Database client, drain on app deletion, clear without executing on sandbox reset, and are excluded from persisted RTDB snapshots</span></span></summary>
392
- <div class="compat-evidence"><div class="compat-probe">The explicit <code>rtdb-modular#M82</code> assertion set in <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/on-disconnect.test.ts#L252" target="_blank" rel="noopener noreferrer"><code>unit:database/on-disconnect.test.ts</code></a> covers independent clients, app deletion, reset clearing, and snapshot exclusion; these sandbox-owned boundaries have no production oracle equivalent.</div></div>
395
+ <div class="compat-evidence"><div class="compat-probe">The explicit <code>rtdb-modular#M82</code> assertion set in <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/on-disconnect.test.ts#L254" target="_blank" rel="noopener noreferrer"><code>unit:database/on-disconnect.test.ts</code></a> covers independent clients, app deletion, reset clearing, and snapshot exclusion; these sandbox-owned boundaries have no production oracle equivalent.</div></div>
393
396
  </details>
394
397
  <details class="compat-row" data-status="ok">
395
398
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>OnDisconnect.setWithPriority(value, priority)</code> writes both the value and RTDB priority metadata when the disconnect queue drains.</span></span></summary>
396
- <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-ondisconnect-operations-cancel.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-ondisconnect-operations-cancel</code></a> captures export-format priority 7; sandbox <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/on-disconnect.test.ts#L96" target="_blank" rel="noopener noreferrer"><code>unit:database/on-disconnect.test.ts</code></a> replays the value and priority.</div></div>
399
+ <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-ondisconnect-operations-cancel.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-ondisconnect-operations-cancel</code></a> captures export-format priority 7; sandbox <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/on-disconnect.test.ts#L97" target="_blank" rel="noopener noreferrer"><code>unit:database/on-disconnect.test.ts</code></a> replays the value and priority.</div></div>
397
400
  </details>
398
401
  <details class="compat-row" data-status="diverged">
399
402
  <summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-behavior"><strong>Divergence (pending fix):</strong> clean <code>goOffline</code>, app deletion, playground <code>pagehide</code>, and best-effort MessagePort close drain queued operations, but unannounced total renderer/process loss is not guaranteed by the in-memory sandbox</span></span></summary>
@@ -425,7 +428,7 @@
425
428
  </details>
426
429
  <details class="compat-row" data-status="ok">
427
430
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Priority changes participate in plain and explicitly ordered child movement/listener sequencing, transactions, and updates without losing metadata.</span></span></summary>
428
- <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-priority-contract.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-priority-contract</code></a> captures priority movement, update/transaction preservation, and descendant delivery when ancestor replacement clears metadata; replayed by <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/priority-metadata-cdd.test.ts#L20" target="_blank" rel="noopener noreferrer"><code>unit:modular/priority-metadata-cdd.test.ts</code></a> and <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/priority-listeners.test.ts#L18" target="_blank" rel="noopener noreferrer"><code>unit:modular/priority-listeners.test.ts</code></a>. Disconnect priority execution is owned separately by M83.</div></div>
431
+ <div class="compat-evidence"><div class="compat-probe">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-priority-contract.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-priority-contract</code></a> captures priority movement, update/transaction preservation, and descendant delivery when ancestor replacement clears metadata; replayed by <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/priority-metadata-cdd.test.ts#L20" target="_blank" rel="noopener noreferrer"><code>unit:modular/priority-metadata-cdd.test.ts</code></a> and <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/priority-listeners.test.ts#L19" target="_blank" rel="noopener noreferrer"><code>unit:modular/priority-listeners.test.ts</code></a>. Disconnect priority execution is owned separately by M83.</div></div>
429
432
  </details>
430
433
  <details class="compat-row" data-status="ok">
431
434
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>off(query)</code> removes listeners only from the equivalent constrained query view, while <code>off(ref)</code> removes listeners from every query view at that path.</span></span></summary>
@@ -444,15 +447,15 @@
444
447
  <div class="compat-list">
445
448
  <details class="compat-row" data-status="ok">
446
449
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>getDatabase(ctx)</code> returns a tagged sandbox-target handle (frozen identity)</span></span></summary>
447
- <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/database-instances-cdd.test.ts#L14" target="_blank" rel="noopener noreferrer"><code>unit:modular/database-instances-cdd.test.ts</code></a> asserts the returned Database carries a sandbox target.</div></div>
450
+ <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/database-instances-cdd.test.ts#L15" target="_blank" rel="noopener noreferrer"><code>unit:modular/database-instances-cdd.test.ts</code></a> asserts the returned Database carries a sandbox target.</div></div>
448
451
  </details>
449
452
  <details class="compat-row" data-status="ok">
450
453
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>getDatabase(sandbox)</code> returns a tagged sandbox-live handle (per-op identity)</span></span></summary>
451
- <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/database-instances-cdd.test.ts#L21" target="_blank" rel="noopener noreferrer"><code>unit:modular/database-instances-cdd.test.ts</code></a> asserts the returned Database carries a sandbox-live target.</div></div>
454
+ <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/database-instances-cdd.test.ts#L22" target="_blank" rel="noopener noreferrer"><code>unit:modular/database-instances-cdd.test.ts</code></a> asserts the returned Database carries a sandbox-live target.</div></div>
452
455
  </details>
453
456
  <details class="compat-row" data-status="ok">
454
457
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Inactive canonical <code>firebase/database</code> imports remain the upstream package; the mirror does not create tagged production targets</span></span></summary>
455
- <div class="compat-evidence"><div class="compat-probe">Package-resolution boundary assertion in <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/database-instances-cdd.test.ts#L45" target="_blank" rel="noopener noreferrer"><code>unit:modular/database-instances-cdd.test.ts</code></a> proves a real Firebase Database remains untagged and is rejected by the mirror.</div></div>
458
+ <div class="compat-evidence"><div class="compat-probe">Package-resolution boundary assertion in <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/database-instances-cdd.test.ts#L49" target="_blank" rel="noopener noreferrer"><code>unit:modular/database-instances-cdd.test.ts</code></a> proves a real Firebase Database remains untagged and is rejected by the mirror.</div></div>
456
459
  </details>
457
460
  <details class="compat-row" data-status="ok">
458
461
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior"><code>getDatabase()</code> (no argument) — wrapped in the playground preview to supply the sandbox; a raw mirror call rejects with package-resolution guidance</span></span></summary>
@@ -461,11 +464,11 @@
461
464
  </details>
462
465
  <details class="compat-row" data-status="ok">
463
466
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Two <code>getDatabase(sandbox)</code> calls share state (same underlying <code>LocalEnvironment</code>)</span></span></summary>
464
- <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/database-instances-cdd.test.ts#L28" target="_blank" rel="noopener noreferrer"><code>unit:modular/database-instances-cdd.test.ts</code></a> writes through one handle and reads through another handle owned by the same sandbox.</div></div>
467
+ <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/database-instances-cdd.test.ts#L29" target="_blank" rel="noopener noreferrer"><code>unit:modular/database-instances-cdd.test.ts</code></a> writes through one handle and reads through another handle owned by the same sandbox.</div></div>
465
468
  </details>
466
469
  <details class="compat-row" data-status="ok">
467
470
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Handle dispatch by <code>TARGET_SYMBOL</code> brand — refs route to their owning target via a <code>refToTarget</code> WeakMap (mirror of firestore's pattern)</span></span></summary>
468
- <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/database-instances-cdd.test.ts#L36" target="_blank" rel="noopener noreferrer"><code>unit:modular/database-instances-cdd.test.ts</code></a> proves references from independent sandbox targets route to independent backends.</div></div>
471
+ <div class="compat-evidence"><div class="compat-probe"><a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/database-instances-cdd.test.ts#L38" target="_blank" rel="noopener noreferrer"><code>unit:modular/database-instances-cdd.test.ts</code></a> proves references from independent sandbox targets route to independent backends.</div></div>
469
472
  </details>
470
473
  </div>
471
474
  <h3 id="refdb-path--child--parent--root"><code>ref(db, path)</code> / <code>child</code> / <code>parent</code> / <code>root</code></h3>
@@ -511,7 +514,7 @@
511
514
  </details>
512
515
  <details class="compat-row" data-status="ok">
513
516
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Round-trip: <code>set(ref, payload)</code> then <code>get(ref)</code> returns the payload (lock the basic write→read invariant)</span></span></summary>
514
- <div class="compat-evidence"><div class="compat-probe">oracle: <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json</code></a> — the payload round-trips structurally on both sides (this row's claim holds). NOTE — adjacent divergence pinned in <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/oracle-conformance.test.ts#L95" target="_blank" rel="noopener noreferrer"><code>oracle-conformance.test.ts</code></a>: prod returns object children in LEXICOGRAPHIC key order (the capture's <code>roundTripEqual: false</code> — a <code>JSON.stringify</code> round-trip against a non-sorted payload fails), while the sandbox preserves insertion order (stringify round-trip succeeds). Key-order-sensitive consumers behave differently.</div></div>
517
+ <div class="compat-evidence"><div class="compat-probe">oracle: <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json</code></a> — the payload round-trips structurally on both sides (this row's claim holds). NOTE — adjacent divergence pinned in <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/oracle-conformance.test.ts#L96" target="_blank" rel="noopener noreferrer"><code>oracle-conformance.test.ts</code></a>: prod returns object children in LEXICOGRAPHIC key order (the capture's <code>roundTripEqual: false</code> — a <code>JSON.stringify</code> round-trip against a non-sorted payload fails), while the sandbox preserves insertion order (stringify round-trip succeeds). Key-order-sensitive consumers behave differently.</div></div>
515
518
  </details>
516
519
  <details class="compat-row" data-status="ok">
517
520
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied read throws a plain <code>Error</code> (NOT a <code>FirebaseError</code>) with <code>code: 'PERMISSION_DENIED'</code> (uppercase snake-case) — matches the agent-tool rows #15/#20</span></span></summary>
@@ -534,7 +537,7 @@
534
537
  </details>
535
538
  <details class="compat-row" data-status="ok">
536
539
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Primitive round-trip — numbers, strings, booleans, arrays all survive a set→get cycle</span></span></summary>
537
- <div class="compat-evidence"><div class="compat-probe">oracle: <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json</code></a> — the payload round-trips structurally on both sides (this row's claim holds). NOTE — adjacent divergence pinned in <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/oracle-conformance.test.ts#L95" target="_blank" rel="noopener noreferrer"><code>oracle-conformance.test.ts</code></a>: prod returns object children in LEXICOGRAPHIC key order (the capture's <code>roundTripEqual: false</code> — a <code>JSON.stringify</code> round-trip against a non-sorted payload fails), while the sandbox preserves insertion order (stringify round-trip succeeds). Key-order-sensitive consumers behave differently.</div></div>
540
+ <div class="compat-evidence"><div class="compat-probe">oracle: <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json" target="_blank" rel="noopener noreferrer"><code>packages/conformance/observations/rtdb/rtdb-set-then-get-roundtrip.json</code></a> — the payload round-trips structurally on both sides (this row's claim holds). NOTE — adjacent divergence pinned in <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/oracle-conformance.test.ts#L96" target="_blank" rel="noopener noreferrer"><code>oracle-conformance.test.ts</code></a>: prod returns object children in LEXICOGRAPHIC key order (the capture's <code>roundTripEqual: false</code> — a <code>JSON.stringify</code> round-trip against a non-sorted payload fails), while the sandbox preserves insertion order (stringify round-trip succeeds). Key-order-sensitive consumers behave differently.</div></div>
538
541
  </details>
539
542
  <details class="compat-row" data-status="ok">
540
543
  <summary class="compat-line"><span class="compat-dot" data-status="ok" role="img" aria-label="Conforming" title="Conforming"></span><span class="compat-main"><span class="compat-behavior">Rules-denied write throws plain <code>Error</code> with <code>code: 'PERMISSION_DENIED'</code> (same shape as #110)</span></span></summary>
@@ -801,11 +804,11 @@
801
804
  <p>Known differences between Pyric and production Firebase. Each remains tracked as a non-conforming row.</p>
802
805
  <div class="compat-list">
803
806
  <details class="compat-row" data-status="diverged"><summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-sub"><span class="compat-behavior">Cold production clients may invoke the update fn first with speculative <code>null</code> and then with the current seeded value; the always-warm in-process sandbox invokes it once with the current value</span></span></span></summary>
804
- <div class="compat-evidence"><div class="compat-note">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-current-value-arg.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-runtransaction-current-value-arg</code></a> captures two seeded-path production invocations (<code>null</code>, then current); <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/oracle-conformance-transactions.test.ts#L52" target="_blank" rel="noopener noreferrer"><code>unit:modular/oracle-conformance-transactions.test.ts</code></a> pins the sandbox's single current-value invocation. The separate warm-client observation matches the sandbox but does not erase the cold-client contract. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/transaction.test.ts#L93" target="_blank" rel="noopener noreferrer"><code>transaction.test.ts</code></a>)</div></div></details>
807
+ <div class="compat-evidence"><div class="compat-note">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-runtransaction-current-value-arg.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-runtransaction-current-value-arg</code></a> captures two seeded-path production invocations (<code>null</code>, then current); <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/oracle-conformance-transactions.test.ts#L52" target="_blank" rel="noopener noreferrer"><code>unit:modular/oracle-conformance-transactions.test.ts</code></a> pins the sandbox's single current-value invocation. The separate warm-client observation matches the sandbox but does not erase the cold-client contract. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/transaction.test.ts#L94" target="_blank" rel="noopener noreferrer"><code>transaction.test.ts</code></a>)</div></div></details>
805
808
  <details class="compat-row" data-status="diverged"><summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-sub"><span class="compat-behavior">**Divergence:** two ordinary concurrent <code>runTransaction</code> calls are serialized by the in-process backend, so their update functions are not retried with Firebase's captured contention counts. A synchronous re-entrant conflicting write does trigger a deterministic retry.</span></span></span></summary>
806
809
  <div class="compat-evidence"><div class="compat-note">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-concurrent-transforms.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-concurrent-transforms</code></a> captures invocation counts [2, 3]; <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/transaction-contention-cdd.test.ts#L12" target="_blank" rel="noopener noreferrer"><code>unit:modular/transaction-contention-cdd.test.ts</code></a> pins the sandbox's [1, 1] ordinary-concurrency boundary and separately covers its deterministic re-entrant retry seam.</div></div></details>
807
810
  <details class="compat-row" data-status="diverged"><summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-sub"><span class="compat-behavior">Production rejects an unindexed <code>orderByValue() + limitToFirst(N)</code> query; the sandbox does not enforce <code>.indexOn</code> and returns the N smallest primitive values</span></span></span></summary>
808
- <div class="compat-evidence"><div class="compat-note">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-orderbyvalue-numeric.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-orderbyvalue-numeric</code></a> captures production's <code>Index not defined</code> rejection; <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L108" target="_blank" rel="noopener noreferrer"><code>unit:modular/oracle-conformance-queries.test.ts</code></a> pins that rejection beside the sandbox's successful <code>[10,20,30]</code> window. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/oracle-conformance-queries.test.ts#L51" target="_blank" rel="noopener noreferrer"><code>oracle-conformance-queries.test.ts</code></a>)</div></div></details>
811
+ <div class="compat-evidence"><div class="compat-note">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-orderbyvalue-numeric.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-orderbyvalue-numeric</code></a> captures production's <code>Index not defined</code> rejection; <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/queries.test.ts#L103" target="_blank" rel="noopener noreferrer"><code>unit:modular/oracle-conformance-queries.test.ts</code></a> pins that rejection beside the sandbox's successful <code>[10,20,30]</code> window. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/pyric/test/database/modular/oracle-conformance-queries.test.ts#L51" target="_blank" rel="noopener noreferrer"><code>oracle-conformance-queries.test.ts</code></a>)</div></div></details>
809
812
  <details class="compat-row" data-status="diverged"><summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-sub"><span class="compat-behavior">**Divergence (pending fix):** clean <code>goOffline</code>, app deletion, playground <code>pagehide</code>, and best-effort MessagePort close drain queued operations, but unannounced total renderer/process loss is not guaranteed by the in-memory sandbox</span></span></span></summary>
810
813
  <div class="compat-evidence"><div class="compat-note">Oracle <a href="https://github.com/davideast/pyric/blob/main/packages/conformance/observations/rtdb-modular/rtdb-modular-ondisconnect-abrupt-exit.json" target="_blank" rel="noopener noreferrer"><code>rtdb-modular-ondisconnect-abrupt-exit</code></a> proves Firebase executes an acknowledged registration after forced writer termination. The two-port worker integration exercises <code>goOffline</code>, served-app deletion, and non-persisted <code>pagehide</code>; browser MessagePort close delivery cannot prove total-process loss without durable host-owned leases. (Structured evidence: <a href="https://github.com/davideast/pyric/blob/main/packages/cli/test/serve/worker/rtdb-integration.test.ts#L24" target="_blank" rel="noopener noreferrer"><code>rtdb-integration.test.ts</code></a>)</div></div></details>
811
814
  <details class="compat-row" data-status="diverged"><summary class="compat-line"><span class="compat-dot" data-status="diverged" role="img" aria-label="Diverged (documented)" title="Diverged (documented)"></span><span class="compat-main"><span class="compat-sub"><span class="compat-behavior">**Divergence:** <code>DatabaseReference</code> and <code>Query</code> equality includes database target, path, and canonical query parameters like Firebase, but <code>toJSON()</code> serializes the local <code>sandbox://rtdb/...</code> identity instead of Firebase's HTTPS database URL.</span></span></span></summary>