dsh-standards 1.1.2 → 1.2.1

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 (42) hide show
  1. package/40-checker/README.md +15 -0
  2. package/40-checker/bin/dsh-flow-collect.mjs +3 -0
  3. package/40-checker/bin/dsh-levels.mjs +13 -2
  4. package/40-checker/scripts/bundle-smoke.mjs +3 -0
  5. package/40-checker/scripts/entry18-ci.mjs +4 -3
  6. package/40-checker/scripts/entry18-web.mjs +4 -1
  7. package/40-checker/scripts/flow-collect.mjs +494 -0
  8. package/40-checker/scripts/flow-sample-ci.mjs +4 -4
  9. package/40-checker/scripts/host-farm.mjs +2 -1
  10. package/40-checker/scripts/journey-config-observe.mjs +5 -3
  11. package/40-checker/scripts/journey-runtime.mjs +208 -83
  12. package/40-checker/scripts/level-audit.mjs +119 -19
  13. package/40-checker/scripts/m2-runner.mjs +4 -3
  14. package/40-checker/scripts/runtime-child.mjs +4 -0
  15. package/40-checker/src/cli.mjs +10 -2
  16. package/40-checker/src/flow-evidence.mjs +455 -0
  17. package/40-checker/src/index.mjs +3 -0
  18. package/40-checker/src/remediation.mjs +137 -0
  19. package/40-checker/src/report.mjs +19 -2
  20. package/40-checker/src/sandbox-env.mjs +78 -0
  21. package/CHANGELOG.md +22 -0
  22. package/bin/dsh-flow-collect.mjs +4 -0
  23. package/package.json +1 -2
  24. package/spec/README.md +2 -0
  25. package/spec/flow/README.md +27 -2
  26. package/spec/flow-evidence.schema.json +221 -0
  27. package/spec/levels.json +2 -0
  28. package/spec/remediation.json +478 -0
  29. package/40-checker/test/attestation.test.mjs +0 -59
  30. package/40-checker/test/checks.test.mjs +0 -414
  31. package/40-checker/test/claim.test.mjs +0 -28
  32. package/40-checker/test/client-shape.test.mjs +0 -35
  33. package/40-checker/test/dco.test.mjs +0 -51
  34. package/40-checker/test/entry-validate.test.mjs +0 -172
  35. package/40-checker/test/governance.test.mjs +0 -76
  36. package/40-checker/test/label.test.mjs +0 -97
  37. package/40-checker/test/level-audit.test.mjs +0 -99
  38. package/40-checker/test/levels.test.mjs +0 -31
  39. package/40-checker/test/ops.test.mjs +0 -117
  40. package/40-checker/test/permissions.test.mjs +0 -40
  41. package/40-checker/test/semver.test.mjs +0 -32
  42. package/40-checker/test/verify.test.mjs +0 -57
