From 59dd963edca60684e798bbdaedea93d04330e9d7 Mon Sep 17 00:00:00 2001 From: JP Hastings-Spital Date: Tue, 11 Aug 2026 07:30:52 +0100 Subject: [PATCH] docs: close out the dev.atfs.server v2 bean MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The lexicon is published and the bench record carries accounts, both verified against the network: the published schema normalises byte-identical to lexicons/dev/atfs/server.json, and the record is now valid under it — which the old owner-implicit record would not have been. Records why a rejected serviceDid logs rather than exits, against the plan the bean was opened with. --- ...er-v2-accounts-required-and-did-only-en.md | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/.beans/ATFS-7peg--devatfsserver-v2-accounts-required-and-did-only-en.md b/.beans/ATFS-7peg--devatfsserver-v2-accounts-required-and-did-only-en.md index abfd856..8c23324 100644 --- a/.beans/ATFS-7peg--devatfsserver-v2-accounts-required-and-did-only-en.md +++ b/.beans/ATFS-7peg--devatfsserver-v2-accounts-required-and-did-only-en.md @@ -1,10 +1,11 @@ --- # ATFS-7peg title: 'dev.atfs.server v2: accounts required and DID-only, endpoint derived from serviceDid, ipfs.port gone' -status: in-progress +status: completed type: task +priority: normal created_at: 2026-08-10T20:30:59Z -updated_at: 2026-08-10T20:30:59Z +updated_at: 2026-08-11T06:30:44Z --- Three changes to the record, agreed 2026-08-10, that shrink it to three load-bearing fields — accounts (who), serviceDid (where, and who-am-I), follows (what to mirror). @@ -24,7 +25,7 @@ Three changes to the record, agreed 2026-08-10, that shrink it to three load-bea - [x] internal/daemon: allowlist is rec.Accounts; ipfs port constant; reload.go loses the port and endpoints branches - [x] internal/ipfs: DefaultPort - [x] Docs: README (record examples, did:web section, follow section), CLAUDE.md ground rules -- [ ] External, needs JP: re-publish the lexicon to did:web:atfs.dev (ATFS-0oko), and add accounts to the live bench record +- [x] External, needs JP: re-publish the lexicon to did:web:atfs.dev (ATFS-0oko), and add accounts to the live bench record ## Summary of Changes @@ -40,3 +41,44 @@ Three changes to the record, agreed 2026-08-10, that shrink it to three load-bea Deliberate departures from the bean's literal wording, judged in-repo: - `buildVerifier`'s "record whose accounts can't build an allowlist" test (`TestReload_UnusableRecordKeepsTheRunningConfiguration`) was repointed at `auth.NewAllowlist` rejecting a malformed accounts entry, rather than `syntax.ParseDID` rejecting a malformed serviceDid — the latter path is now nearly unreachable, since `UploadsEnabled()`'s bare-domain-did:web check filters out almost everything `ParseDID` would also reject. - A new `TestReload_RejectedServiceDIDDisablesUploads` replaces the old "unusable record keeps running" framing for a bad serviceDid specifically, because that scenario's outcome actually changed: `buildVerifier` no longer errors for a non-bare-domain-did:web value (it hits the `UploadsEnabled()` gate first and returns `auth.Disabled{}, nil`), so a live edit to a rejected serviceDid now disables uploads rather than leaving the old verifier running. + +## Summary of Changes + +The record is three fields: accounts, serviceDid, follows. + +`accounts` is required, minItems 1, format did, and no longer implies the +owner — `EffectiveAccounts` is gone and the allowlist is `rec.Accounts`. +`ipfs.port` is gone with `IPFSPort`/`DefaultIPFSPort`; the node binds +`ipfs.DefaultPort`, which leaves the did:web document as the only +startup-bound setting (CLAUDE.md's ground rule dropped from two exceptions +to one). `endpoints` is gone, derived from serviceDid by `Server.Endpoint`; +`ParseDIDWebDomain` moved from internal/serve to internal/record, and +`serve.DIDWeb` — down to one field — collapsed to a plain string. + +`UploadsEnabled` now needs a bare-domain did:web serviceDid *and* a +non-empty allowlist, so a did:plc serviceDid stops enabling uploads. + +**Rejected config, not a fatal error** — contrary to the plan this bean was +opened with. Exiting on a bad serviceDid would let a typo in a remote, +live-reloaded record restart-loop an appliance with no shell, where the +failure reads as a hardware fault. It logs `slog.Error` naming the value and +holds the bootstrap state instead, exactly as an absent record does, which +is what keeps "a missing record is never fatal" true. + +internal/follow's tests moved to `httptest.NewTLSServer` with a transport +redirecting TLS dials to the real listener: production now always polls a +derived `https://` URL, so a test origin at a domain that doesn't resolve is +the only way to exercise the real derive-then-fetch path rather than +side-stepping it. `diffRecords`' restart detection was tightened to key on +serviceDid rather than the broader auth flag, which could previously claim a +restart was needed for an accounts-only edit. + +## External steps (JP, 2026-08-11) + +Both done and verified from here. The live bench record now reads +`{accounts: [did:plc:ephkzpinhaqcabtkugtbzrwu], serviceDid: +did:web:atfs.byjp.me}` — valid under the new schema, and enough for +`UploadsEnabled`, which the old owner-implicit record would no longer have +been. The published `com.atproto.lexicon.schema` under did:web:atfs.dev +compares byte-identical to `lexicons/dev/atfs/server.json` after +normalisation, so the two are in sync as of this commit. -- 2.51.2