a0018cafd0
Addresses egilewski (Codex) CR on PR #52355: the persisted-row fallback in _resume_target_allowed() skipped the platform/source check when sessions.source was blank (the row_src guard only rejects a *mismatching* non-blank source), then accepted the row on user_id equality alone. A legacy/malformed row with a blank source but a matching user_id was therefore resumable — an identified caller could bind to a transcript whose origin it can't prove. Now an identity-bearing caller is allowed only when the row proves BOTH the same owner (non-blank user_id match) AND the same platform/origin (non-blank source match). A blank/legacy source fails closed, exactly like a missing user_id. No-identity (single-user) callers are unaffected. Adds a regression replaying the reviewer's blank-source same-uid probe. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>