@pyric/cli 0.1.0-alpha.13 → 0.1.0-alpha.15

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 (614) hide show
  1. package/dist/assurance/.generated/conformance-verdicts.d.ts +120 -75
  2. package/dist/assurance/.generated/conformance-verdicts.d.ts.map +1 -1
  3. package/dist/assurance/.generated/conformance-verdicts.js +120 -75
  4. package/dist/assurance/.generated/conformance-verdicts.js.map +1 -1
  5. package/dist/cli/serve.d.ts +1 -1
  6. package/dist/cli/serve.d.ts.map +1 -1
  7. package/dist/cli/serve.js +208 -285
  8. package/dist/cli/serve.js.map +1 -1
  9. package/dist/cli/service-command-records/database-rules-generate.d.ts +4 -0
  10. package/dist/cli/service-command-records/database-rules-generate.d.ts.map +1 -0
  11. package/dist/cli/service-command-records/database-rules-generate.js +3 -0
  12. package/dist/cli/service-command-records/database-rules-generate.js.map +1 -0
  13. package/dist/cli/service-command-records/database-rules-lint.d.ts +4 -0
  14. package/dist/cli/service-command-records/database-rules-lint.d.ts.map +1 -0
  15. package/dist/cli/service-command-records/database-rules-lint.js +3 -0
  16. package/dist/cli/service-command-records/database-rules-lint.js.map +1 -0
  17. package/dist/cli/service-command-records/database-rules-simulate.d.ts +4 -0
  18. package/dist/cli/service-command-records/database-rules-simulate.d.ts.map +1 -0
  19. package/dist/cli/service-command-records/database-rules-simulate.js +3 -0
  20. package/dist/cli/service-command-records/database-rules-simulate.js.map +1 -0
  21. package/dist/cli/service-command-records/database-rules-validate.d.ts +4 -0
  22. package/dist/cli/service-command-records/database-rules-validate.d.ts.map +1 -0
  23. package/dist/cli/service-command-records/database-rules-validate.js +3 -0
  24. package/dist/cli/service-command-records/database-rules-validate.js.map +1 -0
  25. package/dist/cli/service-command-records/firestore-indexes-generate.d.ts +4 -0
  26. package/dist/cli/service-command-records/firestore-indexes-generate.d.ts.map +1 -0
  27. package/dist/cli/service-command-records/firestore-indexes-generate.js +3 -0
  28. package/dist/cli/service-command-records/firestore-indexes-generate.js.map +1 -0
  29. package/dist/cli/service-command-records/firestore-rules-lint.d.ts +4 -0
  30. package/dist/cli/service-command-records/firestore-rules-lint.d.ts.map +1 -0
  31. package/dist/cli/service-command-records/firestore-rules-lint.js +3 -0
  32. package/dist/cli/service-command-records/firestore-rules-lint.js.map +1 -0
  33. package/dist/cli/service-command-records/firestore-rules-resolve.d.ts +4 -0
  34. package/dist/cli/service-command-records/firestore-rules-resolve.d.ts.map +1 -0
  35. package/dist/cli/service-command-records/firestore-rules-resolve.js +3 -0
  36. package/dist/cli/service-command-records/firestore-rules-resolve.js.map +1 -0
  37. package/dist/cli/service-command-records/firestore-rules-simulate.d.ts +4 -0
  38. package/dist/cli/service-command-records/firestore-rules-simulate.d.ts.map +1 -0
  39. package/dist/cli/service-command-records/firestore-rules-simulate.js +3 -0
  40. package/dist/cli/service-command-records/firestore-rules-simulate.js.map +1 -0
  41. package/dist/cli/service-command-records/firestore-rules-validate.d.ts +4 -0
  42. package/dist/cli/service-command-records/firestore-rules-validate.d.ts.map +1 -0
  43. package/dist/cli/service-command-records/firestore-rules-validate.js +3 -0
  44. package/dist/cli/service-command-records/firestore-rules-validate.js.map +1 -0
  45. package/dist/cli/service-command-records/storage-rules-lint.d.ts +4 -0
  46. package/dist/cli/service-command-records/storage-rules-lint.d.ts.map +1 -0
  47. package/dist/cli/service-command-records/storage-rules-lint.js +3 -0
  48. package/dist/cli/service-command-records/storage-rules-lint.js.map +1 -0
  49. package/dist/cli/service-command-records/storage-rules-simulate.d.ts +4 -0
  50. package/dist/cli/service-command-records/storage-rules-simulate.d.ts.map +1 -0
  51. package/dist/cli/service-command-records/storage-rules-simulate.js +3 -0
  52. package/dist/cli/service-command-records/storage-rules-simulate.js.map +1 -0
  53. package/dist/cli/service-commands.d.ts +7 -0
  54. package/dist/cli/service-commands.d.ts.map +1 -1
  55. package/dist/cli/service-commands.generated.d.ts +35 -0
  56. package/dist/cli/service-commands.generated.d.ts.map +1 -0
  57. package/dist/cli/service-commands.generated.js +25 -0
  58. package/dist/cli/service-commands.generated.js.map +1 -0
  59. package/dist/cli/service-commands.js +23 -40
  60. package/dist/cli/service-commands.js.map +1 -1
  61. package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
  62. package/dist/conformance/.generated/can-i-use-browser.js +1 -1
  63. package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
  64. package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
  65. package/dist/conformance/.generated/can-i-use.js +1 -1
  66. package/dist/conformance/.generated/can-i-use.js.map +1 -1
  67. package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
  68. package/dist/conformance/.generated/conformance-docs.js +1 -1
  69. package/dist/conformance/.generated/conformance-docs.js.map +1 -1
  70. package/dist/functions-rtdb/development-runtime.d.ts +63 -0
  71. package/dist/functions-rtdb/development-runtime.d.ts.map +1 -0
  72. package/dist/functions-rtdb/development-runtime.js +244 -0
  73. package/dist/functions-rtdb/development-runtime.js.map +1 -0
  74. package/dist/serve/bridge-mount.d.ts +32 -2
  75. package/dist/serve/bridge-mount.d.ts.map +1 -1
  76. package/dist/serve/bridge-mount.js +232 -18
  77. package/dist/serve/bridge-mount.js.map +1 -1
  78. package/dist/serve/bundler.d.ts +4 -18
  79. package/dist/serve/bundler.d.ts.map +1 -1
  80. package/dist/serve/bundler.js +15 -37
  81. package/dist/serve/bundler.js.map +1 -1
  82. package/dist/serve/entries/app-client.d.ts.map +1 -1
  83. package/dist/serve/entries/app-client.js +5 -5
  84. package/dist/serve/entries/app-client.js.map +1 -1
  85. package/dist/serve/entries/auth-helper-core.d.ts +23 -6
  86. package/dist/serve/entries/auth-helper-core.d.ts.map +1 -1
  87. package/dist/serve/entries/auth-helper-core.js +55 -24
  88. package/dist/serve/entries/auth-helper-core.js.map +1 -1
  89. package/dist/serve/entries/database.d.ts +28 -0
  90. package/dist/serve/entries/database.d.ts.map +1 -1
  91. package/dist/serve/entries/database.js +95 -26
  92. package/dist/serve/entries/database.js.map +1 -1
  93. package/dist/serve/entries/init.d.ts.map +1 -1
  94. package/dist/serve/entries/init.js +21 -12
  95. package/dist/serve/entries/init.js.map +1 -1
  96. package/dist/serve/html-injection.d.ts +5 -0
  97. package/dist/serve/html-injection.d.ts.map +1 -0
  98. package/dist/serve/html-injection.js +59 -0
  99. package/dist/serve/html-injection.js.map +1 -0
  100. package/dist/serve/namespace.d.ts +6 -22
  101. package/dist/serve/namespace.d.ts.map +1 -1
  102. package/dist/serve/namespace.js +23 -145
  103. package/dist/serve/namespace.js.map +1 -1
  104. package/dist/serve/runtime/worker-generation.d.ts +10 -2
  105. package/dist/serve/runtime/worker-generation.d.ts.map +1 -1
  106. package/dist/serve/runtime/worker-generation.js +29 -8
  107. package/dist/serve/runtime/worker-generation.js.map +1 -1
  108. package/dist/serve/runtime/worker-replacement.d.ts +1 -2
  109. package/dist/serve/runtime/worker-replacement.d.ts.map +1 -1
  110. package/dist/serve/sandbox-session.d.ts +78 -0
  111. package/dist/serve/sandbox-session.d.ts.map +1 -0
  112. package/dist/serve/sandbox-session.js +171 -0
  113. package/dist/serve/sandbox-session.js.map +1 -0
  114. package/dist/serve/server.d.ts +5 -2
  115. package/dist/serve/server.d.ts.map +1 -1
  116. package/dist/serve/server.js +21 -5
  117. package/dist/serve/server.js.map +1 -1
  118. package/dist/serve/site-tree.d.ts +8 -0
  119. package/dist/serve/site-tree.d.ts.map +1 -0
  120. package/dist/serve/site-tree.js +113 -0
  121. package/dist/serve/site-tree.js.map +1 -0
  122. package/dist/serve/site-ui/_astro/RulesCodeEditor.CzwHdCi9.js +23 -0
  123. package/dist/serve/site-ui/_astro/_example_.jevZ7OdV.css +1 -0
  124. package/dist/serve/site-ui/_astro/_slug_.BoKXYrnu.css +1 -0
  125. package/dist/serve/site-ui/_astro/_studio_.BtYpqe1A.css +1 -0
  126. package/dist/serve/site-ui/_astro/app.BnMC0ywl.js +109 -0
  127. package/dist/serve/site-ui/_astro/app.BsFsMjn0.css +1 -0
  128. package/dist/serve/site-ui/_astro/app.DVXXR-WI.js +1 -0
  129. package/dist/serve/site-ui/_astro/chess-showcase.DzPO6kz0.js +1 -0
  130. package/dist/serve/site-ui/_astro/chess-source-explorer.C5k9c5yK.js +1 -0
  131. package/dist/serve/site-ui/_astro/chess-v2.CFHmd3UL.js +354 -0
  132. package/dist/serve/site-ui/_astro/client.D2ORs4B-.js +25 -0
  133. package/dist/serve/site-ui/_astro/example-runtime.CM0H02rx.js +291 -0
  134. package/dist/serve/site-ui/_astro/index.B4Kh80he.js +1 -0
  135. package/dist/serve/site-ui/_astro/index.DBy5LfQW.js +9 -0
  136. package/dist/serve/site-ui/_astro/index.DNyk7q8W.js +9 -0
  137. package/dist/serve/site-ui/_astro/jsx-runtime.D_zvdyIk.js +9 -0
  138. package/dist/serve/site-ui/_astro/reads.D1exkX1-.js +1 -0
  139. package/dist/serve/site-ui/_astro/sandbox-controls.BqMePr5V.js +1153 -0
  140. package/dist/serve/site-ui/_astro/seed.BCn5DhHS.js +20 -0
  141. package/dist/serve/site-ui/auth/index.html +11 -0
  142. package/dist/serve/site-ui/docs/_rhythm/index.html +100 -0
  143. package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +43 -0
  144. package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +26 -0
  145. package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +70 -0
  146. package/dist/serve/{docs-ui → site-ui}/docs/ai-compat/index.html +3 -3
  147. package/dist/serve/site-ui/docs/api-reference/index.html +68 -0
  148. package/dist/serve/{docs-ui → site-ui}/docs/app-compat/index.html +3 -3
  149. package/dist/serve/{docs-ui → site-ui}/docs/auth-compat/index.html +3 -3
  150. package/dist/serve/site-ui/docs/build/ai-logic/index.html +64 -0
  151. package/dist/serve/site-ui/docs/build/authentication/index.html +66 -0
  152. package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +84 -0
  153. package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +71 -0
  154. package/dist/serve/site-ui/docs/build/cloud-storage/index.html +66 -0
  155. package/dist/serve/{docs-ui → site-ui}/docs/build/cloud-storage.md +2 -2
  156. package/dist/serve/site-ui/docs/build/realtime-database/index.html +67 -0
  157. package/dist/serve/site-ui/docs/conformance-scores/index.html +50 -0
  158. package/dist/serve/{docs-ui → site-ui}/docs/conformance-scores.md +3 -3
  159. package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +531 -0
  160. package/dist/serve/{docs-ui → site-ui}/docs/database-compat/index.html +211 -168
  161. package/dist/serve/{docs-ui → site-ui}/docs/database-compat.md +208 -170
  162. package/dist/serve/site-ui/docs/examples/chess/index.html +384 -0
  163. package/dist/serve/site-ui/docs/examples/chess.md +57 -0
  164. package/dist/serve/site-ui/docs/examples/index.html +3 -0
  165. package/dist/serve/site-ui/docs/examples.md +4 -0
  166. package/dist/serve/{docs-ui → site-ui}/docs/firestore-compat/index.html +55 -91
  167. package/dist/serve/{docs-ui → site-ui}/docs/firestore-compat.md +52 -88
  168. package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +73 -0
  169. package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +29 -0
  170. package/dist/serve/site-ui/docs/get-started/start-building/index.html +33 -0
  171. package/dist/serve/{docs-ui → site-ui}/docs/index.json +595 -26
  172. package/dist/serve/site-ui/docs/messaging-compat/index.html +324 -0
  173. package/dist/serve/{docs-ui → site-ui}/docs/messaging-compat.md +71 -1
  174. package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +28 -0
  175. package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +74 -0
  176. package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +45 -0
  177. package/dist/serve/site-ui/docs/overview/index.html +17 -0
  178. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +186 -0
  179. package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-auth-reference-api/index.html +4 -4
  180. package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-database-reference-api/index.html +4 -4
  181. package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-firestore-reference-api/index.html +318 -202
  182. package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-firestore-reference-api.md +154 -27
  183. package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-messaging-reference-api/index.html +5 -5
  184. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +318 -0
  185. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ai-reference-api/index.html +5 -5
  186. package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +160 -0
  187. package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +425 -0
  188. package/dist/serve/{docs-ui → site-ui}/docs/pyric-auth-reference-api/index.html +5 -5
  189. package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +60 -0
  190. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-assurance-reference-api/index.html +4 -4
  191. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-bridge-client-reference-api/index.html +4 -4
  192. package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +507 -0
  193. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +258 -0
  194. package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +51 -0
  195. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +308 -0
  196. package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +68 -0
  197. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-discover-reference-api/index.html +4 -4
  198. package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +11 -0
  199. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-remote-reference-api/index.html +4 -4
  200. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-serve-worker-reference-api/index.html +1186 -1384
  201. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-serve-worker-reference-api.md +817 -1291
  202. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-verify-reference-api/index.html +4 -4
  203. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +126 -0
  204. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-vite-reference-api.md +1 -1
  205. package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +2641 -0
  206. package/dist/serve/{docs-ui → site-ui}/docs/pyric-database-reference-api.md +1055 -158
  207. package/dist/serve/{docs-ui → site-ui}/docs/pyric-firestore-reference-api/index.html +311 -249
  208. package/dist/serve/{docs-ui → site-ui}/docs/pyric-firestore-reference-api.md +72 -54
  209. package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +509 -0
  210. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +182 -0
  211. package/dist/serve/{docs-ui → site-ui}/docs/pyric-rules-reference-api/index.html +7 -26
  212. package/dist/serve/{docs-ui → site-ui}/docs/pyric-rules-reference-api.md +13 -23
  213. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +121 -0
  214. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +203 -0
  215. package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-reference-api/index.html +26 -5
  216. package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-reference-api.md +22 -22
  217. package/dist/serve/{docs-ui → site-ui}/docs/pyric-storage-reference-api/index.html +5 -15
  218. package/dist/serve/{docs-ui → site-ui}/docs/pyric-storage-reference-api.md +0 -13
  219. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +639 -0
  220. package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +100 -0
  221. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-auth-reference-api/index.html +4 -4
  222. package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +24 -0
  223. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-events-reference-api/index.html +4 -4
  224. package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +136 -0
  225. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-firestore-reference-api/index.html +7 -7
  226. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-firestore-reference-api.md +4 -4
  227. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-primitives-reference-api/index.html +4 -4
  228. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rtdb-reference-api/index.html +4 -4
  229. package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +16 -0
  230. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rules-reference-api/index.html +4 -4
  231. package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +176 -0
  232. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-storage-reference-api/index.html +10 -11
  233. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-storage-reference-api.md +7 -8
  234. package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +188 -0
  235. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-traffic-reference-api/index.html +4 -4
  236. package/dist/serve/{docs-ui → site-ui}/docs/rules-compat/index.html +87 -57
  237. package/dist/serve/{docs-ui → site-ui}/docs/rules-compat.md +84 -54
  238. package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +51 -0
  239. package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +106 -0
  240. package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +41 -0
  241. package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +67 -0
  242. package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +159 -0
  243. package/dist/serve/{docs-ui → site-ui}/docs/secure/rules-standard-library.md +2 -2
  244. package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +47 -0
  245. package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +95 -0
  246. package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +82 -0
  247. package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +37 -0
  248. package/dist/serve/site-ui/docs/ship/test-in-node/index.html +75 -0
  249. package/dist/serve/{docs-ui → site-ui}/docs/storage-compat/index.html +8 -8
  250. package/dist/serve/{docs-ui → site-ui}/docs/storage-compat.md +5 -5
  251. package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +132 -0
  252. package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +861 -0
  253. package/dist/serve/site-ui/docs/trust/rules-standard-library.md +344 -0
  254. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +582 -0
  255. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research.md +448 -0
  256. package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +14 -0
  257. package/dist/serve/{docs-ui → site-ui}/docs/tutorial/index.html +4 -4
  258. package/dist/serve/{docs-ui → site-ui}/docs/tutorial.md +1 -1
  259. package/dist/serve/site-ui/examples/chess/index.html +2 -0
  260. package/dist/serve/site-ui/examples/firestore-first-write/index.html +2 -0
  261. package/dist/serve/site-ui/firestore/index.html +11 -0
  262. package/dist/serve/site-ui/index.html +11 -0
  263. package/dist/serve/{docs-ui → site-ui}/llms.txt +6 -2
  264. package/dist/serve/site-ui/rtdb/index.html +11 -0
  265. package/dist/serve/site-ui/settings/index.html +11 -0
  266. package/dist/serve/site-ui/storage/index.html +11 -0
  267. package/dist/serve/site-ui/studio-routes.json +1 -0
  268. package/dist/serve/site-ui/traffic/index.html +11 -0
  269. package/dist/serve/standalone-assets.d.ts +4 -10
  270. package/dist/serve/standalone-assets.d.ts.map +1 -1
  271. package/dist/serve/standalone-assets.js +8 -21
  272. package/dist/serve/standalone-assets.js.map +1 -1
  273. package/dist/serve/vite-ai-config.d.ts +2 -0
  274. package/dist/serve/vite-ai-config.d.ts.map +1 -1
  275. package/dist/serve/vite-ai-config.js +4 -0
  276. package/dist/serve/vite-ai-config.js.map +1 -1
  277. package/dist/serve/vite-functions-development.d.ts +29 -0
  278. package/dist/serve/vite-functions-development.d.ts.map +1 -0
  279. package/dist/serve/vite-functions-development.js +150 -0
  280. package/dist/serve/vite-functions-development.js.map +1 -0
  281. package/dist/serve/vite-generation-bridge.d.ts +17 -0
  282. package/dist/serve/vite-generation-bridge.d.ts.map +1 -0
  283. package/dist/serve/vite-generation-bridge.js +47 -0
  284. package/dist/serve/vite-generation-bridge.js.map +1 -0
  285. package/dist/serve/vite-generation-functions.d.ts +35 -0
  286. package/dist/serve/vite-generation-functions.d.ts.map +1 -0
  287. package/dist/serve/vite-generation-functions.js +46 -0
  288. package/dist/serve/vite-generation-functions.js.map +1 -0
  289. package/dist/serve/vite-generation-middleware.d.ts +10 -0
  290. package/dist/serve/vite-generation-middleware.d.ts.map +1 -0
  291. package/dist/serve/vite-generation-middleware.js +40 -0
  292. package/dist/serve/vite-generation-middleware.js.map +1 -0
  293. package/dist/serve/vite-generation-rules-watch.d.ts +8 -0
  294. package/dist/serve/vite-generation-rules-watch.d.ts.map +1 -0
  295. package/dist/serve/vite-generation-rules-watch.js +33 -0
  296. package/dist/serve/vite-generation-rules-watch.js.map +1 -0
  297. package/dist/serve/vite-module-swap.d.ts +16 -0
  298. package/dist/serve/vite-module-swap.d.ts.map +1 -0
  299. package/dist/serve/vite-module-swap.js +96 -0
  300. package/dist/serve/vite-module-swap.js.map +1 -0
  301. package/dist/serve/vite-page-runtime.d.ts +29 -0
  302. package/dist/serve/vite-page-runtime.d.ts.map +1 -0
  303. package/dist/serve/vite-page-runtime.js +71 -0
  304. package/dist/serve/vite-page-runtime.js.map +1 -0
  305. package/dist/serve/vite-plugin.d.ts +44 -4
  306. package/dist/serve/vite-plugin.d.ts.map +1 -1
  307. package/dist/serve/vite-plugin.js +62 -864
  308. package/dist/serve/vite-plugin.js.map +1 -1
  309. package/dist/serve/vite-sandbox-generation.d.ts +57 -0
  310. package/dist/serve/vite-sandbox-generation.d.ts.map +1 -0
  311. package/dist/serve/vite-sandbox-generation.js +178 -0
  312. package/dist/serve/vite-sandbox-generation.js.map +1 -0
  313. package/dist/serve/vite-worker-runtime.d.ts +1 -1
  314. package/dist/serve/vite-worker-runtime.d.ts.map +1 -1
  315. package/dist/serve/vite-worker-runtime.js +8 -4
  316. package/dist/serve/vite-worker-runtime.js.map +1 -1
  317. package/dist/serve/worker/client/disconnect.d.ts.map +1 -1
  318. package/dist/serve/worker/client/disconnect.js +2 -0
  319. package/dist/serve/worker/client/disconnect.js.map +1 -1
  320. package/dist/serve/worker/client/handles.d.ts +5 -0
  321. package/dist/serve/worker/client/handles.d.ts.map +1 -1
  322. package/dist/serve/worker/client/handles.js.map +1 -1
  323. package/dist/serve/worker/client/pagehide.d.ts +13 -0
  324. package/dist/serve/worker/client/pagehide.d.ts.map +1 -0
  325. package/dist/serve/worker/client/pagehide.js +19 -0
  326. package/dist/serve/worker/client/pagehide.js.map +1 -0
  327. package/dist/serve/worker/client/rtdb-admin.d.ts +8 -0
  328. package/dist/serve/worker/client/rtdb-admin.d.ts.map +1 -0
  329. package/dist/serve/worker/client/rtdb-admin.js +39 -0
  330. package/dist/serve/worker/client/rtdb-admin.js.map +1 -0
  331. package/dist/serve/worker/client/rtdb-connection-lifecycle.d.ts +15 -0
  332. package/dist/serve/worker/client/rtdb-connection-lifecycle.d.ts.map +1 -0
  333. package/dist/serve/worker/client/rtdb-connection-lifecycle.js +45 -0
  334. package/dist/serve/worker/client/rtdb-connection-lifecycle.js.map +1 -0
  335. package/dist/serve/worker/client/rtdb-controls.d.ts +6 -0
  336. package/dist/serve/worker/client/rtdb-controls.d.ts.map +1 -0
  337. package/dist/serve/worker/client/rtdb-controls.js +8 -0
  338. package/dist/serve/worker/client/rtdb-controls.js.map +1 -0
  339. package/dist/serve/worker/client/rtdb-listeners.d.ts +24 -0
  340. package/dist/serve/worker/client/rtdb-listeners.d.ts.map +1 -0
  341. package/dist/serve/worker/client/rtdb-listeners.js +262 -0
  342. package/dist/serve/worker/client/rtdb-listeners.js.map +1 -0
  343. package/dist/serve/worker/client/rtdb-reads.d.ts +4 -0
  344. package/dist/serve/worker/client/rtdb-reads.d.ts.map +1 -0
  345. package/dist/serve/worker/client/rtdb-reads.js +11 -0
  346. package/dist/serve/worker/client/rtdb-reads.js.map +1 -0
  347. package/dist/serve/worker/client/rtdb-references.d.ts +19 -0
  348. package/dist/serve/worker/client/rtdb-references.d.ts.map +1 -0
  349. package/dist/serve/worker/client/rtdb-references.js +63 -0
  350. package/dist/serve/worker/client/rtdb-references.js.map +1 -0
  351. package/dist/serve/worker/client/rtdb-snapshots.d.ts +20 -0
  352. package/dist/serve/worker/client/rtdb-snapshots.d.ts.map +1 -0
  353. package/dist/serve/worker/client/rtdb-snapshots.js +64 -0
  354. package/dist/serve/worker/client/rtdb-snapshots.js.map +1 -0
  355. package/dist/serve/worker/client/rtdb-transactions.d.ts +14 -0
  356. package/dist/serve/worker/client/rtdb-transactions.d.ts.map +1 -0
  357. package/dist/serve/worker/client/rtdb-transactions.js +34 -0
  358. package/dist/serve/worker/client/rtdb-transactions.js.map +1 -0
  359. package/dist/serve/worker/client/rtdb-writes.d.ts +8 -0
  360. package/dist/serve/worker/client/rtdb-writes.d.ts.map +1 -0
  361. package/dist/serve/worker/client/rtdb-writes.js +65 -0
  362. package/dist/serve/worker/client/rtdb-writes.js.map +1 -0
  363. package/dist/serve/worker/client.d.ts +0 -2
  364. package/dist/serve/worker/client.d.ts.map +1 -1
  365. package/dist/serve/worker/client.js +0 -2
  366. package/dist/serve/worker/client.js.map +1 -1
  367. package/dist/serve/worker/entry.js +2 -2
  368. package/dist/serve/worker/entry.js.map +1 -1
  369. package/dist/serve/worker/host/dispatch.d.ts +2 -0
  370. package/dist/serve/worker/host/dispatch.d.ts.map +1 -1
  371. package/dist/serve/worker/host/dispatch.js +24 -2
  372. package/dist/serve/worker/host/dispatch.js.map +1 -1
  373. package/dist/serve/worker/host/rtdb.d.ts +6 -2
  374. package/dist/serve/worker/host/rtdb.d.ts.map +1 -1
  375. package/dist/serve/worker/host/rtdb.js +224 -2
  376. package/dist/serve/worker/host/rtdb.js.map +1 -1
  377. package/dist/serve/worker/host/studio.d.ts.map +1 -1
  378. package/dist/serve/worker/host/studio.js +2 -0
  379. package/dist/serve/worker/host/studio.js.map +1 -1
  380. package/dist/serve/worker/host/subscriptions.d.ts.map +1 -1
  381. package/dist/serve/worker/host/subscriptions.js +3 -3
  382. package/dist/serve/worker/host/subscriptions.js.map +1 -1
  383. package/dist/serve/worker/host.d.ts +1 -1
  384. package/dist/serve/worker/host.d.ts.map +1 -1
  385. package/dist/serve/worker/host.js +1 -1
  386. package/dist/serve/worker/host.js.map +1 -1
  387. package/dist/serve/worker/index.d.ts +16 -1
  388. package/dist/serve/worker/index.d.ts.map +1 -1
  389. package/dist/serve/worker/index.js +17 -4
  390. package/dist/serve/worker/index.js.map +1 -1
  391. package/dist/serve/worker/protocol.d.ts +57 -0
  392. package/dist/serve/worker/protocol.d.ts.map +1 -1
  393. package/dist/serve/worker/protocol.js.map +1 -1
  394. package/dist/serve/worker/rtdb-value-equality.d.ts +3 -0
  395. package/dist/serve/worker/rtdb-value-equality.d.ts.map +1 -0
  396. package/dist/serve/worker/rtdb-value-equality.js +18 -0
  397. package/dist/serve/worker/rtdb-value-equality.js.map +1 -0
  398. package/dist/serve/worker/serve-init.js +2 -2
  399. package/dist/serve/worker/serve-init.js.map +1 -1
  400. package/dist/serve/worker/service-worker-relay.js +2 -2
  401. package/dist/serve/worker/service-worker-relay.js.map +1 -1
  402. package/package.json +7 -5
  403. package/src/assurance/.generated/conformance-verdicts.ts +120 -75
  404. package/src/cli/serve.ts +216 -308
  405. package/src/cli/service-command-records/database-rules-generate.ts +3 -0
  406. package/src/cli/service-command-records/database-rules-lint.ts +3 -0
  407. package/src/cli/service-command-records/database-rules-simulate.ts +3 -0
  408. package/src/cli/service-command-records/database-rules-validate.ts +3 -0
  409. package/src/cli/service-command-records/firestore-indexes-generate.ts +3 -0
  410. package/src/cli/service-command-records/firestore-rules-lint.ts +3 -0
  411. package/src/cli/service-command-records/firestore-rules-resolve.ts +3 -0
  412. package/src/cli/service-command-records/firestore-rules-simulate.ts +3 -0
  413. package/src/cli/service-command-records/firestore-rules-validate.ts +3 -0
  414. package/src/cli/service-command-records/storage-rules-lint.ts +3 -0
  415. package/src/cli/service-command-records/storage-rules-simulate.ts +3 -0
  416. package/src/cli/service-commands.generated.ts +27 -0
  417. package/src/cli/service-commands.test.ts +43 -0
  418. package/src/cli/service-commands.ts +36 -51
  419. package/src/conformance/.generated/can-i-use-browser.ts +1 -1
  420. package/src/conformance/.generated/can-i-use.ts +1 -1
  421. package/src/conformance/.generated/conformance-docs.ts +1 -1
  422. package/src/functions-rtdb/development-runtime.ts +299 -0
  423. package/src/serve/bridge-mount.ts +253 -19
  424. package/src/serve/bundler.ts +17 -36
  425. package/src/serve/entries/app-client.ts +5 -4
  426. package/src/serve/entries/auth-helper-core.ts +83 -30
  427. package/src/serve/entries/database.ts +180 -57
  428. package/src/serve/entries/init.ts +30 -20
  429. package/src/serve/html-injection.ts +65 -0
  430. package/src/serve/namespace.ts +26 -169
  431. package/src/serve/runtime/worker-generation.ts +29 -7
  432. package/src/serve/runtime/worker-replacement.ts +1 -1
  433. package/src/serve/sandbox-session.ts +233 -0
  434. package/src/serve/server.ts +20 -5
  435. package/src/serve/site-tree.ts +146 -0
  436. package/src/serve/standalone-assets.ts +9 -26
  437. package/src/serve/vite-ai-config.ts +8 -0
  438. package/src/serve/vite-functions-development.ts +201 -0
  439. package/src/serve/vite-generation-bridge.ts +66 -0
  440. package/src/serve/vite-generation-functions.ts +78 -0
  441. package/src/serve/vite-generation-middleware.ts +56 -0
  442. package/src/serve/vite-generation-rules-watch.ts +37 -0
  443. package/src/serve/vite-module-swap.ts +119 -0
  444. package/src/serve/vite-page-runtime.ts +100 -0
  445. package/src/serve/vite-plugin.ts +78 -882
  446. package/src/serve/vite-sandbox-generation.ts +255 -0
  447. package/src/serve/vite-worker-runtime.ts +12 -5
  448. package/src/serve/worker/client/disconnect.ts +3 -1
  449. package/src/serve/worker/client/handles.ts +5 -0
  450. package/src/serve/worker/client/pagehide.ts +31 -0
  451. package/src/serve/worker/client/rtdb-admin.ts +74 -0
  452. package/src/serve/worker/client/rtdb-connection-lifecycle.ts +52 -0
  453. package/src/serve/worker/client/rtdb-controls.ts +8 -0
  454. package/src/serve/worker/client/rtdb-listeners.ts +337 -0
  455. package/src/serve/worker/client/rtdb-reads.ts +12 -0
  456. package/src/serve/worker/client/rtdb-references.ts +85 -0
  457. package/src/serve/worker/client/rtdb-snapshots.ts +118 -0
  458. package/src/serve/worker/client/rtdb-transactions.ts +51 -0
  459. package/src/serve/worker/client/rtdb-writes.ts +74 -0
  460. package/src/serve/worker/client.ts +0 -2
  461. package/src/serve/worker/entry.ts +2 -2
  462. package/src/serve/worker/host/dispatch.ts +22 -2
  463. package/src/serve/worker/host/rtdb.ts +243 -2
  464. package/src/serve/worker/host/studio.ts +2 -0
  465. package/src/serve/worker/host/subscriptions.ts +8 -4
  466. package/src/serve/worker/host.ts +1 -1
  467. package/src/serve/worker/index.ts +58 -10
  468. package/src/serve/worker/protocol.ts +23 -2
  469. package/src/serve/worker/rtdb-value-equality.ts +17 -0
  470. package/src/serve/worker/serve-init.ts +2 -2
  471. package/src/serve/worker/service-worker-relay.ts +2 -2
  472. package/dist/serve/docs-ui/_astro/_slug_.DUci-duz.css +0 -1
  473. package/dist/serve/docs-ui/docs/_rhythm/index.html +0 -100
  474. package/dist/serve/docs-ui/docs/agent/set-up-your-agent/index.html +0 -43
  475. package/dist/serve/docs-ui/docs/agent/watch-and-review/index.html +0 -26
  476. package/dist/serve/docs-ui/docs/agent/work-with-an-agent/index.html +0 -70
  477. package/dist/serve/docs-ui/docs/api-reference/index.html +0 -68
  478. package/dist/serve/docs-ui/docs/build/ai-logic/index.html +0 -64
  479. package/dist/serve/docs-ui/docs/build/authentication/index.html +0 -66
  480. package/dist/serve/docs-ui/docs/build/cloud-firestore/index.html +0 -70
  481. package/dist/serve/docs-ui/docs/build/cloud-messaging/index.html +0 -71
  482. package/dist/serve/docs-ui/docs/build/cloud-storage/index.html +0 -66
  483. package/dist/serve/docs-ui/docs/build/realtime-database/index.html +0 -67
  484. package/dist/serve/docs-ui/docs/conformance-scores/index.html +0 -50
  485. package/dist/serve/docs-ui/docs/create-pyric-reference-api/index.html +0 -531
  486. package/dist/serve/docs-ui/docs/functions-rtdb-compat/index.html +0 -73
  487. package/dist/serve/docs-ui/docs/get-started/how-the-swap-works/index.html +0 -29
  488. package/dist/serve/docs-ui/docs/get-started/start-building/index.html +0 -33
  489. package/dist/serve/docs-ui/docs/messaging-compat/index.html +0 -265
  490. package/dist/serve/docs-ui/docs/observe/resolve-runtime-status/index.html +0 -28
  491. package/dist/serve/docs-ui/docs/observe/see-whats-happening/index.html +0 -74
  492. package/dist/serve/docs-ui/docs/observe/shape-your-data/index.html +0 -45
  493. package/dist/serve/docs-ui/docs/overview/index.html +0 -17
  494. package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api/index.html +0 -186
  495. package/dist/serve/docs-ui/docs/pyric-admin-storage-reference-api/index.html +0 -318
  496. package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api/index.html +0 -160
  497. package/dist/serve/docs-ui/docs/pyric-app-reference-api/index.html +0 -425
  498. package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +0 -60
  499. package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api/index.html +0 -507
  500. package/dist/serve/docs-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +0 -258
  501. package/dist/serve/docs-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +0 -51
  502. package/dist/serve/docs-ui/docs/pyric-cli-conformance-reference-api/index.html +0 -308
  503. package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api/index.html +0 -68
  504. package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api/index.html +0 -11
  505. package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api/index.html +0 -126
  506. package/dist/serve/docs-ui/docs/pyric-database-reference-api/index.html +0 -1852
  507. package/dist/serve/docs-ui/docs/pyric-messaging-reference-api/index.html +0 -509
  508. package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api/index.html +0 -182
  509. package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api/index.html +0 -121
  510. package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api/index.html +0 -203
  511. package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api/index.html +0 -639
  512. package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +0 -100
  513. package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api/index.html +0 -24
  514. package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +0 -136
  515. package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +0 -16
  516. package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +0 -176
  517. package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +0 -188
  518. package/dist/serve/docs-ui/docs/secure/audit-your-rules/index.html +0 -51
  519. package/dist/serve/docs-ui/docs/secure/firestore-rules-limits/index.html +0 -106
  520. package/dist/serve/docs-ui/docs/secure/read-a-denial/index.html +0 -41
  521. package/dist/serve/docs-ui/docs/secure/rtdb-rules-in-typescript/index.html +0 -67
  522. package/dist/serve/docs-ui/docs/secure/rules-standard-library/index.html +0 -159
  523. package/dist/serve/docs-ui/docs/secure/secure-it-with-rules/index.html +0 -47
  524. package/dist/serve/docs-ui/docs/secure/simulate-and-lint/index.html +0 -95
  525. package/dist/serve/docs-ui/docs/secure/write-a-rules-test-suite/index.html +0 -82
  526. package/dist/serve/docs-ui/docs/ship/ship-to-production/index.html +0 -37
  527. package/dist/serve/docs-ui/docs/ship/test-in-node/index.html +0 -75
  528. package/dist/serve/docs-ui/docs/trust/how-we-know-it-matches-firebase/index.html +0 -132
  529. package/dist/serve/docs-ui/docs/trust/versioning-and-compatibility/index.html +0 -14
  530. package/dist/serve/docs-ui/index.html +0 -1
  531. package/dist/serve/studio-ui/assets/RulesCodeEditor-BDlH-5lp.js +0 -23
  532. package/dist/serve/studio-ui/assets/index-Bf9SSE8L.js +0 -1218
  533. package/dist/serve/studio-ui/assets/index-BlSGru_r.css +0 -1
  534. package/dist/serve/studio-ui/assets/seed-D_UjxfOU.js +0 -20
  535. package/dist/serve/studio-ui/index.html +0 -32
  536. package/dist/serve/worker/client/rtdb.d.ts +0 -36
  537. package/dist/serve/worker/client/rtdb.d.ts.map +0 -1
  538. package/dist/serve/worker/client/rtdb.js +0 -241
  539. package/dist/serve/worker/client/rtdb.js.map +0 -1
  540. package/src/serve/worker/client/rtdb.ts +0 -311
  541. /package/dist/serve/{docs-ui → site-ui}/404.html +0 -0
  542. /package/dist/serve/{docs-ui → site-ui}/_astro/_slug_.CXh9yTP1.css +0 -0
  543. /package/dist/serve/{docs-ui → site-ui}/docs/_rhythm.md +0 -0
  544. /package/dist/serve/{docs-ui → site-ui}/docs/agent/set-up-your-agent.md +0 -0
  545. /package/dist/serve/{docs-ui → site-ui}/docs/agent/watch-and-review.md +0 -0
  546. /package/dist/serve/{docs-ui → site-ui}/docs/agent/work-with-an-agent.md +0 -0
  547. /package/dist/serve/{docs-ui → site-ui}/docs/ai-compat.md +0 -0
  548. /package/dist/serve/{docs-ui → site-ui}/docs/api-reference.md +0 -0
  549. /package/dist/serve/{docs-ui → site-ui}/docs/app-compat.md +0 -0
  550. /package/dist/serve/{docs-ui → site-ui}/docs/auth-compat.md +0 -0
  551. /package/dist/serve/{docs-ui → site-ui}/docs/build/ai-logic.md +0 -0
  552. /package/dist/serve/{docs-ui → site-ui}/docs/build/authentication.md +0 -0
  553. /package/dist/serve/{docs-ui → site-ui}/docs/build/cloud-firestore.md +0 -0
  554. /package/dist/serve/{docs-ui → site-ui}/docs/build/cloud-messaging.md +0 -0
  555. /package/dist/serve/{docs-ui → site-ui}/docs/build/realtime-database.md +0 -0
  556. /package/dist/serve/{docs-ui → site-ui}/docs/create-pyric-reference-api.md +0 -0
  557. /package/dist/serve/{docs-ui → site-ui}/docs/functions-rtdb-compat.md +0 -0
  558. /package/dist/serve/{docs-ui → site-ui}/docs/get-started/how-the-swap-works.md +0 -0
  559. /package/dist/serve/{docs-ui → site-ui}/docs/get-started/start-building.md +0 -0
  560. /package/dist/serve/{docs-ui → site-ui}/docs/index.html +0 -0
  561. /package/dist/serve/{docs-ui → site-ui}/docs/observe/resolve-runtime-status.md +0 -0
  562. /package/dist/serve/{docs-ui → site-ui}/docs/observe/see-whats-happening.md +0 -0
  563. /package/dist/serve/{docs-ui → site-ui}/docs/observe/shape-your-data.md +0 -0
  564. /package/dist/serve/{docs-ui → site-ui}/docs/overview.md +0 -0
  565. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-app-reference-api.md +0 -0
  566. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-auth-reference-api.md +0 -0
  567. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-database-reference-api.md +0 -0
  568. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-messaging-reference-api.md +0 -0
  569. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-storage-reference-api.md +0 -0
  570. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ai-reference-api.md +0 -0
  571. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ai-scripting-reference-api.md +0 -0
  572. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-app-reference-api.md +0 -0
  573. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-auth-reference-api.md +0 -0
  574. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-assurance-browser-reference-api.md +0 -0
  575. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-assurance-reference-api.md +0 -0
  576. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-bridge-client-reference-api.md +0 -0
  577. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-bridge-reference-api.md +0 -0
  578. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-conformance-browser-reference-api.md +0 -0
  579. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-conformance-docs-reference-api.md +0 -0
  580. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-conformance-reference-api.md +0 -0
  581. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-credentials-node-reference-api.md +0 -0
  582. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-discover-reference-api.md +0 -0
  583. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-register-reference-api.md +0 -0
  584. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-remote-reference-api.md +0 -0
  585. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-verify-reference-api.md +0 -0
  586. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-messaging-reference-api.md +0 -0
  587. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-messaging-sw-reference-api.md +0 -0
  588. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-database-reference-api.md +0 -0
  589. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-firestore-reference-api.md +0 -0
  590. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-agents-reference-api.md +0 -0
  591. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-auth-hooks-reference-api.md +0 -0
  592. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-auth-reference-api.md +0 -0
  593. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-events-hooks-reference-api.md +0 -0
  594. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-events-reference-api.md +0 -0
  595. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-firestore-hooks-reference-api.md +0 -0
  596. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-primitives-reference-api.md +0 -0
  597. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rtdb-reference-api.md +0 -0
  598. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rules-hooks-reference-api.md +0 -0
  599. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rules-reference-api.md +0 -0
  600. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-storage-hooks-reference-api.md +0 -0
  601. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-traffic-hooks-reference-api.md +0 -0
  602. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-traffic-reference-api.md +0 -0
  603. /package/dist/serve/{docs-ui → site-ui}/docs/secure/audit-your-rules.md +0 -0
  604. /package/dist/serve/{docs-ui → site-ui}/docs/secure/firestore-rules-limits.md +0 -0
  605. /package/dist/serve/{docs-ui → site-ui}/docs/secure/read-a-denial.md +0 -0
  606. /package/dist/serve/{docs-ui → site-ui}/docs/secure/rtdb-rules-in-typescript.md +0 -0
  607. /package/dist/serve/{docs-ui → site-ui}/docs/secure/secure-it-with-rules.md +0 -0
  608. /package/dist/serve/{docs-ui → site-ui}/docs/secure/simulate-and-lint.md +0 -0
  609. /package/dist/serve/{docs-ui → site-ui}/docs/secure/write-a-rules-test-suite.md +0 -0
  610. /package/dist/serve/{docs-ui → site-ui}/docs/ship/ship-to-production.md +0 -0
  611. /package/dist/serve/{docs-ui → site-ui}/docs/ship/test-in-node.md +0 -0
  612. /package/dist/serve/{docs-ui → site-ui}/docs/trust/how-we-know-it-matches-firebase.md +0 -0
  613. /package/dist/serve/{docs-ui → site-ui}/docs/trust/versioning-and-compatibility.md +0 -0
  614. /package/dist/serve/{studio-ui → site-ui}/pyric-logo.svg +0 -0
