dsh-plugin-shop 0.9.0 → 0.10.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -55,6 +55,7 @@ const dsh_plugin_shop_shop_catalog_result$schema = z.object({
55
55
  'installSize': z.union([z.undefined(), z.number()]).optional(),
56
56
  'archived': z.union([z.undefined(), z.literal(false), z.literal(true)]).optional(),
57
57
  'forked': z.union([z.undefined(), z.literal(false), z.literal(true)]).optional(),
58
+ 'icon': z.union([z.undefined(), z.string()]).optional(),
58
59
  })),
59
60
  'denied': z.array(z.object({
60
61
  'name': z.string(),
@@ -63,6 +64,7 @@ const dsh_plugin_shop_shop_catalog_result$schema = z.object({
63
64
  })),
64
65
  'notAShop': z.union([z.undefined(), z.array(z.string())]).optional(),
65
66
  'stars': z.record(z.string(), z.number()),
67
+ 'icons': z.record(z.string(), z.string()),
66
68
  'incompatible': z.record(z.string(), z.array(z.string())),
67
69
  'incompatibleHarness': z.record(z.string(), z.object({
68
70
  'dsh': z.union([z.undefined(), z.object({
@@ -202,7 +204,7 @@ export const TYPERT = {
202
204
  schema: dsh_plugin_shop_shop_catalog_result$schema,
203
205
  create: () => dsh_plugin_shop_shop_catalog_result$schema,
204
206
  },
205
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1314,"column":9},
207
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1317,"column":9},
206
208
  },
207
209
  {
208
210
  id: 'dsh-plugin-shop#shop/installed',
@@ -218,7 +220,7 @@ export const TYPERT = {
218
220
  schema: dsh_plugin_shop_shop_installed_result$schema,
219
221
  create: () => dsh_plugin_shop_shop_installed_result$schema,
220
222
  },
221
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1821,"column":9},
223
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1825,"column":9},
222
224
  },
223
225
  {
224
226
  id: 'dsh-plugin-shop#shop/installedSpecs',
@@ -234,7 +236,7 @@ export const TYPERT = {
234
236
  schema: dsh_plugin_shop_shop_installedSpecs_result$schema,
235
237
  create: () => dsh_plugin_shop_shop_installedSpecs_result$schema,
236
238
  },
237
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1812,"column":9},
239
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1816,"column":9},
238
240
  },
239
241
  {
240
242
  id: 'dsh-plugin-shop#shop/installStart',
@@ -262,7 +264,7 @@ export const TYPERT = {
262
264
  schema: dsh_plugin_shop_shop_installStart_result$schema,
263
265
  create: () => dsh_plugin_shop_shop_installStart_result$schema,
264
266
  },
265
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1440,"column":9},
267
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1444,"column":9},
266
268
  },
267
269
  {
268
270
  id: 'dsh-plugin-shop#shop/installStatus',
@@ -289,7 +291,7 @@ export const TYPERT = {
289
291
  schema: dsh_plugin_shop_shop_installStatus_result$schema,
290
292
  create: () => dsh_plugin_shop_shop_installStatus_result$schema,
291
293
  },
292
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1788,"column":3},
294
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1792,"column":3},
293
295
  },
294
296
  {
295
297
  id: 'dsh-plugin-shop#shop/restart',
@@ -305,7 +307,7 @@ export const TYPERT = {
305
307
  schema: dsh_plugin_shop_shop_restart_result$schema,
306
308
  create: () => dsh_plugin_shop_shop_restart_result$schema,
307
309
  },
308
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":2072,"column":9},
310
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":2076,"column":9},
309
311
  },
310
312
  {
311
313
  id: 'dsh-plugin-shop#shop/setEnabled',
@@ -332,7 +334,7 @@ export const TYPERT = {
332
334
  schema: dsh_plugin_shop_shop_setEnabled_result$schema,
333
335
  create: () => dsh_plugin_shop_shop_setEnabled_result$schema,
334
336
  },
335
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":966,"column":9},
337
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":969,"column":9},
336
338
  },
