# ROA2WEB Ultrathin Monolith Architecture **Version:** 1.0.0 **Last Updated:** 2025-12-29 **Status:** ✅ Active --- ## 🎯 Overview ROA2WEB uses an **ultrathin monolith** architecture - a single unified backend and frontend application with modular organization. This architecture provides the simplicity of a monolith with the organizational benefits of microservices. ### Key Characteristics - **Single Backend Process**: One FastAPI application serving all modules - **Single Frontend Build**: One Vue.js SPA with lazy-loaded modules - **Modular Organization**: Business logic separated into distinct modules - **Shared Resources**: Database pools, auth, cache shared across modules - **Independent Modules**: Each module can be developed and tested independently --- ## 🏗️ Architecture Diagram ``` ┌─────────────────────────────────────────────────────────────────────────────┐ │ 🌐 CLIENT BROWSER │ └────────────────────────────────┬────────────────────────────────────────────┘ │ HTTP/HTTPS Requests ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ 📦 UNIFIED VUE.JS FRONTEND │ │ Single-page application (SPA) served from /dist │ │ Port: 3000 (dev) / 80,443 (production) │ │ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ Frontend Modules (Lazy Loaded) │ │ │ │ │ │ │ │ • src/modules/reports/ - Reports module UI │ │ │ │ • src/modules/data-entry/ - Data entry module UI │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ Shared Frontend Components │ │ │ │ │ │ │ │ • src/shared/components/ - Reusable Vue components │ │ │ │ • src/shared/stores/ - Pinia stores │ │ │ │ • src/assets/css/ - Global CSS system │ │ │ │ • shared/frontend/ - Login, auth components │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ └────────────────────────────────┬────────────────────────────────────────────┘ │ API Calls (Axios) │ Authorization: Bearer ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ 🚀 UNIFIED FASTAPI BACKEND │ │ Single Python process running all modules │ │ Port: 8000 (dev) / 8001 (production) │ │ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 🛡️ Global Middleware Layer │ │ │ │ │ │ │ │ • CORSMiddleware - CORS handling │ │ │ │ • AuthenticationMiddleware - JWT validation & user injection │ │ │ │ • Rate Limiting - 5 req/5 min per IP │ │ │ │ • Security Headers - XSS, CSP, Frame protection │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 📊 Backend Modules (backend/modules/) │ │ │ │ │ │ │ │ reports/ │ │ │ │ ├── routers/ - API endpoints │ │ │ │ ├── services/ - Business logic with caching │ │ │ │ ├── models/ - Pydantic models │ │ │ │ └── cache/ - L1+L2 cache implementation │ │ │ │ │ │ │ │ data_entry/ │ │ │ │ ├── routers/ - API endpoints │ │ │ │ ├── services/ - Business logic │ │ │ │ ├── models/ - SQLModel ORM models │ │ │ │ └── db/ - SQLite database │ │ │ │ │ │ │ │ telegram/ │ │ │ │ ├── bot/ - Telegram bot handlers │ │ │ │ ├── api/ - Internal API for bot │ │ │ │ └── db/ - Bot session management │ │ │ │ │ │ │ │ data/ │ │ │ │ └── telegram_bot.db - Telegram bot SQLite database │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────────┐ │ │ │ 🔧 Shared Backend Components (shared/) │ │ │ │ │ │ │ │ database/ │ │ │ │ └── oracle_pool.py - Singleton Oracle connection pool │ │ │ │ │ │ │ │ auth/ │ │ │ │ ├── middleware.py - JWT authentication middleware │ │ │ │ ├── jwt_handler.py - Token creation/validation │ │ │ │ └── models.py - Auth data models │ │ │ │ │ │ │ └─────────────────────────────────────────────────────────────────────┘ │ └────────────────────────────────┬────────────────────────────────────────────┘ │ Database Queries │ (Oracle + SQLite) ▼ ┌─────────────────────────────────────────────────────────────────────────────┐ │ 🗄️ DATABASE LAYER │ │ │ │ ┌─────────────────────────┐ ┌─────────────────────────┐ │ │ │ Oracle Database │ │ SQLite Databases │ │ │ │ (via SSH Tunnel) │ │ (Local Files) │ │ │ │ │ │ │ │ │ │ • CONTAFIN_ORACLE │ │ • data_entry.db │ │ │ │ • Financial schemas │ │ • telegram_bot.db │ │ │ │ • User management │ │ • cache.db │ │ │ │ │ │ │ │ │ │ Port: 1521 (remote) │ │ Path: backend/modules/ │ │ │ │ 1526 (tunnel) │ │ /data/ │ │ │ │ │ │ │ │ │ └─────────────────────────┘ └─────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────────┘ ``` --- ## 📁 Directory Structure ### Backend Structure ``` backend/ ├── main.py # FastAPI app entry point ├── config.py # Centralized configuration ├── .env # Environment variables ├── .env.dev # Development environment ├── .env.test # Test environment ├── .env.prod # Production environment │ └── modules/ # Business logic modules ├── __init__.py │ ├── reports/ # Reports module (Oracle read-only) │ ├── __init__.py │ ├── routers/ # API endpoints │ │ ├── dashboard.py │ │ ├── invoices.py │ │ └── treasury.py │ ├── services/ # Business logic │ │ ├── dashboard_service.py │ │ └── invoice_service.py │ ├── models/ # Pydantic models │ ├── schemas/ # Response schemas │ └── cache/ # Cache implementation │ ├── decorators.py # @cached decorator │ └── manager.py # L1+L2 cache manager │ ├── data_entry/ # Data entry module (SQLite + workflow) │ ├── __init__.py │ ├── routers/ # API endpoints │ │ ├── receipts.py │ │ └── entries.py │ ├── services/ # Business logic │ ├── models/ # SQLModel ORM models │ │ ├── receipt.py │ │ ├── attachment.py │ │ └── accounting_entry.py │ ├── db/ # Database │ │ ├── session.py # SQLite session │ │ └── migrations/ # Alembic migrations │ └── utils/ # Helper functions │ ├── telegram/ # Telegram bot module │ ├── __init__.py │ ├── bot/ # Bot implementation │ │ ├── handlers.py # Command handlers │ │ ├── helpers.py # Helper functions │ │ └── formatters.py # Message formatters │ ├── api/ # Internal API │ │ └── auth.py # Auth code management │ ├── db/ # Bot database │ │ └── session.py # Session management │ └── bot_main.py # Bot entry point │ └── data/ # Shared data └── telegram_bot.db # Telegram bot database ``` ### Frontend Structure ``` src/ ├── main.js # App entry point ├── App.vue # Root component │ ├── modules/ # Feature modules │ ├── reports/ # Reports module │ │ ├── views/ # Page components │ │ │ ├── DashboardView.vue │ │ │ ├── InvoicesView.vue │ │ │ └── TreasuryView.vue │ │ ├── components/ # Module-specific components │ │ ├── stores/ # Module-specific Pinia stores │ │ │ ├── dashboard.js │ │ │ └── invoices.js │ │ ├── services/ # API client │ │ │ └── api.js │ │ └── utils/ # Helpers │ │ │ └── data-entry/ # Data entry module │ ├── views/ # Page components │ │ ├── ReceiptsView.vue │ │ └── EntriesView.vue │ ├── components/ # Module-specific components │ ├── stores/ # Module-specific Pinia stores │ │ └── receipts.js │ └── services/ # API client │ └── api.js │ ├── shared/ # Shared components │ ├── components/ # Reusable Vue components │ │ ├── ErrorBoundary.vue │ │ ├── CompanySelector.vue │ │ └── PeriodSelector.vue │ └── stores/ # Shared Pinia stores │ ├── auth.js │ ├── companies.js │ └── accountingPeriod.js │ ├── router/ # Vue Router │ ├── index.js # Main router │ ├── reports.js # Reports routes │ └── data-entry.js # Data entry routes │ ├── assets/ # Global assets │ ├── css/ # Global CSS system │ │ ├── core/ # Design tokens │ │ ├── components/ # Component styles │ │ ├── patterns/ # UI patterns │ │ ├── layout/ # Layout styles │ │ ├── utilities/ # Utility classes │ │ └── vendor/ # PrimeVue overrides │ └── images/ # Images │ └── views/ # Global views └── LoginView.vue # Login page ``` --- ## 🔄 Request Flow ### 1. User Authentication Flow ``` User Login Request ↓ Frontend (LoginView.vue) ↓ POST /api/auth/login Backend (main.py) ↓ AuthenticationMiddleware (excluded for /login) ↓ Auth Router (/api/auth/login) ↓ Oracle Database (pack_drepturi.verificautilizator) ↓ JWT Token Generation ↓ Response with access_token + refresh_token ↓ Frontend stores token in localStorage ↓ Subsequent requests include: Authorization: Bearer ``` ### 2. Reports Data Flow (with Cache) ``` User Request (Dashboard data) ↓ Frontend (DashboardView.vue) ↓ GET /api/reports/dashboard Backend Middleware ├─ CORS check ✓ ├─ JWT validation ✓ └─ User injection into request.state ↓ Reports Router (/api/reports/dashboard) ↓ DashboardService.get_dashboard_data() ↓ @cached decorator checks cache ├─ L1 Cache (Memory) HIT? → Return cached data ├─ L2 Cache (SQLite) HIT? → Store in L1, return data └─ MISS → Query Oracle ↓ Oracle Database (via connection pool) ↓ Process and cache result (L1 + L2) ↓ Return data ↓ Response with cache metadata headers ↓ Frontend updates Pinia store ↓ Vue component reactively updates UI ``` ### 3. Data Entry Flow (with Workflow) ``` User Creates Receipt ↓ Frontend (ReceiptsView.vue) ↓ POST /api/data-entry/receipts Backend Middleware (JWT validation) ↓ Data Entry Router ↓ ReceiptService.create_receipt() ↓ SQLModel ORM ↓ SQLite Database (data_entry.db) ├─ Insert Receipt (status: DRAFT) ├─ Insert Attachments └─ Generate AccountingEntries ↓ Response with receipt ID ↓ Frontend updates Pinia store ↓ UI shows new receipt in DRAFT state ↓ User submits for approval ↓ POST /api/data-entry/receipts/{id}/submit Backend updates status: DRAFT → PENDING ↓ Workflow continues (PENDING → APPROVED/REJECTED) ``` --- ## 🚀 Module Independence ### Benefits of Modular Monolith 1. **Development**: - Each module can be developed independently - Clear boundaries between features - Easy to understand and navigate 2. **Testing**: - Modules can be tested in isolation - Shared components tested once - Integration tests verify module interactions 3. **Deployment**: - Single deployment process - No service coordination complexity - Atomic updates (all or nothing) 4. **Performance**: - No network latency between modules - Shared connection pools - Efficient resource utilization ### Module Communication **Within Backend**: - Modules can directly import from each other - Use shared utilities from `shared/` - Share database connections and auth **Within Frontend**: - Modules use shared Pinia stores - Shared components in `src/shared/` - Routing handles module navigation --- ## 🔧 Configuration Management ### Environment-Based Configuration The backend supports multiple environment configurations: ```bash # Development backend/.env.dev # Local development settings PORT=8000 DEBUG=True ORACLE_HOST=localhost ORACLE_PORT=1526 # Testing backend/.env.test # Testing environment PORT=8001 DEBUG=False ORACLE_HOST=10.0.20.121 # Production backend/.env.prod # Production settings PORT=8001 DEBUG=False ORACLE_HOST=10.0.20.36 ``` ### Module Toggle Configuration Modules can be enabled/disabled via environment variables: ```bash MODULE_REPORTS_ENABLED=true MODULE_DATA_ENTRY_ENABLED=true MODULE_TELEGRAM_ENABLED=true ``` --- ## 📊 Shared Resources ### 1. Database Connection Pool **Oracle Pool** (`shared/database/oracle_pool.py`): - Singleton pattern - Configured pool size (min=2, max=10) - Automatic reconnection - Connection health checks - Used by Reports module ### 2. Authentication & Authorization **JWT Authentication** (`shared/auth/`): - Centralized token management - Middleware auto-injection of user - Rate limiting (5 req/5 min) - Used by all modules ### 3. Cache System (Reports Module) **Two-Tier Cache**: - L1: In-memory (LRU, 1000 entries) - L2: SQLite persistent cache - Automatic TTL management - Performance tracking ### 4. Frontend Shared Components **Shared UI** (`src/shared/` and `shared/frontend/`): - Authentication components - Company/Period selectors - Error boundaries - Global CSS system --- ## 🎯 Migration from Microservices ### What Changed **Before (Microservices)**: ``` reports-app/backend/ → Port 8001 data-entry-app/backend/ → Port 8003 telegram-bot/ → Port 8002 ``` **After (Monolith)**: ``` backend/ → Single port 8000/8001 └── modules/ ├── reports/ ├── data_entry/ └── telegram/ ``` ### Migration Benefits 1. ✅ Simpler deployment (1 service instead of 3) 2. ✅ Faster startup (no multi-service coordination) 3. ✅ Easier debugging (single process) 4. ✅ Shared connection pools (better resource utilization) 5. ✅ No inter-service network latency 6. ✅ Atomic deployments (all modules update together) ### What Stayed the Same - ✅ Module boundaries and organization - ✅ Business logic and models - ✅ Frontend structure - ✅ Database schemas - ✅ API contracts - ✅ Authentication flow --- ## 🔒 Security Considerations ### Middleware Stack All requests pass through: 1. CORS validation 2. JWT authentication 3. Rate limiting 4. Security headers injection ### Module Isolation While modules share the same process: - Each has its own routers - Business logic is separated - Database access is controlled - Permissions are enforced at API level --- ## 📈 Scalability ### Horizontal Scaling The monolith can be scaled horizontally: - Multiple instances behind load balancer - Stateless design (JWT, no sessions) - Shared database (Oracle) - Redis for distributed cache (future) ### Vertical Scaling Optimize single instance: - Increase worker processes - Connection pool tuning - Cache optimization - Query optimization ### Future: Microservices Migration If needed, modules can be extracted: - Each module already has clear boundaries - Services are independent - API contracts are defined - Database can be split (if needed) --- ## 📚 Related Documentation - **Setup & Commands**: `README.md` - **CSS Architecture**: `docs/ONBOARDING_CSS.md` - **Data Entry Module**: `docs/data-entry/ARCHITECTURE.md` - **Telegram Bot**: `docs/telegram/README.md` - **Deployment**: `deployment/windows/README.md` (Windows) or `DOKPLOY_DEPLOYMENT.md` (Linux) --- **For questions about this architecture, consult the development team or open an issue in the repository.**