Skip to content

Add admin-only community activity visibility - #794

Merged
kody-bot merged 11 commits into
mainfrom
cursor/kody-admin-community-activity-9b86
Jul 20, 2026
Merged

kody-bot merged 11 commits into
mainfrom
cursor/kody-admin-community-activity-9b86

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Jul 20, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • add admin_community_activity_list, a paginated admin-role-gated feed for fork and rating metadata
  • dispatch durable community.activity.recorded events only to admin-owned package subscriptions
  • preserve fork provenance after listing deletion with snapshotted public listing identity
  • migrate existing stable user IDs before deployment so actor usernames stay index-only
  • document the explicit cross-user boundary and provision the dedicated Queue/DLQ
  • pin fork-count behavior with real SQL and Worker-flow assertions

Authorization boundary

This is a narrow, documented exception to per-user isolation: admins receive activity metadata only—public listing id/name/kody id, acting username, timestamp, and rating scores. The capability and event omit package source, forked package/source ids, target ids, rating notes, email, stable user ids, secrets, private profiles, and unrelated account content. Execute-time capability access requires the admin role, and subscription fan-out reloads admin ownership for every Queue attempt.

The existing schema does not distinguish one-click installs from ordinary forks; both persist a community_forks row and are reported as fork. The exception is linked to the documented boundaries in project intent, authorization, and data storage.

Migration decisions

  • 0070-community-fork-listing-snapshots.sql rebuilds community_forks, backfills listing name/kody id, and works whether preview state already has the snapshot columns or production starts from the original schema.
  • Production deploys invoke the existing stable-user-id backfill endpoint before installing code that relies on the indexed username join. No new runtime scan/fallback path was added.
  • Fork rows intentionally survive listing deletion; the admin feed and queued events retain their public listing identity snapshots.

Fork-count verification

The aggregate SQL already counts community_forks correctly for every listing materialized by detail/search/browse loaders. The production mismatch is consistent with a snapshot/cache artifact, so this PR does not change aggregate logic; it adds real-SQL and Worker-flow regression assertions.

Verification

  • ✅ Validate passed
  • 🔎 Deploy Preview Resources passed
  • local unit/Workers suite: 308 files, 1,004 tests passed
  • local Playwright E2E: 18 passed
  • MCP E2E passed under the authoritative validation gate
  • npm run primitives:classify and npm run primitives:check passed
  • manual privacy-page walkthrough confirmed the disclosure is readable with no clipping or overflow

privacy-community-activity-disclosure.mp4

System recap — adds a new primitive (high risk)

Mode: recap · Base: main @ a270fcc · Head: b648fa6

Classification: adds — introduces a dedicated durable community-activity dispatch Queue; extends community listing persistence/metadata reads and the role-gated admin capability contract.

Primitives touched

Primitive Group Impact
community-activity-dispatch-queue storage adds — Queue, DLQ, consumer, and idempotent admin fan-out
community-listings assistant extends — admin activity projection, identity snapshots, and enqueue on fork/rating writes
d1-app-db storage extends — migration backfills fork listing snapshots
rbac auth extends — new admin-only cross-user metadata capability
capability-registry assistant extends — registers admin_community_activity_list
saved-packages assistant extends — subscription discovery documents the new topic
app-ui surfaces extends — public privacy disclosure
platform-feedback-dispatch-queue storage composes — shared Queue router/provisioning conventions

System map

Fork and rating writes persist in D1, enqueue opaque activity identifiers, and fan out a metadata-only event to freshly authorized admin package owners.

Legend: green = composes (wiring only) · amber = extended by this PR · red = new primitive · gray = context (unchanged, included only when an edge crosses it).

