# M1 Smoke Test — Live Results

Run on 2026-06-13, host interserver2. All 9 steps from
`M1_VERIFICATION.md` passed.

## Step results

| # | step | result |
|---|---|---|
| 1 | `docker compose build` | ✅ all 6 images built |
| 1 | `docker compose up -d` | ✅ all 10 services up (postgres, redis, nats, emqx, clickhouse, fakefcmd, ingestd, routerd, deliverd, admind) |
| 1 | `docker compose up seed` | ✅ `seed: ok` |
| 2 | verify companies/individuals/fcm_tokens | ✅ 1+1+1 rows |
| 3 | fakefcmd `/health` | ✅ `{"status":"ok","received":0,"failed":0}` |
| 4 | signed POST to ingestd | ✅ `202 {"alert_id":"0000019ec2...","dedupe_count":1}` |
| 5 | `deliveries` row appears | ✅ `status=sent, attempts=1, channel=fcm` |
| 6 | fakefcmd log | ✅ `alert_id=0000019ec2... title="Disk full on db-prod-03"` |
| 7 | bad signature | ✅ `401` |
| 7 | payload > 256KB | ✅ `413` |
| 7 | invalid JSON | ✅ `400` |
| 7 | bad severity | ✅ `400` |
| 8 | loadgen-http 50/s × 30s | ✅ 1529 sent, 0 failed, 0 rate_limited |
| 8 | deliveries count after burst | ✅ 1530 sent (1529 burst + 1 step-4) |
| 9 | same dedupe_key 3x | ✅ `dedupe_count: 1, 2, 3` |

## Issues found and fixed during the live run

| # | issue | fix |
|---|---|---|
| 1 | `Dockerfile` `COPY ... 2>/dev/null \|\| true` not supported by BuildKit | removed the shell redirect; only copy the file that exists |
| 2 | `go.mod` requires Go 1.25; Docker base image was 1.24 | bumped Dockerfile `FROM golang:1.25-alpine` |
| 3 | `emqx/emqx:5-alpine` tag no longer exists in Docker Hub | pinned to `emqx/emqx:5.10.4` (latest v5 stable) |
| 4 | EMQX 5.10 healthcheck `wget` against `/api/v5/status` requires auth | swapped to `bash /dev/tcp/127.0.0.1/1883` — the MQTT TCP port is the real liveness signal |
| 5 | `nats:2.10-alpine` healthcheck failed because HTTP monitoring needs explicit `-m 8222` flag | added `-m 8222` to the nats command line |
| 6 | Host already has a redis on `:6379` and a postgres on `:5432`; docker proxy failed to bind | changed compose to `expose:` (no host port mapping) for postgres + redis. App services reach them via docker DNS. |

## Honest notes

- The `emqx` container shows `health: starting` indefinitely in step 1; the
  TCP probe is succeeding (we can connect to 1883) but docker's
  healthcheck machinery seems slow to mark it healthy. Doesn't block
  M1. Will revisit in M4.
- The `seed` container is a one-shot sidecar that doesn't restart. To
  re-run it: `docker compose up seed`.
- Default `BA_POSTGRES_PASSWORD` and `BA_REDIS_URL` in compose are
  dev-only values; production overrides via `.env` are out of M1
  scope.
