@striae-org/striae 5.3.1 → 5.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +3 -0
- package/app/components/actions/generate-pdf.ts +22 -0
- package/app/components/auth/auth.module.css +531 -0
- package/app/components/auth/mfa-enrollment.tsx +132 -79
- package/app/components/auth/mfa-totp-enrollment.tsx +231 -0
- package/app/components/auth/mfa-verification.tsx +155 -33
- package/app/components/{sidebar/cases/cases-modal.tsx → navbar/case-modals/all-cases-modal.tsx} +4 -4
- package/app/components/navbar/case-modals/archive-case-modal.tsx +9 -10
- package/app/components/navbar/case-modals/case-modal-shared.module.css +88 -0
- package/app/components/navbar/case-modals/delete-case-modal.tsx +9 -10
- package/app/components/navbar/case-modals/export-case-modal.tsx +9 -10
- package/app/components/navbar/case-modals/export-confirmations-modal.tsx +9 -10
- package/app/components/navbar/case-modals/open-case-modal.tsx +4 -4
- package/app/components/navbar/case-modals/rename-case-modal.tsx +9 -10
- package/app/components/navbar/navbar.tsx +1 -1
- package/app/components/sidebar/files/delete-files-modal.tsx +3 -3
- package/app/components/sidebar/files/files-modal.module.css +29 -0
- package/app/components/sidebar/notes/{class-details-fields.tsx → class-details/class-details-fields.tsx} +1 -1
- package/app/components/sidebar/notes/{class-details-modal.tsx → class-details/class-details-modal.tsx} +1 -1
- package/app/components/sidebar/notes/{class-details-sections.tsx → class-details/class-details-sections.tsx} +1 -1
- package/app/components/sidebar/notes/notes-editor-form.tsx +2 -2
- package/app/components/sidebar/notes/notes-editor-modal.tsx +6 -6
- package/app/components/sidebar/notes/notes.module.css +52 -0
- package/app/components/toolbar/toolbar-color-selector.tsx +8 -8
- package/app/components/toolbar/toolbar.module.css +181 -2
- package/app/components/user/delete-account.tsx +7 -7
- package/app/components/user/inactivity-warning.tsx +6 -6
- package/app/components/user/manage-profile.tsx +18 -1
- package/app/components/user/mfa-enrolled-factors.tsx +117 -0
- package/app/components/user/mfa-phone-update.tsx +8 -4
- package/app/components/user/mfa-totp-section.tsx +446 -0
- package/app/components/user/user.module.css +665 -0
- package/app/routes/striae/striae.tsx +1 -1
- package/app/services/audit/audit.service.ts +1 -1
- package/app/services/audit/builders/audit-event-builders-user-security.ts +4 -2
- package/app/services/firebase/errors.ts +2 -0
- package/app/utils/auth/mfa.ts +35 -1
- package/functions/api/image/[[path]].ts +19 -3
- package/package.json +16 -21
- package/scripts/deploy-all.sh +166 -0
- package/scripts/deploy-config/modules/env-utils.sh +322 -0
- package/scripts/deploy-config/modules/keys.sh +404 -0
- package/scripts/deploy-config/modules/prompt.sh +375 -0
- package/scripts/deploy-config/modules/scaffolding.sh +310 -0
- package/scripts/deploy-config/modules/validation.sh +354 -0
- package/scripts/deploy-config.sh +236 -0
- package/scripts/deploy-pages-secrets.sh +231 -0
- package/scripts/deploy-pages.sh +34 -0
- package/scripts/deploy-primershear-emails.sh +167 -0
- package/scripts/deploy-worker-secrets.sh +385 -0
- package/scripts/dev.cjs +23 -0
- package/scripts/enable-totp-mfa.mjs +57 -0
- package/scripts/install-workers.sh +87 -0
- package/scripts/run-eslint.cjs +43 -0
- package/scripts/update-compatibility-dates.cjs +124 -0
- package/scripts/update-markdown-versions.cjs +43 -0
- package/workers/audit-worker/package.json +1 -1
- package/workers/audit-worker/wrangler.jsonc.example +1 -1
- package/workers/data-worker/package.json +1 -1
- package/workers/data-worker/wrangler.jsonc.example +1 -1
- package/workers/image-worker/package.json +1 -1
- package/workers/image-worker/src/image-worker.example.ts +36 -2
- package/workers/image-worker/wrangler.jsonc.example +1 -1
- package/workers/pdf-worker/package.json +1 -1
- package/workers/pdf-worker/wrangler.jsonc.example +1 -1
- package/workers/user-worker/package.json +1 -1
- package/workers/user-worker/wrangler.jsonc.example +1 -1
- package/wrangler.toml.example +1 -1
- package/app/components/auth/mfa-enrollment.module.css +0 -276
- package/app/components/auth/mfa-verification.module.css +0 -259
- package/app/components/navbar/case-modals/archive-case-modal.module.css +0 -34
- package/app/components/navbar/case-modals/delete-case-modal.module.css +0 -9
- package/app/components/navbar/case-modals/export-case-modal.module.css +0 -27
- package/app/components/navbar/case-modals/export-confirmations-modal.module.css +0 -24
- package/app/components/navbar/case-modals/open-case-modal.module.css +0 -82
- package/app/components/navbar/case-modals/rename-case-modal.module.css +0 -9
- package/app/components/sidebar/files/delete-files-modal.module.css +0 -26
- package/app/components/sidebar/notes/notes-editor-modal.module.css +0 -49
- package/app/components/toolbar/toolbar-color-selector.module.css +0 -171
- package/app/components/user/delete-account.module.css +0 -277
- package/app/components/user/inactivity-warning.module.css +0 -148
- package/app/components/user/manage-profile.module.css +0 -192
- package/app/routes/auth/login.module.css +0 -523
- package/app/routes/auth/login.tsx +0 -705
- /package/app/components/{sidebar → navbar}/case-import/case-import.module.css +0 -0
- /package/app/components/{sidebar → navbar}/case-import/case-import.tsx +0 -0
- /package/app/components/{sidebar → navbar}/case-import/components/CasePreviewSection.tsx +0 -0
- /package/app/components/{sidebar → navbar}/case-import/components/ConfirmationDialog.tsx +0 -0
- /package/app/components/{sidebar → navbar}/case-import/components/ConfirmationPreviewSection.tsx +0 -0
- /package/app/components/{sidebar → navbar}/case-import/components/ExistingCaseSection.tsx +0 -0
- /package/app/components/{sidebar → navbar}/case-import/components/FileSelector.tsx +0 -0
- /package/app/components/{sidebar → navbar}/case-import/components/ProgressSection.tsx +0 -0
- /package/app/components/{sidebar → navbar}/case-import/hooks/useFilePreview.ts +0 -0
- /package/app/components/{sidebar → navbar}/case-import/hooks/useImportExecution.ts +0 -0
- /package/app/components/{sidebar → navbar}/case-import/hooks/useImportState.ts +0 -0
- /package/app/components/{sidebar → navbar}/case-import/index.ts +0 -0
- /package/app/components/{sidebar → navbar}/case-import/utils/file-validation.ts +0 -0
- /package/app/components/{sidebar/cases/cases-modal.module.css → navbar/case-modals/all-cases-modal.module.css} +0 -0
- /package/app/components/sidebar/notes/{class-details-shared.ts → class-details/class-details-shared.ts} +0 -0
- /package/app/components/sidebar/notes/{use-class-details-state.ts → class-details/use-class-details-state.ts} +0 -0
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
copy_example_configs() {
|
|
4
|
+
echo -e "\n${BLUE}📋 Copying example configuration files...${NC}"
|
|
5
|
+
|
|
6
|
+
# Copy app configuration files
|
|
7
|
+
echo -e "${YELLOW} Copying app configuration files...${NC}"
|
|
8
|
+
|
|
9
|
+
# Copy app config-example directory to config (always sync non-admin files)
|
|
10
|
+
if [ -d "app/config-example" ]; then
|
|
11
|
+
local admin_service_backup=""
|
|
12
|
+
local copied_config_files=0
|
|
13
|
+
local skipped_existing_files=0
|
|
14
|
+
|
|
15
|
+
if [ -f "app/config/admin-service.json" ]; then
|
|
16
|
+
admin_service_backup=$(mktemp)
|
|
17
|
+
cp "app/config/admin-service.json" "$admin_service_backup"
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
if [ "$update_env" = "true" ]; then
|
|
21
|
+
rm -rf app/config
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
mkdir -p app/config
|
|
25
|
+
|
|
26
|
+
while IFS= read -r source_file; do
|
|
27
|
+
local relative_path
|
|
28
|
+
local destination_file
|
|
29
|
+
relative_path="${source_file#app/config-example/}"
|
|
30
|
+
destination_file="app/config/$relative_path"
|
|
31
|
+
|
|
32
|
+
mkdir -p "$(dirname "$destination_file")"
|
|
33
|
+
|
|
34
|
+
if [ "$update_env" = "true" ] || [ ! -f "$destination_file" ]; then
|
|
35
|
+
cp "$source_file" "$destination_file"
|
|
36
|
+
copied_config_files=$((copied_config_files + 1))
|
|
37
|
+
else
|
|
38
|
+
skipped_existing_files=$((skipped_existing_files + 1))
|
|
39
|
+
fi
|
|
40
|
+
done < <(find app/config-example -type f ! -name "admin-service.json")
|
|
41
|
+
|
|
42
|
+
# Ensure example credentials are never copied from config-example.
|
|
43
|
+
rm -f app/config/admin-service.json
|
|
44
|
+
|
|
45
|
+
if [ -n "$admin_service_backup" ] && [ -f "$admin_service_backup" ]; then
|
|
46
|
+
cp "$admin_service_backup" "app/config/admin-service.json"
|
|
47
|
+
rm -f "$admin_service_backup"
|
|
48
|
+
echo -e "${GREEN} ✅ app: preserved existing admin-service.json${NC}"
|
|
49
|
+
else
|
|
50
|
+
echo -e "${YELLOW} ⚠️ app: skipped copying admin-service.json (provide your own credentials file)${NC}"
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
if [ "$update_env" = "true" ]; then
|
|
54
|
+
echo -e "${GREEN} ✅ app: config directory reset from config-example (excluding admin-service.json)${NC}"
|
|
55
|
+
else
|
|
56
|
+
echo -e "${GREEN} ✅ app: synced missing files from config-example (excluding admin-service.json)${NC}"
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
if [ "$skipped_existing_files" -gt 0 ]; then
|
|
60
|
+
echo -e "${YELLOW} ℹ️ app: kept $skipped_existing_files existing config file(s)${NC}"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
echo -e "${GREEN} ✅ app: copied $copied_config_files config file(s) from config-example${NC}"
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# Copy auth route template files
|
|
67
|
+
echo -e "${YELLOW} Copying auth route template files...${NC}"
|
|
68
|
+
|
|
69
|
+
if [ -f "app/routes/auth/login.example.tsx" ] && { [ "$update_env" = "true" ] || [ ! -f "app/routes/auth/login.tsx" ]; }; then
|
|
70
|
+
cp app/routes/auth/login.example.tsx app/routes/auth/login.tsx
|
|
71
|
+
echo -e "${GREEN} ✅ auth: login.tsx created from example${NC}"
|
|
72
|
+
elif [ -f "app/routes/auth/login.tsx" ]; then
|
|
73
|
+
echo -e "${YELLOW} ⚠️ auth: login.tsx already exists, skipping copy${NC}"
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
if [ -f "app/routes/auth/login.module.example.css" ] && { [ "$update_env" = "true" ] || [ ! -f "app/routes/auth/login.module.css" ]; }; then
|
|
77
|
+
cp app/routes/auth/login.module.example.css app/routes/auth/login.module.css
|
|
78
|
+
echo -e "${GREEN} ✅ auth: login.module.css created from example${NC}"
|
|
79
|
+
elif [ -f "app/routes/auth/login.module.css" ]; then
|
|
80
|
+
echo -e "${YELLOW} ⚠️ auth: login.module.css already exists, skipping copy${NC}"
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# Navigate to each worker directory and copy the example file
|
|
84
|
+
echo -e "${YELLOW} Copying worker configuration files...${NC}"
|
|
85
|
+
|
|
86
|
+
cd workers/user-worker
|
|
87
|
+
if [ -f "wrangler.jsonc.example" ] && { [ "$update_env" = "true" ] || [ ! -f "wrangler.jsonc" ]; }; then
|
|
88
|
+
cp wrangler.jsonc.example wrangler.jsonc
|
|
89
|
+
echo -e "${GREEN} ✅ user-worker: wrangler.jsonc created from example${NC}"
|
|
90
|
+
elif [ -f "wrangler.jsonc" ]; then
|
|
91
|
+
echo -e "${YELLOW} ⚠️ user-worker: wrangler.jsonc already exists, skipping copy${NC}"
|
|
92
|
+
fi
|
|
93
|
+
|
|
94
|
+
cd ../data-worker
|
|
95
|
+
if [ -f "wrangler.jsonc.example" ] && { [ "$update_env" = "true" ] || [ ! -f "wrangler.jsonc" ]; }; then
|
|
96
|
+
cp wrangler.jsonc.example wrangler.jsonc
|
|
97
|
+
echo -e "${GREEN} ✅ data-worker: wrangler.jsonc created from example${NC}"
|
|
98
|
+
elif [ -f "wrangler.jsonc" ]; then
|
|
99
|
+
echo -e "${YELLOW} ⚠️ data-worker: wrangler.jsonc already exists, skipping copy${NC}"
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
cd ../audit-worker
|
|
103
|
+
if [ -f "wrangler.jsonc.example" ] && { [ "$update_env" = "true" ] || [ ! -f "wrangler.jsonc" ]; }; then
|
|
104
|
+
cp wrangler.jsonc.example wrangler.jsonc
|
|
105
|
+
echo -e "${GREEN} ✅ audit-worker: wrangler.jsonc created from example${NC}"
|
|
106
|
+
elif [ -f "wrangler.jsonc" ]; then
|
|
107
|
+
echo -e "${YELLOW} ⚠️ audit-worker: wrangler.jsonc already exists, skipping copy${NC}"
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
cd ../image-worker
|
|
111
|
+
if [ -f "wrangler.jsonc.example" ] && { [ "$update_env" = "true" ] || [ ! -f "wrangler.jsonc" ]; }; then
|
|
112
|
+
cp wrangler.jsonc.example wrangler.jsonc
|
|
113
|
+
echo -e "${GREEN} ✅ image-worker: wrangler.jsonc created from example${NC}"
|
|
114
|
+
elif [ -f "wrangler.jsonc" ]; then
|
|
115
|
+
echo -e "${YELLOW} ⚠️ image-worker: wrangler.jsonc already exists, skipping copy${NC}"
|
|
116
|
+
fi
|
|
117
|
+
|
|
118
|
+
cd ../pdf-worker
|
|
119
|
+
if [ -f "wrangler.jsonc.example" ] && { [ "$update_env" = "true" ] || [ ! -f "wrangler.jsonc" ]; }; then
|
|
120
|
+
cp wrangler.jsonc.example wrangler.jsonc
|
|
121
|
+
echo -e "${GREEN} ✅ pdf-worker: wrangler.jsonc created from example${NC}"
|
|
122
|
+
elif [ -f "wrangler.jsonc" ]; then
|
|
123
|
+
echo -e "${YELLOW} ⚠️ pdf-worker: wrangler.jsonc already exists, skipping copy${NC}"
|
|
124
|
+
fi
|
|
125
|
+
|
|
126
|
+
# Return to project root
|
|
127
|
+
cd ../..
|
|
128
|
+
|
|
129
|
+
# Copy worker source template files
|
|
130
|
+
echo -e "${YELLOW} Copying worker source template files...${NC}"
|
|
131
|
+
|
|
132
|
+
if [ -f "workers/user-worker/src/user-worker.example.ts" ] && { [ "$update_env" = "true" ] || [ ! -f "workers/user-worker/src/user-worker.ts" ]; }; then
|
|
133
|
+
cp workers/user-worker/src/user-worker.example.ts workers/user-worker/src/user-worker.ts
|
|
134
|
+
echo -e "${GREEN} ✅ user-worker: user-worker.ts created from example${NC}"
|
|
135
|
+
elif [ -f "workers/user-worker/src/user-worker.ts" ]; then
|
|
136
|
+
echo -e "${YELLOW} ⚠️ user-worker: user-worker.ts already exists, skipping copy${NC}"
|
|
137
|
+
fi
|
|
138
|
+
|
|
139
|
+
if [ -f "workers/data-worker/src/data-worker.example.ts" ] && { [ "$update_env" = "true" ] || [ ! -f "workers/data-worker/src/data-worker.ts" ]; }; then
|
|
140
|
+
cp workers/data-worker/src/data-worker.example.ts workers/data-worker/src/data-worker.ts
|
|
141
|
+
echo -e "${GREEN} ✅ data-worker: data-worker.ts created from example${NC}"
|
|
142
|
+
elif [ -f "workers/data-worker/src/data-worker.ts" ]; then
|
|
143
|
+
echo -e "${YELLOW} ⚠️ data-worker: data-worker.ts already exists, skipping copy${NC}"
|
|
144
|
+
fi
|
|
145
|
+
|
|
146
|
+
if [ -f "workers/audit-worker/src/audit-worker.example.ts" ] && { [ "$update_env" = "true" ] || [ ! -f "workers/audit-worker/src/audit-worker.ts" ]; }; then
|
|
147
|
+
cp workers/audit-worker/src/audit-worker.example.ts workers/audit-worker/src/audit-worker.ts
|
|
148
|
+
echo -e "${GREEN} ✅ audit-worker: audit-worker.ts created from example${NC}"
|
|
149
|
+
elif [ -f "workers/audit-worker/src/audit-worker.ts" ]; then
|
|
150
|
+
echo -e "${YELLOW} ⚠️ audit-worker: audit-worker.ts already exists, skipping copy${NC}"
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
if [ -f "workers/image-worker/src/image-worker.example.ts" ] && { [ "$update_env" = "true" ] || [ ! -f "workers/image-worker/src/image-worker.ts" ]; }; then
|
|
154
|
+
cp workers/image-worker/src/image-worker.example.ts workers/image-worker/src/image-worker.ts
|
|
155
|
+
echo -e "${GREEN} ✅ image-worker: image-worker.ts created from example${NC}"
|
|
156
|
+
elif [ -f "workers/image-worker/src/image-worker.ts" ]; then
|
|
157
|
+
echo -e "${YELLOW} ⚠️ image-worker: image-worker.ts already exists, skipping copy${NC}"
|
|
158
|
+
fi
|
|
159
|
+
|
|
160
|
+
if [ -f "workers/pdf-worker/src/pdf-worker.example.ts" ] && { [ "$update_env" = "true" ] || [ ! -f "workers/pdf-worker/src/pdf-worker.ts" ]; }; then
|
|
161
|
+
cp workers/pdf-worker/src/pdf-worker.example.ts workers/pdf-worker/src/pdf-worker.ts
|
|
162
|
+
echo -e "${GREEN} ✅ pdf-worker: pdf-worker.ts created from example${NC}"
|
|
163
|
+
elif [ -f "workers/pdf-worker/src/pdf-worker.ts" ]; then
|
|
164
|
+
echo -e "${YELLOW} ⚠️ pdf-worker: pdf-worker.ts already exists, skipping copy${NC}"
|
|
165
|
+
fi
|
|
166
|
+
|
|
167
|
+
# Copy main wrangler.toml from example
|
|
168
|
+
if [ -f "wrangler.toml.example" ] && { [ "$update_env" = "true" ] || [ ! -f "wrangler.toml" ]; }; then
|
|
169
|
+
cp wrangler.toml.example wrangler.toml
|
|
170
|
+
echo -e "${GREEN} ✅ root: wrangler.toml created from example${NC}"
|
|
171
|
+
elif [ -f "wrangler.toml" ]; then
|
|
172
|
+
echo -e "${YELLOW} ⚠️ root: wrangler.toml already exists, skipping copy${NC}"
|
|
173
|
+
fi
|
|
174
|
+
|
|
175
|
+
echo -e "${GREEN}✅ Configuration file copying completed${NC}"
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
update_wrangler_configs() {
|
|
179
|
+
echo -e "\n${BLUE}🔧 Updating wrangler configuration files...${NC}"
|
|
180
|
+
|
|
181
|
+
local normalized_account_id
|
|
182
|
+
local escaped_account_id
|
|
183
|
+
local normalized_pages_custom_domain
|
|
184
|
+
local escaped_pages_custom_domain
|
|
185
|
+
|
|
186
|
+
normalized_account_id=$(printf '%s' "$ACCOUNT_ID" | tr -d '\r' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
|
|
187
|
+
ACCOUNT_ID="$normalized_account_id"
|
|
188
|
+
export ACCOUNT_ID
|
|
189
|
+
write_env_var "ACCOUNT_ID" "$ACCOUNT_ID"
|
|
190
|
+
escaped_account_id=$(escape_for_sed_replacement "$ACCOUNT_ID")
|
|
191
|
+
|
|
192
|
+
normalized_pages_custom_domain=$(normalize_domain_value "$PAGES_CUSTOM_DOMAIN")
|
|
193
|
+
PAGES_CUSTOM_DOMAIN="$normalized_pages_custom_domain"
|
|
194
|
+
export PAGES_CUSTOM_DOMAIN
|
|
195
|
+
write_env_var "PAGES_CUSTOM_DOMAIN" "$PAGES_CUSTOM_DOMAIN"
|
|
196
|
+
escaped_pages_custom_domain=$(escape_for_sed_replacement "$PAGES_CUSTOM_DOMAIN")
|
|
197
|
+
|
|
198
|
+
# Audit Worker
|
|
199
|
+
if [ -f "workers/audit-worker/wrangler.jsonc" ]; then
|
|
200
|
+
echo -e "${YELLOW} Updating audit-worker/wrangler.jsonc...${NC}"
|
|
201
|
+
sed -i "s/\"AUDIT_WORKER_NAME\"/\"$AUDIT_WORKER_NAME\"/g" workers/audit-worker/wrangler.jsonc
|
|
202
|
+
sed -i "s/\"ACCOUNT_ID\"/\"$escaped_account_id\"/g" workers/audit-worker/wrangler.jsonc
|
|
203
|
+
sed -i "s/\"AUDIT_BUCKET_NAME\"/\"$AUDIT_BUCKET_NAME\"/g" workers/audit-worker/wrangler.jsonc
|
|
204
|
+
echo -e "${GREEN} ✅ audit-worker configuration updated${NC}"
|
|
205
|
+
fi
|
|
206
|
+
|
|
207
|
+
if [ -f "workers/audit-worker/src/audit-worker.ts" ]; then
|
|
208
|
+
echo -e "${YELLOW} Updating audit-worker source placeholders...${NC}"
|
|
209
|
+
sed -i "s|'Access-Control-Allow-Origin': '[^']*'|'Access-Control-Allow-Origin': 'https://$escaped_pages_custom_domain'|g" workers/audit-worker/src/audit-worker.ts
|
|
210
|
+
echo -e "${GREEN} ✅ audit-worker source placeholders updated${NC}"
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
if [ -f "workers/data-worker/wrangler.jsonc" ]; then
|
|
214
|
+
echo -e "${YELLOW} Updating data-worker/wrangler.jsonc...${NC}"
|
|
215
|
+
sed -i "s/\"DATA_WORKER_NAME\"/\"$DATA_WORKER_NAME\"/g" workers/data-worker/wrangler.jsonc
|
|
216
|
+
sed -i "s/\"ACCOUNT_ID\"/\"$escaped_account_id\"/g" workers/data-worker/wrangler.jsonc
|
|
217
|
+
sed -i "s/\"DATA_BUCKET_NAME\"/\"$DATA_BUCKET_NAME\"/g" workers/data-worker/wrangler.jsonc
|
|
218
|
+
echo -e "${GREEN} ✅ data-worker configuration updated${NC}"
|
|
219
|
+
fi
|
|
220
|
+
|
|
221
|
+
if [ -f "workers/data-worker/src/data-worker.ts" ]; then
|
|
222
|
+
echo -e "${YELLOW} Updating data-worker source placeholders...${NC}"
|
|
223
|
+
sed -i "s|'Access-Control-Allow-Origin': '[^']*'|'Access-Control-Allow-Origin': 'https://$escaped_pages_custom_domain'|g" workers/data-worker/src/data-worker.ts
|
|
224
|
+
echo -e "${GREEN} ✅ data-worker source placeholders updated${NC}"
|
|
225
|
+
fi
|
|
226
|
+
|
|
227
|
+
if [ -f "workers/image-worker/wrangler.jsonc" ]; then
|
|
228
|
+
echo -e "${YELLOW} Updating image-worker/wrangler.jsonc...${NC}"
|
|
229
|
+
sed -i "s/\"IMAGES_WORKER_NAME\"/\"$IMAGES_WORKER_NAME\"/g" workers/image-worker/wrangler.jsonc
|
|
230
|
+
sed -i "s/\"ACCOUNT_ID\"/\"$escaped_account_id\"/g" workers/image-worker/wrangler.jsonc
|
|
231
|
+
sed -i "s/\"FILES_BUCKET_NAME\"/\"$FILES_BUCKET_NAME\"/g" workers/image-worker/wrangler.jsonc
|
|
232
|
+
echo -e "${GREEN} ✅ image-worker configuration updated${NC}"
|
|
233
|
+
fi
|
|
234
|
+
|
|
235
|
+
if [ -f "workers/image-worker/src/image-worker.ts" ]; then
|
|
236
|
+
echo -e "${YELLOW} Updating image-worker source placeholders...${NC}"
|
|
237
|
+
sed -i "s|'Access-Control-Allow-Origin': '[^']*'|'Access-Control-Allow-Origin': 'https://$escaped_pages_custom_domain'|g" workers/image-worker/src/image-worker.ts
|
|
238
|
+
echo -e "${GREEN} ✅ image-worker source placeholders updated${NC}"
|
|
239
|
+
fi
|
|
240
|
+
|
|
241
|
+
if [ -f "workers/pdf-worker/wrangler.jsonc" ]; then
|
|
242
|
+
echo -e "${YELLOW} Updating pdf-worker/wrangler.jsonc...${NC}"
|
|
243
|
+
sed -i "s/\"PDF_WORKER_NAME\"/\"$PDF_WORKER_NAME\"/g" workers/pdf-worker/wrangler.jsonc
|
|
244
|
+
sed -i "s/\"ACCOUNT_ID\"/\"$escaped_account_id\"/g" workers/pdf-worker/wrangler.jsonc
|
|
245
|
+
echo -e "${GREEN} ✅ pdf-worker configuration updated${NC}"
|
|
246
|
+
fi
|
|
247
|
+
|
|
248
|
+
if [ -f "workers/pdf-worker/src/pdf-worker.ts" ]; then
|
|
249
|
+
echo -e "${YELLOW} Updating pdf-worker source placeholders...${NC}"
|
|
250
|
+
sed -i "s|'Access-Control-Allow-Origin': '[^']*'|'Access-Control-Allow-Origin': 'https://$escaped_pages_custom_domain'|g" workers/pdf-worker/src/pdf-worker.ts
|
|
251
|
+
echo -e "${GREEN} ✅ pdf-worker source placeholders updated${NC}"
|
|
252
|
+
fi
|
|
253
|
+
|
|
254
|
+
if [ -f "workers/user-worker/wrangler.jsonc" ]; then
|
|
255
|
+
echo -e "${YELLOW} Updating user-worker/wrangler.jsonc...${NC}"
|
|
256
|
+
sed -i "s/\"USER_WORKER_NAME\"/\"$USER_WORKER_NAME\"/g" workers/user-worker/wrangler.jsonc
|
|
257
|
+
sed -i "s/\"ACCOUNT_ID\"/\"$escaped_account_id\"/g" workers/user-worker/wrangler.jsonc
|
|
258
|
+
sed -i "s/\"KV_STORE_ID\"/\"$KV_STORE_ID\"/g" workers/user-worker/wrangler.jsonc
|
|
259
|
+
sed -i "s/\"DATA_BUCKET_NAME\"/\"$DATA_BUCKET_NAME\"/g" workers/user-worker/wrangler.jsonc
|
|
260
|
+
sed -i "s/\"FILES_BUCKET_NAME\"/\"$FILES_BUCKET_NAME\"/g" workers/user-worker/wrangler.jsonc
|
|
261
|
+
echo -e "${GREEN} ✅ user-worker configuration updated${NC}"
|
|
262
|
+
fi
|
|
263
|
+
|
|
264
|
+
if [ -f "workers/user-worker/src/user-worker.ts" ]; then
|
|
265
|
+
echo -e "${YELLOW} Updating user-worker source placeholders...${NC}"
|
|
266
|
+
sed -i "s|'Access-Control-Allow-Origin': '[^']*'|'Access-Control-Allow-Origin': 'https://$escaped_pages_custom_domain'|g" workers/user-worker/src/user-worker.ts
|
|
267
|
+
echo -e "${GREEN} ✅ user-worker source placeholders updated${NC}"
|
|
268
|
+
fi
|
|
269
|
+
|
|
270
|
+
if [ -f "wrangler.toml" ]; then
|
|
271
|
+
echo -e "${YELLOW} Updating wrangler.toml...${NC}"
|
|
272
|
+
sed -i "s/\"PAGES_PROJECT_NAME\"/\"$PAGES_PROJECT_NAME\"/g" wrangler.toml
|
|
273
|
+
echo -e "${GREEN} ✅ main wrangler.toml configuration updated${NC}"
|
|
274
|
+
fi
|
|
275
|
+
|
|
276
|
+
echo -e "${YELLOW} Updating app configuration files...${NC}"
|
|
277
|
+
|
|
278
|
+
if [ -f "app/config/config.json" ]; then
|
|
279
|
+
echo -e "${YELLOW} Updating app/config/config.json...${NC}"
|
|
280
|
+
local escaped_manifest_signing_key_id
|
|
281
|
+
local escaped_manifest_signing_public_key
|
|
282
|
+
local escaped_export_encryption_key_id
|
|
283
|
+
local escaped_export_encryption_public_key
|
|
284
|
+
escaped_manifest_signing_key_id=$(escape_for_sed_replacement "$MANIFEST_SIGNING_KEY_ID")
|
|
285
|
+
escaped_manifest_signing_public_key=$(escape_for_sed_replacement "$MANIFEST_SIGNING_PUBLIC_KEY")
|
|
286
|
+
escaped_export_encryption_key_id=$(escape_for_sed_replacement "$EXPORT_ENCRYPTION_KEY_ID")
|
|
287
|
+
escaped_export_encryption_public_key=$(escape_for_sed_replacement "$EXPORT_ENCRYPTION_PUBLIC_KEY")
|
|
288
|
+
|
|
289
|
+
sed -i "s|\"url\": \"[^\"]*\"|\"url\": \"https://$escaped_pages_custom_domain\"|g" app/config/config.json
|
|
290
|
+
sed -i "s|\"MANIFEST_SIGNING_KEY_ID\"|\"$escaped_manifest_signing_key_id\"|g" app/config/config.json
|
|
291
|
+
sed -i "s|\"MANIFEST_SIGNING_PUBLIC_KEY\"|\"$escaped_manifest_signing_public_key\"|g" app/config/config.json
|
|
292
|
+
sed -i "s|\"EXPORT_ENCRYPTION_KEY_ID\"|\"$escaped_export_encryption_key_id\"|g" app/config/config.json
|
|
293
|
+
sed -i "s|\"EXPORT_ENCRYPTION_PUBLIC_KEY\"|\"$escaped_export_encryption_public_key\"|g" app/config/config.json
|
|
294
|
+
echo -e "${GREEN} ✅ app config.json updated${NC}"
|
|
295
|
+
fi
|
|
296
|
+
|
|
297
|
+
if [ -f "app/config/firebase.ts" ]; then
|
|
298
|
+
echo -e "${YELLOW} Updating app/config/firebase.ts...${NC}"
|
|
299
|
+
sed -i "s|\"YOUR_FIREBASE_API_KEY\"|\"$API_KEY\"|g" app/config/firebase.ts
|
|
300
|
+
sed -i "s|\"YOUR_FIREBASE_AUTH_DOMAIN\"|\"$AUTH_DOMAIN\"|g" app/config/firebase.ts
|
|
301
|
+
sed -i "s|\"YOUR_FIREBASE_PROJECT_ID\"|\"$PROJECT_ID\"|g" app/config/firebase.ts
|
|
302
|
+
sed -i "s|\"YOUR_FIREBASE_STORAGE_BUCKET\"|\"$STORAGE_BUCKET\"|g" app/config/firebase.ts
|
|
303
|
+
sed -i "s|\"YOUR_FIREBASE_MESSAGING_SENDER_ID\"|\"$MESSAGING_SENDER_ID\"|g" app/config/firebase.ts
|
|
304
|
+
sed -i "s|\"YOUR_FIREBASE_APP_ID\"|\"$APP_ID\"|g" app/config/firebase.ts
|
|
305
|
+
sed -i "s|\"YOUR_FIREBASE_MEASUREMENT_ID\"|\"$MEASUREMENT_ID\"|g" app/config/firebase.ts
|
|
306
|
+
echo -e "${GREEN} ✅ app firebase.ts updated${NC}"
|
|
307
|
+
fi
|
|
308
|
+
|
|
309
|
+
echo -e "${GREEN}✅ All configuration files updated${NC}"
|
|
310
|
+
}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
validate_data_at_rest_encryption_settings() {
|
|
4
|
+
local enabled_normalized
|
|
5
|
+
enabled_normalized=$(printf '%s' "${DATA_AT_REST_ENCRYPTION_ENABLED:-false}" | tr '[:upper:]' '[:lower:]')
|
|
6
|
+
|
|
7
|
+
if [ "$enabled_normalized" != "1" ] && [ "$enabled_normalized" != "true" ] && [ "$enabled_normalized" != "yes" ] && [ "$enabled_normalized" != "on" ]; then
|
|
8
|
+
echo -e "${RED}❌ Error: DATA_AT_REST_ENCRYPTION_ENABLED must be true because data-at-rest encryption is mandatory${NC}"
|
|
9
|
+
exit 1
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
local has_legacy_private_key=false
|
|
13
|
+
local has_registry_keys_json=false
|
|
14
|
+
|
|
15
|
+
if [ -n "$DATA_AT_REST_ENCRYPTION_PRIVATE_KEY" ] && ! is_placeholder "$DATA_AT_REST_ENCRYPTION_PRIVATE_KEY"; then
|
|
16
|
+
has_legacy_private_key=true
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
if [ -n "$DATA_AT_REST_ENCRYPTION_KEYS_JSON" ] && ! is_placeholder "$DATA_AT_REST_ENCRYPTION_KEYS_JSON"; then
|
|
20
|
+
has_registry_keys_json=true
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
if [ "$has_legacy_private_key" != "true" ] && [ "$has_registry_keys_json" != "true" ]; then
|
|
24
|
+
echo -e "${RED}❌ Error: either DATA_AT_REST_ENCRYPTION_PRIVATE_KEY or DATA_AT_REST_ENCRYPTION_KEYS_JSON is required when data-at-rest encryption is enabled${NC}"
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
if [ -z "$DATA_AT_REST_ENCRYPTION_PUBLIC_KEY" ] || is_placeholder "$DATA_AT_REST_ENCRYPTION_PUBLIC_KEY"; then
|
|
29
|
+
echo -e "${RED}❌ Error: DATA_AT_REST_ENCRYPTION_PUBLIC_KEY is required when data-at-rest encryption is enabled${NC}"
|
|
30
|
+
exit 1
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
if [ -z "$DATA_AT_REST_ENCRYPTION_KEY_ID" ] || is_placeholder "$DATA_AT_REST_ENCRYPTION_KEY_ID"; then
|
|
34
|
+
echo -e "${RED}❌ Error: DATA_AT_REST_ENCRYPTION_KEY_ID is required when data-at-rest encryption is enabled${NC}"
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
validate_user_kv_encryption_settings() {
|
|
40
|
+
local has_legacy_private_key=false
|
|
41
|
+
local has_registry_keys_json=false
|
|
42
|
+
local write_endpoints_enabled_normalized
|
|
43
|
+
|
|
44
|
+
if [ -n "$USER_KV_ENCRYPTION_PRIVATE_KEY" ] && ! is_placeholder "$USER_KV_ENCRYPTION_PRIVATE_KEY"; then
|
|
45
|
+
has_legacy_private_key=true
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
if [ -n "$USER_KV_ENCRYPTION_KEYS_JSON" ] && ! is_placeholder "$USER_KV_ENCRYPTION_KEYS_JSON"; then
|
|
49
|
+
has_registry_keys_json=true
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
if [ "$has_legacy_private_key" != "true" ] && [ "$has_registry_keys_json" != "true" ]; then
|
|
53
|
+
echo -e "${RED}❌ Error: either USER_KV_ENCRYPTION_PRIVATE_KEY or USER_KV_ENCRYPTION_KEYS_JSON is required${NC}"
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
# Defaults to enabled to preserve current behavior unless explicitly set false for read-only deployments.
|
|
58
|
+
write_endpoints_enabled_normalized=$(printf '%s' "${USER_KV_WRITE_ENDPOINTS_ENABLED:-true}" | tr '[:upper:]' '[:lower:]')
|
|
59
|
+
|
|
60
|
+
if [ "$write_endpoints_enabled_normalized" = "1" ] || [ "$write_endpoints_enabled_normalized" = "true" ] || [ "$write_endpoints_enabled_normalized" = "yes" ] || [ "$write_endpoints_enabled_normalized" = "on" ]; then
|
|
61
|
+
if [ -z "$USER_KV_ENCRYPTION_PUBLIC_KEY" ] || is_placeholder "$USER_KV_ENCRYPTION_PUBLIC_KEY"; then
|
|
62
|
+
echo -e "${RED}❌ Error: USER_KV_ENCRYPTION_PUBLIC_KEY is required when USER_KV_WRITE_ENDPOINTS_ENABLED is true${NC}"
|
|
63
|
+
exit 1
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
if [ -z "$USER_KV_ENCRYPTION_KEY_ID" ] || is_placeholder "$USER_KV_ENCRYPTION_KEY_ID"; then
|
|
67
|
+
echo -e "${RED}❌ Error: USER_KV_ENCRYPTION_KEY_ID is required when USER_KV_WRITE_ENDPOINTS_ENABLED is true${NC}"
|
|
68
|
+
exit 1
|
|
69
|
+
fi
|
|
70
|
+
fi
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# Validate required variables
|
|
74
|
+
required_vars=(
|
|
75
|
+
# Core Cloudflare Configuration
|
|
76
|
+
"ACCOUNT_ID"
|
|
77
|
+
|
|
78
|
+
# Shared Authentication & Storage
|
|
79
|
+
"USER_DB_AUTH"
|
|
80
|
+
"R2_KEY_SECRET"
|
|
81
|
+
"IMAGES_API_TOKEN"
|
|
82
|
+
|
|
83
|
+
# Firebase Auth Configuration
|
|
84
|
+
"API_KEY"
|
|
85
|
+
"AUTH_DOMAIN"
|
|
86
|
+
"PROJECT_ID"
|
|
87
|
+
"STORAGE_BUCKET"
|
|
88
|
+
"MESSAGING_SENDER_ID"
|
|
89
|
+
"APP_ID"
|
|
90
|
+
"MEASUREMENT_ID"
|
|
91
|
+
"FIREBASE_SERVICE_ACCOUNT_EMAIL"
|
|
92
|
+
"FIREBASE_SERVICE_ACCOUNT_PRIVATE_KEY"
|
|
93
|
+
|
|
94
|
+
# Pages Configuration
|
|
95
|
+
"PAGES_PROJECT_NAME"
|
|
96
|
+
"PAGES_CUSTOM_DOMAIN"
|
|
97
|
+
|
|
98
|
+
# Worker Names (required for config replacement)
|
|
99
|
+
"USER_WORKER_NAME"
|
|
100
|
+
"DATA_WORKER_NAME"
|
|
101
|
+
"AUDIT_WORKER_NAME"
|
|
102
|
+
"IMAGES_WORKER_NAME"
|
|
103
|
+
"PDF_WORKER_NAME"
|
|
104
|
+
|
|
105
|
+
# Worker Domains (required for proxy/env secrets and worker fallbacks)
|
|
106
|
+
"USER_WORKER_DOMAIN"
|
|
107
|
+
"DATA_WORKER_DOMAIN"
|
|
108
|
+
"AUDIT_WORKER_DOMAIN"
|
|
109
|
+
"IMAGES_WORKER_DOMAIN"
|
|
110
|
+
"PDF_WORKER_DOMAIN"
|
|
111
|
+
|
|
112
|
+
# Storage Configuration (required for config replacement)
|
|
113
|
+
"DATA_BUCKET_NAME"
|
|
114
|
+
"AUDIT_BUCKET_NAME"
|
|
115
|
+
"FILES_BUCKET_NAME"
|
|
116
|
+
"KV_STORE_ID"
|
|
117
|
+
|
|
118
|
+
# Worker-Specific Secrets (required for deployment)
|
|
119
|
+
"PDF_WORKER_AUTH"
|
|
120
|
+
"IMAGE_SIGNED_URL_SECRET"
|
|
121
|
+
"BROWSER_API_TOKEN"
|
|
122
|
+
"MANIFEST_SIGNING_PRIVATE_KEY"
|
|
123
|
+
"MANIFEST_SIGNING_KEY_ID"
|
|
124
|
+
"MANIFEST_SIGNING_PUBLIC_KEY"
|
|
125
|
+
"EXPORT_ENCRYPTION_PRIVATE_KEY"
|
|
126
|
+
"EXPORT_ENCRYPTION_KEY_ID"
|
|
127
|
+
"EXPORT_ENCRYPTION_PUBLIC_KEY"
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
validate_required_vars() {
|
|
131
|
+
echo -e "${YELLOW}🔍 Validating required environment variables...${NC}"
|
|
132
|
+
for var in "${required_vars[@]}"; do
|
|
133
|
+
if [ -z "${!var}" ] || is_placeholder "${!var}"; then
|
|
134
|
+
echo -e "${RED}❌ Error: $var is not set in .env file or is a placeholder${NC}"
|
|
135
|
+
exit 1
|
|
136
|
+
fi
|
|
137
|
+
done
|
|
138
|
+
echo -e "${GREEN}✅ All required variables found${NC}"
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
assert_file_exists() {
|
|
142
|
+
local file_path=$1
|
|
143
|
+
|
|
144
|
+
if [ ! -f "$file_path" ]; then
|
|
145
|
+
echo -e "${RED}❌ Error: required file is missing: $file_path${NC}"
|
|
146
|
+
exit 1
|
|
147
|
+
fi
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
assert_contains_literal() {
|
|
151
|
+
local file_path=$1
|
|
152
|
+
local literal=$2
|
|
153
|
+
local description=$3
|
|
154
|
+
|
|
155
|
+
if ! grep -Fq -- "$literal" "$file_path"; then
|
|
156
|
+
echo -e "${RED}❌ Error: ${description}${NC}"
|
|
157
|
+
echo -e "${YELLOW} Expected to find '$literal' in $file_path${NC}"
|
|
158
|
+
exit 1
|
|
159
|
+
fi
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
assert_no_match_in_file() {
|
|
163
|
+
local file_path=$1
|
|
164
|
+
local pattern=$2
|
|
165
|
+
local description=$3
|
|
166
|
+
local matches
|
|
167
|
+
|
|
168
|
+
matches=$(grep -En "$pattern" "$file_path" | head -n 3 || true)
|
|
169
|
+
if [ -n "$matches" ]; then
|
|
170
|
+
echo -e "${RED}❌ Error: ${description}${NC}"
|
|
171
|
+
echo -e "${YELLOW} First matching lines in $file_path:${NC}"
|
|
172
|
+
echo "$matches"
|
|
173
|
+
exit 1
|
|
174
|
+
fi
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
validate_json_file() {
|
|
178
|
+
local file_path=$1
|
|
179
|
+
|
|
180
|
+
if ! node -e "const fs=require('fs'); JSON.parse(fs.readFileSync(process.argv[1], 'utf8'));" "$file_path" > /dev/null 2>&1; then
|
|
181
|
+
echo -e "${RED}❌ Error: invalid JSON in $file_path${NC}"
|
|
182
|
+
exit 1
|
|
183
|
+
fi
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
validate_domain_var() {
|
|
187
|
+
local var_name=$1
|
|
188
|
+
local value="${!var_name}"
|
|
189
|
+
local normalized
|
|
190
|
+
|
|
191
|
+
value=$(strip_carriage_returns "$value")
|
|
192
|
+
normalized=$(normalize_domain_value "$value")
|
|
193
|
+
|
|
194
|
+
if [ -z "$value" ] || is_placeholder "$value"; then
|
|
195
|
+
echo -e "${RED}❌ Error: $var_name is missing or placeholder${NC}"
|
|
196
|
+
exit 1
|
|
197
|
+
fi
|
|
198
|
+
|
|
199
|
+
if [ "$value" != "$normalized" ]; then
|
|
200
|
+
echo -e "${RED}❌ Error: $var_name must not include protocol, trailing slash, or surrounding whitespace${NC}"
|
|
201
|
+
echo -e "${YELLOW} Use '$normalized' instead${NC}"
|
|
202
|
+
exit 1
|
|
203
|
+
fi
|
|
204
|
+
|
|
205
|
+
if [[ "$value" == */* ]]; then
|
|
206
|
+
echo -e "${RED}❌ Error: $var_name must be a bare domain (no path segments)${NC}"
|
|
207
|
+
exit 1
|
|
208
|
+
fi
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
validate_env_value_formats() {
|
|
212
|
+
echo -e "${YELLOW}🔍 Validating environment value formats...${NC}"
|
|
213
|
+
|
|
214
|
+
validate_domain_var "PAGES_CUSTOM_DOMAIN"
|
|
215
|
+
validate_domain_var "USER_WORKER_DOMAIN"
|
|
216
|
+
validate_domain_var "DATA_WORKER_DOMAIN"
|
|
217
|
+
validate_domain_var "AUDIT_WORKER_DOMAIN"
|
|
218
|
+
validate_domain_var "IMAGES_WORKER_DOMAIN"
|
|
219
|
+
validate_domain_var "PDF_WORKER_DOMAIN"
|
|
220
|
+
|
|
221
|
+
if ! [[ "$KV_STORE_ID" =~ ^([0-9a-fA-F]{32}|[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$ ]]; then
|
|
222
|
+
echo -e "${RED}❌ Error: KV_STORE_ID must be a 32-character hex namespace ID (or UUID format)${NC}"
|
|
223
|
+
exit 1
|
|
224
|
+
fi
|
|
225
|
+
|
|
226
|
+
if [[ "$ACCOUNT_ID" =~ [[:space:]] ]]; then
|
|
227
|
+
echo -e "${RED}❌ Error: ACCOUNT_ID must not contain whitespace${NC}"
|
|
228
|
+
exit 1
|
|
229
|
+
fi
|
|
230
|
+
|
|
231
|
+
echo -e "${GREEN}✅ Environment value formats look valid${NC}"
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
validate_env_file_entries() {
|
|
235
|
+
local var_name
|
|
236
|
+
local escaped_var_name
|
|
237
|
+
local count
|
|
238
|
+
|
|
239
|
+
echo -e "${YELLOW}🔍 Verifying required .env entries...${NC}"
|
|
240
|
+
for var_name in "${required_vars[@]}"; do
|
|
241
|
+
escaped_var_name=$(escape_for_sed_pattern "$var_name")
|
|
242
|
+
count=$(grep -c "^$escaped_var_name=" .env || true)
|
|
243
|
+
|
|
244
|
+
if [ "$count" -lt 1 ]; then
|
|
245
|
+
echo -e "${RED}❌ Error: missing .env entry for $var_name${NC}"
|
|
246
|
+
exit 1
|
|
247
|
+
fi
|
|
248
|
+
done
|
|
249
|
+
echo -e "${GREEN}✅ Required .env entries found${NC}"
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
validate_generated_configs() {
|
|
253
|
+
echo -e "${YELLOW}🔍 Running generated configuration checkpoint validations...${NC}"
|
|
254
|
+
|
|
255
|
+
local required_files=(
|
|
256
|
+
"wrangler.toml"
|
|
257
|
+
"app/config/config.json"
|
|
258
|
+
"app/config/firebase.ts"
|
|
259
|
+
"app/config/admin-service.json"
|
|
260
|
+
"app/routes/auth/login.tsx"
|
|
261
|
+
"app/routes/auth/login.module.css"
|
|
262
|
+
"workers/audit-worker/wrangler.jsonc"
|
|
263
|
+
"workers/data-worker/wrangler.jsonc"
|
|
264
|
+
"workers/image-worker/wrangler.jsonc"
|
|
265
|
+
"workers/pdf-worker/wrangler.jsonc"
|
|
266
|
+
"workers/user-worker/wrangler.jsonc"
|
|
267
|
+
"workers/audit-worker/src/audit-worker.ts"
|
|
268
|
+
"workers/data-worker/src/data-worker.ts"
|
|
269
|
+
"workers/image-worker/src/image-worker.ts"
|
|
270
|
+
"workers/pdf-worker/src/pdf-worker.ts"
|
|
271
|
+
"workers/user-worker/src/user-worker.ts"
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
local file_path
|
|
275
|
+
for file_path in "${required_files[@]}"; do
|
|
276
|
+
assert_file_exists "$file_path"
|
|
277
|
+
done
|
|
278
|
+
|
|
279
|
+
validate_json_file "app/config/config.json"
|
|
280
|
+
validate_json_file "app/config/admin-service.json"
|
|
281
|
+
|
|
282
|
+
assert_contains_literal "wrangler.toml" "\"$PAGES_PROJECT_NAME\"" "PAGES_PROJECT_NAME was not applied to wrangler.toml"
|
|
283
|
+
|
|
284
|
+
assert_contains_literal "workers/user-worker/wrangler.jsonc" "$USER_WORKER_NAME" "USER_WORKER_NAME was not applied"
|
|
285
|
+
assert_contains_literal "workers/data-worker/wrangler.jsonc" "$DATA_WORKER_NAME" "DATA_WORKER_NAME was not applied"
|
|
286
|
+
assert_contains_literal "workers/audit-worker/wrangler.jsonc" "$AUDIT_WORKER_NAME" "AUDIT_WORKER_NAME was not applied"
|
|
287
|
+
assert_contains_literal "workers/image-worker/wrangler.jsonc" "$IMAGES_WORKER_NAME" "IMAGES_WORKER_NAME was not applied"
|
|
288
|
+
assert_contains_literal "workers/pdf-worker/wrangler.jsonc" "$PDF_WORKER_NAME" "PDF_WORKER_NAME was not applied"
|
|
289
|
+
|
|
290
|
+
assert_contains_literal "workers/user-worker/wrangler.jsonc" "$ACCOUNT_ID" "ACCOUNT_ID missing in user worker config"
|
|
291
|
+
assert_contains_literal "workers/data-worker/wrangler.jsonc" "$ACCOUNT_ID" "ACCOUNT_ID missing in data worker config"
|
|
292
|
+
assert_contains_literal "workers/audit-worker/wrangler.jsonc" "$ACCOUNT_ID" "ACCOUNT_ID missing in audit worker config"
|
|
293
|
+
assert_contains_literal "workers/image-worker/wrangler.jsonc" "$ACCOUNT_ID" "ACCOUNT_ID missing in image worker config"
|
|
294
|
+
assert_contains_literal "workers/pdf-worker/wrangler.jsonc" "$ACCOUNT_ID" "ACCOUNT_ID missing in pdf worker config"
|
|
295
|
+
|
|
296
|
+
assert_contains_literal "workers/data-worker/wrangler.jsonc" "$DATA_BUCKET_NAME" "DATA_BUCKET_NAME missing in data worker config"
|
|
297
|
+
assert_contains_literal "workers/audit-worker/wrangler.jsonc" "$AUDIT_BUCKET_NAME" "AUDIT_BUCKET_NAME missing in audit worker config"
|
|
298
|
+
assert_contains_literal "workers/image-worker/wrangler.jsonc" "$FILES_BUCKET_NAME" "FILES_BUCKET_NAME missing in image worker config"
|
|
299
|
+
assert_contains_literal "workers/user-worker/wrangler.jsonc" "$KV_STORE_ID" "KV_STORE_ID missing in user worker config"
|
|
300
|
+
assert_contains_literal "workers/user-worker/wrangler.jsonc" "$DATA_BUCKET_NAME" "DATA_BUCKET_NAME missing in user worker config"
|
|
301
|
+
assert_contains_literal "workers/user-worker/wrangler.jsonc" "$FILES_BUCKET_NAME" "FILES_BUCKET_NAME missing in user worker config"
|
|
302
|
+
|
|
303
|
+
assert_contains_literal "app/config/config.json" "https://$PAGES_CUSTOM_DOMAIN" "PAGES_CUSTOM_DOMAIN missing in app/config/config.json"
|
|
304
|
+
assert_contains_literal "app/config/config.json" "$EXPORT_ENCRYPTION_KEY_ID" "EXPORT_ENCRYPTION_KEY_ID missing in app/config/config.json"
|
|
305
|
+
assert_contains_literal "app/config/config.json" "\"export_encryption_public_key\":" "export_encryption_public_key missing in app/config/config.json"
|
|
306
|
+
|
|
307
|
+
assert_contains_literal "app/config/firebase.ts" "$API_KEY" "API_KEY missing in app/config/firebase.ts"
|
|
308
|
+
assert_contains_literal "app/config/firebase.ts" "$AUTH_DOMAIN" "AUTH_DOMAIN missing in app/config/firebase.ts"
|
|
309
|
+
assert_contains_literal "app/config/firebase.ts" "$PROJECT_ID" "PROJECT_ID missing in app/config/firebase.ts"
|
|
310
|
+
assert_contains_literal "app/config/firebase.ts" "$STORAGE_BUCKET" "STORAGE_BUCKET missing in app/config/firebase.ts"
|
|
311
|
+
assert_contains_literal "app/config/firebase.ts" "$MESSAGING_SENDER_ID" "MESSAGING_SENDER_ID missing in app/config/firebase.ts"
|
|
312
|
+
assert_contains_literal "app/config/firebase.ts" "$APP_ID" "APP_ID missing in app/config/firebase.ts"
|
|
313
|
+
assert_contains_literal "app/config/firebase.ts" "$MEASUREMENT_ID" "MEASUREMENT_ID missing in app/config/firebase.ts"
|
|
314
|
+
|
|
315
|
+
assert_contains_literal "workers/audit-worker/src/audit-worker.ts" "https://$PAGES_CUSTOM_DOMAIN" "PAGES_CUSTOM_DOMAIN missing in audit-worker source"
|
|
316
|
+
assert_contains_literal "workers/data-worker/src/data-worker.ts" "https://$PAGES_CUSTOM_DOMAIN" "PAGES_CUSTOM_DOMAIN missing in data-worker source"
|
|
317
|
+
assert_contains_literal "workers/image-worker/src/image-worker.ts" "https://$PAGES_CUSTOM_DOMAIN" "PAGES_CUSTOM_DOMAIN missing in image-worker source"
|
|
318
|
+
assert_contains_literal "workers/pdf-worker/src/pdf-worker.ts" "https://$PAGES_CUSTOM_DOMAIN" "PAGES_CUSTOM_DOMAIN missing in pdf-worker source"
|
|
319
|
+
assert_contains_literal "workers/user-worker/src/user-worker.ts" "https://$PAGES_CUSTOM_DOMAIN" "PAGES_CUSTOM_DOMAIN missing in user-worker source"
|
|
320
|
+
|
|
321
|
+
local placeholder_pattern
|
|
322
|
+
placeholder_pattern="(\"(ACCOUNT_ID|PAGES_PROJECT_NAME|PAGES_CUSTOM_DOMAIN|USER_WORKER_NAME|DATA_WORKER_NAME|AUDIT_WORKER_NAME|IMAGES_WORKER_NAME|PDF_WORKER_NAME|USER_WORKER_DOMAIN|DATA_WORKER_DOMAIN|AUDIT_WORKER_DOMAIN|IMAGES_WORKER_DOMAIN|PDF_WORKER_DOMAIN|DATA_BUCKET_NAME|AUDIT_BUCKET_NAME|FILES_BUCKET_NAME|KV_STORE_ID|MANIFEST_SIGNING_KEY_ID|MANIFEST_SIGNING_PUBLIC_KEY|EXPORT_ENCRYPTION_KEY_ID|EXPORT_ENCRYPTION_PUBLIC_KEY|YOUR_FIREBASE_API_KEY|YOUR_FIREBASE_AUTH_DOMAIN|YOUR_FIREBASE_PROJECT_ID|YOUR_FIREBASE_STORAGE_BUCKET|YOUR_FIREBASE_MESSAGING_SENDER_ID|YOUR_FIREBASE_APP_ID|YOUR_FIREBASE_MEASUREMENT_ID)\"|'(PAGES_CUSTOM_DOMAIN|DATA_WORKER_DOMAIN|AUDIT_WORKER_DOMAIN|IMAGES_WORKER_DOMAIN)')"
|
|
323
|
+
|
|
324
|
+
local files_to_scan=(
|
|
325
|
+
"wrangler.toml"
|
|
326
|
+
"workers/audit-worker/wrangler.jsonc"
|
|
327
|
+
"workers/data-worker/wrangler.jsonc"
|
|
328
|
+
"workers/image-worker/wrangler.jsonc"
|
|
329
|
+
"workers/pdf-worker/wrangler.jsonc"
|
|
330
|
+
"workers/user-worker/wrangler.jsonc"
|
|
331
|
+
"workers/audit-worker/src/audit-worker.ts"
|
|
332
|
+
"workers/data-worker/src/data-worker.ts"
|
|
333
|
+
"workers/image-worker/src/image-worker.ts"
|
|
334
|
+
"workers/pdf-worker/src/pdf-worker.ts"
|
|
335
|
+
"workers/user-worker/src/user-worker.ts"
|
|
336
|
+
"app/config/config.json"
|
|
337
|
+
"app/config/firebase.ts"
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
for file_path in "${files_to_scan[@]}"; do
|
|
341
|
+
assert_no_match_in_file "$file_path" "$placeholder_pattern" "Unresolved placeholder token found after config update"
|
|
342
|
+
done
|
|
343
|
+
|
|
344
|
+
echo -e "${GREEN}✅ Generated configuration checkpoint validation passed${NC}"
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
run_validation_checkpoint() {
|
|
348
|
+
validate_required_vars
|
|
349
|
+
validate_env_value_formats
|
|
350
|
+
validate_env_file_entries
|
|
351
|
+
validate_data_at_rest_encryption_settings
|
|
352
|
+
validate_user_kv_encryption_settings
|
|
353
|
+
validate_generated_configs
|
|
354
|
+
}
|