@fleetmesh/textile
The FleetMesh Textile 8-layer content-addressed data plane in TypeScript:
Fiber → Strand → Spool → Fabric → Quilt → Suit → Fit → Tombstone
While @fleetmesh/leaf provides the mediated WebSocket transport, gift-wrapped DIDComm v2 messaging, and NIP-77 Negentropy wire protocol, @fleetmesh/textile provides the universal content-addressed data structures, 1024-byte leaf Bao Merkle DAGs, deterministic CRDT merges, 6-rung Privacy Ladder enforcement, XChaCha20-Poly1305 shard sealing, pluggable storage vaults, and NIP-77 Negentropy set reconciliation across any FleetMesh application (MeshTube, MeshDrive, MeshDocs, MeshChat, MeshGit).
Dependencies are limited to @fleetmesh/leaf and the audited @noble/* and @scure/base cryptographic libraries, pinned exactly.
Installation
npm install @fleetmesh/textile @fleetmesh/leaf
Both top-level named imports and @fleetmesh/leaf-style namespace imports are supported:
import {
MediaFiber,
MetadataFiber,
MediaStrand,
PlaylistFabric,
SovereignQuilt,
FiberVaultRepository,
reconcileTextileVaults,
utf8,
} from '@fleetmesh/textile';
// Or via modular namespaces:
import { bao, canonical, primitives, sealing, signatures, storage, leafBridge } from '@fleetmesh/textile';
Quickstart
import {
createSchnorrTextileSigner,
FiberVaultRepository,
IdentityFiber,
MediaFiber,
MediaStrand,
MetadataFiber,
PlaylistFabric,
reconcileTextileVaults,
SealedShardFiber,
SovereignQuilt,
TextileQuilt,
utf8,
} from '@fleetmesh/textile';
const skHex = '11'.repeat(32);
const signer = createSchnorrTextileSigner(skHex);
const alice = { identity_id: 'alice', did: signer.signerDid, handle: 'alice' };
// 1. Layer 1 (Fiber): Content-addressed atomic byte sequences (1024B leaf Bao Merkle root)
const videoFiber = MediaFiber.fromBytes(utf8('video-payload'), 'video/mp4', { author: alice });
const metaFiber = new MetadataFiber({ title: 'Hello Mesh', synopsis: 'Intro video', content_domain: 'video' });
// 2. Layer 2 (Strand): Role-tagged Fiber references spun into a versioned asset
const strand = new MediaStrand({
id: 'strand-hello-mesh',
title: 'Hello Mesh',
author: alice,
fibers: [videoFiber.toStrandRef('primary'), metaFiber.toStrandRef('metadata')],
});
// 3. Layer 4 (Fabric): Deterministic CRDT collection of Strands
const playlist = PlaylistFabric.create({
fabricId: 'fabric-featured',
owner: alice,
title: 'Featured Videos',
strands: [strand.toManifest()],
});
// 4. Layer 5 (Quilt): Stitch Fabrics, IdentityFibers, and XChaCha20-Poly1305 SealedShardFibers
const vaultKey = new Uint8Array(32).fill(0x42);
const sealedHistory = SealedShardFiber.sealWithKey(
'watch_history',
utf8(JSON.stringify({ watched: [strand.id] })),
vaultKey,
);
const idFiber = IdentityFiber.fromProfilePayload(alice.did, { handle: 'alice' });
const sovereignQuilt = new SovereignQuilt({
id: 'quilt-alice',
author: alice,
identityFibers: [idFiber.toStrandRef('primary_asset')],
fabrics: [playlist],
shardFibers: [sealedHistory.toQuiltShardRef()],
});
// Project a public Quilt view (automatically strips private fabrics and sealed shards)
const publicQuilt = sovereignQuilt.projectForAudience('public');
const sigEnvelope = publicQuilt.signWithKey(skHex);
// 5. Persist primitives into a content-addressed Vault and reconcile with a remote peer via NIP-77
const aliceVault = new FiberVaultRepository();
const bobVault = new FiberVaultRepository();
await aliceVault.putPrimitive(videoFiber);
await aliceVault.putPrimitive(metaFiber);
await aliceVault.putPrimitive(strand);
await aliceVault.putPrimitive(playlist);
await aliceVault.putPrimitive(publicQuilt);
const diff = await reconcileTextileVaults(bobVault, aliceVault);
for (const root of diff.needRoots) {
const bytes = await aliceVault.getFiber(root);
if (bytes) await bobVault.putFiber(bytes, { expectedRoot: root });
}
// Rehydrate and verify typed primitives from the vault
const hydratedQuilt = await bobVault.getPrimitive(publicQuilt.root, TextileQuilt.fromManifest);
console.log(hydratedQuilt?.verify(), hydratedQuilt?.verifySignature(sigEnvelope)); // true, true
The 8-Layer Textile Hierarchy
| Layer | Base Class | Canonical MIME Type | Subclasses & Role |
|---|---|---|---|
| 1. Fiber | TextileFiber | application/vnd.fleetmesh.fiber+octet-stream | Atomic content-addressed byte sequences (1024-byte leaf Bao Merkle tree). Subclasses: MediaFiber, RawBlobFiber, MetadataFiber (JsonMetadataFiber), TimedFiber (MTF1), InteractionFiber, IdentityFiber, SealedShardFiber (MTS1 XChaCha20-Poly1305), ChunkedFiber (Height-10 1 MiB macro-chunk subtrees). |
| 2. Strand | TextileStrand | application/vnd.fleetmesh.strand+json | Spins role-tagged TextileFiber references (FiberRefCollection) into a versioned semantic asset (strand_root). Subclasses: MediaStrand, SubtitleStrand, CommentStrand, InteractionStrand, ScrobbleStrand, DocumentStrand, CodeRepoStrand, ArcadeRomStrand, ProductStrand, GroupStrand, TombstoneNoticeStrand. |
| 3. Spool | TextileSpool | application/vnd.fleetmesh.spool+json | Append-only live temporal buffer of TimedFibers (MTF1) governed by a BIP-340 signed operation chain (SignedSpoolOp). Calling .cut() compacts the live window into a FilamentStrand, SpoolLengthStrand, and SpoolCutFabric. |
| 4. Fabric | TextileFabric | application/vnd.fleetmesh.fabric+json | Ordered (append) or key-indexed (key) CRDT collection of TextileStrands, FabricDelimiters, and FabricInteractions (fabric_root). Subclasses: PlaylistFabric, FeedFabric, CatalogFabric, SubtitleLocalizationFabric, ViewLedgerFabric, TombstoneLedgerFabric, VaultFabric, CircleFeedFabric, ActivityFabric. |
| 5. Quilt | TextileQuilt | application/vnd.fleetmesh.quilt+json | Stitches an identity's or circle's TextileFabrics, IdentityFibers, SealedShardFibers, and live Spindle pointers into audience-scoped projections (self, circle, public) covered by quilt_root. Subclasses: SovereignQuilt, PublishedQuiltView, GroupQuilt. |
| 6. Suit | TextileSuit | application/vnd.fleetmesh.suit+json | Self-contained .fiberpack v2 (MTFP1\n) portable sovereign identity bundle (suit_root) for cross-device sync and Sneakernet / BLE / QR / USB transfer. Subclass: SovereignIdentitySuit. |
| 7. Fit | TextileFit | application/vnd.fleetmesh.fit+json | Content-addressed runtime policy engine (fit_root) governing storage quota, auto-pinning, tombstone boundary enforcement, and sealed-shard leak prevention. |
| 8. Tombstone | TextileTombstone | application/vnd.fleetmesh.tombstone+json | Cross-layer retraction and eviction primitive (PreemptiveTombstone, RetroactiveTombstone, LocalCacheTombstone, EphemeralTtlTombstone, FederatedQuarantineTombstone, SupersededRevisionTombstone, KeyRevocationTombstone) indexed by TombstoneLedgerRepository. |
Cross-Layer Symmetry & Core Invariants
Every layer class inherits from AbstractTextilePrimitive<TManifest> (and container layers inherit from CompositeTextilePrimitive<TManifest>):
- Symmetric Serialization & Hydration: Every layer provides
.toManifest(),.toCanonicalBytes(),.toCanonicalJson(), and staticClass.fromManifest(manifest)hydration, plusvault.putPrimitive(primitive)andvault.getPrimitive(root, Class.fromManifest). - Everything-is-a-Fiber Projection:
primitive.toManifestFiber()andTextileFiber.fromPrimitive(primitive)project any higher-layer manifest into a content-addressedTextileFiberwhoseroot === primitive.root. - Recursive Merkle DAG Traversal:
composite.childRefs(),composite.childRoots(),composite.collectClosureRoots(resolver),composite.verifySubtree(resolver),composite.findTombstonedChildren(predicate), andcomposite.evaluateClosureFit(fit). - Monotonic 6-Rung Privacy Ladder:
public→peer→circle→mutual→link→private. Callingprimitive.escalatePrivacyRung(next)ratchets privacy upward and throwsPrivacyEscalationErroron any de-escalation attempt. - Deterministic CRDT Merge:
strand.merge(remote),fabric.merge(remote), andquilt.merge(remote)satisfy commutativity, associativity, and idempotence (merge(A, B).root === merge(B, A).root). - Dual-Domain BIP-340 Schnorr Signing:
primitive.signWithKey(skHex),primitive.sign(signer), andprimitive.verifySignature(envelope)support bothfleetmesh.textile/v1andmeshtube.textile/v1domains as well as NIP-01 kind-30899replaceable events. - Typed Error Hierarchy: All domain errors inherit from
TextileError(BaoVerificationError,PrivacyEscalationError,SchemaValidationError,SpoolStateError).
Conformance & Multi-Engine Testing
Every primitive in @fleetmesh/textile is tested against frozen cross-language vectors in vectors/textile-v1.json and verified byte-for-byte against the Python 3 reference implementation, as well as across Node.js, Chromium, Firefox, and WebKit via Vitest browser mode on Playwright:
npm install
npm run typecheck # Strict TypeScript (erasableSyntaxOnly, noUncheckedIndexedAccess)
npm run build # Emit dist/*.js and dist/*.d.ts
npm test # Node.js unit, conformance, audit-guard & integration suites
npm run test:coverage # V8 coverage report across src/ (97%+ line coverage)
To run the full suite across Node.js, Chromium, Firefox, and WebKit simultaneously:
npm run browsers # Once: install Chromium, Firefox, and WebKit
npm run test:all # Run all suites across Node + 3 browser engines