# M13 — Meta Plan (milestone grouping)

> Companion to `M13_FRONTEND_SPEC.md`. This is the cross-milestone
> plan; per-milestone detail lives in `M13a_PLAN.md`, `M13b_PLAN.md`,
> `M13c_PLAN.md`.

**Status:** planning (post-M11, parallel to M12)
**Goal:** ship a v1 multi-tenant admin UI that replaces `dlq.html`
and adds CRUD + live-tail + audit + auth surfaces, in a single
`admind` Go binary that embeds a Vite+React 19 SPA.

---

## 0. Why milestones, not one big plan

The original M13 plan (workstream-as-primary-axis, 9 workstreams)
assumed one engineer ships end-to-end. In practice you stop and
review between surfaces — and you want each stop to be a **shippable
artifact**, not "we have some auth working but no UI yet".

The milestone split lets you:

| Stop after | What you have | Why stop here |
|---|---|---|
| **M13a** | authd + web skeleton + login works | "Is the design right? Is the auth model right? Is the SPA architecture right?" — review before committing to feature work. |
| **M13b** | Companies + Sources + Telegram CRUD | ~80% of operator value. The customer can self-onboard, set up sources, configure telegram. Live tail + DLQ + audit can wait. |
| **M13c** | Live tail + DLQ + Audit + K8s + E2E | Full v1. Replaces `dlq.html`, ships Playwright gate, K8s-ready. |

Each milestone flips one SPEC.md row. Each has its own
`M13x_PLAN.md` with workstreams, estimates, and per-milestone DoD.

---

## 1. Milestone overview

```
                ┌──────────────┐
                │  M13.0 spec  │   (this PR — no code)
                │  + API       │
                └──────┬───────┘
                       │
                       ▼
                ┌──────────────┐
                │   M13a       │   ~5-6 days
                │  authd +     │
                │  web shell   │
                │  + JWT gate  │
                └──────┬───────┘
                       │
                       ▼
                ┌──────────────┐
                │   M13b       │   ~7-8 days
                │  CRUD:       │
                │  Companies   │
                │  Sources     │
                │  Telegram    │
                └──────┬───────┘
                       │
                       ▼
                ┌──────────────┐
                │   M13c       │   ~7-9 days
                │  Live tail   │
                │  DLQ         │
                │  Audit       │
                │  K8s         │
                │  Playwright  │
                └──────────────┘
```

**Total estimate: ~19-23 days with one engineer.** Can be parallelized
with a second engineer at M13b (one on Companies, one on Sources).

---

## 2. Milestone summaries

### M13.0 — Spec & API contract
- `M13_FRONTEND_SPEC.md`
- `M13_API_CONTRACT.md`
- No code. This PR. **No DoD beyond "specs reviewed and committed".**

### M13a — authd + web skeleton + JWT gate
- `cmd/authd/` — JWT IdP service on :8804, all 7 endpoints.
- `web/` — Vite + React 19 + shadcn/ui + TanStack Query + RHF + Zod.
  Login page works end-to-end. Other routes render "coming soon".
- `admind` modified to require JWT on all `/v1/*` endpoints (except
  `/health`, `/metrics`).
- Plan: `M13a_PLAN.md`.

### M13b — CRUD
- Companies: list, detail, create, edit, suspend (super); read-only
  (tenant).
- Sources: list, detail, create, edit, rotate secret, suspend. One-time
  secrets modal.
- Telegram: bot config, invite codes, bindings list.
- All forms validate; audit log writes; error toasts.
- Plan: `M13b_PLAN.md`.

### M13c — Ops surface + K8s + E2E
- Live tail: SSE feed, filter bar, drill-in modal, pause-on-scroll.
- DLQ: list, detail, replay, discard. Replaces `dlq.html`.
- Audit log viewer.
- K8s manifests for `admind` and `authd` (carry from M12 W1).
- Playwright E2E happy path green in CI.
- Plan: `M13c_PLAN.md`.

---

## 3. Cross-cutting concerns

These live in the spec but are operationally tested in M13c:

- **Single binary:** `admind` embeds the SPA via `embed.FS`. Target
  size: < 60 MB.
- **No CORS:** SPA is served by `admind` itself. `authd` is same-origin
  via service discovery.
- **OpenAPI client gen:** `pnpm run gen:api` in CI on every Go API
  change. Type drift fails the PR.
- **Tenant isolation:** backend enforces `WHERE company_id = $1` for
  tenant-admins. Tested in Playwright with a cross-tenant 403 check.
- **Audit immutability:** every state-changing call writes to
  `audit_log`. The viewer is read-only.

---

## 4. Dependencies

| From | What | Status | Affects |
|---|---|---|---|
| M11 | gRPC ingest stable, F2 publish counter | ✅ done | M13c (live tail source) |
| M12 W1 | K8s manifests for `admind` and `authd` | ⏳ in flight | M13c W7 (K8s manifests) |
| Postgres | `auth` schema + tables | to be created in M13a W1 | M13a |
| Redis | rate-limit counters for `authd` login | ✅ already in stack | M13a |
| NATS | `tailhub` for in-memory SSE feed (M13c) | ✅ already exists | M13c |
| SMTP (optional) | magic-link email | NOT required for v1 (psql fallback) | M13a (best-effort) |

---

## 5. Parallelism with M12

| When | What runs in parallel |
|---|---|
| M13a W1-W2 | M12 W1 (K8s manifests) — independent |
| M13b W1-W3 | M12 W2 (NATS cluster) — independent |
| M13c W7 | M12 W3-W4 (Helm + 50k/s bench) — blocks K8s manifest merge |

M13 does not block M12. M12 W5 (M11 prod gate on K8s) is independent
of M13. The two milestones converge at "single PR that ships v1 with
K8s + frontend" but the workstream branches don't have to.

---

## 6. Definition of done — whole M13

- [ ] All 3 sub-milestones (M13a, M13b, M13c) have their individual
      DoD checked.
- [ ] `cmd/authd/` exists, builds, runs, healthy on :8804.
- [ ] `cmd/admind/` builds with embedded SPA, < 60 MB.
- [ ] Playwright happy-path green in CI for 3 consecutive runs.
- [ ] Tenant-isolation 403 test green in CI.
- [ ] `M13_VERIFICATION.md` published with: screenshots of the 6
      modules, the Playwright run log, the tenant-isolation test,
      the binary size, and the bundle breakdown.
- [ ] SPEC.md `M13a`, `M13b`, `M13c` rows flipped to **✅ shipped
      YYYY-MM-DD**.
- [ ] `cmd/admind/ui/dlq.html` removed.
- [ ] Demo to a real customer (or internal stakeholder) and signed
      off.

---

**Next step:** commit the 3 docs from M13.0, then start M13a W1
(`authd`).
