feat: support addressing objects by versionId - #1341
Open
TylerHillery wants to merge 11 commits into
Open
Conversation
TylerHillery
force-pushed
the
tyler/feat/object-versioning-wave-1
branch
from
August 21, 2026 02:49
455fc8e to
72f2b66
Compare
TylerHillery
marked this pull request as ready for review
August 21, 2026 02:50
Contributor
There was a problem hiding this comment.
Pull request overview
Adds API-level and storage-layer support for pinning object operations to a specific object version via versionId / sourceVersionId, laying groundwork for multi-version objects while keeping current behavior intact.
Changes:
- Extend object routes (get/head/info, signed URLs, copy/move, delete) to accept a version identifier and pass it through to storage lookups.
- Update storage/database lookup and update paths to optionally filter by
version, and includeversionIdin signed download tokens. - Add new tenant migration indexes to support version-aware addressing and future versioning constraints.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/test/object.test.ts | Adds integration tests covering version-pinned get/info/public get/copy/move/delete and signed URL flows. |
| src/storage/object.ts | Plumbs optional version IDs through findObject, deleteObject, copyObject, moveObject, and signed URL creation. |
| src/storage/database/pg.ts | Extends findObject and updateObject queries to optionally constrain by version. |
| src/storage/database/adapter.ts | Updates the Database interface to accept optional version parameters for findObject and updateObject. |
| src/internal/database/migrations/types.ts | Registers new migration IDs for added object/version indexes. |
| src/internal/auth/jwt.ts | Extends SignedToken to optionally carry versionId. |
| src/http/routes/object/moveObject.ts | Accepts sourceVersionId and forwards it to storage move operation. |
| src/http/routes/object/getSignedURL.ts | Accepts versionId for signed URL generation and forwards it to storage signing. |
| src/http/routes/object/getSignedObject.ts | Uses versionId from verified token to fetch the pinned object version before rendering. |
| src/http/routes/object/getPublicObject.ts | Accepts versionId query param and passes it to object lookup. |
| src/http/routes/object/getObjectInfo.ts | Extends query schema and passes versionId to object info lookup. |
| src/http/routes/object/getObject.ts | Accepts versionId query param and passes it to object lookup. |
| src/http/routes/object/deleteObject.ts | Accepts versionId query param and forwards it to storage delete operation. |
| src/http/routes/object/copyObject.ts | Accepts sourceVersionId and forwards it to storage copy operation. |
| migrations/tenant/0064-objects-key-version-index.sql | Adds a unique index on (bucket_id, name, version) to support version addressing. |
| migrations/tenant/0065-objects-current-version-index.sql | Adds a unique index enforcing a single current (unarchived) row per (bucket_id, name). |
| migrations/tenant/0066-objects-null-version-index.sql | Adds a unique partial index for non-versioned objects keyed by (bucket_id, name). |
Suppressed comments (1)
src/storage/database/pg.ts:1191
versionis gated by a truthy check, so a provided empty string (e.g.?versionId=) would be ignored and the lookup would fall back to the unpinned object. Use an undefined check so any provided value participates in the WHERE clause.
if (version) {
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Coverage Report for CI Build 32666241045Coverage increased (+0.04%) to 81.203%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats💛 - Coveralls |
TylerHillery
force-pushed
the
tyler/feat/object-versioning-wave-1
branch
from
August 21, 2026 12:11
922e71e to
2f920dc
Compare
TylerHillery
force-pushed
the
tyler/feat/object-versioning-wave-1
branch
from
August 23, 2026 21:01
efd3bda to
39413e4
Compare
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.
What kind of change does this PR introduce?
Feature
What is the current behavior?
Currently we don't allow users to specify version id
What is the new behavior?
Can now pin get, head, info, sign, copy, move, delete, and deleteObjectets to a specific object version via versionId. Also added additional indexes.
Additional context
Left out S3 API changes for now as well. Will be done in a follow up PR.
Only one version can exist per object today, so
versionIdjust reselects the same object you'd already get by default but this lays groundwork for real multi-version support later.