docs: reconcile documentation with reality (P3)
Make the project's documentation match the code and remove the sprawl. The docs
claimed Phase 2.8 (drug interactions) was 'planning/0%' and the backend '~91%
complete' — both wrong: 2.8 is implemented and live, plus the P0/P1 security
and test work is done. Five root CI/CD docs described a 'docker-build' CI job
that was removed; ~18 backend/ status snapshots and ~24 docs/implementation
duplicates cluttered the tree.
Deletions (85 files):
- Root: 4 stale CI/CD reports (CI-CD-{COMPLETION-REPORT,IMPLEMENTATION-SUMMARY,
STATUS-REPORT,FINAL-STATUS}.md) — all describe the removed docker-build job.
- backend/: 18 phase/build/fix snapshots and code-dump .txt files.
- docs/: the 3 one-time reorg reports; ~17 docs/implementation duplicates and
process artifacts; 4 stale docs/development CI docs + git snapshots;
redundant deployment/testing files.
- thoughts/: STATUS.md (said Phase 2.4 in-progress), superseded phase notes and
duplicative research inputs. tmp/ (928KB of CI debug logs, gitignored).
Moves (18 files):
- 9 genuine decision records -> docs/adr/ (Architecture Decision Records),
date-prefixes stripped, with an index README.
- 8 historical-but-valuable phase plans/specs + the old CI-CD-FINAL-SOLUTION ->
docs/archive/ (now-populated, with a README explaining it's superseded
material). thoughts/ tree removed.
Rewrites (13 files) to match reality:
- Drop the fake '% complete' figures everywhere in favor of Implemented /
In-Progress / Planned with concrete endpoint/feature lists.
- Phase 2.8 -> Implemented; add /api/interactions/* and /api/auth/{refresh,
logout} to the endpoint lists; fix 'Rust 1.93' -> edition 2021.
- Add a Security section (token_version validation, hashed refresh-token
persistence, fail-fast config, real-IP audit) and correct the test-coverage
and deployment claims to reality.
- New canonical docs/development/CI-CD.md (4 jobs: format/clippy/build/test,
mongo service, no docker-build + why).
- README, docs/README, product/{STATUS,ROADMAP,PROGRESS,README,introduction},
implementation/README, development/README, testing/README, AI_AGENT_GUIDE,
.cursorrules, .gooserules all updated.
Verified: greps for 'Phase 2.8 (Planning)', 'PLANNING (0%)', 'Rust 1.93',
'91%/10%/85% complete', and 'docker-build' return nothing outside docs/archive;
all internal doc links resolve; backend/src untouched (cargo build clean).
This commit is contained in:
parent
bd1b7c2925
commit
17efc4f656
119 changed files with 469 additions and 17801 deletions
183
docs/adr/mongodb-schema-decision.md
Normal file
183
docs/adr/mongodb-schema-decision.md
Normal file
|
|
@ -0,0 +1,183 @@
|
|||
# MongoDB Schema Design Decision Summary
|
||||
|
||||
**Date**: 2026-02-14
|
||||
**Decision**: **Zero-Knowledge Encryption for All Sensitive Data + Metadata**
|
||||
|
||||
---
|
||||
|
||||
## Core Principle
|
||||
|
||||
**ALL sensitive data AND metadata must be encrypted client-side before reaching MongoDB.**
|
||||
|
||||
### Example: Blood Pressure Reading
|
||||
|
||||
**Before encryption** (client-side):
|
||||
```javascript
|
||||
{
|
||||
value: "120/80",
|
||||
type: "blood_pressure",
|
||||
unit: "mmHg",
|
||||
date: "2026-02-14T10:30:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
**After encryption** (stored in MongoDB):
|
||||
```javascript
|
||||
{
|
||||
healthDataId: "health-123",
|
||||
userId: "user-456",
|
||||
profileId: "profile-789",
|
||||
familyId: "family-012",
|
||||
|
||||
// Encrypted (value + metadata)
|
||||
healthData: [
|
||||
{
|
||||
encrypted: true,
|
||||
data: "a1b2c3d4...",
|
||||
iv: "e5f6g7h8...",
|
||||
authTag: "i9j0k1l2..."
|
||||
}
|
||||
],
|
||||
|
||||
// Metadata (plaintext)
|
||||
createdAt: ISODate("2026-02-14T10:30:00Z"),
|
||||
updatedAt: ISODate("2026-02-14T10:30:00Z"),
|
||||
dataSource: "healthKit"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Collections Summary
|
||||
|
||||
| Collection | Purpose | Encrypted Fields | Plaintext Fields |
|
||||
|-----------|---------|------------------|-----------------|
|
||||
| **users** | Authentication | encryptedRecoveryPhrase | userId, email, passwordHash, tokenVersion, familyId, familyRole, permissions |
|
||||
| **families** | Family structure | familyName, familyMetadata | familyId, members[*].userId, members[*].profileId, members[*].role |
|
||||
| **profiles** | Person profiles | profileName, profileMetadata | profileId, userId, familyId, profileType |
|
||||
| **health_data** | Health records | healthData[*] (value + metadata) | healthDataId, userId, profileId, familyId, createdAt, updatedAt, dataSource |
|
||||
| **lab_results** | Lab tests | labData (value + metadata), labMetadata | labResultId, userId, profileId, familyId, createdAt, updatedAt, dataSource |
|
||||
| **medications** | Medication tracking | medicationData (value + metadata), reminderSchedule | medicationId, userId, profileId, familyId, active, createdAt, updatedAt |
|
||||
| **appointments** | Medical appointments | appointmentData (value + metadata), reminderSettings | appointmentId, userId, profileId, familyId, createdAt, updatedAt |
|
||||
| **shares** | Shared data | encryptedData (share-specific password) | shareId, userId, documentId, collectionName, createdAt, expiresAt, accessCount, isRevoked |
|
||||
| **refresh_tokens** | JWT tokens | None | jti, userId, createdAt, expiresAt, revoked |
|
||||
|
||||
---
|
||||
|
||||
## Encryption Strategy
|
||||
|
||||
### Client-Side Encryption
|
||||
|
||||
**Encryption Flow**:
|
||||
1. User enters health data
|
||||
2. Client derives encryption key from password (PBKDF2)
|
||||
3. Client encrypts health data (AES-256-GCM)
|
||||
4. Client sends encrypted data to server
|
||||
5. Server stores encrypted data in MongoDB
|
||||
6. Server NEVER decrypts data
|
||||
|
||||
### What Must Be Encrypted
|
||||
- ✅ **Health data values** (e.g., "120/80")
|
||||
- ✅ **Health data metadata** (e.g., "blood_pressure", "mmHg")
|
||||
- ✅ **Lab test results** (e.g., "cholesterol", "200", "LabCorp")
|
||||
- ✅ **Medication data** (e.g., "Aspirin", "100mg", "daily")
|
||||
- ✅ **Appointment data** (e.g., "checkup", "Dr. Smith")
|
||||
- ✅ **Profile data** (e.g., "John Doe", "1990-01-01")
|
||||
- ✅ **Family data** (e.g., "Smith Family", "123 Main St")
|
||||
### What Can Be Plaintext
|
||||
- ✅ **User IDs** (userId, profileId, familyId) - for queries
|
||||
- ✅ **Email addresses** - for authentication
|
||||
- ✅ **Dates** (createdAt, updatedAt) - for sorting
|
||||
- ✅ **Data sources** (healthKit, googleFit) - for analytics
|
||||
- ✅ **Tags** (cardio, daily) - for client-side search
|
||||
|
||||
---
|
||||
|
||||
## Privacy-Preserving Queries
|
||||
|
||||
### 1. Plaintext Queries (Recommended)
|
||||
|
||||
**Query by plaintext fields only**:
|
||||
```javascript
|
||||
const healthData = await db.health_data.find({
|
||||
userId: 'user-123', // Plaintext ✅
|
||||
profileId: 'profile-456', // Plaintext ✅
|
||||
familyId: 'family-789' // Plaintext ✅
|
||||
}).toArray();
|
||||
|
||||
// Client decrypts healthData[i].healthData[j]
|
||||
```
|
||||
|
||||
### 2. Tagging System (Encrypted Search)
|
||||
|
||||
**Client adds searchable tags to encrypted data**:
|
||||
```javascript
|
||||
const healthData = await db.health_data.find({
|
||||
userId: 'user-123',
|
||||
tags: { $in: ['cardio', 'daily'] } // Plaintext tags ✅
|
||||
}).toArray();
|
||||
|
||||
// Client decrypts healthData[i].healthData[j]
|
||||
```
|
||||
|
||||
### 3. Date Range Queries (Plaintext Dates)
|
||||
|
||||
**Store dates as plaintext** (for range queries):
|
||||
```javascript
|
||||
const healthData = await db.health_data.find({
|
||||
userId: 'user-123',
|
||||
date: {
|
||||
$gte: ISODate("2026-02-01"),
|
||||
$lte: ISODate("2026-02-28")
|
||||
}
|
||||
}).toArray();
|
||||
|
||||
// Client decrypts healthData[i].healthData[j]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Technology Stack
|
||||
|
||||
### Backend (Axum + MongoDB)
|
||||
- **Axum 0.7.x**: Web framework
|
||||
- **MongoDB 6.0+**: Database
|
||||
- **Rust**: Server language
|
||||
### Client (React Native + React)
|
||||
- **AES-256-GCM**: Encryption algorithm
|
||||
- **PBKDF2**: Key derivation function
|
||||
- **Crypto API**: Node.js crypto / react-native-quick-crypto
|
||||
|
||||
---
|
||||
|
||||
## Implementation Timeline
|
||||
|
||||
- **Week 1**: Create MongoDB indexes
|
||||
- **Week 1-2**: Implement client-side encryption (React Native + React)
|
||||
- **Week 2-3**: Implement server-side API (Axum + MongoDB)
|
||||
- **Week 3**: Test encryption flow
|
||||
- **Week 3-4**: Test data migration (key rotation)
|
||||
- **Week 4**: Test privacy-preserving queries
|
||||
- **Week 4-5**: Performance testing
|
||||
**Total**: 4-5 weeks
|
||||
|
||||
---
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. Create MongoDB indexes for all collections
|
||||
2. Implement client-side encryption (React Native + React)
|
||||
3. Implement server-side API (Axum + MongoDB)
|
||||
4. Test encryption flow (end-to-end)
|
||||
5. Test data migration (key rotation)
|
||||
6. Test privacy-preserving queries
|
||||
7. Performance testing
|
||||
8. Create API documentation
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [Comprehensive MongoDB Schema Research](./2026-02-14-mongodb-schema-design-research.md)
|
||||
- [Normogen Encryption Guide](../encryption.md)
|
||||
- [JWT Authentication Research](./2026-02-14-jwt-authentication-research.md)
|
||||
- [Technology Stack Decisions](./2026-02-14-tech-stack-decision.md)
|
||||
Loading…
Add table
Add a link
Reference in a new issue