@striae-org/striae 5.3.2 → 5.4.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.
Files changed (112) hide show
  1. package/app/components/auth/auth.module.css +531 -0
  2. package/app/components/auth/mfa-enrollment.tsx +132 -79
  3. package/app/components/auth/mfa-totp-enrollment.tsx +231 -0
  4. package/app/components/auth/mfa-verification.tsx +162 -33
  5. package/app/components/{sidebar/cases/cases-modal.tsx → navbar/case-modals/all-cases-modal.tsx} +4 -4
  6. package/app/components/navbar/case-modals/archive-case-modal.tsx +9 -10
  7. package/app/components/navbar/case-modals/case-modal-shared.module.css +88 -0
  8. package/app/components/navbar/case-modals/delete-case-modal.tsx +9 -10
  9. package/app/components/navbar/case-modals/export-case-modal.tsx +9 -10
  10. package/app/components/navbar/case-modals/export-confirmations-modal.tsx +9 -10
  11. package/app/components/navbar/case-modals/open-case-modal.tsx +4 -4
  12. package/app/components/navbar/case-modals/rename-case-modal.tsx +9 -10
  13. package/app/components/navbar/navbar.tsx +1 -1
  14. package/app/components/sidebar/files/delete-files-modal.tsx +3 -3
  15. package/app/components/sidebar/files/files-modal.module.css +29 -0
  16. package/app/components/sidebar/notes/{class-details-fields.tsx → class-details/class-details-fields.tsx} +1 -1
  17. package/app/components/sidebar/notes/{class-details-modal.tsx → class-details/class-details-modal.tsx} +1 -1
  18. package/app/components/sidebar/notes/{class-details-sections.tsx → class-details/class-details-sections.tsx} +1 -1
  19. package/app/components/sidebar/notes/notes-editor-form.tsx +2 -2
  20. package/app/components/sidebar/notes/notes-editor-modal.tsx +6 -6
  21. package/app/components/sidebar/notes/notes.module.css +52 -0
  22. package/app/components/toolbar/toolbar-color-selector.tsx +8 -8
  23. package/app/components/toolbar/toolbar.module.css +181 -2
  24. package/app/components/user/delete-account.tsx +7 -7
  25. package/app/components/user/inactivity-warning.tsx +6 -6
  26. package/app/components/user/manage-profile.tsx +18 -1
  27. package/app/components/user/mfa-enrolled-factors.tsx +117 -0
  28. package/app/components/user/mfa-phone-update.tsx +8 -4
  29. package/app/components/user/mfa-totp-section.tsx +446 -0
  30. package/app/components/user/user.module.css +665 -0
  31. package/app/routes/striae/striae.tsx +1 -1
  32. package/app/services/audit/audit.service.ts +1 -1
  33. package/app/services/audit/builders/audit-event-builders-user-security.ts +4 -2
  34. package/app/services/firebase/errors.ts +2 -0
  35. package/app/utils/auth/mfa.ts +35 -1
  36. package/package.json +23 -28
  37. package/scripts/deploy-all.sh +166 -0
  38. package/scripts/deploy-config/modules/env-utils.sh +322 -0
  39. package/scripts/deploy-config/modules/keys.sh +404 -0
  40. package/scripts/deploy-config/modules/prompt.sh +375 -0
  41. package/scripts/deploy-config/modules/scaffolding.sh +310 -0
  42. package/scripts/deploy-config/modules/validation.sh +354 -0
  43. package/scripts/deploy-config.sh +236 -0
  44. package/scripts/deploy-pages-secrets.sh +231 -0
  45. package/scripts/deploy-pages.sh +34 -0
  46. package/scripts/deploy-primershear-emails.sh +167 -0
  47. package/scripts/deploy-worker-secrets.sh +385 -0
  48. package/scripts/dev.cjs +23 -0
  49. package/scripts/enable-totp-mfa.mjs +57 -0
  50. package/scripts/install-workers.sh +87 -0
  51. package/scripts/run-eslint.cjs +43 -0
  52. package/scripts/unenroll-totp-mfa.mjs +82 -0
  53. package/scripts/update-compatibility-dates.cjs +124 -0
  54. package/scripts/update-markdown-versions.cjs +43 -0
  55. package/workers/audit-worker/.editorconfig +12 -0
  56. package/workers/audit-worker/.prettierrc +6 -0
  57. package/workers/audit-worker/package.json +1 -1
  58. package/workers/audit-worker/wrangler.jsonc.example +1 -1
  59. package/workers/data-worker/.editorconfig +12 -0
  60. package/workers/data-worker/.prettierrc +6 -0
  61. package/workers/data-worker/package.json +1 -1
  62. package/workers/data-worker/wrangler.jsonc.example +1 -1
  63. package/workers/image-worker/.editorconfig +12 -0
  64. package/workers/image-worker/.prettierrc +6 -0
  65. package/workers/image-worker/package.json +1 -1
  66. package/workers/image-worker/wrangler.jsonc.example +1 -1
  67. package/workers/pdf-worker/.editorconfig +12 -0
  68. package/workers/pdf-worker/.prettierrc +6 -0
  69. package/workers/pdf-worker/package.json +1 -1
  70. package/workers/pdf-worker/wrangler.jsonc.example +1 -1
  71. package/workers/user-worker/.editorconfig +12 -0
  72. package/workers/user-worker/.prettierrc +6 -0
  73. package/workers/user-worker/package.json +1 -1
  74. package/workers/user-worker/wrangler.jsonc.example +1 -1
  75. package/wrangler.toml.example +1 -1
  76. package/app/components/auth/mfa-enrollment.module.css +0 -276
  77. package/app/components/auth/mfa-verification.module.css +0 -259
  78. package/app/components/navbar/case-modals/archive-case-modal.module.css +0 -34
  79. package/app/components/navbar/case-modals/delete-case-modal.module.css +0 -9
  80. package/app/components/navbar/case-modals/export-case-modal.module.css +0 -27
  81. package/app/components/navbar/case-modals/export-confirmations-modal.module.css +0 -24
  82. package/app/components/navbar/case-modals/open-case-modal.module.css +0 -82
  83. package/app/components/navbar/case-modals/rename-case-modal.module.css +0 -9
  84. package/app/components/sidebar/files/delete-files-modal.module.css +0 -26
  85. package/app/components/sidebar/notes/notes-editor-modal.module.css +0 -49
  86. package/app/components/toolbar/toolbar-color-selector.module.css +0 -171
  87. package/app/components/user/delete-account.module.css +0 -277
  88. package/app/components/user/inactivity-warning.module.css +0 -148
  89. package/app/components/user/manage-profile.module.css +0 -192
  90. package/app/routes/auth/login.module.css +0 -523
  91. package/app/routes/auth/login.tsx +0 -705
  92. package/workers/audit-worker/worker-configuration.d.ts +0 -7448
  93. package/workers/data-worker/worker-configuration.d.ts +0 -7448
  94. package/workers/image-worker/worker-configuration.d.ts +0 -7448
  95. package/workers/pdf-worker/worker-configuration.d.ts +0 -7447
  96. package/workers/user-worker/worker-configuration.d.ts +0 -7450
  97. /package/app/components/{sidebar → navbar}/case-import/case-import.module.css +0 -0
  98. /package/app/components/{sidebar → navbar}/case-import/case-import.tsx +0 -0
  99. /package/app/components/{sidebar → navbar}/case-import/components/CasePreviewSection.tsx +0 -0
  100. /package/app/components/{sidebar → navbar}/case-import/components/ConfirmationDialog.tsx +0 -0
  101. /package/app/components/{sidebar → navbar}/case-import/components/ConfirmationPreviewSection.tsx +0 -0
  102. /package/app/components/{sidebar → navbar}/case-import/components/ExistingCaseSection.tsx +0 -0
  103. /package/app/components/{sidebar → navbar}/case-import/components/FileSelector.tsx +0 -0
  104. /package/app/components/{sidebar → navbar}/case-import/components/ProgressSection.tsx +0 -0
  105. /package/app/components/{sidebar → navbar}/case-import/hooks/useFilePreview.ts +0 -0
  106. /package/app/components/{sidebar → navbar}/case-import/hooks/useImportExecution.ts +0 -0
  107. /package/app/components/{sidebar → navbar}/case-import/hooks/useImportState.ts +0 -0
  108. /package/app/components/{sidebar → navbar}/case-import/index.ts +0 -0
  109. /package/app/components/{sidebar → navbar}/case-import/utils/file-validation.ts +0 -0
  110. /package/app/components/{sidebar/cases/cases-modal.module.css → navbar/case-modals/all-cases-modal.module.css} +0 -0
  111. /package/app/components/sidebar/notes/{class-details-shared.ts → class-details/class-details-shared.ts} +0 -0
  112. /package/app/components/sidebar/notes/{use-class-details-state.ts → class-details/use-class-details-state.ts} +0 -0
