speakers(routes): drop __ URL encoding, narrow serve_audio except
Mirrors d314d183 onto apps/speakers — removes the __↔/ path-encoding
scheme around the serve_audio route and narrows its outer except
Exception to (OSError, ValueError) wrapped only around path validation,
letting send_file run uncaught and logging with exc_info=True.
URL construction now emits raw forward slashes at all three call sites:
apps/speakers/routes.py segment view, apps/speakers/owner.py _audio_url,
and apps/speakers/discovery.py _audio_url. All four serve_audio return
paths now use error_response(...) for consistency with the rest of
apps/speakers/routes.py (48 error_response vs 5 bare-tuple sites).
Aligns with the follow-up flagged for apps/speakers/routes.py:1230 in
d314d183's commit message (CPO ticket req_bqnsdo2v).
Follow-up uncovered during test updates (out of scope here): the
existing test_serve_audio_sets_flac_mimetype was already failing on
main — part of the pre-existing speakers baseline failures. The
production handler builds full_path from state.journal_root/day/...
while day_path(day) resolves under journal_root/chronicle/day; the
commonpath check returns the journal root and never equals day_dir,
so legitimate audio returns 403. The test fixture now sets
state.journal_root to env.journal/chronicle so the narrow path
regression is testable; the underlying production-path mismatch is
a separate issue from this cleanup.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>