@adea-ai/plugins 4.0.0 → 4.0.6

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.
Files changed (147) hide show
  1. package/dist/agent-plugins-catalog.d.ts +2 -4
  2. package/dist/agent-plugins-catalog.js +42 -50
  3. package/dist/agent-plugins-catalog.js.map +1 -1
  4. package/dist/agent-plugins-schema.d.ts +8 -0
  5. package/dist/agent-plugins-schema.js +10 -1
  6. package/dist/agent-plugins-schema.js.map +1 -1
  7. package/dist/artifacts.d.ts +57 -0
  8. package/dist/artifacts.js +159 -0
  9. package/dist/artifacts.js.map +1 -0
  10. package/dist/build.d.ts +20 -0
  11. package/dist/build.js +103 -0
  12. package/dist/build.js.map +1 -0
  13. package/dist/capabilities.d.ts +7 -0
  14. package/dist/capabilities.js +116 -0
  15. package/dist/capabilities.js.map +1 -0
  16. package/dist/catalog-store.d.ts +76 -0
  17. package/dist/catalog-store.js +463 -0
  18. package/dist/catalog-store.js.map +1 -0
  19. package/dist/concurrency.d.ts +1 -0
  20. package/dist/concurrency.js +15 -0
  21. package/dist/concurrency.js.map +1 -0
  22. package/dist/consumer-index.d.ts +7 -29
  23. package/dist/consumer-index.js +24 -15
  24. package/dist/consumer-index.js.map +1 -1
  25. package/dist/digest.d.ts +13 -0
  26. package/dist/digest.js +47 -0
  27. package/dist/digest.js.map +1 -0
  28. package/dist/fs-atomic.d.ts +7 -0
  29. package/dist/fs-atomic.js +30 -0
  30. package/dist/fs-atomic.js.map +1 -0
  31. package/dist/harness.js +2 -1
  32. package/dist/harness.js.map +1 -1
  33. package/dist/icon-mirror.d.ts +5 -4
  34. package/dist/icon-mirror.js +73 -72
  35. package/dist/icon-mirror.js.map +1 -1
  36. package/dist/icons.d.ts +2 -2
  37. package/dist/icons.js +4 -12
  38. package/dist/icons.js.map +1 -1
  39. package/dist/index.d.ts +16 -309
  40. package/dist/index.js +12 -1900
  41. package/dist/index.js.map +1 -1
  42. package/dist/integrity-manifest.d.ts +43 -13
  43. package/dist/integrity-manifest.js +28 -17
  44. package/dist/integrity-manifest.js.map +1 -1
  45. package/dist/json-values.d.ts +3 -0
  46. package/dist/json-values.js +10 -0
  47. package/dist/json-values.js.map +1 -0
  48. package/dist/plugin-release.d.ts +38 -0
  49. package/dist/plugin-release.js +321 -0
  50. package/dist/plugin-release.js.map +1 -0
  51. package/dist/plugin-skips.d.ts +19 -0
  52. package/dist/plugin-skips.js +65 -0
  53. package/dist/plugin-skips.js.map +1 -0
  54. package/dist/policy.d.ts +13 -0
  55. package/dist/policy.js +26 -0
  56. package/dist/policy.js.map +1 -0
  57. package/dist/portable-catalog.d.ts +4 -4
  58. package/dist/portable-catalog.js +14 -126
  59. package/dist/portable-catalog.js.map +1 -1
  60. package/dist/portable-verify.d.ts +2 -0
  61. package/dist/portable-verify.js +68 -0
  62. package/dist/portable-verify.js.map +1 -0
  63. package/dist/publication.d.ts +12 -12
  64. package/dist/publication.js +31 -21
  65. package/dist/publication.js.map +1 -1
  66. package/dist/published-output.d.ts +17 -0
  67. package/dist/published-output.js +49 -0
  68. package/dist/published-output.js.map +1 -0
  69. package/dist/site-icons.d.ts +4 -3
  70. package/dist/site-icons.js +38 -11
  71. package/dist/site-icons.js.map +1 -1
  72. package/dist/snapshots.d.ts +39 -0
  73. package/dist/snapshots.js +238 -0
  74. package/dist/snapshots.js.map +1 -0
  75. package/dist/source-resolution.d.ts +28 -0
  76. package/dist/source-resolution.js +158 -0
  77. package/dist/source-resolution.js.map +1 -0
  78. package/dist/sources.d.ts +5 -1
  79. package/dist/sources.js +21 -27
  80. package/dist/sources.js.map +1 -1
  81. package/dist/synchronize.d.ts +44 -0
  82. package/dist/synchronize.js +118 -0
  83. package/dist/synchronize.js.map +1 -0
  84. package/dist/taxonomy.d.ts +23 -0
  85. package/dist/taxonomy.js +62 -0
  86. package/dist/taxonomy.js.map +1 -0
  87. package/dist/upstream.d.ts +42 -0
  88. package/dist/upstream.js +179 -0
  89. package/dist/upstream.js.map +1 -0
  90. package/dist/verify-artifacts.d.ts +36 -0
  91. package/dist/verify-artifacts.js +286 -0
  92. package/dist/verify-artifacts.js.map +1 -0
  93. package/native/build-provenance.txt +5 -5
  94. package/native/staged-reader-win32-arm64.node +0 -0
  95. package/native/staged-reader-win32-x64.node +0 -0
  96. package/package.json +3 -3
  97. package/src/agent-plugins-catalog.test.ts +2 -2
  98. package/src/agent-plugins-catalog.ts +46 -49
  99. package/src/agent-plugins-schema.ts +11 -1
  100. package/src/artifacts.test.ts +80 -0
  101. package/src/artifacts.ts +234 -0
  102. package/src/build.ts +131 -0
  103. package/src/capabilities.ts +153 -0
  104. package/src/catalog-store.ts +519 -0
  105. package/src/concurrency.ts +19 -0
  106. package/src/consumer-index.test.ts +147 -16
  107. package/src/consumer-index.ts +35 -43
  108. package/src/default-head.test.ts +143 -0
  109. package/src/digest.ts +55 -0
  110. package/src/fs-atomic.ts +32 -0
  111. package/src/harness.test.ts +4 -32
  112. package/src/harness.ts +2 -1
  113. package/src/icon-mirror.ts +78 -72
  114. package/src/icons.test.ts +0 -4
  115. package/src/icons.ts +4 -4
  116. package/src/index.test.ts +172 -46
  117. package/src/index.ts +58 -2562
  118. package/src/integrity-manifest.ts +41 -21
  119. package/src/json-values.ts +11 -0
  120. package/src/manifest-retry.test.ts +49 -0
  121. package/src/plugin-release.ts +457 -0
  122. package/src/plugin-skips.ts +110 -0
  123. package/src/policy.ts +39 -0
  124. package/src/portable-catalog.test.ts +0 -5
  125. package/src/portable-catalog.ts +16 -143
  126. package/src/portable-verify.ts +71 -0
  127. package/src/publication.test.ts +29 -1
  128. package/src/publication.ts +38 -22
  129. package/src/published-output.ts +60 -0
  130. package/src/site-icons.test.ts +73 -1
  131. package/src/site-icons.ts +31 -14
  132. package/src/snapshots.ts +287 -0
  133. package/src/source-config-sync.test.ts +84 -0
  134. package/src/source-digest.test.ts +61 -8
  135. package/src/source-resolution.ts +233 -0
  136. package/src/sources-json.test.ts +18 -2
  137. package/src/sources.ts +27 -33
  138. package/src/synchronize.ts +213 -0
  139. package/src/taxonomy.ts +87 -0
  140. package/src/upstream.ts +194 -0
  141. package/src/verify-artifacts.ts +365 -0
  142. package/src/write-artifacts.test.ts +374 -0
  143. package/dist/source-digest.d.ts +0 -2
  144. package/dist/source-digest.js +0 -12
  145. package/dist/source-digest.js.map +0 -1
  146. package/native/README.md +0 -24
  147. package/src/source-digest.ts +0 -14
@@ -0,0 +1,286 @@
1
+ import { parseIntegrityManifest, publishedAssetOf, } from './integrity-manifest.js';
2
+ import { CATALOG_INDEX_ARTIFACT, iconCoverage, } from './consumer-index.js';
3
+ import { digest } from './digest.js';
4
+ import { assertRepositoryAllowed, DEFAULT_POLICY } from './policy.js';
5
+ import { CatalogSchema, SourcesLockSchema } from './schema.js';
6
+ import { safeRelativePath } from './sources.js';
7
+ export function verifyArtifacts(artifacts) {
8
+ const parsedCatalog = CatalogSchema.parse(JSON.parse(artifacts['catalog.v1.json']));
9
+ verifyCatalogReferences(parsedCatalog);
10
+ const lock = SourcesLockSchema.parse(JSON.parse(artifacts['sources.lock.json']));
11
+ const summary = JSON.parse(artifacts['catalog-summary.v1.json']);
12
+ const compatibility = JSON.parse(artifacts['compatibility.v1.json']);
13
+ const categories = JSON.parse(artifacts['categories.v1.json']);
14
+ const integrity = parseIntegrityManifest(JSON.parse(artifacts['integrity.json']));
15
+ if (parsedCatalog.sources.length !== lock.sources.length)
16
+ throw new Error('INTEGRITY_SOURCE_COUNT_MISMATCH');
17
+ if (summary.schemaVersion !== 1 ||
18
+ summary.catalogId !== parsedCatalog.catalogId ||
19
+ summary.sourceCount !== parsedCatalog.sources.length ||
20
+ summary.pluginCount !== parsedCatalog.plugins.length ||
21
+ !Array.isArray(summary.search) ||
22
+ compatibility.schemaVersion !== 1 ||
23
+ compatibility.catalogId !== parsedCatalog.catalogId ||
24
+ !Array.isArray(compatibility.plugins) ||
25
+ compatibility.plugins.length !== parsedCatalog.plugins.length ||
26
+ categories.schemaVersion !== 1 ||
27
+ categories.catalogId !== parsedCatalog.catalogId ||
28
+ !Array.isArray(categories.categories) ||
29
+ (categories.products !== undefined &&
30
+ (typeof categories.products !== 'object' || categories.products === null)) ||
31
+ (categories.diagnostics !== undefined && !Array.isArray(categories.diagnostics)) ||
32
+ integrity.catalogId !== parsedCatalog.catalogId) {
33
+ throw new Error('INTEGRITY_ARTIFACT_METADATA_MISMATCH');
34
+ }
35
+ // The published file set is exactly what integrity.json enumerates, so the
36
+ // shards can grow with the category configuration without a fixed list here.
37
+ for (const name of Object.keys(artifacts))
38
+ if (name !== 'integrity.json' && integrity.files[name] === undefined)
39
+ throw new Error(`INTEGRITY_FILE_SET_MISMATCH: ${name}`);
40
+ for (const [name, expected] of Object.entries(integrity.files)) {
41
+ const content = artifacts[name];
42
+ if (content === undefined)
43
+ throw new Error(`INTEGRITY_FILE_SET_MISMATCH: ${name}`);
44
+ if (digest(content) !== expected)
45
+ throw new Error(`INTEGRITY_DIGEST_MISMATCH: ${name}`);
46
+ }
47
+ const indexArtifact = artifacts[CATALOG_INDEX_ARTIFACT];
48
+ const verification = verifyConsumerIndex(artifacts['categories.v1.json'], parsedCatalog, indexArtifact);
49
+ if (verification.hasConsumerIndex && indexArtifact === undefined)
50
+ throw new Error(`SHARD_MISSING: ${CATALOG_INDEX_ARTIFACT}`);
51
+ for (const shard of verification.shards)
52
+ verifyShardArtifact(shard, artifacts[shard.name], verification, parsedCatalog.catalogId);
53
+ verifyIconAssets(integrity.assets ?? [], verification);
54
+ }
55
+ /**
56
+ * Re-checks one consumer shard against the navigation index: a shelf carries
57
+ * exactly the curated products in order, and a category list carries exactly
58
+ * the category's products in order. The expected catalog ID must come from a
59
+ * separately verified catalog, not from the shard being checked.
60
+ */
61
+ export function verifyShardArtifact(shard, content, verification, catalogId) {
62
+ if (!CatalogSchema.shape.catalogId.safeParse(catalogId).success)
63
+ throw new Error('SHARD_CATALOG_ID_REQUIRED');
64
+ if (content === undefined)
65
+ throw new Error(`SHARD_MISSING: ${shard.name}`);
66
+ const parsed = JSON.parse(content);
67
+ if (parsed.schemaVersion !== 1 ||
68
+ parsed.catalogId !== catalogId ||
69
+ (shard.kind !== 'index' && parsed.category !== shard.category))
70
+ throw new Error(`SHARD_IDENTITY_MISMATCH: ${shard.name}`);
71
+ const products = shard.kind === 'index'
72
+ ? Object.values((parsed.products ?? {}))
73
+ : parsed.products;
74
+ if (!Array.isArray(products))
75
+ throw new Error(`SHARD_PRODUCTS_INVALID: ${shard.name}`);
76
+ const keys = products.map((product) => product.productKey);
77
+ if (new Set(keys).size !== keys.length)
78
+ throw new Error(`SHARD_DUPLICATE_PRODUCT: ${shard.name}`);
79
+ if (shard.kind === 'index') {
80
+ const expected = Object.keys(verification.products ?? {}).toSorted();
81
+ if (keys.toSorted().join('\n') !== expected.join('\n'))
82
+ throw new Error('SHARD_INDEX_MEMBERSHIP_MISMATCH');
83
+ return;
84
+ }
85
+ const category = verification.categories?.find((item) => item.category === shard.category);
86
+ if (!category)
87
+ throw new Error(`SHARD_CATEGORY_UNKNOWN: ${shard.name}`);
88
+ const expected = shard.kind === 'shelf' ? category.topProductKeys : category.productKeys;
89
+ if (keys.join('\n') !== expected.join('\n'))
90
+ throw new Error(`SHARD_ORDER_MISMATCH: ${shard.name}`);
91
+ for (const product of products) {
92
+ const index = verification.products?.[product.productKey];
93
+ if (!index || digest(index) !== digest(product))
94
+ throw new Error(`SHARD_PRODUCT_MISMATCH: ${shard.name}: ${product.productKey}`);
95
+ }
96
+ }
97
+ function verifyIconAssets(declared, verification) {
98
+ const referenced = new Map();
99
+ for (const product of Object.values(verification.products ?? {})) {
100
+ if (!product.icon)
101
+ continue;
102
+ const existing = referenced.get(product.icon.asset);
103
+ if (existing && existing.digest !== product.icon.digest)
104
+ throw new Error(`ICON_ASSET_DIGEST_CONFLICT: ${product.icon.asset}`);
105
+ referenced.set(product.icon.asset, publishedAssetOf(product.icon));
106
+ }
107
+ if (declared.length !== referenced.size)
108
+ throw new Error('INTEGRITY_ASSET_SET_MISMATCH');
109
+ for (const asset of declared) {
110
+ const expected = referenced.get(asset.name);
111
+ if (!expected)
112
+ throw new Error(`INTEGRITY_ASSET_UNDECLARED: ${asset.name}`);
113
+ if (expected.digest !== asset.digest ||
114
+ expected.bytes !== asset.bytes ||
115
+ expected.contentType !== asset.contentType ||
116
+ expected.kind !== asset.kind ||
117
+ expected.origin !== asset.origin)
118
+ throw new Error(`INTEGRITY_ASSET_MISMATCH: ${asset.name}`);
119
+ }
120
+ }
121
+ /**
122
+ * Re-checks the published consumer index against the catalog it indexes. The
123
+ * index is what Adea renders directly, so a contradiction between the two
124
+ * artifacts must never reach a release. Snapshots published before the index
125
+ * existed carry membership only; those are still membership-checked and
126
+ * reported as `hasConsumerIndex: false`.
127
+ */
128
+ export function verifyConsumerIndex(content, catalog, indexContent) {
129
+ const index = JSON.parse(content);
130
+ const knownPlugins = new Map(catalog.plugins.map((plugin) => [plugin.pluginId, plugin]));
131
+ // Products live in the index shard; the navigation artifact only points at it.
132
+ const shard = indexContent ? JSON.parse(indexContent) : undefined;
133
+ const products = shard && typeof shard.products === 'object' && shard.products !== null
134
+ ? shard.products
135
+ : typeof index.products === 'object' && index.products !== null
136
+ ? index.products
137
+ : undefined;
138
+ const diagnostics = Array.isArray(index.diagnostics) ? index.diagnostics : [];
139
+ for (const category of index.categories ?? []) {
140
+ const members = catalog.plugins.filter((plugin) => plugin.categories.includes(category.category));
141
+ if (category.pluginCount !== undefined && category.pluginCount !== members.length)
142
+ throw new Error(`CONSUMER_INDEX_PLUGIN_COUNT_MISMATCH: ${category.category}`);
143
+ if (category.pluginIds.length !== members.length)
144
+ throw new Error(`CONSUMER_INDEX_PLUGIN_LIST_MISMATCH: ${category.category}`);
145
+ if (new Set(category.pluginIds).size !== category.pluginIds.length)
146
+ throw new Error(`CONSUMER_INDEX_DUPLICATE_PLUGIN: ${category.category}`);
147
+ for (const pluginId of category.pluginIds) {
148
+ const plugin = knownPlugins.get(pluginId);
149
+ if (!plugin || !plugin.categories.includes(category.category))
150
+ throw new Error(`CONSUMER_INDEX_FOREIGN_PLUGIN: ${category.category}: ${pluginId}`);
151
+ }
152
+ if (!products)
153
+ continue;
154
+ if (category.productKeys === undefined || category.topProductKeys === undefined)
155
+ throw new Error(`CONSUMER_INDEX_PRODUCTS_INCOMPLETE: ${category.category}`);
156
+ if (new Set(category.productKeys).size !== category.productKeys.length)
157
+ throw new Error(`CONSUMER_INDEX_DUPLICATE_PRODUCT: ${category.category}`);
158
+ for (const productKey of category.productKeys) {
159
+ const product = products[productKey];
160
+ if (!product)
161
+ throw new Error(`CONSUMER_INDEX_UNKNOWN_PRODUCT: ${productKey}`);
162
+ if (!product.categories.includes(category.category))
163
+ throw new Error(`CONSUMER_INDEX_PRODUCT_CATEGORY_MISMATCH: ${productKey}`);
164
+ }
165
+ if (category.productCount !== category.productKeys.length)
166
+ throw new Error(`CONSUMER_INDEX_PRODUCT_COUNT_MISMATCH: ${category.category}`);
167
+ const topCount = index.topCount;
168
+ if (topCount === undefined || !Number.isInteger(topCount) || topCount < 0)
169
+ throw new Error('CONSUMER_INDEX_TOP_COUNT_INVALID');
170
+ if (category.topProductKeys.length > topCount)
171
+ throw new Error(`CONSUMER_INDEX_TOP_OVERFLOW: ${category.category}`);
172
+ const shelved = new Set();
173
+ for (const product of Object.values(products)) {
174
+ // Indexes published before the install facts existed carry no `release`,
175
+ // and are still valid; a record that does carry one must agree with the
176
+ // catalog it claims to describe.
177
+ if (product.release) {
178
+ const plugin = knownPlugins.get(product.pluginId);
179
+ const release = plugin?.availableReleases.find((candidate) => candidate.releaseId === plugin.currentReleaseId);
180
+ if (!plugin ||
181
+ !release ||
182
+ product.release.releaseId !== release.releaseId ||
183
+ product.release.canonicalContentDigest !== release.canonicalContentDigest ||
184
+ product.release.sourceRevision !== release.resolvedCommitSha ||
185
+ product.provenance?.resolvedCommitSha !== release.resolvedCommitSha)
186
+ throw new Error(`CONSUMER_INDEX_RELEASE_MISMATCH: ${product.productKey}`);
187
+ }
188
+ const icon = product.icon;
189
+ if (!icon?.assetUrl)
190
+ continue;
191
+ if (!icon.assetUrl.startsWith('https://') || !icon.assetUrl.endsWith(`/${icon.asset}`))
192
+ throw new Error(`CONSUMER_INDEX_ASSET_URL_INVALID: ${icon.asset}`);
193
+ }
194
+ for (const productKey of category.topProductKeys) {
195
+ if (!category.productKeys.includes(productKey))
196
+ throw new Error(`CONSUMER_INDEX_TOP_NOT_MEMBER: ${category.category}: ${productKey}`);
197
+ if (shelved.has(productKey))
198
+ throw new Error(`CONSUMER_INDEX_TOP_REPEATED: ${productKey}`);
199
+ shelved.add(productKey);
200
+ }
201
+ }
202
+ if (products) {
203
+ // A product headlines one category only, so no product is shelved twice.
204
+ const claimed = new Set();
205
+ for (const category of index.categories ?? [])
206
+ for (const productKey of category.topProductKeys ?? []) {
207
+ if (claimed.has(productKey))
208
+ throw new Error(`CONSUMER_INDEX_TOP_CROSS_CATEGORY: ${productKey}`);
209
+ claimed.add(productKey);
210
+ }
211
+ for (const [productKey, product] of Object.entries(products)) {
212
+ if (productKey !== product.productKey)
213
+ throw new Error('CONSUMER_INDEX_PRODUCT_KEY_MISMATCH');
214
+ if (product.variantPluginIds[0] !== product.pluginId)
215
+ throw new Error(`CONSUMER_INDEX_CANONICAL_NOT_FIRST: ${productKey}`);
216
+ const variants = new Set(product.variantPluginIds.map((pluginId) => {
217
+ const plugin = knownPlugins.get(pluginId);
218
+ if (!plugin)
219
+ throw new Error(`CONSUMER_INDEX_UNKNOWN_PLUGIN: ${pluginId}`);
220
+ if (plugin.productGroupingKey !== productKey)
221
+ throw new Error(`CONSUMER_INDEX_VARIANT_PRODUCT_MISMATCH: ${pluginId}`);
222
+ return pluginId;
223
+ }));
224
+ if (variants.size !== product.variantPluginIds.length)
225
+ throw new Error(`CONSUMER_INDEX_DUPLICATE_VARIANT: ${productKey}`);
226
+ }
227
+ const counts = shard?.counts ?? index.counts;
228
+ if (counts?.plugins !== catalog.plugins.length)
229
+ throw new Error('CONSUMER_INDEX_TOTAL_MISMATCH');
230
+ if (counts?.products !== Object.keys(products).length)
231
+ throw new Error('CONSUMER_INDEX_PRODUCT_TOTAL_MISMATCH');
232
+ if (counts?.redundantPlugins !== catalog.plugins.length - counts.products)
233
+ throw new Error('CONSUMER_INDEX_REDUNDANCY_MISMATCH');
234
+ if (index.counts && shard?.counts && digest(index.counts) !== digest(shard.counts))
235
+ throw new Error('CONSUMER_INDEX_COUNTS_MISMATCH');
236
+ if (shard?.topCount !== undefined && index.topCount !== shard.topCount)
237
+ throw new Error('CONSUMER_INDEX_TOP_COUNT_MISMATCH');
238
+ }
239
+ if (products && index.iconCoverage) {
240
+ const expected = iconCoverage({ products });
241
+ if (index.iconCoverage.total !== expected.total ||
242
+ index.iconCoverage.content !== expected.content ||
243
+ index.iconCoverage.favicon !== expected.favicon ||
244
+ index.iconCoverage.monogramOnly !== expected.monogramOnly ||
245
+ index.iconCoverage.monogramProductKeys.join('\n') !== expected.monogramProductKeys.join('\n'))
246
+ throw new Error('CONSUMER_INDEX_ICON_COVERAGE_MISMATCH');
247
+ }
248
+ const shards = [
249
+ ...(products ? [{ name: CATALOG_INDEX_ARTIFACT, kind: 'index' }] : []),
250
+ ...(index.categories ?? []).flatMap((category) => products && category.shelfArtifact && category.listArtifact
251
+ ? [
252
+ { name: category.shelfArtifact, kind: 'shelf', category: category.category },
253
+ { name: category.listArtifact, kind: 'list', category: category.category },
254
+ ]
255
+ : []),
256
+ ];
257
+ return {
258
+ hasConsumerIndex: products !== undefined,
259
+ diagnostics,
260
+ ...(products ? { counts: index.counts } : {}),
261
+ ...(products && index.topCount !== undefined ? { topCount: index.topCount } : {}),
262
+ ...(products ? { products, categories: index.categories ?? [] } : {}),
263
+ shards: products ? shards : [],
264
+ };
265
+ }
266
+ export function verifyCatalogReferences(catalog, policy = DEFAULT_POLICY) {
267
+ for (const source of catalog.sources) {
268
+ assertRepositoryAllowed(source.repositoryUrl, policy);
269
+ validateCatalogPath(source.manifestPath, 'SOURCE_MANIFEST_PATH_INVALID');
270
+ }
271
+ for (const plugin of catalog.plugins) {
272
+ assertRepositoryAllowed(plugin.provenance.repositoryUrl, policy);
273
+ validateCatalogPath(plugin.provenance.pluginSubdirectory, 'PROVENANCE_PATH_INVALID');
274
+ for (const release of plugin.availableReleases) {
275
+ assertRepositoryAllowed(release.resolvedRepositoryUrl, policy);
276
+ validateCatalogPath(release.pluginSubdirectory, 'RELEASE_PATH_INVALID');
277
+ for (const path of release.fileIndex)
278
+ validateCatalogPath(path, 'RELEASE_FILE_PATH_INVALID');
279
+ }
280
+ }
281
+ }
282
+ function validateCatalogPath(path, code) {
283
+ if (path !== '.')
284
+ safeRelativePath(path, code);
285
+ }
286
+ //# sourceMappingURL=verify-artifacts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify-artifacts.js","sourceRoot":"","sources":["../src/verify-artifacts.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- source_commit 509620fc5170f5736f99074500ac04546da2196a
1
+ source_commit 562d176d4dd81b49043895b8715fe4a350c0892b
2
2
  12125c7ab1a1e2d7cbe538343e2a11ef4d7fb0fa0310c5251d8606bf20f26834 packages/plugins/native/staged-reader.c