337
339
  {
338
340
  id: 'dsh-plugin-shop#shop/uninstallStart',
@@ -360,7 +362,7 @@ export const TYPERT = {
360
362
  schema: dsh_plugin_shop_shop_uninstallStart_result$schema,
361
363
  create: () => dsh_plugin_shop_shop_uninstallStart_result$schema,
362
364
  },
363
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1966,"column":9},
365
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1970,"column":9},
364
366
  },
365
367
  {
366
368
  id: 'dsh-plugin-shop#shop/updateStart',
@@ -387,7 +389,7 @@ export const TYPERT = {
387
389
  schema: dsh_plugin_shop_shop_updateStart_result$schema,
388
390
  create: () => dsh_plugin_shop_shop_updateStart_result$schema,
389
391
  },
390
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":2179,"column":9},
392
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":2183,"column":9},
391
393
  },
392
394
  {
393
395
  id: 'dsh-plugin-shop#shop/version',
@@ -403,7 +405,7 @@ export const TYPERT = {
403
405
  schema: dsh_plugin_shop_shop_version_result$schema,
404
406
  create: () => dsh_plugin_shop_shop_version_result$schema,
405
407
  },
406
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":2136,"column":9},
408
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":2140,"column":9},
407
409
  },
408
410
  ],
409
411
  model: {
@@ -500,7 +502,7 @@ export const TYPERT = {
500
502
  },
501
503
  {
502
504
  "name": "CatalogEntry",
503
- "declaration": "export interface CatalogEntry {\n name: string;\n version: string;\n integrity: string | null;\n publishedAt: string | null;\n repository: string | null;\n license: string | null;\n tier: 'verified' | 'verified-stale' | 'community';\n metadata: 'declared' | 'derived';\n review?: { reviewedVersion?: string; reviewedCommit?: string; reviewedSha256?: string; repo?: string; reviewer: string; reviewCommit: string; notes: string; };\n catalog?: CatalogSection;\n source: 'npm' | 'github';\n publisher?: string;\n repo?: string;\n subdir?: string;\n tarball?: { url: string; sha256: string; };\n added?: string;\n peers?: string[];\n compatibility?: { dsh?: string; profiles?: string[]; };\n dshPeers?: Record<string, string>;\n manifestVersion?: string;\n unpackedSize?: number;\n installSize?: number;\n archived?: boolean;\n forked?: boolean;\n}"
505
+ "declaration": "export interface CatalogEntry {\n name: string;\n version: string;\n integrity: string | null;\n publishedAt: string | null;\n repository: string | null;\n license: string | null;\n tier: 'verified' | 'verified-stale' | 'community';\n metadata: 'declared' | 'derived';\n review?: { reviewedVersion?: string; reviewedCommit?: string; reviewedSha256?: string; repo?: string; reviewer: string; reviewCommit: string; notes: string; };\n catalog?: CatalogSection;\n source: 'npm' | 'github';\n publisher?: string;\n repo?: string;\n subdir?: string;\n tarball?: { url: string; sha256: string; };\n added?: string;\n peers?: string[];\n compatibility?: { dsh?: string; profiles?: string[]; };\n dshPeers?: Record<string, string>;\n manifestVersion?: string;\n unpackedSize?: number;\n installSize?: number;\n archived?: boolean;\n forked?: boolean;\n icon?: string;\n}"
504
506
  },
505
507
  {
506
508
  "name": "CatalogSection",
@@ -552,7 +554,7 @@ export const TYPERT = {
552
554
  },
553
555
  {
554
556
  "name": "ShopCatalogResult",
555
- "declaration": "export interface ShopCatalogResult {\n schemaVersion: number;\n builtAt: string;\n stale: boolean;\n plugins: CatalogEntry[];\n denied: DeniedEntry[];\n notAShop?: string[];\n stars: Record<string, number>;\n incompatible: Record<string, string[]>;\n incompatibleHarness: Record<string, HarnessVerdict>;\n}"
557
+ "declaration": "export interface ShopCatalogResult {\n schemaVersion: number;\n builtAt: string;\n stale: boolean;\n plugins: CatalogEntry[];\n denied: DeniedEntry[];\n notAShop?: string[];\n stars: Record<string, number>;\n icons: Record<string, string>;\n incompatible: Record<string, string[]>;\n incompatibleHarness: Record<string, HarnessVerdict>;\n}"
556
558
  },
557
559
  {
558
560
  "name": "ShopInstalledEntry",
@@ -55,6 +55,7 @@ const dsh_plugin_shop_shop_catalog_result$schema = z.object({
55
55
  'installSize': z.union([z.undefined(), z.number()]).optional(),
56
56
  'archived': z.union([z.undefined(), z.literal(false), z.literal(true)]).optional(),
57
57
  'forked': z.union([z.undefined(), z.literal(false), z.literal(true)]).optional(),
58
+ 'icon': z.union([z.undefined(), z.string()]).optional(),
58
59
  })),
59
60
  'denied': z.array(z.object({
60
61
  'name': z.string(),
@@ -63,6 +64,7 @@ const dsh_plugin_shop_shop_catalog_result$schema = z.object({
63
64
  })),
64
65
  'notAShop': z.union([z.undefined(), z.array(z.string())]).optional(),
65
66
  'stars': z.record(z.string(), z.number()),
67
+ 'icons': z.record(z.string(), z.string()),
66
68
  'incompatible': z.record(z.string(), z.array(z.string())),
67
69
  'incompatibleHarness': z.record(z.string(), z.object({
68
70
  'dsh': z.union([z.undefined(), z.object({
@@ -199,7 +201,7 @@ export const TYPERT_REMOTE = {
199
201
  schema: dsh_plugin_shop_shop_catalog_result$schema,
200
202
  create: () => dsh_plugin_shop_shop_catalog_result$schema,
201
203
  },
202
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1314,"column":9},
204
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1317,"column":9},
203
205
  },
204
206
  {
205
207
  id: 'dsh-plugin-shop#shop/installed',
@@ -215,7 +217,7 @@ export const TYPERT_REMOTE = {
215
217
  schema: dsh_plugin_shop_shop_installed_result$schema,
216
218
  create: () => dsh_plugin_shop_shop_installed_result$schema,
217
219
  },
218
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1821,"column":9},
220
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1825,"column":9},
219
221
  },
220
222
  {
221
223
  id: 'dsh-plugin-shop#shop/installedSpecs',
@@ -231,7 +233,7 @@ export const TYPERT_REMOTE = {
231
233
  schema: dsh_plugin_shop_shop_installedSpecs_result$schema,
232
234
  create: () => dsh_plugin_shop_shop_installedSpecs_result$schema,
233
235
  },
234
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1812,"column":9},
236
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1816,"column":9},
235
237
  },
236
238
  {
237
239
  id: 'dsh-plugin-shop#shop/installStart',
@@ -259,7 +261,7 @@ export const TYPERT_REMOTE = {
259
261
  schema: dsh_plugin_shop_shop_installStart_result$schema,
260
262
  create: () => dsh_plugin_shop_shop_installStart_result$schema,
261
263
  },
262
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1440,"column":9},
264
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1444,"column":9},
263
265
  },
264
266
  {
265
267
  id: 'dsh-plugin-shop#shop/installStatus',
@@ -286,7 +288,7 @@ export const TYPERT_REMOTE = {
286
288
  schema: dsh_plugin_shop_shop_installStatus_result$schema,
287
289
  create: () => dsh_plugin_shop_shop_installStatus_result$schema,
288
290
  },
289
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1788,"column":3},
291
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1792,"column":3},
290
292
  },
