# Deployment Guard Configuration

Protects Agencio Predict against unauthorized deployments by validating with the License Server.

---

## Overview

The Deployment Guard:
1. **Validates on startup** - Checks in with License Server before serving requests
2. **Heartbeat monitoring** - Periodic validation (every 60 minutes)
3. **Response signing** - HMAC-SHA256 signatures prevent MITM attacks
4. **Graceful degradation** - `action: "warn"` allows continued operation with warnings

---

## Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                 Predict App (Vercel)                        │
│  ┌───────────────────────────────────────────────────────┐ │
│  │  Deployment Guard (instrumentation.ts)                 │ │
│  │  - Generates machine fingerprint on startup            │ │
│  │  - Validates with License Server                       │ │
│  │  - Heartbeat every 60 minutes                          │ │
│  │  - Verifies signed responses                           │ │
│  └───────────────────────────────────────────────────────┘ │
└─────────────────────────┬───────────────────────────────────┘
                          │ HTTPS (signed requests/responses)
                          ▼
┌─────────────────────────────────────────────────────────────┐
│              License Server (EKS preprod)                   │
│  https://licensing.agencio.cloud                            │
│                                                             │
│  POST /api/deployments/validate   - Startup validation      │
│  POST /api/deployments/heartbeat  - Periodic check-in       │
│  POST /api/deployments/register   - Register deployment     │
└─────────────────────────────────────────────────────────────┘
```

---

## Environment Variables (Vercel)

| Variable | Required | Description |
|----------|----------|-------------|
| `LICENSE_SERVER_URL` | Yes | `https://licensing.agencio.cloud` |
| `DEPLOYMENT_KEY` | Yes | Secret from registration (64-char hex) |
| `DEPLOYMENT_ID` | No | Override auto-generated ID (recommended) |
| `DEPLOYMENT_GUARD_ENABLED` | No | Set `false` to disable |

---

## Registration Process

### 1. Register with License Server

```bash
curl -s -X POST https://licensing.agencio.cloud/api/deployments/register \
  -H "Content-Type: application/json" \
  -H "x-api-key: $ADMIN_API_KEY" \
  -d '{
    "deploymentId": "prod-predict-vercel-main",
    "productId": "19a48b25-da89-494d-85b0-caeeadd64a1b",
    "environment": "production"
  }'
```

**Product IDs:**

| Tier | productId |
|------|-----------|
| Predict Basic | `8d820db4-47c9-4d9b-8943-7e3402a6e1d0` |
| Predict Pro | `19a48b25-da89-494d-85b0-caeeadd64a1b` |
| Predict Enterprise | `ba2f9883-33b5-4ba9-beca-8c5b8a6985f5` |

**Response:**
```json
{
  "success": true,
  "deployment": {
    "id": "prod-predict-vercel-main",
    "secret": "4d8c915f2644f54c30452d1da69d663aadd0d55e..."
  }
}
```

**Important:** The `secret` is returned only once. Store it immediately.

### 2. Add Environment Variables to Vercel

```bash
# Add the secret as DEPLOYMENT_KEY
vercel env add DEPLOYMENT_KEY production <<< "<secret-from-step-1>"

# Add the deployment ID
vercel env add DEPLOYMENT_ID production <<< "prod-predict-vercel-main"
```

### 3. Redeploy

```bash
vercel --prod
```

---

## Current Configuration (Production)

| Variable | Value |
|----------|-------|
| `LICENSE_SERVER_URL` | `https://licensing.agencio.cloud` |
| `DEPLOYMENT_ID` | `prod-predict-vercel-main` |
| `DEPLOYMENT_KEY` | `4d8c915f...` (encrypted) |

Registered: 2026-05-10

---

## Validation Response Actions

| Action | Meaning | Behavior |
|--------|---------|----------|
| `continue` | Validation passed | Proceed normally |
| `warn` | Issue detected but continue | Log warning, proceed |
| `kill` | Deployment must terminate | Crash immediately |

---

## Troubleshooting

### "Validation service unavailable"

The License Server is unreachable or has internal issues. With `action: "warn"`, the app continues with a warning.

**Check:**
1. License Server health: `curl https://licensing.agencio.cloud/health`
2. Database tables exist: `deployments`, `deployment_commands`
3. ADMIN_API_KEY is set on License Server

### "UNAUTHORIZED DEPLOYMENT"

The deployment is not registered or validation failed.

**Fix:**
1. Register the deployment (see above)
2. Verify `DEPLOYMENT_KEY` matches the secret from registration
3. Check `DEPLOYMENT_ID` matches the registered ID

### Signature Verification Failed

Response from License Server has invalid signature.

**Check:**
1. `DEPLOYMENT_KEY` matches what License Server has stored
2. Response timestamp is within 5 minutes (prevents replay)
3. No MITM proxy modifying responses

---

## Files

| File | Purpose |
|------|---------|
| `packages/be/src/lib/deployment-guard/validator.ts` | Validation + heartbeat logic |
| `packages/be/src/lib/deployment-guard/watermark.ts` | Code watermark generation |
| `packages/be/src/lib/deployment-guard/index.ts` | Main export |
| `apps/web/src/instrumentation.ts` | Bootstrap integration |

---

## Security Notes

1. **DEPLOYMENT_KEY is secret** - Never commit to git, use Vercel env vars
2. **Response signing** - HMAC-SHA256 prevents license server spoofing
3. **Timestamp validation** - Responses older than 5 minutes are rejected
4. **Timing-safe comparison** - Prevents timing attacks on signature verification