flowchart LR
	communityListings["community-listings<br/>Community package listings"]:::extended
	d1AppDb["d1-app-db<br/>D1 app database"]:::extended
	rbac["rbac<br/>Role-based access control"]:::extended
	capabilityRegistry["capability-registry<br/>Capability registry"]:::extended
	activityQueue["community-activity-dispatch-queue<br/>Community activity dispatch queue"]:::added
	savedPackages["saved-packages<br/>Saved packages"]:::extended
	communityListings -->|"fork/rating rows + listing snapshots"| d1AppDb
	communityListings -->|"fork/rating id after D1 write"| activityQueue
	capabilityRegistry -->|"admin_community_activity_list"| communityListings
	rbac -->|"requiredRole: admin"| capabilityRegistry
	activityQueue -->|"community.activity.recorded; fresh admin-owner lookup"| savedPackages
	classDef touched fill:#1a7f37,color:#fff
	classDef extended fill:#9a6700,color:#fff
	classDef added fill:#cf222e,color:#fff
	classDef untouched fill:#57606a,color:#fff
Loading

Before / after

Before After
Operator needed raw production SQL for fork/rating attribution Admin MCP feed exposes a fixed metadata allowlist
Deleting a listing hid retained fork provenance Snapshotted public listing identity keeps retained forks visible
Unmaterialized stable IDs could miss the username join Deploy migration materializes IDs before indexed reads
No community activity subscription event Durable admin-only community.activity.recorded delivery
Installs and forks indistinguishable in storage Explicitly reported as fork; no invented install classification

Invariants

  • Per-user isolation remains the default; this cross-user read is role-gated and documented as a narrow metadata exception.
  • No private package source, rating notes, email, stable user ids, private profiles, secrets, or unrelated account content cross the boundary.
  • Consumer-time admin-owner lookup makes revocation effective on the next Queue attempt.
Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features
    • Added an admin-only community activity feed for public listing forks/ratings with pagination and filtering.
    • Added durable admin-configured subscription notifications for newly recorded community activity.
  • Privacy
    • Expanded privacy guidance for metadata-only admin visibility around approved platform feedback and public community activity.
  • Bug Fixes
    • Clarified/corrected fork-count behavior to match live activity; added coverage for fork increments.
  • Documentation
    • Updated contributor, architecture, and package-subscription docs, plus the in-app privacy route text.
  • Chores
    • Added production deployment step to materialize stable user IDs and tightened required production environment variables/queue setup.

@coderabbitai

coderabbitai Bot commented Jul 20, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds role-gated admin activity listings for public community forks and ratings, metadata-only subscription events, durable queue processing with retry handling, and production Cloudflare queue provisioning. Documentation defines the privacy boundary, event payload, storage rules, and operational configuration.

Changes

Community activity projection

