Skip to content

F.6: Lemmy bundle — federated link aggregator#15

Open
kh0pper wants to merge 1 commit intof5-pixelfed-bundlefrom
f6-lemmy-bundle
Open

F.6: Lemmy bundle — federated link aggregator#15
kh0pper wants to merge 1 commit intof5-pixelfed-bundlefrom
f6-lemmy-bundle

Conversation

@kh0pper
Copy link
Copy Markdown
Owner

@kh0pper kh0pper commented Apr 12, 2026

Summary

Stacked on F.5 (Pixelfed). First ActivityPub app on this track that isn't Mastodon-compatible — Lemmy has its own v3 REST API, adding a fresh API shape to the bundle roster.

  • dessalines/lemmy:0.19 + dessalines/lemmy-ui:0.19 + postgres:16 + asonix/pictrs:0.5 (4 containers). Lemmy-UI proxies /api/v3/* to lemmy:8536 internally, so a single Caddy federation site to lemmy-ui:1234 is enough.
  • 14 MCP tools per the federated-social verb taxonomy: lemmy_status, lemmy_list_communities, follow/unfollow, lemmy_post (link or body), lemmy_comment (threaded), lemmy_feed (Subscribed/Local/All), lemmy_search, inline lemmy_block_user/lemmy_block_community, queued admin lemmy_block_instance/lemmy_defederate, admin-read lemmy_review_reports, lemmy_media_prune.
  • Community-scoped federation — following a community on a remote instance pulls all its posts + comments to the local server. Disk growth is driven by pict-rs cache (5-20 GB within weeks on active instances); lemmy_media_prune forces aggressive purge.
  • Hardware gate: min_ram_mb=1000, recommended=2000. Pi-friendly when Lemmy is the only federated bundle on the host.
  • Consent text (EN/ES) covers federation reach, pict-rs cache growth, community-scoped federation risk, and defederation risk from major hubs on unaddressed reports.

Test plan

  • node --check on all JS files
  • bash -n on shell scripts
  • MCP server boots via createLemmyServer() with no env set
  • docker compose config parses with required env set
  • JSON parse on manifest, package, registry
  • npm run check passes
  • End-to-end install (deferred to roll-out QA)
  • Queued admin moderation end-to-end (needs F.11 panel UI)

Integration notes

  • First bundle on this track with a non-Mastodon-compatible API. resolveCommunity() + resolvePerson() share pattern with F.1/F.5 resolveAccount; decision to hoist into servers/shared/fediverse-resolvers.js is deferred to F.7 Mastodon.
  • No storage-translator involvement in this round — pict-rs uses on-disk sled. S3-backed pict-rs is a 0.5+ feature we can wire in a follow-up.
  • dessalines/lemmy:0.19 + dessalines/lemmy-ui:0.19 float within 0.19.x. CVE feed checked at implementation time; will re-verify before merge.

Rollout position

  • F.0 → F.5 shipped
  • F.6 (this PR)
  • Next: F.7 Mastodon → F.8 PeerTube → F.11 identity attestation → F.12 cross-app bridging

🤖 Generated with Claude Code

Stacked on F.5 (Pixelfed). First ActivityPub app on this track that
isn't Mastodon-compatible — Lemmy has its own v3 REST API at /api/v3/,
so this adds a fresh API shape to the bundle roster. Federation is
community-scoped rather than user-scoped, which changes the moderation
model slightly (admin block_instance + defederate carry heavier blast
radius because they affect every subscribed community on that instance).

Bundle (bundles/lemmy/):

- manifest.json  consent_required with EN/ES text covering federation
                 reach, pict-rs cache growth (5-20 GB within weeks),
                 community-scoped federation pulling heavy remote content,
                 and legal responsibility for illegal content with
                 defederation risk from major hubs. min_ram_mb=1000,
                 recommended=2000 — Pi-friendly when Lemmy is the only
                 federated bundle on the host.
- docker-compose.yml  dessalines/lemmy:0.19 + dessalines/lemmy-ui:0.19 +
                 postgres:16-alpine + asonix/pictrs:0.5. Lemmy reads env
                 vars but the compose entrypoint writes a /config/config.hjson
                 file deterministically on each start from env — lemmy-ui
                 proxies /api/v3/* to lemmy:8536, so a single Caddy
                 federation site is enough. mem_limits: lemmy=768m,
                 lemmy-ui=256m, postgres=512m, pictrs=512m. pict-rs
                 tuning env vars (GIF max frames/dimensions, video codec)
                 match current defaults from the Lemmy ops docs.
- server/server.js  14 MCP tools per the federated-social verb taxonomy:
                 lemmy_status, lemmy_list_communities, lemmy_follow_community,
                 lemmy_unfollow_community, lemmy_post (title + url or body),
                 lemmy_comment (threaded replies), lemmy_feed
                 (Subscribed/Local/All + sort), lemmy_search,
                 lemmy_block_user, lemmy_block_community (inline,
                 rate-limited), lemmy_block_instance, lemmy_defederate
                 (QUEUED, admin), lemmy_review_reports (read-only),
                 lemmy_media_prune. resolveCommunity() and resolvePerson()
                 helpers handle "name@server" → id resolution via the
                 search API. All z.string() fields bounded. loadSharedDeps()
                 pattern from F.1. Works with no env set and boots clean.
- server/index.js  stdio transport.
- panel/lemmy.js + panel/routes.js  Nest panel: status + local
                 communities + hot posts. XSS-safe. API routes serve
                 /api/lemmy/{status,communities,posts}.
- skills/lemmy.md  setup wizard (no CLI admin bootstrap — web wizard
                 replaces the admin_pending placeholder), JWT login
                 recipe, follow-community / post / comment / search
                 workflows, moderation ladder, troubleshooting
                 (federation, pict-rs, admin permissions).
- scripts/post-install.sh  waits for both lemmy + lemmy-ui health,
                 verifies federation network, prints Caddy + setup
                 wizard + JWT login next steps.
- scripts/backup.sh  pg_dump + pict-rs sled DB + media files tar.
                 Note that federation identity lives in the database
                 (instance private key) — restoring to a different
                 hostname breaks federation.
- package.json  MCP + zod deps.

Integrations with shipped F-series:

- F.0 rate limiter  content + moderation verbs wrapped via the shared
  token-bucket wrapper. Read-only status / review_reports uncapped.
- F.0 hardware gate  min/recommended RAM + disk per manifest schema.
- F.1 federated-social category wiring  already present.
- No storage-translator involvement — pict-rs uses its own sled DB for
  metadata and on-disk files; S3-backing pict-rs is a 0.5+ feature we
  can wire via translator in a follow-up.

Human-in-the-loop moderation:

- Inline (rate-limited): lemmy_block_user, lemmy_block_community
  (user-scoped; hides content from the authenticated user's view).
- Queued (operator confirms in Nest within 72h): lemmy_block_instance,
  lemmy_defederate. Admin-scoped; these affect every subscribed
  community on the target instance. Same moderation_actions table +
  Crow notification flow as F.1/F.4/F.5.

API shape note:

- Lemmy v3 uses `Authorization: Bearer <jwt>` (the older `?auth=` query
  param is still supported but deprecated). Helper code uses Bearer.
- resolveCommunity() and resolvePerson() share a pattern with F.1/F.5's
  account resolution; waiting until F.7 Mastodon to decide whether to
  hoist into servers/shared/fediverse-resolvers.js.

Registry / discovery surface:

- registry/add-ons.json  entry before developer-kit.
- skills/superpowers.md  trigger row (EN+ES: lemmy, link aggregator,
  reddit alternative, subscribe community, post link, fediverse
  discussion, upvote).
- CLAUDE.md  Skills Reference entry after pixelfed.md.

Verified:

- node --check on all JS files
- bash -n on shell scripts
- MCP server boots via createLemmyServer() with no env set
- docker compose config parses with required env set
- JSON parse on manifest, package, registry
- npm run check passes

Next:

- F.7 Mastodon (flagship AP, 3 GB min — heaviest small-AP)
- F.8 PeerTube (video, needs S3 + transcoding policy)
- F.11 identity attestation, F.12 cross-app bridging
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant