Connect-Desk-Project/README.md

120 lines
6.6 KiB
Markdown

# Connect Desk
One window. Every Amazon Connect login signed in at the same time.
```sh
npm start
```
## The problem it solves
All your accounts live on the **same** Connect domain and differ only by login. A browser profile
holds exactly one session per domain, so signing in as account B silently evicts account A — which is
why you ended up with a separate Chrome profile per brand.
Connect Desk gives every account its **own session partition** (its own cookie jar). Ten accounts stay
signed in simultaneously, side by side, in one window. Sessions persist across restarts: sign in once
per account and stay in.
## Why it isn't a web page
Connect sends `Content-Security-Policy: frame-ancestors 'self'`, which forbids any external site from
embedding the CCP in an iframe. Only the AWS account that *owns* the instance can allowlist an origin,
and these instances are owned by Amazon, not by you — so a browser-based dashboard is permanently
blocked.
`frame-ancestors` restricts documents embedded **in a frame**. Here each account is a **top-level
view**, not a frame, so the rule doesn't apply. Verified: the CCP loads in each partition with zero CSP
errors, and no AWS permission of any kind is required.
## The two instances
Accounts live on one of two Amazon Connect instances (separate directories, separate logins):
| Marketplaces | Instance |
|---|---|
| US, CA | `amazon-product-support-a67d8h.my.connect.aws/agent-app-v2` |
| UK, DE, FR, IT, ES, NL, BE, SE | `amazon-product-support-q42kxm.my.connect.aws/agent-app-v2` |
Each account is assigned to an instance when you add it, shown as a **US** / **EU** chip on its row,
and changeable from the right-click menu. The URLs are stored in `accounts.json` under `instances`
if they ever need editing.
## Using it
- **Sidebar** lists your accounts. Click one to switch; the others keep running in the background and
keep receiving chats (background throttling is disabled for exactly this reason).
- **Incoming chat** is impossible to miss: a full-sidebar popup, a native OS notification (Mac and
Windows), a beep, taskbar/Dock flash, and the app switches to the ringing account. Click the popup
or the OS notification to jump there. This still works if you were looking at a different account.
- **+ Add account** first asks which instance (US/CA or UK/EU) the account belongs to, creates a new
isolated session, and drops you straight into naming it. Names also fill in automatically from the
signed-in agent; a manual rename always wins.
- **Right-click an account** for Rename, Set Available, Set Offline, instance selection, Reload, and
Remove (native OS menu).
- **Right-click in a chat** for spelling suggestions plus Cut / Copy / Paste. Spellcheck is on for
Connect composers (US + UK English).
- **All Available / All Offline** flip every signed-in account's status at once; a toast summarizes
which accounts changed and which need sign-in.
- **Sign in all / Sign out all** manage sessions in bulk. Sign-out ends each session server-side,
wipes the account's cookies, and **pauses auto-login for that account** (otherwise saved sign-ins
would immediately log it back in) — the dot goes grey with a "signed out" chip. Sign in all (or
per-account right-click → Sign in) resumes auto-login. This state survives app restarts.
## Credentials
By default none are stored — each account view shows Connect's own login page and the session cookie
stays inside that account's partition.
**Saved sign-ins (optional, off until you use it):** the "Saved sign-ins…" panel stores a username +
password per account so accounts log themselves in — at startup and again whenever a session expires.
Each row has **Save** (store this account's credentials) and **Sign in** (save, then log this one
account in immediately); the footer has **Save all**, **Sign in all**, and **Close**. Saving never
signs anything in on its own — the two are separate deliberate actions. "Sign in all" works through
the accounts **one at a time** with a gap between each, so a dozen simultaneous logins don't hit
Amazon's auth endpoint at once.
How it's protected:
- Passwords are encrypted with the OS keychain-backed key (`safeStorage`: macOS Keychain / Windows
DPAPI) and stored as ciphertext in `credentials.json`. Never plaintext; `accounts.json` never
contains secrets; the file cannot be decrypted on another computer or by another OS user.
- Credentials are released to an account's view **only** when that view is on the account's real
Amazon login host (`<alias>.my.connect.aws` / `<alias>.awsapps.com`) — enforced in the main
process, so no other page can request them.
- At most 2 automatic attempts per account per 5 minutes, so a wrong password can't be hammered into
an account lockout.
- "forget" in the panel deletes an account's saved sign-in; removing an account does too.
- If the form can't be filled, **nothing is submitted** and a toast says why — an empty submit would
burn an auth attempt and push the account toward a lockout.
The sign-in page is a GWT app whose username box is `<input type="username" id="wdc_username">`
`username` is not a valid HTML input type, so the field is matched by name/id, never by type. The
page also carries a hidden `#wdc_organization` decoy and a hidden `#wdc_mfa` second password field;
both are deliberately skipped. If Amazon ever enables MFA on an account, auto sign-in cannot complete
it and you'll need to sign in manually.
The honest trade-off: anyone using your unlocked computer session can start the app and be signed in
— same as any password manager without a master password. Lock your machine.
## Known limits
- **One login per account, once.** AWS confirms there is no cross-account SSO without SAML federation,
which only the instance owner can configure. This app removes the *browser juggling*, not the logins.
- **Chat detection is best-effort.** It hooks Amazon Connect Streams (`window.connect`) in the CCP
iframe inside Agent Workspace, and falls back to scanning the page text if Streams never appears.
The fallback can break if Amazon restyles the CCP. Switching accounts and the sessions themselves
are unaffected either way.
- Ten-plus live CCPs is genuinely heavy. If it drags, remove accounts you aren't covering that day.
## Layout
| File | Role |
|---|---|
| `main.js` | Window, one partitioned `WebContentsView` per account, alerts, notifications |
| `probe.js` | Main-world Streams probe (injected into the CCP page and its iframes) |
| `preload.js` | Injected per account — relays contacts, status commands, login autofill |
| `ui-preload.js` | IPC bridge for the sidebar |
| `ui/` | Sidebar: account list, alerts, controls |