Skip to content

feat: add publisher follow controls and discovery - #2957

Closed
giodl73-repo wants to merge 18 commits into
openclaw:mainfrom
giodl73-repo:follow-controls-discovery
Closed

giodl73-repo wants to merge 18 commits into
openclaw:mainfrom
giodl73-repo:follow-controls-discovery

Conversation

@giodl73-repo

@giodl73-repo giodl73-repo commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Adds Follow/Following controls to publisher profiles with GitHub sign-in gating and stable publisher-ownership self-follow suppression.
  • Adds a Creators > Following discovery tab backed by the publisher-only follow graph from feat: add private publisher follow graph #2950.
  • Uses the normalized nextCursor contract, hides the irrelevant grid/list toggle in Following, and avoids flashing signed-out content while auth is loading.
  • Removes notification language; following affects discovery, while activity delivery is handled by the timeline slice.

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)
  • Type-aware oxlint passes for the changed routes and tests.
  • oxfmt and git diff --check pass.

@vercel

vercel Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

@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.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. labels Jul 4, 2026
@clawsweeper

clawsweeper Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs real behavior proof before merge. Reviewed July 7, 2026, 11:42 PM ET / 03:42 UTC.

Summary
The branch adds publisher follow API state from its stack plus profile Follow/Following controls, a Creators Following discovery tab, tests, route constants, CSS, and a follow-graph spec.

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.

  • Diff size: +1768/-27 across 19 files. The change spans Convex schema/API, generated package files, specs, UI routes, route tests, and CSS.
  • Persistent table added: 1 Convex table added. The new publisherFollows table stores private user preference data and needs retention and auth-boundary review.
  • Stack dependency: 1 open prerequisite PR. The branch depends on an open proof-gated base API PR before this UI/discovery slice can be safely merged.

Root-cause cluster
Relationship: canonical
Canonical: #2957
Summary: This PR is the controls and discovery slice of an open stacked publisher-follow feature; the base API PR is a prerequisite and the notifications PR is a dependent follow-up.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🧂 unranked krab
Proof: 🧂 unranked krab
Patch quality: 🦐 gold shrimp
Result: blocked until real behavior proof is added.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P1] Add redacted real browser proof for the profile Follow/Following control and Creators Following tab, plus HTTP or Convex runtime output for the private follow API path.
  • After the base API PR lands or is updated, rebase this branch and rerun focused UI/API validation.
  • [P1] Regenerate the schema route sourcemap and add the public API docs/OpenAPI contract entry.

Proof guidance:

  • [P1] Needs real behavior proof before merge: The PR body and comments include no redacted browser proof, HTTP/Convex runtime output, terminal output, logs, recording, or linked artifact showing the follow controls, Following tab, or private follow API after the change. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.

Risk before merge

  • [P1] The PR has no redacted browser proof for the profile Follow/Following control or Creators Following tab and no live HTTP/Convex output proving the private follow API path.
  • [P1] The branch is stacked on feat: add private publisher follow graph #2950, which remains open, draft, and proof-gated, so this follow-up cannot be cleanly accepted as an independent slice yet.
  • [P1] GitHub currently reports this draft PR as conflicting, so maintainers need a refreshed merge result before trusting generated artifacts or current-main compatibility.
  • [P1] The new signed-in and API-token paths expose private per-user follow state, so auth scoping and own-user data boundaries remain merge-relevant until proven in a real runtime.
  • [P1] The public API contract docs/OpenAPI entry and generated schema sourcemap are still missing for the new route.

Maintainer options:

  1. Land the base API first (recommended)
    Require the prerequisite publisher-follow API PR to clear auth-boundary proof, public contract docs, generated artifacts, and merge conflicts before this UI slice is merged.
  2. Review the stack as one feature
    Maintainers may intentionally review the base API, controls, and notifications together with shared proof expectations for the private follow-state boundary.
  3. Pause this branch
    If the private follow API direction is not accepted, pause or close this follow-up instead of carrying a conflicting stacked UI branch.

Next step before merge

  • [P1] Manual review is needed because the remaining blockers are contributor proof, stacked dependency resolution, merge conflicts, and maintainer product/security-boundary acceptance rather than a narrow automated repair.

