feat: add publisher follow controls and discovery - #2957
giodl73-repo wants to merge 18 commits into
Conversation
|
@giodl73-repo is attempting to deploy a commit to the OpenClaw Foundation Team on Vercel. A member of the Team first needs to authorize it. |
|
Codex review: needs real behavior proof before merge. Reviewed July 7, 2026, 11:42 PM ET / 03:42 UTC. Summary Reproducibility: not applicable. This PR adds a new publisher-follow feature surface rather than fixing a current-main bug. The claimed behavior is inspectable from the PR body and source diff, but it needs real behavior proof rather than a bug reproduction path. Review metrics: 3 noteworthy metrics.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review findings
Review detailsBest possible solution: Land or explicitly approve the base publisher-follow API first, then rebase this UI/discovery slice, add redacted browser plus HTTP/Convex proof, and update public API docs/OpenAPI plus the generated schema sourcemap before merge. Do we have a high-confidence way to reproduce the issue? Not applicable; this PR adds a new publisher-follow feature surface rather than fixing a current-main bug. The claimed behavior is inspectable from the PR body and source diff, but it needs real behavior proof rather than a bug reproduction path. Is this the best way to solve the issue? Unclear as merge-ready; the UI/API shape is plausible, but the stack needs base API resolution, conflict cleanup, public contract consistency, generated artifact cleanup, and real runtime/browser proof before maintainers can accept it. Full review comments:
Overall correctness: patch is correct AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against dc0fd6d6c821. Label changesLabel justifications:
Evidence reviewedWhat I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (5 earlier review cycles)
|
f6f7bfc to
bc067a9
Compare
Patrick-Erichsen
left a comment
There was a problem hiding this comment.
Deep review of the exact head. The follow-state auth boundary is correctly private, and I found no wording or behavior that treats following as trust, approval, official status, review status, or install authority. The concrete issues are inline. Also verified the already-reported contract blockers remain: /api/v1/publisher-follows is absent from docs/http-api.md and public/api/v1/openapi.json, and packages/schema/dist/routes.js.map is stale. Exact-head pr-gates is currently red because src/styles.css fails oxfmt --check.
| @@ -209,6 +209,7 @@ export const RETENTION_POLICIES = { | |||
| catalogFeedPublications: permanent("Current published hosted catalog feed snapshot."), | |||
| stars: permanent("User star records."), | |||
| promotions: permanent("Curated promotional offers; ended records stay for launch-page history."), | |||
| publisherFollows: permanent("User publisher follow preference records."), | |||
There was a problem hiding this comment.
[P1] Clean follow rows when either identity is hard-deleted. These records are permanent, but hardDeleteSelfDeletedAccountState never deletes rows through by_follower, and hardDeletePublisherRows never deletes rows through by_publisher. Account deletion therefore retains the user's private follow graph indefinitely, while publisher deletion leaves dangling follow rows. Please wire both indexed cleanup paths into the existing hard-delete flows and cover them with deletion tests; durable audit logs can remain separate.
| const followPublisherHandle = publisher?.handle ?? handle; | ||
| const isFollowingPublisher = useQuery( | ||
| api.publisherFollows.isFollowingPublisher, | ||
| isAuthenticated && followPublisherId && !viewerIsPublisher |
There was a problem hiding this comment.
[P2] Use stable publisher ownership for this gate. The repo explicitly supports a personal publisher handle differing from its linked user's handle, but viewerIsPublisher only compares handles. In that supported state the owner sees Edit/Add plus Follow on their own publisher and can create a self-follow. Gate both this query and the control with viewerOwnsPersonalPublisher or the linked user/personal publisher id, and add the differing-handle case to the route test.
|
|
||
| function notificationsFromPayload(payload: Record<string, unknown>) { | ||
| const value = | ||
| typeof payload.notifications === "string" ? payload.notifications.trim() : undefined; |
There was a problem hiding this comment.
[P2] Reject malformed values when the field is present. A body such as {"publisherId":"...","notifications":false} currently treats false as omission and creates the follow with the default all notification preference. Distinguish an absent property from a present non-string/empty value and return 400 unless the value is exactly all or none; add cases for null, boolean, numeric, and empty-string inputs.
| @@ -341,7 +490,18 @@ function PublishersIndex() { | |||
|
|
|||
| <div className="browse-layout"> | |||
| <div className="browse-results"> | |||
| {highlightedPublishers.length > 0 ? ( | |||
| {followingOnly ? ( | |||
There was a problem hiding this comment.
[P2] The view toggle becomes a no-op on the Following tab. It still updates view=grid and shows Grid as selected, but this branch always renders FollowedPublisherDiscovery as list markup, so the visible layout never changes. Hide/disable the toggle while Following is active, or pass the selected variant through and implement the grid rendering.
| {highlightedPublishers.length > 0 ? ( | ||
| {followingOnly ? ( | ||
| <FollowedPublisherDiscovery | ||
| authenticated={isAuthenticated} |
There was a problem hiding this comment.
[P3] Preserve the auth-loading state here. useAuthStatus() reports isAuthenticated=false while hydration is still loading, so a signed-in visitor to ?following=true briefly receives the signed-out 'Sign in to see publishers you follow' state. Pass isLoading into this component and render its loading placeholder before deciding the viewer is anonymous; cover the transition in the route test.
|
ClawSweeper status: review started. I am starting a fresh review of this pull request: feat: add publisher follow controls and discovery This is item 1/1 in the current shard. Shard 2/4. This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking. Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted. |
f5891c6 to
6599355
Compare
6599355 to
5dcbaf9
Compare
5dcbaf9 to
5b409f7
Compare
5b409f7 to
6cb040b
Compare
|
Superseded by #2958, which now combines publisher follow controls/discovery with the pull-based followed-publisher activity timeline. |
Summary
nextCursorcontract, hides the irrelevant grid/list toggle in Following, and avoids flashing signed-out content while auth is loading.Dependency
Depends on #2950. This branch is restacked on the corrected public-social-graph implementation.
Boundary
Following does not mark a publisher, artifact, feed, or install path official, reviewed, trusted, or installable.
Validation
bun x vitest run src/__tests__/creators-route.test.tsx src/__tests__/user-profile-route.test.tsx(36 passed)oxfmtandgit diff --checkpass.