Skip to content

Derive community listing icons from the package's published commit - #725

Merged
kody-bot merged 2 commits into
mainfrom
cursor/fix-community-icon-cache-stale-after-publish-d78e
Jul 11, 2026
Merged

kody-bot merged 2 commits into
mainfrom
cursor/fix-community-icon-cache-stale-after-publish-d78e

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Jul 11, 2026 •

Copy link
Copy Markdown
Member

Problem

Publishing updated community-icon.* files on a saved package (e.g. via package_publish_external_push) never became visible on the public community pages. Confirmed in production for kit, hydrawise, transistor, venstar, and google: the packages' Artifacts HEAD carried the new icons (published 2026-07-11 05:34 UTC), while /community/:listingId kept serving icons for the pinned commit from 2026-07-10.

Root cause: community icon URLs, KV descriptors (~30-day TTL), and R2 assets were all keyed by the listing's pinned snapshot commit, which only moves on an explicit community_publish. A package publish updated entity_sources.published_commit but nothing about the listing icon, so every cache layer kept the stale key alive indefinitely — shorter TTLs would not have fixed this, since the URL itself never changed.

Fix

The listing icon now tracks an icon commit: the owner package's current published commit, falling back to the pinned commit when the package source row is gone.

  • Community listing reads LEFT JOIN entity_sources (scoped to owner + package) and expose iconCommit on CommunityListingRecord.
  • Icon URLs are /community/:listingId/icon/:iconCommit; KV descriptors and R2 assets are keyed by the same commit, so a package publish busts every cache layer by key change (content identity, not TTL).
  • The icon route serves the current icon commit or the pinned snapshot commit and 404s stale commits, matching prior semantics.
  • Descriptor generation reads community-icon.* from the Artifacts repo at the icon commit via a new readFirstArtifactFileAtCommit (one shallow fetch, candidate paths probed in priority order); pinned-commit requests keep the snapshot fast path for SVGs.
  • finalizePublishedEntitySource (external push + repo-session publish lanes) calls a new best-effort refreshCommunityIconForPackagePublish: prunes superseded KV/R2 icon entries by listing prefix and invalidates the public listing data cache.
  • Republish/unpublish/admin hard delete prune all icon entries by listing prefix; account deletion removes pinned + icon commit keys derived from D1.

Note for the affected packages: kit, hydrawise, and transistor added community-icon.png while leaving the old community-icon.svg in place — svg wins by documented priority, so those repos also need the stale svg deleted (handled as post-deploy verification, not in this PR). Docs now warn about this trap.

Testing

  • Unit tests updated + new coverage: icon generation at an ahead-of-snapshot commit, prefix pruning with keep-commits, the package-publish hook (active listing, no-op without one), publish-lane invocation, handler acceptance of icon/pinned commits and 404 for stale, and account-deletion key derivation via the join.
  • npm run validate green locally (format, lint, typecheck, 809 unit tests, 13 Playwright E2E, MCP E2E), re-ran unit suite after rebasing onto main.
System recap — extends existing primitives (medium risk)

Mode: recap · Base: main @ ff425827 · Head: 2b919149

Classification: extends — the community listing read model and icon cache contract change shape (icon commit joins the package source); no new primitives.

Primitives touched

Primitive Group Impact
community-listings assistant extends — listing reads join entity_sources; icon route param is the icon commit
community-assets-r2 storage extends — keys move from pinned commit to pinned-or-icon commit; prefix pruning
bundle-artifacts-kv storage composes — descriptor keys follow the icon commit; prefix pruning
artifacts-repos storage composes — readFirstArtifactFileAtCommit probes icon paths in one fetch
repo-sessions assistant composes — publish lanes call the community icon refresh hook
account-export assistant composes — account deletion derives icon commit keys via the same join

System map

