# MediLink Gmail Orchestrator - GCP Setup Guide

This guide will walk you through setting up the Google Cloud Platform infrastructure for the MediLink Gmail Orchestrator.

## Prerequisites

- A new GCP project created
- `gcloud` CLI installed and authenticated
- Access to Google Workspace Admin Console (for domain-wide delegation)
- The mailbox user email address you want to monitor

## Step-by-Step Setup

### Step 1: Run the Infrastructure Setup Script

Open PowerShell in the `cloud/orchestrator` directory and run:

```powershell
.\setup_gcp.ps1 YOUR_PROJECT_ID
```

Replace `YOUR_PROJECT_ID` with your actual GCP project ID.

This script will:
- ✅ Enable all required Google Cloud APIs
- ✅ Create the service account with proper IAM roles
- ✅ Generate and download the service account key
- ✅ Create the Cloud Storage bucket
- ✅ Create the Pub/Sub topic

**Important Manual Steps After Running the Script:**

1. **Enable Domain-Wide Delegation** (Required for Gmail access):
   - Go to: https://admin.google.com/ac/owl
   - Navigate to: Security → API controls → Domain-wide delegation
   - Click "Add new" and enter the `client_id` from `medilink-gmail-orchestrator.json`
   - Authorize these scopes (comma-separated):
     ```
     https://www.googleapis.com/auth/gmail.modify,https://www.googleapis.com/auth/gmail.readonly,https://www.googleapis.com/auth/gmail.send,https://www.googleapis.com/auth/drive
     ```

2. **Initialize Firestore Database**:
   - Go to: https://console.cloud.google.com/firestore/databases?project=YOUR_PROJECT_ID
   - Click "Create Database"
   - Select "Native mode" (not Datastore mode)
   - Choose location: `us-central1` (recommended)
   - Click "Create"
   
3. **Create Firestore Collections**:
   - In the Firestore Console, create two collections:
     - `queues` (this will be populated automatically)
     - `sync_state` (this will be populated automatically)
   
4. **Create Composite Index** (for efficient queue queries):
   - In Firestore Console → Indexes
   - Click "Create Index"
   - Collection ID: `queues`
   - Fields to index:
     - `machine_id` (Ascending)
     - `acked` (Ascending)  
     - `created_at` (Ascending)
   - Click "Create"

### Step 2: Set Up Service Account Credentials for Cloud Run

You need to make the service account key available to Cloud Run. Choose one method:

**Option A: Using Secret Manager (Recommended)**

```powershell
# Create secret from the service account key
gcloud secrets create orchestrator-service-account --data-file=medilink-gmail-orchestrator.json --project=YOUR_PROJECT_ID

# Grant Cloud Run access to the secret
gcloud secrets add-iam-policy-binding orchestrator-service-account `
    --member="serviceAccount:medilink-gmail-orchestrator@YOUR_PROJECT_ID.iam.gserviceaccount.com" `
    --role="roles/secretmanager.secretAccessor" `
    --project=YOUR_PROJECT_ID
```

**Option B: Set as Environment Variable** (Less secure, simpler)

You'll need to base64 encode the JSON file:

```powershell
# Read the JSON file
$jsonContent = Get-Content -Path medilink-gmail-orchestrator.json -Raw

# Convert to base64
$base64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($jsonContent))

# This will be set during deployment (see Step 3)
```

### Step 3: Build and Deploy Cloud Run Service

Run the deployment script:

```powershell
.\build_and_deploy.ps1 YOUR_PROJECT_ID SERVICE_ACCOUNT@gmail.com
```

Replace:
- `YOUR_PROJECT_ID` with your GCP project ID (use: `genial-analyzer-476721-f8`)
- `SERVICE_ACCOUNT@gmail.com` with the service account's Gmail address

**Note**: The service account must have a Gmail account created. Emails are forwarded from `mariavidaud@gmail.com` to the service account's Gmail address. See `GMAIL_FORWARDING_SETUP.md` for instructions.

**If using Secret Manager**, add this to the deployment command (edit `build_and_deploy.ps1`):
```powershell
--update-secrets="SERVICE_ACCOUNT_JSON=orchestrator-service-account:latest"
```

**If using environment variable**, add this to the deployment:
```powershell
--set-env-vars "SERVICE_ACCOUNT_JSON=$base64"
```

The script will:
- ✅ Build the Docker image
- ✅ Deploy to Cloud Run
- ✅ Set all required environment variables
- ✅ Generate an admin secret (save this!)

**After deployment**, note the Cloud Run service URL. You'll need it for the next steps.

### Step 4: Create Pub/Sub Subscription

Create a push subscription that sends messages to your Cloud Run service:

```powershell
$SERVICE_URL = "https://medilink-gmail-orchestrator-XXXXX-uc.a.run.app"  # From Step 3
$PROJECT_ID = "YOUR_PROJECT_ID"
$SA_EMAIL = "medilink-gmail-orchestrator@${PROJECT_ID}.iam.gserviceaccount.com"

