Package(s) affected
@dwk/activitypub (possibly a new package, e.g. @dwk/mastodon-client-api, if it doesn't fit inside the endpoint package itself — see composition-contract question below).
Problem
Surfaced during the Pixelfed manual conformance run (fediverse interop #273):
after liking and replying to a post from a real Pixelfed account, there was no
way to confirm those activities landed in the actor's inbox — the S2S /inbox
route is write-only by design, and the only read path today is @dwk/mcp's
agent-facing activitypub_list_inbox tool (which the conformance-target
deployment doesn't even mount).
What a real user of @dwk/workers actually wants is simpler and more direct:
log in with the Pixelfed (or Mastodon, or any Mastodon-API-compatible)
client app of their choice and see their own feed/notifications — the same
experience they'd get running an actual Mastodon or Pixelfed instance.
This is explicitly out of scope today. spec/fediverse-interop.md's non-goals
section says:
Platform client APIs (Mastodon REST API, Lemmy HTTP API). Clients speak
micropub/MCP/outbox to this Worker; only federation is multi-platform.
That's the right call for the federation-interop work @dwk/activitypub
currently does, but it means there is currently no way for a site owner to
browse their own notifications/timeline with an off-the-shelf fediverse
client app — only via a custom MCP-connected agent, or by reading the DO's
storage directly.
Proposed solution
Implement a minimal subset of the Mastodon-compatible Client API sufficient
for a real client app (starting with Pixelfed's own web/mobile client, since
that's the platform this was discovered against) to authenticate and show:
- App registration (
POST /api/v1/apps) and OAuth authorization/token
exchange, layered on @dwk/oauth's existing RFC 8414/7591 building blocks
rather than reinventing OAuth.
GET /api/v1/accounts/verify_credentials (identify as the one actor this
deployment serves).
GET /api/v1/timelines/home and/or /api/v1/notifications — read-only,
backed by the same DO storage activitypub_list_inbox already reads.
- Explicitly not in this first cut: posting through the Client API
(micropub already covers publish), streaming, multi-account support (v1 is
one actor per deployment, same as the rest of @dwk/activitypub), or any
Mastodon feature beyond what's needed for read-only timeline/notification
browsing.
Open design questions to resolve before implementation:
- Does this live inside
@dwk/activitypub (a new client-api.ts module +
routes) or as a separate package? A separate package keeps
@dwk/activitypub free of client-API-specific vocabulary/response shapes
that have nothing to do with federation, matching the "confinement" spirit
of the composition contract — but it would need to reach into
@dwk/activitypub's DO the same way @dwk/mcp's tool contribution does.
- Auth model: reuse
@dwk/indieauth/@dwk/oauth, or does the Mastodon app
OAuth flow's specific quirks (dynamic client registration via
/api/v1/apps predates RFC 7591 and isn't quite the same shape) need its
own thin adapter over the shared primitives?
- How much of the Mastodon JSON response shape (
Status, Account,
Notification entities) is required for real clients to render correctly
without erroring on missing fields — needs testing against at least one
real client (Pixelfed's own, plus ideally a generic Mastodon client like
Tusky) rather than guessing from the API docs alone.
Alternatives considered
- Status quo (MCP only): keeps scope small, but means "see your
notifications" requires either a custom MCP-connected agent or reading the
DO directly — not the experience a typical fediverse user expects.
- Push the read surface into
@dwk/microsub (IndieWeb's own unified-inbox
standard) instead of the Mastodon Client API: technically cleaner (stays
inside IndieWeb standards, no foreign-platform API to maintain), but
doesn't satisfy the actual ask here — a Microsub reader isn't "the Pixelfed
client of your choice."
Additional context
Package(s) affected
@dwk/activitypub(possibly a new package, e.g.@dwk/mastodon-client-api, if it doesn't fit inside the endpoint package itself — see composition-contract question below).Problem
Surfaced during the Pixelfed manual conformance run (fediverse interop #273):
after liking and replying to a post from a real Pixelfed account, there was no
way to confirm those activities landed in the actor's inbox — the S2S
/inboxroute is write-only by design, and the only read path today is
@dwk/mcp'sagent-facing
activitypub_list_inboxtool (which the conformance-targetdeployment doesn't even mount).
What a real user of
@dwk/workersactually wants is simpler and more direct:log in with the Pixelfed (or Mastodon, or any Mastodon-API-compatible)
client app of their choice and see their own feed/notifications — the same
experience they'd get running an actual Mastodon or Pixelfed instance.
This is explicitly out of scope today.
spec/fediverse-interop.md's non-goalssection says:
That's the right call for the federation-interop work
@dwk/activitypubcurrently does, but it means there is currently no way for a site owner to
browse their own notifications/timeline with an off-the-shelf fediverse
client app — only via a custom MCP-connected agent, or by reading the DO's
storage directly.
Proposed solution
Implement a minimal subset of the Mastodon-compatible Client API sufficient
for a real client app (starting with Pixelfed's own web/mobile client, since
that's the platform this was discovered against) to authenticate and show:
POST /api/v1/apps) and OAuth authorization/tokenexchange, layered on
@dwk/oauth's existing RFC 8414/7591 building blocksrather than reinventing OAuth.
GET /api/v1/accounts/verify_credentials(identify as the one actor thisdeployment serves).
GET /api/v1/timelines/homeand/or/api/v1/notifications— read-only,backed by the same DO storage
activitypub_list_inboxalready reads.(micropub already covers publish), streaming, multi-account support (v1 is
one actor per deployment, same as the rest of
@dwk/activitypub), or anyMastodon feature beyond what's needed for read-only timeline/notification
browsing.
Open design questions to resolve before implementation:
@dwk/activitypub(a newclient-api.tsmodule +routes) or as a separate package? A separate package keeps
@dwk/activitypubfree of client-API-specific vocabulary/response shapesthat have nothing to do with federation, matching the "confinement" spirit
of the composition contract — but it would need to reach into
@dwk/activitypub's DO the same way@dwk/mcp's tool contribution does.@dwk/indieauth/@dwk/oauth, or does the Mastodon appOAuth flow's specific quirks (dynamic client registration via
/api/v1/appspredates RFC 7591 and isn't quite the same shape) need itsown thin adapter over the shared primitives?
Status,Account,Notificationentities) is required for real clients to render correctlywithout erroring on missing fields — needs testing against at least one
real client (Pixelfed's own, plus ideally a generic Mastodon client like
Tusky) rather than guessing from the API docs alone.
Alternatives considered
notifications" requires either a custom MCP-connected agent or reading the
DO directly — not the experience a typical fediverse user expects.
@dwk/microsub(IndieWeb's own unified-inboxstandard) instead of the Mastodon Client API: technically cleaner (stays
inside IndieWeb standards, no foreign-platform API to maintain), but
doesn't satisfy the actual ask here — a Microsub reader isn't "the Pixelfed
client of your choice."
Additional context
spec/fediverse-interop.md(non-goals section, "Platform client APIs")spec/packages/mcp.md(the currentactivitypub_list_inboxread path)conformance/pixelfed-qa.md— the manual run where this gap surfacedFediverse platform interop: Lemmy, Pixelfed, and arbitrary platforms from the single actor (tracking) #273 is about S2S federation with other platforms; this is about C2S
client access to this actor's own data.