Skip to content

feat: add publisher follow graph API#2950

Open
giodl73-repo wants to merge 14 commits into
openclaw:mainfrom
giodl73-repo:follow-graph-notifications
Open

feat: add publisher follow graph API#2950
giodl73-repo wants to merge 14 commits into
openclaw:mainfrom
giodl73-repo:follow-graph-notifications

Conversation

@giodl73-repo

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

Copy link
Copy Markdown

Summary

  • Adds publisher-only, idempotent follow/unfollow storage and authenticated current-user listing.
  • Adds public, cursor-paginated follower and following lists that expose publisher identities without leaking follower user IDs.
  • Uses ClawHub's canonical publisher visibility rules, rejects self-follow by stable ownership, and removes edges during account or publisher hard deletion in bounded resumable batches.
  • Documents the GET/POST/DELETE follow contract and public social graph in OpenAPI and docs/http-api.md.

Product boundary

Following is discovery state only. It does not grant official status, registry review, source trust, scan success, local approval, or install authority. Notification preferences were removed from this slice; publisher activity belongs in a pull-based timeline so high-volume publishers do not create notification fanout.

API

  • GET|POST|DELETE /api/v1/publisher-follows for the authenticated user's graph.
  • GET /api/v1/publishers/{publisherId}/followers for visible follower publishers.
  • GET /api/v1/publishers/{publisherId}/following for a personal publisher's visible follows.
  • List responses use nextCursor: string | null.

Validation

  • Focused Vitest: 28 passed (publisherFollows, HTTP account-feed/follow handlers, OpenAPI contract).
  • Type-aware oxlint passes for changed backend modules.
  • bun x tsc --noEmit reaches only the existing missing yauzl declaration in scripts/staging-seed/snapshotIo.ts.
  • bun run --cwd packages/schema build regenerated routes.js and its source map.
  • git diff --check passes.

@vercel

vercel Bot commented Jul 1, 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.

@giodl73-repo
giodl73-repo force-pushed the follow-graph-notifications branch from 26ccc1b to bbf3254 Compare July 3, 2026 03:37
@giodl73-repo giodl73-repo changed the title docs: add follow graph notifications spec feat: add publisher follow graph API Jul 3, 2026
@giodl73-repo

Copy link
Copy Markdown
Author

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@giodl73-repo

Copy link
Copy Markdown
Author

@clawsweeper re-review

@giodl73-repo
giodl73-repo force-pushed the follow-graph-notifications branch from bbf3254 to 9b8f03d Compare July 3, 2026 04:05
@clawsweeper

clawsweeper Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@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 8, 2026, 10:13 PM ET / 02:13 UTC.

Summary
The branch adds Convex publisher follow persistence, follow/list/unfollow functions, API-token GET/POST/DELETE HTTP handlers, route constants/generated types, focused tests, retention classification, and a follow-graph spec.

Reproducibility: not applicable. This PR adds a new publisher-follow API surface rather than fixing a current-main bug. Current main has no publisherFollows module or /api/v1/publisher-follows route to reproduce against.

Review metrics: 3 noteworthy metrics.

  • Diff size: +1034/-1 across 14 files. This is a non-trivial backend feature slice, so generated artifacts, runtime proof, and public contract coverage matter before merge.
  • Persistent state: 1 table added. The PR adds permanent private follow state and a retention classification.
  • HTTP surface: 3 methods on 1 new route. GET, POST, and DELETE on a new API-token route need public-contract docs and real behavior proof.

Root-cause cluster
Relationship: canonical
Canonical: #2950
Summary: This PR is the base publisher-follow API slice for the follow-graph stack; the related open PRs add dependent UI/discovery and notification behavior rather than replacing it.

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 terminal or live HTTP output for API-token follow, list, and unfollow against a real Convex runtime.
  • Regenerate packages/schema/dist/routes.js.map with the route dist JS/types.
  • Document /api/v1/publisher-follows in the HTTP API docs and OpenAPI spec.

