Part XV. Assets
This part is proposed for 0.2. The steward asked for it on 18 October 2026: Part XIV keeps fonts, PDF renditions, outside drawings and signed containers as binary files by digest, and no version of 0.1 can hold one. It is not part of OpenEik 0.1, and no 0.1 conformance class requires it. A 0.1 reader leaves binary files alone, assets/ among them, and never removes them (Part III, 7, rule 2). The steward decided its six questions on 18 October 2026, as this part proposed them (open questions 30 to 35; section 12). Since 23 October 2026, @openeik/tools keeps assets in its versions with the proposal assets (section 11).
1. Status and scope
An asset is a binary file of a model, kept by the SHA-256 of its bytes: a PDF rendition or an outside drawing, a font, a signed container, a photograph attached to a review. Part XIV names its assets at assets/<sha256>.<ext> (Part XIV, 7.3). A later version may add other kinds, such as the large meshes of declared geometry (Part II, 6.6, rule 6).
A version of 0.1 holds records and kept files, each as the canonical form of JSON text (Part VI, 1), and a kept file is UTF-8 text of at most 1 MiB (Part III, 7, rule 2). A binary file is left alone: no version holds it, no store keeps it, and a push, a pull or a clone leaves it behind. So a drawing issued with its fonts and its PDF/A rendition reaches another store without them, and its sign-offs name a file that no one there can fetch.
This part keeps an asset in a version as Git LFS keeps a large file in a git repository: by its digest. In a folder, an asset is the file itself. In a version's tree, it is a small pointer that names the bytes by their SHA-256 and their length. The bytes are kept beside the versions, in the store, by their digest, and travel with a push, a pull and a clone. Since a version names an asset's bytes by their digest, its root hash commits to them (section 3); and since the bytes are not in the version, a store can let go of bytes that have to go without rewriting any version (section 7).
1.1 At 0.2 this text moves into
- Part III:
assets/in the folder (1), assets as a file kind of their own beside records and kept files (3 and 7), and what the single-file form leaves out (11, rule 3); - Part VI: pointers in trees (2), assets in a diff and a merge (4 and 5), and in a fetch, a push, a pull and a clone (6);
- Part XIV: 7.3 and 7.4, rule 5 point to this part, whose kinds add the photographs that 13.2 attaches;
- Conformance: what a reader, a writer, a validator and a version store do with assets;
- Security and privacy: assets in 2.4, 5.3, 7.1 and 11;
- the extension registry:
assetsbecomes a folder the standard gives, no longer one it plans.
2. In a folder
- An asset is the file
assets/<sha256>.<ext>:<sha256>is the SHA-256 of the file's bytes, as 64 lowercase hexadecimal digits, and<ext>the extension of its kind (section 4).assets/holds assets only, and no folder. - An asset is never changed: its name is its bytes' digest. A writer MUST write an asset's bytes as they are, and MUST NOT write over an asset.
- A file in
assets/whose bytes do not give its name, or whose name is not an asset's, is not an asset. A reader MUST NOT read it as one: it reports the file and leaves it alone. A validator reports it as an error. - A writer MUST NOT remove an asset that the model names (section 8). It MAY remove one that the model does not name.
- An asset is not a kept file: Part III, 7's limits of size and of text do not hold for it, and section 4's do.
3. In a version
- In a version's tree, an asset is the leaf at its path in the folder,
assets/<sha256>.<ext>, extension included. Its object is the asset's pointer: the canonical form (Part III, 6) of{"asset": {"bytes": <n>, "sha256": "<sha256>"}}, wherebytesis the file's length in bytes andsha256its name's digest. - A reader of versions MUST refuse a version that holds, under
assets, a sub-tree that is not a shard (Part VI, 2.3), or a leaf that is not such a pointer or whosesha256is not its name's digest, naming the entry. - The bytes are not in the tree. A version store keeps them beside its objects, by their SHA-256 (section 5).
- A version's root hash commits to every asset the version holds: two versions with one root hash name the same bytes, by the same digests.
- Making a version from a folder makes each asset's pointer, and writing a version into a folder writes each asset's bytes at its path. Neither changes a byte.
- A diff reports an asset added or removed, by its path (Part VI, 4). An asset is never changed: other bytes are another asset, at another path.
- A merge merges pointers file by file, as it merges kept files (Part VI, 5, rule 5). An asset added on both sides is one asset. A merge that removes an asset which the merged model names MUST be refused, naming the asset and what names it (Part VI, 5, rule 7).
A folder holds a PDF rendition of 812 344 bytes at assets/<sha256>.pdf. The version's tree holds, in its sub-tree assets, the entry ["<sha256>.pdf", "b", "<the pointer's hash>"], and the pointer is
{"asset":{"bytes":812344,"sha256":"<sha256>"}}
4. Kinds and limits
| Extension | Media type | What | Its bytes begin with |
|---|---|---|---|
pdf | application/pdf | a PDF rendition, an outside drawing (Part XIV, 8.3 and 15) | %PDF- |
ttf | font/ttf | a TrueType font of the drawing profile (Part XIV, 4.1) | 00 01 00 00 or true |
otf | font/otf | an OpenType font with CFF outlines | OTTO |
asice | application/vnd.etsi.asic-e+zip | a signed container of the legal tier (Part XIV, 14.6) | PK 03 04, its first entry mimetype |
png | image/png | an image attached to a review item (Part XIV, 13.2) | 89 50 4E 47 0D 0A 1A 0A |
jpg | image/jpeg | a photograph attached to a review item | FF D8 FF |
- An asset MUST be of one of these kinds. Its bytes SHOULD begin as its kind's do; a validator warns about one that does not.
- An asset MUST be at most 64 MiB (67 108 864 bytes), as an issued drawing is (Part XIV, 7.3). A host MAY set a lower limit, and a quota for a building, and says what they are.
- A later version may add kinds. A reader keeps an asset of a kind it does not know: in a folder it leaves the file alone, and in a version it keeps the pointer and writes it back. A writer of 0.2 MUST NOT write one.
5. In a store
- A version store keeps the bytes of assets by their SHA-256, beside its objects. When it takes bytes in, it MUST check that their SHA-256 and their length are those of the pointer that names them, and refuse them otherwise.
- A store that others fetch from (a host) MUST hold the bytes of every asset that a version on one of its refs names, unless it has withheld the asset (section 7). It MUST NOT move a ref to a version that names an asset whose bytes it neither holds nor has withheld.
- A store MAY hold a version without its assets' bytes, and fetch them when they are needed: a partial store, as a clone with Git LFS is. Asked for an asset it lacks, it MUST say that it lacks it, and never answer with other bytes.
- A store answers for an asset, with its bytes or with whether it holds them, within one building only: to a caller who may read the building, about the assets its versions name, and to a caller who may push to it, about the assets a push sends. An answer for a digest says that the file exists: a store that keeps one copy of some bytes for several buildings MUST NOT let its answer for one building tell of another's.
6. Push, fetch, pull and clone
- A push sends, before it moves the remote ref (Part VI, 6.3), the bytes of every asset that a version it sends names and that the remote lacks. Only bytes the remote lacks are sent. A squashed push (Part VI, 6.3, rule 3) sends one version, and so the assets of the newest tree only.
- A fetch reads the objects it needs, pointers among them (Part VI, 6.2). It MAY leave the bytes behind.
- A pull or a clone into a folder MUST fetch the bytes of every asset of the version it writes, and check each as section 5, rule 1 says, before it writes anything. An asset that it cannot fetch, or that fails the check, stops it, naming the asset, unless the asset is withheld (section 7).
- A store that pulls or clones without writing a folder MAY fetch the bytes later, when an asset is read.
7. Withheld assets
- A store MAY withhold an asset: let go of its bytes, keep every pointer to it, and record that it is withheld. It does so when the asset has to go: personal data that a person asks to have erased (Security and privacy, 2.4), a licence that has ended, an order. A withheld asset stays withheld in that store.
- A version that names a withheld asset stays readable. A reader reports the asset as withheld, a warning; a checkout writes no file for it; and a validator does not count it as missing (section 8, rule 2).
- A push of a version that names an asset withheld at the pushing store says so. The remote MAY then accept the version and record the asset as withheld, or refuse it.
- What was signed by the asset's digest stays signed (Part XIV, 14), and can no longer be checked against its file: a reader says so.
8. References
- Part XIV names assets by path,
assets/<sha256>.<ext>: an unlinked drawing'sfile.asset(8.1 and 8.3), the drawing profile'sfonts[].file(4.1), a review item'sattachments[].asset(13.2), and a sign-off'slegal.assetand its statement's subject (14.1, 14.2 and 14.6). Its register names them by digest (11.1). Asha256given beside a path MUST be the path's digest. - In a model, an asset named by path MUST be in it: in a folder, its file; in a version, its pointer. A validator reports one that is not as an error, and one that is withheld as a warning.
- An asset that no member of the model names is unused. A validator MAY warn about it, and a writer MAY remove it (section 2, rule 4); the versions before keep it.
- A digest without a path names a file the model need not hold: a font that the project may not store (Part XIV, 4.3, rule 4), or a rendition that was not kept (Part XIV, 15.2, rule 5).
9. The single-file form, git and hosts
- The single-file form (Part III, 11) carries no asset. Its members name assets by path, and the assets travel beside it, in a folder
assets/next to the file. Reading a folder into one file and writing it back loses no asset only when the assets travel so; Part III, 11, rule 3 counts them among what the single-file form may lose. - A folder kept in git keeps its assets as files. A tool SHOULD mark
assets/**as binary (-text), as Part XIV, 1.5 says, and MAY keep them with Git LFS, whose pointer names the same SHA-256 as this part's. - A host whose store takes only JSON text keeps no asset until it keeps bytes beside its objects. Until then it MUST NOT move a ref to a version that names an asset (section 5, rule 2).
10. Security and privacy
- No asset is code (Security and privacy, 11). A reader that shows an asset MUST NOT run anything it holds: a PDF's scripts, actions and launch links, or a program in a container. It reads a rendition's attachments as data, to check them against the issued files (Part XIV, 15).
- Fonts. A reader that draws with a font from a model SHOULD pass it through a font sanitiser first, as browsers do with fonts from the web: font files have carried attacks on the programs that draw them.
- Containers. A reader that opens a container MUST bound the number and the size of its entries, and refuse an entry whose path leaves the container.
- Bounds. A reader of a model from a source it does not control SHOULD bound how many assets, and how many bytes in all, it fetches and keeps (Security and privacy, 7.2).
- Integrity. An asset is checked by its SHA-256 wherever it arrives (section 5, rule 1). A store that answers other bytes for a digest is refused (section 6, rule 3).
- Photographs are personal data. A photograph shows people, places and things, and its metadata may say where and when it was taken, and with which camera. A writer SHOULD take that metadata out of a photograph before it becomes an asset: once named by its digest, its bytes are fixed. A store withholds a photograph that a person asks to have erased (section 7).
- Confidential files. An outside drawing or a rendition is as confidential as the model it is in. A host gives an asset only to those who may read a version that names it (section 5, rule 4). A host that narrows what a member reads by folder treats
assets/as a folder like any other. - Serving a file. A host that serves an asset over the web SHOULD send it with its kind's media type and as a download, never as a page of its own site: a file that a browser takes for a page could run there.
11. Conformance
A validator that implements this part checks section 2's names against the bytes, section 4's kinds and limits, section 3's pointers in a version, and section 8's references. A version store that implements it keeps bytes as section 5 says, and moves them as section 6 says.
- checks a folder's assets as sections 2 and 4 say;
- makes each asset's pointer in a version, and reads and checks the pointers of a version it reads (section 3);
- sends the bytes a store lacks before a push moves its ref, and fetches and checks every asset of the version a clone or a pull writes before it writes anything (section 6);
- merges a pull's assets file by file, refusing a merge that removes an asset the merged model names (section 3, rule 7);
- keeps the pointers of assets a store has withheld (section 7).
It talks to a store through the three assets calls of the store API it speaks, which the guide Reading and saving models describes (section 5.2), and has a suite of 8 conformance cases for a folder's rules (conformance/proposed/assets/). It does not yet keep the pointer of an asset of a kind it does not know when it writes a version into a folder (section 4, rule 3).
The reference implementation keeps the PDFs it publishes as files of its project, outside the model, and its issued SVGs as kept files (Part XIV, 1.5). A store that takes objects as JSON text, and checks each object's hash against its text, cannot hold an asset as an object.
12. The decisions
The steward decided open questions 30 to 35 on 18 October 2026, each as this part proposed it.
| Question | Decision | Decided |
|---|---|---|
| 30 | How a version holds an asset | a pointer leaf of JSON text, with the bytes beside the version (section 3) |
| 31 | The kinds of 0.2 | pdf, ttf, otf, asice, png and jpg; meshes later (section 4) |
| 32 | The size of an asset | at most 64 MiB, and a host's own limit and quota below it (section 4) |
| 33 | Whether a fetch may leave bytes behind | yes; a pull or a clone into a folder fetches what it writes (section 6) |
| 34 | Whether a store may withhold an asset | yes, keeping every pointer to it (section 7) |
| 35 | Who may remove an unused asset | any writer; the versions before keep it (sections 2 and 8) |