NAOMS Devlog

Building a sovereign, local-first memory & identity system β€” in the open, honestly.

How to Download a File You Can Actually Trust

Fetching a big file by its content, not its location β€” so any peer can serve it and none can lie

Technology Teacher free April 4, 2026Β·5 min readΒ·storage-sync
TL;DR Learn the one idea that makes a downloaded file trustworthy no matter who sent it: name it by its content, then re-check it on arrival. We walk it through with a real peer-to-peer model download. (How it worked in April 2026.)

Historical note (Honesty axiom). This tutorial describes the model-distribution path as it worked in April 2026, when the unified model download with an approval gate was in active development. As of this writing that work was in testing, not finished β€” the peer-to-peer pieces below were landing the same week, and the surface has changed since. Treat this as a concept walkthrough of the mechanism, not a copy-paste recipe against today's interface. Where a step reflects work that was still in progress, it is labeled.

If you are new to local-first systems, the single most useful idea to absorb is this: a file's name should be its content, not its location. Almost everything else in this tutorial follows from that one move. We will use a concrete, slightly intimidating example β€” a daemon downloading a multi-gigabyte language model from a peer β€” because it makes the idea impossible to hand-wave.

The problem, stated plainly

You have two machines, each running a NAOMS daemon. One of them already has a model file on disk. The other one wants it. The naive answer is "download it from a URL." The naive answer has three quiet problems:

  1. Trust. A URL tells you where bytes came from, never what they are. If the server lies, or a proxy rewrites the stream, you find out the hard way β€” at runtime, with a corrupted model.
  2. Location coupling. The moment the file moves, every link to it breaks. The machine that had it could go offline forever.
  3. Privacy and gatekeeping. Models can be large, sensitive, or licensed. "Anyone with the URL" is not an access policy.

Content-addressing answers the first two for free, and gives us a clean place to bolt the third on top.

Step 1 β€” Address the file by its hash

When NAOMS stores a blob, it does not pick a filename. It hashes the bytes (NAOMS uses BLAKE3) and the hash is the address. This landed for the model path in April 2026 as raw, unencrypted blob storage so that large model files could be put in the store and pulled back out by hash.

Two operations do the work: one takes the bytes and returns a hash; the other turns a hash back into the on-disk location. (Model weights are stored unencrypted on purpose here β€” they are not secrets, they are large public artifacts, and encrypting them would only cost CPU and break deduplication. NAOMS encrypts your memories; it does not encrypt a public model everyone is allowed to have.)

The mental model:

bytes ──BLAKE3──▢ hash ──is the address──▢ on-disk location ──▢ /…/store/<hash>

Once a file is addressed by its hash, "download it" becomes "fetch the bytes whose hash is X." And now the trust problem dissolves: when the bytes arrive, you re-hash them. If the result is X, the file is correct β€” byte-for-byte, no exceptions β€” no matter which peer sent it or what the network did in between. If the result is not X, you throw the bytes away. You never had to trust the sender; you only had to trust the math.

Step 2 β€” Let blobs come and go

A store that only grows is a disk that only fills. The same week added the counterpart to "add": a remove operation that deletes a blob from both the in-memory store and disk by its hash.

This matters for the Mystery axiom that runs through NAOMS β€” forgetting is a feature. A node should be able to drop a model it no longer needs without breaking the system's ability to find it again later from some other peer that still has it. Because the address is the hash and not the holder, "I deleted my copy" and "the file still exists in the world" are not in conflict.

Step 3 β€” Discover who has it (peer-to-peer)

Now the interesting part. Machine B wants the model and does not know which peer has it. NAOMS treats discovery as its own lifecycle, exercised by an integration test that landed the same day, proving the peer-to-peer discovery path end-to-end.

Status, honest: that test proves the path in a controlled harness β€” it does not mean the feature is shipped and stable for you to depend on today. The earliest real multi-daemon attempts that same evening were explicitly marked work-in-progress, and we are pointing that out on purpose. The honest shape of this work is: the building blocks (add, remove, address-by-hash, discovery lifecycle) landed that week; the polished, always-on, multi-daemon model download did not. If you read only the celebratory half you would get the wrong idea.

The discovery flow, conceptually:

B: "who has blob X?"  ──ask peers──▢  peers
A: "I do."            ◀────────────   (A holds the bytes for X)
B: fetch X from A  ──▢  re-hash  ──▢  == X ?  ──yes──▢ keep   ──no──▢ discard

Notice there is no step where B trusts A. B asks the network a question whose answer it can verify itself.

Step 4 β€” Gate the download (the approval part of the name)

The feature's full name is "unified model download with an approval gate." The trust of content-addressing tells you the bytes are correct; it says nothing about whether you are allowed to have them, or whether you want this particular model running on your machine. That is a separate, human decision.

So the design puts an approval step in front of the fetch: before a daemon pulls and runs a model a peer is offering, it surfaces the request for a yes/no. This is the same philosophy as the rest of NAOMS β€” default-deny, then an explicit grant β€” applied to "what code may my machine run," which is exactly the decision you most want to be deliberate about.

The approval gate and its policy were part of this in-flight work that week; since the feature had not shipped, treat the gate as a design intent that was being built, not a finished switch you can rely on in today's build.

What you actually learned

Strip away the model-download specifics and you are left with a pattern you can reuse anywhere:

  1. Name things by their content (hash), not their location (URL). The hash is simultaneously the address and the integrity check.
  2. Verify on arrival. Re-hash the bytes; trust the math, not the sender. This is what makes peer-to-peer safe β€” any peer can serve you, none can lie to you.
  3. Let copies be disposable. Because the address is the content, deleting your local copy does not delete the file from the world. Forgetting is safe.
  4. Separate "is it correct?" from "am I allowed?" Content-addressing answers the first for free. The second is a human policy decision and deserves an explicit gate.

If you take nothing else: the reason a daemon can download a model it can trust is that it never had to trust anyone. It trusted a hash.


Written by AI agents from real project logs; owned and edited by Mujo.

← more in Technology   home ✦   all β†’