Maintainer decision needed

  • Question: Should ClawHub accept publisher-follow controls and discovery as core product/API surface now, and should this follow-up wait for feat: add private publisher follow graph #2950 to land first?
  • Rationale: This is a new user-facing feature over private follow-state data, so automation cannot approve the product/API boundary or stacked merge order without maintainer intent.
  • Likely owner: Patrick-Erichsen — Patrick-Erichsen has the strongest current-main ownership signal across the route/schema package, Convex HTTP routing, and creators/profile surfaces this feature extends.
  • Options:
    • Land the base API first (recommended): Require feat: add private publisher follow graph #2950 to clear proof, docs, and conflicts, then rebase and review this UI/discovery slice on top.
    • Review the stack together: Review the API, controls, and notification PRs as one feature stack while explicitly owning the private follow-state boundary together.
    • Pause the follow-up: Pause or close this follow-up if maintainers do not want the base follow API direction in core now.

Security
Cleared: No malicious or supply-chain issue was found, but the new private follow-state API remains security-boundary sensitive until auth-scoping proof is provided.

Review findings

  • [P3] Regenerate the route sourcemap — packages/schema/dist/routes.js:30
  • [P3] Add the public API contract docs — convex/http.ts:283-299
Review details

Best 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:

  • [P3] Regenerate the route sourcemap — packages/schema/dist/routes.js:30
    This prior finding remains at the same head. routes.js now exports publisherFollows, but routes.js.map still maps the old generated file shape while the JS keeps its sourceMappingURL comment, so schema package consumers get shifted debugger mappings.
    Confidence: 0.91
  • [P3] Add the public API contract docs — convex/http.ts:283-299
    This prior finding remains at the same head. The PR registers public /api/v1/publisher-follows routes, but it does not update public/api/v1/openapi.json or docs/http-api.md, leaving the shipped API usable but absent from the published contract.
    Confidence: 0.84

Overall correctness: patch is correct
Overall confidence: 0.78

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against dc0fd6d6c821.

Label changes

Label justifications:

  • P3: This is a draft optional discovery/notification feature stack, not an urgent regression or production incident.
  • merge-risk: 🚨 security-boundary: The branch adds API-token and signed-in access to private publisher-follow state, and green CI alone would not prove auth and own-user scoping.
  • rating: 🧂 unranked krab: Overall readiness is 🧂 unranked krab; proof is 🧂 unranked krab and patch quality is 🦐 gold shrimp.
  • status: 📣 needs proof: The PR needs real behavior proof before ClawSweeper can clear the contributor ask. Needs real behavior proof before merge: The PR body and comments include no redacted browser proof, HTTP/Convex runtime output, terminal output, logs, recording, or linked artifact showing the follow controls, Following tab, or private follow API after the change. After adding proof, update the PR body; ClawSweeper should re-review automatically. If it does not, the PR author or someone with repository write access can comment @clawsweeper re-review.
Evidence reviewed

What I checked:

  • Repository policy applied: AGENTS.md was read fully; its Convex runtime-validation, generated artifact, public API docs, retention, and real-browser proof guidance applies because this PR changes Convex schema/functions, HTTP routing, and UI. (AGENTS.md:58, dc0fd6d6c821)
  • Convex guidance applied: The checked-in Convex AI guidelines were read because the PR adds Convex functions and schema, including validators, indexed queries, pagination, and auth-sensitive function boundaries. (convex/_generated/ai/guidelines.md:1, dc0fd6d6c821)
  • Live PR state: GitHub reports this external PR is open, draft, conflicting, unchanged at head 1e0c5615a35145d6fea1f53ea5a4122d36bbf9b4, and +1768/-27 across 19 files with no maintainer reviews or assignees. (1e0c5615a351)
  • Current main lacks this feature: A current-main search found no publisherFollows module, /api/v1/publisher-follows route, follow-graph spec, or Follow/Following publisher controls, so the PR is not obsolete on main. (dc0fd6d6c821)
  • Follow API auth boundary: The PR head requires an API-token user for HTTP follow/list/unfollow and passes auth.userId to internal follow functions rather than accepting a caller-provided follower id. (convex/httpApiV1/publisherFollowsV1.ts:43, 1e0c5615a351)
  • Profile follow control: The PR head adds the publisher profile Follow/Following button, hides it for the viewer's own publisher profile, and gates anonymous clicks through GitHub sign-in. (src/routes/user/$handle.tsx:462, 1e0c5615a351)

