Reconstructs a single user's AppDataComplete by replaying their op log up to a chosen serverSeq and decrypting E2E-encrypted payloads — the recovery path the server's restore endpoint cannot offer for encrypted accounts (it throws EncryptedOpsNotSupportedError). Read-only on the DB; documented in docs/backup-and-recovery.md. Unverified against real encrypted data — see the script header.
- Add accounts-only pg_dump (users + passkeys) to backup script for
lightweight disaster recovery when clients still have data
- Add pipefail to backup script to catch silent dump failures
- Add test endpoint to simulate partial server revert (ops-after/:serverSeq)
- Add 6 e2e tests covering all disaster recovery scenarios:
complete data loss, partial revert, accounts-only restore (API + SQL),
full dump restore + reset account, and all-clients-lost recovery
- Add backup-and-recovery.md with setup, recovery procedures, and
decision tree
Replace separate JWT_EXPIRY_MAGIC_LINK (365d) and JWT_EXPIRY_PASSKEY (7d)
constants with a single JWT_EXPIRY (365d). The auth method only matters
during login — once a JWT is issued, it represents a verified session
regardless of how the user authenticated.
- Use JWT_EXPIRY_PASSKEY (7d) for replaceToken instead of 365d magic link
expiry — token replacement is a security action, shorter lifetime is safer
- Replace localeCompare with locale-independent comparator in vector clock
tie-breaking to ensure deterministic behavior across environments
- Fix 5 additional stale MAX=30 references in docs and tests (now 20)
- Update authentication.md to reflect dual JWT expiry tiers
- Clean up isLikelyPruningArtifact references in docs and LEGACY_MAX in tests
Both LUKS and TDE encryption don't work on OpenVZ:
- LUKS: requires dm-crypt kernel module (not available)
- TDE: technically not feasible during testing
Reverted TDE commit (1fdcc9a90) and moved all encryption scripts
to archive/encryption-attempts-openvz-incompatible/ for reference.
Decision: Operating without encryption-at-rest for now.
Future options documented in archive README:
- KVM migration (€2-5/month) enables LUKS
- Application-level encryption if staying on OpenVZ
- Managed PostgreSQL service (~€10-20/month)
Kept backup-encrypted.sh (encrypts backup files with passphrase,
separate from database encryption-at-rest).
Internal compliance documentation has been moved to a private location.
These documents contain sensitive operational procedures and security
analysis that should not be public.
Files moved:
- GDPR compliance analysis
- Incident response playbooks
- Data subject request procedures
- DPIA screening decisions
- Records of processing activities
- Infrastructure verification documents
Update incident response, data subject request, and DPIA procedures to
accurately reflect that database encryption at rest is NOT implemented
for non-E2EE users.
Changes:
- INCIDENT-RESPONSE-PLAYBOOK.md: Clarify E2EE is optional throughout,
add physical server compromise scenarios, update risk assessments to
differentiate E2EE vs non-E2EE users, document encryption gap in
prevention measures
- DATA-SUBJECT-REQUEST-PROCEDURES.md: Add encryption status disclosure
to access responses, clarify data export formats, add security notice
about unencrypted storage for non-E2EE users
- DPIA-SCREENING-DECISION.md: Document encryption gap as additional
consideration, update risk level to LOW-MEDIUM, add encryption gap
to conclusion and re-assessment triggers
All procedures now consistently acknowledge 85% compliance score and
risk variance based on E2EE usage, while maintaining that DPIA is not
required per Art. 35.
Update GDPR compliance documentation to accurately reflect that database
encryption at rest is NOT implemented for non-E2EE users. This critical
finding required:
- Update compliance score from 92% to 85% (10% deduction for encryption gap)
- Add comprehensive encryption disclosure to privacy policies (German & English)
- Document risk: unencrypted PostgreSQL data on disk
- Update GDPR analysis with compensating controls (optional E2EE)
- Revise Records of Processing Activities with encryption status
- Add context to Alfahosting verification tracker
Changes prioritize GDPR transparency by honestly documenting security
limitations rather than overstating compliance.
Explain design decisions and security trade-offs:
- Why stateless JWTs (not stored in DB)
- Why token versioning over blacklisting
- Why verification tokens are plain strings
- Why bcrypt with 12 rounds
Include security features table, token lifecycle diagram,
and configuration reference.