# Profile Service — Production Deployment

## Overview

The RedTag B2C Profile system consists of two services:

- **tbi-rlv-profile-frontend** — Next.js 16 web app (`profile.redtag.ca`) on `redtag-prod` cluster
- **tbi-rlv-profile-backend-service** — NestJS API (`tbi-rlv-profile-backend.prod.tbidevelopment.ca`) on `tbi-prod` cluster

Both authenticate users via AWS Cognito User Pool `ca-central-1_ykbZiSwok` in account `489176460030`.

---

## Architecture

```mermaid
graph TB
    subgraph Users["End Users"]
        Web["Web Browser"]
        Mobile["Mobile App"]
    end

    subgraph CDN["CDN / WAF"]
        Imperva["Imperva<br/>profile.redtag.ca"]
    end

    subgraph EKS_RP["redtag-prod Cluster"]
        FE["tbi-rlv-profile-frontend<br/>Next.js 16.0.10<br/>Port 3000"]
    end

    subgraph EKS_P["tbi-prod Cluster"]
        BE["tbi-rlv-profile-backend-service<br/>NestJS<br/>Port 3000"]
    end

    subgraph AWS["AWS Services (489176460030)"]
        Cognito["Cognito User Pool<br/>ca-central-1_ykbZiSwok"]
        DDB["DynamoDB<br/>RL_Profile"]
        S3["S3<br/>tbi-user-profile-prod"]
        Kinesis["Kinesis Firehose<br/>tbi-prod-kinesis-s3-lambda-os"]
        SES["SES<br/>noreply@redtag.ca"]
        CloudWatch["CloudWatch<br/>RedtagUserProfile"]
        Lambda["Lambda Triggers<br/>Pre-signup, Post-confirm, Custom-msg"]
    end

    subgraph External["External Services"]
        Redis["Redis<br/>redis-redtag.prod.tbidevelopment.ca"]
        Travcom["Travcom API"]
        Insurance["Insurance Service<br/>tbi-rlv-insurance-service.redtag.ca"]
    end

    Web --> Imperva --> FE
    Mobile --> Cognito
    Mobile --> BE

    FE --> Cognito
    FE --> Redis
    FE --> Kinesis
    FE --> BE

    BE --> Cognito
    BE --> DDB
    BE --> S3
    BE --> Kinesis
    BE --> SES
    BE --> CloudWatch
    BE --> Redis
    BE --> Travcom
    BE --> Insurance

    Cognito --> Lambda
    Lambda --> BE
    Lambda --> SES
```

---

## Clusters & Namespaces

| Service | Cluster | Namespace | Ingress Host |
|---------|---------|-----------|--------------|
| Frontend | `redtag-prod` | `redtag` | `profile.redtag.ca` |
| Backend | `tbi-prod` | `redtag` | `tbi-rlv-profile-backend.prod.tbidevelopment.ca` |

---

## Authentication Flow

```mermaid
sequenceDiagram
    participant User as User (Browser)
    participant FE as profile.redtag.ca
    participant Cognito as AWS Cognito
    participant Redis as Redis
    participant BE as Backend API
    participant DDB as DynamoDB (RL_Profile)

    User->>FE: Click Sign In
    FE->>Cognito: Hosted UI redirect (PKCE)
    Cognito-->>User: Login form
    User->>Cognito: Submit credentials
    Cognito-->>FE: Authorization code callback
    FE->>Cognito: Exchange code for tokens (+ client_secret)
    Cognito-->>FE: access_token, id_token, refresh_token
    FE->>Redis: Cache tokens
    FE-->>User: Set HTTP-only cookies, redirect to dashboard

    User->>FE: View profile
    FE->>Redis: Get cached access_token
    FE->>BE: GET /profile (Bearer token)
    BE->>BE: Verify JWT (JWKS)
    BE->>DDB: Query PK=USER#{sub}
    DDB-->>BE: Profile data
    BE-->>FE: JSON response
    FE-->>User: Render page
```

---

## Deployment Pipeline

```mermaid
flowchart LR
    Push["Push to master"] --> Lint["lint-and-test"]
    Lint --> SNS1["SNS: Await BUILD"]
    SNS1 --> Approve1["🔒 Approve"]
    Approve1 --> Build["Build + Push ECR"]
    Build --> SNS2["SNS: Await DEPLOY"]
    SNS2 --> Approve2["🔒 Approve"]
    Approve2 --> Deploy["Deploy to K8s"]
```

- **Frontend**: CircleCI config at `redtag-prod/tbi-rlv-profile-frontend/.circleci/config.yml`
- **Backend**: CircleCI config at `prod/tbi-rlv-profile-backend-service/.circleci/config.yml`
- Both use `devops-mgt-prod` context, `prod-win` runner, 2-stage approval

---

## Infrastructure

| Resource | Value | Account |
|----------|-------|---------|
| Cognito User Pool | `ca-central-1_ykbZiSwok` | 489176460030 |
| DynamoDB Table | `RL_Profile` (PAY_PER_REQUEST, deletion protection) | 489176460030 |
| S3 Bucket | `tbi-user-profile-prod` (AES256, public access blocked) | 489176460030 |
| Kinesis Firehose | `tbi-prod-kinesis-s3-lambda-os` | 489176460030 |
| Redis | `redis-redtag.prod.tbidevelopment.ca:6379` (no password) | — |
| SES | `noreply@redtag.ca` (production mode, 50K/day) | 489176460030 |
| KMS (SOPS) | `c3fa2cba-8d35-4448-9993-e17667581699` | 495680544243 |
| Helm Charts S3 | `tbi-charts-prod` | 489176460030 |
| ECR | `489176460030.dkr.ecr.ca-central-1.amazonaws.com` | 489176460030 |

