normogen/docs/AI_AGENT_GUIDE.md
goose fff1ed2e6d
Some checks failed
Lint and Build / format (pull_request) Successful in 1m44s
Lint and Build / clippy (pull_request) Successful in 1m48s
Lint and Build / build (pull_request) Successful in 6m40s
Lint and Build / test (pull_request) Failing after 1s
fix(backend): P2 config & Docker consistency
Resolve the operational/config sprawl (#10-#14 from the review): the app read
NORMOGEN_*/MONGODB_* env vars but every env/compose file set SERVER_*/DATABASE_*,
the ports were all over the place (8080/8000/6500/6800), there were 5
inconsistent Dockerfiles (rust:1.82 vs rust:1.93, missing curl), and an 18 MB
binary was committed.

Env-var names — standardize on what the code reads:
* config/mod.rs: NORMOGEN_PORT default 8080 -> 6500 (avoid the over-common
  8000/8080).
* db/mod.rs: create_database() now reads MONGODB_DATABASE (was DATABASE_NAME).
* .env.example, defaults.env, docker-compose.yml, docker-compose.dev.yml,
  DEPLOYMENT_GUIDE.md, deployment/README.md, deploy-and-test-solaria.sh,
  deploy-local-build.sh: use NORMOGEN_HOST/NORMOGEN_PORT/MONGODB_URI/
  MONGODB_DATABASE/APP_ENVIRONMENT; drop the dead SERVER_*/DATABASE_URI/
  DATABASE_NAME names.

Ports — canonical container port 6500 everywhere:
* Both Dockerfiles EXPOSE 6500; prod compose maps 6500:6500, dev 6501:6500.
* Bulk-replaced the long tail of solaria:8000/localhost:8000/localhost:8080 in
  docs and test scripts -> 6500.

Dockerfiles — 2 canonical, rust:latest, curl + healthcheck:
* backend/Dockerfile (prod): rust:latest builder, debian runtime now installs
  curl (so the compose HEALTHCHECK actually works), EXPOSE 6500.
* backend/docker/Dockerfile.dev (dev): rust:latest both stages, EXPOSE 6500.
* Deleted 3 redundant Dockerfiles (Dockerfile.improved x2, docker/Dockerfile).
* Deleted the committed 18 MB binary backend/docker/normogen-backend.
* Deleted 2 stray fix-notes in backend/docker/.

Compose:
* docker-compose.yml: correct env names, 6500:6500, APP_ENVIRONMENT=production,
  JWT_SECRET/ENCRYPTION_KEY required via compose interpolation, dropped the
  obsolete top-level version: key.
* docker-compose.dev.yml: correct env names, 6501:6500, mongo:7 (was 6.0),
  added a working backend healthcheck.
* Deleted docker/docker-compose.improved.yml + backend/deploy-to-solaria-improved.sh
  (built around the now-deleted 'improved' Docker files).

Verified: cargo fmt --check clean, build + clippy --all-targets clean, 18 unit
tests pass; grep confirms no SERVER_*/DATABASE_* env names and no rust:1.x tags
remain outside docs/archive and docs/adr (historical).
2026-06-27 19:54:32 -03:00

16 KiB

AI Agent Guide - Normogen Repository

Last Updated: 2026-03-09
Project: Normogen - Open-source health data platform
Repository Type: Monorepo (Rust backend + React frontend + Mobile placeholder)


🤖 Quick Start for AI Agents

1-minute Overview

  • Backend: Rust (Axum web framework, MongoDB database)
  • Frontend: React (TypeScript, Material-UI, Zustand state)
  • Mobile: Placeholder (not yet implemented)
  • Documentation: Organized in docs/ directory
  • Current Phase: 2.8 (Drug Interactions & Advanced Features)

Essential Commands

# Backend
cd backend && cargo build              # Build backend
cd backend && cargo test               # Run tests
cd backend && cargo clippy             # Lint
cd backend && docker compose up -d     # Run with Docker

# Frontend
cd web/normogen-web && npm install     # Install dependencies
cd web/normogen-web && npm start       # Dev server
cd web/normogen-web && npm test        # Run tests

# Testing
./docs/testing/quick-test.sh           # Quick smoke tests
./docs/testing/test-api-endpoints.sh   # API tests

📁 Repository Structure

normogen/
├── backend/                 # Rust backend (Axum + MongoDB)
│   ├── src/
│   │   ├── handlers/       # API route handlers (auth, users, medications, etc.)
│   │   ├── models/         # Data models & repositories
│   │   ├── auth/           # JWT authentication
│   │   ├── security/       # Rate limiting, audit logging, session management
│   │   ├── middleware/     # Custom middleware (JWT auth, rate limiting)
│   │   ├── services/       # Business logic (OpenFDA, interactions)
│   │   ├── config/         # Configuration management
│   │   ├── db/             # MongoDB implementation
│   │   └── main.rs         # Entry point, router setup
│   ├── tests/              # Integration tests
│   ├── Cargo.toml          # Rust dependencies
│   └── docker-compose.yml  # Docker deployment
│
├── web/                     # React frontend
│   └── normogen-web/
│       ├── src/
│       │   ├── pages/      # Page components (Login, Register, etc.)
│       │   ├── components/ # Reusable components
│       │   ├── services/   # API service layer (axios)
│       │   ├── store/      # Zustand state management
│       │   └── types/      # TypeScript type definitions
│       └── package.json
│
├── mobile/                  # Mobile app (placeholder)
├── shared/                  # Shared code (placeholder)
├── thoughts/                # Development notes
└── docs/                    # Organized documentation
    ├── product/            # Product definition, roadmap
    ├── implementation/     # Phase plans, specs
    ├── testing/            # Test scripts & results
    ├── deployment/         # Deployment guides
    └── development/        # Git workflow, CI/CD

🔑 Key Concepts

Backend Architecture

Technology Stack

  • Language: Rust (edition 2021)
  • Web Framework: Axum 0.7 (async, tower-based)
  • Database: MongoDB 7.0
  • Authentication: JWT (jsonwebtoken 9)
    • Access tokens: 15 minute expiry
    • Refresh tokens: 30 day expiry
    • PBKDF2 password hashing (100K iterations)
  • Security: Rate limiting (tower-governor), audit logging

Project Structure Pattern

The backend follows a modular architecture:

// Entry point: src/main.rs
mod config;        // Configuration from environment
mod db;            // Database trait + MongoDB impl
mod models;        // Data models with repositories
mod auth;          // JWT service
mod security;      // Security features (audit, sessions, lockout)
mod handlers;      // HTTP request handlers
mod middleware;    // Middleware (JWT, rate limiting)
mod services;      // Business logic (OpenFDA, interactions)

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Load config → Connect DB → Initialize services → Build router
}