@@ -0,0 +1,665 @@
1
+ /* ─── Manage Profile ────────────────────────────────────────────────────── */
2
+
3
+ /* Modal Overlay & Container */
4
+ .modalOverlay {
5
+ position: fixed;
6
+ inset: 0;
7
+ background-color: color-mix(in lab, var(--background) 50%, transparent);
8
+ display: flex;
9
+ justify-content: center;
10
+ align-items: center;
11
+ z-index: var(--zIndex5);
12
+ cursor: default;
13
+ transition: background-color var(--durationM) var(--bezierFastoutSlowin);
14
+ }
15
+
16
+ .modal {
17
+ background: var(--backgroundLight);
18
+ border-radius: var(--spaceXS);
19
+ width: 90%;
20
+ max-width: 500px;
21
+ max-height: min(90vh, 90vw);
22
+ box-shadow: 0 var(--spaceXS) var(--spaceL)
23
+ color-mix(in lab, var(--black) 10%, transparent);
24
+ display: flex;
25
+ flex-direction: column;
26
+ transition: background-color var(--durationM) var(--bezierFastoutSlowin);
27
+ overflow: hidden;
28
+ cursor: default;
29
+ }
30
+
31
+ /* Modal Header */
32
+ .modalHeader {
33
+ display: flex;
34
+ justify-content: space-between;
35
+ align-items: center;
36
+ padding: var(--spaceL);
37
+ font-size: var(--fontSizeBodyL);
38
+ border-bottom: 1px solid color-mix(in lab, var(--text) 10%, transparent);
39
+ color: var(--textTitle);
40
+ }
41
+
42
+ .modalHeader h1 {
43
+ font-size: var(--fontSizeBodyM);
44
+ margin: 0;
45
+ font-weight: var(--fontWeightMedium);
46
+ }
47
+
48
+ /* Close Button */
49
+ .closeButton {
50
+ background: none;
51
+ border: none;
52
+ font-size: var(--fontSizeH5);
53
+ cursor: pointer;
54
+ padding: var(--spaceS);
55
+ color: var(--textLight);
56
+ transition: color var(--durationS) var(--bezierFastoutSlowin);
57
+ }
58
+
59
+ .closeButton:hover {
60
+ color: var(--text);
61
+ }
62
+
63
+ /* Form & Form Groups */
64
+ .form {
65
+ display: flex;
66
+ flex-direction: column;
67
+ flex: 1 1 auto;
68
+ min-height: 0;
69
+ gap: var(--spaceL);
70
+ width: 100%;
71
+ max-width: 100%;
72
+ padding: var(--spaceL);
73
+ margin: 0 auto;
74
+ box-sizing: border-box;
75
+ overflow-y: auto;
76
+ }
77
+
78
+ .formGroup {
79
+ margin-bottom: var(--spaceXS);
80
+ }
81
+
82
+ .formGroup label {
83
+ display: block;
84
+ margin-bottom: var(--spaceS);
85
+ color: var(--textBody);
86
+ }
87
+
88
+ /* Readonly Input Styling (for company/email fields) */
89
+ .input {
90
+ width: 100%;
91
+ padding: var(--spaceM);
92
+ border: 1.5px solid color-mix(in lab, var(--text) 20%, transparent);
93
+ border-radius: var(--spaceXS);
94
+ font-size: var(--fontSizeBodyS);
95
+ background: var(--backgroundLight);
96
+ color: var(--textBody);
97
+ box-sizing: border-box;
98
+ }
99
+
100
+ .input:disabled {
101
+ background-color: color-mix(in lab, var(--background) 95%, transparent);
102
+ cursor: not-allowed;
103
+ }
104
+
105
+ /* Helper Text */
106
+ .helpText {
107
+ font-size: var(--fontSizeBodyXS);
108
+ color: var(--textLight);
109
+ margin-top: var(--spaceXS);
110
+ line-height: 1.4;
111
+ }
112
+
113
+ /* Button Group */
114
+ .buttonGroup {
115
+ display: flex;
116
+ gap: var(--spaceS);
117
+ margin-top: var(--spaceL);
118
+ }
119
+
120
+ .mfaVerificationSection {
121
+ margin-top: var(--spaceM);
122
+ }
123
+
124
+ .mfaReauthSection {
125
+ margin-top: var(--spaceM);
126
+ display: flex;
127
+ flex-direction: column;
128
+ gap: var(--spaceS);
129
+ }
130
+
131
+ .mfaReauthSection label {
132
+ color: var(--textBody);
133
+ }
134
+
135
+ .mfaButtonGroup {
136
+ display: flex;
137
+ gap: var(--spaceS);
138
+ flex-wrap: wrap;
139
+ margin-top: var(--spaceS);
140
+ }
141
+
142
+ .resendTimer {
143
+ margin: 0;
144
+ font-size: var(--fontSizeBodyXS);
145
+ color: var(--textLight);
146
+ display: inline-flex;
147
+ align-items: center;
148
+ }
149
+
150
+ .recaptchaContainer {
151
+ height: 0;
152
+ overflow: hidden;
153
+ }
154
+
155
+ /* ─── Section label (replaces bare <label> for non-input groups) ─────────── */
156
+ .sectionLabel {
157
+ display: block;
158
+ font-weight: 600;
159
+ color: var(--textBody);
160
+ margin-bottom: var(--spaceS);
161
+ }
162
+
163
+ /* ─── Enrolled MFA Factors List ─────────────────────────────────────────── */
164
+
165
+ .enrolledFactorsList {
166
+ list-style: none;
167
+ margin: var(--spaceS) 0 0 0;
168
+ padding: 0;
169
+ display: flex;
170
+ flex-direction: column;
171
+ gap: var(--spaceS);
172
+ }
173
+
174
+ .enrolledFactorItem {
175
+ display: flex;
176
+ align-items: center;
177
+ justify-content: space-between;
178
+ gap: var(--spaceM);
179
+ padding: var(--spaceM);
180
+ border: 1px solid color-mix(in lab, var(--text) 12%, transparent);
181
+ border-radius: var(--spaceXS);
182
+ background: color-mix(in lab, var(--background) 97%, transparent);
183
+ }
184
+
185
+ .enrolledFactorInfo {
186
+ display: flex;
187
+ flex-direction: column;
188
+ gap: 2px;
189
+ min-width: 0;
190
+ }
191
+
192
+ .enrolledFactorLabel {
193
+ font-size: var(--fontSizeBodyS);
194
+ font-weight: var(--fontWeightMedium);
195
+ color: var(--textTitle);
196
+ }
197
+
198
+ .enrolledFactorName {
199
+ font-size: var(--fontSizeBodyXS);
200
+ color: var(--textBody);
201
+ white-space: nowrap;
202
+ overflow: hidden;
203
+ text-overflow: ellipsis;
204
+ }
205
+
206
+ .enrolledFactorDate {
207
+ font-size: var(--fontSizeBodyXS);
208
+ color: var(--textLight);
209
+ }
210
+
211
+ .enrolledFactorsNote {
212
+ font-size: var(--fontSizeBodyXS);
213
+ color: var(--textLight);
214
+ margin: var(--spaceXS) 0 0 0;
215
+ }
216
+
217
+ /* Delete Button (error variant) */
218
+ .deleteButton {
219
+ background-color: var(--error);
220
+ color: var(--white);
221
+ border: none;
222
+ padding: var(--spaceM) var(--spaceL);
223
+ border-radius: var(--spaceXS);
224
+ font-weight: var(--fontWeightMedium);
225
+ cursor: pointer;
226
+ transition: all var(--durationS) var(--bezierFastoutSlowin);
227
+ margin-top: var(--spaceXL);
228
+ width: 100%;
229
+ font-size: var(--fontSizeBodyS);
230
+ }
231
+
232
+ .deleteButton:hover:not(:disabled) {
233
+ background-color: color-mix(in lab, var(--error) 85%, var(--black));
234
+ }
235
+
236
+ .deleteButton:focus {
237
+ outline: 2px solid var(--error);
238
+ outline-offset: 2px;
239
+ }
240
+
241
+ .deleteNotice {
242
+ margin-top: var(--spaceXL);
243
+ font-size: var(--fontSizeBodyXS);
244
+ text-align: center;
245
+ color: var(--textLight);
246
+ }
247
+
248
+ .deleteLink {
249
+ color: var(--error);
250
+ text-decoration: underline;
251
+ transition: color var(--durationS) var(--bezierFastoutSlowin);
252
+ }
253
+
254
+ .deleteLink:hover {
255
+ color: color-mix(in lab, var(--error) 85%, var(--black));
256
+ }
257
+
258
+ /* ─── Delete Account ────────────────────────────────────────────────────── */
259
+
260
+ .deleteAccountModal {
261
+ background: var(--backgroundLight);
262
+ border-radius: var(--spaceXS);
263
+ width: 90%;
264
+ max-width: 600px;
265
+ box-shadow: 0 var(--spaceXS) var(--spaceL)
266
+ color-mix(in lab, var(--black) 10%, transparent);
267
+ transition: background-color var(--durationM) var(--bezierFastoutSlowin);
268
+ overflow: hidden;
269
+ max-height: 90vh;
270
+ overflow-y: auto;
271
+ cursor: default;
272
+ }
273
+
274
+ .dangerModalHeader {
275
+ display: flex;
276
+ justify-content: space-between;
277
+ align-items: center;
278
+ padding: var(--spaceL);
279
+ border-bottom: 2px solid var(--error);
280
+ background-color: color-mix(in lab, var(--error) 5%, transparent);
281
+ }
282
+
283
+ .dangerTitle {
284
+ font-size: var(--fontSizeBodyL);
285
+ margin: 0;
286
+ font-weight: var(--fontWeightMedium);
287
+ color: var(--error);
288
+ }
289
+
290
+ .dangerCloseButton {
291
+ background: none;
292
+ border: none;
293
+ font-size: var(--fontSizeH5);
294
+ cursor: pointer;
295
+ padding: var(--spaceS);
296
+ color: var(--textLight);
297
+ transition: color var(--durationS) var(--bezierFastoutSlowin);
298
+ }
299
+
300
+ .dangerCloseButton:hover {
301
+ color: var(--error);
302
+ }
303
+
304
+ .modalContent {
305
+ padding: var(--spaceL);
306
+ }
307
+
308
+ .divider {
309
+ height: 1px;
310
+ background-color: color-mix(in lab, var(--text) 15%, transparent);
311
+ margin: var(--spaceL) 0;
312
+ }
313
+
314
+ .userInfo {
315
+ display: flex;
316
+ flex-direction: column;
317
+ gap: var(--spaceM);
318
+ }
319
+
320
+ .infoRow {
321
+ display: flex;
322
+ flex-direction: column;
323
+ gap: var(--spaceXS);
324
+ }
325
+
326
+ .label {
327
+ font-weight: var(--fontWeightMedium);
328
+ color: var(--textTitle);
329
+ font-size: var(--fontSizeBodyS);
330
+ }
331
+
332
+ .value {
333
+ color: var(--textBody);
334
+ font-size: var(--fontSizeBodyS);
335
+ padding: var(--spaceS);
336
+ background-color: color-mix(in lab, var(--text) 5%, transparent);
337
+ border-radius: var(--spaceXS);
338
+ border: 1px solid color-mix(in lab, var(--text) 10%, transparent);
339
+ font-family: monospace;
340
+ word-break: break-all;
341
+ }
342
+
343
+ .warningSection {
344
+ text-align: center;
345
+ }
346
+
347
+ .warningText {
348
+ color: var(--error);
349
+ font-weight: var(--fontWeightMedium);
350
+ font-size: var(--fontSizeBodyM);
351
+ line-height: 1.5;
352
+ margin: 0;
353
+ padding: var(--spaceL);
354
+ background-color: color-mix(in lab, var(--error) 8%, transparent);
355
+ border: 1px solid color-mix(in lab, var(--error) 25%, transparent);
356
+ border-radius: var(--spaceXS);
357
+ }
358
+
359
+ .progressSection {
360
+ margin: var(--spaceL) 0;
361
+ padding: var(--spaceM);
362
+ border-radius: var(--spaceXS);
363
+ border: 1px solid color-mix(in lab, var(--error) 25%, transparent);
364
+ background-color: color-mix(in lab, var(--error) 8%, transparent);
365
+ }
366
+
367
+ .progressHeader {
368
+ display: flex;
369
+ justify-content: space-between;
370
+ gap: var(--spaceM);
371
+ margin-bottom: var(--spaceS);
372
+ }
373
+
374
+ .progressTitle {
375
+ margin: 0;
376
+ color: var(--error);
377
+ font-weight: var(--fontWeightMedium);
378
+ font-size: var(--fontSizeBodyS);
379
+ }
380
+
381
+ .progressMeta {
382
+ margin: 0;
383
+ color: var(--textBody);
384
+ font-size: var(--fontSizeBodyS);
385
+ }
386
+
387
+ .progressTrack {
388
+ width: 100%;
389
+ height: var(--spaceM);
390
+ border-radius: var(--spaceXL);
391
+ overflow: hidden;
392
+ background-color: color-mix(in lab, var(--error) 18%, transparent);
393
+ border: 1px solid color-mix(in lab, var(--error) 25%, transparent);
394
+ }
395
+
396
+ .progressFill {
397
+ height: 100%;
398
+ width: 0;
399
+ background-color: var(--error);
400
+ transition: width var(--durationS) var(--bezierFastoutSlowin);
401
+ }
402
+
403
+ .progressStatus {
404
+ margin: var(--spaceS) 0 0;
405
+ color: var(--error);
406
+ font-size: var(--fontSizeBodyS);
407
+ font-weight: var(--fontWeightMedium);
408
+ word-break: break-word;
409
+ }
410
+
411
+ .errorMessage {
412
+ background-color: color-mix(in lab, var(--error) 10%, transparent);
413
+ color: var(--error);
414
+ border: 1px solid color-mix(in lab, var(--error) 25%, transparent);
415
+ padding: var(--spaceM);
416
+ border-radius: var(--spaceXS);
417
+ margin: var(--spaceL) 0;
418
+ text-align: center;
419
+ }
420
+
421
+ .errorMessage p {
422
+ margin: 0;
423
+ font-weight: var(--fontWeightMedium);
424
+ }
425
+
426
+ .successMessage {
427
+ background-color: color-mix(in lab, var(--accent) 10%, transparent);
428
+ color: var(--accent);
429
+ border: 1px solid color-mix(in lab, var(--accent) 25%, transparent);
430
+ padding: var(--spaceM);
431
+ border-radius: var(--spaceXS);
432
+ margin: var(--spaceL) 0;
433
+ text-align: center;
434
+ }
435
+
436
+ .successMessage p {
437
+ margin: 0;
438
+ font-weight: var(--fontWeightMedium);
439
+ }
440
+
441
+ .successMessage p:first-child {
442
+ margin-bottom: var(--spaceS);
443
+ }
444
+
445
+ .confirmationForm {
446
+ display: flex;
447
+ flex-direction: column;
448
+ gap: var(--spaceL);
449
+ }
450
+
451
+ .deleteFormGroup {
452
+ display: flex;
453
+ flex-direction: column;
454
+ gap: var(--spaceS);
455
+ }
456
+
457
+ .formLabel {
458
+ font-weight: var(--fontWeightMedium);
459
+ color: var(--textTitle);
460
+ font-size: var(--fontSizeBodyS);
461
+ }
462
+
463
+ .confirmationInput {
464
+ width: 100%;
465
+ padding: var(--spaceM);
466
+ border: 2px solid color-mix(in lab, var(--error) 30%, transparent);
467
+ border-radius: var(--spaceXS);
468
+ font-size: var(--fontSizeBodyS);
469
+ background: var(--backgroundLight);
470
+ color: var(--textBody);
471
+ transition: all var(--durationS) var(--bezierFastoutSlowin);
472
+ box-sizing: border-box;
473
+ font-family: monospace;
474
+ }
475
+
476
+ .confirmationInput:focus {
477
+ outline: none;
478
+ border-color: var(--error);
479
+ box-shadow: 0 0 0 2px color-mix(in lab, var(--error) 25%, transparent);
480
+ }
481
+
482
+ .confirmationInput::placeholder {
483
+ color: var(--textLight);
484
+ font-family: inherit;
485
+ }
486
+
487
+ .deleteAccountButton {
488
+ background-color: var(--error);
489
+ color: var(--white);
490
+ border: none;
491
+ padding: var(--spaceL) var(--spaceXL);
492
+ border-radius: var(--spaceXS);
493
+ font-weight: var(--fontWeightMedium);
494
+ font-size: var(--fontSizeBodyM);
495
+ cursor: pointer;
496
+ transition: all var(--durationS) var(--bezierFastoutSlowin);
497
+ margin-top: var(--spaceL);
498
+ width: 100%;
499
+ }
500
+
501
+ .deleteAccountButton:hover:not(:disabled) {
502
+ background-color: color-mix(in lab, var(--error) 85%, var(--black));
503
+ }
504
+
505
+ .deleteAccountButton:focus:not(:disabled) {
506
+ outline: 2px solid var(--error);
507
+ outline-offset: 2px;
508
+ }
509
+
510
+ .deleteAccountButton:disabled {
511
+ background-color: color-mix(in lab, var(--text) 20%, transparent);
512
+ color: var(--textLight);
513
+ cursor: not-allowed;
514
+ }
515
+
516
+ /* ─── Inactivity Warning ────────────────────────────────────────────────── */
517
+
518
+ .inactivityOverlay {
519
+ position: fixed;
520
+ top: 0;
521
+ left: 0;
522
+ right: 0;
523
+ bottom: 0;
524
+ background-color: rgba(0, 0, 0, 0.8);
525
+ display: flex;
526
+ justify-content: center;
527
+ align-items: center;
528
+ z-index: 9999;
529
+ backdrop-filter: blur(2px);
530
+ cursor: default;
531
+ }
532
+
533
+ .inactivityModal {
534
+ position: relative;
535
+ background: #ffffff;
536
+ border-radius: 12px;
537
+ padding: 2rem;
538
+ max-width: 400px;
539
+ width: 90%;
540
+ box-shadow: 0 20px 40px rgba(0, 0, 0, 0.4);
541
+ border: 1px solid #e0e0e0;
542
+ animation: inactivitySlideIn 0.3s ease-out;
543
+ cursor: default;
544
+ }
545
+
546
+ @keyframes inactivitySlideIn {
547
+ from {
548
+ opacity: 0;
549
+ transform: translateY(-20px) scale(0.95);
550
+ }
551
+ to {
552
+ opacity: 1;
553
+ transform: translateY(0) scale(1);
554
+ }
555
+ }
556
+
557
+ .inactivityHeader {
558
+ text-align: center;
559
+ margin-bottom: 1.5rem;
560
+ }
561
+
562
+ .inactivityHeader h3 {
563
+ color: #1a1a1a;
564
+ font-size: 1.25rem;
565
+ font-weight: 600;
566
+ margin: 0;
567
+ }
568
+
569
+ .inactivityContent {
570
+ text-align: center;
571
+ margin-bottom: 2rem;
572
+ }
573
+
574
+ .inactivityContent p {
575
+ color: #4a4a4a;
576
+ margin: 0 0 1rem 0;
577
+ line-height: 1.5;
578
+ font-size: 1rem;
579
+ }
580
+
581
+ .countdown {
582
+ font-size: 2rem;
583
+ font-weight: bold;
584
+ color: #dc3545;
585
+ font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
586
+ background: rgba(220, 53, 69, 0.1);
587
+ padding: 1rem;
588
+ border-radius: 8px;
589
+ margin: 1rem 0;
590
+ border: 2px solid rgba(220, 53, 69, 0.2);
591
+ }
592
+
593
+ .inactivityActions {
594
+ display: flex;
595
+ gap: 1rem;
596
+ justify-content: center;
597
+ }
598
+
599
+ .extendButton,
600
+ .signOutButton {
601
+ padding: 0.75rem 1.5rem;
602
+ border-radius: 6px;
603
+ border: none;
604
+ font-weight: 500;
605
+ cursor: pointer;
606
+ transition: all 0.2s ease;
607
+ font-size: 0.9rem;
608
+ }
609
+
610
+ .extendButton {
611
+ background: #007bff;
612
+ color: white;
613
+ }
614
+
615
+ .extendButton:hover {
616
+ background: #0056b3;
617
+ }
618
+
619
+ .signOutButton {
620
+ background: transparent;
621
+ color: #6c757d;
622
+ border: 1px solid #dee2e6;
623
+ }
624
+
625
+ .signOutButton:hover {
626
+ background: #f8f9fa;
627
+ color: #495057;
628
+ border-color: #adb5bd;
629
+ }
630
+
631
+ .extendButton:focus,
632
+ .signOutButton:focus {
633
+ outline: 2px solid #007bff;
634
+ outline-offset: 2px;
635
+ }
636
+
637
+ @media (prefers-color-scheme: dark) {
638
+ .inactivityOverlay {
639
+ background-color: rgba(0, 0, 0, 0.9);
640
+ }
641
+
642
+ .inactivityModal {
643
+ background: #2d2d2d;
644
+ border-color: #404040;
645
+ }
646
+
647
+ .inactivityHeader h3 {
648
+ color: #ffffff;
649
+ }
650
+
651
+ .inactivityContent p {
652
+ color: #cccccc;
653
+ }
654
+
655
+ .signOutButton {
656
+ color: #adb5bd;
657
+ border-color: #6c757d;
658
+ }
659
+
660
+ .signOutButton:hover {
661
+ background: #404040;
662
+ color: #ffffff;
663
+ border-color: #adb5bd;
664
+ }
665
+ }
@@ -14,7 +14,7 @@ import { getImageUrl, fetchFiles, deleteFile } from '~/components/actions/image-
14
14
  import { getNotes, saveNotes } from '~/components/actions/notes-manage';
