feat: remix tier gating — t1/t2 behind explicit opt-in (default unchanged)#20
Open
mtmtian wants to merge 5 commits into
Open
feat: remix tier gating — t1/t2 behind explicit opt-in (default unchanged)#20mtmtian wants to merge 5 commits into
mtmtian wants to merge 5 commits into
Conversation
Add an independent worker-engine RemixJob path alongside the existing
Seedance2-direct remix: control plane creates a pending RemixJob + brief via
POST /api/creatives/remix-jobs, an external HMAC-authenticated worker claims
it, generates beats, assembles/QCs the clip, and reports progress/results
back via /api/worker/remix-jobs/{claim,report,upload}. Purely additive —
reuses buildRemixBrief/competitorCreativeToAnalysis from remix-brief.ts
without touching any existing files.
…n upload Close the code-review gaps on the worker-facing RemixJob surface: report/ now enforces an atomic ALLOWED_PREV transition table (succeeded/failed are terminal), validates outputUrl against the canonical GCS upload path, and surfaces brand-QC failures via Creative.reviewNotes instead of silently promoting. upload/ pre-checks HMAC headers and content-length before buffering the body. claim/ recycles stale in-flight jobs after a configurable lease window and collapses the duplicated jobId/queue branches into one atomic updateMany. De-dupes asJson + canvas-dims math into src/lib/growth/remix-job.ts, and shares the e2e HMAC-signing helper between remix-jobs.spec.ts and competitor-ingest.spec.ts.
Adds t1/t2 tier codes to the remix worker engine behind an explicit REMIX_ENABLED_TIERS opt-in (defaults to t0_5 only, matching current IP policy). t1/t2 require a segmentPlan (t2) and a Tier-2 hand-picked competitor video already stored via the Save video flow; claim now returns refs[] pointing the worker at that stored Asset. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
WHY: post-PR adversarial review of 51c1ce8 WHAT: segmentPlan requires non-negative ordered non-overlapping segments (max 64) within the source video duration; REMIX_ENABLED_TIERS always keeps t0_5 enabled; t2 Creative.duration derives from kept segments; claim refs lookups scoped to the job's org
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR does NOT change the shipped default:
REMIX_ENABLED_TIERSdefaults tot0_5only — the borrow-structure-not-pixels policy inremix-brief.ts/competitor-media.tsremains the effective behavior out of the box.What this adds
Tier codes for t1/t2 exist in the remix worker engine's control plane, but stay behind an explicit env opt-in. Nothing about the default request path changes.
/api/creatives/remix)@referencefor the workersegmentPlan)containsCompetitorFootage: trueGating mechanics
REMIX_ENABLED_TIERS(comma-separated, default"t0_5") gates which tiersPOST /api/creatives/remix-jobswill accept. Tier not in the set →403. Tier not a known code →400.segmentPlanwith at least oneaction: "reuse"segment, or400.CompetitorCreative.assetId→Asset.fileUrl) — this reuses your hand-picked, legal-cleared winners gate rather than adding a new one. Missing it →400with a "use the Tier-2 Save video flow first" message.POST /api/worker/remix-jobs/claimnow returnsrefs: [{url, kind:'video'}]for t1/t2 jobs, pointing the worker at that stored Asset. t0_5 is untouched.reviewStatus: 'pending'— the human review gate is identical across tiers, this PR only changes what's allowed to be generated, never what's allowed to ship without review.Why gate via env instead of code-only
This moves the t1/t2 IP boundary from "not possible in code" to "off by default, explicit config choice + auditable via
REMIX_ENABLED_TIERS, gated behind your own Tier-2 hand-picked-video approval step." That gives you (or legal/product) a deliberate lever to pull per deployment, rather than a hardcoded wall — while leaving the out-of-the-box behavior identical to today.Stacked on #19
This branch is based on
feat/remix-worker(#19, still pending review) and includes its commits. Once #19 merges, this diff will automatically shrink to just the tier-gating commit (51c1ce8).Test plan
npm run lint— 0 errors (pre-existing warnings only)npx tsc --noEmit— cleannpx playwright test e2e/remix-jobs.spec.ts— 14/14 passing, including new coverage for: unknown-tier 400, t2-without-segmentPlan 400, t2/t1-without-stored-video 400. (The e2e webServer runs withREMIX_ENABLED_TIERS="t0_5,t1,t2"so these 400 branches — which sit downstream of the 403 gate — are exercised; the refs[] happy path requires a stored competitor Asset and is left to cross-repo integration with the worker.)🤖 Generated with Claude Code