Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 3
feat: music_generations table and a 100 MiB public-uploads limit#60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Uh oh!
There was an error while loading. Please reload this page.
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading. Please reload this page.
Diff view
Diff view
There are no files selected for viewing
76 changes: 76 additions & 0 deletions
76 supabase/migrations/20260821170000_create_music_generations.sql
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| -- Create music_generations: songs generated with MiniMax Music 3 on fal.ai | ||
| -- (recoupable/chat#1992, contract: recoupable/docs#308). | ||
| -- | ||
| -- Nothing in this schema tracks generated media today, so every column is new | ||
| -- rather than an extension of an existing shape. | ||
| -- | ||
| -- Why the row is also the run record: a generation takes roughly one to two | ||
| -- minutes, far past a request budget, so POST /api/music inserts a pending row | ||
| -- and hands the id to a Vercel Workflow. Same pattern as playcount_snapshots | ||
| -- (20260610010000) - the API reads the row, never the Workflow API. | ||
| -- | ||
| -- Deliberately narrow. Anything another system already knows is not stored | ||
| -- here: generation parameters ride along as workflow arguments, the seed and | ||
| -- the step timeline are readable from fal_request_id and workflow_run_id, and | ||
| -- credits are accounted in usage_events. What stays is what the gallery has to | ||
| -- render without making a call per row. | ||
| -- | ||
| -- Scope needs no second column. Organizations are accounts in this schema, so | ||
| -- an organization's song is one whose account_id is that organization; the | ||
| -- membership join tables already say which accounts are organizations. | ||
| CREATE TABLE IF NOT EXISTS public.music_generations ( | ||
| id UUID PRIMARY KEY DEFAULT gen_random_uuid(), | ||
| -- The owning account, after the standard account_id override resolves. | ||
| -- A person or an organization; nothing here needs to know which. | ||
| account_id UUID NOT NULL REFERENCES public.accounts(id) ON DELETE CASCADE, | ||
| -- TEXT + CHECK, not a Postgres enum: only two enum types exist across all | ||
| -- of these migrations and both are legacy. | ||
| status TEXT NOT NULL DEFAULT 'pending' | ||
| CHECK (status IN ('pending', 'processing', 'completed', 'failed')), | ||
| -- Provenance for immutable content. A song made by one model has to stay | ||
| -- attributable once a second model exists, and it cannot be backfilled. | ||
| model TEXT NOT NULL DEFAULT 'minimax/music-3', | ||
| prompt TEXT NOT NULL, | ||
| lyrics TEXT NOT NULL, | ||
| -- Actual length, reported by fal. Rendered on every gallery card, so it is | ||
| -- stored rather than fetched per row. | ||
| duration_seconds NUMERIC CHECK (duration_seconds IS NULL OR duration_seconds > 0), | ||
| -- Key inside the public-uploads bucket, once the audio is mirrored. NULL | ||
| -- until completed. UNIQUE because two rows pointing at one object would | ||
| -- make deletion unsafe. | ||
| storage_key TEXT UNIQUE, | ||
| -- Handles to the two external systems this generation touches: fal for the | ||
| -- request itself, Vercel Workflow for the run that drove it. Different | ||
| -- systems answer different questions, so both are kept. | ||
| fal_request_id TEXT, | ||
| workflow_run_id TEXT, | ||
| -- Why a generation failed, in terms a user can act on. The one thing the | ||
| -- workflow cannot answer cheaply: the gallery lists failures and cannot | ||
| -- make a call per row, and a failed row with no reason is a dead end. | ||
| error_message TEXT, | ||
| created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), | ||
| updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now() | ||
| ); | ||
| -- The gallery read: one account's generations, newest first. | ||
| CREATE INDEX IF NOT EXISTS music_generations_account_created_idx | ||
| ON public.music_generations (account_id, created_at DESC); | ||
| -- Sweeping for work still in flight. | ||
| CREATE INDEX IF NOT EXISTS music_generations_status_created_idx | ||
| ON public.music_generations (status, created_at DESC); | ||
| -- CREATE TRIGGER has no IF NOT EXISTS, so re-applying this file would fail | ||
| -- here even though every statement above is idempotent. | ||
| DROP TRIGGER IF EXISTS set_updated_at ON public.music_generations; | ||
| CREATE TRIGGER set_updated_at | ||
| BEFORE UPDATE ON public.music_generations | ||
| FOR EACH ROW EXECUTE FUNCTION trigger_set_updated_at(); | ||
coderabbitai[bot] marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| -- RLS on with zero policies: denies anon and authenticated outright while | ||
| -- service_role, which is how the API reads and writes, bypasses it. These rows | ||
| -- hold user-authored prompts and lyrics plus a storage key, so leaving the | ||
| -- table reachable through PostgREST with the anon key would expose one | ||
| -- account's songs to any other. | ||
| ALTER TABLE public.music_generations ENABLE ROW LEVEL SECURITY; | ||
26 changes: 26 additions & 0 deletions
26 supabase/migrations/20260821170100_raise_public_uploads_size_limit.sql
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| -- Raise the public-uploads size limit from 25 MiB to 64 MiB so generated audio | ||
| -- fits (recoupable/chat#1992). | ||
| -- | ||
| -- MiniMax Music 3 returns 44.1 kHz 16-bit stereo WAV, about 10.6 MB per | ||
| -- minute. Against the 25 MiB limit set in 20260508151035 that caps a mirrored | ||
| -- song at roughly 148 seconds, while the API accepts a requested duration of | ||
| -- up to 300. Without this, a long generation renders on fal, is charged for, | ||
| -- and then fails at the upload step. | ||
| -- | ||
| -- 64 MiB is sized to the longest song we accept (300 seconds is about 50.5 | ||
| -- MiB) and no further, rather than a round 100. The limit is per bucket, not | ||
| -- per MIME type, so every raise also raises the ceiling for the images, PDFs | ||
| -- and CSVs that share this bucket - keeping the number tight keeps that blast | ||
| -- radius small. A separate audio-only bucket would scope it exactly, at the | ||
| -- cost of a second bucket, its own keys and a second upload path; not worth it | ||
| -- for a 39 MiB difference on an API-gated bucket. | ||
| -- | ||
| -- allowed_mime_types is untouched: audio/wav and audio/mpeg were permitted | ||
| -- from the start. | ||
| -- | ||
| -- Idempotent: safe to re-apply. | ||
| update storage.buckets | ||
| set file_size_limit = 67108864 -- 64 MiB | ||
| where id = 'public-uploads' | ||
| and (file_size_limit is null or file_size_limit < 67108864); |
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.
Uh oh!
There was an error while loading. Please reload this page.