Skip to content
DeWebProtocolPublic

About

User-controlled MALT local data runtime: CLI, daemon, local trust, UnixFS, backup and sync

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

MALT Local Data Runtime

MALT is a user-controlled local data runtime that runs on the user's device. It accesses local files, maintains local trust and keys, exposes authenticated data through local application interfaces, and communicates through replaceable transport capabilities built on the MALT Core SDK.

This repository is now named malt. The product and binary are MALT; the background process is the MALT daemon. Its Go module deliberately remains github.com/dewebprotocol/malt-client during the initial runtime refactor so a repository rename cannot silently reuse Core's historical module namespace. An active all-tag GitHub ruleset and a defense-in-depth CI check block runtime release tags until the separate module namespace gate is replaced by an approved pre-v1 cutover.

The runtime owns concerns that must not be part of the application-neutral authentication core:

  • separate observed-head, candidate-root, and accepted-root policy;
  • application-path parsing and UnixFS materialization;
  • optional IPFS-compatible Merkle DAG UnixFS import;
  • transport-mediated access to remote or local storage through Gateway HTTP, a durable local CAS, or Gateway-primary/local-cache hybrid CAS policy;
  • durable managed-Bucket base/remote/stash synchronization state;
  • non-authoritative CID-bound cache metadata with explicit verified, dirty, pending, candidate, conflicted, offline-only, and stale states;
  • a durable ordered local-operation journal with frozen retry identities;
  • a crash-recoverable local dirty overlay with read-your-writes behavior and durable whole-file/offset writes and truncate plus an explicit local-journal-only fsync result; the current whole-file implementation has a configurable 256 MiB default staged-file ceiling pending chunked staging;
  • transport-neutral verified write-back orchestration that plans before publication, uploads only final CID-bound staged bodies referenced by the normalized intent, locally computes and verifies a MALT candidate root, and records it without accepting it;
  • flat-v1, hybrid-v1, and rooted-v1 UnixFS planning from verified complete typed candidates, with locally CID-verified manifest reads and writes;
  • a platform-neutral read-only filesystem service pinned to an exact accepted dataset view, with verified lazy Positional ranges and proof-revalidated raw cache hits;
  • a crash-recoverable mount registry and daemon/local-API lifecycle contract that keeps platform drivers outside trust and transport code;
  • daemon-managed Linux FUSE mounts selected from local accepted roots, with lazy verified Gateway reads, a non-authoritative local cache, and an explicitly selected write-back binding that durably journals locally, computes the candidate locally, verifies remote persistence, and never promotes it implicitly;
  • local verification of typed authentication proofs and returned payload bytes;
  • a user-owned daemon control plane over a private Unix socket or Windows named pipe.

The gateway is an untrusted proof producer. A successful gateway response does not update an accepted root automatically: remote heads are observations, while locally computed or strictly verified writes are candidates. Each has a separate explicit acceptance path.

The public Node API defines transport-independent CAS, authentication and dataset-branch capabilities. Gateway services and HTTP, local and hybrid adapters implement the same contracts; synchronization consumes them without acquiring root-acceptance authority.

Status

This is an experimental, pre-v1 local runtime. It currently provides the malt CLI, a local trusted-root daemon, MALT-native encrypted backup/sync/restore, a UnixFS application adapter, a platform-neutral verified filesystem service, and daemon-managed Linux FUSE mounts controlled by malt mount and malt unmount. Mounts remain read-only by default. An explicit write_back policy composes per-dataset/branch staging, the selected UnixFS planner, MALT Core typed candidate computation, the untrusted Gateway remote, and local candidate recording. A successful remote write never accepts the candidate; promotion still requires the separate local root policy. The current remote executor is Gateway HTTP. A durable bounded local CAS and a Gateway-primary, CID-verified read-through hybrid CAS are implemented; local-only mode currently supports Merkle-DAG import, while native MALT managed-Bucket operations require Gateway or hybrid policy. The shared contract also exercises a peer-loopback adapter without defining a premature P2P wire format. A production P2P network transport, encrypted-profile routing through FUSE, and WinFsp remain follow-up work; the encrypted profile already exposes verified directory and range-read capabilities for those adapters. The historical v0.0.1 tag was published for MALT Client before the repository rename and before the staging/write-back APIs existed. Those current experimental Go interfaces have not appeared in any tag and may still make explicitly documented source-breaking changes before a tagged release includes them; build the current runtime from a pinned commit. The typed authentication migration requires coordinated Core/Gateway source and release adoption. An opt-in write-back mount creates an additive owner-private layout.json beside its per-dataset/branch journal and refuses to reuse that state with a different flat/hybrid profile; read-only state and older runtime data remain unchanged. The checked-in go.mod is the dependency source of truth; evaluation campaigns must record the exact runtime and dependency revisions they build.

Build

Go 1.26.0 or newer is required.

go test ./...
go vet ./...
go build -o bin/malt ./cmd/malt

Quick start

Start a compatible gateway, then initialize the local runtime:

./bin/malt init
./bin/malt login
./bin/malt daemon start
./bin/malt daemon status

malt init also creates a runtime-owned 0600 backup keyring. Existing installations can initialize only that missing keyring without replacing their configuration:

./bin/malt backup key-init

malt login generates a dedicated Ed25519 device key locally and opens the Gateway's browser approval page. The browser session may be established with a Passkey. Approval registers only the public key; the Gateway never returns a long-lived device bearer secret. Every later account request proves possession by signing its method, host, URI, body digest, timestamp, and a durable replay counter. Login authorizes the account only; it does not select a Bucket.

The current portable signer stores its private key in the owner-only device credential file and identifies itself as software-file. The transport uses a signer interface so TPM, Secure Enclave, and Windows CNG providers can replace that fallback without changing the request protocol, but those hardware providers are not implemented in this version. Passkeys remain the interactive browser account login; they are not exported as an unattended daemon signing key.

Create and inspect Buckets through the authenticated account:

./bin/malt bucket list
./bin/malt bucket create documents

The lower-level staged-root workflow remains available when gateway.bucket is configured explicitly:

./bin/malt bucket pull
./bin/malt bucket status
./bin/malt add ./local-change --root <observed-head-root>
./bin/malt bucket push <candidate-root-cid> -m "update docs"
./bin/malt bucket branches

In Bucket mode, native malt add and malt rm capture the current base before materialization and stage the resulting candidate in ~/.malt-client/buckets.json. bucket push refuses an unstaged candidate, fetches the remote head without changing the recorded base, and reuses the same push ID across retries. For candidates created by another tool, use bucket stage <candidate> --base-commit ... --base-root ... --base-revision ... with the base captured before materialization. The Gateway may fast-forward, auto-merge independent map changes, or return a preserved conflict branch. Bucket heads remain untrusted observations and are never promoted in roots.json by this workflow.

On Linux, an already accepted UnixFS root can be exposed as a read-only mount, or as an explicitly opt-in write-back mount with a fixed layout:

./bin/malt mount add docs <bucket-id> /mnt/docs \
  --trust-alias docs --branch main
./bin/malt mount add working <bucket-id> /mnt/working \
  --trust-alias docs --branch main \
  --write-policy write_back --layout hybrid-v1
./bin/malt mount list
./bin/malt unmount working

Every successful filesystem mutation is first durable in the local journal. fsync then attempts the complete verified typed batch write-back. Network or conflict failures are reported to the application while the exact local batch remains recoverable for retry. Remote success records a candidate root only; candidate recording and journal completion are fenced against concurrent accepted-root promotion. The mounted accepted view does not advance until an explicit local acceptance decision and remount. The dataset/branch state also freezes the selected layout, so changing flat-v1 to hybrid-v1 (or vice versa) fails closed until an explicit state migration exists. The current whole-file staging limit defaults to 256 MiB and is configurable with filesystem.max_staged_file_bytes.

