# Gmail Push Notifications Revisit — Summary

**Date**: 2026-02-13  
**Status**: Planned  
**Implementation Plan**: `2026-02-13-gmail-push-revisit-implementation-plan.md`

## Overview

Enhance Gmail notification reliability through better deployment pattern support, improved configuration surface, actionable error messages, and comprehensive diagnostics.

## Problems Addressed

1. **Deployment ambiguity**: No clear guidance on supported patterns (push vs pull vs hybrid)
2. **GCP setup confusion**: Topic/subscription/IAM relationships not documented
3. **Network constraints**: Tailscale-only gateways cannot receive push webhooks
4. **Poor error messages**: Failures lack actionable guidance
5. **Config gaps**: No explicit disable, no pull subscription support
6. **Diagnostics gap**: Doctor doesn't validate Pub/Sub setup

## Solution

### Supported Deployment Patterns

| Pattern | Config | Network | Reliability |
|---------|--------|---------|-------------|
| **Push only** | `pubsub_topic` | Public IP or Tailscale funnel | High (when reachable) |
| **Pull only** | `pubsub_subscription_id` | Any | High |
| **Hybrid** ⭐ | Both | Any | Highest |
| **Polling only** | Neither | Any | Medium (5min latency) |

### New Config Fields

```yaml
automation:
  gmail:
    # Push notifications (watch API)
    pubsub_topic: projects/<project>/topics/gmail-push
    disable_push: false  # Explicit disable
    
    # Pull subscription (new)
    pubsub_subscription_id: projects/<project>/subscriptions/gmail-pull
    pubsub_pull_interval: "60s"
    pubsub_max_messages: 10
    
    # History API fallback
    poll_interval: "300s"
```

### Enhanced Doctor Check

```bash
$ flynn doctor
✓ Gmail configured (push + pull + poll-fallback → telegram/123456789)
⚠ Gmail configured (push + poll-fallback ⚠️ push requires public endpoint or Tailscale funnel)
✓ Gmail configured (poll → telegram/123456789)
```

### Improved Error Messages

**Before**:
```
GmailWatcher: Watch setup failed (will use polling only) — Invalid topicName
```

**After**:
```
GmailWatcher: Watch setup failed (push disabled) — Invalid topicName
  Tip: Set automation.gmail.pubsub_topic to "projects/your-project/topics/gmail-push"
  Ensure the topic exists in GCP and the subscription is configured to POST to /gmail/push
  Or set automation.gmail.pubsub_subscription_id for pull-based mode (no webhook required)
```

## Files Modified

### Core (4 files)
- `src/config/schema.ts` — Add new fields
- `src/automation/gmail.ts` — Add pull support, error hints
- `src/cli/doctor.ts` — Enhanced validation
- `package.json` — Add `@google-cloud/pubsub`

### Docs (3 files)
- `README.md` — Rewrite Gmail section
- `config/default.yaml` — Update examples
- `docs/plans/state.json` — Mark completed

### Tests (2 files)
- `src/automation/gmail.test.ts` — +7 test cases
- `src/cli/doctor.test.ts` — +5 test cases

## Implementation Checklist

- [ ] Add config schema fields (`pubsub_subscription_id`, `pubsub_pull_interval`, `pubsub_max_messages`, `disable_push`)
- [ ] Implement `setupPullSubscription()` method
- [ ] Implement `pullSubscriptionMessages()` method
- [ ] Implement `buildWatchErrorHint()` method
- [ ] Update `connect()` to handle `disable_push` and call pull setup
- [ ] Update `disconnect()` to clear pull timer
- [ ] Enhance `checkGmail` doctor check with mode detection
- [ ] Add `@google-cloud/pubsub` dependency
- [ ] Write unit tests for pull mode
- [ ] Write unit tests for `disable_push`
- [ ] Write unit tests for error hints
- [ ] Write doctor check tests
- [ ] Update README Gmail section
- [ ] Update `config/default.yaml` example
- [ ] Manual integration testing (4 modes)
- [ ] Update `state.json`

## Test Plan

### Unit Tests (12 new tests)
- Pull subscription setup (full path)
- Pull subscription setup (shorthand with project_id)
- Skip pull when not configured
- Invalid subscription path warning
- `disable_push` skips watch setup
- `disable_push` logs message
- Error hints (Invalid topicName)
- Error hints (Permission denied)
- Error hints (Not found)
- Connection logging shows modes
- Doctor: push mode detection
- Doctor: pull mode detection
- Doctor: hybrid mode detection
- Doctor: Tailscale reachability warning

### Integration Tests (Manual)
- [ ] Push only deployment
- [ ] Pull only deployment
- [ ] Hybrid deployment
- [ ] Polling only deployment
- [ ] Disable push with topic set
- [ ] Doctor check output for each mode
- [ ] Error message hints for common failures
- [ ] Tailscale warning validation

## Recommended Default

**Hybrid mode** (push + pull + polling):
- Push: ~Real-time when endpoint is reachable
- Pull: 60s latency, always works
- Poll: 300s latency, final fallback

## Estimated Effort

**Total**: 1-2 days
- Implementation: 4-6 hours
- Testing: 2-4 hours
- Documentation: 2-3 hours

## Breaking Changes

**None** — existing `pubsub_topic`-only configs continue to work.

## Benefits

1. ✅ **Clarity**: Explicit deployment patterns with setup instructions
2. ✅ **Flexibility**: Pull mode supports private deployments (no inbound connections)
3. ✅ **Reliability**: Hybrid mode ensures delivery across all network configs
4. ✅ **Debuggability**: Error hints + doctor checks catch misconfigurations
5. ✅ **Documentation**: Comprehensive README with GCP setup, troubleshooting
