Skip to content

fix: exclude inaccessible posts from channel digest generation#3941

Merged
capJavert merged 1 commit into
mainfrom
fix-channel-digest-private-posts
Jun 11, 2026
Merged

fix: exclude inaccessible posts from channel digest generation#3941
capJavert merged 1 commit into
mainfrom
fix-channel-digest-private-posts

Conversation

@capJavert

Copy link
Copy Markdown
Contributor

Problem

Topical channel digests (e.g. the security_digest post igABDFgDV) were generated with Read more links pointing to posts readers cannot access — e.g. yGw6q0Dsw, a private unknown-source article whose only share lives in a private squad.

Two gaps in src/common/channelDigest/generate.ts:

  1. findDigestPosts queried api.post directly with only deleted = false + channel match, bypassing all accessibility guarantees (visible, banned, showOnFeed, private) that the feed inventory provides elsewhere (feed.post_metadata / feed.inventory exclude these at the view level — the digest path never goes through them).
  2. remapUnknownSourcePostIds kept the private post id when no public SharePost fallback existed (id = fallbackId ?? post.id), so the inaccessible post id ended up in the generated markdown.

Fix

  • findDigestPosts now requires visible = true, banned = false, showOnFeed = true, and private = false — except sourceId = 'unknown' posts, which stay in the candidate pool only so they can be remapped to an accessible public share post.
  • remapUnknownSourcePostIds now drops unknown-source posts that have no public share fallback instead of keeping their private id.

The accessibility predicate mirrors the existing one in fetchPublicShareFallbackPostIds (channelHighlight/queries.ts).

Tests

  • Updated the previous should keep the unknown-source post id when no public SharePost exists test to assert the post is now dropped (digest returns null when nothing remains).
  • Added a regression test for the exact production case: unknown-source article whose only share is in a private squad → dropped.
  • Added a test asserting private/banned/invisible/showOnFeed=false posts are excluded from candidates while accessible ones pass.

Channel digests could link to private posts readers cannot access:

- findDigestPosts queried api.post directly with only deleted=false,
  bypassing the visible/banned/showOnFeed/private guarantees that feed
  inventory provides. Private unknown-source posts (squad-shared
  external URLs) entered the candidate pool via contentMeta.channels.
- remapUnknownSourcePostIds kept the original private post id when no
  public SharePost fallback existed, producing broken Read more links
  in the generated digest markdown.

Now candidates must be visible, not banned, shown on feed and public.
Unknown-source posts are kept as candidates only so they can be
remapped to a public share post, and are dropped when no accessible
fallback exists.
@pulumi

pulumi Bot commented Jun 11, 2026

Copy link
Copy Markdown

🍹 The Update (preview) for dailydotdev/api/prod (at 24d7630) was successful.

✨ Neo Code Review

Routine image rollout (commit `9ce11899` → `c17b718a`) that fixes channel digests to suppress private/banned/hidden posts and unreachable unknown-source articles. Includes DB and Clickhouse migration jobs; a migration failure would be the only meaningful risk. ✅ Low Risk

This deployment ships a bug fix to the channel digest generation logic. The code change adds SQL filters to findDigestPosts to exclude private, banned, invisible (visible = false), and feed-hidden (showOnFeed = false) posts from digest candidates. It also adds a guard in remapUnknownSourcePostIds to drop unknown-source posts that have no accessible public share fallback, preventing digest emails from linking to content readers cannot access.

The migration jobs rotating from 9ce11899c17b718a indicate there are accompanying database migrations in this release. All deployments and cron jobs are simply rolling to the new image tag.

🔵 Info — Both a DB migration job and a Clickhouse migration job are being replaced with new versions. If either migration fails, the new pods will be running code that may expect schema changes that haven't landed yet. The migration jobs run as one-shot Kubernetes Jobs (restartPolicy: Never), so failed runs will not auto-retry.

Resource Changes

    Name                                                    Type                           Operation