Encrypted backup and restore

A backup plan is one complete Bucket branch restore unit. Bind a local directory by Bucket name or ID; a second binding on the same branch requires the explicit --merge choice, while another branch creates an independent plan:

./bin/malt backup bind ~/Documents --bucket documents
./bin/malt backup bind ~/Pictures --bucket documents --branch photos --create-branch
./bin/malt backup bind ~/Projects --bucket documents --merge
./bin/malt backup list
./bin/malt daemon start
./bin/malt backup
./bin/malt backup documents
./bin/malt sync

malt backup first recovers the selected Plan's stale ciphertext snapshot spool under its operation lock, rejects pending/conflicted workspace state, then prepares every changed binding in that Plan-exclusive owner-local CAS before publishing any bytes. Snapshot cleanup failures are returned to the caller rather than hidden. It writes the directory directly as the runtime-owned malt.encrypted-unixfs/v1 application profile: directories and files are MALT Prefix Roots, directory listings are encrypted manifests, Map keys are stable opaque tokens, and file ciphertext is stored as a raw block or a MALT Positional Root of independently authenticated chunks. There is no tar/gzip archive. Every Prefix/Positional Root is computed locally with MALT Core; the Gateway must return the exact same block CIDs and graph Roots before the candidate can be staged. Unchanged bindings are reused only from a locally accepted, fully verified base dataset. The root manifest omits child targets, so changes to different bindings remain independently mergeable; concurrent changes to the same binding produce a preserved conflict branch and an actionable error. One failed plan does not prevent other selected plans from completing.

malt sync first performs that same local snapshot and push workflow, then pulls the final latest branch and atomically installs every binding in the plan. A fast-forward or Gateway merge still requires exact local acceptance of the observed final root. In an interactive CLI, sync displays the exact CID and asks before accepting the already recorded observation; the daemon records the observation without accepting it and returns an actionable conflict.

When the Gateway preserves a same-binding conflict, interactive sync asks whether to attempt a conservative plaintext three-way merge. Independent files and one-sided changes merge automatically. Concurrent edits to the same path produce an owner-only conflict workspace with complete base, local, remote, and editable merged trees for each binding. The workspace is separate from every binding, so filenames and suffixes are never rewritten:

./bin/malt conflict list
# edit the reported .../<binding-id>/merged trees
./bin/malt conflict resolve documents --manual
# or choose --keep-local / --keep-remote

There is no unverified bucket/path restore selector. malt restore <plan> <destination> restores the entire branch plan under its encrypted manifest path names. On a new device, the verified and decrypted dataset manifest can reconstruct the Plan without a local plan record:

./bin/malt restore documents ./restored-documents
./bin/malt restore --bucket documents --branch main ./restored-documents

Original file and directory names, binding display names, and Plan display name exist only inside encrypted manifests. Given a plaintext path, an authorized runtime or browser decrypts its parent manifest, derives the next opaque token, and resolves that exact token under the locally selected root. The Gateway necessarily sees the account and Bucket display name, Bucket ID, selected branch, ACL and membership metadata, reserved @payload/@content bindings, opaque tokens, ciphertext sizes, timing, and access patterns. It cannot recover plaintext names or file bytes without the local keyring.

The encrypted filesystem profile preserves regular files, directories, permission bits, modification times, and safe relative symlinks. It does not yet preserve xattrs, ACLs, hard-link identity, sparse-file layout, or device nodes.

This encryption profile applies to malt backup; the general-purpose malt add command retains its existing plaintext UnixFS semantics.

Every manifest and file chunk uses XChaCha20-Poly1305 with a fresh nonce and domain-separated associated data. Reads first verify the caller-selected MALT root and every path ProofList, then verify each returned ciphertext block against its authenticated CID, and only then decrypt. Neither a cache hit nor a successful Gateway response can bypass those checks. The same manifest reader is suitable for the daemon, host-filesystem adapter, local API, and an authorized browser consumer.

