feat(apify): any authenticated key can poll GET /api/apify/runs/{runId} (chat#1840)
Item 1 of recoupable/chat#1840. No docs or database dependency — docs#262 and database#39 both closed unmerged per the design decision below (the existing docs page already matches the new behavior).
Why
An account-scoped key can start a scrape via POST /api/socials/{id}/scrape but got Forbidden polling its own run — validateGetScraperResultsRequest was admin-only (7/7 Forbidden polls in the issue's production evidence, while docs/skills/task prompts all direct agents to poll).
Decision (2026-07-03, supersedes the owner-or-admin draft)
Any valid API key or Bearer token can poll any run id. Scrape datasets are public social content and Apify run ids are long random strings; possession + a valid credential is sufficient. Authentication still gates the endpoint so anonymous callers can't use it as a free Apify proxy. Admin behavior is unchanged (admins hold valid credentials); backend pollers unaffected.
What
One swap in validateGetScraperResultsRequest: validateAdminAuth → validateAuthContext. 401 (no/both credentials), 400 (bad runId), 200/500 all unchanged in shape. Final diff: 2 files, +17/−19.
Tests (TDD, RED→GREEN)
Validator suite rewritten for the new contract: auth-error propagation, 400 empty runId, any-authenticated-caller passthrough. Full lib/apify + lib/socials suites: 117 passed; tsc --noEmit no new errors vs main; eslint clean.
Done-when — preview verification to follow as a comment
- an account key polls a real runId to completion (no admin token involved) — verified on preview 2026-07-03, results table in comments; scrape-start with an account key was already working in prod (this PR only changes the poll validator)
🤖 Generated with Claude Code