update: use a routable owner email for smoke-test shards - #76
Merged
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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:
redeem_pairing_code()succeeds and deletes the code — the core stores exactly one.async_on_first_terminal_addfires.enrich_identity_from_profilereadsowner_emailfrom the controller profile and callsupdate_identity(id, {"email": ...}).update_identitywrites the row, then buildsIdentity(**updated). The@field_validator("email")rejects the reserved.invalidTLD (RFC 2606) → 500.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 diagnostic8d52dbf2-6a5b-4ba1-818f-e6053943947c.Not fixed here
The masking retry.
update/smoke_test.py:53lists 500 inTRANSIENT_STATUS, socore_requestreplays the pairing POST 2s later with the same single-use code. The code was consumed by the first attempt, so the retry returns a genuine401 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_trialtypesowner_emailas a barestr | None, the only email entry point in the controller that is not anEmailStr. FreeshardBase/freeshard-controller#229 and its PR #391 cover it; I added the field evidence to that thread. Verified against pydantic 2.13.5 thatEmailStrrejects this exact address, so #391 would have turned this into a 422 at the boundary.The core side is already fixed on
freeshardmain— FreeshardBase/freeshard#220 droppedidentities.emailentirely, and validation moved toInputUserat 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
update/smoke_test.py— the constant and its commentagents.md— the "Smoke-testing a bundle" paragraph🤖 Generated with Claude Code