@kopexa/grc 0.0.2 → 0.0.3

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 (53) hide show
  1. package/dist/chunk-5TBN3JQA.mjs +66 -0
  2. package/dist/chunk-DC44K745.mjs +46 -0
  3. package/dist/chunk-HI7F2CF4.mjs +1 -0
  4. package/dist/chunk-HJUSN7FD.mjs +1 -0
  5. package/dist/chunk-QDYL5ABK.mjs +118 -0
  6. package/dist/chunk-QS5S6V26.mjs +22 -0
  7. package/dist/chunk-VFX3DASQ.mjs +57 -0
  8. package/dist/common/control/index.d.mts +3 -0
  9. package/dist/common/control/index.d.ts +3 -0
  10. package/dist/common/control/index.js +160 -0
  11. package/dist/common/control/index.mjs +11 -0
  12. package/dist/common/control/mapped-controls.d.mts +33 -0
  13. package/dist/common/control/mapped-controls.d.ts +33 -0
  14. package/dist/common/control/mapped-controls.js +159 -0
  15. package/dist/common/control/mapped-controls.mjs +11 -0
  16. package/dist/common/control/messages.d.mts +16 -0
  17. package/dist/common/control/messages.d.ts +16 -0
  18. package/dist/common/control/messages.js +45 -0
  19. package/dist/common/control/messages.mjs +7 -0
  20. package/dist/common/index.d.mts +5 -0
  21. package/dist/common/index.d.ts +5 -0
  22. package/dist/common/index.js +364 -75
  23. package/dist/common/index.mjs +26 -1
  24. package/dist/common/risk/index.d.mts +4 -0
  25. package/dist/common/risk/index.d.ts +4 -0
  26. package/dist/common/risk/index.js +185 -0
  27. package/dist/common/risk/index.mjs +20 -0
  28. package/dist/common/risk/messages.d.mts +40 -0
  29. package/dist/common/risk/messages.d.ts +40 -0
  30. package/dist/common/risk/messages.js +69 -0
  31. package/dist/common/risk/messages.mjs +7 -0
  32. package/dist/common/risk/risk-rating-display.d.mts +21 -0
  33. package/dist/common/risk/risk-rating-display.d.ts +21 -0
  34. package/dist/common/risk/risk-rating-display.js +139 -0
  35. package/dist/common/risk/risk-rating-display.mjs +10 -0
  36. package/dist/common/risk/types.d.mts +37 -0
  37. package/dist/common/risk/types.d.ts +37 -0
  38. package/dist/common/risk/types.js +82 -0
  39. package/dist/common/risk/types.mjs +11 -0
  40. package/dist/index.d.mts +5 -0
  41. package/dist/index.d.ts +5 -0
  42. package/dist/index.js +364 -75
  43. package/dist/index.mjs +26 -1
  44. package/package.json +8 -7
  45. package/src/common/control/index.ts +6 -0
  46. package/src/common/control/mapped-controls.tsx +192 -0
  47. package/src/common/control/messages.ts +16 -0
  48. package/src/common/index.ts +2 -0
  49. package/src/common/risk/index.ts +12 -0
  50. package/src/common/risk/messages.ts +40 -0
  51. package/src/common/risk/risk-rating-display.tsx +86 -0
  52. package/src/common/risk/types.ts +91 -0
  53. /package/dist/{chunk-BFZPRJQT.mjs → chunk-CND77GVC.mjs} +0 -0
package/dist/index.js CHANGED
@@ -22,14 +22,21 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
22
22
  var index_exports = {};
23
23
  __export(index_exports, {
24
24
  ComplianceBadges: () => ComplianceBadges,
25
+ ControlChip: () => ControlChip,
25
26
  DoraBadge: () => DoraBadge,
26
27
  ImpactCard: () => ImpactCard,
28
+ MappedControls: () => MappedControls,
27
29
  Nis2Badge: () => Nis2Badge,
30
+ RiskRatingDisplay: () => RiskRatingDisplay,
28
31
  assetScale: () => assetScale,
32
+ getRiskLevelFromRating: () => getRiskLevelFromRating,
29
33
  getScale: () => getScale,
30
34
  impactLevels: () => impactLevels,
31
- impactMessages: () => messages2,
35
+ impactMessages: () => messages3,
36
+ isRatingUnrated: () => isRatingUnrated,
32
37
  processScale: () => processScale,
38
+ riskLevelConfig: () => riskLevelConfig,
39
+ riskMessages: () => messages4,
33
40
  riskScale: () => riskScale
34
41
  });