Proof guidance:

  • [P1] Needs real behavior proof before merge: Missing: no redacted terminal output, live HTTP smoke, Convex runtime result, logs, or linked artifact shows API-token follow, own-user list, and unfollow 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 exposes private follow state through API-token HTTP routes, so merge should wait for proof that API-token follow, own-user list, and unfollow work against a real Convex runtime.
  • [P1] GitHub reports the draft PR as conflicting, so final review needs a refreshed merge result before maintainers can trust the current diff and generated artifact state.
  • [P1] The branch registers a new public HTTP route without public API docs/OpenAPI coverage and with a stale schema package sourcemap.

Maintainer options:

  1. Require API-token runtime proof (recommended)
    Ask for redacted terminal or live-output proof that an API token can follow, list only its own follows, and unfollow through /api/v1/publisher-follows against a real Convex runtime.
  2. Accept CI-only evidence deliberately
    Maintainers can intentionally accept unit and CI coverage as enough, but that owns the private-follow API boundary without contributor runtime proof.
  3. Pause the follow stack
    Pause this base slice until the stacked controls/discovery and notification PRs are reviewed together for the final follow product boundary.

Next step before merge

  • [P1] Human review is required because the remaining blockers are maintainer API-boundary acceptance, contributor runtime proof, conflict resolution, and public contract/generated artifact follow-up rather than a narrow automated repair.

Maintainer decision needed

  • Question: Should ClawHub accept this publisher-scoped follow graph API as core now, or pause it until the dependent controls/discovery and notification PRs are reviewed together?
  • Rationale: The patch creates a new private follow-state API and product boundary that automation cannot approve without maintainer intent, even though the implementation follows existing API-token patterns.
  • Likely owner: Patrick Erichsen — Patrick Erichsen has the strongest current-main ownership signal for the API route, schema package, retention, and Convex surfaces this PR changes.
  • Options:
    • Accept after proof and docs (recommended): Proceed with this base API once runtime proof, public contract docs, generated artifacts, and conflict resolution are complete.
    • Pause for stack review: Hold this base PR until the dependent controls/discovery and notification PRs are reviewed as one product boundary.
    • Decline this API shape: Close or redirect the stack if maintainers do not want publisher follow state exposed as a core ClawHub API now.

Security
Cleared: No malicious or supply-chain issue was found; the security-sensitive concern is the intended new private-state API boundary, which needs runtime proof and maintainer acceptance.

Review findings

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

Best possible solution:

Land this API slice only after maintainers accept the follow-graph boundary, the contributor adds redacted runtime proof for follow/list/unfollow, conflicts are resolved, and the public API docs/OpenAPI plus generated sourcemap are updated.

Do we have a high-confidence way to reproduce the issue?

Not applicable; this PR adds a new publisher-follow API surface rather than fixing a current-main bug. Current main has no publisherFollows module or /api/v1/publisher-follows route to reproduce against.

Is this the best way to solve the issue?

Unclear as final product direction; the backend shape follows existing API-token patterns, but public docs/OpenAPI, generated artifacts, conflict resolution, and real runtime proof are still needed before maintainable merge.

Full review comments:

  • [P3] Regenerate the route sourcemap — packages/schema/dist/routes.js:30
    routes.js now exports publisherFollows, but the committed routes.js.map still maps the previous source without this property. Because this package ships the dist sourcemap and the JS references it, consumers debugging clawhub-schema/routes will get shifted mappings until the dist JS/types/map are regenerated together.
    Confidence: 0.91
  • [P3] Document the public follow API — convex/http.ts:283-299
    This registers a new public /api/v1/publisher-follows route, but the branch does not add it to docs/http-api.md or public/api/v1/openapi.json. API consumers rely on those as the published contract, so the route would ship usable but undiscoverable and absent from generated OpenAPI clients.
    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 5d1506159dd9.

Label changes

