NAOMS Devlog

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

Build on NAOMS Without a Copy of NAOMS

An outside developer, with none of our code on their machine, can scaffold a package, sign it, publish it into their own private space, and promote it into a shared one โ€” every step driven by the installed command-line tool talking to a real running system, with a real cryptographic countersignature at the trust boundary.

Technology Architect free July 4, 2026ยท7 min readยทdistribution
TL;DR A software development kit is a promise: take our pieces, build your own thing, and don't inherit our whole world to do it. Here that means an outside developer with none of our code on disk can scaffold a package, sign it, publish it into a private space only they can see, and promote it into a shared one โ€” every step driven by the installed command-line tool against a real running system. The step that crosses from private to shared is the one worth understanding: it is countersigned by the group, so admitting a package into common space is a fact on the record rather than a claim you take on faith. For most of this project's life that only worked from inside our own source tree; this week we closed that gap and proved it the hard way. We also name the one rough edge that's left, because a kit that hides its seams isn't finished.

How a kit is supposed to work

The word "SDK" โ€” software development kit โ€” makes a specific promise. It says: here are the pieces, take them somewhere else, and build your own thing without hauling our entire world along. The test of that promise is brutally simple. Sit a developer down at a clean machine โ€” none of our source, none of our build system, nothing but the published tool and the public instructions โ€” and see whether they can build something. If they can, you have a kit. If they cannot, you have a workshop with the doors locked from the inside.

What an outside developer builds here is a package: a self-contained unit of functionality that a NAOMS system can install and run, the way a browser installs an extension. They build it with the command-line tool โ€” the single program an outside developer installs, which talks to a running NAOMS system rather than containing one. The whole arc runs from a directory with none of our source in it:

flowchart TD
    A["Empty directory
(no NAOMS source on disk)"] --> B["scaffold a package
clean, consistent starting code"] B --> C["pack it
signed with the author's own key"] C --> D["publish into a private space
author's repo โ€” not yet shared"] D --> E{"promote into a shared space?"} E -->|"countersignature at the trust boundary"| F["package lives in the shared hive
trust tier crossed, on the record"] E -->|"no countersignature"| G["stays private
nothing crosses on trust alone"]

Scaffolding is the tool writing out, into an empty directory, a starting package whose code is already clean and consistent โ€” so a new author begins from something correct rather than something they have to repair. Packing bundles that code into a single distributable artifact and signs it with the author's own cryptographic key, so anyone can later verify that this bundle is the one that author produced and that nobody altered it in transit.

Then there are two different destinations, and the difference between them is the heart of the design. Publishing puts the package into the author's own private space โ€” their repo, visible only to them. Promoting moves it into a hive: a shared space belonging to a group of people, where a package becomes available to everyone in it.

Read the branch on the right of that diagram, because it is the part that matters most. Moving a package from your own private space into a shared one is not a file copy. It is a crossing of a trust boundary โ€” the line past which your decisions start affecting other people โ€” and the system treats it as one. The promotion is countersigned: a second cryptographic signature, this one from the group rather than the author, recorded on the shared history. Countersigning is the digital equivalent of a second signature on a cheque; it means the group put its own name on the act of admitting this package. So "this package is now here, in our common space" is a fact anyone can check against the record rather than a claim you have to take on faith.

Publishing something only you can see needs only your own signature. Handing it to a group needs the group's countersignature at the door. The trust tier is not decoration; it is enforced at the exact point where the risk changes.

What was wrong

For most of this project's life, all of that worked beautifully โ€” as long as you were standing inside our own source tree while you used it. The moment you stepped outside, it fell apart in ways that were easy to overlook from the inside precisely because, from the inside, nothing ever went wrong.

Nobody discovered this by reasoning about it. In the middle of June, we did the honest thing and tried it for real: a fresh directory, off to one side, no connection to our source tree, following our own published getting-started guide line by line. It did not take long to hit a wall. It took five.

The very first one was almost comic. The command-line tool โ€” the thing an outside developer installs and runs โ€” refused to start unless it found itself inside a copy of our source. Run it anywhere else and it stopped cold with not inside a NAOMS checkout. The tool that was supposed to be the whole point of leaving our source tree would only work if you never left it.

Behind that stood the next wall: the import line printed verbatim in our own documentation did not resolve. Copy the example, paste it into a real project, and the type checker rejected it โ€” the module our docs told people to import was not something an outside project could actually see. And past that, three more of the same family, each one a place where the "public" surface quietly reached back into private plumbing โ€” governance internals, runtime wiring, native cryptographic libraries โ€” that an external package had no way to bring with it.

None of these were bugs in the usual sense. Everything worked. The tests passed. The system ran. They were a subtler kind of failure: the public edge of the project had grown tangled roots back into the private middle, and those roots were invisible until someone tried to transplant just the edge. This is the failure mode every maturing platform meets sooner or later, and it almost never announces itself โ€” because the people best positioned to notice are the people who never leave home.

How it was fixed โ€” and the seam we are leaving visible

The fix was not one change; it was pulling those roots apart, one family at a time. The public surface โ€” the part an outside developer is meant to touch โ€” had to be severed cleanly from the governance layer, the runtime, and the native crypto, so that the pieces we hand out can stand on their own. Then the tool itself had to learn to run from anywhere, not just from home. Then it had to be able to scaffold into an empty directory.

But the real bar was not any single milestone. It was the whole arc above, walked end-to-end, by the tool, on the real system, from a directory with none of our source in it. And we held ourselves to proving the mechanism fired, not just that the final state looked right. It is easy to write a test that ends green because the answer was quietly handed to it. The bar here was the opposite: the package identity had to be minted from the author's real personal identity as read out of the running system's own reported state; the countersignatures on both the pack and the promotion had to appear as genuine events in that run's own logs; the signing audits had to be real. A test that reached the finish line by disabling the authentication it was supposed to exercise would not have counted, and none of these do that.

There is one rough edge left, and naming it is part of shipping honestly. To mint a package's identity, the flow currently has to ask the running system for the author's personal identifier through a diagnostic, health-style channel โ€” a route that exists to report on the system's condition, not to hand out identity. It works, and it is real, but it is the wrong door. The right fix is for the create step to default to the caller's own identity on its own, or for the tool to grow a plain "who am I" answer an author can ask for directly. We have written that gap down as its own piece of follow-on work rather than papering over it, because the whole value of a kit is that its seams are honest. An outside developer who hits that edge should find our own note already sitting there, saying yes, we know, here is the shape of the fix โ€” not discover it alone and wonder what else we have not told them.

That is the difference between a workshop and a kit. A workshop only has to work for the people who built it. A kit has to work for a stranger on a clean machine, following the instructions, with nobody in the room to help โ€” and it has to be honest with that stranger about exactly how far the road is finished. This week, for the first time, a stranger could walk it from an empty directory all the way into a shared space, with a real signature at the boundary and a truthful map of the one stretch still under construction. The doors open from the outside now.


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

โ† more in Technology   home โœฆ   all โ†’