atproto utils for zig
zat.dev
atproto
sdk
zig
1# changelog
2
3## 0.2.16
4
5- **fix**: bump websocket.zig to `395d0f4` — reads full HTTP body on TCP split writes (fixes empty body when headers and body arrive in separate TCP segments)
6
7## 0.2.15
8
9- **feat**: `parseDidKey`, `verifyDidKeySignature` — parse `did:key` strings back to key type + raw bytes, verify signatures by `did:key` with automatic curve dispatch
10- **feat**: `Keypair` struct — unified abstraction over secp256k1/P-256 for sign, publicKey, did:key formatting
11- **feat**: optional `onConnect` callback on `JetstreamClient` — exposes which host the client connected to
12
13## 0.2.14
14
15- **fix**: memory leak in `HttpTransport.fetch()` — `toArrayList()` transferred buffer ownership without freeing; use `written()` instead to keep ownership with the deferred `deinit()`
16
17## 0.2.13
18
19- **docs**: devlog 007 — up and to the right (corrections to 006, sync 1.1 verification, lightrail collection index)
20
21## 0.2.12
22
23- **feat**: configurable `keep_alive` on `HttpTransport` and `DidResolver.initWithOptions` — allows disabling HTTP connection reuse for memory leak investigation
24
25## 0.2.11
26
27- **fix**: enable TCP keepalive on websocket connections — detect dead peers in ~20s instead of blocking forever
28
29## 0.2.10
30
31- **deps**: bump websocket.zig to fork commit `9e6d732` — TCP split guard for HTTP body reads behind reverse proxies
32
33## 0.2.9
34
35- **fix**: SPA fallback routing for standard.site deep links — `_redirects`, `<base href="/">`, devlog short-name aliases
36- **fix**: add glibc to nixery deps for wisp-cli patchelf in CI
37- **docs**: devlog 006 — building a relay in zig (zlay architecture, deployment war stories, backfill)
38- **fix**: publish-docs.zig missing devlog entries 004-006
39
40## 0.2.8
41
42- **feat**: sync 1.1 — `ChildRef` union, `loadFromBlocks`, `putReturn`/`deleteReturn`, `verifyCommitDiff`
43- **feat**: `loadCommitFromCAR` returns unsigned commit bytes
44
45## 0.2.7
46
47- **feat**: `Value.getUint()` — extract unsigned integers as `?u64` from CBOR maps. `getInt()` truncates values > `i64` max; upstream AT Protocol firehose seq numbers now exceed this limit.
48
49## 0.2.6
50
51- **feat**: specialized MST decoder — `decodeMstNode()` parses known MST CBOR schema directly, zero-copy byte slicing, avoids generic `Value` union construction
52- **feat**: in-walk MST structure verification — `walkAndVerifyMst` checks key heights during traversal instead of full tree rebuild. MST step: 218ms → 39ms (5.5x), compute total: 300ms → 123ms (2.4x)
53- **docs**: devlog 005 — updated benchmark numbers and chart
54
55## 0.2.5
56
57- **feat**: O(1) block lookup in CAR parser — `StringHashMap` index built during `read()`/`readWithOptions()`, `findBlock()` uses index instead of linear scan
58- **fix**: `verifyRepo` bypasses default 2 MB / 10k block limits so large repos (e.g. pfrazee.com at 70 MB / 243k blocks) actually work
59- **docs**: devlog 005 — clarify Rust ecosystem (rsky, jacquard, hand-rolled RustCrypto)
60
61## 0.2.4
62
63- **feat**: configurable CAR size limits — `max_size` and `max_blocks` options in `readWithOptions` for large repo verification
64- **feat**: export `jwt` module (not just `Jwt` type) for direct access to `verifySecp256k1`/`verifyP256`
65- **docs**: devlog 005 — three-way trust chain verification (zig vs Go vs Rust)
66- **docs**: README rewrite — added CBOR, CAR, MST, firehose, jetstream, signing, repo verification
67
68## 0.2.3
69
70- **docs**: devlog 004 — the sig-verify saga (k256 5×52-bit field, Fermat scalar inversion, three-way bench with rsky)
71- changelog backfill for 0.2.1 and 0.2.2
72
73## 0.2.2
74
75- **feat**: CAR parser enforces size limits — 2MB max on blocks field, max block count. matches indigo's limits for production parity.
76
77## 0.2.1
78
79- **feat**: CID hash verification in CAR parser — `car.read()` SHA-256 hashes each block and compares against the CID digest. proves block content wasn't corrupted or tampered with. `readWithOptions(.{ .verify_block_hashes = false })` to skip for trusted local data.
80- **fix**: remove pfrazee.com from default test suite (network-dependent)
81
82## 0.2.0
83
84- **feat**: end-to-end repo verification — `verifyRepo(allocator, identifier)` exercises the full AT Protocol trust chain: handle → DID → DID document → signing key → fetch repo CAR → verify commit signature → walk MST → rebuild tree → CID match
85- **refactor**: organize `src/internal/` into domain subdirectories following the [TypeScript SDK](https://github.com/bluesky-social/atproto/tree/main/packages): `syntax/`, `crypto/`, `identity/`, `repo/`, `xrpc/`, `streaming/`, `testing/`
86
87## 0.1.9
88
89- **feat**: merkle search tree (MST) — `mst.Mst` with `put`, `get`, `delete`, `rootCid`
90- **feat**: ECDSA signing — `signSecp256k1`, `signP256` with low-S normalization (RFC 6979)
91- **feat**: `did:key` construction — `multicodec.formatDidKey`, `multicodec.encodePublicKey`
92- **feat**: multibase encoding — base58btc encode, base32lower encode/decode
93- interop tests: MST common prefix (13 vectors), commit proofs (6 fixtures)
94
95## 0.1.8
96
97- **fix**: NSID parser rejects TLD starting with digit (e.g. `1.0.0.127.record`)
98- **fix**: AT-URI parser validates authority (DID/handle), collection (NSID), and rkey components; rejects `#`, `?`, spaces
99- **fix**: reject high-S ECDSA signatures — atproto requires low-S normalization (BIP-62 style)
100- `verifySecp256k1` and `verifyP256` are now `pub`
101- atproto interop test suite: syntax validation (6 types), crypto signature verification (6 vectors), MST key heights (9 vectors)
102
103## 0.1.7
104
105- slim `Cid` struct from 56 to 16 bytes — store only raw bytes, parse version/codec/digest lazily on demand
106- `Value` union shrinks from 64 to 24 bytes, `MapEntry` from 80 to 40 bytes
107- zero-cost CID decode — tag 42 handler stores a byte slice reference instead of parsing varint fields
108- inline map key reading in CBOR decoder — skips full `decodeAt` + union construction per key
109- comptime size assertions for `Value` and `MapEntry`
110- **breaking**: `Cid` fields (`version`, `codec`, `hash_fn`, `digest`) are now accessor methods returning optionals — e.g. `cid.version` → `cid.version().?`
111- `parseCid` simplified to a trivial raw-bytes wrapper
112
113## 0.1.6
114
115- round-robin host rotation for jetstream and firehose clients
116- `Options.host` → `Options.hosts` with sensible defaults (bsky + community relays)
117- backoff resets on host switch, jetstream rewinds cursor by 10s
118- default jetstream hosts: 4 official bsky, waow.tech, fire.hose.cam, 6 firehose.stream regions
119- default firehose hosts: bsky.network + 3 firehose.network regions
120
121## 0.1.5
122
123- align firehose event types with AT Protocol sync spec
124
125## 0.1.4
126
127- firehose support: DAG-CBOR codec, CAR codec, CID creation, firehose client
128- encode and decode `com.atproto.sync.subscribeRepos` binary frames
129
130## 0.1.3
131
132- jetstream WebSocket client with typed events, reconnection, and cursor tracking
133- `extractAt` ignores unknown JSON fields by default
134- HTTP I/O isolated behind `HttpTransport` for 0.16 prep
135- websocket dependency pinned to specific commit
136
137## 0.1.2
138
139- `extractAt` logs diagnostic info on parse failures (enable with `.zat` debug scope)
140
141## 0.1.1
142
143- xrpc client sets `Content-Type: application/json` for POST requests
144- docs published as `site.standard.document` records on tag releases
145
146## 0.1.0
147
148sync types for firehose consumption:
149
150- `CommitAction` - `.create`, `.update`, `.delete`
151- `EventKind` - `.commit`, `.sync`, `.identity`, `.account`, `.info`
152- `AccountStatus` - `.takendown`, `.suspended`, `.deleted`, `.deactivated`, `.desynchronized`, `.throttled`
153
154these integrate with `std.json` for automatic parsing.
155
156## 0.0.2
157
158- xrpc client with gzip workaround for zig 0.15.x deflate bug
159- jwt parsing and verification
160
161## 0.0.1
162
163- string primitives (Tid, Did, Handle, Nsid, Rkey, AtUri)
164- did/handle resolution
165- json helpers