feat(ingest): declarative follow list — repo-committed communities.yaml + reconciler master
Community subscriptions can now be driven by a repo-committed YAML (FOLLOW_LIST_PATH) instead of one-at-a-time admin curls. A reconciler converges the communities table to the file on startup and every FOLLOW_LIST_INTERVAL (default 15m): entries missing from the table are subscribed, subscriptions missing from the file are unfollowed (Undo{Follow}; materialized records kept). The file is authoritative while set; git history becomes the moderation audit log and additions arrive as reviewed PRs. POST /admin/communities/reconcile forces a synchronous pass. Guard rails against mass-unfollow: a missing/malformed file fails startup; a file that breaks after startup skips sweeps; missing or null communities keys are rejected (only an explicit "communities: []" unfollows all); the desired-vs-current diff runs entirely offline against stored (preferred_username, instance) / canonical group ids, so a resolver or remote outage can never make a desired community look removed. Entries are strictly validated so a typo cannot mint a garbage did:plc. Sweeps are mutex-serialized (ticker vs admin trigger) because a racing EnsureCommunity mint can orphan a permanent DID. Consent (#nobridge) still overrides the file. The HTTP handlers' subscribe/unsubscribe bodies are extracted into transport-agnostic cores (Admin.subscribe / unsubscribeByGroupIRI) shared with the reconciler; the admin surface's behavior is unchanged and existing follow tests pass unmodified. Seed list: !comicstrips@lemmy.world, !selfhosted@lemmy.world, !linux@lemmy.ml — deliberately small, two instances, to shake out cross-instance federation on first deploy before the list grows. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>