dsh-standards 1.0.3 → 1.2.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/40-checker/README.md +15 -0
- package/40-checker/bin/dsh-flow-collect.mjs +3 -0
- package/40-checker/bin/dsh-levels.mjs +13 -2
- package/40-checker/fixtures/bundle-patch-only/cordis.patch.yml +3 -0
- package/40-checker/fixtures/bundle-patch-only/package.json +12 -0
- package/40-checker/fixtures/c12-command-arg/index.mjs +7 -0
- package/40-checker/fixtures/c12-command-arg/package.json +10 -0
- package/40-checker/fixtures/c12-comment/index.mjs +3 -0
- package/40-checker/fixtures/c12-comment/package.json +10 -0
- package/40-checker/fixtures/c12-compare/index.mjs +3 -0
- package/40-checker/fixtures/c12-compare/package.json +10 -0
- package/40-checker/fixtures/c12-doc-string/index.mjs +13 -0
- package/40-checker/fixtures/c12-doc-string/package.json +10 -0
- package/40-checker/fixtures/c12-grant/index.mjs +3 -0
- package/40-checker/fixtures/c12-grant/package.json +10 -0
- package/40-checker/fixtures/c12-string/index.mjs +3 -0
- package/40-checker/fixtures/c12-string/package.json +10 -0
- package/40-checker/fixtures/declaration-file/index.d.ts +1 -0
- package/40-checker/fixtures/declaration-file/index.mjs +9 -0
- package/40-checker/fixtures/declaration-file/package.json +10 -0
- package/40-checker/fixtures/import-local-side-effect/index.mjs +11 -0
- package/40-checker/fixtures/import-local-side-effect/package.json +21 -0
- package/40-checker/fixtures/import-local-side-effect/side-effectful.mjs +5 -0
- package/40-checker/fixtures/import-open-readonly/index.mjs +14 -0
- package/40-checker/fixtures/import-open-readonly/package.json +19 -0
- package/40-checker/fixtures/import-package-only/index.mjs +11 -0
- package/40-checker/fixtures/import-package-only/package.json +21 -0
- package/40-checker/fixtures/import-parse-error/index.mjs +5 -0
- package/40-checker/fixtures/import-parse-error/package.json +10 -0
- package/40-checker/fixtures/import-side-effect/index.mjs +14 -0
- package/40-checker/fixtures/import-side-effect/package.json +19 -0
- package/40-checker/fixtures/import-side-effect-nonentry/index.mjs +9 -0
- package/40-checker/fixtures/import-side-effect-nonentry/package.json +19 -0
- package/40-checker/fixtures/import-side-effect-nonentry/selfcheck.mjs +8 -0
- package/40-checker/fixtures/import-void-main/index.mjs +16 -0
- package/40-checker/fixtures/import-void-main/package.json +19 -0
- package/40-checker/fixtures/no-source/package.json +19 -0
- package/40-checker/fixtures/parse-error-nonentry/index.mjs +2 -0
- package/40-checker/fixtures/parse-error-nonentry/package.json +10 -0
- package/40-checker/fixtures/parse-error-nonentry/references/broken.js +1 -0
- package/40-checker/scripts/bundle-smoke.mjs +3 -0
- package/40-checker/scripts/entry18-ci.mjs +4 -3
- package/40-checker/scripts/entry18-web.mjs +4 -1
- package/40-checker/scripts/flow-collect.mjs +494 -0
- package/40-checker/scripts/flow-sample-ci.mjs +4 -4
- package/40-checker/scripts/host-farm.mjs +2 -1
- package/40-checker/scripts/journey-config-observe.mjs +5 -3
- package/40-checker/scripts/journey-runtime.mjs +208 -83
- package/40-checker/scripts/level-audit.mjs +91 -19
- package/40-checker/scripts/m2-runner.mjs +4 -3
- package/40-checker/scripts/runtime-child.mjs +4 -0
- package/40-checker/src/cli.mjs +11 -3
- package/40-checker/src/declarations.mjs +514 -19
- package/40-checker/src/flow-evidence.mjs +431 -0
- package/40-checker/src/index.mjs +3 -0
- package/40-checker/src/manifest.mjs +5 -0
- package/40-checker/src/remediation.mjs +132 -0
- package/40-checker/src/report.mjs +19 -2
- package/40-checker/src/sandbox-env.mjs +78 -0
- package/40-checker/test/checks.test.mjs +243 -1
- package/40-checker/test/flow-evidence.test.mjs +295 -0
- package/40-checker/test/remediation.test.mjs +300 -0
- package/40-checker/vendor/babel/README.md +10 -0
- package/40-checker/vendor/babel/index.cjs +3 -0
- package/40-checker/vendor/babel/node_modules/@babel/helper-string-parser/LICENSE +22 -0
- package/40-checker/vendor/babel/node_modules/@babel/helper-string-parser/README.md +19 -0
- package/40-checker/vendor/babel/node_modules/@babel/helper-string-parser/lib/index.d.ts +41 -0
- package/40-checker/vendor/babel/node_modules/@babel/helper-string-parser/lib/index.js +286 -0
- package/40-checker/vendor/babel/node_modules/@babel/helper-string-parser/package.json +31 -0
- package/40-checker/vendor/babel/node_modules/@babel/helper-validator-identifier/LICENSE +22 -0
- package/40-checker/vendor/babel/node_modules/@babel/helper-validator-identifier/README.md +19 -0
- package/40-checker/vendor/babel/node_modules/@babel/helper-validator-identifier/lib/identifier-browser.js +62 -0
- package/40-checker/vendor/babel/node_modules/@babel/helper-validator-identifier/lib/identifier.js +60 -0
- package/40-checker/vendor/babel/node_modules/@babel/helper-validator-identifier/lib/index.d.ts +28 -0
- package/40-checker/vendor/babel/node_modules/@babel/helper-validator-identifier/lib/index.js +27 -0
- package/40-checker/vendor/babel/node_modules/@babel/helper-validator-identifier/package.json +45 -0
- package/40-checker/vendor/babel/node_modules/@babel/parser/CHANGELOG.md +1073 -0
- package/40-checker/vendor/babel/node_modules/@babel/parser/LICENSE +19 -0
- package/40-checker/vendor/babel/node_modules/@babel/parser/README.md +19 -0
- package/40-checker/vendor/babel/node_modules/@babel/parser/bin/babel-parser.js +14 -0
- package/40-checker/vendor/babel/node_modules/@babel/parser/lib/index.d.ts +1047 -0
- package/40-checker/vendor/babel/node_modules/@babel/parser/lib/index.js +14612 -0
- package/40-checker/vendor/babel/node_modules/@babel/parser/package.json +57 -0
- package/40-checker/vendor/babel/node_modules/@babel/parser/typings/babel-parser.d.ts +636 -0
- package/40-checker/vendor/babel/node_modules/@babel/types/LICENSE +22 -0
- package/40-checker/vendor/babel/node_modules/@babel/types/README.md +19 -0
- package/40-checker/vendor/babel/node_modules/@babel/types/lib/index-legacy.d.ts +2765 -0
- package/40-checker/vendor/babel/node_modules/@babel/types/lib/index.d.ts +3668 -0
- package/40-checker/vendor/babel/node_modules/@babel/types/lib/index.js +10758 -0
- package/40-checker/vendor/babel/node_modules/@babel/types/lib/index.js.flow +2618 -0
- package/40-checker/vendor/babel/node_modules/@babel/types/package.json +38 -0
- package/CHANGELOG.md +66 -0
- package/bin/dsh-flow-collect.mjs +4 -0
- package/package.json +2 -1
- package/spec/README.md +2 -0
- package/spec/flow/README.md +23 -2
- package/spec/flow-evidence.schema.json +217 -0
- package/spec/levels.json +2 -0
- package/spec/remediation.json +478 -0
package/40-checker/README.md
CHANGED
|
@@ -19,6 +19,8 @@ node bin/dsh-plugin-verify.mjs /path/to/plugin --format json --out report.json
|
|
|
19
19
|
node bin/dsh-plugin-verify.mjs /path/to/plugin --format sarif --out report.sarif
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
`buildReport()` 与 `--format json` 默认带**加性** `advice[]`(来自 `spec/remediation.json` 的 68 条规则;FAIL/WARN detail 优先,无 detail 的运行时 FAIL 用 `check.clause` 兜底)。`--no-advice` 可关闭;它不改变任何 check 的结果或 exit code。
|
|
23
|
+
|
|
22
24
|
## 2. 检查项
|
|
23
25
|
|
|
24
26
|
| ID | 条款 | 层 | 说明 |
|
|
@@ -124,6 +126,19 @@ node scripts/level-audit.mjs ./my-bundle \
|
|
|
124
126
|
- ENTRY 自动;FLOW 只读 `--flow-evidence`(J1–J8),BOOST 只读 `--boost-evidence`(LEV-1–8)。
|
|
125
127
|
- 没有证据就写 `not-run` / `not-measured`,工具不会替作者升级。
|
|
126
128
|
|
|
129
|
+
### FLOW 证据链 `dsh-flow-collect`
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
node bin/dsh-flow-collect.mjs --package ./my-plugin --out flow-evidence.json
|
|
133
|
+
# 等价:node bin/dsh-levels.mjs flow collect --package ./my-plugin --out flow-evidence.json
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- 只接受 `dsh-flow-evidence/2`(`spec/flow-evidence.schema.json`)。`level-audit --flow-evidence` 对 v1(`dsh-flow-journey/1`、`dsh-flow-runtime/1`)和裸 `{Jx:{status}}` 标 `deprecated`,不计 pass。
|
|
137
|
+
- 每个 J 必须至少 1 条 `checks[]` 且全部 `exitCode === 0`、断言成立、至少一条非 `static` 观测检查,才计 pass;`static` preflight 不是 runtime,`warn`/`blocked`/`na` 都不计 8/8。
|
|
138
|
+
- collector 把包复制到临时目录再跑,前后 `treeSha256` 必须一致;子进程 env 走白名单(不含 token/key/secret);不授予 `allowBuilds`,不自动 `allow-version`。
|
|
139
|
+
- 前置缺失(无 dsh、无 `--previous`、宿主兼容门禁拒绝)记 `blocked` + reason,出口码 0;真失败出口码 1,并打印五要素提示(子检查 / 命令 / exitCode / stderr 末 20 行 / 日志绝对路径 + 条款锚)。
|
|
140
|
+
- 本地证据只是 `self-attested`:结构自洽 + 绑定此包 + 未过期,**不证明真跑过**,也不是沙箱、认证或安全审计。
|
|
141
|
+
|
|
127
142
|
## 4. 运行 L1–L3
|
|
128
143
|
|
|
129
144
|
需要一个**已构建**的 `@deepseek-ai/cordis` 入口。检查器不修改宿主,也不从源码构建宿主:
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* dsh-levels — one entry point for the three-level audit.
|
|
4
4
|
* It forwards to level-audit.mjs so there is a single documented command.
|
|
5
|
+
* `dsh-levels flow collect ...` forwards to the FLOW evidence collector.
|
|
5
6
|
*/
|
|
6
7
|
import path from 'node:path'
|
|
7
8
|
import { spawnSync } from 'node:child_process'
|
|
@@ -9,7 +10,17 @@ import { fileURLToPath } from 'node:url'
|
|
|
9
10
|
|
|
10
11
|
const HERE = path.dirname(fileURLToPath(import.meta.url))
|
|
11
12
|
const AUDIT = path.resolve(HERE, '..', 'scripts', 'level-audit.mjs')
|
|
13
|
+
const FLOW_COLLECT = path.resolve(HERE, 'dsh-flow-collect.mjs')
|
|
12
14
|
const args = process.argv.slice(2)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
let target = AUDIT
|
|
16
|
+
if (args[0] === 'flow' && args[1] === 'collect') {
|
|
17
|
+
args.splice(0, 2)
|
|
18
|
+
target = FLOW_COLLECT
|
|
19
|
+
} else if (args[0] === 'flow') {
|
|
20
|
+
console.error('usage: dsh-levels flow collect --package <dir> [--out <file>] [--static] [--previous <dir>]')
|
|
21
|
+
process.exit(2)
|
|
22
|
+
} else if (args[0] === 'audit') {
|
|
23
|
+
args.shift()
|
|
24
|
+
}
|
|
25
|
+
const run = spawnSync(process.execPath, [target, ...args], { stdio: 'inherit' })
|
|
15
26
|
process.exitCode = run.status ?? 1
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/bundle-patch-only",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"engines": { "dsh": ">=0.2.2-alpha.2 <0.3.0" },
|
|
6
|
+
"dsh": {
|
|
7
|
+
"manifestVersion": 1,
|
|
8
|
+
"bundle": { "patch": "./cordis.patch.yml" },
|
|
9
|
+
"capabilities": [],
|
|
10
|
+
"labels": []
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process'
|
|
2
|
+
|
|
3
|
+
export const name = 'c12-command-arg'
|
|
4
|
+
export function apply() {}
|
|
5
|
+
|
|
6
|
+
// C-12.4: --add-dir is a real command-line argument here, not documentation.
|
|
7
|
+
spawnSync('dsh', ['agent', '--add-dir', './docs'], { stdio: 'inherit' })
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/c12-command-arg",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": { ".": "./index.mjs" },
|
|
8
|
+
"engines": { "dsh": ">=0.2.2-alpha.2 <0.3.0" },
|
|
9
|
+
"dsh": { "manifestVersion": 1, "kind": "plugin", "capabilities": [], "labels": [] }
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/c12-comment",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": { ".": "./index.mjs" },
|
|
8
|
+
"engines": { "dsh": ">=0.2.2-alpha.2 <0.3.0" },
|
|
9
|
+
"dsh": { "manifestVersion": 1, "kind": "plugin", "capabilities": [], "labels": [] }
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/c12-compare",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": { ".": "./index.mjs" },
|
|
8
|
+
"engines": { "dsh": ">=0.2.2-alpha.2 <0.3.0" },
|
|
9
|
+
"dsh": { "manifestVersion": 1, "kind": "plugin", "capabilities": [], "labels": [] }
|
|
10
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const name = 'c12-doc-string'
|
|
2
|
+
export function apply() {}
|
|
3
|
+
|
|
4
|
+
// Documentation, not a grant: the literals below are labels and help text.
|
|
5
|
+
const documentation = {
|
|
6
|
+
desc: 'danger-full-access',
|
|
7
|
+
description: '--add-dir',
|
|
8
|
+
help: 'danger-full-access',
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
console.log('danger-full-access')
|
|
12
|
+
console.info('--add-dir')
|
|
13
|
+
console.warn(`mode: ${'danger-full-access'}`)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/c12-doc-string",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": { ".": "./index.mjs" },
|
|
8
|
+
"engines": { "dsh": ">=0.2.2-alpha.2 <0.3.0" },
|
|
9
|
+
"dsh": { "manifestVersion": 1, "kind": "plugin", "capabilities": [], "labels": [] }
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/c12-grant",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": { ".": "./index.mjs" },
|
|
8
|
+
"engines": { "dsh": ">=0.2.2-alpha.2 <0.3.0" },
|
|
9
|
+
"dsh": { "manifestVersion": 1, "kind": "plugin", "capabilities": [], "labels": [] }
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/c12-string",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": { ".": "./index.mjs" },
|
|
8
|
+
"engines": { "dsh": ">=0.2.2-alpha.2 <0.3.0" },
|
|
9
|
+
"dsh": { "manifestVersion": 1, "kind": "plugin", "capabilities": [], "labels": [] }
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function broken(: string
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const name = 'fixture-declaration-file'
|
|
2
|
+
export const inject = ['sessions']
|
|
3
|
+
export const provide = ['declaration-file']
|
|
4
|
+
|
|
5
|
+
export function apply(ctx) {
|
|
6
|
+
const sessions = ctx.sessions
|
|
7
|
+
ctx.provide('declaration-file', { hasSessions: Boolean(sessions) })
|
|
8
|
+
ctx.effect(() => () => {}, 'fixture.declaration-file.effect')
|
|
9
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/declaration-file",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": { ".": "./index.mjs" },
|
|
8
|
+
"engines": { "dsh": ">=0.2.2-alpha.2 <0.3.0" },
|
|
9
|
+
"dsh": { "manifestVersion": 1, "kind": "plugin", "capabilities": ["sessions:read"], "labels": [] }
|
|
10
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import './side-effectful.mjs'
|
|
2
|
+
|
|
3
|
+
export const name = 'fixture-import-local-side-effect'
|
|
4
|
+
export const inject = ['sessions']
|
|
5
|
+
export const provide = ['import-local-side-effect']
|
|
6
|
+
|
|
7
|
+
export function apply(ctx) {
|
|
8
|
+
const sessions = ctx.sessions
|
|
9
|
+
ctx.provide('import-local-side-effect', { hasSessions: Boolean(sessions) })
|
|
10
|
+
ctx.effect(() => () => {}, 'fixture.import-local-side-effect.effect')
|
|
11
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/import-local-side-effect",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.mjs"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"dsh": ">=0.2.2-alpha.2 <0.3.0"
|
|
12
|
+
},
|
|
13
|
+
"dsh": {
|
|
14
|
+
"manifestVersion": 1,
|
|
15
|
+
"kind": "plugin",
|
|
16
|
+
"capabilities": [
|
|
17
|
+
"sessions:read"
|
|
18
|
+
],
|
|
19
|
+
"labels": []
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { openSync } from 'node:fs'
|
|
2
|
+
|
|
3
|
+
export const name = 'fixture-import-open-readonly'
|
|
4
|
+
export const inject = ['sessions']
|
|
5
|
+
export const provide = ['import-open-readonly']
|
|
6
|
+
|
|
7
|
+
export function apply(ctx) {
|
|
8
|
+
const sessions = ctx.sessions
|
|
9
|
+
ctx.provide('import-open-readonly', { hasSessions: Boolean(sessions) })
|
|
10
|
+
ctx.effect(() => () => {}, 'fixture.import-open-readonly.effect')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// C-10.4 is about fs *writes*; a read-only open is a different side effect.
|
|
14
|
+
openSync(new URL(import.meta.url), 'r')
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/import-open-readonly",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.mjs"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"dsh": ">=0.2.2-alpha.2 <0.3.0"
|
|
12
|
+
},
|
|
13
|
+
"dsh": {
|
|
14
|
+
"manifestVersion": 1,
|
|
15
|
+
"kind": "plugin",
|
|
16
|
+
"capabilities": ["sessions:read"],
|
|
17
|
+
"labels": []
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import path from 'node:path'
|
|
2
|
+
|
|
3
|
+
export const name = 'fixture-import-package-only'
|
|
4
|
+
export const inject = ['sessions']
|
|
5
|
+
export const provide = ['import-package-only']
|
|
6
|
+
|
|
7
|
+
export function apply(ctx) {
|
|
8
|
+
const sessions = ctx.sessions
|
|
9
|
+
ctx.provide('import-package-only', { basename: path.basename('.'), hasSessions: Boolean(sessions) })
|
|
10
|
+
ctx.effect(() => () => {}, 'fixture.import-package-only.effect')
|
|
11
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/import-package-only",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.mjs"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"dsh": ">=0.2.2-alpha.2 <0.3.0"
|
|
12
|
+
},
|
|
13
|
+
"dsh": {
|
|
14
|
+
"manifestVersion": 1,
|
|
15
|
+
"kind": "plugin",
|
|
16
|
+
"capabilities": [
|
|
17
|
+
"sessions:read"
|
|
18
|
+
],
|
|
19
|
+
"labels": []
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/import-parse-error",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": { ".": "./index.mjs" },
|
|
8
|
+
"engines": { "dsh": ">=0.2.2-alpha.2 <0.3.0" },
|
|
9
|
+
"dsh": { "manifestVersion": 1, "kind": "plugin", "capabilities": [], "labels": [] }
|
|
10
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { writeFileSync } from 'node:fs'
|
|
2
|
+
|
|
3
|
+
export const name = 'fixture-import-side-effect'
|
|
4
|
+
export const inject = ['sessions']
|
|
5
|
+
export const provide = ['import-side-effect']
|
|
6
|
+
|
|
7
|
+
export function apply(ctx) {
|
|
8
|
+
const sessions = ctx.sessions
|
|
9
|
+
ctx.provide('import-side-effect', { hasSessions: Boolean(sessions) })
|
|
10
|
+
ctx.effect(() => () => {}, 'fixture.import-side-effect.effect')
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// DSC-10.4: a module-scope fs mutation, executed on import.
|
|
14
|
+
writeFileSync('/tmp/dsh-fixture-import-side-effect.txt', 'x')
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/import-side-effect",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.mjs"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"dsh": ">=0.2.2-alpha.2 <0.3.0"
|
|
12
|
+
},
|
|
13
|
+
"dsh": {
|
|
14
|
+
"manifestVersion": 1,
|
|
15
|
+
"kind": "plugin",
|
|
16
|
+
"capabilities": ["sessions:read"],
|
|
17
|
+
"labels": []
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const name = 'fixture-import-side-effect-nonentry'
|
|
2
|
+
export const inject = ['sessions']
|
|
3
|
+
export const provide = ['import-side-effect-nonentry']
|
|
4
|
+
|
|
5
|
+
export function apply(ctx) {
|
|
6
|
+
const sessions = ctx.sessions
|
|
7
|
+
ctx.provide('import-side-effect-nonentry', { hasSessions: Boolean(sessions) })
|
|
8
|
+
ctx.effect(() => () => {}, 'fixture.import-side-effect-nonentry.effect')
|
|
9
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/import-side-effect-nonentry",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.mjs"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"dsh": ">=0.2.2-alpha.2 <0.3.0"
|
|
12
|
+
},
|
|
13
|
+
"dsh": {
|
|
14
|
+
"manifestVersion": 1,
|
|
15
|
+
"kind": "plugin",
|
|
16
|
+
"capabilities": ["sessions:read"],
|
|
17
|
+
"labels": []
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Preflight helper shipped with the package, never imported by the entry module.
|
|
2
|
+
// A module-scope fs mutation here is not an entry import-time side effect (C-10.3).
|
|
3
|
+
import { mkdirSync } from 'node:fs'
|
|
4
|
+
|
|
5
|
+
mkdirSync('/tmp/dsh-fixture-selfcheck', { recursive: true })
|
|
6
|
+
|
|
7
|
+
// Same class of module-scope work, but still outside the entry module.
|
|
8
|
+
globalThis.__dshFixtureSelfcheck = true
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const name = 'fixture-import-void-main'
|
|
2
|
+
export const inject = ['sessions']
|
|
3
|
+
export const provide = ['import-void-main']
|
|
4
|
+
|
|
5
|
+
export function apply(ctx) {
|
|
6
|
+
const sessions = ctx.sessions
|
|
7
|
+
ctx.provide('import-void-main', { hasSessions: Boolean(sessions) })
|
|
8
|
+
ctx.effect(() => () => {}, 'fixture.import-void-main.effect')
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function main() {
|
|
12
|
+
return undefined
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// C-10.2: an immediate module-scope call, expressed as `void main()`.
|
|
16
|
+
void main()
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/import-void-main",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.mjs"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"dsh": ">=0.2.2-alpha.2 <0.3.0"
|
|
12
|
+
},
|
|
13
|
+
"dsh": {
|
|
14
|
+
"manifestVersion": 1,
|
|
15
|
+
"kind": "plugin",
|
|
16
|
+
"capabilities": ["sessions:read"],
|
|
17
|
+
"labels": []
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/no-source",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./index.mjs"
|
|
9
|
+
},
|
|
10
|
+
"engines": {
|
|
11
|
+
"dsh": ">=0.2.2-alpha.2 <0.3.0"
|
|
12
|
+
},
|
|
13
|
+
"dsh": {
|
|
14
|
+
"manifestVersion": 1,
|
|
15
|
+
"kind": "plugin",
|
|
16
|
+
"capabilities": ["sessions:read"],
|
|
17
|
+
"labels": []
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@dsh-fixtures/parse-error-nonentry",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.mjs",
|
|
7
|
+
"exports": { ".": "./index.mjs" },
|
|
8
|
+
"engines": { "dsh": ">=0.2.2-alpha.2 <0.3.0" },
|
|
9
|
+
"dsh": { "manifestVersion": 1, "kind": "plugin", "capabilities": [], "labels": [] }
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const broken = {
|
|
@@ -14,6 +14,7 @@ import fs from 'node:fs'
|
|
|
14
14
|
import os from 'node:os'
|
|
15
15
|
import path from 'node:path'
|
|
16
16
|
import { pathToFileURL } from 'node:url'
|
|
17
|
+
import { scrubProcessEnv } from '../src/sandbox-env.mjs'
|
|
17
18
|
|
|
18
19
|
function parse(argv) {
|
|
19
20
|
const options = { package: null, host: null, base: null, web: null, bare: null, json: false, timeout: 30_000 }
|
|
@@ -42,6 +43,8 @@ function withTimeout(promise, ms, label) {
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
async function main() {
|
|
46
|
+
// Boot happens in this process: drop secrets before any plugin import.
|
|
47
|
+
scrubProcessEnv()
|
|
45
48
|
const options = parse(process.argv.slice(2))
|
|
46
49
|
const pkg = path.resolve(options.package)
|
|
47
50
|
const manifest = JSON.parse(fs.readFileSync(path.join(pkg, 'package.json'), 'utf8'))
|
|
@@ -58,6 +58,7 @@ import fs from 'node:fs'
|
|
|
58
58
|
import os from 'node:os'
|
|
59
59
|
import path from 'node:path'
|
|
60
60
|
import { spawnSync } from 'node:child_process'
|
|
61
|
+
import { sanitizedEnv } from '../src/sandbox-env.mjs'
|
|
61
62
|
import { fileURLToPath } from 'node:url'
|
|
62
63
|
|
|
63
64
|
const HERE = path.dirname(fileURLToPath(import.meta.url))
|
|
@@ -153,16 +154,16 @@ function run(command, args, { cwd, timeout, env } = {}) {
|
|
|
153
154
|
encoding: 'utf8',
|
|
154
155
|
maxBuffer: 64 * 1024 * 1024,
|
|
155
156
|
killSignal: 'SIGKILL',
|
|
156
|
-
env: {
|
|
157
|
-
...process.env,
|
|
157
|
+
env: sanitizedEnv({
|
|
158
158
|
NO_COLOR: '1',
|
|
159
159
|
npm_config_update_notifier: 'false',
|
|
160
160
|
// Bound registry waits so one unresponsive metadata request cannot wedge
|
|
161
161
|
// a shard past its job timeout.
|
|
162
162
|
npm_config_fetch_timeout: '60000',
|
|
163
163
|
npm_config_fetch_retries: '2',
|
|
164
|
+
...(process.env.DSH_HOME ? { DSH_HOME: process.env.DSH_HOME } : {}),
|
|
164
165
|
...env,
|
|
165
|
-
},
|
|
166
|
+
}),
|
|
166
167
|
})
|
|
167
168
|
return {
|
|
168
169
|
command,
|
|
@@ -17,6 +17,7 @@ import fs from 'node:fs'
|
|
|
17
17
|
import os from 'node:os'
|
|
18
18
|
import path from 'node:path'
|
|
19
19
|
import { spawnSync } from 'node:child_process'
|
|
20
|
+
import { sanitizedEnv, scrubProcessEnv } from '../src/sandbox-env.mjs'
|
|
20
21
|
import { fileURLToPath } from 'node:url'
|
|
21
22
|
|
|
22
23
|
const HERE = path.dirname(fileURLToPath(import.meta.url))
|
|
@@ -87,7 +88,7 @@ function run(command, args, { cwd, timeout, env } = {}) {
|
|
|
87
88
|
timeout,
|
|
88
89
|
encoding: 'utf8',
|
|
89
90
|
maxBuffer: 64 * 1024 * 1024,
|
|
90
|
-
env: { ...process.env
|
|
91
|
+
env: sanitizedEnv({ NO_COLOR: '1', ...(process.env.DSH_HOME ? { DSH_HOME: process.env.DSH_HOME } : {}), ...env }),
|
|
91
92
|
})
|
|
92
93
|
return {
|
|
93
94
|
status: result.status,
|
|
@@ -159,6 +160,8 @@ function targetRows(pkgDir, manifest, loadOverlayPatches, composeEntries) {
|
|
|
159
160
|
|
|
160
161
|
async function main() {
|
|
161
162
|
const options = parseArgs(process.argv.slice(2))
|
|
163
|
+
// This harness boots the sample in-process; drop secrets before any import.
|
|
164
|
+
scrubProcessEnv()
|
|
162
165
|
const startedAt = new Date().toISOString()
|
|
163
166
|
const work = fs.mkdtempSync(path.join(os.tmpdir(), 'dsh-entry18-web-'))
|
|
164
167
|
const home = fs.mkdtempSync(path.join(os.tmpdir(), 'dsh-entry18-home-'))
|