Skip to content

Repository files navigation

Sovereign Communication & Permissions

Communication and access-control infrastructure where the intermediary cannot extract your data — not because it promises not to, but because the architecture never gives it the ability.

This repository contains the open specification and reference implementation for two interlocking pieces of sovereignty infrastructure:

  • The GhostBox Protocol — a zero-identity, asynchronous, dead-drop communication protocol. Two parties exchange messages and assets without the transport infrastructure ever learning who is talking to whom.
  • The Companion Permissions Layer — the access-control model between a user's personal data vault and the outside world, mediated by an AI companion that acts as a non-bribable gatekeeper.

Both apply one design decision at two layers: remove the intermediary's ability to extract value from your data by removing its access to that data.


Explain it like I'm five

New here? Start with this. The precise version lives in SPECIFICATION.md; this is the same thing in plain words.

Picture a clubhouse with a magic wall of mailboxes, run by a grown-up who is blindfolded and has no memory. That grown-up is the middleman every app puts between you and your friends. Most apps let him read your notes and sell what he learns. This one is built so he cannot peek and cannot remember. That is the whole idea: not a promise to behave, but a room where misbehaving isn't possible.

Here is what each part does.

Your secret identity (src/identity.ts). You whisper a few secret words only you know, and the machine turns them into your own mailbox address plus the one key that opens it. Nobody hands it to you and nobody can take it away, because it was never stored anywhere. Lose the words, lose the mailbox. That is the trade.

The drop-off wall (src/transport.ts). You leave a locked box in someone's cubby. To collect your own mail, you prove the cubby is yours with a secret handshake. The blindfolded grown-up only ever holds boxes. He never sees who dropped one or who picked one up, so he can never draw a map of who talks to whom.

The unfoolable lock (src/envelope.ts). A box opens for exactly one key, and refuses to even pretend for a wrong one. No jiggling it loose.

A fresh key for every note (src/ratchet.ts). Every message gets a brand-new key, and the old key is burned right after. If a thief steals today's key, yesterday's notes stay locked, because the keys that opened them no longer exist. (Grown-ups call this forward secrecy.)

Saving your place (src/statesync.ts). It writes down, locked up tight, where you are in the key-burning sequence, so you can move from phone to laptop without losing the thread.

The nametag to Bluesky (src/atproto-bridge.ts). If you want to be found, you pin a small note on your public Bluesky profile that says "leave my secret mail here." Handy, but it does tell the world you have a secret mailbox. So it is for people who want to be reachable, not for people who want to stay hidden.

The robot inspectors (test-vectors/ + CI). Little robots that re-run everything and squawk if a toy is broken. There are ten of them, and they all have to give a thumbs-up before anything ships.

What it does not do, said plainly: it is not finished, and not yet checked by an outside expert; the Bluesky nametag reveals that you use this, just not what you say; and a thief who steals your secret words gets everything, on purpose, because there are no accounts to reset.

The punchline the whole thing exists to prove: you could hand a snoop the entire contents of the mailroom and they still could not tell you who is friends with whom. Not because anyone promised to be good, but because there is nothing in there to find.

(There is a planned second half: a "Companion" that guards your personal data vault like a bouncer who cannot be bribed. That part is still a design on paper. This repo is mostly the messaging half so far.)


Status

v0.4.1 — working draft. The reference implementation covers the Spirit Layer (identity derivation, src/identity.ts), the Specter Layer (the dead-drop transport, src/transport.ts, now with a forward-secret in-channel path: RatchetSession routes per-message keys from the §6.2 symmetric ratchet through the committing envelope, and src/statesync.ts serializes ratchet state for the §6.4 sync channel), and an AT Protocol bridge (src/atproto-bridge.ts) that lets an AT Proto / Bluesky identity publish and resolve a GhostBox address — public identity from AT Proto, private transport from GhostBox. An end-to-end integration test drives the transport with real derived identities; a runnable demonstration (test-vectors/verify_unlinkability.mjs) shows by inspection that the server's complete state contains no sender→recipient social graph; and an offline bridge test (test-vectors/atproto-bridge.mjs) verifies the discovery→private-message flow with the network mocked.

Read the scope honestly: the unlinkability demonstration establishes application-layer unlinkability, not resistance to a network-layer adversary (SPEC §8.4); the sealed-box path (the pre-session Lobby flow) gives sender anonymity but not forward secrecy — by design for that flow; in-channel conversation over RatchetSession is forward secret as of v0.4.0, via a symmetric ratchet (no per-message DH step, hence no session-level post-compromise security — deliberate, see SPEC §6.2); the ratchet and its wiring are not independently reviewed yet; and the AT Proto bridge involves a deliberate privacy tradeoff — see below. This is infrastructure for review, not a finished or audited product. See the spec's honestly-named limitations before building anything on it.

Try it / read more

Start here

If you want to... Read
Understand the whole design SPECIFICATION.md
Watch it run (no setup) Live browser demo
See the principles in one screen Design Principles
Understand the threat model §8 Threat Model
Build a client src/identity.ts + src/transport.ts (TypeScript, canonical)
See the unlinkability claim run test-vectors/verify_unlinkability.mjs
Bridge an AT Proto / Bluesky identity src/atproto-bridge.ts + lexicons/ (see AT Protocol integration below)
Cross-check against the book reference/ (Python, illustrative)
Verify your implementation test-vectors/
Contribute CONTRIBUTING.md