Label justifications:

  • P3: This is a draft feature PR for a new discovery and notification preference API, not an urgent production regression.
  • merge-risk: 🚨 security-boundary: The PR exposes private follow state through API-token HTTP routes, and CI alone does not prove the runtime auth and own-user boundary.
  • 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: Missing: no redacted terminal output, live HTTP smoke, Convex runtime result, logs, or linked artifact shows API-token follow, own-user list, and unfollow 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 read: AGENTS.md was read fully and its Convex runtime-validation, generated artifact, retention, and public API documentation guidance applies to this PR. (AGENTS.md:1, 5d1506159dd9)
  • Convex guidance read: The checked-in Convex AI guidelines were read because the PR adds Convex schema, functions, and HTTP actions. (convex/_generated/ai/guidelines.md:1, 5d1506159dd9)
  • Live PR state: GitHub reports this external-authored PR open, draft, conflicting, at head 9b8f03d, with +1034/-1 across 14 files and no maintainer review or assignee. (9b8f03d538af)
  • Current main lacks the feature: A current-main search found no publisherFollows module, /api/v1/publisher-follows route, follow-graph spec, or publisher-follow symbol, so the PR is not obsolete on main. (5d1506159dd9)
  • Core implementation: PR head adds the idempotent follow/unfollow/list implementation over a new publisherFollows table with active-publisher checks and audit events. (convex/publisherFollows.ts:60, 9b8f03d538af)
  • HTTP auth boundary: The new HTTP handlers rate-limit, require the existing API-token user helper, and pass auth.userId into internal follow/list/unfollow calls instead of accepting a caller-supplied follower id. (convex/httpApiV1/publisherFollowsV1.ts:43, 9b8f03d538af)

Likely related people:

  • Patrick Erichsen: Current-main blame ties the adjacent API route cluster, schema package route constants, and retention policy area to Patrick Erichsen. (role: API/schema area contributor; confidence: high; commits: a230d962db64, 07e542f7e694; files: convex/http.ts, packages/schema/src/routes.ts, packages/schema/dist/routes.js)
  • Jason (Json): Recent current-main work added promotions API/feed routes in the same route constants and HTTP routing surface this PR extends. (role: recent adjacent route/feed contributor; confidence: medium; commits: 265157057881; files: packages/schema/src/routes.ts, packages/schema/dist/routes.js, convex/http.ts)
  • Jesse Merhi: Recent merged work touched publisher abuse and schema-adjacent Convex behavior near the publisher-scoped product area this API extends. (role: recent publisher-area contributor; confidence: medium; commits: 76b4f36bb0f7, 3ce0ce4ad6b5; files: convex/schema.ts, convex/publisherAbuse.ts, convex/lib/retentionPolicy.ts)
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 (6 earlier review cycles)
  • reviewed 2026-07-04T06:01:19.325Z sha 9b8f03d :: needs real behavior proof before merge. :: [P3] Regenerate the route sourcemap | [P3] Add the public API contract docs
  • reviewed 2026-07-04T08:18:58.858Z sha 9b8f03d :: needs real behavior proof before merge. :: [P3] Regenerate the route sourcemap | [P3] Add the public API contract docs
  • reviewed 2026-07-06T23:29:34.557Z sha 9b8f03d :: needs real behavior proof before merge. :: [P3] Regenerate the route sourcemap | [P3] Add the public API contract docs
  • reviewed 2026-07-06T23:59:37.987Z sha 9b8f03d :: needs real behavior proof before merge. :: [P3] Regenerate the route sourcemap | [P3] Add the public API contract docs
  • reviewed 2026-07-07T01:14:49.972Z sha 9b8f03d :: needs real behavior proof before merge. :: [P3] Regenerate the route sourcemap | [P3] Add the public API contract docs
  • reviewed 2026-07-08T01:54:15.330Z sha 9b8f03d :: 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-graph-notifications branch from 9b8f03d to 185bddc Compare July 15, 2026 15:34
@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.

This adds a private, authenticated publisher-follow graph with idempotent follow/unfollow, notification preferences, bounded listing, and API-token HTTP handlers. The authentication binding and separation from trust/install authority are sound, but the implementation does not yet preserve ClawHub's existing visibility and deletion invariants.

LOC: +1274/-1 (14 files)