gcloud pubsub subscriptions create gmail-new-emails-run `
    --topic=gmail-new-emails `
    --push-endpoint="${SERVICE_URL}/pubsub/push" `
    --push-auth-service-account=$SA_EMAIL `
    --project=$PROJECT_ID
```

### Step 5: Register Gmail Watch

Use the bootstrap script to register the Gmail watch:

```powershell
cd ..\..  # Back to project root
python tools/gmail_watch_bootstrap.py `
    --project YOUR_PROJECT_ID `
    --service-account cloud/orchestrator/medilink-gmail-orchestrator.json `
    --mailbox MAILBOX_USER@domain.com `
    --topic projects/YOUR_PROJECT_ID/topics/gmail-new-emails
```

This will:
- ✅ Register a watch on the Gmail mailbox
- ✅ Route notifications to the Pub/Sub topic
- ✅ Return a `historyId` that the orchestrator will use

**Important**: Gmail watches expire after 7 days. You need to set up Cloud Scheduler to refresh it (Step 6).

### Step 6: Set Up Cloud Scheduler (Gmail Watch Refresh)

Create a scheduled job to refresh the Gmail watch every 6 hours:

```powershell
$SERVICE_URL = "https://medilink-gmail-orchestrator-XXXXX-uc.a.run.app"
$PROJECT_ID = "YOUR_PROJECT_ID"
$ADMIN_SECRET = "your-admin-secret-from-step-3"  # Save this from Step 3!
$SA_EMAIL = "medilink-gmail-orchestrator@${PROJECT_ID}.iam.gserviceaccount.com"

gcloud scheduler jobs create http gmail-watch-refresh `
    --schedule="0 */6 * * *" `
    --uri="${SERVICE_URL}/admin/resume-history" `
    --http-method=POST `
    --headers="Content-Type=application/json" `
    --message-body='{\"secret\":\"' + $ADMIN_SECRET + '\"}' `
    --oidc-service-account-email=$SA_EMAIL `
    --oidc-token-audience="${SERVICE_URL}/admin/resume-history" `
    --project=$PROJECT_ID
```

### Step 7: Verify the Setup

1. **Test the health endpoint**:
   ```powershell
   curl https://medilink-gmail-orchestrator-XXXXX-uc.a.run.app/health
   ```
   Should return: `{"status":"ok"}`

2. **Check Firestore**:
   - Go to Firestore Console
   - Check that `sync_state/gmail` document exists (created automatically)
   - Check that `queues` collection is empty initially

3. **Send a test email** with an attachment to your monitored mailbox
   - Check Firestore `queues` collection - should see a new document
   - Check Cloud Storage bucket - should see uploaded attachment
   - Check Cloud Run logs for processing messages

### Step 8: Set Up HTTPS Load Balancer (For Windows XP Compatibility)

Cloud Run uses TLS 1.2/SNI which Windows XP cannot handle. You need to front it with a load balancer that supports TLS 1.0.

**This is a complex step - see the main documentation** (`docs/architecture/MediLink_Gmail_GCP_Implementation.md`) for detailed instructions on:
- Reserving an external IP
- Creating a serverless NEG
- Configuring HTTPS proxy with XP-compatible certificate
- Setting up DNS mapping

For initial testing, you can skip this step and test directly with Cloud Run, but XP workstations will need the load balancer.

## Troubleshooting

### Service Account Key Issues
- Make sure domain-wide delegation is enabled in Google Workspace Admin
- Verify all required scopes are authorized
- Check that the `client_id` in the JSON matches what you entered in Admin Console

### Cloud Run Deployment Fails
- Ensure all APIs are enabled: `gcloud services list --enabled`
- Check that Firestore is in Native mode, not Datastore mode
- Verify service account has all required roles

### Gmail Watch Not Working
- Check Pub/Sub subscription status in Console
- Verify push endpoint URL is correct
- Check Cloud Run logs for incoming Pub/Sub messages
- Ensure service account has `pubsub.publisher` role

### Firestore Errors
- Make sure Firestore is in Native mode
- Verify composite index is created for `queues` collection
- Check that collections `queues` and `sync_state` exist

## Next Steps

After completing this setup:
1. ✅ Deploy XP daemon to clinic workstations (see `xp_client/` directory)
2. ✅ Update Google Apps Script to v2 (OTP-only)
3. ✅ Update MediLink desktop UI to point to new secure messages URL
4. ✅ Test end-to-end flow with a pilot clinic

See `docs/architecture/MediLink_Gmail_GCP_Implementation.md` for complete details.

