feat(streams): add starter_pack user stream source with tag-aware IDs - #2391
Open
Orlandohub wants to merge 2 commits into
Open
feat(streams): add starter_pack user stream source with tag-aware IDs#2391Orlandohub wants to merge 2 commits into
Orlandohub wants to merge 2 commits into
Conversation
Adds a 4-part user stream ID format (source:all:all:tag1,tag2) so starter pack results can be cached per ordered tag list in Dexie. While Nexus staging lacks the starter_pack source, a config flag keeps IDs in a starter_pack_mock namespace served by most_followed, so stale mock rows can never satisfy live requests after the swap (#2390). Changes: - buildStarterPackStreamId helper: canonicalizes (trim/lowercase) and validates tags (1-5, 1-20 chars, no banned chars) via Err.validation - createUserStreamParams: parse/validate 4-part starter pack IDs, enforce all:all segments, reject noncanonical hand-built IDs - NexusUserStreamService.fetch: dispatch starter_pack (live URL with tags param) and starter_pack_mock (most_followed, no tags param) - STARTER_PACK_SOURCE_LIVE flag + STARTER_PACK_MAX_TAGS in config - Tests: helper/parser/dispatch coverage + Dexie row isolation and mock-to-live swap regression at the application layer Refs: #2386
Contributor
Greptile SummaryAdds tag-aware starter-pack user stream identifiers, parsing, Nexus dispatch, and isolated Dexie cache keys while temporarily routing the feature through
Confidence Score: 5/5The PR appears safe to merge; no concrete blocking or independently actionable non-blocking issue was identified. The builder, parser, Nexus dispatch, and local cache all preserve the full ordered stream identity, while the temporary mock behavior consistently and intentionally aliases every tag selection to
|
| Filename | Overview |
|---|---|
| src/config/nexus.ts | Adds the backend tag limit and temporary live-source feature flag with explicit mock-to-live cache isolation. |
| src/core/models/stream/user/userStream.helper.ts | Adds the canonical starter-pack stream-ID builder and validates tag count and labels. |
| src/core/models/stream/user/userStream.types.ts | Extends user stream identifiers with distinct live and mock starter-pack namespaces. |
| src/core/services/nexus/stream/users/userStream.utils.ts | Parses and validates four-part starter-pack IDs and produces source-specific Nexus parameters. |
| src/core/services/nexus/stream/users/userStream.ts | Dispatches live starter packs to the new endpoint and temporary mock streams to most_followed. |
| src/core/services/nexus/stream/users/userStream.api.ts | Adds URL construction for Nexus starter-pack requests. |
| src/core/application/stream/users/users.test.ts | Verifies tag-order and mock/live namespaces remain isolated in Dexie. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart LR
Tags["Ordered interest tags"] --> Builder["buildStarterPackStreamId"]
Builder --> MockId["starter_pack_mock:all:all:tags"]
Builder -. "when live flag flips" .-> LiveId["starter_pack:all:all:tags"]
MockId --> Parser["createUserStreamParams"]
LiveId --> Parser
Parser --> MockApi["most_followed request<br/>without tags"]
Parser --> LiveApi["starter_pack request<br/>with ordered tags"]
MockApi --> Nexus["Nexus"]
LiveApi --> Nexus
Nexus --> Dexie["Dexie row keyed by full stream ID"]
Reviews (1): Last reviewed commit: "feat(streams): add starter_pack user str..." | Re-trigger Greptile
Contributor
🚀 Preview DeploymentURL: https://pubky-app-pr-2391-fzxmjul7ya-oa.a.run.app
|
7 tasks
pubky/pubky-nexus#1024 is live on staging (verified: 200 with ordered comma-separated tags, 400 when tags are missing), so the temporary STARTER_PACK_SOURCE_LIVE flag, the starter_pack_mock cache namespace, and the most_followed aliasing are no longer needed. Supersedes #2390.
6 tasks
infin1t3
self-requested a review
August 24, 2026 06:09
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
source:all:all:tag1,tag2) so recommendations for an ordered tag list get their own Dexie cache row.source=starter_packdirectly: feat(api): starter pack stream, users by interest tags pubky-nexus#1024 is deployed on staging (verified 2026-08-21 — 200 with ordered comma-separatedtags, 400 whentagsis missing). An earlier revision of this PR shipped a temporarystarter_pack_mocknamespace behind aSTARTER_PACK_SOURCE_LIVEflag; that machinery was removed in 57f2a7e once staging went live, which also made [Task]: Starter Packs — swap to live starter_pack source + E2E happy path #2390 (the swap issue) unnecessary.buildStarterPackStreamIdwithout touching service internals.Changes
buildStarterPackStreamId(tags)(model helper): canonicalizes labels (trim/lowercase) and validates the full tag contract (1–5 tags, 1–20 chars, no banned chars) viaErr.validation; emitsstarter_pack:all:all:<tags>.createUserStreamParams: parses 4-part starter pack IDs, enforcesall:alltimeframe/reach segments, rejects noncanonical hand-built IDs; invalid-format fallthrough converted from rawErrortoErr.validation.NexusUserStreamService.fetch: dispatchesstarter_pack→ newuserStreamApi.starterPack(source=starter_pack&tags=…); switch default is now anever-checkedErr.validation.STARTER_PACK_MAX_TAGS = 5(Nexus contract) insrc/config/nexus.ts.StarterPackStreamIdextends theUserStreamIdunion;STARTER_PACKenum member andTUserStreamStarterPackParamsin the Nexus service types.Test plan
npm run typecheck— cleanall:allsegment enforcement, invalid timeframe/reach/source/label cases withAppErrorcategory/code assertionssource=starter_pack&tags=…via mockedqueryNexus; endpoint count 10 → 11GET /v0/stream/users/ids?source=starter_pack&tags=bitcoin,art,music→ 200 with user IDs; missingtags→ 400Notes