Handler Pattern

All API handlers follow this pattern:

// In src/handlers/
pub async fn handler_name(
    State(state): State<AppState>,
    Json(req): Json<RequestType>,
) -> Result<Json<ResponseType>, ApiError> {
    // 1. Validate request
    // 2. Call service/repository
    // 3. Return response
}

Authentication Flow

  1. User registers/logs in → JWT tokens generated
  2. Access token in Authorization header → middleware::jwt_auth_middleware validates
  3. User ID extracted and available in handlers
  4. Protected routes require valid JWT

Database Pattern

  • Repository pattern: Each model has a Repository trait
  • MongoDB implementation: db::MongoDb wraps mongodb::Client
  • Collections accessed via Database from MongoDB

Frontend Architecture

Technology Stack

  • Framework: React 19.2.4 + TypeScript 4.9.5
  • UI Library: Material-UI (MUI) 7.3.9
  • State Management: Zustand 5.0.11
  • HTTP Client: Axios 1.13.6
  • Routing: React Router DOM 7.13.1

Project Structure

src/
├── pages/          # Route components (LoginPage, RegisterPage, etc.)
├── components/     # Reusable components (ProtectedRoute, etc.)
├── services/       # API service (axios instance with interceptors)
├── store/          # Zustand stores (auth, user, etc.)
├── types/          # TypeScript interfaces (API types)
└── App.tsx         # Main app with routing

State Management

  • Zustand stores in src/store/
  • Auth store: JWT tokens, user info
  • API client: Axios instance with auth header injection

🚀 Common Workflows

Adding a New API Endpoint

Backend (Rust)

# 1. Add model to src/models/mod.rs
# 2. Create repository methods in src/models/your_model.rs
# 3. Add handler to src/handlers/your_handler.rs
# 4. Register route in src/main.rs
# 5. Add tests to tests/

Example:

// src/models/new_feature.rs
use mongodb::{Collection, Database};
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct NewFeature {
    pub id: String,
    pub name: String,
}

pub struct NewFeatureRepository {
    collection: Collection<NewFeature>,
}

