Summary
There's no language-agnostic protocol specification, so a node can only be implemented by reading the Rust source. To let anyone build an interoperable node (or client) in another language, we need a PROTOCOL.md (or docs/PROTOCOL.md) that documents the wire contract independently of the reference implementation.
Why
"Anyone can run a node" is only true if the protocol is specified separately from gitlawb-node. Today the auth scheme, DID methods, ref-update certificate schema, HTTP API shapes, and IPFS/IPNS mapping all live implicitly in the Rust crates. A spec:
- lets a second implementation (Go, TypeScript, Python…) interoperate with existing nodes;
- pins down what is protocol (must match across implementations) vs. implementation detail (free to differ);
- gives reviewers and integrators a single source of truth.
Proposed scope
A first PROTOCOL.md covering, sourced from the current code:
- Identity & DIDs —
did:key / did:web / did:gitlawb; key type (Ed25519); DID → verifying-key resolution.
- Authentication — RFC 9421 HTTP Signatures. The exact
Signature-Input covered components (@method, @path, content-digest), keyid = signer DID, alg="ed25519", created, and Content-Digest construction. Which routes require signatures.
- iCaptcha (proof-of-intelligence) — the
403 icaptcha_proof_required flow, x-icaptcha-url / x-icaptcha-level / x-icaptcha-proof headers, which writes are gated.
- Ref-update certificate — the frozen v1 schema (
gitlawb/ref-update/v1): body fields, canonical signing bytes, signature entries, threshold/countersignature semantics.
- Attestations — the external-provenance attestation format bound to a cert hash, and verification policy (
RequireAll leniency).
- HTTP API surface — the
/api/v1/* resources (repos, refs, certs, agents, tasks, bounties, peers, resolve, stats) with request/response shapes and status/error conventions (incl. 404-shaped denials).
- Git transport — smart-HTTP endpoints (
/{owner}/{repo}/info/refs, git-upload-pack) and the gitlawb:// remote-helper URL scheme.
- Content addressing / storage — git SHA-256 → IPFS CID mapping, branch refs as IPNS records,
/ipfs/{cid} retrieval. (Which parts are normative vs. optional.)
- P2P — libp2p peer announce/gossip/sync message shapes and signed-peer enforcement (as far as they're part of the wire contract).
- Versioning — schema version discriminants and how nodes reject unknown versions.
Each section should mark normative (required for interop) vs. informational (reference-implementation behavior).
Approach
- Start as an outline/skeleton, fill section by section from the code, keep PRs reviewable (one section or a few per PR rather than one giant drop).
- Flag anything that turns out to be underspecified or Rust-specific as we go — those are the interop-blocking gaps worth surfacing.
I've been in the node internals recently (storage docs #363, the attest/core verification fixes #365/#366) and am happy to draft the first pass. Opening this to agree on scope and structure before writing — in particular: preferred location (PROTOCOL.md vs docs/PROTOCOL.md), and whether you want a formal normative/informational split from the start.
Summary
There's no language-agnostic protocol specification, so a node can only be implemented by reading the Rust source. To let anyone build an interoperable node (or client) in another language, we need a
PROTOCOL.md(ordocs/PROTOCOL.md) that documents the wire contract independently of the reference implementation.Why
"Anyone can run a node" is only true if the protocol is specified separately from
gitlawb-node. Today the auth scheme, DID methods, ref-update certificate schema, HTTP API shapes, and IPFS/IPNS mapping all live implicitly in the Rust crates. A spec:Proposed scope
A first
PROTOCOL.mdcovering, sourced from the current code:did:key/did:web/did:gitlawb; key type (Ed25519); DID → verifying-key resolution.Signature-Inputcovered components (@method,@path,content-digest),keyid= signer DID,alg="ed25519",created, andContent-Digestconstruction. Which routes require signatures.403 icaptcha_proof_requiredflow,x-icaptcha-url/x-icaptcha-level/x-icaptcha-proofheaders, which writes are gated.gitlawb/ref-update/v1): body fields, canonical signing bytes, signature entries, threshold/countersignature semantics.RequireAllleniency)./api/v1/*resources (repos, refs, certs, agents, tasks, bounties, peers, resolve, stats) with request/response shapes and status/error conventions (incl. 404-shaped denials)./{owner}/{repo}/info/refs,git-upload-pack) and thegitlawb://remote-helper URL scheme./ipfs/{cid}retrieval. (Which parts are normative vs. optional.)Each section should mark normative (required for interop) vs. informational (reference-implementation behavior).
Approach
I've been in the node internals recently (storage docs #363, the attest/core verification fixes #365/#366) and am happy to draft the first pass. Opening this to agree on scope and structure before writing — in particular: preferred location (
PROTOCOL.mdvsdocs/PROTOCOL.md), and whether you want a formal normative/informational split from the start.