rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {

    // Profile photos: only the owner may write; both the owner and their
    // partner can read via the tokenized download URL. Direct read is
    // scoped to the owner so raw storage paths aren't publicly accessible.
    //
    // Size cap: 5 MB. Content-type must be an image (enforced at upload,
    // not at read, so the header check only blocks mismatched writes).
    match /users/{uid}/profile.jpg {
      allow write: if request.auth != null
                   && request.auth.uid == uid
                   && request.resource.size < 5 * 1024 * 1024
                   && request.resource.contentType.matches('image/.*');

      // Partners receive the tokenized download URL (generated server-side or
      // at upload time) which bypasses these rules. Direct rule-based read is
      // scoped to the owner only.
      allow read: if request.auth != null && request.auth.uid == uid;
    }

    // Encrypted chat media: the author writes under their own path (already E2E-encrypted
    // ciphertext, so Storage never holds anything readable). The partner reads via the tokenized
    // download URL, which bypasses these rules — same model as profile photos. 15 MB cap.
    match /users/{uid}/chat_media/{file} {
      allow write: if request.auth != null
                   && request.auth.uid == uid
                   && request.resource.size < 15 * 1024 * 1024;
      allow read: if request.auth != null && request.auth.uid == uid;
    }

    // Deny all other paths by default.
    match /{allPaths=**} {
      allow read, write: if false;
    }
  }
}
