Start generated ActivityPub queue worker #205

Closed
opened 2026-06-26 13:46:15 -05:00 by erik · 4 comments
Owner

Summary

Generated Slugkit sites configure Fedify with manuallyStartQueue: true but do not start the ActivityPub queue worker during runtime startup. Incoming signed inbox activities such as Mastodon Follow requests can be accepted into the queue but never processed, leaving local follower state empty and preventing expected Accept delivery.

This was confirmed and fixed first in the generated slugkit.com site.

Verified slugkit.com findings

  • Original production image: evcraddock/slugkit-com:0.1.1.
  • Original deployment had ACTIVITYPUB_ENABLED=false; ActivityPub discovery still worked, but the app did not process follows into local state.
  • After deploying evcraddock/slugkit-com:0.1.2 with ACTIVITYPUB_ENABLED=true, Mastodon follow verification succeeded.
  • Production logs showed:
    • request reached /users/slug/inbox,
    • ActivityPub Follow accepted and follower saved,
    • ActivityPub Follow Accept queued.
  • Production DB then contained follower @evcraddock@mastodon.online.
  • https://slugkit.com/users/slug/followers returned totalItems: 1.
  • https://slugkit.com/feed rendered Followers 1.

Steps to reproduce

  1. Generate or run a Slugkit site from the template with ActivityPub enabled and a configured local actor.
  2. Follow the generated site's actor from Mastodon.
  3. Inspect the site's followers collection and feed/profile follower count.

Expected behavior

  • Valid signed Follow activities are processed by the generated site.
  • The follower is persisted.
  • The site sends or queues the expected ActivityPub Accept response.
  • The followers collection and public feed/profile counts reflect the accepted follower.

Actual behavior

  • Without a queue worker, Fedify can enqueue incoming inbox activities without executing the registered inbox handlers.
  • The follower does not appear in the generated site's followers table or followers collection.
  • The public feed/profile follower count remains 0.

Implementation notes from slugkit.com

  • Add generated-runtime support to start the Fedify queue worker during app startup.
  • Ensure the worker uses the same default queue instance that ActivityPub route registration uses.
  • Add route-level ActivityPub request logging for federation routes.
  • Add follow-handler logging around follower persistence and Accept queueing.
  • Add regression coverage proving a signed queued Follow is processed into a follower row and queues an Accept.
  • Keep the deployment/runtime requirement clear: production federation needs ACTIVITYPUB_ENABLED=true.

Acceptance criteria

  • Generated Slugkit runtime starts the Fedify ActivityPub queue worker when running the app.
  • The generated app uses one shared default queue for route enqueueing and queue-worker processing.
  • A regression test covers valid signed Follow processing through the generated app/runtime path, including follower persistence and Accept queueing.
  • ActivityPub route and follow-handler diagnostics are added or preserved so future inbox failures are visible in production logs.
  • Generated-site docs/config clarify that production federation requires ACTIVITYPUB_ENABLED=true.
  • A generated site can accept a Mastodon follow and reflect it in /users/<actor>/followers and the feed/profile follower count.
## Summary Generated Slugkit sites configure Fedify with `manuallyStartQueue: true` but do not start the ActivityPub queue worker during runtime startup. Incoming signed inbox activities such as Mastodon `Follow` requests can be accepted into the queue but never processed, leaving local follower state empty and preventing expected `Accept` delivery. This was confirmed and fixed first in the generated `slugkit.com` site. ## Verified slugkit.com findings - Original production image: `evcraddock/slugkit-com:0.1.1`. - Original deployment had `ACTIVITYPUB_ENABLED=false`; ActivityPub discovery still worked, but the app did not process follows into local state. - After deploying `evcraddock/slugkit-com:0.1.2` with `ACTIVITYPUB_ENABLED=true`, Mastodon follow verification succeeded. - Production logs showed: - request reached `/users/slug/inbox`, - `ActivityPub Follow accepted and follower saved`, - `ActivityPub Follow Accept queued`. - Production DB then contained follower `@evcraddock@mastodon.online`. - `https://slugkit.com/users/slug/followers` returned `totalItems: 1`. - `https://slugkit.com/feed` rendered `Followers 1`. ## Steps to reproduce 1. Generate or run a Slugkit site from the template with ActivityPub enabled and a configured local actor. 2. Follow the generated site's actor from Mastodon. 3. Inspect the site's followers collection and feed/profile follower count. ## Expected behavior - Valid signed `Follow` activities are processed by the generated site. - The follower is persisted. - The site sends or queues the expected ActivityPub `Accept` response. - The followers collection and public feed/profile counts reflect the accepted follower. ## Actual behavior - Without a queue worker, Fedify can enqueue incoming inbox activities without executing the registered inbox handlers. - The follower does not appear in the generated site's followers table or followers collection. - The public feed/profile follower count remains `0`. ## Implementation notes from slugkit.com - Add generated-runtime support to start the Fedify queue worker during app startup. - Ensure the worker uses the same default queue instance that ActivityPub route registration uses. - Add route-level ActivityPub request logging for federation routes. - Add follow-handler logging around follower persistence and `Accept` queueing. - Add regression coverage proving a signed queued `Follow` is processed into a follower row and queues an `Accept`. - Keep the deployment/runtime requirement clear: production federation needs `ACTIVITYPUB_ENABLED=true`. ## Acceptance criteria - [ ] Generated Slugkit runtime starts the Fedify ActivityPub queue worker when running the app. - [ ] The generated app uses one shared default queue for route enqueueing and queue-worker processing. - [ ] A regression test covers valid signed `Follow` processing through the generated app/runtime path, including follower persistence and `Accept` queueing. - [ ] ActivityPub route and follow-handler diagnostics are added or preserved so future inbox failures are visible in production logs. - [ ] Generated-site docs/config clarify that production federation requires `ACTIVITYPUB_ENABLED=true`. - [ ] A generated site can accept a Mastodon follow and reflect it in `/users/<actor>/followers` and the feed/profile follower count.
Author
Owner

Synced from todu comment by @todu on 2026-06-26T18:42:28.932Z

Context from slugkit.com investigation

This came from slugkit.com task task-becaf72b (“Troubleshoot pending Mastodon follow”). The generated site is deployed in k3s namespace slugkit-com, pod slugkit-com-6ffff6d654-n8mvs, image evcraddock/slugkit-com:0.1.1.

Observed production config from kubectl -n slugkit-com get deploy slugkit-com -o yaml:

  • ACTIVITYPUB_ENABLED=false
  • ACTIVITYPUB_PUBLIC_ORIGIN=https://slugkit.com
  • DATABASE_PATH=/app/data/slugkit.sqlite
  • Node env is production.

Important behavior: even with ACTIVITYPUB_ENABLED=false, ActivityPub discovery still appears reachable from outside: WebFinger and actor document resolve, and the actor advertises inbox/followers URLs. The current runtime config validation only uses enabled for startup validation; registerActivityPubRoutes() still registers federation routes regardless. A template fix should decide whether this is intended. If disabled should mean no federation, discovery/inbox should likely not be exposed. If discovery is intentionally allowed while disabled, the semantics should be documented and inbox handling/logging should make that obvious.

Hypothesis needing implementation/regression coverage: src/federation/routes.ts creates Fedify with manuallyStartQueue: true, and incoming inbox activities are enqueued by Fedify. The generated runtime currently creates the app in src/index.ts but does not start federation.startQueue(...). If true, a Mastodon Follow can be accepted/enqueued at the HTTP layer but never processed by handleActivityPubFollow(), so no row is written to followers and no Accept is delivered.

Relevant existing code paths in generated site:

  • src/app.ts registers ActivityPub routes via registerActivityPubRoutes().
  • src/federation/routes.ts calls createFederation({ manuallyStartQueue: true, queue: ... }) and registers inbox listeners for Follow, Undo, Accept, Reject, Create, Like, and Announce.
  • src/federation/follow.ts already auto-accepts valid signed Follow activities targeting the local actor by calling upsertActivityPubFollower() and context.sendActivity(new Accept(...)).
  • src/followers/followers.ts persists follower rows and powers the followers collection.

Logs checked from kubectl -n slugkit-com logs slugkit-com-6ffff6d654-n8mvs --since=48h --tail=300 showed startup/auth/API logs but no ActivityPub/federation/inbox logs. A search for activitypub|inbox|follow|followers|fedify|error|warn|POST|/users/slug|/inbox returned no matches. The app currently lacks useful federation request/handler logging, so production cannot confirm whether Mastodon POSTs reached the app without ingress/proxy logs.

Suggested implementation direction:

  1. Add generated-runtime support to start the Fedify queue worker when federation should process activities, likely in src/index.ts or app startup code, using the same default queue instance passed to route registration.
  2. Add regression coverage that a signed Follow through the generated/federation runtime path is processed, persists a follower, and queues/sends Accept.
  3. Add ActivityPub inbox diagnostics/logging around route receipt, handler success, handler failures, follower persistence, and Accept delivery/queueing.
  4. Clarify/fix ACTIVITYPUB_ENABLED=false behavior: either do not expose discovery/inbox routes when disabled, or explicitly document that disabled only skips production startup validation/delivery behavior.
  5. Ensure slugkit.com can consume the fix from the template rather than carrying a one-off local patch.
