|
1 | 1 | # ChannelGate — Test Plan |
2 | 2 |
|
| 3 | +## Email accounts (2026-10-22) |
| 4 | + |
| 5 | +### Regression |
| 6 | +- [x] Automated: `node --test test/email-accounts.test.js`. |
| 7 | + - One-form rules: port defaults, security by port, SMTP credentials falling back to IMAP's, |
| 8 | + name/address/port/user validation, loopback/private/link-local/metadata hosts refused by |
| 9 | + name and literal. |
| 10 | + - Updates: blank passwords keep the stored ones, a rotated IMAP password follows into a shared |
| 11 | + SMTP password and leaves a distinct one alone. Upsert by name, the five-entry cap, remove. |
| 12 | + The masked list and `emailAccountSecrets` never disagree; malformed rows are dropped. |
| 13 | + - Run resolution: channel accounts always, personal accounts only for a trusted principal; |
| 14 | + `selectEmailAccount` with bare names, `personal/` / `channel/` / `my/` prefixes, addresses, |
| 15 | + the single-account default and the cross-scope name clash. |
| 16 | + - Store: the connection test receives the MERGED record (stored passwords on an update), a |
| 17 | + failing test stores nothing, the interactive `authorize` re-check runs after it, audit rows |
| 18 | + carry no password; personal accounts on the user record. |
| 19 | + - Tools (fake mail client): every tool registered and in `GATEWAY_TOOL_NAMES`; the verified |
| 20 | + author sees channel + own, an untrusted principal and another person do not see the personal |
| 21 | + account; search/read/move/flag pass the chosen account through and render compactly; |
| 22 | + attachment downloads land under `uploads/email/<account>/` with a sanitized name; `email_send` |
| 23 | + attaches only confined files (a symlink out of the folder and a `../` path are refused) and |
| 24 | + refuses an account with sending off before any client call. |
| 25 | + - `resolveRunIntegrations` returns every channel and personal password as `emailSecrets`, and no |
| 26 | + personal password for an untrusted principal. |
| 27 | + - Admin routes: channel and user PUT/GET/DELETE, the failing-login 400 without the password, |
| 28 | + the loopback refusal, `GET /api/channels` and `/api/users` listings without a password. |
| 29 | +- [x] Automated: `node --test test/slack-email-account-settings.test.js` — the Slack Settings |
| 30 | + inline forms (`em-add:<scope>`, `em:<scope>:<name>`), the MCP and You page sections, manager |
| 31 | + gating, masked rendering, the password-field error mapping. |
| 32 | +- [x] Automated: `node --test test/teams-email-account-settings.test.js |
| 33 | + test/conversation-settings-email.test.js` — the Teams MCPs page blocks and |
| 34 | + `settings.email.save/remove`, public-card refusal, the confirm round-trip, the private browser |
| 35 | + form's save/remove and masked listing. |
| 36 | +- [x] `test/folders-settings.test.js` tracks the new tool module in the permission allowlist; |
| 37 | + `test/progress-report-availability.test.js` still proves the integration resolver's shape. |
| 38 | + |
| 39 | +### Live gates (Claude AND Codex) — UNEXECUTED |
| 40 | +Fixture: a disposable conversation in Worker mode. A mailbox on a public IMAP/SMTP host you own |
| 41 | +(any provider that issues app passwords, or a test domain on a transactional relay with an IMAP |
| 42 | +inbox). Record the address and the servers; never the password. |
| 43 | +- [ ] Connect (dashboard): admin UI → the conversation → Connections → *Email accounts*: name |
| 44 | + `qa`, the address, IMAP host/user/password, SMTP host (ports blank). Pass: the hint says both |
| 45 | + logins were verified, the row shows `qa`, the address, `imap…:993` and `smtp…:587`; |
| 46 | + `GET /api/channels` contains no password. A wrong password answers "IMAP login failed (…)" and |
| 47 | + stores nothing. `127.0.0.1` or a private host name as the IMAP server is refused. |
| 48 | +- [ ] Connect (Slack): ⚙️ Settings → **MCP** → *+ Connect email account* as a channel manager |
| 49 | + (name `qa2`); a non-manager sees the list but no button. ⚙️ Settings → **You** → connect |
| 50 | + `mine`. Pass: the modal acknowledges at once, the row appears masked, no password in the view |
| 51 | + payload (`views.update` body) or in Slack history. |
| 52 | +- [ ] Connect (Teams and Google Chat): Teams Settings → MCPs → *Email accounts* save; Google Chat |
| 53 | + Settings → *Open private settings* → the browser form. Pass: the account appears masked on the |
| 54 | + card and the page; the Chat card itself has no password input. |
| 55 | +- [ ] Read, Claude then Codex (`codex …` directive): "List my newest 5 emails in qa and read the |
| 56 | + first one; save its attachment." Pass: `email_search` output, `email_read` with headers and |
| 57 | + body, `email_download_attachment` saves under `uploads/email/qa/` and the reply names the |
| 58 | + file with a 📄 button. No password in the reply or the artifact dir (`grep -r <password>`). |
| 59 | +- [ ] Send, both engines: "Send an email from qa to <your address>, subject QA, attaching that |
| 60 | + file, replying to the message you read." Pass: the agent confirms recipients first (or the |
| 61 | + prompt gave them), the mail arrives threaded (`In-Reply-To` set), with the attachment, From the |
| 62 | + account's address and display name; a copy sits in the Sent folder where the server has one; |
| 63 | + the reply names the account used. With *allow sending* off, the tool refuses and the agent |
| 64 | + reports it without trying another account. |
| 65 | +- [ ] Scope: the personal account `mine` is used by its owner's turn, absent from another approved |
| 66 | + user's turn in the same conversation and from a `POST /api/runs` turn; a bare name present in |
| 67 | + both scopes makes the agent ask which one. Lean mode does not hide the tools (they are gateway |
| 68 | + tools) but the memory reviewer's run has none. |
| 69 | +- [ ] Rotation and removal: change the IMAP password with the SMTP box blank (shared password) — |
| 70 | + the next send still works; remove the account — the next turn reports it absent. |
| 71 | + |
3 | 72 | ## Registered inventory caps and Enterprise harness approvals (2026-10-22) |
4 | 73 |
|
5 | 74 | - [x] Automated `test/license-registration.test.js`: signed Registered and no-key fixtures admit |
|
0 commit comments