Problem
A cached read (cache(fn,{key:'posts'})) can only be invalidated by calling listPosts.invalidate() from the exact module that owns the wrapper, and even then only the no-args base key is cleared (arg-specific keys leak until TTL). An unrelated mutation (createComment) cannot invalidate a related read (postById) without importing every cached wrapper, and the RPC action dispatcher (actions.js) has no hook to evict server cache() entries on a successful mutation. cache-fn.js takes only {key,ttl} and the CacheStore interface has only get/set/delete/increment with no tag index.
Design / approach
Implement tags as a thin Set-of-keys index in the existing store: cache(fn,{key,tags}) appends the key to each tag's Set, and revalidateTag(tag) deletes that Set's keys. No new subsystem, just a secondary index over store.get/set/delete; revalidateTag/revalidatePath are plain server-importable functions an action calls.
Web-standards fit: A tag is just a Set of keys layered on the existing store API; the whole feature is a small index plus two functions, no cache engine.
Prior art: Next.js unstable_cache(fn,keys,{tags}) plus revalidateTag(tag) invoked inside a Server Action; Rails russian-doll touch:.
Acceptance criteria
Filed from the production-readiness audit (webjs vs Next.js / Remix / Rails / Turbo / Lit). Theme: caching. Priority: P1. Kept to webjs identity: no-build, progressive enhancement, web-components-first, AI-first, batteries-included, close to web standards.
Problem
A cached read (cache(fn,{key:'posts'})) can only be invalidated by calling listPosts.invalidate() from the exact module that owns the wrapper, and even then only the no-args base key is cleared (arg-specific keys leak until TTL). An unrelated mutation (createComment) cannot invalidate a related read (postById) without importing every cached wrapper, and the RPC action dispatcher (actions.js) has no hook to evict server cache() entries on a successful mutation. cache-fn.js takes only {key,ttl} and the CacheStore interface has only get/set/delete/increment with no tag index.
Design / approach
Implement tags as a thin Set-of-keys index in the existing store: cache(fn,{key,tags}) appends the key to each tag's Set, and revalidateTag(tag) deletes that Set's keys. No new subsystem, just a secondary index over store.get/set/delete; revalidateTag/revalidatePath are plain server-importable functions an action calls.
Web-standards fit: A tag is just a Set of keys layered on the existing store API; the whole feature is a small index plus two functions, no cache engine.
Prior art: Next.js unstable_cache(fn,keys,{tags}) plus revalidateTag(tag) invoked inside a Server Action; Rails russian-doll touch:.
Acceptance criteria
Filed from the production-readiness audit (webjs vs Next.js / Remix / Rails / Turbo / Lit). Theme: caching. Priority: P1. Kept to webjs identity: no-build, progressive enhancement, web-components-first, AI-first, batteries-included, close to web standards.