- Shipped
- August 5, 2026 at 10:37 PM UTC
- Author
- Kamo
- Commit
- 1a83506
A message header knows an address and whatever display name the sender chose to put beside it. The organization already knows far more — colleagues, address books, extensions, timezones — and none of it reached the mailbox. POST **************** answers a batch of addresses with the person behind each: colleague (with job title, department, extension, timezone and a member id that unlocks presence and chat), saved contact (with employer, title and numbers), or an explicit EXTERNAL so the caller can cache the answer instead of re-asking on every hover. Deliberately separate from the avatar endpoint rather than folded into it. That one is two-phase by necessity — a full miss can mean DNS plus four HTTP calls to third parties — and this is a handful of local, indexed, org-scoped reads that can answer completely on the first call. Sharing an endpoint would force the synchronous half to inherit an "ask again later" contract it does not need. Keyed on the bare address and never on the display name, which is attacker-controlled text: an outsider can set theirs to a colleague's real name, and this record carries that colleague's direct-dial extension. The normalizer that enforces that is now shared with the avatar endpoint (MailboxAddress), so the two cannot drift apart and miss each other's cache entries. The organization comes from the session, never the request — the endpoint answers "does this tenant hold a record for this address", which is a membership oracle if the caller picks the tenant. Ids serialize as strings: CockroachDB row ids run past MAX_SAFE_INTEGER, and EmailService has no global Long-to-string mapper because message uids are longs the mailbox front end genuinely treats as numbers.