Files
alfred-proxy/SETUP_COMPLETE.md
jknapp 44ac8b6d1c Initial commit: Alfred Proxy with OAuth, TTS, and FCM push notifications
- Environment-based configuration (no hardcoded secrets)
- OAuth authentication via Authentik
- ElevenLabs TTS integration via SAG CLI
- FCM push notification support
- User preferences sync system
- Multi-user support with per-user context files
- No internal IPs or service accounts in tracked files
2026-02-09 11:13:01 -08:00

479 lines
12 KiB
Markdown

# Alfred Proxy - Complete Setup Guide
**Updated:** 2026-02-04
**Status:** ✅ Fully functional with FCM push notifications
## What This Is
Alfred Proxy is an authentication and notification bridge that:
1. Validates OAuth tokens from the Alfred mobile app (via Authentik)
2. Injects OpenClaw gateway tokens (server-side, never exposed)
3. Sends Firebase Cloud Messaging push notifications to mobile devices
4. Persists FCM tokens across restarts for reliable alarm delivery
## Quick Start
### Prerequisites
- Node.js 24+ installed
- OpenClaw gateway running on localhost:18789
- Authentik OAuth provider configured
- Firebase project with FCM enabled
- Google Cloud service account with correct permissions
### 1. Install Dependencies
```bash
cd ~/.openclaw/workspace/alfred-proxy
npm install
```
### 2. Configure Firebase (FCM)
#### a. Create Service Account
1. Go to: https://console.cloud.google.com/iam-admin/serviceaccounts?project=YOUR_PROJECT_ID
2. Click "Create Service Account"
3. Name: `alfred-fcm-server`
4. Grant role: **Firebase Admin SDK Administrator Service Agent**
- This role includes `cloudmessaging.messages.create` permission
- Do NOT use "Firebase Cloud Messaging Admin" (legacy API)
5. Download JSON key
#### b. Enable FCM API
1. Go to: https://console.cloud.google.com/apis/library/fcm.googleapis.com?project=YOUR_PROJECT_ID
2. Click "Enable"
#### c. Place Service Account Key
```bash
cp ~/Downloads/your-key.json service-account.json
chmod 600 service-account.json
```
### 3. Configure Environment
```bash
# Copy example config
cp .env.example .env
# Edit with your settings
nano .env
```
**Required settings:**
```bash
PROXY_PORT=18790
OPENCLAW_URL=ws://127.0.0.1:18789
OPENCLAW_TOKEN=your-openclaw-token # From ~/.openclaw/openclaw.json
AUTHENTIK_URL=https://auth.your-domain.com
AUTHENTIK_CLIENT_ID=your-client-id
REQUIRE_AUTH=true
```
### 4. Start the Proxy
**Development (auto-reload):**
```bash
npm run dev
```
**Production (systemd service):**
```bash
# Copy service file
cp alfred-proxy.service ~/.config/systemd/user/
# Start and enable
systemctl --user daemon-reload
systemctl --user enable alfred-proxy.service
systemctl --user start alfred-proxy.service
# Check status
systemctl --user status alfred-proxy.service
```
### 5. Verify Setup
```bash
# Check proxy is running
curl http://localhost:18790/health
# Expected: {"status":"ok","service":"alfred-proxy"}
# Check logs
tail -f /tmp/alfred-proxy.log
# Look for:
# [firebase] Firebase Admin SDK initialized
# [alfred-proxy] Service started successfully
```
### 6. Test FCM Notifications
```bash
# Send test alarm
./alfred-notify --alarm "Test alarm!"
# Check logs for success
tail -f /tmp/alfred-proxy.log | grep fcm
# Expected: [fcm] Successfully sent X message(s)
```
## Features
### ✅ Working Features
- **OAuth Authentication**: Validates Authentik tokens via userinfo endpoint
- **Token Injection**: Injects OpenClaw gateway token server-side
- **FCM Push Notifications**: Send notifications even when app is closed
- **Token Persistence**: FCM tokens persist across proxy restarts (`fcm-tokens.json`)
- **Dual Delivery**: WebSocket (if connected) + FCM (always)
- **CLI Wrapper**: `alfred-notify` command for easy notification sending
- **Auto-Reconnection**: App reconnects and re-registers FCM token automatically
### Notification Types
- **Alarm**: High-priority, wakes device
- **Alert**: Standard priority notification
- **Silent**: Vibrate only or completely silent
## Usage
### Send Notification via CLI
```bash
# Simple alarm
./alfred-notify --alarm "Wake up!"
# Notification with custom title
./alfred-notify --title "Kitchen Timer" "Oven is ready"
# Silent notification
./alfred-notify --no-sound --no-vibrate "Background task complete"
```
Run `./alfred-notify --help` for all options.
### Send Notification via HTTP API
```bash
curl -X POST http://localhost:18790/api/notify \
-H "Content-Type: application/json" \
-d '{
"notificationType": "alarm",
"title": "Test",
"message": "This is a test alarm",
"priority": "high",
"sound": true,
"vibrate": true
}'
```
**Response:**
```json
{
"success": true,
"clients": 1, // WebSocket clients notified
"fcm": 1 // FCM devices notified
}
```
### Schedule Alarms with Cron
Use OpenClaw's cron tool to schedule alarms:
```javascript
// Example: 5 minute alarm
{
"name": "5 minute alarm",
"schedule": {
"kind": "at",
"atMs": Date.now() + (5 * 60 * 1000)
},
"payload": {
"kind": "agentTurn",
"message": "Run: alfred-notify --alarm '⏰ 5 minute alarm is up!'",
"deliver": false
},
"sessionTarget": "isolated"
}
```
**Critical:** Always use `sessionTarget: "isolated"` + `agentTurn` for alarms.
## Monitoring
### Check Proxy Status
```bash
systemctl --user status alfred-proxy.service
```
### View Logs
```bash
# Live tail
tail -f /tmp/alfred-proxy.log
# Check for FCM activity
grep "fcm" /tmp/alfred-proxy.log | tail -20
# Check for errors
grep "Error\|error" /tmp/alfred-proxy.log | tail -20
```
### Check Token Persistence
```bash
cat fcm-tokens.json
```
Should show registered FCM tokens:
```json
{
"user-id-hash": [
"fcm-token-string"
]
}
```
### Monitor Notification Delivery
```bash
# Send test
./alfred-notify "Test"
# Check logs
tail -f /tmp/alfred-proxy.log
```
Look for:
```
[notify] Broadcasting notification: type=alert title="Alfred" message="Test"
[notify] Sent notification to X connected client(s)
[fcm] Sending push notification to Y registered device(s)
[fcm] Successfully sent Y message(s)
```
## Troubleshooting
### Permission Denied Error
**Error:**
```
[fcm] Error: Permission 'cloudmessaging.messages.create' denied
```
**Solution:**
1. Verify service account role is **Firebase Admin SDK Administrator Service Agent**
- Go to: https://console.cloud.google.com/iam-admin/iam
- Find service account: `alfred-fcm-server@...`
- Should have role: `roles/firebase.sdkAdminServiceAgent`
2. Verify FCM API is enabled
3. Regenerate service account key if > 1 hour old
4. Restart proxy after updating key
### No Tokens Registered
**Error:**
```
[fcm] No FCM tokens registered, skipping push notification
```
**Solution:**
1. Open Alfred mobile app
2. Verify connection (should show "Connected ✅")
3. Check logs for token registration:
```
[fcm] Registering token for user...
[fcm] Saved tokens to disk
```
4. Verify `fcm-tokens.json` file exists and has content
### Tokens Lost After Restart
**This should NOT happen if setup is correct.**
If tokens are lost:
1. Check `fcm-tokens.json` exists in proxy directory
2. Check file permissions: `chmod 600 fcm-tokens.json`
3. Verify logs show: `[fcm] Loaded X token(s) for Y user(s) from disk`
4. Check app sends token on every connection (should be automatic)
### OAuth Token Expired
**Error:**
```
[auth] Authentik validation failed: 401
[proxy] Invalid OAuth token, rejecting connection
```
**Solution:**
1. App needs to implement token refresh (future fix)
2. For now: logout and login again in the app
3. Or disable auth temporarily: `REQUIRE_AUTH=false` in `.env`
### App Not Receiving Notifications
**Checklist:**
1. ✅ Proxy running? `systemctl --user status alfred-proxy.service`
2. ✅ FCM tokens registered? `cat fcm-tokens.json`
3. ✅ Service account has correct role? Check IAM
4. ✅ FCM API enabled? Check APIs & Services
5. ✅ Test notification succeeds? `./alfred-notify "Test"`
6. ✅ Logs show success? `grep "Successfully sent" /tmp/alfred-proxy.log`
If all checks pass but still no notifications:
- Check app is installed and has notification permissions
- Check device has network connectivity
- Check Firebase Cloud Messaging isn't blocked by firewall
- Try uninstall/reinstall app to get fresh FCM token
## Architecture
```
┌──────────────────────┐
│ Alfred Mobile App │
│ (Android/OAuth) │
└──────────┬───────────┘
│ wss:// + OAuth token
┌──────────────────────┐
│ Alfred Proxy │
│ - Validate OAuth │
│ - Inject OpenClaw │
│ token │
│ - Store FCM tokens │
│ - Send FCM push │
└──────────┬───────────┘
┌──────┴───────┐
│ │
▼ ▼
┌────────┐ ┌────────────┐
│OpenClaw│ │ Firebase │
│Gateway │ │ FCM │
│(local) │ └─────┬──────┘
└────────┘ │
┌──────────────┐
│ Mobile Device│
│ (push notif) │
└──────────────┘
```
## Files & Directories
```
alfred-proxy/
├── server.js # Main proxy server
├── alfred-notify # CLI wrapper for notifications
├── .env # Configuration (git-ignored)
├── service-account.json # Firebase credentials (git-ignored)
├── fcm-tokens.json # Persisted FCM tokens (git-ignored)
├── package.json # Dependencies
├── alfred-proxy.service # Systemd service file
├── README.md # Project overview
├── SETUP_COMPLETE.md # This file
├── FCM_SETUP.md # Firebase setup (see alfred-mobile/)
└── /tmp/alfred-proxy.log # Runtime logs
```
## Security
### Sensitive Files (Never Commit)
- `.env` - Contains API tokens
- `service-account.json` - Firebase credentials
- `fcm-tokens.json` - User device tokens
All added to `.gitignore`.
### Best Practices
1. **Restrict service account permissions**: Use minimal role (Firebase Admin SDK Administrator Service Agent)
2. **Rotate keys regularly**: Generate new service account key every 90 days
3. **File permissions**: `chmod 600` for sensitive files
4. **Network isolation**: OpenClaw runs on localhost only, not exposed
5. **OAuth validation**: All connections validated with Authentik before access
## Performance
### Resource Usage
- **Memory**: ~50-100MB RSS
- **CPU**: <1% idle, ~5% during notification bursts
- **Network**: Minimal (WebSocket keepalives + FCM API calls)
### Scalability
- Supports multiple connected devices simultaneously
- FCM batch sending for efficiency
- Token persistence reduces startup overhead
### Monitoring
Monitor with:
```bash
# Process stats
ps aux | grep "node server.js"
# Connection count
ss -tn | grep :18790 | wc -l
# Log size
du -h /tmp/alfred-proxy.log
```
## Updating
### Update Proxy Code
```bash
cd ~/.openclaw/workspace/alfred-proxy
git pull # If using git
npm install # If dependencies changed
systemctl --user restart alfred-proxy.service
```
### Update Service Account Key
```bash
# Download new key from Google Cloud Console
cp ~/Downloads/new-key.json service-account.json
chmod 600 service-account.json
systemctl --user restart alfred-proxy.service
# Verify
tail -f /tmp/alfred-proxy.log | grep firebase
# Should show: [firebase] Firebase Admin SDK initialized
```
## Support & Documentation
- **FCM Setup**: See `../alfred-mobile/FCM_SETUP.md`
- **Agent Integration**: See `../alfred-mobile/AGENT_TOOLS.md`
- **OpenClaw Docs**: https://docs.openclaw.ai
- **Firebase Docs**: https://firebase.google.com/docs/cloud-messaging
## Version History
### 2026-02-04: FCM Token Persistence
- Added token save/load to `fcm-tokens.json`
- App sends token on every connection
- Fixed Firebase IAM permissions (correct role)
- Created `alfred-notify` CLI wrapper
- Updated all documentation
### 2026-02-03: Initial Release
- OAuth authentication via Authentik
- OpenClaw token injection
- Basic FCM notification support
- WebSocket proxy functionality
---
**Status**: ✅ Production Ready
**Last Updated**: 2026-02-04
**Maintainer**: Josh (Shadow)