cocottetech/@platform/codebase/@features/ai-copilot/docs/tryst-connect.screen.md
natalie 1b719e1fd7 chore(bootstrap): initial V4 commit
Clean successor to V3 (forge: lilith/atlilith). Seeded from local Mac
working tree at ~/Code/@projects/@cocottetech/. node_modules and build
artifacts excluded via .gitignore.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 08:11:41 -07:00

184 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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…" 530s.
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)).