291
293
  {
292
294
  id: 'dsh-plugin-shop#shop/restart',
@@ -302,7 +304,7 @@ export const TYPERT_REMOTE = {
302
304
  schema: dsh_plugin_shop_shop_restart_result$schema,
303
305
  create: () => dsh_plugin_shop_shop_restart_result$schema,
304
306
  },
305
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":2072,"column":9},
307
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":2076,"column":9},
306
308
  },
307
309
  {
308
310
  id: 'dsh-plugin-shop#shop/setEnabled',
@@ -329,7 +331,7 @@ export const TYPERT_REMOTE = {
329
331
  schema: dsh_plugin_shop_shop_setEnabled_result$schema,
330
332
  create: () => dsh_plugin_shop_shop_setEnabled_result$schema,
331
333
  },
332
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":966,"column":9},
334
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":969,"column":9},
333
335
  },
334
336
  {
335
337
  id: 'dsh-plugin-shop#shop/uninstallStart',
@@ -357,7 +359,7 @@ export const TYPERT_REMOTE = {
357
359
  schema: dsh_plugin_shop_shop_uninstallStart_result$schema,
358
360
  create: () => dsh_plugin_shop_shop_uninstallStart_result$schema,
359
361
  },
360
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1966,"column":9},
362
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":1970,"column":9},
361
363
  },
