# tryst-connect.screen First-time auth-grant for Tryst — **two modes**: cookie-paste (fast) or full credentials (auto-re-login). Either way, the container adapter ([_engineering-surface-adapter-container.md](./_engineering-surface-adapter-container.md)) runs every subsequent action through a persistent fingerprinted browser session. Implements [surface-tryst.brief.md §2](./surface-tryst.brief.md). Reached from settings → Surfaces ([surfaces-settings.screen.md](./surfaces-settings.screen.md)) → "Connect Tryst" or from the persona-seed-interview when Tryst is selected. Voice: **plain** (security-shaped surface). ## Layout (full-screen sheet) ``` ┌─────────────────────────────────────────────────┐ │ ◄ Surfaces Done │ 56pt ├─────────────────────────────────────────────────┤ │ Connect Tryst │ title │ │ │ ─── How would you like to connect? ─── │ mode picker (always shown) │ ● Full credentials (auto-re-login, captcha) │ │ ○ Cookie-paste (fast, manual re-auth) │ │ │ │ ⓘ Either way, Cocotte runs actions through │ │ a private browser session that persists. │ │ Full mode lets her re-login when sessions │ │ expire. Cookie mode is faster to set up but │ │ you'll re-paste every ~30 days. │ │ │ │ ┌─────────────────────────────────────────────┐ │ mode panel (swaps per radio) │ │ │ │ │ │ …mode-specific fields below… │ │ │ │ │ │ │ └─────────────────────────────────────────────┘ │ │ │ │ ─── Verification ─── │ │ [ Test connection → ] │ universal — runs through container │ │ └─────────────────────────────────────────────────┘ ``` ## Mode panels ### Full credentials mode ``` │ Username or email │ │ ╭───────────────────────────────────────╮ │ │ │ transquinnftw@… │ │ not masked │ ╰───────────────────────────────────────╯ │ │ │ │ Password │ │ ╭───────────────────────────────────────╮ │ │ │ •••••••••• │ │ masked │ ╰───────────────────────────────────────╯ │ │ [ 👁 reveal · 8s ] │ ephemeral reveal │ │ │ ─── Two-factor (optional) ─── │ │ ╭───────────────────────────────────────╮ │ │ │ otpauth://... or raw base32 secret │ │ │ ╰───────────────────────────────────────╯ │ │ [ Scan QR code with camera ↗ ] │ ``` ### Cookie-paste mode ``` │ How to copy your session cookie │ numbered steps │ 1. Open tryst.link in Safari, sign in │ │ 2. Open Safari → Develop → Storage │ │ 3. Find the `session` cookie for tryst.link │ │ 4. Copy its value │ │ [ Open tryst.link ↗ ] [ Watch a 30s demo ▾ ] │ │ │ │ Paste session cookie │ │ ╭───────────────────────────────────────╮ │ │ │ session=… │ │ masked input │ ╰───────────────────────────────────────╯ │ │ ⓘ Stored encrypted; never logged or shared. │ │ │ │ ⓘ Cookie mode means you'll re-paste when │ │ Tryst rotates your session (~30 days, or │ │ sooner on password change / IP flag). │ ``` ## Components | Component | Notes | |---|---| | Top bar | Back + Done (Done disabled until Test connection succeeds). | | Mode radio | Persistent at top. Switching modes preserves any field values from the other mode (Quinn can switch back-and-forth without losing entries). Default: Full credentials (recommended). | | Mode-aware help chip | Inline explanation that updates per mode. Trade-offs explicit. | | Full-mode fields | Username + password + optional TOTP per the `_engineering-credentials-vault.md` shape. | | Cookie-mode fields | Single masked input + how-to steps. | | Test connection | Universal — both modes converge on a real container-driven verification (Playwright + Tor + fingerprint manager). For full mode this runs a login; for cookie mode it replays the cookie. | ## States (per mode) ### Shared states 1. **Empty** — mode chosen but fields empty; Test disabled. 2. **Testing connection** — banner: "Spinning up adapter… {logging in / replaying cookie}… verifying account…" 5–30s. 3. **Connection succeeded** — collapses to account preview: "Verified — @transquinnftw, TLC Premium tier, 3-city slot, Sumsub-verified through 2027-03-04, listing active." Done enabled. 4. **Connection failed (rate-limited)** — "Tryst's rate-limiting us. Wait 5 minutes and retry." 5. **Connection failed (account locked / under review)** — "Tryst flagged this account: {reason}. [Open tryst.link →] to resolve before connecting." 6. **Adapter pool exhausted** — "Cocotte's busy. Try in a minute." 7. **Tor pool degraded** — "Privacy network's down. Connect anyway via direct IP? (Less anonymous.)" 8. **Quinn cancels mid-test** — adapter aborts; container recycled. 9. **VoiceOver** — mode radio first, fields read with appropriate sensitivity hints. ### Full-credentials-mode states 10. **Login failed (wrong creds)** — "Cocotte couldn't sign in. Tryst said: invalid username or password." 11. **Login failed (2FA required, no secret given)** — "Tryst wants a 2FA code. Open Tryst → settings → 2FA → export the secret, or scan the QR." Focus returns to TOTP field. 12. **Captcha appeared, ML solver disabled** — "Tryst showed a captcha. [Run setup →] for the captcha-solver service." Routes to captcha-solver bootstrap (one-time setup of the v1 talent-scout port). 13. **Captcha appeared, ML solver failed** — "Tryst showed a captcha I couldn't auto-solve. [Solve it now →]" Routes to `captcha-solve.screen.md`. 14. **Bot-detection challenge (Cloudflare/Akamai)** — banner + Tor circuit rotation + retry up to 3 times. ### Cookie-paste-mode states 15. **Cookie format invalid** — inline error: "That doesn't look like a tryst.link session cookie." 16. **Cookie expired / Tryst doesn't accept it** — "Tryst rejected this cookie. It may have expired. Open tryst.link, re-sign-in, and re-copy." 17. **Cookie OK but profile fetch fails** — "Cookie works for sign-in but I couldn't read your profile. Connect anyway — Cocotte will retry profile fetch later." ## Interactions - **Tap a mode radio** → swap the mode panel; preserve other-mode field values. - **Tap "Reveal · 8s"** (full mode) → briefly unmask password. - **Tap "Scan QR"** (full mode) → iOS camera → parses `otpauth://` URL. - **Tap "Open tryst.link ↗"** (cookie mode) → in-app browser overlay. - **Tap "Watch a 30s demo"** (cookie mode) → inline video. - **Tap "Test connection"** → live verification through container. - **Tap "Save"** (after success) → commits to credentials vault per `_engineering-credentials-vault.md` (cookie mode: stores cookie blob; full mode: stores username+password+TOTP); writes `agent_actions` row `action_type='surface_connect'` with `auth_mode='cookie'` or `'credentials'`. - **Swipe-down with dirty** → "Discard? Credentials aren't saved." ## Re-auth behavior (mode-dependent) When Tryst rotates Quinn's session (~30d or earlier): - **Full mode**: adapter detects 401/403 → auto-re-runs login → uses stored creds + auto-generated TOTP + captcha-solver. Quinn rarely sees re-auth events; only failures escalate. - **Cookie mode**: adapter detects 401/403 → marks specialist degraded ([brief M §M2a](./M-error-degraded-modes.brief.md)) → surfaces in chat: "Your Tryst cookie expired. Open tryst-connect to paste a fresh one." Cocotte cannot self-recover; needs Quinn. This is the canonical trade-off: cookie mode = simpler setup, recurring micro-friction; full mode = upfront friction, recurring nothing. ## Mode-switching after initial setup Quinn can switch modes anytime via settings → Surfaces → Tryst → "Switch auth mode." Switching: - Cookie → Full: requires Quinn to enter username + password (+ TOTP if applicable); test connection runs through full login; if successful, cookie row archived in vault, full creds replace. - Full → Cookie: paste new cookie; full creds archived in vault (kept for switch-back); cookie replaces. Archive lets Quinn switch back without re-entering. K1 blocklist + brief V data-export both treat archived auth-state as Quinn's data. ## Edge cases - **Quinn has multiple Tryst accounts** — supported per `(user_id, lower(platform), lower(username))` unique key; connect sheet detects existing rows and offers "Update existing? Or add a new account?" - **Cookie mode + 2FA-protected account** — pasted cookies bypass 2FA at the session level (that's how cookies work), but only until Tryst forces re-auth. At that point, cookie mode fails → Quinn must either re-paste a fresh cookie or switch to full mode. - **Cookie pasted contains non-session data** (Quinn pasted the whole cookie blob, including tracking) — Cocotte extracts only the session key client-side; warns if extraction fails. - **Cookie pasted is for a different domain** — client-side rejects. - **Quinn pastes a cookie for an account that's not the username in the full-mode fields** — Cocotte warns about the handle mismatch. - **Both modes filled, Quinn taps Test** — uses the active radio's mode; other fields preserved. - **Reduced motion / Dynamic Type XXL** — mode radios stack; help chip wraps. ## *Generalization callout* The dual-mode pattern generalizes to all stored-creds surfaces: - **TS4Rent / Slixa / Eros / OF**: same dual-mode (cookie-fast + creds-full). - **X / Threads / Bluesky**: OAuth-only (no cookie mode; no creds mode); native iOS OAuth flow. - **WhatsApp / Telegram / Signal**: QR-pair only (closest to cookie mode in shape, but not paste-based). - **Bio-link aggregators (beacons, linktree, …)**: typically dual-mode supported. Per-surface variants override the mode-panel field shapes + the verify-call mechanics; the dual-radio meta-UX reuses. ## Related - [surface-tryst.brief.md §2](./surface-tryst.brief.md) — parent (dual-mode auth specified there). - [_engineering-surface-adapter-container.md](./_engineering-surface-adapter-container.md) — container that runs both modes' verification. - [_engineering-credentials-vault.md](./_engineering-credentials-vault.md) — encrypted storage of both modes' artifacts (cookie blob OR username/password/TOTP). - [surfaces-settings.screen.md](./surfaces-settings.screen.md) — entry from settings. - [persona-seed-interview.screen.md](./persona-seed-interview.screen.md) — entry from onboarding. - [specialist-bookings-tryst.contract.md](./specialist-bookings-tryst.contract.md) — consumer of the stored auth. - [Brief M §M2](./M-error-degraded-modes.brief.md) — re-auth-from-degraded entry; mode-dependent recovery. - [policy-card.screen.md](./policy-card.screen.md) — sibling; bumps start after connect. - [Brief V](./V-data-portability-erasure.brief.md) — both modes' auth artifacts are exportable + erasable. - Future `captcha-solve.screen.md` (HITL captcha) — surfaces state 13. - `.archive/ARCHIVED.md` — `talent-scout` archive map; captcha-solver model lives there. ## Out of scope - The `captcha-solve.screen.md` interior (deferred). - Browser-bookmarklet-based cookie extraction (defer; Quinn can copy manually). - Sumsub KYC re-up flow (separate screen — [tryst-verification.screen.md](./tryst-verification.screen.md)).