Assets and versioning
Asset identity, storage locators, the five typed version relations, lifecycle states, and how composition and external identifiers ride along.
An asset in OWG is a typed, versioned, governed object that carries a locator to wherever the bytes physically live. The asset node holds governance; the storage system holds content. That separation is what lets the same governance record survive a migration between clouds.
{
"id": "delivery_mp4",
"role": "delivery",
"type": "video.delivery",
"content_type": "video/mp4",
"version_relation": "representation",
"predecessor": "source_mov",
"produced_by": "transcode",
"state": "delivered",
"storage": {
"provider": "s3",
"locator": "s3://studio-media/out/clip.mp4",
"zone": "us-east-2"
}
}Only id is required.
Fields
| Field | Type | Notes |
|---|---|---|
id | string | Required. Document-local identifier |
identity | string | Global content-derived identity — content hash or credential manifest reference |
type | string | Asset kind. Open set: video, audio, image, text, model, lora, document |
role | string | Its function in this workflow: source, delivery, thumbnail, captions |
content_type | string | MIME type |
storage | object | Provider, locator, and optional zone or timerange |
produced_by | string | Task id — derived; the task's produced[] is authoritative |
predecessor | string | The asset this one came from |
version_relation | enum | How it relates to its predecessor. See below |
state | enum | Lifecycle position. See below |
assurance | enum | attested | asserted | inferred. See below |
credentials | object | e.g. { "scheme": "c2pa" } |
identifiers | array | External identifier pass-through |
depicts | — | What the asset shows |
depicts_real_entity | — | Deepfake trigger. See AI disclosure |
composes | array | Composition arcs. See below |
profiles | object | Profile-contributed extensions, keyed by profile id (v0.92). See Extensions |
id versus identity. id is local to the document and is what tasks reference. identity is the global, content-derived identity — a hash, URN, or content-credential manifest reference — and it is what lets the same asset be recognised across many runs, systems, and organizations. Populate both.
Typed version relations
This is one of the most consequential details in the specification. The relationship between versions is typed, not merely numbered.
| Relation | Meaning | Example |
|---|---|---|
revision | Incremental change, same context | Rejected comp re-rendered after notes |
variant | Change for a different context | Pristine versus battle-damaged prop |
derivation | A new thing that acknowledges its source | A model trained from a base checkpoint |
representation | Pure format change, same meaning | The proxy of a master |
alternative | One pick from equivalent options | Concept sketches to choose between |
Correctly labelling the relation is the difference between semantically correct lineage and a version counter that quietly lies. Two rules are worth memorising:
- A proxy is not a
revisionof the master. It is arepresentation— same meaning, different format. - An approved retake is a
revision, not a new asset.
Get these wrong and every downstream question — which shots use the latest approved version?, what is this derived from? — returns a confidently incorrect answer. A numbered version chain cannot distinguish "this replaces that" from "this is another way of expressing that", and those have opposite implications for approval.
{
"id": "hero_prop_battle_damaged",
"version_relation": "variant",
"predecessor": "hero_prop_pristine"
}{
"id": "master_proxy_h264",
"version_relation": "representation",
"predecessor": "master_prores"
}Lifecycle states
| State | Meaning |
|---|---|
draft | Work in progress |
growing | Still being appended to — a live feed. See below |
in_review | Submitted, awaiting a decision |
accepted | Approved |
delivered | Handed over |
superseded | Replaced by a newer version |
rejected | Not approved — and retained in the graph |
A rejected asset stays in the graph as a rejected state rather than disappearing. Nothing is overwritten, which is what makes the audit trail a record rather than a reconstruction.
Growing assets
growing is how OWG handles media that is still being captured, without mirroring a single byte:
- While an asset is
growing, itsidentityis the source UUID fromidentifiers[]rather than a content hash — you cannot hash a file that is still being written. - The producing ingest task stays open for the duration.
- When the referenced range closes, fixity is computed over the now-bounded range and the state advances.
This is what carries the model into live sports and news. See the TAMS binding.
Storage locators
{
"storage": {
"provider": "tams",
"timerange": "[1500:0_1620:0)"
}
}provider is an open string. Commonly used values — an implementation may register its own:
| Provider | Meaning |
|---|---|
s3, gcs | Object storage |
saas_dam, iconik, frameio | SaaS asset managers |
camera_media_card | Media not yet ingested |
tams | Time-addressable media store |
usd_resolver | An OpenUSD logical asset identifier |
protected_store | A hardened or protective storage tier |
timerangeis stored opaquely. OWG does not parse or interpret time. The half-open[s:ns_s:ns)syntax belongs to TAMS, and resolving it to bytes is TAMS's job. OWG deliberately does not attempt to solve the International Atomic Time to SMPTE timecode mapping.
External identifiers
OWG never strips an incoming identifier, even one it does not use itself.
{
"identifiers": [
{ "scope": "tams.source", "id": "0f7e...-a91c" },
{ "scope": "usd.assetInfo", "id": "asset://hero_prop/v23" },
{ "scope": "frameio.id", "id": "b2c8e9f1" },
{ "scope": "c2pa", "id": "urn:uuid:9e21..." }
]
}Both scope and id are required per entry. Documented scopes: tams.source, usd.assetInfo, frameio.id, c2pa, urn. Preserved identifiers are the highest-confidence signal for relating objects that arrive from different systems — see declared assurance.
Composition
composes[] records that an asset is assembled from other assets, using the arc vocabulary of the composition system it came from.
{
"id": "shot_0140_assembly",
"composes": [
{ "component": "hero_prop_v23", "arc_type": "reference",
"prim_path": "/World/Set/Hero", "variant_selection": "lod=high" },
{ "component": "env_backlot_v4", "arc_type": "payload",
"prim_path": "/World/Env" }
]
}Arc types: reference, payload, sublayer, inherit, specialize, variant. Only component is required.
The graph never descends below the published-asset boundary. prim_path and variant_selection are opaque edge properties — OWG stores them and does not interpret them. That boundary is what keeps a governance graph from turning into a scene graph.
Assurance and credentials
{
"assurance": "attested",
"credentials": { "scheme": "c2pa" }
}Assurance states how strongly an asset's identity is backed. It uses the same three levels, and the same rule about confidence, as relationships:
| Level | Meaning | Requires confidence + method |
|---|---|---|
attested | A cryptographically verified content credential backs this | No |
asserted | Declared by a participant or system, without cryptographic attestation | No |
inferred | Identity established by a matcher rather than declared | Yes |
An inferred identity carries its score and method, exactly as a proposed edge does:
{
"id": "recovered_plate_0140",
"identity": "sha256:9f2c…",
"assurance": "inferred",
"confidence": 0.79,
"method": "m-corroborated-2"
}The schema enforces the pairing in both directions: inferred without confidence and method is a validation error, and attested or asserted with them is also an error — a confidence score on a human assertion is meaningless.
Offline and physical steps default to asserted: a manually logged camera card is an assertion, whereas signed device output is an attestation. The ingest station — where physical provenance becomes digital provenance — is the boundary where one can become the other.
Note that the C2PA declaration lives on the asset, not on the task that produced it.