2026-01-01 16:26:00 +01:00
# STA - Smart Temperature & Appliance Control
2026-01-01 23:29:31 +01:00
> **🤖 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.
2026-01-01 16:26:00 +01:00
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
2026-01-03 19:14:30 +01:00
### Phase 1 Complete - Foundation
2026-01-01 23:29:31 +01:00
- ✅ Monorepo structure (backend + frontend at root)
- ✅ Rust web server with Poem 3.1 framework
2026-01-01 16:26:00 +01:00
- ✅ Configuration system (YAML + environment variables)
2026-01-01 23:29:31 +01:00
- ✅ Modbus TCP and relay settings structures
2026-01-01 16:26:00 +01:00
- ✅ Health check and metadata API endpoints
- ✅ OpenAPI documentation with Swagger UI
- ✅ Rate limiting middleware
2026-01-01 23:29:31 +01:00
- ✅ SQLite schema and repository for relay labels
- ✅ Vue 3 + TypeScript frontend scaffolding with Vite
- ✅ Type-safe API client generation from OpenAPI specs
2026-01-03 19:14:30 +01:00
### Phase 0.5 Complete - CORS Configuration & Production Security
- ✅ T009: CorsSettings struct with comprehensive unit tests (5 tests)
- ✅ T010: CorsSettings implementation with restrictive fail-safe defaults
- ✅ T011: Development YAML configuration with permissive CORS
- ✅ T012: Production YAML configuration with restrictive CORS
- ✅ T013: From<CorsSettings> for Cors trait unit tests (6 tests)
- ✅ T014: From<CorsSettings> for Cors implementation with security validation
- ✅ T015: Middleware chain integration using From trait
- ✅ T016: Integration tests for CORS headers (9 comprehensive tests)
#### Key CORS Features Implemented
- Environment-specific CORS configuration (development vs production)
- Wildcard origin support for development (`allowed_origins: ["*"]` )
- Multiple specific origins for production
- Credentials support for Authelia authentication
- Security validation (prevents wildcard + credentials)
- Configurable preflight cache duration
- Hardcoded secure methods and headers
- Structured logging for CORS configuration
- Comprehensive test coverage (15 tests total)
2026-01-04 00:18:47 +01:00
### Phase 2 Complete - Domain Layer (Type-Driven Development)
- ✅ T017-T018: RelayId newtype with 1-8 validation and zero-cost abstraction
- ✅ T019-T020: RelayState enum (On/Off) with serialization support
- ✅ T021-T022: Relay aggregate with state control methods (toggle, turn_on, turn_off)
- ✅ T023-T024: RelayLabel newtype with 1-50 character validation
- ✅ T025-T026: ModbusAddress type with From<RelayId> trait (1-8 → 0-7 offset mapping)
- ✅ T027: HealthStatus enum with state machine (Healthy/Degraded/Unhealthy)
#### Key Domain Layer Features Implemented
- 100% test coverage for domain layer (50+ comprehensive tests)
- Zero external dependencies (pure business logic)
- All newtypes use `#[repr(transparent)]` for zero-cost abstractions
- Smart constructors with `Result<T, E>` for type-safe validation
- TDD workflow (red-green-refactor) for all implementations
- RelayController and RelayLabelRepository trait definitions
- Complete separation from infrastructure concerns (hexagonal architecture)
2026-01-01 23:29:31 +01:00
2026-01-03 19:14:30 +01:00
### Planned - Phases 3-8
2026-01-01 23:29:31 +01:00
- 📋 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)
2026-01-01 23:29:31 +01:00
See [tasks.md ](specs/001-modbus-relay-control/tasks.md ) for detailed implementation roadmap (102 tasks across 9 phases).
2026-01-01 16:26:00 +01:00
## Architecture
**Current:**
- **Backend**: Rust 2024 with Poem web framework
- **Configuration**: YAML-based with environment variable overrides
- **API**: RESTful HTTP with OpenAPI documentation
2026-01-03 19:14:30 +01:00
- **CORS**: Production-ready configurable middleware with security validation
- **Middleware Chain**: Rate Limiting → CORS → Data injection
2026-01-01 16:26:00 +01:00
**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
```bash
# 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
2026-01-03 19:14:30 +01:00
Edit `backend/settings/base.yaml` for Modbus device settings:
2026-01-01 16:26:00 +01:00
```yaml
modbus:
host: "192.168.0.200"
port: 502
slave_id: 0
timeout_secs: 5
relay:
label_max_length: 50
```
Override with environment variables:
```bash
APP__MODBUS__HOST=192.168.1.100 cargo run
```
2026-01-01 23:29:31 +01:00
#### CORS Configuration
2026-01-03 19:14:30 +01:00
**Development Mode** (frontend on `localhost:5173` ):
2026-01-01 23:29:31 +01:00
```yaml
# backend/settings/development.yaml
cors:
allowed_origins:
2026-01-03 19:14:30 +01:00
- "*" # Permissive for local development
allow_credentials: false # MUST be false with wildcard
2026-01-01 23:29:31 +01:00
max_age_secs: 3600
```
2026-01-03 19:14:30 +01:00
**Production Mode** (frontend on Cloudflare Pages):
2026-01-01 23:29:31 +01:00
```yaml
# backend/settings/production.yaml
cors:
allowed_origins:
2026-01-03 19:14:30 +01:00
- "https://sta.yourdomain.com" # Specific origin only
2026-01-01 23:29:31 +01:00
allow_credentials: true # Required for Authelia authentication
max_age_secs: 3600
```
2026-01-03 19:14:30 +01:00
**Security Notes:**
- Wildcard `"*"` origin is **only allowed with `allow_credentials: false` **
- Production **must ** use specific origins (e.g., `https://sta.example.com` )
- Multiple origins are supported as a list
- Credentials must be enabled for Authelia authentication to work
**Hardcoded Security Defaults:**
- **Methods**: GET, POST, PUT, PATCH, DELETE, OPTIONS (all required methods)
- **Headers**: content-type, authorization (minimum for API + auth)
**Fail-Safe Defaults:**
- `allowed_origins: []` (restrictive - no origins allowed)
- `allow_credentials: false`
- `max_age_secs: 3600` (1 hour)
2026-01-01 23:29:31 +01:00
See [CORS Configuration Guide ](docs/cors-configuration.md ) for complete documentation.
2026-01-01 16:26:00 +01:00
## API Documentation
The server provides OpenAPI documentation via Swagger UI:
2026-01-01 23:29:31 +01:00
- Swagger UI: `http://localhost:3100/`
2026-01-03 19:14:30 +01:00
- OpenAPI Spec: `http://localhost:3100/specs`
2026-01-01 16:26:00 +01:00
**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
2026-01-01 23:29:31 +01:00
**Monorepo Layout:**
2026-01-01 16:26:00 +01:00
```
2026-01-01 23:29:31 +01:00
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
2026-01-03 19:14:30 +01:00
│ │ ├── settings/ - Configuration module
│ │ │ ├── mod.rs - Settings aggregation
│ │ │ └── cors.rs - CORS configuration (NEW in Phase 0.5)
2026-01-01 23:29:31 +01:00
│ │ ├── telemetry.rs - Logging and tracing setup
2026-01-04 00:18:47 +01:00
│ │ ├── domain/ - Business logic (NEW in Phase 2)
│ │ │ ├── relay/ - Relay domain types, entity, and traits
│ │ │ │ ├── types/ - RelayId, RelayState, RelayLabel newtypes
│ │ │ │ ├── entity.rs - Relay aggregate
│ │ │ │ ├── controller.rs - RelayController trait
│ │ │ │ └── repository.rs - RelayLabelRepository trait
│ │ │ ├── modbus.rs - ModbusAddress type with conversion
│ │ │ └── health.rs - HealthStatus state machine
2026-01-01 23:29:31 +01:00
│ │ ├── 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
2026-01-03 19:14:30 +01:00
│ │ ├── base.yaml - Base configuration
│ │ ├── development.yaml - Development overrides (NEW in Phase 0.5)
│ │ └── production.yaml - Production overrides (NEW in Phase 0.5)
2026-01-01 23:29:31 +01:00
│ └── tests/ - Integration tests
2026-01-03 19:14:30 +01:00
│ └── cors_test.rs - CORS integration tests (NEW in Phase 0.5)
2026-01-01 23:29:31 +01:00
├── src/ # Frontend source (Vue/TypeScript)
│ └── api/ - Type-safe API client
2026-01-01 23:29:31 +01:00
├── docs/ # Project documentation
│ ├── cors-configuration.md - CORS setup guide
2026-01-04 00:18:47 +01:00
│ ├── domain-layer.md - Domain layer architecture (NEW in Phase 2)
│ └── Modbus_POE_ETH_Relay.md - Hardware documentation
2026-01-01 23:29:31 +01:00
├── specs/ # Feature specifications
2026-01-01 23:29:31 +01:00
│ ├── constitution.md - Architectural principles
│ └── 001-modbus-relay-control/
│ ├── spec.md - Feature specification
│ ├── plan.md - Implementation plan
2026-01-01 23:29:31 +01:00
│ ├── tasks.md - Task breakdown (102 tasks)
2026-01-04 00:18:47 +01:00
│ ├── domain-layer-architecture.md - Domain layer docs (NEW in Phase 2)
│ ├── lessons-learned.md - Phase 2 insights (NEW in Phase 2)
│ └── research-cors.md - CORS configuration research
2026-01-01 23:29:31 +01:00
├── package.json - Frontend dependencies
├── vite.config.ts - Vite build configuration
└── justfile - Build commands
2026-01-01 16:26:00 +01:00
```
## 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)
2026-01-01 23:29:31 +01:00
- serde + serde_yaml (configuration deserialization)
2026-01-01 16:26:00 +01:00
**Planned Dependencies:**
- tokio-modbus 0.17 (Modbus TCP client)
- SQLx 0.8 (async SQLite database access)
- mockall 0.13 (mocking for tests)
2026-01-01 23:29:31 +01:00
**Frontend** (scaffolding complete):
2026-01-01 16:26:00 +01:00
- Vue 3 + TypeScript
- Vite build tool
2026-01-01 23:29:31 +01:00
- openapi-typescript (type-safe API client generation)
2026-01-01 16:26:00 +01:00
2026-01-03 19:14:30 +01:00
## Testing Strategy
**Phase 0.5 CORS Testing:**
- **Unit Tests**: 11 tests in `backend/src/settings/cors.rs`
- CorsSettings deserialization (5 tests)
- From<CorsSettings> for Cors trait (6 tests)
- Security validation (wildcard + credentials check)
- **Integration Tests**: 9 tests in `backend/tests/cors_test.rs`
- Preflight OPTIONS requests
- Actual request CORS headers
- Max-age configuration
- Credentials handling
- Allowed methods verification
- Wildcard origin behavior
- Multiple origins support
- Unauthorized origin rejection
**Test Coverage Achieved**: 15 comprehensive tests covering all CORS scenarios
2026-01-04 00:18:47 +01:00
**Phase 2 Domain Layer Testing:**
- **Unit Tests**: 50+ tests embedded in domain modules
- RelayId validation (5 tests)
- RelayState serialization (3 tests)
- RelayLabel validation (5 tests)
- Relay aggregate behavior (8 tests)
- ModbusAddress conversion (3 tests)
- HealthStatus state transitions (15 tests)
- **TDD Approach**: Red-Green-Refactor for all implementations
- **Coverage**: 100% for domain layer (zero external dependencies)
**Test Coverage Achieved**: 100% domain layer coverage with comprehensive test suites
2026-01-01 16:26:00 +01:00
## Documentation
2026-01-01 23:29:31 +01:00
### Configuration Guides
- [CORS Configuration ](docs/cors-configuration.md ) - Cross-origin setup for frontend-backend communication
- [Modbus Hardware Documentation ](docs/Modbus_POE_ETH_Relay.md ) - 8-channel relay device documentation
2026-01-04 00:18:47 +01:00
### Architecture Documentation
- [Domain Layer Architecture ](docs/domain-layer.md ) - Type-driven domain design and implementation
- [Domain Layer Details ](specs/001-modbus-relay-control/domain-layer-architecture.md ) - Comprehensive domain layer documentation
- [Phase 2 Lessons Learned ](specs/001-modbus-relay-control/lessons-learned.md ) - Implementation insights and best practices
2026-01-01 23:29:31 +01:00
### Development Guides
2026-01-01 16:26:00 +01:00
- [Project Constitution ](specs/constitution.md ) - Architectural principles and development guidelines
- [Modbus Relay Control Spec ](specs/001-modbus-relay-control/spec.md ) - Feature specification
- [CLAUDE.md ](CLAUDE.md ) - Developer guide and code style rules
## License
This project is under the AGPL-3.0 license. You can find it in the [LICENSE.md ](LICENSE.md ) file.