@cejel/cejel 0.6.10 → 0.6.11
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/dist/index.js
CHANGED
|
@@ -3,11 +3,12 @@ import { createRequire as __cejelCreateRequire } from 'node:module';
|
|
|
3
3
|
const require = __cejelCreateRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
serveCejelMcpOverStdio
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-S5B5KMSO.js";
|
|
7
7
|
import {
|
|
8
8
|
CALLER_CONTEXT_PRODUCT_IDENTITY_NOTICE,
|
|
9
9
|
CERTIFICATE_GLOSSARY,
|
|
10
10
|
EXTERNAL_FINDINGS_DISPLAY_LIMIT,
|
|
11
|
+
METRIC_DERIVED_FINDING_PATTERN,
|
|
11
12
|
PROSPECTIVE_RUBRIC_NOTICE,
|
|
12
13
|
WITAN_RUBRIC_VERSION_V22,
|
|
13
14
|
WitanReportSchema,
|
|
@@ -44,7 +45,7 @@ import {
|
|
|
44
45
|
verifyRecordedInputDigests,
|
|
45
46
|
verifyWitanAttestationBinding,
|
|
46
47
|
witanHistoryAbstentionInstruction
|
|
47
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-4YOIR3E6.js";
|
|
48
49
|
import "./chunk-2UMHJ23V.js";
|
|
49
50
|
import {
|
|
50
51
|
external_exports
|
|
@@ -67,7 +68,7 @@ init_esm_shims();
|
|
|
67
68
|
init_esm_shims();
|
|
68
69
|
var WITAN_ISSUANCE_STATEMENT_TYPE = "https://in-toto.io/Statement/v1";
|
|
69
70
|
var WITAN_ISSUANCE_PREDICATE_TYPE = "https://cejel.dev/attestations/issuance/v1";
|
|
70
|
-
var WITAN_ISSUANCE_FORMAT_VERSION = "1.
|
|
71
|
+
var WITAN_ISSUANCE_FORMAT_VERSION = "1.1";
|
|
71
72
|
var WITAN_ISSUANCE_SIGNATURE_NAMESPACE = "cejel-issuance";
|
|
72
73
|
var WITAN_ISSUANCE_PRINCIPAL = "issuance@barglabs.ai";
|
|
73
74
|
var WITAN_ISSUER_NAME = "Barg Labs Inc.";
|
|
@@ -95,6 +96,9 @@ var WitanIssuanceStatementSchema = external_exports.object({
|
|
|
95
96
|
toolVersion: external_exports.string().min(1).max(80),
|
|
96
97
|
rubricVersion: external_exports.string().min(1).max(120),
|
|
97
98
|
rubricBehaviourFingerprint: external_exports.string().regex(/^sha256:[a-f0-9]{64}$/).optional(),
|
|
99
|
+
// The scan time the reproduction replayed: the attested scan's predicate.generatedAt
|
|
100
|
+
// (issuance format 1.1 and later). Optional on read, so a 1.0 issuance still verifies.
|
|
101
|
+
generatedAt: external_exports.string().datetime({ offset: true }).optional(),
|
|
98
102
|
reportByteIdentical: external_exports.literal(true)
|
|
99
103
|
}).strict(),
|
|
100
104
|
issuedAt: external_exports.string().datetime({ offset: true }),
|
|
@@ -159,6 +163,7 @@ function createWitanIssuanceStatement(report, options) {
|
|
|
159
163
|
toolVersion: options.toolVersion,
|
|
160
164
|
rubricVersion: report.rubricVersion,
|
|
161
165
|
...report.rubricBehaviourFingerprint ? { rubricBehaviourFingerprint: report.rubricBehaviourFingerprint } : {},
|
|
166
|
+
...options.reproductionGeneratedAt ? { generatedAt: options.reproductionGeneratedAt } : {},
|
|
162
167
|
reportByteIdentical: true
|
|
163
168
|
},
|
|
164
169
|
issuedAt: options.issuedAt,
|
|
@@ -167,6 +172,40 @@ function createWitanIssuanceStatement(report, options) {
|
|
|
167
172
|
}
|
|
168
173
|
});
|
|
169
174
|
}
|
|
175
|
+
var ISO_8601_INSTANT = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(?::\d{2}(?:\.\d+)?)?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
176
|
+
function readReproductionGeneratedAt(attestation, now) {
|
|
177
|
+
const predicate = typeof attestation === "object" && attestation !== null ? attestation.predicate : void 0;
|
|
178
|
+
const value = typeof predicate === "object" && predicate !== null ? predicate.generatedAt : void 0;
|
|
179
|
+
if (value === void 0 || value === null) {
|
|
180
|
+
return {
|
|
181
|
+
ok: false,
|
|
182
|
+
reason: "the attestation's predicate.generatedAt is missing, so the reproduction has no scan time to replay"
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
const instant = typeof value === "string" ? Date.parse(value) : Number.NaN;
|
|
186
|
+
if (typeof value !== "string" || !ISO_8601_INSTANT.test(value) || !Number.isFinite(instant)) {
|
|
187
|
+
return {
|
|
188
|
+
ok: false,
|
|
189
|
+
reason: `the attestation's predicate.generatedAt is not a valid ISO 8601 time: ${JSON.stringify(value)}`
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
if (instant > now.getTime()) {
|
|
193
|
+
return {
|
|
194
|
+
ok: false,
|
|
195
|
+
reason: `the attestation's predicate.generatedAt (${value}) is later than this issuer's clock (${now.toISOString()})`
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
return { ok: true, generatedAt: value };
|
|
199
|
+
}
|
|
200
|
+
var NEW_YEAR_WINDOW_MS = 24 * 60 * 60 * 1e3;
|
|
201
|
+
function isWithinDayOfNewYearUtc(generatedAt) {
|
|
202
|
+
const instant = Date.parse(generatedAt);
|
|
203
|
+
if (!Number.isFinite(instant)) return false;
|
|
204
|
+
const year = new Date(instant).getUTCFullYear();
|
|
205
|
+
const sinceNewYear = instant - Date.UTC(year, 0, 1);
|
|
206
|
+
const untilNewYear = Date.UTC(year + 1, 0, 1) - instant;
|
|
207
|
+
return sinceNewYear <= NEW_YEAR_WINDOW_MS || untilNewYear <= NEW_YEAR_WINDOW_MS;
|
|
208
|
+
}
|
|
170
209
|
function verifyWitanIssuanceBinding(statement, options) {
|
|
171
210
|
const parsed = WitanIssuanceStatementSchema.safeParse(statement);
|
|
172
211
|
if (!parsed.success) {
|
|
@@ -506,8 +545,15 @@ function normalizeRepoRelativePath(raw) {
|
|
|
506
545
|
if (path.split("/").some((segment) => segment === ".." || segment === "")) return void 0;
|
|
507
546
|
return path;
|
|
508
547
|
}
|
|
509
|
-
|
|
510
|
-
|
|
548
|
+
var METRIC_DERIVED_IDENTITY = "metric-derived";
|
|
549
|
+
var NUMBER_PLACEHOLDER = "<n>";
|
|
550
|
+
var NUMBER_PATTERN = /\d+(?:\.\d+)?/g;
|
|
551
|
+
function findingIdentity(summary) {
|
|
552
|
+
if (METRIC_DERIVED_FINDING_PATTERN.test(summary)) return METRIC_DERIVED_IDENTITY;
|
|
553
|
+
return summary.replace(NUMBER_PATTERN, NUMBER_PLACEHOLDER);
|
|
554
|
+
}
|
|
555
|
+
function fingerprint(rule, path, line, identity, ordinal) {
|
|
556
|
+
return createHash2("sha256").update(JSON.stringify([rule, path, line, identity, ordinal])).digest("hex");
|
|
511
557
|
}
|
|
512
558
|
function exportGitLabCodeQuality(report) {
|
|
513
559
|
const ingestedCount = (report.consumedSignals ?? []).reduce(
|
|
@@ -525,6 +571,7 @@ function exportGitLabCodeQuality(report) {
|
|
|
525
571
|
const entries = [];
|
|
526
572
|
let excludedUnlocated = 0;
|
|
527
573
|
const seen = /* @__PURE__ */ new Set();
|
|
574
|
+
const groupSizes = /* @__PURE__ */ new Map();
|
|
528
575
|
for (const criterion of report.criteria) {
|
|
529
576
|
for (const finding of criterion.findings) {
|
|
530
577
|
const path = finding.evidence.path === void 0 ? void 0 : normalizeRepoRelativePath(finding.evidence.path);
|
|
@@ -533,9 +580,14 @@ function exportGitLabCodeQuality(report) {
|
|
|
533
580
|
excludedUnlocated += 1;
|
|
534
581
|
continue;
|
|
535
582
|
}
|
|
536
|
-
const
|
|
537
|
-
if (seen.has(
|
|
538
|
-
seen.add(
|
|
583
|
+
const exact = JSON.stringify([criterion.id, path, line, finding.summary]);
|
|
584
|
+
if (seen.has(exact)) continue;
|
|
585
|
+
seen.add(exact);
|
|
586
|
+
const identity = findingIdentity(finding.summary);
|
|
587
|
+
const group = JSON.stringify([criterion.id, path, line, identity]);
|
|
588
|
+
const ordinal = groupSizes.get(group) ?? 0;
|
|
589
|
+
groupSizes.set(group, ordinal + 1);
|
|
590
|
+
const print = fingerprint(criterion.id, path, line, identity, ordinal);
|
|
539
591
|
entries.push({
|
|
540
592
|
description: finding.summary,
|
|
541
593
|
check_name: criterion.id,
|
|
@@ -1597,6 +1649,12 @@ ${attestationBinding.errors.map((error) => ` - ${error}`).join("\n")}
|
|
|
1597
1649
|
);
|
|
1598
1650
|
return 1;
|
|
1599
1651
|
}
|
|
1652
|
+
const scanTime = readReproductionGeneratedAt(attestationArtifact.value, /* @__PURE__ */ new Date());
|
|
1653
|
+
if (!scanTime.ok) {
|
|
1654
|
+
process.stderr.write(`Cejel: refusing to issue \u2014 ${scanTime.reason}.
|
|
1655
|
+
`);
|
|
1656
|
+
return 1;
|
|
1657
|
+
}
|
|
1600
1658
|
let keyContents;
|
|
1601
1659
|
try {
|
|
1602
1660
|
keyContents = readFileSync(options.keyPath, "utf8");
|
|
@@ -1619,7 +1677,8 @@ ${attestationBinding.errors.map((error) => ` - ${error}`).join("\n")}
|
|
|
1619
1677
|
// comparison below, as it always has.
|
|
1620
1678
|
...suppliedReport.inputBinding?.policy === "strict" ? { strictIngest: true } : {},
|
|
1621
1679
|
...suppliedReport.inputBinding?.scannedSubject.repository ? { subjectRepository: suppliedReport.inputBinding.scannedSubject.repository } : {},
|
|
1622
|
-
toolVersion: cliVersion()
|
|
1680
|
+
toolVersion: cliVersion(),
|
|
1681
|
+
generatedAt: scanTime.generatedAt
|
|
1623
1682
|
});
|
|
1624
1683
|
const reproducedBytes = serializeWitanReport(reproduction.report);
|
|
1625
1684
|
const reproducedSha256 = createHash3("sha256").update(reproducedBytes, "utf8").digest("hex");
|
|
@@ -1633,6 +1692,12 @@ ${attestationBinding.errors.map((error) => ` - ${error}`).join("\n")}
|
|
|
1633
1692
|
" Check that the checkout is at the certificate revision, that the @cejel/cejel version matches",
|
|
1634
1693
|
" report.json's toolVersion, and that --product-name/--name/--rubric-pin/--ingest match the",
|
|
1635
1694
|
" original invocation. An issuance that cannot reproduce is not issued.",
|
|
1695
|
+
// The reproduction replays the scan's instant, but v17's B4 reads that instant's year in
|
|
1696
|
+
// the local time zone. Near a new year two hosts can disagree on it; name the setting,
|
|
1697
|
+
// never guess a zone.
|
|
1698
|
+
...isWithinDayOfNewYearUtc(scanTime.generatedAt) ? [
|
|
1699
|
+
` The scan's generatedAt (${scanTime.generatedAt}) is within 24 hours of a new year in UTC, and v17's B4 freshness year is read in the scan host's local time: an issuer in another time zone may need to re-run with the TZ environment variable set to the scan host's.`
|
|
1700
|
+
] : [],
|
|
1636
1701
|
""
|
|
1637
1702
|
].join("\n")
|
|
1638
1703
|
);
|
|
@@ -1644,6 +1709,7 @@ ${attestationBinding.errors.map((error) => ` - ${error}`).join("\n")}
|
|
|
1644
1709
|
issuerKeyFingerprint: issuerKey.fingerprint,
|
|
1645
1710
|
toolVersion: cliVersion(),
|
|
1646
1711
|
issuedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1712
|
+
reproductionGeneratedAt: scanTime.generatedAt,
|
|
1647
1713
|
engagementRef: options.engagementRef
|
|
1648
1714
|
});
|
|
1649
1715
|
const issuancePath = join2(options.outDir, ISSUANCE_OUTPUT_FILE);
|
package/dist/mcp/index.js
CHANGED
|
@@ -3,8 +3,8 @@ import { createRequire as __cejelCreateRequire } from 'node:module';
|
|
|
3
3
|
const require = __cejelCreateRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
5
|
serveCejelMcpOverStdio
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-S5B5KMSO.js";
|
|
7
|
+
import "../chunk-4YOIR3E6.js";
|
|
8
8
|
import "../chunk-2UMHJ23V.js";
|
|
9
9
|
import "../chunk-AMVP7L26.js";
|
|
10
10
|
import {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cejel/cejel",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.11",
|
|
4
4
|
"mcpName": "io.github.BargLabs/cejel",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"type": "git",
|
|
32
32
|
"url": "git+https://github.com/BargLabs/cejel.git"
|
|
33
33
|
},
|
|
34
|
-
"packageManager": "pnpm@9.0.0",
|
|
34
|
+
"packageManager": "pnpm@9.0.0+sha512.b4106707c7225b1748b61595953ccbebff97b54ad05d002aa3635f633b9c53cd666f7ce9b8bc44704f1fa048b9a49b55371ab2d9e9d667d1efe2ef1514bcd513",
|
|
35
35
|
"type": "module",
|
|
36
36
|
"bin": {
|
|
37
37
|
"cejel": "dist/index.js",
|