@@ -1,82 +0,0 @@
1
- <!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Write a Security Rules test suite · Pyric Studio</title><meta name="description" content="A suite of allow/deny cases that runs in-process, gates CI, and can escalate to Google's own engine."><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_.DUci-duz.css"></head> <body> <header class="studio__bar"> <div class="studio__bar-inner"> <a class="studio__brand" href="/__pyric/ui/" aria-label="Pyric Studio">Pyric</a> <nav class="studio__nav" aria-label="Studio tabs"> <a class="studio__nav-tab" href="/__pyric/ui/"> Home </a><a class="studio__nav-tab" href="/__pyric/ui/firestore"> Firestore </a><a class="studio__nav-tab" href="/__pyric/ui/auth"> Auth </a><a class="studio__nav-tab" href="/__pyric/ui/rtdb"> RTDB </a><a class="studio__nav-tab" href="/__pyric/ui/storage"> Storage </a><a class="studio__nav-tab" href="/__pyric/ui/traffic"> Traffic </a><a class="studio__nav-tab" href="/__pyric/ui/settings"> Settings </a><a class="studio__nav-tab" href="/__pyric/ui/docs" aria-current="page"> Docs </a> </nav> </div> </header> <div class="docs-shell"> <details class="docs-nav-drawer"> <summary>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> </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/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" open> <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/" aria-current="page"> 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> </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><a class="docs-nav-toplink" href="/__pyric/ui/docs/trust/versioning-and-compatibility/"> Trust </a><details class="docs-nav-group"> <summary>Conformance</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/conformance-scores/"> Public API coverage </a> </li><li> <a href="/__pyric/ui/docs/trust/how-we-know-it-matches-firebase/"> How we know it matches Firebase </a> </li><li> <a href="/__pyric/ui/docs/app-compat/"> App </a> </li><li> <a href="/__pyric/ui/docs/ai-compat/"> AI Logic </a> </li><li> <a href="/__pyric/ui/docs/auth-compat/"> Auth </a> </li><li> <a href="/__pyric/ui/docs/firestore-compat/"> Firestore </a> </li><li> <a href="/__pyric/ui/docs/database-compat/"> Realtime Database </a> </li><li> <a href="/__pyric/ui/docs/storage-compat/"> Storage </a> </li><li> <a href="/__pyric/ui/docs/messaging-compat/"> Messaging </a> </li><li> <a href="/__pyric/ui/docs/functions-rtdb-compat/"> Functions · RTDB </a> </li><li> <a href="/__pyric/ui/docs/rules-compat/"> Rules </a> </li> </ul> </div> </div> </details> <details class="docs-nav-group"> <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-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> </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> </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/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" open> <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/" aria-current="page"> 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> </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><a class="docs-nav-toplink" href="/__pyric/ui/docs/trust/versioning-and-compatibility/" id="nav-group-trust"> Trust </a><details class="docs-nav-group" id="nav-group-conformance"> <summary>Conformance</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/conformance-scores/"> Public API coverage </a> </li><li> <a href="/__pyric/ui/docs/trust/how-we-know-it-matches-firebase/"> How we know it matches Firebase </a> </li><li> <a href="/__pyric/ui/docs/app-compat/"> App </a> </li><li> <a href="/__pyric/ui/docs/ai-compat/"> AI Logic </a> </li><li> <a href="/__pyric/ui/docs/auth-compat/"> Auth </a> </li><li> <a href="/__pyric/ui/docs/firestore-compat/"> Firestore </a> </li><li> <a href="/__pyric/ui/docs/database-compat/"> Realtime Database </a> </li><li> <a href="/__pyric/ui/docs/storage-compat/"> Storage </a> </li><li> <a href="/__pyric/ui/docs/messaging-compat/"> Messaging </a> </li><li> <a href="/__pyric/ui/docs/functions-rtdb-compat/"> Functions · RTDB </a> </li><li> <a href="/__pyric/ui/docs/rules-compat/"> Rules </a> </li> </ul> </div> </div> </details> <details class="docs-nav-group" id="nav-group-reference"> <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-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> </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"> <nav class="docs-breadcrumbs" aria-label="Breadcrumb"> <ol> <li> <a href="/__pyric/ui/docs/secure/secure-it-with-rules/">Secure &amp; debug</a> </li><li> <span class="docs-breadcrumbs-sep" aria-hidden="true">/</span> <span aria-current="page">Write a rules test suite</span> </li> </ol> </nav> <article class="prose"> <h1 id="write-a-security-rules-test-suite">Write a Security Rules test suite</h1>
3
- <p>A ruleset is code that decides who sees what. It deserves tests like any other code that matters.</p>
4
- <p>In Pyric a rules test is a small fixture, a <code>TestCase</code>, and a whole suite runs in-process in milliseconds. No Firebase project, no network, no deploy.</p>
5
- <h2 id="the-fixtures">The fixtures</h2>
6
- <p>A <code>TestCase</code> describes one hypothetical request and the verdict you expect:</p>
7
- <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#C678DD">import</span><span style="color:#ABB2BF"> { </span><span style="color:#E06C75">firestoreRules</span><span style="color:#ABB2BF">, </span><span style="color:#C678DD">type</span><span style="color:#E06C75"> FirestoreCase</span><span style="color:#ABB2BF"> } </span><span style="color:#C678DD">from</span><span style="color:#98C379"> 'pyric/rules'</span><span style="color:#ABB2BF">;</span></span>
8
- <span class="line"></span>
9
- <span class="line"><span style="color:#C678DD">const</span><span style="color:#E5C07B"> testCases</span><span style="color:#ABB2BF">: </span><span style="color:#E5C07B">FirestoreCase</span><span style="color:#ABB2BF">[] </span><span style="color:#56B6C2">=</span><span style="color:#ABB2BF"> [</span></span>
10
- <span class="line"><span style="color:#ABB2BF"> {</span></span>
11
- <span class="line"><span style="color:#E06C75"> description</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'authenticated read on /notes is allowed'</span><span style="color:#ABB2BF">,</span></span>
12
- <span class="line"><span style="color:#E06C75"> expectation</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'ALLOW'</span><span style="color:#ABB2BF">,</span></span>
13
- <span class="line"><span style="color:#E06C75"> method</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'get'</span><span style="color:#ABB2BF">,</span></span>
14
- <span class="line"><span style="color:#E06C75"> path</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'notes/n1'</span><span style="color:#ABB2BF">,</span></span>
15
- <span class="line"><span style="color:#E06C75"> auth</span><span style="color:#ABB2BF">: { </span><span style="color:#E06C75">uid</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'alice'</span><span style="color:#ABB2BF"> },</span></span>
16
- <span class="line"><span style="color:#ABB2BF"> },</span></span>
17
- <span class="line"><span style="color:#ABB2BF"> {</span></span>
18
- <span class="line"><span style="color:#E06C75"> description</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'unauthenticated read on /notes is denied'</span><span style="color:#ABB2BF">,</span></span>
19
- <span class="line"><span style="color:#E06C75"> expectation</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'DENY'</span><span style="color:#ABB2BF">,</span></span>
20
- <span class="line"><span style="color:#E06C75"> method</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'get'</span><span style="color:#ABB2BF">,</span></span>
21
- <span class="line"><span style="color:#E06C75"> path</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'notes/n1'</span><span style="color:#ABB2BF">,</span></span>
22
- <span class="line"><span style="color:#7F848E;font-style:italic"> // No auth field at all. request.auth is null.</span></span>
23
- <span class="line"><span style="color:#ABB2BF"> },</span></span>
24
- <span class="line"><span style="color:#ABB2BF"> {</span></span>
25
- <span class="line"><span style="color:#E06C75"> description</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'owner can update their own note'</span><span style="color:#ABB2BF">,</span></span>
26
- <span class="line"><span style="color:#E06C75"> expectation</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'ALLOW'</span><span style="color:#ABB2BF">,</span></span>
27
- <span class="line"><span style="color:#E06C75"> method</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'update'</span><span style="color:#ABB2BF">,</span></span>
28
- <span class="line"><span style="color:#E06C75"> path</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'notes/n1'</span><span style="color:#ABB2BF">,</span></span>
29
- <span class="line"><span style="color:#E06C75"> auth</span><span style="color:#ABB2BF">: { </span><span style="color:#E06C75">uid</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'alice'</span><span style="color:#ABB2BF"> },</span></span>
30
- <span class="line"><span style="color:#E06C75"> resource</span><span style="color:#ABB2BF">: { </span><span style="color:#E06C75">ownerId</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'alice'</span><span style="color:#ABB2BF">, </span><span style="color:#E06C75">title</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'old title'</span><span style="color:#ABB2BF"> },</span></span>
31
- <span class="line"><span style="color:#E06C75"> data</span><span style="color:#ABB2BF">: { </span><span style="color:#E06C75">ownerId</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'alice'</span><span style="color:#ABB2BF">, </span><span style="color:#E06C75">title</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'new title'</span><span style="color:#ABB2BF"> },</span></span>
32
- <span class="line"><span style="color:#ABB2BF"> },</span></span>
33
- <span class="line"><span style="color:#ABB2BF"> {</span></span>
34
- <span class="line"><span style="color:#E06C75"> description</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'admin can read any admin doc'</span><span style="color:#ABB2BF">,</span></span>
35
- <span class="line"><span style="color:#E06C75"> expectation</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'ALLOW'</span><span style="color:#ABB2BF">,</span></span>
36
- <span class="line"><span style="color:#E06C75"> method</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'get'</span><span style="color:#ABB2BF">,</span></span>
37
- <span class="line"><span style="color:#E06C75"> path</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'admin/config/secrets/api-keys'</span><span style="color:#ABB2BF">,</span></span>
38
- <span class="line"><span style="color:#E06C75"> auth</span><span style="color:#ABB2BF">: { </span><span style="color:#E06C75">uid</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'root'</span><span style="color:#ABB2BF">, </span><span style="color:#E06C75">token</span><span style="color:#ABB2BF">: { </span><span style="color:#E06C75">role</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">'admin'</span><span style="color:#ABB2BF"> } },</span></span>
39
- <span class="line"><span style="color:#ABB2BF"> },</span></span>
40
- <span class="line"><span style="color:#ABB2BF">];</span></span></code></pre>
41
- <p>The fields map straight onto what the rule sees. <code>resource</code> is the existing document, <code>data</code> is the proposed write, <code>auth.uid</code> becomes <code>request.auth.uid</code>, and <code>auth.token</code> becomes <code>request.auth.token</code> for rules that check custom claims.</p>
42
- <h2 id="run-the-suite">Run the suite</h2>
43
- <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#C678DD">const</span><span style="color:#E5C07B"> result</span><span style="color:#56B6C2"> =</span><span style="color:#61AFEF"> firestoreRules</span><span style="color:#ABB2BF">(</span><span style="color:#E06C75">source</span><span style="color:#ABB2BF">).</span><span style="color:#61AFEF">simulate</span><span style="color:#ABB2BF">(</span><span style="color:#E06C75">testCases</span><span style="color:#ABB2BF">);</span></span>
44
- <span class="line"></span>
45
- <span class="line"><span style="color:#C678DD">const</span><span style="color:#ABB2BF"> { </span><span style="color:#E5C07B">passed</span><span style="color:#ABB2BF">, </span><span style="color:#E5C07B">failed</span><span style="color:#ABB2BF">, </span><span style="color:#E5C07B">unsupported</span><span style="color:#ABB2BF">, </span><span style="color:#E5C07B">cases</span><span style="color:#ABB2BF"> } </span><span style="color:#56B6C2">=</span><span style="color:#E06C75"> result</span><span style="color:#ABB2BF">;</span></span>
46
- <span class="line"><span style="color:#E5C07B">console</span><span style="color:#ABB2BF">.</span><span style="color:#61AFEF">log</span><span style="color:#ABB2BF">(</span><span style="color:#98C379">`</span><span style="color:#C678DD">${</span><span style="color:#E06C75">passed</span><span style="color:#C678DD">}</span><span style="color:#98C379"> passed · </span><span style="color:#C678DD">${</span><span style="color:#E06C75">failed</span><span style="color:#C678DD">}</span><span style="color:#98C379"> failed · </span><span style="color:#C678DD">${</span><span style="color:#E06C75">unsupported</span><span style="color:#C678DD">}</span><span style="color:#98C379"> unsupported`</span><span style="color:#ABB2BF">);</span></span></code></pre>
47
- <p>A failed case means the simulator’s verdict disagreed with your <code>expectation</code>, and its <code>trace</code> shows which rule decided. An unsupported case means the simulator hit a feature it does not implement and abstained. It is not counted as a failure, and it is never a guess.</p>
48
- <p>Two fixture fields worth knowing before your suite grows:</p>
49
- <ul>
50
- <li>For <code>update</code> and merge writes, set <code>writeMode</code> so the simulator projects the post-write document the way Firestore does.</li>
51
- <li>For rules that read <code>request.time</code>, pin <code>requestTime</code> to an ISO timestamp so the verdict does not depend on the clock. Pass <code>{ testCases }</code> to <code>lintFirestoreRules</code> and <code>REQUEST_TIME_NOT_PINNED</code> flags the cases you missed.</li>
52
- </ul>
53
- <h2 id="gate-ci-on-it">Gate CI on it</h2>
54
- <p>The suite is a script, so CI is one exit code away:</p>
55
- <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#C678DD">if</span><span style="color:#ABB2BF"> (</span><span style="color:#E5C07B">result</span><span style="color:#ABB2BF">.</span><span style="color:#E06C75">failed</span><span style="color:#56B6C2"> ></span><span style="color:#D19A66"> 0</span><span style="color:#ABB2BF">) {</span></span>
56
- <span class="line"><span style="color:#C678DD"> for</span><span style="color:#ABB2BF"> (</span><span style="color:#C678DD">const</span><span style="color:#E5C07B"> r</span><span style="color:#C678DD"> of</span><span style="color:#E5C07B"> result</span><span style="color:#ABB2BF">.</span><span style="color:#E06C75">cases</span><span style="color:#ABB2BF">) {</span></span>
57
- <span class="line"><span style="color:#C678DD"> if</span><span style="color:#ABB2BF"> (</span><span style="color:#56B6C2">!</span><span style="color:#E5C07B">r</span><span style="color:#ABB2BF">.</span><span style="color:#E06C75">passed</span><span style="color:#ABB2BF">) </span><span style="color:#E5C07B">console</span><span style="color:#ABB2BF">.</span><span style="color:#61AFEF">error</span><span style="color:#ABB2BF">(</span><span style="color:#98C379">`FAILED: </span><span style="color:#C678DD">${</span><span style="color:#E5C07B">r</span><span style="color:#ABB2BF">.</span><span style="color:#E06C75">description</span><span style="color:#C678DD">}</span><span style="color:#98C379">`</span><span style="color:#ABB2BF">);</span></span>
58
- <span class="line"><span style="color:#ABB2BF"> }</span></span>
59
- <span class="line"><span style="color:#E5C07B"> process</span><span style="color:#ABB2BF">.</span><span style="color:#61AFEF">exit</span><span style="color:#ABB2BF">(</span><span style="color:#D19A66">1</span><span style="color:#ABB2BF">);</span></span>
60
- <span class="line"><span style="color:#ABB2BF">}</span></span></code></pre>
61
- <p>Sub-millisecond per case once the rules are parsed. There is no reason not to run this on every push.</p>
62
- <h2 id="use-googles-rules-test-api-when-production-authority-matters">Use Google’s Rules Test API when production authority matters</h2>
63
- <p>The hosted Rules Test API evaluates your cases on Google’s servers, in the same engine production uses, without deploying anything. It takes the same <code>TestCase</code> objects and returns the same result shape. It needs a real project and credentials:</p>
64
- <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#C678DD">import</span><span style="color:#ABB2BF"> { </span><span style="color:#E06C75">TestFirestoreRulesHandler</span><span style="color:#ABB2BF"> } </span><span style="color:#C678DD">from</span><span style="color:#98C379"> 'pyric/rules'</span><span style="color:#ABB2BF">;</span></span>
65
- <span class="line"><span style="color:#C678DD">import</span><span style="color:#ABB2BF"> { </span><span style="color:#E06C75">fromServiceAccount</span><span style="color:#ABB2BF"> } </span><span style="color:#C678DD">from</span><span style="color:#98C379"> '@pyric/cli/credentials/node'</span><span style="color:#ABB2BF">;</span></span>
66
- <span class="line"></span>
67
- <span class="line"><span style="color:#C678DD">const</span><span style="color:#E5C07B"> scope</span><span style="color:#56B6C2"> =</span><span style="color:#C678DD"> await</span><span style="color:#61AFEF"> fromServiceAccount</span><span style="color:#ABB2BF">(</span><span style="color:#98C379">'./service-account.json'</span><span style="color:#ABB2BF">);</span></span>
68
- <span class="line"><span style="color:#C678DD">const</span><span style="color:#E5C07B"> remote</span><span style="color:#56B6C2"> =</span><span style="color:#C678DD"> await</span><span style="color:#C678DD"> new</span><span style="color:#61AFEF"> TestFirestoreRulesHandler</span><span style="color:#ABB2BF">()</span></span>
69
- <span class="line"><span style="color:#ABB2BF"> .</span><span style="color:#61AFEF">execute</span><span style="color:#ABB2BF">(</span><span style="color:#E06C75">scope</span><span style="color:#ABB2BF">, </span><span style="color:#E06C75">source</span><span style="color:#ABB2BF">, </span><span style="color:#E06C75">testCases</span><span style="color:#ABB2BF">);</span></span></code></pre>
70
- <p>The practical pattern is local-first: run everything through the simulator, then send only the <code>UNSUPPORTED</code> cases to the hosted engine.</p>
71
- <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="ts"><code><span class="line"><span style="color:#C678DD">const</span><span style="color:#E5C07B"> escalate</span><span style="color:#56B6C2"> =</span><span style="color:#E5C07B"> testCases</span><span style="color:#ABB2BF">.</span><span style="color:#61AFEF">filter</span><span style="color:#ABB2BF">(</span></span>
72
- <span class="line"><span style="color:#ABB2BF"> (</span><span style="color:#E06C75;font-style:italic">_</span><span style="color:#ABB2BF">, </span><span style="color:#E06C75;font-style:italic">i</span><span style="color:#ABB2BF">) </span><span style="color:#C678DD">=></span><span style="color:#E5C07B"> result</span><span style="color:#ABB2BF">.</span><span style="color:#E06C75">cases</span><span style="color:#ABB2BF">[</span><span style="color:#E06C75">i</span><span style="color:#ABB2BF">].</span><span style="color:#E06C75">unsupported</span><span style="color:#ABB2BF">,</span></span>
73
- <span class="line"><span style="color:#ABB2BF">);</span></span>
74
- <span class="line"><span style="color:#C678DD">if</span><span style="color:#ABB2BF"> (</span><span style="color:#E5C07B">escalate</span><span style="color:#ABB2BF">.</span><span style="color:#E06C75">length</span><span style="color:#56B6C2"> ></span><span style="color:#D19A66"> 0</span><span style="color:#ABB2BF">) {</span></span>
75
- <span class="line"><span style="color:#C678DD"> const</span><span style="color:#E5C07B"> remote</span><span style="color:#56B6C2"> =</span><span style="color:#C678DD"> await</span><span style="color:#C678DD"> new</span><span style="color:#61AFEF"> TestFirestoreRulesHandler</span><span style="color:#ABB2BF">()</span></span>
76
- <span class="line"><span style="color:#ABB2BF"> .</span><span style="color:#61AFEF">execute</span><span style="color:#ABB2BF">(</span><span style="color:#E06C75">scope</span><span style="color:#ABB2BF">, </span><span style="color:#E06C75">source</span><span style="color:#ABB2BF">, </span><span style="color:#E06C75">escalate</span><span style="color:#ABB2BF">);</span></span>
77
- <span class="line"><span style="color:#ABB2BF">}</span></span></code></pre>
78
- <p>Each hosted call is one HTTP round-trip, tens to hundreds of milliseconds. The simulator itself is held to that engine’s answers by a parity corpus that runs in CI, so for most suites the local verdicts are the same verdicts, sooner.</p>
79
- <h2 id="run-the-suite-through-an-agent">Run the suite through an agent</h2>
80
- <p>An agent can run the local loop through <code>firestore_simulate_rules</code>, which means the rules it writes can arrive with explicit passing cases instead of a promise. See <a href="../../agent/work-with-an-agent/">Work with an agent</a>.</p>
81
- <h2 id="where-to-go-next">Where to go next</h2>
82
- <p>A test failure tells you a verdict was wrong. A denial explains why. Read <a href="../read-a-denial/">read a denial and understand it</a>. Before those rules ship, see <a href="../../ship/ship-to-production/">ship to production</a>.</p> </article> </main> <aside class="doc-toc" aria-label="On this page"> <h2 class="doc-toc-heading">On this page</h2> <ul> <li data-depth="2"> <a href="#the-fixtures">The fixtures</a> </li><li data-depth="2"> <a href="#run-the-suite">Run the suite</a> </li><li data-depth="2"> <a href="#gate-ci-on-it">Gate CI on it</a> </li><li data-depth="2"> <a href="#use-googles-rules-test-api-when-production-authority-matters">Use Google’s Rules Test API when production authority matters</a> </li><li data-depth="2"> <a href="#run-the-suite-through-an-agent">Run the suite through an agent</a> </li><li data-depth="2"> <a href="#where-to-go-next">Where to go next</a> </li> </ul> </aside> </div> <script type="module">const a=document.querySelector("[data-api-symbol-filter]"),d=[...document.querySelectorAll("[data-api-symbol-group]")],n=document.querySelector("[data-api-symbol-empty]");a?.addEventListener("input",()=>{const t=a.value.trim().toLowerCase();let o=0;for(const i of d){let e=0;i.querySelectorAll("[data-api-symbol]").forEach(l=>{const r=!t||(l.dataset.apiSymbol??"").includes(t);l.hidden=!r,r&&e++}),i.hidden=e===0,o+=e}n&&(n.hidden=o>0)});</script> <script type="module">const s=new Map;document.querySelectorAll('.doc-toc a[href^="#"]').forEach(t=>s.set(decodeURIComponent(t.hash.slice(1)),t));if(s.size>0){const t=new Set,n=()=>{let o=null;for(const e of s.keys())if(t.has(e)){o=e;break}s.forEach((e,c)=>e.classList.toggle("active",c===o))},r=new IntersectionObserver(o=>{for(const e of o)e.isIntersecting?t.add(e.target.id):t.delete(e.target.id);n()},{rootMargin:"-72px 0px -60% 0px"});s.forEach((o,e)=>{const c=document.getElementById(e);c&&r.observe(c)})}</script> <script type="module">document.querySelector('.studio__nav [aria-current="page"]')?.scrollIntoView({block:"nearest",inline:"center"});</script> </body> </html>
@@ -1,37 +0,0 @@
1
- <!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>The same code goes live · Pyric Studio</title><meta name="description" content="Deploy rules, indexes, hosting, and functions, and learn what would change before production does."><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_.DUci-duz.css"></head> <body> <header class="studio__bar"> <div class="studio__bar-inner"> <a class="studio__brand" href="/__pyric/ui/" aria-label="Pyric Studio">Pyric</a> <nav class="studio__nav" aria-label="Studio tabs"> <a class="studio__nav-tab" href="/__pyric/ui/"> Home </a><a class="studio__nav-tab" href="/__pyric/ui/firestore"> Firestore </a><a class="studio__nav-tab" href="/__pyric/ui/auth"> Auth </a><a class="studio__nav-tab" href="/__pyric/ui/rtdb"> RTDB </a><a class="studio__nav-tab" href="/__pyric/ui/storage"> Storage </a><a class="studio__nav-tab" href="/__pyric/ui/traffic"> Traffic </a><a class="studio__nav-tab" href="/__pyric/ui/settings"> Settings </a><a class="studio__nav-tab" href="/__pyric/ui/docs" aria-current="page"> Docs </a> </nav> </div> </header> <div class="docs-shell"> <details class="docs-nav-drawer"> <summary>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> </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/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> </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" open> <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/" aria-current="page"> 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><a class="docs-nav-toplink" href="/__pyric/ui/docs/trust/versioning-and-compatibility/"> Trust </a><details class="docs-nav-group"> <summary>Conformance</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/conformance-scores/"> Public API coverage </a> </li><li> <a href="/__pyric/ui/docs/trust/how-we-know-it-matches-firebase/"> How we know it matches Firebase </a> </li><li> <a href="/__pyric/ui/docs/app-compat/"> App </a> </li><li> <a href="/__pyric/ui/docs/ai-compat/"> AI Logic </a> </li><li> <a href="/__pyric/ui/docs/auth-compat/"> Auth </a> </li><li> <a href="/__pyric/ui/docs/firestore-compat/"> Firestore </a> </li><li> <a href="/__pyric/ui/docs/database-compat/"> Realtime Database </a> </li><li> <a href="/__pyric/ui/docs/storage-compat/"> Storage </a> </li><li> <a href="/__pyric/ui/docs/messaging-compat/"> Messaging </a> </li><li> <a href="/__pyric/ui/docs/functions-rtdb-compat/"> Functions · RTDB </a> </li><li> <a href="/__pyric/ui/docs/rules-compat/"> Rules </a> </li> </ul> </div> </div> </details> <details class="docs-nav-group"> <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-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> </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> </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/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> </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" open> <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/" aria-current="page"> 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><a class="docs-nav-toplink" href="/__pyric/ui/docs/trust/versioning-and-compatibility/" id="nav-group-trust"> Trust </a><details class="docs-nav-group" id="nav-group-conformance"> <summary>Conformance</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/conformance-scores/"> Public API coverage </a> </li><li> <a href="/__pyric/ui/docs/trust/how-we-know-it-matches-firebase/"> How we know it matches Firebase </a> </li><li> <a href="/__pyric/ui/docs/app-compat/"> App </a> </li><li> <a href="/__pyric/ui/docs/ai-compat/"> AI Logic </a> </li><li> <a href="/__pyric/ui/docs/auth-compat/"> Auth </a> </li><li> <a href="/__pyric/ui/docs/firestore-compat/"> Firestore </a> </li><li> <a href="/__pyric/ui/docs/database-compat/"> Realtime Database </a> </li><li> <a href="/__pyric/ui/docs/storage-compat/"> Storage </a> </li><li> <a href="/__pyric/ui/docs/messaging-compat/"> Messaging </a> </li><li> <a href="/__pyric/ui/docs/functions-rtdb-compat/"> Functions · RTDB </a> </li><li> <a href="/__pyric/ui/docs/rules-compat/"> Rules </a> </li> </ul> </div> </div> </details> <details class="docs-nav-group" id="nav-group-reference"> <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-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> </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"> <nav class="docs-breadcrumbs" aria-label="Breadcrumb"> <ol> <li> <a href="/__pyric/ui/docs/ship/ship-to-production/">Ship &amp; test</a> </li><li> <span class="docs-breadcrumbs-sep" aria-hidden="true">/</span> <span aria-current="page">Ship to production</span> </li> </ol> </nav> <article class="prose"> <h1 id="the-same-code-goes-live">The same code goes live</h1>
3
- <p>There is no graduation step. The <code>firebase/*</code> imports that resolved to the sandbox all through development resolve to real Firebase in your production build, and the config you passed to <code>initializeApp</code>, ignored in dev, is the config the built app uses in production. Your source does not change.</p>
4
- <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#61AFEF">vite</span><span style="color:#98C379"> build</span><span style="color:#7F848E;font-style:italic"> # ships the real firebase package, your config, your code</span></span>
5
- <span class="line"><span style="color:#61AFEF">firebase</span><span style="color:#98C379"> deploy</span><span style="color:#D19A66"> --only</span><span style="color:#98C379"> hosting</span></span></code></pre>
6
- <p>One guard stands between the two worlds. A sandbox build (from <code>vite build --mode development</code>) carries a marker in its <code>index.html</code>. Production hosting deploys should use an unmarked build (<code>vite build</code> / production mode) so a sandbox-wired dist never reaches production by accident. Prefer <code>firebase-tools</code> (or the Console) for the deploy itself.</p>
7
- <h2 id="deploy-security-rules">Deploy Security Rules</h2>
8
- <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#61AFEF">firebase</span><span style="color:#98C379"> deploy</span><span style="color:#D19A66"> --only</span><span style="color:#98C379"> firestore:rules</span></span></code></pre>
9
- <p>This pushes the <code>firestore.rules</code> named in <code>firebase.json</code> to your project. By the time you run it, those rules have already been exercised: every operation your app performed in development was evaluated against them, verdict by verdict. You are not deploying a guess.</p>
10
- <h2 id="deploy-indexes-from-application-query-shapes">Deploy indexes from application query shapes</h2>
11
- <p>Composite indexes usually live in a hand-kept file that drifts from the queries. Pyric derives them instead: index extraction reads your <code>query(collection, where, orderBy)</code> call sites in source and produces the <code>firestore.indexes.json</code> those shapes require (<code>pyric firestore indexes generate src</code>). Then:</p>
12
- <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#61AFEF">firebase</span><span style="color:#98C379"> deploy</span><span style="color:#D19A66"> --only</span><span style="color:#98C379"> firestore:indexes</span></span></code></pre>
13
- <p>Index builds are long-running on Firebase’s side; the Firebase CLI starts them and reports status.</p>
14
- <h2 id="learn-what-flips-before-production-does">Learn what flips before production does</h2>
15
- <p>This is the step the others earn. While you worked, <code>pyric dev</code> captured the session to <code>.pyric/last-session.json</code>: every write, every identity, every timestamp. Replay that session against the rules you are about to ship:</p>
16
- <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#61AFEF">pyric</span><span style="color:#98C379"> verify</span><span style="color:#D19A66"> --rules</span><span style="color:#98C379"> firestore=firestore.rules</span></span></code></pre>
17
- <p>The output names each operation whose verdict changed:</p>
18
- <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="plaintext"><code><span class="line"><span>✗ chat - rtdb: 1 failure(s)</span></span>
19
- <span class="line"><span> [rtdb] now-denied: set /rooms/r1/messages/m1 (PERMISSION_DENIED)</span></span></code></pre>
20
- <p><code>now-denied</code> means a write that succeeded during development would be rejected under the new rules. <code>now-allowed</code> means the reverse, a loosening. Auto-id aliases and timestamp drift are reported as informational, not failures, because replaying generated values is supposed to produce them. The exit code is 1 on any real divergence, which makes the CI gate one line:</p>
21
- <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="yaml"><code><span class="line"><span style="color:#ABB2BF">- </span><span style="color:#E06C75">run</span><span style="color:#ABB2BF">: </span><span style="color:#98C379">pyric verify journeys/ --rules firestore=firestore.rules</span></span></code></pre>
22
- <p>By default verification runs on the local sandbox engine. For Firestore you can also send the derived cases to Firebase’s hosted Rules Test API, or run both:</p>
23
- <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#61AFEF">pyric</span><span style="color:#98C379"> verify</span><span style="color:#D19A66"> --service</span><span style="color:#98C379"> firestore</span><span style="color:#D19A66"> --engine</span><span style="color:#98C379"> both</span><span style="color:#D19A66"> --project</span><span style="color:#98C379"> my-app</span><span style="color:#D19A66"> --rules</span><span style="color:#98C379"> firestore=firestore.rules</span></span></code></pre>
24
- <p><code>both</code> cross-checks the two engines against each other and flags any disagreement. That checks your rules and, at the same time, checks Pyric’s own engine against Google’s answer for your exact traffic. The Rules Test API evaluates cases only: it does not deploy rules or change a project. Hosted verification needs a project id plus <code>FIREBASE_SA_BASE64</code> or <code>GOOGLE_APPLICATION_CREDENTIALS</code> (or ADC); build a <code>ProjectScope</code> programmatically with <code>@pyric/cli/credentials/node</code> (<code>fromServiceAccount</code> / <code>fromAdc</code>).</p>
25
- <h2 id="deploy-hosting-and-functions">Deploy hosting and functions</h2>
26
- <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="bash"><code><span class="line"><span style="color:#61AFEF">firebase</span><span style="color:#98C379"> deploy</span><span style="color:#D19A66"> --only</span><span style="color:#98C379"> hosting</span><span style="color:#7F848E;font-style:italic"> # preview channels via firebase hosting:channel:deploy</span></span>
27
- <span class="line"><span style="color:#61AFEF">firebase</span><span style="color:#98C379"> deploy</span><span style="color:#D19A66"> --only</span><span style="color:#98C379"> functions</span></span></code></pre>
28
- <p>Use <code>firebase-tools</code> (or the Console) for production shipping. Preview channels give you a shareable URL with an expiry before anything touches the live site.</p>
29
- <h2 id="configure-credentials-for-verification-and-ci">Configure credentials for verification and CI</h2>
30
- <p><code>pyric verify</code> with the default <code>sandbox</code> engine needs no cloud credentials. For <code>--engine rules-test-api</code> or <code>both</code>:</p>
31
- <ul>
32
- <li><strong>CI / local</strong>: a service account via <code>FIREBASE_SA_BASE64</code> or <code>GOOGLE_APPLICATION_CREDENTIALS</code>.</li>
33
- <li><strong>Fallback</strong>: ambient application-default credentials.</li>
34
- </ul>
35
- <p>The full flag list is in the CLI reference.</p>
36
- <h2 id="where-to-go-next">Where to go next</h2>
37
- <p>To make the captured sessions you verify richer, see <a href="../../observe/shape-your-data/">Shape your data</a>. Use the Firebase Console or <code>firebase-tools</code> for production project setup.</p> </article> </main> <aside class="doc-toc" aria-label="On this page"> <h2 class="doc-toc-heading">On this page</h2> <ul> <li data-depth="2"> <a href="#deploy-security-rules">Deploy Security Rules</a> </li><li data-depth="2"> <a href="#deploy-indexes-from-application-query-shapes">Deploy indexes from application query shapes</a> </li><li data-depth="2"> <a href="#learn-what-flips-before-production-does">Learn what flips before production does</a> </li><li data-depth="2"> <a href="#deploy-hosting-and-functions">Deploy hosting and functions</a> </li><li data-depth="2"> <a href="#configure-credentials-for-verification-and-ci">Configure credentials for verification and CI</a> </li><li data-depth="2"> <a href="#where-to-go-next">Where to go next</a> </li> </ul> </aside> </div> <script type="module">const a=document.querySelector("[data-api-symbol-filter]"),d=[...document.querySelectorAll("[data-api-symbol-group]")],n=document.querySelector("[data-api-symbol-empty]");a?.addEventListener("input",()=>{const t=a.value.trim().toLowerCase();let o=0;for(const i of d){let e=0;i.querySelectorAll("[data-api-symbol]").forEach(l=>{const r=!t||(l.dataset.apiSymbol??"").includes(t);l.hidden=!r,r&&e++}),i.hidden=e===0,o+=e}n&&(n.hidden=o>0)});</script> <script type="module">const s=new Map;document.querySelectorAll('.doc-toc a[href^="#"]').forEach(t=>s.set(decodeURIComponent(t.hash.slice(1)),t));if(s.size>0){const t=new Set,n=()=>{let o=null;for(const e of s.keys())if(t.has(e)){o=e;break}s.forEach((e,c)=>e.classList.toggle("active",c===o))},r=new IntersectionObserver(o=>{for(const e of o)e.isIntersecting?t.add(e.target.id):t.delete(e.target.id);n()},{rootMargin:"-72px 0px -60% 0px"});s.forEach((o,e)=>{const c=document.getElementById(e);c&&r.observe(c)})}</script> <script type="module">document.querySelector('.studio__nav [aria-current="page"]')?.scrollIntoView({block:"nearest",inline:"center"});</script> </body> </html>