@opensip-cli/external-tool-adapter 0.1.15
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/LICENSE +202 -0
- package/NOTICE +8 -0
- package/README.md +33 -0
- package/dist/__tests__/acceptance-harness.test.d.ts +2 -0
- package/dist/__tests__/acceptance-harness.test.d.ts.map +1 -0
- package/dist/__tests__/acceptance-harness.test.js +106 -0
- package/dist/__tests__/acceptance-harness.test.js.map +1 -0
- package/dist/__tests__/artifact-path.test.d.ts +2 -0
- package/dist/__tests__/artifact-path.test.d.ts.map +1 -0
- package/dist/__tests__/artifact-path.test.js +19 -0
- package/dist/__tests__/artifact-path.test.js.map +1 -0
- package/dist/__tests__/binary-resolver.test.d.ts +2 -0
- package/dist/__tests__/binary-resolver.test.d.ts.map +1 -0
- package/dist/__tests__/binary-resolver.test.js +64 -0
- package/dist/__tests__/binary-resolver.test.js.map +1 -0
- package/dist/__tests__/define-external-tool-adapter.test.d.ts +2 -0
- package/dist/__tests__/define-external-tool-adapter.test.d.ts.map +1 -0
- package/dist/__tests__/define-external-tool-adapter.test.js +165 -0
- package/dist/__tests__/define-external-tool-adapter.test.js.map +1 -0
- package/dist/__tests__/doctor-command.test.d.ts +2 -0
- package/dist/__tests__/doctor-command.test.d.ts.map +1 -0
- package/dist/__tests__/doctor-command.test.js +124 -0
- package/dist/__tests__/doctor-command.test.js.map +1 -0
- package/dist/__tests__/exit-model.test.d.ts +2 -0
- package/dist/__tests__/exit-model.test.d.ts.map +1 -0
- package/dist/__tests__/exit-model.test.js +30 -0
- package/dist/__tests__/exit-model.test.js.map +1 -0
- package/dist/__tests__/fingerprint.test.d.ts +2 -0
- package/dist/__tests__/fingerprint.test.d.ts.map +1 -0
- package/dist/__tests__/fingerprint.test.js +39 -0
- package/dist/__tests__/fingerprint.test.js.map +1 -0
- package/dist/__tests__/gate-render.test.d.ts +2 -0
- package/dist/__tests__/gate-render.test.d.ts.map +1 -0
- package/dist/__tests__/gate-render.test.js +82 -0
- package/dist/__tests__/gate-render.test.js.map +1 -0
- package/dist/__tests__/ingest-json.test.d.ts +2 -0
- package/dist/__tests__/ingest-json.test.d.ts.map +1 -0
- package/dist/__tests__/ingest-json.test.js +53 -0
- package/dist/__tests__/ingest-json.test.js.map +1 -0
- package/dist/__tests__/ingest-sarif.test.d.ts +2 -0
- package/dist/__tests__/ingest-sarif.test.d.ts.map +1 -0
- package/dist/__tests__/ingest-sarif.test.js +283 -0
- package/dist/__tests__/ingest-sarif.test.js.map +1 -0
- package/dist/__tests__/manifest-commands.test.d.ts +2 -0
- package/dist/__tests__/manifest-commands.test.d.ts.map +1 -0
- package/dist/__tests__/manifest-commands.test.js +67 -0
- package/dist/__tests__/manifest-commands.test.js.map +1 -0
- package/dist/__tests__/provenance.test.d.ts +2 -0
- package/dist/__tests__/provenance.test.d.ts.map +1 -0
- package/dist/__tests__/provenance.test.js +48 -0
- package/dist/__tests__/provenance.test.js.map +1 -0
- package/dist/__tests__/redact.test.d.ts +2 -0
- package/dist/__tests__/redact.test.d.ts.map +1 -0
- package/dist/__tests__/redact.test.js +37 -0
- package/dist/__tests__/redact.test.js.map +1 -0
- package/dist/__tests__/run-loop-artifact.test.d.ts +21 -0
- package/dist/__tests__/run-loop-artifact.test.d.ts.map +1 -0
- package/dist/__tests__/run-loop-artifact.test.js +186 -0
- package/dist/__tests__/run-loop-artifact.test.js.map +1 -0
- package/dist/__tests__/run-loop-exit.test.d.ts +21 -0
- package/dist/__tests__/run-loop-exit.test.d.ts.map +1 -0
- package/dist/__tests__/run-loop-exit.test.js +123 -0
- package/dist/__tests__/run-loop-exit.test.js.map +1 -0
- package/dist/__tests__/run-loop-gate.test.d.ts +10 -0
- package/dist/__tests__/run-loop-gate.test.d.ts.map +1 -0
- package/dist/__tests__/run-loop-gate.test.js +159 -0
- package/dist/__tests__/run-loop-gate.test.js.map +1 -0
- package/dist/__tests__/session-payload.test.d.ts +12 -0
- package/dist/__tests__/session-payload.test.d.ts.map +1 -0
- package/dist/__tests__/session-payload.test.js +131 -0
- package/dist/__tests__/session-payload.test.js.map +1 -0
- package/dist/__tests__/severity-map.test.d.ts +2 -0
- package/dist/__tests__/severity-map.test.d.ts.map +1 -0
- package/dist/__tests__/severity-map.test.js +57 -0
- package/dist/__tests__/severity-map.test.js.map +1 -0
- package/dist/acceptance-harness.d.ts +48 -0
- package/dist/acceptance-harness.d.ts.map +1 -0
- package/dist/acceptance-harness.js +78 -0
- package/dist/acceptance-harness.js.map +1 -0
- package/dist/adapter-config.d.ts +58 -0
- package/dist/adapter-config.d.ts.map +1 -0
- package/dist/adapter-config.js +73 -0
- package/dist/adapter-config.js.map +1 -0
- package/dist/adapter-manifest.d.ts +57 -0
- package/dist/adapter-manifest.d.ts.map +1 -0
- package/dist/adapter-manifest.js +68 -0
- package/dist/adapter-manifest.js.map +1 -0
- package/dist/artifact-path.d.ts +26 -0
- package/dist/artifact-path.d.ts.map +1 -0
- package/dist/artifact-path.js +22 -0
- package/dist/artifact-path.js.map +1 -0
- package/dist/binary-resolver.d.ts +51 -0
- package/dist/binary-resolver.d.ts.map +1 -0
- package/dist/binary-resolver.js +66 -0
- package/dist/binary-resolver.js.map +1 -0
- package/dist/define-external-tool-adapter.d.ts +25 -0
- package/dist/define-external-tool-adapter.d.ts.map +1 -0
- package/dist/define-external-tool-adapter.js +149 -0
- package/dist/define-external-tool-adapter.js.map +1 -0
- package/dist/doctor-command.d.ts +81 -0
- package/dist/doctor-command.d.ts.map +1 -0
- package/dist/doctor-command.js +160 -0
- package/dist/doctor-command.js.map +1 -0
- package/dist/exit-model.d.ts +33 -0
- package/dist/exit-model.d.ts.map +1 -0
- package/dist/exit-model.js +35 -0
- package/dist/exit-model.js.map +1 -0
- package/dist/fingerprint.d.ts +26 -0
- package/dist/fingerprint.d.ts.map +1 -0
- package/dist/fingerprint.js +32 -0
- package/dist/fingerprint.js.map +1 -0
- package/dist/gate-render.d.ts +18 -0
- package/dist/gate-render.d.ts.map +1 -0
- package/dist/gate-render.js +25 -0
- package/dist/gate-render.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -0
- package/dist/index.js.map +1 -0
- package/dist/ingest-json.d.ts +32 -0
- package/dist/ingest-json.d.ts.map +1 -0
- package/dist/ingest-json.js +66 -0
- package/dist/ingest-json.js.map +1 -0
- package/dist/ingest-sarif.d.ts +113 -0
- package/dist/ingest-sarif.d.ts.map +1 -0
- package/dist/ingest-sarif.js +158 -0
- package/dist/ingest-sarif.js.map +1 -0
- package/dist/manifest-commands.d.ts +23 -0
- package/dist/manifest-commands.d.ts.map +1 -0
- package/dist/manifest-commands.js +47 -0
- package/dist/manifest-commands.js.map +1 -0
- package/dist/process-exec.d.ts +51 -0
- package/dist/process-exec.d.ts.map +1 -0
- package/dist/process-exec.js +99 -0
- package/dist/process-exec.js.map +1 -0
- package/dist/provenance.d.ts +19 -0
- package/dist/provenance.d.ts.map +1 -0
- package/dist/provenance.js +31 -0
- package/dist/provenance.js.map +1 -0
- package/dist/redact.d.ts +24 -0
- package/dist/redact.d.ts.map +1 -0
- package/dist/redact.js +38 -0
- package/dist/redact.js.map +1 -0
- package/dist/run-context.d.ts +24 -0
- package/dist/run-context.d.ts.map +1 -0
- package/dist/run-context.js +36 -0
- package/dist/run-context.js.map +1 -0
- package/dist/run-loop.d.ts +64 -0
- package/dist/run-loop.d.ts.map +1 -0
- package/dist/run-loop.js +320 -0
- package/dist/run-loop.js.map +1 -0
- package/dist/scan-emit.d.ts +81 -0
- package/dist/scan-emit.d.ts.map +1 -0
- package/dist/scan-emit.js +125 -0
- package/dist/scan-emit.js.map +1 -0
- package/dist/session-payload.d.ts +81 -0
- package/dist/session-payload.d.ts.map +1 -0
- package/dist/session-payload.js +86 -0
- package/dist/session-payload.js.map +1 -0
- package/dist/severity-map.d.ts +43 -0
- package/dist/severity-map.d.ts.map +1 -0
- package/dist/severity-map.js +84 -0
- package/dist/severity-map.js.map +1 -0
- package/dist/types.d.ts +228 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +15 -0
- package/dist/types.js.map +1 -0
- package/dist/version-command.d.ts +36 -0
- package/dist/version-command.d.ts.map +1 -0
- package/dist/version-command.js +74 -0
- package/dist/version-command.js.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Scanner exit-code interpretation (ADR-0091, Phase-0 decision 4).
|
|
3
|
+
*
|
|
4
|
+
* Pure: takes a code + the per-command {@link ScannerExitModel} and returns one
|
|
5
|
+
* of `'ok' | 'findings' | 'fault'`. NEVER throws — it returns data and the
|
|
6
|
+
* caller decides whether to raise a typed error.
|
|
7
|
+
*
|
|
8
|
+
* The sharp edge is gitleaks (and the disambiguation it forces): gitleaks exits
|
|
9
|
+
* `1` for BOTH leaks and an internal `log.Fatal`, so an exit in `findings` is
|
|
10
|
+
* only a findings verdict when the artifact actually parsed. The caller passes
|
|
11
|
+
* `artifactValid: false` when the report file is missing/garbage, which downgrades
|
|
12
|
+
* a `findings` code to a `fault`.
|
|
13
|
+
*/
|
|
14
|
+
import type { ScannerExitModel } from './types.js';
|
|
15
|
+
/** The interpreted verdict of a scanner process exit. */
|
|
16
|
+
export type ExitVerdict = 'ok' | 'findings' | 'fault';
|
|
17
|
+
export declare const DEFAULT_EXIT_MODEL: ScannerExitModel;
|
|
18
|
+
/**
|
|
19
|
+
* Interpret a scanner process exit code against its {@link ScannerExitModel}.
|
|
20
|
+
*
|
|
21
|
+
* - code ∈ `ok` ⇒ `'ok'`.
|
|
22
|
+
* - code ∈ `findings` ⇒ `'findings'`, UNLESS `opts.artifactValid === false`
|
|
23
|
+
* (the gitleaks disambiguation: exit 1 + missing/garbage report ⇒ `'fault'`).
|
|
24
|
+
* `artifactValid` left `undefined` is treated as valid (stdout scanners, no
|
|
25
|
+
* artifact to validate).
|
|
26
|
+
* - code `>= errorFrom`, or any other unmodeled value, ⇒ `'fault'`.
|
|
27
|
+
*
|
|
28
|
+
* `ok` is checked before `findings` so an overlap resolves to the cleaner verdict.
|
|
29
|
+
*/
|
|
30
|
+
export declare function interpretExit(code: number, model: ScannerExitModel, opts?: {
|
|
31
|
+
readonly artifactValid?: boolean;
|
|
32
|
+
}): ExitVerdict;
|
|
33
|
+
//# sourceMappingURL=exit-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-model.d.ts","sourceRoot":"","sources":["../src/exit-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAEnD,yDAAyD;AACzD,MAAM,MAAM,WAAW,GAAG,IAAI,GAAG,UAAU,GAAG,OAAO,CAAC;AAEtD,eAAO,MAAM,kBAAkB,EAAE,gBAA2D,CAAC;AAE7F;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,gBAAgB,EACvB,IAAI,CAAC,EAAE;IAAE,QAAQ,CAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,GAC1C,WAAW,CAMb"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Scanner exit-code interpretation (ADR-0091, Phase-0 decision 4).
|
|
3
|
+
*
|
|
4
|
+
* Pure: takes a code + the per-command {@link ScannerExitModel} and returns one
|
|
5
|
+
* of `'ok' | 'findings' | 'fault'`. NEVER throws — it returns data and the
|
|
6
|
+
* caller decides whether to raise a typed error.
|
|
7
|
+
*
|
|
8
|
+
* The sharp edge is gitleaks (and the disambiguation it forces): gitleaks exits
|
|
9
|
+
* `1` for BOTH leaks and an internal `log.Fatal`, so an exit in `findings` is
|
|
10
|
+
* only a findings verdict when the artifact actually parsed. The caller passes
|
|
11
|
+
* `artifactValid: false` when the report file is missing/garbage, which downgrades
|
|
12
|
+
* a `findings` code to a `fault`.
|
|
13
|
+
*/
|
|
14
|
+
export const DEFAULT_EXIT_MODEL = { ok: [0], findings: [1], errorFrom: 2 };
|
|
15
|
+
/**
|
|
16
|
+
* Interpret a scanner process exit code against its {@link ScannerExitModel}.
|
|
17
|
+
*
|
|
18
|
+
* - code ∈ `ok` ⇒ `'ok'`.
|
|
19
|
+
* - code ∈ `findings` ⇒ `'findings'`, UNLESS `opts.artifactValid === false`
|
|
20
|
+
* (the gitleaks disambiguation: exit 1 + missing/garbage report ⇒ `'fault'`).
|
|
21
|
+
* `artifactValid` left `undefined` is treated as valid (stdout scanners, no
|
|
22
|
+
* artifact to validate).
|
|
23
|
+
* - code `>= errorFrom`, or any other unmodeled value, ⇒ `'fault'`.
|
|
24
|
+
*
|
|
25
|
+
* `ok` is checked before `findings` so an overlap resolves to the cleaner verdict.
|
|
26
|
+
*/
|
|
27
|
+
export function interpretExit(code, model, opts) {
|
|
28
|
+
if (model.ok.includes(code))
|
|
29
|
+
return 'ok';
|
|
30
|
+
if (model.findings.includes(code)) {
|
|
31
|
+
return opts?.artifactValid === false ? 'fault' : 'findings';
|
|
32
|
+
}
|
|
33
|
+
return 'fault';
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=exit-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exit-model.js","sourceRoot":"","sources":["../src/exit-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,MAAM,CAAC,MAAM,kBAAkB,GAAqB,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC;AAE7F;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAY,EACZ,KAAuB,EACvB,IAA2C;IAE3C,IAAI,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACzC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QAClC,OAAO,IAAI,EAAE,aAAa,KAAK,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC;IAC9D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The adapter fingerprint strategy map (ADR-0091 §4.5).
|
|
3
|
+
*
|
|
4
|
+
* Scanner output is line-volatile (dependency manifests and IaC files shift line
|
|
5
|
+
* numbers constantly), so the adapter DEFAULT is `message-hash`
|
|
6
|
+
* (`sha256(filePath\nruleId\nmessage)`) — line-shift tolerant — not the host
|
|
7
|
+
* default (`ruleId|filePath|line|col`), which would churn baselines on every
|
|
8
|
+
* unrelated edit. The strategy is stamped WORKER-SIDE when the envelope is built
|
|
9
|
+
* (the host ratchet only reads `signal.fingerprint`; `synthesizeExternalTool`
|
|
10
|
+
* drops `fingerprintStrategy`, so the host never reads it off the synthetic Tool).
|
|
11
|
+
*
|
|
12
|
+
* Byte-identical hash shape to fitness's `message-hash`; a distinct id keeps the
|
|
13
|
+
* adapter family's baseline meta self-describing (ADR-0075).
|
|
14
|
+
*/
|
|
15
|
+
import type { FingerprintStrategyChoice } from './types.js';
|
|
16
|
+
import type { FingerprintStrategy } from '@opensip-cli/core';
|
|
17
|
+
/** `sha256(filePath\nruleId\nmessage)` — the adapter default (line-shift tolerant). */
|
|
18
|
+
export declare const messageHashFingerprintStrategy: FingerprintStrategy;
|
|
19
|
+
/**
|
|
20
|
+
* Resolve a {@link FingerprintStrategyChoice} to a concrete `FingerprintStrategy`.
|
|
21
|
+
* `'message-hash'` (default) → {@link messageHashFingerprintStrategy};
|
|
22
|
+
* `'rule-location'` → the host default (`ruleId|filePath|line|col`), for the rare
|
|
23
|
+
* scanner with stable line anchors.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveFingerprintStrategy(choice: FingerprintStrategyChoice | undefined): FingerprintStrategy;
|
|
26
|
+
//# sourceMappingURL=fingerprint.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.d.ts","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAC5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,uFAAuF;AACvF,eAAO,MAAM,8BAA8B,EAAE,mBAK3C,CAAC;AAEH;;;;;GAKG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,yBAAyB,GAAG,SAAS,GAC5C,mBAAmB,CAErB"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The adapter fingerprint strategy map (ADR-0091 §4.5).
|
|
3
|
+
*
|
|
4
|
+
* Scanner output is line-volatile (dependency manifests and IaC files shift line
|
|
5
|
+
* numbers constantly), so the adapter DEFAULT is `message-hash`
|
|
6
|
+
* (`sha256(filePath\nruleId\nmessage)`) — line-shift tolerant — not the host
|
|
7
|
+
* default (`ruleId|filePath|line|col`), which would churn baselines on every
|
|
8
|
+
* unrelated edit. The strategy is stamped WORKER-SIDE when the envelope is built
|
|
9
|
+
* (the host ratchet only reads `signal.fingerprint`; `synthesizeExternalTool`
|
|
10
|
+
* drops `fingerprintStrategy`, so the host never reads it off the synthetic Tool).
|
|
11
|
+
*
|
|
12
|
+
* Byte-identical hash shape to fitness's `message-hash`; a distinct id keeps the
|
|
13
|
+
* adapter family's baseline meta self-describing (ADR-0075).
|
|
14
|
+
*/
|
|
15
|
+
import { createHash } from 'node:crypto';
|
|
16
|
+
import { defaultFingerprintStrategy, defineFingerprintStrategy } from '@opensip-cli/core';
|
|
17
|
+
/** `sha256(filePath\nruleId\nmessage)` — the adapter default (line-shift tolerant). */
|
|
18
|
+
export const messageHashFingerprintStrategy = defineFingerprintStrategy({
|
|
19
|
+
id: 'external-tool-adapter.sha256-file-rule-message',
|
|
20
|
+
version: 1,
|
|
21
|
+
fingerprint: (s) => createHash('sha256').update(`${s.filePath}\n${s.ruleId}\n${s.message}`).digest('hex'),
|
|
22
|
+
});
|
|
23
|
+
/**
|
|
24
|
+
* Resolve a {@link FingerprintStrategyChoice} to a concrete `FingerprintStrategy`.
|
|
25
|
+
* `'message-hash'` (default) → {@link messageHashFingerprintStrategy};
|
|
26
|
+
* `'rule-location'` → the host default (`ruleId|filePath|line|col`), for the rare
|
|
27
|
+
* scanner with stable line anchors.
|
|
28
|
+
*/
|
|
29
|
+
export function resolveFingerprintStrategy(choice) {
|
|
30
|
+
return choice === 'rule-location' ? defaultFingerprintStrategy : messageHashFingerprintStrategy;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=fingerprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../src/fingerprint.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,OAAO,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAK1F,uFAAuF;AACvF,MAAM,CAAC,MAAM,8BAA8B,GAAwB,yBAAyB,CAAC;IAC3F,EAAE,EAAE,gDAAgD;IACpD,OAAO,EAAE,CAAC;IACV,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CACjB,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;CACxF,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CACxC,MAA6C;IAE7C,OAAO,MAAM,KAAK,eAAe,CAAC,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,8BAA8B,CAAC;AAClG,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pure gate-ratchet presentation for the scan loop (ADR-0036).
|
|
3
|
+
*
|
|
4
|
+
* The substrate inherits the host baseline/ratchet plane verbatim (the four
|
|
5
|
+
* `ToolCliContext` baseline seams over `signal.fingerprint`); these helpers
|
|
6
|
+
* render the `gate-done` presentation lines for `--gate-save` (baseline written)
|
|
7
|
+
* and `--gate-compare` (the added/resolved/unchanged diff + verdict). They are
|
|
8
|
+
* the adapter-family equivalent of fitness's `gate-compare-render` — a separate
|
|
9
|
+
* pure module so the run loop (the IO-excluded orchestration) stays thin and the
|
|
10
|
+
* rendering is unit-covered. No `cli`/IO here: input is the `GateCompareResult`
|
|
11
|
+
* the host compare seam returns; output is plain `string[]` for `cli.render`.
|
|
12
|
+
*/
|
|
13
|
+
import type { GateCompareResult } from '@opensip-cli/core';
|
|
14
|
+
/** The `gate-save` lines: baseline captured into the project store. */
|
|
15
|
+
export declare function renderGateSaveLines(tool: string, signalCount: number): string[];
|
|
16
|
+
/** The full `gate-compare` presentation lines for a {@link GateCompareResult}. */
|
|
17
|
+
export declare function renderGateCompareLines(tool: string, result: GateCompareResult): string[];
|
|
18
|
+
//# sourceMappingURL=gate-render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-render.d.ts","sourceRoot":"","sources":["../src/gate-render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,uEAAuE;AACvE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAE/E;AAED,kFAAkF;AAClF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAKxF"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Pure gate-ratchet presentation for the scan loop (ADR-0036).
|
|
3
|
+
*
|
|
4
|
+
* The substrate inherits the host baseline/ratchet plane verbatim (the four
|
|
5
|
+
* `ToolCliContext` baseline seams over `signal.fingerprint`); these helpers
|
|
6
|
+
* render the `gate-done` presentation lines for `--gate-save` (baseline written)
|
|
7
|
+
* and `--gate-compare` (the added/resolved/unchanged diff + verdict). They are
|
|
8
|
+
* the adapter-family equivalent of fitness's `gate-compare-render` — a separate
|
|
9
|
+
* pure module so the run loop (the IO-excluded orchestration) stays thin and the
|
|
10
|
+
* rendering is unit-covered. No `cli`/IO here: input is the `GateCompareResult`
|
|
11
|
+
* the host compare seam returns; output is plain `string[]` for `cli.render`.
|
|
12
|
+
*/
|
|
13
|
+
import { renderGateCompareLines as renderCoreGateCompareLines } from '@opensip-cli/core';
|
|
14
|
+
/** The `gate-save` lines: baseline captured into the project store. */
|
|
15
|
+
export function renderGateSaveLines(tool, signalCount) {
|
|
16
|
+
return [`${tool}: baseline saved (project SQLite store)`, ` ${signalCount} finding(s) recorded`];
|
|
17
|
+
}
|
|
18
|
+
/** The full `gate-compare` presentation lines for a {@link GateCompareResult}. */
|
|
19
|
+
export function renderGateCompareLines(tool, result) {
|
|
20
|
+
return renderCoreGateCompareLines(result, {
|
|
21
|
+
title: `${tool} gate compare`,
|
|
22
|
+
singularNoun: 'finding',
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=gate-render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gate-render.js","sourceRoot":"","sources":["../src/gate-render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,sBAAsB,IAAI,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAIzF,uEAAuE;AACvE,MAAM,UAAU,mBAAmB,CAAC,IAAY,EAAE,WAAmB;IACnE,OAAO,CAAC,GAAG,IAAI,yCAAyC,EAAE,KAAK,WAAW,sBAAsB,CAAC,CAAC;AACpG,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,sBAAsB,CAAC,IAAY,EAAE,MAAyB;IAC5E,OAAO,0BAA0B,CAAC,MAAM,EAAE;QACxC,KAAK,EAAE,GAAG,IAAI,eAAe;QAC7B,YAAY,EAAE,SAAS;KACxB,CAAC,CAAC;AACL,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @opensip-cli/external-tool-adapter — substrate for External Tool Adapters.
|
|
3
|
+
*
|
|
4
|
+
* Wrap a user-installed CLI scanner (gitleaks/osv-scanner/trivy/…) as an ordinary
|
|
5
|
+
* opensip-cli `Tool`: `defineExternalToolAdapter(spec)`. The substrate owns binary
|
|
6
|
+
* resolution, the run loop (resolve → execFile → ingest → normalize → persist via
|
|
7
|
+
* the host artifact seam), the shared SARIF/JSON ingest + severity mapping, the
|
|
8
|
+
* `doctor`/`version` commands, secret redaction, and provenance. ADR-0090/0091/0092.
|
|
9
|
+
*/
|
|
10
|
+
export { defineExternalToolAdapter } from './define-external-tool-adapter.js';
|
|
11
|
+
export type { AdapterProvenance, AdapterRunContext, BinaryResolutionLayer, BinarySpec, ExternalCommandSpec, ExternalToolAdapterSpec, FingerprintStrategyChoice, ManifestCommandShell, NetworkPosture, ParsedScannerOutput, ResolvedBinary, ScannerExitModel, ScannerOutputKind, } from './types.js';
|
|
12
|
+
export { ingestSarif } from './ingest-sarif.js';
|
|
13
|
+
export type { IngestSarifOptions, SarifDriver, SarifLocation, SarifLog, SarifMessage, SarifPhysicalLocation, SarifReportingDescriptor, SarifResult, SarifRun, SarifTool, } from './ingest-sarif.js';
|
|
14
|
+
export { asArray, asObject, getNumber, getString, navigate, safeParseJson } from './ingest-json.js';
|
|
15
|
+
export type { JsonParseResult } from './ingest-json.js';
|
|
16
|
+
export { cvssToSeverity, parseCvss, sarifLevelToSeverity, withNativeSeverity, } from './severity-map.js';
|
|
17
|
+
export type { SarifLevel } from './severity-map.js';
|
|
18
|
+
export { DEFAULT_EXIT_MODEL, interpretExit } from './exit-model.js';
|
|
19
|
+
export type { ExitVerdict } from './exit-model.js';
|
|
20
|
+
export { defaultBinaryEnvVar, resolveBinary } from './binary-resolver.js';
|
|
21
|
+
export type { BinaryResolution, BinaryResolveDeps, ResolveBinaryInput } from './binary-resolver.js';
|
|
22
|
+
export { messageHashFingerprintStrategy, resolveFingerprintStrategy } from './fingerprint.js';
|
|
23
|
+
export { stampProvenance, stampProvenanceAll } from './provenance.js';
|
|
24
|
+
export { redactSecret, secretHash } from './redact.js';
|
|
25
|
+
export { buildAdapterSessionPayload } from './session-payload.js';
|
|
26
|
+
export type { AdapterFindingSeverity, AdapterSessionCheck, AdapterSessionFinding, AdapterSessionPayload, } from './session-payload.js';
|
|
27
|
+
export { resolveScannerArtifactPath } from './artifact-path.js';
|
|
28
|
+
export type { ArtifactPathScope } from './artifact-path.js';
|
|
29
|
+
export { deriveAdapterManifestCommands } from './manifest-commands.js';
|
|
30
|
+
export { adapterConfigManifestOf, adapterNetworkOf, deriveAdapterConfigManifest, deriveAdapterManifestRequires, } from './adapter-manifest.js';
|
|
31
|
+
export type { AdapterToolMarkers } from './adapter-manifest.js';
|
|
32
|
+
export { defaultAdapterConfig, defaultAdapterConfigManifest, defaultAdapterConfigSchema, } from './adapter-config.js';
|
|
33
|
+
export type { AdapterConfigContribution } from './adapter-config.js';
|
|
34
|
+
export { compareVersion } from './doctor-command.js';
|
|
35
|
+
export type { AdapterDoctorReport, VersionStatus } from './doctor-command.js';
|
|
36
|
+
export type { AdapterVersionReport } from './version-command.js';
|
|
37
|
+
export { normalizedSignalShape, runAcceptanceCase } from './acceptance-harness.js';
|
|
38
|
+
export type { AcceptanceFixture, AcceptanceResult, SignalShape } from './acceptance-harness.js';
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,YAAY,EACV,iBAAiB,EACjB,iBAAiB,EACjB,qBAAqB,EACrB,UAAU,EACV,mBAAmB,EACnB,uBAAuB,EACvB,yBAAyB,EACzB,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EACV,kBAAkB,EAClB,WAAW,EACX,aAAa,EACb,QAAQ,EACR,YAAY,EACZ,qBAAqB,EACrB,wBAAwB,EACxB,WAAW,EACX,QAAQ,EACR,SAAS,GACV,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACpG,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,EACL,cAAc,EACd,SAAS,EACT,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACpE,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAGnD,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC1E,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACpG,OAAO,EAAE,8BAA8B,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9F,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAClE,YAAY,EACV,sBAAsB,EACtB,mBAAmB,EACnB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAChE,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAGhE,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAGrE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,YAAY,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC9E,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAGjE,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACnF,YAAY,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @opensip-cli/external-tool-adapter — substrate for External Tool Adapters.
|
|
3
|
+
*
|
|
4
|
+
* Wrap a user-installed CLI scanner (gitleaks/osv-scanner/trivy/…) as an ordinary
|
|
5
|
+
* opensip-cli `Tool`: `defineExternalToolAdapter(spec)`. The substrate owns binary
|
|
6
|
+
* resolution, the run loop (resolve → execFile → ingest → normalize → persist via
|
|
7
|
+
* the host artifact seam), the shared SARIF/JSON ingest + severity mapping, the
|
|
8
|
+
* `doctor`/`version` commands, secret redaction, and provenance. ADR-0090/0091/0092.
|
|
9
|
+
*/
|
|
10
|
+
// ── The factory + author surface ────────────────────────────────────────────
|
|
11
|
+
export { defineExternalToolAdapter } from './define-external-tool-adapter.js';
|
|
12
|
+
// ── Ingest + normalization ──────────────────────────────────────────────────
|
|
13
|
+
export { ingestSarif } from './ingest-sarif.js';
|
|
14
|
+
export { asArray, asObject, getNumber, getString, navigate, safeParseJson } from './ingest-json.js';
|
|
15
|
+
export { cvssToSeverity, parseCvss, sarifLevelToSeverity, withNativeSeverity, } from './severity-map.js';
|
|
16
|
+
// ── Exit modeling ───────────────────────────────────────────────────────────
|
|
17
|
+
export { DEFAULT_EXIT_MODEL, interpretExit } from './exit-model.js';
|
|
18
|
+
// ── Binary resolution + provenance + fingerprints ───────────────────────────
|
|
19
|
+
export { defaultBinaryEnvVar, resolveBinary } from './binary-resolver.js';
|
|
20
|
+
export { messageHashFingerprintStrategy, resolveFingerprintStrategy } from './fingerprint.js';
|
|
21
|
+
export { stampProvenance, stampProvenanceAll } from './provenance.js';
|
|
22
|
+
export { redactSecret, secretHash } from './redact.js';
|
|
23
|
+
// ── Session payload (tool-owned, dashboard-shaped detail) ────────────────────
|
|
24
|
+
export { buildAdapterSessionPayload } from './session-payload.js';
|
|
25
|
+
// ── Artifact path + manifest parity ─────────────────────────────────────────
|
|
26
|
+
export { resolveScannerArtifactPath } from './artifact-path.js';
|
|
27
|
+
export { deriveAdapterManifestCommands } from './manifest-commands.js';
|
|
28
|
+
export { adapterConfigManifestOf, adapterNetworkOf, deriveAdapterConfigManifest, deriveAdapterManifestRequires, } from './adapter-manifest.js';
|
|
29
|
+
// ── Config namespace claim (binary pin + verdict keys) ───────────────────────
|
|
30
|
+
export { defaultAdapterConfig, defaultAdapterConfigManifest, defaultAdapterConfigSchema, } from './adapter-config.js';
|
|
31
|
+
// ── doctor / version reports ────────────────────────────────────────────────
|
|
32
|
+
export { compareVersion } from './doctor-command.js';
|
|
33
|
+
// ── Acceptance harness ──────────────────────────────────────────────────────
|
|
34
|
+
export { normalizedSignalShape, runAcceptanceCase } from './acceptance-harness.js';
|
|
35
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,+EAA+E;AAC/E,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAiB9E,+EAA+E;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAahD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEpG,OAAO,EACL,cAAc,EACd,SAAS,EACT,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAG3B,+EAA+E;AAC/E,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGpE,+EAA+E;AAC/E,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAE,8BAA8B,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAC9F,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEvD,gFAAgF;AAChF,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAQlE,+EAA+E;AAC/E,OAAO,EAAE,0BAA0B,EAAE,MAAM,oBAAoB,CAAC;AAEhE,OAAO,EAAE,6BAA6B,EAAE,MAAM,wBAAwB,CAAC;AACvE,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,2BAA2B,EAC3B,6BAA6B,GAC9B,MAAM,uBAAuB,CAAC;AAG/B,gFAAgF;AAChF,OAAO,EACL,oBAAoB,EACpB,4BAA4B,EAC5B,0BAA0B,GAC3B,MAAM,qBAAqB,CAAC;AAG7B,+EAA+E;AAC/E,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAIrD,+EAA+E;AAC/E,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Small reusable, defensive JSON navigation helpers (ADR-0091).
|
|
3
|
+
*
|
|
4
|
+
* The per-scanner JSON `parse` lives in each adapter (each scanner's JSON shape
|
|
5
|
+
* differs); these are the shared, total accessors a parser uses to walk a
|
|
6
|
+
* foreign, possibly-malformed document without throwing. All pure.
|
|
7
|
+
*/
|
|
8
|
+
/** The result of a defensive JSON parse — never throws. */
|
|
9
|
+
export type JsonParseResult = {
|
|
10
|
+
readonly ok: true;
|
|
11
|
+
readonly value: unknown;
|
|
12
|
+
} | {
|
|
13
|
+
readonly ok: false;
|
|
14
|
+
readonly error: string;
|
|
15
|
+
};
|
|
16
|
+
/** Parse JSON, returning a Result instead of throwing on malformed input. */
|
|
17
|
+
export declare function safeParseJson(raw: string): JsonParseResult;
|
|
18
|
+
/** Narrow to a plain object (not an array, not null), else `undefined`. */
|
|
19
|
+
export declare function asObject(value: unknown): Record<string, unknown> | undefined;
|
|
20
|
+
/** Narrow to an array, else `undefined`. */
|
|
21
|
+
export declare function asArray(value: unknown): readonly unknown[] | undefined;
|
|
22
|
+
/** Read a string property, else `undefined`. */
|
|
23
|
+
export declare function getString(obj: unknown, key: string): string | undefined;
|
|
24
|
+
/** Read a finite-number property (coercing a numeric string), else `undefined`. */
|
|
25
|
+
export declare function getNumber(obj: unknown, key: string): number | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* Walk a dotted-ish path of object keys (`navigate(doc, ['results', '0', 'id'])`),
|
|
28
|
+
* descending objects and arrays (numeric segments index arrays). Returns
|
|
29
|
+
* `undefined` on the first missing/typed-wrong step — never throws.
|
|
30
|
+
*/
|
|
31
|
+
export declare function navigate(root: unknown, path: readonly string[]): unknown;
|
|
32
|
+
//# sourceMappingURL=ingest-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest-json.d.ts","sourceRoot":"","sources":["../src/ingest-json.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,2DAA2D;AAC3D,MAAM,MAAM,eAAe,GACvB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAC9C;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,6EAA6E;AAC7E,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAM1D;AAED,2EAA2E;AAC3E,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAI5E;AAED,4CAA4C;AAC5C,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,OAAO,EAAE,GAAG,SAAS,CAEtE;AAED,gDAAgD;AAChD,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIvE;AAED,mFAAmF;AACnF,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CASvE;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAaxE"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Small reusable, defensive JSON navigation helpers (ADR-0091).
|
|
3
|
+
*
|
|
4
|
+
* The per-scanner JSON `parse` lives in each adapter (each scanner's JSON shape
|
|
5
|
+
* differs); these are the shared, total accessors a parser uses to walk a
|
|
6
|
+
* foreign, possibly-malformed document without throwing. All pure.
|
|
7
|
+
*/
|
|
8
|
+
/** Parse JSON, returning a Result instead of throwing on malformed input. */
|
|
9
|
+
export function safeParseJson(raw) {
|
|
10
|
+
try {
|
|
11
|
+
return { ok: true, value: JSON.parse(raw) };
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
return { ok: false, error: error instanceof Error ? error.message : String(error) };
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/** Narrow to a plain object (not an array, not null), else `undefined`. */
|
|
18
|
+
export function asObject(value) {
|
|
19
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
20
|
+
? value
|
|
21
|
+
: undefined;
|
|
22
|
+
}
|
|
23
|
+
/** Narrow to an array, else `undefined`. */
|
|
24
|
+
export function asArray(value) {
|
|
25
|
+
return Array.isArray(value) ? value : undefined;
|
|
26
|
+
}
|
|
27
|
+
/** Read a string property, else `undefined`. */
|
|
28
|
+
export function getString(obj, key) {
|
|
29
|
+
const record = asObject(obj);
|
|
30
|
+
const value = record?.[key];
|
|
31
|
+
return typeof value === 'string' ? value : undefined;
|
|
32
|
+
}
|
|
33
|
+
/** Read a finite-number property (coercing a numeric string), else `undefined`. */
|
|
34
|
+
export function getNumber(obj, key) {
|
|
35
|
+
const record = asObject(obj);
|
|
36
|
+
const value = record?.[key];
|
|
37
|
+
if (typeof value === 'number')
|
|
38
|
+
return Number.isFinite(value) ? value : undefined;
|
|
39
|
+
if (typeof value === 'string') {
|
|
40
|
+
const parsed = Number.parseFloat(value);
|
|
41
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Walk a dotted-ish path of object keys (`navigate(doc, ['results', '0', 'id'])`),
|
|
47
|
+
* descending objects and arrays (numeric segments index arrays). Returns
|
|
48
|
+
* `undefined` on the first missing/typed-wrong step — never throws.
|
|
49
|
+
*/
|
|
50
|
+
export function navigate(root, path) {
|
|
51
|
+
let current = root;
|
|
52
|
+
for (const segment of path) {
|
|
53
|
+
if (current === null || current === undefined)
|
|
54
|
+
return undefined;
|
|
55
|
+
if (Array.isArray(current)) {
|
|
56
|
+
const index = Number.parseInt(segment, 10);
|
|
57
|
+
current = Number.isInteger(index) ? current[index] : undefined;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
const record = asObject(current);
|
|
61
|
+
current = record?.[segment];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return current;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=ingest-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest-json.js","sourceRoot":"","sources":["../src/ingest-json.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,6EAA6E;AAC7E,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAY,EAAE,CAAC;IACzD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC;IACtF,CAAC;AACH,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QACzE,CAAC,CAAE,KAAiC;QACpC,CAAC,CAAC,SAAS,CAAC;AAChB,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,OAAO,CAAC,KAAc;IACpC,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,KAA4B,CAAC,CAAC,CAAC,SAAS,CAAC;AAC1E,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,SAAS,CAAC,GAAY,EAAE,GAAW;IACjD,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvD,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,SAAS,CAAC,GAAY,EAAE,GAAW;IACjD,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC7B,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;IAC5B,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACjF,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACxC,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IACtD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CAAC,IAAa,EAAE,IAAuB;IAC7D,IAAI,OAAO,GAAY,IAAI,CAAC;IAC5B,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;QAC3B,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAChE,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;YAC3B,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC3C,OAAO,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACjE,CAAC;aAAM,CAAC;YACN,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC;YACjC,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview The single, substrate-LOCAL SARIF ingest (ADR-0091).
|
|
3
|
+
*
|
|
4
|
+
* This is the ONLY SARIF read/parse path in the workspace (enforced by the
|
|
5
|
+
* `single-sarif-ingest` dependency-cruiser rule). The OpenSIP SARIF *writer*'s
|
|
6
|
+
* shape types are file-private to `@opensip-cli/output` (a layer-3 peer the
|
|
7
|
+
* substrate may not import) and deliberately minimal — so a foreign-scanner
|
|
8
|
+
* ingest defines its OWN defensive INPUT types here: it must read
|
|
9
|
+
* `result.fingerprints`/`partialFingerprints`/`guid`, `properties`, multiple
|
|
10
|
+
* `runs`/`locations`, `ruleIndex`→`rules` joins, and
|
|
11
|
+
* `properties["security-severity"]`.
|
|
12
|
+
*
|
|
13
|
+
* Severity recovery is the core job: the writer collapses BOTH `critical` and
|
|
14
|
+
* `high` → SARIF `error`, so a level-only inverse is ambiguous. `ingestSarif`
|
|
15
|
+
* reads the CVSS `security-severity` number (off the rule descriptor, falling
|
|
16
|
+
* back to the result) and applies the FIRST/NVD v3 bands BEFORE falling back to
|
|
17
|
+
* `level`. The native level/severity are preserved on `Signal.metadata`.
|
|
18
|
+
*
|
|
19
|
+
* Message stability is the second job: real scanners (Trivy) put a VERBOSE,
|
|
20
|
+
* version-volatile block in `result.message.text` (e.g. a `Package:/Installed
|
|
21
|
+
* Version:/Severity:/Fixed Version:/Link:` listing). Surfacing that as
|
|
22
|
+
* `Signal.message` would also feed it into the `message-hash` fingerprint, so the
|
|
23
|
+
* baseline would churn on every dependency bump — defeating the whole point of a
|
|
24
|
+
* line-shift-tolerant hash. So `ingestSarif` prefers the STABLE rule title
|
|
25
|
+
* (`driver.rules[ruleIndex].shortDescription.text`) for `Signal.message` when
|
|
26
|
+
* present and stashes the verbose `result.message.text` on `metadata.detail`. It
|
|
27
|
+
* falls back to `result.message.text` only when no rule/shortDescription exists.
|
|
28
|
+
*/
|
|
29
|
+
import type { Signal } from '@opensip-cli/core';
|
|
30
|
+
/** A SARIF 2.1.0 log: the top-level document a foreign scanner emits (one or more runs). */
|
|
31
|
+
export interface SarifLog {
|
|
32
|
+
readonly version?: string;
|
|
33
|
+
readonly $schema?: string;
|
|
34
|
+
readonly runs?: readonly SarifRun[];
|
|
35
|
+
}
|
|
36
|
+
/** One analysis run within a {@link SarifLog} — a tool plus its results. */
|
|
37
|
+
export interface SarifRun {
|
|
38
|
+
readonly tool?: SarifTool;
|
|
39
|
+
readonly results?: readonly SarifResult[];
|
|
40
|
+
}
|
|
41
|
+
/** The tool component of a {@link SarifRun}; carries the `driver` (the scanner). */
|
|
42
|
+
export interface SarifTool {
|
|
43
|
+
readonly driver?: SarifDriver;
|
|
44
|
+
}
|
|
45
|
+
/** The scanner driver: its identity and the rule catalog `result.ruleIndex` joins against. */
|
|
46
|
+
export interface SarifDriver {
|
|
47
|
+
readonly name?: string;
|
|
48
|
+
readonly version?: string;
|
|
49
|
+
readonly informationUri?: string;
|
|
50
|
+
readonly rules?: readonly SarifReportingDescriptor[];
|
|
51
|
+
}
|
|
52
|
+
/** A rule descriptor in `driver.rules[]` — `properties["security-severity"]` carries the CVSS. */
|
|
53
|
+
export interface SarifReportingDescriptor {
|
|
54
|
+
readonly id?: string;
|
|
55
|
+
readonly name?: string;
|
|
56
|
+
readonly shortDescription?: SarifMessage;
|
|
57
|
+
readonly fullDescription?: SarifMessage;
|
|
58
|
+
readonly helpUri?: string;
|
|
59
|
+
readonly defaultConfiguration?: {
|
|
60
|
+
readonly level?: string;
|
|
61
|
+
};
|
|
62
|
+
readonly properties?: Readonly<Record<string, unknown>>;
|
|
63
|
+
}
|
|
64
|
+
/** A single finding: rule id/index, coarse `level`, message, locations, and native fingerprints. */
|
|
65
|
+
export interface SarifResult {
|
|
66
|
+
readonly ruleId?: string;
|
|
67
|
+
readonly ruleIndex?: number;
|
|
68
|
+
readonly level?: string;
|
|
69
|
+
readonly message?: SarifMessage;
|
|
70
|
+
readonly locations?: readonly SarifLocation[];
|
|
71
|
+
readonly fingerprints?: Readonly<Record<string, unknown>>;
|
|
72
|
+
readonly partialFingerprints?: Readonly<Record<string, unknown>>;
|
|
73
|
+
readonly guid?: string;
|
|
74
|
+
readonly helpUri?: string;
|
|
75
|
+
readonly properties?: Readonly<Record<string, unknown>>;
|
|
76
|
+
}
|
|
77
|
+
/** A result location — wraps the {@link SarifPhysicalLocation} (file + region). */
|
|
78
|
+
export interface SarifLocation {
|
|
79
|
+
readonly physicalLocation?: SarifPhysicalLocation;
|
|
80
|
+
}
|
|
81
|
+
/** The physical location of a finding: an artifact (file) URI and an optional source region. */
|
|
82
|
+
export interface SarifPhysicalLocation {
|
|
83
|
+
readonly artifactLocation?: {
|
|
84
|
+
readonly uri?: string;
|
|
85
|
+
readonly uriBaseId?: string;
|
|
86
|
+
};
|
|
87
|
+
readonly region?: {
|
|
88
|
+
readonly startLine?: number;
|
|
89
|
+
readonly startColumn?: number;
|
|
90
|
+
readonly endLine?: number;
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/** A SARIF message object — the `text` is the human-readable finding description. */
|
|
94
|
+
export interface SarifMessage {
|
|
95
|
+
readonly text?: string;
|
|
96
|
+
}
|
|
97
|
+
/** Options for {@link ingestSarif}. */
|
|
98
|
+
export interface IngestSarifOptions {
|
|
99
|
+
/** `Signal.source` for every produced signal (defaults to the driver name, lowercased, or `'sarif'`). */
|
|
100
|
+
readonly source?: string;
|
|
101
|
+
/** `Signal.category` (defaults to `'security'` — these are security scanners). */
|
|
102
|
+
readonly category?: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Ingest a SARIF 2.1.0 log into normalized {@link Signal}s. Defensive over
|
|
106
|
+
* foreign output: tolerates multiple runs, missing rules/locations, and
|
|
107
|
+
* `ruleIndex` joins. Severity is recovered from CVSS `security-severity` before
|
|
108
|
+
* `level` (ADR-0091); native fingerprints/level/severity are preserved on
|
|
109
|
+
* `metadata`. `Signal.fingerprint` is left unstamped — the host ratchet's
|
|
110
|
+
* `message-hash` strategy stamps it worker-side at envelope construction.
|
|
111
|
+
*/
|
|
112
|
+
export declare function ingestSarif(sarif: SarifLog, options?: IngestSarifOptions): readonly Signal[];
|
|
113
|
+
//# sourceMappingURL=ingest-sarif.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ingest-sarif.d.ts","sourceRoot":"","sources":["../src/ingest-sarif.ts"],"names":[],"mappings":"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"}
|