Skip to content

About

Workspace Protocol: the specification (in flight) and reference implementation of Workspace's peer-to-peer data and permissions layer, across iOS, Android, macOS, web and *nix

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Workspace Protocol

The specification, still in flight, and reference implementation of Workspace's peer-to-peer data and permissions layer: a .workspace portable bundle format, a workspace:// URI scheme for discovery, and the permissions layer that sits underneath.

It began as a research spike (this repository was workspace-p2p-spike) asking whether Hypercore would do. The answer was yes; the work since has been designing and implementing the layers above it. Some of it is still exploration, and says so (the documents marked as spikes).


The two concepts that matter

.workspace — the folder is the unit

A .workspace is a folder (or an archive of one) that contains a collection of files plus the metadata needed to sync them and enforce access between peers. The folder is the workspace. Sharing is a file-system operation: copy it to a USB stick, AirDrop it, drop it on a NAS, attach it to an email.

What's on disk is already safe to share — public files appear in plaintext, tier-gated content lives only as encrypted bytes inside .workspace/, and per-recipient bootstrap envelopes are sealed to their intended DIDs. Copy-paste sharing does not leak. No "export" step is needed for safety.

workspace:// — the URI

The same workspace, addressable by URL. Encodes the bootstrap metadata (workspace ID, root DID, Hyperswarm topic, attestation) compactly enough to embed in a chat message, a QR code, or a webpage. Tap it on any platform that has the Workspace app installed; the app opens, validates the attestation, asks the user to confirm, joins the swarm.

This is the magnet-link analogue: tiny, URL-shareable, leaks nothing sensitive, the actual content lives in the swarm.

Together, the folder form and the URI form are the two ways a workspace gets distributed and discovered. They carry the same underlying metadata; one is a file, one is a URL; both lead to the same place.

See docs/format/workspace-format.md for the full format spec.


Quick start

Three escalating ways to see this working, smallest first.

1. Verify the install (no network)

git clone https://github.com/workspace-sh/workspace-protocol.git
cd workspace-protocol
npm install
npm run typecheck
npm run test

All tests pass in-process — cryptographic primitives, UCAN delegation chains, bundle round-trip, and Hypercore replication through a direct duplex pipe. No network, no external dependencies.

2. Run the small-org demo (still no network)

npm -w @workspace.sh/p2p-spike-node run demo:acme

Three "Acme" members — Alice, Bob, Carol — share a workspace. Alice creates a .workspace/ bundle with envelopes for Bob and Carol; the data log carries content sealed under K0_org. Bob and Carol unwrap their envelopes and decrypt. Eve (no envelope, no key) cannot. Runs in one process via direct pipes — ~20ms end-to-end, deterministic, doesn't touch the network.

3. Run the same demo over a real swarm, isolated in a container

For exercising the actual Hyperswarm transport without touching the host network:

# One-time: install a container runtime (Colima is fully FOSS)
brew install colima docker

# Per session: start the runtime
colima start

# Per run: build + run the demo. Brings up the bootstrap first
# (via compose dependency), runs acme against it, auto-exits when
# acme finishes.
docker compose up --build --abort-on-container-exit acme

# Per session: stop the runtime when you're done with all containers
colima stop

The bootstrap and peer process each run in their own container on a private bridge network. Nothing leaves the bridge. Hard memory + CPU caps protect against runaway processes. See docker/README.md for the runtime options — Colima recommended (fully FOSS); OrbStack and Docker Desktop work identically with the same compose file.

Building against the SDK

The app codes against @workspace.sh/workspace — one object over the proven primitives:

import { createRuntime } from '@workspace.sh/p2p-runtime/node';
import { Workspace } from '@workspace.sh/workspace';

const ws = await Workspace.create({ createRuntime, folder: 'Acme.workspace', name: 'Acme' });
await ws.invite(bobDid);
await ws.write(new TextEncoder().encode('hello'));
ws.on('change', render);

// on another device, after receiving the folder:
const ws2 = await Workspace.open({ createRuntime, folder: 'Acme.workspace', identitySeed });

npm -w @workspace.sh/p2p-spike-node run demo:workspace runs this end-to-end over a private swarm — the same flow as the hand-wired acme-org-live demo, in ~10 lines.

Other test paths

  • npm -w @workspace.sh/p2p-spike-node run smoke — verifies the live Hyperswarm DHT works (needs internet)
  • npm -w @workspace.sh/p2p-spike-node run demo:end-to-end — bundle + topic + replication over the live public DHT
  • npm -w @workspace.sh/p2p-spike-node run demo:bootstrap + demo:acme:live — same as the container demo but on the bare host
  • npm -w @workspace.sh/p2p-spike-node run demo:key-delivery / demo:topic-auth — the #9 / #10 flows in isolation

See apps/node/README.md for the full testing-mode matrix.

npm-only — Bun doesn't compose cleanly with react-native-macos.


Status

