diff --git a/frontend/Dockerfile.development b/frontend/Dockerfile.development deleted file mode 100644 index 6069bda8..00000000 --- a/frontend/Dockerfile.development +++ /dev/null @@ -1,38 +0,0 @@ -# frontend/Dockerfile.development - FIXED VERSION -FROM node:18-alpine - -# Install curl for healthchecks -RUN apk add --no-cache curl - -# Set working directory -WORKDIR /app - -# Create non-root user for security but don't switch yet -RUN addgroup -g 1001 -S nodejs && \ - adduser -S reactjs -u 1001 -G nodejs - -# Copy package files first (better caching) -COPY package*.json ./ - -# Install all dependencies (including dev dependencies) as root -RUN npm ci --verbose && \ - npm cache clean --force - -# Copy source code -COPY . . - -# Change ownership of all files to the non-root user -RUN chown -R reactjs:nodejs /app - -# Now switch to non-root user -USER reactjs - -# Expose port 3000 (Vite default) -EXPOSE 3000 - -# Add healthcheck -HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ - CMD curl -f http://localhost:3000/ || exit 1 - -# Start development server with host binding -CMD ["npm", "run", "dev", "--", "--host", "0.0.0.0"] \ No newline at end of file diff --git a/frontend/Dockerfile b/frontend/Dockerfile.kubernetes similarity index 66% rename from frontend/Dockerfile rename to frontend/Dockerfile.kubernetes index 29619177..80350c42 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile.kubernetes @@ -1,5 +1,5 @@ -# Production Dockerfile for Frontend with Nginx -# Multi-stage build for optimal size and performance +# Kubernetes-optimized Dockerfile for Frontend +# Multi-stage build for production deployment # Stage 1: Build the application FROM node:18-alpine AS builder @@ -17,6 +17,7 @@ RUN npm ci --verbose && \ COPY . . # Build the application for production +# This will use environment variables available at build time RUN npm run build # Stage 2: Production server with Nginx @@ -34,7 +35,30 @@ COPY nginx.conf /etc/nginx/conf.d/ # Copy built application from builder stage COPY --from=builder /app/dist /usr/share/nginx/html -# Nginx user already exists in the base image, just ensure proper ownership +# Create a script to substitute environment variables at runtime +COPY <<'EOF' /docker-entrypoint.d/30-substitute-env.sh +#!/bin/sh +set -e + +# Default values for environment variables +export VITE_API_URL=${VITE_API_URL:-"http://gateway-service:8000"} +export VITE_APP_TITLE=${VITE_APP_TITLE:-"PanIA Dashboard"} +export VITE_APP_VERSION=${VITE_APP_VERSION:-"1.0.0"} + +# Create a runtime configuration file that can be loaded by the frontend +cat > /usr/share/nginx/html/runtime-config.js << EOL +window.__RUNTIME_CONFIG__ = { + VITE_API_URL: '${VITE_API_URL}', + VITE_APP_TITLE: '${VITE_APP_TITLE}', + VITE_APP_VERSION: '${VITE_APP_VERSION}' +}; +EOL + +echo "Runtime configuration created with API URL: ${VITE_API_URL}" +EOF + +# Make the script executable +RUN chmod +x /docker-entrypoint.d/30-substitute-env.sh # Set proper permissions RUN chown -R nginx:nginx /usr/share/nginx/html && \ @@ -65,7 +89,7 @@ EXPOSE 3000 # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \ - CMD curl -f http://localhost:3000/ || exit 1 + CMD curl -f http://localhost:3000/health || exit 1 # Start nginx CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/frontend/Dockerfile.production b/frontend/Dockerfile.production deleted file mode 100644 index 98ba917c..00000000 --- a/frontend/Dockerfile.production +++ /dev/null @@ -1,41 +0,0 @@ -# frontend/Dockerfile.production -# Multi-stage build for production - -# Build stage -FROM node:18-alpine as builder - -WORKDIR /app - -# Copy package files -COPY package*.json ./ - -# Install dependencies -RUN npm ci --only=production - -# Copy source code -COPY . . - -# Build the application -RUN npm run build - -# Production stage -FROM nginx:alpine - -# Install curl for healthchecks -RUN apk add --no-cache curl - -# Copy built app from builder stage -COPY --from=builder /app/dist /usr/share/nginx/html - -# Copy nginx configuration -COPY nginx.conf /etc/nginx/nginx.conf - -# Expose port 80 -EXPOSE 80 - -# Add healthcheck -HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \ - CMD curl -f http://localhost/ || exit 1 - -# Start nginx -CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/frontend/index.html b/frontend/index.html index e7d78224..86708766 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -22,6 +22,8 @@
+ + \ No newline at end of file diff --git a/frontend/nginx.conf b/frontend/nginx.conf index a4de780e..b973433c 100644 --- a/frontend/nginx.conf +++ b/frontend/nginx.conf @@ -12,7 +12,7 @@ server { add_header X-Content-Type-Options "nosniff" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; - add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.googleapis.com https://js.stripe.com; script-src-elem 'self' 'unsafe-inline' https://js.stripe.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' http://localhost:8000 http://localhost:8006 ws: wss:; frame-src https://js.stripe.com;" always; + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://fonts.googleapis.com https://js.stripe.com; script-src-elem 'self' 'unsafe-inline' https://js.stripe.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' http://gateway-service:8000 http://localhost:8000 http://localhost:8006 ws: wss:; frame-src https://js.stripe.com;" always; # Gzip compression gzip on; @@ -31,9 +31,9 @@ server { application/atom+xml image/svg+xml; - # API proxy to gateway service (Kubernetes internal name) + # API proxy to gateway service (Kubernetes service name) location /api/ { - proxy_pass http://gateway:8000; + proxy_pass http://gateway-service:8000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; diff --git a/frontend/src/api/client/apiClient.ts b/frontend/src/api/client/apiClient.ts index 2991f60e..6e50f9b7 100644 --- a/frontend/src/api/client/apiClient.ts +++ b/frontend/src/api/client/apiClient.ts @@ -10,6 +10,7 @@ * React Query doesn't replace HTTP clients - it manages data fetching/caching/sync */ import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios'; +import { getApiUrl } from '../../config/runtime'; export interface ApiError { message: string; @@ -55,7 +56,7 @@ class ApiClient { config: AxiosRequestConfig; }> = []; - constructor(baseURL: string = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000/api/v1') { + constructor(baseURL: string = getApiUrl() + '/api/v1') { this.baseURL = baseURL; this.client = axios.create({ diff --git a/frontend/src/config/runtime.ts b/frontend/src/config/runtime.ts new file mode 100644 index 00000000..8facbae7 --- /dev/null +++ b/frontend/src/config/runtime.ts @@ -0,0 +1,62 @@ +// Runtime configuration for Kubernetes deployments +// This allows environment variables to be injected at container startup + +interface RuntimeConfig { + VITE_API_URL: string; + VITE_APP_TITLE: string; + VITE_APP_VERSION: string; +} + +declare global { + interface Window { + __RUNTIME_CONFIG__?: RuntimeConfig; + } +} + +// Types are defined in vite-env.d.ts + +// Get configuration from runtime or fall back to build-time environment variables +function getRuntimeConfig(): RuntimeConfig { + // First try to get from window (injected at runtime in Kubernetes) + if (typeof window !== 'undefined' && window.__RUNTIME_CONFIG__) { + return window.__RUNTIME_CONFIG__; + } + + // Fall back to build-time environment variables (development/local) + return { + VITE_API_URL: import.meta.env.VITE_API_URL || 'http://localhost:8000', + VITE_APP_TITLE: import.meta.env.VITE_APP_TITLE || 'PanIA Dashboard', + VITE_APP_VERSION: import.meta.env.VITE_APP_VERSION || '1.0.0', + }; +} + +export const config = getRuntimeConfig(); + +// Helper function to get the API base URL +export function getApiUrl(): string { + return config.VITE_API_URL; +} + +// Helper function to get app title +export function getAppTitle(): string { + return config.VITE_APP_TITLE; +} + +// Helper function to get app version +export function getAppVersion(): string { + return config.VITE_APP_VERSION; +} + +// Helper to check if running in Kubernetes +export function isKubernetesEnvironment(): boolean { + return typeof window !== 'undefined' && !!window.__RUNTIME_CONFIG__; +} + +// Debug function to log current configuration +export function logConfig(): void { + console.log('Current configuration:', { + ...config, + isKubernetes: isKubernetesEnvironment(), + source: isKubernetesEnvironment() ? 'runtime' : 'build-time' + }); +} \ No newline at end of file diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts new file mode 100644 index 00000000..31c75329 --- /dev/null +++ b/frontend/src/vite-env.d.ts @@ -0,0 +1,14 @@ +/// + +interface ImportMetaEnv { + readonly VITE_API_URL: string + readonly VITE_API_BASE_URL: string + readonly VITE_APP_TITLE: string + readonly VITE_APP_VERSION: string + readonly VITE_ENVIRONMENT: string + // more env variables... +} + +interface ImportMeta { + readonly env: ImportMetaEnv +} \ No newline at end of file diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index ff05626e..5dfb8987 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -28,10 +28,12 @@ export default defineConfig({ }, proxy: { '/api': { - target: process.env.NODE_ENV === 'development' - ? 'http://gateway:8000' // Use internal service name in Kubernetes - : 'http://localhost:8000', + target: process.env.VITE_API_URL || + (process.env.NODE_ENV === 'development' && process.env.KUBERNETES_SERVICE_HOST + ? 'http://gateway-service:8000' // Kubernetes internal service + : 'http://localhost:8000'), // Local development changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, ''), }, }, }, diff --git a/infrastructure/kubernetes/components/alert-processor/alert-processor-service.yaml b/infrastructure/kubernetes/base/components/alert-processor/alert-processor-service.yaml similarity index 95% rename from infrastructure/kubernetes/components/alert-processor/alert-processor-service.yaml rename to infrastructure/kubernetes/base/components/alert-processor/alert-processor-service.yaml index c3f2185a..f3a7284a 100644 --- a/infrastructure/kubernetes/components/alert-processor/alert-processor-service.yaml +++ b/infrastructure/kubernetes/base/components/alert-processor/alert-processor-service.yaml @@ -98,6 +98,11 @@ spec: secretKeyRef: name: rabbitmq-secrets key: RABBITMQ_PASSWORD + - name: RABBITMQ_VHOST + valueFrom: + configMapKeyRef: + name: bakery-config + key: RABBITMQ_VHOST - name: NOTIFICATION_SERVICE_URL valueFrom: configMapKeyRef: diff --git a/infrastructure/kubernetes/components/auth/auth-service.yaml b/infrastructure/kubernetes/base/components/auth/auth-service.yaml similarity index 100% rename from infrastructure/kubernetes/components/auth/auth-service.yaml rename to infrastructure/kubernetes/base/components/auth/auth-service.yaml diff --git a/infrastructure/kubernetes/components/databases/alert-processor-db.yaml b/infrastructure/kubernetes/base/components/databases/alert-processor-db.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/alert-processor-db.yaml rename to infrastructure/kubernetes/base/components/databases/alert-processor-db.yaml diff --git a/infrastructure/kubernetes/components/databases/auth-db.yaml b/infrastructure/kubernetes/base/components/databases/auth-db.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/auth-db.yaml rename to infrastructure/kubernetes/base/components/databases/auth-db.yaml diff --git a/infrastructure/kubernetes/components/databases/external-db.yaml b/infrastructure/kubernetes/base/components/databases/external-db.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/external-db.yaml rename to infrastructure/kubernetes/base/components/databases/external-db.yaml diff --git a/infrastructure/kubernetes/components/databases/forecasting-db.yaml b/infrastructure/kubernetes/base/components/databases/forecasting-db.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/forecasting-db.yaml rename to infrastructure/kubernetes/base/components/databases/forecasting-db.yaml diff --git a/infrastructure/kubernetes/components/databases/inventory-db.yaml b/infrastructure/kubernetes/base/components/databases/inventory-db.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/inventory-db.yaml rename to infrastructure/kubernetes/base/components/databases/inventory-db.yaml diff --git a/infrastructure/kubernetes/components/databases/notification-db.yaml b/infrastructure/kubernetes/base/components/databases/notification-db.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/notification-db.yaml rename to infrastructure/kubernetes/base/components/databases/notification-db.yaml diff --git a/infrastructure/kubernetes/components/databases/orders-db.yaml b/infrastructure/kubernetes/base/components/databases/orders-db.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/orders-db.yaml rename to infrastructure/kubernetes/base/components/databases/orders-db.yaml diff --git a/infrastructure/kubernetes/components/databases/pos-db.yaml b/infrastructure/kubernetes/base/components/databases/pos-db.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/pos-db.yaml rename to infrastructure/kubernetes/base/components/databases/pos-db.yaml diff --git a/infrastructure/kubernetes/components/databases/postgres-template.yaml b/infrastructure/kubernetes/base/components/databases/postgres-template.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/postgres-template.yaml rename to infrastructure/kubernetes/base/components/databases/postgres-template.yaml diff --git a/infrastructure/kubernetes/components/databases/production-db.yaml b/infrastructure/kubernetes/base/components/databases/production-db.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/production-db.yaml rename to infrastructure/kubernetes/base/components/databases/production-db.yaml diff --git a/infrastructure/kubernetes/components/databases/rabbitmq.yaml b/infrastructure/kubernetes/base/components/databases/rabbitmq.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/rabbitmq.yaml rename to infrastructure/kubernetes/base/components/databases/rabbitmq.yaml diff --git a/infrastructure/kubernetes/components/databases/recipes-db.yaml b/infrastructure/kubernetes/base/components/databases/recipes-db.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/recipes-db.yaml rename to infrastructure/kubernetes/base/components/databases/recipes-db.yaml diff --git a/infrastructure/kubernetes/components/databases/redis.yaml b/infrastructure/kubernetes/base/components/databases/redis.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/redis.yaml rename to infrastructure/kubernetes/base/components/databases/redis.yaml diff --git a/infrastructure/kubernetes/components/databases/sales-db.yaml b/infrastructure/kubernetes/base/components/databases/sales-db.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/sales-db.yaml rename to infrastructure/kubernetes/base/components/databases/sales-db.yaml diff --git a/infrastructure/kubernetes/components/databases/suppliers-db.yaml b/infrastructure/kubernetes/base/components/databases/suppliers-db.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/suppliers-db.yaml rename to infrastructure/kubernetes/base/components/databases/suppliers-db.yaml diff --git a/infrastructure/kubernetes/components/databases/tenant-db.yaml b/infrastructure/kubernetes/base/components/databases/tenant-db.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/tenant-db.yaml rename to infrastructure/kubernetes/base/components/databases/tenant-db.yaml diff --git a/infrastructure/kubernetes/components/databases/training-db.yaml b/infrastructure/kubernetes/base/components/databases/training-db.yaml similarity index 100% rename from infrastructure/kubernetes/components/databases/training-db.yaml rename to infrastructure/kubernetes/base/components/databases/training-db.yaml diff --git a/infrastructure/kubernetes/components/external/external-service.yaml b/infrastructure/kubernetes/base/components/external/external-service.yaml similarity index 100% rename from infrastructure/kubernetes/components/external/external-service.yaml rename to infrastructure/kubernetes/base/components/external/external-service.yaml diff --git a/infrastructure/kubernetes/components/forecasting/forecasting-service.yaml b/infrastructure/kubernetes/base/components/forecasting/forecasting-service.yaml similarity index 100% rename from infrastructure/kubernetes/components/forecasting/forecasting-service.yaml rename to infrastructure/kubernetes/base/components/forecasting/forecasting-service.yaml diff --git a/infrastructure/kubernetes/components/frontend/frontend-service.yaml b/infrastructure/kubernetes/base/components/frontend/frontend-service.yaml similarity index 75% rename from infrastructure/kubernetes/components/frontend/frontend-service.yaml rename to infrastructure/kubernetes/base/components/frontend/frontend-service.yaml index 484f8b37..cdca7997 100644 --- a/infrastructure/kubernetes/components/frontend/frontend-service.yaml +++ b/infrastructure/kubernetes/base/components/frontend/frontend-service.yaml @@ -22,18 +22,33 @@ spec: containers: - name: frontend image: bakery/dashboard:latest + imagePullPolicy: Always ports: - containerPort: 3000 name: http env: - name: NODE_ENV - value: "development" + value: "production" - name: VITE_APP_TITLE - value: "PanIA Dashboard" + valueFrom: + configMapKeyRef: + name: bakery-config + key: VITE_APP_TITLE - name: VITE_APP_VERSION - value: "1.0.0" + valueFrom: + configMapKeyRef: + name: bakery-config + key: VITE_APP_VERSION - name: VITE_API_URL - value: "http://gateway-service:8000" + valueFrom: + configMapKeyRef: + name: bakery-config + key: VITE_API_URL + - name: VITE_ENVIRONMENT + valueFrom: + configMapKeyRef: + name: bakery-config + key: VITE_ENVIRONMENT resources: requests: memory: "512Mi" diff --git a/infrastructure/kubernetes/components/infrastructure/gateway-service.yaml b/infrastructure/kubernetes/base/components/infrastructure/gateway-service.yaml similarity index 100% rename from infrastructure/kubernetes/components/infrastructure/gateway-service.yaml rename to infrastructure/kubernetes/base/components/infrastructure/gateway-service.yaml diff --git a/infrastructure/kubernetes/components/inventory/inventory-service.yaml b/infrastructure/kubernetes/base/components/inventory/inventory-service.yaml similarity index 100% rename from infrastructure/kubernetes/components/inventory/inventory-service.yaml rename to infrastructure/kubernetes/base/components/inventory/inventory-service.yaml diff --git a/infrastructure/kubernetes/components/microservice-template.yaml b/infrastructure/kubernetes/base/components/microservice-template.yaml similarity index 100% rename from infrastructure/kubernetes/components/microservice-template.yaml rename to infrastructure/kubernetes/base/components/microservice-template.yaml diff --git a/infrastructure/kubernetes/components/notification/notification-service.yaml b/infrastructure/kubernetes/base/components/notification/notification-service.yaml similarity index 100% rename from infrastructure/kubernetes/components/notification/notification-service.yaml rename to infrastructure/kubernetes/base/components/notification/notification-service.yaml diff --git a/infrastructure/kubernetes/components/orders/orders-service.yaml b/infrastructure/kubernetes/base/components/orders/orders-service.yaml similarity index 100% rename from infrastructure/kubernetes/components/orders/orders-service.yaml rename to infrastructure/kubernetes/base/components/orders/orders-service.yaml diff --git a/infrastructure/kubernetes/components/pos/pos-service.yaml b/infrastructure/kubernetes/base/components/pos/pos-service.yaml similarity index 100% rename from infrastructure/kubernetes/components/pos/pos-service.yaml rename to infrastructure/kubernetes/base/components/pos/pos-service.yaml diff --git a/infrastructure/kubernetes/components/production/production-service.yaml b/infrastructure/kubernetes/base/components/production/production-service.yaml similarity index 100% rename from infrastructure/kubernetes/components/production/production-service.yaml rename to infrastructure/kubernetes/base/components/production/production-service.yaml diff --git a/infrastructure/kubernetes/components/recipes/recipes-service.yaml b/infrastructure/kubernetes/base/components/recipes/recipes-service.yaml similarity index 100% rename from infrastructure/kubernetes/components/recipes/recipes-service.yaml rename to infrastructure/kubernetes/base/components/recipes/recipes-service.yaml diff --git a/infrastructure/kubernetes/components/sales/sales-service.yaml b/infrastructure/kubernetes/base/components/sales/sales-service.yaml similarity index 100% rename from infrastructure/kubernetes/components/sales/sales-service.yaml rename to infrastructure/kubernetes/base/components/sales/sales-service.yaml diff --git a/infrastructure/kubernetes/components/suppliers/suppliers-service.yaml b/infrastructure/kubernetes/base/components/suppliers/suppliers-service.yaml similarity index 100% rename from infrastructure/kubernetes/components/suppliers/suppliers-service.yaml rename to infrastructure/kubernetes/base/components/suppliers/suppliers-service.yaml diff --git a/infrastructure/kubernetes/components/tenant/tenant-service.yaml b/infrastructure/kubernetes/base/components/tenant/tenant-service.yaml similarity index 100% rename from infrastructure/kubernetes/components/tenant/tenant-service.yaml rename to infrastructure/kubernetes/base/components/tenant/tenant-service.yaml diff --git a/infrastructure/kubernetes/components/training/training-service.yaml b/infrastructure/kubernetes/base/components/training/training-service.yaml similarity index 100% rename from infrastructure/kubernetes/components/training/training-service.yaml rename to infrastructure/kubernetes/base/components/training/training-service.yaml diff --git a/infrastructure/kubernetes/base/configmap.yaml b/infrastructure/kubernetes/base/configmap.yaml index 068d3eee..3f1b1dbe 100644 --- a/infrastructure/kubernetes/base/configmap.yaml +++ b/infrastructure/kubernetes/base/configmap.yaml @@ -7,16 +7,24 @@ metadata: app.kubernetes.io/name: bakery-ia app.kubernetes.io/component: config data: - # Environment Settings - ENVIRONMENT: "development" - DEBUG: "true" + # ================================================================ + # ENVIRONMENT & BUILD SETTINGS + # ================================================================ + ENVIRONMENT: "production" + DEBUG: "false" LOG_LEVEL: "INFO" - AUTO_RELOAD: "true" + BUILD_DATE: "2024-01-20T10:00:00Z" + VCS_REF: "latest" + IMAGE_TAG: "latest" + DOMAIN: "localhost" + AUTO_RELOAD: "false" PROFILING_ENABLED: "false" MOCK_EXTERNAL_APIS: "false" TESTING: "false" - # Service Discovery + # ================================================================ + # SERVICE DISCOVERY (KUBERNETES INTERNAL) + # ================================================================ REDIS_HOST: "redis-service" REDIS_PORT: "6379" RABBITMQ_HOST: "rabbitmq-service" @@ -24,7 +32,7 @@ data: RABBITMQ_MANAGEMENT_PORT: "15672" RABBITMQ_VHOST: "/" - # Database Hosts + # Database Hosts (Kubernetes Services) AUTH_DB_HOST: "auth-db-service" TENANT_DB_HOST: "tenant-db-service" TRAINING_DB_HOST: "training-db-service" @@ -40,10 +48,8 @@ data: PRODUCTION_DB_HOST: "production-db-service" ALERT_PROCESSOR_DB_HOST: "alert-processor-db-service" - # Database Ports + # Database Configuration DB_PORT: "5432" - - # Database Names AUTH_DB_NAME: "auth_db" TENANT_DB_NAME: "tenant_db" TRAINING_DB_NAME: "training_db" @@ -58,11 +64,12 @@ data: ORDERS_DB_NAME: "orders_db" PRODUCTION_DB_NAME: "production_db" ALERT_PROCESSOR_DB_NAME: "alert_processor_db" + POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --lc-collate=C --lc-ctype=C" - # PostgreSQL Settings - POSTGRES_INITDB_ARGS: "--auth-host=scram-sha-256" - - # Service URLs (internal cluster communication) + # ================================================================ + # SERVICE URLS (KUBERNETES INTERNAL) + # ================================================================ + GATEWAY_URL: "http://gateway-service:8000" AUTH_SERVICE_URL: "http://auth-service:8000" TENANT_SERVICE_URL: "http://tenant-service:8000" TRAINING_SERVICE_URL: "http://training-service:8000" @@ -77,9 +84,242 @@ data: ORDERS_SERVICE_URL: "http://orders-service:8000" PRODUCTION_SERVICE_URL: "http://production-service:8000" - # Cache Settings - REDIS_MAX_MEMORY: "512mb" + # ================================================================ + # AUTHENTICATION & SECURITY SETTINGS + # ================================================================ + JWT_ALGORITHM: "HS256" + JWT_ACCESS_TOKEN_EXPIRE_MINUTES: "30" + JWT_REFRESH_TOKEN_EXPIRE_DAYS: "7" + ENABLE_SERVICE_AUTH: "false" + PASSWORD_MIN_LENGTH: "8" + PASSWORD_REQUIRE_UPPERCASE: "true" + PASSWORD_REQUIRE_LOWERCASE: "true" + PASSWORD_REQUIRE_NUMBERS: "true" + PASSWORD_REQUIRE_SYMBOLS: "false" + BCRYPT_ROUNDS: "12" + MAX_LOGIN_ATTEMPTS: "5" + LOCKOUT_DURATION_MINUTES: "30" - # Monitoring + # ================================================================ + # CORS & API CONFIGURATION + # ================================================================ + CORS_ORIGINS: "http://frontend-service:3000,http://localhost:3000,https://bakery.yourdomain.com" + CORS_ALLOW_CREDENTIALS: "true" + RATE_LIMIT_ENABLED: "true" + RATE_LIMIT_REQUESTS: "100" + RATE_LIMIT_WINDOW: "60" + RATE_LIMIT_BURST: "10" + API_DOCS_ENABLED: "true" + + # ================================================================ + # HTTP CLIENT SETTINGS + # ================================================================ + HTTP_TIMEOUT: "30000" + HTTP_RETRIES: "3" + HTTP_RETRY_DELAY: "1.0" + + # ================================================================ + # EXTERNAL API CONFIGURATION + # ================================================================ + AEMET_BASE_URL: "https://opendata.aemet.es/opendata" + AEMET_TIMEOUT: "60" + AEMET_RETRY_ATTEMPTS: "3" + MADRID_OPENDATA_BASE_URL: "https://datos.madrid.es" + MADRID_OPENDATA_TIMEOUT: "30" + + # ================================================================ + # PAYMENT CONFIGURATION + # ================================================================ + STRIPE_PUBLISHABLE_KEY: "pk_test_your_stripe_publishable_key_here" + SQUARE_APPLICATION_ID: "your-square-application-id" + SQUARE_ENVIRONMENT: "sandbox" + TOAST_ENVIRONMENT: "sandbox" + LIGHTSPEED_ENVIRONMENT: "sandbox" + + # ================================================================ + # EMAIL CONFIGURATION + # ================================================================ + SMTP_HOST: "smtp.gmail.com" + SMTP_PORT: "587" + SMTP_TLS: "true" + SMTP_SSL: "false" + DEFAULT_FROM_EMAIL: "noreply@bakeryforecast.es" + DEFAULT_FROM_NAME: "Bakery-Forecast" + EMAIL_FROM_ADDRESS: "alerts@bakery.local" + EMAIL_FROM_NAME: "Bakery Alert System" + + # ================================================================ + # WHATSAPP CONFIGURATION + # ================================================================ + WHATSAPP_BASE_URL: "https://api.twilio.com" + WHATSAPP_FROM_NUMBER: "whatsapp:+14155238886" + + # ================================================================ + # ALERT SYSTEM CONFIGURATION + # ================================================================ + ALERT_PROCESSOR_INSTANCES: "2" + ALERT_PROCESSOR_MAX_MEMORY: "512M" + ALERT_BATCH_SIZE: "10" + ALERT_PROCESSING_TIMEOUT: "30" + EMAIL_ENABLED: "true" + WHATSAPP_ENABLED: "true" + SSE_ENABLED: "true" + PUSH_NOTIFICATIONS_ENABLED: "false" + ALERT_DEDUPLICATION_WINDOW_MINUTES: "15" + RECOMMENDATION_DEDUPLICATION_WINDOW_MINUTES: "60" + + # ================================================================ + # CHECK FREQUENCIES (CRON EXPRESSIONS) + # ================================================================ + STOCK_CHECK_FREQUENCY: "*/5" + EXPIRY_CHECK_FREQUENCY: "*/2" + TEMPERATURE_CHECK_FREQUENCY: "*/2" + PRODUCTION_DELAY_CHECK_FREQUENCY: "*/5" + CAPACITY_CHECK_FREQUENCY: "*/10" + INVENTORY_OPTIMIZATION_FREQUENCY: "*/30" + EFFICIENCY_RECOMMENDATIONS_FREQUENCY: "*/30" + ENERGY_RECOMMENDATIONS_FREQUENCY: "0" + WASTE_REDUCTION_FREQUENCY: "0" + + # ================================================================ + # MODEL STORAGE & TRAINING + # ================================================================ + MODEL_STORAGE_PATH: "/app/models" + MODEL_BACKUP_ENABLED: "true" + MODEL_VERSIONING_ENABLED: "true" + MAX_TRAINING_TIME_MINUTES: "30" + MAX_CONCURRENT_TRAINING_JOBS: "3" + MIN_TRAINING_DATA_DAYS: "30" + TRAINING_BATCH_SIZE: "1000" + + # ================================================================ + # OPTIMIZATION SETTINGS + # ================================================================ + ENABLE_HYPERPARAMETER_OPTIMIZATION: "true" + ENABLE_PRODUCT_SPECIFIC_PARAMS: "true" + ENABLE_DYNAMIC_PARAM_SELECTION: "true" + OPTUNA_N_TRIALS: "50" + OPTUNA_CV_FOLDS: "3" + OPTUNA_TIMEOUT_MINUTES: "10" + HIGH_VOLUME_THRESHOLD: "1.0" + INTERMITTENT_THRESHOLD: "0.6" + + # ================================================================ + # PROPHET PARAMETERS + # ================================================================ + PROPHET_SEASONALITY_MODE: "additive" + PROPHET_CHANGEPOINT_PRIOR_SCALE: "0.05" + PROPHET_SEASONALITY_PRIOR_SCALE: "10.0" + PROPHET_HOLIDAYS_PRIOR_SCALE: "10.0" + PROPHET_DAILY_SEASONALITY: "true" + PROPHET_WEEKLY_SEASONALITY: "true" + PROPHET_YEARLY_SEASONALITY: "true" + + # ================================================================ + # BUSINESS CONFIGURATION + # ================================================================ + SERVICE_VERSION: "1.0.0" + TIMEZONE: "Europe/Madrid" + LOCALE: "es_ES.UTF-8" + CURRENCY: "EUR" + BUSINESS_HOUR_START: "7" + BUSINESS_HOUR_END: "20" + ENABLE_SPANISH_HOLIDAYS: "true" + ENABLE_MADRID_HOLIDAYS: "true" + SCHOOL_CALENDAR_ENABLED: "true" + WEATHER_IMPACT_ENABLED: "true" + + # ================================================================ + # MONITORING & LOGGING + # ================================================================ + LOG_FORMAT: "json" + LOG_FILE_ENABLED: "false" + LOG_FILE_PATH: "/app/logs" + LOG_ROTATION_SIZE: "100MB" + LOG_RETENTION_DAYS: "30" + PROMETHEUS_ENABLED: "true" PROMETHEUS_RETENTION: "200h" - TIMEZONE: "UTC" \ No newline at end of file + HEALTH_CHECK_TIMEOUT: "30" + HEALTH_CHECK_INTERVAL: "30" + PROMETHEUS_RETENTION_DAYS: "30" + GRAFANA_ROOT_URL: "http://monitoring.bakery-ia.local/grafana" + + # ================================================================ + # DATA COLLECTION SETTINGS + # ================================================================ + WEATHER_COLLECTION_INTERVAL_HOURS: "1" + TRAFFIC_COLLECTION_INTERVAL_HOURS: "1" + EVENTS_COLLECTION_INTERVAL_HOURS: "6" + DATA_VALIDATION_ENABLED: "true" + OUTLIER_DETECTION_ENABLED: "true" + DATA_COMPLETENESS_THRESHOLD: "0.8" + DEFAULT_LATITUDE: "40.4168" + DEFAULT_LONGITUDE: "-3.7038" + LOCATION_RADIUS_KM: "50.0" + + # ================================================================ + # NOTIFICATION SETTINGS + # ================================================================ + ENABLE_EMAIL_NOTIFICATIONS: "true" + ENABLE_WHATSAPP_NOTIFICATIONS: "true" + ENABLE_PUSH_NOTIFICATIONS: "false" + MAX_RETRY_ATTEMPTS: "3" + RETRY_DELAY_SECONDS: "60" + NOTIFICATION_BATCH_SIZE: "100" + EMAIL_RATE_LIMIT_PER_HOUR: "1000" + WHATSAPP_RATE_LIMIT_PER_HOUR: "100" + DEFAULT_LANGUAGE: "es" + DATE_FORMAT: "%d/%m/%Y" + TIME_FORMAT: "%H:%M" + EMAIL_TEMPLATES_PATH: "/app/templates/email" + WHATSAPP_TEMPLATES_PATH: "/app/templates/whatsapp" + IMMEDIATE_DELIVERY: "true" + SCHEDULED_DELIVERY_ENABLED: "true" + DELIVERY_TRACKING_ENABLED: "true" + OPEN_TRACKING_ENABLED: "true" + CLICK_TRACKING_ENABLED: "true" + + # ================================================================ + # FORECASTING SETTINGS + # ================================================================ + MAX_FORECAST_DAYS: "30" + MIN_HISTORICAL_DAYS: "60" + PREDICTION_CONFIDENCE_THRESHOLD: "0.8" + PREDICTION_CACHE_TTL_HOURS: "6" + FORECAST_BATCH_SIZE: "100" + + # ================================================================ + # BUSINESS RULES + # ================================================================ + WEEKEND_ADJUSTMENT_FACTOR: "0.8" + HOLIDAY_ADJUSTMENT_FACTOR: "0.5" + TEMPERATURE_THRESHOLD_COLD: "10.0" + TEMPERATURE_THRESHOLD_HOT: "30.0" + RAIN_IMPACT_FACTOR: "0.7" + HIGH_DEMAND_THRESHOLD: "1.5" + LOW_DEMAND_THRESHOLD: "0.5" + STOCKOUT_RISK_THRESHOLD: "0.9" + + # ================================================================ + # CACHE SETTINGS + # ================================================================ + REDIS_MAX_MEMORY: "512mb" + REDIS_MAX_CONNECTIONS: "50" + REDIS_DB: "1" + WEATHER_CACHE_TTL_HOURS: "1" + TRAFFIC_CACHE_TTL_HOURS: "1" + + # ================================================================ + # FRONTEND CONFIGURATION + # ================================================================ + VITE_APP_TITLE: "PanIA Dashboard" + VITE_APP_VERSION: "1.0.0" + VITE_API_URL: "http://gateway-service:8000" + VITE_ENVIRONMENT: "production" + + # ================================================================ + # LOCATION SETTINGS + # ================================================================ + NOMINATIM_PBF_URL: "http://download.geofabrik.de/europe/spain-latest.osm.pbf" + NOMINATIM_MEMORY_LIMIT: "8G" + NOMINATIM_CPU_LIMIT: "4" \ No newline at end of file diff --git a/infrastructure/kubernetes/base/kustomization.yaml b/infrastructure/kubernetes/base/kustomization.yaml index ded5ee89..aacdf31b 100644 --- a/infrastructure/kubernetes/base/kustomization.yaml +++ b/infrastructure/kubernetes/base/kustomization.yaml @@ -51,9 +51,11 @@ resources: # Frontend - components/frontend/frontend-service.yaml -commonLabels: - app.kubernetes.io/part-of: bakery-ia - app.kubernetes.io/managed-by: kustomize +labels: + - includeSelectors: true + pairs: + app.kubernetes.io/part-of: bakery-ia + app.kubernetes.io/managed-by: kustomize images: - name: bakery/auth-service diff --git a/infrastructure/kubernetes/base/secrets.yaml b/infrastructure/kubernetes/base/secrets.yaml index 8331dccc..2996a1c9 100644 --- a/infrastructure/kubernetes/base/secrets.yaml +++ b/infrastructure/kubernetes/base/secrets.yaml @@ -8,37 +8,37 @@ metadata: app.kubernetes.io/component: database type: Opaque data: - # Database Users (base64 encoded) - AUTH_DB_USER: YmFrZXJ5X2F1dGg= # bakery_auth - TENANT_DB_USER: YmFrZXJ5X3RlbmFudA== # bakery_tenant - TRAINING_DB_USER: YmFrZXJ5X3RyYWluaW5n # bakery_training - FORECASTING_DB_USER: YmFrZXJ5X2ZvcmVjYXN0aW5n # bakery_forecasting - SALES_DB_USER: YmFrZXJ5X3NhbGVz # bakery_sales - EXTERNAL_DB_USER: YmFrZXJ5X2V4dGVybmFs # bakery_external - NOTIFICATION_DB_USER: YmFrZXJ5X25vdGlmaWNhdGlvbg== # bakery_notification - INVENTORY_DB_USER: YmFrZXJ5X2ludmVudG9yeQ== # bakery_inventory - RECIPES_DB_USER: YmFrZXJ5X3JlY2lwZXM= # bakery_recipes - SUPPLIERS_DB_USER: YmFrZXJ5X3N1cHBsaWVycw== # bakery_suppliers - POS_DB_USER: YmFrZXJ5X3Bvcw== # bakery_pos - ORDERS_DB_USER: YmFrZXJ5X29yZGVycw== # bakery_orders - PRODUCTION_DB_USER: YmFrZXJ5X3Byb2R1Y3Rpb24= # bakery_production - ALERT_PROCESSOR_DB_USER: YmFrZXJ5X2FsZXJ0X3Byb2Nlc3Nvcg== # bakery_alert_processor + # Database Users (base64 encoded from .env) + AUTH_DB_USER: YXV0aF91c2Vy # auth_user + TENANT_DB_USER: dGVuYW50X3VzZXI= # tenant_user + TRAINING_DB_USER: dHJhaW5pbmdfdXNlcg== # training_user + FORECASTING_DB_USER: Zm9yZWNhc3RpbmdfdXNlcg== # forecasting_user + SALES_DB_USER: c2FsZXNfdXNlcg== # sales_user + EXTERNAL_DB_USER: ZXh0ZXJuYWxfdXNlcg== # external_user + NOTIFICATION_DB_USER: bm90aWZpY2F0aW9uX3VzZXI= # notification_user + INVENTORY_DB_USER: aW52ZW50b3J5X3VzZXI= # inventory_user + RECIPES_DB_USER: cmVjaXBlc191c2Vy # recipes_user + SUPPLIERS_DB_USER: c3VwcGxpZXJzX3VzZXI= # suppliers_user + POS_DB_USER: cG9zX3VzZXI= # pos_user + ORDERS_DB_USER: b3JkZXJzX3VzZXI= # orders_user + PRODUCTION_DB_USER: cHJvZHVjdGlvbl91c2Vy # production_user + ALERT_PROCESSOR_DB_USER: YWxlcnRfcHJvY2Vzc29yX3VzZXI= # alert_processor_user - # Database Passwords (base64 encoded - change these in production!) - AUTH_DB_PASSWORD: ZGV2X3Bhc3N3b3JkXzEyMw== # dev_password_123 - TENANT_DB_PASSWORD: ZGV2X3Bhc3N3b3JkXzEyMw== # dev_password_123 - TRAINING_DB_PASSWORD: ZGV2X3Bhc3N3b3JkXzEyMw== # dev_password_123 - FORECASTING_DB_PASSWORD: ZGV2X3Bhc3N3b3JkXzEyMw== # dev_password_123 - SALES_DB_PASSWORD: ZGV2X3Bhc3N3b3JkXzEyMw== # dev_password_123 - EXTERNAL_DB_PASSWORD: ZGV2X3Bhc3N3b3JkXzEyMw== # dev_password_123 - NOTIFICATION_DB_PASSWORD: ZGV2X3Bhc3N3b3JkXzEyMw== # dev_password_123 - INVENTORY_DB_PASSWORD: ZGV2X3Bhc3N3b3JkXzEyMw== # dev_password_123 - RECIPES_DB_PASSWORD: ZGV2X3Bhc3N3b3JkXzEyMw== # dev_password_123 - SUPPLIERS_DB_PASSWORD: ZGV2X3Bhc3N3b3JkXzEyMw== # dev_password_123 - POS_DB_PASSWORD: ZGV2X3Bhc3N3b3JkXzEyMw== # dev_password_123 - ORDERS_DB_PASSWORD: ZGV2X3Bhc3N3b3JkXzEyMw== # dev_password_123 - PRODUCTION_DB_PASSWORD: ZGV2X3Bhc3N3b3JkXzEyMw== # dev_password_123 - ALERT_PROCESSOR_DB_PASSWORD: ZGV2X3Bhc3N3b3JkXzEyMw== # dev_password_123 + # Database Passwords (base64 encoded from .env) + AUTH_DB_PASSWORD: YXV0aF9wYXNzMTIz # auth_pass123 + TENANT_DB_PASSWORD: dGVuYW50X3Bhc3MxMjM= # tenant_pass123 + TRAINING_DB_PASSWORD: dHJhaW5pbmdfcGFzczEyMw== # training_pass123 + FORECASTING_DB_PASSWORD: Zm9yZWNhc3RpbmdfcGFzczEyMw== # forecasting_pass123 + SALES_DB_PASSWORD: c2FsZXNfcGFzczEyMw== # sales_pass123 + EXTERNAL_DB_PASSWORD: ZXh0ZXJuYWxfcGFzczEyMw== # external_pass123 + NOTIFICATION_DB_PASSWORD: bm90aWZpY2F0aW9uX3Bhc3MxMjM= # notification_pass123 + INVENTORY_DB_PASSWORD: aW52ZW50b3J5X3Bhc3MxMjM= # inventory_pass123 + RECIPES_DB_PASSWORD: cmVjaXBlc19wYXNzMTIz # recipes_pass123 + SUPPLIERS_DB_PASSWORD: c3VwcGxpZXJzX3Bhc3MxMjM= # suppliers_pass123 + POS_DB_PASSWORD: cG9zX3Bhc3MxMjM= # pos_pass123 + ORDERS_DB_PASSWORD: b3JkZXJzX3Bhc3MxMjM= # orders_pass123 + PRODUCTION_DB_PASSWORD: cHJvZHVjdGlvbl9wYXNzMTIz # production_pass123 + ALERT_PROCESSOR_DB_PASSWORD: YWxlcnRfcHJvY2Vzc29yX3Bhc3MxMjM= # alert_processor_pass123 --- apiVersion: v1 @@ -51,7 +51,7 @@ metadata: app.kubernetes.io/component: redis type: Opaque data: - REDIS_PASSWORD: ZGV2X3JlZGlzXzEyMw== # dev_redis_123 + REDIS_PASSWORD: cmVkaXNfcGFzczEyMw== # redis_pass123 --- apiVersion: v1 @@ -64,8 +64,9 @@ metadata: app.kubernetes.io/component: rabbitmq type: Opaque data: - RABBITMQ_USER: YmFrZXJ5X3VzZXI= # bakery_user - RABBITMQ_PASSWORD: ZGV2X3JhYmJpdF8xMjM= # dev_rabbit_123 + RABBITMQ_USER: YmFrZXJ5 # bakery + RABBITMQ_PASSWORD: Zm9yZWNhc3QxMjM= # forecast123 + RABBITMQ_ERLANG_COOKIE: YmFrZXJ5LXNlY3JldC1jb29raWU= # bakery-secret-cookie --- apiVersion: v1 @@ -78,8 +79,51 @@ metadata: app.kubernetes.io/component: auth type: Opaque data: - JWT_SECRET_KEY: ZGV2X2p3dF9zZWNyZXRfa2V5XzEyMzQ1Njc4OTA= # dev_jwt_secret_key_1234567890 - JWT_REFRESH_SECRET_KEY: ZGV2X2p3dF9yZWZyZXNoX3NlY3JldF9rZXlfMTIzNDU2Nzg5MA== # dev_jwt_refresh_secret_key_1234567890 + JWT_SECRET_KEY: eW91ci1zdXBlci1zZWNyZXQtand0LWtleS1jaGFuZ2UtaW4tcHJvZHVjdGlvbi1taW4tMzItY2hhcmFjdGVycy1sb25n # your-super-secret-jwt-key-change-in-production-min-32-characters-long + JWT_REFRESH_SECRET_KEY: eW91ci1zdXBlci1zZWNyZXQtcmVmcmVzaC1qd3Qta2V5LWNoYW5nZS1pbi1wcm9kdWN0aW9uLW1pbi0zMi1jaGFyYWN0ZXJzLWxvbmc= # your-super-secret-refresh-jwt-key-change-in-production-min-32-characters-long + SERVICE_API_KEY: c2VydmljZS1hcGkta2V5LWNoYW5nZS1pbi1wcm9kdWN0aW9u # service-api-key-change-in-production + +--- +apiVersion: v1 +kind: Secret +metadata: + name: external-api-secrets + namespace: bakery-ia + labels: + app.kubernetes.io/name: bakery-ia + app.kubernetes.io/component: external-apis +type: Opaque +data: + AEMET_API_KEY: ZXlKaGJHY2lPaUpJVXpJMU5pSjkuZXlKemRXSWlPaUoxWVd4bVlYSnZRR2R0WVdsc0xtTnZiU0lzSW1wMGFTSTZJbVJqWldWbU5URXdMVGRtWXpFdE5HTXhOeTFoT0RaaUxXUTROemRsWkRjNVpEbGxOeUlzSW1semN5STZJa0ZGVFVWVUlpd2lhV0YwSWpveE56VXlPRE13TURnM0xDSjFjMlZ5U1dRaU9pSmtZMlZsWmpVeE1DMDNabU14TFRSak1UY3RZVGcyWkMxa09EYzNaV1EzT1dRNVpUY2lMQ0p5YjJ4bElqb2lJbjAuQzA0N2dhaUVoV2hINEl0RGdrSFN3ZzhIektUend3ODdUT1BUSTJSZ01mOGotMnc= + MADRID_OPENDATA_API_KEY: eW91ci1tYWRyaWQtb3BlbmRhdGEta2V5LWhlcmU= # your-madrid-opendata-key-here + +--- +apiVersion: v1 +kind: Secret +metadata: + name: payment-secrets + namespace: bakery-ia + labels: + app.kubernetes.io/name: bakery-ia + app.kubernetes.io/component: payments +type: Opaque +data: + STRIPE_SECRET_KEY: c2tfdGVzdF95b3VyX3N0cmlwZV9zZWNyZXRfa2V5X2hlcmU= # sk_test_your_stripe_secret_key_here + STRIPE_WEBHOOK_SECRET: d2hzZWNfeW91cl9zdHJpcGVfd2ViaG9va19zZWNyZXRfaGVyZQ== # whsec_your_stripe_webhook_secret_here + +--- +apiVersion: v1 +kind: Secret +metadata: + name: email-secrets + namespace: bakery-ia + labels: + app.kubernetes.io/name: bakery-ia + app.kubernetes.io/component: notifications +type: Opaque +data: + SMTP_USER: eW91ci1lbWFpbEBnbWFpbC5jb20= # your-email@gmail.com + SMTP_PASSWORD: eW91ci1hcHAtc3BlY2lmaWMtcGFzc3dvcmQ= # your-app-specific-password --- apiVersion: v1 @@ -93,4 +137,42 @@ metadata: type: Opaque data: GRAFANA_ADMIN_USER: YWRtaW4= # admin - GRAFANA_ADMIN_PASSWORD: ZGV2X2dyYWZhbmFfMTIz # dev_grafana_123 \ No newline at end of file + GRAFANA_ADMIN_PASSWORD: YWRtaW4xMjM= # admin123 + GRAFANA_SECRET_KEY: Z3JhZmFuYS1zZWNyZXQta2V5LWNoYW5nZS1pbi1wcm9kdWN0aW9u # grafana-secret-key-change-in-production + PGADMIN_EMAIL: YWRtaW5AYmFrZXJ5LmxvY2Fs # admin@bakery.local + PGADMIN_PASSWORD: YWRtaW4xMjM= # admin123 + REDIS_COMMANDER_USER: YWRtaW4= # admin + REDIS_COMMANDER_PASSWORD: YWRtaW4xMjM= # admin123 + +--- +apiVersion: v1 +kind: Secret +metadata: + name: pos-integration-secrets + namespace: bakery-ia + labels: + app.kubernetes.io/name: bakery-ia + app.kubernetes.io/component: pos +type: Opaque +data: + SQUARE_ACCESS_TOKEN: eW91ci1zcXVhcmUtYWNjZXNzLXRva2Vu # your-square-access-token + SQUARE_WEBHOOK_SECRET: eW91ci1zcXVhcmUtd2ViaG9vay1zZWNyZXQ= # your-square-webhook-secret + TOAST_API_KEY: eW91ci10b2FzdC1hcGkta2V5 # your-toast-api-key + TOAST_API_SECRET: eW91ci10b2FzdC1hcGktc2VjcmV0 # your-toast-api-secret + TOAST_WEBHOOK_SECRET: eW91ci10b2FzdC13ZWJob29rLXNlY3JldA== # your-toast-webhook-secret + LIGHTSPEED_API_KEY: eW91ci1saWdodHNwZWVkLWFwaS1rZXk= # your-lightspeed-api-key + LIGHTSPEED_API_SECRET: eW91ci1saWdodHNwZWVkLWFwaS1zZWNyZXQ= # your-lightspeed-api-secret + LIGHTSPEED_WEBHOOK_SECRET: eW91ci1saWdodHNwZWVkLXdlYmhvb2stc2VjcmV0 # your-lightspeed-webhook-secret + +--- +apiVersion: v1 +kind: Secret +metadata: + name: whatsapp-secrets + namespace: bakery-ia + labels: + app.kubernetes.io/name: bakery-ia + app.kubernetes.io/component: notifications +type: Opaque +data: + WHATSAPP_API_KEY: eW91ci13aGF0c2FwcC1hcGkta2V5LWhlcmU= # your-whatsapp-api-key-here \ No newline at end of file diff --git a/infrastructure/kubernetes/overlays/dev/dev-patches.yaml b/infrastructure/kubernetes/overlays/dev/dev-patches.yaml index 5699ea50..494d33fb 100644 --- a/infrastructure/kubernetes/overlays/dev/dev-patches.yaml +++ b/infrastructure/kubernetes/overlays/dev/dev-patches.yaml @@ -5,12 +5,18 @@ metadata: namespace: bakery-ia data: # Development specific overrides + ENVIRONMENT: "development" DEBUG: "true" LOG_LEVEL: "DEBUG" AUTO_RELOAD: "true" PROFILING_ENABLED: "true" MOCK_EXTERNAL_APIS: "true" + # Frontend Development Configuration + VITE_ENVIRONMENT: "development" + VITE_API_URL: "http://gateway-service:8000" + + --- apiVersion: networking.k8s.io/v1 kind: Ingress diff --git a/infrastructure/kubernetes/overlays/dev/kustomization.yaml b/infrastructure/kubernetes/overlays/dev/kustomization.yaml index 9cd23c66..be1dee9f 100644 --- a/infrastructure/kubernetes/overlays/dev/kustomization.yaml +++ b/infrastructure/kubernetes/overlays/dev/kustomization.yaml @@ -12,6 +12,101 @@ resources: patchesStrategicMerge: - dev-patches.yaml +patchesJson6902: + - target: + group: apps + version: v1 + kind: Deployment + name: auth-db + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "128Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: redis + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "64Mi" + cpu: "50m" + limits: + memory: "128Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: rabbitmq + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "128Mi" + cpu: "100m" + limits: + memory: "256Mi" + cpu: "300m" + - target: + group: apps + version: v1 + kind: Deployment + name: auth-service + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "128Mi" + cpu: "50m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: frontend + patch: |- + - op: replace + path: /spec/template/spec/containers/0/imagePullPolicy + value: Never + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "128Mi" + cpu: "50m" + limits: + memory: "256Mi" + cpu: "200m" + - target: + group: apps + version: v1 + kind: Deployment + name: alert-processor-service + patch: |- + - op: replace + path: /spec/template/spec/containers/0/resources + value: + requests: + memory: "128Mi" + cpu: "50m" + limits: + memory: "256Mi" + cpu: "200m" + configMapGenerator: - name: bakery-dev-config literals: @@ -26,9 +121,11 @@ secretGenerator: literals: - DEV_MODE=true -commonLabels: - environment: development - tier: local +labels: + - includeSelectors: true + pairs: + environment: development + tier: local images: - name: bakery/auth-service diff --git a/services/auth/app/core/config.py b/services/auth/app/core/config.py index 70887b1e..bf7d6655 100644 --- a/services/auth/app/core/config.py +++ b/services/auth/app/core/config.py @@ -13,12 +13,12 @@ import os class AuthSettings(BaseServiceSettings): """Auth service specific settings""" - + # Service Identity APP_NAME: str = "Authentication Service" SERVICE_NAME: str = "auth-service" DESCRIPTION: str = "User authentication and authorization service" - + # Database configuration (secure approach - build from components) @property def DATABASE_URL(self) -> str: diff --git a/shared/config/base.py b/shared/config/base.py index 8273c98f..4a72e871 100644 --- a/shared/config/base.py +++ b/shared/config/base.py @@ -40,9 +40,9 @@ class BaseServiceSettings(BaseSettings): # ================================================================ # DATABASE CONFIGURATION # ================================================================ - - # Primary database URL (should be overridden by each service) - DATABASE_URL: str = os.getenv("DATABASE_URL", "") + + # Note: DATABASE_URL is defined as a property in each service-specific config + # to construct the URL from secure environment variables # Database connection settings DB_POOL_SIZE: int = int(os.getenv("DB_POOL_SIZE", "10")) @@ -75,8 +75,23 @@ class BaseServiceSettings(BaseSettings): # ================================================================ # RABBITMQ CONFIGURATION # ================================================================ - - RABBITMQ_URL: str = os.getenv("RABBITMQ_URL", "amqp://bakery:forecast123@rabbitmq:5672/") + + @property + def RABBITMQ_URL(self) -> str: + """Build RabbitMQ URL from secure components""" + # Try complete URL first (for backward compatibility) + complete_url = os.getenv("RABBITMQ_URL") + if complete_url: + return complete_url + + # Build from components (secure approach) + user = os.getenv("RABBITMQ_USER", "bakery") + password = os.getenv("RABBITMQ_PASSWORD", "forecast123") + host = os.getenv("RABBITMQ_HOST", "rabbitmq-service") + port = os.getenv("RABBITMQ_PORT", "5672") + vhost = os.getenv("RABBITMQ_VHOST", "/") + + return f"amqp://{user}:{password}@{host}:{port}{vhost}" RABBITMQ_EXCHANGE: str = os.getenv("RABBITMQ_EXCHANGE", "bakery_events") RABBITMQ_QUEUE_PREFIX: str = os.getenv("RABBITMQ_QUEUE_PREFIX", "bakery") RABBITMQ_RETRY_ATTEMPTS: int = int(os.getenv("RABBITMQ_RETRY_ATTEMPTS", "3"))