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.