Customer Document Management
The document management system handles file uploads, cloud storage, and download link generation for customer-related documents. Documents are stored in Google Cloud Storage (or local storage for development), with metadata tracked in the database through event sourcing. The system supports any file type but is primarily used for identity documents, corporate filings, and supporting materials for KYC and credit processes.
Storage Architecture
Documents are stored using a two-part approach: the file metadata (ID, filename, content type, status, reference to owning customer) is persisted as an event-sourced entity in PostgreSQL, while the actual file bytes are uploaded to cloud storage. The storage path follows the pattern documents/customer_document/{document_id}{extension}.
When a user requests a download, the system generates a presigned URL with a time-limited expiration, allowing direct browser download from cloud storage without proxying the file through the application server.
Document Lifecycle
| Status | Description |
|---|---|
| New | Document record created, file upload in progress |
| Active | File successfully uploaded to cloud storage and available for download |
| Failed | Upload to cloud storage failed (can be retried) |
| Archived | Soft-archived; file remains in cloud storage but is marked as no longer current |
| DeletionRequested | Deletion accepted; removal waits for storage retention when necessary |
| Deleted | Removed from both the entity record (soft delete) and cloud storage (hard delete) |
Document creation, staging the upload bytes, and scheduling the upload happen in one database transaction. A background operation uploads the bytes and records the outcome. Successfully uploaded bytes are then removed from staging. A late upload outcome cannot cancel a deletion request.
File Handling
Filename Sanitization
When a document is uploaded, the original filename is sanitized for safe storage. All non-alphanumeric characters (except hyphens) are replaced with hyphens, and whitespace is trimmed. Both the original and sanitized filenames are preserved in the document record for reference.
Content Types and Extensions
| Content Type | Extension |
|---|---|
application/pdf | .pdf |
text/csv | .csv |
| All others | No extension added |
The system accepts any content type. The extension mapping is used only for constructing the cloud storage path.
Document Operations
| Operation | Description | Permission |
|---|---|---|
| Attach document | Upload a file and associate it with a customer | CUSTOMER_DOCUMENT_CREATE |
| List documents | Retrieve all documents for a customer, sorted by creation date (newest first) | CUSTOMER_DOCUMENT_LIST |
| View document | Look up a single document by ID | CUSTOMER_DOCUMENT_READ |
| Generate download link | Create a time-limited presigned URL for downloading the file | CUSTOMER_DOCUMENT_GENERATE_DOWNLOAD_LINK |
| Archive document | Mark an active document as no longer current, retaining its file and metadata | CUSTOMER_DOCUMENT_DELETE |
| Delete document | Request permanent file removal, followed by a soft-delete of the record | CUSTOMER_DOCUMENT_DELETE |
Upload Flow
- The operator selects a file in the admin panel and initiates the upload.
- The system creates a document record with status
New, including the sanitized filename and content type. - A background operation uploads the staged file bytes to cloud storage at the computed path.
- On success, a
FileUploadedevent transitions the document toActivestatus. - On failure, an
UploadFailedevent records the error and transitions toFailedstatus.
Download Flow
- The operator or system requests a download link for a document.
- The authorization boundary records the request in the audit log; no document event is appended.
- The system checks that the document is
Active, then generates a presigned URL from the cloud storage provider. - The presigned URL is returned, allowing direct download from cloud storage within the expiration window.
The customerDocumentDownloadLinkGenerate mutation returns either CustomerDocumentDownloadLinksGeneratePayloadSuccess with the link or CustomerDocumentDownloadLinksGeneratePayloadError with DOCUMENT_NOT_DOWNLOADABLE when the document is in any other status (an unfinished or failed upload, archived, or deletion requested), or DOCUMENT_NOT_FOUND when the lookup fails, including once removal has completed.
Archive and Delete
Archive is an explicit admin API operation. Only an Active document can become Archived; repeating archive on an archived document succeeds without changing it. Archived documents remain in ordinary listings and keep their stored bytes. There is no restore operation or automatic archive-on-replacement workflow.
The customerDocumentArchive mutation returns either CustomerDocumentArchivePayloadSuccess or CustomerDocumentArchivePayloadError. Its business error codes are DOCUMENT_NOT_READY for unfinished or failed uploads, DOCUMENT_DELETION_REQUESTED for pending deletion, DOCUMENT_DELETED for completed deletion when reachable, and DOCUMENT_NOT_FOUND when the lookup fails. Normal lookups exclude soft-deleted records. Authorization failures remain top-level GraphQL errors.
Delete accepts documents in New, Failed, Active, or Archived state. It records DeletionRequested and schedules removal. Repeating a pending deletion request is idempotent. Removal waits for the configured retention period and any retention enforced by the storage provider. After removal completes, staged bytes are cleared and the record is soft-deleted; event history is retained.
Archive cannot cancel a pending or completed deletion. Accepting a delete request stops new download links from being issued, but does not mean removal has finished or previously issued download links have been revoked.
Security
- Presigned URLs: Download links are time-limited and signed by the cloud storage provider. They expire after a configured duration, preventing indefinite access from shared or leaked URLs.
- Encrypted transmission: All uploads and downloads use TLS.
- Encrypted at rest: Files in cloud storage are encrypted using the provider's server-side encryption.
- Authorization: Every document operation requires the appropriate permission, enforced through the RBAC system. All operations are recorded in the audit log.