fix/p0-security-hardening #1

Merged
alvaro merged 4 commits from fix/p0-security-hardening into main 2026-06-27 23:17:09 +00:00
31 changed files with 115 additions and 553 deletions
Showing only changes of commit fff1ed2e6d - Show all commits

View file

@ -25,8 +25,8 @@ cp .env.example .env
# Run with Docker Compose # Run with Docker Compose
docker compose up -d docker compose up -d
# Check status (default port is 6800 on Solaria / 8080 via NORMOGEN_PORT) # Check status (default port is 6500 via NORMOGEN_PORT; Solaria maps it to host 6800)
curl http://localhost:8080/health curl http://localhost:6500/health
``` ```
## 📊 Current Status ## 📊 Current Status

View file

@ -6,8 +6,10 @@ RUST_LOG=info
# strong, non-default values. # strong, non-default values.
APP_ENVIRONMENT=development APP_ENVIRONMENT=development
SERVER_HOST=0.0.0.0 # The app reads NORMOGEN_HOST / NORMOGEN_PORT (config/mod.rs), NOT SERVER_*.
SERVER_PORT=8000 # Defaults: host 0.0.0.0, port 6500.
NORMOGEN_HOST=0.0.0.0
NORMOGEN_PORT=6500
MONGODB_URI=mongodb://mongodb:27017 MONGODB_URI=mongodb://mongodb:27017
MONGODB_DATABASE=normogen MONGODB_DATABASE=normogen
@ -15,6 +17,7 @@ MONGODB_DATABASE=normogen
# MUST be changed and MUST NOT equal "secret" when APP_ENVIRONMENT=production. # MUST be changed and MUST NOT equal "secret" when APP_ENVIRONMENT=production.
JWT_SECRET=change-this-to-a-strong-random-secret-key JWT_SECRET=change-this-to-a-strong-random-secret-key
JWT_ACCESS_TOKEN_EXPIRY_MINUTES=15 JWT_ACCESS_TOKEN_EXPIRY_MINUTES=15
# Default is 7 days; 30 shown here as an opinionated example.
JWT_REFRESH_TOKEN_EXPIRY_DAYS=30 JWT_REFRESH_TOKEN_EXPIRY_DAYS=30
# MUST be set (and not the default) when APP_ENVIRONMENT=production. # MUST be set (and not the default) when APP_ENVIRONMENT=production.

View file

@ -1,43 +1,37 @@
# Use a lightweight Rust image # Production image. Built by docker-compose.yml (`build: .`).
FROM rust:1.82-slim as builder FROM rust:latest AS builder
WORKDIR /app WORKDIR /app
# Install build dependencies # Build dependencies
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
pkg-config \ pkg-config \
libssl-dev \ libssl-dev \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Copy Cargo files # Copy Cargo files and cache dependency build via a dummy main.rs
COPY Cargo.toml Cargo.lock ./ COPY Cargo.toml Cargo.lock ./
# Create a dummy main.rs to cache dependencies
RUN mkdir src && echo "fn main() {}" > src/main.rs RUN mkdir src && echo "fn main() {}" > src/main.rs
# Build dependencies
RUN cargo build --release && rm -rf src RUN cargo build --release && rm -rf src
# Copy actual source code # Copy actual source and build the application
COPY src ./src COPY src ./src
# Build the application
RUN touch src/main.rs && cargo build --release RUN touch src/main.rs && cargo build --release
# Runtime image # --- runtime stage ---
FROM debian:bookworm-slim FROM debian:bookworm-slim
# curl is required for the compose HEALTHCHECK to work.
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
ca-certificates \ ca-certificates \
libssl3 \
curl \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
WORKDIR /app WORKDIR /app
# Copy the binary from builder
COPY --from=builder /app/target/release/normogen-backend /app/normogen-backend COPY --from=builder /app/target/release/normogen-backend /app/normogen-backend
# Expose port # The app listens on NORMOGEN_PORT (default 6500, set in compose/.env).
EXPOSE 8080 EXPOSE 6500
# Run the application
CMD ["./normogen-backend"] CMD ["./normogen-backend"]

View file

