feat: Firebase project config — Firestore, Storage rules, Functions setup (batch v0.2.3)

- .firebaserc: default project set to couples-connect-dev
- firebase.json: Firestore rules/indexes, Storage rules, Functions source config
- storage.rules: profile photo write/read rules (5MB cap, image-only, owner-scoped)
- firestore.indexes.json: empty (no custom indexes yet)
This commit is contained in:
null 2026-06-19 18:46:25 -05:00
parent 7552c451db
commit c878a9be1f
4 changed files with 58 additions and 0 deletions

5
.firebaserc Normal file
View File

@ -0,0 +1,5 @@
{
"projects": {
"default": "couples-connect-dev"
}
}

21
firebase.json Normal file
View File

@ -0,0 +1,21 @@
{
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"storage": {
"rules": "storage.rules"
},
"functions": [
{
"source": "functions",
"codebase": "default",
"ignore": [
"node_modules",
".git",
"firebase-debug.log",
"firebase-debug.*.log"
]
}
]
}

4
firestore.indexes.json Normal file
View File

@ -0,0 +1,4 @@
{
"indexes": [],
"fieldOverrides": []
}

28
storage.rules Normal file
View File

@ -0,0 +1,28 @@
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;
}
// Deny all other paths by default.
match /{allPaths=**} {
allow read, write: if false;
}
}
}