Issues/1263 scope assets to project in scratch#783
Conversation
Test coverage89.47% line coverage reported by SimpleCov. |
ef4870e to
ddfaa05
Compare
5ef7e67 to
d2dd13c
Compare
There was a problem hiding this comment.
Pull request overview
Scopes Scratch assets to projects (via project_id) so assets are no longer globally shared by default, while preserving remix lineage access and keeping library assets usable as global fallbacks. It also tightens Scratch project access control and avoids duplicate remix creation.
Changes:
- Added
project_idtoscratch_assets(with partial unique indexes) and a migration to backfill legacy assets onto referencing projects while reusing blobs. - Updated Scratch asset endpoints to require
X-Project-ID, enforce project/remix visibility, and adjust SVG content-type behavior (trusted only for global/library SVGs). - Updated Scratch project endpoints to authorize access and to reuse an existing remix instead of creating duplicates.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
app/controllers/api/scratch/assets_controller.rb |
Requires X-Project-ID, enforces authorization, scopes asset reads/writes to project/remix visibility, and can auto-create a remix for uploads. |
app/controllers/api/scratch/projects_controller.rb |
Adds explicit authorization for show/update and reuses an existing remix on remix create. |
app/controllers/concerns/scratch_remix_creation.rb |
New concern to create a remix with fallback Scratch content when needed (e.g., asset upload before first save). |
app/models/scratch_asset.rb |
Introduces project scoping, global/project scopes, lineage-based asset lookup, and SVG content-type policy. |
app/models/project.rb |
Adds self_and_ancestor_ids to support remix-lineage asset resolution. |
db/migrate/20260410110000_scope_scratch_assets_to_projects.rb |
Adds project_id, removes old uniqueness, backfills legacy assets to projects, and adds partial unique indexes. |
db/schema.rb |
Reflects scratch_assets.project_id and new indexes/foreign key. |
lib/scratch_asset_importer.rb |
Ensures imports only short-circuit on existing global assets and creates imported assets as global (project_id: nil). |
spec/factories/scratch_assets.rb |
Sets default project: nil for assets in tests. |
spec/lib/scratch_asset_importer_spec.rb |
Adds expectations around global imports and filename collisions with project assets. |
spec/features/scratch/creating_and_showing_a_scratch_asset_spec.rb |
Expands coverage for X-Project-ID, project scoping, remix/ancestor fallback, SVG content-type policy, and concurrent/idempotent uploads. |
spec/features/scratch/creating_a_scratch_asset_spec.rb |
Updates request headers/tests for X-Project-ID requirement. |
spec/features/scratch/creating_a_scratch_project_spec.rb |
Updates authorization expectations and tests remix reuse behavior. |
spec/features/scratch/showing_a_scratch_project_spec.rb |
Adds private-project access control tests (unauthenticated vs owner). |
spec/features/scratch/updating_a_scratch_project_spec.rb |
Updates cat_mode setup and adds “forbidden when cannot update” coverage. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
aa15b2d to
9c7b3e6
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
939c90e to
3ce43b4
Compare
a5d5dd9 to
ef6a5ac
Compare
e218a2d to
0effe97
Compare
0effe97 to
5cb0c28
Compare
5cb0c28 to
10ee4a0
Compare
10ee4a0 to
1b8ce23
Compare
1b8ce23 to
f502f28
Compare
Status
What’s changed?
Scratch assets are now scoped by project and uploader instead of being treated as globally shared.
That changes ownership like this:
Scratch asset reads and uploads
The Scratch asset endpoints now behave like this:
Asset lookup now resolves in this order:
This means:
For SVGs:
Scratch remix behavior
Remix creation still reuses an existing remix for the same user and original project instead of creating duplicates.
The tricky case is when a student adds a Scratch asset before pressing Save for the first time:
This keeps remix logic inside the remix flow, instead of mixing remix creation into the asset endpoints.