Description
The object store path includes the repository component:
{root}/{registry}/{repository}/{algorithm}/{shard1}/{shard2}/{shard3}/
This means two repositories sharing a common blob (same digest) get separate copies on disk, completely defeating content-addressed deduplication. The correct layout should be:
{root}/{registry}/{algorithm}/{shard1}/{shard2}/{shard3}/
The registry is correctly included (registries should not share blobs for security), but the repository should be excluded — objects are identified by digest, not by repo.
Impact: All existing object stores have the wrong layout. Since we're pre-1.0, a breaking change is acceptable without migration.
Scope: ObjectStore::path() in crates/ocx_lib/src/file_structure/object_store.rs joins repository_path() into the path. This also affects list_all(), MAX_WALK_DEPTH, is_valid_object_path(), the GC walker, and documentation in subsystem-file-structure.md.
Steps to Reproduce
- Install the same blob from two different repos:
ocx install repo-a/tool:1.0 and ocx install repo-b/tool:1.0 (where both point to the same digest)
- Observe that
~/.ocx/objects/ contains two copies of the same content under different repo paths
Environment
- All platforms, all versions since initial implementation (commit
5294912, 2026-02-28)
Origin
This was introduced in the very first version of object_store.rs and has been present since day one. The install store correctly uses repo for symlink namespacing (installs/{registry}/{repo}/candidates/{tag}), but the object store incorrectly mirrors that structure.
Description
The object store path includes the repository component:
This means two repositories sharing a common blob (same digest) get separate copies on disk, completely defeating content-addressed deduplication. The correct layout should be:
The registry is correctly included (registries should not share blobs for security), but the repository should be excluded — objects are identified by digest, not by repo.
Impact: All existing object stores have the wrong layout. Since we're pre-1.0, a breaking change is acceptable without migration.
Scope:
ObjectStore::path()incrates/ocx_lib/src/file_structure/object_store.rsjoinsrepository_path()into the path. This also affectslist_all(),MAX_WALK_DEPTH,is_valid_object_path(), the GC walker, and documentation insubsystem-file-structure.md.Steps to Reproduce
ocx install repo-a/tool:1.0andocx install repo-b/tool:1.0(where both point to the same digest)~/.ocx/objects/contains two copies of the same content under different repo pathsEnvironment
5294912, 2026-02-28)Origin
This was introduced in the very first version of
object_store.rsand has been present since day one. The install store correctly uses repo for symlink namespacing (installs/{registry}/{repo}/candidates/{tag}), but the object store incorrectly mirrors that structure.