Version: 0.4.1
Category: Standards Track
Status: Final Draft — Authorized for canonfs-rs 1.0
Target v1.0 Release: Q4 2026
Applies to: T81 Architecture, HanoiVM, Axion Kernel, CanonNet, T243–T19683 tiers
CanonFS is the native filesystem for ternary (T81-class) computing.
It is immutable, content-addressed, capability-secured, self-healing, tryte-compressible, and tensor-indexable.
CanonFS replaces:
…with a single unifying primitive:
CanonRef = capability + content hash + (optional) sealed envelope metadata
CanonFS guarantees deterministic indexing, perfect provenance, global uniqueness, and automatic parity-based recovery — all without compromising immutability.
CanonFS is legally defined by five invariants. Violation of any is a protocol-level error:
CanonHash-81(serialized_form).f(hash) MUST remain stable forever.A CanonBlock is the indivisible storage atom of CanonFS.
CanonHash-81(block)| Form Type | Tag Range | Description |
|---|---|---|
| Raw | 0x00–0x0F | Uncompressed payload |
| Compressed | 0x10–0x1F | LZ81 or Z3std tryte-optimal compression |
| Encrypted | 0x20–0x2F | CanonSeal AEAD envelope (ternary ChaCha variant) |
Hashing always occurs post-decompression + decryption, ensuring identical logical content yields identical identities.
CanonHash-81 is defined as:
CanonHash-81(data) := base81_encode( BLAKE3(data)[0..60] )
CanonHash-81 is the sole hash function permitted for CanonFS v0.3–v1.0.
All objects begin with a one-byte Type ID, preventing type confusion attacks.
| Type ID | Object Type | Description |
|---|---|---|
| 0x00 | RawBlock | 729-tryte canonical block |
| 0x01 | FileNode | Merkle-81 interior node or leaf reference |
| 0x02 | Directory | Sparse 81×81 tensor |
| 0x03 | Snapshot | CanonHash-81 of root directory |
| 0x04 | CapabilityGrant | v2 signed capability (§6.1) |
| 0x05 | CapabilityRevoke | Signed anti-token used for canonical deletion |
| 0x10 | CompressedBlock | [algo][compressed_payload] |
| 0x11 | CanonParity | Reed–Solomon parity shard (§7) |
| 0x12 | CanonIndex | Sparse inverted index |
| 0x13 | CanonMeta | Sparse metadata tensor |
| 0x14 | CanonSeal | Encrypted + authenticated envelope |
| 0x15 | CanonLink | Symbolic link with optional display hint (§6.2) |
| 0x16 | CanonExec | Executable metadata + entrypoint |
| 0x17–0x1F | Reserved | |
| 0x20 | CanonTensor | Canonical tensor object |
Object identity is always:
CanonHash-81( TypeID || SerializedPayload )
CapabilityGrant ::= {
target: CanonHash-81, // Object or subtree root
permissions: u16, // Bitfield: rwx-search-exec
granted_by: CanonHash-81, // Public key OR prior grant hash
expires_at: u64, // T81 chain height; 0 = never
revocable_by: CanonHash-81, // Entity allowed to revoke
signature: 81-tryte ed448-ph (or QR-resistant successor)
}
Capabilities are content-addressed, delegatable, and tamper-evident.
CanonLink ::= {
target: CanonHash-81,
display_hint: Option<UTF8 String ≤ 255 trytes>
}
display_hint MUST NOT affect CanonHash-81.
CanonFS operations are Axion-guarded. Every AXSET/AXREAD/AXVERIFY interaction triggers an Axion syscall before touching storage so the Axion kernel can enforce capability constraints, recursion bounds, and policy predicates.
meta slot axion event segment=meta addr=<value> entry to the Axion trace before the actual write. CanonFS implementations MUST emit action=Write for AXSET/write_object paths and action=Read for AXREAD/read_object paths so policies can assert them via (require-axion-event (reason "<substring>")).meta slot string every time CanonFS writes persist metadata (e.g., capability grants, snapshots, links). Changing the verbatim string invalidates RFC-0020 policies and must be coordinated through a new RFC.canonfs_axion_trace_test reproduction (see docs/guides/axion-trace.md) records those exact strings into build/artifacts/canonfs_axion_trace.log, providing auditors with a reference trace that CanonFS policies can expect before touching the filesystem.Maintaining this contract makes CanonFS the canonical source of policy-verified persistence for Axion-aware binaries: canonical trace strings, capability enforcement, and deterministic writes all execute before the block is sealed inside CanonFS.
The reference implementation exposes make_persistent_driver(root) (see include/t81/canonfs/canon_driver.hpp), creating a directory tree under root with objects/, caps/, and parity/. Each object is stored at objects/<hash>.blk, while capability masks live at caps/<hash>.cap as decimal perms values. The driver currently treats parity/ as a placeholder directory for future repair shards.
Every write_object, read_object_bytes, publish_capability, and revoke_capability invocation runs the Axion hook before mutating objects/ or caps/. That hook emits the canonical meta slot axion event segment=meta addr=<n> action=Write (for writes) and action=Read (for reads), so scripts/capture-axion-trace.sh can verify canonfs_axion_trace_test produces the same strings auditors expect. Capabilities gate access via the CANON_PERM_READ/CANON_PERM_WRITE bitmask; when no capabilities exist the driver permits bootstrap writes, but once a capability is published, only callers with the matching mask may read or write the object.
Read paths re-verify content identity by default: after loading bytes, the driver recomputes CanonHash and compares it to the requested CanonRef. Mismatches fail with deterministic decode errors. A diagnostic override exists via T81_CANONFS_READ_VERIFY=0.
This driver fulfills the Axion observability requirements in a deterministic, disk-backed form: writes now flush to persistent storage, the Axion trace includes the canonical meta slot events before any data touches disk, and audits can replay the resulting build/artifacts/canonfs_axion_trace.log snippet to prove that canonical strings preceded persistence.
CanonFS introduces automatic self-healing via parity shards.
Default policy: 3 data + 2 parity (survives any 2 losses)
Wire format (v0.4.1):
CanonParity ::= [
0x11,
data_count: u16,
parity_count: u8,
set_merkle_root: CanonHash-81, // NEW: O(1) validation
shard_idx: u8,
targets: CanonHash-81[data_count],
parity_data: 729 trytes
]
Implementations MUST verify set_merkle_root before reconstruction.
| Algo | Code | Typical Ratio | Speed | Use Case |
|---|---|---|---|---|
| LZ81 | 0x10 | ~2.8× | Fast | General files |
| Z3std | 0x11 | ~4.2× | Medium | Large tensors, logs, archives |
if entropy_9 >= 7.8 trit/bit => Z3std
else if repetitiveness >= 0.42 => LZ81
else => Raw
Compression occurs before hashing, ensuring identical logical content yields identical CanonHash-81.
CanonIndex provides fast search and indexing capabilities.
CanonHash-81(token or n-gram)Useful for full-text search, semantic index, and metadata lookup.
Key/value metadata controlled entirely by hashes.
Used for xattrs, user metadata, or extended ACL semantics.
Encryption is object-local and content-address stable.
KDF(capability || object_hash)Leaves may be:
…but all MUST reduce to identical logical content before hashing.
Directory ::= {
entries: Map<(u8,u8), CanonRef>,
index: CanonRef | null, // CanonIndex
meta: CanonRef | null, // CanonMeta
parity: [CanonRef] // Optional CanonParity shards
}
Deterministic. Immutable. Content-addressable.
| Object | Canonical Wire Format |
|---|---|
| CompressedBlock | [0x10][algo u8][len u16][compressed_bytes] |
| CanonParity | [0x11][data_count u16][parity_count u8][set_merkle_root][idx][…] |
| CanonIndex | [0x12][term_count u32][term_hash, CanonRef[], offsets[]] |
| CanonMeta | [0x13][pair_count u16][(key_hash value_hash)…] |
| CanonSeal | [0x14][nonce 24 trytes][ciphertext][tag 16 trytes] |
| CanonTensor | [0x20][ver][fmt][rank][res][shape][payload] |
Integers must be little-endian.
Implementations MUST:
Deletion is logical:
Delete = publish CapabilityRevoke tombstone
| Operation | Behavior (v0.4.1) |
|---|---|
| Write | Creates new objects + parity + optional index |
| Read | Capability validation → hash check → auto-repair → decompress/decrypt |
| Search | Via CanonIndex (fallback to brute traversal) |
| Delete | CapabilityRevoke tombstone |
| Recover | Fully automatic |
Must implement:
Exposes structured, layered views:
.canon/meta/.canon/index/.canon/parity/.canon/raw/Hidden unless CANONFS_DEBUG=1 or -o debug is enabled.
Planned for post-1.0:
| Workload | Compression | Parity (data:parity) | Index |
|---|---|---|---|
| General files | LZ81 | 3:2 | Yes |
| Large tensors/logs | Z3std | 6:3 | Yes |
| Cognitive graphs | Z3std | 9:3 | Full |
| Cold archival | Z3std | 10:10 | No |