A package publish flows through the publish finalizer into the community icon cache, and public listing reads now join the package source to build icon URLs.

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
	repoSessions["repo-sessions<br/>Repo-backed editing sessions"]:::touched
	communityListings["community-listings<br/>Community package listings"]:::extended
	communityAssetsR2["community-assets-r2<br/>Community asset storage (R2)"]:::extended
	bundleArtifactsKv["bundle-artifacts-kv<br/>Bundle artifacts KV"]:::touched
	artifactsRepos["artifacts-repos<br/>Artifacts source repos"]:::touched
	d1AppDb["d1-app-db<br/>D1 app database"]:::untouched
	repoSessions -->|"finalizePublishedEntitySource → refreshCommunityIconForPackagePublish"| communityListings
	communityListings -->|"LEFT JOIN entity_sources.published_commit AS iconCommit"| d1AppDb
	communityListings -->|"prune + write community-icon:v1/{listingId}/{commit}/asset"| communityAssetsR2
	communityListings -->|"descriptor derived-cache:v1:community-icon:v1:{listingId}:{commit}"| bundleArtifactsKv
	communityListings -->|"readFirstArtifactFileAtCommit(community-icon.*) @ iconCommit"| artifactsRepos
	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: /community/:listingId/icon/:pinnedCommit   (moves only on community_publish)
after:  /community/:listingId/icon/:iconCommit     (moves on every package publish;
                                                    pinned commit stays servable)

Invariants

Per-user isolation: the entity_sources join is constrained to the listing's owner_user_id, entity_kind = 'package', and package_id, so a foreign source row can never contribute a commit (or icon bytes) to another user's listing. The icon read path keeps the existing owner/package/source validation before touching the Artifacts repo.

Open in Web Open in Cursor 

Summary by CodeRabbit

  • New Features
    • Community listing icons now automatically refresh when a package is published.
    • Icon URLs now use the current package commit (with fallback to the pinned snapshot commit), supporting prioritized icon filename selection.
  • Bug Fixes
    • Prevents stale or mismatched commit URLs from serving incorrect icons.
    • Account deletion, unpublish, and hard delete now remove community icon assets/caches for both pinned and icon commits.
  • Documentation
    • Updated guidance covering icon derivation, storage keying, caching/pruning behavior, and endpoint/route parameter naming.

Community icon URLs and caches were keyed only by the listing's pinned
snapshot commit, so publishing updated community-icon.* files on a saved
package never became visible: the listing kept serving the icon derived
from the old pinned commit (30-day KV descriptor + R2 asset + 1h HTTP
cache all keyed by the stale commit).

Listing reads now join entity_sources so each listing carries an
iconCommit (the owner package's current published commit, falling back
to the pinned commit when the source row is gone). Icon URLs embed the
icon commit, descriptors and R2 assets are keyed by it, and the icon
route serves the icon commit or the pinned commit and 404s anything
else. Package publish prunes superseded icon cache entries by listing
prefix and invalidates the public listing data cache; republish,
unpublish, hard delete, and account deletion clean up both commits.
@coderabbitai

coderabbitai Bot commented Jul 11, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e5cabd35-ee44-416f-89ea-6383d176bc19

📥 Commits

Reviewing files that changed from the base of the PR and between 2b91914 and 659cb33.

📒 Files selected for processing (1)
  • docs/use/community-packages.md
✅ Files skipped from review due to trivial changes (1)
  • docs/use/community-packages.md

📝 Walkthrough

Walkthrough

Community listing icons now use the package’s current published commit or pinned snapshot commit for URL generation, cache keys, asset storage, validation, cleanup, account deletion, and publish-time refresh. Documentation and tests reflect the updated behavior.

Changes

Community icon commit flow