35
42
  module.exports = __toCommonJS(index_exports);
@@ -104,16 +111,144 @@ function ComplianceBadges({
104
111
  ] });
105
112
  }
106
113
 
107
- // src/common/impact/impact-card.tsx
114
+ // src/common/control/mapped-controls.tsx
108
115
  var import_i18n4 = require("@kopexa/i18n");
109
- var import_icons2 = require("@kopexa/icons");
116
+ var import_krn = require("@kopexa/krn");
110
117
  var import_sight2 = require("@kopexa/sight");
111
118
  var import_theme2 = require("@kopexa/theme");
112
- var import_react = require("react");
113
119
 
114
- // src/common/impact/messages.ts
120
+ // src/common/control/messages.ts
115
121
  var import_i18n3 = require("@kopexa/i18n");
116
122
  var messages2 = (0, import_i18n3.defineMessages)({
123
+ more_controls: {
124
+ id: "grc.control.mapped.more",
125
+ defaultMessage: "+{count} more"
126
+ },
127
+ view_all: {
128
+ id: "grc.control.mapped.view_all",
129
+ defaultMessage: "View all {count} controls"
130
+ },
131
+ no_controls: {
132
+ id: "grc.control.mapped.no_controls",
133
+ defaultMessage: "No mapped controls"
134
+ }
135
+ });
136
+
137
+ // src/common/control/mapped-controls.tsx
138
+ var import_jsx_runtime2 = require("react/jsx-runtime");
139
+ function formatControlKrn(krnString) {
140
+ const parsed = import_krn.KRN.tryParse(krnString);
141
+ if (!parsed) {
142
+ return { framework: null, controlId: krnString, full: krnString };
143
+ }
144
+ const framework = parsed.tryResourceId("frameworks");
145
+ const control = parsed.tryResourceId("controls");
146
+ if (framework && control) {
147
+ return {
148
+ framework,
149
+ controlId: control,
150
+ full: `${framework}:${control}`
151
+ };
152
+ }
153
+ const basename = parsed.basename();
154
+ return {
155
+ framework: null,
156
+ controlId: basename || krnString,
157
+ full: basename || krnString
158
+ };
159
+ }
160
+ function ControlChip({
161
+ krn,
162
+ size = "md",
163
+ interactive = false,
164
+ onClick,
165
+ className
166
+ }) {
167
+ const styles = (0, import_theme2.relatedControlChip)({ size, interactive });
168
+ const { controlId, full } = formatControlKrn(krn);
169
+ const displayId = controlId.toUpperCase();
170
+ const content = /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.chipId(), children: displayId });
171
+ const chip = interactive && onClick ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
172
+ "button",
173
+ {
174
+ type: "button",
175
+ className: styles.chip({ className }),
176
+ onClick,
177
+ children: content
178
+ }
179
+ ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.chip({ className }), children: content });
180
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sight2.Tooltip, { content: full, children: chip });
181
+ }
182
+ function MappedControls({
183
+ controls,
184
+ maxVisible = 2,
185
+ size = "md",
186
+ interactive = false,
187
+ onControlClick,
188
+ showEmpty = false,
189
+ className,
190
+ ...rest
191
+ }) {
192
+ const intl = (0, import_i18n4.useSafeIntl)();
193
+ const styles = (0, import_theme2.relatedControlChip)({ size, interactive });
194
+ if (controls.length === 0) {
195
+ if (!showEmpty) return null;
196
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs text-muted-foreground", children: intl.formatMessage(messages2.no_controls) });
197
+ }
198
+ const visibleControls = controls.slice(0, maxVisible);
199
+ const hiddenCount = controls.length - maxVisible;
200
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: styles.root({ className }), ...rest, children: [
201
+ visibleControls.map((krn) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
202
+ ControlChip,
203
+ {
204
+ krn,
205
+ size,
206
+ interactive,
207
+ onClick: onControlClick ? () => onControlClick(krn) : void 0
208
+ },
209
+ krn
210
+ )),
211
+ hiddenCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_sight2.Popover.Root, { children: [
212
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sight2.Popover.Trigger, { className: styles.overflow(), children: intl.formatMessage(messages2.more_controls, {
213
+ count: hiddenCount
214
+ }) }),
215
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
216
+ import_sight2.Popover.Content,
217
+ {
218
+ align: "start",
219
+ className: "p-2 max-w-xs",
220
+ showArrow: false,
221
+ children: [
222
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "text-xs font-medium text-muted-foreground mb-2", children: intl.formatMessage(messages2.view_all, {
223
+ count: controls.length
224
+ }) }),
225
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex flex-wrap gap-1", children: controls.map((krn) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
226
+ ControlChip,
227
+ {
228
+ krn,
229
+ size,
230
+ interactive,
231
+ onClick: onControlClick ? () => onControlClick(krn) : void 0
232
+ },
233
+ krn
234
+ )) })
235
+ ]
236
+ }
237
+ )
238
+ ] })
239
+ ] });
240
+ }
241
+
242
+ // src/common/impact/impact-card.tsx
243
+ var import_i18n6 = require("@kopexa/i18n");
244
+ var import_icons2 = require("@kopexa/icons");
245
+ var import_sight3 = require("@kopexa/sight");
246
+ var import_theme3 = require("@kopexa/theme");
247
+ var import_react = require("react");
248
+
249
+ // src/common/impact/messages.ts
250
+ var import_i18n5 = require("@kopexa/i18n");
251
+ var messages3 = (0, import_i18n5.defineMessages)({
117
252
  // Card titles
118
253
  title_cia: {
119
254
  id: "grc.impact.title_cia",
@@ -250,42 +385,42 @@ var messages2 = (0, import_i18n3.defineMessages)({
250
385
  // src/common/impact/scales.ts
251
386
  var riskScale = {
252
387
  0: {
253
- message: messages2.risk_0,
388
+ message: messages3.risk_0,
254
389
  fallbackLabel: "Not rated",
255
390
  color: "text-muted-foreground",
256
391
  bgColor: "bg-muted",
257
392
  barColor: "bg-muted"
258
393
  },
259
394
  1: {
260
- message: messages2.risk_1,
395
+ message: messages3.risk_1,
261
396
  fallbackLabel: "Negligible",
262
397
  color: "text-green-700",
263
398
  bgColor: "bg-green-100",
264
399
  barColor: "bg-green-500"
265
400
  },
266
401
  2: {
267
- message: messages2.risk_2,
402
+ message: messages3.risk_2,
268
403
  fallbackLabel: "Low",
269
404
  color: "text-lime-700",
270
405
  bgColor: "bg-lime-100",
271
406
  barColor: "bg-lime-500"
272
407
  },
273
408
  3: {
274
- message: messages2.risk_3,
409
+ message: messages3.risk_3,
275
410
  fallbackLabel: "Medium",
276
411
  color: "text-yellow-700",
277
412
  bgColor: "bg-yellow-100",
278
413
  barColor: "bg-yellow-500"
279
414
  },
280
415
  4: {
281
- message: messages2.risk_4,
416
+ message: messages3.risk_4,
282
417
  fallbackLabel: "High",
283
418
  color: "text-orange-700",
284
419
  bgColor: "bg-orange-100",
285
420
  barColor: "bg-orange-500"
286
421
  },
287
422
  5: {
288
- message: messages2.risk_5,
423
+ message: messages3.risk_5,
289
424
  fallbackLabel: "Critical",
290
425
  color: "text-red-700",
291
426
  bgColor: "bg-red-100",
@@ -294,42 +429,42 @@ var riskScale = {
294
429
  };
295
430
  var processScale = {
296
431
  0: {
297
- message: messages2.process_0,
432
+ message: messages3.process_0,
298
433
  fallbackLabel: "Not rated",
299
434
  color: "text-muted-foreground",
300
435
  bgColor: "bg-muted",
301
436
  barColor: "bg-muted"
302
437
  },
303
438
  1: {
304
- message: messages2.process_1,
439
+ message: messages3.process_1,
305
440
  fallbackLabel: "Insignificant",
306
441
  color: "text-green-700",
307
442
  bgColor: "bg-green-100",
308
443
  barColor: "bg-green-500"
309
444
  },
310
445
  2: {
311
- message: messages2.process_2,
446
+ message: messages3.process_2,
312
447
  fallbackLabel: "Low",
313
448
  color: "text-lime-700",
314
449
  bgColor: "bg-lime-100",
315
450
  barColor: "bg-lime-500"
316
451
  },
317
452
  3: {
318
- message: messages2.process_3,
453
+ message: messages3.process_3,
319
454
  fallbackLabel: "Relevant",
320
455
  color: "text-yellow-700",
321
456
  bgColor: "bg-yellow-100",
322
457
  barColor: "bg-yellow-500"
323
458
  },
324
459
  4: {
325
- message: messages2.process_4,
460
+ message: messages3.process_4,
326
461
  fallbackLabel: "Important",
327
462
  color: "text-orange-700",
328
463
  bgColor: "bg-orange-100",
329
464
  barColor: "bg-orange-500"
330
465
  },
331
466
  5: {
332
- message: messages2.process_5,
467
+ message: messages3.process_5,
333
468
  fallbackLabel: "Vital",
334
469
  color: "text-red-700",
335
470
  bgColor: "bg-red-100",
@@ -338,42 +473,42 @@ var processScale = {
338
473
  };
339
474
  var assetScale = {
340
475
  0: {
341
- message: messages2.asset_0,
476
+ message: messages3.asset_0,
342
477
  fallbackLabel: "Not classified",
343
478
  color: "text-muted-foreground",
344
479
  bgColor: "bg-muted",
345
480
  barColor: "bg-muted"
346
481
  },
347
482
  1: {
348
- message: messages2.asset_1,
483
+ message: messages3.asset_1,
349
484
  fallbackLabel: "Insignificant",
350
485
  color: "text-green-700",
351
486
  bgColor: "bg-green-100",
352
487
  barColor: "bg-green-500"
353
488
  },
354
489
  2: {
355
- message: messages2.asset_2,
490
+ message: messages3.asset_2,
356
491
  fallbackLabel: "Low",
357
492
  color: "text-lime-700",
358
493
  bgColor: "bg-lime-100",
359
494
  barColor: "bg-lime-500"
360
495
  },
361
496
  3: {
362
- message: messages2.asset_3,
497
+ message: messages3.asset_3,
363
498
  fallbackLabel: "Medium",
364
499
  color: "text-yellow-700",
365
500
  bgColor: "bg-yellow-100",
366
501
  barColor: "bg-yellow-500"
367
502
  },
368
503
  4: {
369
- message: messages2.asset_4,
504
+ message: messages3.asset_4,
370
505
  fallbackLabel: "High",
371
506
  color: "text-orange-700",
372
507
  bgColor: "bg-orange-100",
373
508
  barColor: "bg-orange-500"
374
509
  },
375
510
  5: {
376
- message: messages2.asset_5,
511
+ message: messages3.asset_5,
377
512
  fallbackLabel: "Business Critical",
378
513
  color: "text-red-700",
379
514
  bgColor: "bg-red-100",
@@ -393,7 +528,7 @@ function getScale(preset) {
393
528
  }
394
529
 
395
530
  // src/common/impact/impact-card.tsx
396
- var import_jsx_runtime2 = require("react/jsx-runtime");
531
+ var import_jsx_runtime3 = require("react/jsx-runtime");
397
532
  function ImpactItemRow({
398
533
  label,
399
534
  shortLabel,
@@ -406,29 +541,29 @@ function ImpactItemRow({
406
541
  const config = scale[value];
407
542
  const isUnrated = value === 0;
408
543
  const percentage = isUnrated ? 0 : value / 5 * 100;
409
- const styles = (0, import_theme2.impactCard)({ unrated: isUnrated });
410
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: styles.row(), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: styles.rowContent(), children: [
411
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.rowIcon(), children: shortLabel }),
412
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: styles.rowBody(), children: [
413
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: styles.rowHeader(), children: [
414
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.rowLabel(), children: label }),
415
- isEditing ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
416
- import_sight2.Select,
544
+ const styles = (0, import_theme3.impactCard)({ unrated: isUnrated });
545
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: styles.row(), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: styles.rowContent(), children: [
546
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: styles.rowIcon(), children: shortLabel }),
547
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: styles.rowBody(), children: [
548
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: styles.rowHeader(), children: [
549
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: styles.rowLabel(), children: label }),
550
+ isEditing ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
551
+ import_sight3.Select,
417
552
  {
418
553
  value: String(value),
419
554
  onValueChange: (val) => onLevelChange(Number(val)),
420
555
  size: "sm",
421
556
  children: [
422
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sight2.Select.Trigger, { className: "w-36", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sight2.Select.Value, {}) }),
423
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sight2.Select.Content, { children: impactLevels.map((level) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sight2.Select.Item, { value: String(level), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "flex items-center gap-2", children: [
424
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-xs text-muted-foreground w-3", children: level }),
557
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_sight3.Select.Trigger, { className: "w-36", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_sight3.Select.Value, {}) }),
558
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_sight3.Select.Content, { children: impactLevels.map((level) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_sight3.Select.Item, { value: String(level), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "flex items-center gap-2", children: [
559
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-xs text-muted-foreground w-3", children: level }),
425
560
  formatLabel(level)
426
561
  ] }) }, level)) })
427
562
  ]
428
563
  }
429
- ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: styles.rowValue(), children: [
430
- !isUnrated && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.rowValueNumber(), children: value }),
431
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
564
+ ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: styles.rowValue(), children: [
565
+ !isUnrated && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: styles.rowValueNumber(), children: value }),
566
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
432
567
  "span",
433
568
  {
434
569
  className: styles.rowValueBadge({
@@ -439,7 +574,7 @@ function ImpactItemRow({
439
574
  )
440
575
  ] })
441
576
  ] }),
442
- !isUnrated && !isEditing && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: styles.progressContainer(), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
577
+ !isUnrated && !isEditing && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: styles.progressContainer(), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
443
578
  "div",
444
579
  {
445
580
  className: styles.progressBar({ className: config.barColor }),
@@ -465,32 +600,32 @@ function ImpactCard({
465
600
  title
466
601
  }) {
467
602
  var _a, _b;
468
- const intl = (0, import_i18n4.useSafeIntl)();
603
+ const intl = (0, import_i18n6.useSafeIntl)();
469
604
  const [isEditing, setIsEditing] = (0, import_react.useState)(false);
470
605
  const [editValues, setEditValues] = (0, import_react.useState)(
471
606
  value || defaultImpact
472
607
  );
473
- const styles = (0, import_theme2.impactCard)({ editing: isEditing });
608
+ const styles = (0, import_theme3.impactCard)({ editing: isEditing });
474
609
  const scaleConfig = typeof scale === "string" ? getScale(scale) : scale;
475
610
  const formatLabel = (level) => {
476
611
  const config = scaleConfig[level];
477
612
  return intl.formatMessage(config.message);
478
613
  };
479
614
  const t = {
480
- titleCia: intl.formatMessage(messages2.title_cia),
481
- titleCiaa: intl.formatMessage(messages2.title_ciaa),
482
- confidentiality: intl.formatMessage(messages2.confidentiality),
483
- integrity: intl.formatMessage(messages2.integrity),
484
- availability: intl.formatMessage(messages2.availability),
485
- authenticity: intl.formatMessage(messages2.authenticity),
486
- justification: intl.formatMessage(messages2.justification),
615
+ titleCia: intl.formatMessage(messages3.title_cia),
616
+ titleCiaa: intl.formatMessage(messages3.title_ciaa),
617
+ confidentiality: intl.formatMessage(messages3.confidentiality),
618
+ integrity: intl.formatMessage(messages3.integrity),
619
+ availability: intl.formatMessage(messages3.availability),
620
+ authenticity: intl.formatMessage(messages3.authenticity),
621
+ justification: intl.formatMessage(messages3.justification),
487
622
  justificationPlaceholder: intl.formatMessage(
488
- messages2.justification_placeholder
623
+ messages3.justification_placeholder
489
624
  ),
490
- noJustification: intl.formatMessage(messages2.no_justification),
491
- edit: intl.formatMessage(messages2.edit),
492
- cancel: intl.formatMessage(messages2.cancel),
493
- save: intl.formatMessage(messages2.save)
625
+ noJustification: intl.formatMessage(messages3.no_justification),
626
+ edit: intl.formatMessage(messages3.edit),
627
+ cancel: intl.formatMessage(messages3.cancel),
628
+ save: intl.formatMessage(messages3.save)
494
629
  };
495
630
  const defaultTitle = showAuthenticity ? t.titleCiaa : t.titleCia;
496
631
  const cardTitle = title != null ? title : defaultTitle;
@@ -526,31 +661,31 @@ function ImpactCard({
526
661
  (_a = currentImpact.impactAuthenticity) != null ? _a : 0
527
662
  );
528
663
  const highestLabel = formatLabel(highestImpact);
529
- const justificationHint = intl.formatMessage(messages2.justification_hint, {
664
+ const justificationHint = intl.formatMessage(messages3.justification_hint, {
530
665
  level: highestLabel
531
666
  });
532
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_sight2.Card.Root, { className: styles.root(), children: [
533
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_sight2.Card.Header, { className: "flex flex-row items-center justify-between", children: [
534
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
535
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sight2.Heading, { level: "h4", className: "text-sm font-medium", children: cardTitle }),
536
- isEditing && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sight2.Chip, { size: "sm", color: "primary", children: t.edit })
667
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_sight3.Card.Root, { className: styles.root(), children: [
668
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_sight3.Card.Header, { className: "flex flex-row items-center justify-between", children: [
669
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center gap-2", children: [
670
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_sight3.Heading, { level: "h4", className: "text-sm font-medium", children: cardTitle }),
671
+ isEditing && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_sight3.Chip, { size: "sm", color: "primary", children: t.edit })
537
672
  ] }),
538
- !readOnly && (!isEditing ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
673
+ !readOnly && (!isEditing ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
539
674
  "button",
540
675
  {
541
676
  type: "button",
542
677
  onClick: handleStartEdit,
543
678
  className: styles.editButton(),
544
679
  "aria-label": t.edit,
545
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_icons2.EditIcon, { className: "size-4" })
680
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons2.EditIcon, { className: "size-4" })
546
681
  }
547
- ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
548
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sight2.Button, { variant: "ghost", size: "sm", onClick: handleCancel, children: t.cancel }),
549
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_sight2.Button, { size: "sm", onClick: handleSave, children: t.save })
682
+ ) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center gap-2", children: [
683
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_sight3.Button, { variant: "ghost", size: "sm", onClick: handleCancel, children: t.cancel }),
684
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_sight3.Button, { size: "sm", onClick: handleSave, children: t.save })
550
685
  ] }))
551
686
  ] }),