15
15
  import { generatePDF } from '~/components/actions/generate-pdf';
16
16
  import { exportConfirmationData } from '~/components/actions/confirm-export';
17
- import { CasesModal } from '~/components/sidebar/cases/cases-modal';
17
+ import { CasesModal } from '~/components/navbar/case-modals/all-cases-modal';
18
18
  import { FilesModal } from '~/components/sidebar/files/files-modal';
19
19
  import { NotesEditorModal } from '~/components/sidebar/notes/notes-editor-modal';
20
20
  import { UserAuditViewer } from '~/components/audit/user-audit-viewer';
@@ -784,7 +784,7 @@ class AuditService {
784
784
  */
785
785
  public async logMfaEnrollment(
786
786
  user: User,
787
- phoneNumber: string,
787
+ phoneNumber: string | undefined,
788
788
  mfaMethod: 'sms' | 'totp' | 'hardware-key',
789
789
  result: AuditResult,
790
790
  enrollmentAttempts?: number,
@@ -216,7 +216,7 @@ export const buildUserRegistrationAuditParams = (
216
216
 
217
217
  interface BuildMfaEnrollmentAuditParamsInput {
218
218
  user: User;
219
- phoneNumber: string;
219
+ phoneNumber?: string;
220
220
  mfaMethod: 'sms' | 'totp' | 'hardware-key';
221
221
  result: AuditResult;
222
222
  enrollmentAttempts?: number;
@@ -249,7 +249,9 @@ export const buildMfaEnrollmentAuditParams = (
249
249
  : { userAgent: input.userAgent },
250
250
  securityDetails: {
251
251
  mfaMethod: input.mfaMethod,
252
- phoneNumber: getMaskedPhoneNumber(input.phoneNumber),
252
+ ...(input.mfaMethod === 'sms' && input.phoneNumber
253
+ ? { phoneNumber: getMaskedPhoneNumber(input.phoneNumber) }
254
+ : {}),
253
255
  enrollmentAttempts: input.enrollmentAttempts,
254
256
  enrollmentDate: new Date().toISOString(),
255
257
  mandatoryEnrollment: true,
@@ -30,6 +30,8 @@ export const ERROR_MESSAGES = {
30
30
  MFA_RECAPTCHA_ERROR: 'reCAPTCHA needs to be reset. Please send another code.',
31
31
  MFA_CODE_REQUIRED: 'Please enter the verification code',
32
32
 
33
+ MFA_TOTP_SETUP_ERROR: 'Failed to set up authenticator. Please try again.',
34
+
33
35
  // General
34
36
  GENERAL_ERROR: 'Something went wrong. Please contact support.',
35
37
  NO_USER: 'No user found',