Task graph covers all Phase 1 concerns: config system, TLS termination, proxy handler, operations (rate limiting, logging, health check, admin socket, signals, shutdown, body size limit), deployment artifacts, and two review checkpoints. No circular dependencies. Critical path length of 7. Risk distribution: 3 high-risk (ACME, TLS listener setup, startup orchestration), 7 medium, 11 low, 2 trivial.
74 lines
3.1 KiB
Markdown
74 lines
3.1 KiB
Markdown
---
|
|
id: config/static-config
|
|
name: Implement StaticConfig, ListenerConfig, TlsConfig, and LoggingConfig structs with TOML deserialization
|
|
status: pending
|
|
depends_on: [setup/project-init]
|
|
scope: moderate
|
|
risk: low
|
|
impact: component
|
|
level: implementation
|
|
---
|
|
|
|
## Description
|
|
|
|
Implement the static configuration structs that are immutable after startup. These are deserialized from the TOML config file and validated at startup. Changes to static config require a process restart.
|
|
|
|
### Structs to Implement
|
|
|
|
**StaticConfig** (top-level, immutable after startup):
|
|
- `listeners: Vec<ListenerConfig>` — at least one required
|
|
- `allow_wildcard_bind: bool` — default `false`
|
|
- `health_check_port: u16` — default `9900`, `0` to disable
|
|
- `admin_socket_path: String` — default `/run/reverse-proxy/admin.sock`, empty string to disable
|
|
- `shutdown_timeout_secs: u64` — default `30`
|
|
- `logging: LoggingConfig`
|
|
|
|
**LoggingConfig** (nested in `[logging]`):
|
|
- `level: String` — default `"info"`
|
|
- `format: String` — default `"text"`
|
|
- `log_file_path: Option<String>` — optional, enables file logging when set
|
|
|
|
**ListenerConfig** (per `[[listeners]]`):
|
|
- `bind_addr: String` — required
|
|
- `http_port: u16` — default `80`, `0` to disable
|
|
- `https_port: u16` — default `443`
|
|
- `tls: TlsConfig`
|
|
- `sites: Vec<SiteConfig>` — sites defined per listener (moved to global routing in DynamicConfig)
|
|
|
|
**TlsConfig** (nested in `[listeners.tls]`):
|
|
- `mode: String` — `"acme"` or `"manual"`
|
|
- ACME fields: `acme_domains`, `acme_cache_dir`, `acme_directory`
|
|
- Manual fields: `cert_path`, `key_path`
|
|
|
|
**SiteConfig** (per `[[listeners.sites]]`):
|
|
- `host: String` — hostname to match
|
|
- `upstream: String` — `host:port` format
|
|
- `upstream_scheme: String` — default `"http"`
|
|
- `upstream_connect_timeout_secs: u64` — default `5`
|
|
- `upstream_request_timeout_secs: u64` — default `60`
|
|
|
|
All structs derive `Debug`, `Clone`, `serde::Deserialize`. Use serde defaults for optional fields.
|
|
|
|
## Acceptance Criteria
|
|
|
|
- [ ] `StaticConfig`, `LoggingConfig`, `ListenerConfig`, `TlsConfig`, and `SiteConfig` structs defined with correct fields and types
|
|
- [ ] All structs derive `Debug`, `Clone`, `serde::Deserialize`
|
|
- [ ] Default values implemented per config.md defaults table
|
|
- [ ] TOML deserialization works for both multi-config (dedicated-IP) and shared-IP (SAN certificate) config formats
|
|
- [ ] Unit tests verify deserialization of both example configs from config.md
|
|
- [ ] `cargo check` and `cargo test` succeed
|
|
|
|
## References
|
|
|
|
- docs/architecture/config.md — full config structure, defaults, TOML format
|
|
- docs/architecture/decisions/003-toml-config.md — TOML format decision
|
|
- docs/architecture/decisions/008-static-dynamic-config-split.md — static/dynamic split rationale
|
|
- docs/architecture/decisions/019-multi-config-listeners.md — `[[listeners]]` format
|
|
|
|
## Notes
|
|
|
|
> SiteConfig is defined per-listener in TOML but collected into a global routing table in DynamicConfig. The per-listener definition is just for config organization; at runtime, hostnames must be unique across all listeners.
|
|
|
|
## Summary
|
|
|
|
> To be filled on completion |