Tracking: v0.7.0 update cycle — protocol catch-up, optimization, debloat, API reshaping #141

Closed
opened 2026-09-24 12:39:33 +00:00 by Grandiras · 2 comments
Owner

The v0.7.0 update cycle has four goals:

  • bring the SDK up to date with the protocol, especially Spaces;
  • an optimization pass (performance, memory, latency);
  • a debloat that stays fully functional;
  • more robust APIs. Breaking changes are accepted.

This issue tracks the work. Each item below is one PR. A PR merges once opencode-bot has approved its current head and CI is green.

What the audit found (2026-09-24)

Six parallel audits:

  • Spaces protocol drift
  • Lexicon coverage
  • Protocol specs
  • Performance
  • Debloat
  • API design

The headline findings:

  • Spaces: upstream split simplespace access into read and write (#5496). Most simplespace calls are now wire-incompatible. Five interop bugs were already present.
  • Crashes in hot paths:
    • One gallery post fails a whole timeline page (about 1 in 8 pages).
    • Any unknown union variant fails the whole response.
    • Signed labels fail to deserialize.
    • A crafted CAR overflows the stack.
    • An MST PrefixLen can force a ~2 GB allocation.
  • Correctness:
    • The MST doesn't match the spec: every root CID is wrong.
    • Tid.Next() goes out of order and produces duplicates.
    • AddAtProto() cannot resolve its client.
    • Logout revokes nothing.
    • A failed OAuth refresh is stored as a token.
    • Concurrent refreshes log users out.
    • Wrong JSON names, one non-existent endpoint and 7 invented permission sets.
    • 48 of 72 invalid AT URIs are accepted.
  • Performance:
    • A DID lookup per firehose commit.
    • An extra DPoP round trip per server-side request.
    • Uncompressed, fully buffered responses.
    • Unbounded 429 sleeps.
    • Reference-style BLAKE3 and LtHash (up to 17× headroom).
  • Coverage: 183 of 350 upstream endpoints and records. Missing include group chat, bookmarks, multipart video, searchPostsV2, Sync 1.1, service-auth verification and confidential OAuth clients.
  • Bloat:
    • Every Server or Blazor app pulls in 19 NuGet packages.
    • Base64url is written 11×, JWT 7×, and there are 2 DID resolvers.
    • 17.4 MB of vendored Bootstrap.
    • Unused and duplicated API.

Owner decisions

  • Typed identifiers everywhere (Did/Handle/AtUri/Nsid/Cid/RecordKey/Tid, plus AtDatetime).
  • Re-split EF Core into ATProtoNet.Server.EntityFrameworkCore, drop the Redis replay store (a documented snippet replaces it), and drop Http.Resilience.
  • Move OAuth login into Server; fix the Blazor widgets.
  • In scope: Sync 1.1 + Tap, Lexicon resolution/publishing, label signing, Ozone breadth.

Roadmap

Waves run in parallel internally and merge before the next wave starts.

Wave 1: independent fixes and foundations

  • #110 chore: project metadata, unused dependencies, sample assets
  • #111 fix(repo): spec-correct MST, hardened DAG-CBOR/CAR parsing
  • #112 perf(crypto): vectorized BLAKE3/LtHash, cached key parsing
  • #113 fix(spaces)!: simplespace read/write access, authority interop
  • #114 fix(identity)!: spec-conformant identifiers, monotonic TIDs
  • #115 feat(serialization)!: open unions, unknown-field round-tripping
  • #116 refactor(hosting): shared PDS resource base

Wave 2: transport and primitives

  • #117 refactor(http)!: one error model, robust XRPC transport
  • #118 refactor(auth): shared JWT/DPoP/base64url primitives

Wave 3: the big API reshape

  • #119 feat!: typed identifiers and uniform conventions everywhere

Wave 4

  • #120 feat(identity)!: resolver abstraction, caching, SSRF-safe fetching
  • #121 refactor(server)!: XRPC endpoint hosting
  • #122 feat(records)!: record/custom-XRPC ergonomics, client.Bsky helpers
  • #123 fix(lexicon)!: wire fidelity + drift test

Wave 5

  • #124 feat(auth)!: unified session model and lifecycle
  • #125 feat(server): inbound service-auth verification
  • #126 refactor(streaming)!: one streaming core
  • #127 feat(bsky): new app.bsky surface
  • #128 feat(chat): group chats and chat.bsky
  • #129 feat(atproto): com.atproto / site.standard gaps

Wave 6

  • #130 feat(lexicon): lexicon resolution/publishing, permission sets
  • #131 feat(ozone): moderation/report/queue tooling
  • #132 feat(oauth)!: hardened OAuth client, confidential clients
  • #133 fix(spaces): hardening, performance, smaller server surface
  • #134 feat(sync): Sync 1.1 verification, Tap client
  • #135 feat(labels): label signing and verification

Wave 7

  • #136 refactor(server)!: package structure, DI, OAuth hosting, Blazor widgets

Wave 8: finish

  • #137 test: infrastructure consolidation
  • #138 docs: overhaul + migration guide
  • #139 chore: ConfigureAwait, comment compaction, public API tracking
  • #140 chore: release v0.7.0 (the maintainer pushes the tag)

Also related: #108, a security fix for the mirror-sync workflows (separate; rotate FORGEJO_TOKEN and GH_MIRROR_TOKEN).

The v0.7.0 update cycle has four goals: - bring the SDK up to date with the protocol, especially Spaces; - an optimization pass (performance, memory, latency); - a debloat that stays fully functional; - more robust APIs. **Breaking changes are accepted.** This issue tracks the work. Each item below is one PR. A PR merges once opencode-bot has approved its current head and CI is green. ## What the audit found (2026-09-24) Six parallel audits: - Spaces protocol drift - Lexicon coverage - Protocol specs - Performance - Debloat - API design The headline findings: - **Spaces:** upstream split simplespace access into read and write (#5496). Most `simplespace` calls are now wire-incompatible. Five interop bugs were already present. - **Crashes in hot paths:** - One gallery post fails a whole timeline page (about 1 in 8 pages). - Any unknown union variant fails the whole response. - Signed labels fail to deserialize. - A crafted CAR overflows the stack. - An MST `PrefixLen` can force a ~2 GB allocation. - **Correctness:** - The MST doesn't match the spec: every root CID is wrong. - `Tid.Next()` goes out of order and produces duplicates. - `AddAtProto()` cannot resolve its client. - Logout revokes nothing. - A failed OAuth refresh is stored as a token. - Concurrent refreshes log users out. - Wrong JSON names, one non-existent endpoint and 7 invented permission sets. - 48 of 72 invalid AT URIs are accepted. - **Performance:** - A DID lookup per firehose commit. - An extra DPoP round trip per server-side request. - Uncompressed, fully buffered responses. - Unbounded 429 sleeps. - Reference-style BLAKE3 and LtHash (up to 17× headroom). - **Coverage:** 183 of 350 upstream endpoints and records. Missing include group chat, bookmarks, multipart video, searchPostsV2, Sync 1.1, service-auth verification and confidential OAuth clients. - **Bloat:** - Every Server or Blazor app pulls in 19 NuGet packages. - Base64url is written 11×, JWT 7×, and there are 2 DID resolvers. - 17.4 MB of vendored Bootstrap. - Unused and duplicated API. ## Owner decisions - Typed identifiers everywhere (Did/Handle/AtUri/Nsid/Cid/RecordKey/Tid, plus AtDatetime). - Re-split EF Core into `ATProtoNet.Server.EntityFrameworkCore`, **drop** the Redis replay store (a documented snippet replaces it), and drop Http.Resilience. - Move OAuth login into Server; **fix** the Blazor widgets. - In scope: Sync 1.1 + Tap, Lexicon resolution/publishing, label signing, Ozone breadth. ## Roadmap Waves run in parallel internally and merge before the next wave starts. **Wave 1: independent fixes and foundations** - [x] #110 chore: project metadata, unused dependencies, sample assets - [x] #111 fix(repo): spec-correct MST, hardened DAG-CBOR/CAR parsing - [x] #112 perf(crypto): vectorized BLAKE3/LtHash, cached key parsing - [x] #113 fix(spaces)!: simplespace read/write access, authority interop - [x] #114 fix(identity)!: spec-conformant identifiers, monotonic TIDs - [x] #115 feat(serialization)!: open unions, unknown-field round-tripping - [x] #116 refactor(hosting): shared PDS resource base **Wave 2: transport and primitives** - [x] #117 refactor(http)!: one error model, robust XRPC transport - [x] #118 refactor(auth): shared JWT/DPoP/base64url primitives **Wave 3: the big API reshape** - [x] #119 feat!: typed identifiers and uniform conventions everywhere **Wave 4** - [x] #120 feat(identity)!: resolver abstraction, caching, SSRF-safe fetching - [x] #121 refactor(server)!: XRPC endpoint hosting - [x] #122 feat(records)!: record/custom-XRPC ergonomics, `client.Bsky` helpers - [x] #123 fix(lexicon)!: wire fidelity + drift test **Wave 5** - [x] #124 feat(auth)!: unified session model and lifecycle - [x] #125 feat(server): inbound service-auth verification - [x] #126 refactor(streaming)!: one streaming core - [x] #127 feat(bsky): new app.bsky surface - [x] #128 feat(chat): group chats and chat.bsky - [x] #129 feat(atproto): com.atproto / site.standard gaps **Wave 6** - [x] #130 feat(lexicon): lexicon resolution/publishing, permission sets - [x] #131 feat(ozone): moderation/report/queue tooling - [x] #132 feat(oauth)!: hardened OAuth client, confidential clients - [x] #133 fix(spaces): hardening, performance, smaller server surface - [x] #134 feat(sync): Sync 1.1 verification, Tap client - [x] #135 feat(labels): label signing and verification **Wave 7** - [x] #136 refactor(server)!: package structure, DI, OAuth hosting, Blazor widgets **Wave 8: finish** - [x] #137 test: infrastructure consolidation - [x] #138 docs: overhaul + migration guide - [x] #139 chore: ConfigureAwait, comment compaction, public API tracking - [x] #140 chore: release v0.7.0 (the maintainer pushes the tag) Also related: #108, a security fix for the mirror-sync workflows (separate; **rotate `FORGEJO_TOKEN` and `GH_MIRROR_TOKEN`**).
Author
Owner

Follow-up to schedule once #128 (group chat) and #131 (Ozone) have both merged: com.atproto.moderation.createReport needs the chat.bsky.convo.defs#messageRef subject variant, so chat messages can be reported with a typed subject (the Ozone ModerationSubject union already has it). It's small; fold it into #137 or #138 if nothing else picks it up.

Follow-up to schedule once #128 (group chat) and #131 (Ozone) have both merged: `com.atproto.moderation.createReport` needs the `chat.bsky.convo.defs#messageRef` subject variant, so chat messages can be reported with a typed subject (the Ozone `ModerationSubject` union already has it). It's small; fold it into #137 or #138 if nothing else picks it up.
Author
Owner

v0.7.0 is released: tag v0.7.0 on 861106c (#192). The release workflow published all six packages and their symbol packages to the Forgejo feed (all linked to this repo) and to nuget.org, and created the v0.7.0 release from the CHANGELOG section.

v0.7.0 is released: tag `v0.7.0` on 861106c (#192). The release workflow published all six packages and their symbol packages to the Forgejo feed (all linked to this repo) and to nuget.org, and created the [v0.7.0 release](https://git.grandiras.net/Grandiras/ATProto.NET/releases/tag/v0.7.0) from the CHANGELOG section.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Grandiras/ATProto.NET#141
No description provided.