From 0ff507f67dc0b004488bb1c389bec92590a3ebf5 Mon Sep 17 00:00:00 2001 From: gabogg Date: Thu, 11 Jun 2026 13:43:34 +0000 Subject: [PATCH] feat: add dual-container compose configuration and test environment specifications --- docker-compose.yml | 66 +++++++++++++++++++++++++++++++ docs/AI_DEVELOPER_WORKSTATION.md | 30 ++++++++++++++ docs/ARCHITECTURE.md | 67 +++++++++++++++++++++++++------- 3 files changed, 149 insertions(+), 14 deletions(-) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..ee0aa3c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,66 @@ +version: '3.8' + +services: + # ----------------------------------------------------------------------------- + # Production Application Instance + # ----------------------------------------------------------------------------- + app-prod: + build: + context: . + dockerfile: Dockerfile + container_name: special-hotel-prod + restart: unless-stopped + ports: + - "127.0.0.1:3000:3000" + environment: + - NODE_ENV=production + - DATABASE_URL=${DATABASE_URL} + - NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL} + - NEXTAUTH_SECRET=${NEXTAUTH_SECRET} + - N8N_WEBHOOK_URL=${N8N_WEBHOOK_URL} + - N8N_WEBHOOK_SECRET=${N8N_WEBHOOK_SECRET} + # Log tag prefix for syslog / journald, or environment labeling for standard output + logging: + driver: "json-file" + options: + tag: "app-prod/{{.Name}}" + max-size: "10m" + max-file: "3" + + # ----------------------------------------------------------------------------- + # Development & Testing Application Instance + # ----------------------------------------------------------------------------- + app-dev: + build: + context: . + dockerfile: Dockerfile + container_name: special-hotel-dev + restart: no # Do not auto-restart if variables are missing or if it gracefully stops + ports: + - "127.0.0.1:3001:3000" + environment: + - NODE_ENV=development + - DATABASE_URL=${DATABASE_URL_DEV} + - TEST_DATABASE_URL=${TEST_DATABASE_URL} + - NEXT_PUBLIC_APP_URL=${NEXT_PUBLIC_APP_URL_DEV} + - NEXTAUTH_SECRET=${NEXTAUTH_SECRET_DEV} + - N8N_TEST_WEBHOOK_URL=${N8N_TEST_WEBHOOK_URL} + - N8N_WEBHOOK_SECRET=${N8N_WEBHOOK_SECRET_DEV} + # Commands run a pre-startup verification. If development-exclusive + # variables are missing, it logs a warning and exits with code 0 (graceful exit). + entrypoint: > + /bin/sh -c " + if [ -z \"$${TEST_DATABASE_URL}\" ] || [ -z \"$${N8N_TEST_WEBHOOK_URL}\" ]; then + echo '[DEV] Required development-exclusive variables (TEST_DATABASE_URL, N8N_TEST_WEBHOOK_URL) are missing.'; + echo '[DEV] Gracefully shutting down the development service with exit code 0.'; + exit 0; + fi; + echo '[DEV] Starting Next.js development server...'; + exec npm run dev + " + logging: + driver: "json-file" + options: + tag: "app-dev/{{.Name}}" + max-size: "10m" + max-file: "3" diff --git a/docs/AI_DEVELOPER_WORKSTATION.md b/docs/AI_DEVELOPER_WORKSTATION.md index 06046d8..4b85bdd 100644 --- a/docs/AI_DEVELOPER_WORKSTATION.md +++ b/docs/AI_DEVELOPER_WORKSTATION.md @@ -201,4 +201,34 @@ With `tea` configured, you can manage pull requests directly from the repository * **Merge a PR**: `tea pulls merge ` * **Approve/Review a PR**: `tea pulls review --approve` +--- + +## 4. Testing Procedures & Webhook Testing Flow + +Testing must occur in complete isolation from production data. We achieve this by splitting execution paths using dedicated test hooks in both Next.js and n8n. + +### 4.1. Development & Test Variables Configuration +During test executions (such as running Jest, Cypress, or integration suites), the application uses the following development-exclusive variables: +* `TEST_DATABASE_URL`: Dedicated database connection URL for test schemas (e.g. `postgresql://.../special_hotel_test`). Migrations are run here independently. +* `N8N_TEST_WEBHOOK_URL`: The specific path n8n exposes for test triggers. + +### 4.2. n8n Testing Webhook Routing +All calculations triggered by test suites route to n8n via `/webhook-test` path segments: +1. **Trigger**: Test suite invokes n8n via `POST ${process.env.N8N_TEST_WEBHOOK_URL}/calculate-commissions`. +2. **n8n Path Branching**: + - Within the n8n canvas, an **`IF` node** checks: `{{ $json.headers["x-nginx-original-uri"] || $json.path }}` contains `webhook-test`. + - **True**: The n8n workspace connects to the database utilizing `TEST_DATABASE_URL` credentials. It pulls test sales/goals data and pushes calculations back to the Next.js dev API. + - **False**: Connects to the main `DATABASE_URL` for production processing. + +### 4.3. Running Integration Tests Locally +To run the full sandbox locally: +1. Spin up both databases: `docker compose up -d postgres-dev postgres-test`. +2. Run database migrations on the test database: + ```bash + DATABASE_URL=$TEST_DATABASE_URL npx prisma migrate deploy + ``` +3. Run the Next.js development server (which connects to the dev database by default, but switches API routing to test endpoints under integration scripts). +4. Run testing script: `npm run test:integration`. + + diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index ca1997a..4f4d1aa 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -18,23 +18,30 @@ ## 2. Decoupled Network & Environment Independence -The project is structured to run in any isolated Docker environment. All parameters are fed via environment variables: +The project is structured to run in any isolated Docker environment. All parameters are fed via environment variables to cleanly partition production and development configurations: -* `DATABASE_URL`: Connection string for PostgreSQL (e.g. `postgresql://user:pass@host:port/dbname`). -* `N8N_WEBHOOK_URL`: The entry point for the n8n workflow engine. -* `N8N_API_KEY`: Token to authorize callbacks from n8n to the Next.js API. -* `NEXTAUTH_SECRET`: Secret for securing JWT cookies. +### 2.1. Environment Variables +* **Core Variables (Both Env)**: + * `DATABASE_URL`: Connection string for the active database (Production or Development). + * `NEXT_PUBLIC_APP_URL`: The domain or local host path of the running application. + * `NEXTAUTH_SECRET`: Secret key for JWT session validation. +* **Development-Exclusive Test Variables**: + * `TEST_DATABASE_URL`: Connection string to the secondary sandbox/test database. + * `N8N_TEST_WEBHOOK_URL`: The n8n testing webhook entry point. Used by development services and test runners. + * `N8N_WEBHOOK_SECRET`: Token to authorize and verify n8n webhook payload signatures locally. -### Component Interaction: +### 2.2. Component Interaction: ```mermaid graph TD User([User Client]) -->|HTTPS| WebApp[Next.js App Router] subgraph Isolated Network - WebApp -->|Prisma Client| DB[(PostgreSQL)] - WebApp -->|HTTP POST Webhook| n8n[n8n Workflow Engine] + WebApp -->|Prisma Client| DB[(PostgreSQL Main)] + WebApp -.->|Prisma Client - Test Env| DBTest[(PostgreSQL Test)] + WebApp -->|HTTP POST Webhook /webhook-test| n8n[n8n Workflow Engine] + n8n -->|IF Webhook Path Match| DBTest + n8n -->|Else| DB n8n -->|HTTP POST Callback| WebApp - n8n -->|Interact| LLM[AI Model / Provider] end ``` @@ -190,11 +197,21 @@ By offloading calculations and integrations to n8n, we achieve a highly visual, ### 4.2. Settlement Calculation Workflow 1. **Trigger**: Next.js calls n8n to execute the calculation for period `YYYY-MM`. 2. **n8n Processing**: - - Pulls active plans, individual goals, and actual sales from the Next.js API. - - Evaluates the mathematical formulas. - - Evaluates rule scales and applies caps. - - Generates notifications (via email or push notifications) using n8n integrations. -3. **Response**: Updates database records via the Next.js API and completes the task. + - Pulls active plans, individual goals, and actual sales from the Next.js API. + - Evaluates the mathematical formulas. + - Evaluates rule scales and applies caps. + - Generates notifications (via email or push notifications) using n8n integrations. + 3. **Response**: Updates database records via the Next.js API and completes the task. + +### 4.3. Test Webhook Branching & Database Isolation in n8n +To ensure complete isolation of production data, all n8n workflows must follow a strict testing branch architecture: +1. **Webhook Entry Node**: n8n listens on two webhook path variants: + - Production calls hit: `/webhook/calculate-commissions` + - Test suite calls hit: `/webhook-test/calculate-commissions` +2. **Conditional Path Routing**: + - An `IF` node immediately checks if the webhook request path contains `webhook-test`. + - **True (Test Mode)**: The workflow overrides its database credential node configurations to connect to `TEST_DATABASE_URL` (the secondary test sandbox database) and makes API callbacks back to the Next.js test instance. + - **False (Prod Mode)**: The workflow executes against the main `DATABASE_URL` and interacts with the production Next.js instance. --- @@ -211,3 +228,25 @@ We define role-based access restrictions as follows: | **Analista Financiero** | Reviews calculations. Exports consolidated PDF/Excel reports. | Cannot approve. | | **Consulta** | Read-only. | No mutations allowed. | | **Colaborador** | Consults own history & dashboard. | Restricted to `user_id`. | + +--- + +## 6. Dual-Environment Docker Deployment Model + +We design the containerized architecture to run two distinct instances of the application concurrently from the same codebase, ensuring clean division. + +### 6.1. Service Configurations +* **Production Container (`app-prod`)**: + * **Network Port**: Exposed on port `3000` (mapped via Caddy to `special-hotel.yourdomain.com`). + * **Database**: Bound to the production `DATABASE_URL`. + * **Logs**: Prefixed with `[PROD]` inside the container engine. +* **Development Container (`app-dev`)**: + * **Network Port**: Exposed on port `3001` (mapped via Caddy to `special-hotel-dev.yourdomain.com`). + * **Database**: Bound to `TEST_DATABASE_URL` (acting as its main `DATABASE_URL` for test isolated migrations). + * **Logs**: Prefixed with `[DEV]` for easy debugging contrast. + +### 6.2. Graceful Dev Failure Model +The development instance utilizes a validation startup hook. If any development-exclusive environment variables (like `TEST_DATABASE_URL`) are omitted: +1. The `app-dev` container logs a clear notification: `[DEV] Missing required development variables. Gracefully shutting down development service.` +2. The entrypoint script exits with **exit code 0**. +3. Docker or the compose orchestrator registers the container as cleanly stopped (not crashed). The production stack is completely unaffected, avoiding restart-loop penalties or deployment failures.