[FEAT] Provider Identity Document Upload & Watermarking Pipeline
telegram link : t.me/nullifiersystem
1. Summary & Core Promise
Velo's provider onboarding workflow in apps/api/src/routes/provider.ts allows liquidity providers to register and upload identity documents for verification. Currently, uploaded documents are stored in raw format without content validation, signature verification, or watermarking, posing security risks if administrative storage accounts are audited or inspected.
This feature implements a Provider Identity Document Upload & Watermarking Pipeline. It adds server-side image format signature validation (JPEG, PNG, WebP up to 5 MB), dynamic cryptographic watermarking ("FOR VELO VERIFICATION ONLY"), encrypted storage in apps/api/src/lib/provider-verification-store.ts, PostgreSQL transaction locking (SELECT FOR UPDATE), and restricted admin document retrieval endpoints.
2. Background & Architectural Risks
- Malicious Payload Injection: Allowing arbitrary document file uploads without inspecting magic number byte signatures exposes backend storage to remote code execution or file inclusion vulnerabilities.
- Identity Document Leakage: Storing un-watermarked identity documents allows compromised administrative channels to leak sensitive provider identity cards.
- Race Condition Upload Overwrites: Concurrent uploads for the same provider profile could overwrite pending document reviews without database locking.
3. Database Layer Specifications
Migration SQL (014_add_provider_document_watermarks.sql)
CREATE TYPE document_review_status AS ENUM ('PENDING', 'APPROVED', 'REJECTED');
CREATE TABLE provider_verification_documents (
document_id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
provider_id VARCHAR(64) NOT NULL REFERENCES provider_profiles(id) ON DELETE CASCADE,
file_name VARCHAR(255) NOT NULL,
mime_type VARCHAR(50) NOT NULL,
file_size_bytes INT NOT NULL,
watermarked_hash VARCHAR(64) NOT NULL,
storage_path VARCHAR(512) NOT NULL,
status document_review_status NOT NULL DEFAULT 'PENDING',
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_provider_docs ON provider_verification_documents(provider_id);
Pessimistic Data Locking (SELECT FOR UPDATE)
BEGIN;
-- Lock provider profile record to prevent concurrent upload collisions
SELECT id, verification_status
FROM provider_profiles
WHERE id = $1
FOR UPDATE;
-- Update provider verification status to PENDING
UPDATE provider_profiles SET verification_status = 'PENDING' WHERE id = $1;
COMMIT;
4. Backend Route & Service Layer Specifications
Route: POST /api/v1/provider/verification-document
- Validation: Validates file size (
<= 5MB) and inspects magic number bytes (FF D8 FF for JPEG, 89 50 4E 47 for PNG, 52 49 46 46 for WebP). Rejects invalid extensions/signatures.
- Locking: DB transaction acquires
SELECT FOR UPDATE on provider_profiles.
- Dynamic Watermarking: Applies semi-transparent diagonal text
"FOR VELO VERIFICATION ONLY" and timestamps image buffer before saving.
- Synchronous DB Commit: Stores document metadata in
provider_verification_documents and sets provider status to PENDING.
- Response: Returns
HTTP 201 Created with document tracking metadata.
Error Payload Shapes
- HTTP 400 Bad Request (Invalid file format/signature):
{
"error": {
"code": "INVALID_FILE_SIGNATURE",
"message": "Uploaded file magic number does not match supported image formats (JPEG, PNG, WebP).",
"requestId": "req-doc-101"
}
}
- HTTP 413 Payload Too Large (File size > 5 MB):
{
"error": {
"code": "FILE_TOO_LARGE",
"message": "Verification document exceeds maximum allowable limit of 5 MB.",
"requestId": "req-doc-102"
}
}
5. Background Processors / Workers
Document Cleanup Worker (apps/api/src/lib/workers/documentCleanupWorker.ts)
- Schedule: Runs daily.
- Task: Identifies rejected verification documents older than 90 days in
provider_verification_documents and purges underlying disk/object storage files safely.
6. Frontend / UI Component Specifications
Component: mobile/frontend/src/components/ProviderDocumentUpload.tsx
- File Selection Blur/Change Validation: Inspects selected file size and extension on change. Shows inline error
"File size must be under 5 MB and in JPEG, PNG, or WebP format".
- Uploading State: Displays progress bar
"Uploading & Applying Security Watermark...".
- Uploaded State: Displays checkmark badge
"Document Uploaded - Awaiting Admin Review".
- Error Recovery State: Displays error alert
"Upload Failed: Unsupported Image File" with button "Choose Another File".
7. Rigor & Test Plan
- Unit Tests (
apps/api/src/routes/__tests__/provider-document.test.ts):
- Upload valid JPEG file. Assert
201 Created and verify watermark image buffer header.
- Upload executable script masked as
.png. Assert magic number checker returns 400 Bad Request.
- Concurrency Test (
tests/concurrency/provider_document_stress.test.ts):
- Concurrently upload 10 documents for the same provider profile (
Promise.all()).
- Expectation: DB locking prevents state corruption; provider status consistently set to
PENDING.
- Frontend Test (
ProviderDocumentUpload.test.tsx):
- Test client-side file validation and progress bar rendering.
8. Relevant Files Inventory
New Files to Create
apps/api/src/db/migrations/014_add_provider_document_watermarks.sql
apps/api/src/lib/provider-watermark.ts
apps/api/src/routes/__tests__/provider-document.test.ts
tests/concurrency/provider_document_stress.test.ts
mobile/frontend/src/components/ProviderDocumentUpload.tsx
Existing Files to Modify
apps/api/src/app.ts
apps/api/src/routes/provider.ts
apps/api/src/routes/admin.ts
apps/api/src/lib/provider-verification-store.ts
packages/shared/src/index.ts
9. Acceptance Criteria
10. Contributor / Architectural Notes
- ⚠️ Order: Apply SQL migration -> Deploy backend watermark utility & route -> Update frontend component.
- ⚠️ Security Warning: NEVER trust client-side file MIME extensions; ALWAYS verify binary magic numbers on the backend.
[FEAT] Provider Identity Document Upload & Watermarking Pipeline
telegram link : t.me/nullifiersystem
1. Summary & Core Promise
Velo's provider onboarding workflow in
apps/api/src/routes/provider.tsallows liquidity providers to register and upload identity documents for verification. Currently, uploaded documents are stored in raw format without content validation, signature verification, or watermarking, posing security risks if administrative storage accounts are audited or inspected.This feature implements a Provider Identity Document Upload & Watermarking Pipeline. It adds server-side image format signature validation (JPEG, PNG, WebP up to 5 MB), dynamic cryptographic watermarking (
"FOR VELO VERIFICATION ONLY"), encrypted storage inapps/api/src/lib/provider-verification-store.ts, PostgreSQL transaction locking (SELECT FOR UPDATE), and restricted admin document retrieval endpoints.2. Background & Architectural Risks
3. Database Layer Specifications
Migration SQL (
014_add_provider_document_watermarks.sql)Pessimistic Data Locking (
SELECT FOR UPDATE)4. Backend Route & Service Layer Specifications
Route:
POST /api/v1/provider/verification-document<= 5MB) and inspects magic number bytes (FF D8 FFfor JPEG,89 50 4E 47for PNG,52 49 46 46for WebP). Rejects invalid extensions/signatures.SELECT FOR UPDATEonprovider_profiles."FOR VELO VERIFICATION ONLY"and timestamps image buffer before saving.provider_verification_documentsand sets provider status toPENDING.HTTP 201 Createdwith document tracking metadata.Error Payload Shapes
{ "error": { "code": "INVALID_FILE_SIGNATURE", "message": "Uploaded file magic number does not match supported image formats (JPEG, PNG, WebP).", "requestId": "req-doc-101" } }{ "error": { "code": "FILE_TOO_LARGE", "message": "Verification document exceeds maximum allowable limit of 5 MB.", "requestId": "req-doc-102" } }5. Background Processors / Workers
Document Cleanup Worker (
apps/api/src/lib/workers/documentCleanupWorker.ts)provider_verification_documentsand purges underlying disk/object storage files safely.6. Frontend / UI Component Specifications
Component:
mobile/frontend/src/components/ProviderDocumentUpload.tsx"File size must be under 5 MB and in JPEG, PNG, or WebP format"."Uploading & Applying Security Watermark..."."Document Uploaded - Awaiting Admin Review"."Upload Failed: Unsupported Image File"with button"Choose Another File".7. Rigor & Test Plan
apps/api/src/routes/__tests__/provider-document.test.ts):201 Createdand verify watermark image buffer header..png. Assert magic number checker returns400 Bad Request.tests/concurrency/provider_document_stress.test.ts):Promise.all()).PENDING.ProviderDocumentUpload.test.tsx):8. Relevant Files Inventory
New Files to Create
apps/api/src/db/migrations/014_add_provider_document_watermarks.sqlapps/api/src/lib/provider-watermark.tsapps/api/src/routes/__tests__/provider-document.test.tstests/concurrency/provider_document_stress.test.tsmobile/frontend/src/components/ProviderDocumentUpload.tsxExisting Files to Modify
apps/api/src/app.tsapps/api/src/routes/provider.tsapps/api/src/routes/admin.tsapps/api/src/lib/provider-verification-store.tspackages/shared/src/index.ts9. Acceptance Criteria
provider_verification_documentstable.400 Bad Request."FOR VELO VERIFICATION ONLY"on uploaded images.GET /api/v1/admin/providers/:providerId/verifications/:documentId).10. Contributor / Architectural Notes