Repository navigation
feat: add publish-only ActivityPub federation - #31
Merged
Merged
Conversation
Lets Mastodon-like clients follow the site as a single site-wide actor and receive new links, quotes, and images as Create(Note) activities. Opt-in via activitypub.enabled config; no inbound interactions beyond Follow/Undo are handled, since the site only publishes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Adds an icon (avatar), defaulting to https://github.com/websages.png, and manuallyApprovesFollowers to the actor document so federated profiles show useful information beyond username/name/summary. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
stephenyeargin
marked this pull request as ready for review
August 23, 2026 01:00
stephenyeargin
requested review from
stahnma
and
a lite review from Copilot
and removed request for
stahnma
August 23, 2026 01:06
- Assign the inserted row's ID onto the struct before building a Note,
instead of relying on Store implementations mutating the passed
struct (irclink.go, quote.go, dailycat.go)
- Fix broken HTML permalink link on /image/{id}: use image.URL instead
of image.Link, which isn't guaranteed to be a URL (e.g. the daily
kitten's Link is a credit label, not a link)
- Include image count in the ActivityPub outbox's totalItems, via a
new Store.CountImages method
- Document the /image/{id} permalink in the OpenAPI spec
- Wire ActivityPub publishing into the REST API create endpoints
(apiV1CreateLink, apiV1CreateQuote), which were missing the same
federation hook already present on the IRC-facing form endpoints
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Add explicit numbered steps (public HTTPS baseurl requirement, config key, restart, discovery) instead of just showing the config snippet. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Member
|
@stephenyeargin should I just merge this? Is this just you can follow each person in a mastadon client? |
stephenyeargin
commented
Sep 9, 2026
| | `TUMBLE_COPYRIGHT` | RSS copyright field | omitted | | ||
| | `TUMBLE_ACTIVITYPUB_ENABLED` | Enable ActivityPub federation | `false` | | ||
| | `TUMBLE_ACTIVITYPUB_ACTOR_NAME` | Site actor's `preferredUsername` | `tumble` | | ||
| | `TUMBLE_ACTIVITYPUB_AVATAR_URL` | Site actor's `icon` (avatar) image URL | `https://github.com/websages.png` | |
Member
Author
There was a problem hiding this comment.
These need to be set
Member
Author
Correct. |
Member
|
@stephenyeargin wait, so one account for the whole site? I'm confused as to what this feature does |
Member
Author
|
It makes it so you can follow |
Member
Author
|
Think RSS-via-Mastodon. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Create(Note)activities to followers, delivered via signed HTTP requests with retry/backoffFollow(→Accept) andUndo(Follow), since this is publish-only — no replies, likes, or boostsactivitypub.enabledin config (default off); runs in-process (delivery sweep is a goroutine in the existing scheduler, not a separate service)How to enable
baseurlto the site's real, public HTTPS URL (required for real federation — Mastodon-like servers won't federate withlocalhostor non-HTTPS hosts).activitypub.enabled: true(TUMBLE_ACTIVITYPUB_ENABLED=true). Optionally setactivitypub.actor_nameandactivitypub.avatar_url(defaults tohttps://github.com/websages.png).@<actor_name>@<host>. See the README's "ActivityPub Federation" section for full details.Details
internal/activitypubpackage: actor/webfinger/collection documents, RSA key management, HTTP Signature signing (go-fed/httpsig) and verification, Note builders for links/quotes/images, delivery queue with exponential backoffAutoMigrate:activitypub_key,activitypub_follower,activitypub_delivery(+ reference SQL migrations)/.well-known/webfinger,/activitypub/actor,/activitypub/followers,/activitypub/outbox,/activitypub/inbox, and a new/image/{id}permalinkAccept: application/activity+jsoncontent negotiation added to/link/{id},/quote/{id},/image/{id}icon(avatar) andmanuallyApprovesFollowers: false/api/v1/links,/api/v1/quotes) create pathsReview
/image/{id}route, and three spots relying onStoreimplementations mutating a passed struct rather than using the returned ID)Test plan
make buildmake test(all packages pass, including newinternal/activitypubsuite covering key generation, actor/webfinger/note shape, delivery dedup, signing↔verification round-trip, and retry/backoff)make test-api🤖 Generated with Claude Code