362
364
  {
363
365
  id: 'dsh-plugin-shop#shop/updateStart',
@@ -384,7 +386,7 @@ export const TYPERT_REMOTE = {
384
386
  schema: dsh_plugin_shop_shop_updateStart_result$schema,
385
387
  create: () => dsh_plugin_shop_shop_updateStart_result$schema,
386
388
  },
387
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":2179,"column":9},
389
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":2183,"column":9},
388
390
  },
389
391
  {
390
392
  id: 'dsh-plugin-shop#shop/version',
@@ -400,7 +402,7 @@ export const TYPERT_REMOTE = {
400
402
  schema: dsh_plugin_shop_shop_version_result$schema,
401
403
  create: () => dsh_plugin_shop_shop_version_result$schema,
402
404
  },
403
- sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":2136,"column":9},
405
+ sourceLocation: {"file":"packages/dsh-plugin-shop/src/host/index.ts","line":2140,"column":9},
404
406
  },
405
407
  ],
406
408
  }
@@ -0,0 +1,27 @@
1
+ import { type ReactNode } from 'react';
2
+ /** The artwork an entry without a usable icon draws: dsh's own default,
3
+ * `PluginArtworkDefault` from `dsh-client-ui-primitives` (MIT, DeepSeek — see
4
+ * the dsh repository's LICENSE). Copied rather than imported because
5
+ * 0.1.5-rc.3 exports nothing this build could borrow at run time.
6
+ *
7
+ * A constant data URL drawn through an `<img>`, not inline markup: the SVG
8
+ * carries a gradient addressed by id, so thousands of inline copies would each
9
+ * need one, while an image document is its own namespace and needs none
10
+ * (design 2026-10-23-shop-plugin-icons §8.1). The id inside this string is
11
+ * fixed for the same reason.
12
+ */
13
+ export declare const DEFAULT_ICON_DATA_URL = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzYiIGhlaWdodD0iMzYiIHZpZXdCb3g9IjAgMCAzNiAzNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMjQuNjI5NCA4LjYzNjk2QzI2LjI4NjIgOC42MzcwNSAyNy42Mjk0IDkuOTgwMTYgMjcuNjI5NCAxMS42MzdWMTIuNzgyNUMyNy42MjkyIDE0LjQzOTEgMjYuMjg2MSAxNS43ODI0IDI0LjYyOTQgMTUuNzgyNUgyMy40ODM5QzIyLjY1MTkgMTUuNzgyNSAyMS41NDU0IDE2LjM0NTkgMjEuNTQ1NCAxNy4xNzc4VjE4LjE1NzNDMjEuNTQ1NCAxOC43NzU3IDIyLjIxNiAxOS4xOTY2IDIyLjgzNDUgMTkuMTk2NUgyNC42Mjk0QzI2LjI4NjEgMTkuMTk2NSAyNy42MjkyIDIwLjUzOTggMjcuNjI5NCAyMi4xOTY1VjIzLjk5MjRDMjcuNjI5MiAyNS42NDkxIDI2LjI4NjEgMjYuOTkyNCAyNC42Mjk0IDI2Ljk5MjRIMjIuODM0NUMyMS4xNzc4IDI2Ljk5MjQgMTkuODM0NyAyNS42NDkgMTkuODM0NSAyMy45OTI0VjIyLjE5NjVDMTkuODM0NSAyMS43MTQ4IDE5LjQ5NTcgMjEuMjMyNyAxOS4wMTQgMjEuMjMyN0gxNi40NzkyQzE1Ljc5NzUgMjEuMjMyNyAxNS4zMzc0IDIyLjAwNjEgMTUuMzM3NCAyMi42ODc3VjIzLjgzMzNDMTUuMzM3MyAyNS40OSAxMy45OTQyIDI2LjgzMzMgMTIuMzM3NCAyNi44MzMzSDExLjE5MTlDOS41MzUwOSAyNi44MzMzIDguMTkxOTggMjUuNDkgOC4xOTE4OSAyMy44MzMzVjIyLjY4NzdDOC4xOTE4OSAyMS4wMzA5IDkuNTM1MDQgMTkuNjg3NyAxMS4xOTE5IDE5LjY4NzdIMTIuMzM3NEMxMy4xOTY0IDE5LjY4NzcgMTQuMzk5OSAxOS4wOTU5IDE0LjM5OTkgMTguMjM2OVYxNi4wMTg1QzE0LjM5OTkgMTQuOTUxOCAxNS4yNjQ2IDE0LjA4NzIgMTYuMzMxMiAxNC4wODcySDE5LjQzNUMyMC4wNTk2IDE0LjA4NzIgMjAuNDg0IDEzLjQwNzEgMjAuNDgzOSAxMi43ODI1VjExLjYzN0MyMC40ODM5IDkuOTgwMTEgMjEuODI3IDguNjM2OTYgMjMuNDgzOSA4LjYzNjk2SDI0LjYyOTRaTTEzLjQxMTYgMTEuMjQ2OEMxMy40MTE2IDEyLjY4ODIgMTIuMjQzMSAxMy44NTY3IDEwLjgwMTggMTMuODU2N0M5LjM2MDM3IDEzLjg1NjcgOC4xOTE4OSAxMi42ODgyIDguMTkxODkgMTEuMjQ2OEM4LjE5MTg5IDkuODA1NDQgOS4zNjAzNyA4LjYzNjk2IDEwLjgwMTggOC42MzY5NkMxMi4yNDMxIDguNjM2OTYgMTMuNDExNiA5LjgwNTQ0IDEzLjQxMTYgMTEuMjQ2OFoiIGZpbGw9InVybCgjYSkiLz48ZGVmcz48bGluZWFyR3JhZGllbnQgaWQ9ImEiIHgxPSIxNS4xNDgxIiB5MT0iOS45NDE4OCIgeDI9IjE1LjE0ODEiIHkyPSIxMy42Mzc1IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agc3RvcC1jb2xvcj0iIzU0RUNFNyIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzY1OEVGRiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjwvc3ZnPg==";
14
+ /** One entry's icon: a 32px tile holding a 24px image (design §8.3).
15
+ *
16
+ * An author's icon reaches the DOM only here, as this `<img>`'s `src` — a
17
+ * `data:` URL built from bytes the catalog carried. Never `innerHTML`, never
18
+ * an inline `<svg>`: an image document runs no script and loads nothing
19
+ * external, and that is the whole defence for an SVG (§8.5).
20
+ *
21
+ * `onError` swaps a source that will not decode for the default, as dsh's own
22
+ * `PackageArtwork` does. The failed source, not a boolean, is remembered, so a
23
+ * later entry reusing this component instance still tries its own icon.
24
+ */
25
+ export declare function EntryIcon({ icon }: {
26
+ icon: string | undefined;
27
+ }): ReactNode;
@@ -478,6 +478,14 @@ export declare function entryKey(entry: CatalogEntry): string;
478
478
  * shelf that hides the plugin.
