@striae-org/striae 4.0.0 → 4.0.2

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 (99) hide show
  1. package/.env.example +1 -0
  2. package/README.md +1 -1
  3. package/app/components/actions/case-export/data-processing.ts +1 -1
  4. package/app/components/actions/case-export/download-handlers.ts +5 -4
  5. package/app/components/actions/case-export/metadata-helpers.ts +1 -1
  6. package/app/components/actions/case-import/confirmation-import.ts +1 -1
  7. package/app/components/actions/case-import/image-operations.ts +1 -1
  8. package/app/components/actions/case-import/orchestrator.ts +1 -1
  9. package/app/components/actions/case-import/storage-operations.ts +3 -3
  10. package/app/components/actions/case-import/validation.ts +3 -4
  11. package/app/components/actions/case-import/zip-processing.ts +1 -1
  12. package/app/components/actions/case-manage.ts +3 -5
  13. package/app/components/actions/confirm-export.ts +4 -5
  14. package/app/components/actions/generate-pdf.ts +1 -1
  15. package/app/components/actions/image-manage.ts +4 -4
  16. package/app/components/actions/notes-manage.ts +1 -1
  17. package/app/components/actions/signout.tsx +1 -1
  18. package/app/components/audit/user-audit-viewer.tsx +1 -1
  19. package/app/components/auth/auth-provider.tsx +1 -1
  20. package/app/components/auth/mfa-verification.tsx +1 -1
  21. package/app/components/button/button.tsx +1 -1
  22. package/app/components/canvas/box-annotations/box-annotations.tsx +1 -1
  23. package/app/components/canvas/confirmation/confirmation.tsx +1 -1
  24. package/app/components/icon/icon.tsx +1 -1
  25. package/app/components/public-signing-key-modal/public-signing-key-modal.tsx +1 -1
  26. package/app/components/sidebar/case-export/case-export.tsx +1 -1
  27. package/app/components/sidebar/cases/case-sidebar.tsx +3 -3
  28. package/app/components/sidebar/cases/cases-modal.tsx +1 -1
  29. package/app/components/sidebar/files/files-modal.tsx +1 -1
  30. package/app/components/sidebar/notes/notes-sidebar.tsx +1 -1
  31. package/app/components/sidebar/sidebar-container.tsx +2 -17
  32. package/app/components/sidebar/sidebar.module.css +0 -29
  33. package/app/components/theme-provider/theme-provider.tsx +1 -1
  34. package/app/components/theme-provider/theme.ts +1 -1
  35. package/app/components/user/delete-account.tsx +1 -1
  36. package/app/components/user/manage-profile.tsx +1 -1
  37. package/app/components/user/mfa-phone-update.tsx +1 -1
  38. package/app/root.tsx +18 -51
  39. package/app/routes/auth/emailActionHandler.tsx +2 -3
  40. package/app/routes/auth/emailVerification.tsx +2 -2
  41. package/app/routes/auth/login.tsx +7 -9
  42. package/app/routes/auth/passwordReset.tsx +2 -2
  43. package/app/routes/striae/striae.tsx +2 -2
  44. package/app/services/audit/audit-export-signing.ts +2 -2
  45. package/app/services/audit/audit-export.service.ts +1 -2
  46. package/app/services/audit/audit.service.ts +1 -1
  47. package/app/services/firebase/index.ts +1 -1
  48. package/app/utils/api/index.ts +4 -0
  49. package/app/utils/auth/index.ts +5 -0
  50. package/app/utils/common/index.ts +3 -0
  51. package/app/utils/{version.ts → common/version.ts} +1 -1
  52. package/app/utils/{data-operations.ts → data/data-operations.ts} +4 -4
  53. package/app/utils/data/index.ts +2 -0
  54. package/app/utils/{permissions.ts → data/permissions.ts} +1 -1
  55. package/app/utils/forensics/index.ts +5 -0
  56. package/app/utils/ui/index.ts +2 -0
  57. package/functions/api/image/[[path]].ts +17 -1
  58. package/package.json +18 -20
  59. package/public/.well-known/keybase.txt +56 -0
  60. package/public/.well-known/security.txt +3 -4
  61. package/scripts/deploy-config.sh +178 -142
  62. package/scripts/deploy-worker-secrets.sh +1 -2
  63. package/worker-configuration.d.ts +7491 -11363
  64. package/workers/audit-worker/worker-configuration.d.ts +11323 -7448
  65. package/workers/audit-worker/wrangler.jsonc.example +1 -1
  66. package/workers/data-worker/worker-configuration.d.ts +11323 -7448
  67. package/workers/data-worker/wrangler.jsonc.example +1 -1
  68. package/workers/image-worker/src/image-worker.example.ts +10 -2
  69. package/workers/image-worker/worker-configuration.d.ts +11322 -7447
  70. package/workers/image-worker/wrangler.jsonc.example +1 -1
  71. package/workers/keys-worker/src/keys.ts +2 -1
  72. package/workers/keys-worker/worker-configuration.d.ts +11322 -7447
  73. package/workers/keys-worker/wrangler.jsonc.example +1 -1
  74. package/workers/pdf-worker/src/pdf-worker.example.ts +144 -39
  75. package/workers/pdf-worker/worker-configuration.d.ts +11323 -7448
  76. package/workers/pdf-worker/wrangler.jsonc.example +1 -1
  77. package/workers/user-worker/worker-configuration.d.ts +11323 -7448
  78. package/workers/user-worker/wrangler.jsonc.example +1 -1
  79. package/wrangler.toml.example +1 -1
  80. package/public/.well-known/publickey.info@striae.org.asc +0 -17
  81. package/public/oin-badge.png +0 -0
  82. /package/app/utils/{data-api-client.ts → api/data-api-client.ts} +0 -0
  83. /package/app/utils/{image-api-client.ts → api/image-api-client.ts} +0 -0
  84. /package/app/utils/{pdf-api-client.ts → api/pdf-api-client.ts} +0 -0
  85. /package/app/utils/{user-api-client.ts → api/user-api-client.ts} +0 -0
  86. /package/app/utils/{auth-action-settings.ts → auth/auth-action-settings.ts} +0 -0
  87. /package/app/utils/{auth.ts → auth/auth.ts} +0 -0
  88. /package/app/utils/{mfa-phone.ts → auth/mfa-phone.ts} +0 -0
  89. /package/app/utils/{mfa.ts → auth/mfa.ts} +0 -0
  90. /package/app/utils/{password-policy.ts → auth/password-policy.ts} +0 -0
  91. /package/app/utils/{batch-operations.ts → common/batch-operations.ts} +0 -0
  92. /package/app/utils/{id-generator.ts → common/id-generator.ts} +0 -0
  93. /package/app/utils/{SHA256.ts → forensics/SHA256.ts} +0 -0
  94. /package/app/utils/{audit-export-signature.ts → forensics/audit-export-signature.ts} +0 -0
  95. /package/app/utils/{confirmation-signature.ts → forensics/confirmation-signature.ts} +0 -0
  96. /package/app/utils/{export-verification.ts → forensics/export-verification.ts} +0 -0
  97. /package/app/utils/{signature-utils.ts → forensics/signature-utils.ts} +0 -0
  98. /package/app/utils/{annotation-timestamp.ts → ui/annotation-timestamp.ts} +0 -0
  99. /package/app/utils/{style.ts → ui/style.ts} +0 -0