3
- 04b0085f0a471b87c11c67d2f9c39174f239aa1865cd83a3bec201efb0872ee8 packages/plugins/native/staged-reader-test-win32-arm64.node
4
- 0e48eff409720188de9e53d0ead458f4240c415e64460be113fda9cbf4b9cefc packages/plugins/native/staged-reader-test-win32-x64.node
5
- 5dd361a5ff4fbe2ac4949a59083e1b7fae0c54f13f48b0a17d67c02b2e8962ff packages/plugins/native/staged-reader-win32-arm64.node
6
- abf65f3e3e1ef1f899b627065b20fd9bf027e70493939505695bde976284cc1a packages/plugins/native/staged-reader-win32-x64.node
3
+ 19fc1fbf9a4e1fa31a130a20f4108e1e64ea72d3d30ef29b259c4a0164221261 packages/plugins/native/staged-reader-test-win32-arm64.node
4
+ 030e0cf5e08996b18672430246d39ad29e9d01aa25d34869b7873b5056840e2b packages/plugins/native/staged-reader-test-win32-x64.node
5
+ dd2d78b06c6047a366ec339223754bd2f1d1706300967532436cf15990d81421 packages/plugins/native/staged-reader-win32-arm64.node
6
+ cd01057f673bdf1694890fe0037ad522c3f5bcfe08d2b0ae5cc84268d3977789 packages/plugins/native/staged-reader-win32-x64.node
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adea-ai/plugins",
3
- "version": "4.0.0",
3
+ "version": "4.0.6",
4
4
  "description": "Deterministic compiler for AI agent plugin marketplaces: schemas, source parsing, provenance verification, per-harness materialization, and provenance-checked static artifacts.",