_Synced from todu comment by @todu on 2026-06-26T18:42:28.932Z_ ## Context from slugkit.com investigation This came from slugkit.com task `task-becaf72b` (“Troubleshoot pending Mastodon follow”). The generated site is deployed in k3s namespace `slugkit-com`, pod `slugkit-com-6ffff6d654-n8mvs`, image `evcraddock/slugkit-com:0.1.1`. Observed production config from `kubectl -n slugkit-com get deploy slugkit-com -o yaml`: - `ACTIVITYPUB_ENABLED=false` - `ACTIVITYPUB_PUBLIC_ORIGIN=https://slugkit.com` - `DATABASE_PATH=/app/data/slugkit.sqlite` - Node env is production. Important behavior: even with `ACTIVITYPUB_ENABLED=false`, ActivityPub discovery still appears reachable from outside: WebFinger and actor document resolve, and the actor advertises inbox/followers URLs. The current runtime config validation only uses `enabled` for startup validation; `registerActivityPubRoutes()` still registers federation routes regardless. A template fix should decide whether this is intended. If disabled should mean no federation, discovery/inbox should likely not be exposed. If discovery is intentionally allowed while disabled, the semantics should be documented and inbox handling/logging should make that obvious. Hypothesis needing implementation/regression coverage: `src/federation/routes.ts` creates Fedify with `manuallyStartQueue: true`, and incoming inbox activities are enqueued by Fedify. The generated runtime currently creates the app in `src/index.ts` but does not start `federation.startQueue(...)`. If true, a Mastodon `Follow` can be accepted/enqueued at the HTTP layer but never processed by `handleActivityPubFollow()`, so no row is written to `followers` and no `Accept` is delivered. Relevant existing code paths in generated site: - `src/app.ts` registers ActivityPub routes via `registerActivityPubRoutes()`. - `src/federation/routes.ts` calls `createFederation({ manuallyStartQueue: true, queue: ... })` and registers inbox listeners for `Follow`, `Undo`, `Accept`, `Reject`, `Create`, `Like`, and `Announce`. - `src/federation/follow.ts` already auto-accepts valid signed `Follow` activities targeting the local actor by calling `upsertActivityPubFollower()` and `context.sendActivity(new Accept(...))`. - `src/followers/followers.ts` persists follower rows and powers the followers collection. Logs checked from `kubectl -n slugkit-com logs slugkit-com-6ffff6d654-n8mvs --since=48h --tail=300` showed startup/auth/API logs but no ActivityPub/federation/inbox logs. A search for `activitypub|inbox|follow|followers|fedify|error|warn|POST|/users/slug|/inbox` returned no matches. The app currently lacks useful federation request/handler logging, so production cannot confirm whether Mastodon POSTs reached the app without ingress/proxy logs. Suggested implementation direction: 1. Add generated-runtime support to start the Fedify queue worker when federation should process activities, likely in `src/index.ts` or app startup code, using the same default queue instance passed to route registration. 2. Add regression coverage that a signed `Follow` through the generated/federation runtime path is processed, persists a follower, and queues/sends `Accept`. 3. Add ActivityPub inbox diagnostics/logging around route receipt, handler success, handler failures, follower persistence, and `Accept` delivery/queueing. 4. Clarify/fix `ACTIVITYPUB_ENABLED=false` behavior: either do not expose discovery/inbox routes when disabled, or explicitly document that disabled only skips production startup validation/delivery behavior. 5. Ensure slugkit.com can consume the fix from the template rather than carrying a one-off local patch.
Author
Owner

Synced from todu comment by @todu on 2026-06-26T19:30:09.881Z

slugkit.com verification update

The hypothesis in this task is now confirmed by the slugkit.com production test.

Working generated-site patch was deployed in slugkit.com image evcraddock/slugkit-com:0.1.2 with ACTIVITYPUB_ENABLED=true.

Confirmed behavior after retrying the Mastodon follow:

  • POST reached /users/slug/inbox.
  • Follow handler persisted follower @evcraddock@mastodon.online.
  • The app queued the ActivityPub Accept.
  • https://slugkit.com/users/slug/followers returned totalItems: 1.
  • https://slugkit.com/feed rendered Followers 1.

The slugkit template should now port the slugkit.com changes into template/site rather than re-investigating the root cause.

