lula2 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_app/immutable/assets/0.Dv98laBw.css +1 -0
- package/dist/_app/immutable/chunks/ByYV7ZA-.js +3 -0
- package/dist/_app/immutable/chunks/{FrGcBm1x.js → ByvTzPiZ.js} +1 -1
- package/dist/_app/immutable/chunks/{B1zoZ4R1.js → Dz1EplPN.js} +1 -1
- package/dist/_app/immutable/entry/{app.CcHyV-rk.js → app.fwEu_ZMM.js} +2 -2
- package/dist/_app/immutable/entry/start.8aoHS084.js +1 -0
- package/dist/_app/immutable/nodes/{0.7Mlh1gzf.js → 0.DNuR4AgZ.js} +1 -1
- package/dist/_app/immutable/nodes/{1.D0l0sji4.js → 1.55kAQB_N.js} +1 -1
- package/dist/_app/immutable/nodes/{2.caO8ptPP.js → 2.CIjVJr71.js} +1 -1
- package/dist/_app/immutable/nodes/{3.AKSpRWBb.js → 3.DGF3hckf.js} +1 -1
- package/dist/_app/immutable/nodes/4.BHxnD-Qp.js +12 -0
- package/dist/_app/version.json +1 -1
- package/dist/cli/commands/crawl.js +3 -1
- package/dist/cli/commands/ui.js +37 -2
- package/dist/cli/server/index.js +37 -2
- package/dist/cli/server/server.js +37 -2
- package/dist/cli/server/spreadsheetRoutes.js +35 -0
- package/dist/cli/server/websocketServer.js +37 -2
- package/dist/index.html +6 -6
- package/dist/index.js +40 -3
- package/package.json +1 -1
- package/src/lib/components/setup/SpreadsheetImport.svelte +105 -2
- package/dist/_app/immutable/assets/0.BjwH76RW.css +0 -1
- package/dist/_app/immutable/chunks/RAfQ0xU4.js +0 -3
- package/dist/_app/immutable/entry/start.DuJH3lYs.js +0 -1
- package/dist/_app/immutable/nodes/4.Cxgvwfsg.js +0 -9
package/dist/cli/commands/ui.js
CHANGED
|
@@ -2828,6 +2828,7 @@ __export(spreadsheetRoutes_exports, {
|
|
|
2828
2828
|
default: () => spreadsheetRoutes_default,
|
|
2829
2829
|
scanControlSets: () => scanControlSets
|
|
2830
2830
|
});
|
|
2831
|
+
import crypto from "crypto";
|
|
2831
2832
|
import { parse as parseCSVSync } from "csv-parse/sync";
|
|
2832
2833
|
import ExcelJS from "exceljs";
|
|
2833
2834
|
import express from "express";
|
|
@@ -3146,6 +3147,15 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3146
3147
|
controlSetName = "Imported Control Set",
|
|
3147
3148
|
controlSetDescription = "Imported from spreadsheet"
|
|
3148
3149
|
} = req.body;
|
|
3150
|
+
let justificationFields = [];
|
|
3151
|
+
if (req.body.justificationFields) {
|
|
3152
|
+
try {
|
|
3153
|
+
justificationFields = JSON.parse(req.body.justificationFields);
|
|
3154
|
+
debug("Justification fields received:", justificationFields);
|
|
3155
|
+
} catch (e) {
|
|
3156
|
+
console.error("Failed to parse justification fields:", e);
|
|
3157
|
+
}
|
|
3158
|
+
}
|
|
3149
3159
|
debug("Import parameters received:", {
|
|
3150
3160
|
controlIdField,
|
|
3151
3161
|
startRow,
|
|
@@ -3393,11 +3403,17 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3393
3403
|
};
|
|
3394
3404
|
writeFileSync2(join4(baseDir, "lula.yaml"), yaml4.dump(controlSetData));
|
|
3395
3405
|
const controlsDir = join4(baseDir, "controls");
|
|
3406
|
+
const mappingsDir = join4(baseDir, "mappings");
|
|
3407
|
+
const justificationFieldNames = justificationFields;
|
|
3396
3408
|
families.forEach((familyControls, family) => {
|
|
3397
3409
|
const familyDir = join4(controlsDir, family);
|
|
3410
|
+
const familyMappingsDir = join4(mappingsDir, family);
|
|
3398
3411
|
if (!existsSync3(familyDir)) {
|
|
3399
3412
|
mkdirSync2(familyDir, { recursive: true });
|
|
3400
3413
|
}
|
|
3414
|
+
if (!existsSync3(familyMappingsDir)) {
|
|
3415
|
+
mkdirSync2(familyMappingsDir, { recursive: true });
|
|
3416
|
+
}
|
|
3401
3417
|
familyControls.forEach((control) => {
|
|
3402
3418
|
const controlId = control[controlIdFieldNameClean];
|
|
3403
3419
|
if (!controlId) {
|
|
@@ -3407,12 +3423,24 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3407
3423
|
const controlIdStr = String(controlId).slice(0, 50);
|
|
3408
3424
|
const fileName2 = `${controlIdStr.replace(/[^a-zA-Z0-9-]/g, "_")}.yaml`;
|
|
3409
3425
|
const filePath = join4(familyDir, fileName2);
|
|
3426
|
+
const mappingFileName = `${controlIdStr.replace(/[^a-zA-Z0-9-]/g, "_")}-mappings.yaml`;
|
|
3427
|
+
const mappingFilePath = join4(familyMappingsDir, mappingFileName);
|
|
3410
3428
|
const filteredControl = {};
|
|
3429
|
+
const mappingData = {
|
|
3430
|
+
control_id: controlIdStr,
|
|
3431
|
+
justification: "",
|
|
3432
|
+
uuid: crypto.randomUUID()
|
|
3433
|
+
};
|
|
3434
|
+
const justificationContents = [];
|
|
3411
3435
|
if (control.family !== void 0) {
|
|
3412
3436
|
filteredControl.family = control.family;
|
|
3413
3437
|
}
|
|
3414
3438
|
Object.keys(control).forEach((fieldName) => {
|
|
3415
3439
|
if (fieldName === "family") return;
|
|
3440
|
+
if (justificationFields.includes(fieldName) && control[fieldName] !== void 0 && control[fieldName] !== null) {
|
|
3441
|
+
justificationContents.push(control[fieldName]);
|
|
3442
|
+
return;
|
|
3443
|
+
}
|
|
3416
3444
|
const isInFrontendSchema = frontendFieldSchema?.some((f) => f.fieldName === fieldName);
|
|
3417
3445
|
const isInFieldsMetadata = fields.hasOwnProperty(fieldName);
|
|
3418
3446
|
if (isInFrontendSchema || isInFieldsMetadata) {
|
|
@@ -3420,6 +3448,13 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3420
3448
|
}
|
|
3421
3449
|
});
|
|
3422
3450
|
writeFileSync2(filePath, yaml4.dump(filteredControl));
|
|
3451
|
+
if (justificationContents.length > 0) {
|
|
3452
|
+
mappingData.justification = justificationContents.join("\n\n");
|
|
3453
|
+
}
|
|
3454
|
+
if (mappingData.justification && mappingData.justification.trim() !== "") {
|
|
3455
|
+
const mappingArray = [mappingData];
|
|
3456
|
+
writeFileSync2(mappingFilePath, yaml4.dump(mappingArray));
|
|
3457
|
+
}
|
|
3423
3458
|
});
|
|
3424
3459
|
});
|
|
3425
3460
|
res.json({
|
|
@@ -4533,8 +4568,8 @@ var WebSocketManager = class {
|
|
|
4533
4568
|
if (payload && payload.control_id) {
|
|
4534
4569
|
const mapping = payload;
|
|
4535
4570
|
if (!mapping.uuid) {
|
|
4536
|
-
const
|
|
4537
|
-
mapping.uuid =
|
|
4571
|
+
const crypto2 = await import("crypto");
|
|
4572
|
+
mapping.uuid = crypto2.randomUUID();
|
|
4538
4573
|
}
|
|
4539
4574
|
await state.fileStore.saveMapping(mapping);
|
|
4540
4575
|
state.mappingsCache.set(mapping.uuid, mapping);
|
package/dist/cli/server/index.js
CHANGED
|
@@ -2810,6 +2810,7 @@ __export(spreadsheetRoutes_exports, {
|
|
|
2810
2810
|
default: () => spreadsheetRoutes_default,
|
|
2811
2811
|
scanControlSets: () => scanControlSets
|
|
2812
2812
|
});
|
|
2813
|
+
import crypto from "crypto";
|
|
2813
2814
|
import { parse as parseCSVSync } from "csv-parse/sync";
|
|
2814
2815
|
import ExcelJS from "exceljs";
|
|
2815
2816
|
import express from "express";
|
|
@@ -3128,6 +3129,15 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3128
3129
|
controlSetName = "Imported Control Set",
|
|
3129
3130
|
controlSetDescription = "Imported from spreadsheet"
|
|
3130
3131
|
} = req.body;
|
|
3132
|
+
let justificationFields = [];
|
|
3133
|
+
if (req.body.justificationFields) {
|
|
3134
|
+
try {
|
|
3135
|
+
justificationFields = JSON.parse(req.body.justificationFields);
|
|
3136
|
+
debug("Justification fields received:", justificationFields);
|
|
3137
|
+
} catch (e) {
|
|
3138
|
+
console.error("Failed to parse justification fields:", e);
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3131
3141
|
debug("Import parameters received:", {
|
|
3132
3142
|
controlIdField,
|
|
3133
3143
|
startRow,
|
|
@@ -3375,11 +3385,17 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3375
3385
|
};
|
|
3376
3386
|
writeFileSync2(join4(baseDir, "lula.yaml"), yaml4.dump(controlSetData));
|
|
3377
3387
|
const controlsDir = join4(baseDir, "controls");
|
|
3388
|
+
const mappingsDir = join4(baseDir, "mappings");
|
|
3389
|
+
const justificationFieldNames = justificationFields;
|
|
3378
3390
|
families.forEach((familyControls, family) => {
|
|
3379
3391
|
const familyDir = join4(controlsDir, family);
|
|
3392
|
+
const familyMappingsDir = join4(mappingsDir, family);
|
|
3380
3393
|
if (!existsSync3(familyDir)) {
|
|
3381
3394
|
mkdirSync2(familyDir, { recursive: true });
|
|
3382
3395
|
}
|
|
3396
|
+
if (!existsSync3(familyMappingsDir)) {
|
|
3397
|
+
mkdirSync2(familyMappingsDir, { recursive: true });
|
|
3398
|
+
}
|
|
3383
3399
|
familyControls.forEach((control) => {
|
|
3384
3400
|
const controlId = control[controlIdFieldNameClean];
|
|
3385
3401
|
if (!controlId) {
|
|
@@ -3389,12 +3405,24 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3389
3405
|
const controlIdStr = String(controlId).slice(0, 50);
|
|
3390
3406
|
const fileName2 = `${controlIdStr.replace(/[^a-zA-Z0-9-]/g, "_")}.yaml`;
|
|
3391
3407
|
const filePath = join4(familyDir, fileName2);
|
|
3408
|
+
const mappingFileName = `${controlIdStr.replace(/[^a-zA-Z0-9-]/g, "_")}-mappings.yaml`;
|
|
3409
|
+
const mappingFilePath = join4(familyMappingsDir, mappingFileName);
|
|
3392
3410
|
const filteredControl = {};
|
|
3411
|
+
const mappingData = {
|
|
3412
|
+
control_id: controlIdStr,
|
|
3413
|
+
justification: "",
|
|
3414
|
+
uuid: crypto.randomUUID()
|
|
3415
|
+
};
|
|
3416
|
+
const justificationContents = [];
|
|
3393
3417
|
if (control.family !== void 0) {
|
|
3394
3418
|
filteredControl.family = control.family;
|
|
3395
3419
|
}
|
|
3396
3420
|
Object.keys(control).forEach((fieldName) => {
|
|
3397
3421
|
if (fieldName === "family") return;
|
|
3422
|
+
if (justificationFields.includes(fieldName) && control[fieldName] !== void 0 && control[fieldName] !== null) {
|
|
3423
|
+
justificationContents.push(control[fieldName]);
|
|
3424
|
+
return;
|
|
3425
|
+
}
|
|
3398
3426
|
const isInFrontendSchema = frontendFieldSchema?.some((f) => f.fieldName === fieldName);
|
|
3399
3427
|
const isInFieldsMetadata = fields.hasOwnProperty(fieldName);
|
|
3400
3428
|
if (isInFrontendSchema || isInFieldsMetadata) {
|
|
@@ -3402,6 +3430,13 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3402
3430
|
}
|
|
3403
3431
|
});
|
|
3404
3432
|
writeFileSync2(filePath, yaml4.dump(filteredControl));
|
|
3433
|
+
if (justificationContents.length > 0) {
|
|
3434
|
+
mappingData.justification = justificationContents.join("\n\n");
|
|
3435
|
+
}
|
|
3436
|
+
if (mappingData.justification && mappingData.justification.trim() !== "") {
|
|
3437
|
+
const mappingArray = [mappingData];
|
|
3438
|
+
writeFileSync2(mappingFilePath, yaml4.dump(mappingArray));
|
|
3439
|
+
}
|
|
3405
3440
|
});
|
|
3406
3441
|
});
|
|
3407
3442
|
res.json({
|
|
@@ -4510,8 +4545,8 @@ var WebSocketManager = class {
|
|
|
4510
4545
|
if (payload && payload.control_id) {
|
|
4511
4546
|
const mapping = payload;
|
|
4512
4547
|
if (!mapping.uuid) {
|
|
4513
|
-
const
|
|
4514
|
-
mapping.uuid =
|
|
4548
|
+
const crypto2 = await import("crypto");
|
|
4549
|
+
mapping.uuid = crypto2.randomUUID();
|
|
4515
4550
|
}
|
|
4516
4551
|
await state.fileStore.saveMapping(mapping);
|
|
4517
4552
|
state.mappingsCache.set(mapping.uuid, mapping);
|
|
@@ -2810,6 +2810,7 @@ __export(spreadsheetRoutes_exports, {
|
|
|
2810
2810
|
default: () => spreadsheetRoutes_default,
|
|
2811
2811
|
scanControlSets: () => scanControlSets
|
|
2812
2812
|
});
|
|
2813
|
+
import crypto from "crypto";
|
|
2813
2814
|
import { parse as parseCSVSync } from "csv-parse/sync";
|
|
2814
2815
|
import ExcelJS from "exceljs";
|
|
2815
2816
|
import express from "express";
|
|
@@ -3128,6 +3129,15 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3128
3129
|
controlSetName = "Imported Control Set",
|
|
3129
3130
|
controlSetDescription = "Imported from spreadsheet"
|
|
3130
3131
|
} = req.body;
|
|
3132
|
+
let justificationFields = [];
|
|
3133
|
+
if (req.body.justificationFields) {
|
|
3134
|
+
try {
|
|
3135
|
+
justificationFields = JSON.parse(req.body.justificationFields);
|
|
3136
|
+
debug("Justification fields received:", justificationFields);
|
|
3137
|
+
} catch (e) {
|
|
3138
|
+
console.error("Failed to parse justification fields:", e);
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3131
3141
|
debug("Import parameters received:", {
|
|
3132
3142
|
controlIdField,
|
|
3133
3143
|
startRow,
|
|
@@ -3375,11 +3385,17 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3375
3385
|
};
|
|
3376
3386
|
writeFileSync2(join4(baseDir, "lula.yaml"), yaml4.dump(controlSetData));
|
|
3377
3387
|
const controlsDir = join4(baseDir, "controls");
|
|
3388
|
+
const mappingsDir = join4(baseDir, "mappings");
|
|
3389
|
+
const justificationFieldNames = justificationFields;
|
|
3378
3390
|
families.forEach((familyControls, family) => {
|
|
3379
3391
|
const familyDir = join4(controlsDir, family);
|
|
3392
|
+
const familyMappingsDir = join4(mappingsDir, family);
|
|
3380
3393
|
if (!existsSync3(familyDir)) {
|
|
3381
3394
|
mkdirSync2(familyDir, { recursive: true });
|
|
3382
3395
|
}
|
|
3396
|
+
if (!existsSync3(familyMappingsDir)) {
|
|
3397
|
+
mkdirSync2(familyMappingsDir, { recursive: true });
|
|
3398
|
+
}
|
|
3383
3399
|
familyControls.forEach((control) => {
|
|
3384
3400
|
const controlId = control[controlIdFieldNameClean];
|
|
3385
3401
|
if (!controlId) {
|
|
@@ -3389,12 +3405,24 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3389
3405
|
const controlIdStr = String(controlId).slice(0, 50);
|
|
3390
3406
|
const fileName2 = `${controlIdStr.replace(/[^a-zA-Z0-9-]/g, "_")}.yaml`;
|
|
3391
3407
|
const filePath = join4(familyDir, fileName2);
|
|
3408
|
+
const mappingFileName = `${controlIdStr.replace(/[^a-zA-Z0-9-]/g, "_")}-mappings.yaml`;
|
|
3409
|
+
const mappingFilePath = join4(familyMappingsDir, mappingFileName);
|
|
3392
3410
|
const filteredControl = {};
|
|
3411
|
+
const mappingData = {
|
|
3412
|
+
control_id: controlIdStr,
|
|
3413
|
+
justification: "",
|
|
3414
|
+
uuid: crypto.randomUUID()
|
|
3415
|
+
};
|
|
3416
|
+
const justificationContents = [];
|
|
3393
3417
|
if (control.family !== void 0) {
|
|
3394
3418
|
filteredControl.family = control.family;
|
|
3395
3419
|
}
|
|
3396
3420
|
Object.keys(control).forEach((fieldName) => {
|
|
3397
3421
|
if (fieldName === "family") return;
|
|
3422
|
+
if (justificationFields.includes(fieldName) && control[fieldName] !== void 0 && control[fieldName] !== null) {
|
|
3423
|
+
justificationContents.push(control[fieldName]);
|
|
3424
|
+
return;
|
|
3425
|
+
}
|
|
3398
3426
|
const isInFrontendSchema = frontendFieldSchema?.some((f) => f.fieldName === fieldName);
|
|
3399
3427
|
const isInFieldsMetadata = fields.hasOwnProperty(fieldName);
|
|
3400
3428
|
if (isInFrontendSchema || isInFieldsMetadata) {
|
|
@@ -3402,6 +3430,13 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3402
3430
|
}
|
|
3403
3431
|
});
|
|
3404
3432
|
writeFileSync2(filePath, yaml4.dump(filteredControl));
|
|
3433
|
+
if (justificationContents.length > 0) {
|
|
3434
|
+
mappingData.justification = justificationContents.join("\n\n");
|
|
3435
|
+
}
|
|
3436
|
+
if (mappingData.justification && mappingData.justification.trim() !== "") {
|
|
3437
|
+
const mappingArray = [mappingData];
|
|
3438
|
+
writeFileSync2(mappingFilePath, yaml4.dump(mappingArray));
|
|
3439
|
+
}
|
|
3405
3440
|
});
|
|
3406
3441
|
});
|
|
3407
3442
|
res.json({
|
|
@@ -4510,8 +4545,8 @@ var WebSocketManager = class {
|
|
|
4510
4545
|
if (payload && payload.control_id) {
|
|
4511
4546
|
const mapping = payload;
|
|
4512
4547
|
if (!mapping.uuid) {
|
|
4513
|
-
const
|
|
4514
|
-
mapping.uuid =
|
|
4548
|
+
const crypto2 = await import("crypto");
|
|
4549
|
+
mapping.uuid = crypto2.randomUUID();
|
|
4515
4550
|
}
|
|
4516
4551
|
await state.fileStore.saveMapping(mapping);
|
|
4517
4552
|
state.mappingsCache.set(mapping.uuid, mapping);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// cli/server/spreadsheetRoutes.ts
|
|
2
|
+
import crypto from "crypto";
|
|
2
3
|
import { parse as parseCSVSync } from "csv-parse/sync";
|
|
3
4
|
import ExcelJS from "exceljs";
|
|
4
5
|
import express from "express";
|
|
@@ -93,6 +94,15 @@ router.post("/import-spreadsheet", upload.single("file"), async (req, res) => {
|
|
|
93
94
|
controlSetName = "Imported Control Set",
|
|
94
95
|
controlSetDescription = "Imported from spreadsheet"
|
|
95
96
|
} = req.body;
|
|
97
|
+
let justificationFields = [];
|
|
98
|
+
if (req.body.justificationFields) {
|
|
99
|
+
try {
|
|
100
|
+
justificationFields = JSON.parse(req.body.justificationFields);
|
|
101
|
+
debug("Justification fields received:", justificationFields);
|
|
102
|
+
} catch (e) {
|
|
103
|
+
console.error("Failed to parse justification fields:", e);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
96
106
|
debug("Import parameters received:", {
|
|
97
107
|
controlIdField,
|
|
98
108
|
startRow,
|
|
@@ -340,11 +350,17 @@ router.post("/import-spreadsheet", upload.single("file"), async (req, res) => {
|
|
|
340
350
|
};
|
|
341
351
|
writeFileSync(join(baseDir, "lula.yaml"), yaml4.dump(controlSetData));
|
|
342
352
|
const controlsDir = join(baseDir, "controls");
|
|
353
|
+
const mappingsDir = join(baseDir, "mappings");
|
|
354
|
+
const justificationFieldNames = justificationFields;
|
|
343
355
|
families.forEach((familyControls, family) => {
|
|
344
356
|
const familyDir = join(controlsDir, family);
|
|
357
|
+
const familyMappingsDir = join(mappingsDir, family);
|
|
345
358
|
if (!existsSync(familyDir)) {
|
|
346
359
|
mkdirSync(familyDir, { recursive: true });
|
|
347
360
|
}
|
|
361
|
+
if (!existsSync(familyMappingsDir)) {
|
|
362
|
+
mkdirSync(familyMappingsDir, { recursive: true });
|
|
363
|
+
}
|
|
348
364
|
familyControls.forEach((control) => {
|
|
349
365
|
const controlId = control[controlIdFieldNameClean];
|
|
350
366
|
if (!controlId) {
|
|
@@ -354,12 +370,24 @@ router.post("/import-spreadsheet", upload.single("file"), async (req, res) => {
|
|
|
354
370
|
const controlIdStr = String(controlId).slice(0, 50);
|
|
355
371
|
const fileName2 = `${controlIdStr.replace(/[^a-zA-Z0-9-]/g, "_")}.yaml`;
|
|
356
372
|
const filePath = join(familyDir, fileName2);
|
|
373
|
+
const mappingFileName = `${controlIdStr.replace(/[^a-zA-Z0-9-]/g, "_")}-mappings.yaml`;
|
|
374
|
+
const mappingFilePath = join(familyMappingsDir, mappingFileName);
|
|
357
375
|
const filteredControl = {};
|
|
376
|
+
const mappingData = {
|
|
377
|
+
control_id: controlIdStr,
|
|
378
|
+
justification: "",
|
|
379
|
+
uuid: crypto.randomUUID()
|
|
380
|
+
};
|
|
381
|
+
const justificationContents = [];
|
|
358
382
|
if (control.family !== void 0) {
|
|
359
383
|
filteredControl.family = control.family;
|
|
360
384
|
}
|
|
361
385
|
Object.keys(control).forEach((fieldName) => {
|
|
362
386
|
if (fieldName === "family") return;
|
|
387
|
+
if (justificationFields.includes(fieldName) && control[fieldName] !== void 0 && control[fieldName] !== null) {
|
|
388
|
+
justificationContents.push(control[fieldName]);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
363
391
|
const isInFrontendSchema = frontendFieldSchema?.some((f) => f.fieldName === fieldName);
|
|
364
392
|
const isInFieldsMetadata = fields.hasOwnProperty(fieldName);
|
|
365
393
|
if (isInFrontendSchema || isInFieldsMetadata) {
|
|
@@ -367,6 +395,13 @@ router.post("/import-spreadsheet", upload.single("file"), async (req, res) => {
|
|
|
367
395
|
}
|
|
368
396
|
});
|
|
369
397
|
writeFileSync(filePath, yaml4.dump(filteredControl));
|
|
398
|
+
if (justificationContents.length > 0) {
|
|
399
|
+
mappingData.justification = justificationContents.join("\n\n");
|
|
400
|
+
}
|
|
401
|
+
if (mappingData.justification && mappingData.justification.trim() !== "") {
|
|
402
|
+
const mappingArray = [mappingData];
|
|
403
|
+
writeFileSync(mappingFilePath, yaml4.dump(mappingArray));
|
|
404
|
+
}
|
|
370
405
|
});
|
|
371
406
|
});
|
|
372
407
|
res.json({
|
|
@@ -1257,6 +1257,7 @@ __export(spreadsheetRoutes_exports, {
|
|
|
1257
1257
|
default: () => spreadsheetRoutes_default,
|
|
1258
1258
|
scanControlSets: () => scanControlSets
|
|
1259
1259
|
});
|
|
1260
|
+
import crypto from "crypto";
|
|
1260
1261
|
import { parse as parseCSVSync } from "csv-parse/sync";
|
|
1261
1262
|
import ExcelJS from "exceljs";
|
|
1262
1263
|
import express from "express";
|
|
@@ -1575,6 +1576,15 @@ var init_spreadsheetRoutes = __esm({
|
|
|
1575
1576
|
controlSetName = "Imported Control Set",
|
|
1576
1577
|
controlSetDescription = "Imported from spreadsheet"
|
|
1577
1578
|
} = req.body;
|
|
1579
|
+
let justificationFields = [];
|
|
1580
|
+
if (req.body.justificationFields) {
|
|
1581
|
+
try {
|
|
1582
|
+
justificationFields = JSON.parse(req.body.justificationFields);
|
|
1583
|
+
debug("Justification fields received:", justificationFields);
|
|
1584
|
+
} catch (e) {
|
|
1585
|
+
console.error("Failed to parse justification fields:", e);
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1578
1588
|
debug("Import parameters received:", {
|
|
1579
1589
|
controlIdField,
|
|
1580
1590
|
startRow,
|
|
@@ -1822,11 +1832,17 @@ var init_spreadsheetRoutes = __esm({
|
|
|
1822
1832
|
};
|
|
1823
1833
|
writeFileSync2(join4(baseDir, "lula.yaml"), yaml4.dump(controlSetData));
|
|
1824
1834
|
const controlsDir = join4(baseDir, "controls");
|
|
1835
|
+
const mappingsDir = join4(baseDir, "mappings");
|
|
1836
|
+
const justificationFieldNames = justificationFields;
|
|
1825
1837
|
families.forEach((familyControls, family) => {
|
|
1826
1838
|
const familyDir = join4(controlsDir, family);
|
|
1839
|
+
const familyMappingsDir = join4(mappingsDir, family);
|
|
1827
1840
|
if (!existsSync3(familyDir)) {
|
|
1828
1841
|
mkdirSync2(familyDir, { recursive: true });
|
|
1829
1842
|
}
|
|
1843
|
+
if (!existsSync3(familyMappingsDir)) {
|
|
1844
|
+
mkdirSync2(familyMappingsDir, { recursive: true });
|
|
1845
|
+
}
|
|
1830
1846
|
familyControls.forEach((control) => {
|
|
1831
1847
|
const controlId = control[controlIdFieldNameClean];
|
|
1832
1848
|
if (!controlId) {
|
|
@@ -1836,12 +1852,24 @@ var init_spreadsheetRoutes = __esm({
|
|
|
1836
1852
|
const controlIdStr = String(controlId).slice(0, 50);
|
|
1837
1853
|
const fileName2 = `${controlIdStr.replace(/[^a-zA-Z0-9-]/g, "_")}.yaml`;
|
|
1838
1854
|
const filePath = join4(familyDir, fileName2);
|
|
1855
|
+
const mappingFileName = `${controlIdStr.replace(/[^a-zA-Z0-9-]/g, "_")}-mappings.yaml`;
|
|
1856
|
+
const mappingFilePath = join4(familyMappingsDir, mappingFileName);
|
|
1839
1857
|
const filteredControl = {};
|
|
1858
|
+
const mappingData = {
|
|
1859
|
+
control_id: controlIdStr,
|
|
1860
|
+
justification: "",
|
|
1861
|
+
uuid: crypto.randomUUID()
|
|
1862
|
+
};
|
|
1863
|
+
const justificationContents = [];
|
|
1840
1864
|
if (control.family !== void 0) {
|
|
1841
1865
|
filteredControl.family = control.family;
|
|
1842
1866
|
}
|
|
1843
1867
|
Object.keys(control).forEach((fieldName) => {
|
|
1844
1868
|
if (fieldName === "family") return;
|
|
1869
|
+
if (justificationFields.includes(fieldName) && control[fieldName] !== void 0 && control[fieldName] !== null) {
|
|
1870
|
+
justificationContents.push(control[fieldName]);
|
|
1871
|
+
return;
|
|
1872
|
+
}
|
|
1845
1873
|
const isInFrontendSchema = frontendFieldSchema?.some((f) => f.fieldName === fieldName);
|
|
1846
1874
|
const isInFieldsMetadata = fields.hasOwnProperty(fieldName);
|
|
1847
1875
|
if (isInFrontendSchema || isInFieldsMetadata) {
|
|
@@ -1849,6 +1877,13 @@ var init_spreadsheetRoutes = __esm({
|
|
|
1849
1877
|
}
|
|
1850
1878
|
});
|
|
1851
1879
|
writeFileSync2(filePath, yaml4.dump(filteredControl));
|
|
1880
|
+
if (justificationContents.length > 0) {
|
|
1881
|
+
mappingData.justification = justificationContents.join("\n\n");
|
|
1882
|
+
}
|
|
1883
|
+
if (mappingData.justification && mappingData.justification.trim() !== "") {
|
|
1884
|
+
const mappingArray = [mappingData];
|
|
1885
|
+
writeFileSync2(mappingFilePath, yaml4.dump(mappingArray));
|
|
1886
|
+
}
|
|
1852
1887
|
});
|
|
1853
1888
|
});
|
|
1854
1889
|
res.json({
|
|
@@ -2090,8 +2125,8 @@ var WebSocketManager = class {
|
|
|
2090
2125
|
if (payload && payload.control_id) {
|
|
2091
2126
|
const mapping = payload;
|
|
2092
2127
|
if (!mapping.uuid) {
|
|
2093
|
-
const
|
|
2094
|
-
mapping.uuid =
|
|
2128
|
+
const crypto2 = await import("crypto");
|
|
2129
|
+
mapping.uuid = crypto2.randomUUID();
|
|
2095
2130
|
}
|
|
2096
2131
|
await state.fileStore.saveMapping(mapping);
|
|
2097
2132
|
state.mappingsCache.set(mapping.uuid, mapping);
|
package/dist/index.html
CHANGED
|
@@ -6,10 +6,10 @@
|
|
|
6
6
|
<link rel="icon" href="/lula.png" />
|
|
7
7
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
8
8
|
|
|
9
|
-
<link rel="modulepreload" href="/_app/immutable/entry/start.
|
|
10
|
-
<link rel="modulepreload" href="/_app/immutable/chunks/
|
|
9
|
+
<link rel="modulepreload" href="/_app/immutable/entry/start.8aoHS084.js">
|
|
10
|
+
<link rel="modulepreload" href="/_app/immutable/chunks/ByYV7ZA-.js">
|
|
11
11
|
<link rel="modulepreload" href="/_app/immutable/chunks/Cby0Z7eP.js">
|
|
12
|
-
<link rel="modulepreload" href="/_app/immutable/entry/app.
|
|
12
|
+
<link rel="modulepreload" href="/_app/immutable/entry/app.fwEu_ZMM.js">
|
|
13
13
|
<link rel="modulepreload" href="/_app/immutable/chunks/DsnmJJEf.js">
|
|
14
14
|
<link rel="modulepreload" href="/_app/immutable/chunks/DqsOU3kV.js">
|
|
15
15
|
<link rel="modulepreload" href="/_app/immutable/chunks/CoF2vljD.js">
|
|
@@ -19,15 +19,15 @@
|
|
|
19
19
|
<div style="display: contents">
|
|
20
20
|
<script>
|
|
21
21
|
{
|
|
22
|
-
|
|
22
|
+
__sveltekit_fjsoc9 = {
|
|
23
23
|
base: ""
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
const element = document.currentScript.parentElement;
|
|
27
27
|
|
|
28
28
|
Promise.all([
|
|
29
|
-
import("/_app/immutable/entry/start.
|
|
30
|
-
import("/_app/immutable/entry/app.
|
|
29
|
+
import("/_app/immutable/entry/start.8aoHS084.js"),
|
|
30
|
+
import("/_app/immutable/entry/app.fwEu_ZMM.js")
|
|
31
31
|
]).then(([kit, app]) => {
|
|
32
32
|
kit.start(app, element);
|
|
33
33
|
});
|
package/dist/index.js
CHANGED
|
@@ -2829,6 +2829,7 @@ __export(spreadsheetRoutes_exports, {
|
|
|
2829
2829
|
default: () => spreadsheetRoutes_default,
|
|
2830
2830
|
scanControlSets: () => scanControlSets
|
|
2831
2831
|
});
|
|
2832
|
+
import crypto from "crypto";
|
|
2832
2833
|
import { parse as parseCSVSync } from "csv-parse/sync";
|
|
2833
2834
|
import ExcelJS from "exceljs";
|
|
2834
2835
|
import express from "express";
|
|
@@ -3147,6 +3148,15 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3147
3148
|
controlSetName = "Imported Control Set",
|
|
3148
3149
|
controlSetDescription = "Imported from spreadsheet"
|
|
3149
3150
|
} = req.body;
|
|
3151
|
+
let justificationFields = [];
|
|
3152
|
+
if (req.body.justificationFields) {
|
|
3153
|
+
try {
|
|
3154
|
+
justificationFields = JSON.parse(req.body.justificationFields);
|
|
3155
|
+
debug("Justification fields received:", justificationFields);
|
|
3156
|
+
} catch (e) {
|
|
3157
|
+
console.error("Failed to parse justification fields:", e);
|
|
3158
|
+
}
|
|
3159
|
+
}
|
|
3150
3160
|
debug("Import parameters received:", {
|
|
3151
3161
|
controlIdField,
|
|
3152
3162
|
startRow,
|
|
@@ -3394,11 +3404,17 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3394
3404
|
};
|
|
3395
3405
|
writeFileSync2(join4(baseDir, "lula.yaml"), yaml4.dump(controlSetData));
|
|
3396
3406
|
const controlsDir = join4(baseDir, "controls");
|
|
3407
|
+
const mappingsDir = join4(baseDir, "mappings");
|
|
3408
|
+
const justificationFieldNames = justificationFields;
|
|
3397
3409
|
families.forEach((familyControls, family) => {
|
|
3398
3410
|
const familyDir = join4(controlsDir, family);
|
|
3411
|
+
const familyMappingsDir = join4(mappingsDir, family);
|
|
3399
3412
|
if (!existsSync3(familyDir)) {
|
|
3400
3413
|
mkdirSync2(familyDir, { recursive: true });
|
|
3401
3414
|
}
|
|
3415
|
+
if (!existsSync3(familyMappingsDir)) {
|
|
3416
|
+
mkdirSync2(familyMappingsDir, { recursive: true });
|
|
3417
|
+
}
|
|
3402
3418
|
familyControls.forEach((control) => {
|
|
3403
3419
|
const controlId = control[controlIdFieldNameClean];
|
|
3404
3420
|
if (!controlId) {
|
|
@@ -3408,12 +3424,24 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3408
3424
|
const controlIdStr = String(controlId).slice(0, 50);
|
|
3409
3425
|
const fileName2 = `${controlIdStr.replace(/[^a-zA-Z0-9-]/g, "_")}.yaml`;
|
|
3410
3426
|
const filePath = join4(familyDir, fileName2);
|
|
3427
|
+
const mappingFileName = `${controlIdStr.replace(/[^a-zA-Z0-9-]/g, "_")}-mappings.yaml`;
|
|
3428
|
+
const mappingFilePath = join4(familyMappingsDir, mappingFileName);
|
|
3411
3429
|
const filteredControl = {};
|
|
3430
|
+
const mappingData = {
|
|
3431
|
+
control_id: controlIdStr,
|
|
3432
|
+
justification: "",
|
|
3433
|
+
uuid: crypto.randomUUID()
|
|
3434
|
+
};
|
|
3435
|
+
const justificationContents = [];
|
|
3412
3436
|
if (control.family !== void 0) {
|
|
3413
3437
|
filteredControl.family = control.family;
|
|
3414
3438
|
}
|
|
3415
3439
|
Object.keys(control).forEach((fieldName) => {
|
|
3416
3440
|
if (fieldName === "family") return;
|
|
3441
|
+
if (justificationFields.includes(fieldName) && control[fieldName] !== void 0 && control[fieldName] !== null) {
|
|
3442
|
+
justificationContents.push(control[fieldName]);
|
|
3443
|
+
return;
|
|
3444
|
+
}
|
|
3417
3445
|
const isInFrontendSchema = frontendFieldSchema?.some((f) => f.fieldName === fieldName);
|
|
3418
3446
|
const isInFieldsMetadata = fields.hasOwnProperty(fieldName);
|
|
3419
3447
|
if (isInFrontendSchema || isInFieldsMetadata) {
|
|
@@ -3421,6 +3449,13 @@ var init_spreadsheetRoutes = __esm({
|
|
|
3421
3449
|
}
|
|
3422
3450
|
});
|
|
3423
3451
|
writeFileSync2(filePath, yaml4.dump(filteredControl));
|
|
3452
|
+
if (justificationContents.length > 0) {
|
|
3453
|
+
mappingData.justification = justificationContents.join("\n\n");
|
|
3454
|
+
}
|
|
3455
|
+
if (mappingData.justification && mappingData.justification.trim() !== "") {
|
|
3456
|
+
const mappingArray = [mappingData];
|
|
3457
|
+
writeFileSync2(mappingFilePath, yaml4.dump(mappingArray));
|
|
3458
|
+
}
|
|
3424
3459
|
});
|
|
3425
3460
|
});
|
|
3426
3461
|
res.json({
|
|
@@ -4537,8 +4572,8 @@ var WebSocketManager = class {
|
|
|
4537
4572
|
if (payload && payload.control_id) {
|
|
4538
4573
|
const mapping = payload;
|
|
4539
4574
|
if (!mapping.uuid) {
|
|
4540
|
-
const
|
|
4541
|
-
mapping.uuid =
|
|
4575
|
+
const crypto2 = await import("crypto");
|
|
4576
|
+
mapping.uuid = crypto2.randomUUID();
|
|
4542
4577
|
}
|
|
4543
4578
|
await state.fileStore.saveMapping(mapping);
|
|
4544
4579
|
state.mappingsCache.set(mapping.uuid, mapping);
|
|
@@ -5313,6 +5348,7 @@ function crawlCommand() {
|
|
|
5313
5348
|
return new Command().command("crawl").description("Detect compliance-related changes between @lulaStart and @lulaEnd in PR files").addOption(
|
|
5314
5349
|
new Option("--post-mode <mode>", "How to post findings").choices(["review", "comment"]).default("review")
|
|
5315
5350
|
).action(async (opts) => {
|
|
5351
|
+
let leavePost = false;
|
|
5316
5352
|
const { owner, repo, pull_number } = getPRContext();
|
|
5317
5353
|
console.log(`Analyzing PR #${pull_number} in ${owner}/${repo} for compliance changes...`);
|
|
5318
5354
|
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
|
|
@@ -5338,6 +5374,7 @@ Lula reviewed ${files.length} files changed that affect compliance.
|
|
|
5338
5374
|
]);
|
|
5339
5375
|
const changedBlocks = getChangedBlocks(oldText, newText);
|
|
5340
5376
|
for (const block of changedBlocks) {
|
|
5377
|
+
leavePost = true;
|
|
5341
5378
|
commentBody += `
|
|
5342
5379
|
|
|
5343
5380
|
---
|
|
@@ -5356,7 +5393,7 @@ Lula reviewed ${files.length} files changed that affect compliance.
|
|
|
5356
5393
|
console.error(`Error processing ${file.filename}: ${err}`);
|
|
5357
5394
|
}
|
|
5358
5395
|
}
|
|
5359
|
-
if (
|
|
5396
|
+
if (leavePost) {
|
|
5360
5397
|
await postFinding({
|
|
5361
5398
|
octokit,
|
|
5362
5399
|
postMode: opts.postMode,
|