impl NewFeatureRepository {
    pub fn new(db: &Database) -> Self {
        Self {
            collection: db.collection("new_features"),
        }
    }
    
    pub async fn create(&self, feature: &NewFeature) -> Result<()> {
        self.collection.insert_one(feature).await?;
        Ok(())
    }
}

// src/handlers/new_feature.rs
use axum::{Json, State};
use crate::models::new_feature::{NewFeature, NewFeatureRepository};

pub async fn create_new_feature(
    State(state): State<AppState>,
    Json(req): Json<NewFeature>,
) -> Result<Json<NewFeature>, ApiError> {
    let repo = NewFeatureRepository::new(&state.db.get_database());
    repo.create(&req).await?;
    Ok(Json(req))
}

// src/main.rs
.route("/api/new-features", post(handlers::create_new_feature))

Frontend (React/TypeScript)

# 1. Add types to src/types/api.ts
# 2. Add API service to src/services/api.ts
# 3. Create Zustand store in src/store/useStore.ts
# 4. Create page/component in src/pages/ or src/components/

Example:

// src/types/api.ts
export interface NewFeature {
  id: string;
  name: string;
}

// src/services/api.ts
export const newFeatureApi = {
  create: (data: NewFeature) => 
    api.post('/api/new-features', data),
  getAll: () => 
    api.get('/api/new-features'),
};

// src/store/useStore.ts
import { create } from 'zustand';

interface NewFeatureStore {
  features: NewFeature[];
  fetchFeatures: () => Promise<void>;
}

export const useNewFeatureStore = create<NewFeatureStore>((set) => ({
  features: [],
  fetchFeatures: async () => {
    const response = await newFeatureApi.getAll();
    set({ features: response.data });
  },
}));

// src/pages/NewFeaturePage.tsx
import { useNewFeatureStore } from '../store/useStore';

export const NewFeaturePage = () => {
  const { features, fetchFeatures } = useNewFeatureStore();
  
  useEffect(() => { fetchFeatures(); }, []);
  
  return <div>{/* UI here */}</div>;
};

Running Tests

Backend Tests

# Unit tests
cd backend && cargo test

# Integration tests
cd backend && cargo test --test '*'

# Specific test
cd backend && cargo test test_name

# With output
cd backend && cargo test -- --nocapture

Frontend Tests

cd web/normogen-web && npm test

# Coverage
cd web/normogen-web && npm test -- --coverage

API Endpoint Tests

# Quick smoke test
./docs/testing/quick-test.sh

# Full API test suite
./docs/testing/test-api-endpoints.sh

# Medication-specific tests
./docs/testing/test-medication-api.sh

Deployment

Local Development

cd backend
docker compose up -d

# Check logs
docker compose logs -f backend

# Check health
curl http://localhost:6500/health

Production (Solaria)

# Use deployment script
./docs/deployment/deploy-to-solaria.sh

# Manual deployment
cd backend
docker compose -f docker-compose.prod.yml up -d

🔒 Security Guidelines

Authentication

  • All protected routes require JWT in Authorization: Bearer <token> header
  • Access tokens expire in 15 minutes
  • Refresh tokens expire in 30 days
  • Tokens are rotated on refresh

Rate Limiting

  • General rate limiting applied to all routes
  • Configured in middleware::general_rate_limit_middleware
  • Account lockout after 5 failed login attempts (15min base, max 24hr)

Password Security

  • PBKDF2 with 100,000 iterations
  • Passwords never logged or returned in API responses
  • Zero-knowledge recovery phrases

Data Validation

  • Request validation using validator crate
  • Input sanitization in handlers
  • MongoDB uses BSON type system

📊 Current Implementation Status

Completed Features

  • JWT authentication (login, register, logout, refresh)
  • User management (profile, settings, password change)
  • Permission-based access control (Read, Write, Admin)
  • Share management (share resources with permissions)
  • Security hardening (rate limiting, audit logging, session management)
  • Medication management (CRUD, dose logging, adherence tracking)
  • Health statistics tracking (weight, BP, trends)
  • Lab results storage
  • OpenFDA integration for drug data

Implemented

  • Drug interaction checking (Phase 2.8) — /api/interactions/check, /check-new

In Progress / Not Started 🚧

  • Automated reminder system (Phase 2.8 stretch)
  • Frontend integration with backend (Phase 3)

Planned 📋

  • Medication refill tracking
  • Advanced health analytics
  • Healthcare data export (FHIR, HL7)
  • Caregiver access
  • Mobile app

🛠️ Development Guidelines

Code Style

Rust (Backend)

  • Use cargo fmt for formatting
  • Use cargo clippy for linting
  • Follow Rust naming conventions
  • Use Result<_, ApiError> for error handling
  • Document public APIs with rustdoc comments

TypeScript (Frontend)

  • Use functional components with hooks
  • Prefer TypeScript interfaces over types
  • Use Material-UI components
  • Follow React best practices
  • Use Zustand for state management

Commit Guidelines

  • Use conventional commits: feat(scope): description
  • Examples:
    • feat(backend): implement drug interaction checking
    • fix(medication): resolve adherence calculation bug
    • docs(readme): update quick start guide
    • test(auth): add refresh token rotation tests

Testing Guidelines

  • Write tests for new features
  • Test edge cases (empty inputs, null values, etc.)
  • Use descriptive test names
  • Mock external dependencies (OpenFDA API)
  • Test both success and error paths

📚 Documentation Navigation

Quick Reference

For Specific Tasks

Task Documentation
Add new API endpoint Implementation Guide + code examples above
Deploy to production Deployment Guide
Run tests Testing Guide
Understand architecture Product README
Check current status STATUS.md
Review phase progress Implementation README

🤖 AI Agent Specific Tips

Before Making Changes

  1. Read the context: Check STATUS.md and Implementation README
  2. Understand the phase: Know which phase is active (currently 2.8)
  3. Check existing code: Look at similar implementations in backend/src/
  4. Review tests: Check backend/tests/ for test patterns

When Implementing Features

  1. Follow patterns: Use existing code as templates (see examples above)
  2. Add tests: Write tests in backend/tests/ or inline with #[cfg(test)]
  3. Update documentation: Add/update docs in docs/implementation/
  4. Test thoroughly: Run cargo test, cargo clippy, and integration tests

When Debugging

  1. Check logs: docker compose logs -f backend
  2. Test API: Use scripts in docs/testing/
  3. Verify MongoDB: mongosh to check data
  4. Check recent changes: git log --oneline -10

Common Pitfalls to Avoid

  1. Don't hardcode values - Use environment variables (see backend/src/config/mod.rs)
  2. Don't skip tests - Always run tests before committing
  3. Don't forget auth - Protected routes need JWT middleware
  4. Don't ignore errors - Use ? operator and proper error handling
  5. Don't break existing APIs - Check for existing endpoints before adding new ones

File Locations Quick Reference

  • Add API handler: backend/src/handlers/
  • Add model: backend/src/models/
  • Add middleware: backend/src/middleware/
  • Add service: backend/src/services/
  • Add tests: backend/tests/
  • Add config: backend/src/config/mod.rs
  • Add frontend page: web/normogen-web/src/pages/
  • Add frontend component: web/normogen-web/src/components/
  • Add API service: web/normogen-web/src/services/api.ts
  • Add types: web/normogen-web/src/types/api.ts

📞 Getting Help

Internal Resources

External Resources


🔄 Version Information

Current Versions:

  • Rust: rustc 1.90.0 (1159e78c4 2025-09-14)

rustc 1.90.0 (1159e78c4 2025-09-14)

  • Node: v20.20.0

v20.20.0

  • Docker: Docker version 29.2.1, build a5c7197

Docker version 29.2.1, build a5c7197

Repository: origin ssh://git@gitea.soliverez.com.ar/alvaro/normogen.git (fetch)

origin ssh://git@gitea.soliverez.com.ar/alvaro/normogen.git (fetch)

Branch: git branch --show-current


Checklist for AI Agents

Before starting work, ensure you:

  • Read STATUS.md for current progress
  • Reviewed Implementation README for phase context
  • Understand the architecture (backend/frontend structure)
  • Know which phase is active (currently 2.8)
  • Have reviewed similar existing code
  • Understand testing requirements

During work:

  • Follow existing code patterns
  • Write/update tests
  • Run cargo test and cargo clippy
  • Document changes in docs/implementation/
  • Update relevant STATUS files

Before completing:

  • All tests pass
  • Code is formatted (cargo fmt)
  • No clippy warnings
  • Documentation updated
  • Commit message follows conventions

This guide is maintained in: docs/AI_AGENT_GUIDE.md

Last updated: 2026-03-09
Maintained by: Project maintainers
For questions: Consult project documentation or create an issue