Skip to content

feat(clips): three free hosted clips behind a rollout flag - #7624

Merged
steve8708 merged 18 commits into
mainfrom
clips-free-hosted-recordings
Oct 16, 2026
Merged

steve8708 merged 18 commits into
mainfrom
clips-free-hosted-recordings

Conversation

@steve8708

Copy link
Copy Markdown
Contributor

What ships

Let new users create and store their first three Clips recordings before connecting their own storage. Add private hosted GCS storage, per-identity allowance reservations and abuse limits, status and recovery behavior, and a takedown path.

Rollout

New grants require the runtime clips-hosted-free-clips flag, default off, and CLIPS_HOSTED_STORAGE_ENABLED. Beta storage is provisioned and enabled; production remains off. Existing hosted recordings continue working when the rollout flag is off.

Verification

  • Clips suite: 3,211 tests passed; core legacy-auth suite: 312 passed.
  • pnpm guards: all 89 checks passed; both i18n guards passed.
  • Local S3 browser walkthrough covered the allowance UI, exhaustion, owner playback, signed-out share playback, and import; screenshots are indexed in the local .tmp/clips-free-hosted/screenshots/ directory.
  • Real beta GCS server-path walkthrough used a 13.7 MB synthetic MP4. Multipart start, both parts with ETags, and completion returned 200; signed-out proxy playback returned all 13,741,102 bytes; anonymous raw-storage access returned 403; delete removed the recording and object. Bucket inventory was 0 before and 0 after cleanup, with 0 remaining objects from the run. The intermediate recursive JSON listing did not independently enumerate the in-flight object; the recorded GCS request events and proxy read confirmed the upload/read path, and GCS delete responses confirmed cleanup.

Follow-ups

  • Add signup registration rate limiting.
  • Add a per-identity daily reservation cap.
  • Replace the recorder's raw “Invalid state” error with user-facing copy.

builder-io-integration[bot]

This comment was marked as outdated.

builder-io-integration[bot]

This comment was marked as outdated.

Confirmed hosted object deletes now subtract stored bytes from the allowance
ledger. Permanent delete removes hosted media before the row and fails loudly
when cleanup is unconfirmed. Abort and takedown keep the reservation until the
resumable session abort is confirmed, and the reaper retries aborted rows.
Failed hosted Loom verification links the upload so the reaper cleans it.
builder-io-integration[bot]

This comment was marked as outdated.

…counting failures

A Loom upload that failed hosted size verification is marked
media_verification_failed; an in-place retry deletes the stale object and
downloads fresh instead of reusing it. Byte-accounting failures after a
confirmed hosted delete now log and emit clips_hosted_byte_accounting_failed.
Permanent delete removes hosted media only after the fallible pre-row steps.
builder-io-integration[bot]

This comment was marked as outdated.

…smatch

A transient verifier read error no longer marks a complete hosted upload as
unusable, so a retry reuses and re-verifies it instead of deleting it.
builder-io-integration[bot]

This comment was marked as outdated.

Cleanup and the thumbnail route share one in-bucket predicate, so a hosted
Loom recording's external thumbnail no longer blocks permanent delete or
falls back to the default image. A lost CompleteMultipartUpload body is
reconciled against the completed object. Direct imports mark confirmed size
mismatches media_verification_failed and keep the object URL when deleting a
failed upload is unconfirmed. Hosted derivatives are capped at the per-clip
byte budget.
builder-io-integration[bot]

This comment was marked as outdated.

Release a new hosted reservation when an import fails before any upload; find
an existing allowance by recording id so email changes don't strand clips;
reconcile a completed object when a multipart abort returns 404; apply hosted
size/duration caps only in hosted mode; delete superseded hosted media after
seekable repair and thumbnail replacement; reject thumbnail uploads on
taken-down recordings.
builder-io-integration[bot]

This comment was marked as outdated.

… clips-free-hosted-recordings

# Conflicts:
#	templates/clips/actions/delete-recording-permanent.ts
#	templates/clips/server/plugins/db.ts
builder-io-integration[bot]

This comment was marked as outdated.

The desktop storage probe now reads the hosted maxClipDurationMs (hosted mode
only) and the recorder stops through the existing clips:recorder-stop path when
an unpaused take reaches it, matching the web recorder.
builder-io-integration[bot]

This comment was marked as outdated.

create-recording now returns maxClipDurationMs for hosted recordings (null for
own storage), and the desktop recorder uses it as the per-take cap, so a stale
cached storage status can no longer leave a hosted take uncapped.
The extension passes create-recording's maxClipDurationMs to the offscreen
recorder, which stops an unpaused hosted take at the cap through the existing
CLIPS_NATIVE_ENDED stop path; own-storage takes stay uncapped.
builder-io-integration[bot]

This comment was marked as outdated.

A restarted take reuses its session id, so the superseded take's limit timer
is cleared on restart and refuses to fire once its recording is no longer the
active one.

@builder-io-integration builder-io-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Builder reviewed your changes — looks good ✅

Review Details

Incremental review — PR #7624

Reviewed the latest head a533f12e421ae9d936b4917f86d0eee3e32b79a9; the only delta since d5d41a61afca140a09020adec7ffb4acdcf9ba25 is a restart-timer fix in the Chrome extension offscreen recorder. Restart now clears the superseded take’s duration interval before detaching it, and the interval callback also self-clears if its recording is no longer active. These changes address the previous finding that an old timer could stop the replacement take through the reused session ID; the thread is resolved.

Risk: High for the overall PR due to private hosted media, allowance accounting, and takedown functionality; this incremental patch is narrowly scoped to recorder timer lifecycle. The fix is correctly placed in restart teardown and adds a defensive identity check without changing the ordinary stop path. The independent code-review agents found no additional actionable issues.

🧪 Browser testing: Skipped — the browser-test-planner agent is unavailable in this environment, and this change affects the native Chrome extension capture flow.

@steve8708
steve8708 merged commit 61089ee into main Oct 16, 2026
72 checks passed
@steve8708
steve8708 deleted the clips-free-hosted-recordings branch October 16, 2026 00:44
@github-actions

Copy link
Copy Markdown
Contributor

Here's a visual recap of what changed:

Visual recap

Open the full interactive recap

Large diff — this recap is a summarized view (top files + schema/API deltas).

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