Files
orca/config/scripts/ssh-relay-runtime-sbom.test.mjs
T
2026-07-14 17:06:44 -04:00

123 lines
4.8 KiB
JavaScript

import { describe, expect, it } from 'vitest'
import { createSshRelayRuntimeSbom } from './ssh-relay-runtime-sbom.mjs'
const sha256 = (character) => `sha256:${character.repeat(64)}`
function file(path, role, character) {
return { path, type: 'file', role, size: 1, mode: 0o644, sha256: sha256(character) }
}
function identity(tuple = 'linux-arm64-glibc') {
return {
tupleId: tuple,
nodeVersion: '24.18.0',
contentId: sha256('f'),
entries: [
file('bin/node', 'node', '1'),
file('relay.js', 'relay', '2'),
file('THIRD_PARTY_LICENSES.txt', 'license', '3'),
file('node_modules/node-pty/lib/index.js', 'runtime-javascript', '4'),
file('node_modules/@parcel/watcher/index.js', 'runtime-javascript', '5'),
file(`node_modules/@parcel/watcher-${tuple}/watcher.node`, 'parcel-watcher-native', '6'),
file('node_modules/detect-libc/lib/detect-libc.js', 'runtime-javascript', '7'),
file('node_modules/is-glob/index.js', 'runtime-javascript', '8'),
file('node_modules/is-extglob/index.js', 'runtime-javascript', '9'),
file('node_modules/picomatch/index.js', 'runtime-javascript', 'a')
]
}
}
const archive = { sha256: sha256('e') }
function ownerName(sbom, fileName) {
const fileId = sbom.files.find((entry) => entry.fileName === fileName).SPDXID
const owners = sbom.relationships.filter(
(entry) => entry.relationshipType === 'CONTAINS' && entry.relatedSpdxElement === fileId
)
expect(owners).toHaveLength(1)
return sbom.packages.find((entry) => entry.SPDXID === owners[0].spdxElementId).name
}
describe('SSH relay runtime SPDX SBOM', () => {
it('inventories every runtime file under exactly one package', () => {
const fixture = identity()
const sbom = createSshRelayRuntimeSbom({
identity: fixture,
archive,
sourceDateEpoch: 1_752_710_400
})
expect(sbom.spdxVersion).toBe('SPDX-2.3')
expect(sbom.documentNamespace).toBe(
`https://github.com/stablyai/orca/ssh-relay-runtime/spdx/${'e'.repeat(64)}`
)
expect(sbom.creationInfo.created).toBe('2025-07-17T00:00:00.000Z')
expect(sbom.packages.map((entry) => entry.name)).toEqual([
'node',
'orca-ssh-relay',
'node-pty',
'@parcel/watcher',
'@parcel/watcher-linux-arm64-glibc',
'detect-libc',
'is-glob',
'is-extglob',
'picomatch'
])
expect(sbom.packages.find((entry) => entry.name === 'node')).toMatchObject({
versionInfo: '24.18.0',
licenseDeclared: 'MIT'
})
expect(sbom.packages.find((entry) => entry.name === 'orca-ssh-relay')).toMatchObject({
versionInfo: fixture.contentId,
licenseDeclared: 'NOASSERTION'
})
expect(sbom.files).toHaveLength(fixture.entries.length)
expect(new Set([...sbom.packages, ...sbom.files].map((entry) => entry.SPDXID)).size).toBe(
sbom.packages.length + sbom.files.length
)
expect(ownerName(sbom, 'bin/node')).toBe('node')
expect(ownerName(sbom, 'relay.js')).toBe('orca-ssh-relay')
expect(ownerName(sbom, 'THIRD_PARTY_LICENSES.txt')).toBe('orca-ssh-relay')
expect(ownerName(sbom, 'node_modules/node-pty/lib/index.js')).toBe('node-pty')
expect(ownerName(sbom, 'node_modules/@parcel/watcher/index.js')).toBe('@parcel/watcher')
expect(ownerName(sbom, 'node_modules/@parcel/watcher-linux-arm64-glibc/watcher.node')).toBe(
'@parcel/watcher-linux-arm64-glibc'
)
expect(ownerName(sbom, 'node_modules/detect-libc/lib/detect-libc.js')).toBe('detect-libc')
expect(ownerName(sbom, 'node_modules/is-glob/index.js')).toBe('is-glob')
expect(ownerName(sbom, 'node_modules/is-extglob/index.js')).toBe('is-extglob')
expect(ownerName(sbom, 'node_modules/picomatch/index.js')).toBe('picomatch')
expect(
sbom.relationships.filter((entry) => entry.relationshipType === 'DEPENDS_ON')
).toHaveLength(8)
})
it('rejects an unowned node_modules path and colliding SPDX identifiers', () => {
const unowned = identity()
unowned.entries.push(file('node_modules/unreviewed/index.js', 'runtime-javascript', 'b'))
expect(() =>
createSshRelayRuntimeSbom({ identity: unowned, archive, sourceDateEpoch: 1_752_710_400 })
).toThrow(/cannot assign a package owner/i)
const collision = identity()
collision.entries.push(
file('relay/a+b.js', 'runtime-javascript', 'b'),
file('relay/a@b.js', 'runtime-javascript', 'c')
)
expect(() =>
createSshRelayRuntimeSbom({ identity: collision, archive, sourceDateEpoch: 1_752_710_400 })
).toThrow(/duplicate SPDX identifier/i)
})
it('requires the exact archive digest to make the document namespace immutable', () => {
expect(() =>
createSshRelayRuntimeSbom({
identity: identity(),
archive: { sha256: 'missing-prefix' },
sourceDateEpoch: 1_752_710_400
})
).toThrow(/archive SHA-256/i)
})
})