From 2347c04211daef7e67866815f6551cffe5a54598 Mon Sep 17 00:00:00 2001 From: Jeena Date: Thu, 15 Jan 2026 03:32:49 +0000 Subject: [PATCH] docs: expand development guidelines and security documentation --- AGENTS.md | 105 +++++++++++++++++++++++++++++++++++++++++++----------- README.md | 6 ++++ 2 files changed, 91 insertions(+), 20 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 20f6488..96718d7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,31 +1,96 @@ -Overview --------- - +# Overview This project is a very simple gemini server which only serves static files, nothing else. It is meant to be generic so other people can use it. -Setup -===== +# Build/Test/Lint Commands -This is a modern Rust project with the default rust setup. +## Core Commands +- `cargo build` - Build the project +- `cargo build --release` - Build optimized release version +- `cargo run` - Run the server with default config +- `cargo test` - Run all unit tests +- `cargo test ` - Run a specific test +- `cargo test ::tests` - Run tests in a specific module +- `cargo clippy` - Run linter checks +- `cargo fmt` - Format code according to Rust standards +- `cargo check` - Quick compile check without building -Security -======== +## Common Test Patterns +- `cargo test config::tests` - Run config module tests +- `cargo test request::tests` - Run request handling tests +- `cargo test -- --nocapture` - Show println output in tests -In this project cyber security is very important because we are implementing -a server which reads arbitrary data from other computers and we need to make -sure that bad actors can't break it and read random things from outside -the directory, or even worse write things. +# Code Style Guidelines -Testing -======= -We have UnitTests which should be kept up to date before committing any new code. +## Imports +- Group imports: std libs first, then external crates, then local modules +- Use `use crate::module::function` for internal imports +- Prefer specific imports over `use std::prelude::*` +- Keep imports at module level, not inside functions -Fix every compiler warning before committing. +## Code Structure +- Use `#[tokio::main]` for async main function +- Keep functions small and focused (single responsibility) +- Use `const` for configuration values that don't change +- Error handling with `Result` and `?` operator +- Use `tracing` for logging, not `println!` in production code -### Development Notes +## Naming Conventions +- `PascalCase` for types, structs, enums +- `snake_case` for functions, variables, modules +- `SCREAMING_SNAKE_CASE` for constants +- Use descriptive names that indicate purpose -Development -- Generate self-signed certificates for local testing in `dev/` directory +## Error Handling +- Use `io::Result<()>` for I/O operations +- Convert errors to appropriate types with `map_err` when needed +- Use `unwrap()` only in tests and main() for unrecoverable errors +- Use `expect()` with meaningful messages for debugging +- Return early with `Err()` for validation failures + +## Security Requirements +- **Critical**: Always validate file paths with `path_security::validate_path` +- Never construct paths from user input without validation +- Use timeouts for network operations (`tokio::time::timeout`) +- Limit request sizes (see `MAX_REQUEST_SIZE` constant) +- Validate TLS certificates properly +- Never expose directory listings + +## Testing Guidelines +- Use `tempfile::TempDir` for temporary directories in tests +- Test both success and error paths +- Use `#[cfg(test)]` for test modules +- Create temporary test files in `tmp/` directory +- Test security boundaries (path traversal, invalid inputs) +- Use `assert_eq!` and `assert!` for validations + +## Async Patterns +- Use `.await` on async calls +- Prefer `tokio::fs` over `std::fs` in async contexts +- Handle timeouts for network operations +- Use `Arc` for shared data across tasks + +## Gemini Protocol Specific +- Response format: "STATUS META\r\n" +- Status 20: Success (follow with MIME type) +- Status 51: Not found +- Status 59: Bad request +- Default MIME: "text/gemini" for .gmi files +- Default file: "index.gmi" for directory requests + +## Configuration +- TOML config files with `serde::Deserialize` +- CLI args override config file values +- Required fields: root, cert, key, host +- Optional: port, log_level + +# Development Notes +- Generate self-signed certificates for local testing in `tmp/` directory - Use CN=localhost for development - +- Fix every compiler warning before committing any code +- Create temporary files in the tmp/ directory for your tests like .gem files + or images, etc., so they are gitignored +- Use `path-security` crate for path validation +- Default port: 1965 (standard Gemini port) +- Default host: 0.0.0.0 for listening +- Log level defaults to "info" diff --git a/README.md b/README.md index d42dd5d..5f4b268 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,12 @@ Or specify options directly (overrides config): Access with a Gemini client like Lagrange at `gemini://yourdomain.com/`. +### Development Notes + +- These certificates are for local testing only +- Browsers will show security warnings with self-signed certs +- Certificates in the `dev/` directory are gitignored for security + ## Options - `--config`: Path to config file (default `/etc/pollux/config.toml`)