@@ -1,172 +0,0 @@
1
- import { test } from 'node:test'
2
- import assert from 'node:assert/strict'
3
- import { spawnSync } from 'node:child_process'
4
- import { fileURLToPath } from 'node:url'
5
- import path from 'node:path'
6
- import fs from 'node:fs'
7
- import os from 'node:os'
8
-
9
- const HERE = path.dirname(fileURLToPath(import.meta.url))
10
- const STD = path.resolve(HERE, '..', '..')
11
- const SCRIPT = path.join(STD, '40-checker', 'scripts', 'entry-validate.mjs')
12
- const FIXTURES = path.join(STD, 'adoption', 'entry', 'fixtures')
13
-
14
- function run(name, withMeta = true) {
15
- const dir = path.join(FIXTURES, name)
16
- const args = [SCRIPT, dir, '--json']
17
- const meta = path.join(dir, 'meta.json')
18
- if (withMeta && fs.existsSync(meta)) args.push('--meta', meta)
19
- return spawnSync(process.execPath, args, { encoding: 'utf8', timeout: 30_000 })
20
- }
21
-
22
- function result(name, withMeta = true) {
23
- const out = run(name, withMeta)
24
- assert.ok(out.stdout, out.stderr)
25
- return { out, json: JSON.parse(out.stdout) }
26
- }
27
-
28
- test('entry-validate: the good fixture passes C1-C8', () => {
29
- const { out, json } = result('good')
30
- assert.equal(out.status, 0, out.stderr)
31
- assert.equal(json.conclusion.status, 'pass')
32
- assert.deepEqual(json.conclusion.failed, [])
33
- assert.deepEqual(json.conclusion.notRun, [])
34
- })
35
-
36
- test('entry-validate: missing meta is incomplete, never a pass', () => {
37
- const { out, json } = result('no-meta', false)
38
- assert.equal(out.status, 3)
39
- assert.equal(json.conclusion.status, 'incomplete')
40
- assert.ok(json.conclusion.notRun.includes('C1'))
41
- assert.ok(json.conclusion.notRun.includes('C7'))
42
- })
43
-
44
- const failures = [
45
- ['client-only', 'C2'],
46
- ['missing-patch', 'C2'],
47
- ['engines-star', 'C4'],
48
- ['client-no-export', 'C5'],
49
- ['no-metadata', 'C6'],
50
- ['no-version', 'C7'],
51
- ['forbidden-label', 'C8'],
52
- ]
53
-
54
- for (const [name, id] of failures) {
55
- test(`entry-validate: ${name} fails ${id}`, () => {
56
- const { out, json } = result(name)
57
- assert.equal(out.status, 2, out.stderr)
58
- assert.equal(json.conclusion.status, 'fail')
59
- assert.ok(json.conclusion.failed.includes(id), JSON.stringify(json.conclusion))
60
- })
61
- }
62
-
63
- test('entry-validate: a peer range is an accepted C4 source', () => {
64
- const { out, json } = result('peer-ok')
65
- assert.equal(out.status, 0, out.stderr)
66
- assert.equal(json.checks.find(row => row.id === 'C4').status, 'pass')
67
- })
68
-
69
- test('entry-validate: a declared but uncommitted build output is a warning, not a fail', () => {
70
- const { out, json } = result('build-output')
71
- assert.equal(out.status, 0, out.stderr)
72
- assert.equal(json.conclusion.status, 'pass-with-warnings')
73
- assert.ok(json.conclusion.warnings.includes('C5'))
74
- assert.equal(json.checks.find(row => row.id === 'C6').status, 'pass')
75
- assert.deepEqual(json.conclusion.failed, [])
76
- })
77
-
78
- test('entry-validate: an ordered dsh.bundle.patch list is accepted', () => {
79
- const { out, json } = result('patch-list')
80
- assert.equal(out.status, 0, out.stderr)
81
- assert.equal(json.checks.find(row => row.id === 'C2').status, 'pass')
82
- assert.equal(json.conclusion.status, 'pass')
83
- })
84
-
85
- function hostEvidence(status) {
86
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'dsh-entry-host-'))
87
- const file = path.join(dir, 'host.json')
88
- fs.writeFileSync(file, JSON.stringify({
89
- status,
90
- command: 'dsh plugin --profile test add @dsh-fixtures/entry-good',
91
- host: 'dsh 0.2.2-alpha.2 / cordis 4.0.6-alpha.1',
92
- evidence: 'https://example.invalid/host-install/1',
93
- generatedAt: '2026-11-02',
94
- }))
95
- return { dir, file, cleanup: () => fs.rmSync(dir, { recursive: true, force: true }) }
96
- }
97
-
98
- test('entry-validate: a passed host install upgrades C3 to pass', () => {
99
- const h = hostEvidence('pass')
100
- try {
101
- const out = spawnSync(process.execPath, [SCRIPT, path.join(FIXTURES, 'good'), '--json', '--meta', path.join(FIXTURES, 'good', 'meta.json'), '--host-evidence', h.file], { encoding: 'utf8', timeout: 30_000 })
102
- assert.equal(out.status, 0, out.stderr)
103
- const json = JSON.parse(out.stdout)
104
- assert.equal(json.checks.find(row => row.id === 'C3').status, 'pass')
105
- assert.equal(json.conclusion.status, 'pass')
106
- } finally { h.cleanup() }
107
- })
108
-
109
- test('entry-validate: a failed host install fails C3', () => {
110
- const h = hostEvidence('fail')
111
- try {
112
- const out = spawnSync(process.execPath, [SCRIPT, path.join(FIXTURES, 'good'), '--json', '--meta', path.join(FIXTURES, 'good', 'meta.json'), '--host-evidence', h.file], { encoding: 'utf8', timeout: 30_000 })
113
- assert.equal(out.status, 2)
114
- const json = JSON.parse(out.stdout)
115
- assert.equal(json.checks.find(row => row.id === 'C3').status, 'fail')
116
- assert.ok(json.conclusion.failed.includes('C3'))
117
- } finally { h.cleanup() }
118
- })
119
-
120
- test('entry-validate: a blocked host install is incomplete, not a pass', () => {
121
- const h = hostEvidence('blocked')
122
- try {
123
- const out = spawnSync(process.execPath, [SCRIPT, path.join(FIXTURES, 'good'), '--json', '--meta', path.join(FIXTURES, 'good', 'meta.json'), '--host-evidence', h.file], { encoding: 'utf8', timeout: 30_000 })
124
- assert.equal(out.status, 3)
125
- const json = JSON.parse(out.stdout)
126
- assert.equal(json.checks.find(row => row.id === 'C3').status, 'blocked')
127
- assert.ok(json.conclusion.blocked.includes('C3'))
128
- assert.equal(json.conclusion.status, 'incomplete')
129
- } finally { h.cleanup() }
130
- })
131
-
132
- test('entry-validate: C3 is flow-only when no host evidence is supplied', () => {
133
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'dsh-c3-flow-'))
134
- try {
135
- const meta = JSON.parse(fs.readFileSync(path.join(FIXTURES, 'good', 'meta.json'), 'utf8'))
136
- delete meta.installCommand
137
- const metaFile = path.join(dir, 'meta.json')
138
- fs.writeFileSync(metaFile, JSON.stringify(meta))
139
- const out = spawnSync(process.execPath, [SCRIPT, path.join(FIXTURES, 'good'), '--json', '--meta', metaFile], { encoding: 'utf8', timeout: 30_000 })
140
- assert.equal(out.status, 0, out.stderr)
141
- const json = JSON.parse(out.stdout)
142
- assert.equal(json.checks.find(row => row.id === 'C3').status, 'not-applicable')
143
- assert.equal(json.conclusion.status, 'pass')
144
- } finally { fs.rmSync(dir, { recursive: true, force: true }) }
145
- })
146
-
147
- test('entry-validate: host evidence can mark C3 not-applicable for a host/directory sample', () => {
148
- const h = hostEvidence('not-applicable')
149
- try {
150
- const out = spawnSync(process.execPath, [SCRIPT, path.join(FIXTURES, 'good'), '--json', '--meta', path.join(FIXTURES, 'good', 'meta.json'), '--host-evidence', h.file], { encoding: 'utf8', timeout: 30_000 })
151
- assert.equal(out.status, 0, out.stderr)
152
- const json = JSON.parse(out.stdout)
153
- assert.equal(json.checks.find(row => row.id === 'C3').status, 'not-applicable')
154
- assert.equal(json.conclusion.status, 'pass')
155
- } finally { h.cleanup() }
156
- })
157
-
158
- test('entry-validate: a missing license is A7 advisory, not a C6 fail', () => {
159
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'dsh-c6-license-'))
160
- try {
161
- const src = path.join(FIXTURES, 'good')
162
- for (const name of ['index.js', 'client.js', 'cordis.patch.yml', 'meta.json']) fs.copyFileSync(path.join(src, name), path.join(dir, name))
163
- const pkg = JSON.parse(fs.readFileSync(path.join(src, 'package.json'), 'utf8'))
164
- delete pkg.license
165
- fs.writeFileSync(path.join(dir, 'package.json'), JSON.stringify(pkg))
166
- const out = spawnSync(process.execPath, [SCRIPT, dir, '--json', '--meta', path.join(dir, 'meta.json')], { encoding: 'utf8', timeout: 30_000 })
167
- assert.equal(out.status, 0, out.stderr)
168
- const json = JSON.parse(out.stdout)
169
- assert.equal(json.checks.find(row => row.id === 'C6').status, 'pass')
170
- assert.ok(json.advisories.some(row => row.id === 'A7'))
171
- } finally { fs.rmSync(dir, { recursive: true, force: true }) }
172
- })
@@ -1,76 +0,0 @@
1
- import test from 'node:test'
2
- import assert from 'node:assert/strict'
3
- import fs from 'node:fs'
4
- import path from 'node:path'
5
- import { fileURLToPath } from 'node:url'
6
- import { validateGovernance } from '../scripts/governance-check.mjs'
7
-
8
- const HERE = path.dirname(fileURLToPath(import.meta.url))
9
- const ROOT = path.resolve(HERE, '..', '..')
10
- const read = (rel) => JSON.parse(fs.readFileSync(path.join(ROOT, rel), 'utf8'))
11
-
12
- function fixture() {
13
- return {
14
- roles: read('governance/roles.json'),
15
- contributors: read('governance/contributors.json'),
16
- reviewers: read('governance/reviewers.json'),
17
- coi: read('governance/coi.json'),
18
- }
19
- }
20
-
21
- test('governance: the checked-in files pass', () => {
22
- const result = validateGovernance(fixture())
23
- assert.deepEqual(result.errors, [])
24
- })
25
-
26
- test('governance: exactly one human organizer is required', () => {
27
- const data = fixture()
28
- data.roles.roles.organizer.bot = true
29
- data.roles.roles.organizer.humanOnly = false
30
- const result = validateGovernance(data)
31
- assert.ok(result.errors.some((e) => /organizer must be humanOnly/.test(e)))
32
- })
33
-
34
- test('governance: AI must not decide spec semantics', () => {
35
- const data = fixture()
36
- data.roles.matrix['ai-steward']['spec.decide'] = 'allow'
37
- const result = validateGovernance(data)
38
- assert.ok(result.errors.some((e) => /must not hold spec\.decide/.test(e)))
39
- })
40
-
41
- test('governance: AI merge must be allowlist-only', () => {
42
- const data = fixture()
43
- data.roles.matrix['ai-steward']['repo.merge.main'] = 'allow'
44
- const result = validateGovernance(data)
45
- assert.ok(result.errors.some((e) => /allow-with-allowlist/.test(e)))
46
- })
47
-
48
- test('governance: class A approver must be human', () => {
49
- const data = fixture()
50
- data.roles.decisions.A.approver = ['ai-steward']
51
- const result = validateGovernance(data)
52
- assert.ok(result.errors.some((e) => /decision A approver/.test(e)))
53
- })
54
-
55
- test('governance: AI merge denylist protects spec and governance', () => {
56
- const data = fixture()
57
- data.roles.ai.mergeDenylist = ['spec/']
58
- const result = validateGovernance(data)
59
- assert.ok(result.errors.some((e) => /governance\//.test(e)))
60
- })
61
-
62
- test('governance: a contributor needs DCO and the current terms', () => {
63
- const data = fixture()
64
- data.contributors.contributors[0].signedOff = false
65
- data.contributors.contributors[0].terms = 'dsh-ct/0'
66
- const result = validateGovernance(data)
67
- assert.ok(result.errors.some((e) => /no DCO sign-off/.test(e)))
68
- assert.ok(result.errors.some((e) => /terms mismatch/.test(e)))
69
- })
70
-
71
- test('governance: reviewer must reference a human role', () => {
72
- const data = fixture()
73
- data.reviewers.reviewers[0].role = 'ai-steward'
74
- const result = validateGovernance(data)
75
- assert.ok(result.errors.some((e) => /human role/.test(e)))
76
- })
@@ -1,97 +0,0 @@
1
- import { test } from 'node:test'
2
- import assert from 'node:assert/strict'
3
- import { spawnSync } from 'node:child_process'
4
- import { fileURLToPath } from 'node:url'
5
- import path from 'node:path'
6
- import fs from 'node:fs'
7
- import os from 'node:os'
8
-
9
- const HERE = path.dirname(fileURLToPath(import.meta.url))
10
- const STD = path.resolve(HERE, '..', '..')
11
- const SYNC = path.join(STD, '40-checker', 'scripts', 'label-sync.mjs')
12
- const DRIFT = path.join(STD, '40-checker', 'scripts', 'label-drift.mjs')
13
- const VERIFY = path.join(STD, '40-checker', 'scripts', 'label-verify.mjs')
14
- const SAMPLE = path.join(STD, 'adoption', 'market', 'sample-source.json')
15
-
16
- function tempDir() {
17
- return fs.mkdtempSync(path.join(os.tmpdir(), 'dsh-label-test-'))
18
- }
19
-
20
- function run(script, args) {
21
- return spawnSync(process.execPath, [script, ...args], { encoding: 'utf8', timeout: 30_000 })
22
- }
23
-
24
- test('label-sync: writes a valid index from the sample source', () => {
25
- const dir = tempDir()
26
- try {
27
- const out = path.join(dir, 'labels')
28
- const sync = run(SYNC, ['--source', SAMPLE, '--out', out])
29
- assert.equal(sync.status, 0, sync.stderr)
30
- const index = JSON.parse(fs.readFileSync(path.join(out, 'index.json'), 'utf8'))
31
- assert.equal(index.schema, 'dsh-label-index/1')
32
- assert.equal(index.records.length, 1)
33
- assert.match(index.records[0].recordHash, /^sha256:[0-9a-f]{64}$/)
34
- const drift = run(DRIFT, ['--index', path.join(out, 'index.json'), '--now', '2026-11-02'])
35
- assert.equal(drift.status, 0, drift.stdout + drift.stderr)
36
- const verify = run(VERIFY, ['--index', path.join(out, 'index.json'), '--hash', index.records[0].recordHash, '--json'])
37
- assert.equal(verify.status, 0, verify.stderr)
38
- const view = JSON.parse(verify.stdout)
39
- assert.equal(view.ok, true)
40
- assert.equal(view.claimLevel, 'reference')
41
- assert.equal(Object.prototype.hasOwnProperty.call(view, 'grade'), false)
42
- } finally {
43
- fs.rmSync(dir, { recursive: true, force: true })
44
- }
45
- })
46
-
47
- test('label-drift: an expired label is stale and fails', () => {
48
- const dir = tempDir()
49
- try {
50
- const out = path.join(dir, 'labels')
51
- assert.equal(run(SYNC, ['--source', SAMPLE, '--out', out]).status, 0)
52
- const drift = run(DRIFT, ['--index', path.join(out, 'index.json'), '--now', '2028-01-01', '--json'])
53
- assert.equal(drift.status, 1)
54
- const result = JSON.parse(drift.stdout)
55
- assert.equal(result.stale, 1)
56
- assert.equal(result.ok, false)
57
- } finally {
58
- fs.rmSync(dir, { recursive: true, force: true })
59
- }
60
- })
61
-
62
- test('label-sync: a grade or a wrong hash is rejected', () => {
63
- const dir = tempDir()
64
- try {
65
- const source = JSON.parse(fs.readFileSync(SAMPLE, 'utf8'))
66
- const badGrade = structuredClone(source)
67
- badGrade[0].grade = 'A'
68
- const gradeFile = path.join(dir, 'bad-grade.json')
69
- fs.writeFileSync(gradeFile, JSON.stringify(badGrade))
70
- const grade = run(SYNC, ['--source', gradeFile, '--check'])
71
- assert.equal(grade.status, 1)
72
- assert.match(grade.stderr, /forbidden field: grade/)
73
-
74
- const badHash = structuredClone(source)
75
- badHash[0].recordHash = `sha256:${'0'.repeat(64)}`
76
- const hashFile = path.join(dir, 'bad-hash.json')
77
- fs.writeFileSync(hashFile, JSON.stringify(badHash))
78
- const hash = run(SYNC, ['--source', hashFile, '--check'])
79
- assert.equal(hash.status, 1)
80
- assert.match(hash.stderr, /recordHash does not match/)
81
- } finally {
82
- fs.rmSync(dir, { recursive: true, force: true })
83
- }
84
- })
85
-
86
- test('label-verify: an unknown hash is a 404, not a fake pass', () => {
87
- const dir = tempDir()
88
- try {
89
- const out = path.join(dir, 'labels')
90
- assert.equal(run(SYNC, ['--source', SAMPLE, '--out', out]).status, 0)
91
- const verify = run(VERIFY, ['--index', path.join(out, 'index.json'), '--hash', `sha256:${'f'.repeat(64)}`])
92
- assert.equal(verify.status, 2)
93
- assert.match(verify.stderr, /not found/)
94
- } finally {
95
- fs.rmSync(dir, { recursive: true, force: true })
96
- }
97
- })
@@ -1,99 +0,0 @@
1
- import { test } from 'node:test'
2
- import assert from 'node:assert/strict'
3
- import { spawnSync } from 'node:child_process'
4
- import { fileURLToPath } from 'node:url'
5
- import path from 'node:path'
6
-
7
- const HERE = path.dirname(fileURLToPath(import.meta.url))
8
- const STD = path.resolve(HERE, '..', '..')
9
- const SCRIPT = path.join(STD, '40-checker', 'scripts', 'level-audit.mjs')
10
- const GOOD = path.join(STD, '40-checker', 'fixtures', 'good')
11
-
12
- test('level-audit: static ENTRY is recognized, FLOW/BOOST are not upgraded', () => {
13
- const run = spawnSync(process.execPath, [SCRIPT, GOOD, '--format', 'json'], { encoding: 'utf8', timeout: 30_000 })
14
- assert.equal(run.status, 0, run.stderr)
15
- const result = JSON.parse(run.stdout)
16
- assert.equal(result.schema, 'dsh-level-audit/1')
17
- assert.equal(result.levelsSpec.schema, 'dsh-levels/1')
18
- assert.equal(result.levels.entry.state, 'recognized')
19
- assert.equal(result.levels.flow.state, 'not-run')
20
- assert.equal(result.levels.boost.state, 'not-measured')
21
- assert.deepEqual(result.notClaimed.includes('certification'), true)
22
- })
23
-
24
- test('level-audit: a missing package exits 3 and does not print a fake pass', () => {
25
- const run = spawnSync(process.execPath, [SCRIPT, '/no/such/package', '--format', 'json'], { encoding: 'utf8', timeout: 30_000 })
26
- assert.equal(run.status, 3)
27
- assert.match(run.stderr, /not a package directory/)
28
- })
29
-
30
- import fs from 'node:fs'
31
- import os from 'node:os'
32
-
33
- const BOOST_IDS = ['LEV-1', 'LEV-2', 'LEV-3', 'LEV-4', 'LEV-5', 'LEV-6', 'LEV-7', 'LEV-8']
34
-
35
- function writeBoostEvidence(rows) {
36
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'dsh-boost-evidence-'))
37
- const file = path.join(dir, 'boost.json')
38
- fs.writeFileSync(file, JSON.stringify(rows))
39
- return { dir, file, cleanup: () => fs.rmSync(dir, { recursive: true, force: true }) }
40
- }
41
-
42
- function validCard(expiresAt = '2099-01-01', generatedAt = '2026-11-01') {
43
- return {
44
- subject: 'fixture@1.0.0',
45
- host: 'fixture-host',
46
- method: 'fixture',
47
- scope: 'fixture',
48
- command: 'node fixture.mjs',
49
- result: 'pass',
50
- negativeControl: 'control fails as expected',
51
- generatedAt,
52
- expiresAt,
53
- recordHash: `sha256:${'a'.repeat(64)}`,
54
- claimLevel: 'self-reported',
55
- issuer: 'fixture',
56
- selfAssessed: true,
57
- }
58
- }
59
-
60
- test('level-audit: status-only BOOST rows are not measured without evidence cards', () => {
61
- const rows = Object.fromEntries(BOOST_IDS.map(id => [id, { status: 'measured', evidence: 'looks fine' }]))
62
- const fixture = writeBoostEvidence(rows)
63
- try {
64
- const run = spawnSync(process.execPath, [SCRIPT, GOOD, '--format', 'json', '--boost-evidence', fixture.file], { encoding: 'utf8', timeout: 30_000 })
65
- assert.equal(run.status, 0, run.stderr)
66
- const result = JSON.parse(run.stdout)
67
- assert.equal(result.levels.boost.state, 'not-measured')
68
- assert.equal(result.levels.boost.practices['LEV-1'].card.valid, false)
69
- } finally {
70
- fixture.cleanup()
71
- }
72
- })
73
-
74
- test('level-audit: BOOST is measured only with eight valid evidence cards', () => {
75
- const rows = Object.fromEntries(BOOST_IDS.map(id => [id, { status: 'measured', evidenceCard: validCard() }]))
76
- const fixture = writeBoostEvidence(rows)
77
- try {
78
- const run = spawnSync(process.execPath, [SCRIPT, GOOD, '--format', 'json', '--boost-evidence', fixture.file], { encoding: 'utf8', timeout: 30_000 })
79
- assert.equal(run.status, 0, run.stderr)
80
- const result = JSON.parse(run.stdout)
81
- assert.equal(result.levels.boost.state, 'measured')
82
- assert.equal(result.levels.boost.validCards, 8)
83
- } finally {
84
- fixture.cleanup()
85
- }
86
- })
87
-
88
- test('level-audit: expired BOOST cards are stale, not measured', () => {
89
- const rows = Object.fromEntries(BOOST_IDS.map(id => [id, { status: 'measured', evidenceCard: validCard('2020-01-01', '2019-01-01') }]))
90
- const fixture = writeBoostEvidence(rows)
91
- try {
92
- const run = spawnSync(process.execPath, [SCRIPT, GOOD, '--format', 'json', '--boost-evidence', fixture.file], { encoding: 'utf8', timeout: 30_000 })
93
- assert.equal(run.status, 0, run.stderr)
94
- const result = JSON.parse(run.stdout)
95
- assert.equal(result.levels.boost.state, 'stale')
96
- } finally {
97
- fixture.cleanup()
98
- }
99
- })
@@ -1,31 +0,0 @@
1
- import { test } from 'node:test'
2
- import assert from 'node:assert/strict'
3
- import { readFileSync } from 'node:fs'
4
- import { fileURLToPath } from 'node:url'
5
- import path from 'node:path'
6
-
7
- const HERE = path.dirname(fileURLToPath(import.meta.url))
8
- const STD = path.resolve(HERE, '..', '..')
9
- const levels = JSON.parse(readFileSync(path.join(STD, 'spec', 'levels.json'), 'utf8'))
10
-
11
- test('levels: exactly three levels with the expected ids and analogies', () => {
12
- assert.equal(levels.schema, 'dsh-levels/1')
13
- assert.equal(levels.nonOfficial, true)
14
- assert.deepEqual(levels.levels.map(level => level.id), ['entry', 'flow', 'boost'])
15
- assert.deepEqual(levels.levels.map(level => level.analogy), ['GB', 'GB/T', 'GB/Z'])
16
- })
17
-
18
- test('levels: ENTRY has G0-G5, FLOW has J1-J8, BOOST has LEV-1..LEV-8', () => {
19
- const gates = Object.fromEntries(levels.levels.map(level => [level.id, level.gates.map(gate => gate.id)]))
20
- assert.deepEqual(gates.entry, ['G0', 'G1', 'G2', 'G3', 'G4', 'G5'])
21
- assert.deepEqual(gates.flow, ['J1', 'J2', 'J3', 'J4', 'J5', 'J6', 'J7', 'J8'])
22
- assert.deepEqual(gates.boost, ['LEV-1', 'LEV-2', 'LEV-3', 'LEV-4', 'LEV-5', 'LEV-6', 'LEV-7', 'LEV-8'])
23
- })
24
-
25
- test('levels: evidence states include not-run and never imply a pass', () => {
26
- const all = new Set(levels.levels.flatMap(level => level.evidenceStates))
27
- assert.equal(all.has('not-run'), true)
28
- assert.equal(all.has('runtime'), true)
29
- assert.equal(all.has('measured'), true)
30
- assert.equal(levels.axes.rules.some(rule => rule.includes('skip is not a pass')), true)
31
- })
@@ -1,117 +0,0 @@
1
- import test from 'node:test'
2
- import assert from 'node:assert/strict'
3
- import fs from 'node:fs'
4
- import os from 'node:os'
5
- import path from 'node:path'
6
- import { fileURLToPath } from 'node:url'
7
- import { validateClauseMap } from '../scripts/clause-map.mjs'
8
- import { effective } from '../scripts/stale-check.mjs'
9
- import { appendRecord, verifyChain } from '../scripts/evidence-chain.mjs'
10
- import { buildDashboard } from '../scripts/dashboard.mjs'
11
- import { inspect } from '../scripts/surveillance.mjs'
12
-
13
- const HERE = path.dirname(fileURLToPath(import.meta.url))
14
- const ROOT = path.resolve(HERE, '..', '..')
15
- const read = (rel) => JSON.parse(fs.readFileSync(path.join(ROOT, rel), 'utf8'))
16
-
17
- test('clause map: the checked-in map covers every gate', () => {
18
- const result = validateClauseMap({ levels: read('spec/levels.json'), clauses: read('spec/clauses.json') })
19
- assert.deepEqual(result.errors, [])
20
- assert.deepEqual(result.covered.entry.sort(), ['G0', 'G1', 'G2', 'G3', 'G4', 'G5'])
21
- })
22
-
23
- test('clause map: a missing gate is an error', () => {
24
- const levels = read('spec/levels.json')
25
- const clauses = read('spec/clauses.json')
26
- clauses.clauses = clauses.clauses.filter((c) => !c.gates.includes('G4'))
27
- const result = validateClauseMap({ levels, clauses })
28
- assert.ok(result.errors.some((e) => /G4/.test(e)))
29
- })
30
-
31
- test('stale: an active expired record is expired', () => {
32
- const r = effective({ status: 'active', expiresAt: '2020-01-01' }, new Date('2026-11-01T00:00:00Z'))
33
- assert.equal(r.status, 'expired')
34
- assert.equal(r.stale, true)
35
- })
36
-
37
- test('stale: a draft is not valid but not “stale”', () => {
38
- const r = effective({ status: 'draft', expiresAt: '2030-01-01' }, new Date('2026-11-01T00:00:00Z'))
39
- assert.equal(r.status, 'draft')
40
- assert.equal(r.stale, false)
41
- })
42
-
43
- test('evidence chain: append then verify', () => {
44
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'dsh-chain-'))
45
- const record = path.join(dir, 'record.json')
46
- fs.writeFileSync(record, '{"ok":true}')
47
- const chain = path.join(dir, 'chain.jsonl')
48
- appendRecord({ chain, record, ts: '2026-11-02T00:00:00Z' })
49
- appendRecord({ chain, record, ts: '2026-11-02T00:00:01Z' })
50
- const result = verifyChain(fs.readFileSync(chain, 'utf8').split('\n'))
51
- assert.deepEqual(result.errors, [])
52
- assert.equal(result.entries, 2)
53
- fs.rmSync(dir, { recursive: true, force: true })
54
- })
55
-
56
- test('evidence chain: tampering is detected', () => {
57
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'dsh-chain-'))
58
- const record = path.join(dir, 'record.json')
59
- fs.writeFileSync(record, '{"ok":true}')
60
- const chain = path.join(dir, 'chain.jsonl')
61
- appendRecord({ chain, record, ts: '2026-11-02T00:00:00Z' })
62
- const lines = fs.readFileSync(chain, 'utf8').split('\n')
63
- lines[0] = lines[0].replace(/("recordSha256":")([0-9a-f])/, (m, a, b) => a + (b === '0' ? '1' : '0'))
64
- const result = verifyChain(lines)
65
- assert.ok(result.errors.length > 0)
66
- fs.rmSync(dir, { recursive: true, force: true })
67
- })
68
-
69
- test('dashboard: never claims official/security/production', () => {
70
- const d = buildDashboard(ROOT)
71
- assert.equal(d.schema, 'dsh-dashboard/1')
72
- assert.ok(d.notClaimed.includes('security audit'))
73
- assert.equal(d.flow.packages, 10)
74
- })
75
-
76
- test('surveillance: expired record becomes an issue', () => {
77
- const report = inspect({ attestations: [{ attestationId: 'DSH-ATT-2020-001', status: 'active', expiresAt: '2020-01-01', verifyUrl: 'https://example.com', claimLevel: 'self-reported' }] }, new Date('2026-11-01T00:00:00Z'))
78
- assert.ok(report.issues.some((i) => i.issues.includes('expired')))
79
- })
80
-
81
- test('round-robin: independent matching runs are comparable', async () => {
82
- const { compare } = await import('../scripts/round-robin.mjs')
83
- const expected = { good: { expected: 'warn' }, bad: { expected: 'fail' } }
84
- const r = compare({
85
- a: { runner: 'runner-a', results: { good: { status: 'warn' }, bad: { status: 'fail' } } },
86
- b: { runner: 'runner-b', results: { good: { status: 'warn' }, bad: { status: 'fail' } } },
87
- expected,
88
- })
89
- assert.equal(r.comparable, true)
90
- })
91
-
92
- test('round-robin: two not-run results are not comparable', async () => {
93
- const { compare } = await import('../scripts/round-robin.mjs')
94
- const r = compare({
95
- a: { runner: 'runner-a', results: { good: { status: 'not-run' } } },
96
- b: { runner: 'runner-b', results: { good: { status: 'not-run' } } },
97
- expected: { good: { expected: 'warn' } },
98
- })
99
- assert.equal(r.comparable, false)
100
- })
101
-
102
- test('flow index: aggregates result files without upgrading a verdict', async () => {
103
- const { buildFlowIndex } = await import('../scripts/flow-index.mjs')
104
- const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'dsh-flow-index-'))
105
- const row = (id, pass, fail) => ({
106
- schema: 'dsh-flow-real/1', id, package: id, version: '1.0.0', source: 'fixture', why: 'test',
107
- verdicts: { J1: pass ? 'pass' : 'fail', J2: 'not-run', J4: 'not-run', J6: 'not-run' },
108
- classification: 'clean', conclusion: 'partial', caveats: [], summary: { checks: { pass, fail, blocked: 0, notRun: 6 }, verdicts: { pass: pass ? 1 : 0, fail: fail, blocked: 0, partial: 0, notRun: 3 } },
109
- })
110
- fs.writeFileSync(path.join(dir, 'a.json'), JSON.stringify(row('a', 1, 0)))
111
- fs.writeFileSync(path.join(dir, 'b.json'), JSON.stringify(row('b', 0, 1)))
112
- const index = buildFlowIndex(dir)
113
- assert.equal(index.totals.packages, 2)
114
- assert.equal(index.totals.checks.fail, 1)
115
- assert.equal(index.totals.verdicts.fail, 1)
116
- fs.rmSync(dir, { recursive: true, force: true })
117
- })
@@ -1,40 +0,0 @@
1
- import test from 'node:test'
2
- import assert from 'node:assert/strict'
3
- import { checkCredentials } from '../src/declarations.mjs'
4
- import { validateCommitments, validateDisclosure, COMMITMENT_IDS } from '../src/permissions.mjs'
5
-
6
- const manifest = {
7
- dsh: {
8
- commitmentsVersion: 1,
9
- commitments: Object.fromEntries(COMMITMENT_IDS.map(id => [id, true])),
10
- disclosure: {
11
- endpoints: ['https://api.example.com'],
12
- retention: 'none',
13
- systemPrompt: 'unchanged',
14
- },
15
- capabilities: ['network:egress'],
16
- },
17
- }
18
-
19
- test('all 9 commitments validate as booleans', () => {
20
- const details = validateCommitments(manifest)
21
- assert.equal(details.length, 1)
22
- assert.equal(details[0].result, 'PASS')
23
- })
24
-
25
- test('missing commitment is a warning, not a failure', () => {
26
- const details = validateCommitments({ dsh: { commitments: { 'no-session-upload': true } } })
27
- assert.ok(details.some(item => item.result === 'WARN' && item.reason.includes('missing commitment')))
28
- })
29
-
30
- test('disclosure endpoints must be https URLs', () => {
31
- const details = validateDisclosure({ dsh: { disclosure: { endpoints: ['http://insecure.example.com'] } } })
32
- assert.ok(details.some(item => item.result === 'WARN'))
33
- })
34
-
35
- test('checkCredentials reads both declaration fields', () => {
36
- const check = checkCredentials(manifest, [])
37
- assert.equal(check.result, 'PASS')
38
- assert.ok(check.details.some(item => item.item === 'C-12.6' && item.result === 'PASS'))
39
- assert.ok(check.details.some(item => item.item === 'C-12.7' && item.result === 'PASS'))
40
- })
@@ -1,32 +0,0 @@
1
- import test from 'node:test'
2
- import assert from 'node:assert/strict'
3
- import { compareVersions, parseVersion, satisfies, validRange } from '../src/semver.mjs'
4
-
5
- test('parseVersion accepts exact semver and prerelease', () => {
6
- assert.deepEqual(parseVersion('0.2.2-alpha.2'), { major: 0, minor: 2, patch: 2, prerelease: ['alpha', '2'] })
7
- assert.equal(parseVersion('^0.2.2'), null)
8
- })
9
-
10
- test('compareVersions orders release above prerelease', () => {
11
- assert.equal(compareVersions(parseVersion('0.2.2'), parseVersion('0.2.2-alpha.2')), 1)
12
- assert.equal(compareVersions(parseVersion('0.2.2-alpha.2'), parseVersion('0.2.2-alpha.1')), 1)
13
- assert.equal(compareVersions(parseVersion('0.2.0-rc.2'), parseVersion('0.2.0-0')), 1)
14
- })
15
-
16
- test('satisfies handles the ranges used by real plugins', () => {
17
- assert.equal(satisfies('0.2.2-alpha.2', '>=0.2.2-alpha.2 <0.3.0'), true)
18
- assert.equal(satisfies('0.2.2-alpha.2', '>=0.1.5-rc.1 <0.2.0-0 || >=0.2.0-rc.2 <0.3.0-0'), true)
19
- assert.equal(satisfies('0.2.2-alpha.2', '^0.2.2-alpha.2'), true)
20
- assert.equal(satisfies('0.2.2-alpha.2', '~0.2.2'), false)
21
- assert.equal(satisfies('0.2.2-alpha.2', '^0.2.2'), false)
22
- assert.equal(satisfies('0.2.2-alpha.2', '>=0.3.0'), false)
23
- assert.equal(satisfies('0.2.2-alpha.2', 'workspace:^'), false)
24
- assert.equal(satisfies('24.0.0', '^22.19.0 || >=24.0.0'), true)
25
- })
26
-
27
- test('validRange rejects empty and malformed ranges', () => {
28
- assert.equal(validRange('>=0.2.2 <0.3.0'), true)
29
- assert.equal(validRange(''), false)
30
- assert.equal(validRange('workspace:^'), false)
31
- assert.equal(validRange('not-a-range'), false)
32
- })