---

## IAM

| User | Access Key | Permissions |
|------|-----------|-------------|
| `tbi-rlv-profile-service` | `AKIAXDZJQNL7BXEY6JAL` | DynamoDB (RL_Profile), S3 (tbi-user-profile-prod), CloudWatch, SES |
| `tbi-rlv-kinesis` | `AKIAXDZJQNL7AEXTEI6W` | Kinesis Firehose (shared, used by both services) |

---

## Cognito Configuration

| Setting | Web App | Mobile App |
|---------|---------|------------|
| Client ID | `6c5ot1tijetjf2d2q0vpn2scs3` | `2qj2ovsreij61c4on86n1spmjm` |
| Client Secret | Yes | No |
| Domain | `tbi-redtag-prod.auth.ca-central-1.amazoncognito.com` | Same |
| Redirect URI | `https://profile.redtag.ca/auth/callback` | `redtagapp://Home` |
| Email Sending | SES (`RedTag <noreply@redtag.ca>`) | Same |

### Lambda Triggers

| Trigger | Function | Purpose |
|---------|----------|---------|
| `tbi-redtag-lambda-pre-signup` | Social login linking, duplicate email check | Links Google/Facebook/Apple to existing accounts |
| `tbi-redtag-lambda-post` | Welcome email + profile creation | Sends email via SMTP, POSTs to backend `/profile` |
| `tbi-redtag-lambda-custom` | Email templates | Branded verification/reset emails |

---

## Secrets Management

Secrets are SOPS-encrypted in `tbi-environments`:
- **Frontend**: `redtag-prod/secrets/secrets.tbi-rlv-profile-frontend.yaml`
- **Backend**: `prod/secrets/secrets.tbi-rlv-profile-backend-service.yaml`

```bash
# Decrypt
cd tbi-environments/redtag-prod && sops -d secrets/secrets.tbi-rlv-profile-frontend.yaml
cd tbi-environments/prod && sops -d secrets/secrets.tbi-rlv-profile-backend-service.yaml

# Edit and re-encrypt
sops -d secrets/secrets.<service>.yaml > /tmp/temp.yaml
vim /tmp/temp.yaml
cp /tmp/temp.yaml secrets/secrets.<service>.yaml
sops -e -i secrets/secrets.<service>.yaml
rm /tmp/temp.yaml
```

---

## Manual Deployment (via deploy pipeline)

```bash
# Frontend (redtag-prod cluster)
cd tbi-environments
AWS_PROFILE=tbi-prod python3.9 _helpers/deploy_pipeline/deploy-pipeline upgrade-components redtag-prod tbi-rlv-profile-frontend --quiet --no-slack-message

# Backend (tbi-prod cluster)
AWS_PROFILE=tbi-prod python3.9 _helpers/deploy_pipeline/deploy-pipeline upgrade-components prod tbi-rlv-profile-backend-service --quiet --no-slack-message
```

---

## TLS

| Service | Method | Cert |
|---------|--------|------|
| Frontend | Manual (in secrets) | `*.redtag.ca` wildcard, expires Jul 9, 2026 |
| Backend | cert-manager (auto) | Auto-provisioned |

Cert source: `sftp certs@sftp2.travelapps.ca` → `tbi/redtag.ca/`

---

## Hostnames & DNS

| Hostname | Points To | Via |
|----------|-----------|-----|
| `profile.redtag.ca` | ELB `a0b57df2aa2cb4f278eeeff7af7c1bbe-26732875.ca-central-1.elb.amazonaws.com` | Imperva CDN |
| `tbi-rlv-profile-backend.prod.tbidevelopment.ca` | tbi-prod cluster ingress | Direct |

---

## Post-Deployment Checklist

- [ ] `kubectl get pods -n redtag | grep profile` (both clusters)
- [ ] `curl https://tbi-rlv-profile-backend.prod.tbidevelopment.ca/health` → 200
- [ ] `curl https://profile.redtag.ca/` → 200
- [ ] Test sign-up flow end-to-end
- [ ] Verify welcome email from `noreply@redtag.ca`
- [ ] Check DynamoDB `RL_Profile` for new user record
- [ ] Monitor CloudWatch `RedtagUserProfile` namespace
- [ ] Check Kinesis logs flowing

---

## Rollback

```bash
# Frontend
aws eks update-kubeconfig --name redtag-prod --region ca-central-1 --profile tbi-prod
helm history tbi-rlv-profile-frontend -n redtag
helm rollback tbi-rlv-profile-frontend <REVISION> -n redtag

# Backend
aws eks update-kubeconfig --name tbi-prod --region ca-central-1 --profile tbi-prod
helm history tbi-rlv-profile-backend-service -n redtag
helm rollback tbi-rlv-profile-backend-service <REVISION> -n redtag
```

---

## Known Issues

- **Imperva bot challenge**: API routes (`/api/*`) may be intercepted by Imperva JS challenge. Configure Imperva to whitelist API paths.
- **Promotions endpoint**: Returns 500 — GraphQL endpoint on `www.redtag.ca` may need configuration.

---

*Last updated: 2026-05-14*
