diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-12 12:14:40 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-12 16:36:54 +0200 |
| commit | 17c06bc23252929af13f4361c4a6300ee76a0c51 (patch) | |
| tree | 0f6cc4e0e3680ac253a88ccad580e97019abf77f /CLAUDE.md | |
| parent | c8462c6060ccd2cccb305edcd64ef12a675f2f58 (diff) | |
| download | meshbay-17c06bc23252929af13f4361c4a6300ee76a0c51.tar.gz | |
docs: AV13–AV15, and two lessons from how they were found
AV13 the mail gate, AV14 the MHP audience and the hub's own identity, AV15
the shape check on the unauthenticated blocklist endpoints. §13.5b also
records the auto-block threshold as an open decision rather than a defect.
Two lessons, both about tests.
A fixture narrower than production tests the fixture — and when it writes down
*why* it has to be narrow, that is a bug report nobody filed. Two test helpers
described the federation defects accurately, in comments, while routing
around them.
And a global's state is not a given, in a test least of all. One assertion —
that a refusal never logs the address — took three attempts, each passing
alone and failing in the full run, for three different reasons: caplog saw
nothing because the app configures logging, then a handler saw nothing
because an earlier test raised the logger's level, then because `disabled`
was left True.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T4YmK41VsEURWFdop4EEeT
Diffstat (limited to 'CLAUDE.md')
| -rw-r--r-- | CLAUDE.md | 23 |
1 files changed, 22 insertions, 1 deletions
@@ -122,7 +122,7 @@ that produced it. | Looking for | Read | |---|---| | What a label means (`C1`, `H3`, `NS6`, `T3`, `C5b`, `W2`, `E9`, `F1`, `AV4`, …) | `docs/MESHBAY_DESIGN.md` §13 | -| What one member can cost the others (`AV1`–`AV12`) | §13.5b — the newest category, and the one the first three reviews had no question for | +| What one member can cost the others (`AV1`–`AV15`) | §13.5b — the newest category, and the one the first three reviews had no question for | | Trust model, and what the project may and may not claim | §2 | | Identity, devices, admission, recovery, the keypair bundle | §3 | | Cryptography, key hierarchy, the group and chat envelopes | §4 | @@ -148,6 +148,27 @@ These are about working on the tree rather than about the design: interface, for the web and the app alike; `packages/meshbay-client/scripts/ sync-ui.js` copies it (`npm run sync-ui`) and CI fails if the copy drifts — **never edit `packages/meshbay-client/ui/` by hand** +- **A test fixture narrower than production tests the fixture — and when it + writes down *why* it has to be narrow, that is a bug report nobody filed.** + `test_federation.py` built its MHP envelopes by hand without an `aud`, and + `test_public_groups_toggle.py` signed its own token with a comment saying + `_issue_mhp_token` "binds `_hub_sk_pem` at import time, before the lifespan + loads it, so it cannot be used from a test", and another saying PyJWT + rejects a token carrying `aud` when decode is given none. Both observations + were exactly right. Between them, MHP could not complete a single + authenticated request between two real hubs, and the hub announced itself as + `meshbay.org` whatever it was configured as — for a month, with the suite + green. When a test has to route around the code to run, the thing it routed + around is the finding. Federation's tokens now come from the real issuer + +- **A global's state is not a given, in a test least of all.** One assertion — + that a refusal never logs the address — took three attempts: `caplog` saw + nothing because the app configures logging, then a handler on the module's + own logger saw nothing because an earlier test had raised its level, then + because `logger.disabled` was left True. Each version passed alone and + failed in the full run. Pin what you depend on (level, `.disabled`, + `logging.disable`) or assert on a value instead of on a side effect + - **A blocking call in an async handler is the whole instance's problem.** `mail._send` is `smtplib` with a ten-second timeout, and it was called straight from four handlers: while the MTA thought about it, nothing else was |