From edbe8c117b5105f8f9ba85e693994a380e8779c7 Mon Sep 17 00:00:00 2001 From: sepehr-safari Date: Mon, 7 Sep 2026 23:01:44 +0300 Subject: [PATCH] The docs say what actually shipped Four things a stranger reads first, each of them wrong. The Quickstart's one copy-pasteable line fetched v0.12.0. That is the command a reader from a package list or a forum actually runs, and it silently handed them a version two releases old, without the leak fix 0.14.1 exists for. The status line four lines above it already said 0.14.1. `CURRENT_STATE.md`, which the README sends people to for "exactly what's in progress", said the library was v0.5.0, Notary v0.3.0 and Plaza v0.2.0. Ten, seven and sixteen releases behind. It also called Notary macOS-only on the day Linux tarballs shipped, and named notifications as the next milestone when notifications have been in Plaza for months. So the version numbers come out of that file entirely. It went nine releases stale saying them, and a stale number is worse than no number: it is readable, specific and wrong. It links to each project's releases instead, which cannot drift. What stays is the description of what exists, which changes slowly. Both apps were described as macOS-only in the README's own "Built with it" section, on the day both shipped Linux builds. Also here: the em-dashes are gone from AGENTS.md and CONTRIBUTING.md, and while in AGENTS.md the dependency graph is corrected. It listed `karlseguin/websocket.zig` and `allyourcodebase/lmdb` as PLANNED. LMDB has been a real dependency since the store landed, and the websocket is not a dependency at all: `src/websocket.zig` implements RFC 6455 here, because the relay connection needs control over when a frame surfaces. The repository layout block listed three files when there are twenty-four. The CHANGELOG's em-dashes are left alone deliberately. Those entries are the published text of past releases, and editing them here would only make the file disagree with the release pages. --- AGENTS.md | 38 ++++++++++++++++++++++++-------------- CONTRIBUTING.md | 4 ++-- CURRENT_STATE.md | 35 ++++++++++++++++++++++------------- README.md | 9 +++++---- 4 files changed, 53 insertions(+), 33 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 512cba8..a233d39 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,17 +8,24 @@ coding agents at the conventions, build system, and structure used here. `nostr` is a [Nostr](https://nostr.com) protocol library for Zig: keys and encoding, event construction and signing, relay transport, encrypted messaging, and a local-first event store. It has no runtime dependency on -any specific application — it is consumed as a library by other repos in +any specific application: it is consumed as a library by other repos in the `zig-nostr` org (a signer, a DM client, a read-only client). ## Repository layout ``` src/ - root.zig — public module entry point (@import("nostr")) -build.zig — build graph: module + test step -build.zig.zon — package manifest, dependencies -.zigversion — pinned Zig compiler version + root.zig # public module entry point (@import("nostr")) + keys.zig # secp256k1 keys and BIP-340 signatures + event.zig # the NIP-01 event model and canonical serialization + relay.zig # the live dialer and the relay connection + websocket.zig # RFC 6455 framing, hand-written + store.zig # the local-first LMDB event store + liveness.zig # when a relay connection has gone quiet + ... # one file per NIP, plus filter/message/json/hex/bech32 +build.zig # build graph: module + test step +build.zig.zon # package manifest, dependencies +.zigversion # pinned Zig compiler version ``` As modules are added (keys, encoding, events, transport, store, crypto), @@ -39,14 +46,17 @@ Use the Zig version pinned in `.zigversion`. CI runs on Linux and macOS. Current: -- `bitcoin-core/secp256k1` — BIP-340 Schnorr signing/verification. Compiled +- `bitcoin-core/secp256k1`: BIP-340 Schnorr signing/verification. Compiled from source and exposed to Zig via translate-c in `build.zig`; wrapped by `src/keys.zig`. Pinned by exact commit in `build.zig.zon`. -Planned, added as each milestone needs them: +- `LMDB/lmdb`: the local event store's backing. Compiled from source and + pinned the same way. +- `atman/zg`: Unicode normalization, for NIP-49 passphrases. -- `karlseguin/websocket.zig` — relay transport. -- `allyourcodebase/lmdb` — local event store backing. +The websocket transport is not a dependency. `src/websocket.zig` implements +RFC 6455 framing directly, because the relay connection needs control over when +a frame surfaces and no client library exposed that. Dependencies are pinned in `build.zig.zon`; never vendor or hand-roll crypto primitives that have an audited upstream implementation. @@ -61,13 +71,13 @@ primitives that have an audited upstream implementation. - Never push directly to `main`; all changes land via reviewed PRs from short-lived branches. - Update `CHANGELOG.md` (Unreleased section) and `CURRENT_STATE.md` inside - the same PR that introduces the change — not as a follow-up. + the same PR that introduces the change, not as a follow-up. ## Code style - `zig fmt` is the formatter; CI fails on unformatted code. - Prefer explicit error sets over `anyerror`. -- No hand-rolled cryptography for signing/verification — bind to audited +- No hand-rolled cryptography for signing/verification: bind to audited upstream implementations (see Dependency graph). - Validate all externally-sourced data (relay messages, parsed events) at the boundary; don't assume well-formed input. @@ -81,9 +91,9 @@ must pass its official test vectors, before either ships. ## Orientation -- [`CURRENT_STATE.md`](CURRENT_STATE.md) — what's built, in progress, and +- [`CURRENT_STATE.md`](CURRENT_STATE.md): what's built, in progress, and next, updated on every merge. -- [`CONTRIBUTING.md`](CONTRIBUTING.md) — full contribution workflow. +- [`CONTRIBUTING.md`](CONTRIBUTING.md): full contribution workflow. - [GitHub milestones](https://github.com/zig-nostr/nostr/milestones) and the - [org project board](https://github.com/orgs/zig-nostr/projects) — the + [org project board](https://github.com/orgs/zig-nostr/projects): the full roadmap. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4c0f5c8..194ad40 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,7 +12,7 @@ workflow used for all changes to this repository. ## Workflow 1. **Open or claim an issue** describing the change, with acceptance - criteria. Every PR links back to an issue — even small fixes. + criteria. Every PR links back to an issue, even small fixes. 2. **Branch from `main`**, named after the change (`feat/nip19-encoding`, `fix/event-id-hash`, `chore/ci-macos`). 3. **Implement** the change with tests. Update `CHANGELOG.md` (Unreleased @@ -53,5 +53,5 @@ for what's built so far and what's next. ## Security -Do not open public issues for security vulnerabilities — see +Do not open public issues for security vulnerabilities; see [`SECURITY.md`](SECURITY.md). diff --git a/CURRENT_STATE.md b/CURRENT_STATE.md index a9d1b23..786bf5e 100644 --- a/CURRENT_STATE.md +++ b/CURRENT_STATE.md @@ -5,16 +5,22 @@ A snapshot for somebody reading this repo. The [milestones](https://github.com/zig-nostr/plaza/milestones) are the tracker; this file only says where things stand today. +Version numbers are deliberately not repeated here. This file went nine releases +out of date saying them, and a stale number is worse than no number: it is +readable, specific and wrong. Each project's own releases page is the answer. + ## The library -`v0.5.0`. Shipped and covered by tests: +[Latest release](https://github.com/zig-nostr/nostr/releases). Shipped and +covered by tests: - **Core**: secp256k1 keys, BIP-340 Schnorr signatures against the official vectors, the NIP-01 event model, NIP-19/21 encoding, NIP-06 derivation, NIP-49 encrypted keys. - **Transport**: RFC 6455 WebSocket, a relay connection state machine, a live TCP/TLS dialer, NIP-42 authentication, and the NIP-65 outbox model with no - hardcoded relays. + hardcoded relays. A read can carry a deadline, so a thread serving a quiet + relay can still notice that its pool changed. - **Store**: a memory-mapped LMDB event store with a bounded, newest-first query planner. A 500-note feed query is 0.28 ms at 100,000 stored events, and a profile read is 8 microseconds. @@ -27,22 +33,25 @@ on the roadmap while groups, messages, media and payments are still landing. ## The apps -- **[Notary](https://github.com/zig-nostr/notary)** `v0.3.0`: a native macOS - NIP-46 signer. Your key lives in a local daemon, nothing signs without your - approval, and the `nsec` never enters a client. -- **[Plaza](https://github.com/zig-nostr/plaza)** `v0.2.0`: the flagship client. - Read without an account, post in four clicks, with the feed rendered from - disk. Reads - every account you follow, with no cap on how far you can scroll. +- **[Notary](https://github.com/zig-nostr/notary)**: a native NIP-46 signer. + Your key lives in a local daemon, nothing signs without your approval, and the + `nsec` never enters a client. +- **[Plaza](https://github.com/zig-nostr/plaza)**: the flagship client. Read + without an account, post in four clicks, with the feed rendered from disk. + Reads every account you follow, with no cap on how far you can scroll. -Both are downloadable. What comes next lands inside them rather than as new apps. +Both are downloadable for macOS (Apple Silicon) and Linux (x86_64 and aarch64). +Off macOS there is no platform text layer, so both draw every glyph from faces +they carry: emoji are drawn in colour, and scripts those faces do not cover are +not drawn at all. What comes next lands inside these two rather than as new apps. ## What is next The ten milestones, in order, are on the -[roadmap](https://zignostr.com/roadmap). The first is notifications: who acted, -what they did, and the note it was about, which the current one-line row does not -say. +[roadmap](https://zignostr.com/roadmap). The first is everything you do on the +first day: the four things already built that do not work (reposts by people you +follow, relay hints, hashtags, bookmarks), then pictures, a full profile, zaps +you can send, and search. That page also lists what is deliberately **not** being built, and why. Reading the second half is the faster way to understand the first. diff --git a/README.md b/README.md index e371dd8..dfedbfa 100644 --- a/README.md +++ b/README.md @@ -77,7 +77,7 @@ Methodology and the full write-up are on the Add the library to your `build.zig.zon`: ```sh -zig fetch --save https://github.com/zig-nostr/nostr/archive/refs/tags/v0.12.0.tar.gz +zig fetch --save https://github.com/zig-nostr/nostr/archive/refs/tags/v0.14.1.tar.gz ``` Wire the module in `build.zig`: @@ -169,12 +169,13 @@ do. The library is proven by native apps built on it, the ecosystem forming around one core: -- **[Notary](https://github.com/zig-nostr/notary)**: *shipped.* A native macOS - remote signer (NIP-46 bunker): your key lives in a local daemon, every signing +- **[Notary](https://github.com/zig-nostr/notary)**: *shipped.* A native remote + signer (NIP-46 bunker): your key lives in a local daemon, every signing request waits for your approval, and the `nsec` never enters a client. + Downloadable for macOS (Apple Silicon) and Linux (x86_64 and aarch64). - **[Plaza](https://github.com/zig-nostr/plaza)**: *shipped.* The flagship: a fast, local-first client where you read without an account, post in four - clicks, and the feed renders from disk. A downloadable macOS app. + clicks, and the feed renders from disk. Downloadable for the same two. Private messages, zaps and groups land inside Plaza rather than as separate apps. A messenger you have to switch to is one you stop using.