@ -1,55 +0,0 @@
# Multi-stage Dockerfile for Normogen Backend
# Stage 1: Build the Rust application
FROM rust:1.93-slim as builder
WORKDIR /app
# Install build dependencies
RUN apt-get update && apt-get install -y \
pkg-config \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*
# Copy manifests
COPY Cargo.toml Cargo.lock ./
COPY src ./src
# Build the application in release mode
RUN cargo build --release
# Stage 2: Runtime image
FROM debian:bookworm-slim
# Install runtime dependencies only
RUN apt-get update && apt-get install -y \
ca-certificates \
libssl3 \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get clean
# Create a non-root user
RUN useradd -m -u 1000 normogen
WORKDIR /app
# Copy the binary from builder
COPY --from=builder /app/target/release/normogen-backend /app/normogen-backend
# Change ownership
RUN chown -R normogen:normogen /app
# Switch to non-root user
USER normogen
# Expose the port
EXPOSE 8000
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
# Set the entrypoint to ensure proper signal handling
ENTRYPOINT ["/app/normogen-backend"]
# Run with proper signal forwarding
CMD []

View file

@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
API_URL="http://localhost:8080" API_URL="http://localhost:6500"
USER_EMAIL="med-test-${RANDOM}@example.com" USER_EMAIL="med-test-${RANDOM}@example.com"
USER_NAME="medtest${RANDOM}" USER_NAME="medtest${RANDOM}"

View file

@ -1 +0,0 @@
test

View file

@ -1,4 +1,4 @@
RUST_LOG=debug RUST_LOG=debug
SERVER_PORT=8000 NORMOGEN_PORT=6500
MONGODB_URI=mongodb://mongodb:27017 MONGODB_URI=mongodb://mongodb:27017
MONGODB_DATABASE=normogen MONGODB_DATABASE=normogen

View file

@ -1,102 +0,0 @@
#!/bin/bash
set -e
echo "🚀 Deploying Normogen Backend to Solaria (Improved)"
echo "===================================================="
# Configuration
REMOTE_HOST="solaria"
REMOTE_DIR="/srv/normogen"
DOCKER_COMPOSE_FILE="docker/docker-compose.improved.yml"
# Colors for output
RED='\\033[0;31m'
GREEN='\\033[0;32m'
YELLOW='\\033[1;33m'
NC='\\033[0m' # No Color
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
# Check if JWT_SECRET is set
if [ -z "${JWT_SECRET}" ]; then
log_error "JWT_SECRET environment variable not set!"
echo "Usage: JWT_SECRET=your-secret ./backend/deploy-to-solaria-improved.sh"
echo ""
echo "Generate a secure secret with:"
echo " openssl rand -base64 32"
exit 1
fi
# Step 1: Build locally
log_info "Step 1: Building backend binary locally..."
cargo build --release
log_info "✅ Build complete"
# Step 2: Create remote directory structure
log_info "Step 2: Setting up remote directory..."
ssh ${REMOTE_HOST} "mkdir -p ${REMOTE_DIR}/docker"
log_info "✅ Directory ready"
# Step 3: Create .env file on remote
log_info "Step 3: Setting up environment variables..."
ssh ${REMOTE_HOST} "cat > ${REMOTE_DIR}/.env << EOF
MONGODB_DATABASE=normogen
JWT_SECRET=${JWT_SECRET}
RUST_LOG=info
SERVER_PORT=8000
SERVER_HOST=0.0.0.0
EOF"
log_info "✅ Environment configured"
# Step 4: Copy improved Docker files to remote
log_info "Step 4: Copying Docker files to remote..."
scp docker/Dockerfile.improved ${REMOTE_HOST}:${REMOTE_DIR}/docker/Dockerfile.improved
scp docker/docker-compose.improved.yml ${REMOTE_HOST}:${REMOTE_DIR}/docker/docker-compose.improved.yml
log_info "✅ Docker files copied"
# Step 5: Stop old containers
log_info "Step 5: Stopping old containers..."
ssh ${REMOTE_HOST} "cd ${REMOTE_DIR} && docker compose down 2>/dev/null || true"
log_info "✅ Old containers stopped"
# Step 6: Start new containers with improved configuration
log_info "Step 6: Starting new containers..."
ssh ${REMOTE_HOST} "cd ${REMOTE_DIR} && docker compose -f ${DOCKER_COMPOSE_FILE} up -d"
log_info "✅ Containers started"
# Step 7: Wait for containers to be healthy
log_info "Step 7: Waiting for containers to stabilize..."
sleep 10
ssh ${REMOTE_HOST} "docker compose -f ${REMOTE_DIR}/${DOCKER_COMPOSE_FILE} ps"
log_info "✅ Container status retrieved"
# Step 8: Test API health endpoint
log_info "Step 8: Testing API health endpoint..."
sleep 5
if curl -f http://solaria.solivarez.com.ar:8001/health > /dev/null 2>&1; then
log_info "✅ API is responding correctly"
else
log_warn "⚠️ API health check failed - check logs with:"
echo " ssh ${REMOTE_HOST} 'docker logs -f normogen-backend'"
fi
log_info "🎉 Deployment complete!"
echo ""
echo "View logs:"
echo " ssh ${REMOTE_HOST} 'docker compose -f ${REMOTE_DIR}/${DOCKER_COMPOSE_FILE} logs -f backend'"
echo ""
echo "View status:"
echo " ssh ${REMOTE_HOST} 'docker compose -f ${REMOTE_DIR}/${DOCKER_COMPOSE_FILE} ps'"
echo ""
echo "Restart services:"
echo " ssh ${REMOTE_HOST} 'docker compose -f ${REMOTE_DIR}/${DOCKER_COMPOSE_FILE} restart'"

View file

@ -30,7 +30,7 @@ curl -s --max-time 3 http://localhost:6500/health || echo "Local connection fail
echo "" echo ""
echo "7. Testing container connection..." echo "7. Testing container connection..."
docker exec normogen-backend-dev curl -s --max-time 3 http://localhost:8000/health || echo "Container connection failed" docker exec normogen-backend-dev curl -s --max-time 3 http://localhost:6500/health || echo "Container connection failed"
echo "" echo ""
echo "==========================================" echo "=========================================="

View file

@ -8,27 +8,35 @@ services:
pull_policy: build pull_policy: build
container_name: normogen-backend-dev container_name: normogen-backend-dev
ports: ports:
- '6500:8000' # host 6501 (dev) -> container 6500, distinct from prod's 6500.
- '6501:6500'
volumes: volumes:
- ./src:/app/src - ./src:/app/src
- startup-logs:/tmp - startup-logs:/tmp
environment: environment:
- APP_ENVIRONMENT=development
- RUST_LOG=debug - RUST_LOG=debug
- SERVER_PORT=8000
- SERVER_HOST=0.0.0.0
- MONGODB_URI=mongodb://mongodb:27017
- DATABASE_NAME=normogen_dev
- JWT_SECRET=dev-jwt-secret-key-minimum-32-chars
- RUST_LOG_STYLE=always - RUST_LOG_STYLE=always
- NORMOGEN_HOST=0.0.0.0
- NORMOGEN_PORT=6500
- MONGODB_URI=mongodb://mongodb:27017
- MONGODB_DATABASE=normogen_dev
- JWT_SECRET=dev-jwt-secret-key-minimum-32-chars
depends_on: depends_on:
mongodb: mongodb:
condition: service_healthy condition: service_healthy
networks: networks:
- normogen-network - normogen-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:6500/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
restart: unless-stopped restart: unless-stopped
mongodb: mongodb:
image: mongo:6.0 image: mongo:7
container_name: normogen-mongodb-dev container_name: normogen-mongodb-dev
ports: ports:
- '27017:27017' - '27017:27017'

View file

@ -1,5 +1,3 @@
version: '3.8'
services: services:
mongodb: mongodb:
image: mongo:7 image: mongo:7
@ -22,19 +20,23 @@ services:
container_name: normogen-backend container_name: normogen-backend
restart: unless-stopped restart: unless-stopped
ports: ports:
- "8000:8080" - "6500:6500"
environment: environment:
- DATABASE_URI=mongodb://mongodb:27017 # The app reads NORMOGEN_* / MONGODB_* / APP_ENVIRONMENT (config/mod.rs).
- DATABASE_NAME=normogen - APP_ENVIRONMENT=production
- JWT_SECRET=your-secret-key-change-in-production - NORMOGEN_HOST=0.0.0.0
- SERVER_HOST=0.0.0.0 - NORMOGEN_PORT=6500
- SERVER_PORT=8080 - MONGODB_URI=mongodb://mongodb:27017
- RUST_LOG=debug - MONGODB_DATABASE=normogen
# Set real, strong values in your prod .env; production boot refuses insecure defaults.
- JWT_SECRET=${JWT_SECRET:?JWT_SECRET must be set}
- ENCRYPTION_KEY=${ENCRYPTION_KEY:?ENCRYPTION_KEY must be set}
- RUST_LOG=info
depends_on: depends_on:
mongodb: mongodb:
condition: service_healthy condition: service_healthy
healthcheck: healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"] test: ["CMD", "curl", "-f", "http://localhost:6500/health"]
interval: 30s interval: 30s
timeout: 10s timeout: 10s
retries: 3 retries: 3

View file