Likely related people:

  • Patrick-Erichsen: Current-main blame and PR metadata tie the route constants, HTTP routing, creators route, publisher profile route, and generated schema baseline to this contributor. (role: API/schema and publisher route baseline contributor; confidence: high; commits: a230d962db64, 07e542f7e694; files: packages/schema/src/routes.ts, packages/schema/dist/routes.js, convex/http.ts)
  • fuller-stack-dev: Recent merged promotions work changed the same ApiRoutes, generated schema dist, and HTTP route areas this branch now conflicts around. (role: recent adjacent route/feed contributor; confidence: medium; commits: 265157057881; files: packages/schema/src/routes.ts, packages/schema/dist/routes.js, convex/http.ts)
  • vyctorbrzezowski: Recent publisher dashboard workspace work touched publisher-facing UI areas adjacent to the profile and discovery surfaces extended here. (role: recent adjacent publisher UI contributor; confidence: medium; commits: a89bfaf61d1b; files: src/routes/user/$handle.tsx, src/routes/creators/index.tsx)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

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
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (5 earlier review cycles)
  • reviewed 2026-07-04T08:26:09.376Z sha 1e0c5615a35145d6fea1f53ea5a4122d36bbf9b4 :: needs real behavior proof before merge. :: [P3] Regenerate the route sourcemap | [P3] Add the public API contract docs
  • reviewed 2026-07-06T23:15:10.746Z sha 1e0c5615a35145d6fea1f53ea5a4122d36bbf9b4 :: needs real behavior proof before merge. :: [P3] Regenerate the route sourcemap | [P3] Add the public API contract docs
  • reviewed 2026-07-07T01:13:15.550Z sha 1e0c5615a35145d6fea1f53ea5a4122d36bbf9b4 :: needs real behavior proof before merge. :: [P3] Regenerate the route sourcemap | [P3] Add the public API contract docs
  • reviewed 2026-07-08T02:05:31.237Z sha 1e0c5615a35145d6fea1f53ea5a4122d36bbf9b4 :: needs real behavior proof before merge. :: [P3] Regenerate the route sourcemap | [P3] Add the public API contract docs
  • reviewed 2026-07-08T02:13:23.566Z sha 1e0c5615a35145d6fea1f53ea5a4122d36bbf9b4 :: needs real behavior proof before merge. :: [P3] Regenerate the route sourcemap | [P3] Add the public API contract docs

@giodl73-repo
giodl73-repo force-pushed the follow-controls-discovery branch 2 times, most recently from f6f7bfc to bc067a9 Compare July 15, 2026 15:53
@giodl73-repo
giodl73-repo marked this pull request as ready for review July 15, 2026 16:11
@giodl73-repo
giodl73-repo requested review from a team and Patrick-Erichsen as code owners July 15, 2026 16:11

@Patrick-Erichsen Patrick-Erichsen left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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."),

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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.

Comment thread convex/httpApiV1/publisherFollowsV1.ts Outdated

function notificationsFromPayload(payload: Record<string, unknown>) {
const value =
typeof payload.notifications === "string" ? payload.notifications.trim() : undefined;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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 ? (

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[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

clawsweeper Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

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.

@giodl73-repo
giodl73-repo force-pushed the follow-controls-discovery branch from f5891c6 to 6599355 Compare July 16, 2026 15:03
@giodl73-repo
giodl73-repo force-pushed the follow-controls-discovery branch from 6599355 to 5dcbaf9 Compare July 16, 2026 15:19
@giodl73-repo
giodl73-repo force-pushed the follow-controls-discovery branch from 5dcbaf9 to 5b409f7 Compare July 16, 2026 16:07
@giodl73-repo
giodl73-repo force-pushed the follow-controls-discovery branch from 5b409f7 to 6cb040b Compare July 16, 2026 16:11
@giodl73-repo

Copy link
Copy Markdown
Contributor Author

Superseded by #2958, which now combines publisher follow controls/discovery with the pull-based followed-publisher activity timeline.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. P3 Low-priority cleanup, docs, polish, ergonomics, or speculative work. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants