pyric 0.0.1 → 0.1.0-alpha.8

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 (787) hide show
  1. package/README.md +138 -2
  2. package/README.md.orig +54 -0
  3. package/dist/app/index.d.ts +81 -0
  4. package/dist/app/index.d.ts.map +1 -0
  5. package/dist/app/index.js +78 -0
  6. package/dist/app/index.js.map +1 -0
  7. package/dist/auth/index.d.ts +346 -0
  8. package/dist/auth/index.d.ts.map +1 -0
  9. package/dist/auth/index.js +701 -0
  10. package/dist/auth/index.js.map +1 -0
  11. package/dist/auth/prod-backend.d.ts +39 -0
  12. package/dist/auth/prod-backend.d.ts.map +1 -0
  13. package/dist/auth/prod-backend.js +179 -0
  14. package/dist/auth/prod-backend.js.map +1 -0
  15. package/dist/auth/providers.d.ts +107 -0
  16. package/dist/auth/providers.d.ts.map +1 -0
  17. package/dist/auth/providers.js +138 -0
  18. package/dist/auth/providers.js.map +1 -0
  19. package/dist/auth/sandbox-backend.d.ts +769 -0
  20. package/dist/auth/sandbox-backend.d.ts.map +1 -0
  21. package/dist/auth/sandbox-backend.js +1598 -0
  22. package/dist/auth/sandbox-backend.js.map +1 -0
  23. package/dist/auth/target.d.ts +40 -0
  24. package/dist/auth/target.d.ts.map +1 -0
  25. package/dist/auth/target.js +28 -0
  26. package/dist/auth/target.js.map +1 -0
  27. package/dist/auth/types.d.ts +252 -0
  28. package/dist/auth/types.d.ts.map +1 -0
  29. package/dist/auth/types.js +26 -0
  30. package/dist/auth/types.js.map +1 -0
  31. package/dist/database/constraints/atoms.d.ts +29 -0
  32. package/dist/database/constraints/atoms.d.ts.map +1 -0
  33. package/dist/database/constraints/atoms.js +43 -0
  34. package/dist/database/constraints/atoms.js.map +1 -0
  35. package/dist/database/constraints/compose.d.ts +16 -0
  36. package/dist/database/constraints/compose.d.ts.map +1 -0
  37. package/dist/database/constraints/compose.js +15 -0
  38. package/dist/database/constraints/compose.js.map +1 -0
  39. package/dist/database/constraints/data.d.ts +30 -0
  40. package/dist/database/constraints/data.d.ts.map +1 -0
  41. package/dist/database/constraints/data.js +46 -0
  42. package/dist/database/constraints/data.js.map +1 -0
  43. package/dist/database/constraints/document.d.ts +42 -0
  44. package/dist/database/constraints/document.d.ts.map +1 -0
  45. package/dist/database/constraints/document.js +86 -0
  46. package/dist/database/constraints/document.js.map +1 -0
  47. package/dist/database/constraints/game.d.ts +30 -0
  48. package/dist/database/constraints/game.d.ts.map +1 -0
  49. package/dist/database/constraints/game.js +49 -0
  50. package/dist/database/constraints/game.js.map +1 -0
  51. package/dist/database/constraints/index.d.ts +12 -0
  52. package/dist/database/constraints/index.d.ts.map +1 -0
  53. package/dist/database/constraints/index.js +9 -0
  54. package/dist/database/constraints/index.js.map +1 -0
  55. package/dist/database/constraints/policies.d.ts +16 -0
  56. package/dist/database/constraints/policies.d.ts.map +1 -0
  57. package/dist/database/constraints/policies.js +17 -0
  58. package/dist/database/constraints/policies.js.map +1 -0
  59. package/dist/database/constraints/ruleset.d.ts +5 -0
  60. package/dist/database/constraints/ruleset.d.ts.map +1 -0
  61. package/dist/database/constraints/ruleset.js +132 -0
  62. package/dist/database/constraints/ruleset.js.map +1 -0
  63. package/dist/database/constraints/schema.d.ts +17 -0
  64. package/dist/database/constraints/schema.d.ts.map +1 -0
  65. package/dist/database/constraints/schema.js +74 -0
  66. package/dist/database/constraints/schema.js.map +1 -0
  67. package/dist/database/constraints/types.d.ts +22 -0
  68. package/dist/database/constraints/types.d.ts.map +1 -0
  69. package/dist/database/constraints/types.js +2 -0
  70. package/dist/database/constraints/types.js.map +1 -0
  71. package/dist/database/crawl/handler.d.ts +7 -0
  72. package/dist/database/crawl/handler.d.ts.map +1 -0
  73. package/dist/database/crawl/handler.js +91 -0
  74. package/dist/database/crawl/handler.js.map +1 -0
  75. package/dist/database/crawl/semaphore.d.ts +9 -0
  76. package/dist/database/crawl/semaphore.d.ts.map +1 -0
  77. package/dist/database/crawl/semaphore.js +27 -0
  78. package/dist/database/crawl/semaphore.js.map +1 -0
  79. package/dist/database/crawl/spec.d.ts +33 -0
  80. package/dist/database/crawl/spec.d.ts.map +1 -0
  81. package/dist/database/crawl/spec.js +12 -0
  82. package/dist/database/crawl/spec.js.map +1 -0
  83. package/dist/database/data/handler.d.ts +9 -0
  84. package/dist/database/data/handler.d.ts.map +1 -0
  85. package/dist/database/data/handler.js +96 -0
  86. package/dist/database/data/handler.js.map +1 -0
  87. package/dist/database/data/spec.d.ts +77 -0
  88. package/dist/database/data/spec.d.ts.map +1 -0
  89. package/dist/database/data/spec.js +17 -0
  90. package/dist/database/data/spec.js.map +1 -0
  91. package/dist/database/data/validated.d.ts +8 -0
  92. package/dist/database/data/validated.d.ts.map +1 -0
  93. package/dist/database/data/validated.js +99 -0
  94. package/dist/database/data/validated.js.map +1 -0
  95. package/dist/database/grammar/RtdbExpr.ohm +98 -0
  96. package/dist/database/grammar/RtdbExpr.ohm.generated.d.ts +2 -0
  97. package/dist/database/grammar/RtdbExpr.ohm.generated.d.ts.map +1 -0
  98. package/dist/database/grammar/RtdbExpr.ohm.generated.js +103 -0
  99. package/dist/database/grammar/RtdbExpr.ohm.generated.js.map +1 -0
  100. package/dist/database/grammar/RtdbExprParser.d.ts +5 -0
  101. package/dist/database/grammar/RtdbExprParser.d.ts.map +1 -0
  102. package/dist/database/grammar/RtdbExprParser.js +53 -0
  103. package/dist/database/grammar/RtdbExprParser.js.map +1 -0
  104. package/dist/database/grammar/linter.d.ts +3 -0
  105. package/dist/database/grammar/linter.d.ts.map +1 -0
  106. package/dist/database/grammar/linter.js +66 -0
  107. package/dist/database/grammar/linter.js.map +1 -0
  108. package/dist/database/grammar/simulator.d.ts +31 -0
  109. package/dist/database/grammar/simulator.d.ts.map +1 -0
  110. package/dist/database/grammar/simulator.js +255 -0
  111. package/dist/database/grammar/simulator.js.map +1 -0
  112. package/dist/database/grammar/validator.d.ts +3 -0
  113. package/dist/database/grammar/validator.d.ts.map +1 -0
  114. package/dist/database/grammar/validator.js +84 -0
  115. package/dist/database/grammar/validator.js.map +1 -0
  116. package/dist/database/host.d.ts +50 -0
  117. package/dist/database/host.d.ts.map +1 -0
  118. package/dist/database/host.js +41 -0
  119. package/dist/database/host.js.map +1 -0
  120. package/dist/database/index.d.ts +40 -0
  121. package/dist/database/index.d.ts.map +1 -0
  122. package/dist/database/index.js +47 -0
  123. package/dist/database/index.js.map +1 -0
  124. package/dist/database/initialize-from-app.d.ts +28 -0
  125. package/dist/database/initialize-from-app.d.ts.map +1 -0
  126. package/dist/database/initialize-from-app.js +23 -0
  127. package/dist/database/initialize-from-app.js.map +1 -0
  128. package/dist/database/ir/handler.d.ts +6 -0
  129. package/dist/database/ir/handler.d.ts.map +1 -0
  130. package/dist/database/ir/handler.js +52 -0
  131. package/dist/database/ir/handler.js.map +1 -0
  132. package/dist/database/ir/spec.d.ts +25 -0
  133. package/dist/database/ir/spec.d.ts.map +1 -0
  134. package/dist/database/ir/spec.js +11 -0
  135. package/dist/database/ir/spec.js.map +1 -0
  136. package/dist/database/mapper.d.ts +9 -0
  137. package/dist/database/mapper.d.ts.map +1 -0
  138. package/dist/database/mapper.js +115 -0
  139. package/dist/database/mapper.js.map +1 -0
  140. package/dist/database/modular.d.ts +604 -0
  141. package/dist/database/modular.d.ts.map +1 -0
  142. package/dist/database/modular.js +1226 -0
  143. package/dist/database/modular.js.map +1 -0
  144. package/dist/database/replay.d.ts +33 -0
  145. package/dist/database/replay.d.ts.map +1 -0
  146. package/dist/database/replay.js +124 -0
  147. package/dist/database/replay.js.map +1 -0
  148. package/dist/database/resolver.d.ts +4 -0
  149. package/dist/database/resolver.d.ts.map +1 -0
  150. package/dist/database/resolver.js +66 -0
  151. package/dist/database/resolver.js.map +1 -0
  152. package/dist/database/sandbox/backend.d.ts +403 -0
  153. package/dist/database/sandbox/backend.d.ts.map +1 -0
  154. package/dist/database/sandbox/backend.js +1467 -0
  155. package/dist/database/sandbox/backend.js.map +1 -0
  156. package/dist/database/sandbox/data-tree.d.ts +123 -0
  157. package/dist/database/sandbox/data-tree.d.ts.map +1 -0
  158. package/dist/database/sandbox/data-tree.js +310 -0
  159. package/dist/database/sandbox/data-tree.js.map +1 -0
  160. package/dist/database/sandbox/normalize.d.ts +77 -0
  161. package/dist/database/sandbox/normalize.d.ts.map +1 -0
  162. package/dist/database/sandbox/normalize.js +165 -0
  163. package/dist/database/sandbox/normalize.js.map +1 -0
  164. package/dist/database/sandbox/push-id.d.ts +32 -0
  165. package/dist/database/sandbox/push-id.d.ts.map +1 -0
  166. package/dist/database/sandbox/push-id.js +82 -0
  167. package/dist/database/sandbox/push-id.js.map +1 -0
  168. package/dist/database/sandbox/query.d.ts +175 -0
  169. package/dist/database/sandbox/query.d.ts.map +1 -0
  170. package/dist/database/sandbox/query.js +269 -0
  171. package/dist/database/sandbox/query.js.map +1 -0
  172. package/dist/database/sandbox/rules-eval.d.ts +69 -0
  173. package/dist/database/sandbox/rules-eval.d.ts.map +1 -0
  174. package/dist/database/sandbox/rules-eval.js +124 -0
  175. package/dist/database/sandbox/rules-eval.js.map +1 -0
  176. package/dist/database/sandbox/sentinels.d.ts +71 -0
  177. package/dist/database/sandbox/sentinels.d.ts.map +1 -0
  178. package/dist/database/sandbox/sentinels.js +92 -0
  179. package/dist/database/sandbox/sentinels.js.map +1 -0
  180. package/dist/database/simulation/handler.d.ts +6 -0
  181. package/dist/database/simulation/handler.d.ts.map +1 -0
  182. package/dist/database/simulation/handler.js +236 -0
  183. package/dist/database/simulation/handler.js.map +1 -0
  184. package/dist/database/simulation/spec.d.ts +69 -0
  185. package/dist/database/simulation/spec.d.ts.map +1 -0
  186. package/dist/database/simulation/spec.js +25 -0
  187. package/dist/database/simulation/spec.js.map +1 -0
  188. package/dist/database/tools.d.ts +22 -0
  189. package/dist/database/tools.d.ts.map +1 -0
  190. package/dist/database/tools.js +272 -0
  191. package/dist/database/tools.js.map +1 -0
  192. package/dist/database/types.d.ts +210 -0
  193. package/dist/database/types.d.ts.map +1 -0
  194. package/dist/database/types.js +26 -0
  195. package/dist/database/types.js.map +1 -0
  196. package/dist/database/write/handler.d.ts +7 -0
  197. package/dist/database/write/handler.d.ts.map +1 -0
  198. package/dist/database/write/handler.js +42 -0
  199. package/dist/database/write/handler.js.map +1 -0
  200. package/dist/database/write/spec.d.ts +18 -0
  201. package/dist/database/write/spec.d.ts.map +1 -0
  202. package/dist/database/write/spec.js +7 -0
  203. package/dist/database/write/spec.js.map +1 -0
  204. package/dist/firestore/index.d.ts +533 -0
  205. package/dist/firestore/index.d.ts.map +1 -0
  206. package/dist/firestore/index.js +1536 -0
  207. package/dist/firestore/index.js.map +1 -0
  208. package/dist/firestore/tools.d.ts +67 -0
  209. package/dist/firestore/tools.d.ts.map +1 -0
  210. package/dist/firestore/tools.js +318 -0
  211. package/dist/firestore/tools.js.map +1 -0
  212. package/dist/firestore-values/index.d.ts +63 -0
  213. package/dist/firestore-values/index.d.ts.map +1 -0
  214. package/dist/firestore-values/index.js +148 -0
  215. package/dist/firestore-values/index.js.map +1 -0
  216. package/dist/project-scope.d.ts +5 -0
  217. package/dist/project-scope.d.ts.map +1 -0
  218. package/dist/project-scope.js +2 -0
  219. package/dist/project-scope.js.map +1 -0
  220. package/dist/rules/extract.d.ts +28 -0
  221. package/dist/rules/extract.d.ts.map +1 -0
  222. package/dist/rules/extract.js +25 -0
  223. package/dist/rules/extract.js.map +1 -0
  224. package/dist/rules/generators/assembler.d.ts +19 -0
  225. package/dist/rules/generators/assembler.d.ts.map +1 -0
  226. package/dist/rules/generators/assembler.js +292 -0
  227. package/dist/rules/generators/assembler.js.map +1 -0
  228. package/dist/rules/generators/expressions.d.ts +52 -0
  229. package/dist/rules/generators/expressions.d.ts.map +1 -0
  230. package/dist/rules/generators/expressions.js +117 -0
  231. package/dist/rules/generators/expressions.js.map +1 -0
  232. package/dist/rules/generators/grid.d.ts +22 -0
  233. package/dist/rules/generators/grid.d.ts.map +1 -0
  234. package/dist/rules/generators/grid.js +52 -0
  235. package/dist/rules/generators/grid.js.map +1 -0
  236. package/dist/rules/grammar/FirestoreAST.d.ts +129 -0
  237. package/dist/rules/grammar/FirestoreAST.d.ts.map +1 -0
  238. package/dist/rules/grammar/FirestoreAST.js +3 -0
  239. package/dist/rules/grammar/FirestoreAST.js.map +1 -0
  240. package/dist/rules/grammar/FirestoreAssembler.d.ts +5 -0
  241. package/dist/rules/grammar/FirestoreAssembler.d.ts.map +1 -0
  242. package/dist/rules/grammar/FirestoreAssembler.js +158 -0
  243. package/dist/rules/grammar/FirestoreAssembler.js.map +1 -0
  244. package/dist/rules/grammar/FirestoreParser.d.ts +46 -0
  245. package/dist/rules/grammar/FirestoreParser.d.ts.map +1 -0
  246. package/dist/rules/grammar/FirestoreParser.js +409 -0
  247. package/dist/rules/grammar/FirestoreParser.js.map +1 -0
  248. package/dist/rules/grammar/FirestoreRules.ohm +229 -0
  249. package/dist/rules/grammar/FirestoreRules.ohm.generated.d.ts +2 -0
  250. package/dist/rules/grammar/FirestoreRules.ohm.generated.d.ts.map +1 -0
  251. package/dist/rules/grammar/FirestoreRules.ohm.generated.js +234 -0
  252. package/dist/rules/grammar/FirestoreRules.ohm.generated.js.map +1 -0
  253. package/dist/rules/grammar/FirestoreValidator.d.ts +10 -0
  254. package/dist/rules/grammar/FirestoreValidator.d.ts.map +1 -0
  255. package/dist/rules/grammar/FirestoreValidator.js +482 -0
  256. package/dist/rules/grammar/FirestoreValidator.js.map +1 -0
  257. package/dist/rules/index.d.ts +67 -0
  258. package/dist/rules/index.d.ts.map +1 -0
  259. package/dist/rules/index.js +80 -0
  260. package/dist/rules/index.js.map +1 -0
  261. package/dist/rules/indexes/extract/annotation-collect.d.ts +42 -0
  262. package/dist/rules/indexes/extract/annotation-collect.d.ts.map +1 -0
  263. package/dist/rules/indexes/extract/annotation-collect.js +69 -0
  264. package/dist/rules/indexes/extract/annotation-collect.js.map +1 -0
  265. package/dist/rules/indexes/extract/annotations.d.ts +50 -0
  266. package/dist/rules/indexes/extract/annotations.d.ts.map +1 -0
  267. package/dist/rules/indexes/extract/annotations.js +144 -0
  268. package/dist/rules/indexes/extract/annotations.js.map +1 -0
  269. package/dist/rules/indexes/extract/ast.d.ts +54 -0
  270. package/dist/rules/indexes/extract/ast.d.ts.map +1 -0
  271. package/dist/rules/indexes/extract/ast.js +119 -0
  272. package/dist/rules/indexes/extract/ast.js.map +1 -0
  273. package/dist/rules/indexes/extract/classify.d.ts +41 -0
  274. package/dist/rules/indexes/extract/classify.d.ts.map +1 -0
  275. package/dist/rules/indexes/extract/classify.js +138 -0
  276. package/dist/rules/indexes/extract/classify.js.map +1 -0
  277. package/dist/rules/indexes/extract/composite.d.ts +38 -0
  278. package/dist/rules/indexes/extract/composite.d.ts.map +1 -0
  279. package/dist/rules/indexes/extract/composite.js +85 -0
  280. package/dist/rules/indexes/extract/composite.js.map +1 -0
  281. package/dist/rules/indexes/extract/dataflow.d.ts +45 -0
  282. package/dist/rules/indexes/extract/dataflow.d.ts.map +1 -0
  283. package/dist/rules/indexes/extract/dataflow.js +200 -0
  284. package/dist/rules/indexes/extract/dataflow.js.map +1 -0
  285. package/dist/rules/indexes/extract/enumerate.d.ts +41 -0
  286. package/dist/rules/indexes/extract/enumerate.d.ts.map +1 -0
  287. package/dist/rules/indexes/extract/enumerate.js +163 -0
  288. package/dist/rules/indexes/extract/enumerate.js.map +1 -0
  289. package/dist/rules/indexes/extract/extractor.d.ts +3 -0
  290. package/dist/rules/indexes/extract/extractor.d.ts.map +1 -0
  291. package/dist/rules/indexes/extract/extractor.js +274 -0
  292. package/dist/rules/indexes/extract/extractor.js.map +1 -0
  293. package/dist/rules/indexes/extract/types.d.ts +211 -0
  294. package/dist/rules/indexes/extract/types.d.ts.map +1 -0
  295. package/dist/rules/indexes/extract/types.js +14 -0
  296. package/dist/rules/indexes/extract/types.js.map +1 -0
  297. package/dist/rules/indexes/extractHandler.d.ts +16 -0
  298. package/dist/rules/indexes/extractHandler.d.ts.map +1 -0
  299. package/dist/rules/indexes/extractHandler.js +100 -0
  300. package/dist/rules/indexes/extractHandler.js.map +1 -0
  301. package/dist/rules/indexes/extractTool.d.ts +15 -0
  302. package/dist/rules/indexes/extractTool.d.ts.map +1 -0
  303. package/dist/rules/indexes/extractTool.js +55 -0
  304. package/dist/rules/indexes/extractTool.js.map +1 -0
  305. package/dist/rules/indexes/types.d.ts +71 -0
  306. package/dist/rules/indexes/types.d.ts.map +1 -0
  307. package/dist/rules/indexes/types.js +15 -0
  308. package/dist/rules/indexes/types.js.map +1 -0
  309. package/dist/rules/inspect/handler.d.ts +6 -0
  310. package/dist/rules/inspect/handler.d.ts.map +1 -0
  311. package/dist/rules/inspect/handler.js +144 -0
  312. package/dist/rules/inspect/handler.js.map +1 -0
  313. package/dist/rules/inspect/spec.d.ts +37 -0
  314. package/dist/rules/inspect/spec.d.ts.map +1 -0
  315. package/dist/rules/inspect/spec.js +2 -0
  316. package/dist/rules/inspect/spec.js.map +1 -0
  317. package/dist/rules/inspect/tools.d.ts +21 -0
  318. package/dist/rules/inspect/tools.d.ts.map +1 -0
  319. package/dist/rules/inspect/tools.js +21 -0
  320. package/dist/rules/inspect/tools.js.map +1 -0
  321. package/dist/rules/linter/ast-utils.d.ts +97 -0
  322. package/dist/rules/linter/ast-utils.d.ts.map +1 -0
  323. package/dist/rules/linter/ast-utils.js +491 -0
  324. package/dist/rules/linter/ast-utils.js.map +1 -0
  325. package/dist/rules/linter/hallucinations.d.ts +34 -0
  326. package/dist/rules/linter/hallucinations.d.ts.map +1 -0
  327. package/dist/rules/linter/hallucinations.js +334 -0
  328. package/dist/rules/linter/hallucinations.js.map +1 -0
  329. package/dist/rules/linter/linter.d.ts +84 -0
  330. package/dist/rules/linter/linter.d.ts.map +1 -0
  331. package/dist/rules/linter/linter.js +784 -0
  332. package/dist/rules/linter/linter.js.map +1 -0
  333. package/dist/rules/modules/resolver-browser.d.ts +41 -0
  334. package/dist/rules/modules/resolver-browser.d.ts.map +1 -0
  335. package/dist/rules/modules/resolver-browser.js +63 -0
  336. package/dist/rules/modules/resolver-browser.js.map +1 -0
  337. package/dist/rules/modules/resolver-core.d.ts +51 -0
  338. package/dist/rules/modules/resolver-core.d.ts.map +1 -0
  339. package/dist/rules/modules/resolver-core.js +338 -0
  340. package/dist/rules/modules/resolver-core.js.map +1 -0
  341. package/dist/rules/modules/resolver.d.ts +17 -0
  342. package/dist/rules/modules/resolver.d.ts.map +1 -0
  343. package/dist/rules/modules/resolver.js +49 -0
  344. package/dist/rules/modules/resolver.js.map +1 -0
  345. package/dist/rules/modules/stdlib/atomic.rules +52 -0
  346. package/dist/rules/modules/stdlib/atomic.test.json +152 -0
  347. package/dist/rules/modules/stdlib/auth.rules +7 -0
  348. package/dist/rules/modules/stdlib/auth.test.json +53 -0
  349. package/dist/rules/modules/stdlib/content.rules +50 -0
  350. package/dist/rules/modules/stdlib/content.test.json +238 -0
  351. package/dist/rules/modules/stdlib/counters.rules +41 -0
  352. package/dist/rules/modules/stdlib/counters.test.json +254 -0
  353. package/dist/rules/modules/stdlib/geometry.rules +43 -0
  354. package/dist/rules/modules/stdlib/geometry.test.json +200 -0
  355. package/dist/rules/modules/stdlib/joining.rules +49 -0
  356. package/dist/rules/modules/stdlib/joining.test.json +287 -0
  357. package/dist/rules/modules/stdlib/lifecycle.rules +51 -0
  358. package/dist/rules/modules/stdlib/lifecycle.test.json +288 -0
  359. package/dist/rules/modules/stdlib/lobby.rules +44 -0
  360. package/dist/rules/modules/stdlib/lobby.test.json +32 -0
  361. package/dist/rules/modules/stdlib/membership.rules +40 -0
  362. package/dist/rules/modules/stdlib/membership.test.json +107 -0
  363. package/dist/rules/modules/stdlib/spaces.rules +46 -0
  364. package/dist/rules/modules/stdlib/spaces.test.json +392 -0
  365. package/dist/rules/modules/stdlib/state.rules +28 -0
  366. package/dist/rules/modules/stdlib/state.test.json +55 -0
  367. package/dist/rules/modules/stdlib/timing.rules +20 -0
  368. package/dist/rules/modules/stdlib/timing.test.json +106 -0
  369. package/dist/rules/modules/stdlib/transitions.rules +34 -0
  370. package/dist/rules/modules/stdlib/transitions.test.json +86 -0
  371. package/dist/rules/modules/stdlib/turns.rules +27 -0
  372. package/dist/rules/modules/stdlib/turns.test.json +64 -0
  373. package/dist/rules/modules/stdlib/validation.rules +31 -0
  374. package/dist/rules/modules/stdlib/validation.test.json +184 -0
  375. package/dist/rules/modules/stdlib-content.d.ts +11 -0
  376. package/dist/rules/modules/stdlib-content.d.ts.map +1 -0
  377. package/dist/rules/modules/stdlib-content.js +590 -0
  378. package/dist/rules/modules/stdlib-content.js.map +1 -0
  379. package/dist/rules/node.d.ts +17 -0
  380. package/dist/rules/node.d.ts.map +1 -0
  381. package/dist/rules/node.js +21 -0
  382. package/dist/rules/node.js.map +1 -0
  383. package/dist/rules/rtdb.d.ts +28 -0
  384. package/dist/rules/rtdb.d.ts.map +1 -0
  385. package/dist/rules/rtdb.js +15 -0
  386. package/dist/rules/rtdb.js.map +1 -0
  387. package/dist/rules/simulator/evaluator.d.ts +179 -0
  388. package/dist/rules/simulator/evaluator.d.ts.map +1 -0
  389. package/dist/rules/simulator/evaluator.js +1221 -0
  390. package/dist/rules/simulator/evaluator.js.map +1 -0
  391. package/dist/rules/simulator/expression/eval-errors.d.ts +86 -0
  392. package/dist/rules/simulator/expression/eval-errors.d.ts.map +1 -0
  393. package/dist/rules/simulator/expression/eval-errors.js +68 -0
  394. package/dist/rules/simulator/expression/eval-errors.js.map +1 -0
  395. package/dist/rules/simulator/expression/evaluator.d.ts +43 -0
  396. package/dist/rules/simulator/expression/evaluator.d.ts.map +1 -0
  397. package/dist/rules/simulator/expression/evaluator.js +298 -0
  398. package/dist/rules/simulator/expression/evaluator.js.map +1 -0
  399. package/dist/rules/simulator/expression/lexer.d.ts +36 -0
  400. package/dist/rules/simulator/expression/lexer.d.ts.map +1 -0
  401. package/dist/rules/simulator/expression/lexer.js +318 -0
  402. package/dist/rules/simulator/expression/lexer.js.map +1 -0
  403. package/dist/rules/simulator/expression/parser.d.ts +39 -0
  404. package/dist/rules/simulator/expression/parser.d.ts.map +1 -0
  405. package/dist/rules/simulator/expression/parser.js +329 -0
  406. package/dist/rules/simulator/expression/parser.js.map +1 -0
  407. package/dist/rules/simulator/expression/types.d.ts +137 -0
  408. package/dist/rules/simulator/expression/types.d.ts.map +1 -0
  409. package/dist/rules/simulator/expression/types.js +90 -0
  410. package/dist/rules/simulator/expression/types.js.map +1 -0
  411. package/dist/rules/simulator/expression/walk-data.d.ts +52 -0
  412. package/dist/rules/simulator/expression/walk-data.d.ts.map +1 -0
  413. package/dist/rules/simulator/expression/walk-data.js +167 -0
  414. package/dist/rules/simulator/expression/walk-data.js.map +1 -0
  415. package/dist/rules/simulator/firestore-set.d.ts +25 -0
  416. package/dist/rules/simulator/firestore-set.d.ts.map +1 -0
  417. package/dist/rules/simulator/firestore-set.js +89 -0
  418. package/dist/rules/simulator/firestore-set.js.map +1 -0
  419. package/dist/rules/simulator/handler.d.ts +36 -0
  420. package/dist/rules/simulator/handler.d.ts.map +1 -0
  421. package/dist/rules/simulator/handler.js +583 -0
  422. package/dist/rules/simulator/handler.js.map +1 -0
  423. package/dist/rules/simulator/mapdiff.d.ts +29 -0
  424. package/dist/rules/simulator/mapdiff.d.ts.map +1 -0
  425. package/dist/rules/simulator/mapdiff.js +72 -0
  426. package/dist/rules/simulator/mapdiff.js.map +1 -0
  427. package/dist/rules/simulator/project-after-state.d.ts +33 -0
  428. package/dist/rules/simulator/project-after-state.d.ts.map +1 -0
  429. package/dist/rules/simulator/project-after-state.js +88 -0
  430. package/dist/rules/simulator/project-after-state.js.map +1 -0
  431. package/dist/rules/simulator/query-proof.d.ts +80 -0
  432. package/dist/rules/simulator/query-proof.d.ts.map +1 -0
  433. package/dist/rules/simulator/query-proof.js +142 -0
  434. package/dist/rules/simulator/query-proof.js.map +1 -0
  435. package/dist/rules/simulator/value-equality.d.ts +8 -0
  436. package/dist/rules/simulator/value-equality.d.ts.map +1 -0
  437. package/dist/rules/simulator/value-equality.js +40 -0
  438. package/dist/rules/simulator/value-equality.js.map +1 -0
  439. package/dist/rules/simulator/wrappers/base.d.ts +129 -0
  440. package/dist/rules/simulator/wrappers/base.d.ts.map +1 -0
  441. package/dist/rules/simulator/wrappers/base.js +90 -0
  442. package/dist/rules/simulator/wrappers/base.js.map +1 -0
  443. package/dist/rules/simulator/wrappers/bytes.d.ts +45 -0
  444. package/dist/rules/simulator/wrappers/bytes.d.ts.map +1 -0
  445. package/dist/rules/simulator/wrappers/bytes.js +130 -0
  446. package/dist/rules/simulator/wrappers/bytes.js.map +1 -0
  447. package/dist/rules/simulator/wrappers/duration.d.ts +76 -0
  448. package/dist/rules/simulator/wrappers/duration.d.ts.map +1 -0
  449. package/dist/rules/simulator/wrappers/duration.js +176 -0
  450. package/dist/rules/simulator/wrappers/duration.js.map +1 -0
  451. package/dist/rules/simulator/wrappers/float.d.ts +52 -0
  452. package/dist/rules/simulator/wrappers/float.d.ts.map +1 -0
  453. package/dist/rules/simulator/wrappers/float.js +88 -0
  454. package/dist/rules/simulator/wrappers/float.js.map +1 -0
  455. package/dist/rules/simulator/wrappers/latlng.d.ts +40 -0
  456. package/dist/rules/simulator/wrappers/latlng.d.ts.map +1 -0
  457. package/dist/rules/simulator/wrappers/latlng.js +100 -0
  458. package/dist/rules/simulator/wrappers/latlng.js.map +1 -0
  459. package/dist/rules/simulator/wrappers/path.d.ts +75 -0
  460. package/dist/rules/simulator/wrappers/path.d.ts.map +1 -0
  461. package/dist/rules/simulator/wrappers/path.js +158 -0
  462. package/dist/rules/simulator/wrappers/path.js.map +1 -0
  463. package/dist/rules/simulator/wrappers/reference.d.ts +82 -0
  464. package/dist/rules/simulator/wrappers/reference.d.ts.map +1 -0
  465. package/dist/rules/simulator/wrappers/reference.js +145 -0
  466. package/dist/rules/simulator/wrappers/reference.js.map +1 -0
  467. package/dist/rules/simulator/wrappers/timestamp.d.ts +86 -0
  468. package/dist/rules/simulator/wrappers/timestamp.d.ts.map +1 -0
  469. package/dist/rules/simulator/wrappers/timestamp.js +207 -0
  470. package/dist/rules/simulator/wrappers/timestamp.js.map +1 -0
  471. package/dist/rules/simulator/wrappers/vector.d.ts +43 -0
  472. package/dist/rules/simulator/wrappers/vector.d.ts.map +1 -0
  473. package/dist/rules/simulator/wrappers/vector.js +80 -0
  474. package/dist/rules/simulator/wrappers/vector.js.map +1 -0
  475. package/dist/rules/simulator-tools-impl.d.ts +64 -0
  476. package/dist/rules/simulator-tools-impl.d.ts.map +1 -0
  477. package/dist/rules/simulator-tools-impl.js +462 -0
  478. package/dist/rules/simulator-tools-impl.js.map +1 -0
  479. package/dist/rules/simulator.d.ts +20 -0
  480. package/dist/rules/simulator.d.ts.map +1 -0
  481. package/dist/rules/simulator.js +24 -0
  482. package/dist/rules/simulator.js.map +1 -0
  483. package/dist/rules/stdlib-modules.d.ts +73 -0
  484. package/dist/rules/stdlib-modules.d.ts.map +1 -0
  485. package/dist/rules/stdlib-modules.js +849 -0
  486. package/dist/rules/stdlib-modules.js.map +1 -0
  487. package/dist/rules/stdlib-tools.d.ts +19 -0
  488. package/dist/rules/stdlib-tools.d.ts.map +1 -0
  489. package/dist/rules/stdlib-tools.js +164 -0
  490. package/dist/rules/stdlib-tools.js.map +1 -0
  491. package/dist/rules/test/handler.d.ts +9 -0
  492. package/dist/rules/test/handler.d.ts.map +1 -0
  493. package/dist/rules/test/handler.js +124 -0
  494. package/dist/rules/test/handler.js.map +1 -0
  495. package/dist/rules/test/spec.d.ts +517 -0
  496. package/dist/rules/test/spec.d.ts.map +1 -0
  497. package/dist/rules/test/spec.js +227 -0
  498. package/dist/rules/test/spec.js.map +1 -0
  499. package/dist/rules/tools.d.ts +41 -0
  500. package/dist/rules/tools.d.ts.map +1 -0
  501. package/dist/rules/tools.js +124 -0
  502. package/dist/rules/tools.js.map +1 -0
  503. package/dist/rules/write/handler.d.ts +6 -0
  504. package/dist/rules/write/handler.d.ts.map +1 -0
  505. package/dist/rules/write/handler.js +126 -0
  506. package/dist/rules/write/handler.js.map +1 -0
  507. package/dist/rules/write/spec.d.ts +28 -0
  508. package/dist/rules/write/spec.d.ts.map +1 -0
  509. package/dist/rules/write/spec.js +2 -0
  510. package/dist/rules/write/spec.js.map +1 -0
  511. package/dist/sandbox/admin-compat.d.ts +20 -0
  512. package/dist/sandbox/admin-compat.d.ts.map +1 -0
  513. package/dist/sandbox/admin-compat.js +19 -0
  514. package/dist/sandbox/admin-compat.js.map +1 -0
  515. package/dist/sandbox/admin-firestore/error-translation.d.ts +86 -0
  516. package/dist/sandbox/admin-firestore/error-translation.d.ts.map +1 -0
  517. package/dist/sandbox/admin-firestore/error-translation.js +204 -0
  518. package/dist/sandbox/admin-firestore/error-translation.js.map +1 -0
  519. package/dist/sandbox/admin-firestore/index.d.ts +169 -0
  520. package/dist/sandbox/admin-firestore/index.d.ts.map +1 -0
  521. package/dist/sandbox/admin-firestore/index.js +456 -0
  522. package/dist/sandbox/admin-firestore/index.js.map +1 -0
  523. package/dist/sandbox/admin-firestore/remote.d.ts +97 -0
  524. package/dist/sandbox/admin-firestore/remote.d.ts.map +1 -0
  525. package/dist/sandbox/admin-firestore/remote.js +735 -0
  526. package/dist/sandbox/admin-firestore/remote.js.map +1 -0
  527. package/dist/sandbox/branches/index.d.ts +141 -0
  528. package/dist/sandbox/branches/index.d.ts.map +1 -0
  529. package/dist/sandbox/branches/index.js +327 -0
  530. package/dist/sandbox/branches/index.js.map +1 -0
  531. package/dist/sandbox/firestore/admin-compat/batch.d.ts +34 -0
  532. package/dist/sandbox/firestore/admin-compat/batch.d.ts.map +1 -0
  533. package/dist/sandbox/firestore/admin-compat/batch.js +73 -0
  534. package/dist/sandbox/firestore/admin-compat/batch.js.map +1 -0
  535. package/dist/sandbox/firestore/admin-compat/doc-ref.d.ts +38 -0
  536. package/dist/sandbox/firestore/admin-compat/doc-ref.d.ts.map +1 -0
  537. package/dist/sandbox/firestore/admin-compat/doc-ref.js +154 -0
  538. package/dist/sandbox/firestore/admin-compat/doc-ref.js.map +1 -0
  539. package/dist/sandbox/firestore/admin-compat/firestore.d.ts +45 -0
  540. package/dist/sandbox/firestore/admin-compat/firestore.d.ts.map +1 -0
  541. package/dist/sandbox/firestore/admin-compat/firestore.js +114 -0
  542. package/dist/sandbox/firestore/admin-compat/firestore.js.map +1 -0
  543. package/dist/sandbox/firestore/admin-compat/index.d.ts +45 -0
  544. package/dist/sandbox/firestore/admin-compat/index.d.ts.map +1 -0
  545. package/dist/sandbox/firestore/admin-compat/index.js +27 -0
  546. package/dist/sandbox/firestore/admin-compat/index.js.map +1 -0
  547. package/dist/sandbox/firestore/admin-compat/paths.d.ts +37 -0
  548. package/dist/sandbox/firestore/admin-compat/paths.d.ts.map +1 -0
  549. package/dist/sandbox/firestore/admin-compat/paths.js +49 -0
  550. package/dist/sandbox/firestore/admin-compat/paths.js.map +1 -0
  551. package/dist/sandbox/firestore/admin-compat/query.d.ts +261 -0
  552. package/dist/sandbox/firestore/admin-compat/query.d.ts.map +1 -0
  553. package/dist/sandbox/firestore/admin-compat/query.js +704 -0
  554. package/dist/sandbox/firestore/admin-compat/query.js.map +1 -0
  555. package/dist/sandbox/firestore/admin-compat/read-translation.d.ts +8 -0
  556. package/dist/sandbox/firestore/admin-compat/read-translation.d.ts.map +1 -0
  557. package/dist/sandbox/firestore/admin-compat/read-translation.js +59 -0
  558. package/dist/sandbox/firestore/admin-compat/read-translation.js.map +1 -0
  559. package/dist/sandbox/firestore/admin-compat/snapshots.d.ts +39 -0
  560. package/dist/sandbox/firestore/admin-compat/snapshots.d.ts.map +1 -0
  561. package/dist/sandbox/firestore/admin-compat/snapshots.js +50 -0
  562. package/dist/sandbox/firestore/admin-compat/snapshots.js.map +1 -0
  563. package/dist/sandbox/firestore/admin-compat/transaction.d.ts +35 -0
  564. package/dist/sandbox/firestore/admin-compat/transaction.d.ts.map +1 -0
  565. package/dist/sandbox/firestore/admin-compat/transaction.js +88 -0
  566. package/dist/sandbox/firestore/admin-compat/transaction.js.map +1 -0
  567. package/dist/sandbox/firestore/admin-compat/types.d.ts +297 -0
  568. package/dist/sandbox/firestore/admin-compat/types.d.ts.map +1 -0
  569. package/dist/sandbox/firestore/admin-compat/types.js +127 -0
  570. package/dist/sandbox/firestore/admin-compat/types.js.map +1 -0
  571. package/dist/sandbox/firestore/admin-compat/value-order.d.ts +49 -0
  572. package/dist/sandbox/firestore/admin-compat/value-order.d.ts.map +1 -0
  573. package/dist/sandbox/firestore/admin-compat/value-order.js +172 -0
  574. package/dist/sandbox/firestore/admin-compat/value-order.js.map +1 -0
  575. package/dist/sandbox/firestore/auto-id.d.ts +26 -0
  576. package/dist/sandbox/firestore/auto-id.d.ts.map +1 -0
  577. package/dist/sandbox/firestore/auto-id.js +36 -0
  578. package/dist/sandbox/firestore/auto-id.js.map +1 -0
  579. package/dist/sandbox/firestore/converters/bytes-geopoint.d.ts +48 -0
  580. package/dist/sandbox/firestore/converters/bytes-geopoint.d.ts.map +1 -0
  581. package/dist/sandbox/firestore/converters/bytes-geopoint.js +85 -0
  582. package/dist/sandbox/firestore/converters/bytes-geopoint.js.map +1 -0
  583. package/dist/sandbox/firestore/converters/fieldvalue.d.ts +69 -0
  584. package/dist/sandbox/firestore/converters/fieldvalue.d.ts.map +1 -0
  585. package/dist/sandbox/firestore/converters/fieldvalue.js +166 -0
  586. package/dist/sandbox/firestore/converters/fieldvalue.js.map +1 -0
  587. package/dist/sandbox/firestore/converters/reference.d.ts +31 -0
  588. package/dist/sandbox/firestore/converters/reference.d.ts.map +1 -0
  589. package/dist/sandbox/firestore/converters/reference.js +51 -0
  590. package/dist/sandbox/firestore/converters/reference.js.map +1 -0
  591. package/dist/sandbox/firestore/converters/timestamp.d.ts +32 -0
  592. package/dist/sandbox/firestore/converters/timestamp.d.ts.map +1 -0
  593. package/dist/sandbox/firestore/converters/timestamp.js +63 -0
  594. package/dist/sandbox/firestore/converters/timestamp.js.map +1 -0
  595. package/dist/sandbox/firestore/converters/user-timestamp.d.ts +46 -0
  596. package/dist/sandbox/firestore/converters/user-timestamp.d.ts.map +1 -0
  597. package/dist/sandbox/firestore/converters/user-timestamp.js +65 -0
  598. package/dist/sandbox/firestore/converters/user-timestamp.js.map +1 -0
  599. package/dist/sandbox/firestore/converters/vector.d.ts +24 -0
  600. package/dist/sandbox/firestore/converters/vector.d.ts.map +1 -0
  601. package/dist/sandbox/firestore/converters/vector.js +53 -0
  602. package/dist/sandbox/firestore/converters/vector.js.map +1 -0
  603. package/dist/sandbox/firestore/errors.d.ts +82 -0
  604. package/dist/sandbox/firestore/errors.d.ts.map +1 -0
  605. package/dist/sandbox/firestore/errors.js +54 -0
  606. package/dist/sandbox/firestore/errors.js.map +1 -0
  607. package/dist/sandbox/firestore/event-log.d.ts +99 -0
  608. package/dist/sandbox/firestore/event-log.d.ts.map +1 -0
  609. package/dist/sandbox/firestore/event-log.js +67 -0
  610. package/dist/sandbox/firestore/event-log.js.map +1 -0
  611. package/dist/sandbox/firestore/field-merge.d.ts +64 -0
  612. package/dist/sandbox/firestore/field-merge.d.ts.map +1 -0
  613. package/dist/sandbox/firestore/field-merge.js +221 -0
  614. package/dist/sandbox/firestore/field-merge.js.map +1 -0
  615. package/dist/sandbox/firestore/list-query-proof.d.ts +77 -0
  616. package/dist/sandbox/firestore/list-query-proof.d.ts.map +1 -0
  617. package/dist/sandbox/firestore/list-query-proof.js +170 -0
  618. package/dist/sandbox/firestore/list-query-proof.js.map +1 -0
  619. package/dist/sandbox/firestore/local-environment.d.ts +806 -0
  620. package/dist/sandbox/firestore/local-environment.d.ts.map +1 -0
  621. package/dist/sandbox/firestore/local-environment.js +3028 -0
  622. package/dist/sandbox/firestore/local-environment.js.map +1 -0
  623. package/dist/sandbox/firestore/local-state.d.ts +196 -0
  624. package/dist/sandbox/firestore/local-state.d.ts.map +1 -0
  625. package/dist/sandbox/firestore/local-state.js +413 -0
  626. package/dist/sandbox/firestore/local-state.js.map +1 -0
  627. package/dist/sandbox/firestore/overlay-backing.d.ts +44 -0
  628. package/dist/sandbox/firestore/overlay-backing.d.ts.map +1 -0
  629. package/dist/sandbox/firestore/overlay-backing.js +82 -0
  630. package/dist/sandbox/firestore/overlay-backing.js.map +1 -0
  631. package/dist/sandbox/firestore/sentinel-capture.d.ts +30 -0
  632. package/dist/sandbox/firestore/sentinel-capture.d.ts.map +1 -0
  633. package/dist/sandbox/firestore/sentinel-capture.js +61 -0
  634. package/dist/sandbox/firestore/sentinel-capture.js.map +1 -0
  635. package/dist/sandbox/firestore/snapshot-listeners.d.ts +284 -0
  636. package/dist/sandbox/firestore/snapshot-listeners.d.ts.map +1 -0
  637. package/dist/sandbox/firestore/snapshot-listeners.js +194 -0
  638. package/dist/sandbox/firestore/snapshot-listeners.js.map +1 -0
  639. package/dist/sandbox/firestore/topk.d.ts +12 -0
  640. package/dist/sandbox/firestore/topk.d.ts.map +1 -0
  641. package/dist/sandbox/firestore/topk.js +42 -0
  642. package/dist/sandbox/firestore/topk.js.map +1 -0
  643. package/dist/sandbox/firestore/transaction-merge.d.ts +55 -0
  644. package/dist/sandbox/firestore/transaction-merge.d.ts.map +1 -0
  645. package/dist/sandbox/firestore/transaction-merge.js +107 -0
  646. package/dist/sandbox/firestore/transaction-merge.js.map +1 -0
  647. package/dist/sandbox/firestore/transaction-types.d.ts +152 -0
  648. package/dist/sandbox/firestore/transaction-types.d.ts.map +1 -0
  649. package/dist/sandbox/firestore/transaction-types.js +10 -0
  650. package/dist/sandbox/firestore/transaction-types.js.map +1 -0
  651. package/dist/sandbox/firestore/transaction.d.ts +79 -0
  652. package/dist/sandbox/firestore/transaction.d.ts.map +1 -0
  653. package/dist/sandbox/firestore/transaction.js +95 -0
  654. package/dist/sandbox/firestore/transaction.js.map +1 -0
  655. package/dist/sandbox/firestore/value-equality.d.ts +2 -0
  656. package/dist/sandbox/firestore/value-equality.d.ts.map +1 -0
  657. package/dist/sandbox/firestore/value-equality.js +35 -0
  658. package/dist/sandbox/firestore/value-equality.js.map +1 -0
  659. package/dist/sandbox/firestore/value-resolver.d.ts +172 -0
  660. package/dist/sandbox/firestore/value-resolver.d.ts.map +1 -0
  661. package/dist/sandbox/firestore/value-resolver.js +221 -0
  662. package/dist/sandbox/firestore/value-resolver.js.map +1 -0
  663. package/dist/sandbox/firestore/wire-encoder.d.ts +14 -0
  664. package/dist/sandbox/firestore/wire-encoder.d.ts.map +1 -0
  665. package/dist/sandbox/firestore/wire-encoder.js +130 -0
  666. package/dist/sandbox/firestore/wire-encoder.js.map +1 -0
  667. package/dist/sandbox/index.d.ts +50 -0
  668. package/dist/sandbox/index.d.ts.map +1 -0
  669. package/dist/sandbox/index.js +63 -0
  670. package/dist/sandbox/index.js.map +1 -0
  671. package/dist/sandbox/internal/index.d.ts +36 -0
  672. package/dist/sandbox/internal/index.d.ts.map +1 -0
  673. package/dist/sandbox/internal/index.js +72 -0
  674. package/dist/sandbox/internal/index.js.map +1 -0
  675. package/dist/sandbox/internal/sandbox-impl.d.ts +343 -0
  676. package/dist/sandbox/internal/sandbox-impl.d.ts.map +1 -0
  677. package/dist/sandbox/internal/sandbox-impl.js +718 -0
  678. package/dist/sandbox/internal/sandbox-impl.js.map +1 -0
  679. package/dist/sandbox/persistence/backends.d.ts +37 -0
  680. package/dist/sandbox/persistence/backends.d.ts.map +1 -0
  681. package/dist/sandbox/persistence/backends.js +202 -0
  682. package/dist/sandbox/persistence/backends.js.map +1 -0
  683. package/dist/sandbox/persistence/chunk-format.d.ts +58 -0
  684. package/dist/sandbox/persistence/chunk-format.d.ts.map +1 -0
  685. package/dist/sandbox/persistence/chunk-format.js +163 -0
  686. package/dist/sandbox/persistence/chunk-format.js.map +1 -0
  687. package/dist/sandbox/persistence/controller.d.ts +39 -0
  688. package/dist/sandbox/persistence/controller.d.ts.map +1 -0
  689. package/dist/sandbox/persistence/controller.js +605 -0
  690. package/dist/sandbox/persistence/controller.js.map +1 -0
  691. package/dist/sandbox/persistence/index.d.ts +13 -0
  692. package/dist/sandbox/persistence/index.d.ts.map +1 -0
  693. package/dist/sandbox/persistence/index.js +5 -0
  694. package/dist/sandbox/persistence/index.js.map +1 -0
  695. package/dist/sandbox/persistence/serialize.d.ts +53 -0
  696. package/dist/sandbox/persistence/serialize.d.ts.map +1 -0
  697. package/dist/sandbox/persistence/serialize.js +98 -0
  698. package/dist/sandbox/persistence/serialize.js.map +1 -0
  699. package/dist/sandbox/persistence/types.d.ts +118 -0
  700. package/dist/sandbox/persistence/types.d.ts.map +1 -0
  701. package/dist/sandbox/persistence/types.js +15 -0
  702. package/dist/sandbox/persistence/types.js.map +1 -0
  703. package/dist/sandbox/remote.d.ts +118 -0
  704. package/dist/sandbox/remote.d.ts.map +1 -0
  705. package/dist/sandbox/remote.js +60 -0
  706. package/dist/sandbox/remote.js.map +1 -0
  707. package/dist/sandbox/replay/index.d.ts +106 -0
  708. package/dist/sandbox/replay/index.d.ts.map +1 -0
  709. package/dist/sandbox/replay/index.js +246 -0
  710. package/dist/sandbox/replay/index.js.map +1 -0
  711. package/dist/sandbox/sandbox-context.d.ts +40 -0
  712. package/dist/sandbox/sandbox-context.d.ts.map +1 -0
  713. package/dist/sandbox/sandbox-context.js +72 -0
  714. package/dist/sandbox/sandbox-context.js.map +1 -0
  715. package/dist/sandbox/tab-sync/index.d.ts +120 -0
  716. package/dist/sandbox/tab-sync/index.d.ts.map +1 -0
  717. package/dist/sandbox/tab-sync/index.js +272 -0
  718. package/dist/sandbox/tab-sync/index.js.map +1 -0
  719. package/dist/sandbox/types.d.ts +1235 -0
  720. package/dist/sandbox/types.d.ts.map +1 -0
  721. package/dist/sandbox/types.js +46 -0
  722. package/dist/sandbox/types.js.map +1 -0
  723. package/dist/storage/admin/api.d.ts +206 -0
  724. package/dist/storage/admin/api.d.ts.map +1 -0
  725. package/dist/storage/admin/api.js +349 -0
  726. package/dist/storage/admin/api.js.map +1 -0
  727. package/dist/storage/admin/handler.d.ts +29 -0
  728. package/dist/storage/admin/handler.d.ts.map +1 -0
  729. package/dist/storage/admin/handler.js +82 -0
  730. package/dist/storage/admin/handler.js.map +1 -0
  731. package/dist/storage/admin/spec.d.ts +64 -0
  732. package/dist/storage/admin/spec.d.ts.map +1 -0
  733. package/dist/storage/admin/spec.js +8 -0
  734. package/dist/storage/admin/spec.js.map +1 -0
  735. package/dist/storage/admin/tools.d.ts +23 -0
  736. package/dist/storage/admin/tools.d.ts.map +1 -0
  737. package/dist/storage/admin/tools.js +90 -0
  738. package/dist/storage/admin/tools.js.map +1 -0
  739. package/dist/storage/download.d.ts +27 -0
  740. package/dist/storage/download.d.ts.map +1 -0
  741. package/dist/storage/download.js +136 -0
  742. package/dist/storage/download.js.map +1 -0
  743. package/dist/storage/enforce.d.ts +26 -0
  744. package/dist/storage/enforce.d.ts.map +1 -0
  745. package/dist/storage/enforce.js +16 -0
  746. package/dist/storage/enforce.js.map +1 -0
  747. package/dist/storage/errors.d.ts +46 -0
  748. package/dist/storage/errors.d.ts.map +1 -0
  749. package/dist/storage/errors.js +62 -0
  750. package/dist/storage/errors.js.map +1 -0
  751. package/dist/storage/index.d.ts +49 -0
  752. package/dist/storage/index.d.ts.map +1 -0
  753. package/dist/storage/index.js +60 -0
  754. package/dist/storage/index.js.map +1 -0
  755. package/dist/storage/internal.d.ts +18 -0
  756. package/dist/storage/internal.d.ts.map +1 -0
  757. package/dist/storage/internal.js +18 -0
  758. package/dist/storage/internal.js.map +1 -0
  759. package/dist/storage/list.d.ts +17 -0
  760. package/dist/storage/list.d.ts.map +1 -0
  761. package/dist/storage/list.js +91 -0
  762. package/dist/storage/list.js.map +1 -0
  763. package/dist/storage/metadata.d.ts +86 -0
  764. package/dist/storage/metadata.d.ts.map +1 -0
  765. package/dist/storage/metadata.js +167 -0
  766. package/dist/storage/metadata.js.map +1 -0
  767. package/dist/storage/persistence.d.ts +134 -0
  768. package/dist/storage/persistence.d.ts.map +1 -0
  769. package/dist/storage/persistence.js +132 -0
  770. package/dist/storage/persistence.js.map +1 -0
  771. package/dist/storage/reference.d.ts +63 -0
  772. package/dist/storage/reference.d.ts.map +1 -0
  773. package/dist/storage/reference.js +156 -0
  774. package/dist/storage/reference.js.map +1 -0
  775. package/dist/storage/rules.d.ts +176 -0
  776. package/dist/storage/rules.d.ts.map +1 -0
  777. package/dist/storage/rules.js +621 -0
  778. package/dist/storage/rules.js.map +1 -0
  779. package/dist/storage/service.d.ts +139 -0
  780. package/dist/storage/service.d.ts.map +1 -0
  781. package/dist/storage/service.js +241 -0
  782. package/dist/storage/service.js.map +1 -0
  783. package/dist/storage/upload.d.ts +43 -0
  784. package/dist/storage/upload.d.ts.map +1 -0
  785. package/dist/storage/upload.js +235 -0
  786. package/dist/storage/upload.js.map +1 -0
  787. package/package.json +110 -3
