Skip to content

Assets, derivatives and metadata

An asset is the logical unit a user thinks in: one photo, one video, one recording, one document. Its identity is the asset_id minted when it first enters the mesh, and its physical representation is a set of blob objects sharing that asset_id — one original and any number of derivatives.

An asset is immutable. Editing a photo produces a new asset (optionally recorded as related in the metadata tables); there is no in-place mutation to merge and therefore no conflict algebra in the blob plane. The mutable facts about an asset — title, tags, album membership, favorite state — belong in tables with the appropriate SOP/1 workload class, where concurrent edits already have defined semantics.

Queryable metadata lives in ordinary SOP/1 APPEND_DELETE Parquet tables, not in the blob plane. This extension does not fix the application’s schema; it fixes the contract between the planes:

  1. Every asset MUST have exactly one governing row set in the table named by its manifests’ asset_table, keyed by asset_id. That table’s equality deletes are the asset’s deletion authority (lifecycle).
  2. A row referencing blob bytes MUST reference them by storage_id, and SHOULD carry the object’s content_type and sizes alongside, so that placement and display decisions need no manifest lookup.
  3. References point in one direction only: the index references blobs; blobs never reference the index. A blob manifest names its lifecycle table but never row identities, foreign keys, or query state.

A representative (non-normative) governing table:

assets (APPEND_DELETE, identity = asset_id)
asset_id
original_storage_id
content_type
captured_hlc
capture_lat, capture_lon
width_px, height_px, duration_s
source_device
derivative_storage_ids[] -- or a companion asset_derivatives table

Derived features computed later — labels, embeddings, transcript text — land in further ordinary tables keyed by asset_id. Media search is a query over the tabular plane that returns storage_ids; the blob plane is only ever asked for bytes it can address.

A derivative is an independent SOP-BLOB-1 object: its own DEK, its own manifest carrying derived_from and derivative_kind, its own access records, the same asset_id.

Derivatives are separate objects rather than embedded previews for three reasons, all borrowed from systems that ship this at scale:

  • Access asymmetry. Browsing a library touches thumbnails by the thousand and originals rarely. Separate objects let placement policy pin the small hot set everywhere and leave originals on storage-rich nodes.
  • Scope asymmetry. A device entitled to show a grid need not be entitled to originals (section 4).
  • Regenerability. A derivative is recomputable from its source. Keeping that property explicit in the object graph is what makes derivative garbage collection safe (lifecycle, section 2).

Streaming-oriented derivatives are the intended answer to format-aware playback: an application MAY produce a transcode segmented for adaptive streaming and store it as one blob object (with its playlist or segment index as encrypted metadata or a small companion object), rather than asking the plane for smaller chunks. The plane’s 1 MiB range granularity (format, section 3) is deliberately format-blind.

Derivative production SHOULD follow the compaction placement guidance (SOP/1 section 18.4): schedule it on powered, storage-rich devices; a phone that captured a video need only publish the original and a cheap thumbnail.

Because every object’s access is granted individually, derivatives MAY be assigned to a broader domain than their originals:

PHOTOS domain laptop, phone, home-server
PHOTOS-PREVIEW domain laptop, phone, home-server, wall-display
original -> AccessRecord under PHOTOS
thumbnail -> AccessRecord under PHOTOS-PREVIEW

The wall display holds thumbnail DEK grants and blind ciphertext of nothing else; the originals’ domain membership never grows. The entitlement rule of SOP/1 section 7.6 applies unchanged: an access record for an object is never created under a KEK generation whose holders include a device not entitled to that object.

The domain-granularity guidance of SOP/1 section 6.4 also applies unchanged: create a preview domain when a device that must not read originals actually exists, not before.

Nothing in this extension requires an asset’s bytes to originate on a mesh node. An importer that reads an export archive, a camera roll, or a backup MAY mint assets, publish originals, and enqueue derivative production in one pass — the publication pipeline’s durability and idempotency rules (SOP/1 section 13.2) are what make a crashed import resumable.