dreamcontext 0.5.0

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 (247) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +523 -0
  3. package/agents/dreamcontext-explore.md +137 -0
  4. package/agents/dreamcontext-initializer.md +169 -0
  5. package/agents/sleep-product.md +268 -0
  6. package/agents/sleep-state.md +270 -0
  7. package/agents/sleep-tasks.md +134 -0
  8. package/dist/agents/dreamcontext-explore.md +137 -0
  9. package/dist/agents/dreamcontext-initializer.md +169 -0
  10. package/dist/agents/sleep-product.md +268 -0
  11. package/dist/agents/sleep-state.md +270 -0
  12. package/dist/agents/sleep-tasks.md +134 -0
  13. package/dist/dashboard/assets/BrainCanvas3D-BLJ4_SqE.js +5126 -0
  14. package/dist/dashboard/assets/_baseUniq-DpaDAx_H.js +1 -0
  15. package/dist/dashboard/assets/arc-JvK3Ik1p.js +1 -0
  16. package/dist/dashboard/assets/architectureDiagram-Q4EWVU46-CCvw4XFg.js +36 -0
  17. package/dist/dashboard/assets/blockDiagram-DXYQGD6D-DMobz1n7.js +132 -0
  18. package/dist/dashboard/assets/c4Diagram-AHTNJAMY-FwcHT5er.js +10 -0
  19. package/dist/dashboard/assets/channel-D6954IHZ.js +1 -0
  20. package/dist/dashboard/assets/chunk-4BX2VUAB-B5kYwmBa.js +1 -0
  21. package/dist/dashboard/assets/chunk-4TB4RGXK-0ot1eS0J.js +206 -0
  22. package/dist/dashboard/assets/chunk-55IACEB6-24ngcLgH.js +1 -0
  23. package/dist/dashboard/assets/chunk-EDXVE4YY-DATt1OUl.js +1 -0
  24. package/dist/dashboard/assets/chunk-FMBD7UC4-BprbGSJw.js +15 -0
  25. package/dist/dashboard/assets/chunk-OYMX7WX6-CJJhpKWP.js +231 -0
  26. package/dist/dashboard/assets/chunk-QZHKN3VN-Cisp65Vq.js +1 -0
  27. package/dist/dashboard/assets/chunk-YZCP3GAM-DtMk33tU.js +1 -0
  28. package/dist/dashboard/assets/classDiagram-6PBFFD2Q-Bk4KDqBj.js +1 -0
  29. package/dist/dashboard/assets/classDiagram-v2-HSJHXN6E-Bk4KDqBj.js +1 -0
  30. package/dist/dashboard/assets/clone-C9Yhti5q.js +1 -0
  31. package/dist/dashboard/assets/cose-bilkent-S5V4N54A-BxYomDLe.js +1 -0
  32. package/dist/dashboard/assets/cytoscape.esm-D_LviqZs.js +331 -0
  33. package/dist/dashboard/assets/dagre-KV5264BT-CsX1ZayG.js +4 -0
  34. package/dist/dashboard/assets/defaultLocale-DX6XiGOO.js +1 -0
  35. package/dist/dashboard/assets/diagram-5BDNPKRD-B2G4mPPw.js +10 -0
  36. package/dist/dashboard/assets/diagram-G4DWMVQ6-C8nxN9ZB.js +24 -0
  37. package/dist/dashboard/assets/diagram-MMDJMWI5-DaYymOrR.js +43 -0
  38. package/dist/dashboard/assets/diagram-TYMM5635-BpiYFv-I.js +24 -0
  39. package/dist/dashboard/assets/erDiagram-SMLLAGMA-C6pE7F61.js +85 -0
  40. package/dist/dashboard/assets/flowDiagram-DWJPFMVM-jdNEPVFq.js +162 -0
  41. package/dist/dashboard/assets/ganttDiagram-T4ZO3ILL-C8GoRj1C.js +292 -0
  42. package/dist/dashboard/assets/gitGraphDiagram-UUTBAWPF-SiRn7RJ8.js +106 -0
  43. package/dist/dashboard/assets/graph-9wbTW7ld.js +1 -0
  44. package/dist/dashboard/assets/index-BHp63EMw.js +475 -0
  45. package/dist/dashboard/assets/index-CdnDt_7U.css +1 -0
  46. package/dist/dashboard/assets/infoDiagram-42DDH7IO-DcDC8M1a.js +2 -0
  47. package/dist/dashboard/assets/ishikawaDiagram-UXIWVN3A-UjyrPeaS.js +70 -0
  48. package/dist/dashboard/assets/journeyDiagram-VCZTEJTY-CXJPYMxN.js +139 -0
  49. package/dist/dashboard/assets/kanban-definition-6JOO6SKY-Cm1n9eat.js +89 -0
  50. package/dist/dashboard/assets/katex-DkKDou_j.js +257 -0
  51. package/dist/dashboard/assets/layout-w8zmQGXp.js +1 -0
  52. package/dist/dashboard/assets/linear-CMNvIisH.js +1 -0
  53. package/dist/dashboard/assets/min-BqXwiqEr.js +1 -0
  54. package/dist/dashboard/assets/mindmap-definition-QFDTVHPH-tksxnjhx.js +96 -0
  55. package/dist/dashboard/assets/pieDiagram-DEJITSTG-lIVvnPyq.js +30 -0
  56. package/dist/dashboard/assets/quadrantDiagram-34T5L4WZ-DSMB57t5.js +7 -0
  57. package/dist/dashboard/assets/requirementDiagram-MS252O5E-NG99tgmc.js +84 -0
  58. package/dist/dashboard/assets/sankeyDiagram-XADWPNL6-C6EkbQKo.js +10 -0
  59. package/dist/dashboard/assets/sequenceDiagram-FGHM5R23-ASU7Zp6_.js +157 -0
  60. package/dist/dashboard/assets/stateDiagram-FHFEXIEX-DHklUzce.js +1 -0
  61. package/dist/dashboard/assets/stateDiagram-v2-QKLJ7IA2-BZXFb2Fh.js +1 -0
  62. package/dist/dashboard/assets/timeline-definition-GMOUNBTQ-B37xNhjS.js +120 -0
  63. package/dist/dashboard/assets/vennDiagram-DHZGUBPP-D28OvWbm.js +34 -0
  64. package/dist/dashboard/assets/wardley-RL74JXVD-BQdaLyVb.js +162 -0
  65. package/dist/dashboard/assets/wardleyDiagram-NUSXRM2D-D0vChrnT.js +20 -0
  66. package/dist/dashboard/assets/xychartDiagram-5P7HB3ND-BzSx7EpJ.js +7 -0
  67. package/dist/dashboard/favicon.svg +14 -0
  68. package/dist/dashboard/index.html +18 -0
  69. package/dist/hooks/marketing-binary-guard.sh +18 -0
  70. package/dist/index.js +15881 -0
  71. package/dist/skill-packs/agents/biv-customer-analyst.md +140 -0
  72. package/dist/skill-packs/agents/biv-decision-gate.md +147 -0
  73. package/dist/skill-packs/agents/biv-financial-analyst.md +128 -0
  74. package/dist/skill-packs/agents/biv-market-analyst.md +103 -0
  75. package/dist/skill-packs/agents/biv-researcher.md +140 -0
  76. package/dist/skill-packs/agents/biv-strategist.md +164 -0
  77. package/dist/skill-packs/agents/council-persona.md +142 -0
  78. package/dist/skill-packs/agents/council-synthesizer.md +208 -0
  79. package/dist/skill-packs/agents/discover-brand.md +216 -0
  80. package/dist/skill-packs/agents/goal-implementer.md +70 -0
  81. package/dist/skill-packs/agents/goal-plan-reviewer.md +68 -0
  82. package/dist/skill-packs/agents/goal-planner.md +75 -0
  83. package/dist/skill-packs/agents/goal-validator.md +68 -0
  84. package/dist/skill-packs/agents/marketing-creative.md +85 -0
  85. package/dist/skill-packs/agents/marketing-monitor.md +143 -0
  86. package/dist/skill-packs/agents/marketing-strategy.md +139 -0
  87. package/dist/skill-packs/agents/review-cloud-functions.md +158 -0
  88. package/dist/skill-packs/agents/review-edge-cases.md +147 -0
  89. package/dist/skill-packs/agents/review-frontend.md +134 -0
  90. package/dist/skill-packs/agents/review-router.md +165 -0
  91. package/dist/skill-packs/agents/review-security.md +139 -0
  92. package/dist/skill-packs/agents/reviewer.md +152 -0
  93. package/dist/skill-packs/brand-voice/SKILL.md +115 -0
  94. package/dist/skill-packs/brand-voice/discover-brand.md +126 -0
  95. package/dist/skill-packs/brand-voice/guideline-generation.md +154 -0
  96. package/dist/skill-packs/brand-voice/references/before-after-examples.md +194 -0
  97. package/dist/skill-packs/brand-voice/references/confidence-scoring.md +128 -0
  98. package/dist/skill-packs/brand-voice/references/guideline-template.md +241 -0
  99. package/dist/skill-packs/brand-voice/references/search-strategies.md +271 -0
  100. package/dist/skill-packs/brand-voice/references/source-ranking.md +248 -0
  101. package/dist/skill-packs/brand-voice/references/voice-constant-tone-flexes.md +115 -0
  102. package/dist/skill-packs/business-idea-discovery/SKILL.md +452 -0
  103. package/dist/skill-packs/business-idea-validation/SKILL.md +209 -0
  104. package/dist/skill-packs/business-idea-validation/stage-definitions.md +658 -0
  105. package/dist/skill-packs/catalog.json +657 -0
  106. package/dist/skill-packs/council/SKILL.md +134 -0
  107. package/dist/skill-packs/council/debate-protocol.md +90 -0
  108. package/dist/skill-packs/design/SKILL.md +301 -0
  109. package/dist/skill-packs/design/design-mobile.md +207 -0
  110. package/dist/skill-packs/design/design-web.md +148 -0
  111. package/dist/skill-packs/design/frontend-principles.md +157 -0
  112. package/dist/skill-packs/design/onboarding-design.md +230 -0
  113. package/dist/skill-packs/engineering/SKILL.md +155 -0
  114. package/dist/skill-packs/engineering/backend-principles.md +233 -0
  115. package/dist/skill-packs/engineering/firebase-cloud-functions/SKILL.md +44 -0
  116. package/dist/skill-packs/engineering/firebase-cloud-functions/references/gen_comparison.md +45 -0
  117. package/dist/skill-packs/engineering/firebase-cloud-functions/references/idempotency.md +145 -0
  118. package/dist/skill-packs/engineering/firebase-cloud-functions/references/local_testing.md +218 -0
  119. package/dist/skill-packs/engineering/firebase-cloud-functions/references/scaling.md +128 -0
  120. package/dist/skill-packs/engineering/firebase-cloud-functions/references/secrets.md +70 -0
  121. package/dist/skill-packs/engineering/firebase-cloud-functions/references/triggers_and_deployment.md +139 -0
  122. package/dist/skill-packs/engineering/firebase-firestore/SKILL.md +50 -0
  123. package/dist/skill-packs/engineering/firebase-firestore/references/indexes.md +96 -0
  124. package/dist/skill-packs/engineering/firebase-firestore/references/provisioning.md +101 -0
  125. package/dist/skill-packs/engineering/firebase-firestore/references/query_mechanics.md +182 -0
  126. package/dist/skill-packs/engineering/firebase-firestore/references/security_rules.md +299 -0
  127. package/dist/skill-packs/engineering/firebase-firestore/references/web_sdk_usage.md +265 -0
  128. package/dist/skill-packs/engineering/web-app-frontend.md +187 -0
  129. package/dist/skill-packs/goal-skill/SKILL.md +203 -0
  130. package/dist/skill-packs/growth/SKILL.md +480 -0
  131. package/dist/skill-packs/growth/lean-analytics-experiments.md +341 -0
  132. package/dist/skill-packs/growth/lean-analytics-metrics.md +295 -0
  133. package/dist/skill-packs/growth/performance-marketing.md +337 -0
  134. package/dist/skill-packs/meta-marketing/SKILL.md +423 -0
  135. package/dist/skill-packs/meta-marketing/account-ops.md +190 -0
  136. package/dist/skill-packs/meta-marketing/api-reference.md +535 -0
  137. package/dist/skill-packs/meta-marketing/copy-formulas.md +123 -0
  138. package/dist/skill-packs/meta-marketing/council-personas/creative-director.md +76 -0
  139. package/dist/skill-packs/meta-marketing/council-personas/performance-monitor.md +71 -0
  140. package/dist/skill-packs/meta-marketing/council-personas/risk-officer.md +79 -0
  141. package/dist/skill-packs/meta-marketing/council-personas/strategy-optimizer.md +76 -0
  142. package/dist/skill-packs/meta-marketing/creative-frameworks.md +176 -0
  143. package/dist/skill-packs/meta-marketing/mistakes.md +154 -0
  144. package/dist/skill-packs/meta-marketing/platform-state.md +63 -0
  145. package/dist/skill-packs/multi-review/REVIEWER_SHARED.md +143 -0
  146. package/dist/skill-packs/multi-review/SKILL.md +182 -0
  147. package/dist/skill-packs/system-prompts/SKILL.md +472 -0
  148. package/dist/templates/AGENTS.md +84 -0
  149. package/dist/templates/CLAUDE.md +84 -0
  150. package/dist/templates/council-debate.md +20 -0
  151. package/dist/templates/council-final-report.md +34 -0
  152. package/dist/templates/council-persona.md +10 -0
  153. package/dist/templates/council-report.md +6 -0
  154. package/dist/templates/feature.md +38 -0
  155. package/dist/templates/init/0.soul.md +33 -0
  156. package/dist/templates/init/1.user.md +29 -0
  157. package/dist/templates/init/2.memory.md +21 -0
  158. package/dist/templates/init/3.style_guide_and_branding.md +18 -0
  159. package/dist/templates/init/4.tech_stack.md +22 -0
  160. package/dist/templates/init/CHANGELOG.json +1 -0
  161. package/dist/templates/init/RELEASES.json +1 -0
  162. package/dist/templates/init/data-structures/default.md +35 -0
  163. package/dist/templates/knowledge.md +10 -0
  164. package/dist/templates/obsidian/app.json +15 -0
  165. package/dist/templates/obsidian/appearance.json +4 -0
  166. package/dist/templates/obsidian/graph.json +58 -0
  167. package/dist/templates/task.md +70 -0
  168. package/install.sh +73 -0
  169. package/package.json +58 -0
  170. package/skill/SKILL.md +529 -0
  171. package/skill-packs/agents/biv-customer-analyst.md +140 -0
  172. package/skill-packs/agents/biv-decision-gate.md +147 -0
  173. package/skill-packs/agents/biv-financial-analyst.md +128 -0
  174. package/skill-packs/agents/biv-market-analyst.md +103 -0
  175. package/skill-packs/agents/biv-researcher.md +140 -0
  176. package/skill-packs/agents/biv-strategist.md +164 -0
  177. package/skill-packs/agents/council-persona.md +142 -0
  178. package/skill-packs/agents/council-synthesizer.md +208 -0
  179. package/skill-packs/agents/discover-brand.md +216 -0
  180. package/skill-packs/agents/goal-implementer.md +70 -0
  181. package/skill-packs/agents/goal-plan-reviewer.md +68 -0
  182. package/skill-packs/agents/goal-planner.md +75 -0
  183. package/skill-packs/agents/goal-validator.md +68 -0
  184. package/skill-packs/agents/marketing-creative.md +85 -0
  185. package/skill-packs/agents/marketing-monitor.md +143 -0
  186. package/skill-packs/agents/marketing-strategy.md +139 -0
  187. package/skill-packs/agents/review-cloud-functions.md +158 -0
  188. package/skill-packs/agents/review-edge-cases.md +147 -0
  189. package/skill-packs/agents/review-frontend.md +134 -0
  190. package/skill-packs/agents/review-router.md +165 -0
  191. package/skill-packs/agents/review-security.md +139 -0
  192. package/skill-packs/agents/reviewer.md +152 -0
  193. package/skill-packs/brand-voice/SKILL.md +115 -0
  194. package/skill-packs/brand-voice/discover-brand.md +126 -0
  195. package/skill-packs/brand-voice/guideline-generation.md +154 -0
  196. package/skill-packs/brand-voice/references/before-after-examples.md +194 -0
  197. package/skill-packs/brand-voice/references/confidence-scoring.md +128 -0
  198. package/skill-packs/brand-voice/references/guideline-template.md +241 -0
  199. package/skill-packs/brand-voice/references/search-strategies.md +271 -0
  200. package/skill-packs/brand-voice/references/source-ranking.md +248 -0
  201. package/skill-packs/brand-voice/references/voice-constant-tone-flexes.md +115 -0
  202. package/skill-packs/business-idea-discovery/SKILL.md +452 -0
  203. package/skill-packs/business-idea-validation/SKILL.md +209 -0
  204. package/skill-packs/business-idea-validation/stage-definitions.md +658 -0
  205. package/skill-packs/catalog.json +657 -0
  206. package/skill-packs/council/SKILL.md +134 -0
  207. package/skill-packs/council/debate-protocol.md +90 -0
  208. package/skill-packs/design/SKILL.md +301 -0
  209. package/skill-packs/design/design-mobile.md +207 -0
  210. package/skill-packs/design/design-web.md +148 -0
  211. package/skill-packs/design/frontend-principles.md +157 -0
  212. package/skill-packs/design/onboarding-design.md +230 -0
  213. package/skill-packs/engineering/SKILL.md +155 -0
  214. package/skill-packs/engineering/backend-principles.md +233 -0
  215. package/skill-packs/engineering/firebase-cloud-functions/SKILL.md +44 -0
  216. package/skill-packs/engineering/firebase-cloud-functions/references/gen_comparison.md +45 -0
  217. package/skill-packs/engineering/firebase-cloud-functions/references/idempotency.md +145 -0
  218. package/skill-packs/engineering/firebase-cloud-functions/references/local_testing.md +218 -0
  219. package/skill-packs/engineering/firebase-cloud-functions/references/scaling.md +128 -0
  220. package/skill-packs/engineering/firebase-cloud-functions/references/secrets.md +70 -0
  221. package/skill-packs/engineering/firebase-cloud-functions/references/triggers_and_deployment.md +139 -0
  222. package/skill-packs/engineering/firebase-firestore/SKILL.md +50 -0
  223. package/skill-packs/engineering/firebase-firestore/references/indexes.md +96 -0
  224. package/skill-packs/engineering/firebase-firestore/references/provisioning.md +101 -0
  225. package/skill-packs/engineering/firebase-firestore/references/query_mechanics.md +182 -0
  226. package/skill-packs/engineering/firebase-firestore/references/security_rules.md +299 -0
  227. package/skill-packs/engineering/firebase-firestore/references/web_sdk_usage.md +265 -0
  228. package/skill-packs/engineering/web-app-frontend.md +187 -0
  229. package/skill-packs/goal-skill/SKILL.md +203 -0
  230. package/skill-packs/growth/SKILL.md +480 -0
  231. package/skill-packs/growth/lean-analytics-experiments.md +341 -0
  232. package/skill-packs/growth/lean-analytics-metrics.md +295 -0
  233. package/skill-packs/growth/performance-marketing.md +337 -0
  234. package/skill-packs/meta-marketing/SKILL.md +423 -0
  235. package/skill-packs/meta-marketing/account-ops.md +190 -0
  236. package/skill-packs/meta-marketing/api-reference.md +535 -0
  237. package/skill-packs/meta-marketing/copy-formulas.md +123 -0
  238. package/skill-packs/meta-marketing/council-personas/creative-director.md +76 -0
  239. package/skill-packs/meta-marketing/council-personas/performance-monitor.md +71 -0
  240. package/skill-packs/meta-marketing/council-personas/risk-officer.md +79 -0
  241. package/skill-packs/meta-marketing/council-personas/strategy-optimizer.md +76 -0
  242. package/skill-packs/meta-marketing/creative-frameworks.md +176 -0
  243. package/skill-packs/meta-marketing/mistakes.md +154 -0
  244. package/skill-packs/meta-marketing/platform-state.md +63 -0
  245. package/skill-packs/multi-review/REVIEWER_SHARED.md +143 -0
  246. package/skill-packs/multi-review/SKILL.md +182 -0
  247. package/skill-packs/system-prompts/SKILL.md +472 -0
