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>
13 KiB
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) runs every subsequent action through a persistent fingerprinted browser session.
Implements surface-tryst.brief.md §2. Reached from settings → Surfaces (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
- Empty — mode chosen but fields empty; Test disabled.
- Testing connection — banner: "Spinning up adapter… {logging in / replaying cookie}… verifying account…" 5–30s.
- Connection succeeded — collapses to account preview: "Verified — @transquinnftw, TLC Premium tier, 3-city slot, Sumsub-verified through 2027-03-04, listing active." Done enabled.
- Connection failed (rate-limited) — "Tryst's rate-limiting us. Wait 5 minutes and retry."
- Connection failed (account locked / under review) — "Tryst flagged this account: {reason}. [Open tryst.link →] to resolve before connecting."
- Adapter pool exhausted — "Cocotte's busy. Try in a minute."
- Tor pool degraded — "Privacy network's down. Connect anyway via direct IP? (Less anonymous.)"
- Quinn cancels mid-test — adapter aborts; container recycled.
- VoiceOver — mode radio first, fields read with appropriate sensitivity hints.
Full-credentials-mode states
- Login failed (wrong creds) — "Cocotte couldn't sign in. Tryst said: invalid username or password."
- 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.
- 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).
- Captcha appeared, ML solver failed — "Tryst showed a captcha I couldn't auto-solve. [Solve it now →]" Routes to
captcha-solve.screen.md. - Bot-detection challenge (Cloudflare/Akamai) — banner + Tor circuit rotation + retry up to 3 times.
Cookie-paste-mode states
- Cookie format invalid — inline error: "That doesn't look like a tryst.link session cookie."
- Cookie expired / Tryst doesn't accept it — "Tryst rejected this cookie. It may have expired. Open tryst.link, re-sign-in, and re-copy."
- 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); writesagent_actionsrowaction_type='surface_connect'withauth_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) → 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 — parent (dual-mode auth specified there).
- _engineering-surface-adapter-container.md — container that runs both modes' verification.
- _engineering-credentials-vault.md — encrypted storage of both modes' artifacts (cookie blob OR username/password/TOTP).
- surfaces-settings.screen.md — entry from settings.
- persona-seed-interview.screen.md — entry from onboarding.
- specialist-bookings-tryst.contract.md — consumer of the stored auth.
- Brief M §M2 — re-auth-from-degraded entry; mode-dependent recovery.
- policy-card.screen.md — sibling; bumps start after connect.
- Brief V — both modes' auth artifacts are exportable + erasable.
- Future
captcha-solve.screen.md(HITL captcha) — surfaces state 13. .archive/ARCHIVED.md—talent-scoutarchive map; captcha-solver model lives there.
Out of scope
- The
captcha-solve.screen.mdinterior (deferred). - Browser-bookmarklet-based cookie extraction (defer; Quinn can copy manually).
- Sumsub KYC re-up flow (separate screen — tryst-verification.screen.md).