Node runtime — Hypercore + Hyperswarm done
IPC layer — JSON-RPC over stdio done
macOS TurboModule — NSTask spawning done
Permissions layer — wrap primitive implemented
Permissions layer — UCAN delegation boundary implemented
Permissions layer — root attestation implemented
Permissions layer — bootstrap envelopes implemented
Permissions layer — transparent log encryption (encryptedLog) implemented
Workspace SDK facade (@workspace.sh/workspace) v1 implemented (single-writer; Autobase + doc model pending)
Live key delivery log (#9) implemented (polish pending)
Topic-layer authentication (#10) implemented (topic rotation pending)
workspace:// URI scheme + .workspace format + discovery designed (specs locked); see docs/
Autobase wrapper (#11) pending
.workspace folder + archive shape (#24) designed; implementation pending
DNS / .well-known discovery (#25) designed; implementation pending
Layered peer discovery (local / LAN / WAN) designed; only WAN implemented
Lighthouse — trusted always-on node concept; post-spike, separate repo
Mobile path (#6) separate workstream

Permissions epic: #5. Active development on feat/permissions-layer (PR #22). 65 tests green across three packages; typecheck clean.


How the layers fit

┌─────────────────────────────────────────────────────────────────────┐
│  .workspace folder / workspace:// URI                               │  ← Portable / discoverable
├─────────────────────────────────────────────────────────────────────┤
│  Bootstrap envelopes + bundled manifest + root attestation          │  ← @workspace.sh/portable-bootstrap
├─────────────────────────────────────────────────────────────────────┤
│  UCAN 1.0 delegations (issue, validate, serialise) via iso-ucan     │  ← @workspace.sh/ucan-boundary
├─────────────────────────────────────────────────────────────────────┤
│  Wrap primitive + root attestation + did:key encode/decode          │  ← @workspace.sh/p2p-runtime (crypto)
├─────────────────────────────────────────────────────────────────────┤
│  Hypercore logs + Hyperswarm topics + NSTask IPC                    │  ← @workspace.sh/p2p-runtime (sync)
└─────────────────────────────────────────────────────────────────────┘

Each layer composes on the one below. Files in .workspace/ are self-contained at rest; the URI form is a pointer the app resolves. The cryptographic substrate is the same regardless of how the workspace was distributed.


Repository layout

.
├── README.md                            ← you are here
├── FINDINGS.md                          ← spike outcomes + extraction checklist
├── docs/
│   ├── workspace-format.md              ← .workspace on-disk format spec
│   ├── uri-scheme.md                    ← workspace:// URI scheme
│   ├── discovery.md                     ← DNS TXT + .well-known/workspace
│   ├── discovery-layers.md              ← local-first / LAN / WAN peer discovery
│   ├── lighthouse.md                    ← trusted always-on node concept
│   ├── identity-recovery.md             ← device linking, recovery, key rotation
│   ├── permissions-model.md             ← UCAN + Hypercore protocol design
│   ├── threat-model.md                  ← what Workspace protects (and doesn't)
│   ├── risks.md                         ← where this could fail and what we're doing
│   ├── ucan-prior-research.md           ← UCAN library notes from earlier spike
│   └── adr/                             ← architecture decision records
│       ├── 0001-ucan-library.md         ← superseded: UCAN 1.0 via iso-ucan
│       └── 0002-autobase-merge-strategy.md ← per-format LWW over Autobase
├── packages/
│   ├── p2p-runtime/                     ← @workspace.sh/p2p-runtime
│   │   └── src/
│   │       ├── types.ts                 ← P2PRuntime, Log, Did, TopicId, LogKey
│   │       ├── runtime.{node,ios,android,macos,web,windows}.ts
│   │       ├── did.ts                   ← did:key encode/decode (ed25519)
│   │       ├── wrap.ts                  ← X25519 ECDH sealed envelopes
│   │       └── attestation.ts           ← root attestation sign/verify
│   ├── ucan-boundary/                   ← @workspace.sh/ucan-boundary
│   │   └── src/index.ts                 ← every UCAN library call lives here
│   ├── portable-bootstrap/              ← @workspace.sh/portable-bootstrap
│   │   └── src/
│   │       ├── index.ts                 ← createBundle / consumeBundle / createEnvelope
│   │       ├── folder.ts                ← writeBundleFolder / readBundleFolder
│   │       ├── key-delivery.ts          ← publishDelivery / scanDeliveries (#9)
│   │       └── membership.ts            ← verifyMembership (#10)
│   └── workspace/                       ← @workspace.sh/workspace (app-facing SDK)
│       └── src/index.ts                 ← Workspace.create / open / invite / write
└── apps/
    ├── node/                            ← smoke harness over real Hyperswarm
    ├── macos/native/                    ← P2PRuntimeModule (Obj-C++ TurboModule)
    └── macos-probe/                     ← Swift probe validating the NSTask path

Documentation

The design lives in docs/, one folder per subject, each with its own index:

  • Format: the .workspace on-disk shape and the workspace:// URI scheme
  • Sync: blocks, merging, multi-writer, many workspaces in one runtime
  • Network: discovery and network conditions
  • Lighthouse: always-on peers a workspace opts into
  • Permissions and identity: UCAN, joining, recovery, prior art
  • Security: the threat model and risks
  • Workspace actions: sandboxed functions in documents and workspaces (a spike within the spec)
  • Decisions: architecture decision records

Start with format/workspace-format.md for what's being built, then security/threat-model.md for the contract that bounds it, format/uri-scheme.md for addressing, permissions/permissions-model.md for the protocol underneath, and security/risks.md for where it could fall down.


Related repositories

About

Workspace Protocol: the specification (in flight) and reference implementation of Workspace's peer-to-peer data and permissions layer, across iOS, Android, macOS, web and *nix

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages