Markdown Files
AGENTS.md
This file contains guidelines for AI coding agents working on this repository.
Project Overview
Fig is a Git server and web UI built with Rust (Actix-web). It serves Git repositories over HTTP and provides a web interface for browsing repositories.
Build/Lint/Test Commands
Essential Commands (use these via just)
# Full verification (runs all checks, tests, and hurl tests)
just verify
# Format code
just fmt
# Run the application
just run
# Run hurl acceptance tests (requires server running)
just hurl test
# Run a single hurl test file
just hurl test health.hurl
# Start/stop Docker environment
just up # kill, docker stop, docker run, hurl test
just down # docker stop
Direct Cargo Commands
# Check code without building
cargo check
# Run linter
cargo clippy
# Format code
cargo fmt
# Run unit tests
cargo test
# Run a specific test
cargo test <test_name>
# Build release
cargo build --release
Docker Commands
# Build Docker image
just docker build
# Run Docker container
just docker run
# Stop Docker container
just docker stop
# Build and push release
just docker release <version>
Code Style Guidelines
Imports
- Group imports: std library first, then external crates, then local modules
- Use
use crate::for local module imports - Example:
use std::path::Path; use actix_web::{HttpRequest, get, web}; use serde::Deserialize; use crate::{config, git};
Formatting
- Run
cargo fmtbefore committing - Run
cargo clippyand fix all warnings - 4 spaces for indentation (Rust default)
Types and Naming
- Structs/Enums: PascalCase (e.g.,
GitRequest,Server) - Functions/Variables: snake_case (e.g.,
get_commits,project_root) - Constants: SCREAMING_SNAKE_CASE (e.g.,
TCSS,HTMX) - Modules: snake_case (e.g.,
repo.rs,bare.rs) - Use descriptive names; avoid abbreviations except common ones (
req,ctx)
Error Handling
- Use
Result<T, E>for fallible operations - Propagate errors with
?operator when appropriate - Log errors using
log::error!()before returning HTTP error responses - Handle
Optionwithif letormatchrather than.unwrap()in production code
HTML/Views
- Always use
htmandt.cssfor creating views - do not change CSS without reason - Use
maudfor HTML templating - Use
maud::html!macro for markup - Use
maud::DOCTYPEfor doctype declaration - Check for
HX-Requestheader to determine if rendering full layout or partial content - Structure:
if req.headers().get("HX-Request").is_some() { Ok(content) } else { Ok(super::render_layout(&content)) }
Request Handlers
- Use Actix-web macros:
#[get("/path")],#[post("/path")] - Return
impl Responderor specific types likeAwResult<maud::Markup> - Extract path params with
web::Path<Params>using a#[derive(Deserialize)]struct - Access config via
web::Data<config::Server>
Testing
- Always use hurl commands/recipes to run format and test
- Hurl tests are in
tests/*.hurl - Variables in
tests/variables - Run
just hurl testfor acceptance tests - To run a single test:
just hurl test <file.hurl>
Environment Variables
PORT: Server port (default: 8080)LOG_LEVEL: Logging level (default: info)PROJECT_ROOT: Git repositories root path (default: /srv/git)DB_PATH: Path to the SQLite database file (default: fig.db)API_KEY: API key for user signup endpoint (auto-generated if not set)
Git Workflow
- Do not run
git commit,git push, or destructive git operations unless explicitly asked - The project uses semantic-release for automated versioning
Authentication System
Fig includes a complete authentication system. See docs/git-auth.md for Git authentication details.
Flow Overview
- Get Ticket (requires API Key) → Returns one-time signup ticket
- Signup (requires ticket) → Creates account
- Login → Sets session cookie (UI) or returns Bearer token (API)
- Create Namespace → Uses session (UI) or Bearer token (API)
- Git Operations → Uses Basic Auth with username/password
Authentication by Endpoint Type
| Endpoint Type | Auth Method |
|---|---|
Git operations (git push) | Basic Auth (username:password) |
Web UI pages (/auth/*) | Session cookies |
API endpoints (/api/*) | API Key, Basic Auth, or Bearer token |
Init repo (POST /init) | Basic Auth |
Database Schema
The system uses libsql (SQLite) for storing:
- users: User accounts with hashed passwords
- namespaces: Namespace definitions with owners
- namespace_members: Many-to-many relationship for namespace access
- tickets: Single-use tickets for signup
- tokens: Session tokens for API/UI authentication
Security
- Passwords are hashed using Argon2 (memory-hard password hashing)
- API key required for ticket generation to prevent unauthorized account creation
- Tickets are single-use for signup only
- Per-namespace access control
- Sessions expire after 30 days of inactivity
Dependencies
Key crates used:
actix-web: Web frameworkmaud: HTML templatinggit2: Git operationsxshell: Shell command executionserde: Serializationchrono: Date/time handlinglibsql: SQLite database for auth dataargon2: Password hashingbase64: Base64 encoding/decoding