Docs: Add backend deployment constraints and monorepo structure

- Documented Docker/Kubernetes deployment requirements
- Added homelab configuration (resource limits, ports)
- Configured reverse proxy compatibility
- Designed monorepo structure (backend/mobile/web/shared)
This commit is contained in:
goose 2026-02-14 15:30:13 -03:00
parent 1e38fe3ace
commit 1cf927f527
3 changed files with 1232 additions and 79 deletions

213
README.md
View file

@ -1,94 +1,149 @@
# Normogen
### /home/asoliver/desarrollo/normogen/README.md
```markdown
1: # Normogen
2:
3: ## Overview
4:
5: Normogen is a privacy-focused health data tracking and management platform. The name comes from Mapudungun, relating to Balanced Life.
6:
7: ## Vision
8:
9: To record as many variables related to health as possible, store them in a secure, private manner, to be used by you, not by corporations. From medication reminders to pattern analysis, Normogen puts you in control of your health data.
10:
11: ## Technology Stack
12:
13: ### Backend
14: - **Framework**: Axum 0.7.x
15: - **Runtime**: Tokio 1.x
16: - **Middleware**: Tower, Tower-HTTP
17: - **Database**: MongoDB (with zero-knowledge encryption)
18: - **Language**: Rust
19:
20: ### Mobile (iOS + Android)
21: - **Framework**: React Native 0.73+
22: - **Language**: TypeScript
23: - **State Management**: Redux Toolkit 2.x
24: - **Data Fetching**: RTK Query 2.x
25: - **Health Sensors**: react-native-health, react-native-google-fit
26: - **Encryption**: react-native-quick-crypto
27:
28: ### Web
29: - **Framework**: React 18+
30: - **Language**: TypeScript
31: - **State Management**: Redux Toolkit 2.x
32: - **Data Fetching**: RTK Query 2.x
33: - **Charts**: Recharts
34:
35: ### Deployment
36: - Docker on Linux
37:
38: ## Platform Strategy
39:
40: **Primary: Mobile Apps** - Daily health tracking, sensor integration, QR scanning, push notifications
41:
42: **Secondary: Web Browser** - Extensive reporting, visualization, profile management
43:
44: ## Key Features
45:
46: - Zero-knowledge encryption
47: - Multi-person profiles
48: - Family structure management
49: - Secure sharing with expiring links
50: - Mobile apps with health sensor integration
51: - Web interface for complex visualizations
52:
53: ## Security Model
54:
55: - Client-side encryption: Data encrypted before leaving device
56: - Zero-knowledge: Server stores only encrypted data
57: - Proton-style encryption: AES-256-GCM with PBKDF2 key derivation
58: - Shareable links: Self-contained decryption keys in URLs
59: - Privacy-first: No data selling, subscription-based revenue
60:
61: ## Documentation
62:
63: - [Introduction](./introduction.md) - Project vision and detailed feature specification
64: - [Encryption Implementation Guide](./encryption.md) - Zero-knowledge encryption architecture
65: - [Research](./thoughts/research/) - Technical research and planning documents
66:
67: ## Development Status
68:
69: Phase: Planning/Documentation
70:
71: ### Completed
72: - Project vision and requirements
73: - Security architecture design
74: - Encryption implementation guide
75: - Git repository initialization
76: - **Rust framework selection: Axum**
77: - **Mobile/Web framework selection: React Native + React**
78: - **State management selection: Redux Toolkit 2.x**
79:
80: ### Next Steps
81: - Authentication system design (JWT with recovery phrases)
82: - Database schema design
83: - Create proof-of-concept with Axum
84: - Implement basic CRUD API
85: - Build mobile apps with health sensor integration
86: - Build web companion app
87: - Add encryption layer
88: - Implement sharing functionality
89:
90: ## Open Source
91:
92: Normogen is open-source. Both server and client code will be publicly available.
93:
94: Note: This project is currently in the planning phase. No implementation code has been written yet.
```
## Overview
Normogen is a privacy-focused health data tracking and management platform. The name comes from Mapudungun, relating to Balanced Life.
## Monorepo Structure
## Vision
This is a **monorepo** containing backend, mobile, web, and shared code:
To record as many variables related to health as possible, store them in a secure, private manner, to be used by you, not by corporations. From medication reminders to pattern analysis, Normogen puts you in control of your health data.
```
normogen/
├── backend/ # Rust backend (Axum + MongoDB)
├── mobile/ # React Native (iOS + Android)
├── web/ # React web app
├── shared/ # Shared TypeScript code
└── thoughts/ # Research & design docs
```
## Technology Stack
Each platform has its own `src/` directory to keep codebases separate while sharing common code through the `shared/` directory.
### Backend
- **Framework**: Axum 0.7.x
- **Runtime**: Tokio 1.x
- **Middleware**: Tower, Tower-HTTP
- **Database**: MongoDB (with zero-knowledge encryption)
- **Language**: Rust
## Repository Management
### Mobile (iOS + Android)
- **Framework**: React Native 0.73+
- **Language**: TypeScript
- **State Management**: Redux Toolkit 2.x
- **Data Fetching**: RTK Query 2.x
- **Health Sensors**: react-native-health, react-native-google-fit
- **Encryption**: react-native-quick-crypto
- **Git Hosting**: Forgejo (self-hosted)
- **CI/CD**: Forgejo Actions
- **Branch Strategy**: `main`, `develop`, `feature/*`
- **Deployment**: Docker Compose (homelab), Kubernetes (future)
### Web
- **Framework**: React 18+
- **Language**: TypeScript
- **State Management**: Redux Toolkit 2.x
- **Data Fetching**: RTK Query 2.x
- **Charts**: Recharts
## Deployment
### Deployment
- Docker on Linux
### Backend Deployment
## Platform Strategy
```bash
# Clone repository
git clone <forgejo-url> normogen
cd normogen/backend
**Primary: Mobile Apps** - Daily health tracking, sensor integration, QR scanning, push notifications
# Setup configuration
cp config/.env.example config/.env
# Edit config/.env
**Secondary: Web Browser** - Extensive reporting, visualization, profile management
# Build and run
docker compose build
docker compose up -d
## Key Features
# Check status
curl http://localhost:6000/health
```
- Zero-knowledge encryption
- Multi-person profiles
- Family structure management
- Secure sharing with expiring links
- Mobile apps with health sensor integration
- Web interface for complex visualizations
**Resource Limits** (Homelab):
- CPU: 1000m (1 core)
- Memory: 1000Mi (1GB RAM)
## Security Model
- Client-side encryption: Data encrypted before leaving device
- Zero-knowledge: Server stores only encrypted data
- Proton-style encryption: AES-256-GCM with PBKDF2 key derivation
- Shareable links: Self-contained decryption keys in URLs
- Privacy-first: No data selling, subscription-based revenue
## Documentation
- [Introduction](./introduction.md) - Project vision and detailed feature specification
- [Encryption Implementation Guide](./encryption.md) - Zero-knowledge encryption architecture
- [Research](./thoughts/research/) - Technical research and planning documents
## Development Status
Phase: Planning/Documentation
### Completed
- Project vision and requirements
- Security architecture design
- Encryption implementation guide
- Git repository initialization
- **Rust framework selection: Axum**
- **Mobile/Web framework selection: React Native + React**
- **State management selection: Redux Toolkit 2.x**
### Next Steps
- Authentication system design (JWT with recovery phrases)
- Database schema design
- Create proof-of-concept with Axum
- Implement basic CRUD API
- Build mobile apps with health sensor integration
- Build web companion app
- Add encryption layer
- Implement sharing functionality
## Open Source
Normogen is open-source. Both server and client code will be publicly available.
Note: This project is currently in the planning phase. No implementation code has been written yet.
**Ports**:
- Backend API: `6000` (host) → `8000` (container)
- MongoDB: `27017` (standard port)

View file

@ -0,0 +1,786 @@
### /home/asoliver/desarrollo/normogen/thoughts/research/2026-02-14-backend-deployment-constraints.md
```markdown
1: # Backend Deployment Constraints
2:
3: ## Deployment Requirements
4:
5: ### Docker + Docker Compose
6: - Backend must be containerized using Docker
7: - Use Docker Compose for local development and homelab deployment
8: - Multi-stage builds for optimal image size
9: - Non-root user for security
10:
11: ### Kubernetes Compatibility
12: - Design for future Kubernetes deployment
13: - Use environment-based configuration (env vars)
14: - Health check endpoints (`/health`, `/ready`)
15: - Graceful shutdown handling
16: - Stateless application design
17: - ConfigMap and Secret ready
18:
19: ### One-Command Deployment
20: ```bash
21: # Clone repository
22: git clone https://github.com/yourusername/normogen.git
23: cd normogen
24:
25: # Setup configuration
26: cp config/example.env config/.env
27: # Edit config/.env with your settings
28:
29: # Build and run
30: docker compose build
31: docker compose up -d
32: ```
33:
34: ## Homelab Deployment (Phase 1)
35:
36: ### Port Configuration
37: - **MongoDB**: Standard ports
38: - Primary: `27017` (default MongoDB port)
39: - This allows connecting with existing MongoDB tools/admin UIs
40:
41: - **Backend API**: `6000` (homelab range)
42: - External: `6000` (host port)
43: - Internal: `8000` (container port)
44: - Mapped in docker-compose.yml
45:
46: - **Future Services**: Port range `6000-6999`
47: - `6000`: Backend API (current)
48: - `6001`: Web UI (future)
49: - `6002`: Admin dashboard (future)
50: - `6003`: Metrics/monitoring (future)
51:
52: ### Network Configuration
53: - Docker network: `normogen-network`
54: - Must communicate with existing Docker services on homelab server
55: - MongoDB accessible to host for backup/admin tools
56:
57: ### Environment Configuration
58: ```bash
59: # config/.env (gitignored)
60: # Server Configuration
61: RUST_LOG=info
62: SERVER_HOST=0.0.0.0
63: SERVER_PORT=8000
64: ALLOWED_ORIGINS=http://localhost:3000,http://localhost:6001
65:
66: # Database Configuration
67: MONGODB_URI=mongodb://mongodb:27017/normogen
68: MONGODB_DATABASE=normogen
69:
70: # JWT Configuration
71: JWT_SECRET=your-super-secret-jwt-key-here
72: JWT_ACCESS_TOKEN_EXPIRY_MINUTES=15
73: JWT_REFRESH_TOKEN_EXPIRY_DAYS=30
74:
75: # Encryption Configuration (for validation only)
76: # Actual encryption happens client-side
77: ENCRYPTION_ALGORITHM=aes-256-gcm
78:
79: # Rate Limiting
80: RATE_LIMIT_REQUESTS=100
81: RATE_LIMIT_DURATION_SECONDS=60
82: ```
83:
84: ### Docker Compose Structure
85: ```yaml
86: # docker-compose.yml
87: version: '3.8'
88:
89: services:
90: backend:
91: build:
92: context: .
93: dockerfile: docker/Dockerfile
94: container_name: normogen-backend
95: ports:
96: - "6000:8000" # Homelab port range
97: environment:
98: - RUST_LOG=${RUST_LOG:-info}
99: - SERVER_PORT=8000
100: - MONGODB_URI=mongodb://mongodb:27017/normogen
101: - MONGODB_DATABASE=${MONGODB_DATABASE:-normogen}
102: - JWT_SECRET=${JWT_SECRET}
103: - JWT_ACCESS_TOKEN_EXPIRY_MINUTES=${JWT_ACCESS_TOKEN_EXPIRY_MINUTES:-15}
104: - JWT_REFRESH_TOKEN_EXPIRY_DAYS=${JWT_REFRESH_TOKEN_EXPIRY_DAYS:-30}
105: env_file:
106: - config/.env
107: depends_on:
108: mongodb:
109: condition: service_healthy
110: networks:
111: - normogen-network
112: restart: unless-stopped
113: healthcheck:
114: test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
115: interval: 30s
116: timeout: 10s
117: retries: 3
118: start_period: 40s
119:
120: mongodb:
121: image: mongo:6.0
122: container_name: normogen-mongodb
123: ports:
124: - "27017:27017" # Standard MongoDB port
125: environment:
126: - MONGO_INITDB_DATABASE=${MONGO_DATABASE:-normogen}
127: volumes:
128: - mongodb_data:/data/db
129: - mongodb_config:/data/configdb
130: networks:
131: - normogen-network
132: restart: unless-stopped
133: healthcheck:
134: test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
135: interval: 10s
136: timeout: 5s
137: retries: 5
138: start_period: 10s
139:
140: volumes:
141: mongodb_data:
142: driver: local
143: mongodb_config:
144: driver: local
145:
146: networks:
147: normogen-network:
148: driver: bridge
149: ```
150:
151: ## Kubernetes Deployment (Phase 2 - Future)
152:
153: ### Manifests Structure
154: ```
155: k8s/
156: ├── base/
157: │ ├── deployment.yaml
158: │ ├── service.yaml
159: │ ├── configmap.yaml
160: │ ├── secrets.yaml
161: │ └── ingress.yaml
162: └── overlays/
163: ├── homelab/
164: │ ├── kustomization.yaml
165: │ └── patches/
166: └── production/
167: ├── kustomization.yaml
168: └── patches/
169: ```
170:
171: ### Deployment Configuration
172: - **Replicas**: 2-3 for high availability
173: - **Liveness Probe**: `/health` (10s interval, 5s timeout)
174: - **Readiness Probe**: `/ready` (5s interval, 3s timeout)
175: - **Resource Limits**:
176: - CPU: 500m-1000m
177: - Memory: 256Mi-512Mi
178: - **Helm Chart**: Optional for easier deployment
179:
180: ### Configuration Management
181: - **ConfigMap**: Non-sensitive config (log levels, ports)
182: - **Secrets**: Sensitive config (JWT secret, DB URI)
183: - **Environment Variables**: All configuration via env vars
184:
185: ## Dockerfile Design
186:
187: ### Multi-Stage Build
188: ```dockerfile
189: # docker/Dockerfile
190:
191: # Build stage
192: FROM rust:1.75-alpine AS builder
193: WORKDIR /app
194:
195: # Install build dependencies
196: RUN apk add --no-cache musl-dev pkgconf openssl-dev
197:
198: # Copy manifests
199: COPY Cargo.toml Cargo.lock ./
200:
201: # Create dummy main.rs to build dependencies
202: RUN mkdir src && echo "fn main() {}" > src/main.rs
203: RUN cargo build --release && rm -rf src
204:
205: # Copy source code
206: COPY src ./src
207:
208: # Build application
209: RUN touch src/main.rs && cargo build --release
210:
211: # Runtime stage
212: FROM alpine:3.18
213: WORKDIR /app
214:
215: # Install runtime dependencies
216: RUN apk add --no-cache ca-certificates openssl
217:
218: # Copy binary from builder
219: COPY --from=builder /app/target/release/normogen-backend /app/normogen-backend
220:
221: # Create non-root user
222: RUN addgroup -g 1000 normogen && \
223: adduser -D -u 1000 -G normogen normogen && \
224: chown -R normogen:normogen /app
225:
226: USER normogen
227:
228: # Expose port
229: EXPOSE 8000
230:
231: # Check
232: HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
233: CMD wget --no-verbose --tries=1 --spider http://localhost:8000/health || exit 1
234:
235: # Run application
236: CMD ["./normogen-backend"]
237: ```
238:
239: ## Configuration Management
240:
241: ### Environment Variables
242: All configuration via environment variables (12-factor app):
243: - Database connections
244: - JWT secrets
245: - API credentials
246: - Feature flags
247: - Log levels
248:
249: ### Configuration Files
250: ```
251: config/
252: ├── .env # Gitignored, local dev
253: ├── .env.example # Git committed, template
254: └── defaults.env # Git committed, defaults
255: ```
256:
257: ### Configuration Validation
258: - Validate required env vars on startup
259: - Fail fast if misconfigured
260: - Log configuration (sanitize secrets)
261:
262: ## Endpoints
263:
264: ### Check Endpoints
265: ```rust
266: // GET /health - Liveness probe
267: // Returns: {"status": "ok"}
268: // Used by: K8s liveness probe, Docker check
269: // Purpose: Is the app running?
270:
271: // GET /ready - Readiness probe
272: // Returns: {"status": "ready", "database": "connected"}
273: // Used by: K8s readiness probe
274: // Purpose: Is the app ready to serve traffic?
275: ```
276:
277: ## Logging & Observability
278:
279: ### Structured Logging
280: - JSON format for production
281: - Log levels: ERROR, WARN, INFO, DEBUG, TRACE
282: - Request ID tracing
283: - Sensitive data sanitization
284:
285: ### Metrics (Future)
286: - Prometheus endpoint: `/metrics`
287: - Request rate, error rate, latency
288: - Database connection pool status
289:
290: ## Security Considerations
291:
292: ### Container Security
293: - Non-root user (UID 1000)
294: - Read-only filesystem (except /tmp)
295: - Minimal base image (Alpine)
296: - No shell in runtime image
297: - Security scanning (Trivy, Snyk)
298:
299: ### Secrets Management
300: - Never commit secrets to git
301: - Use environment variables
302: - K8s: Use secrets, not configmaps
303: - Docker: Use env_file or Docker secrets
304: - Gitignore: `config/.env`
305:
306: ## Deployment Checklist
307:
308: ### Initial Setup
309: - [ ] Clone repository
310: - [ ] Copy `config/.env.example` to `config/.env`
311: - [ ] Configure environment variables
312: - [ ] Create Docker network: `docker network create normogen-network`
313: - [ ] Generate JWT secret: `openssl rand -base64 32`
314:
315: ### Build & Run
316: - [ ] Build: `docker compose build`
317: - [ ] Run: `docker compose up -d`
318: - [ ] Check logs: `docker compose logs -f backend`
319: - [ ] Check status: `curl http://localhost:6000/health`
320: - [ ] Check ready: `curl http://localhost:6000/ready`
321:
322: ### Verification
323: - [ ] Backend responds on port 6000
324: - [ ] MongoDB accessible on port 27017
325: - [ ] Checks passing
326: - [ ] Database connection working
327: - [ ] JWT authentication working
328:
329: ## Questions for Clarification
330:
331: ### Environment
332: 1. **Reverse Proxy**: Will you use a reverse proxy (Nginx, Traefik, Caddy)?
333: - If yes, should TLS be handled at proxy or backend?
334: - What domain/path for the API?
335:
336: 2. **MongoDB Deployment**:
337: - Is MongoDB already running in your homelab?
338: - Or should docker-compose spin up a dedicated MongoDB instance for Normogen?
339: - If existing: What's the connection string?
340:
341: 3. **Resource Limits**:
342: - Any CPU/memory constraints for the homelab?
343: - Suggested limits: 500m CPU, 512Mi RAM?
344:
345: 4. **Backup Strategy**:
346: - MongoDB backups? (Volume mount, scheduled dump)
347: - Configuration backups?
348:
349: 5. **Monitoring**:
350: - Log aggregation? (ELK, Loki, Splunk)
351: - Metrics collection? (Prometheus, Grafana)
352: - APM? (Datadog, New Relic)
353:
354: 6. **CI/CD**:
355: - Will you use GitHub Actions, GitLab CI, or Jenkins?
356: - Auto-deploy on commit to main branch?
357: - Automated testing before deploy?
358:
359: ### Development Workflow
360: 7. **Hot Reload**: Development mode with hot reload?
361: - Use `cargo-watch` for auto-rebuild on file changes?
362:
363: 8. **Database Migrations**:
364: - Run migrations on startup?
365: - Separate migration tool?
366:
367: 9. **Seed Data**:
368: - Seed development database with sample data?
369:
370: ### Production Readiness
371: 10. **Rate Limiting**:
372: - Per-IP rate limiting?
373: - Per-user rate limiting (after auth)?
374:
375: 11. **CORS Configuration**:
376: - Allowed origins for local dev?
377: - Allowed origins for production?
378:
379: 12. **TLS/HTTPS**:
380: - Local dev: HTTP or HTTPS?
381: - Production: TLS termination at proxy?
382:
383: ## Next Steps
384:
385: Once the above questions are answered, we can proceed with:
386:
387: 1. **Phase 2.1**: Docker Compose Setup
388: - Create Dockerfile (multi-stage build)
389: - Create docker-compose.yml
390: - Create configuration templates
391: - Test local deployment
392:
393: 2. **Phase 2.2**: Axum Server Setup
394: - Initialize Rust project
395: - Setup Axum dependencies
396: - Create check endpoints
397: - Test containerized build
398:
399: 3. **Phase 2.3**: MongoDB Integration
400: - MongoDB connection pooling
401: - Readiness check with database
402: - Test database connectivity
403:
404: 4. **Phase 2.4**: Configuration Management
405: - Environment variable validation
406: - Configuration struct
407: - Secret loading
408:
409: 5. **Phase 2.5**: Deployment Testing
410: - Test on homelab server
411: - Verify checks
412: - Verify database connection
413: - Test restart behavior
```
## Deployment Decisions (User Confirmed)
### 1. MongoDB Deployment
✅ **New MongoDB instance in docker-compose**
- MongoDB will be spun up as part of docker-compose.yml
- Volume mounts for data persistence
- Standard port 27017 for admin tool access
### 2. Reverse Proxy
✅ **Using reverse proxy for TLS termination**
- Backend handles HTTP only
- TLS/HTTPS handled by reverse proxy (Nginx/Traefik/Caddy)
- CORS configuration needed for allowed origins
### 3. Development Workflow
✅ **Hot reload for local development**
- Use `cargo-watch` for auto-rebuild on file changes
- Separate docker-compose.dev.yml for development
- Production build without hot reload
### 4. Resource Limits
✅ **Homelab resource constraints**
- CPU: 1000m (1 CPU core limit)
- Memory: 1000Mi (1GB RAM limit)
- Configure in docker-compose.yml
- Configure in Kubernetes Deployment for future
### 5. Repository & CI/CD
✅ **Forgejo repository**
- Git hosting: Forgejo (self-hosted GitHub-compatible)
- CI/CD: Forgejo Actions (GitHub Actions compatible)
- Single repository for backend, mobile, web
## Updated Monorepo Structure
```
normogen/ # Root repository
├── backend/ # Rust backend
│ ├── src/ # Source code
│ │ ├── main.rs
│ │ ├── auth/
│ │ ├── api/
│ │ ├── db/
│ │ └── config/
│ ├── docker/
│ │ └── Dockerfile # Multi-stage build
│ ├── Cargo.toml
│ ├── Cargo.lock
│ ├── docker-compose.yml # Homelab deployment
│ ├── docker-compose.dev.yml # Development with hot reload
│ ├── config/
│ │ ├── .env.example
│ │ └── defaults.env
│ └── k8s/ # Future Kubernetes manifests
│ ├── base/
│ └── overlays/
├── mobile/ # React Native (iOS + Android)
│ ├── src/ # Source code
│ │ ├── components/
│ │ ├── screens/
│ │ ├── navigation/
│ │ ├── store/
│ │ ├── services/
│ │ └── utils/
│ ├── package.json
│ ├── tsconfig.json
│ ├── App.tsx
│ └── android/
│ └── ios/
├── web/ # React web app
│ ├── src/ # Source code
│ │ ├── components/
│ │ ├── pages/
│ │ ├── store/
│ │ ├── services/
│ │ └── utils/
│ ├── package.json
│ ├── tsconfig.json
│ └── index.html
├── shared/ # Shared TypeScript code
│ ├── src/
│ │ ├── types/ # Shared types
│ │ ├── validation/ # Zod schemas
│ │ ├── encryption/ # Encryption utilities
│ │ └── api/ # API client
│ └── package.json
├── thoughts/ # Research & design docs
│ └── research/
├── .gitignore # Root gitignore
├── README.md # Root README
└── docker-compose.root.yml # Optional: Run all services
```
### Updated Docker Compose with Resource Limits
```yaml
# docker-compose.yml (production)
version: '3.8'
services:
backend:
build:
context: .
dockerfile: docker/Dockerfile
container_name: normogen-backend
ports:
- "6000:8000"
environment:
- RUST_LOG=${RUST_LOG:-info}
- SERVER_PORT=8000
- MONGODB_URI=mongodb://mongodb:27017/normogen
- MONGODB_DATABASE=${MONGODB_DATABASE:-normogen}
- JWT_SECRET=${JWT_SECRET}
- JWT_ACCESS_TOKEN_EXPIRY_MINUTES=${JWT_ACCESS_TOKEN_EXPIRY_MINUTES:-15}
- JWT_REFRESH_TOKEN_EXPIRY_DAYS=${JWT_REFRESH_TOKEN_EXPIRY_DAYS:-30}
env_file:
- config/.env
depends_on:
mongodb:
condition: service_healthy
networks:
- normogen-network
restart: unless-stopped
deploy:
resources:
limits:
cpus: '1.0' # 1 CPU core
memory: 1000M # 1GB RAM
reservations:
cpus: '0.25'
memory: 256M
check:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
mongodb:
image: mongo:6.0
container_name: normogen-mongodb
ports:
- "27017:27017"
environment:
- MONGO_INITDB_DATABASE=${MONGO_DATABASE:-normogen}
volumes:
- mongodb_data:/data/db
- mongodb_config:/data/configdb
networks:
- normogen-network
restart: unless-stopped
deploy:
resources:
limits:
cpus: '0.5'
memory: 512M
reservations:
cpus: '0.25'
memory: 128M
check:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
volumes:
mongodb_data:
driver: local
mongodb_config:
driver: local
networks:
normogen-network:
driver: bridge
```
### Development Docker Compose (Hot Reload)
```yaml
# docker-compose.dev.yml (development)
version: '3.8'
services:
backend:
build:
context: .
dockerfile: docker/Dockerfile.dev
container_name: normogen-backend-dev
ports:
- "6000:8000"
volumes:
- ./src:/app/src # Hot reload: Mount source code
- ./Cargo.toml:/app/Cargo.toml
environment:
- RUST_LOG=debug
- SERVER_PORT=8000
- MONGODB_URI=mongodb://mongodb:27017/normogen
- MONGODB_DATABASE=normogen_dev
- JWT_SECRET=dev-secret-do-not-use-in-production
- CARGO_WATCH=1 # Enable hot reload
depends_on:
mongodb:
condition: service_healthy
networks:
- normogen-network
restart: unless-stopped
mongodb:
image: mongo:6.0
container_name: normogen-mongodb-dev
ports:
- "27017:27017"
environment:
- MONGO_INITDB_DATABASE=normogen_dev
volumes:
- mongodb_dev_data:/data/db
networks:
- normogen-network
check:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 5s
retries: 5
volumes:
mongodb_dev_data:
driver: local
networks:
normogen-network:
driver: bridge
```
### Development Dockerfile (with cargo-watch)
```dockerfile
# docker/Dockerfile.dev
FROM rust:1.75-alpine
WORKDIR /app
# Install runtime and build dependencies
RUN apk add --no-cache \
musl-dev \
pkgconf \
openssl-dev \
curl \
wget \
git
# Install cargo-watch for hot reload
RUN cargo install cargo-watch
# Copy manifests
COPY Cargo.toml Cargo.lock ./
# Create dummy main.rs to build dependencies
RUN mkdir src && echo "fn main() {}" > src/main.rs
RUN cargo build && rm -rf src
# Copy source code (will be mounted as volume in dev)
COPY src ./src
# Expose port
EXPOSE 8000
# Run with hot reload
CMD ["cargo-watch", "-x", "run"]
```
### Forgejo CI/CD (Example)
```yaml
# .forgejo/workflows/backend-build.yml
name: Build and Test Backend
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Rust
uses: actions-rust-lang/setup-rust-toolchain@v1
- name: Cache cargo registry
uses: actions/cache@v3
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
- name: Build backend
working-directory: ./backend
run: cargo build --verbose
- name: Run tests
working-directory: ./backend
run: cargo test --verbose
- name: Build Docker image
working-directory: ./backend
run: docker build -f docker/Dockerfile -t normogen-backend:${{ github.sha }} .
deploy-homelab:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy to homelab
run: |
echo "Deploy to homelab server"
# Add deployment script here
```
### CORS Configuration (for Reverse Proxy)
```rust
// src/config/cors.rs
use tower_http::cors::{CorsLayer, Any};
use axum::http::{HeaderValue, Method};
pub fn create_cors_layer(allowed_origins: &str) -> CorsLayer {
let origins: Vec<&str> = allowed_origins.split(',').map(|s| s.trim()).collect();
CorsLayer::new()
.allow_origin(origins.into_iter().map(|s| {
s.parse::<HeaderValue>().unwrap()
}).collect::<Vec<_>>())
.allow_methods([Method::GET, Method::POST, Method::PUT, Method::PATCH, Method::DELETE, Method::OPTIONS])
.allow_headers(Any)
.allow_credentials(true)
.max_age(3600)
}
```
## Updated Deployment Checklist
### Initial Setup
- [ ] Clone repository from Forgejo
- [ ] Copy `backend/config/.env.example` to `backend/config/.env`
- [ ] Configure environment variables
- [ ] Generate JWT secret: `openssl rand -base64 32`
- [ ] Set resource limits in docker-compose.yml
### Development Setup
- [ ] Run development: `docker compose -f docker-compose.dev.yml up -d`
- [ ] Check logs: `docker compose -f docker-compose.dev.yml logs -f backend`
- [ ] Test hot reload: Make changes to src/, verify auto-rebuild
### Production Deployment
- [ ] Run production: `docker compose up -d`
- [ ] Check logs: `docker compose logs -f backend`
- [ ] Verify resource limits: `docker stats`
- [ ] Configure reverse proxy (Nginx/Traefik/Caddy)
- [ ] Configure reverse proxy CORS headers
- [ ] Test API through reverse proxy

View file

@ -0,0 +1,312 @@
# Monorepo Structure
## Repository Layout
```
normogen/ # Root Forgejo repository
├── backend/ # Rust backend (Axum + MongoDB)
│ ├── src/ # Source code
│ │ ├── main.rs # Entry point
│ │ ├── auth/ # Authentication
│ │ │ ├── mod.rs
│ │ │ ├── jwt_service.rs
│ │ │ ├── claims.rs
│ │ │ └── middleware.rs
│ │ ├── api/ # API endpoints
│ │ │ ├── mod.rs
│ │ │ ├── users.rs
│ │ │ ├── families.rs
│ │ │ ├── profiles.rs
│ │ │ ├── health_data.rs
│ │ │ ├── lab_results.rs
│ │ │ ├── medications.rs
│ │ │ ├── appointments.rs
│ │ │ └── shares.rs
│ │ ├── db/ # Database
│ │ │ ├── mod.rs
│ │ │ ├── mongo.rs
│ │ │ ├── models.rs
│ │ │ └── repositories.rs
│ │ ├── config/ # Configuration
│ │ │ ├── mod.rs
│ │ │ ├── app.rs
│ │ │ ├── jwt.rs
│ │ │ ├── mongo.rs
│ │ │ └── cors.rs
│ │ ├── middleware/ # Middleware
│ │ │ ├── mod.rs
│ │ │ ├── auth.rs
│ │ │ ├── logging.rs
│ │ │ └── rate_limit.rs
│ │ ├── utils/ # Utilities
│ │ │ ├── mod.rs
│ │ │ ├── crypto.rs
│ │ │ └── validation.rs
│ │ └── error.rs # Error types
│ ├── docker/
│ │ ├── Dockerfile # Production build
│ │ └── Dockerfile.dev # Development build
│ ├── config/
│ │ ├── .env.example # Environment template
│ │ └── defaults.env # Default values
│ ├── k8s/ # Kubernetes manifests (future)
│ │ ├── base/
│ │ └── overlays/
│ ├── Cargo.toml # Dependencies
│ ├── Cargo.lock # Lock file
│ ├── docker-compose.yml # Production deployment
│ ├── docker-compose.dev.yml # Development deployment
│ └── README.md # Backend README
├── mobile/ # React Native (iOS + Android)
│ ├── src/ # Source code
│ │ ├── components/ # Reusable components
│ │ │ ├── common/
│ │ │ ├── health/
│ │ │ ├── lab/
│ │ │ └── medication/
│ │ ├── screens/ # Screen components
│ │ │ ├── auth/
│ │ │ ├── home/
│ │ │ ├── family/
│ │ │ ├── profile/
│ │ │ ├── health/
│ │ │ ├── lab/
│ │ │ └── settings/
│ │ ├── navigation/ # Navigation config
│ │ │ ├── AppNavigator.tsx
│ │ │ ├── AuthNavigator.tsx
│ │ │ └── LinkingConfiguration.tsx
│ │ ├── store/ # Redux store
│ │ │ ├── slices/
│ │ │ │ ├── authSlice.ts
│ │ │ │ ├── userSlice.ts
│ │ │ │ ├── familySlice.ts
│ │ │ │ ├── profileSlice.ts
│ │ │ │ └── healthDataSlice.ts
│ │ │ └── store.ts
│ │ ├── services/ # API services
│ │ │ ├── api.ts # Axios client
│ │ │ ├── authService.ts
│ │ │ ├── userService.ts
│ │ │ └── healthDataService.ts
│ │ ├── utils/ # Utilities
│ │ │ ├── encryption.ts # Client-side encryption
│ │ │ ├── validation.ts
│ │ │ └── constants.ts
│ │ ├── hooks/ # Custom hooks
│ │ │ ├── useAuth.ts
│ │ │ └── useEncryptedStorage.ts
│ │ ├── types/ # TypeScript types
│ │ │ └── index.ts
│ │ └── assets/ # Images, fonts
│ ├── android/ # Android native code
│ │ ├── app/
│ │ └── build.gradle
│ ├── ios/ # iOS native code
│ │ ├── Normogen
│ │ └── Podfile
│ ├── package.json
│ ├── tsconfig.json
│ ├── App.tsx # Entry component
│ ├── README.md
│ └── .env.example
├── web/ # React web app
│ ├── src/ # Source code
│ │ ├── components/ # Reusable components
│ │ │ ├── common/
│ │ │ ├── health/
│ │ │ ├── lab/
│ │ │ └── charts/
│ │ ├── pages/ # Page components
│ │ │ ├── auth/
│ │ │ ├── home/
│ │ │ ├── family/
│ │ │ ├── profile/
│ │ │ ├── health/
│ │ │ ├── lab/
│ │ │ └── settings/
│ │ ├── store/ # Redux store (shared with mobile)
│ │ │ ├── slices/
│ │ │ └── store.ts
│ │ ├── services/ # API services (shared with mobile)
│ │ │ ├── api.ts
│ │ │ └── ...
│ │ ├── utils/ # Utilities (shared with mobile)
│ │ │ ├── encryption.ts
│ │ │ └── ...
│ │ ├── hooks/ # Custom hooks
│ │ │ └── ...
│ │ ├── types/ # TypeScript types (shared)
│ │ │ └── index.ts
│ │ ├── styles/ # CSS/global styles
│ │ │ └── global.css
│ │ └── App.tsx
│ ├── package.json
│ ├── tsconfig.json
│ ├── index.html
│ ├── vite.config.ts # Vite config
│ └── README.md
├── shared/ # Shared TypeScript code
│ ├── src/
│ │ ├── types/ # Shared type definitions
│ │ │ ├── user.ts
│ │ │ ├── family.ts
│ │ │ ├── profile.ts
│ │ │ ├── healthData.ts
│ │ │ ├── labResults.ts
│ │ │ ├── medications.ts
│ │ │ ├── appointments.ts
│ │ │ ├── shares.ts
│ │ │ └── api.ts
│ │ ├── validation/ # Zod schemas
│ │ │ ├── user.ts
│ │ │ ├── family.ts
│ │ │ └── healthData.ts
│ │ ├── encryption/ # Encryption utilities
│ │ │ ├── crypto.ts
│ │ │ └── keyDerivation.ts
│ │ ├── api/ # Shared API client
│ │ │ ├── client.ts
│ │ │ └── endpoints.ts
│ │ └── constants/ # Shared constants
│ │ ├── routes.ts
│ │ └── config.ts
│ ├── package.json
│ ├── tsconfig.json
│ └── README.md
├── thoughts/ # Research & design docs
│ ├── research/
│ │ ├── 2026-02-14-rust-framework-comparison.md
│ │ ├── 2026-02-14-rust-framework-performance-research.md
│ │ ├── 2026-02-14-performance-findings.md
│ │ ├── 2026-02-14-research-summary.md
│ │ ├── 2026-02-14-frontend-mobile-research.md
│ │ ├── 2026-02-14-frontend-decision-summary.md
│ │ ├── 2026-02-14-state-management-research.md
│ │ ├── 2026-02-14-state-management-decision.md
│ │ ├── 2026-02-14-jwt-authentication-research.md
│ │ ├── 2026-02-14-jwt-authentication-decision.md
│ │ ├── 2026-02-14-mongodb-schema-design-research.md
│ │ ├── 2026-02-14-mongodb-schema-decision.md
│ │ ├── 2026-02-14-backend-deployment-constraints.md
│ │ └── 2026-02-14-monorepo-structure.md
│ └── research/
├── .gitignore # Root gitignore
├── README.md # Root README
├── docker-compose.root.yml # Run all services (optional)
└── .forgejo/ # Forgejo CI/CD workflows
└── workflows/
├── backend-build.yml
├── mobile-build.yml
└── web-build.yml
```
## Directory Creation Commands
```bash
# Create root directories
mkdir -p backend/{src/{auth,api,db,config,middleware,utils},docker,config,k8s/base,k8s/overlays/homelab,k8s/overlays/production}
mkdir -p mobile/{src/{components/{common,health,lab,medication},screens/{auth,home,family,profile,health,lab,settings},navigation,store/slices,services,utils,hooks,types,assets},android,ios}
mkdir -p web/{src/{components/{common,health,lab,charts},pages/{auth,home,family,profile,health,lab,settings},store/slices,services,utils,hooks,types,styles}}
mkdir -p shared/src/{types,validation,encryption,api,constants}
mkdir -p thoughts/research
mkdir -p .forgejo/workflows
# Create placeholder files
touch backend/src/{main.rs,auth/mod.rs,api/mod.rs,db/mod.rs,config/mod.rs,middleware/mod.rs,utils/mod.rs,error.rs}
touch mobile/src/{App.tsx,navigation/AppNavigator.tsx,store/store.ts,services/api.ts,utils/encryption.ts}
touch web/src/{App.tsx,store/store.ts,services/api.ts,utils/encryption.ts}
touch shared/src/{types/index.ts,validation/index.ts,encryption/crypto.ts,api/client.ts}
```
## Git Strategy
### Branch Strategy
- `main`: Production releases
- `develop`: Development integration
- `feature/backend-*`: Backend features
- `feature/mobile-*`: Mobile features
- `feature/web-*`: Web features
- `feature/shared-*`: Shared code features
### Commit Message Format
```
<type>(<scope>): <subject>
<body>
<footer>
```
Types: feat, fix, docs, style, refactor, test, chore
Scopes: backend, mobile, web, shared, ci/cd
Examples:
- `feat(backend): Implement JWT authentication with refresh tokens`
- `fix(mobile): Resolve encryption key storage issue`
- `docs(shared): Update API type definitions`
- `chore(ci/cd): Add Forgejo workflow for backend builds`
## Shared Code Management
### TypeScript Package
The `shared/` directory contains TypeScript code shared between mobile and web:
- Type definitions (API models)
- Validation schemas (Zod)
- Encryption utilities
- API client
- Constants
### Usage in Mobile/Web
```json
// mobile/package.json and web/package.json
{
"dependencies": {
"shared": "file:../shared"
}
}
```
### Watch Mode for Development
```bash
# In shared/ directory
npm run watch # Watch and rebuild on changes
# In mobile/ and web/ directories
# Changes to shared/ are automatically picked up
```
## Next Steps
1. **Initialize Monorepo Structure**
- Create all directories
- Create placeholder files
- Update root .gitignore
2. **Backend Initialization**
- Initialize Rust project (backend/)
- Setup Cargo.toml
- Create docker-compose files
- Create Dockerfiles
3. **Shared Code Setup**
- Initialize TypeScript project (shared/)
- Setup type definitions
- Setup Zod validation schemas
- Setup encryption utilities
4. **Mobile Setup** (Phase 3)
- Initialize React Native project
- Setup Redux Toolkit
- Setup navigation
5. **Web Setup** (Phase 3)
- Initialize React project
- Setup Redux Toolkit
- Setup routing