@cyclonedx/cdxgen 12.1.4 → 12.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. package/README.md +47 -39
  2. package/bin/cdxgen.js +181 -90
  3. package/bin/evinse.js +4 -4
  4. package/bin/repl.js +3 -3
  5. package/bin/sign.js +102 -0
  6. package/bin/validate.js +233 -0
  7. package/bin/verify.js +69 -28
  8. package/data/queries.json +1 -1
  9. package/data/rules/ci-permissions.yaml +186 -0
  10. package/data/rules/dependency-sources.yaml +123 -0
  11. package/data/rules/package-integrity.yaml +135 -0
  12. package/data/rules/vscode-extensions.yaml +228 -0
  13. package/lib/cli/index.js +484 -440
  14. package/lib/evinser/db.js +137 -0
  15. package/lib/{helpers → evinser}/db.poku.js +2 -6
  16. package/lib/evinser/evinser.js +5 -18
  17. package/lib/evinser/swiftsem.js +1 -1
  18. package/lib/helpers/bomSigner.js +312 -0
  19. package/lib/helpers/bomSigner.poku.js +156 -0
  20. package/lib/helpers/caxa.js +1 -1
  21. package/lib/helpers/ciParsers/azurePipelines.js +295 -0
  22. package/lib/helpers/ciParsers/azurePipelines.poku.js +253 -0
  23. package/lib/helpers/ciParsers/circleCi.js +286 -0
  24. package/lib/helpers/ciParsers/circleCi.poku.js +230 -0
  25. package/lib/helpers/ciParsers/common.js +24 -0
  26. package/lib/helpers/ciParsers/githubActions.js +636 -0
  27. package/lib/helpers/ciParsers/githubActions.poku.js +802 -0
  28. package/lib/helpers/ciParsers/gitlabCi.js +213 -0
  29. package/lib/helpers/ciParsers/gitlabCi.poku.js +247 -0
  30. package/lib/helpers/ciParsers/jenkins.js +181 -0
  31. package/lib/helpers/ciParsers/jenkins.poku.js +197 -0
  32. package/lib/helpers/depsUtils.js +203 -0
  33. package/lib/helpers/depsUtils.poku.js +150 -0
  34. package/lib/helpers/display.js +429 -14
  35. package/lib/helpers/envcontext.js +23 -8
  36. package/lib/helpers/formulationParsers.js +351 -0
  37. package/lib/helpers/logger.js +14 -0
  38. package/lib/helpers/protobom.js +9 -9
  39. package/lib/helpers/pythonutils.js +305 -0
  40. package/lib/helpers/pythonutils.poku.js +469 -0
  41. package/lib/helpers/utils.js +970 -528
  42. package/lib/helpers/utils.poku.js +139 -256
  43. package/lib/helpers/versutils.js +202 -0
  44. package/lib/helpers/versutils.poku.js +315 -0
  45. package/lib/helpers/vsixutils.js +1061 -0
  46. package/lib/helpers/vsixutils.poku.js +2247 -0
  47. package/lib/managers/binary.js +19 -19
  48. package/lib/managers/docker.js +108 -1
  49. package/lib/managers/oci.js +10 -0
  50. package/lib/managers/piptree.js +4 -10
  51. package/lib/parsers/npmrc.js +92 -0
  52. package/lib/parsers/npmrc.poku.js +528 -0
  53. package/lib/server/openapi.yaml +1 -10
  54. package/lib/server/server.js +58 -16
  55. package/lib/server/server.poku.js +123 -144
  56. package/lib/stages/postgen/annotator.js +1 -1
  57. package/lib/stages/postgen/auditBom.js +197 -0
  58. package/lib/stages/postgen/auditBom.poku.js +378 -0
  59. package/lib/stages/postgen/postgen.js +54 -1
  60. package/lib/stages/postgen/postgen.poku.js +90 -1
  61. package/lib/stages/postgen/ruleEngine.js +369 -0
  62. package/lib/stages/pregen/envAudit.js +299 -0
  63. package/lib/stages/pregen/envAudit.poku.js +572 -0
  64. package/lib/stages/pregen/pregen.js +12 -8
  65. package/lib/third-party/arborist/lib/deepest-nesting-target.js +1 -1
  66. package/lib/third-party/arborist/lib/node.js +3 -3
  67. package/lib/third-party/arborist/lib/shrinkwrap.js +1 -1
  68. package/lib/third-party/arborist/lib/tree-check.js +1 -1
  69. package/lib/{helpers/validator.js → validator/bomValidator.js} +107 -47
  70. package/lib/validator/complianceEngine.js +241 -0
  71. package/lib/validator/complianceEngine.poku.js +168 -0
  72. package/lib/validator/complianceRules.js +1610 -0
  73. package/lib/validator/complianceRules.poku.js +328 -0
  74. package/lib/validator/index.js +222 -0
  75. package/lib/validator/index.poku.js +144 -0
  76. package/lib/validator/reporters/annotations.js +121 -0
  77. package/lib/validator/reporters/console.js +149 -0
  78. package/lib/validator/reporters/index.js +41 -0
  79. package/lib/validator/reporters/json.js +37 -0
  80. package/lib/validator/reporters/sarif.js +184 -0
  81. package/lib/validator/reporters.poku.js +150 -0
  82. package/package.json +8 -8
  83. package/types/bin/sign.d.ts +3 -0
  84. package/types/bin/sign.d.ts.map +1 -0
  85. package/types/bin/validate.d.ts +3 -0
  86. package/types/bin/validate.d.ts.map +1 -0
  87. package/types/helpers/utils.d.ts +0 -1
  88. package/types/lib/cli/index.d.ts +49 -52
  89. package/types/lib/cli/index.d.ts.map +1 -1
  90. package/types/lib/evinser/db.d.ts +34 -0
  91. package/types/lib/evinser/db.d.ts.map +1 -0
  92. package/types/lib/evinser/evinser.d.ts +63 -16
  93. package/types/lib/evinser/evinser.d.ts.map +1 -1
  94. package/types/lib/helpers/bomSigner.d.ts +27 -0
  95. package/types/lib/helpers/bomSigner.d.ts.map +1 -0
  96. package/types/lib/helpers/ciParsers/azurePipelines.d.ts +17 -0
  97. package/types/lib/helpers/ciParsers/azurePipelines.d.ts.map +1 -0
  98. package/types/lib/helpers/ciParsers/circleCi.d.ts +17 -0
  99. package/types/lib/helpers/ciParsers/circleCi.d.ts.map +1 -0
  100. package/types/lib/helpers/ciParsers/common.d.ts +11 -0
  101. package/types/lib/helpers/ciParsers/common.d.ts.map +1 -0
  102. package/types/lib/helpers/ciParsers/githubActions.d.ts +34 -0
  103. package/types/lib/helpers/ciParsers/githubActions.d.ts.map +1 -0
  104. package/types/lib/helpers/ciParsers/gitlabCi.d.ts +17 -0
  105. package/types/lib/helpers/ciParsers/gitlabCi.d.ts.map +1 -0
  106. package/types/lib/helpers/ciParsers/jenkins.d.ts +17 -0
  107. package/types/lib/helpers/ciParsers/jenkins.d.ts.map +1 -0
  108. package/types/lib/helpers/depsUtils.d.ts +21 -0
  109. package/types/lib/helpers/depsUtils.d.ts.map +1 -0
  110. package/types/lib/helpers/display.d.ts +111 -11
  111. package/types/lib/helpers/display.d.ts.map +1 -1
  112. package/types/lib/helpers/envcontext.d.ts +19 -7
  113. package/types/lib/helpers/envcontext.d.ts.map +1 -1
  114. package/types/lib/helpers/formulationParsers.d.ts +50 -0
  115. package/types/lib/helpers/formulationParsers.d.ts.map +1 -0
  116. package/types/lib/helpers/logger.d.ts +15 -1
  117. package/types/lib/helpers/logger.d.ts.map +1 -1
  118. package/types/lib/helpers/protobom.d.ts +2 -2
  119. package/types/lib/helpers/pythonutils.d.ts +18 -0
  120. package/types/lib/helpers/pythonutils.d.ts.map +1 -0
  121. package/types/lib/helpers/utils.d.ts +532 -128
  122. package/types/lib/helpers/utils.d.ts.map +1 -1
  123. package/types/lib/helpers/versutils.d.ts +8 -0
  124. package/types/lib/helpers/versutils.d.ts.map +1 -0
  125. package/types/lib/helpers/vsixutils.d.ts +130 -0
  126. package/types/lib/helpers/vsixutils.d.ts.map +1 -0
  127. package/types/lib/managers/docker.d.ts +12 -31
  128. package/types/lib/managers/docker.d.ts.map +1 -1
  129. package/types/lib/managers/oci.d.ts +11 -1
  130. package/types/lib/managers/oci.d.ts.map +1 -1
  131. package/types/lib/managers/piptree.d.ts.map +1 -1
  132. package/types/lib/parsers/npmrc.d.ts +26 -0
  133. package/types/lib/parsers/npmrc.d.ts.map +1 -0
  134. package/types/lib/server/server.d.ts +21 -2
  135. package/types/lib/server/server.d.ts.map +1 -1
  136. package/types/lib/stages/postgen/auditBom.d.ts +20 -0
  137. package/types/lib/stages/postgen/auditBom.d.ts.map +1 -0
  138. package/types/lib/stages/postgen/postgen.d.ts +8 -1
  139. package/types/lib/stages/postgen/postgen.d.ts.map +1 -1
  140. package/types/lib/stages/postgen/ruleEngine.d.ts +18 -0
  141. package/types/lib/stages/postgen/ruleEngine.d.ts.map +1 -0
  142. package/types/lib/stages/pregen/envAudit.d.ts +8 -0
  143. package/types/lib/stages/pregen/envAudit.d.ts.map +1 -0
  144. package/types/lib/stages/pregen/pregen.d.ts.map +1 -1
  145. package/types/lib/{helpers/validator.d.ts → validator/bomValidator.d.ts} +1 -1
  146. package/types/lib/validator/bomValidator.d.ts.map +1 -0
  147. package/types/lib/validator/complianceEngine.d.ts +66 -0
  148. package/types/lib/validator/complianceEngine.d.ts.map +1 -0
  149. package/types/lib/validator/complianceRules.d.ts +70 -0
  150. package/types/lib/validator/complianceRules.d.ts.map +1 -0
  151. package/types/lib/validator/index.d.ts +70 -0
  152. package/types/lib/validator/index.d.ts.map +1 -0
  153. package/types/lib/validator/reporters/annotations.d.ts +31 -0
  154. package/types/lib/validator/reporters/annotations.d.ts.map +1 -0
  155. package/types/lib/validator/reporters/console.d.ts +30 -0
  156. package/types/lib/validator/reporters/console.d.ts.map +1 -0
  157. package/types/lib/validator/reporters/index.d.ts +21 -0
  158. package/types/lib/validator/reporters/index.d.ts.map +1 -0
  159. package/types/lib/validator/reporters/json.d.ts +11 -0
  160. package/types/lib/validator/reporters/json.d.ts.map +1 -0
  161. package/types/lib/validator/reporters/sarif.d.ts +16 -0
  162. package/types/lib/validator/reporters/sarif.d.ts.map +1 -0
  163. package/lib/helpers/db.js +0 -162
  164. package/types/helpers/db.d.ts +0 -35
  165. package/types/helpers/db.d.ts.map +0 -1
  166. package/types/lib/helpers/db.d.ts +0 -35
  167. package/types/lib/helpers/db.d.ts.map +0 -1
  168. package/types/lib/helpers/validator.d.ts.map +0 -1
  169. package/types/managers/binary.d.ts +0 -37
  170. package/types/managers/binary.d.ts.map +0 -1
  171. package/types/managers/docker.d.ts +0 -56
  172. package/types/managers/docker.d.ts.map +0 -1
  173. package/types/managers/oci.d.ts +0 -2
  174. package/types/managers/oci.d.ts.map +0 -1
  175. package/types/managers/piptree.d.ts +0 -2
  176. package/types/managers/piptree.d.ts.map +0 -1
  177. package/types/server/server.d.ts +0 -34
  178. package/types/server/server.d.ts.map +0 -1
  179. package/types/stages/postgen/annotator.d.ts +0 -27
  180. package/types/stages/postgen/annotator.d.ts.map +0 -1
  181. package/types/stages/postgen/postgen.d.ts +0 -51
  182. package/types/stages/postgen/postgen.d.ts.map +0 -1
  183. package/types/stages/pregen/pregen.d.ts +0 -59
  184. package/types/stages/pregen/pregen.d.ts.map +0 -1
@@ -0,0 +1,351 @@
1
+ import process from "node:process";
2
+
3
+ import { v4 as uuidv4 } from "uuid";
4
+
5
+ import { collectOSCryptoLibs } from "./cbomutils.js";
6
+ import { azurePipelinesParser } from "./ciParsers/azurePipelines.js";
7
+ import { circleCiParser } from "./ciParsers/circleCi.js";
8
+ import { githubActionsParser } from "./ciParsers/githubActions.js";
9
+ import { gitlabCiParser } from "./ciParsers/gitlabCi.js";
10
+ import { jenkinsParser } from "./ciParsers/jenkins.js";
11
+ import { trimComponents } from "./depsUtils.js";
12
+ import {
13
+ collectEnvInfo,
14
+ getBranch,
15
+ getOriginUrl,
16
+ gitTreeHashes,
17
+ listFiles,
18
+ } from "./envcontext.js";
19
+ import { getAllFiles } from "./utils.js";
20
+
21
+ /**
22
+ * The parser registry. Pre-populated with the five built-in CI system parsers.
23
+ *
24
+ * External parsers added via {@link registerParser} are appended here.
25
+ *
26
+ * Each entry must satisfy the FormulationParser contract:
27
+ * ```
28
+ * {
29
+ * id: string, // unique stable identifier
30
+ * patterns: string[], // non-empty array of glob patterns for file discovery
31
+ * parse(files: string[], options: Object): // synchronous function
32
+ * { workflows?, components?, services?, properties?, dependencies? }
33
+ * }
34
+ * ```
35
+ */
36
+ const _parsers = [
37
+ githubActionsParser,
38
+ gitlabCiParser,
39
+ jenkinsParser,
40
+ circleCiParser,
41
+ azurePipelinesParser,
42
+ ];
43
+
44
+ /**
45
+ * Register an external formulation parser.
46
+ *
47
+ * The parser is appended to the registry and will be invoked by
48
+ * {@link addFormulationSection} on the next call.
49
+ *
50
+ * @param {{ id: string, patterns: string[], parse: Function }} parser
51
+ */
52
+ export function registerParser(parser) {
53
+ const hasValidPatterns =
54
+ Array.isArray(parser?.patterns) &&
55
+ parser.patterns.length > 0 &&
56
+ parser.patterns.every(
57
+ (pattern) => typeof pattern === "string" && pattern.trim().length > 0,
58
+ );
59
+ if (
60
+ typeof parser?.id !== "string" ||
61
+ parser.id.trim().length === 0 ||
62
+ !hasValidPatterns ||
63
+ typeof parser?.parse !== "function"
64
+ ) {
65
+ throw new TypeError(
66
+ "registerParser: parser must have id (string), patterns (non-empty string[]), and parse (function)",
67
+ );
68
+ }
69
+ _parsers.push(parser);
70
+ }
71
+
72
+ /**
73
+ * Return a shallow copy of the currently registered parsers.
74
+ *
75
+ * @returns {Array<{ id: string, patterns: string[], parse: Function }>}
76
+ */
77
+ export function getParsers() {
78
+ return [..._parsers];
79
+ }
80
+
81
+ /**
82
+ * Environment-variable prefixes whose values are safe to include in the
83
+ * formulation section. All other variables are ignored.
84
+ */
85
+ const ENV_PREFIXES = [
86
+ "GIT_",
87
+ "ANDROID_",
88
+ "DENO_",
89
+ "DOTNET_",
90
+ "JAVA_",
91
+ "SDKMAN_",
92
+ "CARGO_",
93
+ "CONDA_",
94
+ "RUST",
95
+ "GEM_",
96
+ "SCALA_",
97
+ "MAVEN_",
98
+ "GRADLE_",
99
+ ];
100
+
101
+ /**
102
+ * Sub-strings that, when found (case-insensitively) in the variable *name*
103
+ * or *value*, cause the variable to be excluded from the formulation section.
104
+ *
105
+ * This blocklist is intentionally conservative to avoid leaking secrets.
106
+ * Common CI tokens and credentials patterns are enumerated explicitly.
107
+ */
108
+ const ENV_BLOCKLIST = [
109
+ "key",
110
+ "token",
111
+ "pass",
112
+ "secret",
113
+ "user",
114
+ "email",
115
+ "auth",
116
+ "session",
117
+ "proxy",
118
+ "cred",
119
+ "askpass",
120
+ "api_key",
121
+ "apikey",
122
+ "private",
123
+ "signature",
124
+ "webhook",
125
+ ];
126
+
127
+ /**
128
+ * Build the formulation section for a CycloneDX BOM.
129
+ *
130
+ * This function is the top-level aggregator: it collects git metadata,
131
+ * invokes every registered CI parser, and merges the results into a single
132
+ * CycloneDX formulation entry.
133
+ *
134
+ * The function falls back to a minimal stub workflow when no CI config files
135
+ * are detected at the given path.
136
+ *
137
+ * @param {string} filePath File path
138
+ * @param {Object} options CLI options; `options.path` is used as the
139
+ * project root for file discovery.
140
+ * @param {Object} [context={}] Optional context object. If it contains a
141
+ * non-empty `formulationList` array those
142
+ * components are merged into the result.
143
+ *
144
+ * @returns {{ formulation: Object[], dependencies: Object[] }}
145
+ * `formulation` – array to be placed at `bomJson.formulation`
146
+ * `dependencies` – dependency objects to be merged into
147
+ * `bomJson.dependencies` via `mergeDependencies`
148
+ */
149
+ export function addFormulationSection(filePath, options, context = {}) {
150
+ const projectPath = filePath;
151
+ const formulation = [];
152
+ const dependencies = [];
153
+
154
+ // ── Git metadata ─────────────────────────────────────────────────────────
155
+ const gitBranch = getBranch(undefined, projectPath);
156
+ const originUrl = getOriginUrl(projectPath);
157
+ const gitFiles = listFiles(projectPath);
158
+ const treeHashes = gitTreeHashes(projectPath);
159
+
160
+ let components = [];
161
+
162
+ // Reuse any existing formulation components (e.g. from Pixi lock data)
163
+ // See: PR #1172
164
+ if (context?.formulationList?.length) {
165
+ components = components.concat(trimComponents(context.formulationList));
166
+ }
167
+
168
+ // OmniBOR / Artifact Dependency Graph components (spec 1.6+)
169
+ let parentOmniborId;
170
+ let treeOmniborId;
171
+ if (options.specVersion >= 1.6 && Object.keys(treeHashes).length === 2) {
172
+ // treeHashes.parent is the parent commit SHA → gitoid:commit:sha1:
173
+ // treeHashes.tree is the git tree object SHA → gitoid:tree:sha1:
174
+ parentOmniborId = `gitoid:commit:sha1:${treeHashes.parent}`;
175
+ treeOmniborId = `gitoid:tree:sha1:${treeHashes.tree}`;
176
+ components.push({
177
+ type: "file",
178
+ name: "git-parent",
179
+ description: "Git Parent Node.",
180
+ "bom-ref": parentOmniborId,
181
+ omniborId: [parentOmniborId],
182
+ swhid: [`swh:1:rev:${treeHashes.parent}`],
183
+ });
184
+ components.push({
185
+ type: "file",
186
+ name: "git-tree",
187
+ description: "Git Tree Node.",
188
+ "bom-ref": treeOmniborId,
189
+ omniborId: [treeOmniborId],
190
+ swhid: [`swh:1:dir:${treeHashes.tree}`],
191
+ });
192
+ // OmniBOR linkage goes into the top-level dependencies array
193
+ dependencies.push({ ref: parentOmniborId, provides: [treeOmniborId] });
194
+ }
195
+
196
+ // Git file list
197
+ if (gitBranch && gitFiles?.length) {
198
+ const gitFileComponents = gitFiles.map((f) =>
199
+ options.specVersion >= 1.6
200
+ ? {
201
+ type: "file",
202
+ name: f.name,
203
+ version: f.hash,
204
+ "bom-ref": f.omniborId,
205
+ omniborId: [f.omniborId],
206
+ swhid: [f.swhid],
207
+ }
208
+ : {
209
+ type: "file",
210
+ name: f.name,
211
+ version: f.hash,
212
+ },
213
+ );
214
+ components = components.concat(gitFileComponents);
215
+
216
+ // Complete the Artifact Dependency Graph: tree → blob links
217
+ if (options.specVersion >= 1.6 && treeOmniborId) {
218
+ dependencies.push({
219
+ ref: treeOmniborId,
220
+ provides: gitFiles.map((f) => f.omniborId).filter(Boolean),
221
+ });
222
+ }
223
+ }
224
+
225
+ // Build environment details (Java, .NET, Python, Node, GCC, Rust, Go, Ruby)
226
+ const infoComponents = collectEnvInfo(projectPath);
227
+ if (infoComponents?.length) {
228
+ components = components.concat(infoComponents);
229
+ }
230
+
231
+ // OS crypto libraries (cbom mode)
232
+ if (options.includeCrypto) {
233
+ const cryptoLibs = collectOSCryptoLibs(options);
234
+ if (cryptoLibs?.length) {
235
+ components = components.concat(cryptoLibs);
236
+ }
237
+ }
238
+
239
+ // ── CI parser dispatch ────────────────────────────────────────────────────
240
+ const ciWorkflows = [];
241
+ const ciComponents = [];
242
+ const ciServices = [];
243
+ const ciProperties = [];
244
+
245
+ const discoveryPath = projectPath || ".";
246
+
247
+ for (const parser of _parsers) {
248
+ const matchedFiles = [];
249
+ for (const pattern of parser.patterns) {
250
+ const found = getAllFiles(discoveryPath, pattern, options);
251
+ if (found?.length) {
252
+ matchedFiles.push(...found);
253
+ }
254
+ }
255
+ const uniqueMatchedFiles = [...new Set(matchedFiles)];
256
+ if (!uniqueMatchedFiles.length) {
257
+ continue;
258
+ }
259
+
260
+ let result;
261
+ try {
262
+ result = parser.parse(uniqueMatchedFiles, options);
263
+ } catch (err) {
264
+ // A broken parser must not kill SBOM generation
265
+ console.warn(
266
+ `[formulationParsers] Parser "${parser.id}" threw an error:`,
267
+ err.message,
268
+ );
269
+ continue;
270
+ }
271
+
272
+ if (result?.workflows?.length) {
273
+ ciWorkflows.push(...result.workflows);
274
+ }
275
+ if (result?.components?.length) {
276
+ ciComponents.push(...result.components);
277
+ }
278
+ if (result?.services?.length) {
279
+ ciServices.push(...result.services);
280
+ }
281
+ if (result?.properties?.length) {
282
+ ciProperties.push(...result.properties);
283
+ }
284
+ if (result?.dependencies?.length) {
285
+ dependencies.push(...result.dependencies);
286
+ }
287
+ }
288
+
289
+ // Merge CI components into the formulation component list
290
+ if (ciComponents.length) {
291
+ components = components.concat(ciComponents);
292
+ }
293
+
294
+ // ── Environment variables ─────────────────────────────────────────────────
295
+ let environmentVars = gitBranch?.length
296
+ ? [{ name: "GIT_BRANCH", value: gitBranch }]
297
+ : [];
298
+
299
+ for (const aevar of Object.keys(process.env)) {
300
+ const lower = aevar.toLowerCase();
301
+ const value = process.env[aevar] ?? "";
302
+ if (
303
+ ENV_PREFIXES.some((p) => aevar.startsWith(p)) &&
304
+ !ENV_BLOCKLIST.some((b) => lower.includes(b)) &&
305
+ !ENV_BLOCKLIST.some((b) => value.toLowerCase().includes(b)) &&
306
+ value.length
307
+ ) {
308
+ environmentVars.push({ name: aevar, value });
309
+ }
310
+ }
311
+
312
+ if (!environmentVars.length) {
313
+ environmentVars = undefined;
314
+ }
315
+
316
+ // ── Assemble formulation object ───────────────────────────────────────────
317
+ const aformulation = {
318
+ "bom-ref": uuidv4(),
319
+ components: trimComponents(components),
320
+ };
321
+
322
+ if (ciServices.length) {
323
+ aformulation.services = ciServices;
324
+ }
325
+
326
+ if (ciProperties.length) {
327
+ aformulation.properties = ciProperties;
328
+ }
329
+
330
+ // Use CI-detected workflows; fall back to a minimal stub when none found
331
+ if (ciWorkflows.length) {
332
+ aformulation.workflows = ciWorkflows;
333
+ } else {
334
+ let sourceInput;
335
+ if (environmentVars) {
336
+ sourceInput = { environmentVars };
337
+ }
338
+ const sourceWorkflow = {
339
+ "bom-ref": uuidv4(),
340
+ uid: uuidv4(),
341
+ taskTypes: originUrl ? ["build", "clone"] : ["build"],
342
+ };
343
+ if (sourceInput) {
344
+ sourceWorkflow.inputs = [sourceInput];
345
+ }
346
+ aformulation.workflows = [sourceWorkflow];
347
+ }
348
+
349
+ formulation.push(aformulation);
350
+ return { formulation, dependencies };
351
+ }
@@ -44,6 +44,14 @@ const traceLogger = new Console({
44
44
  if (THINK_MODE) {
45
45
  thinkLogger.group(colorizeText("<think>"));
46
46
  }
47
+ /**
48
+ * Logs a thought message to the think logger if THINK_MODE is enabled.
49
+ * Automatically appends a period to the message if it lacks terminal punctuation.
50
+ *
51
+ * @param {string} s The thought message to log
52
+ * @param {Object} [args] Optional additional arguments to log alongside the message
53
+ * @returns {void}
54
+ */
47
55
  export function thoughtLog(s, args) {
48
56
  if (!THINK_MODE) {
49
57
  return;
@@ -58,6 +66,12 @@ export function thoughtLog(s, args) {
58
66
  thinkLogger.log(colorizeText(`${s}`));
59
67
  }
60
68
  }
69
+ /**
70
+ * Closes the think log group by emitting the closing `</think>` marker.
71
+ * Has no effect if THINK_MODE is not enabled.
72
+ *
73
+ * @returns {void}
74
+ */
61
75
  export function thoughtEnd() {
62
76
  if (THINK_MODE) {
63
77
  thinkLogger.groupEnd();
@@ -1,6 +1,6 @@
1
1
  import { readFileSync, writeFileSync } from "node:fs";
2
2
 
3
- import { cdx_15, cdx_16 } from "@appthreat/cdx-proto";
3
+ import { cdx_16, cdx_17 } from "@appthreat/cdx-proto";
4
4
  import {
5
5
  fromBinary,
6
6
  fromJsonString,
@@ -32,10 +32,10 @@ const stringifyIfNeeded = (bomJson) => {
32
32
  export const writeBinary = (bomJson, binFile) => {
33
33
  if (bomJson && binFile) {
34
34
  let bomSchema;
35
- if (+bomJson.specVersion === 1.6) {
36
- bomSchema = cdx_16.BomSchema;
35
+ if (+bomJson.specVersion === 1.7) {
36
+ bomSchema = cdx_17.BomSchema;
37
37
  } else {
38
- bomSchema = cdx_15.BomSchema;
38
+ bomSchema = cdx_16.BomSchema;
39
39
  }
40
40
  writeFileSync(
41
41
  binFile,
@@ -57,17 +57,17 @@ export const writeBinary = (bomJson, binFile) => {
57
57
  *
58
58
  * @param {string} binFile Binary file name
59
59
  * @param {boolean} asJson Convert to JSON
60
- * @param {number} specVersion Specification version. Defaults to 1.6
60
+ * @param {number} specVersion Specification version. Defaults to 1.7
61
61
  */
62
- export const readBinary = (binFile, asJson = true, specVersion = 1.6) => {
62
+ export const readBinary = (binFile, asJson = true, specVersion = 1.7) => {
63
63
  if (!safeExistsSync(binFile)) {
64
64
  return undefined;
65
65
  }
66
66
  let bomSchema;
67
- if (specVersion === 1.6) {
68
- bomSchema = cdx_16.BomSchema;
67
+ if (specVersion === 1.7) {
68
+ bomSchema = cdx_17.BomSchema;
69
69
  } else {
70
- bomSchema = cdx_15.BomSchema;
70
+ bomSchema = cdx_16.BomSchema;
71
71
  }
72
72
  const bomObject = fromBinary(bomSchema, readFileSync(binFile), {
73
73
  readUnknownFields: true,