From 70591ec6065c3b73dc2ee57fda4fd819f6de08b0 Mon Sep 17 00:00:00 2001 From: Mark Xue Date: Wed, 19 Aug 2026 00:19:51 -0700 Subject: [PATCH 1/2] Make VerificationMethod.init public MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only code inside this package could construct a VerificationMethod, so a resolver adapter in another package that is handed a signing key directly rather than a full DID document — Slingshot's resolveMiniDoc — had no way to publish it and shipped verificationMethod: []. Matches Service's initializer, already public. Co-Authored-By: Claude Sonnet 5 --- .changeset/public-verification-method-init.md | 5 +++++ Sources/AtprotoTypes/Atproto/DIDDocument.swift | 8 +++++++- 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 .changeset/public-verification-method-init.md diff --git a/.changeset/public-verification-method-init.md b/.changeset/public-verification-method-init.md new file mode 100644 index 0000000..28bd12f --- /dev/null +++ b/.changeset/public-verification-method-init.md @@ -0,0 +1,5 @@ +--- +"@germ-network/atprototypes": patch +--- + +`Atproto.DIDDocument.VerificationMethod`'s memberwise initializer is now public, matching its `Service` sibling. Only code inside this package could construct one, so a resolver adapter in another package that is handed a signing key directly rather than a DID document — Slingshot's `resolveMiniDoc`, which returns `signing_key` on the wire — had no way to publish it and shipped `verificationMethod: []`. `AtprotoTypesVerify`'s `RepoSigningKey` then refuses every document that resolver produces, and since `optimizedResolve` races it against plc.directory, whether a repo proof verifies depends on which resolver wins. diff --git a/Sources/AtprotoTypes/Atproto/DIDDocument.swift b/Sources/AtprotoTypes/Atproto/DIDDocument.swift index 318e87c..28c7760 100644 --- a/Sources/AtprotoTypes/Atproto/DIDDocument.swift +++ b/Sources/AtprotoTypes/Atproto/DIDDocument.swift @@ -178,7 +178,13 @@ extension Atproto.DIDDocument { /// though this type does not model that field, since nothing here reads it. public let publicKeyMultibase: String? - package init( + /// Public, matching ``Service``'s initializer, because a resolver + /// adapter in another package may be handed the signing key directly + /// rather than a full DID document — Slingshot's `resolveMiniDoc` + /// returns it on the wire. While this was package-scoped, such an + /// adapter could only publish an empty `verificationMethod`, and any + /// repo proof checked against its documents failed for want of a key. + public init( id: String, type: String, controller: String, From c33db525546eaccec0dfc5f0f1a43e66eb8366b5 Mon Sep 17 00:00:00 2001 From: Mark Xue Date: Wed, 19 Aug 2026 00:45:51 -0700 Subject: [PATCH 2/2] Update a comment left stale by the resolveMiniDoc fix Slingshot's adapter no longer ships an empty verificationMethod, so "today's ... builds a document with verificationMethod: []" was about to go wrong the moment this repo's own change reached Microcosm. Co-Authored-By: Claude Sonnet 5 --- Tests/AtprotoTypesVerifyTests/RepoProofVerifierTests.swift | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Tests/AtprotoTypesVerifyTests/RepoProofVerifierTests.swift b/Tests/AtprotoTypesVerifyTests/RepoProofVerifierTests.swift index 3255cc5..dcdf740 100644 --- a/Tests/AtprotoTypesVerifyTests/RepoProofVerifierTests.swift +++ b/Tests/AtprotoTypesVerifyTests/RepoProofVerifierTests.swift @@ -380,9 +380,10 @@ struct RepoProofVerifierTests { } } - ///The gap this closes on the shipped fetch path: today's `resolveMiniDoc` - ///adapter builds a document with `verificationMethod: []`, so every proof - ///would stop here until that key is carried through. + ///The gap this closes on the shipped fetch path: Slingshot's + ///`resolveMiniDoc` adapter used to build a document with + ///`verificationMethod: []`, so every proof stopped here until that key + ///was carried through. @Test("a document with only a non-atproto method is refused") func refusesWrongFragment() throws { let scenario = Scenario()