@@ -0,0 +1,784 @@
1
+ import { parseToASTOrError } from '../grammar/FirestoreParser.js';
2
+ import { maxChainDepth, deepestChain, countExpressionNodes, expressionFingerprint, extractFirstExpression, buildCallGraph, maxCallDepth, countGetCalls, countFunctionCallSites, functionContainsGet, referencesRequestTime, collectAllFunctions, collectAllRules, } from './ast-utils.js';
3
+ import { checkSyntaxHints, checkHallucinations } from './hallucinations.js';
4
+ // ═══ Thresholds (from production verification) ═══
5
+ const THRESHOLDS = {
6
+ SOURCE_SIZE: 256 * 1024, // 256 KB — exact, verified
7
+ CHAIN_DEPTH_ERROR: 95, // warn before the hard limit
8
+ CHAIN_DEPTH_WARN: 85,
9
+ CHAIN_DEPTH_LIMIT: 98, // exact compile limit, verified
10
+ LET_LIMIT: 11, // exact, verified (12 fails)
11
+ // Runtime budget is call-count-dependent and non-deterministic
12
+ RUNTIME_BUDGET: {
13
+ low: { calls: 2, warn: 100, error: 120 },
14
+ mid: { calls: 4, warn: 60, error: 90 },
15
+ high: { calls: Infinity, warn: 40, error: 60 },
16
+ },
17
+ CALL_DEPTH_WARN: 6,
18
+ CALL_DEPTH_ERROR: 10,
19
+ GET_COUNT_WARN: 5,
20
+ GET_COUNT_ERROR: 10, // documented by Google
21
+ };
22
+ // ═══ Lint Rules ═══
23
+ function checkSourceSize(source, warnings) {
24
+ if (source.length > THRESHOLDS.SOURCE_SIZE) {
25
+ warnings.push({
26
+ rule: 'SOURCE_SIZE',
27
+ severity: 'error',
28
+ message: `Rules source is ${(source.length / 1024).toFixed(0)} KB, exceeding the 256 KB limit.`,
29
+ fix: 'Reduce string literals, remove comments, or split into smaller match blocks.',
30
+ });
31
+ }
32
+ }
33
+ function checkLetBindings(functions, warnings) {
34
+ for (const fn of functions) {
35
+ if (fn.lets.length > THRESHOLDS.LET_LIMIT) {
36
+ warnings.push({
37
+ rule: 'LET_LIMIT',
38
+ severity: 'error',
39
+ message: `Function '${fn.name}' has ${fn.lets.length} let bindings. Limit is ${THRESHOLDS.LET_LIMIT}.`,
40
+ location: { functionName: fn.name },
41
+ fix: 'Inline some let expressions into the return statement, or split the function.',
42
+ });
43
+ }
44
+ }
45
+ }
46
+ function checkChainDepth(functions, warnings) {
47
+ for (const fn of functions) {
48
+ const chain = deepestChain(fn.body);
49
+ // Also check let binding values for deep chains
50
+ for (const binding of fn.lets) {
51
+ const letChain = deepestChain(binding.value);
52
+ if (letChain.depth > chain.depth) {
53
+ chain.depth = letChain.depth;
54
+ chain.op = letChain.op;
55
+ }
56
+ }
57
+ if (chain.depth >= THRESHOLDS.CHAIN_DEPTH_LIMIT) {
58
+ warnings.push({
59
+ rule: 'CHAIN_DEPTH',
60
+ severity: 'error',
61
+ message: `Function '${fn.name}' has a ${chain.op} chain of depth ${chain.depth}. Limit is ${THRESHOLDS.CHAIN_DEPTH_LIMIT}.`,
62
+ location: { functionName: fn.name },
63
+ fix: `Split into nested groups: 'a && b && c && d' → '(a && b) && (c && d)' to halve chain depth.`,
64
+ });
65
+ }
66
+ else if (chain.depth >= THRESHOLDS.CHAIN_DEPTH_ERROR) {
67
+ warnings.push({
68
+ rule: 'CHAIN_DEPTH',
69
+ severity: 'error',
70
+ message: `Function '${fn.name}' has a ${chain.op} chain of depth ${chain.depth}. Limit is ${THRESHOLDS.CHAIN_DEPTH_LIMIT}. Approaching failure.`,
71
+ location: { functionName: fn.name },
72
+ fix: `Split the chain into nested groups to reduce depth.`,
73
+ });
74
+ }
75
+ else if (chain.depth >= THRESHOLDS.CHAIN_DEPTH_WARN) {
76
+ warnings.push({
77
+ rule: 'CHAIN_DEPTH',
78
+ severity: 'warning',
79
+ message: `Function '${fn.name}' has a ${chain.op} chain of depth ${chain.depth}. Limit is ${THRESHOLDS.CHAIN_DEPTH_LIMIT}.`,
80
+ location: { functionName: fn.name },
81
+ });
82
+ }
83
+ }
84
+ }
85
+ function checkSharedGates(rules, warnings) {
86
+ // Group allow update rules by match path
87
+ const byPath = new Map();
88
+ for (let i = 0; i < rules.length; i++) {
89
+ const r = rules[i];
90
+ // Only check update rules (most susceptible to budget issues)
91
+ if (!r.rule.operations.some(op => op === 'update' || op === 'write'))
92
+ continue;
93
+ const gate = expressionFingerprint(extractFirstExpression(r.rule.condition));
94
+ const path = r.path;
95
+ if (!byPath.has(path))
96
+ byPath.set(path, []);
97
+ byPath.get(path).push({ index: i, gate, ops: r.rule.operations });
98
+ }
99
+ for (const [path, entries] of byPath) {
100
+ const gateGroups = new Map();
101
+ for (const e of entries) {
102
+ if (!gateGroups.has(e.gate))
103
+ gateGroups.set(e.gate, []);
104
+ gateGroups.get(e.gate).push(e.index);
105
+ }
106
+ for (const [gate, indices] of gateGroups) {
107
+ if (indices.length >= 2) {
108
+ warnings.push({
109
+ rule: 'SHARED_GATE',
110
+ severity: 'warning',
111
+ message: `${indices.length} allow rules in '${path}' share the same gate expression. This may cause cross-rule budget exhaustion. Rules: ${indices.join(', ')}.`,
112
+ location: { matchPath: path },
113
+ fix: 'Assign unique moveType or discriminator values so each rule has a unique first expression.',
114
+ });
115
+ }
116
+ }
117
+ }
118
+ }
119
+ /**
120
+ * Count function calls and total expressions for a SINGLE rule's condition,
121
+ * following function calls transitively. Skips already-visited functions
122
+ * to avoid double-counting shared helpers (like cfg()).
123
+ */
124
+ function estimateRuleBudget(condition, fnMap) {
125
+ let totalExprs = countExpressionNodes(condition);
126
+ const visited = new Set();
127
+ function walkForCalls(expr) {
128
+ if (expr.type === 'functionCall' && fnMap.has(expr.name) && !visited.has(expr.name)) {
129
+ visited.add(expr.name);
130
+ const fn = fnMap.get(expr.name);
131
+ totalExprs += countExpressionNodes(fn.body);
132
+ for (const b of fn.lets)
133
+ totalExprs += countExpressionNodes(b.value);
134
+ walkForCalls(fn.body);
135
+ for (const b of fn.lets)
136
+ walkForCalls(b.value);
137
+ }
138
+ // Walk children to find nested function calls
139
+ switch (expr.type) {
140
+ case 'binaryOp':
141
+ walkForCalls(expr.left);
142
+ walkForCalls(expr.right);
143
+ break;
144
+ case 'unaryOp':
145
+ walkForCalls(expr.operand);
146
+ break;
147
+ case 'methodCall':
148
+ walkForCalls(expr.object);
149
+ expr.args.forEach(walkForCalls);
150
+ break;
151
+ case 'memberAccess':
152
+ walkForCalls(expr.object);
153
+ break;
154
+ case 'bracketAccess':
155
+ walkForCalls(expr.object);
156
+ walkForCalls(expr.index);
157
+ break;
158
+ case 'ternary':
159
+ walkForCalls(expr.condition);
160
+ walkForCalls(expr.consequent);
161
+ walkForCalls(expr.alternate);
162
+ break;
163
+ case 'inExpr':
164
+ walkForCalls(expr.element);
165
+ walkForCalls(expr.collection);
166
+ break;
167
+ case 'isExpr':
168
+ walkForCalls(expr.value);
169
+ break;
170
+ case 'listLiteral':
171
+ expr.elements.forEach(walkForCalls);
172
+ break;
173
+ case 'mapLiteral':
174
+ expr.entries.forEach(e => { walkForCalls(e.key); walkForCalls(e.value); });
175
+ break;
176
+ case 'functionCall':
177
+ expr.args.forEach(walkForCalls);
178
+ break;
179
+ }
180
+ }
181
+ walkForCalls(condition);
182
+ return { totalExprs, callCount: visited.size };
183
+ }
184
+ function checkExpressionBudget(rules, allFunctions, warnings) {
185
+ const fnMap = new Map();
186
+ for (const fn of allFunctions)
187
+ fnMap.set(fn.name, fn);
188
+ for (let i = 0; i < rules.length; i++) {
189
+ const { totalExprs, callCount } = estimateRuleBudget(rules[i].rule.condition, fnMap);
190
+ // The runtime budget depends on function call count.
191
+ // With unique gates (SHARED_GATE check handles this separately),
192
+ // only this rule's expressions are evaluated. The budget model
193
+ // accounts for per-call overhead making the available budget
194
+ // decrease with more calls.
195
+ //
196
+ // However, the total node count is a WORST-CASE estimate (assumes
197
+ // all branches evaluate). Firestore short-circuits && and ||.
198
+ // For rules with many OR branches where only 1 matches, the actual
199
+ // evaluated count is much lower than the tree size.
200
+ //
201
+ // To avoid false positives on rules with large but well-gated trees
202
+ // (like chess check detection with 16 OR branches), we use a
203
+ // conservative multiplier: if the rule has many OR branches at the
204
+ // top level, discount the estimate.
205
+ const topLevelOrs = maxChainDepth(rules[i].rule.condition, '||');
206
+ const discountFactor = topLevelOrs > 5 ? 0.3 : topLevelOrs > 2 ? 0.5 : 1.0;
207
+ const adjustedExprs = Math.round(totalExprs * discountFactor);
208
+ const budget = callCount <= THRESHOLDS.RUNTIME_BUDGET.low.calls
209
+ ? THRESHOLDS.RUNTIME_BUDGET.low
210
+ : callCount <= THRESHOLDS.RUNTIME_BUDGET.mid.calls
211
+ ? THRESHOLDS.RUNTIME_BUDGET.mid
212
+ : THRESHOLDS.RUNTIME_BUDGET.high;
213
+ // Expression budget is always a WARNING, never an error, because:
214
+ // 1. We count the full tree but Firestore short-circuits && and ||
215
+ // 2. The runtime budget is non-deterministic (has a flaky zone)
216
+ // 3. The actual evaluated expressions depend on data at runtime
217
+ // Hard structural errors (chain depth, let limit) catch compilation failures.
218
+ // This check catches POTENTIAL runtime issues as advisory warnings.
219
+ if (adjustedExprs >= budget.warn) {
220
+ warnings.push({
221
+ rule: 'EXPRESSION_BUDGET',
222
+ severity: 'warning',
223
+ message: `Rule #${i} has ~${totalExprs} expression nodes across ${callCount} function calls. Runtime budget is non-deterministic; actual evaluation depends on short-circuit behavior.`,
224
+ location: { ruleIndex: i },
225
+ fix: 'If this rule fails at runtime (403), reduce function calls or expression count.',
226
+ });
227
+ }
228
+ }
229
+ }
230
+ function checkCallDepth(rules, allFunctions, warnings) {
231
+ const callGraph = buildCallGraph(allFunctions);
232
+ const fnMap = new Map();
233
+ for (const fn of allFunctions)
234
+ fnMap.set(fn.name, fn);
235
+ for (let i = 0; i < rules.length; i++) {
236
+ let maxDepth = 0;
237
+ const findDepth = (expr) => {
238
+ if (expr.type === 'functionCall' && fnMap.has(expr.name)) {
239
+ const depth = maxCallDepth(expr.name, callGraph);
240
+ if (depth > maxDepth)
241
+ maxDepth = depth;
242
+ }
243
+ switch (expr.type) {
244
+ case 'binaryOp':
245
+ findDepth(expr.left);
246
+ findDepth(expr.right);
247
+ break;
248
+ case 'unaryOp':
249
+ findDepth(expr.operand);
250
+ break;
251
+ case 'methodCall':
252
+ findDepth(expr.object);
253
+ expr.args.forEach(findDepth);
254
+ break;
255
+ case 'memberAccess':
256
+ findDepth(expr.object);
257
+ break;
258
+ case 'bracketAccess':
259
+ findDepth(expr.object);
260
+ findDepth(expr.index);
261
+ break;
262
+ case 'ternary':
263
+ findDepth(expr.condition);
264
+ findDepth(expr.consequent);
265
+ findDepth(expr.alternate);
266
+ break;
267
+ case 'inExpr':
268
+ findDepth(expr.element);
269
+ findDepth(expr.collection);
270
+ break;
271
+ case 'functionCall':
272
+ expr.args.forEach(findDepth);
273
+ break;
274
+ }
275
+ };
276
+ findDepth(rules[i].rule.condition);
277
+ if (maxDepth >= THRESHOLDS.CALL_DEPTH_ERROR) {
278
+ warnings.push({
279
+ rule: 'CALL_DEPTH',
280
+ severity: 'error',
281
+ message: `Rule #${i} has a function call chain of depth ${maxDepth}. May exceed call budget.`,
282
+ location: { ruleIndex: i },
283
+ fix: 'Inline intermediate functions to reduce call depth.',
284
+ });
285
+ }
286
+ else if (maxDepth >= THRESHOLDS.CALL_DEPTH_WARN) {
287
+ warnings.push({
288
+ rule: 'CALL_DEPTH',
289
+ severity: 'warning',
290
+ message: `Rule #${i} has a function call chain of depth ${maxDepth}.`,
291
+ location: { ruleIndex: i },
292
+ });
293
+ }
294
+ }
295
+ }
296
+ function checkGetCount(rules, allFunctions, warnings) {
297
+ const fnMap = new Map();
298
+ for (const fn of allFunctions)
299
+ fnMap.set(fn.name, fn);
300
+ for (let i = 0; i < rules.length; i++) {
301
+ const count = countGetCalls(rules[i].rule.condition, fnMap);
302
+ if (count >= THRESHOLDS.GET_COUNT_ERROR) {
303
+ warnings.push({
304
+ rule: 'GET_COUNT',
305
+ severity: 'error',
306
+ message: `Rule #${i} may invoke ${count} get()/exists() calls. Limit is ${THRESHOLDS.GET_COUNT_ERROR}.`,
307
+ location: { ruleIndex: i },
308
+ fix: 'Cache get() results via a config() wrapper function. Same-path calls are cached by Firestore.',
309
+ });
310
+ }
311
+ else if (count >= THRESHOLDS.GET_COUNT_WARN) {
312
+ warnings.push({
313
+ rule: 'GET_COUNT',
314
+ severity: 'warning',
315
+ message: `Rule #${i} invokes ${count} get()/exists() calls. Limit is ${THRESHOLDS.GET_COUNT_ERROR}.`,
316
+ location: { ruleIndex: i },
317
+ });
318
+ }
319
+ }
320
+ }
321
+ function checkGetDuplication(rules, allFunctions, warnings) {
322
+ const fnMap = new Map();
323
+ for (const fn of allFunctions)
324
+ fnMap.set(fn.name, fn);
325
+ const fnNames = new Set(allFunctions.map(f => f.name));
326
+ for (let i = 0; i < rules.length; i++) {
327
+ const callCounts = countFunctionCallSites(rules[i].rule.condition, fnNames);
328
+ for (const [fnName, count] of callCounts) {
329
+ if (count >= 2 && functionContainsGet(fnName, fnMap)) {
330
+ warnings.push({
331
+ rule: 'GET_DUPLICATION',
332
+ severity: 'warning',
333
+ message: `Function '${fnName}' (contains get/exists) is called ${count} times in rule #${i}. Cache the result with a let binding in a wrapper function to reduce get() calls from ${count} to 1.`,
334
+ location: { ruleIndex: i },
335
+ fix: `Create a wrapper: function verifyAll(ret) { let c = ${fnName}(); return verify1(ret, c) && verify2(ret, c) && ...; }`,
336
+ });
337
+ }
338
+ }
339
+ }
340
+ }
341
+ /**
342
+ * REQUEST_TIME_NOT_PINNED — couples the static linter to the per-test data
343
+ * (REBUILD_PLAN.md Item 0.F deferred follow-up). When a rule transitively
344
+ * reads `request.time`, the rule's verdict depends on wallclock unless the
345
+ * test pins `requestTime`. Pre-fix, date-gated rules failed
346
+ * non-deterministically across CI runs and agents either gave up or
347
+ * hardcoded today's date.
348
+ *
349
+ * Emits one warning per affected (rule, test case) pair so the agent gets
350
+ * a precise checklist. Only fires when the caller passes a test suite —
351
+ * source-only `lintFirestoreRules(source)` calls are unaffected.
352
+ */
353
+ function checkRequestTimePinned(rules, allFunctions, testCases, warnings) {
354
+ const fnMap = new Map();
355
+ for (const fn of allFunctions)
356
+ fnMap.set(fn.name, fn);
357
+ // Find which rule indices reference request.time. Per-rule rather than
358
+ // per-source so a test case targeting an unrelated match block isn't
359
+ // wrongly flagged.
360
+ const timeGatedRules = new Set();
361
+ for (let i = 0; i < rules.length; i++) {
362
+ if (referencesRequestTime(rules[i].rule.condition, fnMap)) {
363
+ timeGatedRules.add(i);
364
+ }
365
+ }
366
+ if (timeGatedRules.size === 0)
367
+ return;
368
+ // Cheap match-path resolution: a test case at "users/alice" matches a
369
+ // rule whose match path is "users/{id}". Full path matching is the
370
+ // simulator/handler's job — here we just need a "could this rule fire
371
+ // for this test case?" estimate. Match by segment-count + literal-match.
372
+ function pathMatches(rulePath, tcPath) {
373
+ const ruleSegs = rulePath.split('/').filter(Boolean);
374
+ const tcSegs = tcPath.split('/').filter(Boolean);
375
+ if (ruleSegs.length !== tcSegs.length)
376
+ return false;
377
+ for (let i = 0; i < ruleSegs.length; i++) {
378
+ const rs = ruleSegs[i];
379
+ // Wildcard or recursive wildcard matches any segment.
380
+ if (rs.startsWith('{') && rs.endsWith('}'))
381
+ continue;
382
+ if (rs !== tcSegs[i])
383
+ return false;
384
+ }
385
+ return true;
386
+ }
387
+ for (const tc of testCases) {
388
+ if (tc.requestTime)
389
+ continue; // pinned — fine
390
+ for (const ruleIdx of timeGatedRules) {
391
+ if (!pathMatches(rules[ruleIdx].path, tc.path))
392
+ continue;
393
+ warnings.push({
394
+ rule: 'REQUEST_TIME_NOT_PINNED',
395
+ severity: 'warning',
396
+ message: `Test case "${tc.description}" targets rule #${ruleIdx} (path '${rules[ruleIdx].path}') which reads request.time, but does not set requestTime. Result is non-deterministic across runs.`,
397
+ location: { ruleIndex: ruleIdx, matchPath: rules[ruleIdx].path, testCaseDescription: tc.description },
398
+ fix: 'Set requestTime on this TestCase to an ISO-8601 timestamp so the rule evaluates deterministically.',
399
+ });
400
+ }
401
+ }
402
+ }
403
+ /**
404
+ * PERMISSIVE_RULE — `allow ... if true` (or any condition that statically
405
+ * resolves to the boolean literal `true`) disables security for the
406
+ * matched paths. Empirically the most common agent failure mode: when a
407
+ * targeted rule denies a write the agent doesn't understand, the easy
408
+ * escape is to write the predicate true. That ships an open collection.
409
+ *
410
+ * Severity is `error` so `deployRules` refuses to swap the ruleset — the
411
+ * agent has to fix the actual denial instead of widening the gate.
412
+ *
413
+ * Detection is deliberately conservative: we only fold `&&`/`||` over
414
+ * boolean literals and recognize the literal `true`. We do NOT try to
415
+ * prove `1 == 1` or follow function calls. A few false negatives are
416
+ * acceptable; a single false positive on a legitimate rule would break
417
+ * deploys.
418
+ */
419
+ function evalConstBool(expr) {
420
+ if (expr.type === 'literal' && typeof expr.value === 'boolean')
421
+ return expr.value;
422
+ if (expr.type === 'binaryOp') {
423
+ const left = evalConstBool(expr.left);
424
+ const right = evalConstBool(expr.right);
425
+ if (expr.op === '&&') {
426
+ if (left === false || right === false)
427
+ return false;
428
+ if (left === true && right === true)
429
+ return true;
430
+ return null;
431
+ }
432
+ if (expr.op === '||') {
433
+ if (left === true || right === true)
434
+ return true;
435
+ if (left === false && right === false)
436
+ return false;
437
+ return null;
438
+ }
439
+ }
440
+ if (expr.type === 'unaryOp' && expr.op === '!') {
441
+ const inner = evalConstBool(expr.operand);
442
+ return inner === null ? null : !inner;
443
+ }
444
+ return null;
445
+ }
446
+ const WRITE_OPS = new Set([
447
+ 'write', 'create', 'update', 'delete',
448
+ ]);
449
+ function checkPermissiveRules(rules, warnings) {
450
+ for (let i = 0; i < rules.length; i++) {
451
+ const r = rules[i];
452
+ if (evalConstBool(r.rule.condition) !== true)
453
+ continue;
454
+ // `allow read: if true` is a legitimate "public read" pattern (e.g.
455
+ // a shared config doc). Only flag when the rule grants any write
456
+ // capability — that's where `if true` actually disables security.
457
+ const grantsWrite = r.rule.operations.some((op) => WRITE_OPS.has(op));
458
+ if (!grantsWrite)
459
+ continue;
460
+ const ops = r.rule.operations.join(', ');
461
+ warnings.push({
462
+ rule: 'PERMISSIVE_RULE',
463
+ // Severity: warning, not error. Rationale: `allow write: if true`
464
+ // is the canonical dev/sandbox/quickstart pattern; classifying it
465
+ // as a hard error caused `sandbox.setRules(...)` to silently no-op
466
+ // and the scaffolded `pyric init` quickstart to break in confusing
467
+ // ways. The diagnostic itself stays — production deploy gates
468
+ // (`pyric deploy rules`) can re-run lint at a stricter level and
469
+ // refuse on warning-too. The dev-loop sandbox stays permissive.
470
+ severity: 'warning',
471
+ message: `allow ${ops} at ${r.path} resolves to a constant true predicate — `
472
+ + `this disables write security for the matched paths. If you reached `
473
+ + `for \`if true\` to escape a denial you don't understand, narrow `
474
+ + `the predicate to the specific request shape instead (auth identity, `
475
+ + `affected fields via diff, status transitions).`,
476
+ location: { ruleIndex: i, matchPath: r.path },
477
+ fix: 'Replace the always-true predicate with a request-shape check (e.g. request.auth != null && request.resource.data.ownerId == request.auth.uid).',
478
+ });
479
+ }
480
+ }
481
+ /**
482
+ * RECURSIVE_WILDCARD_OPEN — `match /{x=**} { allow read, write: if true }`
483
+ * is the most permissive ruleset Firebase will accept. Distinct from
484
+ * PERMISSIVE_RULE so the agent gets a specifically named diagnostic; the
485
+ * recursive-wildcard form is what the playground trace ended up at after
486
+ * the agent gave up debugging.
487
+ *
488
+ * Fires only when the path uses the recursive form AND the predicate
489
+ * folds to constant true — a recursive wildcard with a real predicate
490
+ * (e.g. `if request.auth.uid == userId`) is a legitimate pattern.
491
+ */
492
+ function checkRecursiveWildcardOpen(match, warnings) {
493
+ const hasRecursive = match.path.segments.some((s) => s.type === 'recursive');
494
+ if (hasRecursive) {
495
+ for (let i = 0; i < match.allows.length; i++) {
496
+ if (evalConstBool(match.allows[i].condition) === true) {
497
+ warnings.push({
498
+ rule: 'RECURSIVE_WILDCARD_OPEN',
499
+ severity: 'error',
500
+ message: `Recursive wildcard match (${match.path.raw}) with an always-true `
501
+ + `predicate exposes every document under this prefix. This is the `
502
+ + `Firebase open-rules anti-pattern — never ship it.`,
503
+ location: { ruleIndex: i, matchPath: match.path.raw },
504
+ fix: 'Either narrow the match path to specific collections, or replace `if true` with a real predicate (auth identity, ownership, role).',
505
+ });
506
+ }
507
+ }
508
+ }
509
+ for (const child of match.children)
510
+ checkRecursiveWildcardOpen(child, warnings);
511
+ }
512
+ /**
513
+ * RULES_WEAKENED — when a previous ruleset is supplied, flag every
514
+ * security predicate that the new ruleset has *removed*. Catches the
515
+ * agent failure mode where a denial is silently escaped by deleting the
516
+ * predicate (or whole rule, or whole match block) rather than fixing
517
+ * the request.
518
+ *
519
+ * Severity is `warning` (not `error`) — there are legitimate reasons to
520
+ * remove a predicate (refactor, dedupe), so this is advisory and does
521
+ * not block deploys. The agent has to decide whether the removal is
522
+ * intentional.
523
+ *
524
+ * Conjunct extraction: walk the predicate tree splitting on top-level
525
+ * `&&` only. We do NOT descend into `||` branches — splitting an OR
526
+ * would change semantics, so we treat the entire OR sub-tree as one
527
+ * conjunct. Each conjunct is normalized to a canonical string and
528
+ * compared as a set. Removed conjuncts → warnings; added/changed
529
+ * conjuncts → silence (refinement is fine).
530
+ */
531
+ /** Normalize a path segment for cross-ruleset comparison. Wildcards
532
+ * compare equal regardless of their binding name. */
533
+ function normalizePathSegment(seg) {
534
+ if (seg.type === 'literal')
535
+ return seg.value ?? '';
536
+ if (seg.type === 'wildcard')
537
+ return '{*}';
538
+ if (seg.type === 'recursive')
539
+ return '{**}';
540
+ return '';
541
+ }
542
+ /** Build the full normalized path from root to this match block by
543
+ * joining every ancestor's segments with '/'. */
544
+ function buildMatchPathChain(segments) {
545
+ return segments.map(normalizePathSegment).join('/');
546
+ }
547
+ /** Walk the AST and yield every match block with its full normalized
548
+ * path (concatenated from root). The leaf `MatchBlock.path.raw` only
549
+ * reflects the local segment, which collides across siblings. */
550
+ function collectMatchBlocksWithPaths(match, parentPath) {
551
+ const localPath = buildMatchPathChain(match.path.segments);
552
+ const fullPath = parentPath ? `${parentPath}/${localPath}` : localPath;
553
+ const out = [
554
+ { block: match, normalizedPath: fullPath },
555
+ ];
556
+ for (const child of match.children) {
557
+ out.push(...collectMatchBlocksWithPaths(child, fullPath));
558
+ }
559
+ return out;
560
+ }
561
+ /** Deterministic serializer producing the same string for structurally
562
+ * identical expressions. No surrounding whitespace; no parens (the
563
+ * structure of nested binaryOp nodes already encodes precedence). */
564
+ function serializeExpression(expr) {
565
+ switch (expr.type) {
566
+ case 'literal':
567
+ return expr.raw;
568
+ case 'identifier':
569
+ return expr.name;
570
+ case 'memberAccess':
571
+ return `${serializeExpression(expr.object)}.${expr.property}`;
572
+ case 'methodCall':
573
+ return `${serializeExpression(expr.object)}.${expr.method}(${expr.args.map(serializeExpression).join(',')})`;
574
+ case 'bracketAccess':
575
+ return `${serializeExpression(expr.object)}[${serializeExpression(expr.index)}]`;
576
+ case 'sliceAccess':
577
+ return `${serializeExpression(expr.object)}[${serializeExpression(expr.start)}:${serializeExpression(expr.end)}]`;
578
+ case 'binaryOp':
579
+ return `(${serializeExpression(expr.left)}${expr.op}${serializeExpression(expr.right)})`;
580
+ case 'unaryOp':
581
+ return `(${expr.op}${serializeExpression(expr.operand)})`;
582
+ case 'ternary':
583
+ return `(${serializeExpression(expr.condition)}?${serializeExpression(expr.consequent)}:${serializeExpression(expr.alternate)})`;
584
+ case 'inExpr':
585
+ return `(${serializeExpression(expr.element)} in ${serializeExpression(expr.collection)})`;
586
+ case 'isExpr':
587
+ return `(${serializeExpression(expr.value)} is ${expr.typeName})`;
588
+ case 'listLiteral':
589
+ return `[${expr.elements.map(serializeExpression).join(',')}]`;
590
+ case 'mapLiteral':
591
+ return `{${expr.entries.map((e) => `${serializeExpression(e.key)}:${serializeExpression(e.value)}`).join(',')}}`;
592
+ case 'pathLiteral':
593
+ return expr.raw;
594
+ case 'functionCall':
595
+ return `${expr.name}(${expr.args.map(serializeExpression).join(',')})`;
596
+ }
597
+ }
598
+ /** Split a predicate into its top-level conjuncts (split only on `&&`).
599
+ * An `||` sub-tree is preserved as a single conjunct so we don't
600
+ * change semantics by treating one of its branches as removable. */
601
+ function extractConjuncts(expr) {
602
+ if (expr.type === 'binaryOp' && expr.op === '&&') {
603
+ return [...extractConjuncts(expr.left), ...extractConjuncts(expr.right)];
604
+ }
605
+ return [expr];
606
+ }
607
+ function checkRulesWeakened(currentMatch, previousMatch, warnings) {
608
+ const currentBlocks = collectMatchBlocksWithPaths(currentMatch, '');
609
+ const previousBlocks = collectMatchBlocksWithPaths(previousMatch, '');
610
+ const currentByPath = new Map();
611
+ for (const { block, normalizedPath } of currentBlocks) {
612
+ // If duplicate paths exist (rare but possible with sibling literal
613
+ // matches reused), keep the first — comparing the first occurrence
614
+ // is sufficient for "did this path lose predicates?"
615
+ if (!currentByPath.has(normalizedPath))
616
+ currentByPath.set(normalizedPath, block);
617
+ }
618
+ for (const { block: prevBlock, normalizedPath } of previousBlocks) {
619
+ const curBlock = currentByPath.get(normalizedPath);
620
+ if (!curBlock) {
621
+ // Whole match block disappeared. Only emit when the previous
622
+ // block actually had allow rules — a parent shell with no allows
623
+ // disappearing tells the agent nothing.
624
+ if (prevBlock.allows.length > 0) {
625
+ warnings.push({
626
+ rule: 'RULES_WEAKENED',
627
+ severity: 'warning',
628
+ message: `Match block removed: ${normalizedPath}`,
629
+ location: { matchPath: normalizedPath },
630
+ });
631
+ }
632
+ continue;
633
+ }
634
+ // For each previous allow rule, find the corresponding current
635
+ // allow rule by op-set equality.
636
+ for (const prevAllow of prevBlock.allows) {
637
+ const opsKey = [...prevAllow.operations].sort().join(',');
638
+ const curAllow = curBlock.allows.find((a) => [...a.operations].sort().join(',') === opsKey);
639
+ const opsLabel = prevAllow.operations.join(', ');
640
+ if (!curAllow) {
641
+ warnings.push({
642
+ rule: 'RULES_WEAKENED',
643
+ severity: 'warning',
644
+ message: `Allow rule removed: ${normalizedPath} allow ${opsLabel}`,
645
+ location: { matchPath: normalizedPath },
646
+ });
647
+ continue;
648
+ }
649
+ // Diff the conjunct sets.
650
+ const prevConjuncts = extractConjuncts(prevAllow.condition).map(serializeExpression);
651
+ const curConjuncts = new Set(extractConjuncts(curAllow.condition).map(serializeExpression));
652
+ for (const pc of prevConjuncts) {
653
+ if (!curConjuncts.has(pc)) {
654
+ warnings.push({
655
+ rule: 'RULES_WEAKENED',
656
+ severity: 'warning',
657
+ message: `Predicate removed from ${normalizedPath} allow ${opsLabel}: ${pc}`,
658
+ location: { matchPath: normalizedPath },
659
+ });
660
+ }
661
+ }
662
+ }
663
+ }
664
+ }
665
+ /**
666
+ * Lint Firestore security rules.
667
+ *
668
+ * Contract: if the source doesn't parse, `parseError` is populated and
669
+ * budget checks are skipped — `warnings` will be empty (or contain only
670
+ * source-size which doesn't depend on parsing) and `metrics` fields other
671
+ * than `sourceSize` are zeroed. Callers must check `parseError` first.
672
+ *
673
+ * Pass `options.testCases` to activate test-suite-coupled checks (e.g.
674
+ * REQUEST_TIME_NOT_PINNED). When omitted, the linter behaves exactly as
675
+ * it did before — back-compat with all existing callers.
676
+ */
677
+ export function lintFirestoreRules(source, options = {}) {
678
+ const warnings = [];
679
+ // Pre-parse syntax hints — run on raw source so they fire even when the
680
+ // rules fail to parse. Surface JS-isms (===, ?., ??, backtick strings)
681
+ // that would otherwise produce opaque parse errors.
682
+ warnings.push(...checkSyntaxHints(source));
683
+ // Rule 1: Source size — runs even on unparseable source so a 300KB blob
684
+ // of garbage still surfaces the size error.
685
+ checkSourceSize(source, warnings);
686
+ // Parse AST. On failure, return early with a structured parseError;
687
+ // budget checks intentionally do not run on partial ASTs.
688
+ const parsed = parseToASTOrError(source);
689
+ if (!parsed.ok) {
690
+ return {
691
+ warnings,
692
+ metrics: {
693
+ sourceSize: source.length, functionCount: 0, allowRuleCount: 0,
694
+ maxChainDepth: 0, maxChainOp: '', maxLetBindings: 0, maxLetBindingsFunction: '',
695
+ maxCallDepth: 0, maxEstimatedExpressions: 0, getCallCount: 0,
696
+ },
697
+ parseError: parsed.error,
698
+ };
699
+ }
700
+ const ast = parsed.ast;
701
+ // Collect all functions and rules from the AST
702
+ const allFunctions = collectAllFunctions(ast.service.match);
703
+ const allRules = collectAllRules(ast.service.match);
704
+ // Rule 2: Chain depth
705
+ checkChainDepth(allFunctions, warnings);
706
+ // Rule 3: Let bindings
707
+ checkLetBindings(allFunctions, warnings);
708
+ // Rule 4: Shared gates
709
+ checkSharedGates(allRules, warnings);
710
+ // Rule 5: Expression budget
711
+ checkExpressionBudget(allRules, allFunctions, warnings);
712
+ // Rule 6: Call depth
713
+ checkCallDepth(allRules, allFunctions, warnings);
714
+ // Rule 7: Get count
715
+ checkGetCount(allRules, allFunctions, warnings);
716
+ // Rule 8: Get duplication (same get()-containing function called multiple times)
717
+ checkGetDuplication(allRules, allFunctions, warnings);
718
+ // Rule 9: Hallucinations — JS-style code that parses but fails at runtime
719
+ warnings.push(...checkHallucinations(ast));
720
+ // Rule 9.5: Always-true predicates and recursive-wildcard open rules.
721
+ // Severity: error so deployRules refuses to swap. The agent's #1
722
+ // failure mode in the playground was escaping denials with `if true`.
723
+ checkPermissiveRules(allRules, warnings);
724
+ checkRecursiveWildcardOpen(ast.service.match, warnings);
725
+ // Rule 10: request.time without pinned TestCase.requestTime
726
+ // (Item 0.F deferred follow-up). Only fires when caller passes a test suite.
727
+ if (options.testCases && options.testCases.length > 0) {
728
+ checkRequestTimePinned(allRules, allFunctions, options.testCases, warnings);
729
+ }
730
+ // Rule 11: RULES_WEAKENED — diff against the previously deployed
731
+ // ruleset to catch silently-removed security predicates. Only runs
732
+ // when the caller supplies `previousSource` AND it parses cleanly.
733
+ // A malformed previous ruleset is silently skipped — the current
734
+ // ruleset is still valid and we don't want to fail open.
735
+ if (options.previousSource) {
736
+ const prev = parseToASTOrError(options.previousSource);
737
+ if (prev.ok) {
738
+ checkRulesWeakened(ast.service.match, prev.ast.service.match, warnings);
739
+ }
740
+ }
741
+ // Compute metrics
742
+ let maxChain = { depth: 0, op: '' };
743
+ let maxLets = { count: 0, fn: '' };
744
+ for (const fn of allFunctions) {
745
+ const chain = deepestChain(fn.body);
746
+ if (chain.depth > maxChain.depth)
747
+ maxChain = { depth: chain.depth, op: chain.op };
748
+ if (fn.lets.length > maxLets.count)
749
+ maxLets = { count: fn.lets.length, fn: fn.name };
750
+ }
751
+ const callGraph = buildCallGraph(allFunctions);
752
+ let maxDepth = 0;
753
+ for (const fn of allFunctions) {
754
+ const d = maxCallDepth(fn.name, callGraph);
755
+ if (d > maxDepth)
756
+ maxDepth = d;
757
+ }
758
+ const fnMap = new Map();
759
+ for (const fn of allFunctions)
760
+ fnMap.set(fn.name, fn);
761
+ let maxExprs = 0;
762
+ let maxGets = 0;
763
+ for (const r of allRules) {
764
+ const gets = countGetCalls(r.rule.condition, fnMap);
765
+ if (gets > maxGets)
766
+ maxGets = gets;
767
+ }
768
+ return {
769
+ warnings,
770
+ metrics: {
771
+ sourceSize: source.length,
772
+ functionCount: allFunctions.length,
773
+ allowRuleCount: allRules.length,
774
+ maxChainDepth: maxChain.depth,
775
+ maxChainOp: maxChain.op,
776
+ maxLetBindings: maxLets.count,
777
+ maxLetBindingsFunction: maxLets.fn,
778
+ maxCallDepth: maxDepth,
779
+ maxEstimatedExpressions: maxExprs,
780
+ getCallCount: maxGets,
781
+ },
782
+ };
783
+ }
784
+ //# sourceMappingURL=linter.js.map