@striae-org/striae 5.2.1 → 5.3.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 (117) hide show
  1. package/.env.example +2 -10
  2. package/README.md +5 -46
  3. package/app/components/actions/case-export/core-export.ts +5 -174
  4. package/app/components/actions/case-export/download-handlers.ts +84 -751
  5. package/app/components/actions/case-export/index.ts +6 -30
  6. package/app/components/actions/case-export/metadata-helpers.ts +0 -78
  7. package/app/components/actions/case-export/types-constants.ts +0 -43
  8. package/app/components/actions/case-import/confirmation-import.ts +75 -36
  9. package/app/components/actions/case-import/confirmation-package.ts +68 -1
  10. package/app/components/actions/case-import/index.ts +1 -1
  11. package/app/components/actions/case-import/orchestrator.ts +78 -53
  12. package/app/components/actions/case-import/zip-processing.ts +160 -330
  13. package/app/components/actions/generate-pdf.ts +3 -2
  14. package/app/components/audit/user-audit-viewer.tsx +0 -19
  15. package/app/components/audit/viewer/audit-viewer-header.tsx +0 -33
  16. package/app/components/navbar/case-modals/archive-case-modal.tsx +1 -1
  17. package/app/components/navbar/case-modals/export-case-modal.module.css +27 -0
  18. package/app/components/navbar/case-modals/export-case-modal.tsx +132 -0
  19. package/app/components/navbar/case-modals/export-confirmations-modal.module.css +24 -0
  20. package/app/components/navbar/case-modals/export-confirmations-modal.tsx +108 -0
  21. package/app/components/navbar/navbar.tsx +1 -1
  22. package/app/components/sidebar/case-import/case-import.module.css +35 -0
  23. package/app/components/sidebar/case-import/components/CasePreviewSection.tsx +51 -3
  24. package/app/components/sidebar/case-import/components/ConfirmationDialog.tsx +2 -4
  25. package/app/components/sidebar/case-import/components/ConfirmationPreviewSection.tsx +36 -5
  26. package/app/components/sidebar/case-import/hooks/useFilePreview.ts +5 -9
  27. package/app/components/sidebar/case-import/index.ts +1 -4
  28. package/app/components/sidebar/notes/class-details-shared.ts +2 -2
  29. package/app/components/toast/toast.module.css +36 -0
  30. package/app/components/toast/toast.tsx +6 -2
  31. package/app/components/user/manage-profile.tsx +4 -3
  32. package/app/config-example/config.json +1 -2
  33. package/app/root.tsx +0 -7
  34. package/app/routes/_index.tsx +1 -1
  35. package/app/routes/auth/login.example.tsx +22 -103
  36. package/app/routes/auth/login.tsx +22 -103
  37. package/app/routes/auth/route.ts +1 -1
  38. package/app/routes/striae/striae.tsx +117 -59
  39. package/app/services/firebase/index.ts +0 -3
  40. package/app/types/case.ts +1 -0
  41. package/app/types/export.ts +2 -2
  42. package/app/types/import.ts +10 -0
  43. package/app/utils/auth/index.ts +0 -1
  44. package/app/utils/data/permissions.ts +3 -2
  45. package/package.json +9 -16
  46. package/public/_headers +0 -4
  47. package/public/_routes.json +0 -1
  48. package/worker-configuration.d.ts +20 -17
  49. package/workers/audit-worker/src/audit-worker.example.ts +9 -806
  50. package/workers/audit-worker/src/config.ts +7 -0
  51. package/workers/audit-worker/src/crypto/data-at-rest.ts +410 -0
  52. package/workers/audit-worker/src/handlers/audit-routes.ts +125 -0
  53. package/workers/audit-worker/src/storage/audit-storage.ts +99 -0
  54. package/workers/audit-worker/src/types.ts +56 -0
  55. package/workers/audit-worker/worker-configuration.d.ts +1 -1
  56. package/workers/audit-worker/wrangler.jsonc.example +1 -1
  57. package/workers/data-worker/src/config.ts +11 -0
  58. package/workers/data-worker/src/data-worker.example.ts +21 -942
  59. package/workers/data-worker/src/handlers/decrypt-export.ts +118 -0
  60. package/workers/data-worker/src/handlers/signing.ts +174 -0
  61. package/workers/data-worker/src/handlers/storage-routes.ts +129 -0
  62. package/workers/data-worker/src/registry/key-registry.ts +368 -0
  63. package/workers/data-worker/src/types.ts +46 -0
  64. package/workers/data-worker/worker-configuration.d.ts +1 -1
  65. package/workers/data-worker/wrangler.jsonc.example +1 -1
  66. package/workers/image-worker/worker-configuration.d.ts +1 -1
  67. package/workers/image-worker/wrangler.jsonc.example +1 -1
  68. package/workers/pdf-worker/worker-configuration.d.ts +2 -3
  69. package/workers/pdf-worker/wrangler.jsonc.example +1 -1
  70. package/workers/user-worker/src/auth.ts +30 -0
  71. package/workers/user-worker/src/cleanup/account-deletion.ts +337 -0
  72. package/workers/user-worker/src/config.ts +4 -0
  73. package/workers/user-worker/src/encryption-utils.ts +25 -0
  74. package/workers/user-worker/src/firebase/admin.ts +152 -0
  75. package/workers/user-worker/src/handlers/user-routes.ts +242 -0
  76. package/workers/user-worker/src/registry/user-kv.ts +172 -0
  77. package/workers/user-worker/src/storage/user-records.ts +34 -0
  78. package/workers/user-worker/src/types.ts +106 -0
  79. package/workers/user-worker/src/user-worker.example.ts +18 -964
  80. package/workers/user-worker/worker-configuration.d.ts +4 -2
  81. package/workers/user-worker/wrangler.jsonc.example +12 -1
  82. package/wrangler.toml.example +1 -1
  83. package/app/components/actions/case-export/data-processing.ts +0 -223
  84. package/app/components/sidebar/case-export/case-export.module.css +0 -418
  85. package/app/components/sidebar/case-export/case-export.tsx +0 -310
  86. package/app/types/exceljs-bare.d.ts +0 -9
  87. package/app/utils/auth/auth.ts +0 -11
  88. package/public/.well-known/security.txt +0 -6
  89. package/public/favicon.ico +0 -0
  90. package/public/icon-256.png +0 -0
  91. package/public/icon-512.png +0 -0
  92. package/public/manifest.json +0 -39
  93. package/public/shortcut.png +0 -0
  94. package/public/social-image.png +0 -0
  95. package/public/vendor/exceljs.LICENSE +0 -22
  96. package/public/vendor/exceljs.bare.min.js +0 -45
  97. package/scripts/deploy-all.sh +0 -166
  98. package/scripts/deploy-config/modules/env-utils.sh +0 -322
  99. package/scripts/deploy-config/modules/keys.sh +0 -404
  100. package/scripts/deploy-config/modules/prompt.sh +0 -372
  101. package/scripts/deploy-config/modules/scaffolding.sh +0 -344
  102. package/scripts/deploy-config/modules/validation.sh +0 -365
  103. package/scripts/deploy-config.sh +0 -236
  104. package/scripts/deploy-pages-secrets.sh +0 -231
  105. package/scripts/deploy-pages.sh +0 -34
  106. package/scripts/deploy-primershear-emails.sh +0 -167
  107. package/scripts/deploy-worker-secrets.sh +0 -374
  108. package/scripts/dev.cjs +0 -23
  109. package/scripts/install-workers.sh +0 -88
  110. package/scripts/run-eslint.cjs +0 -43
  111. package/scripts/update-compatibility-dates.cjs +0 -124
  112. package/scripts/update-markdown-versions.cjs +0 -43
  113. package/workers/keys-worker/package.json +0 -18
  114. package/workers/keys-worker/src/keys.example.ts +0 -67
  115. package/workers/keys-worker/src/keys.ts +0 -67
  116. package/workers/keys-worker/worker-configuration.d.ts +0 -7447
  117. package/workers/keys-worker/wrangler.jsonc.example +0 -15
