# Assigning a mailbox role, end to end

A role names the kind of work a mailbox is for, and Connect reads it when it chooses where a new conversation should start. Assigning one is a settings change with no provider call behind it: nothing moves at Gmail, Graph or your IMAP server. It takes effect for threads created after the change, and every conversation already running keeps the mailbox it was bound to.

- **Status:** Available
- **Audience:** both
- **Channels:** email
- **In the app:** #/mailboxes
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/docs/workflows/mailbox-role-assignment/

## The flow, stage by stage

1. Trigger — an administrator changes the role on a mailbox row.
2. User event — a request from a browser carrying one mailbox id and one role.
3. Authentication and workspace resolution — the session is resolved and the mailbox is fetched through `mailbox_console.row_for`, so an id typed by a browser cannot reach another workspace's row.
4. Ingest — the role is validated against the roles the workspace supports; an unknown value is refused rather than stored.
5. Canonical record — the role is written on the mailbox beside its signature, autonomy and health verdicts, through the one policy module both audiences share.
6. Classification and reasoning — none. This is a stated decision, not an inference, and no model is asked anything.
7. Knowledge, memory and rules — untouched. Guidance recorded against a contact still applies to what is written; the role only decides where it is written from.
8. Autonomy and approval — untouched. A role says which mailbox; autonomy says whether Connect may send at all, and the two are set separately on purpose.
9. Action through a provider — none. No label, folder, alias or forwarding rule changes at the provider.
10. Result — the next conversation that needs a sending mailbox resolves against the new roles.
11. Relationship, timeline and memory — nothing is added to a person's timeline; no customer-visible event has happened.
12. Audit, usage and Needs You — the change is recorded with who made it, and no allowance is consumed.

> **Note** Stage three is not paperwork. Four mailbox routes once took an id from a browser and looked the row up directly, which can answer for another workspace's mailbox when that row is already loaded in memory. They go through one lookup now, and the lesson generalises: a settings screen is an API surface.

## What each stage looks like from the outside

| Stage | What you see | What changes | What can fail |
|---|---|---|---|
| Request | The role control on the mailbox row | Nothing yet | A stale screen offering a mailbox that has since been disconnected |
| Resolution | No visible step | Nothing | A mailbox with an empty workspace stamp is not returned by any scoped lookup |
| Store | The row redraws with its new role | One column on one mailbox | Two mailboxes left holding a role that expects one |
| Routing | The next new conversation | Which mailbox is chosen for a first message | The chosen mailbox has no working send path |
| Audit | The decision log | One entry naming the person and the change | Nothing — a refused change is recorded too |

## What the change does and does not re-route

- **Re-routed:** the mailbox chosen for a conversation that starts after the change — an outreach message, a first contact, a reply on a thread that Connect itself begins.
- **Not re-routed:** every existing thread. A conversation is bound to the mailbox that received it, and keeps that binding so the recipient's client keeps one thread instead of two.
- **Not re-routed:** mail already arriving at the old mailbox. Where mail lands is decided by aliases and forwarding at the provider, which a role in Connect cannot reach.
- **Not changed:** the signature, which belongs to the mailbox rather than to the role, and the autonomy rule, which is set per mailbox and per channel.

That combination explains the most common surprise after a role change: new conversations behave as intended while an older, busier thread carries on exactly as before. Both are correct. If an old thread genuinely needs to move, the honest move is to say so in the thread and let the next one start in the right place.

## Failure modes worth knowing before you change one

**The role points at a mailbox that cannot send** — A mailbox connected for reading only will be chosen and then have nothing to send with. Check the mailbox's health, not its connection state.
**Two mailboxes claim the same job** — Resolution still returns one of them, and which one is not something to rely on. Give one mailbox the role and leave the other without it.
**The workspace ends up with no primary mailbox** — First messages lose their fallback. That case has its own repair, described in [Repairing a workspace with no primary mailbox](/docs/workflows/primary-mailbox-repair/).
**The mailbox is not in the list at all** — An empty workspace stamp makes a row invisible to every scoped list while by-id actions still work. No screen can repair it; the boot-time migration does.

> **Careful** Changing a role does not widen what Connect may do. A mailbox switched to a customer-facing role under `ask_before_send` still holds every reply for a person. Read the autonomy setting at the same time, or the change will look as though it did nothing.

## Verifying it worked

1. Re-open the Mailboxes screen after the change and read the row back.
   - Result: The stored role is what routing will read. A screen that still shows the old value is a stale view, not a failed write.
2. Start one new conversation — an outreach message or a follow-up that has not run yet.
   - Result: The from-address on that message is the real proof. An existing thread proves nothing, because it was never going to move.
3. Check the decision log for the entry naming the change.
   - Result: You have a record of who changed the routing and when, which is the question asked months later when a thread looks odd.

## Questions

### Does assigning a role move mail between mailboxes?

No. Nothing at the provider changes, and no message is copied or moved. A role decides which mailbox Connect sends *from* when it starts something new; where mail arrives is an alias and forwarding question at Gmail, Microsoft or your own server.

### Two mailboxes have the same role. Which one wins?

One of them is chosen, and the choice is not something to design around. Treat it as a misconfiguration: leave the role on the mailbox that should own the work and remove it from the other.

### Can a customer workspace assign roles, or is this operator-only?

Both audiences do it over the same implementation and the same policy module. The Owner's own handlers were rewired onto that module rather than kept as a second version, so the behaviour described here is one behaviour.

## Related

- [Mailbox roles](https://connectbyjbrh.com/docs/email/mailbox-roles/)
- [The primary mailbox](https://connectbyjbrh.com/docs/email/primary-mailbox/)
- [Repairing a workspace with no primary mailbox](https://connectbyjbrh.com/docs/workflows/primary-mailbox-repair/)
- [The reply went from the wrong address](https://connectbyjbrh.com/docs/troubleshooting/wrong-mailbox-sent/)
- [One implementation, two audiences](https://connectbyjbrh.com/research/two-audiences-one-implementation/)

## What this page is based on

- CHANNELS.md §1 — mailboxes, roles and the four routes now going through `row_for`
- GENERAL.md §5 — autonomy scopes and the audit trail
- `backend/app/mailboxes.py`, `mailbox_console.py`
- Connect capability registry (docs-source/facts.py) — `mailbox_roles`
