VirtualPR/docs/SECURITY.md

1.9 KiB

Security operations

Secrets

Rotate JWT_SECRET, PII_ENCRYPTION_KEY, PII_PEPPER, Mongo, SendGrid, Google, and AWS keys after any suspected leak. Do not commit .env.

Production refuses the default JWT_SECRET and SEED_ADMIN_PASSWORD=Admin@123.

PII encryption keys

PII_ENCRYPTION_KEY is 32 bytes, base64-encoded. PII_KEY_ID is stored on each ciphertext (kid).

To rotate:

  1. Generate a new key and a new PII_KEY_ID.
  2. Keep the old key available until node scripts/migrate-pii.js has rewritten every document.
  3. Point PII_ENCRYPTION_KEY / PII_KEY_ID at the new values, then re-run the migration (dual-read still decrypts leftover plaintext).

PII_PEPPER is used only for nameHash / mobileHash. Changing it requires recomputing hashes.

AWS S3

  • Block public access on the bucket.
  • IAM: s3:PutObject, s3:GetObject, s3:DeleteObject on onboarding/* only.
  • Screenshots use SSE-S3. The API issues a GET URL that expires in S3_PRESIGN_TTL_SEC (default 10 minutes).
  • To revoke a leaked URL before expiry, delete or replace the object (new key). Then run node scripts/migrate-s3.js for leftover local files.

Sessions

Access JWT lives in the vpr_access httpOnly cookie (~15 minutes). Refresh token lives in vpr_refresh (7 days) and is hashed in Mongo. Logout and user disable revoke refresh sessions.

Retention

Settings → “Delete rejected/unpaid after (days)” (default 365). A daily job at 03:15 (APP_TIMEZONE) deletes matching onboarded rows and their S3 objects. Confirmed patients are never auto-deleted.

Audit

Super Admin → Audit log. Events: login success/failure, screenshot view, onboarding confirm/reject, report export, user disable. No patient names or mobiles are stored.

Treat onboarded records as personal + health data under the DPDP Act. Keep a DPA with AWS. Limit who may export reports.