Lucien Cartier-Tilet e577fb5095 test(cors): write tests for build_cors() function (TDD red)
Add failing test cases for the CORS configuration builder function.
Tests verify correct initialization of CorsSettings with allowed origins,
credentials, and max age configuration. These tests fail until build_cors()
is implemented in the green phase.

Ref: T013 (specs/001-modbus-relay-control)
2026-01-22 00:57:11 +01:00
2026-01-11 00:39:18 +01:00
2026-01-11 00:39:18 +01:00
2026-01-11 00:39:18 +01:00
2026-01-11 00:39:18 +01:00

STA - Smart Temperature & Appliance Control

🤖 AI-Assisted Development Notice: This project uses Claude Code as a development assistant for task planning, code organization, and workflow management. However, all code is human-written, reviewed, and validated by the project maintainer. AI is used as a productivity tool, not as the author of the implementation.

Web-based Modbus relay control system for managing 8-channel relay modules over TCP.

⚠️ Development Status: This project is in early development. Core features are currently being implemented following a specification-driven approach.

Overview

STA will provide a modern web interface for controlling Modbus-compatible relay devices, eliminating the need for specialized industrial software. The goal is to enable browser-based relay control with real-time status updates.

Current Status

Phase 1 Complete - Foundation:

  • Monorepo structure (backend + frontend at root)
  • Rust web server with Poem 3.1 framework
  • Configuration system (YAML + environment variables)
  • Modbus TCP and relay settings structures
  • Health check and metadata API endpoints
  • OpenAPI documentation with Swagger UI
  • Rate limiting middleware
  • CORS middleware (configurable for production)
  • SQLite schema and repository for relay labels
  • Vue 3 + TypeScript frontend scaffolding with Vite
  • Type-safe API client generation from OpenAPI specs

Phase 0.5 In Progress - CORS Configuration:

  • T009: CorsSettings tests written (TDD)
  • T010: CorsSettings struct implemented with fail-safe defaults
  • 🚧 T011-T016: YAML configuration and middleware integration

Phase 2 Planned - Domain Layer:

  • 📋 Domain types with Type-Driven Development (RelayId, RelayState, RelayLabel)
  • 📋 100% test coverage for domain layer

Planned - Phases 3-8:

  • 📋 Modbus TCP client with tokio-modbus (Phase 3)
  • 📋 Mock controller for testing (Phase 3)
  • 📋 Health monitoring service (Phase 3)
  • 📋 US1: Monitor & toggle relay states - MVP (Phase 4)
  • 📋 US2: Bulk relay controls (Phase 5)
  • 📋 US3: Health status display (Phase 6)
  • 📋 US4: Relay labeling (Phase 7)
  • 📋 Production deployment (Phase 8)

See tasks.md for detailed implementation roadmap (102 tasks across 9 phases).

Architecture

Current:

  • Backend: Rust 2024 with Poem web framework
  • Configuration: YAML-based with environment variable overrides
  • API: RESTful HTTP with OpenAPI documentation
  • CORS: Configurable middleware for production security

Planned:

  • Modbus Integration: tokio-modbus for Modbus TCP communication
  • Frontend: Vue 3 with TypeScript
  • Deployment: Backend on Raspberry Pi, frontend on Cloudflare Pages
  • Access: Traefik reverse proxy with Authelia authentication
  • Persistence: SQLite for relay labels and configuration

Quick Start

Prerequisites

  • Rust 1.83+ (edition 2024)
  • Just command runner

Development

# Run development server
just run

# Run tests
just test

# Run linter
just lint

# Format code
just format

# Watch mode with bacon
bacon          # clippy-all (default)
bacon test     # test watcher

Configuration

Edit settings/base.yaml for Modbus device settings:

modbus:
  host: "192.168.0.200"
  port: 502
  slave_id: 0
  timeout_secs: 5

relay:
  label_max_length: 50

Override with environment variables:

APP__MODBUS__HOST=192.168.1.100 cargo run

CORS Configuration

