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>
184 lines
13 KiB
Markdown
184 lines
13 KiB
Markdown
# 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)).
|