feat: driver documents (sovereignty storage adapter) + load-test script

- documents: upload (multipart) + review (admin/CS) + auto-approve driver when all docs approved
- StorageService: per-tenant local volume now, in-country storage swap via STORAGE_BASE_URL
- doc.number encrypted (AES-256-GCM); migration InitDocuments; tripz-storage volume
- scripts/loadtest.mjs: concurrent full trip-cycle benchmark (throughput + latency percentiles)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-16 19:36:27 +03:00
co-authored by Claude Opus 4.8
parent f3383c3cf8
commit 7a58a01417
11 changed files with 424 additions and 0 deletions
@@ -0,0 +1,28 @@
import { MigrationInterface, QueryRunner } from 'typeorm';
/** وثائق السائق. الجدول: tripz_driver_documents. */
export class InitDocuments1721700000000 implements MigrationInterface {
public async up(q: QueryRunner): Promise<void> {
await q.query(`
CREATE TABLE IF NOT EXISTS tripz_driver_documents (
id uuid PRIMARY KEY DEFAULT uuid_generate_v4(),
tenant_id uuid NOT NULL,
driver_id uuid NOT NULL,
type varchar NOT NULL,
file_key varchar NOT NULL,
number varchar,
expiry_date date,
status varchar NOT NULL DEFAULT 'pending',
review_note varchar,
reviewed_by uuid,
created_at timestamptz NOT NULL DEFAULT now(),
updated_at timestamptz NOT NULL DEFAULT now()
)`);
await q.query(`CREATE INDEX IF NOT EXISTS "IDX_tripz_driver_documents_driver" ON tripz_driver_documents (tenant_id, driver_id)`);
await q.query(`CREATE INDEX IF NOT EXISTS "IDX_tripz_driver_documents_status" ON tripz_driver_documents (tenant_id, status)`);
}
public async down(q: QueryRunner): Promise<void> {
await q.query(`DROP TABLE IF EXISTS tripz_driver_documents`);
}
}