@atproto/bsky 0.0.250 → 0.0.253
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/dist/api/age-assurance/const.js +19 -19
- package/dist/api/age-assurance/const.js.map +1 -1
- package/dist/api/app/bsky/feed/getFeed.d.ts.map +1 -1
- package/dist/api/app/bsky/feed/getFeed.js +4 -0
- package/dist/api/app/bsky/feed/getFeed.js.map +1 -1
- package/dist/api/app/bsky/feed/searchPosts.js +5 -0
- package/dist/api/app/bsky/feed/searchPosts.js.map +1 -1
- package/dist/api/app/bsky/feed/searchPostsV2.js +5 -0
- package/dist/api/app/bsky/feed/searchPostsV2.js.map +1 -1
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +5 -0
- package/dist/config.js.map +1 -1
- package/dist/hydration/feed.d.ts +1 -2
- package/dist/hydration/feed.d.ts.map +1 -1
- package/dist/hydration/feed.js.map +1 -1
- package/dist/kws.d.ts +8 -0
- package/dist/kws.d.ts.map +1 -1
- package/dist/kws.js +53 -4
- package/dist/kws.js.map +1 -1
- package/package.json +28 -23
- package/bin/migration-create.ts +0 -46
- package/buf.gen.yaml +0 -12
- package/proto/bsky.proto +0 -1907
- package/proto/courier.proto +0 -84
- package/proto/rolodex.proto +0 -116
- package/src/api/age-assurance/const.ts +0 -203
- package/src/api/age-assurance/index.ts +0 -34
- package/src/api/age-assurance/kws/age-verified.test.ts +0 -98
- package/src/api/age-assurance/kws/age-verified.ts +0 -81
- package/src/api/age-assurance/kws/const.ts +0 -33
- package/src/api/age-assurance/kws/external-payload.test.ts +0 -72
- package/src/api/age-assurance/kws/external-payload.ts +0 -149
- package/src/api/age-assurance/redirects/kws-age-verified.ts +0 -107
- package/src/api/age-assurance/stash.ts +0 -23
- package/src/api/age-assurance/types.ts +0 -10
- package/src/api/age-assurance/util.ts +0 -68
- package/src/api/age-assurance/webhooks/kws-age-verified.ts +0 -75
- package/src/api/app/bsky/actor/getProfile.ts +0 -106
- package/src/api/app/bsky/actor/getProfiles.ts +0 -99
- package/src/api/app/bsky/actor/getSuggestions.ts +0 -163
- package/src/api/app/bsky/actor/searchActors.ts +0 -171
- package/src/api/app/bsky/actor/searchActorsTypeahead.ts +0 -164
- package/src/api/app/bsky/ageassurance/begin.ts +0 -175
- package/src/api/app/bsky/ageassurance/getConfig.ts +0 -16
- package/src/api/app/bsky/ageassurance/getState.ts +0 -58
- package/src/api/app/bsky/bookmark/createBookmark.ts +0 -39
- package/src/api/app/bsky/bookmark/deleteBookmark.ts +0 -32
- package/src/api/app/bsky/bookmark/getBookmarks.ts +0 -97
- package/src/api/app/bsky/bookmark/util.ts +0 -13
- package/src/api/app/bsky/contact/dismissMatch.ts +0 -26
- package/src/api/app/bsky/contact/getMatches.ts +0 -111
- package/src/api/app/bsky/contact/getSyncStatus.ts +0 -38
- package/src/api/app/bsky/contact/importContacts.ts +0 -119
- package/src/api/app/bsky/contact/removeData.ts +0 -25
- package/src/api/app/bsky/contact/sendNotification.ts +0 -33
- package/src/api/app/bsky/contact/startPhoneVerification.ts +0 -26
- package/src/api/app/bsky/contact/util.ts +0 -92
- package/src/api/app/bsky/contact/verifyPhone.ts +0 -29
- package/src/api/app/bsky/draft/createDraft.ts +0 -45
- package/src/api/app/bsky/draft/deleteDraft.ts +0 -20
- package/src/api/app/bsky/draft/getDrafts.ts +0 -44
- package/src/api/app/bsky/draft/updateDraft.ts +0 -26
- package/src/api/app/bsky/embed/getEmbedExternalView.ts +0 -154
- package/src/api/app/bsky/feed/getActorFeeds.ts +0 -101
- package/src/api/app/bsky/feed/getActorLikes.ts +0 -128
- package/src/api/app/bsky/feed/getAuthorFeed.ts +0 -279
- package/src/api/app/bsky/feed/getFeed.ts +0 -277
- package/src/api/app/bsky/feed/getFeedGenerator.ts +0 -68
- package/src/api/app/bsky/feed/getFeedGenerators.ts +0 -86
- package/src/api/app/bsky/feed/getLikes.ts +0 -151
- package/src/api/app/bsky/feed/getListFeed.ts +0 -147
- package/src/api/app/bsky/feed/getPostThread.ts +0 -156
- package/src/api/app/bsky/feed/getPosts.ts +0 -100
- package/src/api/app/bsky/feed/getQuotes.ts +0 -122
- package/src/api/app/bsky/feed/getRepostedBy.ts +0 -121
- package/src/api/app/bsky/feed/getSuggestedFeeds.ts +0 -39
- package/src/api/app/bsky/feed/getTimeline.ts +0 -127
- package/src/api/app/bsky/feed/searchPosts.ts +0 -267
- package/src/api/app/bsky/feed/searchPostsV2.ts +0 -236
- package/src/api/app/bsky/graph/getActorStarterPacks.ts +0 -103
- package/src/api/app/bsky/graph/getBlocks.ts +0 -94
- package/src/api/app/bsky/graph/getFollowers.ts +0 -153
- package/src/api/app/bsky/graph/getFollows.ts +0 -151
- package/src/api/app/bsky/graph/getKnownFollowers.ts +0 -123
- package/src/api/app/bsky/graph/getList.ts +0 -152
- package/src/api/app/bsky/graph/getListBlocks.ts +0 -87
- package/src/api/app/bsky/graph/getListMutes.ts +0 -87
- package/src/api/app/bsky/graph/getLists.ts +0 -125
- package/src/api/app/bsky/graph/getListsWithMembership.ts +0 -146
- package/src/api/app/bsky/graph/getMutes.ts +0 -87
- package/src/api/app/bsky/graph/getRelationships.ts +0 -58
- package/src/api/app/bsky/graph/getStarterPack.ts +0 -82
- package/src/api/app/bsky/graph/getStarterPacks.ts +0 -86
- package/src/api/app/bsky/graph/getStarterPacksWithMembership.ts +0 -136
- package/src/api/app/bsky/graph/getSuggestedFollowsByActor.ts +0 -171
- package/src/api/app/bsky/graph/muteActor.ts +0 -24
- package/src/api/app/bsky/graph/muteActorList.ts +0 -19
- package/src/api/app/bsky/graph/muteThread.ts +0 -19
- package/src/api/app/bsky/graph/searchStarterPacks.ts +0 -169
- package/src/api/app/bsky/graph/unmuteActor.ts +0 -21
- package/src/api/app/bsky/graph/unmuteActorList.ts +0 -19
- package/src/api/app/bsky/graph/unmuteThread.ts +0 -19
- package/src/api/app/bsky/labeler/getServices.ts +0 -41
- package/src/api/app/bsky/notification/getPreferences.ts +0 -49
- package/src/api/app/bsky/notification/getUnreadCount.ts +0 -83
- package/src/api/app/bsky/notification/listActivitySubscriptions.ts +0 -116
- package/src/api/app/bsky/notification/listNotifications.ts +0 -272
- package/src/api/app/bsky/notification/putActivitySubscription.ts +0 -69
- package/src/api/app/bsky/notification/putPreferences.ts +0 -17
- package/src/api/app/bsky/notification/putPreferencesV2.ts +0 -64
- package/src/api/app/bsky/notification/registerPush.ts +0 -40
- package/src/api/app/bsky/notification/unregisterPush.ts +0 -39
- package/src/api/app/bsky/notification/updateSeen.ts +0 -52
- package/src/api/app/bsky/notification/util.ts +0 -134
- package/src/api/app/bsky/unspecced/getAgeAssuranceState.ts +0 -48
- package/src/api/app/bsky/unspecced/getConfig.ts +0 -20
- package/src/api/app/bsky/unspecced/getOnboardingSuggestedStarterPacks.ts +0 -162
- package/src/api/app/bsky/unspecced/getPopularFeedGenerators.ts +0 -91
- package/src/api/app/bsky/unspecced/getPostThreadOtherV2.ts +0 -126
- package/src/api/app/bsky/unspecced/getPostThreadV2.ts +0 -148
- package/src/api/app/bsky/unspecced/getSuggestedFeeds.ts +0 -100
- package/src/api/app/bsky/unspecced/getSuggestedOnboardingUsers.ts +0 -143
- package/src/api/app/bsky/unspecced/getSuggestedStarterPacks.ts +0 -165
- package/src/api/app/bsky/unspecced/getSuggestedUsers.ts +0 -183
- package/src/api/app/bsky/unspecced/getSuggestedUsersForDiscover.ts +0 -175
- package/src/api/app/bsky/unspecced/getSuggestedUsersForExplore.ts +0 -178
- package/src/api/app/bsky/unspecced/getSuggestedUsersForSeeMore.ts +0 -178
- package/src/api/app/bsky/unspecced/getTaggedSuggestions.ts +0 -27
- package/src/api/app/bsky/unspecced/getTrendingTopics.ts +0 -96
- package/src/api/app/bsky/unspecced/getTrends.ts +0 -162
- package/src/api/app/bsky/unspecced/initAgeAssurance.ts +0 -150
- package/src/api/blob-dispatcher.ts +0 -41
- package/src/api/blob-resolver.ts +0 -401
- package/src/api/com/atproto/admin/getAccountInfos.ts +0 -49
- package/src/api/com/atproto/admin/getSubjectStatus.ts +0 -79
- package/src/api/com/atproto/admin/updateSubjectStatus.ts +0 -80
- package/src/api/com/atproto/identity/resolveHandle.ts +0 -19
- package/src/api/com/atproto/label/queryLabels.ts +0 -42
- package/src/api/com/atproto/repo/getRecord.ts +0 -44
- package/src/api/com/atproto/temp/fetchLabels.ts +0 -9
- package/src/api/external.ts +0 -15
- package/src/api/health.ts +0 -47
- package/src/api/index.ts +0 -216
- package/src/api/internal/bsky/actor/getProfiles.ts +0 -87
- package/src/api/kws/api.ts +0 -113
- package/src/api/kws/index.ts +0 -29
- package/src/api/kws/types.ts +0 -78
- package/src/api/kws/util.test.ts +0 -50
- package/src/api/kws/util.ts +0 -109
- package/src/api/kws/webhook.ts +0 -134
- package/src/api/sitemap.ts +0 -76
- package/src/api/util.ts +0 -45
- package/src/api/well-known.ts +0 -44
- package/src/auth-verifier.ts +0 -522
- package/src/bsync.ts +0 -41
- package/src/cache/read-through.ts +0 -157
- package/src/config.ts +0 -710
- package/src/context.ts +0 -143
- package/src/courier.ts +0 -41
- package/src/data-plane/client/hosts.ts +0 -103
- package/src/data-plane/client/index.ts +0 -125
- package/src/data-plane/client/util.test.ts +0 -29
- package/src/data-plane/client/util.ts +0 -74
- package/src/data-plane/index.ts +0 -2
- package/src/data-plane/server/background.ts +0 -66
- package/src/data-plane/server/bsync-subscription.ts +0 -590
- package/src/data-plane/server/db/database-schema.ts +0 -90
- package/src/data-plane/server/db/db.ts +0 -204
- package/src/data-plane/server/db/index.ts +0 -2
- package/src/data-plane/server/db/migrations/20230309T045948368Z-init.ts +0 -305
- package/src/data-plane/server/db/migrations/20230408T152211201Z-notification-init.ts +0 -25
- package/src/data-plane/server/db/migrations/20230417T210628672Z-moderation-init.ts +0 -127
- package/src/data-plane/server/db/migrations/20230420T211446071Z-did-cache.ts +0 -14
- package/src/data-plane/server/db/migrations/20230427T194702079Z-notif-record-index.ts +0 -14
- package/src/data-plane/server/db/migrations/20230605T144730094Z-post-profile-aggs.ts +0 -23
- package/src/data-plane/server/db/migrations/20230607T211442112Z-feed-generator-init.ts +0 -34
- package/src/data-plane/server/db/migrations/20230608T155101190Z-algo-whats-hot-view.ts +0 -85
- package/src/data-plane/server/db/migrations/20230608T201813132Z-mute-lists.ts +0 -78
- package/src/data-plane/server/db/migrations/20230608T205147239Z-mutes.ts +0 -15
- package/src/data-plane/server/db/migrations/20230609T153623961Z-blocks.ts +0 -33
- package/src/data-plane/server/db/migrations/20230609T232122649Z-actor-deletion-indexes.ts +0 -27
- package/src/data-plane/server/db/migrations/20230610T203555962Z-suggested-follows.ts +0 -13
- package/src/data-plane/server/db/migrations/20230611T215300060Z-actor-state.ts +0 -13
- package/src/data-plane/server/db/migrations/20230620T161134972Z-post-langs.ts +0 -9
- package/src/data-plane/server/db/migrations/20230627T212437895Z-optional-handle.ts +0 -15
- package/src/data-plane/server/db/migrations/20230629T220835893Z-remove-post-hierarchy.ts +0 -32
- package/src/data-plane/server/db/migrations/20230703T045536691Z-feed-and-label-indices.ts +0 -31
- package/src/data-plane/server/db/migrations/20230720T164800037Z-posts-cursor-idx.ts +0 -19
- package/src/data-plane/server/db/migrations/20230807T035309811Z-feed-item-delete-invite-for-user-idx.ts +0 -14
- package/src/data-plane/server/db/migrations/20230808T172902639Z-repo-rev.ts +0 -12
- package/src/data-plane/server/db/migrations/20230810T203349843Z-action-duration.ts +0 -23
- package/src/data-plane/server/db/migrations/20230817T195936007Z-native-notifications.ts +0 -16
- package/src/data-plane/server/db/migrations/20230830T205507322Z-suggested-feeds.ts +0 -13
- package/src/data-plane/server/db/migrations/20230904T211011773Z-block-lists.ts +0 -24
- package/src/data-plane/server/db/migrations/20230906T222220386Z-thread-gating.ts +0 -27
- package/src/data-plane/server/db/migrations/20230920T213858047Z-add-tags-to-post.ts +0 -9
- package/src/data-plane/server/db/migrations/20230929T192920807Z-record-cursor-indexes.ts +0 -40
- package/src/data-plane/server/db/migrations/20231003T202833377Z-create-moderation-subject-status.ts +0 -123
- package/src/data-plane/server/db/migrations/20231220T225126090Z-blob-takedowns.ts +0 -66
- package/src/data-plane/server/db/migrations/20240124T023719200Z-tagged-suggestions.ts +0 -15
- package/src/data-plane/server/db/migrations/20240226T225725627Z-labelers.ts +0 -27
- package/src/data-plane/server/db/migrations/20240530T170337073Z-account-deactivation.ts +0 -12
- package/src/data-plane/server/db/migrations/20240606T171229898Z-thread-mutes.ts +0 -15
- package/src/data-plane/server/db/migrations/20240606T222548219Z-starter-packs.ts +0 -45
- package/src/data-plane/server/db/migrations/20240719T203853939Z-priority-notifs.ts +0 -25
- package/src/data-plane/server/db/migrations/20240723T220700077Z-quotes-post-aggs.ts +0 -12
- package/src/data-plane/server/db/migrations/20240723T220703655Z-quotes.ts +0 -28
- package/src/data-plane/server/db/migrations/20240801T193939827Z-post-gate.ts +0 -17
- package/src/data-plane/server/db/migrations/20240808T224251220Z-post-gate-flags.ts +0 -25
- package/src/data-plane/server/db/migrations/20240829T211238293Z-simplify-actor-sync.ts +0 -23
- package/src/data-plane/server/db/migrations/20240831T134810923Z-pinned-posts.ts +0 -17
- package/src/data-plane/server/db/migrations/20241114T153108102Z-add-starter-packs-name.ts +0 -19
- package/src/data-plane/server/db/migrations/20250116T222618297Z-post-embed-video.ts +0 -17
- package/src/data-plane/server/db/migrations/20250207T174822012Z-add-label-exp.ts +0 -9
- package/src/data-plane/server/db/migrations/20250404T163421487Z-verifications.ts +0 -39
- package/src/data-plane/server/db/migrations/20250526T023712742Z-like-repost-via.ts +0 -17
- package/src/data-plane/server/db/migrations/20250528T221913281Z-add-record-tags.ts +0 -9
- package/src/data-plane/server/db/migrations/20250602T190357447Z-add-private-data.ts +0 -22
- package/src/data-plane/server/db/migrations/20250611T140649895Z-add-activity-subscription.ts +0 -22
- package/src/data-plane/server/db/migrations/20250627T025331240Z-add-actor-age-assurance-columns.ts +0 -22
- package/src/data-plane/server/db/migrations/20250812T183735692Z-add-bookmarks.ts +0 -23
- package/src/data-plane/server/db/migrations/20250813T174955711Z-add-post-agg-bookmarks.ts +0 -12
- package/src/data-plane/server/db/migrations/20251120T004738098Z-update-actor-age-assurance-v2.ts +0 -28
- package/src/data-plane/server/db/migrations/20260112T133951271Z-add-drafts.ts +0 -24
- package/src/data-plane/server/db/migrations/20260604T224952774Z-post-embed-gallery-image.ts +0 -19
- package/src/data-plane/server/db/migrations/index.ts +0 -60
- package/src/data-plane/server/db/migrations/provider.ts +0 -26
- package/src/data-plane/server/db/pagination.ts +0 -341
- package/src/data-plane/server/db/tables/activity-subscription.ts +0 -12
- package/src/data-plane/server/db/tables/actor-block.ts +0 -14
- package/src/data-plane/server/db/tables/actor-state.ts +0 -10
- package/src/data-plane/server/db/tables/actor-sync.ts +0 -9
- package/src/data-plane/server/db/tables/actor.ts +0 -19
- package/src/data-plane/server/db/tables/algo.ts +0 -11
- package/src/data-plane/server/db/tables/blob-takedown.ts +0 -9
- package/src/data-plane/server/db/tables/bookmark.ts +0 -11
- package/src/data-plane/server/db/tables/did-cache.ts +0 -13
- package/src/data-plane/server/db/tables/draft.ts +0 -11
- package/src/data-plane/server/db/tables/duplicate-record.ts +0 -12
- package/src/data-plane/server/db/tables/feed-generator.ts +0 -21
- package/src/data-plane/server/db/tables/feed-item.ts +0 -12
- package/src/data-plane/server/db/tables/follow.ts +0 -15
- package/src/data-plane/server/db/tables/label.ts +0 -13
- package/src/data-plane/server/db/tables/labeler.ts +0 -16
- package/src/data-plane/server/db/tables/like.ts +0 -18
- package/src/data-plane/server/db/tables/list-block.ts +0 -15
- package/src/data-plane/server/db/tables/list-item.ts +0 -16
- package/src/data-plane/server/db/tables/list-mute.ts +0 -9
- package/src/data-plane/server/db/tables/list.ts +0 -19
- package/src/data-plane/server/db/tables/mute.ts +0 -9
- package/src/data-plane/server/db/tables/notification-push-token.ts +0 -10
- package/src/data-plane/server/db/tables/notification.ts +0 -16
- package/src/data-plane/server/db/tables/post-agg.ts +0 -16
- package/src/data-plane/server/db/tables/post-embed.ts +0 -47
- package/src/data-plane/server/db/tables/post-gate.ts +0 -12
- package/src/data-plane/server/db/tables/post.ts +0 -28
- package/src/data-plane/server/db/tables/private-data.ts +0 -13
- package/src/data-plane/server/db/tables/profile-agg.ts +0 -14
- package/src/data-plane/server/db/tables/profile.ts +0 -17
- package/src/data-plane/server/db/tables/quote.ts +0 -15
- package/src/data-plane/server/db/tables/record.ts +0 -15
- package/src/data-plane/server/db/tables/repost.ts +0 -18
- package/src/data-plane/server/db/tables/starter-pack.ts +0 -17
- package/src/data-plane/server/db/tables/subscription.ts +0 -9
- package/src/data-plane/server/db/tables/suggested-feed.ts +0 -10
- package/src/data-plane/server/db/tables/suggested-follow.ts +0 -10
- package/src/data-plane/server/db/tables/tagged-suggestion.ts +0 -11
- package/src/data-plane/server/db/tables/thread-gate.ts +0 -12
- package/src/data-plane/server/db/tables/thread-mute.ts +0 -9
- package/src/data-plane/server/db/tables/verification.ts +0 -20
- package/src/data-plane/server/db/tables/view-param.ts +0 -12
- package/src/data-plane/server/db/types.ts +0 -12
- package/src/data-plane/server/db/util.ts +0 -67
- package/src/data-plane/server/index.ts +0 -44
- package/src/data-plane/server/indexing/index.ts +0 -458
- package/src/data-plane/server/indexing/plugins/block.ts +0 -84
- package/src/data-plane/server/indexing/plugins/chat-declaration.ts +0 -60
- package/src/data-plane/server/indexing/plugins/feed-generator.ts +0 -80
- package/src/data-plane/server/indexing/plugins/follow.ts +0 -132
- package/src/data-plane/server/indexing/plugins/germ-declaration.ts +0 -57
- package/src/data-plane/server/indexing/plugins/labeler.ts +0 -74
- package/src/data-plane/server/indexing/plugins/like.ts +0 -151
- package/src/data-plane/server/indexing/plugins/list-block.ts +0 -84
- package/src/data-plane/server/indexing/plugins/list-item.ts +0 -92
- package/src/data-plane/server/indexing/plugins/list.ts +0 -80
- package/src/data-plane/server/indexing/plugins/notif-declaration.ts +0 -57
- package/src/data-plane/server/indexing/plugins/post-gate.ts +0 -101
- package/src/data-plane/server/indexing/plugins/post.ts +0 -675
- package/src/data-plane/server/indexing/plugins/profile.ts +0 -90
- package/src/data-plane/server/indexing/plugins/repost.ts +0 -176
- package/src/data-plane/server/indexing/plugins/starter-pack.ts +0 -74
- package/src/data-plane/server/indexing/plugins/status.ts +0 -57
- package/src/data-plane/server/indexing/plugins/thread-gate.ts +0 -101
- package/src/data-plane/server/indexing/plugins/verification.ts +0 -113
- package/src/data-plane/server/indexing/processor.ts +0 -292
- package/src/data-plane/server/routes/activity-subscription.ts +0 -84
- package/src/data-plane/server/routes/blocks.ts +0 -127
- package/src/data-plane/server/routes/bookmarks.ts +0 -83
- package/src/data-plane/server/routes/drafts.ts +0 -37
- package/src/data-plane/server/routes/feed-gens.ts +0 -89
- package/src/data-plane/server/routes/feeds.ts +0 -176
- package/src/data-plane/server/routes/follows.ts +0 -141
- package/src/data-plane/server/routes/identity.ts +0 -59
- package/src/data-plane/server/routes/index.ts +0 -67
- package/src/data-plane/server/routes/interactions.ts +0 -120
- package/src/data-plane/server/routes/labels.ts +0 -55
- package/src/data-plane/server/routes/likes.ts +0 -92
- package/src/data-plane/server/routes/lists.ts +0 -88
- package/src/data-plane/server/routes/moderation.ts +0 -102
- package/src/data-plane/server/routes/mutes.ts +0 -195
- package/src/data-plane/server/routes/notifs.ts +0 -239
- package/src/data-plane/server/routes/profile.ts +0 -220
- package/src/data-plane/server/routes/quotes.ts +0 -32
- package/src/data-plane/server/routes/records.ts +0 -119
- package/src/data-plane/server/routes/relationships.ts +0 -174
- package/src/data-plane/server/routes/reposts.ts +0 -76
- package/src/data-plane/server/routes/search.ts +0 -181
- package/src/data-plane/server/routes/site-standard.ts +0 -12
- package/src/data-plane/server/routes/sitemap.ts +0 -43
- package/src/data-plane/server/routes/starter-packs.ts +0 -32
- package/src/data-plane/server/routes/suggestions.ts +0 -175
- package/src/data-plane/server/routes/sync.ts +0 -16
- package/src/data-plane/server/routes/threads.ts +0 -33
- package/src/data-plane/server/subscription.ts +0 -152
- package/src/data-plane/server/util.ts +0 -202
- package/src/error.ts +0 -12
- package/src/etcd.ts +0 -90
- package/src/feature-gates/README.md +0 -83
- package/src/feature-gates/gates.ts +0 -25
- package/src/feature-gates/index.ts +0 -235
- package/src/feature-gates/metrics.test.ts +0 -196
- package/src/feature-gates/metrics.ts +0 -107
- package/src/feature-gates/types.ts +0 -62
- package/src/feature-gates/utils.test.ts +0 -66
- package/src/feature-gates/utils.ts +0 -135
- package/src/hydration/actor.ts +0 -578
- package/src/hydration/external.test.ts +0 -281
- package/src/hydration/external.ts +0 -268
- package/src/hydration/feed.ts +0 -456
- package/src/hydration/graph.ts +0 -354
- package/src/hydration/hydrator.ts +0 -1835
- package/src/hydration/label.ts +0 -207
- package/src/hydration/util.ts +0 -199
- package/src/image/index.ts +0 -2
- package/src/image/invalidator.ts +0 -33
- package/src/image/logger.ts +0 -6
- package/src/image/server.ts +0 -228
- package/src/image/sharp.ts +0 -89
- package/src/image/uri.ts +0 -114
- package/src/image/util.ts +0 -41
- package/src/index.ts +0 -312
- package/src/kws.ts +0 -197
- package/src/logger.ts +0 -40
- package/src/pipeline.ts +0 -60
- package/src/redis.ts +0 -205
- package/src/rolodex.ts +0 -42
- package/src/stash.ts +0 -76
- package/src/util/debug.ts +0 -10
- package/src/util/http.ts +0 -42
- package/src/util/retry.ts +0 -10
- package/src/util/standard-site.test.ts +0 -423
- package/src/util/standard-site.ts +0 -196
- package/src/util/uris.ts +0 -38
- package/src/util.ts +0 -48
- package/src/views/index.ts +0 -2783
- package/src/views/threads-v2.ts +0 -510
- package/src/views/types.ts +0 -193
- package/src/views/util.ts +0 -114
- package/test.env +0 -2
- package/tests/__snapshots__/feed-generation.test.ts.snap +0 -2463
- package/tests/_util.ts +0 -292
- package/tests/admin/admin-auth.test.ts +0 -190
- package/tests/admin/moderation.test.ts +0 -222
- package/tests/auth.test.ts +0 -90
- package/tests/blob-resolver.test.ts +0 -125
- package/tests/data-plane/__snapshots__/indexing.test.ts.snap +0 -887
- package/tests/data-plane/db.test.ts +0 -189
- package/tests/data-plane/duplicate-records.test.ts +0 -156
- package/tests/data-plane/handle-invalidation.test.ts +0 -153
- package/tests/data-plane/indexing.test.ts +0 -827
- package/tests/data-plane/subscription.test.ts +0 -128
- package/tests/data-plane/thread-mutes.test.ts +0 -175
- package/tests/entryway-auth.test.ts +0 -177
- package/tests/etcd.test.ts +0 -302
- package/tests/feed-generation.test.ts +0 -919
- package/tests/hydration/util.test.ts +0 -119
- package/tests/image/server.test.ts +0 -97
- package/tests/image/sharp.test.ts +0 -199
- package/tests/image/uri.test.ts +0 -106
- package/tests/label-hydration.test.ts +0 -245
- package/tests/postgates.test.ts +0 -182
- package/tests/query-labels.test.ts +0 -85
- package/tests/redis-cache.test.ts +0 -230
- package/tests/seed/feed-hidden-replies.ts +0 -63
- package/tests/seed/get-suggested-starter-packs.ts +0 -64
- package/tests/seed/get-trends.ts +0 -71
- package/tests/seed/known-followers.ts +0 -111
- package/tests/seed/postgates.ts +0 -57
- package/tests/server.test.ts +0 -115
- package/tests/sitemap.test.ts +0 -75
- package/tests/stash.test.ts +0 -180
- package/tests/utils.test.ts +0 -36
- package/tests/views/__snapshots__/actor-search.test.ts.snap +0 -155
- package/tests/views/__snapshots__/author-feed.test.ts.snap +0 -6301
- package/tests/views/__snapshots__/block-lists.test.ts.snap +0 -690
- package/tests/views/__snapshots__/blocks.test.ts.snap +0 -462
- package/tests/views/__snapshots__/bookmarks.test.ts.snap +0 -379
- package/tests/views/__snapshots__/follows.test.ts.snap +0 -798
- package/tests/views/__snapshots__/labeler-service.test.ts.snap +0 -233
- package/tests/views/__snapshots__/likes.test.ts.snap +0 -124
- package/tests/views/__snapshots__/list-feed.test.ts.snap +0 -883
- package/tests/views/__snapshots__/lists.test.ts.snap +0 -650
- package/tests/views/__snapshots__/mute-lists.test.ts.snap +0 -705
- package/tests/views/__snapshots__/mutes.test.ts.snap +0 -353
- package/tests/views/__snapshots__/notifications.test.ts.snap +0 -3074
- package/tests/views/__snapshots__/posts.test.ts.snap +0 -1019
- package/tests/views/__snapshots__/profile.test.ts.snap +0 -811
- package/tests/views/__snapshots__/quotes.test.ts.snap +0 -445
- package/tests/views/__snapshots__/reposts.test.ts.snap +0 -112
- package/tests/views/__snapshots__/starter-packs.test.ts.snap +0 -836
- package/tests/views/__snapshots__/thread-v2.test.ts.snap +0 -1298
- package/tests/views/__snapshots__/thread.test.ts.snap +0 -2051
- package/tests/views/__snapshots__/threadgating.test.ts.snap +0 -189
- package/tests/views/__snapshots__/timeline.test.ts.snap +0 -7252
- package/tests/views/account-deactivation.test.ts +0 -81
- package/tests/views/actor-likes.test.ts +0 -138
- package/tests/views/actor-search.test.ts +0 -261
- package/tests/views/age-assurance-v2.test.ts +0 -823
- package/tests/views/age-assurance.test.ts +0 -479
- package/tests/views/author-feed.test.ts +0 -694
- package/tests/views/block-lists.test.ts +0 -661
- package/tests/views/blocks.test.ts +0 -889
- package/tests/views/bookmarks.test.ts +0 -345
- package/tests/views/drafts.test.ts +0 -430
- package/tests/views/feed-hidden-replies.test.ts +0 -243
- package/tests/views/feed-view-post.test.ts +0 -501
- package/tests/views/follows.test.ts +0 -372
- package/tests/views/get-config.test.ts +0 -64
- package/tests/views/get-suggested-onboarding-users.test.ts +0 -193
- package/tests/views/get-suggested-starter-packs.test.ts +0 -137
- package/tests/views/get-trends.test.ts +0 -141
- package/tests/views/internal-actor.test.ts +0 -127
- package/tests/views/known-followers.test.ts +0 -193
- package/tests/views/labeler-service.test.ts +0 -242
- package/tests/views/labels-needs-review.test.ts +0 -316
- package/tests/views/labels-takedown.test.ts +0 -247
- package/tests/views/likes.test.ts +0 -192
- package/tests/views/list-feed.test.ts +0 -195
- package/tests/views/lists.test.ts +0 -412
- package/tests/views/mute-lists.test.ts +0 -509
- package/tests/views/mutes.test.ts +0 -308
- package/tests/views/notifications.test.ts +0 -1581
- package/tests/views/post-search.test.ts +0 -200
- package/tests/views/posts-debug.test.ts +0 -79
- package/tests/views/posts.test.ts +0 -427
- package/tests/views/profile-debug.test.ts +0 -75
- package/tests/views/profile.test.ts +0 -795
- package/tests/views/quotes.test.ts +0 -133
- package/tests/views/reposts.test.ts +0 -112
- package/tests/views/starter-packs.test.ts +0 -395
- package/tests/views/suggestions.test.ts +0 -145
- package/tests/views/thread-v2.test.ts +0 -2005
- package/tests/views/thread.test.ts +0 -637
- package/tests/views/threadgating.test.ts +0 -843
- package/tests/views/timeline.test.ts +0 -328
- package/tests/views/verification.test.ts +0 -296
- package/tsconfig.build.json +0 -10
- package/tsconfig.build.tsbuildinfo +0 -1
- package/tsconfig.json +0 -7
- package/tsconfig.tests.json +0 -8
- package/vitest.config.ts +0 -10
package/src/api/kws/api.ts
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import express, { RequestHandler } from 'express'
|
|
2
|
-
import { httpLogger as log } from '../../logger.js'
|
|
3
|
-
import { AGE_ASSURANCE_CONFIG } from '../age-assurance/const.js'
|
|
4
|
-
import {
|
|
5
|
-
KWSExternalPayloadVersion,
|
|
6
|
-
parseKWSExternalPayloadV1WithV2Compat,
|
|
7
|
-
} from '../age-assurance/kws/external-payload.js'
|
|
8
|
-
import { createEvent } from '../age-assurance/stash.js'
|
|
9
|
-
import { computeAgeAssuranceAccessOrThrow } from '../age-assurance/util.js'
|
|
10
|
-
import { AppContextWithKwsClient } from './types.js'
|
|
11
|
-
import {
|
|
12
|
-
createStashEvent,
|
|
13
|
-
getClientUa,
|
|
14
|
-
parseStatus,
|
|
15
|
-
validateSignature,
|
|
16
|
-
} from './util.js'
|
|
17
|
-
|
|
18
|
-
function parseQueryParams(
|
|
19
|
-
ctx: AppContextWithKwsClient,
|
|
20
|
-
req: express.Request,
|
|
21
|
-
): {
|
|
22
|
-
status: string
|
|
23
|
-
externalPayload: string
|
|
24
|
-
} {
|
|
25
|
-
try {
|
|
26
|
-
const status = String(req.query.status)
|
|
27
|
-
const externalPayload = String(req.query.externalPayload)
|
|
28
|
-
const signature = String(req.query.signature)
|
|
29
|
-
|
|
30
|
-
validateSignature(
|
|
31
|
-
ctx.cfg.kws.verificationSecret,
|
|
32
|
-
`${status}:${externalPayload}`,
|
|
33
|
-
signature,
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
return {
|
|
37
|
-
status,
|
|
38
|
-
externalPayload,
|
|
39
|
-
}
|
|
40
|
-
} catch (err) {
|
|
41
|
-
throw new Error('Invalid KWS API request', { cause: err })
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export const verificationHandler =
|
|
46
|
-
(ctx: AppContextWithKwsClient): RequestHandler =>
|
|
47
|
-
async (req: express.Request, res: express.Response) => {
|
|
48
|
-
let actorDid: string | undefined
|
|
49
|
-
try {
|
|
50
|
-
const query = parseQueryParams(ctx, req)
|
|
51
|
-
const { verified } = parseStatus(query.status)
|
|
52
|
-
if (!verified) {
|
|
53
|
-
throw new Error(
|
|
54
|
-
'Unexpected KWS verification response call with unverified status',
|
|
55
|
-
)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// Assumes `app.set('trust proxy', ...)` configured with `true` or specific values.
|
|
59
|
-
const completeIp = req.ip
|
|
60
|
-
const completeUa = getClientUa(req)
|
|
61
|
-
const externalPayload = parseKWSExternalPayloadV1WithV2Compat(
|
|
62
|
-
query.externalPayload,
|
|
63
|
-
)
|
|
64
|
-
actorDid = externalPayload.actorDid
|
|
65
|
-
|
|
66
|
-
if (externalPayload.version === KWSExternalPayloadVersion.V2) {
|
|
67
|
-
const { countryCode, regionCode, attemptId } = externalPayload
|
|
68
|
-
const { access } = computeAgeAssuranceAccessOrThrow(
|
|
69
|
-
AGE_ASSURANCE_CONFIG,
|
|
70
|
-
{
|
|
71
|
-
countryCode: countryCode,
|
|
72
|
-
regionCode: regionCode,
|
|
73
|
-
verifiedMinimumAge: 18, // `adult-verified` is 18+ only
|
|
74
|
-
},
|
|
75
|
-
)
|
|
76
|
-
await createEvent(ctx, actorDid, {
|
|
77
|
-
attemptId,
|
|
78
|
-
status: 'assured',
|
|
79
|
-
access,
|
|
80
|
-
countryCode,
|
|
81
|
-
regionCode,
|
|
82
|
-
completeIp,
|
|
83
|
-
completeUa,
|
|
84
|
-
})
|
|
85
|
-
} else {
|
|
86
|
-
await createStashEvent(ctx, {
|
|
87
|
-
actorDid,
|
|
88
|
-
attemptId: externalPayload.attemptId,
|
|
89
|
-
status: 'assured',
|
|
90
|
-
completeIp,
|
|
91
|
-
completeUa,
|
|
92
|
-
})
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
return res
|
|
96
|
-
.status(302)
|
|
97
|
-
.setHeader(
|
|
98
|
-
'Location',
|
|
99
|
-
`${ctx.cfg.kws.redirectUrl}?${new URLSearchParams({ actorDid, result: 'success' })}`,
|
|
100
|
-
)
|
|
101
|
-
.end()
|
|
102
|
-
} catch (err) {
|
|
103
|
-
log.error({ err }, 'Failed to handle KWS verification response')
|
|
104
|
-
|
|
105
|
-
return res
|
|
106
|
-
.status(302)
|
|
107
|
-
.setHeader(
|
|
108
|
-
'Location',
|
|
109
|
-
`${ctx.cfg.kws.redirectUrl}?${new URLSearchParams({ ...(actorDid ? { actorDid } : {}), result: 'unknown' })}`,
|
|
110
|
-
)
|
|
111
|
-
.end()
|
|
112
|
-
}
|
|
113
|
-
}
|
package/src/api/kws/index.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { Router, raw } from 'express'
|
|
2
|
-
import { AppContext } from '../../context.js'
|
|
3
|
-
import { verificationHandler } from './api.js'
|
|
4
|
-
import { AppContextWithKwsClient } from './types.js'
|
|
5
|
-
import { webhookAuth, webhookHandler } from './webhook.js'
|
|
6
|
-
|
|
7
|
-
export const createRouter = (ctx: AppContext): Router => {
|
|
8
|
-
assertAppContextWithAgeAssuranceClient(ctx)
|
|
9
|
-
|
|
10
|
-
const router = Router()
|
|
11
|
-
router.use(raw({ type: 'application/json' }))
|
|
12
|
-
router.post(
|
|
13
|
-
'/age-assurance-webhook',
|
|
14
|
-
webhookAuth({
|
|
15
|
-
secret: ctx.cfg.kws.webhookSecret,
|
|
16
|
-
}),
|
|
17
|
-
webhookHandler(ctx),
|
|
18
|
-
)
|
|
19
|
-
router.get('/age-assurance-verification', verificationHandler(ctx))
|
|
20
|
-
return router
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const assertAppContextWithAgeAssuranceClient: (
|
|
24
|
-
ctx: AppContext,
|
|
25
|
-
) => asserts ctx is AppContextWithKwsClient = (ctx: AppContext) => {
|
|
26
|
-
if (!ctx.kwsClient) {
|
|
27
|
-
throw new Error('Tried to set up KWS router without kwsClient configured.')
|
|
28
|
-
}
|
|
29
|
-
}
|
package/src/api/kws/types.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod'
|
|
2
|
-
import { KwsConfig, ServerConfig } from '../../config.js'
|
|
3
|
-
import { AppContext } from '../../context.js'
|
|
4
|
-
import { KwsClient } from '../../kws.js'
|
|
5
|
-
|
|
6
|
-
export type AppContextWithKwsClient = AppContext & {
|
|
7
|
-
kwsClient: KwsClient
|
|
8
|
-
cfg: ServerConfig & {
|
|
9
|
-
kws: KwsConfig
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export type KwsExternalPayload = {
|
|
14
|
-
actorDid: string
|
|
15
|
-
attemptId: string
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// `.strict()` because we control the payload structure.
|
|
19
|
-
export const externalPayloadSchema = z
|
|
20
|
-
.object({
|
|
21
|
-
actorDid: z.string(),
|
|
22
|
-
attemptId: z.string(),
|
|
23
|
-
})
|
|
24
|
-
.strict()
|
|
25
|
-
|
|
26
|
-
export type KwsStatus = {
|
|
27
|
-
verified: boolean
|
|
28
|
-
// A unique reference ID for the verification transaction.
|
|
29
|
-
transactionId?: string
|
|
30
|
-
// A code indicating the reason for failure, or null when verification
|
|
31
|
-
// succeeded.
|
|
32
|
-
errorCode?: string | null
|
|
33
|
-
// Epoch seconds indicating when KWS generated the payload. Optional so we
|
|
34
|
-
// remain compatible with payloads sent before this field was introduced.
|
|
35
|
-
timestamp?: number
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export type KwsVerificationIntermediateQuery = {
|
|
39
|
-
externalPayload: string
|
|
40
|
-
status: string
|
|
41
|
-
signature: string
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Not `.strict()` to avoid breaking if KWS adds fields.
|
|
45
|
-
export const verificationIntermediateQuerySchema = z.object({
|
|
46
|
-
externalPayload: z.string(),
|
|
47
|
-
signature: z.string(),
|
|
48
|
-
status: z.string(),
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
export type KwsVerificationQuery = {
|
|
52
|
-
externalPayload: KwsExternalPayload
|
|
53
|
-
signature: string
|
|
54
|
-
status: KwsStatus
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export type KwsWebhookBody = {
|
|
58
|
-
payload: {
|
|
59
|
-
externalPayload: KwsExternalPayload
|
|
60
|
-
status: KwsStatus
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Not `.strict()` to avoid breaking if KWS adds fields.
|
|
65
|
-
export const statusSchema = z.object({
|
|
66
|
-
verified: z.boolean(),
|
|
67
|
-
transactionId: z.string().optional(),
|
|
68
|
-
errorCode: z.string().nullable().optional(),
|
|
69
|
-
timestamp: z.number().optional(),
|
|
70
|
-
})
|
|
71
|
-
|
|
72
|
-
// Not `.strict()` to avoid breaking if KWS adds fields.
|
|
73
|
-
export const webhookBodyIntermediateSchema = z.object({
|
|
74
|
-
payload: z.object({
|
|
75
|
-
externalPayload: z.string(),
|
|
76
|
-
status: statusSchema,
|
|
77
|
-
}),
|
|
78
|
-
})
|
package/src/api/kws/util.test.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { parseStatus } from './util.js'
|
|
3
|
-
|
|
4
|
-
describe('parseStatus', () => {
|
|
5
|
-
it('parses a minimal status object', () => {
|
|
6
|
-
const raw = JSON.stringify({ verified: true })
|
|
7
|
-
expect(parseStatus(raw)).toEqual({ verified: true })
|
|
8
|
-
})
|
|
9
|
-
|
|
10
|
-
it('parses the optional transactionId, errorCode, and timestamp fields', () => {
|
|
11
|
-
const raw = JSON.stringify({
|
|
12
|
-
verified: true,
|
|
13
|
-
transactionId: 'txn-123',
|
|
14
|
-
errorCode: null,
|
|
15
|
-
timestamp: 1750680000,
|
|
16
|
-
})
|
|
17
|
-
expect(parseStatus(raw)).toEqual({
|
|
18
|
-
verified: true,
|
|
19
|
-
transactionId: 'txn-123',
|
|
20
|
-
errorCode: null,
|
|
21
|
-
timestamp: 1750680000,
|
|
22
|
-
})
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
it('parses a non-null errorCode', () => {
|
|
26
|
-
const raw = JSON.stringify({ verified: false, errorCode: 'some-failure' })
|
|
27
|
-
expect(parseStatus(raw)).toEqual({
|
|
28
|
-
verified: false,
|
|
29
|
-
errorCode: 'some-failure',
|
|
30
|
-
})
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
it('silently strips unknown fields KWS may add', () => {
|
|
34
|
-
const raw = JSON.stringify({
|
|
35
|
-
verified: true,
|
|
36
|
-
timestamp: 1750680000,
|
|
37
|
-
somethingNew: 'ignored',
|
|
38
|
-
})
|
|
39
|
-
expect(parseStatus(raw)).toEqual({ verified: true, timestamp: 1750680000 })
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
it('throws on malformed JSON', () => {
|
|
43
|
-
expect(() => parseStatus('not json')).toThrow(/Invalid status/)
|
|
44
|
-
})
|
|
45
|
-
|
|
46
|
-
it('throws when verified is missing', () => {
|
|
47
|
-
const raw = JSON.stringify({ timestamp: 1750680000 })
|
|
48
|
-
expect(() => parseStatus(raw)).toThrow(/Invalid status/)
|
|
49
|
-
})
|
|
50
|
-
})
|
package/src/api/kws/util.ts
DELETED
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
import crypto from 'node:crypto'
|
|
2
|
-
import express from 'express'
|
|
3
|
-
import { TID } from '@atproto/common'
|
|
4
|
-
import { DatetimeString } from '@atproto/syntax'
|
|
5
|
-
import { AppContext } from '../../context.js'
|
|
6
|
-
import { app } from '../../lexicons/index.js'
|
|
7
|
-
import { Namespaces } from '../../stash.js'
|
|
8
|
-
import {
|
|
9
|
-
KwsExternalPayload,
|
|
10
|
-
KwsStatus,
|
|
11
|
-
externalPayloadSchema,
|
|
12
|
-
statusSchema,
|
|
13
|
-
} from './types.js'
|
|
14
|
-
|
|
15
|
-
export const createStashEvent = async (
|
|
16
|
-
ctx: AppContext,
|
|
17
|
-
{
|
|
18
|
-
actorDid,
|
|
19
|
-
attemptId,
|
|
20
|
-
email,
|
|
21
|
-
initIp,
|
|
22
|
-
initUa,
|
|
23
|
-
completeIp,
|
|
24
|
-
completeUa,
|
|
25
|
-
status,
|
|
26
|
-
}: {
|
|
27
|
-
actorDid: string
|
|
28
|
-
attemptId: string
|
|
29
|
-
email?: string
|
|
30
|
-
initIp?: string
|
|
31
|
-
initUa?: string
|
|
32
|
-
completeIp?: string
|
|
33
|
-
completeUa?: string
|
|
34
|
-
status: app.bsky.unspecced.defs.AgeAssuranceState['status']
|
|
35
|
-
},
|
|
36
|
-
) => {
|
|
37
|
-
const stashPayload: app.bsky.unspecced.defs.AgeAssuranceEvent = {
|
|
38
|
-
createdAt: new Date().toISOString() as DatetimeString,
|
|
39
|
-
email,
|
|
40
|
-
status,
|
|
41
|
-
attemptId,
|
|
42
|
-
initIp,
|
|
43
|
-
initUa,
|
|
44
|
-
completeIp,
|
|
45
|
-
completeUa,
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
await ctx.stashClient.create({
|
|
49
|
-
actorDid,
|
|
50
|
-
namespace: Namespaces.AppBskyUnspeccedDefsAgeAssuranceEvent,
|
|
51
|
-
key: TID.nextStr(),
|
|
52
|
-
payload: stashPayload,
|
|
53
|
-
})
|
|
54
|
-
return stashPayload
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export const validateSignature = (
|
|
58
|
-
key: string,
|
|
59
|
-
data: string,
|
|
60
|
-
signature: string,
|
|
61
|
-
) => {
|
|
62
|
-
const expectedSignature = crypto
|
|
63
|
-
.createHmac('sha256', key)
|
|
64
|
-
.update(data)
|
|
65
|
-
.digest('hex')
|
|
66
|
-
|
|
67
|
-
const expectedSignatureBuf = Buffer.from(expectedSignature, 'hex')
|
|
68
|
-
const actualSignatureBuf = Buffer.from(signature, 'hex')
|
|
69
|
-
|
|
70
|
-
if (expectedSignatureBuf.length !== actualSignatureBuf.length) {
|
|
71
|
-
throw new Error(`Signature mismatch`)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (!crypto.timingSafeEqual(expectedSignatureBuf, actualSignatureBuf)) {
|
|
75
|
-
throw new Error(`Signature mismatch`)
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export const serializeExternalPayload = (value: KwsExternalPayload): string => {
|
|
80
|
-
return JSON.stringify(value)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export const parseExternalPayload = (
|
|
84
|
-
serialized: string,
|
|
85
|
-
): KwsExternalPayload => {
|
|
86
|
-
try {
|
|
87
|
-
const value: unknown = JSON.parse(serialized)
|
|
88
|
-
return externalPayloadSchema.parse(value)
|
|
89
|
-
} catch (err) {
|
|
90
|
-
throw new Error(`Invalid external payload: ${serialized}`, { cause: err })
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export const parseStatus = (serialized: string): KwsStatus => {
|
|
95
|
-
try {
|
|
96
|
-
const value: unknown = JSON.parse(serialized)
|
|
97
|
-
return statusSchema.parse(value)
|
|
98
|
-
} catch (err) {
|
|
99
|
-
throw new Error(`Invalid status: ${serialized}`, { cause: err })
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
export const kwsWwwAuthenticate = (): Record<string, string> => ({
|
|
104
|
-
'www-authenticate': `Signature realm="kws"`,
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
export const getClientUa = (req: express.Request): string | undefined => {
|
|
108
|
-
return req.headers['user-agent']
|
|
109
|
-
}
|
package/src/api/kws/webhook.ts
DELETED
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
import express, { RequestHandler } from 'express'
|
|
2
|
-
import { httpLogger as log } from '../../logger.js'
|
|
3
|
-
import { AGE_ASSURANCE_CONFIG } from '../age-assurance/const.js'
|
|
4
|
-
import {
|
|
5
|
-
KWSExternalPayloadVersion,
|
|
6
|
-
parseKWSExternalPayloadV1WithV2Compat,
|
|
7
|
-
} from '../age-assurance/kws/external-payload.js'
|
|
8
|
-
import { createEvent } from '../age-assurance/stash.js'
|
|
9
|
-
import { computeAgeAssuranceAccessOrThrow } from '../age-assurance/util.js'
|
|
10
|
-
import {
|
|
11
|
-
AppContextWithKwsClient,
|
|
12
|
-
KwsWebhookBody,
|
|
13
|
-
webhookBodyIntermediateSchema,
|
|
14
|
-
} from './types.js'
|
|
15
|
-
import {
|
|
16
|
-
createStashEvent,
|
|
17
|
-
kwsWwwAuthenticate,
|
|
18
|
-
validateSignature,
|
|
19
|
-
} from './util.js'
|
|
20
|
-
|
|
21
|
-
export const webhookAuth =
|
|
22
|
-
({ secret }: { secret: string }): RequestHandler =>
|
|
23
|
-
(req: express.Request, res: express.Response, next: express.NextFunction) => {
|
|
24
|
-
const body: Buffer = req.body
|
|
25
|
-
const sigHeader = req.headers['x-kws-signature']
|
|
26
|
-
if (!sigHeader || typeof sigHeader !== 'string') {
|
|
27
|
-
return res.status(401).header(kwsWwwAuthenticate()).json({
|
|
28
|
-
success: false,
|
|
29
|
-
error:
|
|
30
|
-
'Invalid authentication for KWS webhook: missing signature header',
|
|
31
|
-
})
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
try {
|
|
35
|
-
const parts = sigHeader.split(',')
|
|
36
|
-
const timestamp = parts.find((p) => p.startsWith('t='))?.split('=')[1]
|
|
37
|
-
const signature = parts.find((p) => p.startsWith('v1='))?.split('=')[1]
|
|
38
|
-
if (typeof timestamp !== 'string' || typeof signature !== 'string') {
|
|
39
|
-
throw new Error('Invalid webhook signature format')
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
const data = `${timestamp}.${body}`
|
|
43
|
-
validateSignature(secret, data, signature)
|
|
44
|
-
next()
|
|
45
|
-
} catch (err) {
|
|
46
|
-
log.error({ err }, 'Invalid KWS webhook signature')
|
|
47
|
-
return res.status(401).header(kwsWwwAuthenticate()).json({
|
|
48
|
-
success: false,
|
|
49
|
-
error: 'Invalid authentication for KWS webhook: signature mismatch',
|
|
50
|
-
})
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
type AgeAssuranceWebhookIntermediateBody = {
|
|
55
|
-
payload: Omit<KwsWebhookBody['payload'], 'externalPayload'> & {
|
|
56
|
-
externalPayload: string
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const parseBody = (serialized: string): AgeAssuranceWebhookIntermediateBody => {
|
|
61
|
-
try {
|
|
62
|
-
const value: unknown = JSON.parse(serialized)
|
|
63
|
-
return webhookBodyIntermediateSchema.parse(value)
|
|
64
|
-
} catch (err) {
|
|
65
|
-
throw new Error(`Invalid webhook body: ${serialized}`, { cause: err })
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
export const webhookHandler =
|
|
70
|
-
(ctx: AppContextWithKwsClient): RequestHandler =>
|
|
71
|
-
async (req: express.Request, res: express.Response) => {
|
|
72
|
-
let body: AgeAssuranceWebhookIntermediateBody
|
|
73
|
-
try {
|
|
74
|
-
body = parseBody(req.body)
|
|
75
|
-
} catch (err) {
|
|
76
|
-
log.error({ err }, 'Invalid KWS webhook body')
|
|
77
|
-
return res.status(400).json(err)
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
const { verified } = body.payload.status
|
|
81
|
-
if (!verified) {
|
|
82
|
-
throw new Error('Unexpected KWS webhook call with unverified status')
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const externalPayload = parseKWSExternalPayloadV1WithV2Compat(
|
|
86
|
-
body.payload.externalPayload,
|
|
87
|
-
)
|
|
88
|
-
const isV2 = externalPayload.version === KWSExternalPayloadVersion.V2
|
|
89
|
-
|
|
90
|
-
let result: ReturnType<typeof computeAgeAssuranceAccessOrThrow> | undefined
|
|
91
|
-
if (isV2) {
|
|
92
|
-
const { attemptId, actorDid, countryCode, regionCode } = externalPayload
|
|
93
|
-
try {
|
|
94
|
-
result = computeAgeAssuranceAccessOrThrow(AGE_ASSURANCE_CONFIG, {
|
|
95
|
-
countryCode: countryCode,
|
|
96
|
-
regionCode: regionCode,
|
|
97
|
-
verifiedMinimumAge: 18, // `adult-verified` is 18+ only
|
|
98
|
-
})
|
|
99
|
-
} catch (err) {
|
|
100
|
-
// internal errors
|
|
101
|
-
log.error(
|
|
102
|
-
{ err, attemptId, actorDid, countryCode, regionCode },
|
|
103
|
-
'Failed to compute age assurance access',
|
|
104
|
-
)
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
try {
|
|
109
|
-
if (isV2) {
|
|
110
|
-
if (result) {
|
|
111
|
-
const { attemptId, actorDid, countryCode, regionCode } =
|
|
112
|
-
externalPayload
|
|
113
|
-
await createEvent(ctx, actorDid, {
|
|
114
|
-
attemptId,
|
|
115
|
-
status: 'assured',
|
|
116
|
-
access: result.access,
|
|
117
|
-
countryCode,
|
|
118
|
-
regionCode,
|
|
119
|
-
})
|
|
120
|
-
} // else do nothing
|
|
121
|
-
} else {
|
|
122
|
-
const { attemptId, actorDid } = externalPayload
|
|
123
|
-
await createStashEvent(ctx, {
|
|
124
|
-
attemptId: attemptId,
|
|
125
|
-
actorDid: actorDid,
|
|
126
|
-
status: 'assured',
|
|
127
|
-
})
|
|
128
|
-
}
|
|
129
|
-
return res.status(200).end()
|
|
130
|
-
} catch (err) {
|
|
131
|
-
log.error({ err }, 'Failed to handle KWS webhook')
|
|
132
|
-
return res.status(500).json(err)
|
|
133
|
-
}
|
|
134
|
-
}
|
package/src/api/sitemap.ts
DELETED
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { Readable } from 'node:stream'
|
|
2
|
-
import { Timestamp } from '@bufbuild/protobuf'
|
|
3
|
-
import { Code, ConnectError } from '@connectrpc/connect'
|
|
4
|
-
import express, { RequestHandler, Router } from 'express'
|
|
5
|
-
import { AppContext } from '../context.js'
|
|
6
|
-
import { httpLogger as log } from '../logger.js'
|
|
7
|
-
import { SitemapPageType } from '../proto/bsky_pb.js'
|
|
8
|
-
|
|
9
|
-
export const createRouter = (ctx: AppContext): Router => {
|
|
10
|
-
const router = Router()
|
|
11
|
-
router.get('/external/sitemap/users.xml.gz', userIndexHandler(ctx))
|
|
12
|
-
router.get(
|
|
13
|
-
'/external/sitemap/users/:date/:bucket.xml.gz',
|
|
14
|
-
userPageHandler(ctx),
|
|
15
|
-
)
|
|
16
|
-
return router
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const userIndexHandler =
|
|
20
|
-
(ctx: AppContext): RequestHandler =>
|
|
21
|
-
async (_req: express.Request, res: express.Response) => {
|
|
22
|
-
try {
|
|
23
|
-
const result = await ctx.dataplane.getSitemapIndex({
|
|
24
|
-
type: SitemapPageType.USER,
|
|
25
|
-
})
|
|
26
|
-
res.set('Content-Type', 'application/gzip')
|
|
27
|
-
res.set('Content-Encoding', 'gzip')
|
|
28
|
-
Readable.from(Buffer.from(result.sitemap)).pipe(res)
|
|
29
|
-
} catch (err) {
|
|
30
|
-
log.error({ err }, 'failed to get sitemap index')
|
|
31
|
-
return res.status(500).send('Internal Server Error')
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const userPageHandler =
|
|
36
|
-
(ctx: AppContext): RequestHandler =>
|
|
37
|
-
async (req: express.Request, res: express.Response) => {
|
|
38
|
-
const { date, bucket } = req.params
|
|
39
|
-
|
|
40
|
-
// Parse date (YYYY-MM-DD format)
|
|
41
|
-
const dateParts = date.split('-')
|
|
42
|
-
if (dateParts.length !== 3) {
|
|
43
|
-
return res.status(400).send('Invalid date format. Expected YYYY-MM-DD')
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const year = parseInt(dateParts[0], 10)
|
|
47
|
-
const month = parseInt(dateParts[1], 10)
|
|
48
|
-
const day = parseInt(dateParts[2], 10)
|
|
49
|
-
|
|
50
|
-
if (isNaN(year) || isNaN(month) || isNaN(day)) {
|
|
51
|
-
return res.status(400).send('Invalid date format. Expected YYYY-MM-DD')
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Parse bucket (1-indexed)
|
|
55
|
-
const bucketNum = parseInt(bucket, 10)
|
|
56
|
-
if (isNaN(bucketNum) || bucketNum < 1) {
|
|
57
|
-
return res.status(400).send('Invalid bucket number')
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
try {
|
|
61
|
-
const result = await ctx.dataplane.getSitemapPage({
|
|
62
|
-
type: SitemapPageType.USER,
|
|
63
|
-
date: Timestamp.fromDate(new Date(year, month - 1, day)),
|
|
64
|
-
bucket: bucketNum,
|
|
65
|
-
})
|
|
66
|
-
res.set('Content-Type', 'application/gzip')
|
|
67
|
-
res.set('Content-Encoding', 'gzip')
|
|
68
|
-
Readable.from(Buffer.from(result.sitemap)).pipe(res)
|
|
69
|
-
} catch (err) {
|
|
70
|
-
if (err instanceof ConnectError && err.code === Code.NotFound) {
|
|
71
|
-
return res.status(404).send('Sitemap page not found')
|
|
72
|
-
}
|
|
73
|
-
log.error({ err }, 'failed to get sitemap page')
|
|
74
|
-
return res.status(500).send('Internal Server Error')
|
|
75
|
-
}
|
|
76
|
-
}
|
package/src/api/util.ts
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { IncomingHttpHeaders } from 'node:http'
|
|
2
|
-
import { ServerConfig } from '../config.js'
|
|
3
|
-
import { ParsedLabelers, formatLabelerHeader } from '../util.js'
|
|
4
|
-
|
|
5
|
-
export const BSKY_USER_AGENT = 'BskyAppView'
|
|
6
|
-
export const ATPROTO_CONTENT_LABELERS = 'Atproto-Content-Labelers'
|
|
7
|
-
export const ATPROTO_REPO_REV = 'Atproto-Repo-Rev'
|
|
8
|
-
|
|
9
|
-
type ResHeaderOpts = {
|
|
10
|
-
labelers: ParsedLabelers
|
|
11
|
-
repoRev: string | null
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const resHeaders = (
|
|
15
|
-
opts: Partial<ResHeaderOpts>,
|
|
16
|
-
): Record<string, string> => {
|
|
17
|
-
const headers = {}
|
|
18
|
-
if (opts.labelers) {
|
|
19
|
-
headers[ATPROTO_CONTENT_LABELERS] = formatLabelerHeader(opts.labelers)
|
|
20
|
-
}
|
|
21
|
-
if (opts.repoRev) {
|
|
22
|
-
headers[ATPROTO_REPO_REV] = opts.repoRev
|
|
23
|
-
}
|
|
24
|
-
return headers
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const clearlyBadCursor = (cursor?: string) => {
|
|
28
|
-
// hallmark of v1 cursor, highly unlikely in v2 cursors based on time or rkeys
|
|
29
|
-
return !!cursor?.includes('::')
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// @TEMPORARY backdoor to force search v2 via a request header, gated by the
|
|
33
|
-
// BSKY_SEARCH_V2_OVERRIDE_HEADER env var. Remove once search v2 is fully rolled out.
|
|
34
|
-
const SEARCH_V2_OVERRIDE_HEADER = 'x-bsky-search-v2-override'
|
|
35
|
-
|
|
36
|
-
export const resolveSearchV2Override = (
|
|
37
|
-
req: { headers: IncomingHttpHeaders },
|
|
38
|
-
cfg: ServerConfig,
|
|
39
|
-
): boolean => {
|
|
40
|
-
const expected = cfg.searchV2OverrideHeader
|
|
41
|
-
if (!expected) return false
|
|
42
|
-
const value = req.headers[SEARCH_V2_OVERRIDE_HEADER]
|
|
43
|
-
const header = Array.isArray(value) ? value.join(',') : value
|
|
44
|
-
return header === expected
|
|
45
|
-
}
|
package/src/api/well-known.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { Router } from 'express'
|
|
2
|
-
import { didWebToUrl, isDidWeb } from '@atproto/did'
|
|
3
|
-
import { AppContext } from '../context.js'
|
|
4
|
-
|
|
5
|
-
export const createRouter = (ctx: AppContext): Router => {
|
|
6
|
-
const router = Router()
|
|
7
|
-
|
|
8
|
-
const did = ctx.cfg.serverDid
|
|
9
|
-
if (isDidWeb(did)) {
|
|
10
|
-
const serviceEndpoint = didWebToUrl(did).origin
|
|
11
|
-
|
|
12
|
-
router.get('/.well-known/did.json', (_req, res) => {
|
|
13
|
-
res.json({
|
|
14
|
-
'@context': [
|
|
15
|
-
'https://www.w3.org/ns/did/v1',
|
|
16
|
-
'https://w3id.org/security/multikey/v1',
|
|
17
|
-
],
|
|
18
|
-
id: did,
|
|
19
|
-
verificationMethod: [
|
|
20
|
-
{
|
|
21
|
-
id: `${did}#atproto`,
|
|
22
|
-
type: 'Multikey',
|
|
23
|
-
controller: did,
|
|
24
|
-
publicKeyMultibase: ctx.signingKey.did().replace('did:key:', ''),
|
|
25
|
-
},
|
|
26
|
-
],
|
|
27
|
-
service: [
|
|
28
|
-
{
|
|
29
|
-
id: '#bsky_notif',
|
|
30
|
-
type: 'BskyNotificationService',
|
|
31
|
-
serviceEndpoint,
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
id: '#bsky_appview',
|
|
35
|
-
type: 'BskyAppView',
|
|
36
|
-
serviceEndpoint,
|
|
37
|
-
},
|
|
38
|
-
],
|
|
39
|
-
})
|
|
40
|
-
})
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
return router
|
|
44
|
-
}
|