@pyric/cli 0.1.0-alpha.14 → 0.1.0-alpha.16

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 (606) 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/bridge/client/dispatch.js +1 -1
  6. package/dist/bridge/client/dispatch.js.map +1 -1
  7. package/dist/cli/serve.d.ts +1 -1
  8. package/dist/cli/serve.d.ts.map +1 -1
  9. package/dist/cli/serve.js +207 -284
  10. package/dist/cli/serve.js.map +1 -1
  11. package/dist/cli/service-command-records/database-rules-generate.d.ts +4 -0
  12. package/dist/cli/service-command-records/database-rules-generate.d.ts.map +1 -0
  13. package/dist/cli/service-command-records/database-rules-generate.js +3 -0
  14. package/dist/cli/service-command-records/database-rules-generate.js.map +1 -0
  15. package/dist/cli/service-command-records/database-rules-lint.d.ts +4 -0
  16. package/dist/cli/service-command-records/database-rules-lint.d.ts.map +1 -0
  17. package/dist/cli/service-command-records/database-rules-lint.js +3 -0
  18. package/dist/cli/service-command-records/database-rules-lint.js.map +1 -0
  19. package/dist/cli/service-command-records/database-rules-simulate.d.ts +4 -0
  20. package/dist/cli/service-command-records/database-rules-simulate.d.ts.map +1 -0
  21. package/dist/cli/service-command-records/database-rules-simulate.js +3 -0
  22. package/dist/cli/service-command-records/database-rules-simulate.js.map +1 -0
  23. package/dist/cli/service-command-records/database-rules-validate.d.ts +4 -0
  24. package/dist/cli/service-command-records/database-rules-validate.d.ts.map +1 -0
  25. package/dist/cli/service-command-records/database-rules-validate.js +3 -0
  26. package/dist/cli/service-command-records/database-rules-validate.js.map +1 -0
  27. package/dist/cli/service-command-records/firestore-indexes-generate.d.ts +4 -0
  28. package/dist/cli/service-command-records/firestore-indexes-generate.d.ts.map +1 -0
  29. package/dist/cli/service-command-records/firestore-indexes-generate.js +3 -0
  30. package/dist/cli/service-command-records/firestore-indexes-generate.js.map +1 -0
  31. package/dist/cli/service-command-records/firestore-rules-lint.d.ts +4 -0
  32. package/dist/cli/service-command-records/firestore-rules-lint.d.ts.map +1 -0
  33. package/dist/cli/service-command-records/firestore-rules-lint.js +3 -0
  34. package/dist/cli/service-command-records/firestore-rules-lint.js.map +1 -0
  35. package/dist/cli/service-command-records/firestore-rules-resolve.d.ts +4 -0
  36. package/dist/cli/service-command-records/firestore-rules-resolve.d.ts.map +1 -0
  37. package/dist/cli/service-command-records/firestore-rules-resolve.js +3 -0
  38. package/dist/cli/service-command-records/firestore-rules-resolve.js.map +1 -0
  39. package/dist/cli/service-command-records/firestore-rules-simulate.d.ts +4 -0
  40. package/dist/cli/service-command-records/firestore-rules-simulate.d.ts.map +1 -0
  41. package/dist/cli/service-command-records/firestore-rules-simulate.js +3 -0
  42. package/dist/cli/service-command-records/firestore-rules-simulate.js.map +1 -0
  43. package/dist/cli/service-command-records/firestore-rules-validate.d.ts +4 -0
  44. package/dist/cli/service-command-records/firestore-rules-validate.d.ts.map +1 -0
  45. package/dist/cli/service-command-records/firestore-rules-validate.js +3 -0
  46. package/dist/cli/service-command-records/firestore-rules-validate.js.map +1 -0
  47. package/dist/cli/service-command-records/storage-rules-lint.d.ts +4 -0
  48. package/dist/cli/service-command-records/storage-rules-lint.d.ts.map +1 -0
  49. package/dist/cli/service-command-records/storage-rules-lint.js +3 -0
  50. package/dist/cli/service-command-records/storage-rules-lint.js.map +1 -0
  51. package/dist/cli/service-command-records/storage-rules-simulate.d.ts +4 -0
  52. package/dist/cli/service-command-records/storage-rules-simulate.d.ts.map +1 -0
  53. package/dist/cli/service-command-records/storage-rules-simulate.js +3 -0
  54. package/dist/cli/service-command-records/storage-rules-simulate.js.map +1 -0
  55. package/dist/cli/service-commands.d.ts +7 -0
  56. package/dist/cli/service-commands.d.ts.map +1 -1
  57. package/dist/cli/service-commands.generated.d.ts +35 -0
  58. package/dist/cli/service-commands.generated.d.ts.map +1 -0
  59. package/dist/cli/service-commands.generated.js +25 -0
  60. package/dist/cli/service-commands.generated.js.map +1 -0
  61. package/dist/cli/service-commands.js +23 -40
  62. package/dist/cli/service-commands.js.map +1 -1
  63. package/dist/conformance/.generated/can-i-use-browser.d.ts.map +1 -1
  64. package/dist/conformance/.generated/can-i-use-browser.js +1 -1
  65. package/dist/conformance/.generated/can-i-use-browser.js.map +1 -1
  66. package/dist/conformance/.generated/can-i-use.d.ts.map +1 -1
  67. package/dist/conformance/.generated/can-i-use.js +1 -1
  68. package/dist/conformance/.generated/can-i-use.js.map +1 -1
  69. package/dist/conformance/.generated/conformance-docs.d.ts.map +1 -1
  70. package/dist/conformance/.generated/conformance-docs.js +1 -1
  71. package/dist/conformance/.generated/conformance-docs.js.map +1 -1
  72. package/dist/functions-rtdb/development-runtime.d.ts +63 -0
  73. package/dist/functions-rtdb/development-runtime.d.ts.map +1 -0
  74. package/dist/functions-rtdb/development-runtime.js +244 -0
  75. package/dist/functions-rtdb/development-runtime.js.map +1 -0
  76. package/dist/serve/bridge-mount.d.ts +32 -2
  77. package/dist/serve/bridge-mount.d.ts.map +1 -1
  78. package/dist/serve/bridge-mount.js +232 -18
  79. package/dist/serve/bridge-mount.js.map +1 -1
  80. package/dist/serve/bundler.d.ts +2 -18
  81. package/dist/serve/bundler.d.ts.map +1 -1
  82. package/dist/serve/bundler.js +7 -35
  83. package/dist/serve/bundler.js.map +1 -1
  84. package/dist/serve/entries/app-client.d.ts.map +1 -1
  85. package/dist/serve/entries/app-client.js +5 -5
  86. package/dist/serve/entries/app-client.js.map +1 -1
  87. package/dist/serve/entries/auth-helper-core.d.ts +32 -6
  88. package/dist/serve/entries/auth-helper-core.d.ts.map +1 -1
  89. package/dist/serve/entries/auth-helper-core.js +82 -24
  90. package/dist/serve/entries/auth-helper-core.js.map +1 -1
  91. package/dist/serve/entries/auth.d.ts.map +1 -1
  92. package/dist/serve/entries/auth.js +6 -4
  93. package/dist/serve/entries/auth.js.map +1 -1
  94. package/dist/serve/entries/database.d.ts +28 -0
  95. package/dist/serve/entries/database.d.ts.map +1 -1
  96. package/dist/serve/entries/database.js +95 -26
  97. package/dist/serve/entries/database.js.map +1 -1
  98. package/dist/serve/entries/init.d.ts.map +1 -1
  99. package/dist/serve/entries/init.js +21 -12
  100. package/dist/serve/entries/init.js.map +1 -1
  101. package/dist/serve/html-injection.d.ts +5 -0
  102. package/dist/serve/html-injection.d.ts.map +1 -0
  103. package/dist/serve/html-injection.js +59 -0
  104. package/dist/serve/html-injection.js.map +1 -0
  105. package/dist/serve/namespace.d.ts +6 -22
  106. package/dist/serve/namespace.d.ts.map +1 -1
  107. package/dist/serve/namespace.js +23 -145
  108. package/dist/serve/namespace.js.map +1 -1
  109. package/dist/serve/runtime/worker-replacement.d.ts +1 -2
  110. package/dist/serve/runtime/worker-replacement.d.ts.map +1 -1
  111. package/dist/serve/sandbox-session.d.ts +78 -0
  112. package/dist/serve/sandbox-session.d.ts.map +1 -0
  113. package/dist/serve/sandbox-session.js +171 -0
  114. package/dist/serve/sandbox-session.js.map +1 -0
  115. package/dist/serve/server.d.ts +5 -2
  116. package/dist/serve/server.d.ts.map +1 -1
  117. package/dist/serve/server.js +21 -5
  118. package/dist/serve/server.js.map +1 -1
  119. package/dist/serve/site-tree.d.ts +8 -0
  120. package/dist/serve/site-tree.d.ts.map +1 -0
  121. package/dist/serve/site-tree.js +113 -0
  122. package/dist/serve/site-tree.js.map +1 -0
  123. package/dist/serve/site-ui/_astro/RulesCodeEditor.CzwHdCi9.js +23 -0
  124. package/dist/serve/site-ui/_astro/_example_.jevZ7OdV.css +1 -0
  125. package/dist/serve/site-ui/_astro/_slug_.BoKXYrnu.css +1 -0
  126. package/dist/serve/site-ui/_astro/_studio_.BtYpqe1A.css +1 -0
  127. package/dist/serve/site-ui/_astro/app.4HeLP_FA.js +109 -0
  128. package/dist/serve/site-ui/_astro/app.BgSnCR5G.js +1 -0
  129. package/dist/serve/site-ui/_astro/app.BsFsMjn0.css +1 -0
  130. package/dist/serve/site-ui/_astro/chess-showcase.CnoxIle5.js +1 -0
  131. package/dist/serve/site-ui/_astro/chess-source-explorer.C5k9c5yK.js +1 -0
  132. package/dist/serve/site-ui/_astro/chess-v2.CFHmd3UL.js +354 -0
  133. package/dist/serve/site-ui/_astro/client.D2ORs4B-.js +25 -0
  134. package/dist/serve/site-ui/_astro/example-runtime.R1d96L6-.js +291 -0
  135. package/dist/serve/site-ui/_astro/index.BJiOemMX.js +1 -0
  136. package/dist/serve/site-ui/_astro/index.DBy5LfQW.js +9 -0
  137. package/dist/serve/site-ui/_astro/index.DNyk7q8W.js +9 -0
  138. package/dist/serve/site-ui/_astro/jsx-runtime.D_zvdyIk.js +9 -0
  139. package/dist/serve/site-ui/_astro/reads.BrKNdKAa.js +1 -0
  140. package/dist/serve/site-ui/_astro/sandbox-controls.BTb3EbQp.js +1153 -0
  141. package/dist/serve/site-ui/_astro/seed.EyI3VYEu.js +20 -0
  142. package/dist/serve/site-ui/auth/index.html +11 -0
  143. package/dist/serve/site-ui/docs/_rhythm/index.html +100 -0
  144. package/dist/serve/site-ui/docs/agent/set-up-your-agent/index.html +43 -0
  145. package/dist/serve/site-ui/docs/agent/watch-and-review/index.html +26 -0
  146. package/dist/serve/site-ui/docs/agent/work-with-an-agent/index.html +70 -0
  147. package/dist/serve/{docs-ui → site-ui}/docs/ai-compat/index.html +3 -3
  148. package/dist/serve/site-ui/docs/api-reference/index.html +68 -0
  149. package/dist/serve/{docs-ui → site-ui}/docs/app-compat/index.html +3 -3
  150. package/dist/serve/{docs-ui → site-ui}/docs/auth-compat/index.html +3 -3
  151. package/dist/serve/site-ui/docs/build/ai-logic/index.html +64 -0
  152. package/dist/serve/site-ui/docs/build/authentication/index.html +66 -0
  153. package/dist/serve/site-ui/docs/build/cloud-firestore/index.html +84 -0
  154. package/dist/serve/site-ui/docs/build/cloud-messaging/index.html +71 -0
  155. package/dist/serve/site-ui/docs/build/cloud-storage/index.html +66 -0
  156. package/dist/serve/{docs-ui → site-ui}/docs/build/cloud-storage.md +2 -2
  157. package/dist/serve/site-ui/docs/build/realtime-database/index.html +67 -0
  158. package/dist/serve/site-ui/docs/conformance-scores/index.html +50 -0
  159. package/dist/serve/{docs-ui → site-ui}/docs/conformance-scores.md +3 -3
  160. package/dist/serve/site-ui/docs/create-pyric-reference-api/index.html +531 -0
  161. package/dist/serve/{docs-ui → site-ui}/docs/database-compat/index.html +211 -168
  162. package/dist/serve/{docs-ui → site-ui}/docs/database-compat.md +208 -170
  163. package/dist/serve/site-ui/docs/examples/chess/index.html +384 -0
  164. package/dist/serve/site-ui/docs/examples/chess.md +57 -0
  165. package/dist/serve/site-ui/docs/examples/index.html +3 -0
  166. package/dist/serve/site-ui/docs/examples.md +4 -0
  167. package/dist/serve/{docs-ui → site-ui}/docs/firestore-compat/index.html +55 -91
  168. package/dist/serve/{docs-ui → site-ui}/docs/firestore-compat.md +52 -88
  169. package/dist/serve/site-ui/docs/functions-rtdb-compat/index.html +73 -0
  170. package/dist/serve/site-ui/docs/get-started/how-the-swap-works/index.html +29 -0
  171. package/dist/serve/site-ui/docs/get-started/start-building/index.html +33 -0
  172. package/dist/serve/{docs-ui → site-ui}/docs/index.json +595 -26
  173. package/dist/serve/site-ui/docs/messaging-compat/index.html +324 -0
  174. package/dist/serve/{docs-ui → site-ui}/docs/messaging-compat.md +71 -1
  175. package/dist/serve/site-ui/docs/observe/resolve-runtime-status/index.html +28 -0
  176. package/dist/serve/site-ui/docs/observe/see-whats-happening/index.html +74 -0
  177. package/dist/serve/site-ui/docs/observe/shape-your-data/index.html +45 -0
  178. package/dist/serve/site-ui/docs/overview/index.html +17 -0
  179. package/dist/serve/site-ui/docs/pyric-admin-app-reference-api/index.html +186 -0
  180. package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-auth-reference-api/index.html +4 -4
  181. package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-database-reference-api/index.html +4 -4
  182. package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-firestore-reference-api/index.html +318 -202
  183. package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-firestore-reference-api.md +154 -27
  184. package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-messaging-reference-api/index.html +5 -5
  185. package/dist/serve/site-ui/docs/pyric-admin-storage-reference-api/index.html +318 -0
  186. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ai-reference-api/index.html +5 -5
  187. package/dist/serve/site-ui/docs/pyric-ai-scripting-reference-api/index.html +160 -0
  188. package/dist/serve/site-ui/docs/pyric-app-reference-api/index.html +425 -0
  189. package/dist/serve/{docs-ui → site-ui}/docs/pyric-auth-reference-api/index.html +6 -6
  190. package/dist/serve/{docs-ui → site-ui}/docs/pyric-auth-reference-api.md +1 -1
  191. package/dist/serve/site-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +60 -0
  192. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-assurance-reference-api/index.html +4 -4
  193. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-bridge-client-reference-api/index.html +4 -4
  194. package/dist/serve/site-ui/docs/pyric-cli-bridge-reference-api/index.html +507 -0
  195. package/dist/serve/site-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +258 -0
  196. package/dist/serve/site-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +51 -0
  197. package/dist/serve/site-ui/docs/pyric-cli-conformance-reference-api/index.html +308 -0
  198. package/dist/serve/site-ui/docs/pyric-cli-credentials-node-reference-api/index.html +68 -0
  199. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-discover-reference-api/index.html +4 -4
  200. package/dist/serve/site-ui/docs/pyric-cli-register-reference-api/index.html +11 -0
  201. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-remote-reference-api/index.html +4 -4
  202. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-serve-worker-reference-api/index.html +1186 -1384
  203. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-serve-worker-reference-api.md +817 -1291
  204. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-verify-reference-api/index.html +4 -4
  205. package/dist/serve/site-ui/docs/pyric-cli-vite-reference-api/index.html +126 -0
  206. package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-vite-reference-api.md +1 -1
  207. package/dist/serve/site-ui/docs/pyric-database-reference-api/index.html +2641 -0
  208. package/dist/serve/{docs-ui → site-ui}/docs/pyric-database-reference-api.md +1055 -158
  209. package/dist/serve/{docs-ui → site-ui}/docs/pyric-firestore-reference-api/index.html +311 -249
  210. package/dist/serve/{docs-ui → site-ui}/docs/pyric-firestore-reference-api.md +72 -54
  211. package/dist/serve/site-ui/docs/pyric-messaging-reference-api/index.html +509 -0
  212. package/dist/serve/site-ui/docs/pyric-messaging-sw-reference-api/index.html +182 -0
  213. package/dist/serve/{docs-ui → site-ui}/docs/pyric-rules-reference-api/index.html +7 -26
  214. package/dist/serve/{docs-ui → site-ui}/docs/pyric-rules-reference-api.md +13 -23
  215. package/dist/serve/site-ui/docs/pyric-sandbox-database-reference-api/index.html +121 -0
  216. package/dist/serve/site-ui/docs/pyric-sandbox-firestore-reference-api/index.html +203 -0
  217. package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-reference-api/index.html +26 -5
  218. package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-reference-api.md +22 -22
  219. package/dist/serve/{docs-ui → site-ui}/docs/pyric-storage-reference-api/index.html +5 -15
  220. package/dist/serve/{docs-ui → site-ui}/docs/pyric-storage-reference-api.md +0 -13
  221. package/dist/serve/site-ui/docs/pyric-ui-agents-reference-api/index.html +639 -0
  222. package/dist/serve/site-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +100 -0
  223. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-auth-reference-api/index.html +4 -4
  224. package/dist/serve/site-ui/docs/pyric-ui-events-hooks-reference-api/index.html +24 -0
  225. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-events-reference-api/index.html +4 -4
  226. package/dist/serve/site-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +136 -0
  227. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-firestore-reference-api/index.html +7 -7
  228. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-firestore-reference-api.md +4 -4
  229. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-primitives-reference-api/index.html +4 -4
  230. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rtdb-reference-api/index.html +4 -4
  231. package/dist/serve/site-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +16 -0
  232. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rules-reference-api/index.html +4 -4
  233. package/dist/serve/site-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +176 -0
  234. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-storage-reference-api/index.html +10 -11
  235. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-storage-reference-api.md +7 -8
  236. package/dist/serve/site-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +188 -0
  237. package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-traffic-reference-api/index.html +4 -4
  238. package/dist/serve/{docs-ui → site-ui}/docs/rules-compat/index.html +87 -57
  239. package/dist/serve/{docs-ui → site-ui}/docs/rules-compat.md +84 -54
  240. package/dist/serve/site-ui/docs/secure/audit-your-rules/index.html +51 -0
  241. package/dist/serve/site-ui/docs/secure/firestore-rules-limits/index.html +106 -0
  242. package/dist/serve/site-ui/docs/secure/read-a-denial/index.html +41 -0
  243. package/dist/serve/site-ui/docs/secure/rtdb-rules-in-typescript/index.html +67 -0
  244. package/dist/serve/site-ui/docs/secure/rules-standard-library/index.html +159 -0
  245. package/dist/serve/{docs-ui → site-ui}/docs/secure/rules-standard-library.md +2 -2
  246. package/dist/serve/site-ui/docs/secure/secure-it-with-rules/index.html +47 -0
  247. package/dist/serve/site-ui/docs/secure/simulate-and-lint/index.html +95 -0
  248. package/dist/serve/site-ui/docs/secure/write-a-rules-test-suite/index.html +82 -0
  249. package/dist/serve/site-ui/docs/ship/ship-to-production/index.html +37 -0
  250. package/dist/serve/site-ui/docs/ship/test-in-node/index.html +75 -0
  251. package/dist/serve/{docs-ui → site-ui}/docs/storage-compat/index.html +8 -8
  252. package/dist/serve/{docs-ui → site-ui}/docs/storage-compat.md +5 -5
  253. package/dist/serve/site-ui/docs/trust/how-we-know-it-matches-firebase/index.html +132 -0
  254. package/dist/serve/site-ui/docs/trust/rules-standard-library/index.html +861 -0
  255. package/dist/serve/site-ui/docs/trust/rules-standard-library.md +344 -0
  256. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research/index.html +582 -0
  257. package/dist/serve/site-ui/docs/trust/storage-rules-stdlib-research.md +448 -0
  258. package/dist/serve/site-ui/docs/trust/versioning-and-compatibility/index.html +14 -0
  259. package/dist/serve/{docs-ui → site-ui}/docs/tutorial/index.html +4 -4
  260. package/dist/serve/{docs-ui → site-ui}/docs/tutorial.md +1 -1
  261. package/dist/serve/site-ui/examples/chess/index.html +2 -0
  262. package/dist/serve/site-ui/examples/firestore-first-write/index.html +2 -0
  263. package/dist/serve/site-ui/firestore/index.html +11 -0
  264. package/dist/serve/site-ui/index.html +11 -0
  265. package/dist/serve/{docs-ui → site-ui}/llms.txt +6 -2
  266. package/dist/serve/site-ui/rtdb/index.html +11 -0
  267. package/dist/serve/site-ui/settings/index.html +11 -0
  268. package/dist/serve/site-ui/storage/index.html +11 -0
  269. package/dist/serve/site-ui/studio-routes.json +1 -0
  270. package/dist/serve/site-ui/traffic/index.html +11 -0
  271. package/dist/serve/standalone-assets.d.ts +4 -10
  272. package/dist/serve/standalone-assets.d.ts.map +1 -1
  273. package/dist/serve/standalone-assets.js +8 -21
  274. package/dist/serve/standalone-assets.js.map +1 -1
  275. package/dist/serve/vite-functions-development.d.ts +29 -0
  276. package/dist/serve/vite-functions-development.d.ts.map +1 -0
  277. package/dist/serve/vite-functions-development.js +150 -0
  278. package/dist/serve/vite-functions-development.js.map +1 -0
  279. package/dist/serve/vite-generation-bridge.d.ts +17 -0
  280. package/dist/serve/vite-generation-bridge.d.ts.map +1 -0
  281. package/dist/serve/vite-generation-bridge.js +47 -0
  282. package/dist/serve/vite-generation-bridge.js.map +1 -0
  283. package/dist/serve/vite-generation-functions.d.ts +35 -0
  284. package/dist/serve/vite-generation-functions.d.ts.map +1 -0
  285. package/dist/serve/vite-generation-functions.js +46 -0
  286. package/dist/serve/vite-generation-functions.js.map +1 -0
  287. package/dist/serve/vite-generation-middleware.d.ts +10 -0
  288. package/dist/serve/vite-generation-middleware.d.ts.map +1 -0
  289. package/dist/serve/vite-generation-middleware.js +40 -0
  290. package/dist/serve/vite-generation-middleware.js.map +1 -0
  291. package/dist/serve/vite-generation-rules-watch.d.ts +8 -0
  292. package/dist/serve/vite-generation-rules-watch.d.ts.map +1 -0
  293. package/dist/serve/vite-generation-rules-watch.js +33 -0
  294. package/dist/serve/vite-generation-rules-watch.js.map +1 -0
  295. package/dist/serve/vite-module-swap.d.ts +16 -0
  296. package/dist/serve/vite-module-swap.d.ts.map +1 -0
  297. package/dist/serve/vite-module-swap.js +96 -0
  298. package/dist/serve/vite-module-swap.js.map +1 -0
  299. package/dist/serve/vite-page-runtime.d.ts +29 -0
  300. package/dist/serve/vite-page-runtime.d.ts.map +1 -0
  301. package/dist/serve/vite-page-runtime.js +71 -0
  302. package/dist/serve/vite-page-runtime.js.map +1 -0
  303. package/dist/serve/vite-plugin.d.ts +44 -4
  304. package/dist/serve/vite-plugin.d.ts.map +1 -1
  305. package/dist/serve/vite-plugin.js +62 -864
  306. package/dist/serve/vite-plugin.js.map +1 -1
  307. package/dist/serve/vite-sandbox-generation.d.ts +57 -0
  308. package/dist/serve/vite-sandbox-generation.d.ts.map +1 -0
  309. package/dist/serve/vite-sandbox-generation.js +178 -0
  310. package/dist/serve/vite-sandbox-generation.js.map +1 -0
  311. package/dist/serve/worker/client/disconnect.d.ts.map +1 -1
  312. package/dist/serve/worker/client/disconnect.js +2 -0
  313. package/dist/serve/worker/client/disconnect.js.map +1 -1
  314. package/dist/serve/worker/client/handles.d.ts +5 -0
  315. package/dist/serve/worker/client/handles.d.ts.map +1 -1
  316. package/dist/serve/worker/client/handles.js.map +1 -1
  317. package/dist/serve/worker/client/pagehide.d.ts +13 -0
  318. package/dist/serve/worker/client/pagehide.d.ts.map +1 -0
  319. package/dist/serve/worker/client/pagehide.js +19 -0
  320. package/dist/serve/worker/client/pagehide.js.map +1 -0
  321. package/dist/serve/worker/client/rtdb-admin.d.ts +8 -0
  322. package/dist/serve/worker/client/rtdb-admin.d.ts.map +1 -0
  323. package/dist/serve/worker/client/rtdb-admin.js +39 -0
  324. package/dist/serve/worker/client/rtdb-admin.js.map +1 -0
  325. package/dist/serve/worker/client/rtdb-connection-lifecycle.d.ts +15 -0
  326. package/dist/serve/worker/client/rtdb-connection-lifecycle.d.ts.map +1 -0
  327. package/dist/serve/worker/client/rtdb-connection-lifecycle.js +45 -0
  328. package/dist/serve/worker/client/rtdb-connection-lifecycle.js.map +1 -0
  329. package/dist/serve/worker/client/rtdb-controls.d.ts +6 -0
  330. package/dist/serve/worker/client/rtdb-controls.d.ts.map +1 -0
  331. package/dist/serve/worker/client/rtdb-controls.js +8 -0
  332. package/dist/serve/worker/client/rtdb-controls.js.map +1 -0
  333. package/dist/serve/worker/client/rtdb-listeners.d.ts +24 -0
  334. package/dist/serve/worker/client/rtdb-listeners.d.ts.map +1 -0
  335. package/dist/serve/worker/client/rtdb-listeners.js +262 -0
  336. package/dist/serve/worker/client/rtdb-listeners.js.map +1 -0
  337. package/dist/serve/worker/client/rtdb-reads.d.ts +4 -0
  338. package/dist/serve/worker/client/rtdb-reads.d.ts.map +1 -0
  339. package/dist/serve/worker/client/rtdb-reads.js +11 -0
  340. package/dist/serve/worker/client/rtdb-reads.js.map +1 -0
  341. package/dist/serve/worker/client/rtdb-references.d.ts +19 -0
  342. package/dist/serve/worker/client/rtdb-references.d.ts.map +1 -0
  343. package/dist/serve/worker/client/rtdb-references.js +63 -0
  344. package/dist/serve/worker/client/rtdb-references.js.map +1 -0
  345. package/dist/serve/worker/client/rtdb-snapshots.d.ts +20 -0
  346. package/dist/serve/worker/client/rtdb-snapshots.d.ts.map +1 -0
  347. package/dist/serve/worker/client/rtdb-snapshots.js +64 -0
  348. package/dist/serve/worker/client/rtdb-snapshots.js.map +1 -0
  349. package/dist/serve/worker/client/rtdb-transactions.d.ts +14 -0
  350. package/dist/serve/worker/client/rtdb-transactions.d.ts.map +1 -0
  351. package/dist/serve/worker/client/rtdb-transactions.js +34 -0
  352. package/dist/serve/worker/client/rtdb-transactions.js.map +1 -0
  353. package/dist/serve/worker/client/rtdb-writes.d.ts +8 -0
  354. package/dist/serve/worker/client/rtdb-writes.d.ts.map +1 -0
  355. package/dist/serve/worker/client/rtdb-writes.js +65 -0
  356. package/dist/serve/worker/client/rtdb-writes.js.map +1 -0
  357. package/dist/serve/worker/client.d.ts +0 -2
  358. package/dist/serve/worker/client.d.ts.map +1 -1
  359. package/dist/serve/worker/client.js +0 -2
  360. package/dist/serve/worker/client.js.map +1 -1
  361. package/dist/serve/worker/entry.js +2 -2
  362. package/dist/serve/worker/entry.js.map +1 -1
  363. package/dist/serve/worker/host/dispatch.d.ts +2 -0
  364. package/dist/serve/worker/host/dispatch.d.ts.map +1 -1
  365. package/dist/serve/worker/host/dispatch.js +24 -2
  366. package/dist/serve/worker/host/dispatch.js.map +1 -1
  367. package/dist/serve/worker/host/rtdb.d.ts +6 -2
  368. package/dist/serve/worker/host/rtdb.d.ts.map +1 -1
  369. package/dist/serve/worker/host/rtdb.js +224 -2
  370. package/dist/serve/worker/host/rtdb.js.map +1 -1
  371. package/dist/serve/worker/host/studio.d.ts.map +1 -1
  372. package/dist/serve/worker/host/studio.js +2 -0
  373. package/dist/serve/worker/host/studio.js.map +1 -1
  374. package/dist/serve/worker/host/subscriptions.d.ts.map +1 -1
  375. package/dist/serve/worker/host/subscriptions.js +3 -3
  376. package/dist/serve/worker/host/subscriptions.js.map +1 -1
  377. package/dist/serve/worker/host.d.ts +1 -1
  378. package/dist/serve/worker/host.d.ts.map +1 -1
  379. package/dist/serve/worker/host.js +1 -1
  380. package/dist/serve/worker/host.js.map +1 -1
  381. package/dist/serve/worker/index.d.ts +16 -1
  382. package/dist/serve/worker/index.d.ts.map +1 -1
  383. package/dist/serve/worker/index.js +17 -4
  384. package/dist/serve/worker/index.js.map +1 -1
  385. package/dist/serve/worker/protocol.d.ts +57 -0
  386. package/dist/serve/worker/protocol.d.ts.map +1 -1
  387. package/dist/serve/worker/protocol.js.map +1 -1
  388. package/dist/serve/worker/rtdb-value-equality.d.ts +3 -0
  389. package/dist/serve/worker/rtdb-value-equality.d.ts.map +1 -0
  390. package/dist/serve/worker/rtdb-value-equality.js +18 -0
  391. package/dist/serve/worker/rtdb-value-equality.js.map +1 -0
  392. package/dist/serve/worker/serve-init.js +2 -2
  393. package/dist/serve/worker/serve-init.js.map +1 -1
  394. package/dist/serve/worker/service-worker-relay.js +2 -2
  395. package/dist/serve/worker/service-worker-relay.js.map +1 -1
  396. package/package.json +7 -5
  397. package/src/assurance/.generated/conformance-verdicts.ts +120 -75
  398. package/src/bridge/client/dispatch.ts +1 -1
  399. package/src/cli/serve.ts +215 -307
  400. package/src/cli/service-command-records/database-rules-generate.ts +3 -0
  401. package/src/cli/service-command-records/database-rules-lint.ts +3 -0
  402. package/src/cli/service-command-records/database-rules-simulate.ts +3 -0
  403. package/src/cli/service-command-records/database-rules-validate.ts +3 -0
  404. package/src/cli/service-command-records/firestore-indexes-generate.ts +3 -0
  405. package/src/cli/service-command-records/firestore-rules-lint.ts +3 -0
  406. package/src/cli/service-command-records/firestore-rules-resolve.ts +3 -0
  407. package/src/cli/service-command-records/firestore-rules-simulate.ts +3 -0
  408. package/src/cli/service-command-records/firestore-rules-validate.ts +3 -0
  409. package/src/cli/service-command-records/storage-rules-lint.ts +3 -0
  410. package/src/cli/service-command-records/storage-rules-simulate.ts +3 -0
  411. package/src/cli/service-commands.generated.ts +27 -0
  412. package/src/cli/service-commands.test.ts +43 -0
  413. package/src/cli/service-commands.ts +36 -51
  414. package/src/conformance/.generated/can-i-use-browser.ts +1 -1
  415. package/src/conformance/.generated/can-i-use.ts +1 -1
  416. package/src/conformance/.generated/conformance-docs.ts +1 -1
  417. package/src/functions-rtdb/development-runtime.ts +299 -0
  418. package/src/serve/bridge-mount.ts +253 -19
  419. package/src/serve/bundler.ts +8 -34
  420. package/src/serve/entries/app-client.ts +5 -4
  421. package/src/serve/entries/auth-helper-core.ts +117 -30
  422. package/src/serve/entries/auth.ts +8 -4
  423. package/src/serve/entries/database.ts +180 -57
  424. package/src/serve/entries/init.ts +30 -20
  425. package/src/serve/html-injection.ts +65 -0
  426. package/src/serve/namespace.ts +26 -169
  427. package/src/serve/runtime/worker-replacement.ts +1 -1
  428. package/src/serve/sandbox-session.ts +233 -0
  429. package/src/serve/server.ts +20 -5
  430. package/src/serve/site-tree.ts +146 -0
  431. package/src/serve/standalone-assets.ts +9 -26
  432. package/src/serve/vite-functions-development.ts +201 -0
  433. package/src/serve/vite-generation-bridge.ts +66 -0
  434. package/src/serve/vite-generation-functions.ts +78 -0
  435. package/src/serve/vite-generation-middleware.ts +56 -0
  436. package/src/serve/vite-generation-rules-watch.ts +37 -0
  437. package/src/serve/vite-module-swap.ts +119 -0
  438. package/src/serve/vite-page-runtime.ts +100 -0
  439. package/src/serve/vite-plugin.ts +78 -883
  440. package/src/serve/vite-sandbox-generation.ts +255 -0
  441. package/src/serve/worker/client/disconnect.ts +3 -1
  442. package/src/serve/worker/client/handles.ts +5 -0
  443. package/src/serve/worker/client/pagehide.ts +31 -0
  444. package/src/serve/worker/client/rtdb-admin.ts +74 -0
  445. package/src/serve/worker/client/rtdb-connection-lifecycle.ts +52 -0
  446. package/src/serve/worker/client/rtdb-controls.ts +8 -0
  447. package/src/serve/worker/client/rtdb-listeners.ts +337 -0
  448. package/src/serve/worker/client/rtdb-reads.ts +12 -0
  449. package/src/serve/worker/client/rtdb-references.ts +85 -0
  450. package/src/serve/worker/client/rtdb-snapshots.ts +118 -0
  451. package/src/serve/worker/client/rtdb-transactions.ts +51 -0
  452. package/src/serve/worker/client/rtdb-writes.ts +74 -0
  453. package/src/serve/worker/client.ts +0 -2
  454. package/src/serve/worker/entry.ts +2 -2
  455. package/src/serve/worker/host/dispatch.ts +22 -2
  456. package/src/serve/worker/host/rtdb.ts +243 -2
  457. package/src/serve/worker/host/studio.ts +2 -0
  458. package/src/serve/worker/host/subscriptions.ts +8 -4
  459. package/src/serve/worker/host.ts +1 -1
  460. package/src/serve/worker/index.ts +58 -10
  461. package/src/serve/worker/protocol.ts +23 -2
  462. package/src/serve/worker/rtdb-value-equality.ts +17 -0
  463. package/src/serve/worker/serve-init.ts +2 -2
  464. package/src/serve/worker/service-worker-relay.ts +2 -2
  465. package/dist/serve/docs-ui/_astro/_slug_.DUci-duz.css +0 -1
  466. package/dist/serve/docs-ui/docs/_rhythm/index.html +0 -100
  467. package/dist/serve/docs-ui/docs/agent/set-up-your-agent/index.html +0 -43
  468. package/dist/serve/docs-ui/docs/agent/watch-and-review/index.html +0 -26
  469. package/dist/serve/docs-ui/docs/agent/work-with-an-agent/index.html +0 -70
  470. package/dist/serve/docs-ui/docs/api-reference/index.html +0 -68
  471. package/dist/serve/docs-ui/docs/build/ai-logic/index.html +0 -64
  472. package/dist/serve/docs-ui/docs/build/authentication/index.html +0 -66
  473. package/dist/serve/docs-ui/docs/build/cloud-firestore/index.html +0 -70
  474. package/dist/serve/docs-ui/docs/build/cloud-messaging/index.html +0 -71
  475. package/dist/serve/docs-ui/docs/build/cloud-storage/index.html +0 -66
  476. package/dist/serve/docs-ui/docs/build/realtime-database/index.html +0 -67
  477. package/dist/serve/docs-ui/docs/conformance-scores/index.html +0 -50
  478. package/dist/serve/docs-ui/docs/create-pyric-reference-api/index.html +0 -531
  479. package/dist/serve/docs-ui/docs/functions-rtdb-compat/index.html +0 -73
  480. package/dist/serve/docs-ui/docs/get-started/how-the-swap-works/index.html +0 -29
  481. package/dist/serve/docs-ui/docs/get-started/start-building/index.html +0 -33
  482. package/dist/serve/docs-ui/docs/messaging-compat/index.html +0 -265
  483. package/dist/serve/docs-ui/docs/observe/resolve-runtime-status/index.html +0 -28
  484. package/dist/serve/docs-ui/docs/observe/see-whats-happening/index.html +0 -74
  485. package/dist/serve/docs-ui/docs/observe/shape-your-data/index.html +0 -45
  486. package/dist/serve/docs-ui/docs/overview/index.html +0 -17
  487. package/dist/serve/docs-ui/docs/pyric-admin-app-reference-api/index.html +0 -186
  488. package/dist/serve/docs-ui/docs/pyric-admin-storage-reference-api/index.html +0 -318
  489. package/dist/serve/docs-ui/docs/pyric-ai-scripting-reference-api/index.html +0 -160
  490. package/dist/serve/docs-ui/docs/pyric-app-reference-api/index.html +0 -425
  491. package/dist/serve/docs-ui/docs/pyric-cli-assurance-browser-reference-api/index.html +0 -60
  492. package/dist/serve/docs-ui/docs/pyric-cli-bridge-reference-api/index.html +0 -507
  493. package/dist/serve/docs-ui/docs/pyric-cli-conformance-browser-reference-api/index.html +0 -258
  494. package/dist/serve/docs-ui/docs/pyric-cli-conformance-docs-reference-api/index.html +0 -51
  495. package/dist/serve/docs-ui/docs/pyric-cli-conformance-reference-api/index.html +0 -308
  496. package/dist/serve/docs-ui/docs/pyric-cli-credentials-node-reference-api/index.html +0 -68
  497. package/dist/serve/docs-ui/docs/pyric-cli-register-reference-api/index.html +0 -11
  498. package/dist/serve/docs-ui/docs/pyric-cli-vite-reference-api/index.html +0 -126
  499. package/dist/serve/docs-ui/docs/pyric-database-reference-api/index.html +0 -1852
  500. package/dist/serve/docs-ui/docs/pyric-messaging-reference-api/index.html +0 -509
  501. package/dist/serve/docs-ui/docs/pyric-messaging-sw-reference-api/index.html +0 -182
  502. package/dist/serve/docs-ui/docs/pyric-sandbox-database-reference-api/index.html +0 -121
  503. package/dist/serve/docs-ui/docs/pyric-sandbox-firestore-reference-api/index.html +0 -203
  504. package/dist/serve/docs-ui/docs/pyric-ui-agents-reference-api/index.html +0 -639
  505. package/dist/serve/docs-ui/docs/pyric-ui-auth-hooks-reference-api/index.html +0 -100
  506. package/dist/serve/docs-ui/docs/pyric-ui-events-hooks-reference-api/index.html +0 -24
  507. package/dist/serve/docs-ui/docs/pyric-ui-firestore-hooks-reference-api/index.html +0 -136
  508. package/dist/serve/docs-ui/docs/pyric-ui-rules-hooks-reference-api/index.html +0 -16
  509. package/dist/serve/docs-ui/docs/pyric-ui-storage-hooks-reference-api/index.html +0 -176
  510. package/dist/serve/docs-ui/docs/pyric-ui-traffic-hooks-reference-api/index.html +0 -188
  511. package/dist/serve/docs-ui/docs/secure/audit-your-rules/index.html +0 -51
  512. package/dist/serve/docs-ui/docs/secure/firestore-rules-limits/index.html +0 -106
  513. package/dist/serve/docs-ui/docs/secure/read-a-denial/index.html +0 -41
  514. package/dist/serve/docs-ui/docs/secure/rtdb-rules-in-typescript/index.html +0 -67
  515. package/dist/serve/docs-ui/docs/secure/rules-standard-library/index.html +0 -159
  516. package/dist/serve/docs-ui/docs/secure/secure-it-with-rules/index.html +0 -47
  517. package/dist/serve/docs-ui/docs/secure/simulate-and-lint/index.html +0 -95
  518. package/dist/serve/docs-ui/docs/secure/write-a-rules-test-suite/index.html +0 -82
  519. package/dist/serve/docs-ui/docs/ship/ship-to-production/index.html +0 -37
  520. package/dist/serve/docs-ui/docs/ship/test-in-node/index.html +0 -75
  521. package/dist/serve/docs-ui/docs/trust/how-we-know-it-matches-firebase/index.html +0 -132
  522. package/dist/serve/docs-ui/docs/trust/versioning-and-compatibility/index.html +0 -14
  523. package/dist/serve/docs-ui/index.html +0 -1
  524. package/dist/serve/studio-ui/assets/RulesCodeEditor-BDlH-5lp.js +0 -23
  525. package/dist/serve/studio-ui/assets/index-Bf9SSE8L.js +0 -1218
  526. package/dist/serve/studio-ui/assets/index-BlSGru_r.css +0 -1
  527. package/dist/serve/studio-ui/assets/seed-D_UjxfOU.js +0 -20
  528. package/dist/serve/studio-ui/index.html +0 -32
  529. package/dist/serve/worker/client/rtdb.d.ts +0 -36
  530. package/dist/serve/worker/client/rtdb.d.ts.map +0 -1
  531. package/dist/serve/worker/client/rtdb.js +0 -241
  532. package/dist/serve/worker/client/rtdb.js.map +0 -1
  533. package/src/serve/worker/client/rtdb.ts +0 -311
  534. /package/dist/serve/{docs-ui → site-ui}/404.html +0 -0
  535. /package/dist/serve/{docs-ui → site-ui}/_astro/_slug_.CXh9yTP1.css +0 -0
  536. /package/dist/serve/{docs-ui → site-ui}/docs/_rhythm.md +0 -0
  537. /package/dist/serve/{docs-ui → site-ui}/docs/agent/set-up-your-agent.md +0 -0
  538. /package/dist/serve/{docs-ui → site-ui}/docs/agent/watch-and-review.md +0 -0
  539. /package/dist/serve/{docs-ui → site-ui}/docs/agent/work-with-an-agent.md +0 -0
  540. /package/dist/serve/{docs-ui → site-ui}/docs/ai-compat.md +0 -0
  541. /package/dist/serve/{docs-ui → site-ui}/docs/api-reference.md +0 -0
  542. /package/dist/serve/{docs-ui → site-ui}/docs/app-compat.md +0 -0
  543. /package/dist/serve/{docs-ui → site-ui}/docs/auth-compat.md +0 -0
  544. /package/dist/serve/{docs-ui → site-ui}/docs/build/ai-logic.md +0 -0
  545. /package/dist/serve/{docs-ui → site-ui}/docs/build/authentication.md +0 -0
  546. /package/dist/serve/{docs-ui → site-ui}/docs/build/cloud-firestore.md +0 -0
  547. /package/dist/serve/{docs-ui → site-ui}/docs/build/cloud-messaging.md +0 -0
  548. /package/dist/serve/{docs-ui → site-ui}/docs/build/realtime-database.md +0 -0
  549. /package/dist/serve/{docs-ui → site-ui}/docs/create-pyric-reference-api.md +0 -0
  550. /package/dist/serve/{docs-ui → site-ui}/docs/functions-rtdb-compat.md +0 -0
  551. /package/dist/serve/{docs-ui → site-ui}/docs/get-started/how-the-swap-works.md +0 -0
  552. /package/dist/serve/{docs-ui → site-ui}/docs/get-started/start-building.md +0 -0
  553. /package/dist/serve/{docs-ui → site-ui}/docs/index.html +0 -0
  554. /package/dist/serve/{docs-ui → site-ui}/docs/observe/resolve-runtime-status.md +0 -0
  555. /package/dist/serve/{docs-ui → site-ui}/docs/observe/see-whats-happening.md +0 -0
  556. /package/dist/serve/{docs-ui → site-ui}/docs/observe/shape-your-data.md +0 -0
  557. /package/dist/serve/{docs-ui → site-ui}/docs/overview.md +0 -0
  558. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-app-reference-api.md +0 -0
  559. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-auth-reference-api.md +0 -0
  560. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-database-reference-api.md +0 -0
  561. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-messaging-reference-api.md +0 -0
  562. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-admin-storage-reference-api.md +0 -0
  563. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ai-reference-api.md +0 -0
  564. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ai-scripting-reference-api.md +0 -0
  565. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-app-reference-api.md +0 -0
  566. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-assurance-browser-reference-api.md +0 -0
  567. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-assurance-reference-api.md +0 -0
  568. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-bridge-client-reference-api.md +0 -0
  569. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-bridge-reference-api.md +0 -0
  570. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-conformance-browser-reference-api.md +0 -0
  571. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-conformance-docs-reference-api.md +0 -0
  572. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-conformance-reference-api.md +0 -0
  573. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-credentials-node-reference-api.md +0 -0
  574. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-discover-reference-api.md +0 -0
  575. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-register-reference-api.md +0 -0
  576. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-remote-reference-api.md +0 -0
  577. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-cli-verify-reference-api.md +0 -0
  578. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-messaging-reference-api.md +0 -0
  579. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-messaging-sw-reference-api.md +0 -0
  580. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-database-reference-api.md +0 -0
  581. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-sandbox-firestore-reference-api.md +0 -0
  582. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-agents-reference-api.md +0 -0
  583. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-auth-hooks-reference-api.md +0 -0
  584. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-auth-reference-api.md +0 -0
  585. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-events-hooks-reference-api.md +0 -0
  586. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-events-reference-api.md +0 -0
  587. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-firestore-hooks-reference-api.md +0 -0
  588. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-primitives-reference-api.md +0 -0
  589. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rtdb-reference-api.md +0 -0
  590. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rules-hooks-reference-api.md +0 -0
  591. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-rules-reference-api.md +0 -0
  592. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-storage-hooks-reference-api.md +0 -0
  593. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-traffic-hooks-reference-api.md +0 -0
  594. /package/dist/serve/{docs-ui → site-ui}/docs/pyric-ui-traffic-reference-api.md +0 -0
  595. /package/dist/serve/{docs-ui → site-ui}/docs/secure/audit-your-rules.md +0 -0
  596. /package/dist/serve/{docs-ui → site-ui}/docs/secure/firestore-rules-limits.md +0 -0
  597. /package/dist/serve/{docs-ui → site-ui}/docs/secure/read-a-denial.md +0 -0
  598. /package/dist/serve/{docs-ui → site-ui}/docs/secure/rtdb-rules-in-typescript.md +0 -0
  599. /package/dist/serve/{docs-ui → site-ui}/docs/secure/secure-it-with-rules.md +0 -0
  600. /package/dist/serve/{docs-ui → site-ui}/docs/secure/simulate-and-lint.md +0 -0
  601. /package/dist/serve/{docs-ui → site-ui}/docs/secure/write-a-rules-test-suite.md +0 -0
  602. /package/dist/serve/{docs-ui → site-ui}/docs/ship/ship-to-production.md +0 -0
  603. /package/dist/serve/{docs-ui → site-ui}/docs/ship/test-in-node.md +0 -0
  604. /package/dist/serve/{docs-ui → site-ui}/docs/trust/how-we-know-it-matches-firebase.md +0 -0
  605. /package/dist/serve/{docs-ui → site-ui}/docs/trust/versioning-and-compatibility.md +0 -0
  606. /package/dist/serve/{studio-ui → site-ui}/pyric-logo.svg +0 -0
@@ -0,0 +1,384 @@
1
+ <!DOCTYPE html><html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Play chess against Security Rules · Pyric Studio</title><meta name="description" content="Play chess against Firestore Security Rules in an isolated Pyric sandbox."><link rel="icon" type="image/svg+xml" href="/__pyric/ui/pyric-logo.svg"><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet"><link rel="stylesheet" href="/__pyric/ui/_astro/_slug_.CXh9yTP1.css">
2
+ <link rel="stylesheet" href="/__pyric/ui/_astro/_slug_.BoKXYrnu.css"></head> <body> <header class="studio__bar" data-astro-cid-mw7aashj> <div class="studio__bar-inner" data-astro-cid-mw7aashj> <a class="studio__brand" href="/__pyric/ui/" aria-label="Pyric Studio" data-astro-cid-mw7aashj>Pyric</a> <nav class="studio__nav" aria-label="Studio tabs" data-astro-cid-mw7aashj> <a class="studio__nav-tab" href="/__pyric/ui/" data-astro-cid-mw7aashj> Home </a><a class="studio__nav-tab" href="/__pyric/ui/firestore" data-astro-cid-mw7aashj> Firestore </a><a class="studio__nav-tab" href="/__pyric/ui/auth" data-astro-cid-mw7aashj> Auth </a><a class="studio__nav-tab" href="/__pyric/ui/rtdb" data-astro-cid-mw7aashj> RTDB </a><a class="studio__nav-tab" href="/__pyric/ui/storage" data-astro-cid-mw7aashj> Storage </a><a class="studio__nav-tab" href="/__pyric/ui/traffic" data-astro-cid-mw7aashj> Traffic </a><a class="studio__nav-tab" href="/__pyric/ui/settings" data-astro-cid-mw7aashj> Settings </a><a class="studio__nav-tab" href="/__pyric/ui/docs" aria-current="page" data-astro-cid-mw7aashj> Docs </a> </nav> </div> </header> <div class="docs-shell docs-shell--example" data-astro-cid-mw7aashj> <details class="docs-nav-drawer" data-astro-cid-mw7aashj> <summary data-astro-cid-mw7aashj>Navigate</summary> <nav class="docs-nav" aria-label="Documentation"> <div class="docs-search" data-index-url="/__pyric/ui/docs/index.json"> <div class="docs-search-field"> <svg class="docs-search-icon" viewBox="0 0 16 16" width="14" height="14" aria-hidden="true"> <path d="M11.5 11.5 15 15M13 7A6 6 0 1 1 1 7a6 6 0 0 1 12 0Z" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"></path> </svg> <input type="text" class="docs-search-input" placeholder="Search docs" aria-label="Search docs" autocomplete="off" spellcheck="false"> <kbd class="docs-search-kbd">⌘K</kbd> </div> <ul class="docs-search-results" hidden></ul> </div> <script type="module">let i=null;function d(t){return i||(i=fetch(t).then(e=>e.json())),i}function l(t,e){return t.title.toLowerCase().includes(e)||t.excerpt.toLowerCase().includes(e)?!0:t.headings.some(r=>r.text.toLowerCase().includes(e))}function u(t,e,r){if(e.innerHTML="",t.length===0){e.hidden=!1;{const n=document.createElement("li");n.className="docs-search-empty",n.textContent="No matches",e.appendChild(n)}return}e.hidden=!1;for(const n of t.slice(0,8)){const s=document.createElement("li"),c=document.createElement("a");c.href=n.path;const o=document.createElement("span");o.className="docs-search-result-title",o.textContent=n.title;const a=document.createElement("span");a.className="docs-search-result-meta",a.textContent=[n.group,n.section].filter(Boolean).join(" / "),c.append(o,a),s.appendChild(c),e.appendChild(s)}}document.querySelectorAll(".docs-search").forEach(t=>{const e=t.dataset.indexUrl,r=t.querySelector(".docs-search-input"),n=t.querySelector(".docs-search-results");r.addEventListener("input",async()=>{const s=r.value.trim().toLowerCase();if(!s){n.hidden=!0,n.innerHTML="";return}const{pages:c}=await d(e);r.value.trim().toLowerCase()===s&&u(c.filter(o=>l(o,s)),n)}),r.addEventListener("focus",()=>{d(e),n.childElementCount>0&&(n.hidden=!1)}),r.addEventListener("keydown",s=>{s.key==="Escape"&&(r.value="",n.hidden=!0,n.innerHTML="",r.blur())}),r.addEventListener("blur",()=>{window.setTimeout(()=>{n.hidden=!0},150)})});document.addEventListener("keydown",t=>{if(!(t.metaKey||t.ctrlKey)||t.key.toLowerCase()!=="k")return;const e=[...document.querySelectorAll(".docs-search-input")].find(r=>r.offsetParent!==null);e&&(t.preventDefault(),e.focus(),e.select())});</script> <details class="docs-nav-group"> <summary>Overview</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/overview/"> Overview </a> </li><li> <a href="/__pyric/ui/docs/tutorial/"> Tutorial </a> </li><li> <a href="/__pyric/ui/docs/examples/"> Examples </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Get started</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/get-started/start-building/"> Quickstart </a> </li><li> <a href="/__pyric/ui/docs/get-started/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/"> Write a rules test suite </a> </li><li> <a href="/__pyric/ui/docs/secure/read-a-denial/"> Read a denial and understand it </a> </li><li> <a href="/__pyric/ui/docs/secure/rules-standard-library/"> The rules standard library </a> </li><li> <a href="/__pyric/ui/docs/secure/rtdb-rules-in-typescript/"> RTDB rules in TypeScript </a> </li><li> <a href="/__pyric/ui/docs/secure/firestore-rules-limits/"> Rules limits </a> </li><li> <a href="/__pyric/ui/docs/secure/audit-your-rules/"> Audit rules and data </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading"> Examples </h2> <ul> <li> <a href="/__pyric/ui/docs/examples/chess/" aria-current="page"> Chess showcase </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Observe &amp; shape</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/observe/see-whats-happening/"> Traffic &amp; rule verdicts </a> </li><li> <a href="/__pyric/ui/docs/observe/resolve-runtime-status/"> Runtime status </a> </li><li> <a href="/__pyric/ui/docs/observe/shape-your-data/"> Seed, snapshot, replay </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Ship &amp; test</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/ship/ship-to-production/"> Ship to production </a> </li><li> <a href="/__pyric/ui/docs/ship/test-in-node/"> Test in Node </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Work with an agent</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/agent/set-up-your-agent/"> Connect an agent </a> </li><li> <a href="/__pyric/ui/docs/agent/work-with-an-agent/"> Use the MCP tools </a> </li><li> <a href="/__pyric/ui/docs/agent/watch-and-review/"> Watch in Pyric Studio </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <summary>Trust</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/trust/versioning-and-compatibility/"> Versioning and the fb tag </a> </li><li> <a href="/__pyric/ui/docs/trust/storage-rules-stdlib-research/"> Storage Rules modules: evidence and design </a> </li><li> <a href="/__pyric/ui/docs/trust/rules-standard-library/"> Rules standard library reference </a> </li> </ul> </div> </div> </details><details class="docs-nav-group"> <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><li> <a href="/__pyric/ui/docs/examples/"> Examples </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-get-started"> <summary>Get started</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/get-started/start-building/"> Quickstart </a> </li><li> <a href="/__pyric/ui/docs/get-started/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/"> Write a rules test suite </a> </li><li> <a href="/__pyric/ui/docs/secure/read-a-denial/"> Read a denial and understand it </a> </li><li> <a href="/__pyric/ui/docs/secure/rules-standard-library/"> The rules standard library </a> </li><li> <a href="/__pyric/ui/docs/secure/rtdb-rules-in-typescript/"> RTDB rules in TypeScript </a> </li><li> <a href="/__pyric/ui/docs/secure/firestore-rules-limits/"> Rules limits </a> </li><li> <a href="/__pyric/ui/docs/secure/audit-your-rules/"> Audit rules and data </a> </li> </ul> </div><div class="docs-nav-section"> <h2 class="docs-nav-heading" id="nav-section-secure-debug-examples"> Examples </h2> <ul> <li> <a href="/__pyric/ui/docs/examples/chess/" aria-current="page"> Chess showcase </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-observe-shape"> <summary>Observe &amp; shape</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/observe/see-whats-happening/"> Traffic &amp; rule verdicts </a> </li><li> <a href="/__pyric/ui/docs/observe/resolve-runtime-status/"> Runtime status </a> </li><li> <a href="/__pyric/ui/docs/observe/shape-your-data/"> Seed, snapshot, replay </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-ship-test"> <summary>Ship &amp; test</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/ship/ship-to-production/"> Ship to production </a> </li><li> <a href="/__pyric/ui/docs/ship/test-in-node/"> Test in Node </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-work-with-an-agent"> <summary>Work with an agent</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/agent/set-up-your-agent/"> Connect an agent </a> </li><li> <a href="/__pyric/ui/docs/agent/work-with-an-agent/"> Use the MCP tools </a> </li><li> <a href="/__pyric/ui/docs/agent/watch-and-review/"> Watch in Pyric Studio </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-trust"> <summary>Trust</summary> <div class="docs-nav-group-body"> <div class="docs-nav-section"> <ul> <li> <a href="/__pyric/ui/docs/trust/versioning-and-compatibility/"> Versioning and the fb tag </a> </li><li> <a href="/__pyric/ui/docs/trust/storage-rules-stdlib-research/"> Storage Rules modules: evidence and design </a> </li><li> <a href="/__pyric/ui/docs/trust/rules-standard-library/"> Rules standard library reference </a> </li> </ul> </div> </div> </details><details class="docs-nav-group" id="nav-group-conformance"> <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 doc-main--example" data-astro-cid-mw7aashj> <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> <a href="#nav-section-secure-debug-examples">Examples</a> </li><li> <span class="docs-breadcrumbs-sep" aria-hidden="true">/</span> <span aria-current="page">Chess showcase</span> </li> </ol> </nav> <div class="example-doc-page" data-astro-cid-ghke3xma> <header class="example-header" data-astro-cid-3f5pqdpq> <p data-astro-cid-3f5pqdpq>Firestore Security Rules · Isolated browser sandbox</p> <h1 data-astro-cid-3f5pqdpq>Play chess against Security Rules</h1> <div data-astro-cid-3f5pqdpq>Move a piece; Pyric commits the new board or denies the write.</div> </header> <div class="example-stage is-showcase" data-astro-cid-xgvwrve7> <iframe title="Play chess against Security Rules" src="/__pyric/ui/examples/chess/" sandbox="allow-scripts allow-same-origin" scrolling="no" data-example-frame data-example-id="chess" data-min-height="560" data-astro-cid-xgvwrve7></iframe> </div> <script type="module">const i=t=>{if(t.dataset.sizingInstalled==="true")return;t.dataset.sizingInstalled="true";let n;const o=()=>{const e=t.contentDocument;if(!e)return;const s=Math.max(Number(t.dataset.minHeight??0),e.documentElement.scrollHeight,e.body?.scrollHeight??0);t.style.height=`${s}px`};t.addEventListener("load",()=>{n?.disconnect();const e=t.contentDocument;e&&(n=new ResizeObserver(o),n.observe(e.documentElement),e.body&&n.observe(e.body),o())})};document.querySelectorAll("[data-example-frame]").forEach(i);</script> <article class="prose example-explanation" data-astro-cid-ghke3xma> <h2 id="try-the-board">Try the board</h2>
3
+ <p>Choose a piece and its destination. <code>e2 → e4</code> is allowed; <code>e2 → e5</code> is denied and leaves the board unchanged. Switch the identity to see turn ownership enforced.</p>
4
+ <p>Choose a scenario to run a complete sequence through the Rules. Fool’s Mate and Scholar’s Mate end in checkmate; the opening remains in progress; the illegal pawn leap is denied without changing the board.</p>
5
+ <h2 id="a-move-is-a-firestore-write">A move is a Firestore write</h2>
6
+ <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="text"><code><span class="line"><span>move → proposed Firestore document → Security Rules → commit or deny → next board</span></span></code></pre>
7
+ <p>Each game is one Firestore document. A move proposes its next state: one square is emptied, another receives the piece, the turn changes, and the move count increases.</p>
8
+ <p>Pyric evaluates that write against Firestore Security Rules in the browser. An allowed write changes the document and the board. A denied write changes neither.</p>
9
+ <h2 id="keep-the-rules-focused-on-chess">Keep the Rules focused on chess</h2>
10
+ <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="rules"><code><span class="line"><span style="color:#C678DD">rules_version</span><span style="color:#ABB2BF"> = </span><span style="color:#98C379">'2+modules'</span><span style="color:#ABB2BF">;</span></span>
11
+ <span class="line"></span>
12
+ <span class="line"><span style="color:#C678DD">import</span><span style="color:#ABB2BF"> { isAuthenticated } </span><span style="color:#C678DD">from</span><span style="color:#98C379"> 'auth'</span><span style="color:#ABB2BF">;</span></span>
13
+ <span class="line"><span style="color:#C678DD">import</span><span style="color:#ABB2BF"> { validSimpleMove } </span><span style="color:#C678DD">from</span><span style="color:#98C379"> 'geometry'</span><span style="color:#ABB2BF">;</span></span>
14
+ <span class="line"><span style="color:#C678DD">import</span><span style="color:#ABB2BF"> { isPlaying, moveIncremented, participantsUnchanged } </span><span style="color:#C678DD">from</span><span style="color:#98C379"> 'state'</span><span style="color:#ABB2BF">;</span></span>
15
+ <span class="line"><span style="color:#C678DD">import</span><span style="color:#ABB2BF"> { isMyTurn, turnFlipped } </span><span style="color:#C678DD">from</span><span style="color:#98C379"> 'turns'</span><span style="color:#ABB2BF">;</span></span></code></pre>
16
+ <p><code>2+modules</code> is Pyric’s modular Rules format. Pyric resolves its imports into ordinary version 2 Rules before evaluation or deployment.</p>
17
+ <p>The Standard Library modules handle checks that are useful beyond chess: authentication, participants, turns, move counts, and movement across a grid. The remaining Rules can concentrate on chess-specific behavior such as blocked paths, captures, castling, and king safety.</p>
18
+ <p>The board’s geometry lives in a read-only Firestore document. <code>validSimpleMove(cfg())</code> uses that data to check whether a piece can travel from one square to another. This turns movement into lookups that the Rules language can evaluate.</p>
19
+ <h2 id="stop-unrelated-rules-early">Stop unrelated Rules early</h2>
20
+ <pre class="astro-code one-dark-pro" style="background-color:#282c34;color:#abb2bf; overflow-x: auto;" tabindex="0" data-language="rules"><code><span class="line"><span style="color:#C678DD">allow</span><span style="color:#61AFEF"> update</span><span style="color:#ABB2BF">: </span><span style="color:#C678DD">if</span><span style="color:#E5C07B"> request</span><span style="color:#ABB2BF">.</span><span style="color:#E5C07B">resource</span><span style="color:#ABB2BF">.data.moveType == </span><span style="color:#98C379">'normal'</span></span>
21
+ <span class="line"><span style="color:#ABB2BF"> &#x26;&#x26; baseMoveChecks() &#x26;&#x26; validPieceMove() &#x26;&#x26; myKingSafe();</span></span>
22
+ <span class="line"></span>
23
+ <span class="line"><span style="color:#C678DD">allow</span><span style="color:#61AFEF"> update</span><span style="color:#ABB2BF">: </span><span style="color:#C678DD">if</span><span style="color:#E5C07B"> request</span><span style="color:#ABB2BF">.</span><span style="color:#E5C07B">resource</span><span style="color:#ABB2BF">.data.moveType == </span><span style="color:#98C379">'capture'</span></span>
24
+ <span class="line"><span style="color:#ABB2BF"> &#x26;&#x26; baseMoveChecks() &#x26;&#x26; validPieceMove() &#x26;&#x26; captureValid() &#x26;&#x26; myKingSafe();</span></span></code></pre>
25
+ <p>Firestore limits how much work a Rules evaluation may perform. Each move type starts with a different value, so only the matching branch continues into the expensive chess checks. Pyric’s linter checks these limits locally instead of waiting for a deployment to expose them.</p>
26
+ <h2 id="checkmate-is-a-result-not-a-trusted-claim">Checkmate is a result, not a trusted claim</h2>
27
+ <p>Security Rules decide whether a move may be stored. After an allowed move commits, the browser checks the resulting board. It reports checkmate only when the king is attacked and no legal move, capture, block, king escape, or en passant response removes the attack.</p>
28
+ <p>There is no client-authored <code>checkmate</code> move for the Rules to trust. The result is derived from the board that the Rules already accepted.</p>
29
+ <h2 id="test-the-same-boundaries-before-production">Test the same boundaries before production</h2>
30
+ <p>The local suite covers allowed and denied geometry, blocked paths, captures, pins, check, turn ownership, resignation, and checkmate. It runs against the same resolved Rules as the board.</p>
31
+ <p>Pyric is a development mirror, not Firebase production. Before shipping a game or any Rules-heavy application, run its important cases against a Firebase project too.</p> </article> <section class="example-rules" data-astro-cid-ghke3xma> <h2 data-astro-cid-ghke3xma>Security Rules</h2> <p data-astro-cid-ghke3xma>The board uses the modular Rules below. Pyric resolves the Standard Library imports into ordinary version 2 Rules before the sandbox evaluates each move.</p> <style>astro-island,astro-slot,astro-static-slot{display:contents}</style><script>(()=>{var a=(s,i,o)=>{let r=async()=>{await(await s())()},t=typeof i.value=="object"?i.value:void 0,c={rootMargin:t==null?void 0:t.rootMargin},n=new IntersectionObserver(e=>{for(let l of e)if(l.isIntersecting){n.disconnect(),r();break}},c);for(let e of o.children)n.observe(e)};(self.Astro||(self.Astro={})).visible=a;window.dispatchEvent(new Event("astro:visible"));})();</script><script>(()=>{var A=Object.defineProperty;var g=(i,o,a)=>o in i?A(i,o,{enumerable:!0,configurable:!0,writable:!0,value:a}):i[o]=a;var d=(i,o,a)=>g(i,typeof o!="symbol"?o+"":o,a);{let i={0:t=>m(t),1:t=>a(t),2:t=>new RegExp(t),3:t=>new Date(t),4:t=>new Map(a(t)),5:t=>new Set(a(t)),6:t=>BigInt(t),7:t=>new URL(t),8:t=>new Uint8Array(t),9:t=>new Uint16Array(t),10:t=>new Uint32Array(t),11:t=>1/0*t},o=t=>{let[l,e]=t;return l in i?i[l](e):void 0},a=t=>t.map(o),m=t=>typeof t!="object"||t===null?t:Object.fromEntries(Object.entries(t).map(([l,e])=>[l,o(e)]));class y extends HTMLElement{constructor(){super(...arguments);d(this,"Component");d(this,"hydrator");d(this,"hydrate",async()=>{var b;if(!this.hydrator||!this.isConnected)return;let e=(b=this.parentElement)==null?void 0:b.closest("astro-island[ssr]");if(e){e.addEventListener("astro:hydrate",this.hydrate,{once:!0});return}let c=this.querySelectorAll("astro-slot"),n={},h=this.querySelectorAll("template[data-astro-template]");for(let r of h){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("data-astro-template")||"default"]=r.innerHTML,r.remove())}for(let r of c){let s=r.closest(this.tagName);s!=null&&s.isSameNode(this)&&(n[r.getAttribute("name")||"default"]=r.innerHTML)}let p;try{p=this.hasAttribute("props")?m(JSON.parse(this.getAttribute("props"))):{}}catch(r){let s=this.getAttribute("component-url")||"<unknown>",v=this.getAttribute("component-export");throw v&&(s+=` (export ${v})`),console.error(`[hydrate] Error parsing props for component ${s}`,this.getAttribute("props"),r),r}let u;await this.hydrator(this)(this.Component,p,n,{client:this.getAttribute("client")}),this.removeAttribute("ssr"),this.dispatchEvent(new CustomEvent("astro:hydrate"))});d(this,"unmount",()=>{this.isConnected||this.dispatchEvent(new CustomEvent("astro:unmount"))})}disconnectedCallback(){document.removeEventListener("astro:after-swap",this.unmount),document.addEventListener("astro:after-swap",this.unmount,{once:!0})}connectedCallback(){if(!this.hasAttribute("await-children")||document.readyState==="interactive"||document.readyState==="complete")this.childrenConnectedCallback();else{let e=()=>{document.removeEventListener("DOMContentLoaded",e),c.disconnect(),this.childrenConnectedCallback()},c=new MutationObserver(()=>{var n;((n=this.lastChild)==null?void 0:n.nodeType)===Node.COMMENT_NODE&&this.lastChild.nodeValue==="astro:end"&&(this.lastChild.remove(),e())});c.observe(this,{childList:!0}),document.addEventListener("DOMContentLoaded",e)}}async childrenConnectedCallback(){let e=this.getAttribute("before-hydration-url");e&&await import(e),this.start()}async start(){let e=JSON.parse(this.getAttribute("opts")),c=this.getAttribute("client");if(Astro[c]===void 0){window.addEventListener(`astro:${c}`,()=>this.start(),{once:!0});return}try{await Astro[c](async()=>{let n=this.getAttribute("renderer-url"),[h,{default:p}]=await Promise.all([import(this.getAttribute("component-url")),n?import(n):()=>()=>{}]),u=this.getAttribute("component-export")||"default";if(!u.includes("."))this.Component=h[u];else{this.Component=h;for(let f of u.split("."))this.Component=this.Component[f]}return this.hydrator=p,this.hydrate},e,this)}catch(n){console.error(`[astro-island] Error hydrating ${this.getAttribute("component-url")}`,n)}}attributeChangedCallback(){this.hydrate()}}d(y,"observedAttributes",["props"]),customElements.get("astro-island")||customElements.define("astro-island",y)}})();</script><astro-island uid="1V3xbd" prefix="r1" component-url="/__pyric/ui/_astro/chess-source-explorer.C5k9c5yK.js" component-export="ChessSourceExplorer" renderer-url="/__pyric/ui/_astro/client.D2ORs4B-.js" props="{&quot;data-astro-cid-ghke3xma&quot;:[0,true]}" ssr client="visible" opts="{&quot;name&quot;:&quot;ChessSourceExplorer&quot;,&quot;value&quot;:true}" await-children><section class="source-explorer" aria-label="Chess Security Rules"><div class="source-toolbar"><strong>Security Rules</strong><button type="button" class="copy-source">Copy source</button></div><pre><code>rules_version = &#x27;2+modules&#x27;;
32
+
33
+ import { isAuthenticated } from &#x27;auth&#x27;;
34
+ import { validSimpleMove } from &#x27;geometry&#x27;;
35
+ import { isPlaying, moveIncremented, participantsUnchanged } from &#x27;state&#x27;;
36
+ import { isMyTurn, turnFlipped } from &#x27;turns&#x27;;
37
+
38
+ service cloud.firestore {
39
+ match /databases/{database}/documents {
40
+ match /gameConfig/{id} { allow read: if true; allow write: if false; }
41
+ match /chess-v2/{gameId} {
42
+
43
+ function cfg() { return get(/databases/$(database)/documents/gameConfig/chessv2).data; }
44
+
45
+ function isOwnPiece() {
46
+ let piece = resource.data[request.resource.data.moveFrom];
47
+ return (resource.data.currentTurn == &#x27;host&#x27;
48
+ &amp;&amp; (piece == &#x27;K&#x27; || piece == &#x27;Q&#x27; || piece == &#x27;R&#x27; || piece == &#x27;B&#x27; || piece == &#x27;N&#x27; || piece == &#x27;P&#x27;))
49
+ || (resource.data.currentTurn == &#x27;guest&#x27;
50
+ &amp;&amp; (piece == &#x27;k&#x27; || piece == &#x27;q&#x27; || piece == &#x27;r&#x27; || piece == &#x27;b&#x27; || piece == &#x27;n&#x27; || piece == &#x27;p&#x27;));
51
+ }
52
+ function baseMoveChecks() {
53
+ return isAuthenticated() &amp;&amp; isPlaying()
54
+ &amp;&amp; isMyTurn() &amp;&amp; turnFlipped() &amp;&amp; isOwnPiece()
55
+ &amp;&amp; moveIncremented() &amp;&amp; participantsUnchanged();
56
+ }
57
+
58
+ function validPieceMove() {
59
+ let mf = request.resource.data.moveFrom;
60
+ let mt = request.resource.data.moveTo;
61
+ let piece = resource.data[mf];
62
+ let p = cfg().paths[mf][mt];
63
+ return validSimpleMove(cfg())
64
+ &amp;&amp; (cfg().pieceCategory[piece] == &#x27;jump&#x27;
65
+ || ((p.len &lt; 1 || resource.data[p.c0] == &#x27;&#x27;)
66
+ &amp;&amp; (p.len &lt; 2 || resource.data[p.c1] == &#x27;&#x27;)
67
+ &amp;&amp; (p.len &lt; 3 || resource.data[p.c2] == &#x27;&#x27;)
68
+ &amp;&amp; (p.len &lt; 4 || resource.data[p.c3] == &#x27;&#x27;)
69
+ &amp;&amp; (p.len &lt; 5 || resource.data[p.c4] == &#x27;&#x27;)
70
+ &amp;&amp; (p.len &lt; 6 || resource.data[p.c5] == &#x27;&#x27;)));
71
+ }
72
+ function validPawnForward() {
73
+ let mf = request.resource.data.moveFrom;
74
+ let mt = request.resource.data.moveTo;
75
+ let piece = resource.data[mf];
76
+ return (piece == &#x27;P&#x27; || piece == &#x27;p&#x27;) &amp;&amp; mt in cfg().pawnForward[piece][mf] &amp;&amp; resource.data[mt] == &#x27;&#x27;;
77
+ }
78
+ function validPawnDouble() {
79
+ let mf = request.resource.data.moveFrom;
80
+ let mt = request.resource.data.moveTo;
81
+ let piece = resource.data[mf];
82
+ return (piece == &#x27;P&#x27; || piece == &#x27;p&#x27;)
83
+ &amp;&amp; mf in cfg().pawnDouble[piece]
84
+ &amp;&amp; cfg().pawnDouble[piece][mf].to == mt
85
+ &amp;&amp; resource.data[mt] == &#x27;&#x27;
86
+ &amp;&amp; resource.data[cfg().pawnDouble[piece][mf].between] == &#x27;&#x27;;
87
+ }
88
+ function validPawnCapture() {
89
+ let mf = request.resource.data.moveFrom;
90
+ let mt = request.resource.data.moveTo;
91
+ let piece = resource.data[mf];
92
+ let target = resource.data[mt];
93
+ return (piece == &#x27;P&#x27; || piece == &#x27;p&#x27;)
94
+ &amp;&amp; mt in cfg().pawnAttacks[piece][mf]
95
+ &amp;&amp; target != &#x27;&#x27;
96
+ &amp;&amp; ((piece == &#x27;P&#x27; &amp;&amp; (target == &#x27;k&#x27; || target == &#x27;q&#x27; || target == &#x27;r&#x27; || target == &#x27;b&#x27; || target == &#x27;n&#x27; || target == &#x27;p&#x27;))
97
+ || (piece == &#x27;p&#x27; &amp;&amp; (target == &#x27;K&#x27; || target == &#x27;Q&#x27; || target == &#x27;R&#x27; || target == &#x27;B&#x27; || target == &#x27;N&#x27; || target == &#x27;P&#x27;)));
98
+ }
99
+ function validPromotion() {
100
+ let mt = request.resource.data.moveTo;
101
+ let piece = resource.data[request.resource.data.moveFrom];
102
+ let pt = request.resource.data.promotedTo;
103
+ return request.resource.data.moveType == &#x27;promotion&#x27;
104
+ &amp;&amp; ((piece == &#x27;P&#x27; &amp;&amp; mt &gt;= &#x27;a8&#x27; &amp;&amp; mt &lt;= &#x27;h8&#x27; &amp;&amp; (pt == &#x27;Q&#x27; || pt == &#x27;R&#x27; || pt == &#x27;B&#x27; || pt == &#x27;N&#x27;))
105
+ || (piece == &#x27;p&#x27; &amp;&amp; mt &gt;= &#x27;a1&#x27; &amp;&amp; mt &lt;= &#x27;h1&#x27; &amp;&amp; (pt == &#x27;q&#x27; || pt == &#x27;r&#x27; || pt == &#x27;b&#x27; || pt == &#x27;n&#x27;)));
106
+ }
107
+ function pieceMovedCorrectly() {
108
+ let mf = request.resource.data.moveFrom;
109
+ let mt = request.resource.data.moveTo;
110
+ let piece = resource.data[mf];
111
+ return request.resource.data[mf] == &#x27;&#x27;
112
+ &amp;&amp; (request.resource.data.moveType != &#x27;promotion&#x27;
113
+ ? request.resource.data[mt] == piece
114
+ : request.resource.data[mt] == request.resource.data.promotedTo)
115
+ &amp;&amp; resource.data[request.resource.data.movedPiece] == mf
116
+ &amp;&amp; request.resource.data[request.resource.data.movedPiece] == mt;
117
+ }
118
+ function captureValid() {
119
+ let cp = request.resource.data.capturedPiece;
120
+ return cp != &#x27;&#x27;
121
+ &amp;&amp; resource.data[cp] == request.resource.data.moveTo
122
+ &amp;&amp; request.resource.data[cp] == &#x27;&#x27;;
123
+ }
124
+ function validEnPassant() {
125
+ let mf = request.resource.data.moveFrom;
126
+ let mt = request.resource.data.moveTo;
127
+ let piece = resource.data[mf];
128
+ return (piece == &#x27;P&#x27; || piece == &#x27;p&#x27;)
129
+ &amp;&amp; mt in cfg().pawnAttacks[piece][mf]
130
+ &amp;&amp; resource.data[mt] == &#x27;&#x27;
131
+ &amp;&amp; resource.data.lastDoublePawn == mt;
132
+ }
133
+ function validCastleKingside() {
134
+ let turn = resource.data.currentTurn;
135
+ let c = cfg().castling;
136
+ let castle = turn == &#x27;host&#x27; ? c.wk : c.bk;
137
+ let kingMoved = turn == &#x27;host&#x27; ? resource.data.hp_K_moved : resource.data.gp_k_moved;
138
+ let rookMoved = turn == &#x27;host&#x27; ? resource.data.hp_R2_moved : resource.data.gp_r2_moved;
139
+ return !kingMoved &amp;&amp; !rookMoved
140
+ &amp;&amp; request.resource.data.moveFrom == castle.kingFrom
141
+ &amp;&amp; request.resource.data.moveTo == castle.kingTo
142
+ &amp;&amp; resource.data[castle.between[0]] == &#x27;&#x27;
143
+ &amp;&amp; resource.data[castle.between[1]] == &#x27;&#x27;;
144
+ }
145
+ function validCastleQueenside() {
146
+ let turn = resource.data.currentTurn;
147
+ let c = cfg().castling;
148
+ let castle = turn == &#x27;host&#x27; ? c.wq : c.bq;
149
+ let kingMoved = turn == &#x27;host&#x27; ? resource.data.hp_K_moved : resource.data.gp_k_moved;
150
+ let rookMoved = turn == &#x27;host&#x27; ? resource.data.hp_R1_moved : resource.data.gp_r1_moved;
151
+ return !kingMoved &amp;&amp; !rookMoved
152
+ &amp;&amp; request.resource.data.moveFrom == castle.kingFrom
153
+ &amp;&amp; request.resource.data.moveTo == castle.kingTo
154
+ &amp;&amp; resource.data[castle.between[0]] == &#x27;&#x27;
155
+ &amp;&amp; resource.data[castle.between[1]] == &#x27;&#x27;
156
+ &amp;&amp; resource.data[castle.between[2]] == &#x27;&#x27;;
157
+ }
158
+
159
+ function hPC(cfg) {
160
+ let b = request.resource.data;
161
+ let ks = b.hp_K;
162
+ return (b.gp_p1 != &#x27;&#x27; &amp;&amp; b[b.gp_p1] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.gp_p1]][b.gp_p1])
163
+ || (b.gp_p2 != &#x27;&#x27; &amp;&amp; b[b.gp_p2] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.gp_p2]][b.gp_p2])
164
+ || (b.gp_p3 != &#x27;&#x27; &amp;&amp; b[b.gp_p3] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.gp_p3]][b.gp_p3])
165
+ || (b.gp_p4 != &#x27;&#x27; &amp;&amp; b[b.gp_p4] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.gp_p4]][b.gp_p4])
166
+ || (b.gp_p5 != &#x27;&#x27; &amp;&amp; b[b.gp_p5] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.gp_p5]][b.gp_p5])
167
+ || (b.gp_p6 != &#x27;&#x27; &amp;&amp; b[b.gp_p6] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.gp_p6]][b.gp_p6])
168
+ || (b.gp_p7 != &#x27;&#x27; &amp;&amp; b[b.gp_p7] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.gp_p7]][b.gp_p7])
169
+ || (b.gp_p8 != &#x27;&#x27; &amp;&amp; b[b.gp_p8] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.gp_p8]][b.gp_p8]);
170
+ }
171
+ function hMC(cfg) {
172
+ let b = request.resource.data;
173
+ let ks = b.hp_K;
174
+ return (b.gp_n1 != &#x27;&#x27; &amp;&amp; b[b.gp_n1] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.gp_n1]][b.gp_n1])
175
+ || (b.gp_n2 != &#x27;&#x27; &amp;&amp; b[b.gp_n2] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.gp_n2]][b.gp_n2])
176
+ || (b.gp_k != &#x27;&#x27; &amp;&amp; b[b.gp_k] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.gp_k]][b.gp_k]);
177
+ }
178
+ function hSC(cfg) {
179
+ let b = request.resource.data;
180
+ let ks = b.hp_K;
181
+ return (b.gp_q != &#x27;&#x27; &amp;&amp; b[b.gp_q] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.gp_q]][b.gp_q]
182
+ &amp;&amp; (cfg.paths[b.gp_q][ks].len &lt; 1 || b[cfg.paths[b.gp_q][ks].c0] == &#x27;&#x27;)
183
+ &amp;&amp; (cfg.paths[b.gp_q][ks].len &lt; 2 || b[cfg.paths[b.gp_q][ks].c1] == &#x27;&#x27;)
184
+ &amp;&amp; (cfg.paths[b.gp_q][ks].len &lt; 3 || b[cfg.paths[b.gp_q][ks].c2] == &#x27;&#x27;)
185
+ &amp;&amp; (cfg.paths[b.gp_q][ks].len &lt; 4 || b[cfg.paths[b.gp_q][ks].c3] == &#x27;&#x27;)
186
+ &amp;&amp; (cfg.paths[b.gp_q][ks].len &lt; 5 || b[cfg.paths[b.gp_q][ks].c4] == &#x27;&#x27;))
187
+ || (b.gp_r1 != &#x27;&#x27; &amp;&amp; b[b.gp_r1] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.gp_r1]][b.gp_r1]
188
+ &amp;&amp; (cfg.paths[b.gp_r1][ks].len &lt; 1 || b[cfg.paths[b.gp_r1][ks].c0] == &#x27;&#x27;)
189
+ &amp;&amp; (cfg.paths[b.gp_r1][ks].len &lt; 2 || b[cfg.paths[b.gp_r1][ks].c1] == &#x27;&#x27;)
190
+ &amp;&amp; (cfg.paths[b.gp_r1][ks].len &lt; 3 || b[cfg.paths[b.gp_r1][ks].c2] == &#x27;&#x27;)
191
+ &amp;&amp; (cfg.paths[b.gp_r1][ks].len &lt; 4 || b[cfg.paths[b.gp_r1][ks].c3] == &#x27;&#x27;)
192
+ &amp;&amp; (cfg.paths[b.gp_r1][ks].len &lt; 5 || b[cfg.paths[b.gp_r1][ks].c4] == &#x27;&#x27;))
193
+ || (b.gp_r2 != &#x27;&#x27; &amp;&amp; b[b.gp_r2] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.gp_r2]][b.gp_r2]
194
+ &amp;&amp; (cfg.paths[b.gp_r2][ks].len &lt; 1 || b[cfg.paths[b.gp_r2][ks].c0] == &#x27;&#x27;)
195
+ &amp;&amp; (cfg.paths[b.gp_r2][ks].len &lt; 2 || b[cfg.paths[b.gp_r2][ks].c1] == &#x27;&#x27;)
196
+ &amp;&amp; (cfg.paths[b.gp_r2][ks].len &lt; 3 || b[cfg.paths[b.gp_r2][ks].c2] == &#x27;&#x27;)
197
+ &amp;&amp; (cfg.paths[b.gp_r2][ks].len &lt; 4 || b[cfg.paths[b.gp_r2][ks].c3] == &#x27;&#x27;)
198
+ &amp;&amp; (cfg.paths[b.gp_r2][ks].len &lt; 5 || b[cfg.paths[b.gp_r2][ks].c4] == &#x27;&#x27;))
199
+ || (b.gp_b1 != &#x27;&#x27; &amp;&amp; b[b.gp_b1] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.gp_b1]][b.gp_b1]
200
+ &amp;&amp; (cfg.paths[b.gp_b1][ks].len &lt; 1 || b[cfg.paths[b.gp_b1][ks].c0] == &#x27;&#x27;)
201
+ &amp;&amp; (cfg.paths[b.gp_b1][ks].len &lt; 2 || b[cfg.paths[b.gp_b1][ks].c1] == &#x27;&#x27;)
202
+ &amp;&amp; (cfg.paths[b.gp_b1][ks].len &lt; 3 || b[cfg.paths[b.gp_b1][ks].c2] == &#x27;&#x27;)
203
+ &amp;&amp; (cfg.paths[b.gp_b1][ks].len &lt; 4 || b[cfg.paths[b.gp_b1][ks].c3] == &#x27;&#x27;)
204
+ &amp;&amp; (cfg.paths[b.gp_b1][ks].len &lt; 5 || b[cfg.paths[b.gp_b1][ks].c4] == &#x27;&#x27;))
205
+ || (b.gp_b2 != &#x27;&#x27; &amp;&amp; b[b.gp_b2] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.gp_b2]][b.gp_b2]
206
+ &amp;&amp; (cfg.paths[b.gp_b2][ks].len &lt; 1 || b[cfg.paths[b.gp_b2][ks].c0] == &#x27;&#x27;)
207
+ &amp;&amp; (cfg.paths[b.gp_b2][ks].len &lt; 2 || b[cfg.paths[b.gp_b2][ks].c1] == &#x27;&#x27;)
208
+ &amp;&amp; (cfg.paths[b.gp_b2][ks].len &lt; 3 || b[cfg.paths[b.gp_b2][ks].c2] == &#x27;&#x27;)
209
+ &amp;&amp; (cfg.paths[b.gp_b2][ks].len &lt; 4 || b[cfg.paths[b.gp_b2][ks].c3] == &#x27;&#x27;)
210
+ &amp;&amp; (cfg.paths[b.gp_b2][ks].len &lt; 5 || b[cfg.paths[b.gp_b2][ks].c4] == &#x27;&#x27;));
211
+ }
212
+ function gPC(cfg) {
213
+ let b = request.resource.data;
214
+ let ks = b.gp_k;
215
+ return (b.hp_P1 != &#x27;&#x27; &amp;&amp; b[b.hp_P1] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.hp_P1]][b.hp_P1])
216
+ || (b.hp_P2 != &#x27;&#x27; &amp;&amp; b[b.hp_P2] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.hp_P2]][b.hp_P2])
217
+ || (b.hp_P3 != &#x27;&#x27; &amp;&amp; b[b.hp_P3] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.hp_P3]][b.hp_P3])
218
+ || (b.hp_P4 != &#x27;&#x27; &amp;&amp; b[b.hp_P4] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.hp_P4]][b.hp_P4])
219
+ || (b.hp_P5 != &#x27;&#x27; &amp;&amp; b[b.hp_P5] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.hp_P5]][b.hp_P5])
220
+ || (b.hp_P6 != &#x27;&#x27; &amp;&amp; b[b.hp_P6] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.hp_P6]][b.hp_P6])
221
+ || (b.hp_P7 != &#x27;&#x27; &amp;&amp; b[b.hp_P7] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.hp_P7]][b.hp_P7])
222
+ || (b.hp_P8 != &#x27;&#x27; &amp;&amp; b[b.hp_P8] != &#x27;&#x27; &amp;&amp; ks in cfg.pawnAttacks[b[b.hp_P8]][b.hp_P8]);
223
+ }
224
+ function gMC(cfg) {
225
+ let b = request.resource.data;
226
+ let ks = b.gp_k;
227
+ return (b.hp_N1 != &#x27;&#x27; &amp;&amp; b[b.hp_N1] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.hp_N1]][b.hp_N1])
228
+ || (b.hp_N2 != &#x27;&#x27; &amp;&amp; b[b.hp_N2] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.hp_N2]][b.hp_N2])
229
+ || (b.hp_K != &#x27;&#x27; &amp;&amp; b[b.hp_K] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.hp_K]][b.hp_K]);
230
+ }
231
+ function gSC(cfg) {
232
+ let b = request.resource.data;
233
+ let ks = b.gp_k;
234
+ return (b.hp_Q != &#x27;&#x27; &amp;&amp; b[b.hp_Q] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.hp_Q]][b.hp_Q]
235
+ &amp;&amp; (cfg.paths[b.hp_Q][ks].len &lt; 1 || b[cfg.paths[b.hp_Q][ks].c0] == &#x27;&#x27;)
236
+ &amp;&amp; (cfg.paths[b.hp_Q][ks].len &lt; 2 || b[cfg.paths[b.hp_Q][ks].c1] == &#x27;&#x27;)
237
+ &amp;&amp; (cfg.paths[b.hp_Q][ks].len &lt; 3 || b[cfg.paths[b.hp_Q][ks].c2] == &#x27;&#x27;)
238
+ &amp;&amp; (cfg.paths[b.hp_Q][ks].len &lt; 4 || b[cfg.paths[b.hp_Q][ks].c3] == &#x27;&#x27;)
239
+ &amp;&amp; (cfg.paths[b.hp_Q][ks].len &lt; 5 || b[cfg.paths[b.hp_Q][ks].c4] == &#x27;&#x27;))
240
+ || (b.hp_R1 != &#x27;&#x27; &amp;&amp; b[b.hp_R1] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.hp_R1]][b.hp_R1]
241
+ &amp;&amp; (cfg.paths[b.hp_R1][ks].len &lt; 1 || b[cfg.paths[b.hp_R1][ks].c0] == &#x27;&#x27;)
242
+ &amp;&amp; (cfg.paths[b.hp_R1][ks].len &lt; 2 || b[cfg.paths[b.hp_R1][ks].c1] == &#x27;&#x27;)
243
+ &amp;&amp; (cfg.paths[b.hp_R1][ks].len &lt; 3 || b[cfg.paths[b.hp_R1][ks].c2] == &#x27;&#x27;)
244
+ &amp;&amp; (cfg.paths[b.hp_R1][ks].len &lt; 4 || b[cfg.paths[b.hp_R1][ks].c3] == &#x27;&#x27;)
245
+ &amp;&amp; (cfg.paths[b.hp_R1][ks].len &lt; 5 || b[cfg.paths[b.hp_R1][ks].c4] == &#x27;&#x27;))
246
+ || (b.hp_R2 != &#x27;&#x27; &amp;&amp; b[b.hp_R2] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.hp_R2]][b.hp_R2]
247
+ &amp;&amp; (cfg.paths[b.hp_R2][ks].len &lt; 1 || b[cfg.paths[b.hp_R2][ks].c0] == &#x27;&#x27;)
248
+ &amp;&amp; (cfg.paths[b.hp_R2][ks].len &lt; 2 || b[cfg.paths[b.hp_R2][ks].c1] == &#x27;&#x27;)
249
+ &amp;&amp; (cfg.paths[b.hp_R2][ks].len &lt; 3 || b[cfg.paths[b.hp_R2][ks].c2] == &#x27;&#x27;)
250
+ &amp;&amp; (cfg.paths[b.hp_R2][ks].len &lt; 4 || b[cfg.paths[b.hp_R2][ks].c3] == &#x27;&#x27;)
251
+ &amp;&amp; (cfg.paths[b.hp_R2][ks].len &lt; 5 || b[cfg.paths[b.hp_R2][ks].c4] == &#x27;&#x27;))
252
+ || (b.hp_B1 != &#x27;&#x27; &amp;&amp; b[b.hp_B1] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.hp_B1]][b.hp_B1]
253
+ &amp;&amp; (cfg.paths[b.hp_B1][ks].len &lt; 1 || b[cfg.paths[b.hp_B1][ks].c0] == &#x27;&#x27;)
254
+ &amp;&amp; (cfg.paths[b.hp_B1][ks].len &lt; 2 || b[cfg.paths[b.hp_B1][ks].c1] == &#x27;&#x27;)
255
+ &amp;&amp; (cfg.paths[b.hp_B1][ks].len &lt; 3 || b[cfg.paths[b.hp_B1][ks].c2] == &#x27;&#x27;)
256
+ &amp;&amp; (cfg.paths[b.hp_B1][ks].len &lt; 4 || b[cfg.paths[b.hp_B1][ks].c3] == &#x27;&#x27;)
257
+ &amp;&amp; (cfg.paths[b.hp_B1][ks].len &lt; 5 || b[cfg.paths[b.hp_B1][ks].c4] == &#x27;&#x27;))
258
+ || (b.hp_B2 != &#x27;&#x27; &amp;&amp; b[b.hp_B2] != &#x27;&#x27; &amp;&amp; ks in cfg.moves[b[b.hp_B2]][b.hp_B2]
259
+ &amp;&amp; (cfg.paths[b.hp_B2][ks].len &lt; 1 || b[cfg.paths[b.hp_B2][ks].c0] == &#x27;&#x27;)
260
+ &amp;&amp; (cfg.paths[b.hp_B2][ks].len &lt; 2 || b[cfg.paths[b.hp_B2][ks].c1] == &#x27;&#x27;)
261
+ &amp;&amp; (cfg.paths[b.hp_B2][ks].len &lt; 3 || b[cfg.paths[b.hp_B2][ks].c2] == &#x27;&#x27;)
262
+ &amp;&amp; (cfg.paths[b.hp_B2][ks].len &lt; 4 || b[cfg.paths[b.hp_B2][ks].c3] == &#x27;&#x27;)
263
+ &amp;&amp; (cfg.paths[b.hp_B2][ks].len &lt; 5 || b[cfg.paths[b.hp_B2][ks].c4] == &#x27;&#x27;));
264
+ }
265
+
266
+ function myKingSafe() {
267
+ let c = cfg();
268
+ return (resource.data.currentTurn == &#x27;host&#x27; &amp;&amp; !hPC(c) &amp;&amp; !hMC(c) &amp;&amp; !hSC(c))
269
+ || (resource.data.currentTurn == &#x27;guest&#x27; &amp;&amp; !gPC(c) &amp;&amp; !gMC(c) &amp;&amp; !gSC(c));
270
+ }
271
+ function opponentInCheck() {
272
+ let c = cfg();
273
+ return (resource.data.currentTurn == &#x27;host&#x27; &amp;&amp; (gPC(c) || gMC(c) || gSC(c)))
274
+ || (resource.data.currentTurn == &#x27;guest&#x27; &amp;&amp; (hPC(c) || hMC(c) || hSC(c)));
275
+ }
276
+
277
+ // ═══ Lobby ═══
278
+ allow read: if request.auth != null;
279
+ allow create: if request.auth != null
280
+ &amp;&amp; request.resource.data.host == request.auth.uid
281
+ &amp;&amp; request.resource.data.status == &#x27;waiting&#x27;
282
+ &amp;&amp; d.a1 == &#x27;R&#x27;
283
+ &amp;&amp; d.a2 == &#x27;P&#x27;
284
+ &amp;&amp; d.a7 == &#x27;p&#x27;
285
+ &amp;&amp; d.a8 == &#x27;r&#x27;
286
+ &amp;&amp; d.b1 == &#x27;N&#x27;
287
+ &amp;&amp; d.b2 == &#x27;P&#x27;
288
+ &amp;&amp; d.b7 == &#x27;p&#x27;
289
+ &amp;&amp; d.b8 == &#x27;n&#x27;
290
+ &amp;&amp; d.c1 == &#x27;B&#x27;
291
+ &amp;&amp; d.c2 == &#x27;P&#x27;
292
+ &amp;&amp; d.c7 == &#x27;p&#x27;
293
+ &amp;&amp; d.c8 == &#x27;b&#x27;
294
+ &amp;&amp; d.d1 == &#x27;Q&#x27;
295
+ &amp;&amp; d.d2 == &#x27;P&#x27;
296
+ &amp;&amp; d.d7 == &#x27;p&#x27;
297
+ &amp;&amp; d.d8 == &#x27;q&#x27;
298
+ &amp;&amp; d.e1 == &#x27;K&#x27;
299
+ &amp;&amp; d.e2 == &#x27;P&#x27;
300
+ &amp;&amp; d.e7 == &#x27;p&#x27;
301
+ &amp;&amp; d.e8 == &#x27;k&#x27;
302
+ &amp;&amp; d.f1 == &#x27;B&#x27;
303
+ &amp;&amp; d.f2 == &#x27;P&#x27;
304
+ &amp;&amp; d.f7 == &#x27;p&#x27;
305
+ &amp;&amp; d.f8 == &#x27;b&#x27;
306
+ &amp;&amp; d.g1 == &#x27;N&#x27;
307
+ &amp;&amp; d.g2 == &#x27;P&#x27;
308
+ &amp;&amp; d.g7 == &#x27;p&#x27;
309
+ &amp;&amp; d.g8 == &#x27;n&#x27;
310
+ &amp;&amp; d.h1 == &#x27;R&#x27;
311
+ &amp;&amp; d.h2 == &#x27;P&#x27;
312
+ &amp;&amp; d.h7 == &#x27;p&#x27;
313
+ &amp;&amp; d.h8 == &#x27;r&#x27;;
314
+ allow update: if request.auth != null
315
+ &amp;&amp; resource.data.status == &#x27;waiting&#x27;
316
+ &amp;&amp; resource.data.guest == &#x27;&#x27;
317
+ &amp;&amp; request.resource.data.guest == request.auth.uid
318
+ &amp;&amp; request.auth.uid != resource.data.host
319
+ &amp;&amp; request.resource.data.status == &#x27;playing&#x27;
320
+ &amp;&amp; request.resource.data.diff(resource.data).affectedKeys().hasOnly([&#x27;guest&#x27;, &#x27;status&#x27;]);
321
+ allow delete: if request.auth != null
322
+ &amp;&amp; resource.data.status == &#x27;waiting&#x27;
323
+ &amp;&amp; request.auth.uid == resource.data.host;
324
+
325
+ // ═══ UNIQUE moveType gates — each rule category has its own ═══
326
+ // Pawn forward
327
+ allow update: if request.resource.data.moveType == &#x27;pawn_forward&#x27;
328
+ &amp;&amp; request.resource.data.capturedPiece == &#x27;&#x27; &amp;&amp; request.resource.data.status == &#x27;playing&#x27;
329
+ &amp;&amp; baseMoveChecks() &amp;&amp; validPawnForward() &amp;&amp; request.resource.data.promotedTo == &#x27;&#x27;
330
+ &amp;&amp; pieceMovedCorrectly() &amp;&amp; myKingSafe();
331
+ // Pawn capture
332
+ allow update: if request.resource.data.moveType == &#x27;pawn_capture&#x27;
333
+ &amp;&amp; request.resource.data.capturedPiece != &#x27;&#x27; &amp;&amp; request.resource.data.status == &#x27;playing&#x27;
334
+ &amp;&amp; baseMoveChecks() &amp;&amp; validPawnCapture() &amp;&amp; request.resource.data.promotedTo == &#x27;&#x27;
335
+ &amp;&amp; captureValid() &amp;&amp; pieceMovedCorrectly() &amp;&amp; myKingSafe();
336
+ // Pawn double
337
+ allow update: if request.resource.data.moveType == &#x27;double_pawn&#x27;
338
+ &amp;&amp; request.resource.data.capturedPiece == &#x27;&#x27; &amp;&amp; request.resource.data.status == &#x27;playing&#x27;
339
+ &amp;&amp; baseMoveChecks() &amp;&amp; validPawnDouble() &amp;&amp; pieceMovedCorrectly() &amp;&amp; myKingSafe();
340
+ // Promotion (forward)
341
+ allow update: if request.resource.data.moveType == &#x27;promotion&#x27;
342
+ &amp;&amp; request.resource.data.capturedPiece == &#x27;&#x27; &amp;&amp; request.resource.data.status == &#x27;playing&#x27;
343
+ &amp;&amp; baseMoveChecks() &amp;&amp; validPawnForward() &amp;&amp; validPromotion() &amp;&amp; pieceMovedCorrectly() &amp;&amp; myKingSafe();
344
+ // Promotion (capture)
345
+ allow update: if request.resource.data.moveType == &#x27;promotion_capture&#x27;
346
+ &amp;&amp; request.resource.data.capturedPiece != &#x27;&#x27; &amp;&amp; request.resource.data.status == &#x27;playing&#x27;
347
+ &amp;&amp; baseMoveChecks() &amp;&amp; validPawnCapture() &amp;&amp; validPromotion() &amp;&amp; captureValid() &amp;&amp; pieceMovedCorrectly() &amp;&amp; myKingSafe();
348
+ // En passant
349
+ allow update: if request.resource.data.moveType == &#x27;en_passant&#x27;
350
+ &amp;&amp; request.resource.data.status == &#x27;playing&#x27;
351
+ &amp;&amp; baseMoveChecks() &amp;&amp; validEnPassant()
352
+ &amp;&amp; request.resource.data.capturedPiece != &#x27;&#x27; &amp;&amp; request.resource.data[request.resource.data.capturedPiece] == &#x27;&#x27;
353
+ &amp;&amp; pieceMovedCorrectly() &amp;&amp; myKingSafe();
354
+ // Standard piece move (non-pawn)
355
+ allow update: if request.resource.data.moveType == &#x27;normal&#x27;
356
+ &amp;&amp; request.resource.data.capturedPiece == &#x27;&#x27; &amp;&amp; request.resource.data.status == &#x27;playing&#x27;
357
+ &amp;&amp; baseMoveChecks() &amp;&amp; validPieceMove() &amp;&amp; resource.data[request.resource.data.moveTo] == &#x27;&#x27;
358
+ &amp;&amp; pieceMovedCorrectly() &amp;&amp; myKingSafe();
359
+ // Standard piece capture
360
+ allow update: if request.resource.data.moveType == &#x27;capture&#x27;
361
+ &amp;&amp; request.resource.data.capturedPiece != &#x27;&#x27; &amp;&amp; request.resource.data.status == &#x27;playing&#x27;
362
+ &amp;&amp; baseMoveChecks() &amp;&amp; validPieceMove() &amp;&amp; captureValid() &amp;&amp; pieceMovedCorrectly() &amp;&amp; myKingSafe();
363
+ // Castling kingside
364
+ allow update: if request.resource.data.moveType == &#x27;castle_k&#x27;
365
+ &amp;&amp; request.resource.data.status == &#x27;playing&#x27;
366
+ &amp;&amp; baseMoveChecks() &amp;&amp; validCastleKingside() &amp;&amp; myKingSafe();
367
+ // Castling queenside
368
+ allow update: if request.resource.data.moveType == &#x27;castle_q&#x27;
369
+ &amp;&amp; request.resource.data.status == &#x27;playing&#x27;
370
+ &amp;&amp; baseMoveChecks() &amp;&amp; validCastleQueenside() &amp;&amp; myKingSafe();
371
+ // Draw
372
+ allow update: if request.resource.data.moveType == &#x27;draw&#x27;
373
+ &amp;&amp; request.resource.data.status == &#x27;draw&#x27;
374
+ &amp;&amp; resource.data.status == &#x27;playing&#x27; &amp;&amp; isMyTurn();
375
+ // Resign
376
+ allow update: if request.resource.data.moveType == &#x27;resign&#x27;
377
+ &amp;&amp; request.resource.data.status == &#x27;resigned&#x27;
378
+ &amp;&amp; resource.data.status == &#x27;playing&#x27;
379
+ &amp;&amp; request.auth != null
380
+ &amp;&amp; (request.auth.uid == resource.data.host || request.auth.uid == resource.data.guest);
381
+ }
382
+ }
383
+ }
384
+ </code></pre></section><!--astro:end--></astro-island> </section> </div> </main> <aside class="doc-toc" aria-label="On this page" data-astro-cid-mw7aashj> <h2 class="doc-toc-heading" data-astro-cid-mw7aashj>On this page</h2> <ul data-astro-cid-mw7aashj> <li data-depth="2" data-astro-cid-mw7aashj> <a href="#try-the-board" data-astro-cid-mw7aashj>Try the board</a> </li><li data-depth="2" data-astro-cid-mw7aashj> <a href="#a-move-is-a-firestore-write" data-astro-cid-mw7aashj>A move is a Firestore write</a> </li><li data-depth="2" data-astro-cid-mw7aashj> <a href="#keep-the-rules-focused-on-chess" data-astro-cid-mw7aashj>Keep the Rules focused on chess</a> </li><li data-depth="2" data-astro-cid-mw7aashj> <a href="#stop-unrelated-rules-early" data-astro-cid-mw7aashj>Stop unrelated Rules early</a> </li><li data-depth="2" data-astro-cid-mw7aashj> <a href="#checkmate-is-a-result-not-a-trusted-claim" data-astro-cid-mw7aashj>Checkmate is a result, not a trusted claim</a> </li><li data-depth="2" data-astro-cid-mw7aashj> <a href="#test-the-same-boundaries-before-production" data-astro-cid-mw7aashj>Test the same boundaries before production</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>
@@ -0,0 +1,57 @@
1
+
2
+ ## Try the board
3
+
4
+ Choose a piece and its destination. `e2 → e4` is allowed; `e2 → e5` is denied and leaves the board unchanged. Switch the identity to see turn ownership enforced.
5
+
6
+ Choose a scenario to run a complete sequence through the Rules. Fool's Mate and Scholar's Mate end in checkmate; the opening remains in progress; the illegal pawn leap is denied without changing the board.
7
+
8
+ ## A move is a Firestore write
9
+
10
+ ```text
11
+ move → proposed Firestore document → Security Rules → commit or deny → next board
12
+ ```
13
+
14
+ Each game is one Firestore document. A move proposes its next state: one square is emptied, another receives the piece, the turn changes, and the move count increases.
15
+
16
+ Pyric evaluates that write against Firestore Security Rules in the browser. An allowed write changes the document and the board. A denied write changes neither.
17
+
18
+ ## Keep the Rules focused on chess
19
+
20
+ ```rules
21
+ rules_version = '2+modules';
22
+
23
+ import { isAuthenticated } from 'auth';
24
+ import { validSimpleMove } from 'geometry';
25
+ import { isPlaying, moveIncremented, participantsUnchanged } from 'state';
26
+ import { isMyTurn, turnFlipped } from 'turns';
27
+ ```
28
+
29
+ `2+modules` is Pyric's modular Rules format. Pyric resolves its imports into ordinary version 2 Rules before evaluation or deployment.
30
+
31
+ The Standard Library modules handle checks that are useful beyond chess: authentication, participants, turns, move counts, and movement across a grid. The remaining Rules can concentrate on chess-specific behavior such as blocked paths, captures, castling, and king safety.
32
+
33
+ The board's geometry lives in a read-only Firestore document. `validSimpleMove(cfg())` uses that data to check whether a piece can travel from one square to another. This turns movement into lookups that the Rules language can evaluate.
34
+
35
+ ## Stop unrelated Rules early
36
+
37
+ ```rules
38
+ allow update: if request.resource.data.moveType == 'normal'
39
+ && baseMoveChecks() && validPieceMove() && myKingSafe();
40
+
41
+ allow update: if request.resource.data.moveType == 'capture'
42
+ && baseMoveChecks() && validPieceMove() && captureValid() && myKingSafe();
43
+ ```
44
+
45
+ Firestore limits how much work a Rules evaluation may perform. Each move type starts with a different value, so only the matching branch continues into the expensive chess checks. Pyric's linter checks these limits locally instead of waiting for a deployment to expose them.
46
+
47
+ ## Checkmate is a result, not a trusted claim
48
+
49
+ Security Rules decide whether a move may be stored. After an allowed move commits, the browser checks the resulting board. It reports checkmate only when the king is attacked and no legal move, capture, block, king escape, or en passant response removes the attack.
50
+
51
+ There is no client-authored `checkmate` move for the Rules to trust. The result is derived from the board that the Rules already accepted.
52
+
53
+ ## Test the same boundaries before production
54
+
55
+ The local suite covers allowed and denied geometry, blocked paths, captures, pins, check, turn ownership, resignation, and checkmate. It runs against the same resolved Rules as the board.
56
+
57
+ Pyric is a development mirror, not Firebase production. Before shipping a game or any Rules-heavy application, run its important cases against a Firebase project too.