@cejel/cejel 0.6.6 → 0.6.8
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 +27 -7
- package/dist/calibration/llm-detector.js +5 -5
- package/dist/{chunk-RH6FKREX.js → chunk-6LVNNJTG.js} +1 -1
- package/dist/{chunk-FSMZV3Y6.js → chunk-AMVP7L26.js} +1 -1
- package/dist/{chunk-O3MHSK25.js → chunk-AWLKQUI4.js} +56 -6
- package/dist/{chunk-JNTTFAHQ.js → chunk-KJVFCZZ3.js} +2784 -223
- package/dist/{chunk-BG4ZRBQ5.js → chunk-KNTBED5T.js} +3 -3
- package/dist/{chunk-VGBFZBZQ.js → chunk-NIWSYJ6N.js} +1 -1
- package/dist/{chunk-5PFYOIOS.js → chunk-WXPGEQBE.js} +2 -2
- package/dist/index.js +219 -56
- package/dist/mcp/index.js +5 -5
- package/dist/packs/d-series/index.js +4 -4
- package/dist/packs/decision-contracts/index.js +3 -3
- package/package.json +1 -1
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.8 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.8` 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
|
|
|
@@ -159,6 +159,10 @@ The npm package is scoped as `@cejel/cejel`; its executable remains the short co
|
|
|
159
159
|
|
|
160
160
|
`actions/checkout` fetches one commit by default. On a shallow clone, A2 and B2 see only that
|
|
161
161
|
commit, and the certificate says so under "History limitations".
|
|
162
|
+
Under the prospective v27 rubric (`--rubric-pin witan-rubric-v27-prospective-2026-10-19`), a
|
|
163
|
+
shallow clone goes further. A2 abstains unless a confirmed critical secret finding stands or A2
|
|
164
|
+
does not apply. B2 abstains, where it would be scored, when fewer than 12 commits are visible. Each
|
|
165
|
+
abstention counts as 0 in the composite, so a shallow checkout can lower the v27 score.
|
|
162
166
|
|
|
163
167
|
For an executed public example that binds a release artifact to the same commit named by its
|
|
164
168
|
Cejel certificate, see [Certified releases with GitHub build provenance](./docs/certified-release-example.md).
|
|
@@ -187,16 +191,16 @@ gh attestation verify ./cejel-Windows-x86_64.exe -R BargLabs/cejel
|
|
|
187
191
|
This is cryptographically signed provenance. It is distinct from Apple Developer ID or
|
|
188
192
|
Microsoft Authenticode code-signing.
|
|
189
193
|
|
|
190
|
-
**Docker / OCI.** The current container release is `0.6.
|
|
194
|
+
**Docker / OCI.** The current container release is `0.6.8`:
|
|
191
195
|
|
|
192
196
|
```bash
|
|
193
|
-
docker run --rm -i -v "$PWD:/workspace:ro" ghcr.io/barglabs/cejel:0.6.
|
|
197
|
+
docker run --rm -i -v "$PWD:/workspace:ro" ghcr.io/barglabs/cejel:0.6.8
|
|
194
198
|
```
|
|
195
199
|
|
|
196
200
|
The image defaults to `cejel-mcp` over stdio. To use the CLI instead:
|
|
197
201
|
|
|
198
202
|
```bash
|
|
199
|
-
docker run --rm -v "$PWD:/workspace:ro" --entrypoint cejel ghcr.io/barglabs/cejel:0.6.
|
|
203
|
+
docker run --rm -v "$PWD:/workspace:ro" --entrypoint cejel ghcr.io/barglabs/cejel:0.6.8 .
|
|
200
204
|
```
|
|
201
205
|
|
|
202
206
|
The OCI image carries an SBOM of its base-image packages, maximum-mode build provenance, and a
|
|
@@ -296,6 +300,12 @@ prints that boundary on every successful verification.
|
|
|
296
300
|
- `--ingest <file|glob>` — fold another scanner's output into the score (repeatable). Accepts
|
|
297
301
|
SARIF, OpenSSF Scorecard JSON, or the generic Cejel external-signal shape — format is
|
|
298
302
|
auto-detected. See "Aggregate your scanners" below.
|
|
303
|
+
- `--subject-repository <repo>` — name the scanned repository (`github.com/owner/repo` or a clone
|
|
304
|
+
URL) so an ingested input that declares another repository is recorded as mismatched. Cejel
|
|
305
|
+
never infers it from clone state.
|
|
306
|
+
- `--strict-ingest` — refuse, before scoring, an ingested input that declares another repository or
|
|
307
|
+
commit, was observed before the scanned commit existed, or duplicates another input. Without it,
|
|
308
|
+
the binding status is recorded and scoring is unchanged. See [input binding](docs/input-binding.md).
|
|
299
309
|
- `--rubric-pin <version>` — Explicit opt-in only: pin an alternate rubric instead of the
|
|
300
310
|
calibrated public default. It
|
|
301
311
|
accepts the calibrated version or any published prospective rubric
|
|
@@ -414,7 +424,17 @@ Three ways a scanner's output gets ingested:
|
|
|
414
424
|
versions rather than guessing. See the [generic ingest contract](docs/ingest-contract.md), its
|
|
415
425
|
[published JSON Schema](docs/schemas/cejel-ingest-v1.schema.json), and the
|
|
416
426
|
[synthetic CI heal-log mapping](docs/heal-log-mapping.md). Output-field stability and version
|
|
417
|
-
routing are documented in [format stability](docs/format-stability.md).
|
|
427
|
+
routing are documented in [format stability](docs/format-stability.md). Contract `1.1` adds
|
|
428
|
+
optional `subject`, `producer` and `observedAt` fields so the input can be bound to a revision.
|
|
429
|
+
|
|
430
|
+
Every ingested document is also recorded in `report.json` under `inputBinding`: the sha256 of its
|
|
431
|
+
bytes, the producer and subject its own format declares (Scorecard `repo.name`/`repo.commit`/`date`,
|
|
432
|
+
SARIF `versionControlProvenance` and `invocations`, generic `subject`/`observedAt`), and whether that
|
|
433
|
+
subject is the scanned HEAD (`matched`, `mismatched-repository`, `mismatched-commit`, `stale`,
|
|
434
|
+
`unbound`, `unverifiable`). By default this is a record, not a gate: it changes no score.
|
|
435
|
+
`--strict-ingest` refuses mismatched, stale and duplicate inputs instead. `cejel verify ... --input
|
|
436
|
+
<file>` checks a set of input files against the recorded digests, so a swapped input is detected.
|
|
437
|
+
See [input binding](docs/input-binding.md), which carries the conformance table the tests run.
|
|
418
438
|
|
|
419
439
|
## Displaying the trust badge
|
|
420
440
|
|
|
@@ -571,7 +591,7 @@ The OCI image is an alternative when Docker is the preferred execution boundary.
|
|
|
571
591
|
the host path with the repository OpenClaw should allow Cejel to read:
|
|
572
592
|
|
|
573
593
|
```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.
|
|
594
|
+
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.8"]}'
|
|
575
595
|
npx -y openclaw@latest mcp doctor cejel-oci --probe
|
|
576
596
|
```
|
|
577
597
|
|
|
@@ -5,20 +5,20 @@ import {
|
|
|
5
5
|
deriveProductIdentity,
|
|
6
6
|
runCejelScan,
|
|
7
7
|
serializeWitanReport
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-KJVFCZZ3.js";
|
|
9
9
|
import {
|
|
10
10
|
listCejelLlmPackFiles
|
|
11
|
-
} from "../chunk-
|
|
12
|
-
import "../chunk-
|
|
11
|
+
} from "../chunk-WXPGEQBE.js";
|
|
12
|
+
import "../chunk-NIWSYJ6N.js";
|
|
13
13
|
import {
|
|
14
14
|
external_exports
|
|
15
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-AMVP7L26.js";
|
|
16
16
|
import {
|
|
17
17
|
init_esm_shims,
|
|
18
18
|
readRepoText,
|
|
19
19
|
recordContentSkip,
|
|
20
20
|
recordFilesystemSkip
|
|
21
|
-
} from "../chunk-
|
|
21
|
+
} from "../chunk-AWLKQUI4.js";
|
|
22
22
|
|
|
23
23
|
// src/calibration/llm-detector.ts
|
|
24
24
|
init_esm_shims();
|
|
@@ -62,7 +62,11 @@ var MAX_REPOSITORY_CONTENT_BYTES = 512e3;
|
|
|
62
62
|
init_esm_shims();
|
|
63
63
|
import { closeSync, lstatSync, openSync, readFileSync, readSync } from "fs";
|
|
64
64
|
import { resolve } from "path";
|
|
65
|
-
var READ_FAILURE_REASONS = /* @__PURE__ */ new Set([
|
|
65
|
+
var READ_FAILURE_REASONS = /* @__PURE__ */ new Set([
|
|
66
|
+
"unreadable",
|
|
67
|
+
"denied_path",
|
|
68
|
+
"lfs_pointer"
|
|
69
|
+
]);
|
|
66
70
|
function isReadFailureReason(reason) {
|
|
67
71
|
return READ_FAILURE_REASONS.has(reason);
|
|
68
72
|
}
|
|
@@ -131,7 +135,10 @@ function summaryFor(session) {
|
|
|
131
135
|
tooLarge: session.counts.too_large,
|
|
132
136
|
excludedByExtension: session.counts.excluded_by_extension,
|
|
133
137
|
deniedPath: session.counts.denied_path,
|
|
134
|
-
nonRegularFile: session.counts.non_regular_file
|
|
138
|
+
nonRegularFile: session.counts.non_regular_file,
|
|
139
|
+
// Present only when non-zero, so every report without an LFS pointer is byte-identical to one
|
|
140
|
+
// produced before this reason existed (report format 1.6).
|
|
141
|
+
...session.counts.lfs_pointer > 0 ? { lfsPointer: session.counts.lfs_pointer } : {}
|
|
135
142
|
};
|
|
136
143
|
const sortedErrnos = Object.fromEntries(
|
|
137
144
|
[...session.unreadableByErrno.entries()].sort(([left], [right]) => left.localeCompare(right))
|
|
@@ -143,7 +150,7 @@ function summaryFor(session) {
|
|
|
143
150
|
affectedCriteria: [...session.affectedCriteria].sort()
|
|
144
151
|
};
|
|
145
152
|
}
|
|
146
|
-
function trackContentReads(_repoPath, collect) {
|
|
153
|
+
function trackContentReads(_repoPath, collect, options = {}) {
|
|
147
154
|
const existing = activeSession;
|
|
148
155
|
if (existing) {
|
|
149
156
|
return {
|
|
@@ -162,8 +169,10 @@ function trackContentReads(_repoPath, collect) {
|
|
|
162
169
|
too_large: 0,
|
|
163
170
|
excluded_by_extension: 0,
|
|
164
171
|
denied_path: 0,
|
|
165
|
-
non_regular_file: 0
|
|
172
|
+
non_regular_file: 0,
|
|
173
|
+
lfs_pointer: 0
|
|
166
174
|
},
|
|
175
|
+
lfsPointerAbstention: options.lfsPointerAbstention === true,
|
|
167
176
|
unreadableByErrno: /* @__PURE__ */ new Map(),
|
|
168
177
|
deduplicatedSkips: /* @__PURE__ */ new Set(),
|
|
169
178
|
affectedCriteria: /* @__PURE__ */ new Set(),
|
|
@@ -218,6 +227,20 @@ function withContentReadSignals(criterionId, signalIds, collect) {
|
|
|
218
227
|
session.signals = previous;
|
|
219
228
|
}
|
|
220
229
|
}
|
|
230
|
+
function withoutContentReadAttribution(collect) {
|
|
231
|
+
const session = activeSession;
|
|
232
|
+
if (!session) return collect();
|
|
233
|
+
const previousCriterion = session.criterion;
|
|
234
|
+
const previousSignals = session.signals;
|
|
235
|
+
session.criterion = void 0;
|
|
236
|
+
session.signals = void 0;
|
|
237
|
+
try {
|
|
238
|
+
return collect();
|
|
239
|
+
} finally {
|
|
240
|
+
session.criterion = previousCriterion;
|
|
241
|
+
session.signals = previousSignals;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
221
244
|
function recordContentSkip(path2, reason, deduplicate = false) {
|
|
222
245
|
recordSkip(path2, reason, void 0, false, deduplicate);
|
|
223
246
|
}
|
|
@@ -287,12 +310,33 @@ function readRepoText(path2, encoding = "utf8") {
|
|
|
287
310
|
recordFilesystemSkip(path2, error);
|
|
288
311
|
return "";
|
|
289
312
|
}
|
|
313
|
+
let contents;
|
|
290
314
|
try {
|
|
291
|
-
|
|
315
|
+
contents = readFileSync(path2, encoding);
|
|
292
316
|
} catch (error) {
|
|
293
317
|
recordFilesystemSkip(path2, error);
|
|
294
318
|
return "";
|
|
295
319
|
}
|
|
320
|
+
if (isGitLfsPointerText(contents)) {
|
|
321
|
+
recordSkip(path2, "lfs_pointer", void 0, activeSession?.lfsPointerAbstention === true, true);
|
|
322
|
+
}
|
|
323
|
+
return contents;
|
|
324
|
+
}
|
|
325
|
+
var GIT_LFS_POINTER_MAX_BYTES = 1024;
|
|
326
|
+
var GIT_LFS_POINTER_VERSION_LINE = /^version https:\/\/(?:git-lfs\.github\.com\/spec\/v1|hawser\.github\.com\/spec\/v1)\n/;
|
|
327
|
+
var GIT_LFS_POINTER_OID_LINE = /^oid sha256:[0-9a-f]{64}$/m;
|
|
328
|
+
var GIT_LFS_POINTER_SIZE_LINE = /^size [0-9]+$/m;
|
|
329
|
+
var GIT_LFS_POINTER_KEY_LINE = /^[a-z0-9.-]+ \S[^\n]*$/;
|
|
330
|
+
function isGitLfsPointerText(contents) {
|
|
331
|
+
if (isLfGitLfsPointerText(contents)) return true;
|
|
332
|
+
return contents.length < 2 * GIT_LFS_POINTER_MAX_BYTES && contents.includes("\r\n") && !/\r(?!\n)/.test(contents) && !/(?:^|[^\r])\n/.test(contents) && isLfGitLfsPointerText(contents.replaceAll("\r\n", "\n"));
|
|
333
|
+
}
|
|
334
|
+
function isLfGitLfsPointerText(contents) {
|
|
335
|
+
if (contents.length >= GIT_LFS_POINTER_MAX_BYTES || !contents.startsWith("version ")) return false;
|
|
336
|
+
if (!GIT_LFS_POINTER_VERSION_LINE.test(contents)) return false;
|
|
337
|
+
const lines = contents.replace(/\n$/, "").split("\n");
|
|
338
|
+
if (!lines.slice(1).every((line) => GIT_LFS_POINTER_KEY_LINE.test(line))) return false;
|
|
339
|
+
return GIT_LFS_POINTER_OID_LINE.test(contents) && GIT_LFS_POINTER_SIZE_LINE.test(contents);
|
|
296
340
|
}
|
|
297
341
|
function readRepoTextPrefix(path2, byteLimit) {
|
|
298
342
|
try {
|
|
@@ -310,7 +354,11 @@ function readRepoTextPrefix(path2, byteLimit) {
|
|
|
310
354
|
descriptor = openSync(path2, "r");
|
|
311
355
|
const buffer = Buffer.allocUnsafe(byteLimit);
|
|
312
356
|
const bytesRead = readSync(descriptor, buffer, 0, byteLimit, 0);
|
|
313
|
-
|
|
357
|
+
const contents = buffer.subarray(0, bytesRead).toString("utf8");
|
|
358
|
+
if (bytesRead < byteLimit && isGitLfsPointerText(contents)) {
|
|
359
|
+
recordSkip(path2, "lfs_pointer", void 0, activeSession?.lfsPointerAbstention === true, true);
|
|
360
|
+
}
|
|
361
|
+
return contents;
|
|
314
362
|
} catch (error) {
|
|
315
363
|
recordFilesystemSkip(path2, error);
|
|
316
364
|
return "";
|
|
@@ -340,11 +388,13 @@ export {
|
|
|
340
388
|
withContentReadCriterion,
|
|
341
389
|
withContentReadSignal,
|
|
342
390
|
withContentReadSignals,
|
|
391
|
+
withoutContentReadAttribution,
|
|
343
392
|
recordContentSkip,
|
|
344
393
|
registerWithheldRepoPath,
|
|
345
394
|
withheldRepoPaths,
|
|
346
395
|
abstainSignalOnWithheldPaths,
|
|
347
396
|
recordFilesystemSkip,
|
|
348
397
|
readRepoText,
|
|
398
|
+
isGitLfsPointerText,
|
|
349
399
|
readRepoTextPrefix
|
|
350
400
|
};
|