Skip to content

Verification-code entry for browser social posts (+ Mastodon selector fix) - #65

Merged
ralyodio merged 1 commit into
masterfrom
verification-code-entry
Jul 4, 2026
Merged

ralyodio merged 1 commit into
masterfrom
verification-code-entry

Conversation

@ralyodio

@ralyodio ralyodio commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Problem

Browser-automated posts kept failing because platforms (LinkedIn especially) interrupt the cookie session with an identity challenge — "Enter the 6-digit code below to verify your identity." The automation had no way to supply that code, so the post died (and the other platforms' composer timeouts were largely the same challenge being served instead of the composer).

Approach — live paused session (chosen)

When a platform flow detects a code challenge, the worker keeps the same Chromium session open, marks the post awaiting_code, and polls sp_post.verification_code for a code the user submits in the UI — then types it into the live page and finishes posting. Same session that got challenged enters the code, so one-time codes work.

Changes

  • Migration 20260704140000_sp_post_verification.sql: sp_post gains verification_code, verification_prompt, verification_requested_at. status is free text, so 'awaiting_code' needs no enum change.
  • lib/sp/verificationChallenge.ts:
    • detectCodeChallenge — narrow selectors (autocomplete=one-time-code, name/id ~ pin|otp|verification, aria-label ~ verification code) so a normal field isn't mistaken for a challenge.
    • makeCodeWaiter(supabase, postId) — marks awaiting_code + prompt, polls up to 3 min, then flips back to publishing and clears the code (no replay).
    • handleCodeChallenge — fills + submits + waits for the app to render. Wired into all 7 platform flows right after navigation.
  • submitVerificationCode server action — owner-scoped, accepts 4–8 digits (strips spaces/dashes), only writes while the post is awaiting_code.
  • VerificationCodeInput component — shown on awaiting_code rows in both the project Social post history and the /recent outreach history (where the failures were reported). awaiting_code is surfaced via deriveOutreachStatus and kept in the live-refresh set so the row updates when posting completes.
  • Mastodon selector fix — a bare getByRole("textbox") also matched the "Search or paste URL" box and tripped strict-mode (resolved to 2 elements); scoped to the compose textarea.

Verification

  • tsc --noEmit clean
  • tests/sp/* 35/35, incl. new verification-challenge.test.ts (waiter marks awaiting_code → returns the submitted code → clears it; times out cleanly; trims the code)
  • Confirmed sp_post RLS (owner all) permits the owner UPDATE the action relies on
  • Not run against live platform DOM — challenge detection selectors and the per-platform composer selectors are best-effort and may need tuning against real challenge pages

Deploy note

The migration must be applied (I'll apply it to the Supabase project on merge, as with the exit-pages one). The /recent and Social history queries select the new columns, so the DB change ships with the code.

The concurrency cap and this pause both hold a browser slot open; a post waiting on a code occupies one of the SP_BROWSER_CONCURRENCY (default 2) slots for up to 3 min.

🤖 Generated with Claude Code

Platforms like LinkedIn interrupt a cookie session with "enter the 6-digit
code we sent you" before showing the composer, which stranded every
affected post. Adds a live human-in-the-loop flow (the approach chosen for
this): the worker keeps the SAME Chromium session open, pauses, and waits
for a code the user types in the UI.

- migration: sp_post gains verification_code / verification_prompt /
  verification_requested_at (status 'awaiting_code' needs no enum change)
- lib/sp/verificationChallenge.ts: detectCodeChallenge (narrow one-time-code
  / pin / otp selectors), makeCodeWaiter (marks awaiting_code, polls sp_post
  for the code up to 3 min, then flips back to publishing and clears it), and
  handleCodeChallenge to fill + submit. Wired into all 7 platform flows right
  after navigation.
- submitVerificationCode server action (owner-scoped, validates 4–8 digits)
- VerificationCodeInput component shown on 'awaiting_code' rows in both the
  project Social post history and the /recent outreach history; awaiting_code
  surfaced via deriveOutreachStatus and kept in the live-refresh set.
- Fix Mastodon compose selector: a bare getByRole("textbox") also matched the
  search box and tripped strict-mode; scope it to the compose textarea.

Tests: makeCodeWaiter marks/returns/clears, times out, trims the code.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

@ralyodio
ralyodio merged commit cc1f95f into master Jul 4, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant