# Firebase Cloud Messaging (FCM) Setup Guide

Step-by-step guide to set up FCM for Alfred Mobile app with correct IAM permissions.

## Prerequisites

- Google Cloud project with Firebase enabled
- Android app registered with package name: `com.openclaw.alfred`
- `google-services.json` downloaded and placed in `app/` directory

## Firebase Service Account Setup

### Step 1: Create Service Account

1. Go to **Google Cloud Console IAM**:
   - https://console.cloud.google.com/iam-admin/serviceaccounts?project=YOUR_PROJECT_ID

2. Click **"Create Service Account"**

3. **Service account details:**
   - Name: `alfred-fcm-server`
   - Description: `FCM service account for Alfred proxy notifications`
   - Click **Create and Continue**

### Step 2: Grant IAM Role

**CRITICAL**: The service account needs the correct role for FCM HTTP v1 API.

**Required Role:**
- **Firebase Admin SDK Administrator Service Agent** (`roles/firebase.sdkAdminServiceAgent`)

This role includes:
- ✅ `cloudmessaging.messages.create` (required for sending FCM)
- ✅ `firebase.projects.get`
- ❌ NOT `firebasenotifications.*` (legacy API - wrong)

**How to add the role:**
1. In the role selection dropdown, search: **"Firebase Admin SDK Administrator"**
2. Select: **"Firebase Admin SDK Administrator Service Agent"**
3. Click **Continue**, then **Done**

### Step 3: Download Service Account Key

1. Click on the service account you just created
2. Go to **Keys** tab
3. Click **Add Key** → **Create new key**
4. Choose **JSON** format
5. Click **Create** - downloads a JSON file
6. Save this file securely (e.g., `service-account.json`)

### Step 4: Enable Firebase Cloud Messaging API

1. Go to: https://console.cloud.google.com/apis/library/fcm.googleapis.com?project=YOUR_PROJECT_ID
2. Click **"Enable"**
3. Wait for activation (~30 seconds)

## Alfred Proxy Configuration

### Place Service Account Key

```bash
cd ~/.openclaw/workspace/alfred-proxy
cp ~/Downloads/your-service-account-key.json service-account.json
chmod 600 service-account.json
```

### Update .env (if needed)

The proxy reads the service account from `service-account.json` automatically. No additional configuration needed.

### Verify Configuration

```bash
# Check service account email matches
grep "client_email" service-account.json

# Should show: alfred-fcm-server@YOUR_PROJECT_ID.iam.gserviceaccount.com
```

## Testing FCM Permissions

### Test 1: Send Notification via Proxy

```bash
curl -X POST http://localhost:18790/api/notify \
  -H "Content-Type: application/json" \
  -d '{
    "notificationType": "alarm",
    "title": "Test Alarm",
    "message": "Testing FCM permissions",
    "priority": "high",
    "sound": true,
    "vibrate": true
  }'
```

**Expected response:**
```json
{"success":true,"clients":0,"fcm":1}
```

### Test 2: Check Proxy Logs

```bash
tail -f /tmp/alfred-proxy.log | grep fcm
```

**Success looks like:**
```
[fcm] Sending push notification to 1 registered device(s)
[fcm] Successfully sent 1 message(s)
```

**Permission error looks like:**
```
[fcm] Error: Permission 'cloudmessaging.messages.create' denied
```

If you see the permission error, verify:
1. Service account has correct role (Firebase Admin SDK Administrator Service Agent)
2. FCM API is enabled
3. Service account key is fresh (regenerate if > 1 hour old)

## Common Issues

### Wrong Role: "Firebase Cloud Messaging Admin"

**Problem:** This role gives `firebasenotifications.*` permissions (legacy API), not `cloudmessaging.*` (v1 API).

**Solution:** Remove this role, add **"Firebase Admin SDK Administrator Service Agent"** instead.

### API Not Enabled

**Problem:** FCM HTTP v1 API not enabled.

**Solution:**
```bash
# Enable via gcloud (if you have CLI installed)
gcloud services enable fcm.googleapis.com --project=YOUR_PROJECT_ID

# Or enable in console:
# https://console.cloud.google.com/apis/library/fcm.googleapis.com
```

### Token Not Persisted

**Problem:** FCM tokens lost after proxy restarts.

**Solution:** Already fixed! Tokens now persist to `fcm-tokens.json`. Verify:
```bash
cat alfred-proxy/fcm-tokens.json
```

Should show registered tokens. If empty, reconnect the Alfred app.

## Architecture

```
Alfred App (Android)
    ↓ (on connect)
{"type": "fcm.register", "token": "..."}
    ↓
Alfred Proxy
    - Saves to fcm-tokens.json
    - Loads on startup
    ↓ (when alarm triggered)
Firebase Admin SDK
    - admin.messaging().sendEachForMulticast()
    - Requires: cloudmessaging.messages.create permission
    ↓
Firebase Cloud Messaging (Google)
    ↓
Alfred App (receives notification even when asleep)
```

## Security Best Practices

1. **Never commit service account keys** to git
   - Already in `.gitignore`: `service-account.json`

2. **Restrict service account permissions**
   - Use minimal role: Firebase Admin SDK Administrator Service Agent
   - Don't use "Firebase Admin" (too broad)

3. **Rotate keys periodically**
   - Generate new key every 90 days
   - Delete old keys from service account

4. **File permissions**
   ```bash
   chmod 600 alfred-proxy/service-account.json
   ```

## Verification Checklist

After setup, verify:

- [ ] Service account exists with correct name
- [ ] Role: **Firebase Admin SDK Administrator Service Agent**
- [ ] FCM API enabled in Google Cloud Console
- [ ] Service account key downloaded and placed correctly
- [ ] Proxy logs show: `[firebase] Firebase Admin SDK initialized`
- [ ] Test notification succeeds: `[fcm] Successfully sent X message(s)`
- [ ] Alfred app receives notification even when locked

## Next Steps

Once FCM is working:

1. Set up alarms via cron jobs (see TOOLS.md)
2. Configure morning briefings
3. Test cross-device notifications
4. Monitor FCM quota (free tier: 10M messages/month)

---

**Last Updated:** 2026-02-04  
**Status:** ✅ Working with correct IAM role
