docs: v0.7.0 overhaul, migration guide and compiled samples #178
No reviewers
Labels
No labels
breaking-change
bug
documentation
duplicate
enhancement
good first issue
help wanted
performance
question
wontfix
No milestone
No project
No assignees
4 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Grandiras/ATProto.NET!178
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "issue-138-docs"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #138.
The v0.7.0 docs overhaul: a migration guide covering every breaking change, one home page per
topic, the hand-written API reference gone, and every C# sample in
README.mdanddocs/compiled by the build.
Migration guide
docs/migrating-to-0.7.mdcovers the wholeBreaking changessection of[Unreleased](plus theRemovedentries and the security fixes that need action), grouped by theme rather than by PR:packages, dependency injection, the client, typed identifiers and the one API shape, sessions,
errors, records and the Bluesky helpers, custom XRPC and hosted endpoints, unions, the
Bluesky/chat/Ozone models, identity resolution, OAuth, the hosted login and Blazor, service auth,
streaming and Jetstream, repositories, Spaces (client and server), Lexicon tooling, Aspire, and a
closing list of behaviour changes that compile unchanged. It opens with an upgrade checklist
(package references, DI registration, identifiers, sessions, exceptions, OAuth hosting, unions,
database migrations).
v0.6.0: the guide maps from what 0.6 users actually have, where the CHANGELOG sometimes namesintermediate states of this cycle (
AddAtProtoEfCoreTokenStore, notAddAtProtoEfCoreSessionStore;TypedFirehoseConsumer, not the removedFirehoseConsumer; noMetadataHttpClient,IsIssuedRelayUrlorAtProtoServiceAuthDefaults, which 0.6 never had).xrpc-handlers.md's "Upgrading from 0.6",lexicon-codegen.md'smigratesection) now point at the guide; the two Spaces database-migration recipes stay onspaces.md, where the guide links them.docs/api-reference.mddeletedIts links now point at the XML documentation (IntelliSense) or the relevant guide. The only content
without another home, the
client.Bskyguidance (helpers, post search, threads, drafts, bookmarks,notification preferences, graph, link cards, age assurance, records without a client), moved to a
new
docs/bluesky.md; the sub-client overview and the pagination conventions moved togetting-started.md.One home per topic
aspnet-core.mdserver.md,aspire.mdserver.md(retitled Acting as the Signed-In User)aspnet-core.mdxrpc-handlers.mdserver.md,error-handling.mdoauth.md#hosted-login-aspnet-coreblazor.md(now components only)managed-pds.mdaspire.mdIAtProtoSessionStoresession-management.mdserver.md,getting-started.mdidentity-types.mdat-protocol-overview.md(concepts only, auth section rewritten for OAuth)low-level-repo.mdcrypto.md(keys, signing, did:key, service auth)error-handling.md(its hierarchy now lists every SDK exception type)custom-records.md,custom-xrpc.md,batch-operations.mdAlso fixed while there: stale package names (
EfCoreAtProtoSessionStoreis inATProtoNet.Server.EntityFrameworkCore), "the Spaces models don't yet" follow the union pattern(they do), and a sentence claiming chat/Ozone/site models were not typed yet.
Every sample compiles
Approach: a source generator over the Markdown.
tests/ATProtoNet.DocSnippetslistsREADME.mdanddocs/*.mdasAdditionalFiles;tests/ATProtoNet.DocSnippets.Generator(netstandard2.0, Roslyn) extracts each
```csharpblock, parses it as top-level C#, and emits itwith
#linedirectives pointing back at the Markdown. A sample that drifts from the API is a builderror at its own line (
docs/migrating-to-0.7.md(1359,8): error CS1061: 'AtProtoClient' does not contain a definition for 'PostAsync', checked by planting one). Why this over the alternatives:region-included source files would have meant rewriting ~380 samples out of the docs and a tool to
keep them in sync; a test that compiles at run time would have needed a CI step, and #137 is
editing
ci.yml. The generator needs neither: CI already builds the solution, soci.ymlisunchanged. The project is
IsPackable=false(fromtests/Directory.Build.props) andTreatWarningsAsErrors, so a sample calling an[Obsolete]member fails too; nothing runs, sonetwork-bound samples only compile.
Conventions (documented in
CONTRIBUTING.md#documentationand the generator's XML doc):access-modified members into a class; a
usinganywhere applies to the whole page.SnippetContext's conventional variables (client,builder,services,app,configuration,logger,httpClient,args,ct,cancellationToken,stoppingToken).<!-- snippet: OAuthClient oauthClient; string code, state; -->on the line before a fencedeclares what a block takes from the code around it, invisibly in rendered Markdown (93 blocks).
continued(same method as the previous block),partial(a fragment),before(0.6 code in the migration guide).
ApplicationStubs.csholds what an application already has:Program, a BlazorApp, theAppHost's
Projects.*and oneMyRepoHost.Numbers: 380 blocks compiled, 14
partial, 17before. The partial ones are interfaceshapes shown for reference (
IAtProtoClientFactory,IAtProtoSessionStore), the template'sAddServiceDefaults(), skeletons around application services (four inxrpc-handlers.md, four inspaces.md, one incustom-xrpc.md), and the twolexicon-codegen.mdblocks showing generatedspace-type code, which does not compile (see Flagged).
Getting there fixed a lot of drift the compiler found, several hundred errors on the first pass, among them
bare expressions as statements, samples using variables from other blocks, missing namespaces on
nearly every page,
ImagesEmbedView/ExternalEmbedView(they areImagesView/ExternalView),a
record.DueDatesample the parser read as arecorddeclaration,UseNpgsqland Redis cacheextensions no package provides, and
MintServiceAuthAsync-style helpers that never existed. Thetest project references
Microsoft.EntityFrameworkCore.Sqlite,StackExchange.Redis,ZstdSharp.Port,NSubstituteandMicrosoft.Extensions.Http.Resilience, so the samples thatshow those application dependencies compile for real.
CLAUDE.md, CONTRIBUTING.md, the issue workflow
CLAUDE.md: the fivesrc/packages as they are (EF Core package, OAuth hosting and serviceauth in Server, no bearer handler, the
AddAtProto()builder, no Redis or resilience), theCHANGELOG style rule (≤ ~300 chars, bold title + 1–3 sentences, no tables or narration,
(#N)),a CI and releases section replacing the non-existent
packagejob (ci.ymlbuilds, tests andruns
pds-integration;release.ymlpublishes onv*tags to the Forgejo feed and nuget.organd creates the release from the CHANGELOG),
atproto-lexgenas csharp/lexicon/lint/diff/publish/resolve, the integration env vars as
TestInfrastructure.cshas them after #137's secondhalf (admin password only; handle/password as overrides; no
RequiresTheory), and the doc-snippetbuild.
CONTRIBUTING.md: five packages plus the tool, the current project tree, integrationrequirements per
IntegrationRequirement, the issue templates (Forgejo has them; GitHub, whereissues are invited, does not, so the fields are listed), CHANGELOG in the same commit, and a
Documentation section with the snippet conventions.
.github/skills/issue-workflow/SKILL.md: rewritten for branch → implement → CHANGELOG anddocs → commit (
closes #N) → push the branch →fj pr create→ wait for review of the currenthead and CI (
fj pr status --wait,fj pr review list) → fix findings →fj pr merge --method squash --delete→ delete the local branch.git push origin mainis gone.docs/architecture.md: the tree regenerated from the actual folders (all Lexicon domains,Labeling,Spaces,Tap, the Server subfolders, six samples, four test projects).Index, links, stale names
docs/index.mdlists all 34 pages (new:bluesky.md,migrating-to-0.7.md; gone:api-reference.md); README's table links the Bluesky page and the migration guide.README.md,CONTRIBUTING.md,CLAUDE.mdanddocs/*.md(relative pathsand
#anchors, GitHub slug rules): 326 links, 0 broken.AddAtProtoServer,AddAtProtoScoped,AddAtProtoAuthentication,AddAtProtoEfCore*Store,AtProtoClientSettings,AtProtoAuthenticationHandler,IOAuthClientProvider,IFirehoseCursorStore,FirehoseConsumer,JetstreamDictionaryClient,ISpaceReplayStore,RedisSpaceReplayStore,AtProtoTokenData,AtProtoHttpException,AtProtoClientBuilder,SetPdsUrl,ListAllRecordsAsync,PlcException,[XrpcEndpoint], …60-odd names): no hits outside the migration guide, CONTRIBUTING's deliberate "before" example,
and "files written by 0.6 are read as they are" compatibility notes. String-typed identifier
calls cannot survive: the samples compile.
CHANGELOG
One
Addedbullet (the migration guide) and oneChangedbullet (the compiled samples, since thesolution gains two projects). No breaking changes.
Verification
dotnet buildof the solution: 0 warnings, 0 errors (Debug; the snippet project also in Release).dotnet test tests/ATProtoNet.Tests/: 5017 passed, 0 failed, 5 skipped.Flagged, not fixed (outside this PR's files)
atproto-lexgen csharpemits space-type holders that do not compile:tools/ATProtoNet.LexiconGenerator/CodeGen/CSharpEmitter.cs:359writespublic static IReadOnlyList<string> Collections => Declaration.Collections;, butSpaceTypeDeclaration.CollectionsisIReadOnlyList<Nsid>(CS0266). The emitter tests assertthe text, not that it compiles.
docs/lexicon-codegen.mdshows the output as the tool emits it,marked
partial.[Unreleased]CHANGELOG names intermediate states in a few migration notes: #122's"
new FirehoseConsumer(…)" (removed by #126), #136's "services.AddAtProtoEfCoreSessionStore<TContext>()"(0.6 had
AddAtProtoEfCoreTokenStore<TContext>()), and #137's[RequiresTheory]mention. Theguide uses the correct names; the bullets are left for the release edit.
among the
AdditionalFilesas diagnostics if that is wanted later.🤖 Generated with Claude Code
🤖 Reviewing this PR — the review will link the full session transcript.
📜 Live transcript — updating every ~5 minutes while the review runs.
⏳ Held on the OpenCode Go window — the 5-hour window is at 0% (the bot holds at 95%).
This continues automatically after the window resets (2026-09-27T04:03:28.622Z) — nothing to re-trigger.
🤖 Reviewing this PR — the review will link the full session transcript.
📜 Live transcript — updating every ~5 minutes while the review runs.
⏳ Held on the OpenCode Go window — the 5-hour window is at 0% (the bot holds at 95%).
This continues automatically after the window resets (2026-09-27T09:03:59.073Z) — nothing to re-trigger.
🤖 Reviewing this PR — the review will link the full session transcript.
📜 Live transcript — updating every ~5 minutes while the review runs.
⏳ Held on the OpenCode Go window — the 5-hour window is at 0% (the bot holds at 95%).
This continues automatically after the window resets (2026-09-27T14:04:29.524Z) — nothing to re-trigger.
@claude /review, please. This is the v0.7.0 docs overhaul (#138). The diff is large and mostly Markdown. Please focus on:
docs/migrating-to-0.7.md: does it cover every bullet under### Breaking changesand### RemovedinCHANGELOG.md's[Unreleased], and are its before/after snippets right? The "before" side is checked against v0.6.0, and the "after" side compiles, see 2.tests/ATProtoNet.DocSnippetsandtests/ATProtoNet.DocSnippets.Generator: does the generator really compile every csharp fence that isn't markedpartialorbefore? Do the#linemappings point at the Markdown line? Is anything silently skipped?CLAUDE.md,CONTRIBUTING.mdand.github/skills/issue-workflow/SKILL.md: are they accurate for the current repo, meaning five src packages, OAuth hosting in Server, the builder,release.ymlpublishing onv*tags, and a branch → PR → review workflow?The CHANGELOG duplicate from the rebase is already removed in
91bceb2.🤖 Reviewing this PR — follow along in the action run; the reply will link the full session transcript.
🤖 Reviewing this PR — the review will link the full session transcript.
📜 Live transcript — updating every ~5 minutes while the review runs.
⏳ Held on the OpenCode Go window — the 5-hour window is at 0% (the bot holds at 95%).
This continues automatically after the window resets (2026-09-27T15:53:37.817Z) — nothing to re-trigger.
✅ Verdict: approve — no blocking issues found.
This is a very large, self-consistent docs overhaul, and the spot-checks I performed against the actual branch content all held up:
tests/ATProtoNet.DocSnippets.Generator/DocSnippetGenerator.cssource (read fromorigin/issue-138-docs) does emit#pragma warning disable ... CS0219 ...on every generated unit, so thecreatelocal indocs/batch-operations.md's Create/Update/Deletecontinuedchain (declared but never read again) will not tripTreatWarningsAsErrorsas I initially suspected — I verified this by reading the actual pragma line rather than assuming.CLAUDE.md's new CI and releases section matches the real.forgejo/workflows/ci.ymlandrelease.ymlcontent on the branch (job names, test filters, env vars, the removedpackagejob) — I diffed the described behavior against the actual workflow files.EfCoreAtProtoSessionStore, namespaceATProtoNet.Server.EntityFrameworkCore) matches the actual filesrc/ATProtoNet.Server.EntityFrameworkCore/TokenStore/EfCoreAtProtoSessionStore.cs.RecordKey.Value(used in the reworkedaspnet-core.mdTodoController sample) exists as a real public property.Given the doc-snippet compiler this PR introduces genuinely re-parses and compiles every sample (confirmed by reading the generator itself, not just trusting the PR description), and the PR's own verification numbers (5017 unit tests, 380 compiled snippets, 326-link check) are plausible and consistent with the tooling actually added, I did not find a reason to doubt the remaining ~1300-line migration guide or the other page rewrites beyond what I could directly check. The scope makes full manual verification of every prose claim infeasible in review, but nothing I checked was inaccurate, and the self-verification story is unusually rigorous (compiler-enforced samples, grep for stale API names, a link checker). No blocking issues found.
⏱ 1m 51s · 21 turns · tokens: 102.5k in / 7.5k out (+2276.8k cache-read)
📜 Full session transcript
🤖 Resolving the merge conflicts — the reply will link the full session transcript.
📜 Live transcript — updating every ~5 minutes while the fix runs.
⏳ Held on the OpenCode Go window — the 5-hour window is at 0% (the bot holds at 95%).
This continues automatically after the window resets (2026-09-27T15:53:37.817Z) — nothing to re-trigger.
91bceb256da2dfb92c89Approval carry-over check. claude-reviewer approved
91bceb2. After #177 merged I rebased onto main, and CHANGELOG.md was the only file that conflicted: CONTRIBUTING.md merged cleanly and keeps both #177's "Public API tracking" section and this PR's changes.verify-rebase: the patch against the merge base, excluding CHANGELOG.md, is byte-identical between91bceb2anda2dfb92(6,230 changed lines).[RequiresTheory]bullet, so I removed it again. The branch's[Unreleased]now differs from main only by this PR's two bullets.Breaking changesandRemovedbullet's backticked API names indocs/migrating-to-0.7.md.a2dfb92. Locally, the build has 0 warnings and 5,058 tests pass.Merging on the carried-over approval.