feat(posts): cold-load post detail via social.coves.community.post.get master
Posts opened without route extras (deep links, OS state restoration) previously showed a Not Found error. The /post/:postUri route now cold-loads the post by AT-URI: in-app navigation still passes the post via extras (fast path), while the cold path fetches it through a new PostDetailLoader widget and renders loading, success, not-found, blocked, and retryable-error states. Changes: - Add getPosts/getPost to CovesApiService for the batch endpoint social.coves.community.post.get (1-25 URIs, repeated uris= params via ListFormat.multi); malformed or unknown union entries degrade per-entry to PostGetNotFound instead of failing the whole batch, and getPost returns the result matching the requested URI - Add PostGetResult sealed union (PostGetSuccess / PostGetNotFound / PostGetBlocked) discriminated by $type with boolean fallbacks, and an open BlockedBy enum (author/community/moderator/unknown) so missing or unrecognized values show a generic message - Add PostDetailLoader with injectable fetcher, didUpdateWidget + request-id staleness guard for URI changes, catch-all error handling (no infinite spinner), 400-as-not-found mapping, and an always-available back button - Use go_router's already-decoded path parameter directly in the /post/:postUri builder (no double percent-decode); malformed deep links can no longer crash the route builder - Expose createRouter with @visibleForTesting and cover the cold path with router-level tests, mutation-checked against the double-decode bug - Test coverage: batch parsing/degradation, wire-format serialization, getPost URI matching, loader states (success, not-found, blocked variants, retry, 500-keeps-Retry, staleness, default fetcher via real AuthProvider) - 49 tests across three suites Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>