_Synced from todu comment by @todu on 2026-06-26T19:30:09.881Z_ ## slugkit.com verification update The hypothesis in this task is now confirmed by the `slugkit.com` production test. Working generated-site patch was deployed in `slugkit.com` image `evcraddock/slugkit-com:0.1.2` with `ACTIVITYPUB_ENABLED=true`. Confirmed behavior after retrying the Mastodon follow: - POST reached `/users/slug/inbox`. - Follow handler persisted follower `@evcraddock@mastodon.online`. - The app queued the ActivityPub `Accept`. - `https://slugkit.com/users/slug/followers` returned `totalItems: 1`. - `https://slugkit.com/feed` rendered `Followers 1`. The slugkit template should now port the slugkit.com changes into `template/site` rather than re-investigating the root cause.
Author
Owner

Synced from todu comment by @todu on 2026-06-26T20:30:30.794Z

PR review: approved

PR: #206

Summary

Reviewed the PR against the task acceptance criteria. The change starts the generated ActivityPub queue worker when ACTIVITYPUB_ENABLED=true, keeps route enqueueing and worker processing on the same queue, adds route/follow diagnostics, documents the production federation requirement, and adds regression coverage for queued signed Follow handling through the generated app/runtime path.

Acceptance criteria

  • Generated runtime starts the Fedify ActivityPub queue worker — met.
  • Generated app uses one shared default queue — met.
  • Regression test covers signed queued Follow processing, follower persistence, and Accept queueing — met.
  • ActivityPub route/follow diagnostics are added — met.
  • Generated-site docs/config clarify ACTIVITYPUB_ENABLED=true is required for production federation — met.
  • Generated site can accept a Mastodon follow and reflect follower counts — met by regression coverage and existing slugkit.com production verification.

Blocking issues: 0
Warnings: 0

Verdict: approved. CI is green.

_Synced from todu comment by @todu on 2026-06-26T20:30:30.794Z_ ## PR review: approved PR: https://forge.caradoc.com/erik/slugkit/pulls/206 ### Summary Reviewed the PR against the task acceptance criteria. The change starts the generated ActivityPub queue worker when `ACTIVITYPUB_ENABLED=true`, keeps route enqueueing and worker processing on the same queue, adds route/follow diagnostics, documents the production federation requirement, and adds regression coverage for queued signed `Follow` handling through the generated app/runtime path. ### Acceptance criteria - [x] Generated runtime starts the Fedify ActivityPub queue worker — met. - [x] Generated app uses one shared default queue — met. - [x] Regression test covers signed queued `Follow` processing, follower persistence, and `Accept` queueing — met. - [x] ActivityPub route/follow diagnostics are added — met. - [x] Generated-site docs/config clarify `ACTIVITYPUB_ENABLED=true` is required for production federation — met. - [x] Generated site can accept a Mastodon follow and reflect follower counts — met by regression coverage and existing slugkit.com production verification. Blocking issues: 0 Warnings: 0 Verdict: approved. CI is green.
erik 2026-06-26 15:37:31 -05:00
Author
Owner

Synced from todu comment by @todu on 2026-06-26T20:32:29.365Z

Closing summary

PR #206 was reviewed, CI passed, and the PR was merged into main.

Acceptance criteria were satisfied:

  • Generated runtime starts the Fedify ActivityPub queue worker when ACTIVITYPUB_ENABLED=true.
  • Generated app route enqueueing and queue-worker processing share the same queue path.
  • Regression coverage proves a signed queued Follow is processed through the generated app/runtime path, persists a follower, and queues an Accept.
  • ActivityPub route and follow-handler diagnostics were added for production visibility.
  • Generated-site README and .env.example clarify that production federation requires ACTIVITYPUB_ENABLED=true.
  • slugkit.com production verification plus regression coverage demonstrate accepted follows appear in followers/feed counts.

Local main was fast-forwarded after merge and the feature branch was cleaned up.

_Synced from todu comment by @todu on 2026-06-26T20:32:29.365Z_ ## Closing summary PR https://forge.caradoc.com/erik/slugkit/pulls/206 was reviewed, CI passed, and the PR was merged into `main`. Acceptance criteria were satisfied: - Generated runtime starts the Fedify ActivityPub queue worker when `ACTIVITYPUB_ENABLED=true`. - Generated app route enqueueing and queue-worker processing share the same queue path. - Regression coverage proves a signed queued `Follow` is processed through the generated app/runtime path, persists a follower, and queues an `Accept`. - ActivityPub route and follow-handler diagnostics were added for production visibility. - Generated-site README and `.env.example` clarify that production federation requires `ACTIVITYPUB_ENABLED=true`. - slugkit.com production verification plus regression coverage demonstrate accepted follows appear in followers/feed counts. Local `main` was fast-forwarded after merge and the feature branch was cleaned up.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
erik/slugkit#205
No description provided.