docs: update documentation of STA

This commit is contained in:
2026-05-15 10:01:36 +02:00
parent 94105a040c
commit 8cf13503da
9 changed files with 266 additions and 288 deletions

View File

@@ -1,8 +1,8 @@
# CORS Configuration Guide
**Last Updated**: 2026-01-03
**Related Tasks**: T009 (Tests), T010 (Implementation)
**Status**: Implemented (Phase 0.5)
**Last Updated**: 2026-01-23
**Related Tasks**: T009-T016
**Status**: Complete (Phase 0.5)
## Overview
@@ -44,7 +44,7 @@ Relay Device (local network)
### CorsSettings Struct
Located in `backend/src/settings.rs` (lines 217-232):
Located in `backend/src/settings/cors.rs`:
```rust
#[derive(Debug, serde::Deserialize, Clone)]
@@ -76,7 +76,7 @@ The implementation uses a **hybrid approach** (Option C from research):
- `allow_credentials`: Whether to allow cookies/auth headers
- `max_age_secs`: How long browsers cache preflight responses
**Hardcoded in Implementation** (will be in T014):
**Hardcoded in Implementation**:
- **Methods**: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS` (API-specific)
- **Headers**: `content-type`, `authorization` (minimum for API)
@@ -109,7 +109,7 @@ frontend_url: http://localhost:5173 # Vite default port
### Production Environment
**File**: `backend/settings/production.yaml` (to be created in T012)
**File**: `backend/settings/production.yaml`
```yaml
cors:
@@ -129,23 +129,7 @@ frontend_url: "https://sta.example.com"
### Integration with Settings System
The `CorsSettings` struct is integrated into the main `Settings` struct (line 30):
```rust
#[derive(Debug, serde::Deserialize, Clone, Default)]
pub struct Settings {
pub application: ApplicationSettings,
pub debug: bool,
pub frontend_url: String,
pub rate_limit: RateLimitSettings,
pub modbus: ModbusSettings,
pub relay: RelaySettings,
#[serde(default)] // Uses Default::default() if missing
pub cors: CorsSettings,
}
```
The `#[serde(default)]` attribute ensures backward compatibility: if the `cors` section is missing from YAML, it uses the restrictive `Default` implementation.
The `CorsSettings` struct is part of the settings module. Settings are loaded with `#[serde(default)]` to ensure backward compatibility: if the `cors` section is missing from YAML, it uses the restrictive `Default` implementation.
### Loading and Precedence
@@ -318,7 +302,7 @@ cargo test -p sta cors -- --nocapture
**Browser Security Policy**: When `allow_credentials: true`, wildcard origins (`*`) are **forbidden** by the CORS specification.
**Enforcement**: The upcoming `build_cors()` function (T014) will panic during startup if this constraint is violated:
**Enforcement**: The `From<CorsSettings> for Cors` implementation panics during startup if this constraint is violated:
```rust
if settings.allow_credentials && settings.allowed_origins.contains(&"*".to_string()) {
@@ -427,11 +411,9 @@ cors:
### Preflight Requests Failing (OPTIONS)
**Cause**: Backend not allowing OPTIONS method (will be fixed in T014).
**Cause**: Backend not allowing OPTIONS method.
**Temporary Workaround**: None - wait for T014 implementation.
**Permanent Solution**: The upcoming `build_cors()` function will hardcode:
**Solution**: The `From<CorsSettings> for Cors` trait implementation hardcodes OPTIONS in the allowed methods:
```rust
cors.allow_methods(vec![
Method::GET, Method::POST, Method::PUT,
@@ -454,13 +436,13 @@ cors.allow_methods(vec![
### Headers Not Allowed
**Cause**: Custom headers not in allowed list (will be in T014).
**Cause**: Custom headers not in allowed list.
**Current Allowed Headers** (to be implemented):
**Current Allowed Headers**:
- `content-type` (for JSON request bodies)
- `authorization` (for Authelia authentication tokens)
**Adding Custom Headers**: Requires modifying `build_cors()` function (T014).
**Adding Custom Headers**: Requires modifying the `From<CorsSettings> for Cors` trait implementation.
## Dependencies
@@ -481,37 +463,43 @@ serde_yaml = "0.9.34"
| File | Purpose |
|------|---------|
| `backend/src/settings.rs` | `CorsSettings` struct definition |
| `backend/settings/base.yaml` | Baseline configuration (no CORS section yet) |
| `backend/src/settings/cors.rs` | `CorsSettings` struct definition |
| `backend/settings/base.yaml` | Baseline configuration |
| `backend/settings/development.yaml` | Development CORS (permissive) |
| `backend/settings/production.yaml` | Production CORS (restrictive) - to be created in T012 |
| `backend/settings/production.yaml` | Production CORS (restrictive) |
## Next Steps (Remaining Tasks)
## Completed Tasks
### T011: Update development.yaml
- Add `cors:` section with permissive settings
- Update `frontend_url` to `http://localhost:5173` (Vite default)
All CORS configuration tasks (T009-T016) have been implemented and tested:
### T012: Create production.yaml
- Add `cors:` section with restrictive settings
- Use `https://sta.example.com` as allowed origin
- Set `allow_credentials: true` for Authelia
### T009-T010: CorsSettings Struct (Phase 0.5)
- 5 unit tests written (TDD approach) and the `CorsSettings` struct implemented with fail-safe defaults
- Located in `backend/src/settings/cors.rs`
### T013-T014: Implement build_cors() Function
- Create `build_cors(settings: &CorsSettings) -> Cors` in `startup.rs`
- Validate wildcard + credentials constraint
- Hardcode methods (GET, POST, PUT, PATCH, DELETE, OPTIONS)
- Hardcode headers (content-type, authorization)
- Add structured logging
### T011: Development YAML Configuration
- Added `cors:` section with wildcard origin and `allow_credentials: false`
- Updated `frontend_url` to `http://localhost:5173` (Vite default)
- File: `backend/settings/development.yaml`
### T015: Replace Cors::new() in Middleware Chain
- Update `startup.rs` line ~86
- Call `build_cors(&value.settings.cors)`
### T012: Production YAML Configuration
- Added `cors:` section with specific origin and `allow_credentials: true`
- File: `backend/settings/production.yaml`
### T013-T014: Cors Middleware Implementation
- 6 unit tests written for the `From<CorsSettings> for Cors` trait
- Implemented the conversion trait in `backend/src/settings/cors.rs`
- Validates wildcard + credentials constraint (panics on misconfiguration)
- Hardcodes methods (GET, POST, PUT, PATCH, DELETE, OPTIONS)
- Hardcodes headers (content-type, authorization)
- Adds structured logging
### T015: Middleware Chain Integration
- Replaced `Cors::new()` with `Cors::from(settings.cors)` in startup.rs
- CORS applied after rate limiting (order: RateLimit → CORS → Data)
### T016: Integration Tests
- Write tests verifying CORS headers in HTTP responses
- Test OPTIONS preflight requests
- Verify `Access-Control-Allow-Origin` header
- 9 comprehensive integration tests in `backend/tests/cors_test.rs`
- Covers: preflight requests, actual request headers, max-age, credentials, methods, wildcard, multiple origins, unauthorized origin rejection
## References
@@ -533,7 +521,10 @@ serde_yaml = "0.9.34"
| 2026-01-03 | T009 | Test suite written (5 tests, TDD approach) |
| 2026-01-03 | T010 | `CorsSettings` struct implemented with defaults |
| 2026-01-03 | Documentation | This guide created |
| 2026-01-22 | T013-T014 | `From<CorsSettings> for Cors` trait implemented |
| 2026-01-22 | T015 | CORS middleware integrated into startup chain |
| 2026-01-22 | T016 | 9 integration tests written and passing |
---
**Maintainer Notes**: This configuration follows the project's **Type-Driven Development (TyDD)** and **Test-Driven Development (TDD)** principles. Tests were written first (T009), then the implementation (T010) was created to pass those tests. The upcoming `build_cors()` function (T014) will complete the CORS feature by applying these settings to the Poem middleware chain.
**Maintainer Notes**: This configuration follows the project's **Type-Driven Development (TyDD)** and **Test-Driven Development (TDD)** principles. Tests were written first (T009, T013), then implementations were created to pass those tests. The CORS feature is fully implemented and tested across all environments.