diff --git a/.ai/context.json b/.ai/context.json index c343144..736a130 100644 --- a/.ai/context.json +++ b/.ai/context.json @@ -1,6 +1,6 @@ { "version": "6.2.0", - "architecture": "simplified-5-container", + "architecture": "9-container", "repository": { "host": "gitea", "owner": "egullickson", @@ -51,7 +51,7 @@ "project_overview": { "instruction": "Start with README.md for complete architecture context", "files": ["README.md"], - "completeness": "100% - all navigation and 5-container architecture information" + "completeness": "100% - all navigation and 9-container architecture information" }, "application_feature_work": { "instruction": "Load entire application feature directory (features are modules within backend)", @@ -104,6 +104,26 @@ "type": "cache", "description": "Redis cache with AOF persistence", "port": 6379 + }, + "mvp-ocr": { + "type": "ocr_service", + "description": "Python-based OCR for document text extraction", + "port": 8000 + }, + "mvp-loki": { + "type": "log_aggregation", + "description": "Grafana Loki for centralized log storage (30-day retention)", + "port": 3100 + }, + "mvp-alloy": { + "type": "log_collector", + "description": "Grafana Alloy for log collection and forwarding to Loki", + "port": 12345 + }, + "mvp-grafana": { + "type": "log_visualization", + "description": "Grafana for log querying and visualization", + "port": 3000 } }, "application_features": { @@ -290,6 +310,6 @@ "single_tenant_architecture": true, "simplified_deployment": true, "docker_first_development": true, - "container_count": 5 + "container_count": 9 } } diff --git a/.gitea/workflows/production.yaml b/.gitea/workflows/production.yaml index d708e1c..634506f 100644 --- a/.gitea/workflows/production.yaml +++ b/.gitea/workflows/production.yaml @@ -171,7 +171,7 @@ jobs: # Start shared infrastructure services (database, cache, logging) # These persist across blue-green deployments docker compose -f $COMPOSE_FILE -f $COMPOSE_BLUE_GREEN -f $COMPOSE_PROD up -d \ - mvp-postgres mvp-redis mvp-loki mvp-promtail mvp-grafana + mvp-postgres mvp-redis mvp-loki mvp-alloy mvp-grafana - name: Start target stack run: | diff --git a/CLAUDE.md b/CLAUDE.md index 592ada1..b177d0c 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,6 +1,6 @@ # MotoVaultPro -Single-tenant vehicle management application with 9-container architecture (6 application: Traefik, Frontend, Backend, OCR, PostgreSQL, Redis + 3 logging: Loki, Promtail, Grafana). +Single-tenant vehicle management application with 9-container architecture (6 application: Traefik, Frontend, Backend, OCR, PostgreSQL, Redis + 3 logging: Loki, Alloy, Grafana). ## Files @@ -173,7 +173,7 @@ Issues are the source of truth. See `.ai/workflow-contract.json` for complete wo ## Architecture Context for AI ### 9-Container Architecture -**MotoVaultPro uses a unified architecture:** A single-tenant application with 9 containers - 6 application (Traefik, Frontend, Backend, OCR, PostgreSQL, Redis) + 3 logging (Loki, Promtail, Grafana). Application features in `backend/src/features/[name]/` are self-contained modules within the backend service, including the platform feature for vehicle data and VIN decoding. See `docs/LOGGING.md` for unified logging system documentation. +**MotoVaultPro uses a unified architecture:** A single-tenant application with 9 containers - 6 application (Traefik, Frontend, Backend, OCR, PostgreSQL, Redis) + 3 logging (Loki, Alloy, Grafana). Application features in `backend/src/features/[name]/` are self-contained modules within the backend service, including the platform feature for vehicle data and VIN decoding. See `docs/LOGGING.md` for unified logging system documentation. ### Key Principles for AI Understanding - **Feature Capsule Organization**: Application features are self-contained modules within the backend diff --git a/config/CLAUDE.md b/config/CLAUDE.md index 5e688c8..dd73d62 100644 --- a/config/CLAUDE.md +++ b/config/CLAUDE.md @@ -1,6 +1,6 @@ # config/ -Configuration files for the 5-container architecture. +Configuration files for the 9-container architecture (6 application + 3 logging). ## Subdirectories diff --git a/config/alloy/config.alloy b/config/alloy/config.alloy new file mode 100644 index 0000000..91e5ae6 --- /dev/null +++ b/config/alloy/config.alloy @@ -0,0 +1,29 @@ +discovery.docker "containers" { + host = "unix:///var/run/docker.sock" + refresh_interval = "5s" +} + +discovery.relabel "containers" { + targets = discovery.docker.containers.targets + rule { + source_labels = ["__meta_docker_container_name"] + regex = "/(.*)" + target_label = "container" + } + rule { + source_labels = ["__meta_docker_container_label_com_docker_compose_service"] + target_label = "service" + } +} + +loki.source.docker "containers" { + host = "unix:///var/run/docker.sock" + targets = discovery.relabel.containers.output + forward_to = [loki.write.default.receiver] +} + +loki.write "default" { + endpoint { + url = "http://mvp-loki:3100/loki/api/v1/push" + } +} diff --git a/config/loki/config.yml b/config/loki/config.yml index e020d49..a3d6cd7 100644 --- a/config/loki/config.yml +++ b/config/loki/config.yml @@ -15,24 +15,23 @@ ingester: schema_config: configs: - from: 2020-01-01 - store: boltdb-shipper + store: tsdb object_store: filesystem - schema: v11 + schema: v13 index: prefix: index_ period: 24h storage_config: - boltdb_shipper: - active_index_directory: /loki/boltdb-shipper-active - cache_location: /loki/boltdb-shipper-cache - shared_store: filesystem + tsdb_shipper: + active_index_directory: /loki/tsdb-index + cache_location: /loki/tsdb-cache filesystem: directory: /loki/chunks compactor: working_directory: /loki/compactor - shared_store: filesystem limits_config: retention_period: 720h # 30 days + allow_structured_metadata: false diff --git a/config/promtail/config.yml b/config/promtail/config.yml deleted file mode 100644 index 48bf9ab..0000000 --- a/config/promtail/config.yml +++ /dev/null @@ -1,21 +0,0 @@ -server: - http_listen_port: 9080 - grpc_listen_port: 0 - -positions: - filename: /tmp/positions.yaml - -clients: - - url: http://mvp-loki:3100/loki/api/v1/push - -scrape_configs: - - job_name: containers - docker_sd_configs: - - host: unix:///var/run/docker.sock - refresh_interval: 5s - relabel_configs: - - source_labels: ['__meta_docker_container_name'] - regex: '/(.*)' - target_label: 'container' - - source_labels: ['__meta_docker_container_label_com_docker_compose_service'] - target_label: 'service' diff --git a/docker-compose.yml b/docker-compose.yml index 814a76f..d5bf4a7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -266,7 +266,7 @@ services: # Log Aggregation - Loki mvp-loki: - image: ${REGISTRY_MIRRORS:-git.motovaultpro.com/egullickson/mirrors}/grafana/loki:2.9.0 + image: ${REGISTRY_MIRRORS:-git.motovaultpro.com/egullickson/mirrors}/grafana/loki:3.6.1 container_name: mvp-loki restart: unless-stopped volumes: @@ -286,20 +286,29 @@ services: max-size: "10m" max-file: "3" - # Log Aggregation - Promtail - mvp-promtail: - image: ${REGISTRY_MIRRORS:-git.motovaultpro.com/egullickson/mirrors}/grafana/promtail:2.9.0 - container_name: mvp-promtail + # Log Aggregation - Alloy (replaces Promtail) + mvp-alloy: + image: ${REGISTRY_MIRRORS:-git.motovaultpro.com/egullickson/mirrors}/grafana/alloy:v1.12.2 + container_name: mvp-alloy restart: unless-stopped volumes: - - ./config/promtail/config.yml:/etc/promtail/config.yml:ro + - ./config/alloy/config.alloy:/etc/alloy/config.alloy - /var/lib/docker/containers:/var/lib/docker/containers:ro - /var/run/docker.sock:/var/run/docker.sock:ro - command: -config.file=/etc/promtail/config.yml + command: + - run + - --server.http.listen-addr=0.0.0.0:12345 + - --storage.path=/var/lib/alloy/data + - /etc/alloy/config.alloy networks: - backend depends_on: - mvp-loki + healthcheck: + test: ["CMD-SHELL", "wget -q --spider http://localhost:12345/ready || exit 1"] + interval: 30s + timeout: 10s + retries: 3 logging: driver: json-file options: @@ -308,7 +317,7 @@ services: # Log Aggregation - Grafana mvp-grafana: - image: ${REGISTRY_MIRRORS:-git.motovaultpro.com/egullickson/mirrors}/grafana/grafana:10.0.0 + image: ${REGISTRY_MIRRORS:-git.motovaultpro.com/egullickson/mirrors}/grafana/grafana:12.4.0-21693836646 container_name: mvp-grafana restart: unless-stopped environment: diff --git a/docs/ARCHITECTURE-OVERVIEW.md b/docs/ARCHITECTURE-OVERVIEW.md index 55af73c..eb0239b 100644 --- a/docs/ARCHITECTURE-OVERVIEW.md +++ b/docs/ARCHITECTURE-OVERVIEW.md @@ -2,14 +2,20 @@ ## Architecture Summary -MotoVaultPro is a single-tenant vehicle management application built with a **5-container Docker-first architecture**. All development and deployment occurs in production-configured containers with no local installation dependencies. +MotoVaultPro is a single-tenant vehicle management application built with a **9-container Docker-first architecture** (6 application + 3 logging). All development and deployment occurs in production-configured containers with no local installation dependencies. -### Core Containers +### Application Containers (6) 1. **Traefik** - Reverse proxy and service discovery 2. **Frontend** - React SPA with Vite (Node.js 20 + nginx) 3. **Backend** - Node.js API with Fastify (Node.js 20) - includes platform feature module -4. **PostgreSQL** - Primary database (PostgreSQL 18) -5. **Redis** - Caching layer (Redis 8) +4. **OCR** - Python-based document text extraction +5. **PostgreSQL** - Primary database (PostgreSQL 18) +6. **Redis** - Caching layer (Redis 8) + +### Logging Containers (3) +7. **Loki** - Centralized log storage (30-day retention) +8. **Alloy** - Log collection and forwarding +9. **Grafana** - Log querying and visualization ### Key Architectural Principles - **Production-Only**: All services use production builds and configuration diff --git a/docs/AUDIT.md b/docs/AUDIT.md index c101259..6f17a52 100644 --- a/docs/AUDIT.md +++ b/docs/AUDIT.md @@ -4,7 +4,7 @@ **Classification:** Internal/Confidential **Audit Date:** December 13, 2025 **Application Version:** 1.0.0 -**Architecture:** 5-Container Single-Tenant Docker Stack +**Architecture:** 9-Container Single-Tenant Docker Stack (6 application + 3 logging) --- @@ -12,7 +12,7 @@ ### 1.1 High-Level Assessment -**MotoVaultPro** is an automotive vehicle management platform built on a modern 5-container Docker architecture. The application demonstrates solid architectural foundations with proper authentication, modular feature design, and production-ready deployment configuration. +**MotoVaultPro** is an automotive vehicle management platform built on a modern 9-container Docker architecture (6 application + 3 logging). The application demonstrates solid architectural foundations with proper authentication, modular feature design, and production-ready deployment configuration. ### 1.2 Key Findings Summary diff --git a/docs/DATABASE-SCHEMA.md b/docs/DATABASE-SCHEMA.md index ced6224..553dc05 100644 --- a/docs/DATABASE-SCHEMA.md +++ b/docs/DATABASE-SCHEMA.md @@ -1,6 +1,6 @@ # Database Schema Overview -Complete database schema for MotoVaultPro 5-container architecture with 15 feature capsules. +Complete database schema for MotoVaultPro 9-container architecture with 15 feature capsules. ## Migration System diff --git a/docs/LOGGING.md b/docs/LOGGING.md index 0cfffff..19d818d 100644 --- a/docs/LOGGING.md +++ b/docs/LOGGING.md @@ -102,14 +102,14 @@ This creates `.env.logging` which is sourced by docker-compose. +-----------------------------------------------------------------------+ | v - Promtail --> Loki (30-day retention) --> Grafana + Alloy --> Loki (30-day retention) --> Grafana ``` ## Troubleshooting ### Logs not appearing in Grafana -1. Check Promtail is running: `docker logs mvp-promtail` +1. Check Alloy is running: `docker logs mvp-alloy` 2. Check Loki is healthy: `curl http://localhost:3100/ready` 3. Verify log rotation is not too aggressive diff --git a/ocr/Dockerfile b/ocr/Dockerfile index 9c42064..90aa37f 100644 --- a/ocr/Dockerfile +++ b/ocr/Dockerfile @@ -4,7 +4,7 @@ # Build argument for registry (defaults to Gitea mirrors, falls back to Docker Hub) ARG REGISTRY_MIRRORS=git.motovaultpro.com/egullickson/mirrors -FROM ${REGISTRY_MIRRORS}/python:3.11-slim +FROM ${REGISTRY_MIRRORS}/python:3.13-slim # System dependencies RUN apt-get update && apt-get install -y --no-install-recommends \ diff --git a/scripts/ci/mirror-base-images.sh b/scripts/ci/mirror-base-images.sh index 2e26d50..5867a62 100755 --- a/scripts/ci/mirror-base-images.sh +++ b/scripts/ci/mirror-base-images.sh @@ -14,12 +14,10 @@ IMAGES=( "postgres:18-alpine" "redis:8.4-alpine" "traefik:v3.6" - "python:3.11-slim" - "docker:24.0" - "docker:24.0-dind" - "grafana/loki:2.9.0" - "grafana/promtail:2.9.0" - "grafana/grafana:10.0.0" + "python:3.13-slim" + "grafana/loki:3.6.1" + "grafana/alloy:v1.12.2" + "grafana/grafana:12.4.0-21693836646" ) echo "========================================"