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.
Files changed (51) hide show
  1. package/README.md +2 -2
  2. package/dist/_app/immutable/assets/{0.DqWJrcPI.css → 0.DLu2XH4u.css} +1 -1
  3. package/dist/_app/immutable/chunks/BHkKokgA.js +1 -0
  4. package/dist/_app/immutable/chunks/{DsuS1uUo.js → BNu54jRO.js} +1 -1
  5. package/dist/_app/immutable/chunks/BzIr_GrC.js +79 -0
  6. package/dist/_app/immutable/chunks/CC6oS456.js +1 -0
  7. package/dist/_app/immutable/chunks/DHuA7MQr.js +1 -0
  8. package/dist/_app/immutable/chunks/{BIdjJ0zz.js → DJTXGU6C.js} +1 -1
  9. package/dist/_app/immutable/chunks/DSxRA67V.js +2 -0
  10. package/dist/_app/immutable/chunks/DpCtGpHu.js +1 -0
  11. package/dist/_app/immutable/chunks/DznG4VMX.js +2 -0
  12. package/dist/_app/immutable/chunks/Ew6_cz_0.js +1 -0
  13. package/dist/_app/immutable/chunks/kRA7ZCNG.js +1 -0
  14. package/dist/_app/immutable/entry/{app.CjycYot0.js → app.CpHUD0XU.js} +2 -2
  15. package/dist/_app/immutable/entry/start.BavDkynd.js +1 -0
  16. package/dist/_app/immutable/nodes/{0.CGKh5y4X.js → 0.D5TULpJI.js} +2 -2
  17. package/dist/_app/immutable/nodes/1.BBgWG9H0.js +1 -0
  18. package/dist/_app/immutable/nodes/{2.Hrl6uq-b.js → 2.c2WlghKX.js} +1 -1
  19. package/dist/_app/immutable/nodes/3.hNTFAKFs.js +1 -0
  20. package/dist/_app/immutable/nodes/{4.DAVWsDkK.js → 4.C7MOPYAO.js} +7 -7
  21. package/dist/_app/version.json +1 -1
  22. package/dist/cli/commands/ui.js +98 -8
  23. package/dist/cli/server/index.js +98 -8
  24. package/dist/cli/server/server.js +98 -8
  25. package/dist/cli/server/serverState.js +40 -6
  26. package/dist/cli/server/websocketServer.js +1146 -1056
  27. package/dist/index.html +11 -11
  28. package/dist/index.js +98 -8
  29. package/package.json +2 -2
  30. package/src/lib/components/controls/MappingCard.svelte +6 -1
  31. package/src/lib/components/controls/MappingForm.svelte +36 -3
  32. package/src/lib/components/controls/renderers/EditableFieldRenderer.svelte +57 -0
  33. package/src/lib/components/controls/tabs/CustomFieldsTab.svelte +1 -0
  34. package/src/lib/components/controls/tabs/ImplementationTab.svelte +1 -0
  35. package/src/lib/components/controls/tabs/MappingsTab.svelte +39 -14
  36. package/src/lib/components/controls/tabs/OverviewTab.svelte +1 -0
  37. package/src/lib/components/forms/FormField.svelte +65 -3
  38. package/src/lib/types.ts +2 -1
  39. package/src/lib/websocket.ts +7 -0
  40. package/src/routes/control/[id]/+page.svelte +2 -2
  41. package/dist/_app/immutable/chunks/BI-GirXZ.js +0 -1
  42. package/dist/_app/immutable/chunks/BSyVkqhj.js +0 -2
  43. package/dist/_app/immutable/chunks/Cng7c2CG.js +0 -1
  44. package/dist/_app/immutable/chunks/CxBMFlfX.js +0 -1
  45. package/dist/_app/immutable/chunks/DArZRX9-.js +0 -65
  46. package/dist/_app/immutable/chunks/DH2IP9c7.js +0 -1
  47. package/dist/_app/immutable/chunks/DXSHWIjJ.js +0 -2
  48. package/dist/_app/immutable/chunks/urFjAlpd.js +0 -1
  49. package/dist/_app/immutable/entry/start.Bgy9x4Qb.js +0 -1
  50. package/dist/_app/immutable/nodes/1.D5L7DxSG.js +0 -1
  51. 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 lulaConfigPath2 = join2(this.baseDir, "lula.yaml");
1708
- if (!existsSync2(lulaConfigPath2)) {
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
- const lulaConfigPath2 = join2(this.baseDir, "lula.yaml");
1869
- if (existsSync2(lulaConfigPath2)) {
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 lulaConfigPath2 = join2(this.baseDir, "lula.yaml");
130
- if (!existsSync2(lulaConfigPath2)) {
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
- const lulaConfigPath2 = join2(this.baseDir, "lula.yaml");
291
- if (existsSync2(lulaConfigPath2)) {
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
  }