Repository navigation
Commit 254e511
fix(infra): compare the gate's service sets, not their counts
Second review round on the PR. Nine findings were real; four were not, and
are listed at the bottom with what settled them.
**The readiness gate could pass a stack missing a declared service.** Its
exit condition was `no unhealthy rows && observed == declared`. One service
never created plus one orphan still running gives equal counts, so the gate
broke out reporting success. I added the missing/extra sets in the previous
commit for the diagnostic message and left the exit test on counts — the
sets were computed one branch too late to be used for the decision.
Proven on a live stack rather than argued: `meilisearch` removed, a healthy
orphan `ghost` created by Compose itself under the same project, 14 observed
against 14 declared, everything else green. Old condition → `exit 0`, "All
compose services running; every healthcheck green". New condition → `exit 1`,
"saw 14 of 14 declared services; never created: meilisearch; orphaned
(docker compose down --remove-orphans): ghost". Healthy stack still exits 0.
Getting that proof took two false starts worth recording, both the same
shape as everything else this branch has been fixing. A hand-built orphan
carrying Compose's labels is not counted by `docker compose ps`, so the
scenario I first "reproduced" never existed. Then the old-condition copy ran
from the scratchpad, where `REPO_ROOT` resolves relative to `BASH_SOURCE`, so
it inspected an empty directory and failed for a reason that had nothing to do
with the condition under test.
**`TenantContextBehavior`'s comment described RLS as working.** It read "they
are issued by `TransactionBehavior` at step 6". `grep -rn "set_config\|SET LOCAL"
backend/src` returns nothing: no code in this repository sets the GUCs, and
RLS is not enforced at runtime until Packet 7. The reasoning about *why* the
GUCs belong inside the transaction is correct and stays; the tense does not.
**ADR-0032's registration sample was still missing its guards** — the three
`ArgumentNullException`/`ArgumentException` lines the shipped
`ProviderResilienceRegistration` opens with. This is the same fence whose
earlier comparison reported "13 lines, zero differences" because the
normaliser dropped exactly the `ArgumentNullException` lines. The skill's copy
has them; the ADR's did not. Recorded in Amendment 2; § Decision is
byte-identical to `main` (same md5).
**Phase 01's defect list said "All of these were remediated".** One of its six
entries is branch protection, which was *deferred by maintainer decision*, not
fixed. Now scoped, with the trigger named.
**`DROP DATABASE keycloak` was documented with Keycloak still running.**
PostgreSQL refuses to drop a database with a connected client, and Keycloak
holds its pool for its whole lifetime. Stop first, `up -d` after.
**`local-dev-setup` grew a fifth copy of the service inventory.** The previous
commit rebuilt that table from `docker compose config` — accurate, and a second
source of truth next to `infra/compose/README.md`, which carries image,
endpoint and credentials for every service. Replaced with a link plus the three
facts a reader setting up actually needs from it.
Also: both canonical producer fences dropped `CohortId`, a field the command
carries and the event declares, so anyone copying either silently lost it;
README's "two images cannot carry one" conflated the gate's input (Compose
service definitions) with the reason (`daprio/placement` and `daprio/daprd`
ship a single binary on an empty base), and now names both.
**The three new Standards 12 sections cite their derivation** — ADR-0002 for
the compose-stack rules, ADR-0035 for development credentials. I did not mint
an ADR: these tighten how an existing decision is operated rather than deciding
anything new, and the file already derives from six ADRs. If you want a
dedicated record for the dev-loop hygiene rules, that is your call to make.
My own check caught that I had cited a "§ Network Exposure" heading that does
not exist in Standards 11; it points at § Transport now.
Not changed, with the reason:
- **Convert the adapter's `text` flow diagram to mermaid.** CLAUDE.md's mermaid
rule governs documentation diagrams and requires a readable text fallback —
which is what this fence already is. Three skills use `text` flows and one
uses mermaid; converting one of the three makes the corpus less consistent,
not more. A sweep is its own change.
- **Rewrite ADR-0017's remaining Identity references.** Deliberate. Amendment 2
carries the correction and dated banners sit above each stale passage; the
body below them is the record of what was decided in May. Editing it would
undo the governance choice the amendment exists to express.
- **"`List<Entity<CourseId>>.Contains(b)` should say same-id true, different-id
false."** The sentence is describing the *defect* a sneaky explicit
re-implementation produces — `Contains` answering true for different ids —
which is the measured behaviour the entry exists to warn about. Correct as
written.
- **Add `.env` as a prerequisite to `down` / `clean` / `logs` / `ps`.** Those
targets work without it: every compose variable has a `${VAR:-default}`
fallback and the project name is a literal in `dev.yml`. Creating a file as
a side effect of tearing down is worse than the inconsistency.
227 tests green, build 0/0, format clean, 1337 links resolve, gate exercised
against a live 14-service stack and torn down.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>1 parent 1f62d3d commit 254e511
10 files changed
Lines changed: 81 additions & 51 deletions
File tree
- .claude/skills
- add-integration-event
- add-mediatr-handler
- local-dev-setup
- backend/src/LearnStack.Application/Pipeline
- docs
- decisions
- roadmap
- standards
- infra/keycloak
- scripts
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
87 | 87 | | |
88 | 88 | | |
89 | 89 | | |
| 90 | + | |
90 | 91 | | |
91 | 92 | | |
92 | 93 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
150 | 150 | | |
151 | 151 | | |
152 | 152 | | |
| 153 | + | |
153 | 154 | | |
154 | 155 | | |
155 | 156 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
105 | 105 | | |
106 | 106 | | |
107 | 107 | | |
108 | | - | |
109 | | - | |
110 | | - | |
111 | | - | |
112 | | - | |
113 | | - | |
114 | | - | |
115 | | - | |
116 | | - | |
117 | | - | |
118 | | - | |
119 | | - | |
120 | | - | |
121 | | - | |
122 | | - | |
123 | | - | |
124 | | - | |
125 | | - | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
133 | | - | |
134 | | - | |
135 | | - | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
136 | 130 | | |
137 | 131 | | |
138 | 132 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
73 | 73 | | |
74 | 74 | | |
75 | 75 | | |
76 | | - | |
77 | | - | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
78 | 81 | | |
79 | 82 | | |
80 | 83 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
52 | | - | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
58 | | - | |
59 | | - | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
60 | 63 | | |
61 | 64 | | |
62 | 65 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
575 | 575 | | |
576 | 576 | | |
577 | 577 | | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
| 581 | + | |
578 | 582 | | |
579 | 583 | | |
580 | 584 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
111 | 111 | | |
112 | 112 | | |
113 | 113 | | |
114 | | - | |
115 | | - | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
116 | 120 | | |
117 | 121 | | |
118 | 122 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
88 | 88 | | |
89 | 89 | | |
90 | 90 | | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
91 | 95 | | |
92 | 96 | | |
93 | 97 | | |
| |||
106 | 110 | | |
107 | 111 | | |
108 | 112 | | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
109 | 116 | | |
110 | 117 | | |
111 | 118 | | |
| |||
124 | 131 | | |
125 | 132 | | |
126 | 133 | | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
127 | 138 | | |
128 | 139 | | |
129 | 140 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
107 | 107 | | |
108 | 108 | | |
109 | 109 | | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
110 | 113 | | |
111 | 114 | | |
112 | 115 | | |
113 | 116 | | |
114 | | - | |
| 117 | + | |
115 | 118 | | |
116 | 119 | | |
117 | 120 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
116 | 116 | | |
117 | 117 | | |
118 | 118 | | |
119 | | - | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
120 | 133 | | |
121 | 134 | | |
122 | | - | |
| 135 | + | |
| 136 | + | |
123 | 137 | | |
124 | 138 | | |
125 | 139 | | |
126 | | - | |
127 | | - | |
128 | | - | |
129 | | - | |
130 | | - | |
131 | | - | |
132 | | - | |
133 | | - | |
134 | 140 | | |
135 | 141 | | |
136 | 142 | | |
| |||
0 commit comments