CORS implemented in a static manner: unable to configure on another machine
This commit is contained in:
34
specs/008-deploy-to-hosting/checklists/requirements.md
Normal file
34
specs/008-deploy-to-hosting/checklists/requirements.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# Specification Quality Checklist: Deploy to Hosting
|
||||
|
||||
**Purpose**: Validate specification completeness and quality before proceeding to planning
|
||||
**Created**: 2025-10-15
|
||||
**Feature**: [spec.md](./spec.md)
|
||||
|
||||
## Content Quality
|
||||
|
||||
- [x] No implementation details (languages, frameworks, APIs)
|
||||
- [x] Focused on user value and business needs
|
||||
- [x] Written for non-technical stakeholders
|
||||
- [x] All mandatory sections completed
|
||||
|
||||
## Requirement Completeness
|
||||
|
||||
- [x] No [NEEDS CLARIFICATION] markers remain
|
||||
- [x] Requirements are testable and unambiguous
|
||||
- [x] Success criteria are measurable
|
||||
- [x] Success criteria are technology-agnostic (no implementation details)
|
||||
- [x] All acceptance scenarios are defined
|
||||
- [x] Edge cases are identified
|
||||
- [x] Scope is clearly bounded
|
||||
- [x] Dependencies and assumptions identified
|
||||
|
||||
## Feature Readiness
|
||||
|
||||
- [x] All functional requirements have clear acceptance criteria
|
||||
- [x] User scenarios cover primary flows
|
||||
- [x] Feature meets measurable outcomes defined in Success Criteria
|
||||
- [x] No implementation details leak into specification
|
||||
|
||||
## Notes
|
||||
|
||||
- All checks passed. The specification is ready for the next phase.
|
||||
7
specs/008-deploy-to-hosting/contracts/README.md
Normal file
7
specs/008-deploy-to-hosting/contracts/README.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# API Contracts: Deploy to Hosting
|
||||
|
||||
**Date**: 2025-10-15
|
||||
|
||||
This feature does not introduce or modify any API endpoints.
|
||||
|
||||
The changes are focused on the application's hosting configuration, specifically the CORS policy enforced by the API gateway, and do not alter the structure or behavior of the API itself.
|
||||
7
specs/008-deploy-to-hosting/data-model.md
Normal file
7
specs/008-deploy-to-hosting/data-model.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# Data Model: Deploy to Hosting
|
||||
|
||||
**Date**: 2025-10-15
|
||||
|
||||
This feature does not introduce any changes to the application's data model.
|
||||
|
||||
Its focus is on configuration and deployment, not on data persistence or structure.
|
||||
52
specs/008-deploy-to-hosting/plan.md
Normal file
52
specs/008-deploy-to-hosting/plan.md
Normal file
@@ -0,0 +1,52 @@
|
||||
# Implementation Plan: Deploy to Hosting
|
||||
|
||||
**Date**: 2025-10-15
|
||||
**Spec**: [spec.md](./spec.md)
|
||||
|
||||
## 1. Technical Context
|
||||
|
||||
This feature enables the application to be deployed to a public-facing host. The core of this work involves externalizing configuration from code to environment variables and ensuring the backend's Cross-Origin Resource Sharing (CORS) policy is configurable.
|
||||
|
||||
- **Backend**: The Node.js/Express backend will use the `cors` middleware to validate incoming request origins against a configurable whitelist provided by the `CORS_ORIGIN` environment variable.
|
||||
- **Frontend**: The React frontend will fetch the backend URL from a `REACT_APP_API_URL` environment variable, making it easy to target different backends.
|
||||
- **Deployment**: The root `docker-compose.yaml` will be modified to inject these environment variables into the respective containers using `env_file`.
|
||||
|
||||
## 2. Constitution Check
|
||||
|
||||
- [x] **I. Defined Technology Stack**: Adheres to Node.js, React, and Docker.
|
||||
- [x] **II. UI/UX Consistency**: No UI changes are required.
|
||||
- [x] **III. Container-First Development**: The solution is built entirely around enhancing the existing Docker-based workflow.
|
||||
- [x] **IV. Test-Driven Development (TDD)**: New tests will be required to validate the CORS configuration logic and error handling.
|
||||
- [x] **V. API-First Design**: No API changes are made, but the accessibility of the API is modified, which is consistent with this principle.
|
||||
|
||||
**Result**: All constitutional principles are upheld.
|
||||
|
||||
## 3. Implementation Phases
|
||||
|
||||
### Phase 0: Research & Decisions
|
||||
|
||||
Research focused on confirming the standard practices for configuration management in the existing tech stack.
|
||||
|
||||
- **Outcome**: All technical decisions have been documented.
|
||||
- **Artifact**: [research.md](./research.md)
|
||||
|
||||
### Phase 1: Design & Contracts
|
||||
|
||||
This phase defines the developer-facing instructions and confirms that no data or API contract changes are necessary.
|
||||
|
||||
- **Data Model**: No changes are required.
|
||||
- **Artifact**: [data-model.md](./data-model.md)
|
||||
- **API Contracts**: No changes are required.
|
||||
- **Artifact**: [contracts/README.md](./contracts/README.md)
|
||||
- **Developer Quickstart**: Instructions for configuring the environment for deployment have been created.
|
||||
- **Artifact**: [quickstart.md](./quickstart.md)
|
||||
|
||||
### Phase 2: Implementation Tasks
|
||||
|
||||
*(This section will be filled out by the `/speckit.tasks` command.)*
|
||||
|
||||
## 4. Validation Plan
|
||||
|
||||
- **Unit Tests**: Add backend tests to verify that the CORS middleware correctly allows whitelisted origins and rejects others.
|
||||
- **Integration Tests**: An E2E test will be created to simulate a deployment with a custom domain, ensuring the frontend can connect to the backend without CORS errors.
|
||||
- **Manual Tests**: Follow the [quickstart.md](./quickstart.md) guide to perform a full deployment and verify all functionality.
|
||||
64
specs/008-deploy-to-hosting/quickstart.md
Normal file
64
specs/008-deploy-to-hosting/quickstart.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Quickstart: Deploying to a Custom Host
|
||||
|
||||
This guide provides the steps to configure the application to run on a public-facing domain.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- A configured hosting environment with Docker and Docker Compose.
|
||||
- A public domain name pointing to your host.
|
||||
- (Optional) A reverse proxy (like Nginx or Traefik) to handle HTTPS/SSL termination.
|
||||
|
||||
## Configuration Steps
|
||||
|
||||
### 1. Backend Configuration
|
||||
|
||||
In the `backend/` directory, create a file named `.env`.
|
||||
|
||||
Add the following line to this file, replacing the URL with your **frontend's** public domain:
|
||||
|
||||
```
|
||||
CORS_ORIGIN=https://your-frontend-domain.com
|
||||
```
|
||||
|
||||
This tells the backend to accept API requests from your frontend application.
|
||||
|
||||
### 2. Frontend Configuration
|
||||
|
||||
In the `frontend/` directory, create a file named `.env`.
|
||||
|
||||
Add the following line to this file, replacing the URL with your **backend's** public API domain:
|
||||
|
||||
```
|
||||
REACT_APP_API_URL=https://api.your-domain.com
|
||||
```
|
||||
|
||||
This tells the frontend where to send its API requests.
|
||||
|
||||
### 3. Docker Compose Configuration
|
||||
|
||||
Modify the `docker-compose.yaml` file in the project root to pass these environment variables to the containers.
|
||||
|
||||
Update the `backend` and `frontend` services to include the `env_file` property:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
backend:
|
||||
# ... existing configuration ...
|
||||
env_file:
|
||||
- ./backend/.env
|
||||
|
||||
frontend:
|
||||
# ... existing configuration ...
|
||||
env_file:
|
||||
- ./frontend/.env
|
||||
```
|
||||
|
||||
### 4. Deployment
|
||||
|
||||
With the `.env` files in place and `docker-compose.yaml` updated, you can now build and run the application.
|
||||
|
||||
```bash
|
||||
docker-compose up --build -d
|
||||
```
|
||||
|
||||
The application should now be accessible at your public domain without CORS errors.
|
||||
29
specs/008-deploy-to-hosting/research.md
Normal file
29
specs/008-deploy-to-hosting/research.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Research: Deployment Configuration
|
||||
|
||||
**Date**: 2025-10-15
|
||||
|
||||
This document outlines the technical decisions made to enable deploying the application to a custom host.
|
||||
|
||||
## 1. Backend CORS Configuration
|
||||
|
||||
- **Decision**: Use the `cors` npm package in the Express.js backend to manage Cross-Origin Resource Sharing.
|
||||
- **Rationale**: It is the industry-standard, robust, and highly configurable middleware for enabling CORS in Node.js. It provides a simple way to whitelist origins, which directly addresses FR1.
|
||||
- **Alternatives Considered**: Manually setting CORS headers. This is error-prone and less maintainable than using a dedicated, well-tested library.
|
||||
|
||||
## 2. Environment-based Configuration
|
||||
|
||||
- **Decision**: All deployment-specific values (CORS origins, API URLs) will be managed through environment variables.
|
||||
- **Rationale**: This decouples configuration from the codebase, adhering to Twelve-Factor App principles. It allows developers to easily switch between `localhost` and production environments without changing code.
|
||||
- **Alternatives Considered**: Hardcoding values (violates principles), using configuration files (less flexible than environment variables in containerized environments).
|
||||
|
||||
## 3. Frontend to Backend Communication
|
||||
|
||||
- **Decision**: The frontend will use a `REACT_APP_API_URL` environment variable to determine the backend's address.
|
||||
- **Rationale**: This is the standard convention for Create React App applications. It ensures the frontend can be pointed to any backend during development or after deployment.
|
||||
- **Alternatives Considered**: None, as this is the idiomatic approach for this frontend stack.
|
||||
|
||||
## 4. Docker Configuration
|
||||
|
||||
- **Decision**: The `docker-compose.yaml` file will be updated to pass host-level environment variables into the respective `frontend` and `backend` service containers.
|
||||
- **Rationale**: This is the standard and most effective method for injecting runtime configuration into Docker Compose services, allowing for flexible deployment.
|
||||
- **Alternatives Considered**: Building separate images for each environment (inefficient), managing configuration inside the container (violates immutability principles).
|
||||
91
specs/008-deploy-to-hosting/spec.md
Normal file
91
specs/008-deploy-to-hosting/spec.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Feature Specification: Deploy to Hosting
|
||||
|
||||
**Document Status**: DRAFT
|
||||
**Last Updated**: 2025-10-15
|
||||
|
||||
## 1. Introduction
|
||||
|
||||
### 1.1. Feature Name
|
||||
|
||||
Deploy to Hosting
|
||||
|
||||
### 1.2. User Problem
|
||||
|
||||
The application is currently restricted to running on `localhost`. This prevents access from the internet and leads to Cross-Origin Resource Sharing (CORS) violations when the frontend and backend are not served from the exact same origin. Users need to deploy the application to a custom, internet-accessible host (like a NAS with DDNS) and have it function correctly.
|
||||
|
||||
### 1.3. Goals
|
||||
|
||||
- Enable the application to be deployed to a host other than `localhost`.
|
||||
- Ensure the application works seamlessly without CORS errors when accessed from a public domain.
|
||||
- Maintain the existing Docker-based deployment method.
|
||||
|
||||
## 2. Clarifications
|
||||
|
||||
### Session 2025-10-15
|
||||
|
||||
- Q: What should the user see if the frontend application fails to connect to the configured backend URL? → A: Show a simple error message in a standard snackbar.
|
||||
- Q: How should the backend log rejected cross-origin (CORS) requests? → A: Log as `WARN`.
|
||||
- Q: How should the backend behave if the list of allowed CORS origins is not configured or is empty? → A: Default to same-origin only.
|
||||
|
||||
## 3. User Experience and Design
|
||||
|
||||
### 3.1. User Scenarios
|
||||
|
||||
- **Scenario 1: Developer Configuration**
|
||||
- **Actor**: A developer or system administrator.
|
||||
- **Action**: The developer configures the application with the public domain names for the frontend and backend services. They then deploy the application using the existing Docker setup.
|
||||
- **Outcome**: The application starts successfully, configured to run on the specified public host.
|
||||
|
||||
- **Scenario 2: Public Access**
|
||||
- **Actor**: An end-user.
|
||||
- **Action**: The user navigates to the application's public URL (e.g., `https://app.my-nas.com`).
|
||||
- **Outcome**: The application loads and is fully functional. All API requests from the frontend to the backend succeed without any CORS-related errors.
|
||||
|
||||
## 4. Functional Requirements
|
||||
|
||||
### 4.1. Configuration
|
||||
|
||||
- **FR1**: The backend server **must** allow its CORS policy to be configured to accept requests from a specified list of origins.
|
||||
- **FR2**: The frontend application **must** be configurable to direct its API requests to a specified backend URL.
|
||||
- **FR3**: The Docker deployment configuration **must** use environment variables to set all host-specific values, such as domain names and ports.
|
||||
|
||||
### 4.2. Operation
|
||||
|
||||
- **FR4**: The application **must** function correctly when both frontend and backend are accessed over a secure (HTTPS) connection.
|
||||
- **FR5**: All application features available on `localhost` **must** be available and work identically when deployed to a custom host.
|
||||
|
||||
### 4.3. Error Handling
|
||||
|
||||
- **FR6**: If the frontend application cannot connect to the configured backend API, it **must** display a non-intrusive snackbar notification with a simple error message (e.g., "Error: Could not connect to the server.").
|
||||
|
||||
## 5. Non-Functional Requirements
|
||||
|
||||
### 5.1. Security
|
||||
|
||||
- **NFR1**: If the list of allowed CORS origins is not configured or is left empty, the system **must** default to a "same-origin" policy, blocking all cross-origin requests.
|
||||
|
||||
### 5.2. Observability
|
||||
|
||||
- **NFR2**: Rejected cross-origin (CORS) requests **must** be logged at a `WARN` level to facilitate troubleshooting.
|
||||
|
||||
## 6. Success Criteria
|
||||
|
||||
- **SC1**: The application is fully accessible and functional when deployed to a public domain with a valid HTTPS certificate.
|
||||
- **SC2**: No CORS errors are present in the browser's developer console during normal application use.
|
||||
- **SC3**: A developer can successfully deploy the application to a new host by solely updating environment variables and re-running the standard `docker-compose up` command.
|
||||
|
||||
## 7. Assumptions and Dependencies
|
||||
|
||||
### 7.1. Assumptions
|
||||
|
||||
- The underlying infrastructure (e.g., NAS, Docker environment, DDNS, and reverse proxy for SSL/HTTPS termination) is already configured and managed by the user.
|
||||
- The user is familiar with managing environment variables for Docker containers.
|
||||
|
||||
### 7.2. Dependencies
|
||||
|
||||
- This feature depends on a hosting environment that supports Docker and Docker Compose.
|
||||
|
||||
## 8. Out of Scope
|
||||
|
||||
- The setup or configuration of the hosting environment (NAS, DDNS, firewalls, SSL certificates).
|
||||
- The creation of automated deployment (CI/CD) pipelines.
|
||||
72
specs/008-deploy-to-hosting/tasks.md
Normal file
72
specs/008-deploy-to-hosting/tasks.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Tasks: Deploy to Hosting
|
||||
|
||||
**Date**: 2025-10-15
|
||||
**Spec**: [spec.md](./spec.md)
|
||||
**Plan**: [plan.md](./plan.md)
|
||||
|
||||
## Implementation Strategy
|
||||
|
||||
The implementation is broken into phases, starting with foundational backend changes, followed by the core configuration work, and finishing with user-facing error handling and end-to-end testing. User Story 1 (Developer Configuration) contains the critical path tasks and delivers the main goal of the feature. User Story 2 adds robustness and validation.
|
||||
|
||||
**MVP Scope**: Completing all tasks in Phase 3 will deliver a configurable and deployable application.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Setup
|
||||
|
||||
**Goal**: Add necessary dependencies to the backend service.
|
||||
|
||||
| Task ID | Description | File(s) | Status |
|
||||
|---|---|---|---|
|
||||
| T001 | [Backend] Install `cors` and `dotenv` npm packages. | `backend/package.json` | Done |
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Foundational Backend Configuration
|
||||
|
||||
**Goal**: Prepare the backend server to use environment variables.
|
||||
|
||||
| Task ID | Description | File(s) | Status |
|
||||
|---|---|---|---|
|
||||
| T002 | [Backend] Modify the server startup script to load environment variables from a `.env` file using `dotenv`. | `backend/src/index.ts` | Done |
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: User Story 1 - Developer Configuration
|
||||
|
||||
**Goal**: A developer can configure the application for public deployment using environment variables.
|
||||
**Independent Test Criteria**: After completing this phase, a developer can follow `quickstart.md`, deploy the application to a custom domain, and access it without CORS errors.
|
||||
|
||||
| Task ID | Description | File(s) | Status |
|
||||
|---|---|---|---|
|
||||
| T003 | [Backend Test] Create a new unit test file for CORS configuration. Write tests that verify the correct origin is allowed, an incorrect origin is blocked, and the default same-origin policy is applied when no environment variable is set. | `backend/tests/cors.test.ts` | Done |
|
||||
| T004 | [Backend] Implement the `cors` middleware in the Express app. The configuration should read from `process.env.CORS_ORIGIN`, log rejected requests as warnings, and apply the default same-origin policy as defined in the tests. [P] | `backend/src/index.ts` | Done |
|
||||
| T005 | [Frontend] Modify the API service(s) to use `process.env.REACT_APP_API_URL` as the base URL for all backend requests. [P] | `frontend/src/services/websocket.ts` (and any other relevant services) | Done |
|
||||
| T006 | [Root] Update the `docker-compose.yaml` file to use `env_file` to pass `.env` files to the `backend` and `frontend` services. | `docker-compose.yaml` | Done |
|
||||
|
||||
**Checkpoint**: The core feature is implemented. The application is now configurable but lacks polished error handling for the user.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: User Story 2 - Public Access & Polish
|
||||
|
||||
**Goal**: An end-user is gracefully notified of connection issues, and the deployment is validated.
|
||||
**Independent Test Criteria**: When the frontend is configured with an invalid backend URL, the user sees a snackbar error message. An E2E test confirms a successful deployment has no CORS errors.
|
||||
|
||||
| Task ID | Description | File(s) | Status |
|
||||
|---|---|---|---|
|
||||
| T007 | [Frontend] Implement a global error handler that displays a simple error message using the Material-UI (MUI) `Snackbar` component if the application fails to establish a connection with the backend. | `frontend/src/App.tsx` | Done |
|
||||
| T008 | [E2E Test] Create a new end-to-end test that deploys the application with custom environment variables and verifies that the app loads without any CORS-related console errors. [P] | `tests/e2e/deployment.e2e.test.ts` | Done |
|
||||
| T009 | [Docs] Update the root `README.md` with a new "Deployment" section that links to the `quickstart.md` guide for configuration details. [P] | `README.md` | Done |
|
||||
|
||||
---
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **Phase 1 & 2** must be completed before **Phase 3**.
|
||||
- **Phase 3** must be completed before **Phase 4**.
|
||||
|
||||
## Parallel Execution Examples
|
||||
|
||||
- **Within Phase 3**: T004 (Backend CORS) and T005 (Frontend URL) can be worked on in parallel after the test in T003 is written.
|
||||
- **Within Phase 4**: T008 (E2E Test) and T009 (Docs) can be worked on in parallel with T007 (Frontend UI).
|
||||
Reference in New Issue
Block a user