479
479
  */
480
480
  export declare function listedOnShelf(entry: CatalogEntry, cleared: ReadonlySet<string>): boolean;
481
+ /**
482
+ * An entry's icon as the catalog's data URL, or undefined to draw the default:
483
+ * it declares none, the catalog predates the icons file, or the sidecar
484
+ * degraded and the map does not carry its sha256. The map is keyed by 64-hex
485
+ * sha256, so no name from the catalog is ever used as a lookup here (design
486
+ * 2026-10-23-shop-plugin-icons §7).
487
+ */
488
+ export declare function iconOf(entry: CatalogEntry | undefined, icons: Readonly<Record<string, string>>): string | undefined;
481
489
  /**
482
490
  * One entry's star count from the sidecar, or undefined when it has none.
483
491
  *
@@ -28,6 +28,11 @@ export interface CatalogSnapshot {
28
28
  /** GitHub star counts by package name; {} when the pointer names no
29
29
  * sidecar or the sidecar could not be fetched/verified (spec §5). */
30
30
  stars: Record<string, number>;
31
+ /** sha256 → data URL for the catalogue's icons; {} when the pointer names no
32
+ * sidecar, or it could not be fetched, verified or parsed (design
33
+ * 2026-10-23-shop-plugin-icons §7). Optional like `notAShop`: `loadCatalog`
34
+ * always sets it, and a snapshot assembled by hand need not carry it. */
35
+ icons?: Record<string, string>;
31
36
  }
