Read-only ActivityPub → atproto bridge for the threadiverse using Coves lexicons

Task 07: vote aggregation side channel — aggregator, XRPC, seeding master

Lemmy Like/Dislike/Undo activities become bridge-side aggregate counts served over social.coves.bridge.getVoteAggregates (lexicon published under lexicons/social/coves/bridge/). Votes never become PDS records (PLAN decision 7). - Migration 010: vote_aggregates (+ seeded_* baseline columns so re-seeding is idempotent and never clobbers live votes) and append-only vote_events (activity_id dedupe, ≤1 live row per voter+subject, recompute-in-tx under the aggregate row lock). - internal/votes.Aggregator fills the task-06 ingest.VoteAggregator seam: latest-state counting (flips, undos, replays), id-targeted retraction, malformed/unknown/unbridged votes drop as processed no-ops (queue ordering keys can never wedge on vote noise). - Authority binding from review: announced votes require subject ∈ announcing community (post mapping DID / comment reply.root DID — not SameAuthority, since Lemmy hosts post objects on the author's instance); bare Undo{vote} binds inner actor to signer like bare Delete. - XRPC: ≤100 uris, at-uri validation, unknown uris omitted, request-order response, Cache-Control, per-IP limiter (fail-closed 50k cap, throttled sweep). - Optional Lemmy API count seeding during backfill (SEED_COUNTS_FROM_API, SSRF-guarded, presence-checked decode so a wrong-shape 200 cannot zero-clobber a baseline). Reviewed by 6 reviewers (4 Claude specialty + codex gpt-5.5 + security; Gemini perm-denied, GLM watchdog-killed); 13 fixes + ~20 regression tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>