malt backup --foreground [plan...] and malt sync --foreground [plan...] are embedded bypasses when the daemon is not running. Daemon and foreground operations share a cross-process lock, so they cannot race against the same plan workspace. Automatic plans are configured without a GUI and reloaded by the daemon without restart:

./bin/malt backup schedule set documents --every 6h
./bin/malt backup schedule list
./bin/malt backup schedule remove documents

Automatic plans compute local plaintext SHA-256 tree fingerprints and skip unchanged bindings. Fingerprints and source paths stay in local owner-only state. The history journals the exact candidate, original base, and frozen push identity so a lost response is retried without encrypting another snapshot.

The keyring keeps one random master key per epoch and derives per-Bucket keys in memory, so many Buckets do not require many persisted keys. Export an XChaCha20-Poly1305 recovery bundle protected by scrypt and a strong passphrase, store it separately from the remote ciphertext, and import it before a cross-device branch restore:

./bin/malt recovery export ./malt-recovery.json
./bin/malt recovery import ./malt-recovery.json

Use --passphrase-file for unattended recovery tooling; passphrases are never accepted as command-line arguments. A recovery bundle contains all retained epochs and therefore grants decryption of every Bucket owned by this keyring. Import adds missing epochs to an existing keyring only when every overlapping epoch contains byte-identical key material; it never replaces conflicting keys. This permits another device to import later rotations safely. Losing both the keyring and recovery bundle makes the encrypted backups unrecoverable. malt backup key-rotate activates a new content-encryption epoch for future snapshots while retaining old restore keys; it does not rewrite existing encrypted filesystem roots. The epoch-1 namespace key keeps opaque path tokens stable across content-key rotation. The Gateway never receives these keys.

This version supports one account across multiple authorized devices, but does not implement cryptographic sharing of a Bucket with another user. A Gateway ACL grant alone does not grant decryption, and proxy re-encryption, per-member key envelopes, and shared-Bucket revocation are intentionally out of scope.

Runtime state and portable credential-provider files use owner-only Unix permissions or a protected owner-and-SYSTEM Windows DACL. Custom config, keyring, workspace, trust, and Plan-history paths must still live in an owner-only directory: protecting a file cannot prevent another principal with parent-directory replacement rights from deleting and replacing it. Do not place these paths in a shared directory.

Backup sources containing the configured MALT keyring, config, workspace, trust store, backup history, cache, journal, or daemon endpoint are rejected rather than silently omitted or self-encrypted. The snapshot builder walks the source through pinned rooted handles and refuses non-directory binding roots, escaping symlinks, invalid UTF-8 names, identity-changing path replacements, and unsupported filesystem objects. Restore writes use the same rooted boundary. Keep device enrollment/recovery copies through the separate secure channel described above.

The old single-directory backup.jobs model and its history schema are not migrated. This Plan-only implementation rejects that configuration explicitly instead of silently preserving two backup models.

The daemon exposes HTTP semantics over a private user-owned Unix socket or Windows named pipe. It does not open a loopback TCP configuration website. A future Web or native GUI should be a thin client of that private management API; backup, scheduling, trust, and key policy remain reusable application services rather than UI logic.

Trust an independently obtained root, resolve a UnixFS path, and add a local tree:

./bin/malt root trust my-data <root-cid>
./bin/malt resolve my-data docs/readme.txt
./bin/malt add ./my-data --alias my-data
./bin/malt root list
./bin/malt root state my-data
./bin/malt root accept my-data <candidate-root-cid>

# A remote head must already be recorded as an observation.
./bin/malt root accept-observed my-data <observed-root-cid>

Read verified native UnixFS content and materialize a removal candidate:

