@cejel/cejel 0.1.2 → 0.1.4
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 +656 -10
- package/README.md +95 -11
- package/dist/{chunk-MBYVOPJR.js → chunk-SQNTNX5U.js} +1027 -2337
- package/dist/index.js +13 -4
- package/dist/mcp/index.js +216 -216
- package/package.json +9 -7
|
@@ -29,7 +29,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
29
29
|
mod
|
|
30
30
|
));
|
|
31
31
|
|
|
32
|
-
//
|
|
32
|
+
// src/witan/external-findings.ts
|
|
33
33
|
var EXTERNAL_FINDINGS_DISPLAY_LIMIT = 10;
|
|
34
34
|
var SEVERITY_RANK = {
|
|
35
35
|
critical: 0,
|
|
@@ -82,7 +82,7 @@ function collectExternalFindings(consumedSignals) {
|
|
|
82
82
|
});
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
//
|
|
85
|
+
// src/witan/html.ts
|
|
86
86
|
function renderWitanHtmlReport(report) {
|
|
87
87
|
const codeCriteria = criteriaByCategory(report, "code_trust");
|
|
88
88
|
const processCriteria = criteriaByCategory(report, "process_trust");
|
|
@@ -106,7 +106,7 @@ function renderWitanHtmlReport(report) {
|
|
|
106
106
|
<header class="hero">
|
|
107
107
|
<div class="brand">
|
|
108
108
|
<span class="brand-mark" aria-hidden="true">C</span>
|
|
109
|
-
<span class="brand-name">Cejel
|
|
109
|
+
<span class="brand-name">Cejel</span>
|
|
110
110
|
</div>
|
|
111
111
|
<div class="hero-grid">
|
|
112
112
|
<section>
|
|
@@ -403,7 +403,7 @@ a:hover { text-decoration: underline; text-underline-offset: 2px; }
|
|
|
403
403
|
}
|
|
404
404
|
`;
|
|
405
405
|
|
|
406
|
-
//
|
|
406
|
+
// src/witan/badge.ts
|
|
407
407
|
var VERDICT_COLOR = {
|
|
408
408
|
Verified: "brightgreen",
|
|
409
409
|
Conditional: "yellow",
|
|
@@ -470,15 +470,10 @@ function escapeXml(value) {
|
|
|
470
470
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
471
471
|
}
|
|
472
472
|
|
|
473
|
-
//
|
|
474
|
-
import {
|
|
475
|
-
import { join } from "path";
|
|
476
|
-
|
|
477
|
-
// ../witan/src/leaderboard.ts
|
|
478
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync8, writeFileSync as writeFileSync2 } from "fs";
|
|
479
|
-
import { join as join6 } from "path";
|
|
473
|
+
// src/witan/attestation.ts
|
|
474
|
+
import { createHash } from "crypto";
|
|
480
475
|
|
|
481
|
-
//
|
|
476
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
|
|
482
477
|
var external_exports = {};
|
|
483
478
|
__export(external_exports, {
|
|
484
479
|
BRAND: () => BRAND,
|
|
@@ -590,7 +585,7 @@ __export(external_exports, {
|
|
|
590
585
|
void: () => voidType
|
|
591
586
|
});
|
|
592
587
|
|
|
593
|
-
//
|
|
588
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js
|
|
594
589
|
var util;
|
|
595
590
|
(function(util2) {
|
|
596
591
|
util2.assertEqual = (_) => {
|
|
@@ -724,7 +719,7 @@ var getParsedType = (data) => {
|
|
|
724
719
|
}
|
|
725
720
|
};
|
|
726
721
|
|
|
727
|
-
//
|
|
722
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js
|
|
728
723
|
var ZodIssueCode = util.arrayToEnum([
|
|
729
724
|
"invalid_type",
|
|
730
725
|
"invalid_literal",
|
|
@@ -842,7 +837,7 @@ ZodError.create = (issues) => {
|
|
|
842
837
|
return error;
|
|
843
838
|
};
|
|
844
839
|
|
|
845
|
-
//
|
|
840
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js
|
|
846
841
|
var errorMap = (issue, _ctx) => {
|
|
847
842
|
let message;
|
|
848
843
|
switch (issue.code) {
|
|
@@ -945,7 +940,7 @@ var errorMap = (issue, _ctx) => {
|
|
|
945
940
|
};
|
|
946
941
|
var en_default = errorMap;
|
|
947
942
|
|
|
948
|
-
//
|
|
943
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js
|
|
949
944
|
var overrideErrorMap = en_default;
|
|
950
945
|
function setErrorMap(map) {
|
|
951
946
|
overrideErrorMap = map;
|
|
@@ -954,7 +949,7 @@ function getErrorMap() {
|
|
|
954
949
|
return overrideErrorMap;
|
|
955
950
|
}
|
|
956
951
|
|
|
957
|
-
//
|
|
952
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
958
953
|
var makeIssue = (params) => {
|
|
959
954
|
const { data, path, errorMaps, issueData } = params;
|
|
960
955
|
const fullPath = [...path, ...issueData.path || []];
|
|
@@ -1064,14 +1059,14 @@ var isDirty = (x) => x.status === "dirty";
|
|
|
1064
1059
|
var isValid = (x) => x.status === "valid";
|
|
1065
1060
|
var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
|
|
1066
1061
|
|
|
1067
|
-
//
|
|
1062
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js
|
|
1068
1063
|
var errorUtil;
|
|
1069
1064
|
(function(errorUtil2) {
|
|
1070
1065
|
errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {};
|
|
1071
1066
|
errorUtil2.toString = (message) => typeof message === "string" ? message : message?.message;
|
|
1072
1067
|
})(errorUtil || (errorUtil = {}));
|
|
1073
1068
|
|
|
1074
|
-
//
|
|
1069
|
+
// node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
1075
1070
|
var ParseInputLazyPath = class {
|
|
1076
1071
|
constructor(parent, value, path, key) {
|
|
1077
1072
|
this._cachedPath = [];
|
|
@@ -4519,849 +4514,7 @@ var coerce = {
|
|
|
4519
4514
|
};
|
|
4520
4515
|
var NEVER = INVALID;
|
|
4521
4516
|
|
|
4522
|
-
//
|
|
4523
|
-
var attestationOutcomeSchema = external_exports.enum([
|
|
4524
|
-
"ATTESTED_READY",
|
|
4525
|
-
"ATTESTED_WITH_GAPS",
|
|
4526
|
-
"NOT_READY",
|
|
4527
|
-
"REVOKED"
|
|
4528
|
-
]);
|
|
4529
|
-
var attestationKindSchema = external_exports.enum(["OPERATOR_READINESS", "EXTERNAL_ASSESSOR_REFERENCE"]);
|
|
4530
|
-
var attestationEvidenceRefKindSchema = external_exports.enum([
|
|
4531
|
-
"runbook_path",
|
|
4532
|
-
"github_run_url",
|
|
4533
|
-
"vercel_deployment_id",
|
|
4534
|
-
"neon_query_evidence",
|
|
4535
|
-
"report_hash",
|
|
4536
|
-
"external_assessor_ref"
|
|
4537
|
-
]);
|
|
4538
|
-
var attestationEvidenceRefSchema = external_exports.object({
|
|
4539
|
-
kind: attestationEvidenceRefKindSchema,
|
|
4540
|
-
/** Redacted reference string (path, URL, ID, or hash). Max 512 chars. */
|
|
4541
|
-
ref: external_exports.string().min(1).max(512),
|
|
4542
|
-
/** Optional one-line redacted description. */
|
|
4543
|
-
note: external_exports.string().max(280).optional()
|
|
4544
|
-
});
|
|
4545
|
-
var createAttestationInputSchema = external_exports.object({
|
|
4546
|
-
studioId: external_exports.string().uuid(),
|
|
4547
|
-
complianceProfileId: external_exports.string().uuid(),
|
|
4548
|
-
productId: external_exports.string().uuid().nullable().optional(),
|
|
4549
|
-
framework: external_exports.string().min(1).max(120),
|
|
4550
|
-
kind: attestationKindSchema,
|
|
4551
|
-
outcome: attestationOutcomeSchema,
|
|
4552
|
-
/** Redacted operator statement; no payloads. */
|
|
4553
|
-
statement: external_exports.string().min(1).max(4e3),
|
|
4554
|
-
evidenceRefs: external_exports.array(attestationEvidenceRefSchema).min(1),
|
|
4555
|
-
supersedesAttestationId: external_exports.string().uuid().nullable().optional(),
|
|
4556
|
-
metadata: external_exports.record(external_exports.unknown()).default({})
|
|
4557
|
-
});
|
|
4558
|
-
|
|
4559
|
-
// ../shared/src/types/standup-provisioning.ts
|
|
4560
|
-
var ScaffoldFileSchema = external_exports.object({
|
|
4561
|
-
path: external_exports.string().min(1),
|
|
4562
|
-
contents: external_exports.string()
|
|
4563
|
-
}).strict();
|
|
4564
|
-
var ScaffoldManifestSchema = external_exports.array(ScaffoldFileSchema).min(1);
|
|
4565
|
-
var RepoRefSchema = external_exports.object({
|
|
4566
|
-
studioId: external_exports.string().uuid(),
|
|
4567
|
-
owner: external_exports.string().min(1),
|
|
4568
|
-
// GitHub org/account that owns the repo
|
|
4569
|
-
name: external_exports.string().min(1),
|
|
4570
|
-
fullName: external_exports.string().min(1),
|
|
4571
|
-
// owner/name
|
|
4572
|
-
htmlUrl: external_exports.string().url(),
|
|
4573
|
-
defaultBranch: external_exports.string().min(1).default("main")
|
|
4574
|
-
}).strict();
|
|
4575
|
-
var ScopedTokenSchema = external_exports.object({
|
|
4576
|
-
token: external_exports.string().min(1),
|
|
4577
|
-
expiresAt: external_exports.string(),
|
|
4578
|
-
// ISO-8601
|
|
4579
|
-
scope: external_exports.string().min(1)
|
|
4580
|
-
// human-readable, e.g. "contents:write on owner/name"
|
|
4581
|
-
}).strict();
|
|
4582
|
-
var BranchProtectionStatusSchema = external_exports.object({
|
|
4583
|
-
protected: external_exports.boolean(),
|
|
4584
|
-
requiresPullRequestReview: external_exports.boolean(),
|
|
4585
|
-
requiredApprovingReviewCount: external_exports.number().int().nonnegative(),
|
|
4586
|
-
allowsForcePushes: external_exports.boolean(),
|
|
4587
|
-
allowsDeletions: external_exports.boolean()
|
|
4588
|
-
}).strict();
|
|
4589
|
-
var RenderParamsSchema = external_exports.object({
|
|
4590
|
-
productName: external_exports.string().min(1),
|
|
4591
|
-
slug: external_exports.string().min(1),
|
|
4592
|
-
vertical: external_exports.string().min(1)
|
|
4593
|
-
}).strict();
|
|
4594
|
-
var TemplateInputFieldSchema = external_exports.object({
|
|
4595
|
-
name: external_exports.string().min(1),
|
|
4596
|
-
label: external_exports.string().min(1),
|
|
4597
|
-
inputType: external_exports.enum(["text", "number", "date", "slug"]),
|
|
4598
|
-
required: external_exports.boolean().default(true),
|
|
4599
|
-
helperText: external_exports.string().min(1),
|
|
4600
|
-
example: external_exports.string().min(1),
|
|
4601
|
-
defaultValue: external_exports.string().optional()
|
|
4602
|
-
}).strict();
|
|
4603
|
-
var TemplateInputSchema = external_exports.object({
|
|
4604
|
-
fields: external_exports.array(TemplateInputFieldSchema).min(1)
|
|
4605
|
-
}).strict();
|
|
4606
|
-
var TemplateDescriptorSchema = external_exports.object({
|
|
4607
|
-
templateRef: external_exports.string().min(1),
|
|
4608
|
-
vertical: external_exports.string().min(1),
|
|
4609
|
-
description: external_exports.string().default(""),
|
|
4610
|
-
inputSchema: TemplateInputSchema.optional()
|
|
4611
|
-
}).strict();
|
|
4612
|
-
var StandupDryRunPlanSchema = external_exports.object({
|
|
4613
|
-
planOnly: external_exports.literal(true),
|
|
4614
|
-
planOnlyMessage: external_exports.string().min(1),
|
|
4615
|
-
product: external_exports.object({
|
|
4616
|
-
studioId: external_exports.string().min(1),
|
|
4617
|
-
productId: external_exports.string().min(1),
|
|
4618
|
-
name: external_exports.string().min(1),
|
|
4619
|
-
slug: external_exports.string().min(1),
|
|
4620
|
-
vertical: external_exports.string().min(1)
|
|
4621
|
-
}).strict(),
|
|
4622
|
-
targetRepo: external_exports.object({
|
|
4623
|
-
owner: external_exports.string().min(1),
|
|
4624
|
-
name: external_exports.string().min(1),
|
|
4625
|
-
fullName: external_exports.string().min(1),
|
|
4626
|
-
defaultBranch: external_exports.string().min(1),
|
|
4627
|
-
plannedState: external_exports.literal("would_create"),
|
|
4628
|
-
exists: external_exports.literal(false)
|
|
4629
|
-
}).strict(),
|
|
4630
|
-
template: TemplateDescriptorSchema,
|
|
4631
|
-
scaffold: external_exports.object({
|
|
4632
|
-
label: external_exports.literal("scaffold (template output)"),
|
|
4633
|
-
files: ScaffoldManifestSchema
|
|
4634
|
-
}).strict(),
|
|
4635
|
-
buildAgentSeed: external_exports.object({
|
|
4636
|
-
label: external_exports.literal("build-agent instructions (not yet run)"),
|
|
4637
|
-
instructions: external_exports.array(external_exports.string().min(1)).min(1),
|
|
4638
|
-
product: external_exports.object({
|
|
4639
|
-
name: external_exports.string().min(1),
|
|
4640
|
-
slug: external_exports.string().min(1),
|
|
4641
|
-
vertical: external_exports.string().min(1)
|
|
4642
|
-
}).strict(),
|
|
4643
|
-
repoFullName: external_exports.string().min(1)
|
|
4644
|
-
}).strict(),
|
|
4645
|
-
safetyEnvelope: external_exports.object({
|
|
4646
|
-
estimatedCostUsd: external_exports.number().finite().nonnegative(),
|
|
4647
|
-
costCapUsd: external_exports.number().finite().nonnegative(),
|
|
4648
|
-
networkPolicy: external_exports.object({
|
|
4649
|
-
mode: external_exports.literal("restricted"),
|
|
4650
|
-
allowedHosts: external_exports.array(external_exports.string().min(1)).min(1)
|
|
4651
|
-
}).strict(),
|
|
4652
|
-
scopedToken: external_exports.object({
|
|
4653
|
-
tokenMinted: external_exports.literal(false),
|
|
4654
|
-
scope: external_exports.string().min(1),
|
|
4655
|
-
ttlSeconds: external_exports.number().int().positive()
|
|
4656
|
-
}).strict()
|
|
4657
|
-
}).strict()
|
|
4658
|
-
}).strict();
|
|
4659
|
-
var ConstructionWorkflowArtifactKindSchema = external_exports.enum([
|
|
4660
|
-
"profile",
|
|
4661
|
-
"milestone_schedule",
|
|
4662
|
-
"risk_register",
|
|
4663
|
-
"submittal_register",
|
|
4664
|
-
"long_lead_log",
|
|
4665
|
-
"rfi_log",
|
|
4666
|
-
"responsibility_matrix"
|
|
4667
|
-
]);
|
|
4668
|
-
var IsoDateSchema = external_exports.string().regex(/^\d{4}-\d{2}-\d{2}$/);
|
|
4669
|
-
var ConstructionWorkflowTemplateDescriptorSchema = external_exports.object({
|
|
4670
|
-
templateRef: external_exports.string().min(1),
|
|
4671
|
-
workflowKind: external_exports.literal("construction_project"),
|
|
4672
|
-
templateKind: external_exports.literal("workflow_documents"),
|
|
4673
|
-
name: external_exports.string().min(1),
|
|
4674
|
-
description: external_exports.string().default(""),
|
|
4675
|
-
artifacts: external_exports.array(ConstructionWorkflowArtifactKindSchema).min(1),
|
|
4676
|
-
inputSchema: TemplateInputSchema
|
|
4677
|
-
}).strict();
|
|
4678
|
-
var ConstructionProjectSeedSchema = external_exports.object({
|
|
4679
|
-
projectName: external_exports.string().min(1).max(120),
|
|
4680
|
-
areaSqFt: external_exports.number().int().positive(),
|
|
4681
|
-
projectType: external_exports.string().min(1).max(120),
|
|
4682
|
-
buildingName: external_exports.string().min(1).max(160),
|
|
4683
|
-
ntpDate: IsoDateSchema,
|
|
4684
|
-
scheduleTargetDate: IsoDateSchema
|
|
4685
|
-
}).strict();
|
|
4686
|
-
var ConstructionMilestoneSchema = external_exports.object({
|
|
4687
|
-
id: external_exports.string().min(1),
|
|
4688
|
-
name: external_exports.string().min(1),
|
|
4689
|
-
targetDate: IsoDateSchema,
|
|
4690
|
-
status: external_exports.enum(["planned", "at_risk", "slipped", "complete"])
|
|
4691
|
-
}).strict();
|
|
4692
|
-
var ConstructionSubmittalSchema = external_exports.object({
|
|
4693
|
-
id: external_exports.string().min(1),
|
|
4694
|
-
item: external_exports.string().min(1),
|
|
4695
|
-
division: external_exports.string().min(1),
|
|
4696
|
-
needByDate: IsoDateSchema,
|
|
4697
|
-
status: external_exports.enum(["not_started", "open", "in_review", "approved", "done"])
|
|
4698
|
-
}).strict();
|
|
4699
|
-
var ConstructionRfiSchema = external_exports.object({
|
|
4700
|
-
id: external_exports.string().min(1),
|
|
4701
|
-
subject: external_exports.string().min(1),
|
|
4702
|
-
to: external_exports.string().min(1),
|
|
4703
|
-
status: external_exports.enum(["draft", "open", "answered", "closed"]),
|
|
4704
|
-
openedDate: IsoDateSchema
|
|
4705
|
-
}).strict();
|
|
4706
|
-
var ConstructionRiskSchema = external_exports.object({
|
|
4707
|
-
id: external_exports.string().min(1),
|
|
4708
|
-
risk: external_exports.string().min(1),
|
|
4709
|
-
rating: external_exports.enum(["low", "medium", "high"]),
|
|
4710
|
-
mitigation: external_exports.string().min(1),
|
|
4711
|
-
confidence: external_exports.number().min(0).max(1)
|
|
4712
|
-
}).strict();
|
|
4713
|
-
var ConstructionLongLeadItemSchema = external_exports.object({
|
|
4714
|
-
id: external_exports.string().min(1),
|
|
4715
|
-
item: external_exports.string().min(1),
|
|
4716
|
-
needByDate: IsoDateSchema,
|
|
4717
|
-
status: external_exports.enum(["tracking", "ordered", "received", "done"]),
|
|
4718
|
-
assumption: external_exports.string().min(1)
|
|
4719
|
-
}).strict();
|
|
4720
|
-
var ConstructionResponsibilitySchema = external_exports.object({
|
|
4721
|
-
id: external_exports.string().min(1),
|
|
4722
|
-
role: external_exports.string().min(1),
|
|
4723
|
-
owner: external_exports.string().min(1),
|
|
4724
|
-
responsibility: external_exports.string().min(1)
|
|
4725
|
-
}).strict();
|
|
4726
|
-
var ConstructionMarkdownArtifactSchema = external_exports.object({
|
|
4727
|
-
kind: ConstructionWorkflowArtifactKindSchema,
|
|
4728
|
-
path: external_exports.string().min(1),
|
|
4729
|
-
markdown: external_exports.string().min(1)
|
|
4730
|
-
}).strict();
|
|
4731
|
-
var ConstructionWorkflowArtifactSetSchema = external_exports.object({
|
|
4732
|
-
projectName: external_exports.string().min(1),
|
|
4733
|
-
generatedAt: external_exports.string().datetime(),
|
|
4734
|
-
assumptions: external_exports.array(external_exports.string().min(1)).default([]),
|
|
4735
|
-
needsPmData: external_exports.array(external_exports.string().min(1)).default([]),
|
|
4736
|
-
markdownArtifacts: external_exports.array(ConstructionMarkdownArtifactSchema).min(1),
|
|
4737
|
-
structured: external_exports.object({
|
|
4738
|
-
milestones: external_exports.array(ConstructionMilestoneSchema),
|
|
4739
|
-
submittals: external_exports.array(ConstructionSubmittalSchema),
|
|
4740
|
-
rfis: external_exports.array(ConstructionRfiSchema),
|
|
4741
|
-
risks: external_exports.array(ConstructionRiskSchema),
|
|
4742
|
-
longLeadItems: external_exports.array(ConstructionLongLeadItemSchema),
|
|
4743
|
-
responsibilities: external_exports.array(ConstructionResponsibilitySchema)
|
|
4744
|
-
}).strict()
|
|
4745
|
-
}).strict();
|
|
4746
|
-
var ConstructionWorkflowDryRunPlanSchema = external_exports.object({
|
|
4747
|
-
planOnly: external_exports.literal(true),
|
|
4748
|
-
planOnlyMessage: external_exports.string().min(1),
|
|
4749
|
-
product: external_exports.object({
|
|
4750
|
-
studioId: external_exports.string().min(1),
|
|
4751
|
-
productId: external_exports.string().min(1),
|
|
4752
|
-
name: external_exports.string().min(1),
|
|
4753
|
-
vertical: external_exports.string().min(1)
|
|
4754
|
-
}).strict(),
|
|
4755
|
-
template: ConstructionWorkflowTemplateDescriptorSchema,
|
|
4756
|
-
seed: ConstructionProjectSeedSchema,
|
|
4757
|
-
safetyEnvelope: external_exports.object({
|
|
4758
|
-
executor: external_exports.literal("benign_workflow_populator"),
|
|
4759
|
-
sandboxUsed: external_exports.literal(false),
|
|
4760
|
-
scopedTokenMinted: external_exports.literal(false),
|
|
4761
|
-
externalWritesAllowed: external_exports.literal(false),
|
|
4762
|
-
workspaceWriteMode: external_exports.literal("markdown_only")
|
|
4763
|
-
}).strict()
|
|
4764
|
-
}).strict();
|
|
4765
|
-
|
|
4766
|
-
// ../shared/src/types/construction-log-excel.ts
|
|
4767
|
-
var CONSTRUCTION_LOG_EXCEL_SCHEMA_VERSION = "construction-log-excel-v1";
|
|
4768
|
-
var ConstructionLogExcelSheetKeySchema = external_exports.enum([
|
|
4769
|
-
"submittals",
|
|
4770
|
-
"rfis",
|
|
4771
|
-
"riskRegister",
|
|
4772
|
-
"longLead",
|
|
4773
|
-
"responsibilityMatrix",
|
|
4774
|
-
"milestones"
|
|
4775
|
-
]);
|
|
4776
|
-
var ConstructionLogExcelColumnSchema = external_exports.object({
|
|
4777
|
-
key: external_exports.string().min(1),
|
|
4778
|
-
header: external_exports.string().min(1),
|
|
4779
|
-
required: external_exports.boolean(),
|
|
4780
|
-
description: external_exports.string().min(1)
|
|
4781
|
-
}).strict().describe("Canonical column definition for Alfred construction log Excel round-trips.");
|
|
4782
|
-
var ConstructionLogExcelSheetSchema = external_exports.object({
|
|
4783
|
-
key: ConstructionLogExcelSheetKeySchema,
|
|
4784
|
-
sheetName: external_exports.string().min(1),
|
|
4785
|
-
description: external_exports.string().min(1),
|
|
4786
|
-
columns: external_exports.array(ConstructionLogExcelColumnSchema).min(1)
|
|
4787
|
-
}).strict().describe("Canonical worksheet definition for Alfred construction log Excel round-trips.");
|
|
4788
|
-
var ConstructionLogExcelWorkbookSchema = external_exports.object({
|
|
4789
|
-
schemaVersion: external_exports.literal(CONSTRUCTION_LOG_EXCEL_SCHEMA_VERSION),
|
|
4790
|
-
sheets: external_exports.record(ConstructionLogExcelSheetKeySchema, ConstructionLogExcelSheetSchema)
|
|
4791
|
-
}).strict().describe(
|
|
4792
|
-
"Canonical Alfred construction log Excel workbook schema shared by native output generation and export-upload ingestion."
|
|
4793
|
-
);
|
|
4794
|
-
var CONSTRUCTION_LOG_EXCEL_SHEETS = {
|
|
4795
|
-
submittals: {
|
|
4796
|
-
key: "submittals",
|
|
4797
|
-
sheetName: "Submittals",
|
|
4798
|
-
description: "Submittal register rows generated by Alfred or edited by the PM.",
|
|
4799
|
-
columns: [
|
|
4800
|
-
column("id", "ID", true, "Stable submittal identifier, for example SUB-001."),
|
|
4801
|
-
column("item", "Item", true, "Submittal item or package name."),
|
|
4802
|
-
column("division", "Division", true, "Spec division or trade grouping."),
|
|
4803
|
-
column("needByDate", "Need By Date", true, "Date needed in YYYY-MM-DD format."),
|
|
4804
|
-
column("status", "Status", true, "One of not_started, open, in_review, approved, or done."),
|
|
4805
|
-
commonColumn("assumptionsNotes")
|
|
4806
|
-
]
|
|
4807
|
-
},
|
|
4808
|
-
rfis: {
|
|
4809
|
-
key: "rfis",
|
|
4810
|
-
sheetName: "RFIs",
|
|
4811
|
-
description: "RFI log rows generated by Alfred or edited by the PM.",
|
|
4812
|
-
columns: [
|
|
4813
|
-
column("id", "ID", true, "Stable RFI identifier, for example RFI-001."),
|
|
4814
|
-
column("subject", "Subject", true, "RFI subject."),
|
|
4815
|
-
column("to", "To", true, "Responsible recipient or ball-in-court party."),
|
|
4816
|
-
column("status", "Status", true, "One of draft, open, answered, or closed."),
|
|
4817
|
-
column("openedDate", "Opened Date", true, "Date opened in YYYY-MM-DD format."),
|
|
4818
|
-
commonColumn("assumptionsNotes")
|
|
4819
|
-
]
|
|
4820
|
-
},
|
|
4821
|
-
riskRegister: {
|
|
4822
|
-
key: "riskRegister",
|
|
4823
|
-
sheetName: "Risk Register",
|
|
4824
|
-
description: "Risk register rows generated by Alfred or edited by the PM.",
|
|
4825
|
-
columns: [
|
|
4826
|
-
column("id", "ID", true, "Stable risk identifier, for example RISK-001."),
|
|
4827
|
-
column("risk", "Risk", true, "Risk statement."),
|
|
4828
|
-
column("rating", "Rating", true, "One of low, medium, or high."),
|
|
4829
|
-
column("mitigation", "Mitigation", true, "Mitigation plan."),
|
|
4830
|
-
column("confidence", "Confidence", true, "Confidence score from 0 to 1."),
|
|
4831
|
-
commonColumn("assumptionsNotes")
|
|
4832
|
-
]
|
|
4833
|
-
},
|
|
4834
|
-
longLead: {
|
|
4835
|
-
key: "longLead",
|
|
4836
|
-
sheetName: "Long-Lead",
|
|
4837
|
-
description: "Long-lead procurement rows generated by Alfred or edited by the PM.",
|
|
4838
|
-
columns: [
|
|
4839
|
-
column("id", "ID", true, "Stable long-lead identifier, for example LL-001."),
|
|
4840
|
-
column("item", "Item", true, "Long-lead item name."),
|
|
4841
|
-
column("needByDate", "Need By Date", true, "Date needed in YYYY-MM-DD format."),
|
|
4842
|
-
column("status", "Status", true, "One of tracking, ordered, received, or done."),
|
|
4843
|
-
column("assumption", "Assumption", true, "Procurement assumption behind this row."),
|
|
4844
|
-
commonColumn("assumptionsNotes")
|
|
4845
|
-
]
|
|
4846
|
-
},
|
|
4847
|
-
responsibilityMatrix: {
|
|
4848
|
-
key: "responsibilityMatrix",
|
|
4849
|
-
sheetName: "Responsibility Matrix",
|
|
4850
|
-
description: "Responsibility matrix rows generated by Alfred or edited by the PM.",
|
|
4851
|
-
columns: [
|
|
4852
|
-
column("id", "ID", true, "Stable responsibility identifier, for example RESP-001."),
|
|
4853
|
-
column("role", "Role", true, "Role or party."),
|
|
4854
|
-
column("owner", "Owner", true, "Named owner, or Needs PM input when unknown."),
|
|
4855
|
-
column("responsibility", "Responsibility", true, "Responsibility statement."),
|
|
4856
|
-
commonColumn("assumptionsNotes")
|
|
4857
|
-
]
|
|
4858
|
-
},
|
|
4859
|
-
milestones: {
|
|
4860
|
-
key: "milestones",
|
|
4861
|
-
sheetName: "Milestones",
|
|
4862
|
-
description: "Milestone schedule rows used to generate the MS Project XML schedule.",
|
|
4863
|
-
columns: [
|
|
4864
|
-
column("id", "ID", true, "Stable milestone identifier, for example MS-001."),
|
|
4865
|
-
column("name", "Name", true, "Milestone or task name."),
|
|
4866
|
-
column("targetDate", "Target Date", true, "Target date in YYYY-MM-DD format."),
|
|
4867
|
-
column("status", "Status", true, "One of planned, at_risk, slipped, or complete."),
|
|
4868
|
-
column("predecessorId", "Predecessor ID", false, "Optional predecessor milestone ID."),
|
|
4869
|
-
commonColumn("assumptionsNotes")
|
|
4870
|
-
]
|
|
4871
|
-
}
|
|
4872
|
-
};
|
|
4873
|
-
var CONSTRUCTION_LOG_EXCEL_WORKBOOK_SCHEMA = ConstructionLogExcelWorkbookSchema.parse({
|
|
4874
|
-
schemaVersion: CONSTRUCTION_LOG_EXCEL_SCHEMA_VERSION,
|
|
4875
|
-
sheets: CONSTRUCTION_LOG_EXCEL_SHEETS
|
|
4876
|
-
});
|
|
4877
|
-
function column(key, header, required, description) {
|
|
4878
|
-
return { key, header, required, description };
|
|
4879
|
-
}
|
|
4880
|
-
function commonColumn(key) {
|
|
4881
|
-
return column(
|
|
4882
|
-
key,
|
|
4883
|
-
"Assumptions / Notes",
|
|
4884
|
-
false,
|
|
4885
|
-
"Show-your-work note, including generated assumptions and PM-input gaps."
|
|
4886
|
-
);
|
|
4887
|
-
}
|
|
4888
|
-
|
|
4889
|
-
// ../shared/src/types/dev-task-dispatch.ts
|
|
4890
|
-
var CodingAgentExecutorSchema = external_exports.enum(["claude-code", "codex"]);
|
|
4891
|
-
var DevTaskDispatchRequestSchema = external_exports.object({
|
|
4892
|
-
studioId: external_exports.string().uuid(),
|
|
4893
|
-
productId: external_exports.string().uuid(),
|
|
4894
|
-
repo: RepoRefSchema,
|
|
4895
|
-
task: external_exports.string().min(1).max(2e4),
|
|
4896
|
-
executor: CodingAgentExecutorSchema
|
|
4897
|
-
}).strict();
|
|
4898
|
-
var DevTaskDispatchDryRunPlanSchema = external_exports.object({
|
|
4899
|
-
planOnly: external_exports.literal(true),
|
|
4900
|
-
planOnlyMessage: external_exports.string().min(1),
|
|
4901
|
-
targetRepo: RepoRefSchema,
|
|
4902
|
-
task: external_exports.string().min(1),
|
|
4903
|
-
executor: CodingAgentExecutorSchema,
|
|
4904
|
-
branchName: external_exports.string().min(1),
|
|
4905
|
-
safetyEnvelope: external_exports.object({
|
|
4906
|
-
estimatedCostUsd: external_exports.number().finite().nonnegative(),
|
|
4907
|
-
costCapUsd: external_exports.number().finite().nonnegative(),
|
|
4908
|
-
timeoutMs: external_exports.number().int().positive(),
|
|
4909
|
-
scopedToken: external_exports.object({
|
|
4910
|
-
tokenMinted: external_exports.literal(false),
|
|
4911
|
-
scope: external_exports.string().min(1),
|
|
4912
|
-
ttlSeconds: external_exports.number().int().positive()
|
|
4913
|
-
}).strict(),
|
|
4914
|
-
prOnly: external_exports.object({
|
|
4915
|
-
opensPullRequest: external_exports.literal(true),
|
|
4916
|
-
mergesPullRequest: external_exports.literal(false),
|
|
4917
|
-
pushesMain: external_exports.literal(false),
|
|
4918
|
-
deploys: external_exports.literal(false)
|
|
4919
|
-
}).strict()
|
|
4920
|
-
}).strict()
|
|
4921
|
-
}).strict();
|
|
4922
|
-
var CodingAgentRunInputSchema = external_exports.object({
|
|
4923
|
-
executor: CodingAgentExecutorSchema,
|
|
4924
|
-
repo: RepoRefSchema,
|
|
4925
|
-
task: external_exports.string().min(1),
|
|
4926
|
-
scopedToken: ScopedTokenSchema,
|
|
4927
|
-
branchName: external_exports.string().min(1),
|
|
4928
|
-
costCapUsd: external_exports.number().finite().nonnegative(),
|
|
4929
|
-
timeoutMs: external_exports.number().int().positive()
|
|
4930
|
-
}).strict();
|
|
4931
|
-
var CodingAgentRunResultSchema = external_exports.discriminatedUnion("status", [
|
|
4932
|
-
external_exports.object({
|
|
4933
|
-
status: external_exports.literal("succeeded"),
|
|
4934
|
-
prUrl: external_exports.string().url(),
|
|
4935
|
-
summary: external_exports.string().min(1),
|
|
4936
|
-
costUsd: external_exports.number().finite().nonnegative(),
|
|
4937
|
-
/**
|
|
4938
|
-
* The exact commit sha the PR branch was pushed at when it opened —
|
|
4939
|
-
* captured server-side (see server-dispatch-backend.ts) right after a
|
|
4940
|
-
* successful run, before the workspace is torn down. Lets the Maeve
|
|
4941
|
-
* in-flight-fix detector (maeve-in-flight-pr-fix-lesson.ts) key off the
|
|
4942
|
-
* real PR-open head instead of falling back to timestamp matching.
|
|
4943
|
-
*/
|
|
4944
|
-
openedHeadSha: external_exports.string().min(1).optional()
|
|
4945
|
-
}).strict(),
|
|
4946
|
-
external_exports.object({
|
|
4947
|
-
status: external_exports.literal("failed"),
|
|
4948
|
-
summary: external_exports.string().min(1),
|
|
4949
|
-
reason: external_exports.string().min(1),
|
|
4950
|
-
costUsd: external_exports.number().finite().nonnegative().optional()
|
|
4951
|
-
}).strict()
|
|
4952
|
-
]);
|
|
4953
|
-
var DevTaskOutcomeSchema = external_exports.enum(["ci_passed", "pr_merged", "ci_failed"]);
|
|
4954
|
-
var SecurityFindingClassSchema = external_exports.enum(["authz", "csrf", "injection", "secrets", "ssrf"]);
|
|
4955
|
-
var RecordDevTaskOutcomeInputSchema = external_exports.object({
|
|
4956
|
-
product: external_exports.string().min(1).max(120),
|
|
4957
|
-
repo: external_exports.string().min(1).max(240),
|
|
4958
|
-
prUrl: external_exports.string().url(),
|
|
4959
|
-
outcome: DevTaskOutcomeSchema,
|
|
4960
|
-
task: external_exports.string().min(1).max(2e4).optional(),
|
|
4961
|
-
executor: CodingAgentExecutorSchema.optional(),
|
|
4962
|
-
occurredAt: external_exports.string().datetime().optional(),
|
|
4963
|
-
maeveLessonStatement: external_exports.string().min(1).max(1e3).optional(),
|
|
4964
|
-
maeveLessonTags: external_exports.array(external_exports.string().min(1).max(120)).optional(),
|
|
4965
|
-
/** Security metadata — enriches the Maeve lesson with class/pattern, never raw vulnerable detail. */
|
|
4966
|
-
findingClass: SecurityFindingClassSchema.optional(),
|
|
4967
|
-
ruleId: external_exports.string().min(1).max(120).optional(),
|
|
4968
|
-
signalSource: external_exports.string().min(1).max(240).optional()
|
|
4969
|
-
}).strict();
|
|
4970
|
-
|
|
4971
|
-
// ../shared/src/schemas/standup-plan.ts
|
|
4972
|
-
var StandupRequestSchema = external_exports.object({
|
|
4973
|
-
productName: external_exports.string().min(1).max(80),
|
|
4974
|
-
slug: external_exports.string().min(1).optional(),
|
|
4975
|
-
vertical: external_exports.string().min(1).max(80),
|
|
4976
|
-
repoTarget: external_exports.string().min(1).default("barg-labs"),
|
|
4977
|
-
repoName: external_exports.string().min(1).optional(),
|
|
4978
|
-
templateRef: external_exports.string().min(1).optional(),
|
|
4979
|
-
scopeNotes: external_exports.string().max(2e3).optional()
|
|
4980
|
-
}).strict();
|
|
4981
|
-
var StandupPlanSchema = external_exports.object({
|
|
4982
|
-
productName: external_exports.string().min(1).max(80),
|
|
4983
|
-
slug: external_exports.string().regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$/),
|
|
4984
|
-
vertical: external_exports.string().min(1).max(80),
|
|
4985
|
-
templateRef: external_exports.string().min(1),
|
|
4986
|
-
repoTarget: external_exports.string().min(1),
|
|
4987
|
-
repoName: external_exports.string().regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$/),
|
|
4988
|
-
fileManifest: external_exports.array(external_exports.string().min(1)).min(1),
|
|
4989
|
-
credentialScope: external_exports.string().min(1),
|
|
4990
|
-
estimatedCostUsd: external_exports.number().nonnegative(),
|
|
4991
|
-
steps: external_exports.array(external_exports.string().min(1)).min(1),
|
|
4992
|
-
dryRun: external_exports.literal(true)
|
|
4993
|
-
}).strict();
|
|
4994
|
-
|
|
4995
|
-
// ../shared/src/types/coordinator-prompt.ts
|
|
4996
|
-
var CoordinatorPromptContextBlockSchema = external_exports.object({
|
|
4997
|
-
title: external_exports.string().min(1).max(120),
|
|
4998
|
-
body: external_exports.string().min(1).max(6e3),
|
|
4999
|
-
source: external_exports.string().max(500).optional()
|
|
5000
|
-
});
|
|
5001
|
-
var CoordinatorPromptInputPayloadSchema = external_exports.object({
|
|
5002
|
-
objective: external_exports.string().min(1).max(4e3),
|
|
5003
|
-
productId: external_exports.string().min(1),
|
|
5004
|
-
context: external_exports.array(CoordinatorPromptContextBlockSchema).min(1).max(20),
|
|
5005
|
-
escalationHints: external_exports.array(external_exports.string().min(1).max(500)).max(10).optional()
|
|
5006
|
-
});
|
|
5007
|
-
var CoordinatorPromptTokensUsedSchema = external_exports.object({
|
|
5008
|
-
input: external_exports.number().int().nonnegative(),
|
|
5009
|
-
output: external_exports.number().int().nonnegative(),
|
|
5010
|
-
total: external_exports.number().int().nonnegative(),
|
|
5011
|
-
costCents: external_exports.number().nonnegative()
|
|
5012
|
-
});
|
|
5013
|
-
var CoordinatorPromptSchema = external_exports.object({
|
|
5014
|
-
id: external_exports.string().uuid(),
|
|
5015
|
-
studioId: external_exports.string().min(1),
|
|
5016
|
-
productId: external_exports.string().min(1),
|
|
5017
|
-
draftedAt: external_exports.coerce.date(),
|
|
5018
|
-
inputPayload: CoordinatorPromptInputPayloadSchema,
|
|
5019
|
-
markdown: external_exports.string().min(1),
|
|
5020
|
-
metadata: external_exports.object({
|
|
5021
|
-
tokensUsed: CoordinatorPromptTokensUsedSchema.optional(),
|
|
5022
|
-
model: external_exports.string().optional(),
|
|
5023
|
-
templateVersion: external_exports.string().optional()
|
|
5024
|
-
}).catchall(external_exports.unknown()).optional()
|
|
5025
|
-
});
|
|
5026
|
-
var CreateCoordinatorPromptInputSchema = external_exports.object({
|
|
5027
|
-
productId: external_exports.string().min(1),
|
|
5028
|
-
inputPayload: CoordinatorPromptInputPayloadSchema,
|
|
5029
|
-
markdown: external_exports.string().min(1),
|
|
5030
|
-
metadata: external_exports.record(external_exports.unknown()).optional(),
|
|
5031
|
-
draftedAt: external_exports.coerce.date().optional()
|
|
5032
|
-
});
|
|
5033
|
-
var ListCoordinatorPromptsInputSchema = external_exports.object({
|
|
5034
|
-
productId: external_exports.string().min(1).optional(),
|
|
5035
|
-
since: external_exports.coerce.date().optional()
|
|
5036
|
-
});
|
|
5037
|
-
|
|
5038
|
-
// ../shared/src/schemas/inbox-triage.ts
|
|
5039
|
-
var InboxTriageClassificationSchema = external_exports.enum([
|
|
5040
|
-
"needs_reply",
|
|
5041
|
-
"fyi",
|
|
5042
|
-
"waiting",
|
|
5043
|
-
"escalate"
|
|
5044
|
-
]);
|
|
5045
|
-
var InboxTriageLegacyUrgencySchema = external_exports.enum(["needs_reply", "fyi", "noise", "escalation"]);
|
|
5046
|
-
var InboxTriageThreadSchema = external_exports.object({
|
|
5047
|
-
id: external_exports.string().min(1),
|
|
5048
|
-
subject: external_exports.string().min(1),
|
|
5049
|
-
from: external_exports.string(),
|
|
5050
|
-
to: external_exports.string(),
|
|
5051
|
-
snippet: external_exports.string(),
|
|
5052
|
-
labels: external_exports.array(external_exports.string()),
|
|
5053
|
-
unread: external_exports.boolean(),
|
|
5054
|
-
needsReply: external_exports.boolean(),
|
|
5055
|
-
updatedAt: external_exports.string().min(1),
|
|
5056
|
-
url: external_exports.string().min(1),
|
|
5057
|
-
messageCount: external_exports.number().int().nonnegative()
|
|
5058
|
-
});
|
|
5059
|
-
var InboxTriageResultSchema = external_exports.object({
|
|
5060
|
-
threadId: external_exports.string().min(1),
|
|
5061
|
-
classification: InboxTriageClassificationSchema,
|
|
5062
|
-
confidence: external_exports.number().min(0).max(1),
|
|
5063
|
-
reason: external_exports.string(),
|
|
5064
|
-
labelName: external_exports.string(),
|
|
5065
|
-
applied: external_exports.boolean(),
|
|
5066
|
-
error: external_exports.string().optional()
|
|
5067
|
-
});
|
|
5068
|
-
var TriageInboxUsageSchema = external_exports.object({
|
|
5069
|
-
input_tokens: external_exports.number().int().nonnegative(),
|
|
5070
|
-
output_tokens: external_exports.number().int().nonnegative(),
|
|
5071
|
-
cached_tokens: external_exports.number().int().nonnegative().optional(),
|
|
5072
|
-
cost_cents: external_exports.number().nonnegative()
|
|
5073
|
-
});
|
|
5074
|
-
var TriageInboxResultSchema = external_exports.object({
|
|
5075
|
-
productId: external_exports.string().min(1),
|
|
5076
|
-
results: external_exports.array(InboxTriageResultSchema),
|
|
5077
|
-
usage: TriageInboxUsageSchema.optional()
|
|
5078
|
-
});
|
|
5079
|
-
|
|
5080
|
-
// ../shared/src/schemas/inference-usage.ts
|
|
5081
|
-
var InferenceUsageSurfaceSchema = external_exports.string().min(1).max(80).regex(/^[a-z][a-z0-9_-]*$/);
|
|
5082
|
-
var RecordInferenceUsageInputSchema = external_exports.object({
|
|
5083
|
-
product: external_exports.string().min(1).optional(),
|
|
5084
|
-
surface: InferenceUsageSurfaceSchema,
|
|
5085
|
-
model: external_exports.string().min(1).max(120),
|
|
5086
|
-
inputTokens: external_exports.number().int().nonnegative(),
|
|
5087
|
-
outputTokens: external_exports.number().int().nonnegative(),
|
|
5088
|
-
cachedTokens: external_exports.number().int().nonnegative().default(0),
|
|
5089
|
-
costCents: external_exports.number().nonnegative(),
|
|
5090
|
-
timestamp: external_exports.coerce.date().optional()
|
|
5091
|
-
});
|
|
5092
|
-
var InferenceUsageBreakdownQuerySchema = external_exports.object({
|
|
5093
|
-
from: external_exports.coerce.date(),
|
|
5094
|
-
to: external_exports.coerce.date()
|
|
5095
|
-
});
|
|
5096
|
-
var InferenceUsageGroupSchema = external_exports.object({
|
|
5097
|
-
calls: external_exports.number().int().nonnegative(),
|
|
5098
|
-
costCents: external_exports.number().nonnegative(),
|
|
5099
|
-
inputTokens: external_exports.number().int().nonnegative(),
|
|
5100
|
-
outputTokens: external_exports.number().int().nonnegative(),
|
|
5101
|
-
cachedTokens: external_exports.number().int().nonnegative()
|
|
5102
|
-
});
|
|
5103
|
-
var InferenceUsageBreakdownSchema = external_exports.object({
|
|
5104
|
-
from: external_exports.string().datetime(),
|
|
5105
|
-
to: external_exports.string().datetime(),
|
|
5106
|
-
totals: InferenceUsageGroupSchema,
|
|
5107
|
-
bySurface: external_exports.array(InferenceUsageGroupSchema.extend({ surface: InferenceUsageSurfaceSchema })),
|
|
5108
|
-
byModel: external_exports.array(InferenceUsageGroupSchema.extend({ model: external_exports.string().min(1) }))
|
|
5109
|
-
});
|
|
5110
|
-
|
|
5111
|
-
// ../shared/src/schemas/product-health.ts
|
|
5112
|
-
var DEFAULT_PRODUCT_HEALTH_INTERVAL_SECONDS = 24 * 60 * 60;
|
|
5113
|
-
var ISO_DATE_STRING = external_exports.string().datetime({ offset: true }).describe("ISO-8601 timestamp with timezone offset.");
|
|
5114
|
-
var ProductHealthStatusSchema = external_exports.enum(["healthy", "degraded", "halted"]);
|
|
5115
|
-
var ProductHealthDetailsSchema = external_exports.record(external_exports.unknown()).superRefine((details, ctx) => {
|
|
5116
|
-
const credentialPath = findCredentialLikePath(details);
|
|
5117
|
-
if (!credentialPath) return;
|
|
5118
|
-
ctx.addIssue({
|
|
5119
|
-
code: external_exports.ZodIssueCode.custom,
|
|
5120
|
-
message: `Product health details must not contain credentials (${credentialPath}).`
|
|
5121
|
-
});
|
|
5122
|
-
});
|
|
5123
|
-
var ProductHealthReportInputSchema = external_exports.object({
|
|
5124
|
-
productId: external_exports.string().min(1).max(120),
|
|
5125
|
-
status: ProductHealthStatusSchema,
|
|
5126
|
-
lastActivityAt: ISO_DATE_STRING,
|
|
5127
|
-
summary: external_exports.string().min(1).max(1e3),
|
|
5128
|
-
details: ProductHealthDetailsSchema.optional(),
|
|
5129
|
-
reportedAt: ISO_DATE_STRING,
|
|
5130
|
-
expectedIntervalSeconds: external_exports.number().int().positive().optional()
|
|
5131
|
-
});
|
|
5132
|
-
var StoredProductHealthReportSchema = ProductHealthReportInputSchema.extend({
|
|
5133
|
-
expectedIntervalSeconds: external_exports.number().int().positive()
|
|
5134
|
-
});
|
|
5135
|
-
var ProductLivenessStateSchema = external_exports.enum([
|
|
5136
|
-
"healthy",
|
|
5137
|
-
"degraded",
|
|
5138
|
-
"halted",
|
|
5139
|
-
"stale",
|
|
5140
|
-
"unknown"
|
|
5141
|
-
]);
|
|
5142
|
-
var ProductLivenessSnapshotEntrySchema = external_exports.object({
|
|
5143
|
-
productId: external_exports.string().min(1),
|
|
5144
|
-
state: ProductLivenessStateSchema,
|
|
5145
|
-
flagged: external_exports.boolean(),
|
|
5146
|
-
status: ProductHealthStatusSchema.optional(),
|
|
5147
|
-
lastActivityAt: ISO_DATE_STRING.optional(),
|
|
5148
|
-
reportedAt: ISO_DATE_STRING.optional(),
|
|
5149
|
-
expectedIntervalSeconds: external_exports.number().int().positive(),
|
|
5150
|
-
ageSeconds: external_exports.number().int().nonnegative().nullable(),
|
|
5151
|
-
summary: external_exports.string()
|
|
5152
|
-
});
|
|
5153
|
-
function findCredentialLikePath(value, path = []) {
|
|
5154
|
-
if (!value || typeof value !== "object") return null;
|
|
5155
|
-
if (Array.isArray(value)) {
|
|
5156
|
-
for (const [index, item] of value.entries()) {
|
|
5157
|
-
const match = findCredentialLikePath(item, [...path, String(index)]);
|
|
5158
|
-
if (match) return match;
|
|
5159
|
-
}
|
|
5160
|
-
return null;
|
|
5161
|
-
}
|
|
5162
|
-
for (const [key, nested] of Object.entries(value)) {
|
|
5163
|
-
const nextPath = [...path, key];
|
|
5164
|
-
if (/(?:secret|token|password|credential|api[-_]?key|private[-_]?key)/i.test(key)) {
|
|
5165
|
-
return nextPath.join(".");
|
|
5166
|
-
}
|
|
5167
|
-
const match = findCredentialLikePath(nested, nextPath);
|
|
5168
|
-
if (match) return match;
|
|
5169
|
-
}
|
|
5170
|
-
return null;
|
|
5171
|
-
}
|
|
5172
|
-
|
|
5173
|
-
// ../shared/src/schemas/interaction-trace.ts
|
|
5174
|
-
var InteractionTraceVerificationSignalSchema = external_exports.enum([
|
|
5175
|
-
"no_signal",
|
|
5176
|
-
"human_accepted_output",
|
|
5177
|
-
"human_rejected_output",
|
|
5178
|
-
"ci_pr_succeeded",
|
|
5179
|
-
"ci_pr_failed",
|
|
5180
|
-
"brief_accepted",
|
|
5181
|
-
"brief_rejected",
|
|
5182
|
-
"standup_completed",
|
|
5183
|
-
"standup_failed"
|
|
5184
|
-
]);
|
|
5185
|
-
var InteractionTraceVerificationSchema = external_exports.object({
|
|
5186
|
-
success: external_exports.boolean(),
|
|
5187
|
-
signal: InteractionTraceVerificationSignalSchema,
|
|
5188
|
-
confidence: external_exports.number().min(0).max(1),
|
|
5189
|
-
reason: external_exports.string().min(1).max(1e3)
|
|
5190
|
-
});
|
|
5191
|
-
var InteractionTraceActorSchema = external_exports.object({
|
|
5192
|
-
type: external_exports.enum(["human", "agent", "system"]),
|
|
5193
|
-
id: external_exports.string().min(1).max(200),
|
|
5194
|
-
name: external_exports.string().min(1).max(200).optional()
|
|
5195
|
-
});
|
|
5196
|
-
var RecordInteractionTraceInputSchema = external_exports.object({
|
|
5197
|
-
product: external_exports.string().min(1).max(120),
|
|
5198
|
-
intent: external_exports.string().min(1).max(500),
|
|
5199
|
-
actionSummary: external_exports.string().min(1).max(4e3),
|
|
5200
|
-
outcomeSummary: external_exports.string().min(1).max(4e3),
|
|
5201
|
-
model: external_exports.string().min(1).max(200).nullable().optional(),
|
|
5202
|
-
actor: InteractionTraceActorSchema,
|
|
5203
|
-
occurredAt: external_exports.string().datetime().optional(),
|
|
5204
|
-
verification: InteractionTraceVerificationSchema.optional(),
|
|
5205
|
-
metadata: external_exports.record(external_exports.unknown()).optional()
|
|
5206
|
-
});
|
|
5207
|
-
var StoredInteractionTraceSchema = RecordInteractionTraceInputSchema.extend({
|
|
5208
|
-
id: external_exports.string().uuid(),
|
|
5209
|
-
occurredAt: external_exports.string().datetime(),
|
|
5210
|
-
createdAt: external_exports.string().datetime(),
|
|
5211
|
-
verification: InteractionTraceVerificationSchema
|
|
5212
|
-
});
|
|
5213
|
-
var InteractionTraceQualityScoreSchema = external_exports.number().min(0).max(1);
|
|
5214
|
-
var RetrieveRelevantTracesQuerySchema = external_exports.object({
|
|
5215
|
-
product: external_exports.string().min(1).max(120),
|
|
5216
|
-
intent: external_exports.string().min(1).max(500),
|
|
5217
|
-
limit: external_exports.number().int().positive().max(10).optional()
|
|
5218
|
-
});
|
|
5219
|
-
var RetrievedInteractionTraceSchema = StoredInteractionTraceSchema.extend({
|
|
5220
|
-
score: external_exports.number().min(0).max(1),
|
|
5221
|
-
qualityScore: InteractionTraceQualityScoreSchema
|
|
5222
|
-
});
|
|
5223
|
-
|
|
5224
|
-
// ../shared/src/schemas/maeve-lesson.ts
|
|
5225
|
-
var MaeveLessonStatusSchema = external_exports.enum(["candidate", "verified", "retired"]);
|
|
5226
|
-
var MaeveLessonEvidenceSchema = external_exports.object({
|
|
5227
|
-
source: external_exports.enum(["interaction_trace", "artifact"]),
|
|
5228
|
-
traceId: external_exports.string().uuid().optional(),
|
|
5229
|
-
artifact: external_exports.string().min(1).max(1e3).optional(),
|
|
5230
|
-
summary: external_exports.string().min(1).max(1e3),
|
|
5231
|
-
hash: external_exports.string().regex(/^sha256:[a-f0-9]{64}$/)
|
|
5232
|
-
});
|
|
5233
|
-
var MaeveLessonSchema = external_exports.object({
|
|
5234
|
-
id: external_exports.string().uuid(),
|
|
5235
|
-
product: external_exports.string().min(1).max(120),
|
|
5236
|
-
statement: external_exports.string().min(1).max(1e3),
|
|
5237
|
-
scope: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5238
|
-
tags: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5239
|
-
evidence: external_exports.array(MaeveLessonEvidenceSchema),
|
|
5240
|
-
status: MaeveLessonStatusSchema,
|
|
5241
|
-
createdAt: external_exports.string().datetime(),
|
|
5242
|
-
lastSeenAt: external_exports.string().datetime()
|
|
5243
|
-
});
|
|
5244
|
-
var CreateMaeveLessonInputSchema = external_exports.object({
|
|
5245
|
-
product: external_exports.string().min(1).max(120),
|
|
5246
|
-
statement: external_exports.string().min(1).max(1e3),
|
|
5247
|
-
scope: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5248
|
-
tags: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5249
|
-
evidence: external_exports.array(MaeveLessonEvidenceSchema).default([]),
|
|
5250
|
-
status: MaeveLessonStatusSchema.default("candidate"),
|
|
5251
|
-
lastSeenAt: external_exports.string().datetime().optional()
|
|
5252
|
-
});
|
|
5253
|
-
var PromoteMaeveLessonInputSchema = external_exports.object({
|
|
5254
|
-
id: external_exports.string().uuid(),
|
|
5255
|
-
status: MaeveLessonStatusSchema,
|
|
5256
|
-
appendEvidence: external_exports.array(MaeveLessonEvidenceSchema).optional()
|
|
5257
|
-
});
|
|
5258
|
-
var RecallMaeveLessonsQuerySchema = external_exports.object({
|
|
5259
|
-
product: external_exports.string().min(1).max(120).optional(),
|
|
5260
|
-
taskType: external_exports.string().min(1).max(120).optional(),
|
|
5261
|
-
tags: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5262
|
-
limit: external_exports.number().int().positive().max(10).default(5),
|
|
5263
|
-
/**
|
|
5264
|
-
* Free-text query for semantic (pgvector cosine) recall. When set and an
|
|
5265
|
-
* EmbeddingProvider is configured, recallMaeveLessons embeds this text and
|
|
5266
|
-
* retrieves by cosine similarity, with exact-tag matches as a boost.
|
|
5267
|
-
* Falls back to exact-class matching when the provider is NoOp.
|
|
5268
|
-
*/
|
|
5269
|
-
semanticQuery: external_exports.string().min(1).max(500).optional()
|
|
5270
|
-
});
|
|
5271
|
-
var MaeveLessonSeedAnchorSchema = external_exports.object({
|
|
5272
|
-
commit: external_exports.string().regex(/^[0-9a-f]{40}$/i, "commit must be a full 40-character git SHA"),
|
|
5273
|
-
pr: external_exports.number().int().positive().nullable(),
|
|
5274
|
-
summary: external_exports.string().min(1).max(1e3)
|
|
5275
|
-
});
|
|
5276
|
-
var MaeveLessonSeedSchema = external_exports.object({
|
|
5277
|
-
statement: external_exports.string().min(1).max(1e3),
|
|
5278
|
-
scope: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5279
|
-
tags: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5280
|
-
anchors: external_exports.array(MaeveLessonSeedAnchorSchema).min(1),
|
|
5281
|
-
lastSeenAt: external_exports.string().datetime()
|
|
5282
|
-
});
|
|
5283
|
-
var ReviewFindingSeveritySchema = external_exports.enum(["critical", "high", "medium", "low"]);
|
|
5284
|
-
var ReviewFindingLessonInputSchema = external_exports.object({
|
|
5285
|
-
studioId: external_exports.string().min(1),
|
|
5286
|
-
findingStudioId: external_exports.string().min(1),
|
|
5287
|
-
product: external_exports.string().min(1).max(120),
|
|
5288
|
-
repository: external_exports.string().min(1).max(240),
|
|
5289
|
-
pullRequestNumber: external_exports.number().int().positive(),
|
|
5290
|
-
findingText: external_exports.string().min(1).max(4e3),
|
|
5291
|
-
severity: ReviewFindingSeveritySchema,
|
|
5292
|
-
reviewer: external_exports.string().min(1).max(120),
|
|
5293
|
-
remediatingCommitSha: external_exports.string().min(4).max(64),
|
|
5294
|
-
/** The durable, reusable rule distilled from the finding — NOT the finding text verbatim. */
|
|
5295
|
-
lessonStatement: external_exports.string().min(1).max(1e3),
|
|
5296
|
-
scope: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5297
|
-
tags: external_exports.array(external_exports.string().min(1).max(120)).default([]),
|
|
5298
|
-
occurredAt: external_exports.string().datetime()
|
|
5299
|
-
});
|
|
5300
|
-
|
|
5301
|
-
// ../shared/src/schemas/operator-trace.ts
|
|
5302
|
-
var TRACE_ACTORS = [
|
|
5303
|
-
"human",
|
|
5304
|
-
"cowork",
|
|
5305
|
-
"claude-code",
|
|
5306
|
-
"codex",
|
|
5307
|
-
"goal-runner",
|
|
5308
|
-
"ci"
|
|
5309
|
-
];
|
|
5310
|
-
var TraceActorSchema = external_exports.enum(TRACE_ACTORS);
|
|
5311
|
-
var TRACE_SOURCES = [
|
|
5312
|
-
"shell",
|
|
5313
|
-
"cowork",
|
|
5314
|
-
"claude-code",
|
|
5315
|
-
"codex",
|
|
5316
|
-
"goal-runner",
|
|
5317
|
-
"github"
|
|
5318
|
-
];
|
|
5319
|
-
var TraceSourceSchema = external_exports.enum(TRACE_SOURCES);
|
|
5320
|
-
var TraceProvenanceSchema = external_exports.object({
|
|
5321
|
-
source: TraceSourceSchema,
|
|
5322
|
-
/** Absolute path of the source file/dir, or the gh query for CI events. */
|
|
5323
|
-
path: external_exports.string().min(1).max(1e3),
|
|
5324
|
-
/** Line number, session id, or PR number locating the row inside the source. */
|
|
5325
|
-
locator: external_exports.string().min(1).max(200).optional()
|
|
5326
|
-
});
|
|
5327
|
-
var TraceRecordSchema = external_exports.object({
|
|
5328
|
-
t: external_exports.string().datetime(),
|
|
5329
|
-
actor: TraceActorSchema,
|
|
5330
|
-
action: external_exports.string().min(1).max(2e3),
|
|
5331
|
-
target: external_exports.string().max(1e3).default(""),
|
|
5332
|
-
outcome: external_exports.string().max(2e3).default(""),
|
|
5333
|
-
product: external_exports.string().min(1).max(120).optional(),
|
|
5334
|
-
provenance: TraceProvenanceSchema
|
|
5335
|
-
});
|
|
5336
|
-
var ShellRedactionSchema = external_exports.enum(["none", "secret", "unclassified"]);
|
|
5337
|
-
var ShellTraceEntrySchema = external_exports.object({
|
|
5338
|
-
ts: external_exports.string().datetime(),
|
|
5339
|
-
cwd: external_exports.string().min(1).max(1e3),
|
|
5340
|
-
command: external_exports.string().min(1).max(4e3),
|
|
5341
|
-
exitCode: external_exports.number().int(),
|
|
5342
|
-
shellSessionId: external_exports.string().min(1).max(200),
|
|
5343
|
-
redaction: ShellRedactionSchema
|
|
5344
|
-
});
|
|
5345
|
-
var TraceSourceReportSchema = external_exports.discriminatedUnion("status", [
|
|
5346
|
-
external_exports.object({
|
|
5347
|
-
status: external_exports.literal("ok"),
|
|
5348
|
-
source: TraceSourceSchema,
|
|
5349
|
-
recordCount: external_exports.number().int().nonnegative(),
|
|
5350
|
-
/** Files/entries present but skipped (unparseable, filtered) — named, not silent. */
|
|
5351
|
-
skipped: external_exports.array(external_exports.string().min(1).max(500)).default([])
|
|
5352
|
-
}),
|
|
5353
|
-
external_exports.object({
|
|
5354
|
-
status: external_exports.literal("dark"),
|
|
5355
|
-
source: TraceSourceSchema,
|
|
5356
|
-
reason: external_exports.string().min(1).max(500)
|
|
5357
|
-
})
|
|
5358
|
-
]);
|
|
5359
|
-
var OperatorTimelineSchema = external_exports.object({
|
|
5360
|
-
records: external_exports.array(TraceRecordSchema),
|
|
5361
|
-
sources: external_exports.array(TraceSourceReportSchema)
|
|
5362
|
-
});
|
|
5363
|
-
|
|
5364
|
-
// ../shared/src/schemas/witan.ts
|
|
4517
|
+
// src/witan/schemas.ts
|
|
5365
4518
|
var WITAN_RUBRIC_VERSION_V1 = "witan-rubric-v1-2026-06-24";
|
|
5366
4519
|
var WITAN_RUBRIC_VERSION_V2 = "witan-rubric-v2-2026-07-12";
|
|
5367
4520
|
var WITAN_RUBRIC_VERSION_V3 = "witan-rubric-v3-2026-07-13";
|
|
@@ -5391,11 +4544,9 @@ var WITAN_TRADING_RUBRIC_V0_CRITERION_IDS = [
|
|
|
5391
4544
|
"audit-completeness",
|
|
5392
4545
|
"claim-reality"
|
|
5393
4546
|
];
|
|
5394
|
-
var WITAN_QUANT_INTEGRITY_RUBRIC_V0_CRITERION_IDS = ["quant-integrity"];
|
|
5395
4547
|
var WitanCriterionIdSchema = external_exports.enum([
|
|
5396
4548
|
...WITAN_CRITERION_IDS,
|
|
5397
|
-
...WITAN_TRADING_RUBRIC_V0_CRITERION_IDS
|
|
5398
|
-
...WITAN_QUANT_INTEGRITY_RUBRIC_V0_CRITERION_IDS
|
|
4549
|
+
...WITAN_TRADING_RUBRIC_V0_CRITERION_IDS
|
|
5399
4550
|
]);
|
|
5400
4551
|
var WitanTradingCriterionIdSchema = external_exports.enum(WITAN_TRADING_RUBRIC_V0_CRITERION_IDS);
|
|
5401
4552
|
var WitanCriterionCategorySchema = external_exports.enum([
|
|
@@ -5423,8 +4574,6 @@ var WitanEvidenceKindSchema = external_exports.enum([
|
|
|
5423
4574
|
"commit",
|
|
5424
4575
|
"coverage",
|
|
5425
4576
|
"dependency_report",
|
|
5426
|
-
"dispatch_log",
|
|
5427
|
-
"maeve_trace",
|
|
5428
4577
|
"prod_check",
|
|
5429
4578
|
"pull_request",
|
|
5430
4579
|
"repository",
|
|
@@ -5446,7 +4595,10 @@ var WitanEvidencePointerSchema = external_exports.object({
|
|
|
5446
4595
|
label: external_exports.string().min(1).max(180),
|
|
5447
4596
|
url: external_exports.string().url().optional(),
|
|
5448
4597
|
path: external_exports.string().min(1).max(700).optional(),
|
|
5449
|
-
|
|
4598
|
+
// Explicit null means the finding is file-scoped and no real match position was measured —
|
|
4599
|
+
// never a fabricated line (e.g. `1`) standing in for a position the detector never found
|
|
4600
|
+
// (goal_cejel_a2_one_notion_of_production_code_2026-07-13).
|
|
4601
|
+
line: external_exports.number().int().positive().nullable().optional(),
|
|
5450
4602
|
contentHash: external_exports.string().min(8).max(160).optional(),
|
|
5451
4603
|
capturedAt: external_exports.string().datetime({ offset: true }).optional()
|
|
5452
4604
|
}).strict().refine((value) => Boolean(value.url ?? value.path ?? value.contentHash), {
|
|
@@ -5558,981 +4710,124 @@ var WitanReportSchema = external_exports.object({
|
|
|
5558
4710
|
archetype: WitanRepoArchetypeSchema.optional(),
|
|
5559
4711
|
insufficientSourceReason: external_exports.string().min(1).max(2e3).optional()
|
|
5560
4712
|
}).strict();
|
|
5561
|
-
|
|
5562
|
-
|
|
5563
|
-
var
|
|
5564
|
-
var WorkItemPrioritySchema = external_exports.enum(["low", "normal", "high", "urgent"]);
|
|
5565
|
-
var WorkItemStatusSchema = external_exports.enum([
|
|
5566
|
-
"submitted",
|
|
5567
|
-
"scoped",
|
|
5568
|
-
"dispatched",
|
|
5569
|
-
"pr_open",
|
|
5570
|
-
"done",
|
|
5571
|
-
"declined"
|
|
5572
|
-
]);
|
|
5573
|
-
var CreateWorkItemInputSchema = external_exports.object({
|
|
5574
|
-
productId: external_exports.string().uuid(),
|
|
5575
|
-
type: WorkItemTypeSchema,
|
|
5576
|
-
title: external_exports.string().min(3).max(180),
|
|
5577
|
-
description: external_exports.string().min(8).max(2e4),
|
|
5578
|
-
acceptanceCriteria: external_exports.string().max(2e4).optional(),
|
|
5579
|
-
priority: WorkItemPrioritySchema.default("normal")
|
|
5580
|
-
}).strict();
|
|
5581
|
-
var ScopeWorkItemInputSchema = external_exports.object({
|
|
5582
|
-
scopedTask: external_exports.string().min(8).max(2e4).optional()
|
|
5583
|
-
}).strict();
|
|
5584
|
-
var ListWorkItemsQuerySchema = external_exports.object({
|
|
5585
|
-
productId: external_exports.string().uuid().optional(),
|
|
5586
|
-
status: WorkItemStatusSchema.optional()
|
|
5587
|
-
}).strict();
|
|
5588
|
-
var DispatchWorkItemInputSchema = external_exports.object({
|
|
5589
|
-
executor: external_exports.enum(["claude-code", "codex"]).default("codex"),
|
|
5590
|
-
mode: external_exports.enum(["dry-run", "execute"]).default("dry-run")
|
|
5591
|
-
}).strict();
|
|
5592
|
-
|
|
5593
|
-
// ../shared/src/schemas/goal-frontmatter.ts
|
|
5594
|
-
var GoalStreamKindSchema = external_exports.enum(["code", "process"]);
|
|
5595
|
-
var GoalPrioritySchema = external_exports.enum(["p0", "p1", "p2"]);
|
|
5596
|
-
var GoalFrontmatterExtrasSchema = external_exports.object({
|
|
5597
|
-
stream: external_exports.string().min(1).nullable().default(null),
|
|
5598
|
-
order: external_exports.number().int().nullable().default(null),
|
|
5599
|
-
dependsOn: external_exports.array(external_exports.string().min(1)).default([]),
|
|
5600
|
-
priority: GoalPrioritySchema.nullable().default(null),
|
|
5601
|
-
kind: GoalStreamKindSchema.default("code")
|
|
5602
|
-
});
|
|
5603
|
-
|
|
5604
|
-
// ../shared/src/schemas/stream.ts
|
|
5605
|
-
var StreamSchema = external_exports.object({
|
|
5606
|
-
id: external_exports.string().uuid(),
|
|
5607
|
-
studioId: external_exports.string().uuid(),
|
|
5608
|
-
name: external_exports.string().min(1).max(120),
|
|
5609
|
-
tag: external_exports.string().max(60).nullable(),
|
|
5610
|
-
kind: GoalStreamKindSchema,
|
|
5611
|
-
orderIndex: external_exports.number().int(),
|
|
5612
|
-
createdAt: external_exports.coerce.date(),
|
|
5613
|
-
updatedAt: external_exports.coerce.date()
|
|
5614
|
-
});
|
|
5615
|
-
var StreamItemSchema = external_exports.object({
|
|
5616
|
-
id: external_exports.string().uuid(),
|
|
5617
|
-
studioId: external_exports.string().uuid(),
|
|
5618
|
-
streamId: external_exports.string().uuid(),
|
|
5619
|
-
orderIndex: external_exports.number().int(),
|
|
5620
|
-
title: external_exports.string().min(1).max(200),
|
|
5621
|
-
/** docs/orchestration/goal_*.md filename (no extension) for code items; null for process items. */
|
|
5622
|
-
goalName: external_exports.string().min(1).nullable(),
|
|
5623
|
-
refLabel: external_exports.string().max(60).nullable(),
|
|
5624
|
-
/** Free-form governed-run prompt text (mirrors the prototype's per-item `run` string). Null = no run control shown. */
|
|
5625
|
-
runPrompt: external_exports.string().min(1).nullable(),
|
|
5626
|
-
createdAt: external_exports.coerce.date(),
|
|
5627
|
-
updatedAt: external_exports.coerce.date()
|
|
5628
|
-
});
|
|
5629
|
-
var StreamItemDisplayStatusSchema = external_exports.enum([
|
|
5630
|
-
"done",
|
|
5631
|
-
"in-review",
|
|
5632
|
-
"running",
|
|
5633
|
-
"queued",
|
|
5634
|
-
"blocked",
|
|
5635
|
-
"local-unknown"
|
|
5636
|
-
]);
|
|
5637
|
-
|
|
5638
|
-
// ../shared/src/schemas/runner-dispatch.ts
|
|
5639
|
-
var RUNNER_DISPATCH_MODES = ["dry-run", "execute"];
|
|
5640
|
-
var RunnerDispatchModeSchema = external_exports.enum(RUNNER_DISPATCH_MODES);
|
|
5641
|
-
var RUNNER_DISPATCH_STATUSES = ["queued", "claimed", "running", "done", "failed"];
|
|
5642
|
-
var RunnerDispatchStatusSchema = external_exports.enum(RUNNER_DISPATCH_STATUSES);
|
|
5643
|
-
var GOAL_CARD_PATTERN = /^docs\/orchestration\/[A-Za-z0-9_./-]+\.md$/;
|
|
5644
|
-
function isAllowedGoalCardPath(goalCard) {
|
|
5645
|
-
if (!GOAL_CARD_PATTERN.test(goalCard)) return false;
|
|
5646
|
-
return goalCard.split("/").every((segment) => segment !== "." && segment !== "..");
|
|
5647
|
-
}
|
|
5648
|
-
var GoalCardPathSchema = external_exports.string().min(1).max(300).refine(isAllowedGoalCardPath, { message: "goal_card_invalid" });
|
|
5649
|
-
var RunnerDispatchRequestSchema = external_exports.object({
|
|
5650
|
-
goalCard: GoalCardPathSchema,
|
|
5651
|
-
stream: external_exports.string().min(1).max(120).optional(),
|
|
5652
|
-
mode: RunnerDispatchModeSchema
|
|
5653
|
-
});
|
|
5654
|
-
|
|
5655
|
-
// ../shared/src/schemas/witan-metrics-manifest.ts
|
|
5656
|
-
var WITAN_METRICS_MANIFEST_SCHEMA_VERSION = "witan-metrics-manifest-v0";
|
|
5657
|
-
var WitanMetricsManifestReturnsFrequencySchema = external_exports.enum([
|
|
5658
|
-
"daily",
|
|
5659
|
-
"weekly",
|
|
5660
|
-
"monthly",
|
|
5661
|
-
"annual"
|
|
5662
|
-
]);
|
|
5663
|
-
var WitanMetricsManifestFoldSchema = external_exports.object({
|
|
5664
|
-
foldId: external_exports.string().min(1).max(80),
|
|
5665
|
-
inSampleSharpe: external_exports.number().optional(),
|
|
5666
|
-
outOfSampleSharpe: external_exports.number().optional()
|
|
5667
|
-
}).strict();
|
|
5668
|
-
var WitanMetricsManifestCscvTrialSchema = external_exports.object({
|
|
5669
|
-
trialId: external_exports.string().min(1).max(80),
|
|
5670
|
-
blockReturns: external_exports.array(external_exports.number()).min(2)
|
|
5671
|
-
}).strict();
|
|
5672
|
-
var WitanMetricsManifestCscvSchema = external_exports.object({
|
|
5673
|
-
// Must be even (split into IS/OOS halves) — enforced by the grader, not the schema.
|
|
5674
|
-
blocks: external_exports.number().int().min(4).max(16),
|
|
5675
|
-
trials: external_exports.array(WitanMetricsManifestCscvTrialSchema).min(2).max(200)
|
|
5676
|
-
}).strict();
|
|
5677
|
-
var WitanMetricsManifestCostModelSchema = external_exports.object({
|
|
5678
|
-
feeBps: external_exports.number().min(0).optional(),
|
|
5679
|
-
slippageBps: external_exports.number().min(0).optional(),
|
|
5680
|
-
borrowBps: external_exports.number().min(0).optional(),
|
|
5681
|
-
notes: external_exports.string().min(1).max(300).optional()
|
|
5682
|
-
}).strict();
|
|
5683
|
-
var WitanMetricsManifestParameterPointSchema = external_exports.object({
|
|
5684
|
-
// Human-readable label for this point (e.g. "72" or "72 bars") — evidence/display only.
|
|
5685
|
-
paramLabel: external_exports.string().min(1).max(80),
|
|
5686
|
-
// The point's position on its swept axis, used to find its nearest neighbors by distance.
|
|
5687
|
-
paramValue: external_exports.number(),
|
|
5688
|
-
outOfSampleSharpe: external_exports.number()
|
|
5689
|
-
}).strict();
|
|
5690
|
-
var WitanMetricsManifestParameterSweepSchema = external_exports.object({
|
|
5691
|
-
// Name of the swept parameter (e.g. "lookback_bars") — evidence/display only.
|
|
5692
|
-
paramName: external_exports.string().min(1).max(80),
|
|
5693
|
-
points: external_exports.array(WitanMetricsManifestParameterPointSchema).min(3).max(500)
|
|
5694
|
-
}).strict();
|
|
5695
|
-
var WitanMetricsManifestLabelSourceSchema = external_exports.enum([
|
|
5696
|
-
"real_forward_returns",
|
|
5697
|
-
"synthetic",
|
|
5698
|
-
"unknown"
|
|
5699
|
-
]);
|
|
5700
|
-
var WitanMetricsManifestSchema = external_exports.object({
|
|
5701
|
-
schemaVersion: external_exports.literal(WITAN_METRICS_MANIFEST_SCHEMA_VERSION),
|
|
5702
|
-
strategyName: external_exports.string().min(1).max(200).optional(),
|
|
5703
|
-
// The headline reported Sharpe ratio the target repo is claiming.
|
|
5704
|
-
reportedSharpe: external_exports.number(),
|
|
5705
|
-
// How many trials/backtests were run in the search that produced reportedSharpe (the
|
|
5706
|
-
// "1-of-42" count) — required so the grader can correct for selection bias.
|
|
5707
|
-
trialCount: external_exports.number().int().positive(),
|
|
5708
|
-
// Track-record length in return observations (e.g. 252 for a year of daily returns) —
|
|
5709
|
-
// the `n` in the Probabilistic/Deflated Sharpe Ratio formula.
|
|
5710
|
-
trackRecordObservations: external_exports.number().int().positive(),
|
|
5711
|
-
returnsFrequency: WitanMetricsManifestReturnsFrequencySchema.default("daily"),
|
|
5712
|
-
// Skew/kurtosis of the returns distribution; default to the normal-distribution values
|
|
5713
|
-
// (0 skew, kurtosis 3) when the repo does not report them.
|
|
5714
|
-
skewness: external_exports.number().default(0),
|
|
5715
|
-
kurtosis: external_exports.number().min(0).default(3),
|
|
5716
|
-
// Whether reportedSharpe is net of trading costs (fees/slippage/borrow/roll).
|
|
5717
|
-
netOfCosts: external_exports.boolean(),
|
|
5718
|
-
costModel: WitanMetricsManifestCostModelSchema.optional(),
|
|
5719
|
-
// Per-fold in-sample vs out-of-sample breakdown, when the repo reports one.
|
|
5720
|
-
folds: external_exports.array(WitanMetricsManifestFoldSchema).default([]),
|
|
5721
|
-
// Per-trial, per-block performance matrix for the CSCV/PBO computation, when available.
|
|
5722
|
-
cscv: WitanMetricsManifestCscvSchema.optional(),
|
|
5723
|
-
// Parameter-sweep breakdown for the run-tier (L3b) parameter-neighborhood robustness
|
|
5724
|
-
// grader, when the run swept a parameter (e.g. a lookback window) and recorded OOS
|
|
5725
|
-
// performance at each swept value.
|
|
5726
|
-
parameterSweep: WitanMetricsManifestParameterSweepSchema.optional(),
|
|
5727
|
-
// Provenance of the labels behind reportedSharpe (labelling-integrity, L1+artifact tier).
|
|
5728
|
-
labelSource: WitanMetricsManifestLabelSourceSchema.optional()
|
|
5729
|
-
}).strict();
|
|
5730
|
-
|
|
5731
|
-
// ../shared/src/schemas/witan-strategy-adapter.ts
|
|
5732
|
-
var WITAN_STRATEGY_ADAPTER_CONFIG_SCHEMA_VERSION = "witan-strategy-adapter-v0";
|
|
5733
|
-
var WitanStrategyAdapterConfigSchema = external_exports.object({
|
|
5734
|
-
schemaVersion: external_exports.literal(WITAN_STRATEGY_ADAPTER_CONFIG_SCHEMA_VERSION),
|
|
5735
|
-
// Argv for the strategy entrypoint, e.g. ["python3", "strategy.py"] or ["node", "run.mjs"].
|
|
5736
|
-
// Command-argv (not a language enum) is what keeps the adapter language-agnostic — most
|
|
5737
|
-
// real targets are Python, but the contract does not assume it.
|
|
5738
|
-
command: external_exports.array(external_exports.string().min(1).max(300)).min(1).max(20),
|
|
5739
|
-
// Relative path (within the target repo) to the data the strategy should backtest against.
|
|
5740
|
-
dataPath: external_exports.string().min(1).max(500).optional(),
|
|
5741
|
-
// Backtest window, as the target repo defines its own date strings (ISO-8601 recommended).
|
|
5742
|
-
// Optional — a strategy may declare its own default window instead.
|
|
5743
|
-
windowStart: external_exports.string().min(1).max(40).optional(),
|
|
5744
|
-
windowEnd: external_exports.string().min(1).max(40).optional(),
|
|
5745
|
-
// Relative path (within the sandboxed workspace) the entrypoint must write its raw result
|
|
5746
|
-
// to — see WitanStrategyRunResultSchema below.
|
|
5747
|
-
outputPath: external_exports.string().min(1).max(300).default("witan-run-result.json"),
|
|
5748
|
-
timeoutMs: external_exports.number().int().positive().max(30 * 60 * 1e3).default(2 * 60 * 1e3),
|
|
5749
|
-
// Explicit opt-in egress allowlist. Empty by default — no network from the sandboxed run
|
|
5750
|
-
// unless the target repo explicitly whitelists hosts here.
|
|
5751
|
-
allowedHosts: external_exports.array(external_exports.string().min(1).max(255)).max(20).default([])
|
|
5752
|
-
}).strict();
|
|
5753
|
-
var WitanStrategyRunResultSchema = WitanMetricsManifestSchema.omit({
|
|
5754
|
-
schemaVersion: true
|
|
5755
|
-
});
|
|
5756
|
-
|
|
5757
|
-
// ../shared/src/types/tactical-action.ts
|
|
5758
|
-
var TacticalActionTypeSchema = external_exports.enum([
|
|
5759
|
-
"merge_pr_auto_merge_safe",
|
|
5760
|
-
"deploy_staging",
|
|
5761
|
-
"acknowledge_canary_alert",
|
|
5762
|
-
"update_status_md",
|
|
5763
|
-
"provision_product",
|
|
5764
|
-
"dispatch_dev_task"
|
|
5765
|
-
]);
|
|
5766
|
-
var TacticalActionStatusSchema = external_exports.enum(["executed", "blocked", "dry_run"]);
|
|
5767
|
-
var TacticalActionPolicySchema = external_exports.object({
|
|
5768
|
-
studioId: external_exports.string().uuid(),
|
|
5769
|
-
productId: external_exports.string().uuid(),
|
|
5770
|
-
actionType: TacticalActionTypeSchema,
|
|
5771
|
-
allowed: external_exports.boolean(),
|
|
5772
|
-
dryRun: external_exports.boolean(),
|
|
5773
|
-
promotedAt: external_exports.coerce.date().nullable(),
|
|
5774
|
-
forceEnableReason: external_exports.string().nullable()
|
|
5775
|
-
});
|
|
5776
|
-
var BaseActionSchema = external_exports.object({
|
|
5777
|
-
actionType: TacticalActionTypeSchema,
|
|
5778
|
-
productId: external_exports.string().uuid(),
|
|
5779
|
-
coordinatorSessionId: external_exports.string().uuid().nullable().optional(),
|
|
5780
|
-
customerFacingProduction: external_exports.boolean().default(false)
|
|
5781
|
-
});
|
|
5782
|
-
var MergePrTacticalActionSchema = BaseActionSchema.extend({
|
|
5783
|
-
actionType: external_exports.literal("merge_pr_auto_merge_safe"),
|
|
5784
|
-
repository: external_exports.string().min(1),
|
|
5785
|
-
pullRequestNumber: external_exports.number().int().positive(),
|
|
5786
|
-
labels: external_exports.array(external_exports.string()),
|
|
5787
|
-
ciStatus: external_exports.enum(["green", "red", "unknown"]),
|
|
5788
|
-
humanApprovals: external_exports.number().int().nonnegative(),
|
|
5789
|
-
coworkClaudeApprovedStatus: external_exports.enum(["green", "red", "unknown"]),
|
|
5790
|
-
// The PR head SHA captured at the SAME live precondition snapshot that
|
|
5791
|
-
// verified the label/CI/approvals/cowork-claude-approved gates. Threaded
|
|
5792
|
-
// through to the GitHub merge call as the conditional `sha` parameter so a
|
|
5793
|
-
// commit that lands between the snapshot and the merge (a fast follow-up
|
|
5794
|
-
// push, or a re-triggered CI run resetting status) can never be
|
|
5795
|
-
// squash-merged unverified — GitHub rejects the merge with 409 instead.
|
|
5796
|
-
headSha: external_exports.string().min(1)
|
|
5797
|
-
});
|
|
5798
|
-
var DeployStagingTacticalActionSchema = BaseActionSchema.extend({
|
|
5799
|
-
actionType: external_exports.literal("deploy_staging"),
|
|
5800
|
-
environment: external_exports.literal("staging"),
|
|
5801
|
-
mainStatus: external_exports.enum(["green", "red", "unknown"]),
|
|
5802
|
-
stagingStatus: external_exports.enum(["green", "red", "unknown"])
|
|
5803
|
-
});
|
|
5804
|
-
var AcknowledgeCanaryAlertTacticalActionSchema = BaseActionSchema.extend({
|
|
5805
|
-
actionType: external_exports.literal("acknowledge_canary_alert"),
|
|
5806
|
-
alertId: external_exports.string().min(1),
|
|
5807
|
-
fingerprint: external_exports.string().min(1),
|
|
5808
|
-
knownFalsePositiveFingerprints: external_exports.array(external_exports.string()).default([])
|
|
5809
|
-
});
|
|
5810
|
-
var UpdateStatusMdTacticalActionSchema = BaseActionSchema.extend({
|
|
5811
|
-
actionType: external_exports.literal("update_status_md"),
|
|
5812
|
-
source: external_exports.literal("daily_brief_synthesis"),
|
|
5813
|
-
statusMarkdown: external_exports.string().min(1).max(2e4)
|
|
5814
|
-
});
|
|
5815
|
-
var ProvisionProductTacticalActionSchema = BaseActionSchema.extend({
|
|
5816
|
-
actionType: external_exports.literal("provision_product"),
|
|
5817
|
-
productName: external_exports.string().min(1).max(80),
|
|
5818
|
-
vertical: external_exports.string().min(1).max(80),
|
|
5819
|
-
repoTarget: external_exports.string().min(1),
|
|
5820
|
-
templateRef: external_exports.string().min(1),
|
|
5821
|
-
scopeNotes: external_exports.string().max(2e3).optional()
|
|
5822
|
-
});
|
|
5823
|
-
var DispatchDevTaskTacticalActionSchema = BaseActionSchema.extend({
|
|
5824
|
-
actionType: external_exports.literal("dispatch_dev_task"),
|
|
5825
|
-
repo: RepoRefSchema,
|
|
5826
|
-
task: external_exports.string().min(1).max(2e4),
|
|
5827
|
-
executor: CodingAgentExecutorSchema
|
|
5828
|
-
});
|
|
5829
|
-
var TacticalActionSchema = external_exports.discriminatedUnion("actionType", [
|
|
5830
|
-
MergePrTacticalActionSchema,
|
|
5831
|
-
DeployStagingTacticalActionSchema,
|
|
5832
|
-
AcknowledgeCanaryAlertTacticalActionSchema,
|
|
5833
|
-
UpdateStatusMdTacticalActionSchema,
|
|
5834
|
-
ProvisionProductTacticalActionSchema,
|
|
5835
|
-
DispatchDevTaskTacticalActionSchema
|
|
5836
|
-
]);
|
|
5837
|
-
var TacticalActionContextSchema = external_exports.object({
|
|
5838
|
-
studioId: external_exports.string().uuid(),
|
|
5839
|
-
actorUserId: external_exports.string().uuid().nullable().optional(),
|
|
5840
|
-
requestedAt: external_exports.coerce.date().optional()
|
|
5841
|
-
});
|
|
5842
|
-
var TacticalActionPermitResultSchema = external_exports.discriminatedUnion("status", [
|
|
5843
|
-
external_exports.object({
|
|
5844
|
-
status: external_exports.literal("executed"),
|
|
5845
|
-
auditLogId: external_exports.string().uuid(),
|
|
5846
|
-
reason: external_exports.literal("permit_allowed")
|
|
5847
|
-
}),
|
|
4713
|
+
var WITAN_ATTESTATION_STATEMENT_TYPE = "https://in-toto.io/Statement/v1";
|
|
4714
|
+
var WITAN_ATTESTATION_PREDICATE_TYPE = "https://cejel.dev/attestations/scan/v1";
|
|
4715
|
+
var WitanAttestationOutcomeSchema = external_exports.discriminatedUnion("status", [
|
|
5848
4716
|
external_exports.object({
|
|
5849
|
-
status: external_exports.literal("
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
4717
|
+
status: external_exports.literal("scored"),
|
|
4718
|
+
overallScore: external_exports.number().min(0).max(4),
|
|
4719
|
+
codeTrustScore: external_exports.number().min(0).max(4),
|
|
4720
|
+
processTrustScore: external_exports.number().min(0).max(4)
|
|
4721
|
+
}).strict(),
|
|
5853
4722
|
external_exports.object({
|
|
5854
|
-
status: external_exports.literal("
|
|
5855
|
-
|
|
5856
|
-
|
|
5857
|
-
wouldHaveDone: external_exports.record(external_exports.unknown())
|
|
5858
|
-
})
|
|
5859
|
-
]);
|
|
5860
|
-
var TacticalActionLogEntrySchema = external_exports.object({
|
|
5861
|
-
id: external_exports.string().uuid(),
|
|
5862
|
-
studioId: external_exports.string().uuid(),
|
|
5863
|
-
productId: external_exports.string().uuid(),
|
|
5864
|
-
product: external_exports.string().nullable().optional(),
|
|
5865
|
-
coordinatorSessionId: external_exports.string().uuid().nullable(),
|
|
5866
|
-
actionType: TacticalActionTypeSchema.or(external_exports.string()),
|
|
5867
|
-
context: external_exports.record(external_exports.unknown()),
|
|
5868
|
-
permitResult: external_exports.record(external_exports.unknown()),
|
|
5869
|
-
status: TacticalActionStatusSchema,
|
|
5870
|
-
outcome: external_exports.string().nullable(),
|
|
5871
|
-
wouldHaveDone: external_exports.record(external_exports.unknown()).nullable(),
|
|
5872
|
-
attemptedAt: external_exports.string(),
|
|
5873
|
-
executedAt: external_exports.string().nullable()
|
|
5874
|
-
});
|
|
5875
|
-
|
|
5876
|
-
// ../shared/src/schemas/index.ts
|
|
5877
|
-
var StudioSchema = external_exports.object({
|
|
5878
|
-
id: external_exports.string().uuid(),
|
|
5879
|
-
name: external_exports.string().min(1).max(100),
|
|
5880
|
-
billingStatus: external_exports.enum(["trial", "active", "past_due", "cancelled"]),
|
|
5881
|
-
planTier: external_exports.enum(["trial", "solo", "studio", "studio_plus", "self_hosted", "enterprise"]),
|
|
5882
|
-
onPrem: external_exports.boolean().default(false),
|
|
5883
|
-
createdAt: external_exports.coerce.date()
|
|
5884
|
-
});
|
|
5885
|
-
var HumanSchema = external_exports.object({
|
|
5886
|
-
id: external_exports.string().uuid(),
|
|
5887
|
-
studioId: external_exports.string().uuid(),
|
|
5888
|
-
email: external_exports.string().email(),
|
|
5889
|
-
name: external_exports.string().min(1).max(120),
|
|
5890
|
-
oauthProviders: external_exports.array(external_exports.enum(["google", "microsoft", "apple"])).default([]),
|
|
5891
|
-
role: external_exports.enum(["owner", "member", "advisor", "per_product"]),
|
|
5892
|
-
timezone: external_exports.string(),
|
|
5893
|
-
briefTime: external_exports.string().regex(/^\d{2}:\d{2}$/),
|
|
5894
|
-
createdAt: external_exports.coerce.date()
|
|
5895
|
-
});
|
|
5896
|
-
var ProductSchema = external_exports.object({
|
|
5897
|
-
id: external_exports.string().uuid(),
|
|
5898
|
-
studioId: external_exports.string().uuid(),
|
|
5899
|
-
name: external_exports.string().min(1).max(80),
|
|
5900
|
-
slug: external_exports.string().regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$/),
|
|
5901
|
-
status: external_exports.enum(["active", "snoozed", "wound_down", "deleted"]),
|
|
5902
|
-
description: external_exports.string().max(280).optional(),
|
|
5903
|
-
repoUrl: external_exports.string().url().optional(),
|
|
5904
|
-
calendarTag: external_exports.string().optional(),
|
|
5905
|
-
emailLabelPrefix: external_exports.string().optional(),
|
|
5906
|
-
colorHex: external_exports.string().regex(/^#[0-9a-fA-F]{6}$/).optional(),
|
|
5907
|
-
scheduleBriefTime: external_exports.string().regex(/^\d{2}:\d{2}$/).optional(),
|
|
5908
|
-
briefTemplateId: external_exports.string().uuid().optional(),
|
|
5909
|
-
regulated: external_exports.boolean().default(false),
|
|
5910
|
-
createdAt: external_exports.coerce.date(),
|
|
5911
|
-
lastTouchedAt: external_exports.coerce.date()
|
|
5912
|
-
});
|
|
5913
|
-
var AgentSchema = external_exports.object({
|
|
5914
|
-
id: external_exports.string().uuid(),
|
|
5915
|
-
studioId: external_exports.string().uuid(),
|
|
5916
|
-
productId: external_exports.string().uuid(),
|
|
5917
|
-
agentType: external_exports.enum(["codex", "claude-code", "cowork", "cursor", "cline", "aider", "other"]),
|
|
5918
|
-
sessionId: external_exports.string().optional(),
|
|
5919
|
-
status: external_exports.enum(["active", "idle", "registered", "archived"]),
|
|
5920
|
-
registeredAt: external_exports.coerce.date(),
|
|
5921
|
-
lastActiveAt: external_exports.coerce.date().optional(),
|
|
5922
|
-
totalCostCentsLifetime: external_exports.number().int().nonnegative().default(0)
|
|
5923
|
-
});
|
|
5924
|
-
var AgentRunSchema = external_exports.object({
|
|
5925
|
-
id: external_exports.string().uuid(),
|
|
5926
|
-
agentId: external_exports.string().uuid(),
|
|
5927
|
-
coordinatorSessionId: external_exports.string().uuid().nullable().optional(),
|
|
5928
|
-
startedAt: external_exports.coerce.date(),
|
|
5929
|
-
completedAt: external_exports.coerce.date().optional(),
|
|
5930
|
-
actionType: external_exports.string(),
|
|
5931
|
-
toolName: external_exports.string().optional(),
|
|
5932
|
-
toolInputSummary: external_exports.string().optional(),
|
|
5933
|
-
toolOutputSummary: external_exports.string().optional(),
|
|
5934
|
-
tokensUsedInput: external_exports.number().int().nonnegative().default(0),
|
|
5935
|
-
tokensUsedOutput: external_exports.number().int().nonnegative().default(0),
|
|
5936
|
-
costCents: external_exports.number().int().nonnegative().default(0),
|
|
5937
|
-
durationMs: external_exports.number().int().nonnegative().default(0),
|
|
5938
|
-
resultStatus: external_exports.enum(["success", "failure", "partial", "timeout"]).optional(),
|
|
5939
|
-
resultSummary: external_exports.string().optional(),
|
|
5940
|
-
filesTouched: external_exports.array(external_exports.string()).default([])
|
|
5941
|
-
});
|
|
5942
|
-
var CoordinatorStatusSchema = external_exports.enum([
|
|
5943
|
-
"draft",
|
|
5944
|
-
"spawned",
|
|
5945
|
-
"in_progress",
|
|
5946
|
-
"reporting",
|
|
5947
|
-
"closed"
|
|
4723
|
+
status: external_exports.literal("abstained"),
|
|
4724
|
+
reason: external_exports.string().min(1).max(2e3)
|
|
4725
|
+
}).strict()
|
|
5948
4726
|
]);
|
|
5949
|
-
var
|
|
5950
|
-
|
|
5951
|
-
|
|
5952
|
-
urgency: external_exports.enum(["low", "medium", "high", "critical"]).optional()
|
|
5953
|
-
});
|
|
5954
|
-
var CoordinatorSessionSchema = external_exports.object({
|
|
5955
|
-
id: external_exports.string().uuid(),
|
|
5956
|
-
studioId: external_exports.string().uuid(),
|
|
5957
|
-
productId: external_exports.string().uuid(),
|
|
5958
|
-
promptId: external_exports.string().uuid().nullable(),
|
|
5959
|
-
objective: external_exports.string(),
|
|
5960
|
-
status: CoordinatorStatusSchema,
|
|
5961
|
-
spawnedAt: external_exports.coerce.date().nullable(),
|
|
5962
|
-
closedAt: external_exports.coerce.date().nullable(),
|
|
5963
|
-
escalationPolicy: CoordinatorEscalationPolicySchema.nullable(),
|
|
5964
|
-
outcomeSummary: external_exports.string().nullable(),
|
|
5965
|
-
createdAt: external_exports.coerce.date()
|
|
5966
|
-
});
|
|
5967
|
-
var AgentActivityWindowSchema = external_exports.enum(["24h", "7d", "30d"]);
|
|
5968
|
-
var AgentCostBucketSchema = external_exports.object({
|
|
5969
|
-
key: external_exports.string(),
|
|
5970
|
-
name: external_exports.string(),
|
|
5971
|
-
runCount: external_exports.number().int().nonnegative(),
|
|
5972
|
-
costUsd: external_exports.number().nonnegative()
|
|
5973
|
-
});
|
|
5974
|
-
var AgentCostRollupSchema = external_exports.object({
|
|
5975
|
-
window: AgentActivityWindowSchema,
|
|
5976
|
-
studioTotalUsd: external_exports.number().nonnegative(),
|
|
5977
|
-
runCount: external_exports.number().int().nonnegative(),
|
|
5978
|
-
byAgent: external_exports.array(AgentCostBucketSchema),
|
|
5979
|
-
byProduct: external_exports.array(AgentCostBucketSchema)
|
|
5980
|
-
});
|
|
5981
|
-
var AgentConflictRecordSchema = external_exports.object({
|
|
5982
|
-
file: external_exports.string(),
|
|
5983
|
-
agents: external_exports.array(external_exports.string()).min(2),
|
|
5984
|
-
references: external_exports.array(
|
|
4727
|
+
var WitanAttestationStatementSchema = external_exports.object({
|
|
4728
|
+
_type: external_exports.literal(WITAN_ATTESTATION_STATEMENT_TYPE),
|
|
4729
|
+
subject: external_exports.array(
|
|
5985
4730
|
external_exports.object({
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
5989
|
-
|
|
5990
|
-
|
|
5991
|
-
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
|
|
5995
|
-
|
|
5996
|
-
|
|
5997
|
-
|
|
5998
|
-
|
|
5999
|
-
|
|
6000
|
-
|
|
6001
|
-
|
|
6002
|
-
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
|
|
6006
|
-
|
|
6007
|
-
|
|
6008
|
-
|
|
6009
|
-
|
|
6010
|
-
|
|
6011
|
-
|
|
6012
|
-
|
|
6013
|
-
|
|
6014
|
-
|
|
6015
|
-
|
|
6016
|
-
})
|
|
6017
|
-
|
|
6018
|
-
id: external_exports.string().uuid(),
|
|
6019
|
-
studioId: external_exports.string().uuid(),
|
|
6020
|
-
productId: external_exports.string().uuid().nullable(),
|
|
6021
|
-
kind: external_exports.string(),
|
|
6022
|
-
oauthTokenEncrypted: external_exports.string().optional(),
|
|
6023
|
-
refreshTokenEncrypted: external_exports.string().optional(),
|
|
6024
|
-
status: external_exports.enum(["active", "broken", "revoked"]),
|
|
6025
|
-
lastSyncAt: external_exports.coerce.date().optional(),
|
|
6026
|
-
errorCount: external_exports.number().int().nonnegative().default(0)
|
|
6027
|
-
});
|
|
6028
|
-
var EmailAccountSchema = external_exports.object({
|
|
6029
|
-
id: external_exports.string().uuid(),
|
|
6030
|
-
studioId: external_exports.string().uuid(),
|
|
6031
|
-
provider: external_exports.enum(["gmail", "m365", "imap"]),
|
|
6032
|
-
oauthTokenEncrypted: external_exports.string().optional(),
|
|
6033
|
-
defaultLabelPrefix: external_exports.string().optional(),
|
|
6034
|
-
triageCadenceMins: external_exports.number().int().positive().default(240)
|
|
6035
|
-
});
|
|
6036
|
-
var RoutineSchema = external_exports.object({
|
|
6037
|
-
id: external_exports.string().uuid(),
|
|
6038
|
-
productId: external_exports.string().uuid().nullable(),
|
|
6039
|
-
name: external_exports.string(),
|
|
6040
|
-
cronExpression: external_exports.string(),
|
|
6041
|
-
promptTemplate: external_exports.string(),
|
|
6042
|
-
model: external_exports.enum(["sonnet", "opus", "haiku"]).default("sonnet"),
|
|
6043
|
-
lastRunAt: external_exports.coerce.date().optional(),
|
|
6044
|
-
nextRunAt: external_exports.coerce.date().optional(),
|
|
6045
|
-
enabled: external_exports.boolean().default(true),
|
|
6046
|
-
retryCount: external_exports.number().int().nonnegative().default(0)
|
|
6047
|
-
});
|
|
6048
|
-
var RoutineRunSchema = external_exports.object({
|
|
6049
|
-
id: external_exports.string().uuid(),
|
|
6050
|
-
routineId: external_exports.string().uuid(),
|
|
6051
|
-
startedAt: external_exports.coerce.date(),
|
|
6052
|
-
completedAt: external_exports.coerce.date().optional(),
|
|
6053
|
-
status: external_exports.enum(["success", "failed", "retried"]),
|
|
6054
|
-
outputBriefId: external_exports.string().uuid().optional(),
|
|
6055
|
-
errorMessage: external_exports.string().optional(),
|
|
6056
|
-
inferenceCostCents: external_exports.number().int().nonnegative().default(0)
|
|
6057
|
-
});
|
|
6058
|
-
var BriefSchema = external_exports.object({
|
|
6059
|
-
id: external_exports.string().uuid(),
|
|
6060
|
-
studioId: external_exports.string().uuid(),
|
|
6061
|
-
generatedAt: external_exports.coerce.date(),
|
|
6062
|
-
type: external_exports.enum(["daily", "weekly", "on_demand"]),
|
|
6063
|
-
html: external_exports.string().optional(),
|
|
6064
|
-
markdown: external_exports.string(),
|
|
6065
|
-
sourceLinks: external_exports.array(external_exports.object({ label: external_exports.string(), url: external_exports.string() })).default([]),
|
|
6066
|
-
shared: external_exports.boolean().default(false),
|
|
6067
|
-
shareToken: external_exports.string().optional(),
|
|
6068
|
-
shareExpiresAt: external_exports.coerce.date().optional(),
|
|
6069
|
-
inferenceCostCents: external_exports.number().int().nonnegative().default(0)
|
|
6070
|
-
});
|
|
6071
|
-
var MemoryEntrySchema = external_exports.object({
|
|
6072
|
-
id: external_exports.string().uuid(),
|
|
6073
|
-
productId: external_exports.string().uuid(),
|
|
6074
|
-
kind: external_exports.enum(["decision", "fact", "customer", "status", "pattern", "thread"]),
|
|
6075
|
-
content: external_exports.string(),
|
|
6076
|
-
// embedding stored separately in pgvector; not modelled in API layer
|
|
6077
|
-
createdAt: external_exports.coerce.date(),
|
|
6078
|
-
lastReferencedAt: external_exports.coerce.date().optional(),
|
|
6079
|
-
referenceCount: external_exports.number().int().nonnegative().default(0),
|
|
6080
|
-
pinned: external_exports.boolean().default(false)
|
|
6081
|
-
});
|
|
6082
|
-
var InboxClassificationSchema = external_exports.object({
|
|
6083
|
-
id: external_exports.string().uuid(),
|
|
6084
|
-
emailAccountId: external_exports.string().uuid(),
|
|
6085
|
-
productId: external_exports.string().uuid().nullable(),
|
|
6086
|
-
messageId: external_exports.string(),
|
|
6087
|
-
sender: external_exports.string(),
|
|
6088
|
-
labelApplied: external_exports.string(),
|
|
6089
|
-
urgency: external_exports.enum(["needs_reply", "fyi", "noise", "escalation"]),
|
|
6090
|
-
confidence: external_exports.number().min(0).max(1),
|
|
6091
|
-
action: external_exports.enum(["labelled", "archived", "drafted_reply"]),
|
|
6092
|
-
userCorrected: external_exports.boolean().default(false),
|
|
6093
|
-
correctedTo: external_exports.string().optional()
|
|
6094
|
-
});
|
|
6095
|
-
var DraftReplySchema = external_exports.object({
|
|
6096
|
-
id: external_exports.string().uuid(),
|
|
6097
|
-
classificationId: external_exports.string().uuid(),
|
|
6098
|
-
draftText: external_exports.string(),
|
|
6099
|
-
confidence: external_exports.number().min(0).max(1),
|
|
6100
|
-
sentAt: external_exports.coerce.date().optional(),
|
|
6101
|
-
sentVia: external_exports.string().optional()
|
|
6102
|
-
});
|
|
6103
|
-
var AlwaysAlertRuleSchema = external_exports.object({
|
|
6104
|
-
id: external_exports.string().uuid(),
|
|
6105
|
-
studioId: external_exports.string().uuid(),
|
|
6106
|
-
ruleType: external_exports.enum(["sender", "subject", "domain"]),
|
|
6107
|
-
value: external_exports.string(),
|
|
6108
|
-
escalationMethod: external_exports.enum(["push", "slack", "email", "brief_pin"]).default("brief_pin")
|
|
6109
|
-
});
|
|
6110
|
-
var AuditEventSchema = external_exports.object({
|
|
6111
|
-
id: external_exports.string().uuid(),
|
|
6112
|
-
studioId: external_exports.string().uuid(),
|
|
6113
|
-
actor: external_exports.enum(["user", "agent", "system"]),
|
|
6114
|
-
action: external_exports.string(),
|
|
6115
|
-
integrationId: external_exports.string().uuid().optional(),
|
|
6116
|
-
productId: external_exports.string().uuid().optional(),
|
|
6117
|
-
timestamp: external_exports.coerce.date(),
|
|
6118
|
-
metadata: external_exports.record(external_exports.unknown()).default({})
|
|
6119
|
-
});
|
|
6120
|
-
var SubscriptionSchema = external_exports.object({
|
|
6121
|
-
id: external_exports.string().uuid(),
|
|
6122
|
-
studioId: external_exports.string().uuid(),
|
|
6123
|
-
stripeSubscriptionId: external_exports.string().optional(),
|
|
6124
|
-
tier: external_exports.enum(["trial", "solo", "studio", "studio_plus", "self_hosted", "enterprise"]),
|
|
6125
|
-
seats: external_exports.number().int().positive(),
|
|
6126
|
-
status: external_exports.string(),
|
|
6127
|
-
currentPeriodEnd: external_exports.coerce.date(),
|
|
6128
|
-
cancelAt: external_exports.coerce.date().optional()
|
|
6129
|
-
});
|
|
6130
|
-
var ProductMembershipSchema = external_exports.object({
|
|
6131
|
-
humanId: external_exports.string().uuid(),
|
|
6132
|
-
productId: external_exports.string().uuid(),
|
|
6133
|
-
role: external_exports.enum(["lead", "contributor", "observer"])
|
|
6134
|
-
});
|
|
6135
|
-
|
|
6136
|
-
// ../witan/src/batch.ts
|
|
6137
|
-
import { execFileSync as execFileSync3 } from "child_process";
|
|
6138
|
-
import { mkdirSync as mkdirSync2, writeFileSync } from "fs";
|
|
6139
|
-
import { basename as basename2, join as join5 } from "path";
|
|
6140
|
-
|
|
6141
|
-
// ../witan/src/public-scan.ts
|
|
6142
|
-
import { resolve as resolve2 } from "path";
|
|
6143
|
-
|
|
6144
|
-
// ../witan/src/ingest.ts
|
|
6145
|
-
import { readFileSync as readFileSync5, readdirSync as readdirSync2 } from "fs";
|
|
6146
|
-
import { join as join2 } from "path";
|
|
4731
|
+
name: external_exports.string().min(1).max(300),
|
|
4732
|
+
digest: external_exports.object({
|
|
4733
|
+
sha256: external_exports.string().regex(/^[a-f0-9]{64}$/)
|
|
4734
|
+
}).strict()
|
|
4735
|
+
}).strict()
|
|
4736
|
+
).length(1),
|
|
4737
|
+
predicateType: external_exports.literal(WITAN_ATTESTATION_PREDICATE_TYPE),
|
|
4738
|
+
predicate: external_exports.object({
|
|
4739
|
+
tool: external_exports.object({
|
|
4740
|
+
name: external_exports.literal("cejel"),
|
|
4741
|
+
version: external_exports.string().min(1).max(80)
|
|
4742
|
+
}).strict(),
|
|
4743
|
+
generatedAt: external_exports.string().datetime({ offset: true }),
|
|
4744
|
+
rubricVersion: external_exports.string().min(1).max(120),
|
|
4745
|
+
repository: external_exports.object({
|
|
4746
|
+
productSlug: external_exports.string().regex(/^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/),
|
|
4747
|
+
url: external_exports.string().url().optional(),
|
|
4748
|
+
headSha: external_exports.string().min(7).max(64).optional()
|
|
4749
|
+
}).strict(),
|
|
4750
|
+
report: external_exports.object({
|
|
4751
|
+
artifact: external_exports.literal("report.json"),
|
|
4752
|
+
sha256: external_exports.string().regex(/^[a-f0-9]{64}$/)
|
|
4753
|
+
}).strict(),
|
|
4754
|
+
outcome: WitanAttestationOutcomeSchema,
|
|
4755
|
+
assurance: external_exports.object({
|
|
4756
|
+
status: external_exports.literal("unsigned"),
|
|
4757
|
+
issuer: external_exports.literal("self-generated"),
|
|
4758
|
+
signingHint: external_exports.string().min(1).max(500)
|
|
4759
|
+
}).strict(),
|
|
4760
|
+
limitations: external_exports.array(external_exports.string().min(1).max(500)).min(1).max(8)
|
|
4761
|
+
}).strict()
|
|
4762
|
+
}).strict();
|
|
6147
4763
|
|
|
6148
|
-
//
|
|
6149
|
-
var
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
4764
|
+
// src/witan/attestation.ts
|
|
4765
|
+
var ATTESTATION_LIMITATIONS = [
|
|
4766
|
+
"Cejel measures observable repository signals; it is not a security or compliance guarantee.",
|
|
4767
|
+
"This statement is self-generated and unsigned until an external signer binds their identity to it."
|
|
4768
|
+
];
|
|
4769
|
+
function serializeWitanReport(report) {
|
|
4770
|
+
return JSON.stringify(report, null, 2);
|
|
4771
|
+
}
|
|
4772
|
+
function hashWitanReport(report) {
|
|
4773
|
+
return createHash("sha256").update(serializeWitanReport(report), "utf8").digest("hex");
|
|
4774
|
+
}
|
|
4775
|
+
function createWitanAttestation(report, options) {
|
|
4776
|
+
const reportSha256 = hashWitanReport(report);
|
|
4777
|
+
const outcome = report.insufficientSourceReason ? {
|
|
4778
|
+
status: "abstained",
|
|
4779
|
+
reason: report.insufficientSourceReason
|
|
4780
|
+
} : {
|
|
4781
|
+
status: "scored",
|
|
4782
|
+
overallScore: report.overallScore,
|
|
4783
|
+
codeTrustScore: report.codeTrustScore,
|
|
4784
|
+
processTrustScore: report.processTrustScore
|
|
6163
4785
|
};
|
|
4786
|
+
return WitanAttestationStatementSchema.parse({
|
|
4787
|
+
_type: WITAN_ATTESTATION_STATEMENT_TYPE,
|
|
4788
|
+
subject: [
|
|
4789
|
+
{
|
|
4790
|
+
name: `${report.productSlug}/report.json`,
|
|
4791
|
+
digest: { sha256: reportSha256 }
|
|
4792
|
+
}
|
|
4793
|
+
],
|
|
4794
|
+
predicateType: WITAN_ATTESTATION_PREDICATE_TYPE,
|
|
4795
|
+
predicate: {
|
|
4796
|
+
tool: { name: "cejel", version: options.toolVersion },
|
|
4797
|
+
generatedAt: report.generatedAt,
|
|
4798
|
+
rubricVersion: report.rubricVersion,
|
|
4799
|
+
repository: {
|
|
4800
|
+
productSlug: report.productSlug,
|
|
4801
|
+
...report.repo.url ? { url: report.repo.url } : {},
|
|
4802
|
+
...report.repo.headSha ? { headSha: report.repo.headSha } : {}
|
|
4803
|
+
},
|
|
4804
|
+
report: {
|
|
4805
|
+
artifact: "report.json",
|
|
4806
|
+
sha256: reportSha256
|
|
4807
|
+
},
|
|
4808
|
+
outcome,
|
|
4809
|
+
assurance: {
|
|
4810
|
+
status: "unsigned",
|
|
4811
|
+
issuer: "self-generated",
|
|
4812
|
+
signingHint: "Sign this in-toto statement with your existing provenance system; verify the report digest before relying on it."
|
|
4813
|
+
},
|
|
4814
|
+
limitations: [...ATTESTATION_LIMITATIONS]
|
|
4815
|
+
}
|
|
4816
|
+
});
|
|
6164
4817
|
}
|
|
6165
4818
|
|
|
6166
|
-
//
|
|
6167
|
-
import {
|
|
4819
|
+
// src/witan/repo-signals.ts
|
|
4820
|
+
import { execFileSync } from "child_process";
|
|
4821
|
+
import { createHash as createHash2 } from "crypto";
|
|
4822
|
+
import { readFileSync, readdirSync, realpathSync, statSync } from "fs";
|
|
4823
|
+
import { basename, join, relative, resolve, sep } from "path";
|
|
6168
4824
|
|
|
6169
|
-
//
|
|
4825
|
+
// src/witan/json-safe.ts
|
|
6170
4826
|
function stripBom(text) {
|
|
6171
4827
|
return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
|
|
6172
4828
|
}
|
|
6173
4829
|
|
|
6174
|
-
//
|
|
6175
|
-
var VALID_DIMENSIONS = /* @__PURE__ */ new Set([
|
|
6176
|
-
"A1",
|
|
6177
|
-
"A2",
|
|
6178
|
-
"A3",
|
|
6179
|
-
"A4",
|
|
6180
|
-
"A5",
|
|
6181
|
-
"B1",
|
|
6182
|
-
"B2",
|
|
6183
|
-
"B3",
|
|
6184
|
-
"B4",
|
|
6185
|
-
"B5",
|
|
6186
|
-
"B6"
|
|
6187
|
-
]);
|
|
6188
|
-
var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "warning", "info"]);
|
|
6189
|
-
function isGenericSignalDocument(raw) {
|
|
6190
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
|
|
6191
|
-
const doc = raw;
|
|
6192
|
-
return typeof doc.tool === "string" && doc.tool.length > 0 && Array.isArray(doc.signals);
|
|
6193
|
-
}
|
|
6194
|
-
function parseGenericJson(raw) {
|
|
6195
|
-
if (!isGenericSignalDocument(raw)) return [];
|
|
6196
|
-
const source = raw.tool ?? "unknown";
|
|
6197
|
-
const signals = [];
|
|
6198
|
-
for (const signal of raw.signals ?? []) {
|
|
6199
|
-
const dimension = signal.dimension;
|
|
6200
|
-
if (!dimension || !VALID_DIMENSIONS.has(dimension)) continue;
|
|
6201
|
-
const weight = typeof signal.weight === "number" && Number.isFinite(signal.weight) ? Math.min(Math.max(signal.weight, 0), 1) : 0.5;
|
|
6202
|
-
const findings = [];
|
|
6203
|
-
for (const finding of signal.findings ?? []) {
|
|
6204
|
-
const severity = finding.severity;
|
|
6205
|
-
if (!severity || !VALID_SEVERITIES.has(severity)) continue;
|
|
6206
|
-
const ruleId = finding.ruleId ?? "unknown";
|
|
6207
|
-
findings.push({
|
|
6208
|
-
ruleId,
|
|
6209
|
-
severity,
|
|
6210
|
-
message: finding.message ?? ruleId,
|
|
6211
|
-
...finding.location ? { location: finding.location } : {}
|
|
6212
|
-
});
|
|
6213
|
-
}
|
|
6214
|
-
if (findings.length === 0) continue;
|
|
6215
|
-
signals.push({ source, dimension, weight, findings });
|
|
6216
|
-
}
|
|
6217
|
-
return signals;
|
|
6218
|
-
}
|
|
6219
|
-
|
|
6220
|
-
// ../witan/src/sarif-adapter.ts
|
|
6221
|
-
import { readFileSync as readFileSync3 } from "fs";
|
|
6222
|
-
var DIMENSION_RULES = [
|
|
6223
|
-
// A2 — injection / secrets / auth (high weight)
|
|
6224
|
-
{
|
|
6225
|
-
pattern: /sql[- _]?inject|cwe-89|sqli|command[- _]?inject|cwe-78|os[- _]?cmd|rce|remote[- _]?code/i,
|
|
6226
|
-
dimension: "A2",
|
|
6227
|
-
weight: 0.9
|
|
6228
|
-
},
|
|
6229
|
-
{
|
|
6230
|
-
pattern: /secret|credential|api[- _]?key|password[- _]?leak|hardcoded[- _]?(token|key|secret)|cwe-259|cwe-798/i,
|
|
6231
|
-
dimension: "A2",
|
|
6232
|
-
weight: 0.9
|
|
6233
|
-
},
|
|
6234
|
-
{
|
|
6235
|
-
pattern: /path[- _]?traversal|directory[- _]?traversal|cwe-22|lfi|rfi/i,
|
|
6236
|
-
dimension: "A2",
|
|
6237
|
-
weight: 0.8
|
|
6238
|
-
},
|
|
6239
|
-
{
|
|
6240
|
-
pattern: /ssrf|server[- _]?side[- _]?request[- _]?forg|cwe-918/i,
|
|
6241
|
-
dimension: "A2",
|
|
6242
|
-
weight: 0.8
|
|
6243
|
-
},
|
|
6244
|
-
{
|
|
6245
|
-
pattern: /xxe|xml[- _]?external[- _]?entity|cwe-611/i,
|
|
6246
|
-
dimension: "A2",
|
|
6247
|
-
weight: 0.8
|
|
6248
|
-
},
|
|
6249
|
-
{
|
|
6250
|
-
pattern: /auth[- _]?bypass|broken[- _]?auth|missing[- _]?auth|cwe-287|cwe-306|cwe-863|cwe-862/i,
|
|
6251
|
-
dimension: "A2",
|
|
6252
|
-
weight: 0.7
|
|
6253
|
-
},
|
|
6254
|
-
{
|
|
6255
|
-
pattern: /xss|cross[- _]?site[- _]?script|cwe-79/i,
|
|
6256
|
-
dimension: "A2",
|
|
6257
|
-
weight: 0.6
|
|
6258
|
-
},
|
|
6259
|
-
// A4 — dependency vulnerabilities
|
|
6260
|
-
{
|
|
6261
|
-
pattern: /cve-\d{4}-\d+|supply[- _]?chain|depend[a-z]*[- _]?vulner|outdated[- _]?depend|deprecated[- _]?package/i,
|
|
6262
|
-
dimension: "A4",
|
|
6263
|
-
weight: 0.8
|
|
6264
|
-
},
|
|
6265
|
-
{
|
|
6266
|
-
pattern: /npm[- _]?audit|yarn[- _]?audit|pnpm[- _]?audit|pip[- _]?audit|cargo[- _]?audit/i,
|
|
6267
|
-
dimension: "A4",
|
|
6268
|
-
weight: 0.7
|
|
6269
|
-
},
|
|
6270
|
-
// A3 — production readiness / insecure config
|
|
6271
|
-
{
|
|
6272
|
-
pattern: /insecure[- _]?tls|weak[- _]?cipher|tls[- _]?version|http[- _]?strict|hsts|csp[- _]?missing|cwe-326|cwe-327/i,
|
|
6273
|
-
dimension: "A3",
|
|
6274
|
-
weight: 0.5
|
|
6275
|
-
},
|
|
6276
|
-
{
|
|
6277
|
-
pattern: /error[- _]?handl|unhandled[- _]?exception|crash|uncaught|stacktrace[- _]?leak/i,
|
|
6278
|
-
dimension: "A3",
|
|
6279
|
-
weight: 0.4
|
|
6280
|
-
},
|
|
6281
|
-
{
|
|
6282
|
-
pattern: /debug[- _]?mode|dev[- _]?endpoint|staging[- _]?secret/i,
|
|
6283
|
-
dimension: "A3",
|
|
6284
|
-
weight: 0.4
|
|
6285
|
-
},
|
|
6286
|
-
// A1 — test integrity (low weight; SARIF rarely surfaces this)
|
|
6287
|
-
{
|
|
6288
|
-
pattern: /skipped[- _]?test|hollow[- _]?test|empty[- _]?assert|no[- _]?assertion/i,
|
|
6289
|
-
dimension: "A1",
|
|
6290
|
-
weight: 0.2
|
|
6291
|
-
}
|
|
6292
|
-
];
|
|
6293
|
-
var DEFAULT_DIMENSION = "A2";
|
|
6294
|
-
var DEFAULT_WEIGHT = 0.3;
|
|
6295
|
-
var DROP_LEVEL = /* @__PURE__ */ new Set(["none"]);
|
|
6296
|
-
function mapLevel(level) {
|
|
6297
|
-
if (!level || DROP_LEVEL.has(level)) return null;
|
|
6298
|
-
if (level === "error") return "critical";
|
|
6299
|
-
if (level === "warning") return "warning";
|
|
6300
|
-
return "info";
|
|
6301
|
-
}
|
|
6302
|
-
function mapRuleToDimension(ruleId, rules) {
|
|
6303
|
-
for (const rule of rules) {
|
|
6304
|
-
if (rule.pattern.test(ruleId)) {
|
|
6305
|
-
return { dimension: rule.dimension, weight: rule.weight };
|
|
6306
|
-
}
|
|
6307
|
-
}
|
|
6308
|
-
return { dimension: DEFAULT_DIMENSION, weight: DEFAULT_WEIGHT };
|
|
6309
|
-
}
|
|
6310
|
-
function renderLocation(result) {
|
|
6311
|
-
const loc = result.locations?.[0]?.physicalLocation;
|
|
6312
|
-
if (!loc) return void 0;
|
|
6313
|
-
const uri = loc.artifactLocation?.uri;
|
|
6314
|
-
const line = loc.region?.startLine;
|
|
6315
|
-
if (!uri) return void 0;
|
|
6316
|
-
return line != null ? `${uri}:${line}` : uri;
|
|
6317
|
-
}
|
|
6318
|
-
function dedupeFindings(findings) {
|
|
6319
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6320
|
-
return findings.filter((f) => {
|
|
6321
|
-
const key = `${f.ruleId}|${f.severity}|${f.location ?? ""}`;
|
|
6322
|
-
if (seen.has(key)) return false;
|
|
6323
|
-
seen.add(key);
|
|
6324
|
-
return true;
|
|
6325
|
-
});
|
|
6326
|
-
}
|
|
6327
|
-
function parseSarifJson(raw, extraDimensionRules) {
|
|
6328
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return [];
|
|
6329
|
-
const dimensionRules = extraDimensionRules ? [...DIMENSION_RULES, ...extraDimensionRules] : DIMENSION_RULES;
|
|
6330
|
-
const doc = raw;
|
|
6331
|
-
if (!Array.isArray(doc.runs)) return [];
|
|
6332
|
-
const buckets = /* @__PURE__ */ new Map();
|
|
6333
|
-
for (const run of doc.runs) {
|
|
6334
|
-
const driverName = run.tool?.driver?.name ?? "unknown";
|
|
6335
|
-
const source = `sarif:${driverName}`;
|
|
6336
|
-
const ruleDefaultLevels = /* @__PURE__ */ new Map();
|
|
6337
|
-
for (const rule of run.tool?.driver?.rules ?? []) {
|
|
6338
|
-
if (rule.id && rule.defaultConfiguration?.level) {
|
|
6339
|
-
ruleDefaultLevels.set(rule.id, rule.defaultConfiguration.level);
|
|
6340
|
-
}
|
|
6341
|
-
}
|
|
6342
|
-
for (const result of run.results ?? []) {
|
|
6343
|
-
const ruleId = result.ruleId ?? "unknown";
|
|
6344
|
-
const effectiveLevel = result.level ?? ruleDefaultLevels.get(ruleId) ?? "warning";
|
|
6345
|
-
const severity = mapLevel(effectiveLevel);
|
|
6346
|
-
if (!severity) continue;
|
|
6347
|
-
const message = result.message?.text ?? ruleId;
|
|
6348
|
-
const location = renderLocation(result);
|
|
6349
|
-
const { dimension, weight } = mapRuleToDimension(ruleId, dimensionRules);
|
|
6350
|
-
const bucketKey = `${source}|${dimension}`;
|
|
6351
|
-
if (!buckets.has(bucketKey)) {
|
|
6352
|
-
buckets.set(bucketKey, { source, dimension, weight, findings: [] });
|
|
6353
|
-
}
|
|
6354
|
-
buckets.get(bucketKey)?.findings.push({ ruleId, severity, message, ...location ? { location } : {} });
|
|
6355
|
-
}
|
|
6356
|
-
}
|
|
6357
|
-
return Array.from(buckets.values()).map(({ source, dimension, weight, findings }) => ({
|
|
6358
|
-
source,
|
|
6359
|
-
dimension,
|
|
6360
|
-
weight,
|
|
6361
|
-
findings: dedupeFindings(findings)
|
|
6362
|
-
}));
|
|
6363
|
-
}
|
|
6364
|
-
|
|
6365
|
-
// ../witan/src/scorecard-adapter.ts
|
|
6366
|
-
import { readFileSync as readFileSync4 } from "fs";
|
|
6367
|
-
var CHECK_RULES = {
|
|
6368
|
-
// B2 — PR outcome traceability
|
|
6369
|
-
"Branch-Protection": { dimension: "B2", weight: 0.8 },
|
|
6370
|
-
"Code-Review": { dimension: "B2", weight: 0.7 },
|
|
6371
|
-
// B3 — CI and QA discipline
|
|
6372
|
-
"Dangerous-Workflow": { dimension: "B3", weight: 0.9 },
|
|
6373
|
-
"Token-Permissions": { dimension: "B3", weight: 0.8 },
|
|
6374
|
-
"CI-Tests": { dimension: "B3", weight: 0.7 },
|
|
6375
|
-
Maintained: { dimension: "B3", weight: 0.3 },
|
|
6376
|
-
// B4 — audit trail / release integrity
|
|
6377
|
-
"Signed-Releases": { dimension: "B4", weight: 0.7 },
|
|
6378
|
-
Packaging: { dimension: "B4", weight: 0.4 },
|
|
6379
|
-
"Security-Policy": { dimension: "B4", weight: 0.4 },
|
|
6380
|
-
// A4 — dependency hygiene
|
|
6381
|
-
Vulnerabilities: { dimension: "A4", weight: 0.9 },
|
|
6382
|
-
"Pinned-Dependencies": { dimension: "A4", weight: 0.8 },
|
|
6383
|
-
"Dependency-Update-Tool": { dimension: "A4", weight: 0.6 },
|
|
6384
|
-
// A2 — data-layer / static analysis
|
|
6385
|
-
SAST: { dimension: "A2", weight: 0.7 },
|
|
6386
|
-
"Binary-Artifacts": { dimension: "A2", weight: 0.6 },
|
|
6387
|
-
// A1 — test integrity
|
|
6388
|
-
Fuzzing: { dimension: "A1", weight: 0.3 }
|
|
6389
|
-
};
|
|
6390
|
-
function mapScoreToSeverity(score) {
|
|
6391
|
-
if (score == null || Number.isNaN(score)) return null;
|
|
6392
|
-
if (score < 0) return null;
|
|
6393
|
-
if (score >= 10) return null;
|
|
6394
|
-
if (score <= 3) return "critical";
|
|
6395
|
-
if (score <= 6) return "warning";
|
|
6396
|
-
return "info";
|
|
6397
|
-
}
|
|
6398
|
-
function dedupeFindings2(findings) {
|
|
6399
|
-
const seen = /* @__PURE__ */ new Set();
|
|
6400
|
-
return findings.filter((f) => {
|
|
6401
|
-
const key = `${f.ruleId}|${f.severity}|${f.location ?? ""}`;
|
|
6402
|
-
if (seen.has(key)) return false;
|
|
6403
|
-
seen.add(key);
|
|
6404
|
-
return true;
|
|
6405
|
-
});
|
|
6406
|
-
}
|
|
6407
|
-
function parseScorecardJson(raw) {
|
|
6408
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return [];
|
|
6409
|
-
const doc = raw;
|
|
6410
|
-
if (!Array.isArray(doc.checks)) return [];
|
|
6411
|
-
const buckets = /* @__PURE__ */ new Map();
|
|
6412
|
-
for (const check of doc.checks) {
|
|
6413
|
-
const name = check.name;
|
|
6414
|
-
if (!name) continue;
|
|
6415
|
-
const rule = CHECK_RULES[name];
|
|
6416
|
-
if (!rule) continue;
|
|
6417
|
-
const severity = mapScoreToSeverity(check.score);
|
|
6418
|
-
if (!severity) continue;
|
|
6419
|
-
const scoreText = typeof check.score === "number" ? `${check.score}/10` : "n/a";
|
|
6420
|
-
const message = `${name} (Scorecard ${scoreText}): ${check.reason ?? "weakness detected"}`.slice(0, 500);
|
|
6421
|
-
const location = check.documentation?.url;
|
|
6422
|
-
const bucket = buckets.get(rule.dimension) ?? { weight: 0, findings: [] };
|
|
6423
|
-
bucket.weight = Math.max(bucket.weight, rule.weight);
|
|
6424
|
-
bucket.findings.push({
|
|
6425
|
-
ruleId: `scorecard:${name}`,
|
|
6426
|
-
severity,
|
|
6427
|
-
message,
|
|
6428
|
-
...location ? { location } : {}
|
|
6429
|
-
});
|
|
6430
|
-
buckets.set(rule.dimension, bucket);
|
|
6431
|
-
}
|
|
6432
|
-
return Array.from(buckets.entries()).map(([dimension, { weight, findings }]) => ({
|
|
6433
|
-
source: "scorecard",
|
|
6434
|
-
dimension,
|
|
6435
|
-
weight,
|
|
6436
|
-
findings: dedupeFindings2(findings)
|
|
6437
|
-
}));
|
|
6438
|
-
}
|
|
6439
|
-
|
|
6440
|
-
// ../witan/src/ingest.ts
|
|
6441
|
-
function looksLikeSarif(raw) {
|
|
6442
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
|
|
6443
|
-
return Array.isArray(raw.runs);
|
|
6444
|
-
}
|
|
6445
|
-
function looksLikeScorecard(raw) {
|
|
6446
|
-
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
|
|
6447
|
-
return Array.isArray(raw.checks);
|
|
6448
|
-
}
|
|
6449
|
-
function countRawEntries(raw) {
|
|
6450
|
-
const obj = raw;
|
|
6451
|
-
if (Array.isArray(obj.runs)) {
|
|
6452
|
-
return obj.runs.reduce((sum, run) => {
|
|
6453
|
-
const results = run.results;
|
|
6454
|
-
return sum + (Array.isArray(results) ? results.length : 0);
|
|
6455
|
-
}, 0);
|
|
6456
|
-
}
|
|
6457
|
-
if (Array.isArray(obj.checks)) return obj.checks.length;
|
|
6458
|
-
if (Array.isArray(obj.signals)) {
|
|
6459
|
-
return obj.signals.reduce((sum, signal) => {
|
|
6460
|
-
const findings = signal.findings;
|
|
6461
|
-
return sum + (Array.isArray(findings) ? findings.length : 0);
|
|
6462
|
-
}, 0);
|
|
6463
|
-
}
|
|
6464
|
-
return 0;
|
|
6465
|
-
}
|
|
6466
|
-
function rawToolName(raw) {
|
|
6467
|
-
const obj = raw;
|
|
6468
|
-
if (Array.isArray(obj.runs)) {
|
|
6469
|
-
const firstRun = obj.runs[0];
|
|
6470
|
-
return firstRun?.tool?.driver?.name ?? "unknown";
|
|
6471
|
-
}
|
|
6472
|
-
if (typeof obj.tool === "string" && obj.tool.length > 0) return obj.tool;
|
|
6473
|
-
return "scorecard";
|
|
6474
|
-
}
|
|
6475
|
-
function parseIngestFile(filePath) {
|
|
6476
|
-
let raw;
|
|
6477
|
-
try {
|
|
6478
|
-
raw = JSON.parse(stripBom(readFileSync5(filePath, "utf8")));
|
|
6479
|
-
} catch (error) {
|
|
6480
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
6481
|
-
throw new Error(`Cejel: could not parse ingest file as JSON: ${filePath} (${message})`);
|
|
6482
|
-
}
|
|
6483
|
-
let signals;
|
|
6484
|
-
if (looksLikeSarif(raw)) signals = parseSarifJson(raw);
|
|
6485
|
-
else if (looksLikeScorecard(raw)) signals = parseScorecardJson(raw);
|
|
6486
|
-
else if (isGenericSignalDocument(raw)) signals = parseGenericJson(raw);
|
|
6487
|
-
if (!signals) {
|
|
6488
|
-
throw new Error(
|
|
6489
|
-
`Cejel: unrecognized ingest file format: ${filePath} \u2014 expected SARIF (a "runs" array), OpenSSF Scorecard JSON (a "checks" array), or the generic Cejel external-signal shape (a "tool" string + "signals" array). See the cejel README "Aggregate your scanners".`
|
|
6490
|
-
);
|
|
6491
|
-
}
|
|
6492
|
-
const rawCount = countRawEntries(raw);
|
|
6493
|
-
const mappedCount = signals.reduce((sum, signal) => sum + signal.findings.length, 0);
|
|
6494
|
-
if (rawCount > 0 && mappedCount === 0) {
|
|
6495
|
-
process.stderr.write(
|
|
6496
|
-
`Cejel: ${rawCount} findings from ${rawToolName(raw)} (${filePath}), 0 mapped to trust criteria
|
|
6497
|
-
`
|
|
6498
|
-
);
|
|
6499
|
-
}
|
|
6500
|
-
return signals.map((signal) => ({
|
|
6501
|
-
...signal,
|
|
6502
|
-
findings: signal.findings.map(clampFinding)
|
|
6503
|
-
}));
|
|
6504
|
-
}
|
|
6505
|
-
function expandIngestPattern(pattern) {
|
|
6506
|
-
if (!pattern.includes("*")) return [pattern];
|
|
6507
|
-
const lastSlash = pattern.lastIndexOf("/");
|
|
6508
|
-
const dir = lastSlash === -1 ? "." : pattern.slice(0, lastSlash);
|
|
6509
|
-
const filePattern = lastSlash === -1 ? pattern : pattern.slice(lastSlash + 1);
|
|
6510
|
-
const regexSource = filePattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
6511
|
-
const regex = new RegExp(`^${regexSource}$`);
|
|
6512
|
-
let entries;
|
|
6513
|
-
try {
|
|
6514
|
-
entries = readdirSync2(dir);
|
|
6515
|
-
} catch {
|
|
6516
|
-
return [];
|
|
6517
|
-
}
|
|
6518
|
-
return entries.filter((name) => regex.test(name)).sort().map((name) => join2(dir, name));
|
|
6519
|
-
}
|
|
6520
|
-
function discoverIngestInputs(repoPath) {
|
|
6521
|
-
const inputsDir = join2(repoPath, ".cejel", "inputs");
|
|
6522
|
-
let entries;
|
|
6523
|
-
try {
|
|
6524
|
-
entries = readdirSync2(inputsDir);
|
|
6525
|
-
} catch {
|
|
6526
|
-
return [];
|
|
6527
|
-
}
|
|
6528
|
-
return entries.filter((name) => /\.(sarif|json)$/i.test(name)).sort().map((name) => join2(inputsDir, name));
|
|
6529
|
-
}
|
|
6530
|
-
|
|
6531
|
-
// ../witan/src/repo-signals.ts
|
|
6532
|
-
import { execFileSync } from "child_process";
|
|
6533
|
-
import { createHash } from "crypto";
|
|
6534
|
-
import { readFileSync as readFileSync6, readdirSync as readdirSync3, realpathSync, statSync as statSync2 } from "fs";
|
|
6535
|
-
import { basename, join as join3, relative, resolve, sep } from "path";
|
|
4830
|
+
// src/witan/repo-signals.ts
|
|
6536
4831
|
function buildWitanInputFromRepo(options) {
|
|
6537
4832
|
assertRepoPathExists(options.repoPath);
|
|
6538
4833
|
const generatedAt = options.generatedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -6600,6 +4895,7 @@ var BUNDLED_BINARY_EXTENSION_PATTERN = /\.(vsix|zip|tgz|whl|exe|dmg|pkg|msi|jar|
|
|
|
6600
4895
|
var DOCS_OR_MEDIA_EXTENSION_PATTERN = /\.(md|mdx|rst|png|jpe?g|gif|svg|webp|ico|pdf)$/i;
|
|
6601
4896
|
var KNOWN_NON_SOURCE_EXTENSION_PATTERN = /\.(json|jsonc|json5|ya?ml|toml|txt|lock|xml|csv|tsv|ini|cfg|conf|properties|env|sum|mod|graphql|gql|proto|editorconfig|gitignore|gitattributes|npmrc|nvmrc|dockerignore|log|txt\.license)$/i;
|
|
6602
4897
|
var INGEST_POINTER = "To assess a closed/bundled tool, ingest its scanner output via --ingest <sarif|scorecard>.";
|
|
4898
|
+
var SOURCE_DOMINANCE_RATIO_THRESHOLD = 0.2;
|
|
6603
4899
|
function classifyRepoArchetype(repoFiles) {
|
|
6604
4900
|
const totalFileCount = repoFiles.length;
|
|
6605
4901
|
const sourceFileCount = repoFiles.filter((file) => SOURCE_EXTENSION_PATTERN.test(file)).length;
|
|
@@ -6611,57 +4907,83 @@ function classifyRepoArchetype(repoFiles) {
|
|
|
6611
4907
|
insufficientSourceReason: "Repository has no tracked files \u2014 there is nothing to certify."
|
|
6612
4908
|
};
|
|
6613
4909
|
}
|
|
6614
|
-
|
|
4910
|
+
const unrecognisedSourceFiles = collectUnrecognisedSourceFiles(repoFiles);
|
|
4911
|
+
if (sourceFileCount === 0) {
|
|
4912
|
+
const binaryFiles = repoFiles.filter((file) => BUNDLED_BINARY_EXTENSION_PATTERN.test(file));
|
|
4913
|
+
if (binaryFiles.length > 0) {
|
|
4914
|
+
const sample = binaryFiles[0];
|
|
4915
|
+
return {
|
|
4916
|
+
archetype: "binary_only",
|
|
4917
|
+
sourceFileCount,
|
|
4918
|
+
totalFileCount,
|
|
4919
|
+
insufficientSourceReason: `${sourceFileCount} source file(s) found among ${totalFileCount} tracked file(s); repo appears to be a binary/bundled-distribution tree (e.g. ${sample ? basename(sample) : "a packaged artifact"}) \u2014 cejel rates source, not binaries. ${INGEST_POINTER}`
|
|
4920
|
+
};
|
|
4921
|
+
}
|
|
4922
|
+
const docsFiles = repoFiles.filter((file) => DOCS_OR_MEDIA_EXTENSION_PATTERN.test(file));
|
|
4923
|
+
if (docsFiles.length > 0 && docsFiles.length === totalFileCount) {
|
|
4924
|
+
return {
|
|
4925
|
+
archetype: "docs_only",
|
|
4926
|
+
sourceFileCount,
|
|
4927
|
+
totalFileCount,
|
|
4928
|
+
insufficientSourceReason: `${sourceFileCount} source file(s) found among ${totalFileCount} tracked file(s); repo appears to be a docs/distribution tree (README/markdown/media), not a source tree \u2014 cejel rates source, not docs. ${INGEST_POINTER}`
|
|
4929
|
+
};
|
|
4930
|
+
}
|
|
4931
|
+
if (unrecognisedSourceFiles.length > 0) {
|
|
4932
|
+
return unrecognisedEcosystemResult(sourceFileCount, totalFileCount, unrecognisedSourceFiles);
|
|
4933
|
+
}
|
|
4934
|
+
return { archetype: "source", sourceFileCount, totalFileCount };
|
|
4935
|
+
}
|
|
4936
|
+
if (unrecognisedSourceFiles.length === 0) {
|
|
6615
4937
|
return {
|
|
6616
4938
|
archetype: isLikelyMonorepo(repoFiles) ? "monorepo" : "source",
|
|
6617
4939
|
sourceFileCount,
|
|
6618
4940
|
totalFileCount
|
|
6619
4941
|
};
|
|
6620
4942
|
}
|
|
6621
|
-
const
|
|
6622
|
-
if (
|
|
6623
|
-
const sample = binaryFiles[0];
|
|
4943
|
+
const dominanceRatio = sourceFileCount / (sourceFileCount + unrecognisedSourceFiles.length);
|
|
4944
|
+
if (dominanceRatio >= SOURCE_DOMINANCE_RATIO_THRESHOLD) {
|
|
6624
4945
|
return {
|
|
6625
|
-
archetype: "
|
|
6626
|
-
sourceFileCount,
|
|
6627
|
-
totalFileCount,
|
|
6628
|
-
insufficientSourceReason: `${sourceFileCount} source file(s) found among ${totalFileCount} tracked file(s); repo appears to be a binary/bundled-distribution tree (e.g. ${sample ? basename(sample) : "a packaged artifact"}) \u2014 cejel rates source, not binaries. ${INGEST_POINTER}`
|
|
6629
|
-
};
|
|
6630
|
-
}
|
|
6631
|
-
const docsFiles = repoFiles.filter((file) => DOCS_OR_MEDIA_EXTENSION_PATTERN.test(file));
|
|
6632
|
-
if (docsFiles.length > 0 && docsFiles.length === totalFileCount) {
|
|
6633
|
-
return {
|
|
6634
|
-
archetype: "docs_only",
|
|
6635
|
-
sourceFileCount,
|
|
6636
|
-
totalFileCount,
|
|
6637
|
-
insufficientSourceReason: `${sourceFileCount} source file(s) found among ${totalFileCount} tracked file(s); repo appears to be a docs/distribution tree (README/markdown/media), not a source tree \u2014 cejel rates source, not docs. ${INGEST_POINTER}`
|
|
6638
|
-
};
|
|
6639
|
-
}
|
|
6640
|
-
const unrecognisedExtensions = collectUnrecognisedSourceExtensions(repoFiles);
|
|
6641
|
-
if (unrecognisedExtensions.length > 0) {
|
|
6642
|
-
const sample = unrecognisedExtensions.slice(0, 6).join(", ");
|
|
6643
|
-
return {
|
|
6644
|
-
archetype: "unrecognised_ecosystem",
|
|
4946
|
+
archetype: isLikelyMonorepo(repoFiles) ? "monorepo" : "source",
|
|
6645
4947
|
sourceFileCount,
|
|
6646
|
-
totalFileCount
|
|
6647
|
-
insufficientSourceReason: `Cejel does not yet read this repository's source language(s) (${sample}) \u2014 0 of ${totalFileCount} tracked file(s) matched a recognised source extension. Cejel abstains from a verdict rather than score a language it cannot parse; the Criterion Profile and Measured coverage below show exactly which dimensions were and were not measured. ${INGEST_POINTER}`
|
|
4948
|
+
totalFileCount
|
|
6648
4949
|
};
|
|
6649
4950
|
}
|
|
6650
|
-
return
|
|
4951
|
+
return unrecognisedEcosystemResult(sourceFileCount, totalFileCount, unrecognisedSourceFiles);
|
|
6651
4952
|
}
|
|
6652
|
-
function
|
|
6653
|
-
|
|
6654
|
-
for (const file of repoFiles) {
|
|
4953
|
+
function collectUnrecognisedSourceFiles(repoFiles) {
|
|
4954
|
+
return repoFiles.filter((file) => {
|
|
6655
4955
|
const base = basename(file);
|
|
6656
|
-
|
|
4956
|
+
if (!/\.([a-zA-Z0-9_]+)$/.test(base)) return false;
|
|
4957
|
+
if (KNOWN_NON_SOURCE_EXTENSION_PATTERN.test(base)) return false;
|
|
4958
|
+
if (DOCS_OR_MEDIA_EXTENSION_PATTERN.test(base)) return false;
|
|
4959
|
+
if (BUNDLED_BINARY_EXTENSION_PATTERN.test(base)) return false;
|
|
4960
|
+
if (SOURCE_EXTENSION_PATTERN.test(base)) return false;
|
|
4961
|
+
return true;
|
|
4962
|
+
});
|
|
4963
|
+
}
|
|
4964
|
+
function extensionsByFileCountDescending(files) {
|
|
4965
|
+
const counts = /* @__PURE__ */ new Map();
|
|
4966
|
+
for (const file of files) {
|
|
4967
|
+
const match = /\.([a-zA-Z0-9_]+)$/.exec(basename(file));
|
|
6657
4968
|
const ext = match?.[1];
|
|
6658
4969
|
if (!ext) continue;
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
if (BUNDLED_BINARY_EXTENSION_PATTERN.test(base)) continue;
|
|
6662
|
-
found.add(`.${ext.toLowerCase()}`);
|
|
4970
|
+
const key = `.${ext.toLowerCase()}`;
|
|
4971
|
+
counts.set(key, (counts.get(key) ?? 0) + 1);
|
|
6663
4972
|
}
|
|
6664
|
-
return [...
|
|
4973
|
+
return [...counts.entries()].sort(([extA, countA], [extB, countB]) => countB - countA || extA.localeCompare(extB)).map(([ext]) => ext);
|
|
4974
|
+
}
|
|
4975
|
+
function unrecognisedEcosystemResult(sourceFileCount, totalFileCount, unrecognisedSourceFiles) {
|
|
4976
|
+
const sample = extensionsByFileCountDescending(unrecognisedSourceFiles).slice(0, 6).join(", ");
|
|
4977
|
+
const candidateCount = sourceFileCount + unrecognisedSourceFiles.length;
|
|
4978
|
+
const dominancePct = candidateCount > 0 ? (sourceFileCount / candidateCount * 100).toFixed(1) : "0.0";
|
|
4979
|
+
const thresholdPct = (SOURCE_DOMINANCE_RATIO_THRESHOLD * 100).toFixed(0);
|
|
4980
|
+
const measuredClause = sourceFileCount > 0 ? `${sourceFileCount} of ${candidateCount} source-shaped file(s) (${dominancePct}%) are in a language Cejel reads \u2014 below the ${thresholdPct}% dominance threshold a score would need to be meaningful (${totalFileCount} tracked files in total; manifests, lockfiles, docs, media and bundled binaries are excluded from both sides of the ratio)` : `0 of ${totalFileCount} tracked file(s) matched a recognised source extension`;
|
|
4981
|
+
return {
|
|
4982
|
+
archetype: "unrecognised_ecosystem",
|
|
4983
|
+
sourceFileCount,
|
|
4984
|
+
totalFileCount,
|
|
4985
|
+
insufficientSourceReason: `Cejel does not yet read this repository's dominant source language(s) (${sample}) \u2014 ${measuredClause}. Cejel abstains from a verdict rather than score a repository whose recognised source is incidental rather than dominant; the Criterion Profile and Measured coverage below show exactly which dimensions were and were not measured. ${INGEST_POINTER}`
|
|
4986
|
+
};
|
|
6665
4987
|
}
|
|
6666
4988
|
function isLikelyMonorepo(repoFiles) {
|
|
6667
4989
|
const packageRoots = new Set(
|
|
@@ -6672,7 +4994,7 @@ function isLikelyMonorepo(repoFiles) {
|
|
|
6672
4994
|
function assertRepoPathExists(repoPath) {
|
|
6673
4995
|
let stats;
|
|
6674
4996
|
try {
|
|
6675
|
-
stats =
|
|
4997
|
+
stats = statSync(repoPath);
|
|
6676
4998
|
} catch {
|
|
6677
4999
|
throw new Error(`Cejel: path not found: ${repoPath}`);
|
|
6678
5000
|
}
|
|
@@ -6740,7 +5062,7 @@ function collectA1TestIntegrityEvidence(repoPath, repoFiles) {
|
|
|
6740
5062
|
const runnerFiles = repoFiles.filter(isTestRunnerConfig).slice(0, 6);
|
|
6741
5063
|
const coverageFiles = repoFiles.filter(isCoverageConfig).slice(0, 4);
|
|
6742
5064
|
const packageJson = findRootPackageJson(repoFiles);
|
|
6743
|
-
const packageScripts = packageJson ? readPackageScripts(
|
|
5065
|
+
const packageScripts = packageJson ? readPackageScripts(join(repoPath, packageJson)) : /* @__PURE__ */ new Map();
|
|
6744
5066
|
const coveragePercent = readCoveragePercent(repoPath, coverageFiles);
|
|
6745
5067
|
const ciWorkflows = repoFiles.filter(isCiWorkflow);
|
|
6746
5068
|
const ciTestWorkflow = ciWorkflows.find(
|
|
@@ -7106,7 +5428,8 @@ function collectCryptoHygieneEvidence(repoPath, implFiles) {
|
|
|
7106
5428
|
const findings = [];
|
|
7107
5429
|
let hasSurface = false;
|
|
7108
5430
|
let insecureFound = false;
|
|
7109
|
-
const
|
|
5431
|
+
const productionImplFiles = implFiles.filter(isProductionSourcePath);
|
|
5432
|
+
const timingSafeFile = productionImplFiles.find(
|
|
7110
5433
|
(file) => fileContains(repoPath, file, TIMING_SAFE_COMPARE_PATTERN)
|
|
7111
5434
|
);
|
|
7112
5435
|
if (timingSafeFile) {
|
|
@@ -7120,7 +5443,7 @@ function collectCryptoHygieneEvidence(repoPath, implFiles) {
|
|
|
7120
5443
|
)
|
|
7121
5444
|
);
|
|
7122
5445
|
}
|
|
7123
|
-
const canonicalSignFile =
|
|
5446
|
+
const canonicalSignFile = productionImplFiles.find(
|
|
7124
5447
|
(file) => fileContains(repoPath, file, CANONICAL_SERIALIZE_PATTERN) && fileContains(repoPath, file, SIGN_OR_HMAC_CALL_PATTERN)
|
|
7125
5448
|
);
|
|
7126
5449
|
if (canonicalSignFile) {
|
|
@@ -7134,20 +5457,31 @@ function collectCryptoHygieneEvidence(repoPath, implFiles) {
|
|
|
7134
5457
|
)
|
|
7135
5458
|
);
|
|
7136
5459
|
}
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
)
|
|
5460
|
+
let insecureCompareFile = null;
|
|
5461
|
+
let insecureCompareLine = null;
|
|
5462
|
+
for (const file of implFiles) {
|
|
5463
|
+
const line = findInsecureSecretCompareLine(repoPath, file);
|
|
5464
|
+
if (line != null) {
|
|
5465
|
+
insecureCompareFile = file;
|
|
5466
|
+
insecureCompareLine = line;
|
|
5467
|
+
break;
|
|
5468
|
+
}
|
|
5469
|
+
}
|
|
7140
5470
|
if (insecureCompareFile) {
|
|
7141
|
-
|
|
7142
|
-
|
|
5471
|
+
const isTestPath = isTestOrFixturePath(insecureCompareFile);
|
|
5472
|
+
if (!isTestPath) {
|
|
5473
|
+
hasSurface = true;
|
|
5474
|
+
insecureFound = true;
|
|
5475
|
+
}
|
|
7143
5476
|
findings.push({
|
|
7144
|
-
severity: "warning",
|
|
7145
|
-
summary: "A secret/HMAC/signature value appears compared with a plain equality operator instead of a constant-time comparison \u2014 potential timing side-channel.",
|
|
7146
|
-
evidence:
|
|
5477
|
+
severity: isTestPath ? "info" : "warning",
|
|
5478
|
+
summary: isTestPath ? `A secret/HMAC/signature comparison via plain equality appears in a test/fixture file (${insecureCompareFile}) \u2014 likely a test assertion, not a production timing leak; verify.` : "A secret/HMAC/signature value appears compared with a plain equality operator instead of a constant-time comparison \u2014 potential timing side-channel.",
|
|
5479
|
+
evidence: evidenceForRelativeAtLine(
|
|
7147
5480
|
repoPath,
|
|
7148
5481
|
insecureCompareFile,
|
|
7149
5482
|
"artifact",
|
|
7150
|
-
"Non-constant-time secret comparison"
|
|
5483
|
+
"Non-constant-time secret comparison",
|
|
5484
|
+
insecureCompareLine
|
|
7151
5485
|
)
|
|
7152
5486
|
});
|
|
7153
5487
|
}
|
|
@@ -7155,16 +5489,25 @@ function collectCryptoHygieneEvidence(repoPath, implFiles) {
|
|
|
7155
5489
|
(file) => fileContains(repoPath, file, UNSORTED_JSON_SIGN_PATTERN) && !fileContains(repoPath, file, CANONICAL_SERIALIZE_PATTERN)
|
|
7156
5490
|
);
|
|
7157
5491
|
if (unsortedSignFile) {
|
|
7158
|
-
|
|
7159
|
-
|
|
5492
|
+
const isTestPath = isTestOrFixturePath(unsortedSignFile);
|
|
5493
|
+
if (!isTestPath) {
|
|
5494
|
+
hasSurface = true;
|
|
5495
|
+
insecureFound = true;
|
|
5496
|
+
}
|
|
5497
|
+
const unsortedSignLine = findFirstMatchingLine(
|
|
5498
|
+
repoPath,
|
|
5499
|
+
unsortedSignFile,
|
|
5500
|
+
UNSORTED_JSON_SIGN_PATTERN
|
|
5501
|
+
);
|
|
7160
5502
|
findings.push({
|
|
7161
|
-
severity: "warning",
|
|
7162
|
-
summary: "A signature/HMAC appears computed directly over JSON.stringify output with no canonical key ordering in the same file \u2014 signatures may not verify across equivalent payloads.",
|
|
7163
|
-
evidence:
|
|
5503
|
+
severity: isTestPath ? "info" : "warning",
|
|
5504
|
+
summary: isTestPath ? `Signing over unsorted JSON serialization appears in a test/fixture file (${unsortedSignFile}) \u2014 likely a test assertion, not a production signing gap; verify.` : "A signature/HMAC appears computed directly over JSON.stringify output with no canonical key ordering in the same file \u2014 signatures may not verify across equivalent payloads.",
|
|
5505
|
+
evidence: evidenceForRelativeAtLine(
|
|
7164
5506
|
repoPath,
|
|
7165
5507
|
unsortedSignFile,
|
|
7166
5508
|
"artifact",
|
|
7167
|
-
"Signing over unsorted JSON serialization"
|
|
5509
|
+
"Signing over unsorted JSON serialization",
|
|
5510
|
+
unsortedSignLine
|
|
7168
5511
|
)
|
|
7169
5512
|
});
|
|
7170
5513
|
}
|
|
@@ -7180,7 +5523,7 @@ function collectA3ProdReadinessEvidence(repoPath, repoFiles) {
|
|
|
7180
5523
|
const evidence = [];
|
|
7181
5524
|
const findings = [];
|
|
7182
5525
|
const packageJson = findRootPackageJson(repoFiles);
|
|
7183
|
-
const scripts = packageJson ? readPackageScripts(
|
|
5526
|
+
const scripts = packageJson ? readPackageScripts(join(repoPath, packageJson)) : /* @__PURE__ */ new Map();
|
|
7184
5527
|
const workflows = repoFiles.filter(isCiWorkflow);
|
|
7185
5528
|
const workflow = workflows[0];
|
|
7186
5529
|
const deployConfigs = repoFiles.filter(isDeployConfig);
|
|
@@ -7614,7 +5957,7 @@ function collectB2PrTraceEvidence(repoPath, repoFiles) {
|
|
|
7614
5957
|
function collectB3CiDisciplineEvidence(repoPath, repoFiles, mono) {
|
|
7615
5958
|
const evidence = [];
|
|
7616
5959
|
const packageJson = findRootPackageJson(repoFiles);
|
|
7617
|
-
const scripts = packageJson ? readPackageScripts(
|
|
5960
|
+
const scripts = packageJson ? readPackageScripts(join(repoPath, packageJson)) : /* @__PURE__ */ new Map();
|
|
7618
5961
|
const workflows = repoFiles.filter(isCiWorkflow);
|
|
7619
5962
|
const workflow = workflows[0];
|
|
7620
5963
|
const rootWorkflows = mono ? mono.sharedFiles.filter(isCiWorkflow) : [];
|
|
@@ -7880,11 +6223,20 @@ function collectB6PrivilegedOpsGatingEvidence(repoPath, repoFiles) {
|
|
|
7880
6223
|
var CPP_TEST_FRAMEWORK_PATTERN = /<gtest\/gtest\.h>|<catch2\/|<doctest\/|<boost\/test\/|"gtest\/gtest\.h"|"catch2\//;
|
|
7881
6224
|
var CPP_TEST_MACRO_PATTERN = /\bTEST\s*\(|\bTEST_F\s*\(|\bTEST_CASE\s*\(|\bSECTION\s*\(|\bCATCH_|BOOST_AUTO_TEST_CASE\b|BOOST_FIXTURE_TEST_CASE\b/;
|
|
7882
6225
|
var CPP_CONTENT_SCAN_LIMIT = 150;
|
|
7883
|
-
var
|
|
7884
|
-
var
|
|
6226
|
+
var NON_PRODUCTION_DIR_PATTERN = /(^|\/)(__tests__|__mocks__|__fixtures__|tests?|fixtures?|testdata|e2e|cypress|examples?|samples?|demos?)(\/|$)/i;
|
|
6227
|
+
var NON_PRODUCTION_FILE_SUFFIX_PATTERN = /\.(test|spec|stories)\.[^/]+$/i;
|
|
7885
6228
|
function isTestOrFixturePath(path) {
|
|
7886
|
-
return
|
|
6229
|
+
return NON_PRODUCTION_DIR_PATTERN.test(path) || NON_PRODUCTION_FILE_SUFFIX_PATTERN.test(path);
|
|
6230
|
+
}
|
|
6231
|
+
function isProductionSourcePath(path) {
|
|
6232
|
+
return !isTestOrFixturePath(path);
|
|
7887
6233
|
}
|
|
6234
|
+
function isTestFile(file) {
|
|
6235
|
+
return /(^|\/)(__tests__|test|tests|spec)\/.*\.(?:[cm]?[jt]sx?|py|go|rs|java|rb|cpp|cc|cxx)$/.test(
|
|
6236
|
+
file
|
|
6237
|
+
) || /\.(test|spec)\.[cm]?[jt]sx?$/.test(file) || /(^|\/)test_.*\.py$/.test(file) || /_test\.go$/.test(file) || /(^|\/)test_.*\.(cpp|cc|cxx)$/.test(file) || /_(test|tests)\.(cpp|cc|cxx)$/.test(file) || /Tests?\.(java|kt)$/.test(file) || /(_test|_spec)\.(rs|rb|php|swift|kt)$/.test(file);
|
|
6238
|
+
}
|
|
6239
|
+
var NAME_SHAPED_TEST_FILE_PATTERN = /\.(test|spec)\.[cm]?[jt]sx?$|(^|\/)__tests__\/|(^|\/)test_[^/]*\.py$|(^|\/)tests?\.py$|_test\.go$|(^|\/)test_[^/]*\.(cpp|cc|cxx)$|_(test|tests)\.(cpp|cc|cxx)$|Tests?\.(java|kt)$|(_test|_spec)\.(rs|rb|php|swift|kt)$/;
|
|
7888
6240
|
var TEST_RUNNER_PATTERN = /\b(vitest|jest|mocha|ava|tap|pytest|go test|cargo test|rspec|phpunit|gradle test|mvn test)\b/i;
|
|
7889
6241
|
var CI_TEST_COMMAND_PATTERN = /\b(pytest|go\s+test|cargo\s+test|mvn\s+test|gradle\s+test|ctest|make\s+test|jest|vitest|mocha|rspec|phpunit|pnpm\s+test|npm\s+test|yarn\s+test|node\s+--test|node:test)\b/i;
|
|
7890
6242
|
var CI_LINT_COMMAND_PATTERN = /\b(eslint|pylint|flake8|black|ruff)\b/i;
|
|
@@ -7917,7 +6269,28 @@ var HEAVY_TEST_DEPENDENCY_NAME_PATTERN = /^(?:jest|mocha|ava|tape|jasmine|karma)
|
|
|
7917
6269
|
var TIMING_SAFE_COMPARE_PATTERN = /\btiming[-_]?safe[-_]?(?:equal|compare)\b|crypto\.timingSafeEqual\s*\(/i;
|
|
7918
6270
|
var CANONICAL_SERIALIZE_PATTERN = /\bcanonicalize\s*\(|\bcanonicalJson\b|\bstableStringify\s*\(|json-stable-stringify|safe-stable-stringify|\bsortKeys\s*\(/i;
|
|
7919
6271
|
var SIGN_OR_HMAC_CALL_PATTERN = /\bcreateHmac\s*\(|\bcreateSign\s*\(|\.sign\s*\(/;
|
|
7920
|
-
var
|
|
6272
|
+
var INSECURE_SECRET_COMPARE_LINE_PATTERN = /\b\w*(?:hmac|signature|\bmac|digest)\w*\s*(===|!==)\s*(?!['"`]|undefined\b|null\b)([\w.]+(?:\s*[-+]\s*\d+)?)/i;
|
|
6273
|
+
var NUMERIC_SHAPED_OPERAND_PATTERN = /^-?\d+$|\.(?:length|len|size|count)\b|(?:length|index|idx|offset|count|size|len)$/i;
|
|
6274
|
+
function lineHasInsecureSecretCompare(line) {
|
|
6275
|
+
const match = INSECURE_SECRET_COMPARE_LINE_PATTERN.exec(line);
|
|
6276
|
+
const operand = match?.[2];
|
|
6277
|
+
if (!operand) return false;
|
|
6278
|
+
return !NUMERIC_SHAPED_OPERAND_PATTERN.test(operand.trim());
|
|
6279
|
+
}
|
|
6280
|
+
function findInsecureSecretCompareLine(repoPath, file) {
|
|
6281
|
+
const fullPath = join(repoPath, file);
|
|
6282
|
+
if (!isRegularFile(fullPath)) return null;
|
|
6283
|
+
const lines = readFileSync(fullPath, "utf8").split("\n");
|
|
6284
|
+
const index = lines.findIndex((line) => lineHasInsecureSecretCompare(line));
|
|
6285
|
+
return index === -1 ? null : index + 1;
|
|
6286
|
+
}
|
|
6287
|
+
function findFirstMatchingLine(repoPath, file, pattern) {
|
|
6288
|
+
const fullPath = join(repoPath, file);
|
|
6289
|
+
if (!isRegularFile(fullPath)) return null;
|
|
6290
|
+
const lines = readFileSync(fullPath, "utf8").split("\n");
|
|
6291
|
+
const index = lines.findIndex((line) => pattern.test(line));
|
|
6292
|
+
return index === -1 ? null : index + 1;
|
|
6293
|
+
}
|
|
7921
6294
|
var UNSORTED_JSON_SIGN_PATTERN = /\.update\s*\(\s*JSON\.stringify\s*\(|\.sign\s*\([^)]*JSON\.stringify\s*\(/;
|
|
7922
6295
|
var KILL_SWITCH_NAME_FRAGMENT = "kill[_-]?switch|emergency[_-]?stop|circuit[_-]?breaker|safety[_-]?(?:toggle|gate|switch)|governance[_-]?(?:toggle|gate)";
|
|
7923
6296
|
var KILL_SWITCH_NAME_PATTERN = new RegExp(`\\b(?:${KILL_SWITCH_NAME_FRAGMENT})\\b`, "i");
|
|
@@ -8029,13 +6402,13 @@ function listGitTrackedFiles(repoPath) {
|
|
|
8029
6402
|
function visitRepoDir(repoPath, dirPath, files) {
|
|
8030
6403
|
let entries;
|
|
8031
6404
|
try {
|
|
8032
|
-
entries =
|
|
6405
|
+
entries = readdirSync(dirPath, { withFileTypes: true });
|
|
8033
6406
|
} catch {
|
|
8034
6407
|
return;
|
|
8035
6408
|
}
|
|
8036
6409
|
for (const entry of entries) {
|
|
8037
6410
|
if (shouldSkipDir(entry.name)) continue;
|
|
8038
|
-
const fullPath =
|
|
6411
|
+
const fullPath = join(dirPath, entry.name);
|
|
8039
6412
|
if (entry.isDirectory()) {
|
|
8040
6413
|
visitRepoDir(repoPath, fullPath, files);
|
|
8041
6414
|
continue;
|
|
@@ -8043,7 +6416,7 @@ function visitRepoDir(repoPath, dirPath, files) {
|
|
|
8043
6416
|
if (!entry.isFile()) continue;
|
|
8044
6417
|
let size;
|
|
8045
6418
|
try {
|
|
8046
|
-
size =
|
|
6419
|
+
size = statSync(fullPath).size;
|
|
8047
6420
|
} catch {
|
|
8048
6421
|
continue;
|
|
8049
6422
|
}
|
|
@@ -8068,20 +6441,15 @@ function shouldSkipDir(name) {
|
|
|
8068
6441
|
"target"
|
|
8069
6442
|
].includes(name);
|
|
8070
6443
|
}
|
|
8071
|
-
function isHardExcludedPath(path) {
|
|
8072
|
-
return HARD_EXCLUDED_PATH_PATTERN.test(path);
|
|
8073
|
-
}
|
|
8074
|
-
function isTestFile(file) {
|
|
8075
|
-
return /(^|\/)(__tests__|test|tests|spec)\/.*\.(?:[cm]?[jt]sx?|py|go|rs|java|rb|cpp|cc|cxx)$/.test(
|
|
8076
|
-
file
|
|
8077
|
-
) || /\.(test|spec)\.[cm]?[jt]sx?$/.test(file) || /(^|\/)test_.*\.py$/.test(file) || /_test\.go$/.test(file) || /(^|\/)test_.*\.(cpp|cc|cxx)$/.test(file) || /_(test|tests)\.(cpp|cc|cxx)$/.test(file) || /Tests?\.(java|kt)$/.test(file) || /(_test|_spec)\.(rs|rb|php|swift|kt)$/.test(file);
|
|
8078
|
-
}
|
|
6444
|
+
function isHardExcludedPath(path) {
|
|
6445
|
+
return HARD_EXCLUDED_PATH_PATTERN.test(path);
|
|
6446
|
+
}
|
|
8079
6447
|
function collectContentBasedCppTestFiles(repoPath, repoFiles) {
|
|
8080
6448
|
const candidates = repoFiles.filter((file) => /\.(cpp|cc|cxx)$/.test(file) && !isTestFile(file)).slice(0, CPP_CONTENT_SCAN_LIMIT);
|
|
8081
6449
|
return candidates.filter((file) => {
|
|
8082
|
-
const fullPath =
|
|
6450
|
+
const fullPath = join(repoPath, file);
|
|
8083
6451
|
if (!isRegularFile(fullPath)) return false;
|
|
8084
|
-
const contents =
|
|
6452
|
+
const contents = readFileSync(fullPath, "utf8");
|
|
8085
6453
|
return CPP_TEST_FRAMEWORK_PATTERN.test(contents) || CPP_TEST_MACRO_PATTERN.test(contents);
|
|
8086
6454
|
});
|
|
8087
6455
|
}
|
|
@@ -8095,14 +6463,13 @@ var JS_TEST_ASSERTION_PATTERN = /(expect\(|assert\.|should\.|toEqual\(|toBe\(|as
|
|
|
8095
6463
|
var CPP_TEST_ASSERTION_PATTERN = /\bEXPECT_|ASSERT_EQ\b|ASSERT_TRUE\b|ASSERT_FALSE\b|\bREQUIRE\s*\(|\bCHECK\s*\(|\bTEST\s*\(|\bTEST_F\s*\(|\bTEST_CASE\s*\(|\bSECTION\s*\(/;
|
|
8096
6464
|
var MULTI_ECOSYSTEM_TEST_ASSERTION_PATTERN = /\.assert[A-Z_]\w*\s*\(|\bassert[A-Z]\w*\s*\(|\bpytest\.raises\b|\bself\.fail\s*\(|\bt\.(?:Error|Errorf|Fatal|Fatalf|Fail|FailNow)\b|\brequire\.[A-Z]\w*\s*\(|\b(?:debug_)?assert(?:_eq|_ne)?!\s*\(|\bassert_\w+\b|\$this->assert\w+\s*\(/;
|
|
8097
6465
|
var SUITE_LEVEL_SKIP_PATTERN = /\b(?:describe|suite|context)\.skip\s*\(/;
|
|
8098
|
-
var NAME_SHAPED_TEST_FILE_PATTERN = /\.(test|spec)\.[cm]?[jt]sx?$|(^|\/)__tests__\/|(^|\/)test_[^/]*\.py$|(^|\/)tests?\.py$|_test\.go$|(^|\/)test_[^/]*\.(cpp|cc|cxx)$|_(test|tests)\.(cpp|cc|cxx)$|Tests?\.(java|kt)$|(_test|_spec)\.(rs|rb|php|swift|kt)$/;
|
|
8099
6466
|
function measureNonHollowTestShare(repoPath, files) {
|
|
8100
6467
|
let nonHollowCount = 0;
|
|
8101
6468
|
let ratedCount = 0;
|
|
8102
6469
|
for (const file of files) {
|
|
8103
|
-
const fullPath =
|
|
6470
|
+
const fullPath = join(repoPath, file);
|
|
8104
6471
|
if (!isRegularFile(fullPath)) continue;
|
|
8105
|
-
const contents =
|
|
6472
|
+
const contents = readFileSync(fullPath, "utf8");
|
|
8106
6473
|
const nonHollow = (JS_TEST_ASSERTION_PATTERN.test(contents) || CPP_TEST_ASSERTION_PATTERN.test(contents) || MULTI_ECOSYSTEM_TEST_ASSERTION_PATTERN.test(contents)) && !SUITE_LEVEL_SKIP_PATTERN.test(contents);
|
|
8107
6474
|
if (nonHollow) {
|
|
8108
6475
|
nonHollowCount += 1;
|
|
@@ -8121,17 +6488,17 @@ function countPatternMatches(repoPath, files, pattern) {
|
|
|
8121
6488
|
const matcher = new RegExp(pattern.source, flags);
|
|
8122
6489
|
let count = 0;
|
|
8123
6490
|
for (const file of files) {
|
|
8124
|
-
const fullPath =
|
|
6491
|
+
const fullPath = join(repoPath, file);
|
|
8125
6492
|
if (!isRegularFile(fullPath)) continue;
|
|
8126
|
-
count += [...
|
|
6493
|
+
count += [...readFileSync(fullPath, "utf8").matchAll(matcher)].length;
|
|
8127
6494
|
}
|
|
8128
6495
|
return count;
|
|
8129
6496
|
}
|
|
8130
6497
|
function readCoveragePercent(repoPath, files) {
|
|
8131
6498
|
for (const file of files) {
|
|
8132
|
-
const fullPath =
|
|
6499
|
+
const fullPath = join(repoPath, file);
|
|
8133
6500
|
if (!isRegularFile(fullPath)) continue;
|
|
8134
|
-
const contents =
|
|
6501
|
+
const contents = readFileSync(fullPath, "utf8");
|
|
8135
6502
|
const summaryPercent = parseCoverageSummaryPercent(contents);
|
|
8136
6503
|
if (summaryPercent !== null) return summaryPercent;
|
|
8137
6504
|
const thresholdPercent = parseCoverageThresholdPercent(contents);
|
|
@@ -8175,7 +6542,7 @@ function pickPrimaryDependencyManifest(repoPath, manifests) {
|
|
|
8175
6542
|
function readDependencySpecs(repoPath, manifests) {
|
|
8176
6543
|
const specs = [];
|
|
8177
6544
|
for (const manifest of manifests) {
|
|
8178
|
-
const fullPath =
|
|
6545
|
+
const fullPath = join(repoPath, manifest);
|
|
8179
6546
|
if (!isRegularFile(fullPath)) continue;
|
|
8180
6547
|
if (manifest.endsWith("package.json")) {
|
|
8181
6548
|
specs.push(...readPackageJsonDependencySpecs(fullPath));
|
|
@@ -8221,7 +6588,7 @@ function readDependencySpecs(repoPath, manifests) {
|
|
|
8221
6588
|
}
|
|
8222
6589
|
function readGoModDependencySpecs(path) {
|
|
8223
6590
|
const specs = [];
|
|
8224
|
-
const contents =
|
|
6591
|
+
const contents = readFileSync(path, "utf8");
|
|
8225
6592
|
const blockPattern = /require\s*\(([^)]+)\)/gs;
|
|
8226
6593
|
const singlePattern = /^require\s+(\S+)\s+(\S+)/gm;
|
|
8227
6594
|
for (const blockMatch of contents.matchAll(blockPattern)) {
|
|
@@ -8242,7 +6609,7 @@ function readGoModDependencySpecs(path) {
|
|
|
8242
6609
|
}
|
|
8243
6610
|
function readCargoTomlDependencySpecs(path) {
|
|
8244
6611
|
const specs = [];
|
|
8245
|
-
const contents =
|
|
6612
|
+
const contents = readFileSync(path, "utf8");
|
|
8246
6613
|
const depSectionPattern = /^\[(?:dependencies|dev-dependencies|build-dependencies)\]([\s\S]*?)(?=^\[|(?![\s\S]))/gm;
|
|
8247
6614
|
for (const sectionMatch of contents.matchAll(depSectionPattern)) {
|
|
8248
6615
|
const section = sectionMatch[1] ?? "";
|
|
@@ -8264,7 +6631,7 @@ function readCargoTomlDependencySpecs(path) {
|
|
|
8264
6631
|
}
|
|
8265
6632
|
function readPyprojectDependencySpecs(path) {
|
|
8266
6633
|
const specs = [];
|
|
8267
|
-
const contents =
|
|
6634
|
+
const contents = readFileSync(path, "utf8");
|
|
8268
6635
|
const poetrySectionPattern = /^\[tool\.poetry\.dependencies\]([\s\S]*?)(?=^\[|(?![\s\S]))/gm;
|
|
8269
6636
|
for (const sectionMatch of contents.matchAll(poetrySectionPattern)) {
|
|
8270
6637
|
const section = sectionMatch[1] ?? "";
|
|
@@ -8298,7 +6665,7 @@ function readPyprojectDependencySpecs(path) {
|
|
|
8298
6665
|
}
|
|
8299
6666
|
function readPipfileDependencySpecs(path) {
|
|
8300
6667
|
const specs = [];
|
|
8301
|
-
const contents =
|
|
6668
|
+
const contents = readFileSync(path, "utf8");
|
|
8302
6669
|
const sectionPattern = /^\[(?:packages|dev-packages)\]([\s\S]*?)(?=^\[|$(?![\s\S]))/gm;
|
|
8303
6670
|
for (const sectionMatch of contents.matchAll(sectionPattern)) {
|
|
8304
6671
|
for (const line of (sectionMatch[1] ?? "").split("\n")) {
|
|
@@ -8311,7 +6678,7 @@ function readPipfileDependencySpecs(path) {
|
|
|
8311
6678
|
return specs;
|
|
8312
6679
|
}
|
|
8313
6680
|
function readVcpkgJsonDependencySpecs(path) {
|
|
8314
|
-
const parsed = parseJsonObject(
|
|
6681
|
+
const parsed = parseJsonObject(readFileSync(path, "utf8"));
|
|
8315
6682
|
if (!parsed) return [];
|
|
8316
6683
|
const rawDeps = Array.isArray(parsed.dependencies) ? parsed.dependencies : [];
|
|
8317
6684
|
const specs = [];
|
|
@@ -8327,7 +6694,7 @@ function readVcpkgJsonDependencySpecs(path) {
|
|
|
8327
6694
|
}
|
|
8328
6695
|
function readConanfileTxtDependencySpecs(path) {
|
|
8329
6696
|
const specs = [];
|
|
8330
|
-
const contents =
|
|
6697
|
+
const contents = readFileSync(path, "utf8");
|
|
8331
6698
|
const requiresMatch = /^\[requires\]([\s\S]*?)(?=^\[|$(?![\s\S]))/m.exec(contents);
|
|
8332
6699
|
if (!requiresMatch) return specs;
|
|
8333
6700
|
for (const line of (requiresMatch[1] ?? "").split("\n")) {
|
|
@@ -8340,7 +6707,7 @@ function readConanfileTxtDependencySpecs(path) {
|
|
|
8340
6707
|
}
|
|
8341
6708
|
function readConanfilePyDependencySpecs(path) {
|
|
8342
6709
|
const specs = [];
|
|
8343
|
-
const contents =
|
|
6710
|
+
const contents = readFileSync(path, "utf8");
|
|
8344
6711
|
for (const match of contents.matchAll(/self\.requires\s*\(\s*["']([\w.\-]+)\/([\w.\-]+)["']/g)) {
|
|
8345
6712
|
specs.push({ name: match[1] ?? "", version: match[2] ?? "" });
|
|
8346
6713
|
}
|
|
@@ -8354,7 +6721,7 @@ function readConanfilePyDependencySpecs(path) {
|
|
|
8354
6721
|
}
|
|
8355
6722
|
function readCMakeDependencySpecs(path) {
|
|
8356
6723
|
const specs = [];
|
|
8357
|
-
const contents =
|
|
6724
|
+
const contents = readFileSync(path, "utf8");
|
|
8358
6725
|
for (const match of contents.matchAll(/find_package\s*\(\s*([\w]+)(?:\s+([\d.]+))?/gi)) {
|
|
8359
6726
|
const name = match[1];
|
|
8360
6727
|
if (!name) continue;
|
|
@@ -8369,7 +6736,7 @@ function readCMakeDependencySpecs(path) {
|
|
|
8369
6736
|
return specs;
|
|
8370
6737
|
}
|
|
8371
6738
|
function readPackageJsonDependencySpecs(packageJsonPath) {
|
|
8372
|
-
const parsed = parseJsonObject(
|
|
6739
|
+
const parsed = parseJsonObject(readFileSync(packageJsonPath, "utf8"));
|
|
8373
6740
|
if (!parsed) return [];
|
|
8374
6741
|
const optionalPeerNames = /* @__PURE__ */ new Set();
|
|
8375
6742
|
const peerDependenciesMeta = parsed.peerDependenciesMeta;
|
|
@@ -8396,7 +6763,7 @@ function readPackageJsonDependencySpecs(packageJsonPath) {
|
|
|
8396
6763
|
return specs;
|
|
8397
6764
|
}
|
|
8398
6765
|
function readRequirementsDependencySpecs(path) {
|
|
8399
|
-
return
|
|
6766
|
+
return readFileSync(path, "utf8").split("\n").map((line) => line.trim()).filter((line) => line.length > 0 && !line.startsWith("#")).map((line) => {
|
|
8400
6767
|
const [name = line, version = ""] = line.split(/[<>=~!]=?/, 2);
|
|
8401
6768
|
return { name: name.trim(), version: line.includes("==") ? version.trim() : line };
|
|
8402
6769
|
});
|
|
@@ -8412,9 +6779,9 @@ function isPinnedDependencyVersion(version) {
|
|
|
8412
6779
|
return /^\d+\.\d+(?:\.\d+)?(?:[-+][0-9A-Za-z.-]+)?$/.test(trimmed);
|
|
8413
6780
|
}
|
|
8414
6781
|
function workflowTargetsDefaultBranch(repoPath, file) {
|
|
8415
|
-
const fullPath =
|
|
6782
|
+
const fullPath = join(repoPath, file);
|
|
8416
6783
|
if (!isRegularFile(fullPath)) return false;
|
|
8417
|
-
const contents =
|
|
6784
|
+
const contents = readFileSync(fullPath, "utf8").toLowerCase();
|
|
8418
6785
|
return /\bpull_request\b/.test(contents) || /\bbranches:\s*\[[^\]]*\b(main|master)\b[^\]]*\]/.test(contents) || /\bbranches:\s*\n\s*-\s*(main|master)\b/.test(contents);
|
|
8419
6786
|
}
|
|
8420
6787
|
function isPrMergeCommit(commit) {
|
|
@@ -8450,7 +6817,6 @@ function isExplicitDeployTarget(file) {
|
|
|
8450
6817
|
return /^(vercel|netlify|fly|render|railway)\.(json|toml|ya?ml)$/.test(file) || /^docker-compose\.ya?ml$/.test(file) || /^Procfile$/.test(file) || /^app\.ya?ml$/.test(file) || /^serverless\.ya?ml$/.test(file) || /^(k8s|kubernetes|manifests?)\/.+\.ya?ml$/i.test(file) || /^(charts?|helm)\/.+\.ya?ml$/i.test(file);
|
|
8451
6818
|
}
|
|
8452
6819
|
var MAIN_ENTRYPOINT_FILE_PATTERN = /(^|\/)(main|server|app|wsgi|asgi|index|entry|start|run)\.(ts|tsx|js|jsx|mjs|cjs|py|go|rs)$/i;
|
|
8453
|
-
var EXAMPLE_OR_TEST_DIR_PATTERN = /(?:^|\/)(examples?|samples?|demos?|tests?|__tests__|spec|fixtures?)(?:\/|$)/i;
|
|
8454
6820
|
var SERVER_ENTRYPOINT_PATTERN = /\bapp\.listen\s*\(|\bserver\.listen\s*\(\s*(?:PORT|port|\d+)|http\.ListenAndServe\s*\(|http\.ListenAndServeTLS\s*\(|axum::Server(?:::|\.)|actix_web::HttpServer(?:::|\.)|uvicorn\.run\s*\(/;
|
|
8455
6821
|
var CI_DEPLOY_JOB_PATTERN = /(?:^\s{2,4}deploy\s*:|\b(?:fly|heroku|vercel|netlify|railway|render)\s+deploy\b|kubectl\s+apply\b|helm\s+(?:install|upgrade|deploy)\b|docker\s+push\b)/im;
|
|
8456
6822
|
function isDeployableService(repoPath, repoFiles) {
|
|
@@ -8467,9 +6833,7 @@ function detectServerEntrypoint(repoPath, repoFiles) {
|
|
|
8467
6833
|
return findServerEntrypointFile(repoPath, repoFiles) !== null;
|
|
8468
6834
|
}
|
|
8469
6835
|
function findServerEntrypointFile(repoPath, repoFiles) {
|
|
8470
|
-
const candidates = repoFiles.filter(
|
|
8471
|
-
(file) => MAIN_ENTRYPOINT_FILE_PATTERN.test(file) && !EXAMPLE_OR_TEST_DIR_PATTERN.test(file)
|
|
8472
|
-
).slice(0, 30);
|
|
6836
|
+
const candidates = repoFiles.filter((file) => MAIN_ENTRYPOINT_FILE_PATTERN.test(file) && isProductionSourcePath(file)).slice(0, 30);
|
|
8473
6837
|
return candidates.find((file) => fileContains(repoPath, file, SERVER_ENTRYPOINT_PATTERN)) ?? null;
|
|
8474
6838
|
}
|
|
8475
6839
|
function isHealthCheckSignalFile(repoPath, file) {
|
|
@@ -8481,391 +6845,785 @@ function isHealthCheckSignalFile(repoPath, file) {
|
|
|
8481
6845
|
if (/(^|\/)(health|healthcheck|readiness|liveness|ready)\.[cm]?[jt]sx?$/.test(file)) {
|
|
8482
6846
|
return fileContains(repoPath, file, /health|ready|readiness|liveness/i);
|
|
8483
6847
|
}
|
|
8484
|
-
if (/(^|\/)(health|healthcheck|readiness|liveness|ready)\.py$/.test(file)) {
|
|
8485
|
-
return fileContains(repoPath, file, /health|ready|readiness|liveness/i);
|
|
6848
|
+
if (/(^|\/)(health|healthcheck|readiness|liveness|ready)\.py$/.test(file)) {
|
|
6849
|
+
return fileContains(repoPath, file, /health|ready|readiness|liveness/i);
|
|
6850
|
+
}
|
|
6851
|
+
return false;
|
|
6852
|
+
}
|
|
6853
|
+
function isDependencyManifest(file) {
|
|
6854
|
+
return /(^|\/)(package\.json|pyproject\.toml|requirements(?:[^/]*)?\.txt|go\.mod|Cargo\.toml|pom\.xml|build\.gradle|vcpkg\.json|Pipfile|CMakeLists\.txt|conanfile\.txt|conanfile\.py)$/.test(
|
|
6855
|
+
file
|
|
6856
|
+
);
|
|
6857
|
+
}
|
|
6858
|
+
function isLockfile(file) {
|
|
6859
|
+
return /(^|\/)(pnpm-lock\.yaml|package-lock\.json|yarn\.lock|uv\.lock|poetry\.lock|go\.sum|Cargo\.lock|Pipfile\.lock|composer\.lock|conan\.lock|vcpkg\.lock\.json)$/.test(
|
|
6860
|
+
file
|
|
6861
|
+
);
|
|
6862
|
+
}
|
|
6863
|
+
function isDependencyUpdateConfig(file) {
|
|
6864
|
+
return /(^|\/)(renovate\.json|renovate\.json5|\.renovaterc\.json|dependabot\.ya?ml)$/.test(file) || /^\.github\/dependabot\.ya?ml$/.test(file);
|
|
6865
|
+
}
|
|
6866
|
+
function packageJsonHasAuditScript(repoPath, manifest) {
|
|
6867
|
+
if (!manifest.endsWith("package.json")) return false;
|
|
6868
|
+
const scripts = readPackageScripts(join(repoPath, manifest));
|
|
6869
|
+
return [...scripts.values()].some(
|
|
6870
|
+
(script) => /\b(audit|npm audit|pnpm audit|yarn audit)\b/i.test(script)
|
|
6871
|
+
);
|
|
6872
|
+
}
|
|
6873
|
+
function packageJsonHasHeavyTestDependency(repoPath, manifest) {
|
|
6874
|
+
const fullPath = join(repoPath, manifest);
|
|
6875
|
+
if (!isRegularFile(fullPath)) return false;
|
|
6876
|
+
const parsed = parseJsonObject(readFileSync(fullPath, "utf8"));
|
|
6877
|
+
if (!parsed) return false;
|
|
6878
|
+
const names = [
|
|
6879
|
+
...Object.keys(isRecord(parsed.dependencies) ? parsed.dependencies : {}),
|
|
6880
|
+
...Object.keys(isRecord(parsed.devDependencies) ? parsed.devDependencies : {})
|
|
6881
|
+
];
|
|
6882
|
+
return names.some((name) => HEAVY_TEST_DEPENDENCY_NAME_PATTERN.test(name));
|
|
6883
|
+
}
|
|
6884
|
+
function isImplementationFile(file) {
|
|
6885
|
+
return /(^|\/)(src|app|lib|packages|cmd|include|source|Sources)\//.test(file) && /\.(ts|tsx|js|jsx|py|go|rs|java|rb|cpp|cc|cxx|c|h|hpp|kt|swift|php)$/.test(file);
|
|
6886
|
+
}
|
|
6887
|
+
function isAuditFile(file) {
|
|
6888
|
+
return (
|
|
6889
|
+
// goal_cejel_calibration_fix_with_strict_gate_2026-07-06: mature OSS repos document the
|
|
6890
|
+
// same audit-trail practice under different filenames/extensions than Alfred's own
|
|
6891
|
+
// conventions (Flask ships CHANGES.rst, not CHANGELOG.md) — recognize the common OSS
|
|
6892
|
+
// release-notes/security-policy/provenance equivalents so real audit-trail artifacts are
|
|
6893
|
+
// credited instead of silently missing the pattern.
|
|
6894
|
+
/(^|\/)(CHANGELOG|CHANGES|HISTORY|NEWS|RELEASE_NOTES|RELEASES|SECURITY|AUDIT|STATUS)\.(md|rst|txt)$/i.test(
|
|
6895
|
+
file
|
|
6896
|
+
) || /(^|\/)docs\/.*(audit|runbook|incident|changelog|security).*\.(md|rst)$/i.test(file) || // Provenance/signed-release tooling config is itself audit-trail evidence (a repo that
|
|
6897
|
+
// wires SLSA/cosign attestation or CITATION.cff is documenting release provenance).
|
|
6898
|
+
/(^|\/)CITATION\.cff$/i.test(file)
|
|
6899
|
+
);
|
|
6900
|
+
}
|
|
6901
|
+
function isSecurityPolicyOnlyAuditFile(file) {
|
|
6902
|
+
return /(^|\/)SECURITY\.(md|rst|txt)$/i.test(file) || /(^|\/)docs\/.*security.*\.(md|rst)$/i.test(file);
|
|
6903
|
+
}
|
|
6904
|
+
function isFreshnessRatableAuditFile(file) {
|
|
6905
|
+
return isAuditFile(file) && !isSecurityPolicyOnlyAuditFile(file);
|
|
6906
|
+
}
|
|
6907
|
+
function isIgnoredScanFile(file) {
|
|
6908
|
+
return /(^|\/)(package-lock\.json|pnpm-lock\.yaml|yarn\.lock|README\.md|CHANGELOG\.md)$/.test(file) || isEnvTemplatePath(file);
|
|
6909
|
+
}
|
|
6910
|
+
function findRootPackageJson(repoFiles) {
|
|
6911
|
+
return repoFiles.includes("package.json") ? "package.json" : null;
|
|
6912
|
+
}
|
|
6913
|
+
function isRegularFile(path) {
|
|
6914
|
+
try {
|
|
6915
|
+
return statSync(path).isFile();
|
|
6916
|
+
} catch {
|
|
6917
|
+
return false;
|
|
6918
|
+
}
|
|
6919
|
+
}
|
|
6920
|
+
function fileContains(repoPath, file, pattern) {
|
|
6921
|
+
const fullPath = join(repoPath, file);
|
|
6922
|
+
if (!isRegularFile(fullPath)) return false;
|
|
6923
|
+
return pattern.test(readFileSync(fullPath, "utf8"));
|
|
6924
|
+
}
|
|
6925
|
+
function fileContainsCommittedSecret(repoPath, file) {
|
|
6926
|
+
const fullPath = join(repoPath, file);
|
|
6927
|
+
if (!isRegularFile(fullPath)) return false;
|
|
6928
|
+
return containsRealSecret(readFileSync(fullPath, "utf8"));
|
|
6929
|
+
}
|
|
6930
|
+
function containsRealSecret(contents) {
|
|
6931
|
+
SECRET_ASSIGNMENT_PATTERN.lastIndex = 0;
|
|
6932
|
+
for (const match of contents.matchAll(SECRET_ASSIGNMENT_PATTERN)) {
|
|
6933
|
+
const rawValue = match[1];
|
|
6934
|
+
if (!rawValue) continue;
|
|
6935
|
+
const value = rawValue.replace(/[,;)]$/, "");
|
|
6936
|
+
if (isPlaceholderSecretValue(value)) continue;
|
|
6937
|
+
if (looksLikeSecretValue(value)) return true;
|
|
6938
|
+
}
|
|
6939
|
+
return false;
|
|
6940
|
+
}
|
|
6941
|
+
function collectHistorySecretEvidence(repoPath) {
|
|
6942
|
+
const historyEntries = readCredentialHistoryEntries(repoPath);
|
|
6943
|
+
let scannedFiles = 0;
|
|
6944
|
+
let envPathEvidence = null;
|
|
6945
|
+
for (const entry of historyEntries) {
|
|
6946
|
+
if (scannedFiles >= HISTORY_SECRET_SCAN_CREDENTIAL_BLOB_LIMIT) {
|
|
6947
|
+
return { evidence: null, envPathEvidence, truncated: true };
|
|
6948
|
+
}
|
|
6949
|
+
scannedFiles += 1;
|
|
6950
|
+
const contents = readGitBlob(repoPath, entry.commit, entry.path);
|
|
6951
|
+
if (!contents) continue;
|
|
6952
|
+
if (containsRealSecret(contents)) {
|
|
6953
|
+
return {
|
|
6954
|
+
evidence: {
|
|
6955
|
+
kind: "secret_scan",
|
|
6956
|
+
label: "Committed secret in recent git history",
|
|
6957
|
+
path: entry.path,
|
|
6958
|
+
contentHash: entry.commit
|
|
6959
|
+
},
|
|
6960
|
+
envPathEvidence,
|
|
6961
|
+
truncated: false
|
|
6962
|
+
};
|
|
6963
|
+
}
|
|
6964
|
+
if (!envPathEvidence && isEnvHistoryPath(entry.path)) {
|
|
6965
|
+
envPathEvidence = {
|
|
6966
|
+
kind: "secret_scan",
|
|
6967
|
+
label: ".env file (not a template) tracked in git history; no confirmed secret value found",
|
|
6968
|
+
path: entry.path,
|
|
6969
|
+
contentHash: entry.commit
|
|
6970
|
+
};
|
|
6971
|
+
}
|
|
6972
|
+
}
|
|
6973
|
+
return { evidence: null, envPathEvidence, truncated: false };
|
|
6974
|
+
}
|
|
6975
|
+
function readCredentialHistoryEntries(repoPath) {
|
|
6976
|
+
const entries = [];
|
|
6977
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6978
|
+
const appendEntry = (entry) => {
|
|
6979
|
+
const key = `${entry.commit}:${entry.path}`;
|
|
6980
|
+
if (seen.has(key)) return;
|
|
6981
|
+
seen.add(key);
|
|
6982
|
+
entries.push(entry);
|
|
6983
|
+
};
|
|
6984
|
+
try {
|
|
6985
|
+
const commits = execFileSync("git", ["rev-list", "--all"], {
|
|
6986
|
+
cwd: repoPath,
|
|
6987
|
+
encoding: "utf8",
|
|
6988
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
6989
|
+
});
|
|
6990
|
+
const output = execFileSync(
|
|
6991
|
+
"git",
|
|
6992
|
+
[
|
|
6993
|
+
"diff-tree",
|
|
6994
|
+
"--stdin",
|
|
6995
|
+
"--root",
|
|
6996
|
+
"--name-only",
|
|
6997
|
+
"-r",
|
|
6998
|
+
"--diff-filter=AM",
|
|
6999
|
+
"--pretty=format:commit:%H"
|
|
7000
|
+
],
|
|
7001
|
+
{
|
|
7002
|
+
cwd: repoPath,
|
|
7003
|
+
encoding: "utf8",
|
|
7004
|
+
input: commits,
|
|
7005
|
+
stdio: ["pipe", "pipe", "ignore"]
|
|
7006
|
+
}
|
|
7007
|
+
);
|
|
7008
|
+
let currentCommit = null;
|
|
7009
|
+
for (const line of output.split("\n")) {
|
|
7010
|
+
if (line.startsWith("commit:")) {
|
|
7011
|
+
currentCommit = line.slice("commit:".length);
|
|
7012
|
+
continue;
|
|
7013
|
+
}
|
|
7014
|
+
const path = line.trim();
|
|
7015
|
+
if (!currentCommit || !path) continue;
|
|
7016
|
+
if (!isCredentialHistoryPath(path)) continue;
|
|
7017
|
+
appendEntry({ commit: currentCommit, path });
|
|
7018
|
+
}
|
|
7019
|
+
} catch {
|
|
7020
|
+
}
|
|
7021
|
+
for (const entry of readDeletedCredentialHistoryEntries(repoPath)) {
|
|
7022
|
+
appendEntry(entry);
|
|
7023
|
+
}
|
|
7024
|
+
return entries;
|
|
7025
|
+
}
|
|
7026
|
+
function readDeletedCredentialHistoryEntries(repoPath) {
|
|
7027
|
+
const deletedPaths = readDeletedCredentialHistoryPaths(repoPath);
|
|
7028
|
+
const entries = [];
|
|
7029
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7030
|
+
for (const path of deletedPaths) {
|
|
7031
|
+
for (const commit of readHistoryCommitsForPath(repoPath, path)) {
|
|
7032
|
+
const key = `${commit}:${path}`;
|
|
7033
|
+
if (seen.has(key)) continue;
|
|
7034
|
+
seen.add(key);
|
|
7035
|
+
entries.push({ commit, path });
|
|
7036
|
+
}
|
|
7037
|
+
}
|
|
7038
|
+
return entries;
|
|
7039
|
+
}
|
|
7040
|
+
function readDeletedCredentialHistoryPaths(repoPath) {
|
|
7041
|
+
try {
|
|
7042
|
+
const output = execFileSync(
|
|
7043
|
+
"git",
|
|
7044
|
+
["log", "--all", "--diff-filter=D", "--name-status", "--format=commit:%H"],
|
|
7045
|
+
{
|
|
7046
|
+
cwd: repoPath,
|
|
7047
|
+
encoding: "utf8",
|
|
7048
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
7049
|
+
}
|
|
7050
|
+
);
|
|
7051
|
+
const paths = [];
|
|
7052
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7053
|
+
for (const line of output.split("\n")) {
|
|
7054
|
+
if (!line.startsWith("D ")) continue;
|
|
7055
|
+
const path = line.slice(2).trim();
|
|
7056
|
+
if (!path || seen.has(path)) continue;
|
|
7057
|
+
if (!isCredentialHistoryPath(path)) continue;
|
|
7058
|
+
seen.add(path);
|
|
7059
|
+
paths.push(path);
|
|
7060
|
+
}
|
|
7061
|
+
return paths;
|
|
7062
|
+
} catch {
|
|
7063
|
+
return [];
|
|
7064
|
+
}
|
|
7065
|
+
}
|
|
7066
|
+
function readHistoryCommitsForPath(repoPath, path) {
|
|
7067
|
+
try {
|
|
7068
|
+
const output = execFileSync(
|
|
7069
|
+
"git",
|
|
7070
|
+
["log", "--all", "--diff-filter=AM", "--format=%H", "--", path],
|
|
7071
|
+
{
|
|
7072
|
+
cwd: repoPath,
|
|
7073
|
+
encoding: "utf8",
|
|
7074
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
7075
|
+
}
|
|
7076
|
+
);
|
|
7077
|
+
return output.split("\n").map((line) => line.trim()).filter((line) => /^[0-9a-f]{40}$/i.test(line));
|
|
7078
|
+
} catch {
|
|
7079
|
+
return [];
|
|
7080
|
+
}
|
|
7081
|
+
}
|
|
7082
|
+
function isCredentialHistoryPath(path) {
|
|
7083
|
+
if (isHardExcludedPath(path)) return false;
|
|
7084
|
+
const lowerPath = path.toLowerCase();
|
|
7085
|
+
const basename3 = lowerPath.split("/").at(-1) ?? lowerPath;
|
|
7086
|
+
if (/\.env(?:\.|$)/.test(basename3)) {
|
|
7087
|
+
return true;
|
|
7088
|
+
}
|
|
7089
|
+
return lowerPath.includes("secret") || lowerPath.includes("credential") || basename3.endsWith(".pem") || basename3.endsWith(".key") || basename3 === "id_rsa" || basename3.endsWith(".p12") || basename3.endsWith(".pfx");
|
|
7090
|
+
}
|
|
7091
|
+
function isEnvHistoryPath(path) {
|
|
7092
|
+
if (isEnvTemplatePath(path)) return false;
|
|
7093
|
+
const basename3 = path.toLowerCase().split("/").at(-1) ?? path.toLowerCase();
|
|
7094
|
+
return /\.env(?:\.|$)/.test(basename3);
|
|
7095
|
+
}
|
|
7096
|
+
function readGitBlob(repoPath, commit, path) {
|
|
7097
|
+
try {
|
|
7098
|
+
return execFileSync("git", ["show", `${commit}:${path}`], {
|
|
7099
|
+
cwd: repoPath,
|
|
7100
|
+
encoding: "utf8",
|
|
7101
|
+
maxBuffer: 512e3,
|
|
7102
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
7103
|
+
});
|
|
7104
|
+
} catch {
|
|
7105
|
+
return null;
|
|
7106
|
+
}
|
|
7107
|
+
}
|
|
7108
|
+
var ALL_CAPS_SNAKE_PLACEHOLDER_PATTERN = /^[A-Z][A-Z0-9]*(?:_[A-Z0-9]+)+$/;
|
|
7109
|
+
function isPlaceholderSecretValue(value) {
|
|
7110
|
+
const normalized = value.trim().toLowerCase();
|
|
7111
|
+
return PLACEHOLDER_SECRET_PATTERN.test(normalized) || normalized.includes("your-") || normalized.includes("example") || ALL_CAPS_SNAKE_PLACEHOLDER_PATTERN.test(value.trim()) || isSyntheticFixtureSecretValue(normalized) || isFillerRunSecretValue(normalized);
|
|
7112
|
+
}
|
|
7113
|
+
function isFillerRunSecretValue(value) {
|
|
7114
|
+
const candidates = [value];
|
|
7115
|
+
const sepIdx = Math.max(value.lastIndexOf("_"), value.lastIndexOf("-"));
|
|
7116
|
+
if (sepIdx > 0 && sepIdx < value.length - 1) {
|
|
7117
|
+
candidates.push(value.slice(sepIdx + 1));
|
|
7118
|
+
}
|
|
7119
|
+
for (const body of candidates) {
|
|
7120
|
+
if (body.length < 8) continue;
|
|
7121
|
+
const counts = /* @__PURE__ */ new Map();
|
|
7122
|
+
for (const ch of body) counts.set(ch, (counts.get(ch) ?? 0) + 1);
|
|
7123
|
+
const distinct = counts.size;
|
|
7124
|
+
const maxRun = Math.max(...counts.values());
|
|
7125
|
+
if (distinct <= 2 && maxRun / body.length >= 0.8) return true;
|
|
8486
7126
|
}
|
|
8487
7127
|
return false;
|
|
8488
7128
|
}
|
|
8489
|
-
function
|
|
8490
|
-
return
|
|
8491
|
-
file
|
|
8492
|
-
);
|
|
8493
|
-
}
|
|
8494
|
-
function isLockfile(file) {
|
|
8495
|
-
return /(^|\/)(pnpm-lock\.yaml|package-lock\.json|yarn\.lock|uv\.lock|poetry\.lock|go\.sum|Cargo\.lock|Pipfile\.lock|composer\.lock|conan\.lock|vcpkg\.lock\.json)$/.test(
|
|
8496
|
-
file
|
|
8497
|
-
);
|
|
8498
|
-
}
|
|
8499
|
-
function isDependencyUpdateConfig(file) {
|
|
8500
|
-
return /(^|\/)(renovate\.json|renovate\.json5|\.renovaterc\.json|dependabot\.ya?ml)$/.test(file) || /^\.github\/dependabot\.ya?ml$/.test(file);
|
|
7129
|
+
function isSyntheticFixtureSecretValue(value) {
|
|
7130
|
+
return value.includes("abcdefghijklmnopqrstuvwxyz") || value.includes("0123456789abcdefghijklmnopqrstuvwxyz") || value.includes("abcdefghijklmnopqrstuvwxyz0123456789") || value.includes("abcdefghijklmnopqrst");
|
|
8501
7131
|
}
|
|
8502
|
-
function
|
|
7132
|
+
function hasSuspiciousDependencies(repoPath, manifest) {
|
|
8503
7133
|
if (!manifest.endsWith("package.json")) return false;
|
|
8504
|
-
const
|
|
8505
|
-
return [...scripts.values()].some(
|
|
8506
|
-
(script) => /\b(audit|npm audit|pnpm audit|yarn audit)\b/i.test(script)
|
|
8507
|
-
);
|
|
8508
|
-
}
|
|
8509
|
-
function packageJsonHasHeavyTestDependency(repoPath, manifest) {
|
|
8510
|
-
const fullPath = join3(repoPath, manifest);
|
|
7134
|
+
const fullPath = join(repoPath, manifest);
|
|
8511
7135
|
if (!isRegularFile(fullPath)) return false;
|
|
8512
|
-
const parsed = parseJsonObject(
|
|
7136
|
+
const parsed = parseJsonObject(readFileSync(fullPath, "utf8"));
|
|
8513
7137
|
if (!parsed) return false;
|
|
8514
|
-
const
|
|
8515
|
-
|
|
8516
|
-
|
|
8517
|
-
|
|
8518
|
-
|
|
7138
|
+
const dependencies = isRecord(parsed.dependencies) ? parsed.dependencies : {};
|
|
7139
|
+
const devDependencies = isRecord(parsed.devDependencies) ? parsed.devDependencies : {};
|
|
7140
|
+
const names = [...Object.keys(dependencies), ...Object.keys(devDependencies)];
|
|
7141
|
+
return names.some(
|
|
7142
|
+
(name) => /^(todo|fake|placeholder|example)-|does-not-exist| hallucinated/i.test(name)
|
|
7143
|
+
);
|
|
8519
7144
|
}
|
|
8520
|
-
function
|
|
8521
|
-
|
|
7145
|
+
function readRecentCommits(repoPath) {
|
|
7146
|
+
try {
|
|
7147
|
+
const output = execFileSync("git", ["log", "--max-count=12", "--format=%H%x00%s"], {
|
|
7148
|
+
cwd: repoPath,
|
|
7149
|
+
encoding: "utf8",
|
|
7150
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
7151
|
+
}).trim();
|
|
7152
|
+
if (!output) return [];
|
|
7153
|
+
return output.split("\n").map((line) => {
|
|
7154
|
+
const [sha = "", subject = ""] = line.split("\0");
|
|
7155
|
+
return { sha, subject };
|
|
7156
|
+
}).filter((commit) => commit.sha.length >= 7);
|
|
7157
|
+
} catch {
|
|
7158
|
+
return [];
|
|
7159
|
+
}
|
|
8522
7160
|
}
|
|
8523
|
-
function
|
|
8524
|
-
return (
|
|
8525
|
-
|
|
8526
|
-
|
|
8527
|
-
|
|
8528
|
-
|
|
8529
|
-
|
|
8530
|
-
|
|
8531
|
-
|
|
8532
|
-
) || /(^|\/)docs\/.*(audit|runbook|incident|changelog|security).*\.(md|rst)$/i.test(file) || // Provenance/signed-release tooling config is itself audit-trail evidence (a repo that
|
|
8533
|
-
// wires SLSA/cosign attestation or CITATION.cff is documenting release provenance).
|
|
8534
|
-
/(^|\/)CITATION\.cff$/i.test(file)
|
|
7161
|
+
function readPackageScripts(packageJsonPath) {
|
|
7162
|
+
if (!isRegularFile(packageJsonPath)) return /* @__PURE__ */ new Map();
|
|
7163
|
+
const parsed = parseJsonObject(readFileSync(packageJsonPath, "utf8"));
|
|
7164
|
+
const scripts = parsed?.scripts;
|
|
7165
|
+
if (!isRecord(scripts)) return /* @__PURE__ */ new Map();
|
|
7166
|
+
return new Map(
|
|
7167
|
+
Object.entries(scripts).filter(
|
|
7168
|
+
(entry) => typeof entry[1] === "string"
|
|
7169
|
+
)
|
|
8535
7170
|
);
|
|
8536
7171
|
}
|
|
8537
|
-
function
|
|
8538
|
-
|
|
7172
|
+
function evidenceForRelative(repoPath, path, kind, label) {
|
|
7173
|
+
const fullPath = join(repoPath, path);
|
|
7174
|
+
const contents = isRegularFile(fullPath) ? readFileSync(fullPath, "utf8") : "";
|
|
7175
|
+
return {
|
|
7176
|
+
kind,
|
|
7177
|
+
label,
|
|
7178
|
+
path,
|
|
7179
|
+
...contents ? {
|
|
7180
|
+
line: firstMeaningfulLine(contents),
|
|
7181
|
+
contentHash: createHash2("sha256").update(contents).digest("hex")
|
|
7182
|
+
} : {}
|
|
7183
|
+
};
|
|
8539
7184
|
}
|
|
8540
|
-
function
|
|
8541
|
-
|
|
7185
|
+
function evidenceForRelativeAtLine(repoPath, path, kind, label, line) {
|
|
7186
|
+
const fullPath = join(repoPath, path);
|
|
7187
|
+
const contents = isRegularFile(fullPath) ? readFileSync(fullPath, "utf8") : "";
|
|
7188
|
+
return {
|
|
7189
|
+
kind,
|
|
7190
|
+
label,
|
|
7191
|
+
path,
|
|
7192
|
+
line,
|
|
7193
|
+
...contents ? { contentHash: createHash2("sha256").update(contents).digest("hex") } : {}
|
|
7194
|
+
};
|
|
8542
7195
|
}
|
|
8543
|
-
function
|
|
8544
|
-
return
|
|
7196
|
+
function metric(name, label, value, max, weight, unit, description, kind) {
|
|
7197
|
+
return {
|
|
7198
|
+
name,
|
|
7199
|
+
label,
|
|
7200
|
+
value: Math.max(0, value),
|
|
7201
|
+
max,
|
|
7202
|
+
...kind ? { kind } : {},
|
|
7203
|
+
weight,
|
|
7204
|
+
unit,
|
|
7205
|
+
description
|
|
7206
|
+
};
|
|
8545
7207
|
}
|
|
8546
|
-
function
|
|
8547
|
-
|
|
7208
|
+
function firstMeaningfulLine(contents) {
|
|
7209
|
+
const lines = contents.split("\n");
|
|
7210
|
+
const index = lines.findIndex((line) => line.trim().length > 0);
|
|
7211
|
+
return index === -1 ? 1 : index + 1;
|
|
8548
7212
|
}
|
|
8549
|
-
function
|
|
7213
|
+
function readGitHead(repoPath) {
|
|
7214
|
+
try {
|
|
7215
|
+
return execFileSync("git", ["rev-parse", "HEAD"], {
|
|
7216
|
+
cwd: repoPath,
|
|
7217
|
+
encoding: "utf8",
|
|
7218
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
7219
|
+
}).trim();
|
|
7220
|
+
} catch {
|
|
7221
|
+
return null;
|
|
7222
|
+
}
|
|
7223
|
+
}
|
|
7224
|
+
function hasEnvPathInGitHistory(repoPath) {
|
|
8550
7225
|
try {
|
|
8551
|
-
|
|
7226
|
+
const output = execFileSync(
|
|
7227
|
+
"git",
|
|
7228
|
+
["log", "--all", "--diff-filter=AM", "--name-only", "--format="],
|
|
7229
|
+
{
|
|
7230
|
+
cwd: repoPath,
|
|
7231
|
+
encoding: "utf8",
|
|
7232
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
7233
|
+
maxBuffer: 512e3
|
|
7234
|
+
}
|
|
7235
|
+
).trim();
|
|
7236
|
+
if (!output) return false;
|
|
7237
|
+
return output.split("\n").some((p) => /(?:^|\/)\.env(?:\.|$)/i.test(p.trim()));
|
|
8552
7238
|
} catch {
|
|
8553
7239
|
return false;
|
|
8554
7240
|
}
|
|
8555
7241
|
}
|
|
8556
|
-
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
|
|
7242
|
+
|
|
7243
|
+
// src/witan/public-scan.ts
|
|
7244
|
+
import { resolve as resolve2 } from "path";
|
|
7245
|
+
|
|
7246
|
+
// src/witan/ingest.ts
|
|
7247
|
+
import { readFileSync as readFileSync5, readdirSync as readdirSync2 } from "fs";
|
|
7248
|
+
import { join as join2 } from "path";
|
|
7249
|
+
|
|
7250
|
+
// src/witan/finding-limits.ts
|
|
7251
|
+
var RULE_ID_MAX = 200;
|
|
7252
|
+
var MESSAGE_MAX = 500;
|
|
7253
|
+
var LOCATION_MAX = 700;
|
|
7254
|
+
function clamp(value, max) {
|
|
7255
|
+
if (value.length <= max) return value;
|
|
7256
|
+
const ellipsis = "...";
|
|
7257
|
+
return `${value.slice(0, Math.max(max - ellipsis.length, 0))}${ellipsis}`;
|
|
8560
7258
|
}
|
|
8561
|
-
function
|
|
8562
|
-
|
|
8563
|
-
|
|
8564
|
-
|
|
7259
|
+
function clampFinding(finding) {
|
|
7260
|
+
return {
|
|
7261
|
+
...finding,
|
|
7262
|
+
ruleId: clamp(finding.ruleId, RULE_ID_MAX),
|
|
7263
|
+
message: clamp(finding.message, MESSAGE_MAX),
|
|
7264
|
+
...finding.location ? { location: clamp(finding.location, LOCATION_MAX) } : {}
|
|
7265
|
+
};
|
|
8565
7266
|
}
|
|
8566
|
-
|
|
8567
|
-
|
|
8568
|
-
|
|
8569
|
-
|
|
8570
|
-
|
|
8571
|
-
|
|
8572
|
-
|
|
8573
|
-
|
|
7267
|
+
|
|
7268
|
+
// src/witan/generic-adapter.ts
|
|
7269
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
7270
|
+
var VALID_DIMENSIONS = /* @__PURE__ */ new Set([
|
|
7271
|
+
"A1",
|
|
7272
|
+
"A2",
|
|
7273
|
+
"A3",
|
|
7274
|
+
"A4",
|
|
7275
|
+
"A5",
|
|
7276
|
+
"B1",
|
|
7277
|
+
"B2",
|
|
7278
|
+
"B3",
|
|
7279
|
+
"B4",
|
|
7280
|
+
"B5",
|
|
7281
|
+
"B6"
|
|
7282
|
+
]);
|
|
7283
|
+
var VALID_SEVERITIES = /* @__PURE__ */ new Set(["critical", "warning", "info"]);
|
|
7284
|
+
function isGenericSignalDocument(raw) {
|
|
7285
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
|
|
7286
|
+
const doc = raw;
|
|
7287
|
+
return typeof doc.tool === "string" && doc.tool.length > 0 && Array.isArray(doc.signals);
|
|
7288
|
+
}
|
|
7289
|
+
function parseGenericJson(raw) {
|
|
7290
|
+
if (!isGenericSignalDocument(raw)) return [];
|
|
7291
|
+
const source = raw.tool ?? "unknown";
|
|
7292
|
+
const signals = [];
|
|
7293
|
+
for (const signal of raw.signals ?? []) {
|
|
7294
|
+
const dimension = signal.dimension;
|
|
7295
|
+
if (!dimension || !VALID_DIMENSIONS.has(dimension)) continue;
|
|
7296
|
+
const weight = typeof signal.weight === "number" && Number.isFinite(signal.weight) ? Math.min(Math.max(signal.weight, 0), 1) : 0.5;
|
|
7297
|
+
const findings = [];
|
|
7298
|
+
for (const finding of signal.findings ?? []) {
|
|
7299
|
+
const severity = finding.severity;
|
|
7300
|
+
if (!severity || !VALID_SEVERITIES.has(severity)) continue;
|
|
7301
|
+
const ruleId = finding.ruleId ?? "unknown";
|
|
7302
|
+
findings.push({
|
|
7303
|
+
ruleId,
|
|
7304
|
+
severity,
|
|
7305
|
+
message: finding.message ?? ruleId,
|
|
7306
|
+
...finding.location ? { location: finding.location } : {}
|
|
7307
|
+
});
|
|
7308
|
+
}
|
|
7309
|
+
if (findings.length === 0) continue;
|
|
7310
|
+
signals.push({ source, dimension, weight, findings });
|
|
7311
|
+
}
|
|
7312
|
+
return signals;
|
|
7313
|
+
}
|
|
7314
|
+
|
|
7315
|
+
// src/witan/sarif-adapter.ts
|
|
7316
|
+
import { readFileSync as readFileSync3 } from "fs";
|
|
7317
|
+
var DIMENSION_RULES = [
|
|
7318
|
+
// A2 — injection / secrets / auth (high weight)
|
|
7319
|
+
{
|
|
7320
|
+
pattern: /sql[- _]?inject|cwe-89|sqli|command[- _]?inject|cwe-78|os[- _]?cmd|rce|remote[- _]?code/i,
|
|
7321
|
+
dimension: "A2",
|
|
7322
|
+
weight: 0.9
|
|
7323
|
+
},
|
|
7324
|
+
{
|
|
7325
|
+
pattern: /secret|credential|api[- _]?key|password[- _]?leak|hardcoded[- _]?(token|key|secret)|cwe-259|cwe-798/i,
|
|
7326
|
+
dimension: "A2",
|
|
7327
|
+
weight: 0.9
|
|
7328
|
+
},
|
|
7329
|
+
{
|
|
7330
|
+
pattern: /path[- _]?traversal|directory[- _]?traversal|cwe-22|lfi|rfi/i,
|
|
7331
|
+
dimension: "A2",
|
|
7332
|
+
weight: 0.8
|
|
7333
|
+
},
|
|
7334
|
+
{
|
|
7335
|
+
pattern: /ssrf|server[- _]?side[- _]?request[- _]?forg|cwe-918/i,
|
|
7336
|
+
dimension: "A2",
|
|
7337
|
+
weight: 0.8
|
|
7338
|
+
},
|
|
7339
|
+
{
|
|
7340
|
+
pattern: /xxe|xml[- _]?external[- _]?entity|cwe-611/i,
|
|
7341
|
+
dimension: "A2",
|
|
7342
|
+
weight: 0.8
|
|
7343
|
+
},
|
|
7344
|
+
{
|
|
7345
|
+
pattern: /auth[- _]?bypass|broken[- _]?auth|missing[- _]?auth|cwe-287|cwe-306|cwe-863|cwe-862/i,
|
|
7346
|
+
dimension: "A2",
|
|
7347
|
+
weight: 0.7
|
|
7348
|
+
},
|
|
7349
|
+
{
|
|
7350
|
+
pattern: /xss|cross[- _]?site[- _]?script|cwe-79/i,
|
|
7351
|
+
dimension: "A2",
|
|
7352
|
+
weight: 0.6
|
|
7353
|
+
},
|
|
7354
|
+
// A4 — dependency vulnerabilities
|
|
7355
|
+
{
|
|
7356
|
+
pattern: /cve-\d{4}-\d+|supply[- _]?chain|depend[a-z]*[- _]?vulner|outdated[- _]?depend|deprecated[- _]?package/i,
|
|
7357
|
+
dimension: "A4",
|
|
7358
|
+
weight: 0.8
|
|
7359
|
+
},
|
|
7360
|
+
{
|
|
7361
|
+
pattern: /npm[- _]?audit|yarn[- _]?audit|pnpm[- _]?audit|pip[- _]?audit|cargo[- _]?audit/i,
|
|
7362
|
+
dimension: "A4",
|
|
7363
|
+
weight: 0.7
|
|
7364
|
+
},
|
|
7365
|
+
// A3 — production readiness / insecure config
|
|
7366
|
+
{
|
|
7367
|
+
pattern: /insecure[- _]?tls|weak[- _]?cipher|tls[- _]?version|http[- _]?strict|hsts|csp[- _]?missing|cwe-326|cwe-327/i,
|
|
7368
|
+
dimension: "A3",
|
|
7369
|
+
weight: 0.5
|
|
7370
|
+
},
|
|
7371
|
+
{
|
|
7372
|
+
pattern: /error[- _]?handl|unhandled[- _]?exception|crash|uncaught|stacktrace[- _]?leak/i,
|
|
7373
|
+
dimension: "A3",
|
|
7374
|
+
weight: 0.4
|
|
7375
|
+
},
|
|
7376
|
+
{
|
|
7377
|
+
pattern: /debug[- _]?mode|dev[- _]?endpoint|staging[- _]?secret/i,
|
|
7378
|
+
dimension: "A3",
|
|
7379
|
+
weight: 0.4
|
|
7380
|
+
},
|
|
7381
|
+
// A1 — test integrity (low weight; SARIF rarely surfaces this)
|
|
7382
|
+
{
|
|
7383
|
+
pattern: /skipped[- _]?test|hollow[- _]?test|empty[- _]?assert|no[- _]?assertion/i,
|
|
7384
|
+
dimension: "A1",
|
|
7385
|
+
weight: 0.2
|
|
8574
7386
|
}
|
|
8575
|
-
|
|
7387
|
+
];
|
|
7388
|
+
var DEFAULT_DIMENSION = "A2";
|
|
7389
|
+
var DEFAULT_WEIGHT = 0.3;
|
|
7390
|
+
var DROP_LEVEL = /* @__PURE__ */ new Set(["none"]);
|
|
7391
|
+
function mapLevel(level) {
|
|
7392
|
+
if (!level || DROP_LEVEL.has(level)) return null;
|
|
7393
|
+
if (level === "error") return "critical";
|
|
7394
|
+
if (level === "warning") return "warning";
|
|
7395
|
+
return "info";
|
|
8576
7396
|
}
|
|
8577
|
-
function
|
|
8578
|
-
const
|
|
8579
|
-
|
|
8580
|
-
|
|
8581
|
-
for (const entry of historyEntries) {
|
|
8582
|
-
if (scannedFiles >= HISTORY_SECRET_SCAN_CREDENTIAL_BLOB_LIMIT) {
|
|
8583
|
-
return { evidence: null, envPathEvidence, truncated: true };
|
|
8584
|
-
}
|
|
8585
|
-
scannedFiles += 1;
|
|
8586
|
-
const contents = readGitBlob(repoPath, entry.commit, entry.path);
|
|
8587
|
-
if (!contents) continue;
|
|
8588
|
-
if (containsRealSecret(contents)) {
|
|
8589
|
-
return {
|
|
8590
|
-
evidence: {
|
|
8591
|
-
kind: "secret_scan",
|
|
8592
|
-
label: "Committed secret in recent git history",
|
|
8593
|
-
path: entry.path,
|
|
8594
|
-
contentHash: entry.commit
|
|
8595
|
-
},
|
|
8596
|
-
envPathEvidence,
|
|
8597
|
-
truncated: false
|
|
8598
|
-
};
|
|
8599
|
-
}
|
|
8600
|
-
if (!envPathEvidence && isEnvHistoryPath(entry.path)) {
|
|
8601
|
-
envPathEvidence = {
|
|
8602
|
-
kind: "secret_scan",
|
|
8603
|
-
label: ".env file (not a template) tracked in git history; no confirmed secret value found",
|
|
8604
|
-
path: entry.path,
|
|
8605
|
-
contentHash: entry.commit
|
|
8606
|
-
};
|
|
7397
|
+
function mapRuleToDimension(ruleId, rules) {
|
|
7398
|
+
for (const rule of rules) {
|
|
7399
|
+
if (rule.pattern.test(ruleId)) {
|
|
7400
|
+
return { dimension: rule.dimension, weight: rule.weight };
|
|
8607
7401
|
}
|
|
8608
7402
|
}
|
|
8609
|
-
return {
|
|
7403
|
+
return { dimension: DEFAULT_DIMENSION, weight: DEFAULT_WEIGHT };
|
|
8610
7404
|
}
|
|
8611
|
-
function
|
|
8612
|
-
const
|
|
7405
|
+
function renderLocation(result) {
|
|
7406
|
+
const loc = result.locations?.[0]?.physicalLocation;
|
|
7407
|
+
if (!loc) return void 0;
|
|
7408
|
+
const uri = loc.artifactLocation?.uri;
|
|
7409
|
+
const line = loc.region?.startLine;
|
|
7410
|
+
if (!uri) return void 0;
|
|
7411
|
+
return line != null ? `${uri}:${line}` : uri;
|
|
7412
|
+
}
|
|
7413
|
+
function dedupeFindings(findings) {
|
|
8613
7414
|
const seen = /* @__PURE__ */ new Set();
|
|
8614
|
-
|
|
8615
|
-
const key = `${
|
|
8616
|
-
if (seen.has(key)) return;
|
|
7415
|
+
return findings.filter((f) => {
|
|
7416
|
+
const key = `${f.ruleId}|${f.severity}|${f.location ?? ""}`;
|
|
7417
|
+
if (seen.has(key)) return false;
|
|
8617
7418
|
seen.add(key);
|
|
8618
|
-
|
|
8619
|
-
};
|
|
8620
|
-
try {
|
|
8621
|
-
const commits = execFileSync("git", ["rev-list", "--all"], {
|
|
8622
|
-
cwd: repoPath,
|
|
8623
|
-
encoding: "utf8",
|
|
8624
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
8625
|
-
});
|
|
8626
|
-
const output = execFileSync(
|
|
8627
|
-
"git",
|
|
8628
|
-
[
|
|
8629
|
-
"diff-tree",
|
|
8630
|
-
"--stdin",
|
|
8631
|
-
"--root",
|
|
8632
|
-
"--name-only",
|
|
8633
|
-
"-r",
|
|
8634
|
-
"--diff-filter=AM",
|
|
8635
|
-
"--pretty=format:commit:%H"
|
|
8636
|
-
],
|
|
8637
|
-
{
|
|
8638
|
-
cwd: repoPath,
|
|
8639
|
-
encoding: "utf8",
|
|
8640
|
-
input: commits,
|
|
8641
|
-
stdio: ["pipe", "pipe", "ignore"]
|
|
8642
|
-
}
|
|
8643
|
-
);
|
|
8644
|
-
let currentCommit = null;
|
|
8645
|
-
for (const line of output.split("\n")) {
|
|
8646
|
-
if (line.startsWith("commit:")) {
|
|
8647
|
-
currentCommit = line.slice("commit:".length);
|
|
8648
|
-
continue;
|
|
8649
|
-
}
|
|
8650
|
-
const path = line.trim();
|
|
8651
|
-
if (!currentCommit || !path) continue;
|
|
8652
|
-
if (!isCredentialHistoryPath(path)) continue;
|
|
8653
|
-
appendEntry({ commit: currentCommit, path });
|
|
8654
|
-
}
|
|
8655
|
-
} catch {
|
|
8656
|
-
}
|
|
8657
|
-
for (const entry of readDeletedCredentialHistoryEntries(repoPath)) {
|
|
8658
|
-
appendEntry(entry);
|
|
8659
|
-
}
|
|
8660
|
-
return entries;
|
|
7419
|
+
return true;
|
|
7420
|
+
});
|
|
8661
7421
|
}
|
|
8662
|
-
function
|
|
8663
|
-
|
|
8664
|
-
const
|
|
8665
|
-
const
|
|
8666
|
-
|
|
8667
|
-
|
|
8668
|
-
|
|
8669
|
-
|
|
8670
|
-
|
|
8671
|
-
|
|
7422
|
+
function parseSarifJson(raw, extraDimensionRules) {
|
|
7423
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return [];
|
|
7424
|
+
const dimensionRules = extraDimensionRules ? [...DIMENSION_RULES, ...extraDimensionRules] : DIMENSION_RULES;
|
|
7425
|
+
const doc = raw;
|
|
7426
|
+
if (!Array.isArray(doc.runs)) return [];
|
|
7427
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
7428
|
+
for (const run of doc.runs) {
|
|
7429
|
+
const driverName = run.tool?.driver?.name ?? "unknown";
|
|
7430
|
+
const source = `sarif:${driverName}`;
|
|
7431
|
+
const ruleDefaultLevels = /* @__PURE__ */ new Map();
|
|
7432
|
+
for (const rule of run.tool?.driver?.rules ?? []) {
|
|
7433
|
+
if (rule.id && rule.defaultConfiguration?.level) {
|
|
7434
|
+
ruleDefaultLevels.set(rule.id, rule.defaultConfiguration.level);
|
|
7435
|
+
}
|
|
8672
7436
|
}
|
|
8673
|
-
|
|
8674
|
-
|
|
8675
|
-
|
|
8676
|
-
|
|
8677
|
-
|
|
8678
|
-
|
|
8679
|
-
|
|
8680
|
-
|
|
8681
|
-
{
|
|
8682
|
-
|
|
8683
|
-
|
|
8684
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
7437
|
+
for (const result of run.results ?? []) {
|
|
7438
|
+
const ruleId = result.ruleId ?? "unknown";
|
|
7439
|
+
const effectiveLevel = result.level ?? ruleDefaultLevels.get(ruleId) ?? "warning";
|
|
7440
|
+
const severity = mapLevel(effectiveLevel);
|
|
7441
|
+
if (!severity) continue;
|
|
7442
|
+
const message = result.message?.text ?? ruleId;
|
|
7443
|
+
const location = renderLocation(result);
|
|
7444
|
+
const { dimension, weight } = mapRuleToDimension(ruleId, dimensionRules);
|
|
7445
|
+
const bucketKey = `${source}|${dimension}`;
|
|
7446
|
+
if (!buckets.has(bucketKey)) {
|
|
7447
|
+
buckets.set(bucketKey, { source, dimension, weight, findings: [] });
|
|
8685
7448
|
}
|
|
8686
|
-
|
|
8687
|
-
const paths = [];
|
|
8688
|
-
const seen = /* @__PURE__ */ new Set();
|
|
8689
|
-
for (const line of output.split("\n")) {
|
|
8690
|
-
if (!line.startsWith("D ")) continue;
|
|
8691
|
-
const path = line.slice(2).trim();
|
|
8692
|
-
if (!path || seen.has(path)) continue;
|
|
8693
|
-
if (!isCredentialHistoryPath(path)) continue;
|
|
8694
|
-
seen.add(path);
|
|
8695
|
-
paths.push(path);
|
|
7449
|
+
buckets.get(bucketKey)?.findings.push({ ruleId, severity, message, ...location ? { location } : {} });
|
|
8696
7450
|
}
|
|
8697
|
-
return paths;
|
|
8698
|
-
} catch {
|
|
8699
|
-
return [];
|
|
8700
7451
|
}
|
|
7452
|
+
return Array.from(buckets.values()).map(({ source, dimension, weight, findings }) => ({
|
|
7453
|
+
source,
|
|
7454
|
+
dimension,
|
|
7455
|
+
weight,
|
|
7456
|
+
findings: dedupeFindings(findings)
|
|
7457
|
+
}));
|
|
8701
7458
|
}
|
|
8702
|
-
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
8711
|
-
|
|
8712
|
-
|
|
8713
|
-
|
|
8714
|
-
|
|
8715
|
-
|
|
8716
|
-
}
|
|
7459
|
+
|
|
7460
|
+
// src/witan/scorecard-adapter.ts
|
|
7461
|
+
import { readFileSync as readFileSync4 } from "fs";
|
|
7462
|
+
var CHECK_RULES = {
|
|
7463
|
+
// B2 — PR outcome traceability
|
|
7464
|
+
"Branch-Protection": { dimension: "B2", weight: 0.8 },
|
|
7465
|
+
"Code-Review": { dimension: "B2", weight: 0.7 },
|
|
7466
|
+
// B3 — CI and QA discipline
|
|
7467
|
+
"Dangerous-Workflow": { dimension: "B3", weight: 0.9 },
|
|
7468
|
+
"Token-Permissions": { dimension: "B3", weight: 0.8 },
|
|
7469
|
+
"CI-Tests": { dimension: "B3", weight: 0.7 },
|
|
7470
|
+
Maintained: { dimension: "B3", weight: 0.3 },
|
|
7471
|
+
// B4 — audit trail / release integrity
|
|
7472
|
+
"Signed-Releases": { dimension: "B4", weight: 0.7 },
|
|
7473
|
+
Packaging: { dimension: "B4", weight: 0.4 },
|
|
7474
|
+
"Security-Policy": { dimension: "B4", weight: 0.4 },
|
|
7475
|
+
// A4 — dependency hygiene
|
|
7476
|
+
Vulnerabilities: { dimension: "A4", weight: 0.9 },
|
|
7477
|
+
"Pinned-Dependencies": { dimension: "A4", weight: 0.8 },
|
|
7478
|
+
"Dependency-Update-Tool": { dimension: "A4", weight: 0.6 },
|
|
7479
|
+
// A2 — data-layer / static analysis
|
|
7480
|
+
SAST: { dimension: "A2", weight: 0.7 },
|
|
7481
|
+
"Binary-Artifacts": { dimension: "A2", weight: 0.6 },
|
|
7482
|
+
// A1 — test integrity
|
|
7483
|
+
Fuzzing: { dimension: "A1", weight: 0.3 }
|
|
7484
|
+
};
|
|
7485
|
+
function mapScoreToSeverity(score) {
|
|
7486
|
+
if (score == null || Number.isNaN(score)) return null;
|
|
7487
|
+
if (score < 0) return null;
|
|
7488
|
+
if (score >= 10) return null;
|
|
7489
|
+
if (score <= 3) return "critical";
|
|
7490
|
+
if (score <= 6) return "warning";
|
|
7491
|
+
return "info";
|
|
8717
7492
|
}
|
|
8718
|
-
function
|
|
8719
|
-
|
|
8720
|
-
|
|
8721
|
-
|
|
8722
|
-
|
|
7493
|
+
function dedupeFindings2(findings) {
|
|
7494
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7495
|
+
return findings.filter((f) => {
|
|
7496
|
+
const key = `${f.ruleId}|${f.severity}|${f.location ?? ""}`;
|
|
7497
|
+
if (seen.has(key)) return false;
|
|
7498
|
+
seen.add(key);
|
|
8723
7499
|
return true;
|
|
8724
|
-
}
|
|
8725
|
-
return lowerPath.includes("secret") || lowerPath.includes("credential") || basename4.endsWith(".pem") || basename4.endsWith(".key") || basename4 === "id_rsa" || basename4.endsWith(".p12") || basename4.endsWith(".pfx");
|
|
8726
|
-
}
|
|
8727
|
-
function isEnvHistoryPath(path) {
|
|
8728
|
-
if (isEnvTemplatePath(path)) return false;
|
|
8729
|
-
const basename4 = path.toLowerCase().split("/").at(-1) ?? path.toLowerCase();
|
|
8730
|
-
return /\.env(?:\.|$)/.test(basename4);
|
|
7500
|
+
});
|
|
8731
7501
|
}
|
|
8732
|
-
function
|
|
8733
|
-
|
|
8734
|
-
|
|
8735
|
-
|
|
8736
|
-
|
|
8737
|
-
|
|
8738
|
-
|
|
7502
|
+
function parseScorecardJson(raw) {
|
|
7503
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return [];
|
|
7504
|
+
const doc = raw;
|
|
7505
|
+
if (!Array.isArray(doc.checks)) return [];
|
|
7506
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
7507
|
+
for (const check of doc.checks) {
|
|
7508
|
+
const name = check.name;
|
|
7509
|
+
if (!name) continue;
|
|
7510
|
+
const rule = CHECK_RULES[name];
|
|
7511
|
+
if (!rule) continue;
|
|
7512
|
+
const severity = mapScoreToSeverity(check.score);
|
|
7513
|
+
if (!severity) continue;
|
|
7514
|
+
const scoreText = typeof check.score === "number" ? `${check.score}/10` : "n/a";
|
|
7515
|
+
const message = `${name} (Scorecard ${scoreText}): ${check.reason ?? "weakness detected"}`.slice(0, 500);
|
|
7516
|
+
const location = check.documentation?.url;
|
|
7517
|
+
const bucket = buckets.get(rule.dimension) ?? { weight: 0, findings: [] };
|
|
7518
|
+
bucket.weight = Math.max(bucket.weight, rule.weight);
|
|
7519
|
+
bucket.findings.push({
|
|
7520
|
+
ruleId: `scorecard:${name}`,
|
|
7521
|
+
severity,
|
|
7522
|
+
message,
|
|
7523
|
+
...location ? { location } : {}
|
|
8739
7524
|
});
|
|
8740
|
-
|
|
8741
|
-
return null;
|
|
7525
|
+
buckets.set(rule.dimension, bucket);
|
|
8742
7526
|
}
|
|
7527
|
+
return Array.from(buckets.entries()).map(([dimension, { weight, findings }]) => ({
|
|
7528
|
+
source: "scorecard",
|
|
7529
|
+
dimension,
|
|
7530
|
+
weight,
|
|
7531
|
+
findings: dedupeFindings2(findings)
|
|
7532
|
+
}));
|
|
8743
7533
|
}
|
|
8744
|
-
|
|
8745
|
-
|
|
8746
|
-
|
|
8747
|
-
|
|
7534
|
+
|
|
7535
|
+
// src/witan/ingest.ts
|
|
7536
|
+
function looksLikeSarif(raw) {
|
|
7537
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
|
|
7538
|
+
return Array.isArray(raw.runs);
|
|
8748
7539
|
}
|
|
8749
|
-
function
|
|
8750
|
-
|
|
8751
|
-
|
|
8752
|
-
|
|
8753
|
-
|
|
7540
|
+
function looksLikeScorecard(raw) {
|
|
7541
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return false;
|
|
7542
|
+
return Array.isArray(raw.checks);
|
|
7543
|
+
}
|
|
7544
|
+
function countRawEntries(raw) {
|
|
7545
|
+
const obj = raw;
|
|
7546
|
+
if (Array.isArray(obj.runs)) {
|
|
7547
|
+
return obj.runs.reduce((sum, run) => {
|
|
7548
|
+
const results = run.results;
|
|
7549
|
+
return sum + (Array.isArray(results) ? results.length : 0);
|
|
7550
|
+
}, 0);
|
|
8754
7551
|
}
|
|
8755
|
-
|
|
8756
|
-
|
|
8757
|
-
|
|
8758
|
-
|
|
8759
|
-
|
|
8760
|
-
|
|
8761
|
-
if (distinct <= 2 && maxRun / body.length >= 0.8) return true;
|
|
7552
|
+
if (Array.isArray(obj.checks)) return obj.checks.length;
|
|
7553
|
+
if (Array.isArray(obj.signals)) {
|
|
7554
|
+
return obj.signals.reduce((sum, signal) => {
|
|
7555
|
+
const findings = signal.findings;
|
|
7556
|
+
return sum + (Array.isArray(findings) ? findings.length : 0);
|
|
7557
|
+
}, 0);
|
|
8762
7558
|
}
|
|
8763
|
-
return
|
|
8764
|
-
}
|
|
8765
|
-
function isSyntheticFixtureSecretValue(value) {
|
|
8766
|
-
return value.includes("abcdefghijklmnopqrstuvwxyz") || value.includes("0123456789abcdefghijklmnopqrstuvwxyz") || value.includes("abcdefghijklmnopqrstuvwxyz0123456789") || value.includes("abcdefghijklmnopqrst");
|
|
7559
|
+
return 0;
|
|
8767
7560
|
}
|
|
8768
|
-
function
|
|
8769
|
-
|
|
8770
|
-
|
|
8771
|
-
|
|
8772
|
-
|
|
8773
|
-
|
|
8774
|
-
|
|
8775
|
-
|
|
8776
|
-
const names = [...Object.keys(dependencies), ...Object.keys(devDependencies)];
|
|
8777
|
-
return names.some(
|
|
8778
|
-
(name) => /^(todo|fake|placeholder|example)-|does-not-exist| hallucinated/i.test(name)
|
|
8779
|
-
);
|
|
7561
|
+
function rawToolName(raw) {
|
|
7562
|
+
const obj = raw;
|
|
7563
|
+
if (Array.isArray(obj.runs)) {
|
|
7564
|
+
const firstRun = obj.runs[0];
|
|
7565
|
+
return firstRun?.tool?.driver?.name ?? "unknown";
|
|
7566
|
+
}
|
|
7567
|
+
if (typeof obj.tool === "string" && obj.tool.length > 0) return obj.tool;
|
|
7568
|
+
return "scorecard";
|
|
8780
7569
|
}
|
|
8781
|
-
function
|
|
7570
|
+
function parseIngestFile(filePath) {
|
|
7571
|
+
let raw;
|
|
8782
7572
|
try {
|
|
8783
|
-
|
|
8784
|
-
|
|
8785
|
-
|
|
8786
|
-
|
|
8787
|
-
}).trim();
|
|
8788
|
-
if (!output) return [];
|
|
8789
|
-
return output.split("\n").map((line) => {
|
|
8790
|
-
const [sha = "", subject = ""] = line.split("\0");
|
|
8791
|
-
return { sha, subject };
|
|
8792
|
-
}).filter((commit) => commit.sha.length >= 7);
|
|
8793
|
-
} catch {
|
|
8794
|
-
return [];
|
|
7573
|
+
raw = JSON.parse(stripBom(readFileSync5(filePath, "utf8")));
|
|
7574
|
+
} catch (error) {
|
|
7575
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7576
|
+
throw new Error(`Cejel: could not parse ingest file as JSON: ${filePath} (${message})`);
|
|
8795
7577
|
}
|
|
7578
|
+
let signals;
|
|
7579
|
+
if (looksLikeSarif(raw)) signals = parseSarifJson(raw);
|
|
7580
|
+
else if (looksLikeScorecard(raw)) signals = parseScorecardJson(raw);
|
|
7581
|
+
else if (isGenericSignalDocument(raw)) signals = parseGenericJson(raw);
|
|
7582
|
+
if (!signals) {
|
|
7583
|
+
throw new Error(
|
|
7584
|
+
`Cejel: unrecognized ingest file format: ${filePath} \u2014 expected SARIF (a "runs" array), OpenSSF Scorecard JSON (a "checks" array), or the generic Cejel external-signal shape (a "tool" string + "signals" array). See the cejel README "Aggregate your scanners".`
|
|
7585
|
+
);
|
|
7586
|
+
}
|
|
7587
|
+
const rawCount = countRawEntries(raw);
|
|
7588
|
+
const mappedCount = signals.reduce((sum, signal) => sum + signal.findings.length, 0);
|
|
7589
|
+
if (rawCount > 0 && mappedCount === 0) {
|
|
7590
|
+
process.stderr.write(
|
|
7591
|
+
`Cejel: ${rawCount} findings from ${rawToolName(raw)} (${filePath}), 0 mapped to trust criteria
|
|
7592
|
+
`
|
|
7593
|
+
);
|
|
7594
|
+
}
|
|
7595
|
+
return signals.map((signal) => ({
|
|
7596
|
+
...signal,
|
|
7597
|
+
findings: signal.findings.map(clampFinding)
|
|
7598
|
+
}));
|
|
8796
7599
|
}
|
|
8797
|
-
function
|
|
8798
|
-
if (!
|
|
8799
|
-
const
|
|
8800
|
-
const
|
|
8801
|
-
|
|
8802
|
-
|
|
8803
|
-
|
|
8804
|
-
|
|
8805
|
-
)
|
|
8806
|
-
);
|
|
8807
|
-
}
|
|
8808
|
-
function evidenceForRelative(repoPath, path, kind, label) {
|
|
8809
|
-
const fullPath = join3(repoPath, path);
|
|
8810
|
-
const contents = isRegularFile(fullPath) ? readFileSync6(fullPath, "utf8") : "";
|
|
8811
|
-
return {
|
|
8812
|
-
kind,
|
|
8813
|
-
label,
|
|
8814
|
-
path,
|
|
8815
|
-
...contents ? {
|
|
8816
|
-
line: firstMeaningfulLine(contents),
|
|
8817
|
-
contentHash: createHash("sha256").update(contents).digest("hex")
|
|
8818
|
-
} : {}
|
|
8819
|
-
};
|
|
8820
|
-
}
|
|
8821
|
-
function metric(name, label, value, max, weight, unit, description, kind) {
|
|
8822
|
-
return {
|
|
8823
|
-
name,
|
|
8824
|
-
label,
|
|
8825
|
-
value: Math.max(0, value),
|
|
8826
|
-
max,
|
|
8827
|
-
...kind ? { kind } : {},
|
|
8828
|
-
weight,
|
|
8829
|
-
unit,
|
|
8830
|
-
description
|
|
8831
|
-
};
|
|
8832
|
-
}
|
|
8833
|
-
function firstMeaningfulLine(contents) {
|
|
8834
|
-
const lines = contents.split("\n");
|
|
8835
|
-
const index = lines.findIndex((line) => line.trim().length > 0);
|
|
8836
|
-
return index === -1 ? 1 : index + 1;
|
|
8837
|
-
}
|
|
8838
|
-
function readGitHead(repoPath) {
|
|
7600
|
+
function expandIngestPattern(pattern) {
|
|
7601
|
+
if (!pattern.includes("*")) return [pattern];
|
|
7602
|
+
const lastSlash = pattern.lastIndexOf("/");
|
|
7603
|
+
const dir = lastSlash === -1 ? "." : pattern.slice(0, lastSlash);
|
|
7604
|
+
const filePattern = lastSlash === -1 ? pattern : pattern.slice(lastSlash + 1);
|
|
7605
|
+
const regexSource = filePattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*");
|
|
7606
|
+
const regex = new RegExp(`^${regexSource}$`);
|
|
7607
|
+
let entries;
|
|
8839
7608
|
try {
|
|
8840
|
-
|
|
8841
|
-
cwd: repoPath,
|
|
8842
|
-
encoding: "utf8",
|
|
8843
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
8844
|
-
}).trim();
|
|
7609
|
+
entries = readdirSync2(dir);
|
|
8845
7610
|
} catch {
|
|
8846
|
-
return
|
|
7611
|
+
return [];
|
|
8847
7612
|
}
|
|
7613
|
+
return entries.filter((name) => regex.test(name)).sort().map((name) => join2(dir, name));
|
|
8848
7614
|
}
|
|
8849
|
-
function
|
|
7615
|
+
function discoverIngestInputs(repoPath) {
|
|
7616
|
+
const inputsDir = join2(repoPath, ".cejel", "inputs");
|
|
7617
|
+
let entries;
|
|
8850
7618
|
try {
|
|
8851
|
-
|
|
8852
|
-
"git",
|
|
8853
|
-
["log", "--all", "--diff-filter=AM", "--name-only", "--format="],
|
|
8854
|
-
{
|
|
8855
|
-
cwd: repoPath,
|
|
8856
|
-
encoding: "utf8",
|
|
8857
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
8858
|
-
maxBuffer: 512e3
|
|
8859
|
-
}
|
|
8860
|
-
).trim();
|
|
8861
|
-
if (!output) return false;
|
|
8862
|
-
return output.split("\n").some((p) => /(?:^|\/)\.env(?:\.|$)/i.test(p.trim()));
|
|
7619
|
+
entries = readdirSync2(inputsDir);
|
|
8863
7620
|
} catch {
|
|
8864
|
-
return
|
|
7621
|
+
return [];
|
|
8865
7622
|
}
|
|
7623
|
+
return entries.filter((name) => /\.(sarif|json)$/i.test(name)).sort().map((name) => join2(inputsDir, name));
|
|
8866
7624
|
}
|
|
8867
7625
|
|
|
8868
|
-
//
|
|
7626
|
+
// src/witan/rubric.ts
|
|
8869
7627
|
var WITAN_RUBRIC = [
|
|
8870
7628
|
{
|
|
8871
7629
|
id: "A1",
|
|
@@ -8924,7 +7682,7 @@ var WITAN_RUBRIC = [
|
|
|
8924
7682
|
}
|
|
8925
7683
|
];
|
|
8926
7684
|
|
|
8927
|
-
//
|
|
7685
|
+
// src/witan/scoring.ts
|
|
8928
7686
|
var MAX_SIGNAL_ADJUSTMENT = 0.8;
|
|
8929
7687
|
function createWitanReport(input, inputSignals, rubric = WITAN_RUBRIC) {
|
|
8930
7688
|
const parsedInput = WitanReportInputSchema.parse(input);
|
|
@@ -9232,7 +7990,7 @@ function roundScore(score) {
|
|
|
9232
7990
|
return Math.round(score * 10) / 10;
|
|
9233
7991
|
}
|
|
9234
7992
|
|
|
9235
|
-
//
|
|
7993
|
+
// src/witan/public-scan.ts
|
|
9236
7994
|
function scoreRepoWithPublicCejel(options) {
|
|
9237
7995
|
const input = buildWitanInputFromRepo({
|
|
9238
7996
|
productSlug: options.productSlug,
|
|
@@ -9268,85 +8026,15 @@ function resolvePublicIngestSignals(options) {
|
|
|
9268
8026
|
return files.flatMap((file) => parseIngestFile(file));
|
|
9269
8027
|
}
|
|
9270
8028
|
|
|
9271
|
-
// ../witan/src/repo-clone.ts
|
|
9272
|
-
import { execFileSync as execFileSync2 } from "child_process";
|
|
9273
|
-
import { mkdirSync, rmSync } from "fs";
|
|
9274
|
-
import { tmpdir } from "os";
|
|
9275
|
-
import { join as join4 } from "path";
|
|
9276
|
-
|
|
9277
|
-
// ../witan/src/cejel-package-name.ts
|
|
9278
|
-
import { readFileSync as readFileSync7 } from "fs";
|
|
9279
|
-
import { fileURLToPath } from "url";
|
|
9280
|
-
|
|
9281
|
-
// ../witan/src/leaderboard.ts
|
|
9282
|
-
var RESERVED_CORPUS_SLUGS = ["biome", "tsconfig", "package"];
|
|
9283
|
-
var LeaderboardCorpusEntrySchema = external_exports.object({
|
|
9284
|
-
// Also the evidence-report slug (reports/<name>.{json,md,svg}) — min length 3
|
|
9285
|
-
// to satisfy the WitanReport productSlug pattern.
|
|
9286
|
-
name: external_exports.string().regex(/^[a-z0-9][a-z0-9-]{1,61}[a-z0-9]$/).refine((value) => !RESERVED_CORPUS_SLUGS.includes(value), {
|
|
9287
|
-
message: "Corpus entry name collides with a tool config filename (reports/<name>.json would be discovered by that tool) \u2014 pick a different slug, e.g. biomejs."
|
|
9288
|
-
}),
|
|
9289
|
-
category: external_exports.string().min(1).max(80),
|
|
9290
|
-
expectedArchetype: external_exports.string().min(1).max(40),
|
|
9291
|
-
license: external_exports.string().min(1).max(80),
|
|
9292
|
-
/**
|
|
9293
|
-
* Repository visibility — the redaction policy's first-class input
|
|
9294
|
-
* (goal_cejel_redaction_policy_is_verifiability_2026-07-12): a path is
|
|
9295
|
-
* published exactly when the reader can check it (public), and withheld
|
|
9296
|
-
* entirely when they can't (private). FAIL CLOSED: absent or unrecognized
|
|
9297
|
-
* resolves to 'private' via `.catch` rather than throwing or defaulting
|
|
9298
|
-
* open, so a corpus entry can never accidentally publish paths by omission.
|
|
9299
|
-
*/
|
|
9300
|
-
visibility: external_exports.enum(["public", "private"]).catch("private"),
|
|
9301
|
-
url: external_exports.string().url().optional(),
|
|
9302
|
-
/**
|
|
9303
|
-
* Immutable source snapshot for URL entries. A rubric rescore always uses
|
|
9304
|
-
* the same commits; changing one is a separate corpus update.
|
|
9305
|
-
*/
|
|
9306
|
-
commit: external_exports.string().regex(/^[0-9a-f]{40}$/).optional(),
|
|
9307
|
-
self: external_exports.literal(true).optional(),
|
|
9308
|
-
/**
|
|
9309
|
-
* A directory inside THIS repository (relative to its root), for internal
|
|
9310
|
-
* entries that are a sub-package rather than the whole repo (e.g. the public
|
|
9311
|
-
* cejel CLI at packages/witan-cli). Scored locally like "self".
|
|
9312
|
-
*/
|
|
9313
|
-
path: external_exports.string().min(1).max(200).regex(/^[A-Za-z0-9._/-]+$/).refine((value) => !value.startsWith("/") && !value.split("/").includes(".."), {
|
|
9314
|
-
message: 'Corpus entry "path" must be relative and must not traverse upward.'
|
|
9315
|
-
}).optional()
|
|
9316
|
-
}).strict().refine((entry) => (entry.url ? 1 : 0) + (entry.self ? 1 : 0) + (entry.path ? 1 : 0) === 1, {
|
|
9317
|
-
message: 'Corpus entry must have exactly one of "url", "self", or "path".'
|
|
9318
|
-
}).refine((entry) => entry.url ? entry.commit !== void 0 : entry.commit === void 0, {
|
|
9319
|
-
message: 'Every URL corpus entry must declare exactly one immutable 40-character "commit".'
|
|
9320
|
-
});
|
|
9321
|
-
var LeaderboardCorpusSchema = external_exports.object({
|
|
9322
|
-
comment: external_exports.string().min(1),
|
|
9323
|
-
entries: external_exports.array(LeaderboardCorpusEntrySchema).min(1)
|
|
9324
|
-
}).strict().refine(
|
|
9325
|
-
(corpus) => new Set(corpus.entries.map((entry) => entry.name)).size === corpus.entries.length,
|
|
9326
|
-
{ message: "Corpus entry names must be unique." }
|
|
9327
|
-
);
|
|
9328
|
-
|
|
9329
|
-
// ../witan/src/quant-integrity.ts
|
|
9330
|
-
import { readFileSync as readFileSync10 } from "fs";
|
|
9331
|
-
import { join as join8 } from "path";
|
|
9332
|
-
|
|
9333
|
-
// ../witan/src/quant-metrics-grading.ts
|
|
9334
|
-
import { createHash as createHash2 } from "crypto";
|
|
9335
|
-
import { readFileSync as readFileSync9 } from "fs";
|
|
9336
|
-
import { join as join7 } from "path";
|
|
9337
|
-
|
|
9338
|
-
// ../witan/src/quant-run-tier-grading.ts
|
|
9339
|
-
import { createHash as createHash3 } from "crypto";
|
|
9340
|
-
|
|
9341
8029
|
// src/product-identity.ts
|
|
9342
|
-
import { existsSync
|
|
9343
|
-
import { basename as
|
|
8030
|
+
import { existsSync, readFileSync as readFileSync6 } from "fs";
|
|
8031
|
+
import { basename as basename2, join as join3 } from "path";
|
|
9344
8032
|
var SLUG_PATTERN = /^[a-z0-9][a-z0-9-]{1,62}[a-z0-9]$/;
|
|
9345
8033
|
var FALLBACK_SLUG = "repo";
|
|
9346
8034
|
var FALLBACK_DISPLAY_NAME = "Repository";
|
|
9347
8035
|
function deriveProductIdentity(repoPath) {
|
|
9348
|
-
const packageJsonPath =
|
|
9349
|
-
const raw = readPackageName(packageJsonPath) ??
|
|
8036
|
+
const packageJsonPath = join3(repoPath, "package.json");
|
|
8037
|
+
const raw = readPackageName(packageJsonPath) ?? basename2(repoPath);
|
|
9350
8038
|
const displayName = raw.trim().length > 0 ? raw.trim() : FALLBACK_DISPLAY_NAME;
|
|
9351
8039
|
return {
|
|
9352
8040
|
productSlug: slugify(raw),
|
|
@@ -9354,9 +8042,9 @@ function deriveProductIdentity(repoPath) {
|
|
|
9354
8042
|
};
|
|
9355
8043
|
}
|
|
9356
8044
|
function readPackageName(packageJsonPath) {
|
|
9357
|
-
if (!
|
|
8045
|
+
if (!existsSync(packageJsonPath)) return void 0;
|
|
9358
8046
|
try {
|
|
9359
|
-
const parsed = JSON.parse(
|
|
8047
|
+
const parsed = JSON.parse(readFileSync6(packageJsonPath, "utf8"));
|
|
9360
8048
|
if (typeof parsed === "object" && parsed !== null && "name" in parsed) {
|
|
9361
8049
|
const name = parsed.name;
|
|
9362
8050
|
if (typeof name === "string" && name.trim().length > 0) return name;
|
|
@@ -9432,13 +8120,15 @@ export {
|
|
|
9432
8120
|
__commonJS,
|
|
9433
8121
|
__export,
|
|
9434
8122
|
__toESM,
|
|
9435
|
-
formatExternalSourceLine,
|
|
9436
|
-
renderWitanHtmlReport,
|
|
9437
|
-
renderWitanBadgeEndpoint,
|
|
9438
|
-
renderWitanBadgeSvg,
|
|
9439
8123
|
ZodOptional,
|
|
9440
8124
|
ZodFirstPartyTypeKind,
|
|
9441
8125
|
objectType,
|
|
9442
8126
|
external_exports,
|
|
8127
|
+
formatExternalSourceLine,
|
|
8128
|
+
renderWitanHtmlReport,
|
|
8129
|
+
renderWitanBadgeEndpoint,
|
|
8130
|
+
renderWitanBadgeSvg,
|
|
8131
|
+
serializeWitanReport,
|
|
8132
|
+
createWitanAttestation,
|
|
9443
8133
|
runCejelScan
|
|
9444
8134
|
};
|