Nodes

A node is a block referenced with the dag-cbor codec (§4) whose bytes are a canonical-CBOR map. Every node has:

  • v — integer, MUST be 1 for this version. The value 0 is invalid and permanently reserved; wire versions start at 1. (The "Version 0" in this document's title numbers the specification draft, not the wire format it defines.)
  • t — text string, the node type.

An unknown t, an unknown map field for the given type, or v ≠ 1 MUST be rejected. (Strict v1: format evolution changes v; the mixed-version and lowest-sufficient-version rules are in §15.1.)

Four node types exist:

tmeaningfields
"r"root (commit)e (REQUIRED): the root Entry (§7), usually a directory. OPTIONAL: ts (integer, unix seconds, MAY be negative), note (text ≤ 4096 bytes), prev (dag-cbor-codec Ref → previous root node).
"d"directoryExactly one of: e — entries array (flat form; MAY be empty), or p — page index (paged form; MUST be non-empty). See §8.
"ds"directory segmente — entries array, MUST be non-empty. Only ever referenced from a "d" page index.
"f"file nodesz — integer ≥ 0, total logical size; c — non-empty array of [size, Ref] pairs, each size ≥ 1, with sz = Σ sizes. See §9.

The complete set of legal edges between node types:

A "d" dir carries exactly one of e (flat) or p (paged); nested directories reach unbounded depth.

Entries array: an array of [name, Entry] pairs (each pair a 2-element array), sorted strictly ascending by name order (§3.3). Readers MUST reject unsorted arrays and duplicate names. Name rules: 1–255 UTF-8 bytes, no /, no NUL (U+0000), not ., not ...

UTF-8-only naming is a design constraint of this format, not an accident of encoding: name identity is the UTF-8 byte sequence (§3.3), and there is no representation for other byte sequences. A writer ingesting a source filesystem whose native names are raw byte strings (POSIX) MUST reject the ingest of any name that is not valid UTF-8. It MUST NOT instead substitute (U+FFFD), strip, or transliterate bytes, since two names surviving such a repair could collide and silently merge entries. The same rule applies to symlink targets (§7.3).

Root node validation: e MUST be a valid Entry; ts MUST be an integer (§2.3) when present; note MUST be a text string of at most 4096 UTF-8 bytes containing no U+0000; prev MUST be a dag-cbor-codec Ref, and the node it resolves to MUST be an "r" node — checked when the history chain is walked, not when the referencing root is validated (a block cannot see its neighbors).

unfs  A filesystem you can put in any key–value store.