@ -1,48 +0,0 @@
# Production Dockerfile (Multi-stage build)
# Stage 1: Build
FROM rust:1.93-slim AS builder
WORKDIR /app
# Install build dependencies
RUN apt-get update && apt-get install -y \
pkg-config \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*
# Copy Cargo files first for better caching
COPY Cargo.toml ./
# Create dummy main.rs for dependency caching
RUN mkdir src && echo 'fn main() {}' > src/main.rs
# Build dependencies (this layer will be cached)
RUN cargo build --release && rm -rf src
# Copy actual source code
COPY src ./src
# Build the actual application
RUN cargo build --release
# Stage 2: Runtime
FROM debian:bookworm-slim
WORKDIR /app
# Install runtime dependencies only
RUN apt-get update && apt-get install -y \
ca-certificates \
libssl3 \
&& rm -rf /var/lib/apt/lists/*
# Copy the binary from builder stage
COPY --from=builder /app/target/release/normogen-backend /app/normogen-backend
# Expose port
EXPOSE 8000
# Make the binary executable and run it
RUN chmod +x /app/normogen-backend
CMD ["/app/normogen-backend"]

View file

@ -1,40 +1,35 @@
# Development Dockerfile # Development image. Built by docker-compose.dev.yml.
# Uses Rust 1.93+ to support Edition 2024 dependencies # Debug build; the dev compose mounts ./src:/app/src for rapid rebuilds.
FROM rust:1.93-slim as builder FROM rust:latest AS builder
WORKDIR /app WORKDIR /app
# Install build dependencies
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
pkg-config \ pkg-config \
libssl-dev \ libssl-dev \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Copy Cargo files first for better caching # Cache dependency build via a dummy main.rs
COPY Cargo.toml ./ COPY Cargo.toml ./
# Create dummy main.rs for dependency caching
RUN mkdir src && echo 'fn main() {}' > src/main.rs RUN mkdir src && echo 'fn main() {}' > src/main.rs
# Build dependencies (this layer will be cached)
RUN cargo build && rm -rf src RUN cargo build && rm -rf src
# Copy actual source code # Copy actual source and build
COPY src ./src COPY src ./src
# Build the application
RUN cargo build RUN cargo build
# Runtime stage # Runtime stage — full Rust image so the dev compose can rebuild in-container.
FROM rust:1.93-slim # curl is required for the compose HEALTHCHECK to work.
FROM rust:latest
RUN apt-get update && apt-get install -y \
curl \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /app WORKDIR /app
# Copy the binary from builder
COPY --from=builder /app/target/debug/normogen-backend /app/normogen-backend COPY --from=builder /app/target/debug/normogen-backend /app/normogen-backend
# Expose port # The app listens on NORMOGEN_PORT (default 6500, set in compose/.env).
EXPOSE 8000 EXPOSE 6500
# Run the binary directly
CMD ["/app/normogen-backend"] CMD ["/app/normogen-backend"]

View file

@ -1,65 +0,0 @@
# Multi-stage build for smaller, more secure image
# Stage 1: Build
FROM rust:1.93-slim AS builder
WORKDIR /app
# Install build dependencies
RUN apt-get update && apt-get install -y \
pkg-config \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*
# Copy manifests first (better layer caching)
COPY Cargo.toml Cargo.lock ./
# Create dummy main.rs to cache dependencies
RUN mkdir src && \
echo "fn main() {}" > src/main.rs && \
cargo build --release && \
rm -rf src
# Copy actual source
COPY src ./src
# Build application
RUN cargo build --release
# Stage 2: Runtime
FROM debian:bookworm-slim
# Install runtime dependencies only
RUN apt-get update && apt-get install -y \
ca-certificates \
libssl3 \
curl \
&& rm -rf /var/lib/apt/lists/* \
&& apt-get clean
# Create non-root user
RUN useradd -m -u 1000 normogen && \
mkdir -p /app && \
chown -R normogen:normogen /app
WORKDIR /app
# Copy binary from builder
COPY --from=builder /app/target/release/normogen-backend /app/normogen-backend
# Set permissions
RUN chmod +x /app/normogen-backend && \
chown normogen:normogen /app/normogen-backend
# Switch to non-root user
USER normogen
# Expose port
EXPOSE 8000
# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
# Run with proper signal handling
ENTRYPOINT ["/app/normogen-backend"]
CMD []

View file

@ -1,43 +0,0 @@
# Fix for Rust Edition 2024 Docker Build Error
## Problem
The error occurs because:
1. Your Dockerfile uses `FROM rust:latest` which pulled `rust:1.83-alpine`
2. Several dependencies require Rust 1.85+ for Edition 2024 support:
- `time-core 0.1.8` requires Rust 1.88.0
- `getrandom 0.4.1` requires Rust 1.85.0
- `uuid 1.21.0` requires Rust 1.85.0
- `deranged 0.5.6` requires Rust 1.85.0
- `wasip2/wasip3` require Rust 1.87.0
## Root Cause
Rust Edition 2024 became stable in Rust 1.85.0 (released February 20, 2025).
Some of your transitive dependencies have updated to use Edition 2024,
which requires a newer Rust version than 1.83.
## Solutions
### ✅ RECOMMENDED: Update Rust Base Image
Change `FROM rust:latest` to `FROM rust:1.93` or newer.
**Pros:**
- Future-proof solution
- Gets latest Rust improvements and security fixes
- No dependency management overhead
- Standard practice (update base images regularly)
**Cons:**
- None (this is the correct approach)
### Alternative: Pin Dependency Versions (NOT RECOMMENDED)
Pin problematic dependencies to older versions that don't require Edition 2024.
This creates technical debt and should only be used if you have a specific
constraint preventing Rust version updates.
## Implementation
See the fixed Dockerfiles in this directory.

View file

@ -1,60 +0,0 @@
# MongoDB Health Check Fix
## Problem
The MongoDB container was failing health checks with the original configuration:
```yaml
healthcheck:
test: ['CMD', 'mongosh', '--eval', 'db.adminCommand.ping()']
start_period: 10s # Too short!
```
## Root Causes
1. **start_period too short**: 10s isn't enough for MongoDB to initialize, especially on first start
2. **Command format**: The healthcheck needs proper output handling
## Solution
Updated healthcheck in docker-compose.dev.yml:
```yaml
healthcheck:
test: |
mongosh --eval "db.adminCommand('ping').ok" --quiet
interval: 10s
timeout: 5s
retries: 5
start_period: 40s # Increased from 10s to 40s
```
## Changes Made
- ✅ Increased `start_period` from 10s to 40s (gives MongoDB time to initialize)
- ✅ Simplified the healthcheck command to use shell format
- ✅ Added `--quiet` flag to suppress verbose output
## How to Apply
On your server:
```bash
# Pull the latest changes
git pull origin main
# Stop and remove existing containers
docker compose -f docker-compose.dev.yml down -v
# Start fresh
docker compose -f docker-compose.dev.yml up -d
# Watch the logs
docker compose -f docker-compose.dev.yml logs -f mongodb
```
## Verify Health Check
```bash
# Check container health
docker ps --format "table {{.Names}} {{.Status}}"
# Check health status specifically
docker inspect normogen-mongodb-dev --format='{{.State.Health.Status}}'
```
Expected output: `healthy`

View file

@ -1,68 +0,0 @@
version: '3.8'
services:
mongodb:
image: mongo:6.0
container_name: normogen-mongodb
restart: unless-stopped
ports:
- "27017:27017"
environment:
MONGO_INITDB_DATABASE: normogen
volumes:
- mongodb_data:/data/db
- mongodb_config:/data/configdb
networks:
- normogen-network
healthcheck:
test: ["CMD", "mongosh", "--eval", "db.adminCommand('ping')"]
interval: 10s
timeout: 5s
retries: 5
start_period: 10s
backend:
build:
context: ..
dockerfile: docker/Dockerfile.improved
image: normogen-backend:latest
container_name: normogen-backend
restart: unless-stopped
ports:
- "8001:8000"
environment:
RUST_LOG: ${RUST_LOG:-info}
MONGODB_URI: mongodb://mongodb:27017
MONGODB_DATABASE: ${MONGODB_DATABASE:-normogen}
JWT_SECRET: ${JWT_SECRET}
SERVER_PORT: 8000
SERVER_HOST: 0.0.0.0
depends_on:
mongodb:
condition: service_healthy
networks:
- normogen-network
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 10s
deploy:
resources:
limits:
cpus: '1.0'
memory: 512M
reservations:
cpus: '0.25'
memory: 128M
volumes:
mongodb_data:
driver: local
mongodb_config:
driver: local
networks:
normogen-network:
driver: bridge

Binary file not shown.

View file

@ -147,7 +147,7 @@ impl Config {
server: ServerConfig { server: ServerConfig {
host: std::env::var("NORMOGEN_HOST").unwrap_or_else(|_| "0.0.0.0".to_string()), host: std::env::var("NORMOGEN_HOST").unwrap_or_else(|_| "0.0.0.0".to_string()),
port: std::env::var("NORMOGEN_PORT") port: std::env::var("NORMOGEN_PORT")
.unwrap_or_else(|_| "8080".to_string()) .unwrap_or_else(|_| "6500".to_string())
.parse()?, .parse()?,
}, },
database: DatabaseConfig { database: DatabaseConfig {

View file

@ -23,7 +23,7 @@ pub use mongodb_impl::MongoDb;
pub async fn create_database() -> Result<Database> { pub async fn create_database() -> Result<Database> {
let mongo_uri = env::var("MONGODB_URI").expect("MONGODB_URI must be set"); let mongo_uri = env::var("MONGODB_URI").expect("MONGODB_URI must be set");
let db_name = env::var("DATABASE_NAME").expect("DATABASE_NAME must be set"); let db_name = env::var("MONGODB_DATABASE").expect("MONGODB_DATABASE must be set");
let client = Client::with_uri_str(&mongo_uri).await?; let client = Client::with_uri_str(&mongo_uri).await?;
let database = client.database(&db_name); let database = client.database(&db_name);

View file

@ -3,7 +3,7 @@
# Phase 2.8 Test Suite # Phase 2.8 Test Suite
# Tests Pill Identification, Drug Interactions, and Reminder System # Tests Pill Identification, Drug Interactions, and Reminder System
API_URL="http://localhost:8080/api" API_URL="http://localhost:6500/api"
TEST_USER="test_phase28@example.com" TEST_USER="test_phase28@example.com"
TEST_PASSWORD="TestPassword123!" TEST_PASSWORD="TestPassword123!"

View file

@ -322,7 +322,7 @@ docker compose up -d
docker compose logs -f backend docker compose logs -f backend
# Check health # Check health
curl http://localhost:8000/health curl http://localhost:6500/health
``` ```
#### Production (Solaria) #### Production (Solaria)

View file

@ -83,19 +83,19 @@ docker-compose logs -f backend
### Base URL ### Base URL
``` ```
http://solaria:8000 http://solaria:6500
``` ```
### Public Endpoints (No Auth) ### Public Endpoints (No Auth)
#### Health Check #### Health Check
```bash ```bash
curl http://solaria:8000/health curl http://solaria:6500/health
``` ```
#### Register #### Register
```bash ```bash
curl -X POST http://solaria:8000/api/auth/register \ curl -X POST http://solaria:6500/api/auth/register \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d '{ -d '{
"email": "test@example.com", "email": "test@example.com",
@ -106,7 +106,7 @@ curl -X POST http://solaria:8000/api/auth/register \
#### Login #### Login
```bash ```bash
curl -X POST http://solaria:8000/api/auth/login \ curl -X POST http://solaria:6500/api/auth/login \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d '{ -d '{
"email": "test@example.com", "email": "test@example.com",
@ -116,7 +116,7 @@ curl -X POST http://solaria:8000/api/auth/login \
#### Set Recovery Phrase #### Set Recovery Phrase
```bash ```bash
curl -X POST http://solaria:8000/api/auth/set-recovery-phrase \ curl -X POST http://solaria:6500/api/auth/set-recovery-phrase \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d '{ -d '{
"email": "test@example.com", "email": "test@example.com",
@ -126,7 +126,7 @@ curl -X POST http://solaria:8000/api/auth/set-recovery-phrase \
#### Recover Password #### Recover Password
```bash ```bash
curl -X POST http://solaria:8000/api/auth/recover-password \ curl -X POST http://solaria:6500/api/auth/recover-password \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d '{ -d '{
"email": "test@example.com", "email": "test@example.com",
@ -139,13 +139,13 @@ curl -X POST http://solaria:8000/api/auth/recover-password \
#### Get Profile #### Get Profile
```bash ```bash
curl http://solaria:8000/api/users/me \ curl http://solaria:6500/api/users/me \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
``` ```
#### Update Profile #### Update Profile
```bash ```bash
curl -X PUT http://solaria:8000/api/users/me \ curl -X PUT http://solaria:6500/api/users/me \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{ -d '{
@ -155,13 +155,13 @@ curl -X PUT http://solaria:8000/api/users/me \
#### Get Settings #### Get Settings
```bash ```bash
curl http://solaria:8000/api/users/me/settings \ curl http://solaria:6500/api/users/me/settings \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
``` ```
#### Update Settings #### Update Settings
```bash ```bash
curl -X PUT http://solaria:8000/api/users/me/settings \ curl -X PUT http://solaria:6500/api/users/me/settings \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{ -d '{
@ -171,7 +171,7 @@ curl -X PUT http://solaria:8000/api/users/me/settings \
#### Change Password #### Change Password
```bash ```bash
curl -X POST http://solaria:8000/api/users/me/change-password \ curl -X POST http://solaria:6500/api/users/me/change-password \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{ -d '{
@ -182,7 +182,7 @@ curl -X POST http://solaria:8000/api/users/me/change-password \
#### Delete Account #### Delete Account
```bash ```bash
curl -X DELETE http://solaria:8000/api/users/me \ curl -X DELETE http://solaria:6500/api/users/me \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{ -d '{
"confirmation": "DELETE_ACCOUNT" "confirmation": "DELETE_ACCOUNT"
@ -191,7 +191,7 @@ curl -X DELETE http://solaria:8000/api/users/me \
#### Create Share #### Create Share
```bash ```bash
curl -X POST http://solaria:8000/api/shares \ curl -X POST http://solaria:6500/api/shares \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{ -d '{
@ -204,13 +204,13 @@ curl -X POST http://solaria:8000/api/shares \
#### List Shares #### List Shares
```bash ```bash
curl http://solaria:8000/api/shares \ curl http://solaria:6500/api/shares \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
``` ```
#### Update Share #### Update Share
```bash ```bash
curl -X PUT http://solaria:8000/api/shares/SHARE_ID \ curl -X PUT http://solaria:6500/api/shares/SHARE_ID \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{ -d '{
@ -220,13 +220,13 @@ curl -X PUT http://solaria:8000/api/shares/SHARE_ID \
#### Delete Share #### Delete Share
```bash ```bash
curl -X DELETE http://solaria:8000/api/shares/SHARE_ID \ curl -X DELETE http://solaria:6500/api/shares/SHARE_ID \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
``` ```
#### Check Permission #### Check Permission
```bash ```bash
curl -X POST http://solaria:8000/api/permissions/check \ curl -X POST http://solaria:6500/api/permissions/check \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{ -d '{
@ -237,19 +237,19 @@ curl -X POST http://solaria:8000/api/permissions/check \
#### Get Sessions (NEW) #### Get Sessions (NEW)
```bash ```bash
curl http://solaria:8000/api/sessions \ curl http://solaria:6500/api/sessions \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
``` ```
#### Revoke Session (NEW) #### Revoke Session (NEW)
```bash ```bash
curl -X DELETE http://solaria:8000/api/sessions/SESSION_ID \ curl -X DELETE http://solaria:6500/api/sessions/SESSION_ID \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
``` ```
#### Revoke All Sessions (NEW) #### Revoke All Sessions (NEW)
```bash ```bash
curl -X DELETE http://solaria:8000/api/sessions/all \ curl -X DELETE http://solaria:6500/api/sessions/all \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
``` ```
@ -309,8 +309,9 @@ JWT_SECRET=your-super-secret-jwt-key-min-32-chars
MONGODB_URI=mongodb://mongodb:27017 MONGODB_URI=mongodb://mongodb:27017
MONGODB_DATABASE=normogen MONGODB_DATABASE=normogen
RUST_LOG=info RUST_LOG=info
SERVER_PORT=8000 NORMOGEN_PORT=6500
SERVER_HOST=0.0.0.0 NORMOGEN_HOST=0.0.0.0
APP_ENVIRONMENT=production
``` ```
## Security Features (Phase 2.6) ## Security Features (Phase 2.6)

View file

@ -34,16 +34,17 @@ docker compose up -d
### Environment Configuration ### Environment Configuration
Required environment variables: Required environment variables:
- `DATABASE_URI` - MongoDB connection string - `MONGODB_URI` - MongoDB connection string
- `DATABASE_NAME` - Database name - `MONGODB_DATABASE` - Database name
- `JWT_SECRET` - JWT signing secret (min 32 chars) - `JWT_SECRET` - JWT signing secret (min 32 chars)
- `SERVER_HOST` - Server host (default: 0.0.0.0) - `NORMOGEN_HOST` - Server host (default: 0.0.0.0)
- `SERVER_PORT` - Server port (default: 8080) - `NORMOGEN_PORT` - Server port (default: 6500)
- `APP_ENVIRONMENT` - `development` (default) or `production`
- `RUST_LOG` - Log level (debug/info/warn) - `RUST_LOG` - Log level (debug/info/warn)
### Health Check ### Health Check
```bash ```bash
curl http://localhost:8000/health curl http://localhost:6500/health
``` ```
## 🌐 Deployment Environments ## 🌐 Deployment Environments

12
docs/deployment/deploy-and-test-solaria.sh Executable file → Normal file
View file

@ -25,12 +25,12 @@ if pgrep -f "normogen-backend" > /dev/null; then
sleep 2 sleep 2
fi fi
# Set environment # Set environment (the app reads NORMOGEN_* / MONGODB_* / APP_ENVIRONMENT)
export DATABASE_URI="mongodb://localhost:27017" export MONGODB_URI="mongodb://localhost:27017"
export DATABASE_NAME="normogen" export MONGODB_DATABASE="normogen"
export JWT_SECRET="test-secret-key" export JWT_SECRET="test-secret-key"
export SERVER_HOST="0.0.0.0" export NORMOGEN_HOST="0.0.0.0"
export SERVER_PORT="8080" export NORMOGEN_PORT="6500"
export RUST_LOG="debug" export RUST_LOG="debug"
# Build # Build
@ -54,7 +54,7 @@ fi
# Health check # Health check
echo "" echo ""
echo "Health check..." echo "Health check..."
curl -s http://localhost:8080/health curl -s http://localhost:6500/health
ENDSSH ENDSSH

10
docs/deployment/deploy-local-build.sh Executable file → Normal file
View file

@ -46,11 +46,11 @@ ENDSSH
echo "" echo ""
echo "Step 5: Starting backend on Solaria..." echo "Step 5: Starting backend on Solaria..."
ssh alvaro@solaria bash << 'ENDSSH' ssh alvaro@solaria bash << 'ENDSSH'
export DATABASE_URI="mongodb://localhost:27017" export MONGODB_URI="mongodb://localhost:27017"
export DATABASE_NAME="normogen" export MONGODB_DATABASE="normogen"
export JWT_SECRET="production-secret-key" export JWT_SECRET="production-secret-key"
export SERVER_HOST="0.0.0.0" export NORMOGEN_HOST="0.0.0.0"
export SERVER_PORT="8080" export NORMOGEN_PORT="6500"
export RUST_LOG="normogen_backend=debug,tower_http=debug,axum=debug" export RUST_LOG="normogen_backend=debug,tower_http=debug,axum=debug"
nohup ~/normogen-backend > ~/normogen-backend.log 2>&1 & nohup ~/normogen-backend > ~/normogen-backend.log 2>&1 &
@ -68,7 +68,7 @@ fi
echo "" echo ""
echo "Testing health endpoint..." echo "Testing health endpoint..."
sleep 2 sleep 2
curl -s http://localhost:8080/health curl -s http://localhost:6500/health
echo "" echo ""
ENDSSH ENDSSH

View file

@ -61,6 +61,6 @@ echo "========================================="
echo "Deployment complete!" echo "Deployment complete!"
echo "=========================================" echo "========================================="
echo "" echo ""
echo "API is available at: http://solaria:8000" echo "API is available at: http://solaria:6500"
echo "Health check: http://solaria:8000/health" echo "Health check: http://solaria:6500/health"
echo "" echo ""

View file

@ -108,7 +108,7 @@ Response (with disclaimer)
```bash ```bash
# Check interactions # Check interactions
curl -X POST http://localhost:8080/api/interactions/check \ curl -X POST http://localhost:6500/api/interactions/check \
-H "Authorization: Bearer $TOKEN" \ -H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \ -H "Content-Type: application/json" \
-d '{ -d '{

View file

@ -282,7 +282,7 @@ pub struct Medication {
**Example: Parent managing child's medication**: **Example: Parent managing child's medication**:
```bash ```bash
# Create medication for child's profile # Create medication for child's profile
curl -X POST http://localhost:8000/api/medications \ curl -X POST http://localhost:6500/api/medications \
-H "Authorization: Bearer <token>" \ -H "Authorization: Bearer <token>" \
-d '{ -d '{
"name": "Amoxicillin", "name": "Amoxicillin",
@ -292,12 +292,12 @@ curl -X POST http://localhost:8000/api/medications \
}' }'
# Log dose for child # Log dose for child
curl -X POST http://localhost:8000/api/medications/{id}/log \ curl -X POST http://localhost:6500/api/medications/{id}/log \
-H "Authorization: Bearer <token>" \ -H "Authorization: Bearer <token>" \
-d '{"profile_id": "child_profile_123"}' -d '{"profile_id": "child_profile_123"}'
# View child's adherence # View child's adherence
curl http://localhost:8000/api/medications/{id}/adherence?profile_id=child_profile_123 \ curl http://localhost:6500/api/medications/{id}/adherence?profile_id=child_profile_123 \
-H "Authorization: Bearer <token>" -H "Authorization: Bearer <token>"
``` ```

View file

@ -19,11 +19,11 @@ cd backend
docker compose up -d docker compose up -d
# Check health # Check health
curl http://localhost:8000/health curl http://localhost:6500/health
``` ```
#### 2. Access the API #### 2. Access the API
The backend API will be available at `http://localhost:8000` The backend API will be available at `http://localhost:6500`
### For Developers ### For Developers

View file

@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
set -e set -e
BASE_URL="http://solaria:8000/api" BASE_URL="http://solaria:6500/api"
EMAIL="test@normogen.com" EMAIL="test@normogen.com"
PASSWORD="TestPassword123!" PASSWORD="TestPassword123!"
NEW_PASSWORD="NewPassword456!" NEW_PASSWORD="NewPassword456!"