# CHIMBO Deployment

## Prerequisites

- Node.js 24 LTS
- MySQL 8+ (not MariaDB for production target)
- TLS certificates for apex + wildcard `*.ROOT_DOMAIN`
- SMTP (`smtps://`) for password recovery
- Secrets in a secure store (never in git)

## Environment

Copy `.env.example` → production secret store. Required:

| Variable | Notes |
|----------|--------|
| `NODE_ENV` | `production` |
| `DATABASE_URL` | `mysql://…` with TLS-capable host |
| `APP_URL` | `https://…/` (HTTPS required) |
| `ROOT_DOMAIN` | e.g. `chimbo.co.tz` |
| `RATE_LIMIT_SECRET` | ≥32 random chars, not placeholder |
| `TRUST_CLOUDFLARE` | `true` only when CF is sole ingress |
| `SMTP_URL` / `MAIL_FROM` | both or neither |

Optional: payment provider secrets (not in platform settings UI).

## Database migrations

```bash
# 1. Backup first (see Backup)
# 2. Review pending SQL in prisma/migrations
npm ci
npx prisma migrate deploy
npx prisma generate
```

Never `prisma migrate reset` or `db push` in production.

## Build & start

```bash
npm ci
npm run build
npm start
```

Bind to a private interface behind Cloudflare/reverse proxy. Do **not** serve the repo from Apache document root.

## Cloudflare / DNS

1. Apex `A/AAAA` → origin (proxied).
2. Wildcard `*.ROOT_DOMAIN` → same origin (proxied) with Universal SSL / advanced cert covering wildcards.
3. Page Rules / Cache Rules: **bypass** for `/dashboard*`, `/super-admin*`, `/api*`, `/login*`, HTML documents; cache `/_next/static*`.
4. Set `TRUST_CLOUDFLARE=true` only after origin is firewalled to Cloudflare IPs and headers are sanitized.

## Cookie / subdomain note

Production session cookie is `__Host-chimbo-session` (host-only). It will **not** appear on `broker.ROOT_DOMAIN`. That is intentional.

## PWA

- Manifest: `/manifest.webmanifest` — name **CHIMBO**, icons under `/icons/`.
- Service worker: `/sw.js` (offline page only).
- After deploy, bump SW cache name if offline shell changes (already `chimbo-offline-v2`).

## Post-deploy verification

- [ ] `GET /api/health` → `{ status: "ok" }`
- [ ] HTTPS redirect / HSTS present
- [ ] Register → login → dashboard
- [ ] Password reset email (if SMTP configured)
- [ ] Tenant host serves storefront; private API on tenant host → 404
- [ ] Broker cannot open `/super-admin`
- [ ] Sitemap excludes offers/dashboard
- [ ] Manifest icons load
- [ ] Install prompt / Add to Home Screen smoke on Android Chrome

## Backup

Daily encrypted `mysqldump --single-transaction --routines --triggers --events`, retain 30 days + weekly 12 weeks, **off-host**. Keep binlogs for PITR. RPO/RTO targets: ≤24h / ≤4h until formally approved.

## Restore

1. Provision isolated MySQL 8.
2. Restore dump + apply binlogs to target time.
3. Verify row counts, sample tenant isolation, sample financial totals.
4. Point staging app at restore DB; smoke-test.
5. Record date, duration, issues in ops log.

**Status:** strategy documented; restore rehearsal **not yet recorded** for this environment.

## Rollback

Prefer forward-fix migrations. If release fails: redeploy previous app artifact; DB roll-forward only. Do not drop populated tables.

## Super Admin bootstrap

No public role-assignment API. Promote the first Super Admin via controlled SQL/ops procedure with audit, then use Control Center for further ops.
