Add deployment phase and Traefik compose override

Insert a new Phase 1 (deployment: Compose + Traefik on a server, marked
Done) between the base project and the OTel concepts phase, and shift
the old phases 1-10 to 2-11. Update summary, intro, README and CLAUDE.md
references (spoiler rules now target Phase 9, the bottleneck hunt).

Add docker-compose.traefik.yml: an override that fronts the gateway with
Traefik and Let's Encrypt and removes all other published host ports.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Movses Aslanyan
2026-10-09 15:38:29 +03:30
co-authored by Claude Sonnet 5.5
parent b2112e55e1
commit 5e514ecf25
17 changed files with 1080 additions and 937 deletions
+21 -20
View File
@@ -37,7 +37,7 @@ make test-contract # fast functional suite (~60s)
Then open **http://localhost:8000**.
The observability backend lives in a separate Ansible repo and is deployed to its
own host. From Phase 1 onward:
own host. From Phase 2 onward:
```bash
# in observability-ansible/
@@ -88,7 +88,7 @@ Every HTTP service exposes `GET /healthz` (liveness) and `GET /readyz`
(dependency check).
**Redis Streams is used deliberately** rather than Celery or RabbitMQ: it has no
automatic trace-context propagation, so Phase 2 has to implement it by hand.
automatic trace-context propagation, so Phase 3 has to implement it by hand.
That's the most valuable exercise in the project. Don't swap it out.
### The primary request flow
@@ -137,7 +137,7 @@ Flag names: `slow_sanctions`, `sanctions_errors`, `n_plus_one`,
`no_batching`, `unbounded_cache`, `slow_consumer`, `cold_cache`, `poison_data`,
`chatty_health`.
> **During Phase 8, don't open the chaos panel and don't call
> **During Phase 9, don't open the chaos panel and don't call
> `GET /api/admin/chaos`.** `make chaos-random` picks a subset and never logs the
> seed; the point is to find the pathologies from telemetry alone. The panel
> will happily tell you the answer, which is the one thing you don't want.
@@ -160,8 +160,8 @@ Flag names: `slow_sanctions`, `sanctions_errors`, `n_plus_one`,
| `test-slow` | The soak-ish pathology tests |
| `chaos-clean` / `-light` / `-nightmare` / `-random` | Set the chaos profile |
| `fix-index` / `drop-index` | Add or remove the deliberately missing indexes |
| `dashboards` | Regenerate dashboard JSON via the Grafana Foundation SDK — *Phase 5+* |
| `load-smoke` / `load-average` / `load-stress` / `load-soak` | k6 profiles — *Phase 6+* |
| `dashboards` | Regenerate dashboard JSON via the Grafana Foundation SDK — *Phase 6+* |
| `load-smoke` / `load-average` / `load-stress` / `load-soak` | k6 profiles — *Phase 7+* |
---
@@ -198,17 +198,17 @@ make test # everything except slow
```
> ⚠️ **`make test-pathology` is a spoiler.** It has one named test per flag, so
> its output is a complete answer key. Don't run it during the Phase 8
> its output is a complete answer key. Don't run it during the Phase 9
> bottleneck hunt.
`tests/test_no_observability.py` guards the Phase 0 "before" state — no OTel, no
`prometheus_client`, no structured logging, no `/metrics`. **Delete it at the
start of Phase 2**; it has done its job by then.
start of Phase 3**; it has done its job by then.
Some pathology assertions currently count log lines, because plain text is the
only cross-service observability surface that exists at Phase 0. That is the
deficiency this project sets out to fix — those assertions get rewritten against
structured logs in Phase 3 and span data in Phase 4, and become both simpler and
structured logs in Phase 4 and span data in Phase 5, and become both simpler and
more robust. See `tests/README.md`.
---
@@ -321,14 +321,14 @@ Rehearse this before showing anyone.
└─ docs/
├─ roadmap/ # the ten-phase learning plan, one file per phase
│ ├─ intro.md # platform background, resource spine (read first)
│ ├─ phase-0.md … phase-10.md # one phase per file — status, message, concepts, build
│ ├─ phase-0.md … phase-11.md # one phase per file — status, message, concepts, build
│ └─ summary.md # one-page status/sequencing overview of all phases
├─ phase-0a-test-suite-spec.md # spec the test suite was written from
├─ phase-0-base-project-spec.md # spec the base app was built from
├─ PATHOLOGIES.md # ⚠️ spoilers — the answer key
├─ SLO.md # SLIs, SLOs, SLA, RTO/RPO, error budget policy
├─ CONCEPTS.md # P95/P99, SLO vs SLA vs RTO vs RPO, in my own words
├─ INVESTIGATION.md # the Phase 8 bottleneck hunt, written as an incident doc
├─ INVESTIGATION.md # the Phase 9 bottleneck hunt, written as an incident doc
└─ PIPELINE-CHOICES.md # Filebeat vs Logstash vs OpenTelemetry — when and why
```
@@ -338,16 +338,17 @@ Rehearse this before showing anyone.
- [ ] **Phase 0a** — integration test suite, written first, red against nothing
- [ ] **Phase 0b** — base project implemented until the suite is green
- [ ] **Phase 1** — concepts, first trace end to end
- [ ] **Phase 2** — distributed tracing across all seven services
- [ ] **Phase 3** — structured logs, correlated with traces
- [ ] **Phase 4** — metrics, RED, service map, exemplars
- [ ] **Phase 5** — dashboards and alerts as code
- [ ] **Phase 6** — k6 load testing, percentiles
- [ ] **Phase 7** — SLIs, SLOs, error budgets, RTO/RPO
- [ ] **Phase 8** — bottleneck hunt
- [ ] **Phase 9** — Filebeat / Logstash / OpenTelemetry judgment
- [ ] **Phase 10** — delivery
- [x] **Phase 1** — deployment: Docker Compose + Traefik on a server
- [ ] **Phase 2** — concepts, first trace end to end
- [ ] **Phase 3** — distributed tracing across all seven services
- [ ] **Phase 4** — structured logs, correlated with traces
- [ ] **Phase 5** — metrics, RED, service map, exemplars
- [ ] **Phase 6** — dashboards and alerts as code
- [ ] **Phase 7** — k6 load testing, percentiles
- [ ] **Phase 8** — SLIs, SLOs, error budgets, RTO/RPO
- [ ] **Phase 9** — bottleneck hunt
- [ ] **Phase 10** — Filebeat / Logstash / OpenTelemetry judgment
- [ ] **Phase 11** — delivery
Full plan: [`docs/roadmap/`](docs/roadmap/) — start with
[`intro.md`](docs/roadmap/intro.md), then the phase you're on, or