5
5
  "keywords": [
6
6
  "agents",
@@ -78,14 +78,14 @@
78
78
  "./schema/*": "./schemas/*"
79
79
  },
80
80
  "publishConfig": {
81
- "access": "public",
82
- "provenance": true
81
+ "access": "public"
83
82
  },
84
83
  "scripts": {
85
84
  "build": "node --input-type=module -e \"import { rmSync } from 'node:fs'; rmSync('dist', { recursive: true, force: true })\" && tsc -p tsconfig.json",
86
85
  "typecheck": "bun check -p tsconfig.json"
87
86
  },
88
87
  "dependencies": {
88
+ "parse5": "^8.0.0",
89
89
  "tar-stream": "^3.2.1",
90
90
  "yaml": "2.9.1",
91
91
  "zod": "^4.6.6"
@@ -331,8 +331,8 @@ describe('canonical Agent Plugins package compiler', () => {
331
331
  }
332
332
  })
333
333
  it('rejects duplicate escaped JSON keys without prototype mutation', () => {
334
- assert.throws(() => parsePluginJson('{"x":1,"\\u0078":2}'))
335
- assert.throws(() => parsePluginJson('{"a":{"x":1,"x":2}}'))
334
+ assert.throws(() => parsePluginJson('{"x":1,"\\u0078":2}'), /duplicate JSON object key/)
335
+ assert.throws(() => parsePluginJson('{"a":{"x":1,"x":2}}'), /duplicate JSON object key/)
336
336
  const value = parsePluginJson('{"__proto__":{"polluted":true}}') as Record<string, unknown>
337
337
  assert.equal(Object.prototype.hasOwnProperty.call(value, '__proto__'), true)
338
338
  assert.equal(Object.prototype.hasOwnProperty.call({}, 'polluted'), false)
@@ -1,4 +1,3 @@
1
- import { createHash } from 'node:crypto'
2
1
  import { isIP } from 'node:net'
3
2
  import { posix } from 'node:path'
4
3
  import { validateHeaderName, validateHeaderValue } from 'node:http'
@@ -8,6 +7,7 @@ import {
8
7
  PLUGIN_SCHEMA_ID,
9
8
  MCP_SCHEMA_ID,
10
9
  NORMALIZER_VERSION,
10
+ PACKAGE_LIMITS,
11
11
  AgentManifestSchema,
12
12
  McpServerSchema,
13
13
  SkillFrontmatterSchema,
@@ -18,9 +18,11 @@ import {
18
18
  type PackageFile,
19
19
  type Diagnostic,
20
20
  } from './agent-plugins-schema.js'
21
- import { sourceDigest } from './source-digest.js'
21
+ import { byteDigest, canonicalJson, ordinalCompare, sourceDigest } from './digest.js'
22
22
 
23
23
  export { NORMALIZER_VERSION, sourceDigest }
24
+ // Public names of the shared canonical-JSON and digest helpers.
25
+ export { byteDigest as sha256, canonicalJson as stableJson, ordinalCompare as compare }
24
26
  const decoder = new TextDecoder('utf-8', { fatal: true })
25
27
  const encoder = new TextEncoder()
26
28
  const manifestKeys = new Set([
@@ -49,27 +51,12 @@ const remoteTransportHeaders = new Set([
49
51
  'transfer-encoding',
50
52
  'upgrade',
51
53
  ])
52
- const own = (value: object, key: string) => Object.prototype.hasOwnProperty.call(value, key)
53
- export const compare = (a: string, b: string): number => (a < b ? -1 : a > b ? 1 : 0)
54
- export function stableJson(value: unknown): string {
55
- if (value === null || typeof value !== 'object') return JSON.stringify(value)
56
- if (Array.isArray(value)) return `[${value.map(stableJson).join(',')}]`
57
- const record = value as Record<string, unknown>
58
- return `{${Object.keys(record)
59
- .toSorted(compare)
60
- .map((key) => `${JSON.stringify(key)}:${stableJson(record[key])}`)
61
- .join(',')}}`
62
- }
63
- export function sha256(value: string | Uint8Array): string {
64
- return `sha256:${createHash('sha256').update(value).digest('hex')}`
65
- }
66
-
67
54
  export function packageDigest(files: readonly PackageFile[]): string {
68
- return sha256(
69
- stableJson({
55
+ return byteDigest(
56
+ canonicalJson({
70
57
  algorithm: 'adea-package-files/1',
71
58
  files: [...files]
72
- .toSorted((a, b) => compare(a.targetPath, b.targetPath))
59
+ .toSorted((a, b) => ordinalCompare(a.targetPath, b.targetPath))
73
60
  .map((file) => ({
74
61
  path: file.targetPath,
75
62
  digest: file.digest,
@@ -217,7 +204,7 @@ function portableName(name: string): string {
217
204
  ) || 'plugin'
218
205
  return cleaned.length <= 64
219
206
  ? cleaned
220
- : `${trimPortableEdges(cleaned.slice(0, 54))}-${sha256(name).slice(-8)}`
207
+ : `${trimPortableEdges(cleaned.slice(0, 54))}-${byteDigest(name).slice(-8)}`
221
208
  }
222
209
  function diagnostic(
223
210
  code: string,
@@ -233,7 +220,7 @@ function nativeManifest(raw: unknown, diagnostics: Diagnostic[]): AgentManifest
233
220
  const filtered = Object.fromEntries(Object.entries(raw).filter(([key]) => manifestKeys.has(key)))
234
221
  for (const key of Object.keys(raw)
235
222
  .filter((field) => !manifestKeys.has(field))
236
- .toSorted(compare))
223
+ .toSorted(ordinalCompare))
237
224
  diagnostics.push(
238
225
  diagnostic(
239
226
  'UNKNOWN_MANIFEST_FIELD',
@@ -243,7 +230,7 @@ function nativeManifest(raw: unknown, diagnostics: Diagnostic[]): AgentManifest
243
230
  'warning'
244
231
  )
245
232
  )
246
- if (own(filtered, 'extensions')) {
233
+ if (Object.hasOwn(filtered, 'extensions')) {
247
234
  if (!isRecord(filtered.extensions)) {
248
235
  delete filtered.extensions
249
236
  diagnostics.push(
@@ -360,7 +347,7 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
360
347
  (() => {
361
348
  try {
362
349
  const raw = parsePluginJson(decoder.decode(files.get('plugin.json')!))
363
- return isRecord(raw) && own(raw, '$schema')
350
+ return isRecord(raw) && Object.hasOwn(raw, '$schema')
364
351
  } catch {
365
352
  return true
366
353
  }
@@ -396,7 +383,8 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
396
383
  const paths = new Set<string>()
397
384
  const spellings = new Map<string, string>()
398
385
  let total = 0
399
- if (files.size > 4096) throw new Error('Package exceeds file-count policy.')
386
+ if (files.size > PACKAGE_LIMITS.maxFilesPerPlugin)
387
+ throw new Error('Package exceeds file-count policy.')
400
388
  for (const [path, bytes] of files) {
401
389
  assertPackagePath(path)
402
390
  const folded = path.normalize('NFC').toLowerCase()
@@ -409,7 +397,10 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
409
397
  spellings.set(key, component)
410
398
  }
411
399
  total += bytes.byteLength
412
- if (bytes.byteLength > 5 * 1024 * 1024 || total > 50 * 1024 * 1024)
400
+ if (
401
+ bytes.byteLength > PACKAGE_LIMITS.maxFileBytes ||
402
+ total > PACKAGE_LIMITS.maxBytesPerPlugin
403
+ )
413
404
  throw new Error('Package exceeds byte-size policy.')
414
405
  for (let parent = posix.dirname(path); parent !== '.'; parent = posix.dirname(parent))
415
406
  if (files.has(parent)) throw new Error('File/directory path collision.')
@@ -469,7 +460,7 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
469
460
  diagnostic('INVALID_SKILLS_LOCATION', 'skills', 'skills', 'skills must be a directory.')
470
461
  )
471
462
  }
472
- for (const [path, bytes] of [...files].toSorted(([a], [b]) => compare(a, b))) {
463
+ for (const [path, bytes] of [...files].toSorted(([a], [b]) => ordinalCompare(a, b))) {
473
464
  const match = /^skills\/([^/]+)\/SKILL\.md$/.exec(path)
474
465
  if (!match) continue
475
466
  try {
@@ -551,7 +542,7 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
551
542
  mcpEntries = {}
552
543
  }
553
544
  for (const [name, inputServer] of Object.entries(mcpEntries).toSorted(([a], [b]) =>
554
- compare(a, b)
545
+ ordinalCompare(a, b)
555
546
  )) {
556
547
  try {
557
548
  if (['__proto__', 'constructor', 'prototype'].includes(name) || hasControlCharacters(name))
@@ -612,10 +603,10 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
612
603
  ...(extras.get('client-extension') ?? []),
613
604
  `plugin.json/extensions/${key}`,
614
605
  ])
615
- for (const [kind, paths] of [...extras].toSorted(([a], [b]) => compare(a, b)))
606
+ for (const [kind, paths] of [...extras].toSorted(([a], [b]) => ordinalCompare(a, b)))
616
607
  nonPortable.push({
617
608
  kind,
618
- paths: [...new Set(paths)].toSorted(compare),
609
+ paths: [...new Set(paths)].toSorted(ordinalCompare),
619
610
  reason:
620
611
  'Preserved as source content, not activated or presented as portable Agent Plugins behavior.',
621
612
  })
@@ -634,7 +625,7 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
634
625
  action: 'copy',
635
626
  sourcePath: path,
636
627
  targetPath: path,
637
- digest: sha256(bytes),
628
+ digest: byteDigest(bytes),
638
629
  preserveMode: true,
639
630
  })
640
631
  }
@@ -643,14 +634,20 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
643
634
  ['plugin.json', manifest],
644
635
  ['mcp.json', { $schema: MCP_SCHEMA_ID, mcpServers }],
645
636
  ] as const) {
646
- const content = stableJson(data) + '\n'
647
- operations.push({ action: 'write', targetPath, content, digest: sha256(content), mode: '0644' })
637
+ const content = canonicalJson(data) + '\n'
638
+ operations.push({
639
+ action: 'write',
640
+ targetPath,
641
+ content,
642
+ digest: byteDigest(content),
643
+ mode: '0644',
644
+ })
648
645
  }
649
- const sortedOperations = operations.toSorted((a, b) => compare(a.targetPath, b.targetPath))
646
+ const sortedOperations = operations.toSorted((a, b) => ordinalCompare(a.targetPath, b.targetPath))
650
647
  const values = [...servers.values()]
651
648
  const local = values.filter((server) => server.type === 'stdio')
652
649
  const sortedDiagnostics = diagnostics.toSorted((a, b) =>
653
- compare(`${a.path}:${a.code}`, `${b.path}:${b.code}`)
650
+ ordinalCompare(`${a.path}:${a.code}`, `${b.path}:${b.code}`)
654
651
  )
655
652
  try {
656
653
  return verifyAgentPackage({
@@ -666,8 +663,8 @@ export function compileAgentPackage(input: CompilePackageInput): AgentPackage {
666
663
  mcpServers,
667
664
  requirements: {
668
665
  skills: skills.length > 0,
669
- mcpTransports: [...new Set(values.map((server) => server.type))].toSorted(compare),
670
- executables: [...new Set(local.map((server) => server.command))].toSorted(compare),
666
+ mcpTransports: [...new Set(values.map((server) => server.type))].toSorted(ordinalCompare),
667
+ executables: [...new Set(local.map((server) => server.command))].toSorted(ordinalCompare),
671
668
  environmentReview:
672
669
  local.length > 0 ||
673
670
  skills.some((skill) => !!skill.compatibility || !!skill.allowedTools) ||
@@ -703,7 +700,7 @@ export function verifyAgentPackage(input: unknown): AgentPackage {
703
700
  if (paths.has(key)) throw new Error('Duplicate package target.')
704
701
  paths.add(key)
705
702
  if (file.action === 'copy') assertPackagePath(file.sourcePath)
706
- else if (sha256(file.content) !== file.digest)
703
+ else if (byteDigest(file.content) !== file.digest)
707
704
  throw new Error('Generated file digest mismatch.')
708
705
  }
709
706
  for (const path of paths)
@@ -714,11 +711,11 @@ export function verifyAgentPackage(input: unknown): AgentPackage {
714
711
  if (!file || file.action !== 'write') throw new Error('Missing canonical control file.')
715
712
  return parsePluginJson(file.content)
716
713
  }
717
- if (stableJson(generated('plugin.json')) !== stableJson(pkg.manifest))
714
+ if (canonicalJson(generated('plugin.json')) !== canonicalJson(pkg.manifest))
718
715
  throw new Error('Manifest descriptor differs from package bytes.')
719
716
  if (
720
- stableJson(generated('mcp.json')) !==
721
- stableJson({ $schema: MCP_SCHEMA_ID, mcpServers: pkg.mcpServers })
717
+ canonicalJson(generated('mcp.json')) !==
718
+ canonicalJson({ $schema: MCP_SCHEMA_ID, mcpServers: pkg.mcpServers })
722
719
  )
723
720
  throw new Error('MCP descriptor differs from package bytes.')
724
721
  for (const server of Object.values(pkg.mcpServers)) validateServer(server)
@@ -739,23 +736,23 @@ export function verifyAgentPackage(input: unknown): AgentPackage {
739
736
  throw new Error('Skill inventory differs from package discovery.')
740
737
  const expectedTransports = [
741
738
  ...new Set(Object.values(pkg.mcpServers).map((server) => server.type)),
742
- ].toSorted(compare)
739
+ ].toSorted(ordinalCompare)
743
740
  const expectedExecutables = [
744
741
  ...new Set(
745
742
  Object.values(pkg.mcpServers)
746
743
  .filter((server) => server.type === 'stdio')
747
744
  .map((server) => server.command)
748
745
  ),
749
- ].toSorted(compare)
746
+ ].toSorted(ordinalCompare)
750
747
  if (
751
- stableJson([...pkg.requirements.executables].toSorted(compare)) !==
752
- stableJson(expectedExecutables)
748
+ canonicalJson([...pkg.requirements.executables].toSorted(ordinalCompare)) !==
749
+ canonicalJson(expectedExecutables)
753
750
  )
754
751
  throw new Error('Package executable requirements differ from components.')
755
752
  if (
756
753
  pkg.requirements.skills !== pkg.skills.length > 0 ||
757
- stableJson([...pkg.requirements.mcpTransports].toSorted(compare)) !==
758
- stableJson(expectedTransports)
754
+ canonicalJson([...pkg.requirements.mcpTransports].toSorted(ordinalCompare)) !==
755
+ canonicalJson(expectedTransports)
759
756
  )
760
757
  throw new Error('Package requirements differ from components.')
761
758
  if (
@@ -779,13 +776,13 @@ export function materializeAgentPackage(
779
776
  name: pkg.manifest!.name,
780
777
  sourceDigest: pkg.sourceDigest,
781
778
  })
782
- if (stableJson(rebuilt) !== stableJson(pkg))
779
+ if (canonicalJson(rebuilt) !== canonicalJson(pkg))
783
780
  throw new Error('Recipe differs from deterministic source normalization.')
784
781
  const result = new Map<string, Uint8Array>()
785
782
  for (const file of pkg.files) {
786
783
  const bytes =
787
784
  file.action === 'write' ? encoder.encode(file.content) : source.get(file.sourcePath)
788
- if (!bytes || sha256(bytes) !== file.digest)
785
+ if (!bytes || byteDigest(bytes) !== file.digest)
789
786
  throw new Error('Package file missing or digest mismatch.')
790
787
  result.set(file.targetPath, bytes.slice())
791
788
  }
@@ -1,9 +1,19 @@
1
1
  import { z } from 'zod'
2
+ import { DIGEST_RE } from './schema.js'
2
3
 
3
4
  // Locally pinned contracts. Never fetch a schema while inspecting a plugin.
4
5
  export const AGENT_PLUGINS_VERSION = '1.0.0' as const
5
6
  export const PLUGIN_SCHEMA_ID = 'https://agent-plugins.org/schemas/1.0.0/plugin.schema.json'
6
7
  export const MCP_SCHEMA_ID = 'https://agent-plugins.org/schemas/1.0.0/mcp.schema.json'
8
+ /** Size limits for one package; the catalog policy defaults to the same values. */
9
+ export const PACKAGE_LIMITS = {
10
+ maxFilesPerPlugin: 4096,
11
+ maxFileBytes: 5 * 1024 * 1024,
12
+ maxBytesPerPlugin: 50 * 1024 * 1024,
13
+ } as const
14
+
15
+ /** Where a release carries its compiled Agent Plugins package in `releaseMetadata`. */
16
+ export const PACKAGE_METADATA_KEY = 'agentPlugins'
7
17
  export const NORMALIZER_VERSION = 'adea-agent-plugins/1' as const
8
18
  export const PluginNameSchema = z
9
19
  .string()
@@ -11,7 +21,7 @@ export const PluginNameSchema = z
11
21
  .max(64)
12
22
  .regex(/^(?!.*(?:--|\.\.))[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/)
13
23
  const Strings = z.record(z.string(), z.string())
14
- const Digest = z.string().regex(/^sha256:[a-f0-9]{64}$/)
24
+ const Digest = z.string().regex(DIGEST_RE)
15
25
  const Path = z
16
26
  .string()
17
27
  .min(1)