pollux/AGENTS.md

3.6 KiB

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.

Build/Test/Lint Commands

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 <test_name> - Run a specific test
  • cargo test <module>::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

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

Code Style Guidelines

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

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<T, E> and ? operator
  • Use tracing for logging, not println! in production code

Naming Conventions

  • PascalCase for types, structs, enums
  • snake_case for functions, variables, modules
  • SCREAMING_SNAKE_CASE for constants
  • Use descriptive names that indicate purpose

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<Clone> 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"