# Pathrule Pattern: Firebase and Firestore Production (1.0.0)
# ::pathrule:package:firebase-firestore

### [RULE] Deny access unless rules can prove the entire query safe  (path: /firestore)
<!-- scope: folder | priority: high | strict -->

Firestore evaluates a query against its potential result set, not by filtering unauthorized documents afterward. A rule that secures a document read can still reject a list query whose constraints do not prove the same ownership condition.

- Start from no access and grant the narrow operation on the narrow match path. Separate create, update, delete, get, and list when their invariants differ.
- Derive actor identity from authentication context and existing stored data. Never let a client grant itself ownership, role, or tenant membership by writing the field the rule later trusts.
- Make list queries include the same tenant, owner, visibility, or status constraints the rule requires, then test both allowed and overbroad variants.
- Validate changed fields and immutable fields explicitly on writes so a user cannot preserve an allowed document path while replacing authorization-critical content.

See /src/data for the adjacent decision or procedure that completes this constraint.

---

### [RULE] Keep privileged side effects idempotent and server-owned  (path: /functions)
<!-- scope: folder | priority: high | strict -->

Clients can retry writes after reconnect and server functions can redeliver events. A privileged effect that assumes exactly-once execution can send duplicate email, allocate inventory twice, or charge more than once.

- Move secret-bearing and privilege-escalating operations to a trusted server environment using the Admin SDK only after verifying the caller and target resource.
- Store a stable operation or event identifier with the side effect and reject or return the prior result when the same identifier is observed again.
- Write domain state and the idempotency record in the same atomic boundary where the data model permits it; never mark success before the effect is durably represented.
- Treat function retries, timeouts, and partial failures as normal paths. Log the operation key and final state so an operator can reconcile ambiguity.

See /firestore for the adjacent decision or procedure that completes this constraint.

---

### [RULE] Model offline writes as pending transitions  (path: /src/data)
<!-- scope: folder | priority: medium | strict -->

Firestore can apply a write to the local cache before the server accepts it. The interface must distinguish optimistic local state from a confirmed transition, especially when rules, contention, or connectivity can reject the write later.

- Represent operations with a stable client-generated identifier and show pending state where the user might otherwise repeat the action.
- Listen for server acknowledgement or write failure and reconcile the optimistic item by identity rather than appending a second copy.
- Do not trigger irreversible client-side side effects merely because the local snapshot changed; wait for trusted server state or a server event.
- Design conflict behavior for reconnect explicitly. Last-write-wins is not acceptable for counters, inventory, balances, or approval workflows without a server-owned transition.

See /functions for the adjacent decision or procedure that completes this constraint.

---

### [MEMORY] Document shape follows read and rule boundaries  (path: /firestore)

Firestore documents are not relational rows, and joins do not appear at query time. The useful design question is which data must be read together and which facts Security Rules must inspect to decide access.

- Keep a bounded snapshot of display data with a relation when it avoids an extra read, and define how that snapshot is refreshed when the source changes.
- Duplicate tenant or ownership identifiers where rules and queries need them, but make the trusted server the authority that writes or verifies those fields.
- Keep documents below practical growth limits by moving unbounded collections, logs, and membership lists into subcollections with their own query strategy.
- Choose document IDs and collection paths for stable identity, not for mutable presentation values such as names or email addresses.

See /src/data for the rule or workflow that puts this decision into practice.

---

### [MEMORY] Every production query has an index and cost story  (path: /src/data)

Firestore pricing and latency follow document reads and index traversal. A query that works on a small emulator dataset can become expensive or require a composite index as filters and ordering are combined.

- Define filters, ordering, and cursor pagination together; avoid offset pagination that repeatedly reads skipped documents.
- Commit required index configuration with the application so environments do not depend on a console-created index no one can reproduce.
- Measure how listeners behave when tabs background, reconnect, or observe high-churn collections; a permanent listener is an ongoing read surface.
- Use aggregate or maintained summary documents for dashboards that would otherwise scan large collections on every view.

See /firestore for the rule or workflow that puts this decision into practice.

---

### [SKILL] verify-firestore-contract  (path: /)

---
name: verify-firestore-contract
description: Verify a Firestore data-contract change before deploying rules, indexes, clients, or functions.
---

# Verify Firestore Contract

Run this procedure when the affected surface changes, before the result is promoted to production. Record evidence for every step instead of accepting a plausible-looking result.

- [ ] Seed users, tenants, ownership combinations, and documents in the emulator, including stale and malicious client-controlled fields.
- [ ] Run every operation as owner, member, outsider, unauthenticated caller, and privileged server; include list queries broader than the intended filter.
- [ ] Execute the exact production query shapes against committed index configuration and confirm cursor pagination returns stable, non-duplicated pages.
- [ ] Simulate disconnect, local optimistic write, reconnect, and server rejection; confirm the UI reconciles pending state and does not repeat side effects.
- [ ] Redeliver the same server event and operation key, then prove the function returns the prior outcome without duplicating external or stored effects.

## Exit criteria

The change is complete only when the expected behavior, failure behavior, and rollback path have all been exercised with representative data. Preserve the evidence with the change so the next operator can repeat the same checks.
