feat(post): add Coves-native post permalink page with batch hydration master
Build the post permalink route on the Coves API, replacing the legacy Lemmy single-post path. Posts hydrate through the batch getPosts endpoint (1–25 URIs, order-preserving); the URI is resolved from the explicit ?uri= param, the feed cache, or a DID-based fallback built after one handle→DID hop so the path survives community renames. Hardens the data flow surfaced in review: the getPosts response is a PostViewUnion (a hydrated post or a notFound/blocked sentinel), the loader distinguishes and logs each unavailable reason instead of flattening to a silent "removed", and the sidebar CommunityCard accepts the post's embedded CommunityRef. Changes: - post: new /c/[handle]/post/[rkey] loader + page, sentinel-aware via isHydratedPost; logs URI + discriminator when a post is unavailable - api: getPosts batch endpoint; getPost wrapper throws on empty/non-array responses and returns PostViewUnion (no silent undefined) - types: PostViewUnion (PostView | NotFoundPost | BlockedPost); flag-negative isHydratedPost; BlockedPost carries blockedBy/author - xrpc: throw on nullish array params so positional responses can't desync - feed: model post-page state as a discriminated union (post | unavailable) - community: CommunityCard accepts CommunityRef, gating subscribe/mod/stats behind a hydrated-view guard - post-form: emit social.coves.embed.external with its $type + external wrapper so external link embeds aren't silently dropped - session: log identity-validation failures (bad DID/handle) at error, keep recoverable avatar rejects at warn - tests: loader branch coverage, getPost contract, xrpc nullish guard, isHydratedPost, session log levels Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>