# Monetarie Core - GCP Deployment Plan & Status

**Date:** 2026-02-03
**Project:** `newco20260203`
**Region:** `southamerica-east1` (São Paulo)
**Status:** DEPLOYED

---

## Final Architecture

```
Internet
  │
  ▼
Global HTTPS L7 LB (34.160.49.224)
  │  Cloud Armor (rate limiting + security policy)
  │  Certificate Manager (5 domains, ACTIVE)
  │  SSL Policy: RESTRICTED (TLS 1.2+)
  │  HTTP→HTTPS redirect (301)
  │
  ├── core-api.fluxiq.com.br ──► GKE: Phoenix API (3 pods)
  │                                   ├── Cloud SQL PostgreSQL 16 (HA Regional, Private IP)
  │                                   ├── TigerBeetle (1 pod, dedicated node pool)
  │                                   ├── NATS JetStream (3 pods, cluster mode)
  │                                   └── Redis Sentinel (1 master + 2 replicas)
  │
  ├── ib.fluxiq.com.br ────────► GKE: Nginx (Vue 3 banking, 2 pods)
  ├── core-admin.fluxiq.com.br ► GKE: Nginx (Vue 3 admin, 2 pods)
  ├── core-app.fluxiq.com.br ──► GKE: Nginx (Vue 3 merchant, 2 pods)
  └── core-docs.monetarie.com.br ─► GKE: Nginx (VitePress docs, 2 pods)

VPC: monetariecore (10.100.0.0/23 nodes, 10.101.0.0/23 pods, 10.102.0.0/23 services)
VPC Peering: monetariecore ↔ monetariepix (prepared, CIDRs TBD)
```

---

## Execution Status

### FASE 0: Setup do Projeto e IAM — COMPLETE
- [x] APIs habilitadas
- [x] Service accounts criadas (monetariecore-deployer, monetariecore-workload)
- [x] Artifact Registry: `monetariecore` (southamerica-east1)
- [x] Secrets no Secret Manager (db-password, secret-key-base)

### FASE 1: VPC Network e Conectividade — COMPLETE
- [x] VPC `monetariecore` criada (custom subnet mode)
- [x] Subnet `monetariecore-gke-nodes` (10.100.0.0/23 + secondary ranges)
- [x] Private Service Access para Cloud SQL
- [x] Cloud NAT (monetariecore-router + monetariecore-nat)
- [x] Firewall rules (internal, health checks, IAP SSH, deny-all)
- [ ] VPC Peering com monetariepix (CIDRs pendentes)

### FASE 2: Cloud SQL PostgreSQL 16 — COMPLETE
- [x] Instância `monetariecore-pg` (db-custom-32-131072, HA Regional)
- [x] Database `monetarie_prod` + user `monetarie_app`
- [x] Private IP only (sem IP público)
- [x] Query Insights habilitado
- [x] Deletion protection ativada

### FASE 3: GKE Standard Cluster — COMPLETE
- [x] Cluster `monetariecore-cluster` (3 zonas, private nodes)
- [x] Default pool: e2-standard-8, autoscale 1-5 per zone
- [x] TigerBeetle pool: e2-standard-4, dedicated (taint + label)
- [x] NATS pool: e2-standard-4, dedicated (taint + label)
- [x] Workload Identity habilitado
- [x] Managed Prometheus ativo
- [x] Dataplane V2 (Cilium) + Network Policy

### FASE 4: Build e Push de Container Images — COMPLETE
- [x] API image: `monetariecore/api:v1.0.0` (Elixir 1.19, multi-stage)
- [x] Banking image: `monetariecore/ib:v1.0.0`
- [x] Admin image: `monetariecore/admin:v1.0.0`
- [x] Merchant image: `monetariecore/merchant:v1.0.0`
- [x] Docs image: `monetariecore/docs:v1.0.0`

### FASE 5: Deploy Workloads Stateful — COMPLETE
- [x] Namespaces: monetariecore, tigerbeetle, nats, redis
- [x] TigerBeetle: 1 pod, PVC premium-rwo 100Gi, dedicated node
- [x] NATS JetStream: 3 pods cluster mode, dedicated nodes
  - [x] Streams: MONETARIE_NPC_LEDGER (7 subjects), MONETARIE_NPC_LEDGER_DLQ
  - [x] Consumers: ledger_service, account_service, balance_service, journal_service
- [x] Redis Sentinel: 1 master + 2 replicas (Bitnami Helm chart)

### FASE 6: Deploy Application Services — COMPLETE
- [x] K8s Secrets (DATABASE_URL, SECRET_KEY_BASE, TigerBeetle, NATS, Redis)
- [x] Phoenix API: 3 pods running, /health returning 200
- [x] Frontend deployments: 4x2 pods, all running
- [x] Database migrations executed (all 13 migrations)
- [x] Production seeds executed (PostgreSQL + TigerBeetle)

### FASE 7: DNS, Certificados SSL e Load Balancer — COMPLETE
- [x] Static IP: 34.160.49.224 (monetariecore-external-ip)
- [x] SSL Policy: RESTRICTED (TLS 1.2+)
- [x] Certificate Manager: monetariecore-cert (5 domains, ACTIVE)
- [x] Certificate Map: monetariecore-certmap (5 entries, ACTIVE)
- [x] Cloud Armor: monetariecore-security-policy
- [x] GKE Ingress: monetariecore-ingress (5 host rules, all HEALTHY)
- [x] HTTPS target proxy: manual creation (monetariecore-https-proxy)
- [x] Forwarding rules: HTTP (80) + HTTPS (443)
- [x] DNS A records: all 5 domains → 34.160.49.224
- [x] HTTP→HTTPS redirect: 301