~   vpc-native-clean-old-notifications-cron                 kubernetes:batch/v1:CronJob    update
~   vpc-native-clean-gifted-plus-cron                       kubernetes:batch/v1:CronJob    update
~   vpc-native-update-trending-cron                         kubernetes:batch/v1:CronJob    update
~   vpc-native-validate-active-users-cron                   kubernetes:batch/v1:CronJob    update
~   vpc-native-user-profile-updated-sync-cron               kubernetes:batch/v1:CronJob    update
-   vpc-native-api-clickhouse-migration-9ce11899            kubernetes:batch/v1:Job        delete
~   vpc-native-sync-subscription-with-cio-cron              kubernetes:batch/v1:CronJob    update
~   vpc-native-update-tag-materialized-views-cron           kubernetes:batch/v1:CronJob    update
~   vpc-native-clean-expired-better-auth-sessions-cron      kubernetes:batch/v1:CronJob    update
~   vpc-native-update-tags-str-cron                         kubernetes:batch/v1:CronJob    update
~   vpc-native-user-profile-analytics-clickhouse-cron       kubernetes:batch/v1:CronJob    update
+   vpc-native-api-db-migration-c17b718a                    kubernetes:batch/v1:Job        create
~   vpc-native-generic-referral-reminder-cron               kubernetes:batch/v1:CronJob    update
~   vpc-native-clean-zombie-user-companies-cron             kubernetes:batch/v1:CronJob    update
~   vpc-native-clean-channel-highlights-cron                kubernetes:batch/v1:CronJob    update
~   vpc-native-deployment                                   kubernetes:apps/v1:Deployment  update
+   vpc-native-api-clickhouse-migration-c17b718a            kubernetes:batch/v1:Job        create
-   vpc-native-api-db-migration-9ce11899                    kubernetes:batch/v1:Job        delete
~   vpc-native-ws-deployment                                kubernetes:apps/v1:Deployment  update
~   vpc-native-materialize-yearly-best-post-archives-cron   kubernetes:batch/v1:CronJob    update
~   vpc-native-personalized-digest-cron                     kubernetes:batch/v1:CronJob    update
~   vpc-native-materialize-monthly-best-post-archives-cron  kubernetes:batch/v1:CronJob    update
~   vpc-native-bg-deployment                                kubernetes:apps/v1:Deployment  update
~   vpc-native-channel-digests-cron                         kubernetes:batch/v1:CronJob    update
~   vpc-native-post-analytics-clickhouse-cron               kubernetes:batch/v1:CronJob    update
~   vpc-native-generate-search-invites-cron                 kubernetes:batch/v1:CronJob    update
~   vpc-native-temporal-deployment                          kubernetes:apps/v1:Deployment  update
~   vpc-native-post-lifecycle-state-clickhouse-cron         kubernetes:batch/v1:CronJob    update
~   vpc-native-clean-zombie-users-cron                      kubernetes:batch/v1:CronJob    update
~   vpc-native-update-highlighted-views-cron                kubernetes:batch/v1:CronJob    update
~   vpc-native-update-views-cron                            kubernetes:batch/v1:CronJob    update
~   vpc-native-channel-highlights-cron                      kubernetes:batch/v1:CronJob    update
~   vpc-native-squad-posts-analytics-refresh-cron           kubernetes:batch/v1:CronJob    update
~   vpc-native-rotate-daily-quests-cron                     kubernetes:batch/v1:CronJob    update
~   vpc-native-clean-zombie-opportunities-cron              kubernetes:batch/v1:CronJob    update
~   vpc-native-check-analytics-report-cron                  kubernetes:batch/v1:CronJob    update
~   vpc-native-calculate-top-readers-cron                   kubernetes:batch/v1:CronJob    update
~   vpc-native-hourly-notification-cron                     kubernetes:batch/v1:CronJob    update
~   vpc-native-clean-stale-user-transactions-cron           kubernetes:batch/v1:CronJob    update
~   vpc-native-user-posts-analytics-refresh-cron            kubernetes:batch/v1:CronJob    update
~   vpc-native-private-deployment                           kubernetes:apps/v1:Deployment  update
... and 13 other changes

@capJavert capJavert merged commit da30599 into main Jun 11, 2026
9 checks passed
@capJavert capJavert deleted the fix-channel-digest-private-posts branch June 11, 2026 13:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant