Skip to content

feat: Store task description files on the workspace - #7234

Merged
andrecalil merged 19 commits into
mainfrom
feat/factory-object-storage
Sep 8, 2026
Merged

andrecalil merged 19 commits into
mainfrom
feat/factory-object-storage

Conversation

@andrecalil

@andrecalil andrecalil commented Sep 7, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Stores task description files in SuperPlane object storage. Descriptions keep sp-file:// refs. Signed download URLs are minted at read and dispatch time.

Upload completion rechecks the task file count and the organization byte cap. Concurrent completions lock the organization and task rows before they apply those caps. Factory cleanup deletes blob objects first and commits those row deletes before it removes the rest of the factory domain.

Resolves: #7108

Test plan

  • Attach a PNG on a new task.
  • Confirm the saved description contains sp-file://.
  • Reload the task and confirm the image still renders.
  • Confirm a 21st pending task file is rejected.
  • Confirm factory cleanup removes objects before file rows.
Open in Web Open in Cursor 

RetriggerView in Greptile

The PR appears safe to merge.

Task descriptions stored remote image URLs. Private GitHub images and
editor attachments did not stay available. SuperPlane now stores those
files in platform object storage and keeps a stable sp-file:// ref in
the description.

The API mints a signed GET URL when the UI renders a task. A factory
line also receives signed URLs when it resolves the task description.

Resolves: #7108
Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
@superplanehq-integration

Copy link
Copy Markdown
Contributor

👋 Commands for maintainers:

  • /sp start - Start an ephemeral machine (takes ~30s)
  • /sp stop - Stop a running machine (auto-executed on pr close)

@superplanehq-integration

Copy link
Copy Markdown
Contributor

Maintainers: comment /deploy-storybook to get a Storybook link for this PR.

@andrecalil
andrecalil marked this pull request as ready for review September 7, 2026 14:15
Comment thread pkg/models/file.go
Comment thread pkg/models/factory_resource_cleaner.go Outdated
Comment thread pkg/storedfiles/files.go Outdated
Comment thread db/migrations/20260908004630_add-files.up.sql
cursoragent and others added 3 commits September 7, 2026 16:31
Pending uploads did not count toward the task file limit. MarkReady
now checks the task count and the organization byte cap. A failed
quota check deletes the uploaded object and marks the file failed.

Resolves: #7108
Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
SQL-only deletes left blob objects behind when a factory had more
than one tick of files. The worker now deletes objects first and
waits while file rows remain.

Resolves: #7108
Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
The leftover-file test uses blob.ScopeTask. The models package
did not compile without that import.

Resolves: #7108
Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
Comment thread pkg/models/file.go
Comment thread pkg/workers/factory_cleanup_worker.go Outdated
cursoragent and others added 3 commits September 7, 2026 17:03
Main added Productive.io intake and other schema changes. This merge
keeps those updates and the workspace file storage work.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
Concurrent completions could both read the same ready count and
then mark two files ready. Create and MarkReady now lock the
organization and task rows before they check the cap.

Resolves: #7108
Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
Reparent copied a file and then deleted the source before the
work-order transaction committed. Factory cleanup deleted blobs
in the same transaction as later domain deletes. Both paths now
remove objects only after the matching rows are committed.

Resolves: #7108
Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
Comment thread pkg/storedfiles/files.go Outdated
cursoragent and others added 2 commits September 8, 2026 00:12
Main added last-location tracking and other product updates. This
merge keeps those changes with the workspace file storage work.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
Main added a later last-locations migration. golang-migrate would
skip the older files migration on production. Recreate it with a
fresh timestamp so it stays the newest migration.

Resolves: #7108
Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
Comment thread pkg/workers/factory_cleanup_worker.go Outdated
cursoragent and others added 3 commits September 8, 2026 00:35
Main tells users when a task is still under analysis. This merge
keeps that UI copy with the workspace file storage work.

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Main replaces Viewer with Operator and Maintainer, and keeps
rejected Backlog drafts out of Lines Done.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
Main added owner and role migrations with later merge order.
Recreate the files migration with a fresh timestamp so it stays
the newest migration.

Resolves: #7108
Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
Comment thread pkg/storedfiles/files.go
cursoragent and others added 2 commits September 8, 2026 01:01
The split-run popup now loads live task files through useWorkOrder.
Lines page specs mock useFactoryData without that export, so Vitest
throws when a card opens the popup. CI shards fail on those specs.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
Concurrent binds read the task file count without a row lock, so two
updates can pass the same remaining slot. A later bind failure also
leaves the copied object after the transaction rolls back. Factory
cleanup deleted several objects in one transaction, so a later failure
restored rows whose objects were already gone.

Lock the quota rows before the bind count. Delete copied objects when
bind or the surrounding transaction fails. Commit each factory file
delete in its own transaction.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
Comment thread pkg/grpc/actions/factories/import_factory_intake_item.go
Comment thread pkg/workers/factory_cleanup_worker.go
Remote image ingest writes objects before the work-order transaction
commits. A later bind or content update failure rolled back the file
rows and left those objects in storage.

Return the new object keys from ingest and delete them when the
surrounding transaction fails. Delete each factory cleanup object
before the row transaction so a leftover row is removed on the next
tick.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
Comment thread pkg/grpc/actions/factories/import_factory_intake_item.go Outdated
cursoragent and others added 2 commits September 8, 2026 12:46
Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
A rolled-back import can leave ingested objects if object delete fails.
The catalog row is already gone, so the file cleanup worker cannot find
those objects.

Retry object deletes, then store leftover keys as failed workspace file
rows so the next stale-file sweep can delete them.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
cursoragent and others added 2 commits September 8, 2026 18:05
Analysis, plan, and implement read stored sp-file refs. They need
fetchable download URLs at dispatch time, not catalog refs.

Signed URLs stay off the saved description.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
Keep the branch current with column automation icons.

Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
@andrecalil
andrecalil merged commit 22d66b0 into main Sep 8, 2026
5 of 6 checks passed
@andrecalil
andrecalil deleted the feat/factory-object-storage branch September 8, 2026 18:43
mytmlt pushed a commit that referenced this pull request Sep 8, 2026
Signed-off-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: André Calil <andrecalil@users.noreply.github.com>
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.

Tasks: Store files on workspace

2 participants