Below are drop-in merged rules that keep logos working exactly the same while enabling the business-plan template pipeline.

Firestore — merged (logos + business-plan + settings)
// firestore.rules
rules_version = '2';
service cloud.firestore {
  function isAdmin() {
    return request.auth != null && request.auth.token.admin == true;
  }

  match /databases/{database}/documents {

    // --- EXISTING LOGO TEMPLATES (unchanged behavior) ---
    // Current flat collection you already use
    match /templates/{docId} {
      allow read: if true;                          // everyone can view/browse
      allow create, update, delete: if isAdmin();   // only admins can write
    }

    // Legacy collection (keep until fully retired)
    match /logo_templates/{docId} {
      allow read: if true;
      allow create, update, delete: if isAdmin();
    }

    // --- BUSINESS-PLAN TREE (new) ---
    // If you store BP templates in a nested structure like:
    // templates/business-plan/types/{slug}/versions/{version}
    // use a recursive matcher to cover nested docs:
    match /templates/{document=**} {
      allow read: if true;
      allow write: if isAdmin();
    }

    // Global settings pointer for "master" resolution
    match /settings/{doc=**} {
      allow read: if true;
      allow write: if isAdmin();
    }
  }
}


Why both /templates/{docId} and /templates/{document=**}?

Your logos currently live directly under /templates. Keeping /templates/{docId} preserves that exact behavior.

The business-plan structure is nested (e.g., /templates/business-plan/types/...). The recursive matcher covers those deeper documents.

Both still require isAdmin() for writes, so there’s no new exposure.

If you prefer fewer rules, you can remove the flat /templates/{docId} once all logos are moved to a nested path. Until then, keep both.

Storage — merged (keep logos as-is, add business-plan)
// storage.rules
rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {

    // --- LOGOS (unchanged) ---
    // Your existing logo asset layout
    match /templates/logos/{uid}/{rest=**} {
      allow read: if true;   // public previews/downloads
      allow write: if request.auth != null && request.auth.token.admin == true;
    }

    // --- BUSINESS-PLAN ASSETS (new) ---
    // e.g., templates/business-plan/docs/... and templates/business-plan/previews/...
    match /templates/business-plan/{rest=**} {
      allow read: if true;   // public preview images / public doc downloads if you want
      allow write: if request.auth != null && request.auth.token.admin == true;
    }

    // (Optional) future-proof catch-all for other template families under /templates/
    // Put this AFTER the more specific matchers so it doesn't shadow them.
    match /templates/{rest=**} {
      allow read: if true;
      allow write: if request.auth != null && request.auth.token.admin == true;
    }
  }
}


Notes:

Order matters in storage rules. Specific matchers (/templates/logos/..., /templates/business-plan/...) come before the generic /templates/{rest=**} so they’re not shadowed.

Reads remain public; writes remain admin-only—same posture you already use for logos.

Quick safety checks (takes 2 minutes)

Rules Playground / Emulator

Test get on templates/logos/<uid>/... (should allow).

Test put to the same path with/without admin claim (allow/deny).

Test get/put for templates/business-plan/docs/... similarly.

Minimal app sanity

Confirm logo previews still render.

Upload a dummy BP preview (admin user) → expect success.

Anonymous user upload to BP path → expect deny.