@cejel/cejel 0.6.6 → 0.6.7
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/README.md
CHANGED
|
@@ -92,7 +92,7 @@ if (-not $expected -or $actual -ne $expected.ToLowerInvariant()) {
|
|
|
92
92
|
```
|
|
93
93
|
|
|
94
94
|
> **Windows signing status:** `cejel-Windows-x86_64.exe` is intentionally unsigned in
|
|
95
|
-
> 0.6.
|
|
95
|
+
> 0.6.7 and may trigger Microsoft SmartScreen. The release build removes Node's inherited
|
|
96
96
|
> signature before SEA injection and fails unless Windows reports the result as `NotSigned`;
|
|
97
97
|
> it does not ship an invalid signature. Before running it, verify `SHA256SUMS` and the
|
|
98
98
|
> GitHub build-provenance attestation. Each binary also has an attached SPDX SBOM (the packages
|
|
@@ -116,7 +116,7 @@ docker run --rm --network=none -v "$PWD:/w" -w /w -v "$PWD/cejel:/cejel:ro" debi
|
|
|
116
116
|
npx @cejel/cejel@latest .
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
> **Distribution note:** Cejel `0.6.
|
|
119
|
+
> **Distribution note:** Cejel `0.6.7` is the coordinated release version for npm,
|
|
120
120
|
> standalone binaries, Docker/OCI, GitHub Action, Homebrew, and MCP Registry. A GitLab CI
|
|
121
121
|
> template and Code Quality export live in [`docs/gitlab-ci.md`](./docs/gitlab-ci.md).
|
|
122
122
|
|
|
@@ -187,16 +187,16 @@ gh attestation verify ./cejel-Windows-x86_64.exe -R BargLabs/cejel
|
|
|
187
187
|
This is cryptographically signed provenance. It is distinct from Apple Developer ID or
|
|
188
188
|
Microsoft Authenticode code-signing.
|
|
189
189
|
|
|
190
|
-
**Docker / OCI.** The current container release is `0.6.
|
|
190
|
+
**Docker / OCI.** The current container release is `0.6.7`:
|
|
191
191
|
|
|
192
192
|
```bash
|
|
193
|
-
docker run --rm -i -v "$PWD:/workspace:ro" ghcr.io/barglabs/cejel:0.6.
|
|
193
|
+
docker run --rm -i -v "$PWD:/workspace:ro" ghcr.io/barglabs/cejel:0.6.7
|
|
194
194
|
```
|
|
195
195
|
|
|
196
196
|
The image defaults to `cejel-mcp` over stdio. To use the CLI instead:
|
|
197
197
|
|
|
198
198
|
```bash
|
|
199
|
-
docker run --rm -v "$PWD:/workspace:ro" --entrypoint cejel ghcr.io/barglabs/cejel:0.6.
|
|
199
|
+
docker run --rm -v "$PWD:/workspace:ro" --entrypoint cejel ghcr.io/barglabs/cejel:0.6.7 .
|
|
200
200
|
```
|
|
201
201
|
|
|
202
202
|
The OCI image carries an SBOM of its base-image packages, maximum-mode build provenance, and a
|
|
@@ -571,7 +571,7 @@ The OCI image is an alternative when Docker is the preferred execution boundary.
|
|
|
571
571
|
the host path with the repository OpenClaw should allow Cejel to read:
|
|
572
572
|
|
|
573
573
|
```bash
|
|
574
|
-
npx -y openclaw@latest mcp set cejel-oci '{"command":"docker","args":["run","--rm","-i","-v","/absolute/path/to/repo:/workspace:ro","ghcr.io/barglabs/cejel:0.6.
|
|
574
|
+
npx -y openclaw@latest mcp set cejel-oci '{"command":"docker","args":["run","--rm","-i","-v","/absolute/path/to/repo:/workspace:ro","ghcr.io/barglabs/cejel:0.6.7"]}'
|
|
575
575
|
npx -y openclaw@latest mcp doctor cejel-oci --probe
|
|
576
576
|
```
|
|
577
577
|
|
|
@@ -572,6 +572,7 @@ var WITAN_DIRECTORY_WALK_AUTHENTICATED_A1_ABSENCE_SUMMARY = "Reviewable source i
|
|
|
572
572
|
var WITAN_LEGACY_AUTHENTICATED_A1_ABSENCE_SUMMARY = "Reviewable source is present, but the complete tracked inventory contains no concrete test file, configured test runner, CI test command, or coverage configuration.";
|
|
573
573
|
var WITAN_A5_RECONCILIATION_UNSETTLED_DISCLOSURE = "Whether this repository's claims are reconciled against its implementation cannot be settled from static evidence; Cejel makes no finding on it.";
|
|
574
574
|
var WITAN_A2_TENANT_ISOLATION_UNSETTLED_DISCLOSURE = "Whether tenant isolation is enforced outside the database cannot be settled from static evidence; Cejel makes no finding on it.";
|
|
575
|
+
var WITAN_A3_BUILD_STEP_UNSETTLED_DISCLOSURE = "Whether this package has a build or type-check step outside the files read cannot be settled from static evidence; Cejel makes no finding on it.";
|
|
575
576
|
function isWitanNoMeasurementAbstention(report) {
|
|
576
577
|
return report.verdict === "insufficient_source" && report.insufficientSourceReason.startsWith(WITAN_NO_MEASUREMENT_REASON) && report.criteria.every(
|
|
577
578
|
({ status }) => status === "not_applicable" || status === "insufficient_data"
|
|
@@ -1973,6 +1974,7 @@ function buildWithheldPathsGapSentence(report) {
|
|
|
1973
1974
|
}
|
|
1974
1975
|
var SETTLING_EVIDENCE_DISCLOSURES = [
|
|
1975
1976
|
{ criterionId: "A2", sentence: WITAN_A2_TENANT_ISOLATION_UNSETTLED_DISCLOSURE },
|
|
1977
|
+
{ criterionId: "A3", sentence: WITAN_A3_BUILD_STEP_UNSETTLED_DISCLOSURE },
|
|
1976
1978
|
{ criterionId: "A5", sentence: WITAN_A5_RECONCILIATION_UNSETTLED_DISCLOSURE }
|
|
1977
1979
|
];
|
|
1978
1980
|
function settlingEvidenceDisclosures(report) {
|
|
@@ -3205,6 +3207,7 @@ function buildWitanInputFromRepoUntracked(options) {
|
|
|
3205
3207
|
const usesV24SecretContentContext = rubricVersion === WITAN_RUBRIC_VERSION_V24;
|
|
3206
3208
|
const usesV25InlineHealthRoute = rubricVersion === WITAN_RUBRIC_VERSION_V25 || rubricVersion === WITAN_RUBRIC_VERSION_V26;
|
|
3207
3209
|
const usesV26SettlingEvidence = rubricVersion === WITAN_RUBRIC_VERSION_V26;
|
|
3210
|
+
const usesV26BuildStepEvidence = rubricVersion === WITAN_RUBRIC_VERSION_V26;
|
|
3208
3211
|
const structuralArchetype = classifyRepoArchetype(inventoryFiles, rubricVersion);
|
|
3209
3212
|
const readableArchetype = rubricVersion === WITAN_RUBRIC_VERSION_V13 || rubricVersion === WITAN_RUBRIC_VERSION_V14 || rubricVersion === WITAN_RUBRIC_VERSION_V15 || rubricVersion === WITAN_RUBRIC_VERSION_V16 || usesV17DetectorClosure2(rubricVersion) ? applyReadableSourceRepresentationGate(
|
|
3210
3213
|
options.repoPath,
|
|
@@ -3246,6 +3249,7 @@ function buildWitanInputFromRepoUntracked(options) {
|
|
|
3246
3249
|
usesV24SecretContentContext,
|
|
3247
3250
|
usesV25InlineHealthRoute,
|
|
3248
3251
|
usesV26SettlingEvidence,
|
|
3252
|
+
usesV26BuildStepEvidence,
|
|
3249
3253
|
reviewableSourceProof,
|
|
3250
3254
|
inventoryAbsenceContext,
|
|
3251
3255
|
scanLimitations
|
|
@@ -3860,7 +3864,7 @@ function buildNotApplicableSignal(criterionId, reason) {
|
|
|
3860
3864
|
notApplicable: true
|
|
3861
3865
|
};
|
|
3862
3866
|
}
|
|
3863
|
-
function collectRepoSignals(repoPath, generatedAt, repoFiles, useV27Detectors, useV33Detectors, useV36Detectors, useV39Detectors, useV47Detectors, useV18NativeRls, useV19CommitYear, useV20A3ExplicitGaps, useV21ExecutedEscalations, useV22PackageStartEntrypoint, useV23StrictCoverageAndRecipeRunners, useV23PemPrivateKeyGrammar, useV23WithheldPathAbstention, useV24SecretContentContext, useV25InlineHealthRoute, useV26SettlingEvidence, reviewableSourceProof, inventoryAbsenceContext = LEGACY_INVENTORY_ABSENCE_CONTEXT, scanLimitations = /* @__PURE__ */ new Set()) {
|
|
3867
|
+
function collectRepoSignals(repoPath, generatedAt, repoFiles, useV27Detectors, useV33Detectors, useV36Detectors, useV39Detectors, useV47Detectors, useV18NativeRls, useV19CommitYear, useV20A3ExplicitGaps, useV21ExecutedEscalations, useV22PackageStartEntrypoint, useV23StrictCoverageAndRecipeRunners, useV23PemPrivateKeyGrammar, useV23WithheldPathAbstention, useV24SecretContentContext, useV25InlineHealthRoute, useV26SettlingEvidence, useV26BuildStepEvidence, reviewableSourceProof, inventoryAbsenceContext = LEGACY_INVENTORY_ABSENCE_CONTEXT, scanLimitations = /* @__PURE__ */ new Set()) {
|
|
3864
3868
|
const signals = [];
|
|
3865
3869
|
const mono = resolveMonorepoContext(repoPath, scanLimitations);
|
|
3866
3870
|
const collectCriterion = (criterionId, collect) => withContentReadCriterion(criterionId, collect);
|
|
@@ -3905,7 +3909,8 @@ function collectRepoSignals(repoPath, generatedAt, repoFiles, useV27Detectors, u
|
|
|
3905
3909
|
useV22PackageStartEntrypoint,
|
|
3906
3910
|
useV23WithheldPathAbstention,
|
|
3907
3911
|
inventoryAbsenceContext,
|
|
3908
|
-
useV25InlineHealthRoute
|
|
3912
|
+
useV25InlineHealthRoute,
|
|
3913
|
+
useV26BuildStepEvidence
|
|
3909
3914
|
)
|
|
3910
3915
|
);
|
|
3911
3916
|
const a4Signal = collectCriterion(
|
|
@@ -4828,7 +4833,7 @@ function collectCryptoHygieneEvidence(repoPath, implFiles, useV39Detectors = fal
|
|
|
4828
4833
|
}
|
|
4829
4834
|
return { evidence, findings, hasSurface, clean: hasSurface && !insecureFound };
|
|
4830
4835
|
}
|
|
4831
|
-
function collectA3ProdReadinessEvidence(repoPath, repoFiles, useV27Detectors, useV20ExplicitGaps = false, useV22PackageStartEntrypoint = false, useV23WithheldPathAbstention = false, inventoryAbsenceContext = LEGACY_INVENTORY_ABSENCE_CONTEXT, useV25InlineHealthRoute = false) {
|
|
4836
|
+
function collectA3ProdReadinessEvidence(repoPath, repoFiles, useV27Detectors, useV20ExplicitGaps = false, useV22PackageStartEntrypoint = false, useV23WithheldPathAbstention = false, inventoryAbsenceContext = LEGACY_INVENTORY_ABSENCE_CONTEXT, useV25InlineHealthRoute = false, useV26BuildStepEvidence = false) {
|
|
4832
4837
|
const v20DirectHttpEntrypoint = useV20ExplicitGaps ? findV20DirectHttpServerEntrypointFile(repoPath, repoFiles) : null;
|
|
4833
4838
|
const v22PackageStartHttpEntrypoint = useV22PackageStartEntrypoint ? findV22PackageStartHttpServerEntrypointFile(repoPath, repoFiles) : null;
|
|
4834
4839
|
const v20RuntimeContainer = useV20ExplicitGaps ? findRuntimeContainerEntrypointFile(repoPath, repoFiles, true) : null;
|
|
@@ -5045,13 +5050,22 @@ function collectA3ProdReadinessEvidence(repoPath, repoFiles, useV27Detectors, us
|
|
|
5045
5050
|
}
|
|
5046
5051
|
}
|
|
5047
5052
|
if (evidence.length === 0) return null;
|
|
5053
|
+
let buildStepSettlement;
|
|
5048
5054
|
if (useV20ExplicitGaps) {
|
|
5049
5055
|
const workspaceManifests = packageJson ? findDeclaredWorkspaceManifests(repoPath, repoFiles, packageJson) : NO_DECLARED_WORKSPACE_MANIFESTS;
|
|
5050
5056
|
const hasBuildOrTypecheck = scripts.has("build") || scripts.has("typecheck") || workspaceManifests.declared > workspaceManifests.read.length || workspaceManifests.read.some((file) => {
|
|
5051
5057
|
const workspaceScripts = readPackageScripts(join(repoPath, file));
|
|
5052
5058
|
return workspaceScripts.has("build") || workspaceScripts.has("typecheck");
|
|
5053
5059
|
});
|
|
5054
|
-
|
|
5060
|
+
buildStepSettlement = useV26BuildStepEvidence && packageJson ? settleV26BuildStepEvidence(
|
|
5061
|
+
repoPath,
|
|
5062
|
+
repoFiles,
|
|
5063
|
+
packageJson,
|
|
5064
|
+
workspaceManifests,
|
|
5065
|
+
workflows,
|
|
5066
|
+
(file) => !useV27Detectors || isAuthoredProductionPath(file)
|
|
5067
|
+
) : void 0;
|
|
5068
|
+
if (packageJson && !hasBuildOrTypecheck && (buildStepSettlement === void 0 || buildStepSettlement === "fires")) {
|
|
5055
5069
|
const workspaceRead = workspaceManifests.read.length;
|
|
5056
5070
|
findings.push({
|
|
5057
5071
|
severity: "info",
|
|
@@ -5192,7 +5206,8 @@ function collectA3ProdReadinessEvidence(repoPath, repoFiles, useV27Detectors, us
|
|
|
5192
5206
|
"Counts static rollback or migration-safety artifacts.",
|
|
5193
5207
|
"saturating_count"
|
|
5194
5208
|
)
|
|
5195
|
-
]
|
|
5209
|
+
],
|
|
5210
|
+
...buildStepSettlement === "unsettled" ? { notes: WITAN_A3_BUILD_STEP_UNSETTLED_DISCLOSURE } : {}
|
|
5196
5211
|
};
|
|
5197
5212
|
}
|
|
5198
5213
|
function collectA4DependencyEvidence(repoPath, repoFiles, mono, useV27Detectors, useV47Detectors, inventoryAbsenceContext = LEGACY_INVENTORY_ABSENCE_CONTEXT) {
|
|
@@ -9396,31 +9411,38 @@ function findRootPackageJson(repoFiles) {
|
|
|
9396
9411
|
var WORKSPACE_PATTERN_LIMIT = 64;
|
|
9397
9412
|
var WORKSPACE_PACKAGE_MANIFEST_LIMIT = 200;
|
|
9398
9413
|
var NO_DECLARED_WORKSPACE_MANIFESTS = { read: [], declared: 0 };
|
|
9414
|
+
var UNREADABLE_WORKSPACE_DECLARATION = {
|
|
9415
|
+
read: [],
|
|
9416
|
+
declared: 0,
|
|
9417
|
+
unreadable: true
|
|
9418
|
+
};
|
|
9399
9419
|
function findDeclaredWorkspaceManifests(repoPath, repoFiles, rootPackageJson) {
|
|
9400
9420
|
const patterns = [];
|
|
9401
9421
|
if (rootPackageJson) {
|
|
9402
9422
|
const declared = readPackageJsonWorkspacePatterns(join(repoPath, rootPackageJson));
|
|
9403
|
-
if (declared === null) return
|
|
9423
|
+
if (declared === null) return UNREADABLE_WORKSPACE_DECLARATION;
|
|
9404
9424
|
patterns.push(...declared);
|
|
9405
9425
|
}
|
|
9406
9426
|
if (repoFiles.includes("pnpm-workspace.yaml")) {
|
|
9407
9427
|
const declared = readPnpmWorkspacePatterns(join(repoPath, "pnpm-workspace.yaml"));
|
|
9408
|
-
if (declared === null) return
|
|
9428
|
+
if (declared === null) return UNREADABLE_WORKSPACE_DECLARATION;
|
|
9409
9429
|
patterns.push(...declared);
|
|
9410
9430
|
}
|
|
9411
|
-
if (patterns.length === 0
|
|
9412
|
-
|
|
9413
|
-
}
|
|
9431
|
+
if (patterns.length === 0) return NO_DECLARED_WORKSPACE_MANIFESTS;
|
|
9432
|
+
if (patterns.length > WORKSPACE_PATTERN_LIMIT) return UNREADABLE_WORKSPACE_DECLARATION;
|
|
9414
9433
|
const include = [];
|
|
9415
9434
|
const exclude = [];
|
|
9435
|
+
let unparsedPattern = false;
|
|
9416
9436
|
for (const pattern of patterns) {
|
|
9417
9437
|
const negated = pattern.startsWith("!");
|
|
9418
9438
|
const matcher = workspaceGlobMatcher(negated ? pattern.slice(1) : pattern);
|
|
9419
9439
|
if (negated) {
|
|
9420
|
-
if (matcher === null) return
|
|
9440
|
+
if (matcher === null) return UNREADABLE_WORKSPACE_DECLARATION;
|
|
9421
9441
|
exclude.push(matcher);
|
|
9422
9442
|
} else if (matcher !== null) {
|
|
9423
9443
|
include.push(matcher);
|
|
9444
|
+
} else {
|
|
9445
|
+
unparsedPattern = true;
|
|
9424
9446
|
}
|
|
9425
9447
|
}
|
|
9426
9448
|
const matched = repoFiles.filter((file) => {
|
|
@@ -9429,7 +9451,11 @@ function findDeclaredWorkspaceManifests(repoPath, repoFiles, rootPackageJson) {
|
|
|
9429
9451
|
const dir = file.slice(0, -"/package.json".length);
|
|
9430
9452
|
return include.some((matches) => matches(dir)) && !exclude.some((matches) => matches(dir));
|
|
9431
9453
|
}).sort();
|
|
9432
|
-
return {
|
|
9454
|
+
return {
|
|
9455
|
+
read: matched.slice(0, WORKSPACE_PACKAGE_MANIFEST_LIMIT),
|
|
9456
|
+
declared: matched.length,
|
|
9457
|
+
...unparsedPattern ? { unreadable: true } : {}
|
|
9458
|
+
};
|
|
9433
9459
|
}
|
|
9434
9460
|
function readPackageJsonWorkspacePatterns(packageJsonPath) {
|
|
9435
9461
|
if (!isRegularFile(packageJsonPath)) return [];
|
|
@@ -9639,6 +9665,263 @@ function unreadCiWorkflowReasons(includes) {
|
|
|
9639
9665
|
}
|
|
9640
9666
|
return unread;
|
|
9641
9667
|
}
|
|
9668
|
+
var BUILD_STEP_EXECUTABLES = /* @__PURE__ */ new Set([
|
|
9669
|
+
"babel",
|
|
9670
|
+
"esbuild",
|
|
9671
|
+
"ncc",
|
|
9672
|
+
"rollup",
|
|
9673
|
+
"svelte-check",
|
|
9674
|
+
"swc",
|
|
9675
|
+
"tsc",
|
|
9676
|
+
"tsup",
|
|
9677
|
+
"vue-tsc",
|
|
9678
|
+
"webpack",
|
|
9679
|
+
"webpack-cli"
|
|
9680
|
+
]);
|
|
9681
|
+
var BUILD_STEP_SUBCOMMANDS = /* @__PURE__ */ new Map([
|
|
9682
|
+
["bun", "build"],
|
|
9683
|
+
["nest", "build"],
|
|
9684
|
+
["next", "build"],
|
|
9685
|
+
["ng", "build"],
|
|
9686
|
+
["parcel", "build"],
|
|
9687
|
+
["vite", "build"]
|
|
9688
|
+
]);
|
|
9689
|
+
var BUILD_STEP_TASK_RUNNERS = /* @__PURE__ */ new Set([
|
|
9690
|
+
"bun",
|
|
9691
|
+
"gmake",
|
|
9692
|
+
"just",
|
|
9693
|
+
"lerna",
|
|
9694
|
+
"make",
|
|
9695
|
+
"npm",
|
|
9696
|
+
"nx",
|
|
9697
|
+
"pnpm",
|
|
9698
|
+
"turbo",
|
|
9699
|
+
"yarn"
|
|
9700
|
+
]);
|
|
9701
|
+
var BUILD_STEP_TARGET_NAME_PATTERN = /^(?:build|typecheck)$/u;
|
|
9702
|
+
var BUILD_STEP_TARGET_ARGUMENT_PATTERN = /^(?:[^\s:]+:)?(?:build|typecheck)$/u;
|
|
9703
|
+
var TYPESCRIPT_SOURCE_PATTERN = /\.(?:ts|tsx|mts|cts)$/u;
|
|
9704
|
+
var TYPESCRIPT_DECLARATION_PATTERN = /\.d\.(?:ts|mts|cts)$/u;
|
|
9705
|
+
var TSCONFIG_PATTERN = /(^|\/)tsconfig[^/]*\.json$/u;
|
|
9706
|
+
var BUILD_STEP_DOCKERFILE_PATTERN = /(^|\/)(?:dockerfile|containerfile)(?:\.[^/]*)?$|[^/]\.dockerfile$/iu;
|
|
9707
|
+
function settleV26BuildStepEvidence(repoPath, repoFiles, packageJson, workspaceManifests, workflows, includesWorkflow) {
|
|
9708
|
+
const nestedPackageDirs = repoFiles.filter((file) => file !== packageJson && /(^|\/)package\.json$/u.test(file)).map((file) => file.slice(0, -"package.json".length));
|
|
9709
|
+
const hasSomethingToBuild = repoFiles.some(
|
|
9710
|
+
(file) => isAuthoredProductionPath(file) && (TYPESCRIPT_SOURCE_PATTERN.test(file) && !TYPESCRIPT_DECLARATION_PATTERN.test(file) || TSCONFIG_PATTERN.test(file)) && !nestedPackageDirs.some((dir) => file.startsWith(dir))
|
|
9711
|
+
);
|
|
9712
|
+
if (!hasSomethingToBuild) return "nothing-to-build";
|
|
9713
|
+
let unsettled = false;
|
|
9714
|
+
const commandRunsStep = (command) => {
|
|
9715
|
+
const state = classifyBuildStepCommand(command);
|
|
9716
|
+
if (state === "unparseable") unsettled = true;
|
|
9717
|
+
return state === "step";
|
|
9718
|
+
};
|
|
9719
|
+
for (const manifest of [packageJson, ...workspaceManifests.read]) {
|
|
9720
|
+
const scripts = readBuildStepPackageScripts(join(repoPath, manifest));
|
|
9721
|
+
if (scripts === null) {
|
|
9722
|
+
unsettled = true;
|
|
9723
|
+
continue;
|
|
9724
|
+
}
|
|
9725
|
+
for (const [name, command] of scripts) {
|
|
9726
|
+
if (BUILD_STEP_TARGET_NAME_PATTERN.test(name) || commandRunsStep(command)) return "step-found";
|
|
9727
|
+
}
|
|
9728
|
+
}
|
|
9729
|
+
for (const workflow of workflows) {
|
|
9730
|
+
const fullPath = join(repoPath, workflow);
|
|
9731
|
+
if (!/^\.github\/workflows\//u.test(workflow) || !isRegularFile(fullPath)) {
|
|
9732
|
+
unsettled = true;
|
|
9733
|
+
continue;
|
|
9734
|
+
}
|
|
9735
|
+
if (extractCiRunCommands(readRepoText(fullPath, "utf8")).some(commandRunsStep)) {
|
|
9736
|
+
return "step-found";
|
|
9737
|
+
}
|
|
9738
|
+
}
|
|
9739
|
+
for (const file of repoFiles.filter((path) => BUILD_STEP_DOCKERFILE_PATTERN.test(path))) {
|
|
9740
|
+
const fullPath = join(repoPath, file);
|
|
9741
|
+
if (!isRegularFile(fullPath)) {
|
|
9742
|
+
unsettled = true;
|
|
9743
|
+
continue;
|
|
9744
|
+
}
|
|
9745
|
+
const run = dockerfileRunCommands(readRepoText(fullPath, "utf8"));
|
|
9746
|
+
if (run.unparseable) unsettled = true;
|
|
9747
|
+
if (run.commands.some(commandRunsStep)) return "step-found";
|
|
9748
|
+
}
|
|
9749
|
+
for (const file of repoFiles.filter(isRecipeFile)) {
|
|
9750
|
+
const fullPath = join(repoPath, file);
|
|
9751
|
+
if (!isRegularFile(fullPath)) {
|
|
9752
|
+
unsettled = true;
|
|
9753
|
+
continue;
|
|
9754
|
+
}
|
|
9755
|
+
for (const [name, target] of readRecipeTargets(readRepoText(fullPath, "utf8"))) {
|
|
9756
|
+
if (BUILD_STEP_TARGET_NAME_PATTERN.test(name)) return "step-found";
|
|
9757
|
+
if (target.commands.some((command) => commandRunsStep(command.replace(/\\$/u, "")))) {
|
|
9758
|
+
return "step-found";
|
|
9759
|
+
}
|
|
9760
|
+
}
|
|
9761
|
+
}
|
|
9762
|
+
if (workspaceManifests.declared > workspaceManifests.read.length || workspaceManifests.unreadable) {
|
|
9763
|
+
unsettled = true;
|
|
9764
|
+
}
|
|
9765
|
+
if (unreadCiWorkflowReasons(includesWorkflow).size > 0) unsettled = true;
|
|
9766
|
+
const delegated = countDelegatedCiSteps(repoPath, workflows);
|
|
9767
|
+
if (delegated.crossRepositoryReusableWorkflows + delegated.compositeActions > 0) unsettled = true;
|
|
9768
|
+
if (withheldRepoPaths().some(
|
|
9769
|
+
({ path }) => BUILD_STEP_DOCKERFILE_PATTERN.test(path) || isRecipeFile(path) || /(^|\/)package\.json$/u.test(path) && isAuthoredProductionPath(path)
|
|
9770
|
+
)) {
|
|
9771
|
+
unsettled = true;
|
|
9772
|
+
}
|
|
9773
|
+
return unsettled ? "unsettled" : "fires";
|
|
9774
|
+
}
|
|
9775
|
+
function readBuildStepPackageScripts(packageJsonPath) {
|
|
9776
|
+
if (!isRegularFile(packageJsonPath)) return null;
|
|
9777
|
+
const parsed = parseJsonObject(readRepoText(packageJsonPath, "utf8"));
|
|
9778
|
+
if (parsed === null) return null;
|
|
9779
|
+
if (parsed.scripts === void 0) return /* @__PURE__ */ new Map();
|
|
9780
|
+
if (!isRecord(parsed.scripts)) return null;
|
|
9781
|
+
const entries = Object.entries(parsed.scripts);
|
|
9782
|
+
if (!entries.every((entry) => typeof entry[1] === "string")) return null;
|
|
9783
|
+
return new Map(entries);
|
|
9784
|
+
}
|
|
9785
|
+
function dockerfileRunCommands(contents) {
|
|
9786
|
+
if (/^#\s*escape\s*=/imu.test(contents)) return { commands: [], unparseable: true };
|
|
9787
|
+
const lines = contents.split(/\r?\n/u);
|
|
9788
|
+
const commands = [];
|
|
9789
|
+
let unparseable = false;
|
|
9790
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
9791
|
+
const match = /^\s*RUN(?:\s+(.*))?$/iu.exec(lines[index] ?? "");
|
|
9792
|
+
if (!match) continue;
|
|
9793
|
+
const chunks = [match[1] ?? ""];
|
|
9794
|
+
while (endsWithLineContinuation(chunks) && index + 1 < lines.length) {
|
|
9795
|
+
index += 1;
|
|
9796
|
+
const next = lines[index] ?? "";
|
|
9797
|
+
if (/^\s*#/u.test(next)) continue;
|
|
9798
|
+
dropLineContinuation(chunks);
|
|
9799
|
+
chunks.push(" ", next.trim());
|
|
9800
|
+
}
|
|
9801
|
+
let instruction = chunks.join("");
|
|
9802
|
+
instruction = instruction.replace(/^(?:--[A-Za-z][\w-]*(?:=\S*)?\s+)*/u, "").trim();
|
|
9803
|
+
if (instruction === "" || /<<-?\s*["']?[A-Za-z_]/u.test(instruction)) {
|
|
9804
|
+
unparseable = true;
|
|
9805
|
+
continue;
|
|
9806
|
+
}
|
|
9807
|
+
if (!instruction.startsWith("[")) {
|
|
9808
|
+
commands.push(instruction);
|
|
9809
|
+
continue;
|
|
9810
|
+
}
|
|
9811
|
+
const execForm = dockerfileExecFormCommand(instruction);
|
|
9812
|
+
if (execForm === null) unparseable = true;
|
|
9813
|
+
else commands.push(execForm);
|
|
9814
|
+
}
|
|
9815
|
+
return { commands, unparseable };
|
|
9816
|
+
}
|
|
9817
|
+
function endsWithLineContinuation(chunks) {
|
|
9818
|
+
for (let c = chunks.length - 1; c >= 0; c -= 1) {
|
|
9819
|
+
const chunk = chunks[c] ?? "";
|
|
9820
|
+
for (let i = chunk.length - 1; i >= 0; i -= 1) {
|
|
9821
|
+
const character = chunk.charAt(i);
|
|
9822
|
+
if (/\s/u.test(character)) continue;
|
|
9823
|
+
return character === "\\";
|
|
9824
|
+
}
|
|
9825
|
+
}
|
|
9826
|
+
return false;
|
|
9827
|
+
}
|
|
9828
|
+
function dropLineContinuation(chunks) {
|
|
9829
|
+
while (chunks.length > 0) {
|
|
9830
|
+
const chunk = chunks[chunks.length - 1] ?? "";
|
|
9831
|
+
let i = chunk.length - 1;
|
|
9832
|
+
while (i >= 0 && /\s/u.test(chunk.charAt(i))) i -= 1;
|
|
9833
|
+
if (i < 0) {
|
|
9834
|
+
chunks.pop();
|
|
9835
|
+
continue;
|
|
9836
|
+
}
|
|
9837
|
+
chunks[chunks.length - 1] = chunk.slice(0, i);
|
|
9838
|
+
return;
|
|
9839
|
+
}
|
|
9840
|
+
}
|
|
9841
|
+
function dockerfileExecFormCommand(instruction) {
|
|
9842
|
+
let parsed;
|
|
9843
|
+
try {
|
|
9844
|
+
parsed = JSON.parse(instruction);
|
|
9845
|
+
} catch {
|
|
9846
|
+
return null;
|
|
9847
|
+
}
|
|
9848
|
+
if (!Array.isArray(parsed) || parsed.length === 0 || !parsed.every((part) => typeof part === "string")) {
|
|
9849
|
+
return null;
|
|
9850
|
+
}
|
|
9851
|
+
return parsed.map(
|
|
9852
|
+
(part) => /^[A-Za-z0-9_@%+=:,./-]+$/u.test(part) ? part : `'${part.replaceAll("'", "'\\''")}'`
|
|
9853
|
+
).join(" ");
|
|
9854
|
+
}
|
|
9855
|
+
function classifyBuildStepCommand(command) {
|
|
9856
|
+
return buildStepCommandState(command, 0);
|
|
9857
|
+
}
|
|
9858
|
+
function buildStepCommandState(command, depth) {
|
|
9859
|
+
if (depth > 4) return "unparseable";
|
|
9860
|
+
const states = splitShellCommandSegments(command).map(
|
|
9861
|
+
(segment) => buildStepSegmentState(segment, depth)
|
|
9862
|
+
);
|
|
9863
|
+
if (states.includes("step")) return "step";
|
|
9864
|
+
return states.includes("unparseable") ? "unparseable" : "none";
|
|
9865
|
+
}
|
|
9866
|
+
function buildStepSegmentState(raw, depth) {
|
|
9867
|
+
let segment = stripUnbalancedShellParentheses(raw.trim());
|
|
9868
|
+
for (; ; ) {
|
|
9869
|
+
const keyword = /^(?:if|then|else|elif|do|while|until|exec|!|\{)(?:\s+|$)/u.exec(segment);
|
|
9870
|
+
if (!keyword) break;
|
|
9871
|
+
segment = segment.slice(keyword[0].length);
|
|
9872
|
+
}
|
|
9873
|
+
if (segment === "" || /^(?:fi|done|esac|\})$/u.test(segment)) return "none";
|
|
9874
|
+
const normalized = normalizeCoverageCommandPrefixes(segment);
|
|
9875
|
+
if (normalized.splitShellOperators && splitShellCommandSegments(normalized.segment).length > 1) {
|
|
9876
|
+
return buildStepCommandState(normalized.segment, depth + 1);
|
|
9877
|
+
}
|
|
9878
|
+
if (/\b(?:npm|pnpm|yarn|bun)\s+run\s+(?:\$|["']\$|`)/u.test(normalized.segment)) {
|
|
9879
|
+
return "unparseable";
|
|
9880
|
+
}
|
|
9881
|
+
const words = strictShellWords(normalized.segment);
|
|
9882
|
+
if (words === null) return "unparseable";
|
|
9883
|
+
return words.length === 0 ? "none" : buildStepWordsState(words);
|
|
9884
|
+
}
|
|
9885
|
+
function buildStepWordsState(words) {
|
|
9886
|
+
const first = words[0] === "$(MAKE)" || words[0] === "${MAKE}" ? "make" : words[0] ?? "";
|
|
9887
|
+
if (isUnresolvedCommandWord(first)) return "unparseable";
|
|
9888
|
+
const runner = buildStepCommandName(first);
|
|
9889
|
+
if (BUILD_STEP_TASK_RUNNERS.has(runner) && words.slice(1).some((word) => BUILD_STEP_TARGET_ARGUMENT_PATTERN.test(word))) {
|
|
9890
|
+
return "step";
|
|
9891
|
+
}
|
|
9892
|
+
const command = runner === "bunx" ? words.slice(1) : runner === "bun" && words[1] === "x" ? words.slice(2) : unwrapPackageManagerExecutable(words);
|
|
9893
|
+
const executable = command[0] ?? "";
|
|
9894
|
+
if (isUnresolvedCommandWord(executable)) return "unparseable";
|
|
9895
|
+
const name = buildStepCommandName(executable);
|
|
9896
|
+
if (BUILD_STEP_EXECUTABLES.has(name)) return "step";
|
|
9897
|
+
const subcommand = BUILD_STEP_SUBCOMMANDS.get(name);
|
|
9898
|
+
return subcommand !== void 0 && command.slice(1).includes(subcommand) ? "step" : "none";
|
|
9899
|
+
}
|
|
9900
|
+
function isUnresolvedCommandWord(word) {
|
|
9901
|
+
return word.startsWith("$") || word.includes("`");
|
|
9902
|
+
}
|
|
9903
|
+
function buildStepCommandName(word) {
|
|
9904
|
+
return basename(word).replace(/\.(?:cmd|exe)$/iu, "").toLowerCase();
|
|
9905
|
+
}
|
|
9906
|
+
function stripUnbalancedShellParentheses(segment) {
|
|
9907
|
+
const opens = segment.split("(").length - 1;
|
|
9908
|
+
const closes = segment.split(")").length - 1;
|
|
9909
|
+
if (opens > closes) return segment.replace(/^\(+\s*/u, "");
|
|
9910
|
+
if (closes > opens) return segment.replace(/\s*\)+$/u, "");
|
|
9911
|
+
return segment;
|
|
9912
|
+
}
|
|
9913
|
+
function strictShellWords(segment) {
|
|
9914
|
+
const words = [];
|
|
9915
|
+
let offset = 0;
|
|
9916
|
+
for (; ; ) {
|
|
9917
|
+
while (offset < segment.length && /\s/u.test(segment[offset] ?? "")) offset += 1;
|
|
9918
|
+
if (offset >= segment.length) return words;
|
|
9919
|
+
const scanned = scanShellWord(segment, offset);
|
|
9920
|
+
if (!scanned) return null;
|
|
9921
|
+
if (scanned.word !== "") words.push(scanned.word);
|
|
9922
|
+
offset = scanned.end;
|
|
9923
|
+
}
|
|
9924
|
+
}
|
|
9642
9925
|
function rootOnlyPackageScriptsDisclosure(repoFiles, rootPackageJson) {
|
|
9643
9926
|
const others = repoFiles.filter(
|
|
9644
9927
|
(file) => file !== rootPackageJson && /(^|\/)package\.json$/.test(file) && isAuthoredProductionPath(file)
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ 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-TOQPQPDF.js";
|
|
7
7
|
import {
|
|
8
8
|
CALLER_CONTEXT_PRODUCT_IDENTITY_NOTICE,
|
|
9
9
|
CERTIFICATE_GLOSSARY,
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
runCejelScan,
|
|
30
30
|
serializeWitanReport,
|
|
31
31
|
verifyWitanAttestationBinding
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-ZZHQZW26.js";
|
|
33
33
|
import "./chunk-VGBFZBZQ.js";
|
|
34
34
|
import {
|
|
35
35
|
external_exports
|
|
@@ -41,8 +41,8 @@ import {
|
|
|
41
41
|
// src/index.ts
|
|
42
42
|
init_esm_shims();
|
|
43
43
|
import { createHash as createHash3 } from "crypto";
|
|
44
|
-
import { existsSync,
|
|
45
|
-
import { dirname, join, resolve as
|
|
44
|
+
import { existsSync, readFileSync, realpathSync } from "fs";
|
|
45
|
+
import { dirname, join as join2, resolve as resolve3 } from "path";
|
|
46
46
|
import { fileURLToPath, pathToFileURL } from "url";
|
|
47
47
|
|
|
48
48
|
// src/issuance/index.ts
|
|
@@ -578,6 +578,68 @@ function resolvedToLocalTree(env, cwd) {
|
|
|
578
578
|
return first !== void 0 && first === resolve(cwd, "node_modules", ".bin");
|
|
579
579
|
}
|
|
580
580
|
|
|
581
|
+
// src/output-files.ts
|
|
582
|
+
init_esm_shims();
|
|
583
|
+
import { closeSync, constants, lstatSync, mkdirSync, openSync, writeFileSync } from "fs";
|
|
584
|
+
import { join, resolve as resolve2 } from "path";
|
|
585
|
+
var O_NOFOLLOW = constants.O_NOFOLLOW ?? 0;
|
|
586
|
+
function isSymbolicLink(path) {
|
|
587
|
+
try {
|
|
588
|
+
return lstatSync(path).isSymbolicLink();
|
|
589
|
+
} catch (error) {
|
|
590
|
+
if (error.code === "ENOENT") return false;
|
|
591
|
+
throw error;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
function refusal(what, subject) {
|
|
595
|
+
return new Error(
|
|
596
|
+
`Cejel: refusing to write ${what}: ${subject} is a symbolic link. Nothing was written; remove the link or choose another output path.`
|
|
597
|
+
);
|
|
598
|
+
}
|
|
599
|
+
function refuseSymlinkedDirectory(dir, what) {
|
|
600
|
+
if (isSymbolicLink(resolve2(dir))) throw refusal(what, `output directory ${dir}`);
|
|
601
|
+
}
|
|
602
|
+
function refuseSymlinkedFile(path, what) {
|
|
603
|
+
if (isSymbolicLink(resolve2(path))) throw refusal(what, path);
|
|
604
|
+
}
|
|
605
|
+
function refuseSymlinkedOutputs(dir, names, what) {
|
|
606
|
+
refuseSymlinkedDirectory(dir, what);
|
|
607
|
+
for (const name of names) refuseSymlinkedFile(join(dir, name), what);
|
|
608
|
+
}
|
|
609
|
+
function writeOutputFileNoFollow(path, contents, what) {
|
|
610
|
+
let fd;
|
|
611
|
+
try {
|
|
612
|
+
fd = openSync(
|
|
613
|
+
path,
|
|
614
|
+
constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | O_NOFOLLOW,
|
|
615
|
+
438
|
|
616
|
+
);
|
|
617
|
+
} catch (error) {
|
|
618
|
+
if (error.code === "ELOOP") {
|
|
619
|
+
throw new Error(
|
|
620
|
+
`Cejel: refusing to write ${what}: ${path} is a symbolic link (the open was refused without following it).`
|
|
621
|
+
);
|
|
622
|
+
}
|
|
623
|
+
throw error;
|
|
624
|
+
}
|
|
625
|
+
try {
|
|
626
|
+
writeFileSync(fd, contents, "utf8");
|
|
627
|
+
} finally {
|
|
628
|
+
closeSync(fd);
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
function writeOutputFile(path, contents, what) {
|
|
632
|
+
refuseSymlinkedFile(path, what);
|
|
633
|
+
writeOutputFileNoFollow(path, contents, what);
|
|
634
|
+
}
|
|
635
|
+
function writeOutputFiles(dir, files, what) {
|
|
636
|
+
const names = files.map((file) => file.name);
|
|
637
|
+
refuseSymlinkedOutputs(dir, names, what);
|
|
638
|
+
mkdirSync(dir, { recursive: true });
|
|
639
|
+
refuseSymlinkedDirectory(dir, what);
|
|
640
|
+
for (const file of files) writeOutputFileNoFollow(join(dir, file.name), file.contents, what);
|
|
641
|
+
}
|
|
642
|
+
|
|
581
643
|
// src/terminal.ts
|
|
582
644
|
init_esm_shims();
|
|
583
645
|
function renderMinScoreAbstentionFailure(summary, minScore) {
|
|
@@ -744,6 +806,15 @@ function formatScore(score) {
|
|
|
744
806
|
|
|
745
807
|
// src/index.ts
|
|
746
808
|
var DEFAULT_OUT_DIR = ".cejel";
|
|
809
|
+
var SCAN_OUTPUT_FILES = [
|
|
810
|
+
"report.json",
|
|
811
|
+
"attestation.json",
|
|
812
|
+
"certificate.html",
|
|
813
|
+
"badge.json",
|
|
814
|
+
"badge.svg",
|
|
815
|
+
"summary.json"
|
|
816
|
+
];
|
|
817
|
+
var ISSUANCE_OUTPUT_FILE = "issuance.json";
|
|
747
818
|
var ISSUER_SIGNERS_FILE = "issuer-signers";
|
|
748
819
|
var ISSUER_REVOCATIONS_FILE = "issuer-revocations";
|
|
749
820
|
var SECURITY_FILE_CANDIDATES = ["../docs/security/", "../../docs/security/"];
|
|
@@ -956,6 +1027,7 @@ async function runWitanCli(args, rubricVersion) {
|
|
|
956
1027
|
return 0;
|
|
957
1028
|
}
|
|
958
1029
|
const effectiveRubricVersion = options.rubricPin ?? rubricVersion;
|
|
1030
|
+
refuseSymlinkedOutputs(options.outDir, SCAN_OUTPUT_FILES, "scan output");
|
|
959
1031
|
const { report, summary, generatedAt } = runCejelScan({
|
|
960
1032
|
repoPath: options.repoPath,
|
|
961
1033
|
...options.productName ? { productName: options.productName } : {},
|
|
@@ -970,29 +1042,25 @@ async function runWitanCli(args, rubricVersion) {
|
|
|
970
1042
|
generatedAt,
|
|
971
1043
|
...options.runAttempt ? { githubRunAttempt: options.runAttempt } : {}
|
|
972
1044
|
});
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
JSON.stringify(renderWitanBadgeEndpoint(report), null, 2),
|
|
992
|
-
"utf8"
|
|
1045
|
+
writeOutputFiles(
|
|
1046
|
+
options.outDir,
|
|
1047
|
+
[
|
|
1048
|
+
{ name: "report.json", contents: serializeWitanReport(report) },
|
|
1049
|
+
{ name: "attestation.json", contents: JSON.stringify(attestation, null, 2) },
|
|
1050
|
+
{
|
|
1051
|
+
name: "certificate.html",
|
|
1052
|
+
contents: renderWitanHtmlReport(report, {
|
|
1053
|
+
cliVersion: cliVersion(),
|
|
1054
|
+
generatedAt,
|
|
1055
|
+
...options.runAttempt ? { runAttempt: options.runAttempt } : {}
|
|
1056
|
+
})
|
|
1057
|
+
},
|
|
1058
|
+
{ name: "badge.json", contents: JSON.stringify(renderWitanBadgeEndpoint(report), null, 2) },
|
|
1059
|
+
{ name: "badge.svg", contents: renderWitanBadgeSvg(report) },
|
|
1060
|
+
{ name: "summary.json", contents: JSON.stringify(summary, null, 2) }
|
|
1061
|
+
],
|
|
1062
|
+
"scan output"
|
|
993
1063
|
);
|
|
994
|
-
writeFileSync(join(options.outDir, "badge.svg"), renderWitanBadgeSvg(report), "utf8");
|
|
995
|
-
writeFileSync(join(options.outDir, "summary.json"), JSON.stringify(summary, null, 2), "utf8");
|
|
996
1064
|
if (!options.quiet) {
|
|
997
1065
|
process.stdout.write(renderTerminalCertificate(summary, report));
|
|
998
1066
|
process.stdout.write(
|
|
@@ -1102,8 +1170,8 @@ function parseExportArgs(args) {
|
|
|
1102
1170
|
return {
|
|
1103
1171
|
command: "export",
|
|
1104
1172
|
format,
|
|
1105
|
-
reportPath:
|
|
1106
|
-
outPath:
|
|
1173
|
+
reportPath: resolve3(reportPath),
|
|
1174
|
+
outPath: resolve3(outPath)
|
|
1107
1175
|
};
|
|
1108
1176
|
}
|
|
1109
1177
|
function runExport(invocation) {
|
|
@@ -1121,8 +1189,12 @@ ${members.map((member) => ` - ${member}`).join("\n")}
|
|
|
1121
1189
|
return 1;
|
|
1122
1190
|
}
|
|
1123
1191
|
const result = exportGitLabCodeQuality(reportResult.data);
|
|
1124
|
-
|
|
1125
|
-
|
|
1192
|
+
writeOutputFile(
|
|
1193
|
+
invocation.outPath,
|
|
1194
|
+
`${JSON.stringify(result.entries, null, 2)}
|
|
1195
|
+
`,
|
|
1196
|
+
"export output"
|
|
1197
|
+
);
|
|
1126
1198
|
process.stderr.write(renderGitLabCodeQualityFooter(result));
|
|
1127
1199
|
return 0;
|
|
1128
1200
|
}
|
|
@@ -1137,8 +1209,8 @@ function parseVerifyArgs(args) {
|
|
|
1137
1209
|
if (arg === "--signers" || arg === "--revocations") {
|
|
1138
1210
|
const value = args[index + 1];
|
|
1139
1211
|
if (!value) throw new Error(`Missing value for ${arg}`);
|
|
1140
|
-
if (arg === "--signers") signersPath =
|
|
1141
|
-
else revocationsPath =
|
|
1212
|
+
if (arg === "--signers") signersPath = resolve3(value);
|
|
1213
|
+
else revocationsPath = resolve3(value);
|
|
1142
1214
|
index += 1;
|
|
1143
1215
|
continue;
|
|
1144
1216
|
}
|
|
@@ -1150,10 +1222,10 @@ function parseVerifyArgs(args) {
|
|
|
1150
1222
|
if (!reportPath || !attestationPath) throw new Error(VERIFY_USAGE());
|
|
1151
1223
|
return {
|
|
1152
1224
|
command: "verify",
|
|
1153
|
-
reportPath:
|
|
1154
|
-
attestationPath:
|
|
1155
|
-
...issuancePath ? { issuancePath:
|
|
1156
|
-
...issuanceSignaturePath ? { issuanceSignaturePath:
|
|
1225
|
+
reportPath: resolve3(reportPath),
|
|
1226
|
+
attestationPath: resolve3(attestationPath),
|
|
1227
|
+
...issuancePath ? { issuancePath: resolve3(issuancePath) } : {},
|
|
1228
|
+
...issuanceSignaturePath ? { issuanceSignaturePath: resolve3(issuanceSignaturePath) } : {},
|
|
1157
1229
|
...signersPath ? { signersPath } : {},
|
|
1158
1230
|
...revocationsPath ? { revocationsPath } : {}
|
|
1159
1231
|
};
|
|
@@ -1179,15 +1251,15 @@ function parseIssueArgs(args) {
|
|
|
1179
1251
|
if (arg === void 0) continue;
|
|
1180
1252
|
switch (arg) {
|
|
1181
1253
|
case "--report":
|
|
1182
|
-
reportPath =
|
|
1254
|
+
reportPath = resolve3(takeValue(arg, index + 1));
|
|
1183
1255
|
index += 1;
|
|
1184
1256
|
continue;
|
|
1185
1257
|
case "--attestation":
|
|
1186
|
-
attestationPath =
|
|
1258
|
+
attestationPath = resolve3(takeValue(arg, index + 1));
|
|
1187
1259
|
index += 1;
|
|
1188
1260
|
continue;
|
|
1189
1261
|
case "--key":
|
|
1190
|
-
keyPath =
|
|
1262
|
+
keyPath = resolve3(takeValue(arg, index + 1));
|
|
1191
1263
|
index += 1;
|
|
1192
1264
|
continue;
|
|
1193
1265
|
case "--engagement-ref":
|
|
@@ -1196,7 +1268,7 @@ function parseIssueArgs(args) {
|
|
|
1196
1268
|
continue;
|
|
1197
1269
|
case "--out":
|
|
1198
1270
|
case "--out-dir":
|
|
1199
|
-
outDir =
|
|
1271
|
+
outDir = resolve3(takeValue(arg, index + 1));
|
|
1200
1272
|
index += 1;
|
|
1201
1273
|
continue;
|
|
1202
1274
|
case "--product-name":
|
|
@@ -1240,7 +1312,7 @@ function parseIssueArgs(args) {
|
|
|
1240
1312
|
throw new Error("--product-name and --name cannot be used together");
|
|
1241
1313
|
}
|
|
1242
1314
|
return {
|
|
1243
|
-
repoPath:
|
|
1315
|
+
repoPath: resolve3(repoPath ?? "."),
|
|
1244
1316
|
reportPath,
|
|
1245
1317
|
attestationPath,
|
|
1246
1318
|
keyPath,
|
|
@@ -1410,6 +1482,7 @@ ${attestationBinding.errors.map((error) => ` - ${error}`).join("\n")}
|
|
|
1410
1482
|
throw new Error(`Cejel: could not read --key file ${options.keyPath}: ${message}`);
|
|
1411
1483
|
}
|
|
1412
1484
|
const issuerKey = parseIssuerPublicKey(keyContents);
|
|
1485
|
+
refuseSymlinkedOutputs(options.outDir, [ISSUANCE_OUTPUT_FILE], "issuance output");
|
|
1413
1486
|
const reproduction = runCejelScan({
|
|
1414
1487
|
repoPath: options.repoPath,
|
|
1415
1488
|
...options.productName ? { productName: options.productName } : {},
|
|
@@ -1444,9 +1517,12 @@ ${attestationBinding.errors.map((error) => ` - ${error}`).join("\n")}
|
|
|
1444
1517
|
issuedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1445
1518
|
engagementRef: options.engagementRef
|
|
1446
1519
|
});
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1520
|
+
const issuancePath = join2(options.outDir, ISSUANCE_OUTPUT_FILE);
|
|
1521
|
+
writeOutputFiles(
|
|
1522
|
+
options.outDir,
|
|
1523
|
+
[{ name: ISSUANCE_OUTPUT_FILE, contents: serializeWitanIssuance(statement) }],
|
|
1524
|
+
"issuance output"
|
|
1525
|
+
);
|
|
1450
1526
|
process.stdout.write(
|
|
1451
1527
|
[
|
|
1452
1528
|
`Cejel: reproduced report.json byte for byte (sha256:${reportSha256}).`,
|
|
@@ -1593,7 +1669,7 @@ function parseArgs(args) {
|
|
|
1593
1669
|
throw new Error("--product-name and --name cannot be used together");
|
|
1594
1670
|
}
|
|
1595
1671
|
return {
|
|
1596
|
-
repoPath:
|
|
1672
|
+
repoPath: resolve3(repoPath ?? "."),
|
|
1597
1673
|
outDir,
|
|
1598
1674
|
...minScore != null ? { minScore } : {},
|
|
1599
1675
|
...productName ? { productName } : {},
|
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-TOQPQPDF.js";
|
|
7
|
+
import "../chunk-ZZHQZW26.js";
|
|
8
8
|
import "../chunk-VGBFZBZQ.js";
|
|
9
9
|
import "../chunk-FSMZV3Y6.js";
|
|
10
10
|
import {
|