For development with frontend on localhost:5173:

# backend/settings/development.yaml
cors:
  allowed_origins:
    - "*"
  allow_credentials: false
  max_age_secs: 3600

For production with frontend on Cloudflare Pages:

# backend/settings/production.yaml
cors:
  allowed_origins:
    - "https://sta.example.com"
  allow_credentials: true  # Required for Authelia authentication
  max_age_secs: 3600

See CORS Configuration Guide for complete documentation.

API Documentation

The server provides OpenAPI documentation via Swagger UI:

  • Swagger UI: http://localhost:3100/
  • OpenAPI Spec: http://localhost:3100/openapi.json

Current Endpoints:

  • GET /api/health - Health check endpoint
  • GET /api/meta - Application metadata

Planned Endpoints (see spec):

  • GET /api/relays - List all relay states
  • POST /api/relays/{id}/toggle - Toggle relay state
  • POST /api/relays/all/on - Turn all relays on
  • POST /api/relays/all/off - Turn all relays off
  • PUT /api/relays/{id}/label - Set relay label

Project Structure

Monorepo Layout:

sta/                          # Repository root
├── backend/                  # Rust backend workspace member
│   ├── src/
│   │   ├── lib.rs           - Library entry point
│   │   ├── main.rs          - Binary entry point
│   │   ├── startup.rs       - Application builder and server config
│   │   ├── settings.rs      - Configuration management
│   │   ├── telemetry.rs     - Logging and tracing setup
│   │   ├── domain/          - Business logic (planned Phase 2)
│   │   │   └── relay/       - Relay domain types and repository traits
│   │   ├── application/     - Use cases (planned Phase 3-4)
│   │   ├── infrastructure/  - External integrations (Phase 3)
│   │   │   └── persistence/ - SQLite repository implementation
│   │   ├── presentation/    - API layer (planned Phase 4)
│   │   ├── route/           - HTTP endpoint handlers
│   │   │   ├── health.rs    - Health check endpoints
│   │   │   └── meta.rs      - Application metadata
│   │   └── middleware/      - Custom middleware
│   │       └── rate_limit.rs
│   ├── settings/            - YAML configuration files
│   └── tests/               - Integration tests
├── src/                     # Frontend source (Vue/TypeScript)
│   └── api/                 - Type-safe API client
├── docs/                    # Project documentation
│   ├── cors-configuration.md    - CORS setup guide
│   └── Modbus_POE_ETH_Relay.md - Hardware documentation
├── specs/                   # Feature specifications
│   ├── constitution.md      - Architectural principles
│   └── 001-modbus-relay-control/
│       ├── spec.md          - Feature specification
│       ├── plan.md          - Implementation plan
│       ├── tasks.md         - Task breakdown (102 tasks)
│       └── research-cors.md - CORS configuration research
├── package.json             - Frontend dependencies
├── vite.config.ts          - Vite build configuration
└── justfile                 - Build commands

Technology Stack

Currently Used:

  • Rust 2024 edition
  • Poem 3.1 (web framework with OpenAPI support)
  • Tokio 1.48 (async runtime)
  • config (YAML configuration)
  • tracing + tracing-subscriber (structured logging)
  • governor (rate limiting)
  • thiserror (error handling)
  • serde + serde_yaml (configuration deserialization)

Planned Dependencies:

  • tokio-modbus 0.17 (Modbus TCP client)
  • SQLx 0.8 (async SQLite database access)
  • mockall 0.13 (mocking for tests)

Frontend (scaffolding complete):

  • Vue 3 + TypeScript
  • Vite build tool
  • openapi-typescript (type-safe API client generation)

Documentation

Configuration Guides

Development Guides

License

This project is under the AGPL-3.0 license. You can find it in the LICENSE.md file.

Description
Smart Temperature & Appliance control
Readme 1.1 MiB
Languages
Rust 95.4%
TypeScript 1.6%
Nix 1.4%
Vue 0.6%
CSS 0.5%
Other 0.5%