package/.env.example CHANGED
@@ -88,6 +88,7 @@ HMAC_KEY=your_cloudflare_images_hmac_key_here
88
88
  PDF_WORKER_NAME=your_pdf_worker_name_here
89
89
  PDF_WORKER_DOMAIN=your_pdf_worker_domain_here
90
90
  PDF_WORKER_AUTH=your_custom_pdf_worker_auth_token_here
91
+ BROWSER_API_TOKEN=your_cloudflare_browser_rendering_api_token_here
91
92
 
92
93
  # ================================
93
94
  # QUICK MANUAL SETUP CHECKLIST
package/README.md CHANGED
@@ -6,7 +6,7 @@ This npm package publishes the Striae application source and deployment scaffold
6
6
 
7
7
  ## Live Project
8
8
 
9
- - Application: [https://www.striae.org](https://www.striae.org)
9
+ - Application: [https://striae.app](https://striae.app)
10
10
  - Source repository: [https://github.com/striae-org/striae](https://github.com/striae-org/striae)
11
11
  - Releases: [https://github.com/striae-org/striae/releases](https://github.com/striae-org/striae/releases)
12
12
  - Security policy: [https://github.com/striae-org/striae/security/policy](https://github.com/striae-org/striae/security/policy)
@@ -1,5 +1,5 @@
1
1
  import { type CaseExportData } from '~/types';
2
- import { calculateSHA256Secure } from '~/utils/SHA256';
2
+ import { calculateSHA256Secure } from '~/utils/forensics';
3
3
  import { CSV_HEADERS } from './types-constants';
4
4
  import { addForensicDataWarning } from './metadata-helpers';
5
5
 
@@ -2,13 +2,14 @@ import type { User } from 'firebase/auth';
2
2
  import type * as ExcelJSModule from 'exceljs';
3
3
  import { type FileData, type AllCasesExportData, type CaseExportData, type ExportOptions } from '~/types';
4
4
  import { getImageUrl } from '../image-manage';
5
- import { generateForensicManifestSecure, calculateSHA256Secure } from '~/utils/SHA256';
6
- import { signForensicManifest } from '~/utils/data-operations';
7
5
  import {
6
+ generateForensicManifestSecure,
7
+ calculateSHA256Secure,
8
8
  createPublicSigningKeyFileName,
9
9
  getCurrentPublicSigningKeyDetails,
10
10
  getVerificationPublicKey
11
- } from '~/utils/signature-utils';
11
+ } from '~/utils/forensics';
12
+ import { signForensicManifest } from '~/utils/data';
12
13
  import { type ExportFormat, formatDateForFilename, CSV_HEADERS } from './types-constants';
13
14
  import { protectExcelWorksheet, addForensicDataWarning } from './metadata-helpers';
14
15
  import { generateMetadataRows, generateCSVContent, processFileDataForTabular, sanitizeTabularMatrix } from './data-processing';
@@ -975,7 +976,7 @@ forensic procedures and maintain proper documentation.`;
975
976
  const footer = `
976
977
 
977
978
  Generated by Striae - A Firearms Examiner's Comparison Companion
978
- https://www.striae.org`;
979
+ https://striae.app`;
979
980
 
980
981
  return protectForensicData ? baseContent + forensicAddition + footer : baseContent + footer;
981
982
  }
@@ -1,5 +1,5 @@
1
1
  import type { User } from 'firebase/auth';
2
- import { getUserData } from '~/utils/permissions';
2
+ import { getUserData } from '~/utils/data';
3
3
 
4
4
  /**
5
5
  * Helper function to get user export metadata
@@ -1,5 +1,5 @@
1
1
  import type { User } from 'firebase/auth';
2
- import { fetchDataApi } from '~/utils/data-api-client';
2
+ import { fetchDataApi } from '~/utils/api';
3
3
  import { type ConfirmationImportResult, type ConfirmationImportData } from '~/types';
4
4
  import { checkExistingCase } from '../case-manage';
5
5
  import { extractConfirmationImportPackage } from './confirmation-package';
@@ -1,5 +1,5 @@
1
1
  import type { User } from 'firebase/auth';
2
- import { uploadImageApi } from '~/utils/image-api-client';
2
+ import { uploadImageApi } from '~/utils/api';
3
3
  import { type FileData } from '~/types';
4
4
 
5
5
  /**
@@ -6,7 +6,7 @@ import {
6
6
  type SignedForensicManifest,
7
7
  validateCaseIntegritySecure as validateForensicIntegrity,
8
8
  verifyForensicManifestSignature
9
- } from '~/utils/SHA256';
9
+ } from '~/utils/forensics';
10
10
  import { deleteFile } from '../image-manage';
11
11
  import { parseImportZip } from './zip-processing';
12
12
  import {
@@ -1,10 +1,10 @@
1
1
  import type { User } from 'firebase/auth';
2
- import { fetchDataApi } from '~/utils/data-api-client';
2
+ import { fetchDataApi } from '~/utils/api';
3
3
  import {
4
4
  getUserReadOnlyCases,
5
5
  updateUserData,
6
6
  validateUserSession
7
- } from '~/utils/permissions';
7
+ } from '~/utils/data';
8
8
  import {
9
9
  type CaseExportData,
10
10
  type FileData,
@@ -12,7 +12,7 @@ import {
12
12
  type ReadOnlyCaseMetadata
13
13
  } from '~/types';
14
14
  import { deleteFile } from '../image-manage';
15
- import { type SignedForensicManifest } from '~/utils/SHA256';
15
+ import { type SignedForensicManifest } from '~/utils/forensics';
16
16
 
17
17
  /**
18
18
  * Check if user already has a read-only case with the same number
@@ -1,9 +1,8 @@
1
1
  import type { User } from 'firebase/auth';
2
- import { checkUserExistsApi } from '~/utils/user-api-client';
2
+ import { checkUserExistsApi } from '~/utils/api';
3
3
  import { type CaseExportData, type ConfirmationImportData } from '~/types';
4
- import { type ManifestSignatureVerificationResult } from '~/utils/SHA256';
5
- import { verifyConfirmationSignature } from '~/utils/confirmation-signature';
6
- export { removeForensicWarning, validateConfirmationHash } from '~/utils/export-verification';
4
+ import { type ManifestSignatureVerificationResult, verifyConfirmationSignature } from '~/utils/forensics';
5
+ export { removeForensicWarning, validateConfirmationHash } from '~/utils/forensics';
7
6
 
8
7
  /**
9
8
  * Validate that a user exists in the database by UID and is not the current user
@@ -6,7 +6,7 @@ import {
6
6
  type SignedForensicManifest,
7
7
  validateCaseIntegritySecure as validateForensicIntegrity,
8
8
  verifyForensicManifestSignature
9
- } from '~/utils/SHA256';
9
+ } from '~/utils/forensics';
10
10
  import { validateExporterUid, removeForensicWarning } from './validation';
11
11
 
12
12
  function getLeafFileName(path: string): string {
@@ -4,18 +4,16 @@ import {
4
4
  getUserCases,
5
5
  validateUserSession,
6
6
  addUserCase,
7
- removeUserCase
8
- } from '~/utils/permissions';
9
- import {
7
+ removeUserCase,
10
8
  getCaseData,
11
9
  updateCaseData,
12
10
  deleteCaseData,
13
11
  duplicateCaseData,
14
12
  deleteFileAnnotations
15
- } from '~/utils/data-operations';
13
+ } from '~/utils/data';
16
14
  import { type CaseData, type ReadOnlyCaseData, type FileData } from '~/types';
17
15
  import { auditService } from '~/services/audit';
18
- import { fetchImageApi } from '~/utils/image-api-client';
16
+ import { fetchImageApi } from '~/utils/api';
19
17
 
20
18
  /**
21
19
  * Delete a file without individual audit logging (for bulk operations)
@@ -1,13 +1,12 @@
1
1
  import type { User } from 'firebase/auth';
2
- import { calculateSHA256Secure } from '~/utils/SHA256';
3
- import { getUserData } from '~/utils/permissions';
4
- import { getCaseData, updateCaseData, signConfirmationData } from '~/utils/data-operations';
5
- import { type ConfirmationData, type CaseConfirmations, type CaseDataWithConfirmations, type ConfirmationImportData } from '~/types';
6
2
  import {
3
+ calculateSHA256Secure,
7
4
  createPublicSigningKeyFileName,
8
5
  getCurrentPublicSigningKeyDetails,
9
6
  getVerificationPublicKey
10
- } from '~/utils/signature-utils';
7
+ } from '~/utils/forensics';
8
+ import { getUserData, getCaseData, updateCaseData, signConfirmationData } from '~/utils/data';
9
+ import { type ConfirmationData, type CaseConfirmations, type CaseDataWithConfirmations, type ConfirmationImportData } from '~/types';
11
10
  import { auditService } from '~/services/audit';
12
11
 
13
12
  /**
@@ -1,7 +1,7 @@
1
1
  import { type AnnotationData } from '~/types/annotations';
2
2
  import { auditService } from '~/services/audit';
3
3
  import type { User } from 'firebase/auth';
4
- import { fetchPdfApi } from '~/utils/pdf-api-client';
4
+ import { fetchPdfApi } from '~/utils/api';
5
5
 
6
6
  interface GeneratePDFParams {
7
7
  user: User;
@@ -2,9 +2,8 @@ import type { User } from 'firebase/auth';
2
2
  import {
3
3
  getAccountHash
4
4
  } from '~/utils/auth';
5
- import { fetchImageApi, uploadImageApi } from '~/utils/image-api-client';
6
- import { canUploadFile } from '~/utils/permissions';
7
- import { getCaseData, updateCaseData, deleteFileAnnotations } from '~/utils/data-operations';
5
+ import { fetchImageApi, uploadImageApi } from '~/utils/api';
6
+ import { canUploadFile, getCaseData, updateCaseData, deleteFileAnnotations } from '~/utils/data';
8
7
  import type { CaseData, FileData, ImageUploadResponse } from '~/types';
9
8
  import { auditService } from '~/services/audit';
10
9
 
@@ -244,8 +243,9 @@ export const getImageUrl = async (user: User, fileData: FileData, caseNumber: st
244
243
  try {
245
244
  const { accountHash } = await getImageConfig();
246
245
  const imageDeliveryUrl = `https://imagedelivery.net/${accountHash}/${fileData.id}/${DEFAULT_VARIANT}`;
246
+ const encodedImageDeliveryUrl = encodeURIComponent(imageDeliveryUrl);
247
247
 
248
- const workerResponse = await fetchImageApi(user, `/${imageDeliveryUrl}`, {
248
+ const workerResponse = await fetchImageApi(user, `/${encodedImageDeliveryUrl}`, {
249
249
  method: 'GET',
250
250
  headers: {
251
251
  'Accept': 'text/plain'
@@ -1,6 +1,6 @@
1
1
  import type { User } from 'firebase/auth';
2
2
  import { type AnnotationData } from '~/types/annotations';
3
- import { saveFileAnnotations, getFileAnnotations, type DataOperationOptions } from '~/utils/data-operations';
3
+ import { saveFileAnnotations, getFileAnnotations, type DataOperationOptions } from '~/utils/data';
4
4
 
5
5
  export const saveNotes = async (
6
6
  user: User,
@@ -1,6 +1,6 @@
1
1
  import { auth } from '~/services/firebase';
2
2
  import { auditService } from '~/services/audit';
3
- import { generateUniqueId } from '~/utils/id-generator';
3
+ import { generateUniqueId } from '~/utils/common';
4
4
  import styles from './signout.module.css';
5
5
 
6
6
  interface SignOutProps {
@@ -2,7 +2,7 @@ import { useState, useEffect, useContext, useCallback } from 'react';
2
2
  import { AuthContext } from '~/contexts/auth.context';
3
3
  import { auditService, auditExportService } from '~/services/audit';
4
4
  import { type ValidationAuditEntry, type AuditAction, type AuditResult, type AuditTrail, type UserData, type WorkflowPhase } from '~/types';
5
- import { getUserData } from '~/utils/permissions';
5
+ import { getUserData } from '~/utils/data';
6
6
  import styles from './user-audit.module.css';
7
7
 
8
8
  const isWorkflowPhase = (phase: unknown): phase is WorkflowPhase =>
@@ -6,7 +6,7 @@ import { INACTIVITY_CONFIG } from '~/config/inactivity';
6
6
  import { AuthContext } from '~/contexts/auth.context';
7
7
  import { InactivityWarning } from '~/components/user/inactivity-warning';
8
8
  import { auditService } from '~/services/audit';
9
- import { generateUniqueId } from '~/utils/id-generator';
9
+ import { generateUniqueId } from '~/utils/common';
10
10
 
11
11
  interface AuthProviderProps {
12
12
  children: React.ReactNode;
@@ -10,7 +10,7 @@ import { auth } from '~/services/firebase';
10
10
  import { handleAuthError, getValidationError } from '~/services/firebase/errors';
11
11
  import { SignOut } from '~/components/actions/signout';
12
12
  import { auditService } from '~/services/audit';
13
- import { generateUniqueId } from '~/utils/id-generator';
13
+ import { generateUniqueId } from '~/utils/common';
14
14
  import styles from './mfa-verification.module.css';
15
15
 
16
16
  interface MFAVerificationProps {
@@ -1,6 +1,6 @@
1
1
  import { Icon } from '../icon/icon';
2
2
  import styles from './button.module.css';
3
- import { classes } from '~/utils/style';
3
+ import { classes } from '~/utils/ui';
4
4
 
5
5
  interface ButtonProps {
6
6
  iconId: string;
@@ -2,7 +2,7 @@ import { useState, useCallback, useMemo, useRef, useEffect, useContext } from 'r
2
2
  import { type BoxAnnotation } from '~/types';
3
3
  import { AuthContext } from '~/contexts/auth.context';
4
4
  import { auditService } from '~/services/audit';
5
- import { resolveEarliestAnnotationTimestamp } from '~/utils/annotation-timestamp';
5
+ import { resolveEarliestAnnotationTimestamp } from '~/utils/ui';
6
6
  import styles from './box-annotations.module.css';
7
7
 
8
8
  // Constants
@@ -1,7 +1,7 @@
1
1
  import { useState, useEffect, useContext } from 'react';
2
2
  import { type ConfirmationData } from '~/types/annotations';
3
3
  import { AuthContext } from '~/contexts/auth.context';
4
- import { generateConfirmationId } from '~/utils/id-generator';
4
+ import { generateConfirmationId } from '~/utils/common';
5
5
  import styles from './confirmation.module.css';
6
6
 
7
7
  interface ConfirmationModalProps {
@@ -1,4 +1,4 @@
1
- import { classes } from '~/utils/style';
1
+ import { classes } from '~/utils/ui';
2
2
  import styles from './icon.module.css';
3
3
  import { forwardRef } from 'react';
4
4
  import sprites from './icons.svg';
@@ -9,7 +9,7 @@ import {
9
9
  type MouseEvent
10
10
  } from 'react';
11
11
  import styles from './public-signing-key-modal.module.css';
12
- import { verifyExportFile } from '~/utils/export-verification';
12
+ import { verifyExportFile } from '~/utils/forensics';
13
13
 
14
14
  const NO_PUBLIC_KEY_MESSAGE = 'No public signing key is configured for this environment.';
15
15
 
@@ -2,7 +2,7 @@ import { useState, useEffect, useContext } from 'react';
2
2
  import styles from './case-export.module.css';
3
3
  import { AuthContext } from '~/contexts/auth.context';
4
4
  import { PublicSigningKeyModal } from '~/components/public-signing-key-modal/public-signing-key-modal';
5
- import { getCurrentPublicSigningKeyDetails } from '~/utils/signature-utils';
5
+ import { getCurrentPublicSigningKeyDetails } from '~/utils/forensics';
6
6
  import { getCaseConfirmations, exportConfirmationData } from '../../actions/confirm-export';
7
7
 
8
8
  export type ExportFormat = 'json' | 'csv';
@@ -26,9 +26,9 @@ import {
26
26
  canCreateCase,
27
27
  canUploadFile,
28
28
  getLimitsDescription,
29
- getUserData
30
- } from '~/utils/permissions';
31
- import { getFileAnnotations } from '~/utils/data-operations';
29
+ getUserData,
30
+ getFileAnnotations
31
+ } from '~/utils/data';
32
32
  import { type FileData, type CaseActionType } from '~/types';
33
33
 
34
34
  interface CaseSidebarProps {
@@ -1,7 +1,7 @@
1
1
  import { useState, useEffect } from 'react';
2
2
  import type { User } from 'firebase/auth';
3
3
  import { listCases } from '~/components/actions/case-manage';
4
- import { getFileAnnotations } from '~/utils/data-operations';
4
+ import { getFileAnnotations } from '~/utils/data';
5
5
  import { fetchFiles } from '~/components/actions/image-manage';
6
6
  import styles from './cases-modal.module.css';
7
7
 
@@ -2,7 +2,7 @@ import type React from 'react';
2
2
  import { useState, useContext, useEffect } from 'react';
3
3
  import { AuthContext } from '~/contexts/auth.context';
4
4
  import { deleteFile } from '~/components/actions/image-manage';
5
- import { getFileAnnotations } from '~/utils/data-operations';
5
+ import { getFileAnnotations } from '~/utils/data';
6
6
  import { type FileData } from '~/types';
7
7
  import styles from './files-modal.module.css';
8
8
 
@@ -4,7 +4,7 @@ import { ColorSelector } from '~/components/colors/colors';
4
4
  import { NotesModal } from './notes-modal';
5
5
  import { getNotes, saveNotes } from '~/components/actions/notes-manage';
6
6
  import { type AnnotationData } from '~/types/annotations';
7
- import { resolveEarliestAnnotationTimestamp } from '~/utils/annotation-timestamp';
7
+ import { resolveEarliestAnnotationTimestamp } from '~/utils/ui';
8
8
  import { auditService } from '~/services/audit';
9
9
  import styles from './notes.module.css';
10
10
 
@@ -7,7 +7,7 @@ import { Sidebar } from './sidebar';
7
7
  import type { User } from 'firebase/auth';
8
8
  import { type FileData } from '~/types';
9
9
  import styles from './sidebar.module.css';
10
- import { getAppVersion } from '../../utils/version';
10
+ import { getAppVersion } from '~/utils/common';
11
11
 
12
12
  interface SidebarContainerProps {
13
13
  user: User;
@@ -121,22 +121,7 @@ export const SidebarContainer: React.FC<SidebarContainerProps> = (props) => {
121
121
  Security Policy
122
122
  </Link>
123
123
  </div>
124
- <div className={styles.badgeContainer}>
125
- <div className={styles.oinBadge}>
126
- <a
127
- href="https://openinventionnetwork.com/"
128
- target="_blank"
129
- rel="noopener noreferrer"
130
- className={styles.oinBadgeLink}
131
- >
132
- <img
133
- src="/oin-badge.png"
134
- alt="Open Invention Network Community Member"
135
- className={styles.oinBadgeImage}
136
- />
137
- </a>
138
- </div>
139
- </div>
124
+
140
125
  <div className={styles.footerModalCopyright}>
141
126
  <a href={`https://github.com/striae-org/striae/releases/tag/v${appVersion}`} className={styles.link} target="_blank" rel="noopener noreferrer">Striae v{appVersion}</a> © {year}.{' '}
142
127
  Licensed under Apache 2.0.
@@ -237,36 +237,7 @@
237
237
  text-underline-offset: 3px;
238
238
  }
239
239
 
240
- .badgeContainer {
241
- display: flex;
242
- justify-content: center;
243
- align-items: center;
244
- gap: var(--spaceM, 1rem);
245
- margin-top: var(--spaceXS, 0.5rem);
246
- flex-wrap: wrap;
247
- width: 100%;
248
- }
249
-
250
- .oinBadge {
251
- text-align: center;
252
- }
253
240
 
254
- .oinBadgeLink {
255
- display: inline-block;
256
- transition: opacity var(--durationS, 0.2s)
257
- var(--bezierFastoutSlowin, ease-out);
258
- }
259
-
260
- .oinBadgeLink:hover {
261
- opacity: 0.8;
262
- transform: translateY(-1px);
263
- }
264
-
265
- .oinBadgeImage {
266
- height: 40px;
267
- width: auto;
268
- border-radius: 4px;
269
- }
270
241
 
271
242
  /* Import Section */
272
243
  .importSection {
@@ -1,5 +1,5 @@
1
1
  import { type JSX, createContext, useContext } from 'react';
2
- import { classes, media } from '~/utils/style';
2
+ import { classes, media } from '~/utils/ui';
3
3
  import { themes, tokens } from './theme';
4
4
 
5
5
  interface ThemeContextType {
@@ -1,4 +1,4 @@
1
- import { pxToRem } from '~/utils/style';
1
+ import { pxToRem } from '~/utils/ui';
2
2
 
3
3
  // Full list of tokens
4
4
  const baseTokens = {
@@ -1,7 +1,7 @@
1
1
  import { useState, useEffect } from 'react';
2
2
  import { signOut } from 'firebase/auth';
3
3
  import { auth } from '~/services/firebase';
4
- import { fetchUserApi } from '~/utils/user-api-client';
4
+ import { fetchUserApi } from '~/utils/api';
5
5
  import { auditService } from '~/services/audit';
6
6
  import styles from './delete-account.module.css';
7
7
 
@@ -4,7 +4,7 @@ import { PasswordReset } from '~/routes/auth/passwordReset';
4
4
  import { DeleteAccount } from './delete-account';
5
5
  import { UserAuditViewer } from '../audit/user-audit-viewer';
6
6
  import { AuthContext } from '~/contexts/auth.context';
7
- import { getUserData, updateUserData } from '~/utils/permissions';
7
+ import { getUserData, updateUserData } from '~/utils/data';
8
8
  import { auditService } from '~/services/audit';
9
9
  import { handleAuthError, ERROR_MESSAGES } from '~/services/firebase/errors';
10
10
  import { FormField, FormButton, FormMessage } from '../form';
@@ -21,7 +21,7 @@ import {
21
21
  getPhoneDisplayValue,
22
22
  maskPhoneNumber,
23
23
  validatePhoneNumber,
24
- } from '~/utils/mfa-phone';
24
+ } from '~/utils/auth';
25
25
  import { FormButton, FormMessage } from '../form';
26
26
  import styles from './manage-profile.module.css';
27
27
 
package/app/root.tsx CHANGED
@@ -94,11 +94,6 @@ export default function App() {
94
94
  );
95
95
  }
96
96
 
97
- interface ErrorBoundaryShellProps {
98
- title: string;
99
- children: React.ReactNode;
100
- }
101
-
102
97
  const LOGIN_REDIRECT_PATH = '/';
103
98
 
104
99
  const errorActionStyle = {
@@ -133,30 +128,6 @@ async function returnToLogin() {
133
128
  }
134
129
  }
135
130
 
136
- function ErrorBoundaryShell({ title, children }: ErrorBoundaryShellProps) {
137
- return (
138
- <html lang="en" data-theme="light">
139
- <head>
140
- <meta charSet="utf-8" />
141
- <meta name="viewport" content="width=device-width, initial-scale=1" />
142
- <meta name="theme-color" content="#377087" />
143
- <meta name="color-scheme" content="light" />
144
- <style dangerouslySetInnerHTML={{ __html: themeStyles }} />
145
- <title>{title}</title>
146
- <Meta />
147
- <Links />
148
- </head>
149
- <body className="flex flex-col h-screen w-full overflow-x-hidden">
150
- <ThemeProvider theme="light" className="">
151
- <main>{children}</main>
152
- </ThemeProvider>
153
- <ScrollRestoration />
154
- <Scripts />
155
- </body>
156
- </html>
157
- );
158
- }
159
-
160
131
  export function ErrorBoundary() {
161
132
  const error = useRouteError();
162
133
 
@@ -164,27 +135,9 @@ export function ErrorBoundary() {
164
135
  const statusText = error.statusText || 'Unexpected error';
165
136
 
166
137
  return (
167
- <ErrorBoundaryShell title={`${error.status} ${statusText}`}>
168
- <div className={styles.errorContainer}>
169
- <div className={styles.errorTitle}>{error.status}</div>
170
- <p className={styles.errorMessage}>{statusText}</p>
171
- <button
172
- type="button"
173
- onClick={() => void returnToLogin()}
174
- style={errorActionStyle}
175
- className={styles.errorLink}>
176
- Return to Login
177
- </button>
178
- </div>
179
- </ErrorBoundaryShell>
180
- );
181
- }
182
-
183
- return (
184
- <ErrorBoundaryShell title="Oops! Something went wrong">
185
138
  <div className={styles.errorContainer}>
186
- <div className={styles.errorTitle}>500</div>
187
- <p className={styles.errorMessage}>Something went wrong. Please try again later.</p>
139
+ <div className={styles.errorTitle}>{error.status}</div>
140
+ <p className={styles.errorMessage}>{statusText}</p>
188
141
  <button
189
142
  type="button"
190
143
  onClick={() => void returnToLogin()}
@@ -193,6 +146,20 @@ export function ErrorBoundary() {
193
146
  Return to Login
194
147
  </button>
195
148
  </div>
196
- </ErrorBoundaryShell>
149
+ );
150
+ }
151
+
152
+ return (
153
+ <div className={styles.errorContainer}>
154
+ <div className={styles.errorTitle}>500</div>
155
+ <p className={styles.errorMessage}>Something went wrong. Please try again later.</p>
156
+ <button
157
+ type="button"
158
+ onClick={() => void returnToLogin()}
159
+ style={errorActionStyle}
160
+ className={styles.errorLink}>
161
+ Return to Login
162
+ </button>
163
+ </div>
197
164
  );
198
- }
165
+ }
@@ -8,8 +8,7 @@ import {
8
8
  } from 'firebase/auth';
9
9
  import { auth } from '~/services/firebase';
10
10
  import { handleAuthError } from '~/services/firebase/errors';
11
- import { evaluatePasswordPolicy } from '~/utils/password-policy';
12
- import { getSafeContinuePath } from '~/utils/auth-action-settings';
11
+ import { evaluatePasswordPolicy, getSafeContinuePath } from '~/utils/auth';
13
12
  import { auditService } from '~/services/audit';
14
13
  import { Icon } from '~/components/icon/icon';
15
14
  import styles from './emailActionHandler.module.css';
@@ -283,7 +282,7 @@ export const EmailActionHandler = ({ mode, oobCode, continueUrl, lang }: EmailAc
283
282
  <Link
284
283
  viewTransition
285
284
  prefetch="intent"
286
- to="https://striae.org"
285
+ to="https://striae.app"
287
286
  className={styles.logoLink}
288
287
  >
289
288
  <div className={styles.logo} />
@@ -2,7 +2,7 @@ import { useState } from 'react';
2
2
  import { Link } from 'react-router';
3
3
  import { sendEmailVerification, type User } from 'firebase/auth';
4
4
  import { auditService } from '~/services/audit';
5
- import { buildActionCodeSettings } from '~/utils/auth-action-settings';
5
+ import { buildActionCodeSettings } from '~/utils/auth';
6
6
  import styles from './login.module.css';
7
7
 
8
8
  interface EmailVerificationProps {
@@ -78,7 +78,7 @@ export const EmailVerification = ({
78
78
  <Link
79
79
  viewTransition
80
80
  prefetch="intent"
81
- to="https://striae.org"
81
+ to="https://striae.app"
82
82
  className={styles.logoLink}>
83
83
  <div className={styles.logo} />
84
84
  </Link>