upstream-radar 0.41.0 → 0.42.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.
- package/README.md +77 -144
- package/README.zh-CN.md +89 -0
- package/dist/src/dsh-compatibility-ir.d.ts +1 -0
- package/dist/src/dsh-compatibility-ir.d.ts.map +1 -1
- package/dist/src/dsh-compatibility-ir.js +21 -2
- package/dist/src/dsh-compatibility-ir.js.map +1 -1
- package/dist/src/dsh-compatibility-issues.d.ts +2 -0
- package/dist/src/dsh-compatibility-issues.d.ts.map +1 -1
- package/dist/src/dsh-compatibility-issues.js +39 -1
- package/dist/src/dsh-compatibility-issues.js.map +1 -1
- package/dist/src/dsh-compatibility-ledger.d.ts +3 -1
- package/dist/src/dsh-compatibility-ledger.d.ts.map +1 -1
- package/dist/src/dsh-compatibility-ledger.js +38 -5
- package/dist/src/dsh-compatibility-ledger.js.map +1 -1
- package/dist/src/dsh-directory-feed.d.ts +108 -0
- package/dist/src/dsh-directory-feed.d.ts.map +1 -0
- package/dist/src/dsh-directory-feed.js +267 -0
- package/dist/src/dsh-directory-feed.js.map +1 -0
- package/dist/src/dsh-install-observation.d.ts +2 -1
- package/dist/src/dsh-install-observation.d.ts.map +1 -1
- package/dist/src/dsh-install-observation.js +86 -20
- package/dist/src/dsh-install-observation.js.map +1 -1
- package/dist/src/dsh-install-plan.js +1 -1
- package/dist/src/dsh-install-plan.js.map +1 -1
- package/dist/src/index.d.ts +2 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -1
- package/dist/src/index.js.map +1 -1
- package/dist/src/tar.d.ts.map +1 -1
- package/dist/src/tar.js +28 -13
- package/dist/src/tar.js.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/src/version.js +1 -1
- package/docs/README.zh-CN.md +20 -20
- package/package.json +3 -1
- package/schemas/dsh-compatibility-ir.schema.json +9 -2
- package/schemas/dsh-install-observation.schema.json +7 -1
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { parseDshCompatibilityLedger } from './dsh-compatibility-ledger.js';
|
|
2
|
+
import { parseDshInstallTargets } from './dsh-install-plan.js';
|
|
3
|
+
import { parseNpmSpec } from './npm.js';
|
|
4
|
+
import { TOOL_VERSION } from './version.js';
|
|
5
|
+
export const AWESOME_DSH_COHORT_SCHEMA = 'upstream-radar.awesome-dsh-cohort/v1alpha1';
|
|
6
|
+
export const DSH_DIRECTORY_COMPATIBILITY_FEED_SCHEMA = 'upstream-radar.dsh-directory-compatibility-feed/v1alpha1';
|
|
7
|
+
const MAX_COHORT_PLUGINS = 100;
|
|
8
|
+
const REPOSITORY = /^[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+$/;
|
|
9
|
+
const CATALOG_ENTRY = /^data\/plugins\/[A-Za-z0-9_.@-]+\.ya?ml$/;
|
|
10
|
+
function record(value, label) {
|
|
11
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
12
|
+
throw new Error(`${label} must be an object`);
|
|
13
|
+
return value;
|
|
14
|
+
}
|
|
15
|
+
function boundedString(value, label, maximum) {
|
|
16
|
+
if (typeof value !== 'string' || value.trim() === '' || value.length > maximum) {
|
|
17
|
+
throw new Error(`${label} must be a non-empty string no longer than ${maximum} characters`);
|
|
18
|
+
}
|
|
19
|
+
return value;
|
|
20
|
+
}
|
|
21
|
+
function timestamp(value, label) {
|
|
22
|
+
const parsed = boundedString(value, label, 64);
|
|
23
|
+
if (!Number.isFinite(Date.parse(parsed)))
|
|
24
|
+
throw new Error(`${label} must be an ISO timestamp`);
|
|
25
|
+
return parsed;
|
|
26
|
+
}
|
|
27
|
+
function repository(value, label) {
|
|
28
|
+
const parsed = boundedString(value, label, 256);
|
|
29
|
+
if (!REPOSITORY.test(parsed))
|
|
30
|
+
throw new Error(`${label} must be an owner/repository coordinate`);
|
|
31
|
+
return parsed;
|
|
32
|
+
}
|
|
33
|
+
function httpsUrl(value, label) {
|
|
34
|
+
const parsed = new URL(boundedString(value, label, 2_048));
|
|
35
|
+
if (parsed.protocol !== 'https:' || parsed.username !== '' || parsed.password !== '') {
|
|
36
|
+
throw new Error(`${label} must be a credential-free HTTPS URL`);
|
|
37
|
+
}
|
|
38
|
+
return parsed.toString();
|
|
39
|
+
}
|
|
40
|
+
function githubCatalogUrl(value, repositoryName, label) {
|
|
41
|
+
const parsed = new URL(httpsUrl(value, label));
|
|
42
|
+
const expectedPath = `/${repositoryName}`.toLowerCase();
|
|
43
|
+
const actualPath = parsed.pathname.replace(/\/$/, '').toLowerCase();
|
|
44
|
+
if (parsed.hostname.toLowerCase() !== 'github.com' || (actualPath !== expectedPath && !actualPath.startsWith(`${expectedPath}/`))) {
|
|
45
|
+
throw new Error(`${label} must stay within the selected GitHub repository`);
|
|
46
|
+
}
|
|
47
|
+
parsed.pathname = parsed.pathname.replace(/\/$/, '');
|
|
48
|
+
return parsed.toString();
|
|
49
|
+
}
|
|
50
|
+
function parseDistribution(value, label) {
|
|
51
|
+
const item = record(value, label);
|
|
52
|
+
const kind = boundedString(item.kind, `${label}.kind`, 64);
|
|
53
|
+
if (kind === 'npm') {
|
|
54
|
+
const name = boundedString(item.name, `${label}.name`, 214);
|
|
55
|
+
const selectedVersion = boundedString(item.selectedVersion, `${label}.selectedVersion`, 256);
|
|
56
|
+
parseNpmSpec(`${name}@${selectedVersion}`);
|
|
57
|
+
const distTag = item.distTag === undefined ? undefined : boundedString(item.distTag, `${label}.distTag`, 128);
|
|
58
|
+
return { kind, name, selectedVersion, ...(distTag === undefined ? {} : { distTag }) };
|
|
59
|
+
}
|
|
60
|
+
if (kind === 'github') {
|
|
61
|
+
const reason = boundedString(item.reason, `${label}.reason`, 2_048);
|
|
62
|
+
const installSpec = item.installSpec === undefined
|
|
63
|
+
? undefined
|
|
64
|
+
: boundedString(item.installSpec, `${label}.installSpec`, 512);
|
|
65
|
+
return { kind, reason, ...(installSpec === undefined ? {} : { installSpec }) };
|
|
66
|
+
}
|
|
67
|
+
if (kind === 'repository-installer') {
|
|
68
|
+
return { kind, reason: boundedString(item.reason, `${label}.reason`, 2_048) };
|
|
69
|
+
}
|
|
70
|
+
throw new Error(`${label}.kind is unsupported`);
|
|
71
|
+
}
|
|
72
|
+
export function parseAwesomeDshCohort(input) {
|
|
73
|
+
const root = record(input, 'awesome-dsh-plugin cohort');
|
|
74
|
+
if (root.schema !== AWESOME_DSH_COHORT_SCHEMA) {
|
|
75
|
+
throw new Error(`awesome-dsh-plugin cohort schema must be ${AWESOME_DSH_COHORT_SCHEMA}`);
|
|
76
|
+
}
|
|
77
|
+
const source = record(root.source, 'awesome-dsh-plugin cohort source');
|
|
78
|
+
const commit = boundedString(source.commit, 'awesome-dsh-plugin cohort source.commit', 40);
|
|
79
|
+
if (!/^[a-f0-9]{40}$/.test(commit))
|
|
80
|
+
throw new Error('awesome-dsh-plugin cohort source.commit must be a full Git commit');
|
|
81
|
+
const entryCount = Number(source.entryCount);
|
|
82
|
+
if (!Number.isSafeInteger(entryCount) || entryCount < 1 || entryCount > 100_000) {
|
|
83
|
+
throw new Error('awesome-dsh-plugin cohort source.entryCount must be a positive bounded integer');
|
|
84
|
+
}
|
|
85
|
+
if (!Array.isArray(root.plugins) || root.plugins.length === 0 || root.plugins.length > MAX_COHORT_PLUGINS) {
|
|
86
|
+
throw new Error(`awesome-dsh-plugin cohort plugins must contain between 1 and ${MAX_COHORT_PLUGINS} entries`);
|
|
87
|
+
}
|
|
88
|
+
const ids = new Set();
|
|
89
|
+
const repositories = new Set();
|
|
90
|
+
const plugins = root.plugins.map((value, index) => {
|
|
91
|
+
const item = record(value, `plugins[${index}]`);
|
|
92
|
+
const id = boundedString(item.id, `plugins[${index}].id`, 64);
|
|
93
|
+
if (!/^[a-z0-9][a-z0-9._-]{0,63}$/.test(id))
|
|
94
|
+
throw new Error(`plugins[${index}].id must be a short lowercase label`);
|
|
95
|
+
if (ids.has(id))
|
|
96
|
+
throw new Error(`duplicate awesome-dsh-plugin cohort id: ${id}`);
|
|
97
|
+
ids.add(id);
|
|
98
|
+
const repositoryName = repository(item.repository, `plugins[${index}].repository`);
|
|
99
|
+
if (repositories.has(repositoryName))
|
|
100
|
+
throw new Error(`duplicate awesome-dsh-plugin cohort repository: ${repositoryName}`);
|
|
101
|
+
repositories.add(repositoryName);
|
|
102
|
+
const catalogEntry = boundedString(item.catalogEntry, `plugins[${index}].catalogEntry`, 512);
|
|
103
|
+
if (!CATALOG_ENTRY.test(catalogEntry))
|
|
104
|
+
throw new Error(`plugins[${index}].catalogEntry must identify one catalog YAML entry`);
|
|
105
|
+
return {
|
|
106
|
+
id,
|
|
107
|
+
catalogEntry,
|
|
108
|
+
catalogUrl: githubCatalogUrl(item.catalogUrl, repositoryName, `plugins[${index}].catalogUrl`),
|
|
109
|
+
repository: repositoryName,
|
|
110
|
+
category: boundedString(item.category, `plugins[${index}].category`, 64),
|
|
111
|
+
distribution: parseDistribution(item.distribution, `plugins[${index}].distribution`),
|
|
112
|
+
};
|
|
113
|
+
});
|
|
114
|
+
plugins.sort((left, right) => left.repository.localeCompare(right.repository));
|
|
115
|
+
return {
|
|
116
|
+
schema: AWESOME_DSH_COHORT_SCHEMA,
|
|
117
|
+
selectedAt: timestamp(root.selectedAt, 'awesome-dsh-plugin cohort selectedAt'),
|
|
118
|
+
source: {
|
|
119
|
+
repository: repository(source.repository, 'awesome-dsh-plugin cohort source.repository'),
|
|
120
|
+
commit,
|
|
121
|
+
commitUrl: httpsUrl(source.commitUrl, 'awesome-dsh-plugin cohort source.commitUrl'),
|
|
122
|
+
entryDirectory: boundedString(source.entryDirectory, 'awesome-dsh-plugin cohort source.entryDirectory', 512),
|
|
123
|
+
entryCount,
|
|
124
|
+
license: boundedString(source.license, 'awesome-dsh-plugin cohort source.license', 128),
|
|
125
|
+
},
|
|
126
|
+
plugins,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function cellStatus(result) {
|
|
130
|
+
if (result === 'compatible')
|
|
131
|
+
return 'observed-compatible';
|
|
132
|
+
if (result === 'runtime-incompatible' || result === 'install-failed' || result === 'load-failed') {
|
|
133
|
+
return 'observed-incompatible';
|
|
134
|
+
}
|
|
135
|
+
return 'needs-review';
|
|
136
|
+
}
|
|
137
|
+
function aggregateStatus(cells) {
|
|
138
|
+
if (cells.length === 0)
|
|
139
|
+
return 'not-observed';
|
|
140
|
+
if (cells.some(cell => cell.status === 'observed-incompatible'))
|
|
141
|
+
return 'observed-incompatible';
|
|
142
|
+
if (cells.some(cell => cell.status === 'needs-review'))
|
|
143
|
+
return 'needs-review';
|
|
144
|
+
return 'observed-compatible';
|
|
145
|
+
}
|
|
146
|
+
function dueAt(observedAt, refreshAfterHours) {
|
|
147
|
+
return new Date(Date.parse(observedAt) + refreshAfterHours * 60 * 60 * 1_000).toISOString();
|
|
148
|
+
}
|
|
149
|
+
function normalizedRepositoryBaseUrl(value) {
|
|
150
|
+
const parsed = new URL(value);
|
|
151
|
+
if (parsed.protocol !== 'https:' || parsed.username !== '' || parsed.password !== '' || parsed.search !== '' || parsed.hash !== '') {
|
|
152
|
+
throw new Error('repositoryBaseUrl must be a credential-free HTTPS URL without query or fragment');
|
|
153
|
+
}
|
|
154
|
+
return parsed.toString().replace(/\/$/, '');
|
|
155
|
+
}
|
|
156
|
+
export function buildDshDirectoryCompatibilityFeed(input) {
|
|
157
|
+
const cohort = parseAwesomeDshCohort(input.cohort);
|
|
158
|
+
const installTargets = parseDshInstallTargets(input.installTargets);
|
|
159
|
+
const ledger = parseDshCompatibilityLedger(input.ledger);
|
|
160
|
+
const generatedAt = timestamp(input.generatedAt, 'directory feed generatedAt');
|
|
161
|
+
const repositoryBaseUrl = normalizedRepositoryBaseUrl(input.repositoryBaseUrl ?? 'https://github.com/MicroMilo/upstream-radar');
|
|
162
|
+
const targetByObserverId = new Map(installTargets.plugins
|
|
163
|
+
.filter(target => target.observerTargetId !== undefined)
|
|
164
|
+
.map(target => [target.observerTargetId, target]));
|
|
165
|
+
const plugins = cohort.plugins.map((plugin) => {
|
|
166
|
+
const installTarget = targetByObserverId.get(plugin.id);
|
|
167
|
+
const observations = installTarget === undefined
|
|
168
|
+
? []
|
|
169
|
+
: ledger.entries.filter(entry => entry.targetId === installTarget.id);
|
|
170
|
+
const cells = observations.map((entry) => ({
|
|
171
|
+
caseId: entry.caseId,
|
|
172
|
+
artifact: {
|
|
173
|
+
spec: entry.plugin,
|
|
174
|
+
...(entry.artifact.sha256 === undefined ? {} : { sha256: entry.artifact.sha256 }),
|
|
175
|
+
},
|
|
176
|
+
dsh: { package: '@deepseek-ai/dsh', version: entry.dshVersion },
|
|
177
|
+
runtime: {
|
|
178
|
+
nodeMajor: entry.runtime.nodeMajor,
|
|
179
|
+
nodeVersion: entry.runtime.nodeVersion,
|
|
180
|
+
platform: entry.runtime.platform,
|
|
181
|
+
architecture: entry.runtime.architecture,
|
|
182
|
+
},
|
|
183
|
+
executionPlane: 'headless',
|
|
184
|
+
profile: 'headless',
|
|
185
|
+
status: cellStatus(entry.result),
|
|
186
|
+
radarResult: entry.result,
|
|
187
|
+
...(entry.requiredDependencyBuilds === undefined ? {} : { requiredDependencyBuilds: entry.requiredDependencyBuilds }),
|
|
188
|
+
observedAt: entry.observedAt,
|
|
189
|
+
recheckDueAt: dueAt(entry.observedAt, installTargets.refreshAfterHours),
|
|
190
|
+
reason: entry.reason,
|
|
191
|
+
})).sort((left, right) => left.caseId.localeCompare(right.caseId));
|
|
192
|
+
return {
|
|
193
|
+
id: plugin.id,
|
|
194
|
+
repository: plugin.repository,
|
|
195
|
+
repositoryUrl: `https://github.com/${plugin.repository}`,
|
|
196
|
+
catalogUrl: plugin.catalogUrl,
|
|
197
|
+
catalogEntry: plugin.catalogEntry,
|
|
198
|
+
catalogEntryUrl: `https://github.com/${cohort.source.repository}/blob/${cohort.source.commit}/${plugin.catalogEntry}`,
|
|
199
|
+
category: plugin.category,
|
|
200
|
+
distribution: plugin.distribution,
|
|
201
|
+
status: aggregateStatus(cells),
|
|
202
|
+
cells,
|
|
203
|
+
evidenceUrl: `${repositoryBaseUrl}/blob/main/compatibility-ledger.json`,
|
|
204
|
+
};
|
|
205
|
+
}).sort((left, right) => left.repository.localeCompare(right.repository));
|
|
206
|
+
const summary = {
|
|
207
|
+
total: plugins.length,
|
|
208
|
+
'observed-compatible': 0,
|
|
209
|
+
'observed-incompatible': 0,
|
|
210
|
+
'needs-review': 0,
|
|
211
|
+
'not-observed': 0,
|
|
212
|
+
};
|
|
213
|
+
for (const plugin of plugins)
|
|
214
|
+
summary[plugin.status] += 1;
|
|
215
|
+
return {
|
|
216
|
+
schema: DSH_DIRECTORY_COMPATIBILITY_FEED_SCHEMA,
|
|
217
|
+
generatedAt,
|
|
218
|
+
producer: { name: 'upstream-radar', version: TOOL_VERSION, repository: repositoryBaseUrl, license: 'Apache-2.0' },
|
|
219
|
+
sourceCatalog: cohort.source,
|
|
220
|
+
boundary: {
|
|
221
|
+
claim: 'exact-cell compatibility evidence; not a security review, endorsement, or timeless compatibility badge',
|
|
222
|
+
executionPlane: 'headless',
|
|
223
|
+
profile: 'headless',
|
|
224
|
+
isolation: 'fresh GitHub-hosted VM plus restricted container',
|
|
225
|
+
consumptionRule: 'Treat a cell as stale after recheckDueAt. needs-review and not-observed must never be rendered as pass or fail.',
|
|
226
|
+
refreshAfterHours: installTargets.refreshAfterHours,
|
|
227
|
+
},
|
|
228
|
+
summary,
|
|
229
|
+
plugins,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function markdown(value) {
|
|
233
|
+
return value.replace(/[|<>\r\n]/g, ' ').replace(/\s+/g, ' ').trim();
|
|
234
|
+
}
|
|
235
|
+
function cellCoordinate(entry) {
|
|
236
|
+
if (entry.cells.length === 0)
|
|
237
|
+
return '—';
|
|
238
|
+
return entry.cells.map(cell => `\`${markdown(cell.artifact.spec)}\``).join('<br>');
|
|
239
|
+
}
|
|
240
|
+
function dshCoordinate(entry) {
|
|
241
|
+
if (entry.cells.length === 0)
|
|
242
|
+
return '—';
|
|
243
|
+
return entry.cells.map(cell => `\`${markdown(cell.dsh.version)}\` / Node ${cell.runtime.nodeMajor}`).join('<br>');
|
|
244
|
+
}
|
|
245
|
+
function observedCoordinate(entry) {
|
|
246
|
+
if (entry.cells.length === 0)
|
|
247
|
+
return '—';
|
|
248
|
+
return entry.cells.map(cell => markdown(cell.observedAt)).join('<br>');
|
|
249
|
+
}
|
|
250
|
+
export function renderDshDirectoryCompatibilityFeed(feed) {
|
|
251
|
+
const lines = [
|
|
252
|
+
'# DSH directory compatibility evidence',
|
|
253
|
+
'',
|
|
254
|
+
`Generated from catalog commit [\`${feed.sourceCatalog.commit.slice(0, 12)}\`](${feed.sourceCatalog.commitUrl}) at \`${feed.generatedAt}\`.`,
|
|
255
|
+
'',
|
|
256
|
+
`**${feed.summary['observed-compatible']} observed compatible · ${feed.summary['observed-incompatible']} observed incompatible · ${feed.summary['needs-review']} needs review · ${feed.summary['not-observed']} not observed**`,
|
|
257
|
+
'',
|
|
258
|
+
'| Catalog plugin | Exact artifact | Exact DSH / runtime | Evidence status | Observed |',
|
|
259
|
+
'| --- | --- | --- | --- | --- |',
|
|
260
|
+
];
|
|
261
|
+
for (const entry of feed.plugins) {
|
|
262
|
+
lines.push(`| [${markdown(entry.repository)}](${entry.catalogUrl}) | ${cellCoordinate(entry)} | ${dshCoordinate(entry)} | \`${entry.status}\` | ${observedCoordinate(entry)} |`);
|
|
263
|
+
}
|
|
264
|
+
lines.push('', '## Reading the status', '', '- `observed-compatible`: the exact artifact installed, registered and loaded in the stated headless cell.', '- `observed-incompatible`: the exact cell reproduced a runtime gate, install, registration or load failure.', '- `needs-review`: evidence exists, but Radar cannot yet separate a plugin defect from an uncovered execution plane, environment condition, or explicit dependency-build approval gate.', '- `not-observed`: the catalog entry is monitored statically but has no matching executable npm artifact in this cohort.', '', `A cell expires at its \`recheckDueAt\` value (${feed.boundary.refreshAfterHours} hours after observation). Consumers must then show it as stale. This is exact compatibility evidence, not a security review or endorsement.`, '', `[Machine-readable feed](dsh-plugin-compatibility.json) · [Full compatibility ledger](${feed.producer.repository}/blob/main/compatibility-ledger.json)`, '');
|
|
265
|
+
return lines.join('\n');
|
|
266
|
+
}
|
|
267
|
+
//# sourceMappingURL=dsh-directory-feed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dsh-directory-feed.js","sourceRoot":"","sources":["../../src/dsh-directory-feed.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DependencyKind } from './radar-types.js';
|
|
2
2
|
export declare const DSH_INSTALL_OBSERVATION_SCHEMA: 'upstream-radar.dsh-install-observation/v1alpha1';
|
|
3
|
-
export type DshInstallObservationResult = 'compatible' | 'runtime-incompatible' | 'peer-contract-incompatible' | 'install-failed' | 'load-failed' | 'unknown';
|
|
3
|
+
export type DshInstallObservationResult = 'compatible' | 'runtime-incompatible' | 'peer-contract-incompatible' | 'build-approval-required' | 'install-failed' | 'load-failed' | 'unknown';
|
|
4
4
|
export type InstallObservationPhase = 'runtime' | 'artifact' | 'profile' | 'install' | 'load';
|
|
5
5
|
export type InstallObservationIsolationProvider = 'github-actions-hosted-runner' | 'firecracker' | 'other';
|
|
6
6
|
export interface InstallObservationCommand {
|
|
@@ -219,6 +219,7 @@ export interface DshInstallObservationReport {
|
|
|
219
219
|
pluginCodeMayExecuteDuringLoad: true;
|
|
220
220
|
inheritedHostSecrets: false;
|
|
221
221
|
approvedDependencyBuilds: string[];
|
|
222
|
+
requiredDependencyBuilds: string[];
|
|
222
223
|
note: string;
|
|
223
224
|
};
|
|
224
225
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dsh-install-observation.d.ts","sourceRoot":"","sources":["../../src/dsh-install-observation.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,cAAc,EAAoB,MAAM,kBAAkB,CAAA;AAKxE,eAAO,MAAM,8BAA8B,EAAG,iDAA0D,CAAA;
|
|
1
|
+
{"version":3,"file":"dsh-install-observation.d.ts","sourceRoot":"","sources":["../../src/dsh-install-observation.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,6 +16,7 @@ export const DSH_INSTALL_OBSERVATION_SCHEMA = 'upstream-radar.dsh-install-observ
|
|
|
16
16
|
const EXACT_VERSION = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
17
17
|
const DEFAULT_TIMEOUT_MS = 180_000;
|
|
18
18
|
const MAX_ARTIFACT_BYTES = 64 * 1024 * 1024;
|
|
19
|
+
const MAX_ARTIFACT_UNPACKED_BYTES = 192 * 1024 * 1024;
|
|
19
20
|
const MAX_COMMAND_OUTPUT_BYTES = 64 * 1024;
|
|
20
21
|
const MAX_REPORT_DETAIL_BYTES = 4 * 1024;
|
|
21
22
|
const MAX_TRACE_BYTES = 16 * 1024 * 1024;
|
|
@@ -55,6 +56,51 @@ function normalizeAllowedBuilds(values) {
|
|
|
55
56
|
function isNpmPackageName(value) {
|
|
56
57
|
return /^(?:@[a-z0-9][a-z0-9._-]*\/[a-z0-9][a-z0-9._-]*|[a-z0-9][a-z0-9._-]*)$/.test(value);
|
|
57
58
|
}
|
|
59
|
+
/**
|
|
60
|
+
* pnpm 10+ deliberately stops before running dependency lifecycle scripts
|
|
61
|
+
* unless each package is approved. Keep that policy gate distinct from a
|
|
62
|
+
* plugin install defect, but only when pnpm supplied a bounded, exact list.
|
|
63
|
+
*/
|
|
64
|
+
function requiredDependencyBuilds(output, artifactName) {
|
|
65
|
+
const normalized = output.replace(/\r\n?/g, '\n');
|
|
66
|
+
const marker = '[ERR_PNPM_IGNORED_BUILDS]';
|
|
67
|
+
const markerIndex = normalized.indexOf(marker);
|
|
68
|
+
if (markerIndex < 0)
|
|
69
|
+
return [];
|
|
70
|
+
const tail = normalized.slice(markerIndex, markerIndex + MAX_COMMAND_OUTPUT_BYTES);
|
|
71
|
+
const prefix = 'Ignored build scripts:';
|
|
72
|
+
const prefixIndex = tail.indexOf(prefix);
|
|
73
|
+
if (prefixIndex < marker.length || prefixIndex > 256)
|
|
74
|
+
return [];
|
|
75
|
+
let list = tail.slice(prefixIndex + prefix.length);
|
|
76
|
+
const terminator = list.search(/\n\s*\n|\n\s*Run\s+["']pnpm approve-builds["']/);
|
|
77
|
+
if (terminator >= 0)
|
|
78
|
+
list = list.slice(0, terminator);
|
|
79
|
+
const coordinates = list.split(',').map(value => value.trim()).filter(Boolean);
|
|
80
|
+
if (coordinates.length === 0 || coordinates.length > MAX_ALLOWED_BUILDS)
|
|
81
|
+
return [];
|
|
82
|
+
const names = new Set();
|
|
83
|
+
for (const coordinate of coordinates) {
|
|
84
|
+
try {
|
|
85
|
+
const parsed = parseNpmSpec(coordinate);
|
|
86
|
+
if (!EXACT_VERSION.test(parsed.version) || !isNpmPackageName(parsed.name))
|
|
87
|
+
return [];
|
|
88
|
+
names.add(parsed.name);
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
// When the exact reviewed tarball itself has a lifecycle script, pnpm
|
|
92
|
+
// prints its profile-relative file: coordinate alongside registry
|
|
93
|
+
// dependencies. Accept only the already-established artifact identity;
|
|
94
|
+
// an arbitrary local coordinate must not become an approval suggestion.
|
|
95
|
+
const prefix = `${artifactName}@file:`;
|
|
96
|
+
const localPath = coordinate.startsWith(prefix) ? coordinate.slice(prefix.length) : '';
|
|
97
|
+
if (localPath === '' || localPath.length > 4_096 || /[\u0000-\u0020\u007f]/.test(localPath))
|
|
98
|
+
return [];
|
|
99
|
+
names.add(artifactName);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return [...names].sort();
|
|
103
|
+
}
|
|
58
104
|
function staticPeerUsage(entries, requirements) {
|
|
59
105
|
const state = new Map(requirements.map(requirement => [requirement.name, 'no-literal-reference-observed']));
|
|
60
106
|
let scanned = 0;
|
|
@@ -482,18 +528,30 @@ async function readRegularFileNoFollow(path, maximum) {
|
|
|
482
528
|
async function parsePackedArtifact(result, artifactDirectory, expectedName, expectedVersion) {
|
|
483
529
|
if (commandStage(result).status !== 'passed')
|
|
484
530
|
throw new Error(commandStage(result).detail ?? 'npm pack failed');
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
531
|
+
const stdout = result.stdout.trim();
|
|
532
|
+
let filename;
|
|
533
|
+
let integrity;
|
|
534
|
+
if (stdout.startsWith('[')) {
|
|
535
|
+
let output;
|
|
536
|
+
try {
|
|
537
|
+
output = JSON.parse(stdout);
|
|
538
|
+
}
|
|
539
|
+
catch {
|
|
540
|
+
throw new Error('npm pack did not return valid JSON');
|
|
541
|
+
}
|
|
542
|
+
if (!Array.isArray(output) || output.length !== 1 || typeof output[0] !== 'object' || output[0] === null) {
|
|
543
|
+
throw new Error('npm pack returned an unexpected result');
|
|
544
|
+
}
|
|
545
|
+
const item = output[0];
|
|
546
|
+
filename = item.filename;
|
|
547
|
+
integrity = typeof item.integrity === 'string' ? bounded(item.integrity, 1_024) : undefined;
|
|
491
548
|
}
|
|
492
|
-
|
|
493
|
-
|
|
549
|
+
else {
|
|
550
|
+
const lines = stdout.split(/\r?\n/);
|
|
551
|
+
if (lines.length !== 1)
|
|
552
|
+
throw new Error('npm pack returned an unexpected result');
|
|
553
|
+
filename = lines[0];
|
|
494
554
|
}
|
|
495
|
-
const item = output[0];
|
|
496
|
-
const filename = item.filename;
|
|
497
555
|
if (typeof filename !== 'string' || filename === '' || filename !== basename(filename) || !filename.endsWith('.tgz')) {
|
|
498
556
|
throw new Error('npm pack returned an unsafe artifact filename');
|
|
499
557
|
}
|
|
@@ -501,7 +559,10 @@ async function parsePackedArtifact(result, artifactDirectory, expectedName, expe
|
|
|
501
559
|
if (!path.startsWith(`${resolve(artifactDirectory)}${sep}`))
|
|
502
560
|
throw new Error('npm pack artifact escaped its directory');
|
|
503
561
|
const compressed = await readRegularFileNoFollow(path, MAX_ARTIFACT_BYTES);
|
|
504
|
-
const parsed = parseNpmTarball(compressed
|
|
562
|
+
const parsed = parseNpmTarball(compressed, {
|
|
563
|
+
maxFileBytes: MAX_ARTIFACT_BYTES,
|
|
564
|
+
maxUnpackedBytes: MAX_ARTIFACT_UNPACKED_BYTES,
|
|
565
|
+
});
|
|
505
566
|
const manifestEntry = parsed.entries.find(entry => entry.path === 'package.json' && entry.type === 'file');
|
|
506
567
|
if (manifestEntry?.contents === undefined)
|
|
507
568
|
throw new Error('packed artifact has no package.json');
|
|
@@ -546,7 +607,6 @@ async function parsePackedArtifact(result, artifactDirectory, expectedName, expe
|
|
|
546
607
|
throw new Error('packed artifact Node engine requirement exceeds 512 characters');
|
|
547
608
|
}
|
|
548
609
|
const nodeEngine = rawNodeEngine === undefined || rawNodeEngine === '' ? undefined : bounded(rawNodeEngine, 512);
|
|
549
|
-
const integrity = typeof item.integrity === 'string' ? bounded(item.integrity, 1_024) : undefined;
|
|
550
610
|
const peerRequirements = requiredPeerDependencies(manifest, parsed.entries);
|
|
551
611
|
return {
|
|
552
612
|
path,
|
|
@@ -901,12 +961,12 @@ async function readProfilePeerContracts(path, requirements, sandboxRoot) {
|
|
|
901
961
|
return contracts;
|
|
902
962
|
}
|
|
903
963
|
/**
|
|
904
|
-
*
|
|
905
|
-
*
|
|
906
|
-
*
|
|
907
|
-
*
|
|
964
|
+
* Resolve direct peer contracts from the profile anchor, then boot the actual
|
|
965
|
+
* composed DSH profile. A DSH bundle does not have to export its package root:
|
|
966
|
+
* its patch may load one or more package subpaths (or a command adapter).
|
|
967
|
+
* Importing the root here would therefore test a contract DSH never declared.
|
|
908
968
|
*/
|
|
909
|
-
async function writeProfileLoadProbe(dshHome,
|
|
969
|
+
async function writeProfileLoadProbe(dshHome, dshVersion, pnpmCommand, peerRequirements) {
|
|
910
970
|
const profileDirectory = join(dshHome, 'profiles', PROFILE);
|
|
911
971
|
const profileMetadata = await lstat(profileDirectory);
|
|
912
972
|
if (!profileMetadata.isDirectory() || profileMetadata.isSymbolicLink()) {
|
|
@@ -929,7 +989,6 @@ async function writeProfileLoadProbe(dshHome, pluginName, dshVersion, pnpmComman
|
|
|
929
989
|
' catch { peers.push({ name: peer.name, status: \'missing\' }) }',
|
|
930
990
|
'}',
|
|
931
991
|
`await writeFile(${JSON.stringify(peerResolutionPath)}, JSON.stringify({ schema: ${JSON.stringify(PROFILE_PEER_RESOLUTION_SCHEMA)}, peers }), { encoding: 'utf8', mode: 0o600, flag: 'wx' })`,
|
|
932
|
-
`await import(${JSON.stringify(pluginName)})`,
|
|
933
992
|
`const child = spawn(${JSON.stringify(pnpmCommand)}, ${JSON.stringify(dshBootArgs)}, { cwd: process.cwd(), env: process.env, stdio: 'inherit' })`,
|
|
934
993
|
"const exitCode = await new Promise(resolve => {",
|
|
935
994
|
" child.once('error', error => { console.error(error.message); resolve(1) })",
|
|
@@ -1222,6 +1281,7 @@ export async function observeDshPluginInstall(options) {
|
|
|
1222
1281
|
pluginCodeMayExecuteDuringLoad: true,
|
|
1223
1282
|
inheritedHostSecrets: false,
|
|
1224
1283
|
approvedDependencyBuilds: allowedBuilds,
|
|
1284
|
+
requiredDependencyBuilds: [],
|
|
1225
1285
|
note: 'Radar scrubs the child environment and records Linux system-call evidence, but the caller provides and must verify the disposable isolation boundary. Same-container traces are best-effort evidence, not a malicious-code safety certificate.',
|
|
1226
1286
|
},
|
|
1227
1287
|
};
|
|
@@ -1271,7 +1331,7 @@ export async function observeDshPluginInstall(options) {
|
|
|
1271
1331
|
const artifactResult = await runSafely(runner, {
|
|
1272
1332
|
phase: 'artifact',
|
|
1273
1333
|
command: npmCommand,
|
|
1274
|
-
args: ['pack', `${spec.name}@${spec.version}`, '--ignore-scripts', '--
|
|
1334
|
+
args: ['pack', `${spec.name}@${spec.version}`, '--ignore-scripts', '--pack-destination', '.', '--silent'],
|
|
1275
1335
|
cwd: artifactDirectory,
|
|
1276
1336
|
env: noScriptsEnvironment,
|
|
1277
1337
|
timeoutMs,
|
|
@@ -1354,6 +1414,11 @@ export async function observeDshPluginInstall(options) {
|
|
|
1354
1414
|
return finishReport(report, 'unknown', 'the install command ran without readable trace evidence');
|
|
1355
1415
|
}
|
|
1356
1416
|
if (installResult.code !== 0) {
|
|
1417
|
+
const requiredBuilds = requiredDependencyBuilds(`${installResult.stderr}\n${installResult.stdout}`, spec.name);
|
|
1418
|
+
if (requiredBuilds.length > 0) {
|
|
1419
|
+
report.boundary.requiredDependencyBuilds = requiredBuilds;
|
|
1420
|
+
return finishReport(report, 'build-approval-required', `the DSH plugin install requires explicit approval for dependency builds: ${requiredBuilds.join(', ')}`);
|
|
1421
|
+
}
|
|
1357
1422
|
return finishReport(report, 'install-failed', 'the traced DSH plugin install command failed');
|
|
1358
1423
|
}
|
|
1359
1424
|
const registered = await registeredBundle(environment.DSH_HOME, spec.name);
|
|
@@ -1362,7 +1427,7 @@ export async function observeDshPluginInstall(options) {
|
|
|
1362
1427
|
: { status: 'failed', detail: `the DSH profile did not register ${spec.name}` };
|
|
1363
1428
|
if (!registered)
|
|
1364
1429
|
return finishReport(report, 'install-failed', 'DSH accepted the install command but did not register the plugin bundle');
|
|
1365
|
-
const loadProbe = await writeProfileLoadProbe(environment.DSH_HOME,
|
|
1430
|
+
const loadProbe = await writeProfileLoadProbe(environment.DSH_HOME, options.dshVersion, pnpmCommand, artifact.requiredPeerDependencies);
|
|
1366
1431
|
const loadTracePath = join(traceDirectory, 'load.strace');
|
|
1367
1432
|
const loadResult = await runSafely(runner, {
|
|
1368
1433
|
phase: 'load',
|
|
@@ -1420,6 +1485,7 @@ export function renderDshInstallObservation(report) {
|
|
|
1420
1485
|
`Plugin Node requirement: ${report.artifact.nodeEngine ?? 'not declared'}`,
|
|
1421
1486
|
`Isolation claim: ${report.boundary.isolationProviderClaim} (provided externally; not verified by Radar)`,
|
|
1422
1487
|
`Approved dependency builds: ${report.boundary.approvedDependencyBuilds.length === 0 ? 'none' : report.boundary.approvedDependencyBuilds.join(', ')}`,
|
|
1488
|
+
`Additional dependency builds required: ${report.boundary.requiredDependencyBuilds.length === 0 ? 'none' : report.boundary.requiredDependencyBuilds.join(', ')}`,
|
|
1423
1489
|
'',
|
|
1424
1490
|
`Result: ${report.result.toUpperCase()} — ${report.reason}`,
|
|
1425
1491
|
`Lifecycle scripts declared: ${lifecycle}`,
|