Layer / File(s) Summary
Activity types, persistence, and service APIs
packages/worker/src/community/types.ts, packages/worker/src/community/repo.ts, packages/worker/src/community/service.ts, packages/worker/migrations/*
Forks and latest ratings are normalized into a paginated, filterable admin feed; listing provenance is stored, and rating upserts return persisted records.
Projection and flow validation
packages/worker/src/community/*test.ts
Tests cover ordering, pagination, filtering, fork counts, rating updates, and activity records emitted by community flows.

Admin capability and privacy boundary

Layer / File(s) Summary
Admin activity capability
packages/worker/src/mcp/capabilities/admin/*, packages/worker/src/mcp/capabilities/admin-community-activity.node.test.ts
Adds admin_community_activity_list with admin-role enforcement, pagination and filters, metadata-only output, and audit logging.
Privacy and architecture documentation
docs/contributing/adding-capabilities.md, docs/contributing/architecture/*, docs/contributing/project-intent.md, docs/use/privacy.md, packages/worker/client/routes/privacy.tsx
Documents the narrow public-listing activity exception and excludes private source, notes, secrets, stable user IDs, email, and unrelated account content.

Activity events and subscription dispatch

Layer / File(s) Summary
Recording and event construction
packages/worker/src/community/activity-dispatch-queue-producer.ts, packages/worker/src/community/activity-subscription-event.ts, packages/worker/src/community/service.ts
Fork and rating writes enqueue identifiers, and event builders create discriminated metadata-only fork/rating payloads.
Subscription delivery and queue handling
packages/worker/src/community/activity-package-subscriptions.ts, packages/worker/src/community/activity-dispatch-queue.ts, packages/worker/src/community/*test.ts
Queue processing reloads activity metadata, dispatches to admin package subscribers, acknowledges invalid or cancelled messages, and retries transient failures.
Subscription documentation
docs/contributing/community-packages.md, docs/contributing/packages-and-manifests.md, docs/guides/package-subscriptions.md
Documents the topic, payload omissions, fresh admin-role resolution, idempotency, retry, and DLQ behavior.

Queue infrastructure

Layer / File(s) Summary
Worker routing and bindings
packages/worker/src/queue-handler.ts, packages/worker/worker-configuration.d.ts, packages/worker/wrangler.jsonc
Routes the new queue, adds its environment binding, and declares its producer, consumer, and DLQ.
Production resource validation and provisioning
tools/ci/production-queue-resources.ts, tools/ci/production-resources.ts, tools/ci/*test.ts, docs/contributing/setup-manifest.md, docs/contributing/architecture/primitives.yaml, .github/workflows/deploy.yml
Validates exactly three production consumers, provisions and reports the community activity queue resources, and materializes stable user IDs during deployment.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.35% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding admin-only visibility for community activity metadata.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/kody-admin-community-activity-9b86

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@kody-bot
kody-bot marked this pull request as ready for review July 20, 2026 02:51
…munity-activity-9b86

# Conflicts:
#	packages/worker/worker-configuration.d.ts
@github-actions

github-actions Bot commented Jul 20, 2026 •

Copy link
Copy Markdown
Contributor

🔎 Preview deployed: https://kody-pr-794.kody-a99.workers.dev

Worker: kody-pr-794
D1: kody-pr-794-db
KV: kody-pr-794-oauth-kv

Mocks:

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
packages/worker/src/community/activity-subscription-event.ts (1)

64-68: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Improve runtime error message formatting for object types.

When handling an unexpected activity kind at runtime, String(exhaustive) will output [object Object], making debugging difficult. Consider using JSON.stringify to capture the actual object contents.

♻️ Proposed refactor
 		default: {
 			const exhaustive: never = input.activity
-			throw new Error(`Unsupported community activity: ${String(exhaustive)}`)
+			throw new Error(`Unsupported community activity: ${JSON.stringify(exhaustive)}`)
 		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/worker/src/community/activity-subscription-event.ts` around lines 64
- 68, Update the default branch of the activity handling switch to serialize
unexpected object-valued activities with JSON.stringify instead of
String(exhaustive), preserving the existing “Unsupported community activity”
context and exhaustive type check.
packages/worker/src/community/service.ts (1)

111-125: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add correlation context to the swallowed enqueue failure.

console.error('community-activity-dispatch-enqueue-failed', error) doesn't include kind/activityId, so a failed dispatch can't be traced back to which fork/rating never got a queued admin notification.

♻️ Proposed fix
 	} catch (error) {
-		console.error('community-activity-dispatch-enqueue-failed', error)
+		console.error('community-activity-dispatch-enqueue-failed', {
+			kind: input.kind,
+			activityId: input.activityId,
+			error,
+		})
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/worker/src/community/service.ts` around lines 111 - 125, Update
enqueueRecordedCommunityActivity so its failure log includes the relevant
correlation context, specifically input.kind and input.activityId, alongside the
existing error while preserving the current swallowed-error behavior.
packages/worker/src/mcp/capabilities/admin-community-activity.node.test.ts (1)

39-56: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Exclusion assertions don't actually exercise the privacy filter.

The mocked service result never includes note/user_id/package_source to begin with, and formatCommunityActivity only ever whitelists specific fields (no spread), so result.activity[0]).not.toHaveProperty(...) at Lines 93-95 will pass regardless of whether the filtering logic is correct. To make this a meaningful regression guard, include those sensitive-looking fields in the mocked record and assert they're stripped from the formatted output. Also consider adding a kind: 'fork' case, since only the rating branch is currently exercised.

♻️ Suggested strengthening of the mock/assertions
 	mocks.listCommunityActivityForAdmin.mockResolvedValue({
 		total: 3,
 		page: 2,
 		pageSize: 2,
 		items: [
 			{
 				id: 'rating-1',
 				kind: 'rating',
 				listingId: 'listing-1',
 				listingName: '`@owner/package`',
 				listingKodyId: 'package',
 				actingUsername: 'rater',
 				occurredAt: '2026-07-20T01:00:00.000Z',
 				stars: 5,
 				adaptationEffort: 2,
+				note: 'private rating note',
+				userId: 'rater-user-id',
+				packageSource: 'private source blob',
 			},
 		],
 	})

Also applies to: 93-95

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/worker/src/mcp/capabilities/admin-community-activity.node.test.ts`
around lines 39 - 56, Strengthen the tests around formatCommunityActivity by
adding note, user_id, and package_source to the mocked activity record, then
assert those fields are absent from result.activity[0] after formatting. Add a
separate kind: 'fork' fixture or case so the fork-specific formatting branch is
exercised, while preserving the existing rating assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/worker/src/community/repo.ts`:
- Around line 181-211: Update communityActivityUnion’s fork activity query to
preserve fork events after their listing is deleted: replace the
community_listings INNER JOIN with a LEFT JOIN and provide appropriate
placeholders for missing listing fields, or ensure deleteCommunityListing
removes associated community_forks rows if fork history should not survive.

---

Nitpick comments:
In `@packages/worker/src/community/activity-subscription-event.ts`:
- Around line 64-68: Update the default branch of the activity handling switch
to serialize unexpected object-valued activities with JSON.stringify instead of
String(exhaustive), preserving the existing “Unsupported community activity”
context and exhaustive type check.

In `@packages/worker/src/community/service.ts`:
- Around line 111-125: Update enqueueRecordedCommunityActivity so its failure
log includes the relevant correlation context, specifically input.kind and
input.activityId, alongside the existing error while preserving the current
swallowed-error behavior.

In `@packages/worker/src/mcp/capabilities/admin-community-activity.node.test.ts`:
- Around line 39-56: Strengthen the tests around formatCommunityActivity by
adding note, user_id, and package_source to the mocked activity record, then
assert those fields are absent from result.activity[0] after formatting. Add a
separate kind: 'fork' fixture or case so the fork-specific formatting branch is
exercised, while preserving the existing rating assertions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: f5df1425-85ff-4f44-913d-2a49249604bb

📥 Commits

Reviewing files that changed from the base of the PR and between 21a3a7b and a86c600.

📒 Files selected for processing (37)
  • docs/contributing/adding-capabilities.md
  • docs/contributing/architecture/authorization.md
  • docs/contributing/architecture/data-storage.md
  • docs/contributing/architecture/primitives.yaml
  • docs/contributing/community-packages.md
  • docs/contributing/packages-and-manifests.md
  • docs/contributing/project-intent.md
  • docs/contributing/setup-manifest.md
  • docs/guides/package-subscriptions.md
  • docs/use/privacy.md
  • packages/worker/client/routes/privacy.tsx
  • packages/worker/src/community/activity-dispatch-queue-names.ts
  • packages/worker/src/community/activity-dispatch-queue-producer.ts
  • packages/worker/src/community/activity-dispatch-queue.node.test.ts
  • packages/worker/src/community/activity-dispatch-queue.ts
  • packages/worker/src/community/activity-package-subscriptions.node.test.ts
  • packages/worker/src/community/activity-package-subscriptions.ts
  • packages/worker/src/community/activity-subscription-event.ts
  • packages/worker/src/community/community-activity-service.node.test.ts
  • packages/worker/src/community/community-flow-test-schema.ts
  • packages/worker/src/community/community-flow.workers.test.ts
  • packages/worker/src/community/community-service.node.test.ts
  • packages/worker/src/community/errors.ts
  • packages/worker/src/community/repo.ts
  • packages/worker/src/community/service.ts
  • packages/worker/src/community/types.ts
  • packages/worker/src/mcp/capabilities/admin-community-activity.node.test.ts
  • packages/worker/src/mcp/capabilities/admin/admin-community-activity-list.ts
  • packages/worker/src/mcp/capabilities/admin/domain.ts
  • packages/worker/src/mcp/capabilities/packages/list-package-subscriptions.ts
  • packages/worker/src/queue-handler.node.test.ts
  • packages/worker/src/queue-handler.ts
  • packages/worker/worker-configuration.d.ts
  • packages/worker/wrangler.jsonc
  • tools/ci/production-queue-resources.node.test.ts
  • tools/ci/production-queue-resources.ts
  • tools/ci/production-resources.ts

Comment thread packages/worker/src/community/repo.ts

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 82f80b1. Configure here.

Comment thread packages/worker/src/community/repo.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/worker/migrations/0068-community-fork-listing-snapshots.sql (1)

4-15: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Prefer UPDATE ... FROM here. SQLite/D1 supports join-updates, so this can replace the two correlated subqueries and avoid per-row repetition.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/worker/migrations/0068-community-fork-listing-snapshots.sql` around
lines 4 - 15, Rewrite the community_forks update using SQLite/D1’s UPDATE ...
FROM join syntax, joining community_listings to community_forks via listing_id.
Set both listing_name and listing_kody_id from the joined community_listings
row, and remove the two correlated subqueries.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/worker/migrations/0068-community-fork-listing-snapshots.sql`:
- Around line 4-15: Rewrite the community_forks update using SQLite/D1’s UPDATE
... FROM join syntax, joining community_listings to community_forks via
listing_id. Set both listing_name and listing_kody_id from the joined
community_listings row, and remove the two correlated subqueries.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 260411e5-1650-4452-89f1-ea82676c39d8

📥 Commits

Reviewing files that changed from the base of the PR and between a86c600 and 8d0ffc4.

📒 Files selected for processing (14)
  • docs/contributing/architecture/authorization.md
  • docs/contributing/architecture/data-storage.md
  • docs/contributing/architecture/primitives.yaml
  • docs/contributing/community-packages.md
  • docs/contributing/setup-manifest.md
  • packages/worker/migrations/0068-community-fork-listing-snapshots.sql
  • packages/worker/src/community/community-activity-service.node.test.ts
  • packages/worker/src/community/community-flow-test-schema.ts
  • packages/worker/src/community/community-service.node.test.ts
  • packages/worker/src/community/repo.ts
  • packages/worker/src/community/service.ts
  • packages/worker/src/community/types.ts
  • packages/worker/worker-configuration.d.ts
  • packages/worker/wrangler.jsonc
🚧 Files skipped from review as they are similar to previous changes (11)
  • docs/contributing/architecture/primitives.yaml
  • packages/worker/worker-configuration.d.ts
  • packages/worker/wrangler.jsonc
  • docs/contributing/setup-manifest.md
  • docs/contributing/architecture/data-storage.md
  • packages/worker/src/community/types.ts
  • docs/contributing/architecture/authorization.md
  • packages/worker/src/community/community-service.node.test.ts
  • docs/contributing/community-packages.md
  • packages/worker/src/community/service.ts
  • packages/worker/src/community/repo.ts

@kody-bot
kody-bot merged commit 07e85d8 into main Jul 20, 2026
5 checks passed
@kody-bot
kody-bot deleted the cursor/kody-admin-community-activity-9b86 branch July 20, 2026 04:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants