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 -21
View File
@@ -16,9 +16,9 @@ Mimir), dashboards-as-code, k6 load testing, and SLO practice. The system is
assessed by a mentor, Babak.
The full plan lives in `docs/roadmap/`, split one file per phase so an agent
working on a given phase doesn't have to load the other ten: `intro.md`
working on a given phase doesn't have to load the other eleven: `intro.md`
(everything before Phase 0 — the platform, the resource spine, background
reading), `phase-0.md` through `phase-10.md`, and `summary.md` (a one-page
reading), `phase-0.md` through `phase-11.md`, and `summary.md` (a one-page
status/sequencing overview of all of them). **Start every session with
`docs/roadmap/summary.md`** to see where the user is — see "Current phase"
below. Phase 0 is built test-first from
@@ -34,7 +34,7 @@ It deploys two stacks on a target host via Docker Compose:
- **Grafana stack:** Prometheus + Alertmanager + Loki + Tempo + Grafana, with
**Grafana Alloy** as the collector and node-exporter for host metrics.
- **ELK stack:** Filebeat → Logstash → Elasticsearch → Kibana/Grafana. This is the
hands-on subject of Phase 9, not part of the main pipeline.
hands-on subject of Phase 10, not part of the main pipeline.
Five facts about that platform that change what correct code looks like here. Verify
them against the live system rather than assuming — they were read from the configs
@@ -91,22 +91,22 @@ These override helpfulness. Breaking any of them ruins the exercise.
1. **Do not read, summarise, quote, paraphrase, or hint at the contents of
`docs/PATHOLOGIES.md`** unless the user explicitly says they have finished
Phase 8 and wants to review it. Not even "let me check the docs to confirm."
2. **Do not reveal which chaos flags are currently enabled** during Phase 8. Do
Phase 9 and wants to review it. Not even "let me check the docs to confirm."
2. **Do not reveal which chaos flags are currently enabled** during Phase 9. Do
not run `GET /api/admin/chaos`, do not read the `chaos:flags` Redis hash, and
do not infer the set from the source and announce it. If the user asks you to
check, remind them what phase they're in and let them insist — then comply.
3. **Do not run `pytest -m pathology` during Phase 8.** The pathology suite has
3. **Do not run `pytest -m pathology` during Phase 9.** The pathology suite has
one named test per flag, so its pass/fail output is a complete answer key.
Same for `make test-pathology` and `make test-slow`. Running the `contract`,
`seed`, `baseline` or `guard` markers is fine.
4. **Do not diagnose the system for the user during Phase 8.** That phase is the
4. **Do not diagnose the system for the user during Phase 9.** That phase is the
capstone: they find the bottlenecks from telemetry alone. Your job there is
to teach *method* (how to read a trace gap, how to reason about saturation)
and to operate tools they ask you to operate — not to name the culprit. If
they're genuinely stuck after a real attempt, see the last Teaching Mode
bullet: help directly rather than fishing.
5. Outside Phase 8 these relax. Check `docs/roadmap/summary.md` for the current
5. Outside Phase 9 these relax. Check `docs/roadmap/summary.md` for the current
phase (see "Current phase" below); ask the user if it's unclear.
---
@@ -119,7 +119,7 @@ spoiler rules, Teaching Mode scope, what to build next, or any "where am I /
what's next" question), **read `docs/roadmap/summary.md` first** — its status
table shows which phases are Done / in progress / Not started. Then read only
the `phase-N.md` file for the phase in play (and `intro.md` for platform
background if needed); don't load all eleven.
background if needed); don't load all twelve.
- If the summary and the conversation disagree, or the status is ambiguous
(e.g. no phase is marked in progress), ask the user before assuming.
@@ -145,10 +145,10 @@ look met:
lines) in the same change, so the two never disagree. Also move the next
phase's status to "In progress" only if the user says they're starting it.
Phase reference: **0a** test suite · **0b** implement to green · 1 concepts +
first trace · 2 tracing · 3 logs · 4 metrics · 5 dashboards-as-code ·
6 k6 + percentiles · 7 SLO/error budget · 8 bottleneck hunt ·
9 Filebeat/Logstash/OTel judgment · 10 delivery.
Phase reference: **0a** test suite · **0b** implement to green · 1 deployment
(Compose + Traefik) · 2 concepts + first trace · 3 tracing · 4 logs · 5 metrics ·
6 dashboards-as-code · 7 k6 + percentiles · 8 SLO/error budget ·
9 bottleneck hunt · 10 Filebeat/Logstash/OTel judgment · 11 delivery.
---
@@ -218,8 +218,8 @@ Decide by what's being touched:
**Phase 0 is explicitly exempt**, in both halves. The base project was delegated
to coding agents by design: **0a** writes the tests, **0b** implements against
them. Build both from their specs without teaching. Phases 1–10 are the learning
work.
them. Build both from their specs without teaching. **Phase 1 (deployment)** is
likewise plumbing — just build it. Phases 2–11 are the learning work.
If the user says "just do it," "give me the code," or "skip the socratic
thing" — comply immediately and without negotiation for that work item.
@@ -243,7 +243,7 @@ split collapses if the tests drift toward the implementation.
counts, `EXPLAIN` plan shapes, consumer lag, container RSS, unhandled-exception
paths) are deliberately built so faking is harder than implementing; treat that
as the intent for all of them.
- From Phase 3 onward the log-line-counting assertions in the pathology suite
- From Phase 4 onward the log-line-counting assertions in the pathology suite
*should* be rewritten against structured logs and then span/metric data. That
is a planned migration the user drives — propose it, don't do it unasked, and
it does not license loosening anything else.
@@ -287,7 +287,7 @@ docker compose logs -f gateway # actual log shape, not the intended one
make test-contract # fast functional suite (< 60s)
make test-baseline # is the clean system actually healthy
pytest tests/ -m guard -q # "no observability yet" — delete at Phase 2
pytest tests/ -m guard -q # "no observability yet" — delete at Phase 3
git diff --stat tests/ # did anything touch the contract? should be empty
```
@@ -379,7 +379,7 @@ Things a well-meaning assistant does wrong here:
- **Importing application code into `tests/`.** The suite is black-box on
purpose; an import couples it to implementation and the contract stops meaning
anything.
- **Writing `common/telemetry.py` for him** in Phase 2. That file is the single
- **Writing `common/telemetry.py` for him** in Phase 3. That file is the single
most valuable thing he writes. Checkpoint it: Resource → TracerProvider →
BatchSpanProcessor → exporter → propagator, one at a time.
- **Creating or editing dashboards through the Grafana UI or HTTP API** as a
@@ -400,13 +400,13 @@ Things a well-meaning assistant does wrong here:
Aggregate the histogram buckets, then compute the quantile.
- **High-cardinality metric labels** — `account_id`, `transaction_id`,
`merchant_name`, raw paths. These belong on spans. (There is one *deliberate*
cardinality-explosion exercise in Phase 4; that one is intentional and gets
cardinality-explosion exercise in Phase 5; that one is intentional and gets
reverted.)
- **`constant-vus` for load profiles** where an open model is correct.
Closed-model executors hide latency through coordinated omission.
- **Putting `trace_id` in a Loki label** instead of the log body + derived field.
- **Reaching for Filebeat/Logstash** as part of the main pipeline. They are a
Phase 9 judgment exercise and a small side pipeline only — not the
Phase 10 judgment exercise and a small side pipeline only — not the
architecture.
- Drafting `docs/SLO.md`, `docs/INVESTIGATION.md`, or `docs/PIPELINE-CHOICES.md`
for him. Those are his reasoning. Review, challenge, poke holes — don't write.
@@ -423,7 +423,7 @@ Things a well-meaning assistant does wrong here:
`db.system`, `server.address`). Namespace custom ones as `ledgerline.*`.
- `service.name` matches the directory name under `services/`.
- Duplication across services is fine. Don't refactor toward a shared framework.
- Docker Compose only, locally, through Phase 9. Kubernetes is a later
- Docker Compose only, locally, through Phase 10. Kubernetes is a later
follow-up — porting instrumentation and debugging a cluster at the same time
is how this stalls.
- Never save a Grafana dashboard from the UI.