Asset Zone Locality
The Context
SharedFile records are uploaded by a user, baked into casync chunks, and referenced by baked_url. The zone server that will serve an entity is the Hilbert-authority for the entity’s position. There is currently no explicit link between a SharedFile and the zone responsible for it.
The Problem Statement
Without a zone_id on shared_files, a zone cannot enumerate the assets it owns. On restart, a zone must re-derive its asset set from CMD_INSTANCE_ASSET history rather than querying its own records. GET /shards returns connection metadata but not the assets associated with a zone, so clients cannot make pre-connection routing decisions.
Describe how your proposal will work with code, pseudo-code, mock-ups, or diagrams
Add an optional zone_id foreign key to shared_files:
ALTER TABLE shared_files
ADD COLUMN zone_id UUID REFERENCES zones(id) ON DELETE SET NULL;The column is nullable. Assets uploaded without a zone association remain valid and are accessible to any zone by asset UUID. When a zone server processes CMD_INSTANCE_ASSET and the asset has no zone_id, the authority zone stamps its own id onto the record.
Zone schema gains a logical reverse association:
# Uro.VSekai.Zone
has_many :shared_files, Uro.SharedContent.SharedFile, foreign_key: :zone_idThe zone-backend context gains a lookup:
def list_zone_assets(zone_id) do
SharedFile
|> where([f], f.zone_id == ^zone_id and not is_nil(f.baked_url))
|> Repo.all()
endThe Benefits
A zone can enumerate its own assets without replaying history. Zone restart recovery is deterministic: load the snapshot, then query list_zone_assets/1 to confirm which assets are already baked. The foreign key enables GET /shards/:id/assets (see 20260421-zone-asset-manifest.md).
The Downsides
Assets shared across zones (the same avatar instanced in multiple zones) have at most one zone_id. Cross-zone asset sharing still works by asset UUID; the zone_id field records origin, not exclusivity.
The Road Not Taken
A join table (zone_assets) normalises the many-to-many case but adds a join on every read path and complexity on every write. A nullable foreign key on shared_files covers the common case (one asset, one origin zone) without that overhead.
The Infrequent Use Case
An asset uploaded directly via the REST API without a zone context has a null zone_id. It remains addressable by UUID and is baked and chunked normally. Any zone can instance it via CMD_INSTANCE_ASSET.
In Core and Done by Us
- Migration: add
zone_idtoshared_files Uro.SharedContent.SharedFile— addbelongs_to :zoneUro.VSekai.Zone— addhas_many :shared_filesUro.VSekai.list_zone_assets/1— query by zone_id
Status
Status: Proposed
Decision Makers
- iFire
Further Reading
20260421-zone-asset-manifest.md— exposes zone assets via GET /shards/:id/assets20260421-content-addressed-asset-delivery.md— casync baking pipelinemultiplayer-fabric-zone-backend/lib/uro/shared_content/shared_file.ex