32
37
  export interface CatalogResult {
33
38
  snapshot: CatalogSnapshot;
@@ -308,6 +308,9 @@ export interface ShopCatalogResult {
308
308
  /** GitHub star counts by package name; {} when the pointer names no sidecar
309
309
  * or the sidecar could not be fetched/verified (§5). */
310
310
  stars: Record<string, number>;
311
+ /** sha256 → data URL for the catalogue's icons; {} when the pointer names
312
+ * none or it could not be read (design 2026-10-23-shop-plugin-icons §7). */
313
+ icons: Record<string, string>;
311
314
  /** Install identity (`npm:<name>` / `github:<repo>#<subdir>`) → the declared
312
315
  * peers node resolution cannot find from the profile. This is the HOST half
313
316
  * of the verdict only: a module the browser's module table serves — a
@@ -132,6 +132,13 @@ export interface CatalogEntry {
132
132
  * nothing reads it here yet — it is telemetry the catalog publishes, not a
133
133
  * gate, a badge, or an install decision. */
134
134
  forked?: boolean;
135
+ /** The sha256 that keys this entry's icon in the catalog's icons sidecar
136
+ * (registry `Entry.icon`; design 2026-10-23-shop-plugin-icons §6.1). Present
137
+ * exactly when the build published an icon for the entry. The bytes are not
138
+ * on the entry but in the sidecar, which holds each distinct icon once, so
139
+ * this is only the key. Additive and optional, so it rides every
140
+ * schemaVersion. */
141
+ icon?: string;
135
142
  }
136
143
  export interface DeniedEntry {
137
144
  name: string;
@@ -0,0 +1,42 @@
1
+ /**
2
+ * The npm package-name grammar a catalogue row's `name` must satisfy.
3
+ *
4
+ * ONE definition, read in three places: the Host's entry schema
5
+ * (`host/catalog.ts`), the registry's gate (`registry/scripts/src/gate.ts`)
6
+ * and `emit`'s last-line invariant. The dependency can only point this way —
7
+ * the package's tsconfig pins `rootDir: "src"`, so the registry reaches in
8
+ * and nothing here can reach out (the same reason `shop-like.ts` lives here).
9
+ *
10
+ * Why it is narrower than npm's own rule: `validate-npm-package-name` accepts
11
+ * a scope beginning with `_` or `.` — `@_iluxury/dsh-routerai-price-watcher`
12
+ * is valid for a NEW publication — while this grammar requires the scope's
13
+ * first character to be a letter or digit. That was a deliberate argv-safety
14
+ * choice when the rule lived only in the client: the name becomes half of an
15
+ * install spec, and everything this excludes is shell punctuation. It stopped
16
+ * being merely a client rule the moment a catalogue shipped, because the
17
+ * clients parse the WHOLE data file as one zod object: a single name outside
18
+ * this grammar costs every listing, not one. On 2026-10-30
19
+ * `@_iluxury/dsh-routerai-price-watcher` did exactly that — valid on npm, no
20
+ * gate rule to catch it, and every 0.8.0+ shop answered 「暂时无法读取目录」
21
+ * for a 21,493-row catalogue. The gate now admits only what this parses.
22
+ *
23
+ * The narrow side is therefore the WIRE CONTRACT, frozen by the installed
24
+ * base: widening it in a client release also widens the gate, because this is
25
+ * one constant, and the catalogue would then carry names every older client
26
+ * still refuses. Do not widen it without a way to know which client versions
27
+ * are installed; npm's per-version download counts cannot answer that (the
28
+ * measurement is in `emit.ts`'s `peers` comment).
29
+ *
30
+ * @module shared/npm-name
31
+ */
32
+ /**
33
+ * An optional `@scope/`, then a name starting with a letter or digit and
34
+ * continuing in lowercase letters, digits, `.`, `_` or `-`. No uppercase, no
35
+ * leading dot or underscore on either segment, and no shell punctuation.
36
+ */
37
+ export declare const CATALOG_NPM_NAME: RegExp;
38
+ /**
39
+ * Whether a catalogue row can carry `name`.
40
+ * @param name - the npm package name, taken from the published packument.
41
+ */
42
+ export declare function isCatalogNpmName(name: string): boolean;
@@ -6,8 +6,13 @@
6
6
  /**
7
7
  * Parse an uncompressed tar archive into path → bytes.
8
8
  *
9
- * Directory entries and every non-regular type (symlinks, pax and GNU
10
- * extension headers) are skipped: npm packs regular files under `package/`,
11
- * and a catalog tarball that needs anything else is not one we published.
9
+ * Directory entries and the type flags that carry no file are skipped: npm
10
+ * packs regular files under `package/`, and a catalog tarball that needs
11
+ * anything else is not one we published. A pax (`x`) or GNU (`L`) header is not
12
+ * a file either, but it NAMES the next one: a path too long or too wide for a
13
+ * ustar header arrives this way, and skipping the header without reading it
14
+ * left its file under a truncated name, reported missing from an archive that
15
+ * ships it ({@link pathFromPax}).
16
+ * Each path is spelled by its bytes, one character each ({@link cstring}).
12
17
  */
13
18
  export declare function readTar(buffer: Buffer): Map<string, Buffer>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-plugin-shop",
3
- "version": "0.9.0",
4
- "description": "The DeepSeek Harness plugin shop: browse, install, enable, and update dsh plugins from a git-auditable catalog.",
3
+ "version": "0.10.0-beta.0",
4
+ "description": "Browse, install, enable, and update plugins for DeepSeek Harness.",
5
5
  "icon": "./assets/icon.png",
6
6
  "keywords": [
7
7
  "dsh-plugin",