The three layers (Spectre Stack)

CORPOREAL  (Discovery)  — voluntary presence; how parties find each other
SPECTER    (Transport)  — passive dead-drop; the server that cannot link
SPIRIT     (Identity)   — invisible; derived from a Quad-Key, never server-held

Each layer is independent: compromise of one must not compromise another.

Design principles

  1. Possession is identity. No registration, no account record, nothing for a platform to revoke or sell.
  2. The server cannot build the graph. Sender-recipient unlinkability is a mathematical property, not a policy promise.
  3. Extraction incentive absent by construction. The gatekeeper cannot be bribed because no revenue model rewards letting someone in.
  4. Trust is verifiable, not declared. Open code, public governance, behavior checkable against the spec.
  5. Presence mirrors social reality. A five-state relationship model, not a connected/not-connected binary.
  6. The user decides; the companion holds. Nothing changes without user affirmation.

A note on the canonical reference language

The book Notes from an Acceleration Native ships Python in its appendix. This repository treats TypeScript as canonical because identity derivation must run client-side in the user's browser/device (Principle 1) — Python can't satisfy that constraint without a server. The Python in reference/ is kept as a faithful, illustrative companion so the two never drift. Where the original book code and this repository disagree, this repository governs — see §0.4 of the spec for the two deliberate corrections (per-composite salts; versioned Argon2id).

⚠️ Argon2id is not native to browsers. A conformant TypeScript client needs a WASM build of Argon2 (e.g. hash-wasm). Do not ship a pure-JS fallback — it will be too slow to use safe parameters and silently weakens every identity derived with it.

AT Protocol integration

GhostBox and AT Protocol solve non-overlapping problems and compose cleanly. AT Proto answers who is this person and how do I find them; GhostBox answers how do I talk to them privately. The bridge (src/atproto-bridge.ts) lets an AT Proto identity publish a small public record — a GhostBox locator hash plus an X25519 key — so anyone who can resolve a handle (@you.bsky.social → DID → record) can discover a GhostBox address. The conversation itself then runs over the GhostBox dead-drop, encrypted and unlinkable, never touching the AT Proto network. Bluesky's own DMs are centralized and not end-to-end encrypted; this is the private layer the ecosystem doesn't have.

The record conforms to a published Lexicon, lexicons/com.ghostbox.identity.json, so any AT Proto client can read it. Resolution is DID → DID document → PDS → getRecord → SendTarget; the offline test mocks that chain and verifies a message addressed via a resolved identity round-trips through the dead-drop.

⚠️ The privacy tradeoff — read before publishing

Publishing a locator in a public AT Proto record makes the association between your handle and your GhostBox address public and effectively permanent — AT Proto repos are synced and archived via the firehose, so a published locator can persist in archives even after deletion. Message contents and the social graph of who you message stay private (the dead-drop still does its job). What becomes public is the fact that you use GhostBox, and which locator, bound to your real handle.

So the bridge is for the findable case — a creator or public figure who wants to be privately reachable. It is the wrong tool if your goal is that your very presence on GhostBox stay hidden; that is the Corporeal Layer's unlisted / proximity-only mode (SPEC §5.4), which must not publish this record. Rotating to a fresh locator is the only mitigation once an association is public. Do not publish a locator you need to keep secret.

Publishing your GhostBox identity

The bridge builds the records and resolves them; it does not handle your credentials (credentials never belong in library code). To publish, you run the authenticated write yourself:

  1. Derive your GhostBox identity and take the public locatorHash (hex) and encryptionPublic (hex) from it.
  2. Create an App Password for your account.
  3. Authenticate to your PDS (com.atproto.server.createSession) to get an access token.
  4. buildPutRecordRequest(pdsEndpoint, yourDid, buildIdentityRecord(locatorHex, encHex)) gives you the exact com.atproto.repo.putRecord endpoint and body. POST it with Authorization: Bearer <accessJwt>.

Once published, anyone can resolveGhostBoxIdentity(yourDid) to get a SendTarget and message you privately. (Note: resolveGhostBoxIdentity takes a DID; resolve a handle to a DID first via com.atproto.identity.resolveHandle.)

Verification status: the bridge logic is typechecked against real types and verified offline against a mocked AT Proto network (test-vectors/atproto-bridge.mjs). The live network path — publishing to and resolving from a real PDS — is the step you run; it is not exercised in CI because it requires your credentials and live network access.

License

GNU AGPLv3. Chosen deliberately. This project's whole argument is that infrastructure should make extraction structurally impossible rather than relying on good intentions — so a permissive license that lets a hosted fork quietly add metadata logging and never publish the change would contradict the thesis. The AGPL's network-use clause closes that loophole: anyone who runs a modified version as a service must publish their source, which is what makes Principle 4 (verifiability) enforceable rather than aspirational.

If you need different terms for a specific use, open an issue to discuss.

Provenance

Architecture by Cory A. Ottenwess. Companion text: Notes from an Acceleration Native (Appendix B and Chapter 11). This repository is the implementation reference; the book is the argument for why it should exist.

About

A Framework for a Sovereign Communications Network

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages