| … | … | @@ -246,6 +246,70 @@ test('registry-info / publish-release / releases-list round-trip', async (t) => |
| 246 | 246 | await sidecar.stop() |
| 247 | 247 | }) |
| 248 | 248 | |
| 249 | test('releases-summary omits the dep closure', async (t) => { |
| 250 | // Every registry entry embeds its full dep closure. Measured on prod |
| 251 | // 2026-08-07, ONE pear-git-v3 entry is ~120 KB (285 deps x per-arch prebuild |
| 252 | // hash maps), so `releases-list` never returns across many versions — |
| 253 | // `pgh releases list pear-git-v3` times out at 60s. releases-summary exists so |
| 254 | // a caller that only DISPLAYS releases does not pay for the closure. |
| 255 | // |
| 256 | // PASS = summary carries identity + provenance + depCount, carries NO deps, |
| 257 | // and is dramatically smaller than the same entry from releases-list. |
| 258 | const { sidecar, sock } = await makeSidecar() |
| 259 | const client = await makeClient(sock) |
| 260 | |
| 261 | // A closure big enough that "did we actually drop it" is unambiguous. |
| 262 | const deps = [] |
| 263 | for (let i = 0; i < 200; i++) { |
| 264 | deps.push({ |
| 265 | name: 'dep-' + i, |
| 266 | version: '1.0.0', |
| 267 | tree: 'f'.repeat(64), |
| 268 | prebuilds: { |
| 269 | 'linux-x64': 'a'.repeat(64), |
| 270 | 'linux-arm64': 'b'.repeat(64), |
| 271 | 'darwin-arm64': 'c'.repeat(64) |
| 272 | } |
| 273 | }) |
| 274 | } |
| 275 | |
| 276 | await client.call('publish-release', { |
| 277 | entry: { |
| 278 | name: 'fat-app', |
| 279 | version: '2.0.0', |
| 280 | treeHash: 'deadbeef', |
| 281 | upgrade: 'pgh://reg/fat-app', |
| 282 | publisherDevicePubkey: 'pub123', |
| 283 | deps, |
| 284 | publishedAt: Date.now() |
| 285 | } |
| 286 | }) |
| 287 | |
| 288 | const summary = await client.call('releases-summary', {}) |
| 289 | t.is(summary.length, 1, 'one entry') |
| 290 | const s = summary[0] |
| 291 | t.is(s.name, 'fat-app') |
| 292 | t.is(s.version, '2.0.0') |
| 293 | t.is(s.treeHash, 'deadbeef', 'treeHash retained — it is the install identity') |
| 294 | t.is(s.upgrade, 'pgh://reg/fat-app', 'upgrade URL retained') |
| 295 | t.is(s.publisherDevicePubkey, 'pub123', 'provenance retained') |
| 296 | t.is(s.depCount, 200, 'closure SIZE reported without the closure') |
| 297 | t.absent(s.deps, 'deps dropped — this is the whole point') |
| 298 | |
| 299 | const full = await client.call('releases-list', {}) |
| 300 | t.is(full[0].deps.length, 200, 'releases-list still carries deps for install paths') |
| 301 | |
| 302 | const sBytes = JSON.stringify(summary).length |
| 303 | const fBytes = JSON.stringify(full).length |
| 304 | t.ok(sBytes * 20 < fBytes, 'summary is >20x smaller (' + sBytes + ' vs ' + fBytes + ' bytes)') |
| 305 | |
| 306 | const filtered = await client.call('releases-summary', { name: 'nope' }) |
| 307 | t.is(filtered.length, 0, 'name filter applies') |
| 308 | |
| 309 | await client.close() |
| 310 | await sidecar.stop() |
| 311 | }) |
| 312 | |
| 249 | 313 | test('seed-status reports enabled:false when enableSeed:false', async (t) => { |
| 250 | 314 | const { sidecar, sock } = await makeSidecar() |
| 251 | 315 | const client = await makeClient(sock) |