### FASE 8: Table Partitioning — COMPLETE
- [x] Native PostgreSQL RANGE partitioning (NOT pg_partman)
- [x] Partitioned: transactions, inflow_requests, outflow_requests
- [x] Monthly partitions: Jan 2026 → Mar 2027 + default
- [x] Oban PartitionMaintenance worker: creates 3 months ahead, daily 01:00 UTC

### FASE 9: Security Hardening — PARTIAL
- [x] Cloud SQL: private IP only, no public access
- [x] GKE: private nodes, shielded nodes
- [x] Cloud Armor: active with rate limiting
- [ ] Network Policies: manifests exist, apply after confirming monetariepix CIDRs
- [ ] Cloud Armor rules 100/200: need real CIDRs for VPC Peering and office IPs

### FASE 10: Monitoring e Observability — PARTIAL
- [x] GKE Managed Prometheus active
- [ ] Uptime checks: create now that endpoints are live
- [ ] Grafana dashboards: import from infrastructure/monitoring/

---

## Verified Endpoints (2026-02-04)

| URL | Status | Response |
|-----|--------|----------|
| `https://core-api.fluxiq.com.br/health` | 200 | `{"status":"ok","version":"0.1.0"}` |
| `https://ib.fluxiq.com.br` | 200 | Vue 3 Banking SPA |
| `https://core-admin.fluxiq.com.br` | 200 | Vue 3 Admin SPA |
| `https://core-app.fluxiq.com.br` | 200 | Vue 3 Merchant SPA |
| `https://core-docs.monetarie.com.br` | 200 | VitePress documentation |
| `http://ib.fluxiq.com.br` | 301 | Redirect to HTTPS |

---

## Pod Status (2026-02-04)

| Namespace | Pod | Ready | Status |
|-----------|-----|-------|--------|
| monetariecore | monetariecore-api (x3) | 1/1 | Running |
| monetariecore | ib-frontend (x2) | 1/1 | Running |
| monetariecore | admin-frontend (x2) | 1/1 | Running |
| monetariecore | merchant-frontend (x2) | 1/1 | Running |
| monetariecore | docs-frontend (x2) | 1/1 | Running |
| tigerbeetle | tigerbeetle (x1) | 1/1 | Running |
| nats | monetariecore-nats (x3) | 1/1 | Running |
| redis | redis-master (x1) | 1/1 | Running |
| redis | redis-replica (x2) | 1/1 | Running |

**Total: 19 pods running**

---

## Issues Resolved During Deployment

| Issue | Root Cause | Fix |
|-------|-----------|-----|
| API build: mix.lock not found | File doesn't exist in repo | Removed from Dockerfile COPY, use `--no-frozen-lockfile` |
| Elixir version mismatch | mix.exs `~> 1.19` vs Dockerfile 1.18 | Updated Dockerfile ARG to 1.19 |
| Frontend: @monetarie/shared unresolved | Missing workspace dependency | Added `"@monetarie/shared": "workspace:*"` to all 3 apps |
| Merchant package name mismatch | `@monetarie/merchant` vs `@monetarie/merchant-portal` | Fixed cloudbuild APP_NAME |
| Admin vue-tsc -b failing | tsconfig.node.json missing composite:true | Added composite:true, removed noEmit |
| Shared tsup DTS build failing | tsconfig composite:true in shared package | Removed composite from shared tsconfig |
| Frontend Dockerfile: workspace resolution | Single-app copy broke pnpm workspace | Rewrote to copy full workspace, build shared first |
| pnpm exec vite build → dev server | pnpm exec not passing subcommand | Changed to `sh -c "npx vite build"` |
| Docs ESM error | Missing type:module in package.json | Added `"type": "module"` |
| API crash: Ecto.InvalidURLError | Password with `/` and `=` in URL | URL-encoded password |
| API crash: TigerBeetle invalid_address | DNS hostname not supported | Used ClusterIP:port |
| API crash: NetworkPolicy blocking TB | Wrong namespace label (monetariecore) | Changed to monetariecore |
| No HTTPS forwarding rule | GKE Ingress didn't create HTTPS proxy | Manual target-https-proxy + forwarding rule |
| pg_partman not available on Cloud SQL | Cloud SQL doesn't support pg_partman | Native PostgreSQL partitioning + Oban worker |
| Seeds fail via eval | Port 4000 conflict with running endpoint | Use `rpc` instead of `eval` |

---

## Remaining Work

1. **Cloud Armor**: Set real CIDRs for VPC Peering (monetariepix) and office/VPN IPs
2. **Network Policies**: Apply after confirming monetariepix VPC CIDR
3. **Monitoring**: Create uptime checks, import Grafana dashboards
4. **API image rebuild**: Include prod.exs fix (removed cache_static_manifest)
5. **HPA**: Configure Horizontal Pod Autoscaler for API (3-20 pods)
6. **PDB**: Apply PodDisruptionBudgets (minAvailable: 2 for API, frontends)
7. **CUD**: Evaluate Committed Use Discounts for cost optimization
