Skip to content

KYC Document Security

Document ID: SEC-KYC-001 Version: 1.0 Classification: Internal Effective Date: January 2026 Next Review: July 2026 Owner: Keshless Security Team


1. Overview

All KYC documents are classified as highly sensitive PII and are protected with multiple security layers in compliance with FSRA requirements and international data protection standards.

1.1 Document Types

Document TypeStorage LocationClassificationRetention
ID Card (Front)gs://keshless-documents/kyc/Restricted7 years
ID Card (Back)gs://keshless-documents/kyc/Restricted7 years
Selfie (Liveness)gs://keshless-documents/selfies/Restricted7 years
Business Registrationgs://keshless-documents/vendor-kyc/Confidential7 years
Director IDgs://keshless-documents/vendor-kyc/Restricted7 years

2. Storage Security

2.1 Private Cloud Storage

All KYC documents are stored in GCP Cloud Storage (europe-west1 region) with strict access controls:

bash
# Bucket configuration
gcloud storage buckets create gs://keshless-documents \
  --location=europe-west1 \
  --default-storage-class=STANDARD \
  --uniform-bucket-level-access \
  --public-access-prevention

Security Features:

  • Public Access Prevention: No anonymous or public access possible
  • Uniform Bucket-Level Access: No per-object ACLs (simpler, more secure)
  • Region Restriction: Data never leaves europe-west1
  • Only Cloud Run Service Account: Only the API's service account has access

2.2 Encryption

LayerAlgorithmKey Management
At RestAES-256Google-managed keys
In TransitTLS 1.3Auto-renewed certificates
Backup (Secrets)AES-256-GCMCustomer-managed key

3. Access Control

3.1 Signed URLs

All document access uses time-limited signed URLs. No permanent URLs are ever generated or stored.

typescript
// Generating a signed URL for KYC document
const signedUrl = await GCSService.getSignedUrl(documentKey, 15); // 15 minutes

URL Expiration Settings:

ContextExpiryRationale
KYC Viewing (Dashboard)15 minutesMinimal exposure for review
OCR Verification60 minutesAllow time for AI processing
Document Upload Response15 minutesImmediate viewing after upload

Key Principles:

  • URLs cannot be shared or bookmarked (expire quickly)
  • Each API request generates a fresh URL
  • Database stores only the GCS key, never the URL
  • Expired URLs return 403 Forbidden

3.2 Authentication & Authorization

LayerRequirement
API AuthenticationValid JWT token required
User AccessUsers can only access their own documents
Admin AccessADMIN or SUPER_ADMIN role required
Vendor AdminCan access sub-user documents
typescript
// Authorization check example
if (req.user.role !== 'ADMIN' && req.user.id !== document.userId) {
  throw new UnauthorizedError('Access denied');
}

4. Audit Trail

4.1 Access Logging

Every document access is logged to the AuditLog table:

FieldDescription
eventTypeDOCUMENT_VIEWED, DOCUMENT_UPLOADED, DOCUMENT_DELETED
actorIdUser/Admin who accessed
targetIdDocument key/User ID
ipAddressClient IP address
createdAtTimestamp (UTC)
metadataAdditional context (user agent, request ID)

4.2 Hash Chain Verification

Audit logs are hash-chained for tamper detection:

Entry 1: hash(data1)
Entry 2: hash(data2 + hash(entry1))
Entry 3: hash(data3 + hash(entry2))

Verification:

  • Daily integrity checks via Cloud Scheduler
  • Admin can manually verify via /admin/audit-logs/verify endpoint
  • Any tampering breaks the chain immediately

4.3 Sample Audit Log Entry

json
{
  "eventType": "DOCUMENT_VIEWED",
  "description": "Admin viewed KYC document for user verification",
  "actorId": "admin-123",
  "actorType": "admin",
  "targetType": "kyc_document",
  "targetId": "kyc/user-456/id-front.jpg",
  "ipAddress": "102.215.xxx.xxx",
  "hashPrevious": "a3f5c2...",
  "hashCurrent": "b7d4e1...",
  "createdAt": "2026-01-24T10:30:00.000Z"
}

5. Data Retention

5.1 Retention Periods

Document TypeActive RetentionPost-Closure RetentionTotal
User KYCAccount lifetime5 yearsUp to 7+ years
Vendor KYCBusiness lifetime5 yearsUp to 7+ years
Audit LogsPermanentPermanentIndefinite

5.2 Automatic Deletion

typescript
// Documents eligible for deletion:
// - Account closed + 5 years elapsed
// - No regulatory hold
// - No pending investigations

async function scheduleDocumentDeletion(userId: string) {
  const fiveYearsFromNow = new Date();
  fiveYearsFromNow.setFullYear(fiveYearsFromNow.getFullYear() + 5);

  await ScheduledDeletion.create({
    userId,
    scheduledFor: fiveYearsFromNow,
    status: 'pending'
  });
}

5.3 Deletion Logging

All deletions are logged and cannot be undone:

json
{
  "eventType": "DOCUMENT_DELETED",
  "description": "KYC document deleted after retention period",
  "targetId": "kyc/user-123/id-front.jpg",
  "metadata": {
    "reason": "RETENTION_PERIOD_EXPIRED",
    "retentionDays": 2555,
    "accountClosedAt": "2021-01-15T00:00:00.000Z"
  }
}

6. OCR Verification Flow

6.1 Document Processing

When documents are uploaded for KYC verification:

  1. Upload: Document uploaded to GCS, key stored in DB
  2. URL Generation: Fresh 60-minute signed URL generated
  3. OCR Processing: Gemini AI extracts text from signed URL
  4. Storage: Extracted data stored in PostgreSQL (encrypted)
  5. URL Expiry: Signed URL expires after 60 minutes
typescript
// OCR verification flow
const documentKey = user.idFrontImageKey; // From database
const signedUrl = await GCSService.getSignedUrl(documentKey, 60);
const ocrResult = await geminiService.extractIdData(signedUrl);

6.2 Manual Review

For documents flagged for manual review:

  1. Admin navigates to verification dashboard
  2. API generates fresh 15-minute signed URL
  3. Admin reviews document within time limit
  4. If more time needed, refresh generates new URL
  5. All views logged to audit trail

7. Incident Response

7.1 Data Breach Procedures

See Incident Response Plan for full procedures.

Immediate Actions:

  1. Revoke all service account credentials
  2. Rotate bucket access keys
  3. Notify affected users within 72 hours
  4. Report to FSRA within 72 hours
  5. Preserve audit logs for investigation

7.2 Unauthorized Access

If unauthorized document access is detected:

  1. Block the actor's account immediately
  2. Log incident details with full audit trail
  3. Generate report of all documents accessed
  4. Notify affected users
  5. Review and strengthen access controls

8. Compliance Checklist

8.1 FSRA Requirements

  • [x] Documents stored in approved jurisdiction (europe-west1)
  • [x] Encryption at rest (AES-256)
  • [x] Encryption in transit (TLS 1.3)
  • [x] Access logging and audit trails
  • [x] 7-year retention capability
  • [x] Role-based access control
  • [x] Regular security assessments

8.2 Technical Controls

  • [x] Private buckets (no public access)
  • [x] Signed URLs with time expiration
  • [x] Hash-chained audit logs
  • [x] Service account authentication only
  • [x] No permanent document URLs
  • [x] Automated backup to separate bucket

Internal use only - Keshless Payment Platform