Hi @danielroe, I've added a source to the Public Hash List (PHL) that covers the content-addressed chunks nuxt-cos and vite-plugin-cross-origin-storage emit, so they become eligible under COS availability gating.
Commit: WICG/cross-origin-storage@1962c57
This is aimed at your "Automatic detection of allow-listed dependencies" roadmap item, from the other end: the chunks can't be gated on the list until something puts them there.
The approach
Every other PHL source scrapes bytes from a public URL. These have none, since they exist only inside site builds, so this source reproduces them instead: it enumerates published plugin releases from the npm registry, installs the real plugin, builds a minimal Vite app per (plugin version × vue version), and harvests the 64-hex chunks, re-hashing each from its bytes rather than trusting the filename.
Currently 75 hashes: vue, @vue/shared, @vue/reactivity, @vue/runtime-core and @vue/runtime-dom across the 15 most recent vue releases, under plugin 2.0.3.
The matrix is built with plain Vite rather than Nuxt, on the assumption that the module doesn't influence chunk content. I checked that rather than assuming it: a real nuxt-cos@2.0.3 build emits 5 chunks, all already covered.
What I'd most like you to sanity-check
RECIPE = 'cos1' doesn't capture everything that decides the emitted bytes. The rolldown/oxc minifier version does too. vue@3.5.39 produces three different chunks under rolldown 1.1.0, 1.1.4 and 1.2.0, differing only in minifier whitespace:
// rolldown 1.1.0
(e.appContext.config.idPrefix||`v`)+`-`+e.ids[0]+ e.ids[1]++
// rolldown 1.1.4
(e.appContext.config.idPrefix||`v`)+`-`+e.ids[0]+e.ids[1]++
(Those two came from the same plugin code, which is what isolates rolldown as the cause rather than a plugin change.)
This isn't a correctness problem, since the hash is of the content and differing bytes can't collide. But it does mean cos1 currently spans several mutually byte-incompatible outputs, and that every plugin release changing the rolldown pin silently invalidates the whole chunk set and re-fragments sharing between sites on different plugin versions.
Enumerating the hashes is only tractable because your published releases pin rolldown exactly ("rolldown": "1.2.0", no range), which makes (plugin version, package version) → chunk hash a total, reproducible function. The source deliberately skips any release pinning a range, since its output would depend on when a site happened to install.
So, concretely:
- Is reproducing-by-building the right approach, or would you rather expose the hashes directly? The plugin already knows them at build time.
- Is the exact rolldown pin intentional and something you'd be willing to keep? It's the single assumption everything here rests on.
- Would it be worth folding the rolldown version into
RECIPE, so the specifier is self-describing about which build produced it?
- Is
[/^(?:vue$|@vue\/)/] stable as the default managed set? Widening it would change what sites actually emit.
A heads-up on releases that change the recipe would be genuinely useful, because each one invalidates every hash currently on the list. The PHL pipeline picks up new releases automatically and reports them, but it can only react after the fact.
Two smaller notes from building this. nuxt-cos@2.0.1 emits no chunks at all under a current Nuxt, since the plugin peers vite@^5 || ^6 || ^7 while Nuxt 4 ships Vite 8, so it never applies. And the COS manifest only started recording each chunk's npm package name in 2.0.3, which is why the source starts there; earlier releases would need the package scraped out of the license banner.
Thanks a lot for building this, and for making the chunks reproducible in the first place. That property is the entire reason they can go on a shared allowlist at all.
Hi @danielroe, I've added a source to the Public Hash List (PHL) that covers the content-addressed chunks
nuxt-cosandvite-plugin-cross-origin-storageemit, so they become eligible under COS availability gating.Commit: WICG/cross-origin-storage@1962c57
This is aimed at your "Automatic detection of allow-listed dependencies" roadmap item, from the other end: the chunks can't be gated on the list until something puts them there.
The approach
Every other PHL source scrapes bytes from a public URL. These have none, since they exist only inside site builds, so this source reproduces them instead: it enumerates published plugin releases from the npm registry, installs the real plugin, builds a minimal Vite app per (plugin version ×
vueversion), and harvests the 64-hex chunks, re-hashing each from its bytes rather than trusting the filename.Currently 75 hashes:
vue,@vue/shared,@vue/reactivity,@vue/runtime-coreand@vue/runtime-domacross the 15 most recentvuereleases, under plugin 2.0.3.The matrix is built with plain Vite rather than Nuxt, on the assumption that the module doesn't influence chunk content. I checked that rather than assuming it: a real
nuxt-cos@2.0.3build emits 5 chunks, all already covered.What I'd most like you to sanity-check
RECIPE = 'cos1'doesn't capture everything that decides the emitted bytes. The rolldown/oxc minifier version does too.vue@3.5.39produces three different chunks under rolldown 1.1.0, 1.1.4 and 1.2.0, differing only in minifier whitespace:(Those two came from the same plugin code, which is what isolates rolldown as the cause rather than a plugin change.)
This isn't a correctness problem, since the hash is of the content and differing bytes can't collide. But it does mean
cos1currently spans several mutually byte-incompatible outputs, and that every plugin release changing the rolldown pin silently invalidates the whole chunk set and re-fragments sharing between sites on different plugin versions.Enumerating the hashes is only tractable because your published releases pin rolldown exactly (
"rolldown": "1.2.0", no range), which makes(plugin version, package version) → chunk hasha total, reproducible function. The source deliberately skips any release pinning a range, since its output would depend on when a site happened to install.So, concretely:
RECIPE, so the specifier is self-describing about which build produced it?[/^(?:vue$|@vue\/)/]stable as the default managed set? Widening it would change what sites actually emit.A heads-up on releases that change the recipe would be genuinely useful, because each one invalidates every hash currently on the list. The PHL pipeline picks up new releases automatically and reports them, but it can only react after the fact.
Two smaller notes from building this.
nuxt-cos@2.0.1emits no chunks at all under a current Nuxt, since the plugin peersvite@^5 || ^6 || ^7while Nuxt 4 ships Vite 8, so it never applies. And the COS manifest only started recording each chunk's npm package name in 2.0.3, which is why the source starts there; earlier releases would need the package scraped out of the license banner.Thanks a lot for building this, and for making the chunks reproducible in the first place. That property is the entire reason they can go on a shared allowlist at all.