./bin/malt stat my-data docs/readme.txt
./bin/malt cat my-data docs/readme.txt
./bin/malt cat my-data media/video.bin --offset 1048576 --length 262144 > part.bin
./bin/malt rm my-data docs/obsolete.txt
./bin/malt root accept my-data <candidate-root-from-rm>

stat emits JSON including locally verified typed authentication evidence. cat writes only verified file bytes to stdout. rm never changes the accepted root: it emits accepted: false and, when given an alias, records the result as a candidate for a later explicit root accept command.

The native MALT target exposes three UnixFS application layouts:

  • flat-v1 stores the root manifest, directory manifests and file targets as whole-path label bindings under one Prefix Root.
  • hybrid-v1 keeps a Prefix Root per directory and retains descendant whole-path bindings in ancestor Roots.
  • rooted-v1 keeps immediate-child bindings in each directory Prefix Root, with explicit component traversal between directories.

malt add defaults to hybrid (the short spelling of hybrid-v1) outside managed Bucket mode. With a Bucket selected, add and remove strictly validate its persisted layout; an explicit --layout must match. Flat bulk add rejects followed directory symlinks before uploading blocks because an opaque child Root would violate the single-Prefix layout.

UnixFS file/directory projection comes from each parent's canonical V2 manifest. A file may target a Prefix Root whose typed system payload selector binds its bytes; a flat path may target the payload or manifest directly. UnixFS traversal stops at a file regardless of other application bindings. Name-only V1 manifests, raw-codec fallback and layout-based type inference are removed. See the manifest format for canonical V2 encoding and rejected historical forms.

The same runtime can materialize one local file or directory as an IPFS-compatible Merkle DAG while reusing the gateway CAS:

./bin/malt add --target merkle-dag \
  --file-layout balanced --dir-layout adaptive ./my-data

This returns a Merkle DAG root CID. It does not create a MALT root, ProofList, or trusted-root candidate, so --root and --alias are intentionally rejected for this target.

The public Go API is importable as:

import (
    "github.com/dewebprotocol/malt-client/application"
	"github.com/dewebprotocol/malt-client/bucketsync"
    "github.com/dewebprotocol/malt-client/merkledag"
    "github.com/dewebprotocol/malt-client/transport"
    "github.com/dewebprotocol/malt-client/trust"
    "github.com/dewebprotocol/malt-client/unixfs"
)

Package application is the reusable use-case layer used by the CLI and local daemon. It selects explicit or locally accepted roots, composes verified UnixFS and Merkle DAG reads, records writer results as candidates, and exposes candidate promotion only as an explicit call. Its application/add package owns the CLI-independent ignore, symlink, staging, layout selection, and Merkle DAG import workflow used by malt add. Package unixfs defines the application-level Layout interface and the flat-v1, hybrid-v1, and rooted-v1 identifiers. Layout selection does not change MALT Core codecs, proofs, commitments, or canonical graph semantics.

Content commands (resolve, stat, cat, and rm) share the runtime composition root and use the selected Bucket's layout. Without a Bucket they default to hybrid-v1; --layout selects another current layout. An override that conflicts with a selected Bucket fails before content work.

Only current pre-release state structures are supported: trust v2, workspace v3, and the encrypted UnixFS backup profile. Old schemas and retired fields are rejected without migration. The daemon and CLI root APIs return structured RootState values, including accepted.root, candidates, and observed heads.

Explicit CIDs are selected without opening roots.json; the trust store is required only for an alias. A missing, corrupt, or unwritable alias store therefore cannot block an otherwise valid explicit-CID operation. Explicitly typed alias inputs such as malt add --alias always perform alias lookup, even when the alias text happens to be CID-shaped.

Package transport is an untrusted gateway transport. Package trust owns separate observed/candidate/accepted root policy. Package unixfs composes it into verified Resolve, Stat, ReadFile, ReadFileRange, ReadPositionalPayloadRange, EmptyDirectory, AddDirectory, AddFile, streaming file writes, and RemovePath operations. The UnixFS facade requires a caller-selected root, verifies typed evidence locally, enforces path-to-range continuity, and verifies raw, manifest, and measured Positional payload bytes.

With transport.Options{TenantBearerToken: ..., BucketID: ...}, native MALT/CAS calls use the authenticated Bucket routes. Package bucketsync persists base, observed remote head, and local stashes under a cross-process lock and implements stash-before-fetch push ordering. It deliberately does not import or mutate package trust.

nodeapi also defines public single and ordered-batch CAS contracts plus stable not-found/corruption classification. transport/local stores bounded immutable blocks atomically in an owner-private directory and pins the opened store boundary with no-follow platform handles, rejects reparse/symlink, FIFO/socket, unreadable, non-owner-private, and multiply-linked block identities, and re-hashes disk bytes for both Get and Has without mutating read-path metadata. CID paths are sharded by the first digest byte rather than multihash header metadata. Put repairs an unsafe exact target only through a protected temporary file and atomic replacement. Batch inputs are completely preflighted before the first write; a later error may leave a verified subset, makes the returned results unusable, and is recovered by safely retrying the complete immutable batch. transport/hybrid keeps Gateway as the persistence authority: writes reach Gateway first, Has consults only Gateway, and local cache misses or corrupted bodies fall back to a CID-verified primary read. Cache fill failure cannot turn verified primary bytes into an unverified result.

An unreadable shard directory is classified as corrupted state but is never silently chmodded or replaced: one shard may contain many unrelated valid blocks. Stop users of that store, restore its current-user ownership and 0700 mode explicitly, then retry. Exact block targets remain atomically repairable. On Unix, Open confirms both the CAS boundary contents and its complete descriptor-relative parent directory chain, repeating those syncs after a failed first creation attempt without trusting a renamed pathname.

Runtime composition returns an owned CAS binding. CLI operations, backup plan services, writable mount bindings, and mount-manager shutdown close any local directory handles deterministically. A release error is surfaced; terminally closed os.File handles are never reused, while higher-level synthetic or service cleanup failures retain retryable ownership. The first local-CAS Close attempt disables further I/O even when it returns a diagnostic; later calls are cleanup-only retries. Foreground commands expose the diagnostic. A finalizer remains only a process-safety fallback for direct transport/local embedders.

Filesystem mounts acquire one reference-counted read-side View resource lease. The last reference closes its verified service on unmount, failed mount, unexpected session exit, or shutdown; a failed release remains cleanup-only and is retried without accumulating per-dataset local CAS handles in the daemon. A release-pending route cannot be acquired by a new mount until cleanup finishes and a fresh service is opened.

Single-value CAS Get/Has require that authenticated Bucket selection. The transport does not attempt the Gateway's removed public raw-CAS GET/HEAD route; unscoped calls fail locally without sending a request.

Package merkledag owns the gateway's distinct compatibility profiles over a narrow fixed-route profile transport. ResolveMerkleDAGVerified and ReadMerkleDAGVerified recompute every evidence block CID and replay the UnixFS link traversal locally. These results are never represented as MALT ProofLists.

The transport exposes only fixed Merkle DAG resolve/read route capabilities; applications cannot supply an arbitrary Gateway route and JSON body. When a Bucket is configured, these calls use its authenticated compatibility routes and cannot fall back to the public CAS namespace.

Evaluation adapters

cmd/ contains only the supported malt product binary. Replay workers, benchmark drivers, experimental transports, fixtures, accounting and result schemas live in the separate malt-evaluation repository, under adapters/node/cmd and internal/nodeeval.

The evaluator calls the public nodeapi, UnixFS, Merkle DAG and transport capabilities. The node provides storage and authentication behavior; the evaluator defines workloads and measurement boundaries. Gateway and this runtime are cloud and edge implementations of node capabilities, respectively. Evaluation builds pin the node module separately from the evaluator revision.

