Found by the payload-key sweep required by #46 (see PR #75).
Symptom
Settings → Connected accounts → Disconnect (Views/LinkedIdentitiesView.swift:275) always fails.
The route answers 400 {"error":"provider is required"}.
Root cause
APIClient.unlinkIdentity(provider:providerId:) (Services/APIClient.swift:172-175) sends the
provider in a JSON body:
struct Body: Encodable { let provider: String; let providerId: String }
try await deleteCamel("/api/user/identities", body: Body(...))
deleteCamel (Services/APIClientTransport.swift:140-145) sets httpBody and never touches the
query string. But DELETE /api/user/identities
(app/api/user/identities/route.ts:57-60) reads it from the URL:
const { searchParams } = new URL(request.url);
const provider = searchParams.get('provider');
if (!provider) return badRequest('provider is required');
The body is never parsed, so provider is always null.
Fix
Acceptance criteria
Files: Services/APIClient.swift:172, Views/LinkedIdentitiesView.swift,
InterlinedListTests/APIClientTests/*.
Found by the payload-key sweep required by #46 (see PR #75).
Symptom
Settings → Connected accounts → Disconnect (
Views/LinkedIdentitiesView.swift:275) always fails.The route answers
400 {"error":"provider is required"}.Root cause
APIClient.unlinkIdentity(provider:providerId:)(Services/APIClient.swift:172-175) sends theprovider in a JSON body:
deleteCamel(Services/APIClientTransport.swift:140-145) setshttpBodyand never touches thequery string. But
DELETE /api/user/identities(
app/api/user/identities/route.ts:57-60) reads it from the URL:The body is never parsed, so
provideris alwaysnull.Fix
DELETE /api/user/identities?provider=<provider>.Percent-encode the value (see the hazard note about
.urlQueryAllowedpermitting&/=/+).providerIdis not read by the route at all — drop it from the call, or keep the parameter anddocument that the route unlinks all identities for that provider
(
deleteMany({ userId, provider }),:64-69). Worth confirming that matches the intent: anaccount with two Mastodon identities would lose both.
?provider=and that the body is empty.Acceptance criteria
Files:
Services/APIClient.swift:172,Views/LinkedIdentitiesView.swift,InterlinedListTests/APIClientTests/*.