@gate-forge/core 0.1.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/LICENSE +202 -0
- package/dist/baselines/adoption.d.ts +76 -0
- package/dist/baselines/adoption.d.ts.map +1 -0
- package/dist/baselines/adoption.js +163 -0
- package/dist/baselines/adoption.js.map +1 -0
- package/dist/baselines/index.d.ts +102 -0
- package/dist/baselines/index.d.ts.map +1 -0
- package/dist/baselines/index.js +186 -0
- package/dist/baselines/index.js.map +1 -0
- package/dist/canonical-json.d.ts +51 -0
- package/dist/canonical-json.d.ts.map +1 -0
- package/dist/canonical-json.js +112 -0
- package/dist/canonical-json.js.map +1 -0
- package/dist/classifier/bind.d.ts +64 -0
- package/dist/classifier/bind.d.ts.map +1 -0
- package/dist/classifier/bind.js +188 -0
- package/dist/classifier/bind.js.map +1 -0
- package/dist/classifier/classify.d.ts +154 -0
- package/dist/classifier/classify.d.ts.map +1 -0
- package/dist/classifier/classify.js +1207 -0
- package/dist/classifier/classify.js.map +1 -0
- package/dist/classifier/glob.d.ts +48 -0
- package/dist/classifier/glob.d.ts.map +1 -0
- package/dist/classifier/glob.js +104 -0
- package/dist/classifier/glob.js.map +1 -0
- package/dist/classifier/index.d.ts +10 -0
- package/dist/classifier/index.d.ts.map +1 -0
- package/dist/classifier/index.js +21 -0
- package/dist/classifier/index.js.map +1 -0
- package/dist/classifier/schema.d.ts +150 -0
- package/dist/classifier/schema.d.ts.map +1 -0
- package/dist/classifier/schema.js +139 -0
- package/dist/classifier/schema.js.map +1 -0
- package/dist/config/index.d.ts +259 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +523 -0
- package/dist/config/index.js.map +1 -0
- package/dist/fingerprints.d.ts +56 -0
- package/dist/fingerprints.d.ts.map +1 -0
- package/dist/fingerprints.js +59 -0
- package/dist/fingerprints.js.map +1 -0
- package/dist/graph/build.d.ts +16 -0
- package/dist/graph/build.d.ts.map +1 -0
- package/dist/graph/build.js +423 -0
- package/dist/graph/build.js.map +1 -0
- package/dist/graph/index.d.ts +12 -0
- package/dist/graph/index.d.ts.map +1 -0
- package/dist/graph/index.js +10 -0
- package/dist/graph/index.js.map +1 -0
- package/dist/graph/schema.d.ts +448 -0
- package/dist/graph/schema.d.ts.map +1 -0
- package/dist/graph/schema.js +237 -0
- package/dist/graph/schema.js.map +1 -0
- package/dist/graph/symbols.d.ts +129 -0
- package/dist/graph/symbols.d.ts.map +1 -0
- package/dist/graph/symbols.js +177 -0
- package/dist/graph/symbols.js.map +1 -0
- package/dist/graph/util.d.ts +40 -0
- package/dist/graph/util.d.ts.map +1 -0
- package/dist/graph/util.js +41 -0
- package/dist/graph/util.js.map +1 -0
- package/dist/index.d.ts +683 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +563 -0
- package/dist/index.js.map +1 -0
- package/dist/mapping/resolve.d.ts +177 -0
- package/dist/mapping/resolve.d.ts.map +1 -0
- package/dist/mapping/resolve.js +523 -0
- package/dist/mapping/resolve.js.map +1 -0
- package/dist/policy/coverage.d.ts +79 -0
- package/dist/policy/coverage.d.ts.map +1 -0
- package/dist/policy/coverage.js +119 -0
- package/dist/policy/coverage.js.map +1 -0
- package/dist/policy/evaluate.d.ts +275 -0
- package/dist/policy/evaluate.d.ts.map +1 -0
- package/dist/policy/evaluate.js +382 -0
- package/dist/policy/evaluate.js.map +1 -0
- package/dist/policy/index.d.ts +15 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/policy/index.js +14 -0
- package/dist/policy/index.js.map +1 -0
- package/dist/policy/trusted.d.ts +59 -0
- package/dist/policy/trusted.d.ts.map +1 -0
- package/dist/policy/trusted.js +96 -0
- package/dist/policy/trusted.js.map +1 -0
- package/dist/provenance.d.ts +170 -0
- package/dist/provenance.d.ts.map +1 -0
- package/dist/provenance.js +306 -0
- package/dist/provenance.js.map +1 -0
- package/dist/receipt/index.d.ts +74 -0
- package/dist/receipt/index.d.ts.map +1 -0
- package/dist/receipt/index.js +154 -0
- package/dist/receipt/index.js.map +1 -0
- package/dist/report/index.d.ts +100 -0
- package/dist/report/index.d.ts.map +1 -0
- package/dist/report/index.js +355 -0
- package/dist/report/index.js.map +1 -0
- package/dist/schemas/adoption.d.ts +40 -0
- package/dist/schemas/adoption.d.ts.map +1 -0
- package/dist/schemas/adoption.js +87 -0
- package/dist/schemas/adoption.js.map +1 -0
- package/dist/schemas/baseline.d.ts +19 -0
- package/dist/schemas/baseline.d.ts.map +1 -0
- package/dist/schemas/baseline.js +45 -0
- package/dist/schemas/baseline.js.map +1 -0
- package/dist/schemas/claim.d.ts +32 -0
- package/dist/schemas/claim.d.ts.map +1 -0
- package/dist/schemas/claim.js +34 -0
- package/dist/schemas/claim.js.map +1 -0
- package/dist/schemas/classification-policy.d.ts +84 -0
- package/dist/schemas/classification-policy.d.ts.map +1 -0
- package/dist/schemas/classification-policy.js +130 -0
- package/dist/schemas/classification-policy.js.map +1 -0
- package/dist/schemas/classification-signal.d.ts +125 -0
- package/dist/schemas/classification-signal.d.ts.map +1 -0
- package/dist/schemas/classification-signal.js +126 -0
- package/dist/schemas/classification-signal.js.map +1 -0
- package/dist/schemas/classification.d.ts +120 -0
- package/dist/schemas/classification.d.ts.map +1 -0
- package/dist/schemas/classification.js +154 -0
- package/dist/schemas/classification.js.map +1 -0
- package/dist/schemas/common.d.ts +73 -0
- package/dist/schemas/common.d.ts.map +1 -0
- package/dist/schemas/common.js +60 -0
- package/dist/schemas/common.js.map +1 -0
- package/dist/schemas/coverage-policy.d.ts +89 -0
- package/dist/schemas/coverage-policy.d.ts.map +1 -0
- package/dist/schemas/coverage-policy.js +81 -0
- package/dist/schemas/coverage-policy.js.map +1 -0
- package/dist/schemas/evidence.d.ts +65 -0
- package/dist/schemas/evidence.d.ts.map +1 -0
- package/dist/schemas/evidence.js +64 -0
- package/dist/schemas/evidence.js.map +1 -0
- package/dist/schemas/execution-result.d.ts +214 -0
- package/dist/schemas/execution-result.d.ts.map +1 -0
- package/dist/schemas/execution-result.js +240 -0
- package/dist/schemas/execution-result.js.map +1 -0
- package/dist/schemas/gate-receipt.d.ts +86 -0
- package/dist/schemas/gate-receipt.d.ts.map +1 -0
- package/dist/schemas/gate-receipt.js +193 -0
- package/dist/schemas/gate-receipt.js.map +1 -0
- package/dist/schemas/index.d.ts +22 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +22 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/obligation.d.ts +37 -0
- package/dist/schemas/obligation.d.ts.map +1 -0
- package/dist/schemas/obligation.js +46 -0
- package/dist/schemas/obligation.js.map +1 -0
- package/dist/schemas/plugin.d.ts +19 -0
- package/dist/schemas/plugin.d.ts.map +1 -0
- package/dist/schemas/plugin.js +20 -0
- package/dist/schemas/plugin.js.map +1 -0
- package/dist/schemas/policy.d.ts +73 -0
- package/dist/schemas/policy.d.ts.map +1 -0
- package/dist/schemas/policy.js +46 -0
- package/dist/schemas/policy.js.map +1 -0
- package/dist/schemas/resource.d.ts +26 -0
- package/dist/schemas/resource.d.ts.map +1 -0
- package/dist/schemas/resource.js +29 -0
- package/dist/schemas/resource.js.map +1 -0
- package/dist/schemas/run-manifest.d.ts +72 -0
- package/dist/schemas/run-manifest.d.ts.map +1 -0
- package/dist/schemas/run-manifest.js +125 -0
- package/dist/schemas/run-manifest.js.map +1 -0
- package/dist/schemas/runner-adapter.d.ts +169 -0
- package/dist/schemas/runner-adapter.d.ts.map +1 -0
- package/dist/schemas/runner-adapter.js +2 -0
- package/dist/schemas/runner-adapter.js.map +1 -0
- package/dist/schemas/test-catalog.d.ts +472 -0
- package/dist/schemas/test-catalog.d.ts.map +1 -0
- package/dist/schemas/test-catalog.js +311 -0
- package/dist/schemas/test-catalog.js.map +1 -0
- package/dist/schemas/test-map.d.ts +99 -0
- package/dist/schemas/test-map.d.ts.map +1 -0
- package/dist/schemas/test-map.js +103 -0
- package/dist/schemas/test-map.js.map +1 -0
- package/dist/schemas/verdict.d.ts +73 -0
- package/dist/schemas/verdict.d.ts.map +1 -0
- package/dist/schemas/verdict.js +92 -0
- package/dist/schemas/verdict.js.map +1 -0
- package/dist/schemas/waiver.d.ts +36 -0
- package/dist/schemas/waiver.d.ts.map +1 -0
- package/dist/schemas/waiver.js +42 -0
- package/dist/schemas/waiver.js.map +1 -0
- package/dist/supervision/index.d.ts +170 -0
- package/dist/supervision/index.d.ts.map +1 -0
- package/dist/supervision/index.js +354 -0
- package/dist/supervision/index.js.map +1 -0
- package/dist/testing/clock.d.ts +50 -0
- package/dist/testing/clock.d.ts.map +1 -0
- package/dist/testing/clock.js +75 -0
- package/dist/testing/clock.js.map +1 -0
- package/dist/testing/env.d.ts +66 -0
- package/dist/testing/env.d.ts.map +1 -0
- package/dist/testing/env.js +106 -0
- package/dist/testing/env.js.map +1 -0
- package/dist/testing/gate-runner.d.ts +141 -0
- package/dist/testing/gate-runner.d.ts.map +1 -0
- package/dist/testing/gate-runner.js +173 -0
- package/dist/testing/gate-runner.js.map +1 -0
- package/dist/testing/gf19.d.ts +106 -0
- package/dist/testing/gf19.d.ts.map +1 -0
- package/dist/testing/gf19.js +282 -0
- package/dist/testing/gf19.js.map +1 -0
- package/dist/testing/index.d.ts +20 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +14 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/red-probe.d.ts +138 -0
- package/dist/testing/red-probe.d.ts.map +1 -0
- package/dist/testing/red-probe.js +251 -0
- package/dist/testing/red-probe.js.map +1 -0
- package/dist/testing/temp-repo.d.ts +126 -0
- package/dist/testing/temp-repo.d.ts.map +1 -0
- package/dist/testing/temp-repo.js +214 -0
- package/dist/testing/temp-repo.js.map +1 -0
- package/dist/verdict/cause.d.ts +99 -0
- package/dist/verdict/cause.d.ts.map +1 -0
- package/dist/verdict/cause.js +206 -0
- package/dist/verdict/cause.js.map +1 -0
- package/dist/verdict/evaluate.d.ts +135 -0
- package/dist/verdict/evaluate.d.ts.map +1 -0
- package/dist/verdict/evaluate.js +1513 -0
- package/dist/verdict/evaluate.js.map +1 -0
- package/dist/verdict/index.d.ts +21 -0
- package/dist/verdict/index.d.ts.map +1 -0
- package/dist/verdict/index.js +20 -0
- package/dist/verdict/index.js.map +1 -0
- package/dist/verdict/pack-verifiers.d.ts +97 -0
- package/dist/verdict/pack-verifiers.d.ts.map +1 -0
- package/dist/verdict/pack-verifiers.js +763 -0
- package/dist/verdict/pack-verifiers.js.map +1 -0
- package/dist/verdict/registry.d.ts +180 -0
- package/dist/verdict/registry.d.ts.map +1 -0
- package/dist/verdict/registry.js +67 -0
- package/dist/verdict/registry.js.map +1 -0
- package/dist/waivers/index.d.ts +103 -0
- package/dist/waivers/index.d.ts.map +1 -0
- package/dist/waivers/index.js +192 -0
- package/dist/waivers/index.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gate-receipt signing and verification (plan 2026-09-13 §5.1, ADR 0005
|
|
3
|
+
* D3, Phase 4). The receipt is signed by the SAME authority as witness
|
|
4
|
+
* records — the witness verifier key, HMAC-SHA256 over GF-canonical JSON —
|
|
5
|
+
* reusing the exact provenance primitives (`createHmac`, `canonicalJson`,
|
|
6
|
+
* constant-time compare). No second, weaker evidence system exists here:
|
|
7
|
+
* a receipt without a verifying MAC is rejected, and the MAC domain
|
|
8
|
+
* (`gateforge.receipt.v1`) is distinct from the ledger attestation domain,
|
|
9
|
+
* so neither envelope can ever verify as the other.
|
|
10
|
+
*
|
|
11
|
+
* Issuance rule (plan Phase 4 item 5): a receipt is minted ONLY after
|
|
12
|
+
* complete supervision success and evidence grading; verification is
|
|
13
|
+
* fail-closed — every structural or cryptographic problem is a typed
|
|
14
|
+
* rejection, never a partial pass.
|
|
15
|
+
*/
|
|
16
|
+
import { createHmac, timingSafeEqual } from 'node:crypto';
|
|
17
|
+
import { canonicalJson } from '../canonical-json.js';
|
|
18
|
+
import { GateReceiptSchema } from '../schemas/gate-receipt.js';
|
|
19
|
+
/** Domain tag binding receipt MACs to the gate-receipt envelope format. */
|
|
20
|
+
export const RECEIPT_DOMAIN = 'gateforge.receipt.v1';
|
|
21
|
+
/** The only receipt envelope version this code produces or honors. */
|
|
22
|
+
export const RECEIPT_VERSION = 1;
|
|
23
|
+
/** Shape a 64-char lowercase hex MAC must have. */
|
|
24
|
+
const MAC_PATTERN = /^[0-9a-f]{64}$/;
|
|
25
|
+
/**
|
|
26
|
+
* Computes the receipt MAC (ADR 0005 D3): HMAC-SHA256 over the GF-canonical
|
|
27
|
+
* JSON of `{domain: 'gateforge.receipt.v1', receiptVersion: 1, ...body}`
|
|
28
|
+
* keyed by the witness verifier key — the same secret the tested suite
|
|
29
|
+
* never receives for ledger attestations. The fixed domain tag prevents
|
|
30
|
+
* cross-format signature acceptance in BOTH directions: a v2 ledger MAC
|
|
31
|
+
* can never verify as a receipt, and a receipt MAC can never verify as a
|
|
32
|
+
* ledger attestation.
|
|
33
|
+
*
|
|
34
|
+
* Args:
|
|
35
|
+
* verifierKey: the witness verifier secret (non-empty).
|
|
36
|
+
* body: the unsigned receipt body.
|
|
37
|
+
*
|
|
38
|
+
* Returns:
|
|
39
|
+
* string: 64-char lowercase hex HMAC.
|
|
40
|
+
*
|
|
41
|
+
* Throws:
|
|
42
|
+
* TypeError: when the verifier key is empty.
|
|
43
|
+
*/
|
|
44
|
+
export function gateReceiptMac(verifierKey, body) {
|
|
45
|
+
if (typeof verifierKey !== 'string' || verifierKey.length === 0) {
|
|
46
|
+
throw new TypeError('gateReceiptMac: verifier key must be a non-empty string');
|
|
47
|
+
}
|
|
48
|
+
return createHmac('sha256', verifierKey)
|
|
49
|
+
.update(canonicalJson({
|
|
50
|
+
domain: RECEIPT_DOMAIN,
|
|
51
|
+
...body,
|
|
52
|
+
}))
|
|
53
|
+
.digest('hex');
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Verifies a receipt candidate end-to-end (fail closed):
|
|
57
|
+
* 1. structural — the value must parse against the strict v1 schema;
|
|
58
|
+
* 2. authenticity — the HMAC must verify over the exact body (a forged
|
|
59
|
+
* or tampered receipt is a `mac-fail`, never a downgrade);
|
|
60
|
+
* 3. binding — when an expected context is given, every supplied digest
|
|
61
|
+
* must equal the receipt's (mismatches are typed, per-field);
|
|
62
|
+
* 4. content — the sealed verdict summary must be clean (blocking 0).
|
|
63
|
+
* Adversary-controlled input never throws.
|
|
64
|
+
*
|
|
65
|
+
* Args:
|
|
66
|
+
* verifierKey: the witness verifier secret (non-empty).
|
|
67
|
+
* candidate: an arbitrary value (e.g. a parsed receipt.json).
|
|
68
|
+
* expected: optional digests the receipt must match for THIS use.
|
|
69
|
+
*
|
|
70
|
+
* Returns:
|
|
71
|
+
* ReceiptVerification: the validated receipt or a typed rejection.
|
|
72
|
+
*/
|
|
73
|
+
export function verifyGateReceipt(verifierKey, candidate, expected = {}) {
|
|
74
|
+
if (candidate === undefined || candidate === null) {
|
|
75
|
+
return { ok: false, rejection: 'missing', detail: 'gate receipt is missing' };
|
|
76
|
+
}
|
|
77
|
+
const parsed = GateReceiptSchema.safeParse(candidate);
|
|
78
|
+
if (!parsed.success) {
|
|
79
|
+
const issue = parsed.error.issues[0];
|
|
80
|
+
const path = issue === undefined ? '' : ` at '${issue.path.map(String).join('.')}':`;
|
|
81
|
+
return {
|
|
82
|
+
ok: false,
|
|
83
|
+
rejection: 'malformed',
|
|
84
|
+
detail: `gate receipt is malformed (expected receiptVersion 1 with the full binding set and mac)` +
|
|
85
|
+
`${path} ${issue?.message ?? 'unknown schema error'}`,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const receipt = parsed.data;
|
|
89
|
+
const { mac, ...body } = receipt;
|
|
90
|
+
if (typeof verifierKey !== 'string' || verifierKey.length === 0) {
|
|
91
|
+
return {
|
|
92
|
+
ok: false,
|
|
93
|
+
rejection: 'mac-fail',
|
|
94
|
+
detail: 'gate receipt cannot verify without a verifier key (fail closed)',
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const claimed = mac;
|
|
98
|
+
if (!MAC_PATTERN.test(claimed)) {
|
|
99
|
+
return { ok: false, rejection: 'mac-fail', detail: 'gate receipt mac is malformed' };
|
|
100
|
+
}
|
|
101
|
+
let expectedMac;
|
|
102
|
+
let claimedMac;
|
|
103
|
+
try {
|
|
104
|
+
expectedMac = Buffer.from(gateReceiptMac(verifierKey, body), 'hex');
|
|
105
|
+
claimedMac = Buffer.from(claimed, 'hex');
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return { ok: false, rejection: 'mac-fail', detail: 'gate receipt mac could not be recomputed' };
|
|
109
|
+
}
|
|
110
|
+
if (expectedMac.length !== claimedMac.length || !timingSafeEqual(expectedMac, claimedMac)) {
|
|
111
|
+
return {
|
|
112
|
+
ok: false,
|
|
113
|
+
rejection: 'mac-fail',
|
|
114
|
+
detail: 'gate receipt signature fails; the receipt was forged or tampered with (fail closed)',
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
const digestChecks = [
|
|
118
|
+
{ field: 'inputDigest', receiptValue: receipt.inputDigest, expectedValue: expected.inputDigest, rejection: 'input-digest-mismatch', label: 'input digest' },
|
|
119
|
+
{ field: 'trustedPolicyDigest', receiptValue: receipt.trustedPolicyDigest, expectedValue: expected.trustedPolicyDigest, rejection: 'policy-digest-mismatch', label: 'trusted policy digest' },
|
|
120
|
+
{ field: 'selectionDigest', receiptValue: receipt.selectionDigest, expectedValue: expected.selectionDigest, rejection: 'selection-digest-mismatch', label: 'selection digest' },
|
|
121
|
+
{ field: 'catalogDigest', receiptValue: receipt.catalogDigest, expectedValue: expected.catalogDigest, rejection: 'catalog-digest-mismatch', label: 'catalog digest' },
|
|
122
|
+
{ field: 'executionResultDigest', receiptValue: receipt.executionResultDigest, expectedValue: expected.executionResultDigest, rejection: 'execution-digest-mismatch', label: 'execution-result digest' },
|
|
123
|
+
{
|
|
124
|
+
field: 'evidenceAttestationDigest',
|
|
125
|
+
receiptValue: receipt.evidenceAttestationDigest,
|
|
126
|
+
expectedValue: expected.evidenceAttestationDigest === undefined ? undefined : expected.evidenceAttestationDigest,
|
|
127
|
+
rejection: 'attestation-digest-mismatch',
|
|
128
|
+
label: 'evidence attestation digest',
|
|
129
|
+
},
|
|
130
|
+
];
|
|
131
|
+
for (const check of digestChecks) {
|
|
132
|
+
if (check.expectedValue === undefined)
|
|
133
|
+
continue;
|
|
134
|
+
if (check.receiptValue !== check.expectedValue) {
|
|
135
|
+
return {
|
|
136
|
+
ok: false,
|
|
137
|
+
rejection: check.rejection,
|
|
138
|
+
detail: `gate receipt ${check.label} does not match the current run ` +
|
|
139
|
+
`('${String(check.receiptValue)}' vs '${String(check.expectedValue)}'); ` +
|
|
140
|
+
'the sealed run is not this run (fail closed)',
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (receipt.verdictSummary.blocking !== 0) {
|
|
145
|
+
return {
|
|
146
|
+
ok: false,
|
|
147
|
+
rejection: 'not-clean',
|
|
148
|
+
detail: `gate receipt seals a blocking verdict summary (${String(receipt.verdictSummary.blocking)} blocking); ` +
|
|
149
|
+
'receipts are issued only after complete success (fail closed)',
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
return { ok: true, receipt };
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/receipt/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { ClassificationDecisionTrace } from '../classifier/schema.js';
|
|
2
|
+
import type { BlockingEntry } from '../policy/index.js';
|
|
3
|
+
import type { RunManifest } from '../schemas/run-manifest.js';
|
|
4
|
+
import { type ObligationVerdict } from '../verdict/index.js';
|
|
5
|
+
/** Waiver-population counts for report summaries (from the waivers loader). */
|
|
6
|
+
export interface WaiverCounts {
|
|
7
|
+
/** All waivers found in the configured directory. */
|
|
8
|
+
total: number;
|
|
9
|
+
/** Valid at the injected `now` (five fields, unexpired, owner checked). */
|
|
10
|
+
active: number;
|
|
11
|
+
/** Expired at the injected `now` (GF-16) — blocking as `invalid`. */
|
|
12
|
+
expired: number;
|
|
13
|
+
/** Failed the owner check (GF-17) — blocking as `stale`. */
|
|
14
|
+
staleOwner: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Effective evaluation scope (plan §12.4): one decision, applied to
|
|
18
|
+
* obligations and blockers alike. Output-only — the input-snapshot
|
|
19
|
+
* digest never covers scope labels or report formats, so evidence reuse
|
|
20
|
+
* for identical inputs is unaffected by scope selection.
|
|
21
|
+
*/
|
|
22
|
+
export interface ScopeMetadata {
|
|
23
|
+
/** `all` = every obligation evaluated; `changed` = diff-narrowed. */
|
|
24
|
+
mode: 'all' | 'changed';
|
|
25
|
+
/** Sorted gate-defining inputs/reasons that forced expansion. */
|
|
26
|
+
expandedBecause: readonly string[];
|
|
27
|
+
}
|
|
28
|
+
/** Options for {@link renderRun}. */
|
|
29
|
+
export interface RenderRunOptions {
|
|
30
|
+
/** Output format. */
|
|
31
|
+
format: 'json' | 'sarif' | 'text';
|
|
32
|
+
/** Blocking entries (unclassified/unresolved/findings/stale references). */
|
|
33
|
+
blocking?: readonly BlockingEntry[];
|
|
34
|
+
/** Waiver-population counts; included in json/text when provided. */
|
|
35
|
+
waiverCounts?: WaiverCounts;
|
|
36
|
+
/** Run manifest; included in the json report when provided. */
|
|
37
|
+
run?: RunManifest;
|
|
38
|
+
/** Tool version stamped into SARIF `tool.driver.version`. */
|
|
39
|
+
toolVersion?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Effective evaluation scope (plan §12.4); included in json/SARIF and
|
|
42
|
+
* summarized in text when the scope expanded. Defaults to the full
|
|
43
|
+
* `all` scope when omitted.
|
|
44
|
+
*/
|
|
45
|
+
scope?: ScopeMetadata;
|
|
46
|
+
/**
|
|
47
|
+
* Classification decision provenance per resource id (ADR 0003):
|
|
48
|
+
* decision fingerprint + rule trace, included in json/SARIF/text when
|
|
49
|
+
* provided. Report-visible so any signal change (and hence any
|
|
50
|
+
* fingerprint change) is auditable — never authoritative input.
|
|
51
|
+
*/
|
|
52
|
+
classificationTraces?: Record<string, ClassificationDecisionTrace>;
|
|
53
|
+
/**
|
|
54
|
+
* Adoption-baseline forgiveness counts (phase 8 C), included in the
|
|
55
|
+
* json summary and the text report when provided. Baselined debt is
|
|
56
|
+
* LOUD on every run — a forgiveness that never announces itself is a
|
|
57
|
+
* silent waiver, and there are none of those in gateforge.
|
|
58
|
+
* `classificationBlocked` (two-layer adoption) counts blocking entries
|
|
59
|
+
* waived via the receipt's adopted classification set.
|
|
60
|
+
*/
|
|
61
|
+
baseline?: {
|
|
62
|
+
obligations: number;
|
|
63
|
+
blockingEntries: number;
|
|
64
|
+
classificationBlocked?: number;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** A run's exit code (architecture contract 4). */
|
|
68
|
+
export type RunExitCode = 0 | 1 | 2;
|
|
69
|
+
/**
|
|
70
|
+
* Maps a run outcome to its exit code: 2 for config/usage errors,
|
|
71
|
+
* 1 when any blocking verdict or blocking entry exists, else 0
|
|
72
|
+
* (clean or waived).
|
|
73
|
+
*
|
|
74
|
+
* Args:
|
|
75
|
+
* input: verdicts, optional blocking entries, optional config-error flag.
|
|
76
|
+
*
|
|
77
|
+
* Returns:
|
|
78
|
+
* RunExitCode: 0 clean/waived, 1 unresolved, 2 config.
|
|
79
|
+
*/
|
|
80
|
+
export declare function runExitCode(input: {
|
|
81
|
+
verdicts: readonly ObligationVerdict[];
|
|
82
|
+
blocking?: readonly BlockingEntry[];
|
|
83
|
+
configError?: boolean;
|
|
84
|
+
}): RunExitCode;
|
|
85
|
+
/**
|
|
86
|
+
* Renders a run's verdicts in the requested format. Output is canonical
|
|
87
|
+
* JSON for `json`/`sarif` and deterministic text for `text`.
|
|
88
|
+
*
|
|
89
|
+
* Args:
|
|
90
|
+
* verdicts: per-obligation verdicts (any order; output is sorted).
|
|
91
|
+
* options: format, blocking entries, waiver counts, run manifest.
|
|
92
|
+
*
|
|
93
|
+
* Returns:
|
|
94
|
+
* string: the rendered report.
|
|
95
|
+
*
|
|
96
|
+
* Throws:
|
|
97
|
+
* Error: when `format` is not one of the three supported formats.
|
|
98
|
+
*/
|
|
99
|
+
export declare function renderRun(verdicts: readonly ObligationVerdict[], options: RenderRunOptions): string;
|
|
100
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/report/index.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AAC3E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAE9D,OAAO,EAAqB,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAMhF,+EAA+E;AAC/E,MAAM,WAAW,YAAY;IAC3B,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,IAAI,EAAE,KAAK,GAAG,SAAS,CAAC;IACxB,iEAAiE;IACjE,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC;AAED,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC/B,qBAAqB;IACrB,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,MAAM,CAAC;IAClC,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IACpC,qEAAqE;IACrE,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,+DAA+D;IAC/D,GAAG,CAAC,EAAE,WAAW,CAAC;IAClB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,2BAA2B,CAAC,CAAC;IACnE;;;;;;;OAOG;IACH,QAAQ,CAAC,EAAE;QACT,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,MAAM,CAAC;QACxB,qBAAqB,CAAC,EAAE,MAAM,CAAC;KAChC,CAAC;CACH;AAED,mDAAmD;AACnD,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAEpC;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE;IACjC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACvC,QAAQ,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IACpC,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,GAAG,WAAW,CAOd;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,SAAS,CACvB,QAAQ,EAAE,SAAS,iBAAiB,EAAE,EACtC,OAAO,EAAE,gBAAgB,GACxB,MAAM,CAkBR"}
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Run reports (architecture contract 4, invariant 8, pin #10): renders
|
|
3
|
+
* per-obligation verdicts into one of three formats and maps a run to
|
|
4
|
+
* its exit code.
|
|
5
|
+
*
|
|
6
|
+
* - `json`: GF-canonical JSON (recursively key-sorted, no whitespace) of
|
|
7
|
+
* the full report document — deterministic, snapshot-able.
|
|
8
|
+
* - `sarif`: SARIF 2.1.0 projection (pin #10): ruleId = policyId,
|
|
9
|
+
* `partialFingerprints.gateforgeFingerprint`, blocking verdicts at
|
|
10
|
+
* level `error`, `waived` results carry a suppression with the waiver
|
|
11
|
+
* reason, properties carry resourceId/contract/verdict/trustTier.
|
|
12
|
+
* - `text`: the invariant-8 trace — detector → policy → obligation →
|
|
13
|
+
* evidence gap — plus waiver counts. Every block names its evidence.
|
|
14
|
+
*
|
|
15
|
+
* Exit codes (contract 4): 0 clean/waived, 1 unresolved obligations
|
|
16
|
+
* (any blocking verdict or blocking entry), 2 config/usage error.
|
|
17
|
+
*
|
|
18
|
+
* Rendering is pure and deterministic: identical inputs serialize
|
|
19
|
+
* byte-for-byte identically.
|
|
20
|
+
*/
|
|
21
|
+
import { canonicalJson } from '../canonical-json.js';
|
|
22
|
+
import { fingerprint } from '../fingerprints.js';
|
|
23
|
+
import { compareStrings } from '../graph/util.js';
|
|
24
|
+
import { BLOCKING_VERDICTS } from '../verdict/index.js';
|
|
25
|
+
/** The official SARIF 2.1.0 (errata 01) JSON schema location. */
|
|
26
|
+
const SARIF_SCHEMA_URI = 'https://docs.oasis-open.org/sarif/sarif/v2.1.0/errata01/os/schemas/sarif-schema-2.1.0.json';
|
|
27
|
+
/**
|
|
28
|
+
* Maps a run outcome to its exit code: 2 for config/usage errors,
|
|
29
|
+
* 1 when any blocking verdict or blocking entry exists, else 0
|
|
30
|
+
* (clean or waived).
|
|
31
|
+
*
|
|
32
|
+
* Args:
|
|
33
|
+
* input: verdicts, optional blocking entries, optional config-error flag.
|
|
34
|
+
*
|
|
35
|
+
* Returns:
|
|
36
|
+
* RunExitCode: 0 clean/waived, 1 unresolved, 2 config.
|
|
37
|
+
*/
|
|
38
|
+
export function runExitCode(input) {
|
|
39
|
+
if (input.configError)
|
|
40
|
+
return 2;
|
|
41
|
+
const hasBlockingEntries = (input.blocking ?? []).length > 0;
|
|
42
|
+
const hasBlockingVerdicts = input.verdicts.some((entry) => BLOCKING_VERDICTS.includes(entry.verdict));
|
|
43
|
+
return hasBlockingEntries || hasBlockingVerdicts ? 1 : 0;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Renders a run's verdicts in the requested format. Output is canonical
|
|
47
|
+
* JSON for `json`/`sarif` and deterministic text for `text`.
|
|
48
|
+
*
|
|
49
|
+
* Args:
|
|
50
|
+
* verdicts: per-obligation verdicts (any order; output is sorted).
|
|
51
|
+
* options: format, blocking entries, waiver counts, run manifest.
|
|
52
|
+
*
|
|
53
|
+
* Returns:
|
|
54
|
+
* string: the rendered report.
|
|
55
|
+
*
|
|
56
|
+
* Throws:
|
|
57
|
+
* Error: when `format` is not one of the three supported formats.
|
|
58
|
+
*/
|
|
59
|
+
export function renderRun(verdicts, options) {
|
|
60
|
+
const entries = [...verdicts].sort((a, b) => compareStrings(a.obligation.id, b.obligation.id));
|
|
61
|
+
const blocking = [...(options.blocking ?? [])].sort((a, b) => compareStrings(a.kind, b.kind) ||
|
|
62
|
+
compareStrings(a.resourceId ?? '', b.resourceId ?? '') ||
|
|
63
|
+
compareStrings(a.detail, b.detail));
|
|
64
|
+
// The report documents are JSON-safe by construction; the assertion
|
|
65
|
+
// records that invariant at the canonical-serialization boundary.
|
|
66
|
+
if (options.format === 'json') {
|
|
67
|
+
return canonicalJson(jsonReport(entries, options, blocking));
|
|
68
|
+
}
|
|
69
|
+
if (options.format === 'sarif') {
|
|
70
|
+
return canonicalJson(sarifReport(entries, options));
|
|
71
|
+
}
|
|
72
|
+
if (options.format === 'text')
|
|
73
|
+
return textReport(entries, options, blocking);
|
|
74
|
+
throw new Error(`renderRun: unknown format '${String(options.format)}'`);
|
|
75
|
+
}
|
|
76
|
+
/** Per-verdict summary counts keyed by verdict name. */
|
|
77
|
+
function summarize(entries) {
|
|
78
|
+
const counts = {
|
|
79
|
+
satisfied: 0,
|
|
80
|
+
missing: 0,
|
|
81
|
+
invalid: 0,
|
|
82
|
+
unclassified: 0,
|
|
83
|
+
unresolved: 0,
|
|
84
|
+
waived: 0,
|
|
85
|
+
stale: 0,
|
|
86
|
+
};
|
|
87
|
+
for (const entry of entries)
|
|
88
|
+
counts[entry.verdict] += 1;
|
|
89
|
+
return counts;
|
|
90
|
+
}
|
|
91
|
+
/** Builds the canonical json-format report document. */
|
|
92
|
+
function jsonReport(entries, options, blocking) {
|
|
93
|
+
const counts = summarize(entries);
|
|
94
|
+
// The blocking total covers BOTH sources of red: blocking verdicts and
|
|
95
|
+
// policy blocking entries (findings/stale references block the gate
|
|
96
|
+
// too — undercounting them would show "0 blocking" next to exit 1).
|
|
97
|
+
const blockingCount = counts.missing +
|
|
98
|
+
counts.invalid +
|
|
99
|
+
counts.unclassified +
|
|
100
|
+
counts.unresolved +
|
|
101
|
+
counts.stale +
|
|
102
|
+
blocking.length;
|
|
103
|
+
const scope = options.scope ?? { mode: 'all', expandedBecause: [] };
|
|
104
|
+
const report = {
|
|
105
|
+
schemaVersion: 1,
|
|
106
|
+
summary: {
|
|
107
|
+
obligations: entries.length,
|
|
108
|
+
blocking: blockingCount,
|
|
109
|
+
blockingEntries: blocking.length,
|
|
110
|
+
...counts,
|
|
111
|
+
...(options.baseline !== undefined
|
|
112
|
+
? {
|
|
113
|
+
baselinedObligations: options.baseline.obligations,
|
|
114
|
+
baselinedBlockingEntries: options.baseline.blockingEntries,
|
|
115
|
+
...(options.baseline.classificationBlocked !== undefined
|
|
116
|
+
? { baselinedClassificationBlocked: options.baseline.classificationBlocked }
|
|
117
|
+
: {}),
|
|
118
|
+
}
|
|
119
|
+
: {}),
|
|
120
|
+
},
|
|
121
|
+
// Effective scope (§12.4): which obligations were evaluated and why
|
|
122
|
+
// the scope expanded. Output-only — never part of the snapshot digest.
|
|
123
|
+
scope: { mode: scope.mode, expandedBecause: [...scope.expandedBecause] },
|
|
124
|
+
verdicts: entries.map((entry) => {
|
|
125
|
+
const record = {
|
|
126
|
+
obligationId: entry.obligation.id,
|
|
127
|
+
resourceId: entry.obligation.resourceId,
|
|
128
|
+
contract: entry.obligation.contract,
|
|
129
|
+
policyId: entry.obligation.policyId,
|
|
130
|
+
verdict: entry.verdict,
|
|
131
|
+
reason: entry.reason,
|
|
132
|
+
// Stable plan §5.4 cause + next action (ADR 0005): null when the
|
|
133
|
+
// verdict is clean or no honest mapping exists yet.
|
|
134
|
+
cause: entry.cause ?? null,
|
|
135
|
+
nextAction: entry.nextAction ?? null,
|
|
136
|
+
recordIds: entry.recordIds,
|
|
137
|
+
fingerprint: fingerprint({
|
|
138
|
+
resourceId: entry.obligation.resourceId,
|
|
139
|
+
contract: entry.obligation.contract,
|
|
140
|
+
policyId: entry.obligation.policyId,
|
|
141
|
+
lifecycle: entry.obligation.lifecycle,
|
|
142
|
+
}),
|
|
143
|
+
trustTier: entry.trustTier,
|
|
144
|
+
};
|
|
145
|
+
if (entry.detector !== undefined && entry.detector !== null) {
|
|
146
|
+
record['detector'] = entry.detector;
|
|
147
|
+
}
|
|
148
|
+
return record;
|
|
149
|
+
}),
|
|
150
|
+
blocking,
|
|
151
|
+
};
|
|
152
|
+
if (options.run !== undefined) {
|
|
153
|
+
report['run'] = options.run;
|
|
154
|
+
}
|
|
155
|
+
if (options.waiverCounts !== undefined) {
|
|
156
|
+
report['waiverCounts'] = options.waiverCounts;
|
|
157
|
+
}
|
|
158
|
+
if (options.classificationTraces !== undefined) {
|
|
159
|
+
// Canonical JSON sorts keys, so insertion order is irrelevant.
|
|
160
|
+
report['classifications'] = options.classificationTraces;
|
|
161
|
+
}
|
|
162
|
+
return report;
|
|
163
|
+
}
|
|
164
|
+
/** Builds the SARIF 2.1.0 projection (pin #10). */
|
|
165
|
+
function sarifReport(entries, options) {
|
|
166
|
+
const ruleIds = [...new Set(entries.map((entry) => entry.obligation.policyId))].sort(compareStrings);
|
|
167
|
+
const scope = options.scope ?? { mode: 'all', expandedBecause: [] };
|
|
168
|
+
const ruleIndex = {};
|
|
169
|
+
ruleIds.forEach((ruleId, index) => {
|
|
170
|
+
ruleIndex[ruleId] = index;
|
|
171
|
+
});
|
|
172
|
+
const results = entries.map((entry) => {
|
|
173
|
+
const blocking = BLOCKING_VERDICTS.includes(entry.verdict);
|
|
174
|
+
const result = {
|
|
175
|
+
ruleId: entry.obligation.policyId,
|
|
176
|
+
ruleIndex: ruleIndex[entry.obligation.policyId],
|
|
177
|
+
level: blocking ? 'error' : 'none',
|
|
178
|
+
message: {
|
|
179
|
+
text: entry.reason ??
|
|
180
|
+
`obligation '${entry.obligation.id}' is ${entry.verdict}`,
|
|
181
|
+
},
|
|
182
|
+
properties: {
|
|
183
|
+
resourceId: entry.obligation.resourceId,
|
|
184
|
+
contract: entry.obligation.contract,
|
|
185
|
+
verdict: entry.verdict,
|
|
186
|
+
trustTier: entry.trustTier,
|
|
187
|
+
// Stable plan §5.4 cause + next action (ADR 0005), carried under
|
|
188
|
+
// properties so SARIF consumers see the same codes as text/JSON.
|
|
189
|
+
cause: entry.cause ?? null,
|
|
190
|
+
nextAction: entry.nextAction ?? null,
|
|
191
|
+
...(options.classificationTraces?.[entry.obligation.resourceId] !== undefined
|
|
192
|
+
? {
|
|
193
|
+
classificationFingerprint: options.classificationTraces[entry.obligation.resourceId]?.decisionFingerprint,
|
|
194
|
+
classificationRules: options.classificationTraces[entry.obligation.resourceId]?.rules,
|
|
195
|
+
}
|
|
196
|
+
: {}),
|
|
197
|
+
},
|
|
198
|
+
partialFingerprints: {
|
|
199
|
+
gateforgeFingerprint: fingerprint({
|
|
200
|
+
resourceId: entry.obligation.resourceId,
|
|
201
|
+
contract: entry.obligation.contract,
|
|
202
|
+
policyId: entry.obligation.policyId,
|
|
203
|
+
lifecycle: entry.obligation.lifecycle,
|
|
204
|
+
}),
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
if (entry.verdict === 'waived') {
|
|
208
|
+
result['suppressions'] = [
|
|
209
|
+
{
|
|
210
|
+
kind: 'external',
|
|
211
|
+
status: 'accepted',
|
|
212
|
+
justification: entry.reason ?? 'waived',
|
|
213
|
+
},
|
|
214
|
+
];
|
|
215
|
+
}
|
|
216
|
+
return result;
|
|
217
|
+
});
|
|
218
|
+
return {
|
|
219
|
+
$schema: SARIF_SCHEMA_URI,
|
|
220
|
+
version: '2.1.0',
|
|
221
|
+
runs: [
|
|
222
|
+
{
|
|
223
|
+
tool: {
|
|
224
|
+
driver: {
|
|
225
|
+
name: 'gateforge',
|
|
226
|
+
version: options.toolVersion ?? '0.1.0',
|
|
227
|
+
rules: ruleIds.map((ruleId) => ({ ruleId })),
|
|
228
|
+
},
|
|
229
|
+
},
|
|
230
|
+
// Effective evaluation scope (§12.4) in the run property bag:
|
|
231
|
+
// which obligations were evaluated and why the scope expanded.
|
|
232
|
+
properties: {
|
|
233
|
+
scope: { mode: scope.mode, expandedBecause: [...scope.expandedBecause] },
|
|
234
|
+
},
|
|
235
|
+
// Blocking policy entries (unclassified/unresolved resources,
|
|
236
|
+
// detector findings, stale references) are not obligation
|
|
237
|
+
// verdicts, so they surface as tool-execution notifications
|
|
238
|
+
// (SARIF 2.1.0 §3.20) instead of results — visible, error-level,
|
|
239
|
+
// never silently omitted from the projection.
|
|
240
|
+
invocations: [
|
|
241
|
+
{
|
|
242
|
+
toolExecutionNotifications: (options.blocking ?? []).map((entry) => ({
|
|
243
|
+
level: 'error',
|
|
244
|
+
message: {
|
|
245
|
+
text: `[${entry.kind}] ${entry.resourceId ?? entry.name ?? '<unnamed>'} — ${entry.detail}`,
|
|
246
|
+
},
|
|
247
|
+
properties: {
|
|
248
|
+
kind: entry.kind,
|
|
249
|
+
// Stable plan §5.4 cause + next action when the entry
|
|
250
|
+
// carries one (coverage/strict-enforcement findings).
|
|
251
|
+
...(entry.cause !== undefined && entry.cause !== null
|
|
252
|
+
? { cause: entry.cause, nextAction: entry.nextAction ?? null }
|
|
253
|
+
: {}),
|
|
254
|
+
...(entry.location !== null ? { location: entry.location } : {}),
|
|
255
|
+
},
|
|
256
|
+
})),
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
results,
|
|
260
|
+
},
|
|
261
|
+
],
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
/** One text-format trace block per non-satisfied verdict (invariant 8). */
|
|
265
|
+
function textReport(entries, options, blocking) {
|
|
266
|
+
const lines = [];
|
|
267
|
+
const counts = summarize(entries);
|
|
268
|
+
const blockingCount = counts.missing +
|
|
269
|
+
counts.invalid +
|
|
270
|
+
counts.unclassified +
|
|
271
|
+
counts.unresolved +
|
|
272
|
+
counts.stale +
|
|
273
|
+
blocking.length;
|
|
274
|
+
lines.push(`gateforge run: ${entries.length} obligation(s) — ` +
|
|
275
|
+
`${counts.satisfied} satisfied, ${counts.waived} waived, ${blockingCount} blocking`);
|
|
276
|
+
const scope = options.scope;
|
|
277
|
+
if (scope !== undefined && scope.expandedBecause.length > 0) {
|
|
278
|
+
lines.push(`scope: all obligations; expanded because ${[...scope.expandedBecause].join(', ')}`);
|
|
279
|
+
}
|
|
280
|
+
if (options.waiverCounts !== undefined) {
|
|
281
|
+
const wc = options.waiverCounts;
|
|
282
|
+
lines.push(`waivers: ${wc.total} total, ${wc.active} active, ${wc.expired} expired, ` +
|
|
283
|
+
`${wc.staleOwner} stale-owner`);
|
|
284
|
+
}
|
|
285
|
+
if (options.baseline !== undefined) {
|
|
286
|
+
lines.push(`baseline (adopted): ${options.baseline.obligations} obligation(s) + ` +
|
|
287
|
+
`${options.baseline.blockingEntries} blocking entry(ies)` +
|
|
288
|
+
(options.baseline.classificationBlocked !== undefined
|
|
289
|
+
? ` + ${options.baseline.classificationBlocked} classification-blocked resource(s)`
|
|
290
|
+
: '') +
|
|
291
|
+
` forgiven — shrink-only: resolve debt, then 'gateforge baseline update'`);
|
|
292
|
+
}
|
|
293
|
+
for (const entry of entries) {
|
|
294
|
+
if (entry.verdict === 'satisfied')
|
|
295
|
+
continue;
|
|
296
|
+
lines.push('');
|
|
297
|
+
lines.push(`[${entry.verdict}] ${entry.obligation.id}`);
|
|
298
|
+
if (entry.detector !== undefined && entry.detector !== null) {
|
|
299
|
+
lines.push(` detector: ${entry.detector.id}@${entry.detector.version}`);
|
|
300
|
+
}
|
|
301
|
+
lines.push(` policy: ${entry.obligation.policyId}`);
|
|
302
|
+
lines.push(` obligation: ${entry.obligation.id}`);
|
|
303
|
+
lines.push(` fingerprint: ${fingerprint({
|
|
304
|
+
resourceId: entry.obligation.resourceId,
|
|
305
|
+
contract: entry.obligation.contract,
|
|
306
|
+
policyId: entry.obligation.policyId,
|
|
307
|
+
lifecycle: entry.obligation.lifecycle,
|
|
308
|
+
})}`);
|
|
309
|
+
lines.push(` evidence gap: ${entry.reason ?? '<none>'}`);
|
|
310
|
+
if (entry.cause !== undefined && entry.cause !== null) {
|
|
311
|
+
lines.push(` cause: ${entry.cause}`);
|
|
312
|
+
lines.push(` next action: ${entry.nextAction ?? '<none>'}`);
|
|
313
|
+
}
|
|
314
|
+
lines.push(` records: ${entry.recordIds.length > 0 ? entry.recordIds.join(', ') : '<none consulted>'}`);
|
|
315
|
+
}
|
|
316
|
+
if (blocking.length > 0) {
|
|
317
|
+
lines.push('');
|
|
318
|
+
lines.push('blocking entries (unclassified/unresolved/findings/stale references):');
|
|
319
|
+
for (const entry of blocking) {
|
|
320
|
+
const where = entry.location !== null ? ` at ${entry.location.file}:${entry.location.line}` : '';
|
|
321
|
+
const cause = entry.cause !== undefined && entry.cause !== null
|
|
322
|
+
? ` (cause: ${entry.cause} → ${entry.nextAction ?? 'no action available'})`
|
|
323
|
+
: '';
|
|
324
|
+
lines.push(` [${entry.kind}] ${entry.resourceId ?? entry.name ?? '<unnamed>'} — ${entry.detail}${where}${cause}`);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (options.classificationTraces !== undefined) {
|
|
328
|
+
const ids = Object.keys(options.classificationTraces).sort(compareStrings);
|
|
329
|
+
if (ids.length > 0) {
|
|
330
|
+
lines.push('');
|
|
331
|
+
lines.push('classification decisions (automatic, conservative — ADR 0003):');
|
|
332
|
+
for (const id of ids) {
|
|
333
|
+
const trace = options.classificationTraces[id];
|
|
334
|
+
if (trace === undefined)
|
|
335
|
+
continue;
|
|
336
|
+
lines.push(` ${id}`);
|
|
337
|
+
lines.push(` decision fingerprint: ${trace.decisionFingerprint}`);
|
|
338
|
+
lines.push(` rules: ${trace.rules.join(', ')}`);
|
|
339
|
+
if (trace.defaultsApplied.length > 0) {
|
|
340
|
+
lines.push(` defaults applied: ${trace.defaultsApplied.join(', ')}`);
|
|
341
|
+
}
|
|
342
|
+
lines.push(` contributing signals: ${trace.contributingSignalIds.length}`);
|
|
343
|
+
if (trace.contradictions.length > 0) {
|
|
344
|
+
for (const contradiction of trace.contradictions) {
|
|
345
|
+
lines.push(` contradiction [${contradiction.dimension}]: ${contradiction.detail}`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
lines.push('');
|
|
352
|
+
lines.push(`exit code: ${runExitCode({ verdicts: entries, blocking })}`);
|
|
353
|
+
return `${lines.join('\n')}\n`;
|
|
354
|
+
}
|
|
355
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/report/index.ts"],"names":[],"mappings":"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"}
|