@@ -1,404 +0,0 @@
1
- #!/bin/bash
2
-
3
- is_admin_service_placeholder() {
4
- local value="$1"
5
- local normalized=$(echo "$value" | tr '[:upper:]' '[:lower:]')
6
-
7
- [[ -z "$normalized" || "$normalized" == your-* || "$normalized" == *"your_private_key"* ]]
8
- }
9
-
10
- load_admin_service_credentials() {
11
- local admin_service_path="app/config/admin-service.json"
12
-
13
- if [ ! -f "$admin_service_path" ]; then
14
- echo -e "${RED}❌ Error: Required Firebase admin service file not found: $admin_service_path${NC}"
15
- echo -e "${YELLOW} Create app/config/admin-service.json with service account credentials.${NC}"
16
- exit 1
17
- fi
18
-
19
- local service_project_id
20
- local service_client_email
21
- local service_private_key
22
-
23
- if ! service_project_id=$(node -e "const fs=require('fs'); const data=JSON.parse(fs.readFileSync(process.argv[1], 'utf8')); process.stdout.write(data.project_id || '');" "$admin_service_path"); then
24
- echo -e "${RED}❌ Error: Could not parse project_id from $admin_service_path${NC}"
25
- exit 1
26
- fi
27
-
28
- if ! service_client_email=$(node -e "const fs=require('fs'); const data=JSON.parse(fs.readFileSync(process.argv[1], 'utf8')); process.stdout.write(data.client_email || '');" "$admin_service_path"); then
29
- echo -e "${RED}❌ Error: Could not parse client_email from $admin_service_path${NC}"
30
- exit 1
31
- fi
32
-
33
- if ! service_private_key=$(node -e "const fs=require('fs'); const data=JSON.parse(fs.readFileSync(process.argv[1], 'utf8')); process.stdout.write(data.private_key || '');" "$admin_service_path"); then
34
- echo -e "${RED}❌ Error: Could not parse private_key from $admin_service_path${NC}"
35
- exit 1
36
- fi
37
-
38
- local normalized_private_key="${service_private_key//$'\r'/}"
39
- normalized_private_key="${normalized_private_key//$'\n'/\\n}"
40
-
41
- if is_admin_service_placeholder "$service_project_id"; then
42
- echo -e "${RED}❌ Error: project_id in $admin_service_path is missing or placeholder${NC}"
43
- exit 1
44
- fi
45
-
46
- if is_admin_service_placeholder "$service_client_email" || [[ "$service_client_email" != *".gserviceaccount.com"* ]]; then
47
- echo -e "${RED}❌ Error: client_email in $admin_service_path is invalid${NC}"
48
- exit 1
49
- fi
50
-
51
- if is_admin_service_placeholder "$normalized_private_key" || [[ "$normalized_private_key" != *"-----BEGIN PRIVATE KEY-----"* ]] || [[ "$normalized_private_key" != *"-----END PRIVATE KEY-----"* ]]; then
52
- echo -e "${RED}❌ Error: private_key in $admin_service_path is invalid${NC}"
53
- exit 1
54
- fi
55
-
56
- PROJECT_ID="$service_project_id"
57
- export PROJECT_ID
58
- write_env_var "PROJECT_ID" "$PROJECT_ID"
59
-
60
- FIREBASE_SERVICE_ACCOUNT_EMAIL="$service_client_email"
61
- export FIREBASE_SERVICE_ACCOUNT_EMAIL
62
- write_env_var "FIREBASE_SERVICE_ACCOUNT_EMAIL" "$FIREBASE_SERVICE_ACCOUNT_EMAIL"
63
-
64
- FIREBASE_SERVICE_ACCOUNT_PRIVATE_KEY="$normalized_private_key"
65
- export FIREBASE_SERVICE_ACCOUNT_PRIVATE_KEY
66
- write_env_var "FIREBASE_SERVICE_ACCOUNT_PRIVATE_KEY" "$FIREBASE_SERVICE_ACCOUNT_PRIVATE_KEY"
67
-
68
- echo -e "${GREEN}✅ Imported Firebase service account credentials from $admin_service_path${NC}"
69
- }
70
-
71
- generate_manifest_signing_key_pair() {
72
- local private_key_file
73
- local public_key_file
74
- private_key_file=$(mktemp)
75
- public_key_file=$(mktemp)
76
-
77
- if ! node -e "const { generateKeyPairSync } = require('crypto'); const fs = require('fs'); const pair = generateKeyPairSync('rsa', { modulusLength: 2048, publicKeyEncoding: { type: 'spki', format: 'pem' }, privateKeyEncoding: { type: 'pkcs8', format: 'pem' } }); fs.writeFileSync(process.argv[1], pair.privateKey, 'utf8'); fs.writeFileSync(process.argv[2], pair.publicKey, 'utf8');" "$private_key_file" "$public_key_file"; then
78
- rm -f "$private_key_file" "$public_key_file"
79
- return 1
80
- fi
81
-
82
- local private_key_pem
83
- local public_key_pem
84
- private_key_pem=$(cat "$private_key_file")
85
- public_key_pem=$(cat "$public_key_file")
86
- rm -f "$private_key_file" "$public_key_file"
87
-
88
- private_key_pem="${private_key_pem//$'\r'/}"
89
- public_key_pem="${public_key_pem//$'\r'/}"
90
-
91
- MANIFEST_SIGNING_PRIVATE_KEY="${private_key_pem//$'\n'/\\n}"
92
- MANIFEST_SIGNING_PUBLIC_KEY="${public_key_pem//$'\n'/\\n}"
93
-
94
- export MANIFEST_SIGNING_PRIVATE_KEY
95
- export MANIFEST_SIGNING_PUBLIC_KEY
96
-
97
- write_env_var "MANIFEST_SIGNING_PRIVATE_KEY" "$MANIFEST_SIGNING_PRIVATE_KEY"
98
- write_env_var "MANIFEST_SIGNING_PUBLIC_KEY" "$MANIFEST_SIGNING_PUBLIC_KEY"
99
-
100
- return 0
101
- }
102
-
103
- configure_manifest_signing_credentials() {
104
- echo -e "${BLUE}🛡️ MANIFEST SIGNING CONFIGURATION${NC}"
105
- echo "================================="
106
-
107
- local should_generate="false"
108
- restore_env_var_from_backup_if_missing "MANIFEST_SIGNING_PRIVATE_KEY"
109
- restore_env_var_from_backup_if_missing "MANIFEST_SIGNING_PUBLIC_KEY"
110
- restore_env_var_from_backup_if_missing "MANIFEST_SIGNING_KEY_ID"
111
-
112
- if [ -z "$MANIFEST_SIGNING_PRIVATE_KEY" ] || is_placeholder "$MANIFEST_SIGNING_PRIVATE_KEY" || [ -z "$MANIFEST_SIGNING_PUBLIC_KEY" ] || is_placeholder "$MANIFEST_SIGNING_PUBLIC_KEY"; then
113
- should_generate="true"
114
- else
115
- if confirm_key_pair_regeneration "manifest signing" "Regenerating this key pair can invalidate verification for signatures tied to the previous key ID."; then
116
- should_generate="true"
117
- fi
118
- fi
119
-
120
- if [ "$should_generate" = "true" ]; then
121
- echo -e "${YELLOW}Generating manifest signing RSA key pair...${NC}"
122
- if generate_manifest_signing_key_pair; then
123
- echo -e "${GREEN}✅ Manifest signing key pair generated${NC}"
124
- else
125
- echo -e "${RED}❌ Error: Failed to generate manifest signing key pair${NC}"
126
- exit 1
127
- fi
128
- else
129
- echo -e "${GREEN}✅ Keeping current manifest signing key pair${NC}"
130
- fi
131
-
132
- if [ -z "$MANIFEST_SIGNING_KEY_ID" ] || is_placeholder "$MANIFEST_SIGNING_KEY_ID" || [ "$should_generate" = "true" ]; then
133
- local generated_key_id
134
- generated_key_id=$(generate_worker_subdomain_label)
135
- if [ -z "$generated_key_id" ] || [ ${#generated_key_id} -ne 10 ]; then
136
- echo -e "${RED}❌ Error: Failed to generate MANIFEST_SIGNING_KEY_ID${NC}"
137
- exit 1
138
- fi
139
- MANIFEST_SIGNING_KEY_ID="$generated_key_id"
140
- export MANIFEST_SIGNING_KEY_ID
141
- write_env_var "MANIFEST_SIGNING_KEY_ID" "$MANIFEST_SIGNING_KEY_ID"
142
- echo -e "${GREEN}✅ MANIFEST_SIGNING_KEY_ID generated: $MANIFEST_SIGNING_KEY_ID${NC}"
143
- else
144
- echo -e "${GREEN}✅ MANIFEST_SIGNING_KEY_ID: $MANIFEST_SIGNING_KEY_ID${NC}"
145
- fi
146
-
147
- echo ""
148
- }
149
-
150
- generate_export_encryption_key_pair() {
151
- local private_key_file
152
- local public_key_file
153
- private_key_file=$(mktemp)
154
- public_key_file=$(mktemp)
155
-
156
- if ! node -e "const { generateKeyPairSync } = require('crypto'); const fs = require('fs'); const pair = generateKeyPairSync('rsa', { modulusLength: 2048, publicKeyEncoding: { type: 'spki', format: 'pem' }, privateKeyEncoding: { type: 'pkcs8', format: 'pem' } }); fs.writeFileSync(process.argv[1], pair.privateKey, 'utf8'); fs.writeFileSync(process.argv[2], pair.publicKey, 'utf8');" "$private_key_file" "$public_key_file"; then
157
- rm -f "$private_key_file" "$public_key_file"
158
- return 1
159
- fi
160
-
161
- local private_key_pem
162
- local public_key_pem
163
- private_key_pem=$(cat "$private_key_file")
164
- public_key_pem=$(cat "$public_key_file")
165
- rm -f "$private_key_file" "$public_key_file"
166
-
167
- private_key_pem="${private_key_pem//$'\r'/}"
168
- public_key_pem="${public_key_pem//$'\r'/}"
169
-
170
- EXPORT_ENCRYPTION_PRIVATE_KEY="${private_key_pem//$'\n'/\\n}"
171
- EXPORT_ENCRYPTION_PUBLIC_KEY="${public_key_pem//$'\n'/\\n}"
172
-
173
- export EXPORT_ENCRYPTION_PRIVATE_KEY
174
- export EXPORT_ENCRYPTION_PUBLIC_KEY
175
-
176
- write_env_var "EXPORT_ENCRYPTION_PRIVATE_KEY" "$EXPORT_ENCRYPTION_PRIVATE_KEY"
177
- write_env_var "EXPORT_ENCRYPTION_PUBLIC_KEY" "$EXPORT_ENCRYPTION_PUBLIC_KEY"
178
-
179
- return 0
180
- }
181
-
182
- configure_export_encryption_credentials() {
183
- echo -e "${BLUE}🔐 EXPORT ENCRYPTION CONFIGURATION${NC}"
184
- echo "================================="
185
-
186
- local should_generate="false"
187
- restore_env_var_from_backup_if_missing "EXPORT_ENCRYPTION_PRIVATE_KEY"
188
- restore_env_var_from_backup_if_missing "EXPORT_ENCRYPTION_PUBLIC_KEY"
189
- restore_env_var_from_backup_if_missing "EXPORT_ENCRYPTION_KEY_ID"
190
- restore_env_var_from_backup_if_missing "EXPORT_ENCRYPTION_KEYS_JSON"
191
- restore_env_var_from_backup_if_missing "EXPORT_ENCRYPTION_ACTIVE_KEY_ID"
192
-
193
- if [ -z "$EXPORT_ENCRYPTION_PRIVATE_KEY" ] || is_placeholder "$EXPORT_ENCRYPTION_PRIVATE_KEY" || [ -z "$EXPORT_ENCRYPTION_PUBLIC_KEY" ] || is_placeholder "$EXPORT_ENCRYPTION_PUBLIC_KEY"; then
194
- should_generate="true"
195
- else
196
- if confirm_key_pair_regeneration "export encryption" "Regenerating this key pair can make prior encrypted exports undecryptable without migration."; then
197
- should_generate="true"
198
- fi
199
- fi
200
-
201
- if [ "$should_generate" = "true" ]; then
202
- echo -e "${YELLOW}Generating export encryption RSA key pair...${NC}"
203
- if generate_export_encryption_key_pair; then
204
- echo -e "${GREEN}✅ Export encryption key pair generated${NC}"
205
- else
206
- echo -e "${RED}❌ Error: Failed to generate export encryption key pair${NC}"
207
- exit 1
208
- fi
209
- else
210
- echo -e "${GREEN}✅ Keeping current export encryption key pair${NC}"
211
- fi
212
-
213
- if [ -z "$EXPORT_ENCRYPTION_KEY_ID" ] || is_placeholder "$EXPORT_ENCRYPTION_KEY_ID" || [ "$should_generate" = "true" ]; then
214
- local generated_key_id
215
- generated_key_id=$(generate_worker_subdomain_label)
216
- if [ -z "$generated_key_id" ] || [ ${#generated_key_id} -ne 10 ]; then
217
- echo -e "${RED}❌ Error: Failed to generate EXPORT_ENCRYPTION_KEY_ID${NC}"
218
- exit 1
219
- fi
220
- EXPORT_ENCRYPTION_KEY_ID="$generated_key_id"
221
- export EXPORT_ENCRYPTION_KEY_ID
222
- write_env_var "EXPORT_ENCRYPTION_KEY_ID" "$EXPORT_ENCRYPTION_KEY_ID"
223
- echo -e "${GREEN}✅ EXPORT_ENCRYPTION_KEY_ID generated: $EXPORT_ENCRYPTION_KEY_ID${NC}"
224
- else
225
- echo -e "${GREEN}✅ EXPORT_ENCRYPTION_KEY_ID: $EXPORT_ENCRYPTION_KEY_ID${NC}"
226
- fi
227
-
228
- update_private_key_registry "EXPORT_ENCRYPTION_KEYS_JSON" "EXPORT_ENCRYPTION_ACTIVE_KEY_ID" "$EXPORT_ENCRYPTION_KEY_ID" "$EXPORT_ENCRYPTION_PRIVATE_KEY" "export encryption"
229
-
230
- echo ""
231
- }
232
-
233
- generate_data_at_rest_encryption_key_pair() {
234
- local private_key_file
235
- local public_key_file
236
- private_key_file=$(mktemp)
237
- public_key_file=$(mktemp)
238
-
239
- if ! node -e "const { generateKeyPairSync } = require('crypto'); const fs = require('fs'); const pair = generateKeyPairSync('rsa', { modulusLength: 2048, publicKeyEncoding: { type: 'spki', format: 'pem' }, privateKeyEncoding: { type: 'pkcs8', format: 'pem' } }); fs.writeFileSync(process.argv[1], pair.privateKey, 'utf8'); fs.writeFileSync(process.argv[2], pair.publicKey, 'utf8');" "$private_key_file" "$public_key_file"; then
240
- rm -f "$private_key_file" "$public_key_file"
241
- return 1
242
- fi
243
-
244
- local private_key_pem
245
- local public_key_pem
246
- private_key_pem=$(cat "$private_key_file")
247
- public_key_pem=$(cat "$public_key_file")
248
- rm -f "$private_key_file" "$public_key_file"
249
-
250
- private_key_pem="${private_key_pem//$'\r'/}"
251
- public_key_pem="${public_key_pem//$'\r'/}"
252
-
253
- DATA_AT_REST_ENCRYPTION_PRIVATE_KEY="${private_key_pem//$'\n'/\\n}"
254
- DATA_AT_REST_ENCRYPTION_PUBLIC_KEY="${public_key_pem//$'\n'/\\n}"
255
-
256
- export DATA_AT_REST_ENCRYPTION_PRIVATE_KEY
257
- export DATA_AT_REST_ENCRYPTION_PUBLIC_KEY
258
-
259
- write_env_var "DATA_AT_REST_ENCRYPTION_PRIVATE_KEY" "$DATA_AT_REST_ENCRYPTION_PRIVATE_KEY"
260
- write_env_var "DATA_AT_REST_ENCRYPTION_PUBLIC_KEY" "$DATA_AT_REST_ENCRYPTION_PUBLIC_KEY"
261
-
262
- return 0
263
- }
264
-
265
- generate_user_kv_encryption_key_pair() {
266
- local private_key_file
267
- local public_key_file
268
- private_key_file=$(mktemp)
269
- public_key_file=$(mktemp)
270
-
271
- if ! node -e "const { generateKeyPairSync } = require('crypto'); const fs = require('fs'); const pair = generateKeyPairSync('rsa', { modulusLength: 2048, publicKeyEncoding: { type: 'spki', format: 'pem' }, privateKeyEncoding: { type: 'pkcs8', format: 'pem' } }); fs.writeFileSync(process.argv[1], pair.privateKey, 'utf8'); fs.writeFileSync(process.argv[2], pair.publicKey, 'utf8');" "$private_key_file" "$public_key_file"; then
272
- rm -f "$private_key_file" "$public_key_file"
273
- return 1
274
- fi
275
-
276
- local private_key_pem
277
- local public_key_pem
278
- private_key_pem=$(cat "$private_key_file")
279
- public_key_pem=$(cat "$public_key_file")
280
- rm -f "$private_key_file" "$public_key_file"
281
-
282
- private_key_pem="${private_key_pem//$'\r'/}"
283
- public_key_pem="${public_key_pem//$'\r'/}"
284
-
285
- USER_KV_ENCRYPTION_PRIVATE_KEY="${private_key_pem//$'\n'/\\n}"
286
- USER_KV_ENCRYPTION_PUBLIC_KEY="${public_key_pem//$'\n'/\\n}"
287
-
288
- export USER_KV_ENCRYPTION_PRIVATE_KEY
289
- export USER_KV_ENCRYPTION_PUBLIC_KEY
290
-
291
- write_env_var "USER_KV_ENCRYPTION_PRIVATE_KEY" "$USER_KV_ENCRYPTION_PRIVATE_KEY"
292
- write_env_var "USER_KV_ENCRYPTION_PUBLIC_KEY" "$USER_KV_ENCRYPTION_PUBLIC_KEY"
293
-
294
- return 0
295
- }
296
-
297
- configure_user_kv_encryption_credentials() {
298
- echo -e "${BLUE}🧑 USER KV ENCRYPTION CONFIGURATION${NC}"
299
- echo "=================================="
300
-
301
- local should_generate="false"
302
- restore_env_var_from_backup_if_missing "USER_KV_ENCRYPTION_PRIVATE_KEY"
303
- restore_env_var_from_backup_if_missing "USER_KV_ENCRYPTION_PUBLIC_KEY"
304
- restore_env_var_from_backup_if_missing "USER_KV_ENCRYPTION_KEY_ID"
305
- restore_env_var_from_backup_if_missing "USER_KV_ENCRYPTION_KEYS_JSON"
306
- restore_env_var_from_backup_if_missing "USER_KV_ENCRYPTION_ACTIVE_KEY_ID"
307
-
308
- if [ -z "$USER_KV_ENCRYPTION_PRIVATE_KEY" ] || is_placeholder "$USER_KV_ENCRYPTION_PRIVATE_KEY" || [ -z "$USER_KV_ENCRYPTION_PUBLIC_KEY" ] || is_placeholder "$USER_KV_ENCRYPTION_PUBLIC_KEY"; then
309
- should_generate="true"
310
- else
311
- if confirm_key_pair_regeneration "user KV encryption" "Regenerating this key pair or key ID without re-encryption migration can make existing user KV records undecryptable."; then
312
- should_generate="true"
313
- fi
314
- fi
315
-
316
- if [ "$should_generate" = "true" ]; then
317
- echo -e "${YELLOW}Generating user KV encryption RSA key pair...${NC}"
318
- if generate_user_kv_encryption_key_pair; then
319
- echo -e "${GREEN}✅ User KV encryption key pair generated${NC}"
320
- else
321
- echo -e "${RED}❌ Error: Failed to generate user KV encryption key pair${NC}"
322
- exit 1
323
- fi
324
- else
325
- echo -e "${GREEN}✅ Keeping current user KV encryption key pair${NC}"
326
- fi
327
-
328
- if [ -z "$USER_KV_ENCRYPTION_KEY_ID" ] || is_placeholder "$USER_KV_ENCRYPTION_KEY_ID" || [ "$should_generate" = "true" ]; then
329
- local generated_key_id
330
- generated_key_id=$(generate_worker_subdomain_label)
331
- if [ -z "$generated_key_id" ] || [ ${#generated_key_id} -ne 10 ]; then
332
- echo -e "${RED}❌ Error: Failed to generate USER_KV_ENCRYPTION_KEY_ID${NC}"
333
- exit 1
334
- fi
335
- USER_KV_ENCRYPTION_KEY_ID="$generated_key_id"
336
- export USER_KV_ENCRYPTION_KEY_ID
337
- write_env_var "USER_KV_ENCRYPTION_KEY_ID" "$USER_KV_ENCRYPTION_KEY_ID"
338
- echo -e "${GREEN}✅ USER_KV_ENCRYPTION_KEY_ID generated: $USER_KV_ENCRYPTION_KEY_ID${NC}"
339
- else
340
- echo -e "${GREEN}✅ USER_KV_ENCRYPTION_KEY_ID: $USER_KV_ENCRYPTION_KEY_ID${NC}"
341
- fi
342
-
343
- update_private_key_registry "USER_KV_ENCRYPTION_KEYS_JSON" "USER_KV_ENCRYPTION_ACTIVE_KEY_ID" "$USER_KV_ENCRYPTION_KEY_ID" "$USER_KV_ENCRYPTION_PRIVATE_KEY" "user KV encryption"
344
-
345
- echo ""
346
- }
347
-
348
- configure_data_at_rest_encryption_credentials() {
349
- echo -e "${BLUE}🗃️ DATA-AT-REST ENCRYPTION CONFIGURATION${NC}"
350
- echo "========================================"
351
-
352
- # Data-at-rest encryption is mandatory for all environments.
353
- DATA_AT_REST_ENCRYPTION_ENABLED="true"
354
-
355
- export DATA_AT_REST_ENCRYPTION_ENABLED
356
- write_env_var "DATA_AT_REST_ENCRYPTION_ENABLED" "$DATA_AT_REST_ENCRYPTION_ENABLED"
357
- echo -e "${GREEN}✅ DATA_AT_REST_ENCRYPTION_ENABLED: $DATA_AT_REST_ENCRYPTION_ENABLED${NC}"
358
-
359
- local should_generate="false"
360
- restore_env_var_from_backup_if_missing "DATA_AT_REST_ENCRYPTION_PRIVATE_KEY"
361
- restore_env_var_from_backup_if_missing "DATA_AT_REST_ENCRYPTION_PUBLIC_KEY"
362
- restore_env_var_from_backup_if_missing "DATA_AT_REST_ENCRYPTION_KEY_ID"
363
- restore_env_var_from_backup_if_missing "DATA_AT_REST_ENCRYPTION_KEYS_JSON"
364
- restore_env_var_from_backup_if_missing "DATA_AT_REST_ENCRYPTION_ACTIVE_KEY_ID"
365
-
366
- if [ -z "$DATA_AT_REST_ENCRYPTION_PRIVATE_KEY" ] || is_placeholder "$DATA_AT_REST_ENCRYPTION_PRIVATE_KEY" || [ -z "$DATA_AT_REST_ENCRYPTION_PUBLIC_KEY" ] || is_placeholder "$DATA_AT_REST_ENCRYPTION_PUBLIC_KEY"; then
367
- should_generate="true"
368
- else
369
- if confirm_key_pair_regeneration "data-at-rest encryption" "Regenerating this key pair can make previously encrypted data unreadable without migration."; then
370
- should_generate="true"
371
- fi
372
- fi
373
-
374
- if [ "$should_generate" = "true" ]; then
375
- echo -e "${YELLOW}Generating data-at-rest encryption RSA key pair...${NC}"
376
- if generate_data_at_rest_encryption_key_pair; then
377
- echo -e "${GREEN}✅ Data-at-rest encryption key pair generated${NC}"
378
- else
379
- echo -e "${RED}❌ Error: Failed to generate data-at-rest encryption key pair${NC}"
380
- exit 1
381
- fi
382
- else
383
- echo -e "${GREEN}✅ Keeping current data-at-rest encryption key pair${NC}"
384
- fi
385
-
386
- if [ -z "$DATA_AT_REST_ENCRYPTION_KEY_ID" ] || is_placeholder "$DATA_AT_REST_ENCRYPTION_KEY_ID" || [ "$should_generate" = "true" ]; then
387
- local generated_key_id
388
- generated_key_id=$(generate_worker_subdomain_label)
389
- if [ -z "$generated_key_id" ] || [ ${#generated_key_id} -ne 10 ]; then
390
- echo -e "${RED}❌ Error: Failed to generate DATA_AT_REST_ENCRYPTION_KEY_ID${NC}"
391
- exit 1
392
- fi
393
- DATA_AT_REST_ENCRYPTION_KEY_ID="$generated_key_id"
394
- export DATA_AT_REST_ENCRYPTION_KEY_ID
395
- write_env_var "DATA_AT_REST_ENCRYPTION_KEY_ID" "$DATA_AT_REST_ENCRYPTION_KEY_ID"
396
- echo -e "${GREEN}✅ DATA_AT_REST_ENCRYPTION_KEY_ID generated: $DATA_AT_REST_ENCRYPTION_KEY_ID${NC}"
397
- else
398
- echo -e "${GREEN}✅ DATA_AT_REST_ENCRYPTION_KEY_ID: $DATA_AT_REST_ENCRYPTION_KEY_ID${NC}"
399
- fi
400
-
401
- update_private_key_registry "DATA_AT_REST_ENCRYPTION_KEYS_JSON" "DATA_AT_REST_ENCRYPTION_ACTIVE_KEY_ID" "$DATA_AT_REST_ENCRYPTION_KEY_ID" "$DATA_AT_REST_ENCRYPTION_PRIVATE_KEY" "data-at-rest encryption"
402
-
403
- echo ""
404
- }