Skip to content

update: use a routable owner email for smoke-test shards - #76

Merged
max-tet merged 1 commit into
mainfrom
fix/smoke-test-owner-email
Sep 15, 2026
Merged

max-tet merged 1 commit into
mainfrom
fix/smoke-test-owner-email

Conversation

@ClaydeCode

Copy link
Copy Markdown
Contributor

Summary

The smoke test assigned trial shards with OWNER_EMAIL = "smoke-test@freeshard.invalid", picked so that nothing could reach a real mailbox. The shard core rejects exactly that class of address, and it does so destructively: every trial shard the smoke test touched was bricked on its first pairing attempt.

Switches to a routable address and records why in agents.md, so the next person does not reintroduce an unroutable one for the same good-sounding reason.

The failure this fixes

On the pairing POST, core 0.40.5:

  1. redeem_pairing_code() succeeds and deletes the code — the core stores exactly one.
  2. The terminal is the first, so async_on_first_terminal_add fires.
  3. enrich_identity_from_profile reads owner_email from the controller profile and calls update_identity(id, {"email": ...}).
  4. update_identity writes the row, then builds Identity(**updated). The @field_validator("email") rejects the reserved .invalid TLD (RFC 2606) → 500.
  5. The write already landed, so every later get_default_identity() raises: /public/meta/whoareyou, /public/meta/avatar, and the pairing handler's own cookie-domain lookup. The shard is unpairable by anyone, and no API path can correct the address because they all read the identity first.

Shard 349 (e1kn8b.freeshard.cloud) was lost this way on 2026-09-15. Full chain in diagnostic 8d52dbf2-6a5b-4ba1-818f-e6053943947c.

Not fixed here

The masking retry. update/smoke_test.py:53 lists 500 in TRANSIENT_STATUS, so core_request replays the pairing POST 2s later with the same single-use code. The code was consumed by the first attempt, so the retry returns a genuine 401 This pairing code is not valid — and 401 is not transient, so that is what the script reports. The real 500 never surfaces. It cost a diagnostic to find, and it is latent again the moment pairing 500s for any other reason. A single-use credential should not be replayed by a generic retry; happy to do that separately.

The controller side. /assign_trial types owner_email as a bare str | None, the only email entry point in the controller that is not an EmailStr. FreeshardBase/freeshard-controller#229 and its PR #391 cover it; I added the field evidence to that thread. Verified against pydantic 2.13.5 that EmailStr rejects this exact address, so #391 would have turned this into a 422 at the boundary.

The core side is already fixed on freeshard mainFreeshardBase/freeshard#220 dropped identities.email entirely, and validation moved to InputUser at the write boundary with the read model left unvalidated. The fleet still runs 0.40.5, so that fix is merged but not rolled out.

Recommended reading order

  1. update/smoke_test.py — the constant and its comment
  2. agents.md — the "Smoke-testing a bundle" paragraph

🤖 Generated with Claude Code

The smoke test stamped assigned shards with smoke-test@freeshard.invalid,
chosen so that nothing could reach a mailbox. The core rejects exactly that
class of address, and not harmlessly.

On the first pairing, enrich_identity_from_profile reads owner_email from the
controller profile and calls update_identity, which writes the row and only
then constructs Identity(**updated). The email field validator rejects the
reserved .invalid TLD (RFC 2606), so the request 500s with the bad value
already persisted. Every later get_default_identity() raises, which takes out
/public/meta/whoareyou, the avatar route and the pairing handler's own cookie
lookup. The shard can never be paired, and no API path can correct the address
because they all read the identity first.

Shard 349 was lost this way on 2026-09-15; diagnostic
8d52dbf2-6a5b-4ba1-818f-e6053943947c has the full chain. The controller is the
upstream cause: /assign_trial types owner_email as a bare str while every other
email entry point uses EmailStr, tracked in
FreeshardBase/freeshard-controller#229.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@max-tet
max-tet merged commit 14187e5 into main Sep 15, 2026
2 checks passed
@max-tet
max-tet deleted the fix/smoke-test-owner-email branch September 15, 2026 13:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants