lula2 0.7.5 → 0.8.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/README.md +2 -2
- package/dist/_app/immutable/assets/{0.DqWJrcPI.css → 0.DLu2XH4u.css} +1 -1
- package/dist/_app/immutable/chunks/BHkKokgA.js +1 -0
- package/dist/_app/immutable/chunks/{DsuS1uUo.js → BNu54jRO.js} +1 -1
- package/dist/_app/immutable/chunks/BzIr_GrC.js +79 -0
- package/dist/_app/immutable/chunks/CC6oS456.js +1 -0
- package/dist/_app/immutable/chunks/DHuA7MQr.js +1 -0
- package/dist/_app/immutable/chunks/{BIdjJ0zz.js → DJTXGU6C.js} +1 -1
- package/dist/_app/immutable/chunks/DSxRA67V.js +2 -0
- package/dist/_app/immutable/chunks/DpCtGpHu.js +1 -0
- package/dist/_app/immutable/chunks/DznG4VMX.js +2 -0
- package/dist/_app/immutable/chunks/Ew6_cz_0.js +1 -0
- package/dist/_app/immutable/chunks/kRA7ZCNG.js +1 -0
- package/dist/_app/immutable/entry/{app.CjycYot0.js → app.CpHUD0XU.js} +2 -2
- package/dist/_app/immutable/entry/start.BavDkynd.js +1 -0
- package/dist/_app/immutable/nodes/{0.CGKh5y4X.js → 0.D5TULpJI.js} +2 -2
- package/dist/_app/immutable/nodes/1.BBgWG9H0.js +1 -0
- package/dist/_app/immutable/nodes/{2.Hrl6uq-b.js → 2.c2WlghKX.js} +1 -1
- package/dist/_app/immutable/nodes/3.hNTFAKFs.js +1 -0
- package/dist/_app/immutable/nodes/{4.DAVWsDkK.js → 4.C7MOPYAO.js} +7 -7
- package/dist/_app/version.json +1 -1
- package/dist/cli/commands/ui.js +98 -8
- package/dist/cli/server/index.js +98 -8
- package/dist/cli/server/server.js +98 -8
- package/dist/cli/server/serverState.js +40 -6
- package/dist/cli/server/websocketServer.js +1146 -1056
- package/dist/index.html +11 -11
- package/dist/index.js +98 -8
- package/package.json +2 -2
- package/src/lib/components/controls/MappingCard.svelte +6 -1
- package/src/lib/components/controls/MappingForm.svelte +36 -3
- package/src/lib/components/controls/renderers/EditableFieldRenderer.svelte +57 -0
- package/src/lib/components/controls/tabs/CustomFieldsTab.svelte +1 -0
- package/src/lib/components/controls/tabs/ImplementationTab.svelte +1 -0
- package/src/lib/components/controls/tabs/MappingsTab.svelte +39 -14
- package/src/lib/components/controls/tabs/OverviewTab.svelte +1 -0
- package/src/lib/components/forms/FormField.svelte +65 -3
- package/src/lib/types.ts +2 -1
- package/src/lib/websocket.ts +7 -0
- package/src/routes/control/[id]/+page.svelte +2 -2
- package/dist/_app/immutable/chunks/BI-GirXZ.js +0 -1
- package/dist/_app/immutable/chunks/BSyVkqhj.js +0 -2
- package/dist/_app/immutable/chunks/Cng7c2CG.js +0 -1
- package/dist/_app/immutable/chunks/CxBMFlfX.js +0 -1
- package/dist/_app/immutable/chunks/DArZRX9-.js +0 -65
- package/dist/_app/immutable/chunks/DH2IP9c7.js +0 -1
- package/dist/_app/immutable/chunks/DXSHWIjJ.js +0 -2
- package/dist/_app/immutable/chunks/urFjAlpd.js +0 -1
- package/dist/_app/immutable/entry/start.Bgy9x4Qb.js +0 -1
- package/dist/_app/immutable/nodes/1.D5L7DxSG.js +0 -1
- package/dist/_app/immutable/nodes/3.BoHxdRm3.js +0 -1
|
@@ -1650,6 +1650,7 @@ var fileStore_exports = {};
|
|
|
1650
1650
|
__export(fileStore_exports, {
|
|
1651
1651
|
FileStore: () => FileStore
|
|
1652
1652
|
});
|
|
1653
|
+
import { createHash as createHash2 } from "crypto";
|
|
1653
1654
|
import {
|
|
1654
1655
|
existsSync as existsSync2,
|
|
1655
1656
|
promises as fs,
|
|
@@ -1662,7 +1663,6 @@ import {
|
|
|
1662
1663
|
} from "fs";
|
|
1663
1664
|
import * as yaml2 from "js-yaml";
|
|
1664
1665
|
import { join as join2 } from "path";
|
|
1665
|
-
import { createHash as createHash2 } from "crypto";
|
|
1666
1666
|
var FileStore;
|
|
1667
1667
|
var init_fileStore = __esm({
|
|
1668
1668
|
"cli/server/infrastructure/fileStore.ts"() {
|
|
@@ -1682,6 +1682,40 @@ var init_fileStore = __esm({
|
|
|
1682
1682
|
this.refreshControlsCache();
|
|
1683
1683
|
}
|
|
1684
1684
|
}
|
|
1685
|
+
/**
|
|
1686
|
+
* Update a single mapping in place, preserving file order
|
|
1687
|
+
*/
|
|
1688
|
+
async updateMapping(oldCompositeKey, updatedMapping) {
|
|
1689
|
+
const mappingFiles = this.getAllMappingFiles();
|
|
1690
|
+
for (const file of mappingFiles) {
|
|
1691
|
+
try {
|
|
1692
|
+
const content = readFileSync2(file, "utf8");
|
|
1693
|
+
let mappings = yaml2.load(content) || [];
|
|
1694
|
+
let changed = false;
|
|
1695
|
+
mappings = mappings.map((m) => {
|
|
1696
|
+
const hash = createHash2("sha256").update(JSON.stringify(m)).digest("hex");
|
|
1697
|
+
if (`${m.control_id}:${hash}` === oldCompositeKey) {
|
|
1698
|
+
const clean = { ...updatedMapping };
|
|
1699
|
+
delete clean.hash;
|
|
1700
|
+
changed = true;
|
|
1701
|
+
return clean;
|
|
1702
|
+
}
|
|
1703
|
+
return m;
|
|
1704
|
+
});
|
|
1705
|
+
if (changed) {
|
|
1706
|
+
const yamlContent = yaml2.dump(mappings, {
|
|
1707
|
+
indent: 2,
|
|
1708
|
+
lineWidth: -1,
|
|
1709
|
+
noRefs: true
|
|
1710
|
+
});
|
|
1711
|
+
writeFileSync(file, yamlContent, "utf8");
|
|
1712
|
+
return;
|
|
1713
|
+
}
|
|
1714
|
+
} catch (error) {
|
|
1715
|
+
console.error(`Error processing mapping file ${file}:`, error);
|
|
1716
|
+
}
|
|
1717
|
+
}
|
|
1718
|
+
}
|
|
1685
1719
|
/**
|
|
1686
1720
|
* Get simple filename from control ID
|
|
1687
1721
|
*/
|
|
@@ -1704,8 +1738,8 @@ var init_fileStore = __esm({
|
|
|
1704
1738
|
if (!this.baseDir || this.baseDir === "." || this.baseDir === process.cwd()) {
|
|
1705
1739
|
return;
|
|
1706
1740
|
}
|
|
1707
|
-
const
|
|
1708
|
-
if (!existsSync2(
|
|
1741
|
+
const lulaConfigPath = join2(this.baseDir, "lula.yaml");
|
|
1742
|
+
if (!existsSync2(lulaConfigPath)) {
|
|
1709
1743
|
return;
|
|
1710
1744
|
}
|
|
1711
1745
|
if (!existsSync2(this.controlsDir)) {
|
|
@@ -1864,10 +1898,10 @@ var init_fileStore = __esm({
|
|
|
1864
1898
|
return [];
|
|
1865
1899
|
}
|
|
1866
1900
|
let controlOrder = null;
|
|
1901
|
+
const lulaConfigPath = join2(this.baseDir, "lula.yaml");
|
|
1867
1902
|
try {
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
const content = readFileSync2(lulaConfigPath2, "utf8");
|
|
1903
|
+
if (existsSync2(lulaConfigPath)) {
|
|
1904
|
+
const content = readFileSync2(lulaConfigPath, "utf8");
|
|
1871
1905
|
const metadata = yaml2.load(content);
|
|
1872
1906
|
controlOrder = metadata?.controlOrder || null;
|
|
1873
1907
|
}
|
|
@@ -5116,12 +5150,12 @@ import { fileURLToPath } from "url";
|
|
|
5116
5150
|
import { readFileSync as readFileSync4 } from "fs";
|
|
5117
5151
|
init_debug();
|
|
5118
5152
|
init_controlHelpers();
|
|
5119
|
-
init_serverState();
|
|
5120
5153
|
init_gitHistory();
|
|
5154
|
+
init_serverState();
|
|
5121
5155
|
import * as yaml5 from "js-yaml";
|
|
5156
|
+
import crypto2 from "node:crypto";
|
|
5122
5157
|
import { join as join5 } from "path";
|
|
5123
5158
|
import { WebSocket, WebSocketServer } from "ws";
|
|
5124
|
-
import crypto2 from "node:crypto";
|
|
5125
5159
|
var WebSocketManager = class {
|
|
5126
5160
|
wss = null;
|
|
5127
5161
|
clients = /* @__PURE__ */ new Set();
|
|
@@ -5162,6 +5196,62 @@ var WebSocketManager = class {
|
|
|
5162
5196
|
}
|
|
5163
5197
|
break;
|
|
5164
5198
|
}
|
|
5199
|
+
case "update-mapping": {
|
|
5200
|
+
const state = getServerState();
|
|
5201
|
+
if (payload && payload.old_composite_key && payload.mapping) {
|
|
5202
|
+
const oldCompositeKey = payload.old_composite_key;
|
|
5203
|
+
const existing = state.mappingsCache.get(oldCompositeKey);
|
|
5204
|
+
if (!existing) {
|
|
5205
|
+
console.error("Mapping not found for update:", oldCompositeKey);
|
|
5206
|
+
break;
|
|
5207
|
+
}
|
|
5208
|
+
const incoming = payload.mapping;
|
|
5209
|
+
const updated = {
|
|
5210
|
+
...existing,
|
|
5211
|
+
...incoming,
|
|
5212
|
+
control_id: incoming.control_id || existing.control_id,
|
|
5213
|
+
uuid: incoming.uuid || existing.uuid
|
|
5214
|
+
};
|
|
5215
|
+
if (!updated.hash || updated.hash === "") {
|
|
5216
|
+
updated.hash = crypto2.createHash("sha256").update(JSON.stringify({ ...updated, hash: void 0 })).digest("hex");
|
|
5217
|
+
}
|
|
5218
|
+
const oldHash = existing.hash;
|
|
5219
|
+
const oldControlId = existing.control_id;
|
|
5220
|
+
const oldFamily = oldControlId.split("-")[0];
|
|
5221
|
+
const newHash = updated.hash;
|
|
5222
|
+
const newControlId = updated.control_id;
|
|
5223
|
+
const newFamily = newControlId.split("-")[0];
|
|
5224
|
+
const newCompositeKey = `${newControlId}:${newHash}`;
|
|
5225
|
+
await state.fileStore.updateMapping(oldCompositeKey, updated);
|
|
5226
|
+
const entries = Array.from(state.mappingsCache.entries());
|
|
5227
|
+
const oldIndex = entries.findIndex(([key]) => key === oldCompositeKey);
|
|
5228
|
+
if (oldIndex === -1) {
|
|
5229
|
+
state.mappingsCache.delete(oldCompositeKey);
|
|
5230
|
+
state.mappingsCache.set(newCompositeKey, updated);
|
|
5231
|
+
} else {
|
|
5232
|
+
entries[oldIndex] = [newCompositeKey, updated];
|
|
5233
|
+
state.mappingsCache = new Map(entries);
|
|
5234
|
+
}
|
|
5235
|
+
state.mappingsByFamily.get(oldFamily)?.delete(oldHash);
|
|
5236
|
+
state.mappingsByControl.get(oldControlId)?.delete(oldHash);
|
|
5237
|
+
if (!state.mappingsByFamily.has(newFamily)) {
|
|
5238
|
+
state.mappingsByFamily.set(newFamily, /* @__PURE__ */ new Set());
|
|
5239
|
+
}
|
|
5240
|
+
state.mappingsByFamily.get(newFamily).add(newHash);
|
|
5241
|
+
if (!state.mappingsByControl.has(newControlId)) {
|
|
5242
|
+
state.mappingsByControl.set(newControlId, /* @__PURE__ */ new Set());
|
|
5243
|
+
}
|
|
5244
|
+
state.mappingsByControl.get(newControlId).add(newHash);
|
|
5245
|
+
ws.send(
|
|
5246
|
+
JSON.stringify({
|
|
5247
|
+
type: "mapping-updated",
|
|
5248
|
+
payload: { uuid: updated.uuid, success: true }
|
|
5249
|
+
})
|
|
5250
|
+
);
|
|
5251
|
+
this.broadcastState();
|
|
5252
|
+
}
|
|
5253
|
+
break;
|
|
5254
|
+
}
|
|
5165
5255
|
case "refresh-controls": {
|
|
5166
5256
|
const state = getServerState();
|
|
5167
5257
|
state.controlsCache.clear();
|
|
@@ -11,6 +11,7 @@ function debug(...args) {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
// cli/server/infrastructure/fileStore.ts
|
|
14
|
+
import { createHash } from "crypto";
|
|
14
15
|
import {
|
|
15
16
|
existsSync as existsSync2,
|
|
16
17
|
promises as fs,
|
|
@@ -89,7 +90,6 @@ function getControlId(control, baseDir) {
|
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
// cli/server/infrastructure/fileStore.ts
|
|
92
|
-
import { createHash } from "crypto";
|
|
93
93
|
var FileStore = class {
|
|
94
94
|
baseDir;
|
|
95
95
|
controlsDir;
|
|
@@ -104,6 +104,40 @@ var FileStore = class {
|
|
|
104
104
|
this.refreshControlsCache();
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
|
+
/**
|
|
108
|
+
* Update a single mapping in place, preserving file order
|
|
109
|
+
*/
|
|
110
|
+
async updateMapping(oldCompositeKey, updatedMapping) {
|
|
111
|
+
const mappingFiles = this.getAllMappingFiles();
|
|
112
|
+
for (const file of mappingFiles) {
|
|
113
|
+
try {
|
|
114
|
+
const content = readFileSync2(file, "utf8");
|
|
115
|
+
let mappings = yaml2.load(content) || [];
|
|
116
|
+
let changed = false;
|
|
117
|
+
mappings = mappings.map((m) => {
|
|
118
|
+
const hash = createHash("sha256").update(JSON.stringify(m)).digest("hex");
|
|
119
|
+
if (`${m.control_id}:${hash}` === oldCompositeKey) {
|
|
120
|
+
const clean = { ...updatedMapping };
|
|
121
|
+
delete clean.hash;
|
|
122
|
+
changed = true;
|
|
123
|
+
return clean;
|
|
124
|
+
}
|
|
125
|
+
return m;
|
|
126
|
+
});
|
|
127
|
+
if (changed) {
|
|
128
|
+
const yamlContent = yaml2.dump(mappings, {
|
|
129
|
+
indent: 2,
|
|
130
|
+
lineWidth: -1,
|
|
131
|
+
noRefs: true
|
|
132
|
+
});
|
|
133
|
+
writeFileSync(file, yamlContent, "utf8");
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
} catch (error) {
|
|
137
|
+
console.error(`Error processing mapping file ${file}:`, error);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
107
141
|
/**
|
|
108
142
|
* Get simple filename from control ID
|
|
109
143
|
*/
|
|
@@ -126,8 +160,8 @@ var FileStore = class {
|
|
|
126
160
|
if (!this.baseDir || this.baseDir === "." || this.baseDir === process.cwd()) {
|
|
127
161
|
return;
|
|
128
162
|
}
|
|
129
|
-
const
|
|
130
|
-
if (!existsSync2(
|
|
163
|
+
const lulaConfigPath = join2(this.baseDir, "lula.yaml");
|
|
164
|
+
if (!existsSync2(lulaConfigPath)) {
|
|
131
165
|
return;
|
|
132
166
|
}
|
|
133
167
|
if (!existsSync2(this.controlsDir)) {
|
|
@@ -286,10 +320,10 @@ var FileStore = class {
|
|
|
286
320
|
return [];
|
|
287
321
|
}
|
|
288
322
|
let controlOrder = null;
|
|
323
|
+
const lulaConfigPath = join2(this.baseDir, "lula.yaml");
|
|
289
324
|
try {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
const content = readFileSync2(lulaConfigPath2, "utf8");
|
|
325
|
+
if (existsSync2(lulaConfigPath)) {
|
|
326
|
+
const content = readFileSync2(lulaConfigPath, "utf8");
|
|
293
327
|
const metadata = yaml2.load(content);
|
|
294
328
|
controlOrder = metadata?.controlOrder || null;
|
|
295
329
|
}
|