Layer / File(s) Summary
Listing and artifact commit contracts
packages/worker/src/community/types.ts, packages/worker/src/community/repo.ts, packages/worker/src/app/account-deletion.ts, packages/worker/src/repo/artifact-file.ts
Listing queries derive iconCommit with a pinned fallback, and artifact reads probe multiple candidate icon paths.
Commit-aware icon cache engine
packages/worker/src/community/community-icon.ts, packages/worker/src/community/community-icon.*.test.ts
Descriptors, KV/R2 keys, source loading, validation, deletion, and cache refresh use commit-scoped icon data.
Public icon URLs and serving validation
packages/worker/src/app/community-public.ts, packages/worker/src/app/routes.ts, packages/worker/src/app/handlers/community-icon.ts, packages/worker/src/app/handlers/*test.ts
Icon URLs use iconCommit; handlers accept the current or pinned commit.
Listing cleanup and account deletion
packages/worker/src/community/service.ts, packages/worker/src/app/account-deletion.ts, packages/worker/src/app/account-deletion.node.test.ts
Lifecycle cleanup removes commit-scoped icon cache and asset entries.
Package publish icon refresh
packages/worker/src/repo/external-publish.ts, packages/worker/src/repo/external-publish.node.test.ts
Successful package publication refreshes icon caches after projection updates.
Icon behavior documentation
docs/contributing/architecture/*, docs/contributing/community-packages.md, docs/guides/package-authoring.md, docs/use/community-packages.md
Documentation describes commit selection, cache invalidation, path priority, storage keys, and cleanup.

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

Sequence Diagram(s)

sequenceDiagram
  participant Publisher as Package publisher
  participant Projection as Package projection
  participant IconRefresh as Icon refresh
  participant Cache as Community icon cache
  Publisher->>Projection: finalize published package source
  Projection-->>Publisher: projection refresh succeeds
  Publisher->>IconRefresh: refresh community icon
  IconRefresh->>Cache: remove superseded icon revisions
  IconRefresh-->>Publisher: publish continues
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.63% 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
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: community listing icons now derive from the package's published commit.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/fix-community-icon-cache-stale-after-publish-d78e

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 11, 2026 07:25
@github-actions

github-actions Bot commented Jul 11, 2026 •

Copy link
Copy Markdown
Contributor

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

Worker: kody-pr-725
D1: kody-pr-725-db
KV: kody-pr-725-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

🤖 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 `@docs/use/community-packages.md`:
- Around line 53-58: Update the icon URL documentation to state that URLs use
the package’s current published commit when source is available, but fall back
to the pinned commit when the package source is unavailable. Preserve the
existing guidance about icon priority and removing superseded files.
🪄 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: e2d1c917-36e8-4d0c-b545-aa9a2c504139

📥 Commits

Reviewing files that changed from the base of the PR and between ff42582 and 2b91914.

📒 Files selected for processing (25)
  • docs/contributing/architecture/data-storage.md
  • docs/contributing/architecture/primitives.yaml
  • docs/contributing/community-packages.md
  • docs/guides/package-authoring.md
  • docs/use/community-packages.md
  • packages/worker/src/app/account-deletion.node.test.ts
  • packages/worker/src/app/account-deletion.ts
  • packages/worker/src/app/community-public.ts
  • packages/worker/src/app/handlers/community-detail.frame.node.test.ts
  • packages/worker/src/app/handlers/community-icon.node.test.ts
  • packages/worker/src/app/handlers/community-icon.ts
  • packages/worker/src/app/handlers/community.frame.node.test.ts
  • packages/worker/src/app/handlers/community.node.test.ts
  • packages/worker/src/app/routes.ts
  • packages/worker/src/app/ssr-render.node.test.ts
  • packages/worker/src/community/community-icon.node.test.ts
  • packages/worker/src/community/community-icon.ts
  • packages/worker/src/community/community-icon.workers.test.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/src/repo/artifact-file.ts
  • packages/worker/src/repo/external-publish.node.test.ts
  • packages/worker/src/repo/external-publish.ts

Comment thread docs/use/community-packages.md Outdated
@kody-bot
kody-bot merged commit 0840a62 into main Jul 11, 2026
5 checks passed
@kody-bot
kody-bot deleted the cursor/fix-community-icon-cache-stale-after-publish-d78e branch July 11, 2026 07:46
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