552
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_sight2.Card.Body, { className: "space-y-3", children: [
553
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
687
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_sight3.Card.Body, { className: "space-y-3", children: [
688
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
554
689
  ImpactItemRow,
555
690
  {
556
691
  label: t.confidentiality,
@@ -562,7 +697,7 @@ function ImpactCard({
562
697
  onLevelChange: handleLevelChange("impactConfidentiality")
563
698
  }
564
699
  ),
565
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
700
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
566
701
  ImpactItemRow,
567
702
  {
568
703
  label: t.integrity,
@@ -574,7 +709,7 @@ function ImpactCard({
574
709
  onLevelChange: handleLevelChange("impactIntegrity")
575
710
  }
576
711
  ),
577
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
712
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
578
713
  ImpactItemRow,
579
714
  {
580
715
  label: t.availability,
@@ -586,7 +721,7 @@ function ImpactCard({
586
721
  onLevelChange: handleLevelChange("impactAvailability")
587
722
  }
588
723
  ),
589
- showAuthenticity && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
724
+ showAuthenticity && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
590
725
  ImpactItemRow,
591
726
  {
592
727
  label: t.authenticity,
@@ -598,20 +733,20 @@ function ImpactCard({
598
733
  onLevelChange: handleLevelChange("impactAuthenticity")
599
734
  }
600
735
  ),
601
- showJustification && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: styles.justificationSection(), children: [
602
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
736
+ showJustification && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: styles.justificationSection(), children: [
737
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
603
738
  "label",
604
739
  {
605
740
  htmlFor: "impact-justification",
606
741
  className: styles.justificationLabel(),
607
742
  children: [
608
743
  t.justification,
609
- highestImpact > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: styles.justificationHint(), children: justificationHint })
744
+ highestImpact > 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: styles.justificationHint(), children: justificationHint })
610
745
  ]
611
746
  }
612
747
  ),
613
- isEditing ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
614
- import_sight2.Textarea,
748
+ isEditing ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
749
+ import_sight3.Textarea,
615
750
  {
616
751
  id: "impact-justification",
617
752
  value: currentImpact.impactJustification || "",
@@ -620,21 +755,175 @@ function ImpactCard({
620
755
  rows: 3,
621
756
  className: "text-sm"
622
757
  }
623
- ) : currentImpact.impactJustification ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: styles.justificationText(), children: currentImpact.impactJustification }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: styles.justificationEmpty(), children: t.noJustification })
758
+ ) : currentImpact.impactJustification ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: styles.justificationText(), children: currentImpact.impactJustification }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: styles.justificationEmpty(), children: t.noJustification })
624
759
  ] })