The transport exposes bounded ordered CAS PutBatch/HasBatch and a typed diagnostic metrics snapshot. Merkle DAG import and verified link replay remain in merkledag; the unused generic IPLD parser toolkit is retired.

The CLI exposes the same fail-closed read path without consulting the MALT root store:

./bin/malt merkledag resolve <merkle-dag-root-cid> docs/readme.txt
./bin/malt merkledag cat <merkle-dag-root-cid> docs/readme.txt

Run malt <command> --help for the exact flags and output contract.

Default state lives under ~/.malt-client/. The generated configuration points to http://127.0.0.1:8080; edit gateway.base_url to select another gateway. Tenant bearer credentials and device proof-of-possession authentication require HTTPS except for loopback development.

Immutable-byte topology is selected only by the runtime composition root:

{
  "transport": {
    "cas_policy": "gateway",
    "local_cas_dir": "/home/user/.malt-client/local-cas"
  }
}

cas_policy accepts gateway, local, or hybrid and defaults to gateway for old configuration files. local permits local-only Merkle-DAG import but fails closed for a managed Bucket. hybrid keeps Gateway authoritative and uses local_cas_dir only as a verified read-through CAS. Application and trust packages never inspect this backend selection.

Trust model

  1. The caller chooses an already trusted root.
  2. The runtime sends canonical segments to the gateway.
  3. The gateway returns the result and ProofList.
  4. The runtime verifies the proof against the caller-selected root using MALT core.
  5. For payload reads, the runtime also verifies returned bytes against the authenticated CID.
  6. A mutation's new root remains a candidate until explicit local acceptance or an independent publication mechanism establishes trust.

See ARCHITECTURE.md for repository boundaries. See the encrypted filesystem profile for its manifest, token, encryption, browser-consumer, and compatibility contract, and docs/go-api.md for the public API and CLI contracts. The v0.0.5 migration matrix records which former core application capabilities moved here and which were deliberately re-homed.

License

MIT. See LICENSE.

Rooted ArcSet UnixFS

The explicit rooted-v1 application layout stores one Prefix ArcSet per UnixFS directory: AA2 name inputs address immediate children and a typed system payload binds the directory manifest. Chunked files use measured Positional ArcSets without system payloads. Parent rebinding follows application directory boundaries; no root-relative descendant aliases are emitted.

Use malt add --layout rooted-v1, and select the same layout for malt stat, malt cat, and malt rm. Managed Buckets retain their declared layout; write-back mounts can select rooted-v1. Generic readers identify this schema from the authenticated V=0 AA2 descriptor. Flat, hybrid and rooted remain supported application layouts, all using the same current typed authentication reader and planner.

Writers compute and verify complete typed candidates locally, submit children before parents, and reject a receipt for any different Root. Filesystem replay uploads only final referenced staged bodies and uses the accepted-root fence for completion. None of these operations accepts a candidate automatically. The candidate API is a complete-view workflow, not a stateless transition proof.

Evaluation tooling can export bounded file snapshots with go run ./adapters/node/cmd/malt-eval-rooted-file-trace --input snapshots.json from a malt-evaluation checkout. The input is an array of complete versions, each containing files (canonical relative paths mapped to base64 bytes) and queries (canonical paths). --backend ipa and --chunk-size select the commitment and file chunk geometry. The tool calls the production rooted-v1 schema/materializers, retains historical Roots, and emits malt.rooted-trace/v1 for the sibling evaluator. These are authentication-only traces: payload construction is outside measurement, and no CAS-transfer latency or full-file read measurement is claimed.

Writeback transaction identity

An upload batch and its writeback result expose TransactionID. The batch contains individually journaled filesystem operations, whose OperationID identifies an intent rather than a Delta transaction. Core authentication batches and receipts use transaction_id with malt.authentication-batch/2 and malt.authentication-receipt/2. A candidate receipt does not publish a Bucket head or promote an accepted root.

About

User-controlled MALT local data runtime: CLI, daemon, local trust, UnixFS, backup and sync

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages