Skip to content

Standardize admin endpoint address path params - #81

Merged
addisonkline merged 1 commit into
mainfrom
kline/v2-admin-eps
Jun 25, 2026
Merged

Standardize admin endpoint address path params#81
addisonkline merged 1 commit into
mainfrom
kline/v2-admin-eps

Conversation

@addisonkline

Copy link
Copy Markdown
Collaborator

Summary

Standardizes how MAIL addresses are accepted as path parameters across the server admin (and list) endpoints. Previously the same conceptual identifier was expressed three different ways:

  • agents → partial/local address (name@swarm)
  • daemons / users → bare identifier (worker_name / user_id)
  • lists → full address (list:name@swarm@host)

None of these path params were declared to FastAPI (all read via request.path_params.get(...)), so they were undocumented in openapi.yaml and unvalidated — malformed input fell through to a 404 or 500.

The standard

The path param is now the resource's local identifier, with the user-agent prefix implied by the route and the host implied by the server:

Resource Path param
agents name@swarm
daemons worker_name
users user_id
swarms swarm_name
lists name@swarm
webhooks wh_<uuid>

member_address (list members) deliberately stays a full MAIL address — a member can be any user-agent, possibly remote under future federation.

Every by-id endpoint now uses a typed Path(...) param with description/example (documented in OpenAPI) and validates shape: 422 on malformed, 404 on well-formed-but-unknown.

Changes

  • Server: new path-param validators; admin.py and lists.py converted to typed Path params + validation; lists router normalizes local→full (_full_list_address) so backends keep their full-address key; agent_addresslocal_address rename through base.py (+ host: str Protocol attr), memory, and sqlite.
  • Protocol/client: corrected stale Corresponds to docstrings (incl. POST /admin/agent singular typo); fixed the daemon-get CLI arg bug (local_address/"daemon@swarm" → worker_name); clarified list-address help as local form.
  • Tests: updated lists/flows/e2e to local addresses, seed_list returns local form, added 422 path-param tests; regenerated spec/openapi.yaml.

⚠️ Breaking change

The list HTTP endpoints now take the local address (name@swarm) instead of the full list:name@swarm@host address. Message recipients are unaffected — they still use the full list: address (delivery resolution is unchanged). Sharing for team review before merge so callers can be updated; the server could be made to accept both forms during a transition if preferred.

Verification

  • 684 passed (default suite) + 6 e2e passed + OpenAPI drift check green
  • mypy clean (106 files); ruff check clean
  • Diff kept to semantic changes only (no unrelated reformatting)

🤖 Generated with Claude Code

Admin (and list) endpoints addressed resources by three inconsistent
slices of the canonical MAIL address: agents used a partial address
(name@swarm), daemons/users a bare id, and lists the full
list:name@swarm@host address. None of the path params were declared to
FastAPI, so they were undocumented in OpenAPI and unvalidated.

Standardize on a single rule: the path param is the resource's local
identifier, with the user-agent prefix implied by the route and the host
implied by the server (agents name@swarm, daemons worker_name, users
user_id, swarms swarm_name, lists name@swarm, webhooks wh_<uuid>).
member_address stays a full MAIL address — a list member may be any
user-agent, possibly remote.

- Add typed Path(...) params + shape validation across admin/lists
  routers: 422 on malformed, 404 on well-formed-but-unknown; params now
  documented in spec/openapi.yaml.
- Lists HTTP surface now addresses lists by local name@swarm; the router
  reconstructs the full list: key so backends are unchanged. Message
  recipients still use the full list: address (delivery unchanged).
- Rename agent_address -> local_address through base/memory/sqlite
  backends; declare host on the backend Protocol.
- Fix stale "Corresponds to" docstrings, the daemon-get CLI arg bug, and
  list-address help text (local form).
- Update tests + fixtures to local addresses; add 422 path-param tests.

BREAKING CHANGE: list HTTP endpoints now take the local address
(name@swarm) instead of the full list:name@swarm@host address.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@rheaton64 rheaton64 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi Addison —

Reviewed PR #81 and updated chorus to send the new local form
on the consumer side. Approving the PR via gh momentarily.

What I changed on chorus side (commit c299d29 on master):

  • Single shared helper chorus.mail._to_local_address that
    accepts every shape (full, local, list-prefixed full,
    list-prefixed local) and returns the local form. Idempotent
    on already-local inputs. Unfamiliar shapes pass through so
    your 422 validator gets a clean view rather than us
    silently mangling.

  • MailClient.delete_agent keeps the full-address parameter
    (chorus stores full addresses in mail_credentials for
    routing reasons), strips to local on the wire.

  • mb subscribe / mb unsubscribe keep accepting the
    user's full list:foo@chorus@chrn.ai form on the CLI
    (matches user habits and what other tools generate); the
    helper strips for the URL.

The PR itself reads cleanly. Specific things I noticed and
liked:

  • The chosen path-param vocabulary table (agents:
    name@swarm, daemons: worker_name, users:
    user_id, lists: name@swarm, webhooks:
    wh_<uuid>, member_address stays full) is the right
    set. Reserving member_address as full because a member can
    be remote under federation is the right hedge.

  • 422 on malformed vs 404 on well-formed-but-unknown
    is the discipline you want for documented path params.
    Catching the path-shape issue at the validator means
    client bugs surface with precise error messages rather
    than ambiguous 404s.

  • The list router's _full_list_address normalization
    preserves backend keys as full addresses so the storage
    layer doesn't need to change. Clean seam.

  • The CLI daemon-get arg bug fix (local_address /
    daemon@swarmworker_name) is the kind of thing
    that's easy to miss; glad you caught it in the same PR.

Two small things I'd note, neither blocking:

  1. The non-list endpoints' host is implied by the server.
    If MAIL ever supports multi-host deployment, the implication
    stops holding. That's far-future and you'd see it coming;
    just flagging that the standardization commits to
    single-host-per-server semantics here.

  2. member_address staying full is the right call for
    federation-future, but it's also the one path param that
    doesn't match the new pattern — worth a one-line comment
    at the route definition naming why, so future maintainers
    don't "fix" it.

Approving. Merge when ready.

— minichorus-pm

@addisonkline
addisonkline merged commit ae4478f into main Jun 25, 2026
2 checks passed
@addisonkline
addisonkline deleted the kline/v2-admin-eps branch June 25, 2026 21:15
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