625
760
  ] })
626
761
  ] });
627
762
  }
763
+
764
+ // src/common/risk/messages.ts
765
+ var import_i18n7 = require("@kopexa/i18n");
766
+ var messages4 = (0, import_i18n7.defineMessages)({
767
+ level_unrated: {
768
+ id: "grc.risk.level.unrated",
769
+ defaultMessage: "Not rated"
770
+ },
771
+ level_low: {
772
+ id: "grc.risk.level.low",
773
+ defaultMessage: "Low"
774
+ },
775
+ level_medium: {
776
+ id: "grc.risk.level.medium",
777
+ defaultMessage: "Medium"
778
+ },
779
+ level_high: {
780
+ id: "grc.risk.level.high",
781
+ defaultMessage: "High"
782
+ },
783
+ level_critical: {
784
+ id: "grc.risk.level.critical",
785
+ defaultMessage: "Critical"
786
+ },
787
+ likelihood: {
788
+ id: "grc.risk.likelihood",
789
+ defaultMessage: "Likelihood"
790
+ },
791
+ consequence: {
792
+ id: "grc.risk.consequence",
793
+ defaultMessage: "Consequence"
794
+ },
795
+ rating: {
796
+ id: "grc.risk.rating",
797
+ defaultMessage: "Rating"
798
+ },
799
+ not_rated_hint: {
800
+ id: "grc.risk.not_rated_hint",
801
+ defaultMessage: "Risk has not been assessed yet"
802
+ }
803
+ });
804
+
805
+ // src/common/risk/risk-rating-display.tsx
806
+ var import_i18n8 = require("@kopexa/i18n");
807
+ var import_sight4 = require("@kopexa/sight");
808
+ var import_theme4 = require("@kopexa/theme");
809
+
810
+ // src/common/risk/types.ts
811
+ function getRiskLevelFromRating(rating) {
812
+ if (rating === 0) return "unrated";
813
+ if (rating <= 4) return "low";
814
+ if (rating <= 9) return "medium";
815
+ if (rating <= 16) return "high";
816
+ return "critical";
817
+ }
818
+ function isRatingUnrated(rating) {
819
+ if (!rating) return true;
820
+ return rating.rating === 0 || rating.likelihood === 0 || rating.consequence === 0;
821
+ }
822
+ var riskLevelConfig = {
823
+ unrated: {
824
+ label: "Nicht bewertet",
825
+ bgColor: "bg-muted",
826
+ textColor: "text-muted-foreground",
827
+ iconBgColor: "bg-muted/50",
828
+ iconTextColor: "text-muted-foreground"
829
+ },
830
+ low: {
831
+ label: "Niedrig",
832
+ bgColor: "bg-success",
833
+ textColor: "text-success",
834
+ iconBgColor: "bg-success/10",
835
+ iconTextColor: "text-success"
836
+ },
837
+ medium: {
838
+ label: "Mittel",
839
+ bgColor: "bg-warning",
840
+ textColor: "text-warning",
841
+ iconBgColor: "bg-warning/10",
842
+ iconTextColor: "text-warning"
843
+ },
844
+ high: {
845
+ label: "Hoch",
846
+ bgColor: "bg-orange-500",
847
+ textColor: "text-orange-500",
848
+ iconBgColor: "bg-orange-500/10",
849
+ iconTextColor: "text-orange-500"
850
+ },
851
+ critical: {
852
+ label: "Kritisch",
853
+ bgColor: "bg-destructive",
854
+ textColor: "text-destructive",
855
+ iconBgColor: "bg-destructive/10",
856
+ iconTextColor: "text-destructive"
857
+ }
858
+ };
859
+
860
+ // src/common/risk/risk-rating-display.tsx
861
+ var import_jsx_runtime4 = require("react/jsx-runtime");
862
+ function RiskRatingDisplay({
863
+ rating,
864
+ showBadge = true,
865
+ showLabel = true,
866
+ size = "md"
867
+ }) {
868
+ const intl = (0, import_i18n8.useSafeIntl)();
869
+ if (isRatingUnrated(rating)) {
870
+ const styles2 = (0, import_theme4.riskRating)({ size, level: "unrated" });
871
+ const levelLabel2 = intl.formatMessage(messages4.level_unrated);
872
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_sight4.Tooltip, { content: intl.formatMessage(messages4.not_rated_hint), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: styles2.base(), children: [
873
+ showBadge && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: styles2.badge(), children: "\u2014" }),
874
+ showLabel && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: styles2.label(), children: levelLabel2 })
875
+ ] }) });
876
+ }
877
+ const ratedValue = rating;
878
+ const level = getRiskLevelFromRating(ratedValue.rating);
879
+ const styles = (0, import_theme4.riskRating)({
880
+ size,
881
+ level
882
+ });
883
+ const levelLabelKey = `level_${level}`;
884
+ const levelLabel = intl.formatMessage(messages4[levelLabelKey]);
885
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
886
+ import_sight4.Tooltip,
887
+ {
888
+ content: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "text-xs space-y-1", children: [
889
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
890
+ intl.formatMessage(messages4.likelihood),
891
+ ": ",
892
+ ratedValue.likelihood,
893
+ "/5"
894
+ ] }),
895
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { children: [
896
+ intl.formatMessage(messages4.consequence),
897
+ ": ",
898
+ ratedValue.consequence,
899
+ "/5"
900
+ ] }),
901
+ ratedValue.comment && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "text-muted-foreground", children: ratedValue.comment })
902
+ ] }),
903
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: styles.base(), children: [
904
+ showBadge && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: styles.badge(), children: ratedValue.rating }),
905
+ showLabel && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: styles.label(), children: levelLabel })
906
+ ] })
907
+ }
908
+ );
909
+ }
628
910
  // Annotate the CommonJS export names for ESM import in node:
629
911
  0 && (module.exports = {
630
912
  ComplianceBadges,
913
+ ControlChip,
631
914
  DoraBadge,
632
915
  ImpactCard,
916
+ MappedControls,
633
917
  Nis2Badge,
918
+ RiskRatingDisplay,
634
919
  assetScale,
920
+ getRiskLevelFromRating,
635
921
  getScale,
636
922
  impactLevels,
637
923
  impactMessages,
924
+ isRatingUnrated,
638
925
  processScale,
926
+ riskLevelConfig,
927
+ riskMessages,
639
928
  riskScale
640
929
  });