@@ -0,0 +1,299 @@
1
+ # Firestore Security Rules Structure
2
+
3
+ Security rules determine who has read and write access to your database.
4
+
5
+ ## Service and Database Declaration
6
+
7
+ All Firestore rules begin with the service declaration and a match block for the database (usually default).
8
+
9
+ ```
10
+ rules_version = '2';
11
+
12
+ service cloud.firestore {
13
+ match /databases/{database}/documents {
14
+ // Rules go here
15
+ // {database} wildcard represents the database name
16
+ }
17
+ }
18
+ ```
19
+
20
+ ## Basic Read/Write Operations
21
+
22
+ Rules describe **conditions** that must be true to allow an operation.
23
+
24
+ ```
25
+ match /cities/{city} {
26
+ allow read: if <condition>;
27
+ allow write: if <condition>;
28
+ }
29
+ ```
30
+
31
+ ## Common Patterns
32
+
33
+ ### Locked Mode (Deny All)
34
+ Good for starting development or private data.
35
+ ```
36
+ match /{document=**} {
37
+ allow read, write: if false;
38
+ }
39
+ ```
40
+
41
+ ### Test Mode (Allow All)
42
+ **WARNING: insecure.** Only for quick prototyping. Unsafe to deploy for production apps.
43
+ ```
44
+ match /{document=**} {
45
+ allow read, write: if true;
46
+ }
47
+ ```
48
+
49
+ ### Auth Required
50
+ Allow access only to authenticated users. This allows any logged in user access to all data.
51
+ ```
52
+ match /{document=**} {
53
+ allow read, write: if request.auth != null;
54
+ }
55
+ ```
56
+
57
+ ### User-Specific Data
58
+ Allow users to access only their own data.
59
+ ```
60
+ match /users/{userId} {
61
+ allow read, write: if request.auth != null && request.auth.uid == userId;
62
+ }
63
+ ```
64
+
65
+ ### Allow only verified emails
66
+ Requires users to verify ownership of the email address before using it to read or write data
67
+ ```
68
+ // Allow access based on email domain
69
+ match /some_collection/{document} {
70
+ allow read: if request.auth != null
71
+ && request.auth.email_verified
72
+ && request.auth.email.endsWith('@example.com');
73
+ }
74
+ ```
75
+
76
+ ### Validate data in write operations
77
+ ```
78
+ // Example for creating a user profile
79
+ match /users/{userId} {
80
+ allow create: if request.auth.uid == userId &&
81
+ request.resource.data.email is string &&
82
+ request.resource.data.createdAt == request.time;
83
+ }
84
+ ```
85
+
86
+ ### Granular Operations
87
+
88
+ You can break down `read` and `write` into more specific operations:
89
+
90
+ * **read**
91
+ * `get`: Retrieval of a single document.
92
+ * `list`: Queries and collection reads.
93
+ * **write**
94
+ * `create`: Writing to a nonexistent document.
95
+ * `update`: Writing to an existing document.
96
+ * `delete`: Removing a document.
97
+
98
+ ```firestore
99
+ match /cities/{city} {
100
+ allow get: if <condition>;
101
+ allow list: if <condition>;
102
+ allow create: if <condition>;
103
+ allow update: if <condition>;
104
+ allow delete: if <condition>;
105
+ }
106
+ ```
107
+
108
+ ## Hierarchical Data
109
+
110
+ Rules applied to a parent collection **do not** cascade to subcollections. You must explicitly match subcollections.
111
+
112
+ ### Nested Match Statements
113
+
114
+ Inner matches are relative to the outer match path.
115
+
116
+ ```firestore
117
+ match /cities/{city} {
118
+ allow read, write: if <condition>;
119
+
120
+ // Explicitly match the subcollection 'landmarks'
121
+ match /landmarks/{landmark} {
122
+ allow read, write: if <condition>;
123
+ }
124
+ }
125
+ ```
126
+
127
+ ### Recursive Wildcards (`{name=**}`)
128
+
129
+ Use recursive wildcards to apply rules to an arbitrarily deep hierarchy.
130
+
131
+ * **Version 2** (recommended): `{path=**}` matches zero or more path segments.
132
+
133
+ ```firestore
134
+ // Allow read access to ANY document in the 'cities' collection or its subcollections
135
+ match /cities/{document=**} {
136
+ allow read: if true;
137
+ }
138
+ ```
139
+
140
+ ## Controlling Field Access
141
+
142
+ ### Read Limitations
143
+
144
+ Reads in Firestore are **document-level**. You cannot retrieve a partial document.
145
+ * **Allowed**: Read the entire document.
146
+ * **Denied**: logical failure, no data returned.
147
+
148
+ To secure specific fields (e.g., private user data), you must **split them into a separate document** (e.g., a `private` subcollection).
149
+
150
+ ### Write Restrictions
151
+
152
+ You can strictly control which fields can be written or updated.
153
+
154
+ #### On Creation
155
+ Use `request.resource.data.keys()` to validate fields.
156
+
157
+ ```firestore
158
+ match /restaurant/{restId} {
159
+ allow create: if request.resource.data.keys().hasAll(['name', 'location']) &&
160
+ request.resource.data.keys().hasOnly(['name', 'location', 'city', 'address']);
161
+ }
162
+ ```
163
+
164
+ #### On Update
165
+ Use `diff()` to see what changed between the existing document (`resource.data`) and the incoming data (`request.resource.data`).
166
+
167
+ ```firestore
168
+ match /restaurant/{restId} {
169
+ allow update: if request.resource.data.diff(resource.data).affectedKeys()
170
+ .hasOnly(['name', 'location', 'city']); // Prevent others from changing
171
+ }
172
+ ```
173
+
174
+ ### Enforcing Field Types
175
+ Use the `is` operator to validate data types.
176
+
177
+ ```firestore
178
+ allow create: if request.resource.data.score is int &&
179
+ request.resource.data.active is bool &&
180
+ request.resource.data.tags is list;
181
+ ```
182
+
183
+ ## Understanding Rule Evaluation
184
+
185
+ ### Overlapping Matches -> OR Logic
186
+
187
+ If a document matches more than one rule statement, access is allowed if **ANY** of the matching rules allow it.
188
+
189
+ ```firestore
190
+ // Document: /cities/SF
191
+
192
+ match /cities/{city} {
193
+ allow read: if false; // Deny
194
+ }
195
+
196
+ match /cities/{document=**} {
197
+ allow read: if true; // Allow
198
+ }
199
+
200
+ // Result: ALLOWED (because one rule returned true)
201
+ ```
202
+
203
+ ## Common Limits
204
+
205
+ * **Call Depth**: Maximum call depth for custom functions is 20.
206
+ * **Document Access**:
207
+ * 10 access calls for single-doc requests/queries.
208
+ * 20 access calls for multi-doc reads/transactions/batches.
209
+ * **Size**: Ruleset source max 256 KB. Compiled max 250 KB.
210
+
211
+ ## Deploying
212
+
213
+ ```bash
214
+ firebase deploy --only firestore:rules
215
+ ```
216
+
217
+ ## Security Rules Development Workflow
218
+
219
+ For complex applications, follow this structured 6-phase workflow to ensure your rules are secure and comprehensive.
220
+
221
+ ### Phase 1: Codebase Analysis
222
+
223
+ Before writing rules, scan your codebase to identify:
224
+ 1. **Collections & Paths**: List all collections and document structures.
225
+ 2. **Data Models**: Define required fields, data types, and constraints (e.g., string length, regex patterns).
226
+ 3. **Access Patterns**: Document who can read/write what and under what conditions (e.g., exact ownership, role-based).
227
+ 4. **Authentication**: Identify if you use Firebase Auth, anonymous auth, or custom tokens.
228
+
229
+ ### Phase 2: Security Rules Generation
230
+
231
+ Write your rules following these core principles:
232
+ * **Default Deny**: Start with `allow read, write: if false;` and whitelist specific operations.
233
+ * **Least Privilege**: Grant only the minimum permissions required.
234
+ * **Validate Data**: Check types (e.g., `is string`), required fields, and values on `create` and `update`.
235
+ * **UID Protection**: Ensure users cannot create documents with another user's UID or change ownership.
236
+
237
+ #### Recommended Structure
238
+
239
+ It is helpful to define a `User` type or similar helper functions at the top of your rules file.
240
+
241
+ ```javascript
242
+ // Helper Functions
243
+ function isAuthenticated() {
244
+ return request.auth != null;
245
+ }
246
+
247
+ function isOwner(userId) {
248
+ return isAuthenticated() && request.auth.uid == userId;
249
+ }
250
+
251
+ // Validate data types and required fields
252
+ function isValidUser() {
253
+ let user = request.resource.data;
254
+ return user.keys().hasAll(['name', 'email', 'createdAt']) &&
255
+ user.name is string && user.name.size() > 0 &&
256
+ user.email is string && user.email.matches('.+@.+\\..+') &&
257
+ user.createdAt is timestamp;
258
+ }
259
+
260
+ // Prevent UID tampering
261
+ function isUidUnchanged() {
262
+ return request.resource.data.uid == resource.data.uid;
263
+ }
264
+ ```
265
+
266
+ ### Phase 3: Devil's Advocate Attack
267
+
268
+ Attempt to mentally "break" your rules by checking for common vulnerabilities:
269
+ 1. Can I read data I shouldn't?
270
+ 2. Can I create a document with someone else's UID?
271
+ 3. Can I update a document and steal ownership (change the `uid` field)?
272
+ 4. Can I send a massive string to a field with no length limit?
273
+ 5. Can I delete a document I don't own?
274
+ 6. Can I bypass validation by sending `null` or missing fields?
275
+
276
+ If *any* of these succeed, fix the rule and repeat.
277
+
278
+ ### Phase 4: Syntactic Validation
279
+
280
+ Use `firebase deploy --only firestore:rules --dry-run` to validate syntax.
281
+
282
+ ### Phase 5: Test Suite Generation
283
+
284
+ Create a comprehensive test suite using `@firebase/rules-unit-testing`. Ideally, create a dedicated `rules_test/` directory.
285
+
286
+ **Test Coverage Checklist:**
287
+ * [ ] **Authorized Operations**: Users *can* do what they are supposed to.
288
+ * [ ] **Unauthorized Operations**: Users *cannot* do what is forbidden.
289
+ * [ ] **UID Tampering**: Users cannot create/update data with another's UID.
290
+ * [ ] **Data Validation**: Invalid types, missing fields, or malformed data (bad emails, URLs) must fail.
291
+ * [ ] **Immutable Fields**: Fields like `createdAt` or `authorId` cannot be changed on update.
292
+
293
+ ### Phase 6: Test Validation Loop
294
+
295
+ 1. Start the emulator: `firebase emulators:start --only firestore`
296
+ 2. Run tests: `npm test` (inside your test directory)
297
+ 3. If tests fail due to **rules**: Fix the rules.
298
+ 4. If tests fail due to **test bugs**: Fix the tests.
299
+ 5. Repeat until 100% pass rate.
@@ -0,0 +1,265 @@
1
+ # Firestore Web SDK Usage Guide
2
+
3
+ This guide focuses on the **Modular Web SDK** (v9+), which is tree-shakeable and efficient.
4
+
5
+ ## Initialization
6
+
7
+ ```javascript
8
+ import { initializeApp } from "firebase/app";
9
+ import { getFirestore } from "firebase/firestore";
10
+
11
+ // If running in Firebase App Hosting, you can skip Firebase Config and instead use:
12
+ // const app = initializeApp();
13
+
14
+ const firebaseConfig = {
15
+ // Your config options. Get the values by running 'firebase apps:sdkconfig <platform> <app-id>'
16
+ };
17
+
18
+ const app = initializeApp(firebaseConfig);
19
+ const db = getFirestore(app);
20
+
21
+ ```
22
+
23
+ ## Writing Data
24
+
25
+ ### Set a Document (`setDoc`)
26
+ Creates a document if it doesn't exist, or overwrites it if it does.
27
+
28
+ ```javascript
29
+ import { doc, setDoc } from "firebase/firestore";
30
+
31
+ // Create/Overwrite document with ID "LA"
32
+ await setDoc(doc(db, "cities", "LA"), {
33
+ name: "Los Angeles",
34
+ state: "CA",
35
+ country: "USA"
36
+ });
37
+
38
+ // To merge with existing data instead of overwriting:
39
+ await setDoc(doc(db, "cities", "LA"), { population: 3900000 }, { merge: true });
40
+ ```
41
+
42
+ ### Add a Document with Auto-ID (`addDoc`)
43
+ Use when you don't care about the document ID.
44
+
45
+ ```javascript
46
+ import { collection, addDoc } from "firebase/firestore";
47
+
48
+ const docRef = await addDoc(collection(db, "cities"), {
49
+ name: "Tokyo",
50
+ country: "Japan"
51
+ });
52
+ console.log("Document written with ID: ", docRef.id);
53
+ ```
54
+
55
+ ### Update a Document (`updateDoc`)
56
+ Update some fields of an existing document without overwriting the entire document. Fails if the document doesn't exist.
57
+
58
+ ```javascript
59
+ import { doc, updateDoc } from "firebase/firestore";
60
+
61
+ const laRef = doc(db, "cities", "LA");
62
+
63
+ await updateDoc(laRef, {
64
+ capital: true
65
+ });
66
+ ```
67
+
68
+ ### Transactions
69
+ Perform an atomic read-modify-write operation.
70
+
71
+ ```javascript
72
+ import { runTransaction, doc } from "firebase/firestore";
73
+
74
+ const sfDocRef = doc(db, "cities", "SF");
75
+
76
+ try {
77
+ await runTransaction(db, async (transaction) => {
78
+ const sfDoc = await transaction.get(sfDocRef);
79
+ if (!sfDoc.exists()) {
80
+ throw "Document does not exist!";
81
+ }
82
+
83
+ const newPopulation = sfDoc.data().population + 1;
84
+ transaction.update(sfDocRef, { population: newPopulation });
85
+ });
86
+ console.log("Transaction successfully committed!");
87
+ } catch (e) {
88
+ console.log("Transaction failed: ", e);
89
+ }
90
+ ```
91
+
92
+ ## Reading Data
93
+
94
+ ### Get a Single Document (`getDoc`)
95
+
96
+ ```javascript
97
+ import { doc, getDoc } from "firebase/firestore";
98
+
99
+ const docRef = doc(db, "cities", "SF");
100
+ const docSnap = await getDoc(docRef);
101
+
102
+ if (docSnap.exists()) {
103
+ console.log("Document data:", docSnap.data());
104
+ } else {
105
+ console.log("No such document!");
106
+ }
107
+ ```
108
+
109
+ ### Get Multiple Documents (`getDocs`)
110
+ Fetches all documents in a query or collection once.
111
+
112
+ ```javascript
113
+ import { collection, getDocs } from "firebase/firestore";
114
+
115
+ const querySnapshot = await getDocs(collection(db, "cities"));
116
+ querySnapshot.forEach((doc) => {
117
+ // doc.data() is never undefined for query doc snapshots
118
+ console.log(doc.id, " => ", doc.data());
119
+ });
120
+ ```
121
+
122
+ ## Realtime Updates
123
+
124
+ ### Listen to a Document/Query (`onSnapshot`)
125
+
126
+ ```javascript
127
+ import { doc, onSnapshot } from "firebase/firestore";
128
+
129
+ const unsub = onSnapshot(doc(db, "cities", "SF"), (doc) => {
130
+ console.log("Current data: ", doc.data());
131
+ });
132
+
133
+ // Stop listening
134
+ // unsub();
135
+ ```
136
+
137
+ ### Handle Changes (Added/Modified/Removed)
138
+
139
+ ```javascript
140
+ import { collection, query, where, onSnapshot } from "firebase/firestore";
141
+
142
+ const q = query(collection(db, "cities"), where("state", "==", "CA"));
143
+ const unsubscribe = onSnapshot(q, (snapshot) => {
144
+ snapshot.docChanges().forEach((change) => {
145
+ if (change.type === "added") {
146
+ console.log("New city: ", change.doc.data());
147
+ }
148
+ if (change.type === "modified") {
149
+ console.log("Modified city: ", change.doc.data());
150
+ }
151
+ if (change.type === "removed") {
152
+ console.log("Removed city: ", change.doc.data());
153
+ }
154
+ });
155
+ });
156
+ ```
157
+
158
+ ## Queries
159
+
160
+ ### Simple and Compound Queries
161
+ Use `query()` to combine filters.
162
+
163
+ ```javascript
164
+ import { collection, query, where, getDocs } from "firebase/firestore";
165
+
166
+ const citiesRef = collection(db, "cities");
167
+
168
+ // Simple equality
169
+ const q1 = query(citiesRef, where("state", "==", "CA"));
170
+
171
+ // Compound (AND)
172
+ // Note: Requires an index if filtering on different fields
173
+ const q2 = query(citiesRef, where("state", "==", "CA"), where("population", ">", 1000000));
174
+ ```
175
+
176
+ ### OR Queries
177
+ ```javascript
178
+ import { or } from "firebase/firestore";
179
+
180
+ const q = query(citiesRef, or(
181
+ where("capital", "==", true),
182
+ where("population", ">=", 1000000)
183
+ ));
184
+ ```
185
+ Max 30 disjunctions (DNF form). Cannot combine `not-in` with `in`/`array-contains-any`/`or`.
186
+
187
+ ### Collection Group Queries
188
+ Query across ALL subcollections with the same name.
189
+ ```javascript
190
+ import { collectionGroup } from "firebase/firestore";
191
+ const q = query(collectionGroup(db, "landmarks"), where("type", "==", "museum"));
192
+ ```
193
+
194
+ ### Order and Limit
195
+ Sort and limit results.
196
+
197
+ ```javascript
198
+ import { orderBy, limit } from "firebase/firestore";
199
+
200
+ const q = query(citiesRef, orderBy("name"), limit(3));
201
+ ```
202
+
203
+ ### Cursor Pagination
204
+ **Always use cursors** — Firestore has no offset-based pagination.
205
+
206
+ ```javascript
207
+ import { startAfter, limit, orderBy, getDocs } from "firebase/firestore";
208
+
209
+ // Page 1
210
+ const first = query(citiesRef, orderBy("name"), limit(25));
211
+ const snapshot = await getDocs(first);
212
+ const lastDoc = snapshot.docs[snapshot.docs.length - 1];
213
+
214
+ // Page 2
215
+ const next = query(citiesRef, orderBy("name"), startAfter(lastDoc), limit(25));
216
+ ```
217
+
218
+ ## Aggregation Queries
219
+
220
+ **NEVER fetch all documents and reduce client-side. Always use server-side aggregation.**
221
+
222
+ ### Standard Edition
223
+ ```javascript
224
+ import { count, sum, average, getAggregateFromServer } from "firebase/firestore";
225
+
226
+ const q = query(collection(db, "cities"), where("state", "==", "CA"));
227
+ const snapshot = await getAggregateFromServer(q, {
228
+ totalCount: count(),
229
+ totalPop: sum("population"),
230
+ avgPop: average("population")
231
+ });
232
+ console.log(snapshot.data()); // { totalCount: 42, totalPop: 12345678, avgPop: 294420 }
233
+ ```
234
+ Supported: `count()`, `sum(field)`, `average(field)`. NOT supported: min, max, groupBy.
235
+
236
+ ### Enterprise Edition (Pipeline)
237
+ ```javascript
238
+ const result = await db.pipeline()
239
+ .collection("orders")
240
+ .where("status", "==", "shipped")
241
+ .aggregate({
242
+ accumulators: [
243
+ sum("totalAmount").as("revenue"),
244
+ count().as("orderCount"),
245
+ min("totalAmount").as("minOrder"),
246
+ countDistinct("customerId").as("uniqueCustomers")
247
+ ],
248
+ groups: ["productId"] // GROUP BY
249
+ })
250
+ .sort("revenue", "desc")
251
+ .limit(10)
252
+ .execute();
253
+ ```
254
+ Pipeline supports: min, max, countDistinct, groupBy, regex, map, filter-after-aggregate. **No real-time listeners on Pipeline queries.**
255
+
256
+ ## Compound Query Constraints
257
+
258
+ | Rule | Detail |
259
+ |---|---|
260
+ | Inequality filters | Same query needs composite index (equality → inequality → orderBy) |
261
+ | `not-in` + `in`/`or` | Cannot combine |
262
+ | `array-contains` | Max 1 per query |
263
+ | Disjunction limit | 30 (DNF form) |
264
+ | `orderBy` required | For `startAt`/`startAfter` and inequality queries |
265
+ | Missing fields | `!=` and `not-in` exclude docs where field doesn't exist |