Architecture Guide - striae-org/striae GitHub Wiki
Table of Contents
- System Architecture Overview
- High-Level Architecture
- Frontend Architecture
- Backend Architecture (Cloudflare Workers)
- Data Architecture
- Security Architecture
- Performance Architecture
- Scalability Considerations
- Monitoring and Observability
- Development Architecture
- Future Architecture Considerations
- References
System Architecture Overview
Striae is an edge-first forensic annotation platform with clear separation between:
- Presentation and workflow orchestration in the React Router app.
- Same-origin API gateway behavior in Cloudflare Pages Functions (
/api/*). - Domain services in specialized Cloudflare Workers.
- Storage systems partitioned by data responsibility.
The architecture emphasizes service boundaries, typed contracts, and forensic workflow integrity across export, import, and audit paths.
High-Level Architecture
graph TB
subgraph "Client and App"
UI[React Router App on Cloudflare Pages]
AUTH[Firebase Authentication]
end
subgraph "Pages API Gateway"
API[Cloudflare Pages Functions /api/*]
end
subgraph "Edge Service Layer"
UW[User Worker]
DW[Data Worker]
AW[Audit Worker]
IW[Image Worker]
PW[PDF Worker]
end
subgraph "Storage Layer"
KV[Cloudflare KV]
R2D[Cloudflare R2 - Case Data]
R2A[Cloudflare R2 - Audit Data]
R2F[Cloudflare R2 - Encrypted Files]
end
AUTH --> UI
UI --> API
API --> UW
API --> DW
API --> AW
API --> IW
API --> PW
UW --> KV
DW --> R2D
AW --> R2A
IW --> R2F
Architecture Patterns
- Bounded edge services: each worker owns a focused domain boundary.
- Gateway-first transport: browser clients call same-origin Pages APIs, which verify Firebase identity and forward to workers via Cloudflare Service Bindings.
- Storage by concern: user identity/profile, case content, and audit evidence are separated.
- Fail-safe observability: audit logging is integrated broadly but does not generally block core user workflows.
- Typed data contracts: shared application types define domain boundaries across frontend and services.
Frontend Architecture
Technology Stack
- Framework: React Router (React)
- Language: TypeScript
- Styling: CSS Modules and shared global styles
- Deployment Runtime: Cloudflare Pages
Key Frontend Patterns
1. Route-driven shell
- Routes provide page-level composition and navigation state.
- Domain UI is composed from feature-focused components rather than monolithic pages.
2. Canvas-centered casework flow
- Annotation and casework interactions are centered around the canvas domain.
- Sidebar and toolbar state act as control surfaces around the same case context.
3. Action/service boundary
- UI interactions delegate data and workflow operations to action modules and utility services.
- This keeps worker communication and business logic out of presentational components.
- Utility clients call same-origin
/api/*routes instead of direct worker domains.
4. Workflow pipelines
- Export, import, confirmation, and audit workflows are organized as explicit multi-step flows.
- Long-running operations expose progress and error states to maintain user trust and recoverability.
- Case archival is implemented as a dedicated workflow that produces signed archive packages with bundled audit artifacts.
5. Shared domain typing
- Shared types in
app/typesdefine stable contracts across components and services. - The app uses centralized utility modules for permissions, data access, and audit operations.
- Derived confirmation-status summaries are maintained as typed metadata to accelerate file/case confirmation indicators without rescanning all annotations.
For component-level structure and implementation details, use Component Guide.
Backend Architecture (Cloudflare Workers)
Worker Services Overview
Striae uses domain-focused workers to isolate responsibilities and simplify scaling:
| Worker | Primary Domain | Architecture Role |
|---|---|---|
| User Worker | User profile and case assignment state | Identity-linked profile boundary |
| Data Worker | Case, file metadata, and signing operations | Primary case data boundary |
| Audit Worker | Audit entry persistence and retrieval | Immutable accountability boundary |
| Image Worker | Encrypted file/image upload, read, and deletion | Media/file boundary |
| PDF Worker | Report rendering and PDF generation | Document generation boundary |
Current worker implementations are modularized inside each workers/*/src/ tree rather than concentrated in single entrypoint files. Shared patterns now include dedicated handlers/, storage/, registry/, cleanup/, and formats/ modules where they fit the domain.
Worker Boundaries
User Worker (workers/user-worker/)
- Owns user profile lifecycle and case assignment state as the identity-linked boundary.
- Stores user profile records in
USER_DBas encryption envelopes (RSA-OAEP wrapped AES-256-GCM payloads) and decrypts only inside trusted worker paths. - Implements modular architecture:
- Entry point (
src/user-worker.ts): handles authentication, KV config validation, and request routing. - Auth (
src/auth.ts): Firebase token verification and KV permission requirements. - Handlers (
src/handlers/user-routes.ts): unified endpoint router for user profile and case operations (GET, PUT, DELETE). - Storage (
src/storage/): KV access, encryption envelope serialization, and user data persistence. - Registry (
src/registry/): data-at-rest encryption key lookup and active key management. - Cleanup (
src/cleanup/): cascading deletion logic for account termination and case removal. - Firebase (
src/firebase/): Firebase Admin SDK integration for user context from bearer tokens. - Crypto utilities (
src/encryption-utils.ts): RSA-OAEP key wrapping and AES-256-GCM envelope encryption/decryption. - Config (
src/config.ts): auth header names, KV namespace names, and path constants. - Types (
src/types.ts): user profile, case, and API contract types.
- Entry point (
- Enforces read/write KV permissions separately to allow fine-grained deployment scope.
- Supports case assignment tracking and user account lifecycle including secure deletion.
Image Worker (workers/image-worker/)
- Owns encrypted file and image blob storage in a dedicated R2 bucket.
- Implements modular handler architecture for focused separation of concerns:
- Entry point (
src/image-worker.ts): handles error boundaries and delegates to router. - Router (
src/router.ts): dispatches requests by HTTP method and path segments to appropriate handler modules. - Handlers (
src/handlers/): specialized modules for focused operations:upload-image.ts: multipart upload and encryption with envelope storage in R2 metadata.serve-image.ts: authenticated read with decryption from R2 metadata envelopes.delete-image.ts: secure deletion with cleanup.mint-signed-url.ts: HMAC-signed same-origin URL generation.
- Security layer (
src/security/):key-registry.ts: active encryption key lookup and management.signed-url.ts: HMAC generation and validation for delegated browser access.
- Encryption utilities (
src/encryption-utils.ts): AES-256-GCM encryption/decryption with envelope pattern. - Utils (
src/utils/): path parsing, content-disposition headers, storage metadata extraction. - Auth (
src/auth.ts): JWT verification for image worker requests. - Types (
src/types.ts): request, response, and configuration contracts.
- Entry point (
- Encrypts uploads at rest and decrypts on authenticated reads.
- Mints and validates signed same-origin image URLs so browser image surfaces can load media through
/api/image/{fileId}?st=...without exposing worker secrets to the client. - Supports encrypted media with data-at-rest envelope storage in R2 custom metadata and per-request decryption.
PDF Worker (workers/pdf-worker/)
- Isolates report rendering and PDF generation from application UI concerns.
- Implements modular report format architecture:
- Entry point (
src/pdf-worker.ts): handles auth headers and request routing. - Report types (
src/report-types.ts): shared TypeScript interfaces for report generation contracts and PDF options. - Report layout (
src/report-layout.ts): shared rendering utilities and layout logic across formats. - Audit report renderer (
src/audit-trail-report.ts): comprehensive case audit trail PDF rendering (including raw JSON appendix sections) used whendata.reportMode = "audit-trail". - Format modules (
src/formats/): format-specific rendering implementations loaded dynamically:format-striae.ts: default forensic annotation report format.format-primer-shear.ts: agency-specific report variant.
- Assets (
src/assets/): images, templates, and resources used by report formats.
- Entry point (
- Uses Cloudflare Browser Rendering API with scoped bearer auth for HTML-to-PDF conversion.
- Does not persist report payloads; rendering input is processed in-memory per request.
- Supports format discovery and extension through modular loader pattern.
- Supports case-audit report mode for viewer-driven audit trail exports without adding a separate PDF worker endpoint.
Data Worker (workers/data-worker/)
- Owns case and annotation JSON persistence model.
- Implements modular handler and storage architecture:
- Entry point (
src/data-worker.ts): handles auth header validation and request routing to handlers. - Handlers (
src/handlers/):storage-routes.ts: case/annotation CRUD operations and R2 lifecycle.signing.ts: forensic manifest, confirmation, and audit export signing endpoints.decrypt-export.ts: decryption service for encrypted export payloads with verification.
- Registry (
src/registry/): data-at-rest encryption key lookup and rotation management. - Crypto utilities:
encryption-utils.ts: AES-256-GCM encryption/decryption with envelope envelopes.signature-utils.ts: RSA-PSS signing for manifest integrity.signing-payload-utils.ts: payload preparation for cryptographic operations.
- Config (
src/config.ts): auth header names, path constants, and environment bindings. - Types (
src/types.ts): request, response, and storage contracts.
- Entry point (
- Provides signing and decryption services for forensic manifest, confirmation, audit export, and encrypted package workflows.
- Maintains separation between case storage operations and cryptographic signing services.
Audit Worker (workers/audit-worker/)
- Owns append-oriented audit storage and retrieval as immutable evidence records.
- Implements modular architecture:
- Entry point (
src/audit-worker.ts): handles auth header validation, request routing, and path validation. - Handlers (
src/handlers/audit-routes.ts): unified audit endpoint router for GET/POST operations. - Storage (
src/storage/): R2 bucket access, encryption envelope management, and append-only log semantics. - Crypto (
src/crypto/): AES-256-GCM encryption/decryption and signing utilities for audit records. - Config (
src/config.ts): auth header validation, path constants, and environment bindings. - Types (
src/types.ts): audit entry, query, and response contracts.
- Entry point (
- Preserves forensic accountability as a distinct data concern separate from operational case storage.
- Supports paginated retrieval and filtering while maintaining immutable audit trail integrity.
For endpoint-level contracts and request/response formats, use API Reference.
Data Architecture
Storage Systems Overview
| Data Category | Primary Store | Architectural Purpose |
|---|---|---|
| User profile and permissions | Cloudflare KV | Fast key-value profile lookup by user identity with worker-managed encryption-at-rest envelopes |
| Case and annotation payloads | Cloudflare R2 (data bucket) | Encrypted-at-rest casework artifacts |
| Audit evidence trail | Cloudflare R2 (audit bucket) | Encrypted-at-rest accountability records |
| File and image binaries | Cloudflare R2 (files bucket) | Encrypted-at-rest media/file storage with decrypt-on-read |
| Authentication identity | Firebase Auth | Externalized identity and auth lifecycle |
For encryption implementation details, key registry patterns, and key rotation behavior, see Data-at-Rest Encryption.
Data Ownership Model
- User domain: profile metadata and case references.
- Case domain: examination content and associated annotation artifacts.
- Audit domain: immutable event evidence retained separately from case content.
- Media domain: file and image binaries managed independently from case metadata with at-rest encryption.
Derived Workflow Metadata
- A per-user confirmation status summary document is stored at
/{userId}/meta/confirmation-status.json. - The summary tracks per-file and per-case
includeConfirmation/isConfirmedstate and is refreshed opportunistically with staleness checks. - Destructive lifecycle operations (case deletion, case archival, account deletion) remove affected summary entries to prevent stale UI status data.
This ownership model is designed to reduce coupling, support forensic traceability, and allow domain-specific scaling.
For concrete schemas and payload contracts, use API Reference.
Security Architecture
Striae security is implemented as layered boundaries rather than a single control point:
- Identity boundary: Firebase-authenticated user sessions.
- Gateway boundary: Pages Functions validate Firebase bearer tokens and enforce user-scope rules before forwarding.
- Service boundary: workers are called exclusively via Cloudflare Service Bindings from Pages Functions, eliminating the need for internal shared-secret auth headers across the proxy boundary; the Image Worker additionally enforces HMAC-signed
sttokens for delegated browser image reads. - Data boundary: separation of operational case data and audit evidence stores.
- Cryptography boundary: user profile KV, case/audit payloads, and file/image payloads are encrypted at rest and decrypted only in trusted worker paths.
- Integrity boundary: signed forensic payloads for export/import trust workflows.
For detailed security controls, authentication flows, and hardening guidance, use:
- Security Guide
- Data-at-Rest Encryption
- Manifest and Confirmation Signing
- Export Encryption
- Authenticated Confirmation System
- Audit Trail System
Performance Architecture
Performance relies on edge-local compute and clear workload specialization:
- Stateless worker execution for low-latency API handling.
- Separation of hot-path interactions (annotation and casework) from heavier jobs (export and PDF).
- Storage and media services selected by workload profile (KV, R2, Browser Rendering API).
- Browser-side UX patterns that keep long-running operations observable and recoverable.
Scalability Considerations
- Independent service scaling: workers scale per workload domain.
- Storage elasticity: object and key-value stores scale independently of compute.
- Domain isolation: case, audit, file/image, and identity concerns can evolve without full-stack rewrites.
- Extensible report and export pipelines: architecture supports format/module growth without core redesign.
Monitoring and Observability
Observability is layered across platform, application, and forensic accountability domains:
- Platform-level worker/runtime metrics and error visibility.
- Application-level structured logging and error propagation.
- Audit-level event trails for workflow accountability and compliance review.
For audit-specific observability and reporting workflows, use Audit Trail System.
Development Architecture
The development model favors clear boundaries and centralized shared contracts:
- Feature-oriented frontend modules with reusable utility and service layers.
- Public API transport through Pages Functions (
/api/user,/api/data,/api/image,/api/audit,/api/pdf). - Worker services organized by domain ownership with modular internal source layouts.
- Pages Functions route to workers via Cloudflare Service Bindings (
env.USER_WORKER,env.DATA_WORKER, etc.) rather than HTTP domain proxying. - Centralized type definitions to keep contracts stable across features.
- Documentation split by responsibility to avoid architecture-guide overload.
For implementation workflow and operations process, use:
- Repository README plus
app/config-example/and workerwrangler.jsoncfiles - Error Handling Guide
Future Architecture Considerations
Likely extension points while preserving current architecture patterns:
- Additional report modules and agency-specific output formats.
- Policy-driven authorization layers over existing permission boundaries.
- Expanded analytics and compliance reporting pipelines from audit events.
- Greater workflow modularity for specialized forensic review paths.