Findings

  1. [P1] Apply linked-user visibility before accepting or returning personal publishers. requireActivePublisher, list filtering, and isFollowingPublisher only call isPublisherActive, which checks the publisher row's own deletion flags. ClawHub's canonical public publisher path also rejects a personal publisher whose linked user is deleted or deactivated, while user bans set users.deletedAt without deactivating the publisher row. As written, an authenticated caller who knows the publisher ID can follow a banned personal publisher and retrieve its handle, display name, kind, and image through the private list even though normal publisher visibility hides it. Extract/reuse the full publisher visibility check in follow, list, and isFollowingPublisher, and add linked-user ban/deactivation tests. convex/publisherFollows.ts:22 convex/publishers.ts:287 convex/users.ts:1730

  2. [P2] Purge private follow edges during account and publisher deletion. publisherFollows is classified as permanent preference data, but self-service account cleanup never removes rows owned by the deleted follower, and publisher hard deletion never removes rows targeting the deleted publisher. Those rows become permanently unreachable private social-graph data or dangling publisher references. Add bounded, resumable cleanup through the existing follower/publisher indexes, include counts in deletion audit metadata, and cover both lifecycle paths. convex/schema.ts:2693 convex/users.ts:353 convex/publishers.ts:2014

  3. [P2] Define and test the public HTTP contract, including terminal cursor shape. The three /api/v1/publisher-follows methods are absent from OpenAPI and docs/http-api.md. The HTTP handler also exposes the internal Convex { continueCursor, isDone } result verbatim, including continueCursor: "" at completion even though the request parser rejects an empty cursor; sibling HTTP APIs expose nextCursor: string | null. Add OpenAPI schemas/operations, contract tests, and docs, and normalize terminal pagination at the HTTP boundary (or explicitly specify and test a different public shape). convex/http.ts:318 convex/publisherFollows.ts:199 convex/httpApiV1/publisherFollowsV1.ts:41

  4. [P3] Regenerate the route sourcemap. The source, JS, and declarations contain publisherFollows, but the committed routes.js.map still maps the old route object. Running the schema build changes the map to include the new property. packages/schema/dist/routes.js:32

  5. [P3] Include ordering fields in the new index names. by_follower and by_publisher both include updatedAt; the checked-in Convex guidelines require index names to include every indexed field. Rename them to by_follower_and_updatedAt and by_publisher_and_updatedAt (or the repository's equivalent convention) and update callers. convex/schema.ts:2700

Best-fix verdict: too narrow. The follow module's idempotency, auth ownership, and bounded reads are reasonable, but the best implementation shares ClawHub's canonical publisher visibility/lifecycle rules with #2948 instead of creating a second publisher-active definition.

Alternatives considered: marking every personal publisher deleted when its user is banned is too broad for unban/recovery semantics; deleting follows on every reversible suspension is also too broad. Prefer a shared visibility helper for reversible states and bounded edge cleanup for permanent deletion.

Authority check: no caller or callee uses follow state to grant official status, publisher membership, publishing permission, registry review, scan success, source trust, local approval, package eligibility, or install authority.

Validation: focused exact-head tests pass (16 passed); static, unit, packages, types-build, e2e-http, and CodeQL are green. Exact-head CI is still unstable because playwright-local-auth / moderation-star failed in the unrelated malicious-skill ban flow (the same matrix failure is present on #2948), and the external Vercel authorization status is failing.

Stack/base: #2950 and dependency #2948 are sibling branches from base 35cd2e51, not a true stack. A synthetic merge conflicts in convex/http.ts, convex/httpApiV1.ts, and specs/README.md; rebase #2950 after #2948 and rerun exact-head CI.

Reviewed exact head b5519cb2e99eecc6215f4ab756d278cfcc0a9e0a; current main observed at 3134a20492f57423ad52ef8b017788a15b8aebd5.

@giodl73-repo
giodl73-repo force-pushed the follow-graph-notifications branch from b5519cb to 5557133 Compare July 16, 2026 14:58
@clawsweeper

clawsweeper Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper status: review started.

I am starting a fresh review of this pull request: feat: add publisher follow graph API This is item 1/1 in the current shard. Shard 10/19.

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.

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