summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.cursorrules174
-rw-r--r--.woodpecker/lint.yml4
-rw-r--r--.woodpecker/rust-test.yml2
-rw-r--r--README.md77
4 files changed, 254 insertions, 3 deletions
diff --git a/.cursorrules b/.cursorrules
new file mode 100644
index 0000000..4438139
--- /dev/null
+++ b/.cursorrules
@@ -0,0 +1,174 @@
+# Rust Rules
+
+## 🧱 Project Architecture
+
+### **Modular Design**
+
+* Organize code into **crates** and **modules**:
+
+ * Use a **workspace** for multi-crate projects (`Cargo.toml` + `Cargo.lock` at root).
+ * Split concerns into crates: e.g., `core`, `network`, `storage`, `cli`, `web`, `domain`, `infra`.
+* Avoid monoliths β€” design for composability.
+
+### **Layered Architecture**
+
+Separate by **responsibility**, not technology:
+
+* **Domain layer** – business logic, domain models, pure logic, no dependencies.
+* **Application layer** – use-cases, orchestrators, service interfaces.
+* **Infrastructure layer** – database, HTTP clients, FS, external APIs.
+* **Presentation layer** – CLI, gRPC, REST API, etc.
+
+Use traits to **abstract interfaces** between layers.
+
+---
+
+## πŸ“¦ Crate and Module Hygiene
+
+### **Use Visibility Thoughtfully**
+
+* Keep as much private (`pub(crate)` or private) as possible.
+* Use `mod.rs` sparingly β€” prefer flat `mod_x.rs` and `mod x;` where possible.
+* Keep `lib.rs` or `main.rs` minimal β€” just wiring and top-level declarations.
+
+### **Predeclare your modules**
+
+Explicitly declare modules in parent files, avoiding implicit module discovery:
+
+```rust
+mod domain;
+mod services;
+```
+
+---
+
+## 🧠 Code Design and Idioms
+
+### **Prefer Composition Over Inheritance**
+
+* Favor structs + traits over enums for extensibility.
+* Use `impl Trait` for abstraction and `dyn Trait` for dynamic dispatch when needed.
+
+### **Minimize Unnecessary Abstractions**
+
+* Don't abstract over one implementation β€” wait for the second one.
+* Don’t use traits where a simple function will do.
+
+### **Idiomatic Error Handling**
+
+* Use `Result<T, E>`, `?`, and `thiserror` or `anyhow` (depending on layer).
+* Business logic: custom error enums (`thiserror`).
+* App layer or CLI: use `anyhow::Result` for bubble-up and crash-on-error.
+
+### **Zero-cost abstractions**
+
+* Use generics, lifetimes, borrowing, and ownership where appropriate.
+* Minimize heap allocations, unnecessary `.clone()`s.
+
+## πŸ› οΈ Tooling and Dev Experience
+
+### **Use Clippy, Rustfmt, and IDEs**
+
+* `clippy`: catch non-idiomatic code.
+* `rustfmt`: consistent formatting.
+* `cargo-expand`: inspect macro-generated code.
+
+### **Use `cargo features` for Flexibility**
+
+* Feature-gate optional deps and functionalities:
+
+```toml
+[features]
+default = ["serde"]
+cli = ["clap"]
+```
+
+## πŸ§ͺ Testing & Quality
+
+### **Test by Layer**
+
+* Unit tests for pure logic.
+* Integration tests (`tests/`) for subsystems and public interfaces.
+* End-to-end/system tests where applicable.
+
+Use `mockall` or `double` for mocking when interface testing is needed.
+
+### **Property-based test* Study open-source Rust projects like `ripgrep`, `tokio`, `tower`, `axum`, or `zellij`.
+ing**
+
+* Use `proptest` for verifying correctness over ranges of inputs.
+
+## πŸ“ˆ Performance and Safety
+
+### **Measure Before Optimizing**
+
+* Use `cargo bench`, `criterion`, `perf`, or `flamegraph` for real profiling.
+* Don't optimize until there's a clear need.
+
+### **Minimize Unsafe Code**
+
+* Keep `unsafe` blocks minimal, justified, and well-documented.
+* Use crates like `bytemuck`, `zeroize`, or `unsafe-libyaml` only when needed.
+
+## πŸ“š Dependency Hygiene
+
+### **Minimal and Audited Dependencies**
+
+* Prefer well-maintained, minimal, audited crates.
+* Avoid depending on "kitchen sink" crates unless unavoidable.
+* Regularly check for security updates via `cargo audit`.
+
+## 🧾 Documentation & Maintainability
+
+### **Document Public APIs and Crates**
+
+* Use `//!` and `///` comments.
+* Auto-generate docs with `cargo doc --open`.
+
+### **Conventional Naming**
+
+* Stick to Rust conventions: `snake_case` for functions and variables, `PascalCase` for types.
+
+## ☁️ Async, Concurrency, and IO
+
+### **Choose Your Runtime Wisely**
+
+* `tokio`: for production-grade, multi-core async workloads.
+* `async-std`: if you prefer a more "standard" style.
+* Use `tracing` instead of `log` for structured async-aware logging.
+
+### **Limit Shared Mutable State**
+
+* Prefer ownership and message passing (`tokio::sync::mpsc`, `crossbeam`, `flume`) over `Arc<Mutex<T>>`.
+* Avoid global mutable state unless it’s guarded and justified.
+
+### **Reproducible Builds**
+
+* Pin versions where critical.
+* Use lockfiles even in libraries (`[package] publish = false` in internal crates).
+
+## πŸ“ Example Folder Structure
+
+```text
+my-app/
+β”œβ”€β”€ Cargo.toml
+β”œβ”€β”€ Cargo.lock
+β”œβ”€β”€ crates/
+β”‚ β”œβ”€β”€ core/
+β”‚ β”œβ”€β”€ api/
+β”‚ β”œβ”€β”€ domain/
+β”‚ └── storage/
+β”œβ”€β”€ bin/
+β”‚ └── cli.rs
+β”œβ”€β”€ tests/
+β”‚ └── integration.rs
+β”œβ”€β”€ docs/
+β”‚ └── architecture.md
+```
+
+## 🧭 Final Advice
+
+* Think in **lifetimes**, **ownership**, and **borrowing**.
+* Design for **testability** and **composability**.
+* Don't fight the compiler β€” **embrace it as your co-architect**.
+* Be conservative with third-party crates β€” **audit and isolate** them if needed.
diff --git a/.woodpecker/lint.yml b/.woodpecker/lint.yml
index a32ae83..e3c45d6 100644
--- a/.woodpecker/lint.yml
+++ b/.woodpecker/lint.yml
@@ -27,7 +27,7 @@ steps:
- pull_request
- name: rust-fmt
- image: rust:1.76
+ image: rust:1.88
commands:
- cargo fmt --all -- --check
when:
@@ -35,7 +35,7 @@ steps:
- pull_request
- name: rust-clippy
- image: rust:1.76
+ image: rust:1.88
commands:
- cargo clippy --all-targets --all-features -- -D warnings
when:
diff --git a/.woodpecker/rust-test.yml b/.woodpecker/rust-test.yml
index ba9d16a..e25f00d 100644
--- a/.woodpecker/rust-test.yml
+++ b/.woodpecker/rust-test.yml
@@ -2,7 +2,7 @@ when:
event: pull_request
steps:
- name: test
- image: rust:1.76
+ image: rust:1.88
commands:
- cargo test --all
when:
diff --git a/README.md b/README.md
index 6faebe1..61248fd 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,7 @@
Silmataivas is a weather monitoring service that sends personalized alerts based on user-defined thresholds and notification preferences. This is the Rust version, providing a RESTful API for managing users, locations, weather thresholds, and notification settings.
## Features
+
- Weather monitoring using OpenWeatherMap API
- Custom weather thresholds per user
- Flexible notifications: NTFY (push) and SMTP (email)
@@ -10,6 +11,7 @@ Silmataivas is a weather monitoring service that sends personalized alerts based
- RESTful API for all resources
## Project Structure
+
- **src/main.rs**: All application logic and API endpoints (no lib.rs, not a library)
- **src/**: Modules for users, locations, notifications, weather thresholds, etc.
- **migrations/**: SQL migrations for SQLite
@@ -18,10 +20,12 @@ Silmataivas is a weather monitoring service that sends personalized alerts based
## Quick Start
### Prerequisites
+
- Rust (see [rustup.rs](https://rustup.rs/))
- SQLite (default, or set `DATABASE_URL` for PostgreSQL)
### Running Locally
+
```bash
# Clone the repository
git clone https://codeberg.org/silmataivas/silmataivas.git
@@ -35,12 +39,14 @@ Silmataivas is a weather monitoring service that sends personalized alerts based
The server will listen on port 4000 by default. You can set the `DATABASE_URL` environment variable to change the database location.
### Using Docker
+
```bash
docker build -t silmataivas .
docker run -p 4000:4000 -e DATABASE_URL=sqlite:///data/silmataivas.db silmataivas
```
## API Usage
+
All API endpoints (except `/health`) require authentication using a Bearer token:
```
@@ -50,17 +56,88 @@ Authorization: Bearer <user_id>
See the source code for endpoint details. (OpenAPI docs are not yet auto-generated in this Rust version.)
## Migration Note
+
This project was previously implemented in Elixir/Phoenix. All Elixir/Phoenix code, references, and setup instructions have been removed. The project is now a Rust binary only (no library, no Elixir code).
## Development
+
- Format: `cargo fmt`
- Lint: `cargo clippy`
- Test: `cargo test`
## Contributing
+
- Use conventional commits for PRs
- See the code for module structure and API details
---
For any issues or questions, please open an issue on Codeberg.
+
+## TODO
+
+### βœ… Project Completion Checklist for Weather Monitoring App
+
+#### 🧱 Architecture & Code Quality
+
+- [ ] Centralized error handling (e.g., `thiserror`, `anyhow`, `IntoResponse`)
+- [ ] Organize code into service/domain/modules to improve separation of concerns
+- [ ] Add rate limiting/backoff for OpenWeather API usage
+- [ ] Write unit tests for core logic (e.g., user CRUD, weather checks)
+- [ ] Add integration tests for full API endpoints
+- [ ] Benchmark endpoint latency and cold-start performance
+
+#### πŸ”’ Security
+
+- [ ] Ensure proper SQL injection protection (`sqlx` should cover this, but verify inputs)
+- [ ] Review CORS and CSRF protection for web endpoints
+- [ ] Validate and sanitize all environment variables at startup
+- [ ] Secure storage for SMTP/Ntfy credentials (env vars or secret store)
+
+#### πŸ”­ Observability & Monitoring
+
+- [ ] Add `/healthz` and `/metrics` endpoints (e.g., Prometheus)
+- [ ] Use structured logging (`tracing` spans for request lifecycle)
+- [ ] Consider log rotation or persistent log storage
+- [ ] Alerting or notifications if cron job fails
+
+#### βš™οΈ CLI & Deployment
+
+- [ ] Build CLI for DB/settings management (with help output and scripting support)
+- [ ] Implement DB backup or export functionality (even for SQLite)
+- [ ] Enable SQLite WAL mode and regular vacuuming
+- [ ] Add install/setup instructions to CLI or README
+
+#### πŸ§‘β€πŸ’» Web Interface (MVP)
+
+- [ ] Add a minimal web UI (htmx, Yew, or static + API)
+- [ ] Ensure UI is responsive/mobile friendly
+- [ ] Add form to configure thresholds, ntfy/smtp, location, etc.
+- [ ] Web UI: Add table or list of current weather rules
+
+#### β˜€οΈ Weather & Notifications Logic
+
+- [ ] Only send notification on threshold **crossing**, not on every cron run
+- [ ] Allow multiple thresholds per user (e.g., temp < 0Β°C and wind > 30km/h)
+- [ ] Store basic history of weather checks (for debugging/trends)
+- [ ] Abstract weather provider to allow future plug-ins (e.g., Tomorrow.io, Meteomatics)
+
+#### πŸ§ͺ Testing & QA
+
+- [ ] Add CI test for API correctness (user + notification config CRUD)
+- [ ] Add e2e test for full flow: create user β†’ set threshold β†’ trigger alert
+- [ ] Add test for OpenAPI schema consistency
+
+#### πŸ“¦ Open Source Readiness
+
+- [ ] Add detailed README with setup, architecture overview, and usage
+- [ ] Add LICENSE file
+- [ ] Add `CONTRIBUTING.md` with basic guide
+- [ ] Add `.env.example` with defaults
+- [ ] Add changelog or release notes for future versions
+
+#### πŸš€ Final Steps
+
+- [ ] Deploy to production server
+- [ ] Verify Docker Compose deployment with CLI and web UI
+- [ ] Publish initial release/tag on Codeberg