Skip to content

fix: free-plan deploy, seekable playback, and interview worker name - #29

Merged
mrevanzak merged 6 commits into
mainfrom
fix/free-plan-deploy-and-seekable-playback
Aug 18, 2026
Merged

fix: free-plan deploy, seekable playback, and interview worker name#29
mrevanzak merged 6 commits into
mainfrom
fix/free-plan-deploy-and-seekable-playback

Conversation

@mrevanzak

Copy link
Copy Markdown
Collaborator

Summary

  • Deploy the finalizer without Cloudflare Containers (Workers Paid). Local alchemy dev still uses the ffmpeg image; remote deploy concatenates uploaded parts in the Worker.
  • Make MediaRecorder WebM seekable by writing a Cues/Duration index on finalize and rebuilding a blob in the player, so the timeline can be scrubbed.
  • Publish the public web Worker as interview (interview.mrevanzak.workers.dev).

D1 migration squash is already on main.

Commits

  1. fix(finalizer): concat parts on free-plan deploy without Containers
  2. fix(playback): make MediaRecorder WebM seekable
  3. chore(infra): publish the web worker as interview

Test plan

  • pnpm --filter @interview-web/finalizer test
  • pnpm --filter web exec vitest run tests/recording-playback.test.ts tests/recording-playback-view.test.tsx
  • bun run deploy succeeds on a free Cloudflare account
  • Public URL is https://interview.mrevanzak.workers.dev
  • Record a Chrome/Firefox take, open operator playback, scrub the timeline
  • Existing published recordings become seekable after this web deploy (no re-record)

Cloudflare Containers require Workers Paid. Keep the ffmpeg image for
local alchemy dev, and on deploy assemble the submission by concatenating
uploaded parts in the Worker.
Concatenated MediaRecorder output has no Cues or Duration, so the
browser treats it as a live stream. Write a seek index on finalize and
rebuild a blob in the player so the timeline can be scrubbed.
Use a short workers.dev name instead of interview-web-web-rev.
@access-time-code-pr-reviewer

access-time-code-pr-reviewer Bot commented Aug 17, 2026

Copy link
Copy Markdown

Review Summary

This PR adds recording playback, WebM processing, passthrough finalization, and expanded recording test coverage. However, it exposes recording submission deletion without authentication or authorization, allowing anyone with an enumerable session ID to delete stored recording data.

Key Changes:

  • Adds recording playback UI and object URL preparation for WebM and other media.
  • Adds WebM seekability and segment splitting support.
  • Adds a passthrough finalizer for WebM recordings when ffmpeg is unavailable.
  • Expands unit and end-to-end coverage for recording, playback, and finalization flows.
  • Adds or exposes recording submission deletion without access control.

Confidence Score: 5/5

Recommendation: Request changes before merge.

Rationale: The unauthenticated destructive endpoint is a clear, directly evidenced security vulnerability, and the affected recording identifiers can be enumerated through the unauthenticated listing flow.

Special Attention

- Require operator authentication and authorization before mounting the submission DELETE endpoint. - Add CSRF protection if authorization relies on cookies. - Review authentication and authorization for recording list and playback access. - Verify internal finalization routes cannot be invoked or abused externally.

Important Files Changed

File Overview
apps/web/src/routes/api/recordings/$sessionId/submission.ts Handles recording submission access and deletion; its DELETE operation currently lacks authentication and authorization.
apps/web/src/recording/playback.ts Builds recording submission URLs and loads recording bytes for playback.
apps/web/src/recording/playback-view.tsx Renders the recording list and playback detail views.
packages/finalizer/src/domain/webm-seekable.ts Parses and transforms WebM data to support seekable playback and recovered segments.
packages/finalizer/src/worker/passthrough.ts Provides an in-memory WebM finalization path when the ffmpeg container is unavailable.

Flowchart

flowchart TD
  A[Caller obtains or enumerates session ID] --> B[Unauthenticated recording API]
  B --> C{Request method}
  C -->|GET| D[Read recording submission]
  C -->|DELETE| E[Delete stored parts and output]
  E --> F[Recording data lost]
  G[Required operator authorization] -.-> C
Loading
Audit history

@access-time-code-pr-reviewer access-time-code-pr-reviewer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


🤖 review-bot · openai/gpt-5.6-luna · standard · 123.3s · 805,557 tokens · diff: 16 files · preloaded context: 17 changed + 8 related · 1 noise filtered · policy: github-pr-review, thermo-nuclear-code-quality-review · optional skills invoked: none

Comment thread packages/finalizer/src/worker/passthrough.ts Outdated
Without ffmpeg, concatenated MP4 is not a valid submission. Fail those
plans as ContainerRejected so the session is marked failed, not ready.
A refresh starts a new encoder session. Muxing those clusters into one
bitstream makes the browser error on the second keyframe. Keep each
segment as its own file and let the player step through parts.
Record, reload, continue, finalize two segments, then open operator
playback and assert both parts load without Recording unavailable.
@mrevanzak
mrevanzak merged commit 3b4b125 into main Aug 18, 2026
2 of 3 checks passed
@mrevanzak
mrevanzak deleted the fix/free-plan-deploy-and-seekable-playback branch August 18, 2026 05:15
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