@striae-org/striae 5.2.1 → 5.3.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 +2 -10
- package/README.md +5 -46
- package/app/components/actions/case-export/core-export.ts +2 -174
- package/app/components/actions/case-export/download-handlers.ts +83 -750
- package/app/components/actions/case-export/index.ts +6 -30
- package/app/components/actions/case-export/metadata-helpers.ts +0 -78
- package/app/components/actions/case-export/types-constants.ts +0 -43
- package/app/components/actions/case-import/confirmation-import.ts +13 -14
- package/app/components/actions/case-import/zip-processing.ts +92 -12
- package/app/components/actions/generate-pdf.ts +3 -2
- package/app/components/audit/user-audit-viewer.tsx +0 -19
- package/app/components/audit/viewer/audit-viewer-header.tsx +0 -33
- package/app/components/navbar/case-modals/archive-case-modal.tsx +1 -1
- package/app/components/navbar/navbar.tsx +1 -1
- package/app/components/sidebar/case-import/case-import.module.css +35 -0
- package/app/components/sidebar/case-import/components/CasePreviewSection.tsx +59 -3
- package/app/components/sidebar/case-import/components/ConfirmationDialog.tsx +2 -4
- package/app/components/sidebar/case-import/components/ConfirmationPreviewSection.tsx +1 -1
- package/app/components/sidebar/notes/class-details-shared.ts +2 -2
- package/app/components/toast/toast.module.css +36 -0
- package/app/components/toast/toast.tsx +6 -2
- package/app/components/user/manage-profile.tsx +4 -3
- package/app/config-example/config.json +1 -2
- package/app/root.tsx +0 -7
- package/app/routes/_index.tsx +1 -1
- package/app/routes/auth/login.example.tsx +22 -103
- package/app/routes/auth/route.ts +1 -1
- package/app/routes/striae/striae.tsx +53 -59
- package/app/services/firebase/index.ts +0 -3
- package/app/types/export.ts +1 -2
- package/app/utils/auth/index.ts +0 -1
- package/app/utils/data/permissions.ts +3 -2
- package/package.json +9 -16
- package/public/_headers +0 -4
- package/public/_routes.json +0 -1
- package/worker-configuration.d.ts +20 -17
- package/workers/audit-worker/src/audit-worker.example.ts +9 -806
- package/workers/audit-worker/src/config.ts +7 -0
- package/workers/audit-worker/src/crypto/data-at-rest.ts +410 -0
- package/workers/audit-worker/src/handlers/audit-routes.ts +125 -0
- package/workers/audit-worker/src/storage/audit-storage.ts +99 -0
- package/workers/audit-worker/src/types.ts +56 -0
- package/workers/audit-worker/worker-configuration.d.ts +1 -1
- package/workers/audit-worker/wrangler.jsonc.example +1 -1
- package/workers/data-worker/src/config.ts +11 -0
- package/workers/data-worker/src/data-worker.example.ts +21 -942
- package/workers/data-worker/src/handlers/decrypt-export.ts +118 -0
- package/workers/data-worker/src/handlers/signing.ts +174 -0
- package/workers/data-worker/src/handlers/storage-routes.ts +129 -0
- package/workers/data-worker/src/registry/key-registry.ts +368 -0
- package/workers/data-worker/src/types.ts +46 -0
- package/workers/data-worker/worker-configuration.d.ts +1 -1
- package/workers/data-worker/wrangler.jsonc.example +1 -1
- package/workers/image-worker/worker-configuration.d.ts +1 -1
- package/workers/image-worker/wrangler.jsonc.example +1 -1
- package/workers/pdf-worker/worker-configuration.d.ts +2 -3
- package/workers/pdf-worker/wrangler.jsonc.example +1 -1
- package/workers/user-worker/src/auth.ts +30 -0
- package/workers/user-worker/src/cleanup/account-deletion.ts +337 -0
- package/workers/user-worker/src/config.ts +4 -0
- package/workers/user-worker/src/encryption-utils.ts +25 -0
- package/workers/user-worker/src/firebase/admin.ts +152 -0
- package/workers/user-worker/src/handlers/user-routes.ts +242 -0
- package/workers/user-worker/src/registry/user-kv.ts +172 -0
- package/workers/user-worker/src/storage/user-records.ts +34 -0
- package/workers/user-worker/src/types.ts +106 -0
- package/workers/user-worker/src/user-worker.example.ts +18 -964
- package/workers/user-worker/worker-configuration.d.ts +4 -2
- package/workers/user-worker/wrangler.jsonc.example +12 -1
- package/wrangler.toml.example +1 -1
- package/app/components/actions/case-export/data-processing.ts +0 -223
- package/app/components/sidebar/case-export/case-export.module.css +0 -418
- package/app/components/sidebar/case-export/case-export.tsx +0 -310
- package/app/types/exceljs-bare.d.ts +0 -9
- package/app/utils/auth/auth.ts +0 -11
- package/public/.well-known/security.txt +0 -6
- package/public/favicon.ico +0 -0
- package/public/icon-256.png +0 -0
- package/public/icon-512.png +0 -0
- package/public/manifest.json +0 -39
- package/public/shortcut.png +0 -0
- package/public/social-image.png +0 -0
- package/public/vendor/exceljs.LICENSE +0 -22
- package/public/vendor/exceljs.bare.min.js +0 -45
- package/scripts/deploy-all.sh +0 -166
- package/scripts/deploy-config/modules/env-utils.sh +0 -322
- package/scripts/deploy-config/modules/keys.sh +0 -404
- package/scripts/deploy-config/modules/prompt.sh +0 -372
- package/scripts/deploy-config/modules/scaffolding.sh +0 -344
- package/scripts/deploy-config/modules/validation.sh +0 -365
- package/scripts/deploy-config.sh +0 -236
- package/scripts/deploy-pages-secrets.sh +0 -231
- package/scripts/deploy-pages.sh +0 -34
- package/scripts/deploy-primershear-emails.sh +0 -167
- package/scripts/deploy-worker-secrets.sh +0 -374
- package/scripts/dev.cjs +0 -23
- package/scripts/install-workers.sh +0 -88
- package/scripts/run-eslint.cjs +0 -43
- package/scripts/update-compatibility-dates.cjs +0 -124
- package/scripts/update-markdown-versions.cjs +0 -43
- package/workers/keys-worker/package.json +0 -18
- package/workers/keys-worker/src/keys.example.ts +0 -67
- package/workers/keys-worker/src/keys.ts +0 -67
- package/workers/keys-worker/worker-configuration.d.ts +0 -7447
- package/workers/keys-worker/wrangler.jsonc.example +0 -15
package/.env.example
CHANGED
|
@@ -29,8 +29,7 @@ MEASUREMENT_ID=your_firebase_measurement_id_here
|
|
|
29
29
|
# ===============================
|
|
30
30
|
# FIREBASE SERVICE ACCOUNT CONFIGURATION
|
|
31
31
|
# ===============================
|
|
32
|
-
#
|
|
33
|
-
PROJECT_ID=your_firebase_project_id_here
|
|
32
|
+
# Shared PROJECT_ID above is also sourced from app/config/admin-service.json by the deploy scripts.
|
|
34
33
|
FIREBASE_SERVICE_ACCOUNT_EMAIL=your_firebase_service_account_email_here
|
|
35
34
|
FIREBASE_SERVICE_ACCOUNT_PRIVATE_KEY=your_firebase_service_account_private_key_here
|
|
36
35
|
|
|
@@ -81,17 +80,10 @@ DATA_AT_REST_ENCRYPTION_ACTIVE_KEY_ID=
|
|
|
81
80
|
PAGES_PROJECT_NAME=your_pages_project_name_here
|
|
82
81
|
PAGES_CUSTOM_DOMAIN=your_custom_domain_here
|
|
83
82
|
|
|
84
|
-
# ================================
|
|
85
|
-
# KEYS WORKER ENVIRONMENT VARIABLES
|
|
86
|
-
# ================================
|
|
87
|
-
# Worker domains can be entered manually or auto-generated as a 10-character subdomain of PAGES_CUSTOM_DOMAIN during scripts/deploy-config.sh.
|
|
88
|
-
KEYS_WORKER_NAME=your_keys_worker_name_here
|
|
89
|
-
KEYS_WORKER_DOMAIN=your_keys_worker_domain_here
|
|
90
|
-
KEYS_AUTH=your_custom_keys_auth_token_here
|
|
91
|
-
|
|
92
83
|
# ================================
|
|
93
84
|
# USER WORKER ENVIRONMENT VARIABLES
|
|
94
85
|
# ================================
|
|
86
|
+
# Worker domains can be entered manually or auto-generated as a shared subdomain during scripts/deploy-config.sh.
|
|
95
87
|
USER_WORKER_NAME=your_user_worker_name_here
|
|
96
88
|
USER_WORKER_DOMAIN=your_user_worker_domain_here
|
|
97
89
|
KV_STORE_ID=your_kv_store_id_here
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Striae is a cloud-native forensic annotation application for firearms identification, built with React Router and Cloudflare Workers.
|
|
4
4
|
|
|
5
|
-
This npm package publishes the Striae application source
|
|
5
|
+
This npm package publishes the Striae application source for teams that run/develop their own Striae environment.
|
|
6
6
|
|
|
7
7
|
## Live Project
|
|
8
8
|
|
|
@@ -21,53 +21,11 @@ This npm package publishes the Striae application source and deployment scaffold
|
|
|
21
21
|
- Not a small client SDK.
|
|
22
22
|
- Not a zero-config, ready-to-run desktop app.
|
|
23
23
|
|
|
24
|
-
##
|
|
25
|
-
|
|
26
|
-
**Striae Package Links**
|
|
24
|
+
## Striae Package Links
|
|
27
25
|
|
|
28
26
|
- npmjs: [https://www.npmjs.com/package/@striae-org/striae](https://www.npmjs.com/package/@striae-org/striae)
|
|
29
27
|
- GitHub Packages: [https://github.com/orgs/striae-org/packages/npm/package/striae](https://github.com/orgs/striae-org/packages/npm/package/striae)
|
|
30
28
|
|
|
31
|
-
1) Install the latest package:
|
|
32
|
-
|
|
33
|
-
```bash
|
|
34
|
-
npm i @striae-org/striae
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
2) Copy the package scaffold into the project root
|
|
38
|
-
|
|
39
|
-
```bash
|
|
40
|
-
cp -R node_modules/@striae-org/striae/. .
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
3) Reinstall using Striae's own package.json (includes dev deps like wrangler/react-router)
|
|
44
|
-
|
|
45
|
-
```bash
|
|
46
|
-
rm -rf node_modules package-lock.json
|
|
47
|
-
npm install
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
4) Prepare Firebase admin credentials (required before deploy-config can pass)
|
|
51
|
-
|
|
52
|
-
```bash
|
|
53
|
-
mkdir -p app/config
|
|
54
|
-
cp -f app/config-example/admin-service.json app/config/admin-service.json
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
5) Replace `app/config/admin-service.json` with your actual Firebase service account JSON
|
|
58
|
-
|
|
59
|
-
6) Authenticate Cloudflare CLI
|
|
60
|
-
|
|
61
|
-
```bash
|
|
62
|
-
npx wrangler login
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
7) Run guided config + full deployment
|
|
66
|
-
|
|
67
|
-
```bash
|
|
68
|
-
npm run deploy:all
|
|
69
|
-
```
|
|
70
|
-
|
|
71
29
|
## NPM Package Content Policy
|
|
72
30
|
|
|
73
31
|
This package intentionally includes only non-sensitive defaults and runtime source needed for setup.
|
|
@@ -75,9 +33,10 @@ This package intentionally includes only non-sensitive defaults and runtime sour
|
|
|
75
33
|
Included:
|
|
76
34
|
|
|
77
35
|
- `app/` source (with `app/config-example/`)
|
|
78
|
-
- `functions/`, `public
|
|
36
|
+
- `functions/`, `public/`
|
|
79
37
|
- Worker package manifests
|
|
80
|
-
- Worker source files
|
|
38
|
+
- Worker source files needed by the example workers, including nested helper modules, while excluding production worker entry files (`workers/*/src/**/*.ts` excluding `workers/*/src/**/*worker.ts`)
|
|
39
|
+
- PDF worker example support files limited to `workers/pdf-worker/src/assets/generated-assets.example.ts` and `workers/pdf-worker/src/formats/format-striae.ts` (no extra PDF image assets or custom formats)
|
|
81
40
|
- Worker example Wrangler configs (`workers/*/wrangler.jsonc.example`)
|
|
82
41
|
- Project-level example and build config (`.env.example`, `wrangler.toml.example`, `tsconfig.json`, etc.)
|
|
83
42
|
|
|
@@ -1,183 +1,11 @@
|
|
|
1
1
|
import type { User } from 'firebase/auth';
|
|
2
|
-
import { type AnnotationData, type CaseExportData, type
|
|
2
|
+
import { type AnnotationData, type CaseExportData, type ExportOptions } from '~/types';
|
|
3
3
|
import { getCaseData } from '~/utils/data';
|
|
4
4
|
import { fetchFiles } from '../image-manage';
|
|
5
5
|
import { getNotes } from '../notes-manage';
|
|
6
|
-
import { validateCaseNumber
|
|
6
|
+
import { validateCaseNumber } from '../case-manage';
|
|
7
7
|
import { getUserExportMetadata } from './metadata-helpers';
|
|
8
8
|
|
|
9
|
-
/**
|
|
10
|
-
* Export all cases for a user
|
|
11
|
-
*/
|
|
12
|
-
export async function exportAllCases(
|
|
13
|
-
user: User,
|
|
14
|
-
options: ExportOptions = {},
|
|
15
|
-
onProgress?: (current: number, total: number, caseName: string) => void
|
|
16
|
-
): Promise<AllCasesExportData> {
|
|
17
|
-
// NOTE: startTime tracking moved to download handlers
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
// NOTE: Audit workflow management moved to download handlers
|
|
21
|
-
|
|
22
|
-
const {
|
|
23
|
-
includeMetadata = true
|
|
24
|
-
} = options;
|
|
25
|
-
|
|
26
|
-
// Get user export metadata
|
|
27
|
-
const userMetadata = await getUserExportMetadata(user);
|
|
28
|
-
|
|
29
|
-
// Get list of all cases for the user
|
|
30
|
-
const caseNumbers = await listCases(user);
|
|
31
|
-
|
|
32
|
-
if (!caseNumbers || caseNumbers.length === 0) {
|
|
33
|
-
throw new Error('No cases found for user');
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const exportedCases: CaseExportData[] = [];
|
|
37
|
-
let totalFiles = 0;
|
|
38
|
-
let totalAnnotations = 0;
|
|
39
|
-
let totalConfirmations = 0;
|
|
40
|
-
let totalConfirmationsRequested = 0;
|
|
41
|
-
let casesWithFiles = 0;
|
|
42
|
-
let casesWithAnnotations = 0;
|
|
43
|
-
let casesWithoutFiles = 0;
|
|
44
|
-
let lastModified: string | undefined;
|
|
45
|
-
let earliestAnnotationDate: string | undefined;
|
|
46
|
-
let latestAnnotationDate: string | undefined;
|
|
47
|
-
|
|
48
|
-
// Export each case
|
|
49
|
-
for (let i = 0; i < caseNumbers.length; i++) {
|
|
50
|
-
const caseNumber = caseNumbers[i];
|
|
51
|
-
|
|
52
|
-
// Report progress
|
|
53
|
-
if (onProgress) {
|
|
54
|
-
onProgress(i + 1, caseNumbers.length, caseNumber);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
try {
|
|
58
|
-
const caseExport = await exportCaseData(user, caseNumber, options);
|
|
59
|
-
exportedCases.push(caseExport);
|
|
60
|
-
|
|
61
|
-
// Update totals
|
|
62
|
-
totalFiles += caseExport.metadata.totalFiles;
|
|
63
|
-
|
|
64
|
-
if (caseExport.metadata.totalFiles > 0) {
|
|
65
|
-
casesWithFiles++;
|
|
66
|
-
} else {
|
|
67
|
-
casesWithoutFiles++;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// Count annotations and confirmations
|
|
71
|
-
const caseAnnotations = caseExport.files.filter(f => f.hasAnnotations).length;
|
|
72
|
-
if (caseAnnotations > 0) {
|
|
73
|
-
casesWithAnnotations++;
|
|
74
|
-
totalAnnotations += caseAnnotations;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Count confirmations
|
|
78
|
-
if (caseExport.summary?.filesWithConfirmations) {
|
|
79
|
-
totalConfirmations += caseExport.summary.filesWithConfirmations;
|
|
80
|
-
}
|
|
81
|
-
if (caseExport.summary?.filesWithConfirmationsRequested) {
|
|
82
|
-
totalConfirmationsRequested += caseExport.summary.filesWithConfirmationsRequested;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Track latest modification
|
|
86
|
-
if (caseExport.summary?.lastModified) {
|
|
87
|
-
if (!lastModified || caseExport.summary.lastModified > lastModified) {
|
|
88
|
-
lastModified = caseExport.summary.lastModified;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Track annotation date range across all cases
|
|
93
|
-
if (caseExport.summary?.earliestAnnotationDate) {
|
|
94
|
-
if (!earliestAnnotationDate || caseExport.summary.earliestAnnotationDate < earliestAnnotationDate) {
|
|
95
|
-
earliestAnnotationDate = caseExport.summary.earliestAnnotationDate;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
if (caseExport.summary?.latestAnnotationDate) {
|
|
99
|
-
if (!latestAnnotationDate || caseExport.summary.latestAnnotationDate > latestAnnotationDate) {
|
|
100
|
-
latestAnnotationDate = caseExport.summary.latestAnnotationDate;
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
} catch (error) {
|
|
105
|
-
// Get case creation date even for failed exports
|
|
106
|
-
let caseCreatedDate = new Date().toISOString(); // fallback
|
|
107
|
-
try {
|
|
108
|
-
const caseData = await getCaseData(user, caseNumber);
|
|
109
|
-
if (caseData?.createdAt) {
|
|
110
|
-
caseCreatedDate = caseData.createdAt;
|
|
111
|
-
}
|
|
112
|
-
} catch {
|
|
113
|
-
// Use fallback date if case lookup fails
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Create a placeholder entry for failed exports
|
|
117
|
-
exportedCases.push({
|
|
118
|
-
metadata: {
|
|
119
|
-
caseNumber,
|
|
120
|
-
caseCreatedDate,
|
|
121
|
-
exportDate: new Date().toISOString(),
|
|
122
|
-
...userMetadata,
|
|
123
|
-
striaeExportSchemaVersion: '1.0',
|
|
124
|
-
totalFiles: 0
|
|
125
|
-
},
|
|
126
|
-
files: [],
|
|
127
|
-
summary: {
|
|
128
|
-
filesWithAnnotations: 0,
|
|
129
|
-
filesWithoutAnnotations: 0,
|
|
130
|
-
totalBoxAnnotations: 0,
|
|
131
|
-
exportError: error instanceof Error ? error.message : 'Unknown error'
|
|
132
|
-
}
|
|
133
|
-
});
|
|
134
|
-
casesWithoutFiles++;
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const allCasesExport: AllCasesExportData = {
|
|
139
|
-
metadata: {
|
|
140
|
-
exportDate: new Date().toISOString(),
|
|
141
|
-
...userMetadata,
|
|
142
|
-
striaeExportSchemaVersion: '1.0',
|
|
143
|
-
totalCases: caseNumbers.length,
|
|
144
|
-
totalFiles,
|
|
145
|
-
totalAnnotations,
|
|
146
|
-
totalConfirmations,
|
|
147
|
-
totalConfirmationsRequested
|
|
148
|
-
},
|
|
149
|
-
cases: exportedCases
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
if (includeMetadata) {
|
|
153
|
-
allCasesExport.summary = {
|
|
154
|
-
casesWithFiles,
|
|
155
|
-
casesWithAnnotations,
|
|
156
|
-
casesWithoutFiles,
|
|
157
|
-
lastModified,
|
|
158
|
-
earliestAnnotationDate,
|
|
159
|
-
latestAnnotationDate
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Report completion
|
|
164
|
-
if (onProgress) {
|
|
165
|
-
onProgress(caseNumbers.length, caseNumbers.length, 'Export completed!');
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// NOTE: Audit logging moved to download handlers where actual filename and format are known
|
|
169
|
-
|
|
170
|
-
return allCasesExport;
|
|
171
|
-
|
|
172
|
-
} catch (error) {
|
|
173
|
-
console.error('Export all cases failed:', error);
|
|
174
|
-
|
|
175
|
-
// NOTE: Audit logging for failures moved to download handlers
|
|
176
|
-
|
|
177
|
-
throw error;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
9
|
/**
|
|
182
10
|
* Export case data with files and annotations
|
|
183
11
|
*/
|