An audit against the standard the series set — concepts, procedure,
commands, architecture diagram, evidence table, terminal output — found the
three new experiments met it while twelve of the original ones had no
diagram at all: A-0, A-1, A-3, A-4, A-5, A-6, A-8, B-0, B-2, B-7, C-2, D-2.
Each now has one drawn from what that experiment actually found, not filler:
A-0 shows sharing going through PostgreSQL rather than between the caches;
A-3 the gap between the 200 and the WAL flush, with both failed injections;
A-5 the three silent injection failures; A-6 the two places latency is
multiplied; B-0 the repository keyed by principal with no session id; B-2
the primary key that causes the overwrite; D-2 why the rolling update
stopped the accident halfway.
Also corrected the index's stale claim of 11 experiments without a
screenshot — it is 14, and the reason is recorded: those experiments were
measured from terminals, the database and logs, and the observability stack
does not scrape Redis, the BFF or PostgreSQL, so there is no console to
photograph.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The audit found ~80 placeholders, and the damaging ones were where the
measuring apparatus itself was prose rather than a command:
a6 "( curl ... ) & 를 20개 띄우고 wait" — the 22.2s headline came from this
a3 "<로그인 반복, sid 를 /tmp/sids 에>" — the whole RPO measurement
a3 "<sid 목록>" — the control it is compared against
a5 "<수신 파드IP>" — the injection
a8 writes /tmp/tok, reads /tmp/rt — self-inconsistent, sent an empty token
b3 $KC / $RT / $NEW never assigned
c2 bare kcadm.sh with no kubectl exec
a1 conntrack tuples written by hand, though the direction flips per restart
Each is now a shell-expandable form: pod IPs from jsonpath, the admin password
from the secret, ids from kcadm --format csv, conntrack tuples derived from
"conntrack -L" with awk rather than transcribed.
Then the rewritten commands were executed against the live cluster, and one
of them failed — the 20-way load generator, written as "kubectl run --rm -i",
lost its output stream twice in a row. That is a trap this series already hit
once, and the rewrite reintroduced it. A-6 now uses a resident probe pod that
collects into a file and is cat-ed once; verified 20/20 lines.
Evidence: docs/evidence/followup/05-command-reproducibility.txt
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
An independent audit found ten documents printing values their evidence files do not contain. C-1 printed a session count of 0 where the evidence says 4, C-2 printed a success readback for a command that exited 1, and A-1 credited the conntrack flush with a split that the timestamps attribute to a pod restart four seconds earlier.
Also measured wal_writer_delay, which A-3 had asserted as matching without ever querying it, relabelled the A-6 control that moved 41 percent, noted A-8's nine-sample resolution, corrected D-1's RTO to the 41 seconds its own timeline shows, and added a correction banner to D-2. Every experiment document now links its evidence files with their real collection times, and the duplicate screenshots are documented as duplicates.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Cutting TCP 7800 leaves cross-node refresh working (200), confirming sessions travel through PostgreSQL rather than the cluster transport. Logout is the opposite: the database row is deleted but the other node answers from its stale local cache, so the A-0 conclusion that invalidation rides the database is corrected here.
Two things the plan did not anticipate: a NetworkPolicy cannot sever an established connection because conntrack accepts it before policy evaluation, and Keycloak reports the partition through its readiness probe so the split node removes itself from the Service.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>