follow-up: harden feed/thread pagination and provider validation#69
Merged
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: db0134cafb
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
- DB: migration 0016_wall_posts.sql adds wallTargetUserId FK + index on posts table - API schema: wallTargetUserId column on posts, with covering index - API routes: GET /wall/:targetWebId, GET /wall/:targetWebId/posts, POST /wall/:targetWebId, DELETE /wall/posts/:postId - Hardened with isValidWebId() regex on all handlers (injection prevention) - Single-trim of content, eq(posts.isPublic, true) on public fetch - API webhook: MAX_BATCH=500 cap, wallTarget field in body schema, 400 response type - AtBridgeIngestionService: WallPostCreate/WallPostDelete canonical intent kinds - shouldProjectCanonicalToWall() routing helper - handleCanonicalWallCreate() + handleCanonicalWallDelete() handlers - isSupportedLexiconCollection() accepts org.activitypods.* - Wall posts excluded from feed projection (shouldProjectCanonicalToFeed) - Cross-pod (remote author) posts fall back to atRecords only, no FK violation - Idempotent insert via objectUri check - Frontend: WallComposer.vue (500-char limit, Ctrl/Cmd+Enter submit) - Frontend: wallStore.ts (fetchWallPosts, postOnWall optimistic prepend, deleteWallPost) - Frontend: UserProfileView.vue — wall on user profiles, @posted handler reloads store - Frontend: ProfileView.vue — Posts tab loads own wall posts via Eden client - i18n: EN + ES keys for wall feature (wall.post, wall.empty, wall.targetNotFound, etc.) - Router: /profile/:webId route for UserProfileView
- Design system wrappers: AppTabBar, AppTopBar (large-title scroll collapse), AppSegmentedControl, AppSheet, AppActionsSheet - Composables: useHaptics, useKeyboard, useNetworkStatus, useLargeTitle (+sentinel) - Replace Vuesax MemoryButton/MemoryInput with native implementations - Migrate SettingsView to kList/kListItem/kToggle - SignInView (renamed from SingInView) + SignupView with back navigation - Konsta theme integration via useKonstaTheme; semantic token coverage in theme.css - ServiceWorker migrated to src/sw.ts (vite-plugin-pwa injectManifest) - Story rail: StoryRail + StoryViewer + StoryComposer; HomeView integration - AppIcon: add 'add' and 'image' icon variants (story composer needs) - API: stories route + story media attachments + retention service updates - atBridgeWebhook: fix events-before-declaration ordering (TS2448) - dashboard: fix all undefined CSS vars across all dashboard views Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove Vuesax from main.ts, theme.css, style.scss; delete vusax-overrides.scss (vendor chunk drops ~52 kB; 2 lightningcss build warnings eliminated) - Add placeholder PWA icons: pwa-192x192.png, pwa-512x512.png, apple-touch-icon.png (solid #6364f6 accent; swap for branded assets when available) - Update index.html with correct apple-touch-icon.png reference - Update vite.config.ts PWA manifest with all required icon sizes + maskable variant - AppTopBar: fade transition on navbar title (180ms ease opacity crossfade) via Vue <Transition> in #title slot — title no longer snaps on/off on scroll Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Story create: return 500 (not 200 null) when DB re-fetch after insert fails - Story create: distinguish known validation errors (400) from unexpected server errors (500); previously all non-MediaAttachmentError exceptions returned 400 - Story delete: return 500 instead of 400 for unexpected server errors - resolveViewedObjectIds: degrade gracefully on non-OK response (warn + empty set) instead of throwing; also guarded at listStoryGroups call site via .catch() so viewership service outage never blocks the story feed listing Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…tic tokens - PostImageGrid: add animated-gif type with poster, tap-to-play/pause overlay, prefers-reduced-motion support; 'gif' type (Klipy embeds) unchanged - ThreadView: remove redundant manual sticky header — AppTopBar already renders 'Thread' + back button via route.meta.titleKey; remove nested overflow-y-auto (App.vue main handles scroll) - PostPoll: replace ring-indigo-400 / bg-indigo-500 with semantic accent tokens - CreatePostForm: replace poll mode bg-indigo-500 with var(--color-accent) - GifPicker: replace ring-indigo-400 with --tw-ring-color semantic variable Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Push (going deeper): old view fades out (80ms) then new view slides in from right (280ms ease-out cubic) - Pop (going back): old view slides out to right (280ms ease-in quad) then previous view fades in (60ms) - Root tab switches: instant — tabs preserve context feel, no animation - Auth flows: gentle 150ms opacity fade - prefers-reduced-motion: JS forces route-fade name; CSS @media rule also collapses slides to fades as belt-and-suspenders - main gains overflow-x-hidden to clip the translateX(100%) entering view without causing horizontal scrollbar Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- UnifiedFeedList: windowed virtualisation via @tanstack/vue-virtual;
items absolutely positioned with dynamic scrollMargin derived from
feedHeaderRef → scrollEl offset so TanStack Virtual can place rows
correctly inside the shared <main> scroll container
- useResizeObserver (VueUse) recomputes scrollMargin whenever header
height changes (carousel appears/disappears, filters toggle)
- App.vue: provide('scrollEl', mainRef) + router.afterEach resets
scrollTop to 0 on push (slide-left) navigation
- useScrollRestore: new composable; saves position in beforeEach guard
(before the afterEach reset fires), restores via nextTick on mount;
module-level Map survives component remounts
- HomeView: calls useScrollRestore() so feed position survives tab
switches and thread drill-down/back
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AppIcon.types.ts — full rewrite: - AppIconName union (34 semantic names) is the single source of truth - PlatformIconDefinition maps each name to explicit ios/material/fallback sources; IconSource is a discriminated union of ionicon | material | lucide | custom - APP_ICON_REGISTRY satisfies Record<AppIconName, PlatformIconDefinition> — missing any name is a compile-time error - Lucide is used only for 'loader' (explicit choice); it is never an automatic fallback for an unmapped Ionicons name - CustomIconName covers protocol identity glyphs (verified-mark, federation, activitypub, atproto) as inline SVG paths - IconName re-exported as deprecated alias for back-compat AppIcon.vue — full rewrite: - Reads platform via resolveSource(); Material Symbols only on Android and only after font confirmed loaded via Font Loading API - Google Fonts link never injected on iOS — no network call - Dev-mode console.warn for missing IONICONS entries (loud failure) - Filled Ionicons variants bundled alongside outlines New badge components (src/design/components/): - GifBadge.vue — text badge; not an icon - VerifiedBadge.vue — colored circle wrapping AppIcon verified-mark - ProtocolBadge.vue — AT/AP pill with protocol glyph - FederationSourceBadge.vue — federation source pill (atproto/activitypods/local) - TrustBadge.vue — moderation trust level (trusted/flagged/suspended/unknown) Callsite migrations: - AppTabBar: IconName → AppIconName - ExploreView: chevron-left → back (semantic rename) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AppIcon cleanup: - federation → fediverse (three-node glyph stays; name reflects the network) - activitypub / atproto removed as AppIcon custom glyphs — they are logos, not UI symbols; moved to ProtocolLogo - lock, globe, mail added to the registry (PostVisibilityIcon uses them) src/design/logos/: - protocolLogoTypes.ts — ProtocolLogoName union (14 platforms) + NODEINFO_LOGO_MAP for future NodeInfo-based software detection - ProtocolLogo.vue — inline SVG renderer; placeholder glyphs for all platforms; replace individual SVGs with Wakest Fediverse Iconography assets when sourced src/design/components/: - PostVisibilityIcon.vue — AppIcon-based; renders nothing for public/unknown, lock for followers/unlisted, mail for direct, home for local (Apple rule: only surface visibility when it deviates from public) src/features/feed/: - postSourceMetadata.ts — resolvePostSourceMetadata(); typed PostSourceMetadata; hook for NodeInfo software detection and future application[name] field - PostMetadataRow.vue — compact (feed): timestamp·logo·[lock]; detail (thread): label + absolute time + optional client; both gated by appearanceStore - ClientAppBadge.vue — stub "via [app]"; lights up when sidecar forwards the Mastodon-compat application field src/stores/appearanceStore.ts — three persisted toggles: showProtocolBadge (on), showVisibilityIndicator (on), showClientApp (off) UnifiedFeedItem.vue — PostMetadataRow replaces hardcoded green federation-domain text block; getFederationDomain removed SettingsView.vue — Feed appearance section with three kToggle rows Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary\n- fixes remaining feed/thread pagination concerns (keyset thread cursor + pre-pagination viewed filtering)\n- hardens webhook, repost URL validation, AP actor/link preview payload limits\n- fixes local compose ActivityPods networking mismatch\n- aligns signup endpoint validation with allowed provider set\n- fixes frontend type-check API type derivation mismatch\n\n## Validation\n- bun run --cwd api typecheck\n- bun test --cwd api\n- npm run type-check (frontend)\n- npm run lint (frontend)