# AGENTS.md

## Project Overview

CLI tool for Nebula overlay network certificate lifecycle management. Manages CA creation, certificate issuance/revocation, sync/re-issue, and config generation. PKI data is stored in a SOPS-encrypted registry file; network configuration lives in `nebula.config.yml`.

## Tech Stack

- **Language:** Python 3.12+
- **Package manager:** uv
- **Build backend:** Hatchling
- **Key libraries:** Pydantic (models), Jinja2 (templates), PyYAML, Rich (CLI output)
- **External tools:** `nebula-cert`, `sops`, `age`

## Project Structure

```
src/nebula_cert_manager/
├── cli.py              # CLI entry point (argparse)
├── models.py           # Pydantic data models
├── pki.py              # PKI wrapper (calls nebula-cert)
├── sops.py             # SOPS encryption wrapper
├── registry.py         # Registry management
├── config_gen.py       # Config generation logic
├── firewall.py         # Firewall configuration
├── hosts.py            # Host configuration
├── lighthouses.py      # Lighthouse configuration
├── relay.py            # Relay configuration
├── nebula_config.py    # Nebula config loading
├── exceptions.py       # Custom exceptions
├── commands/           # CLI commands (init, import-ca, issue, revoke, delete, list, config, info, sync)
│   └── {command}.py    # Each has add_parser() and run() functions
└── templates/          # Jinja2 templates for Nebula config
    ├── base_config.yml.j2
    └── sections/*.yml.j2
tests/
├── conftest.py         # Shared fixtures
├── fixtures/           # Test data files
└── test_*.py           # Unit tests per module
```

## Development Commands

```bash
uv sync               # Install dependencies
just check            # Format + lint + test (full quality check)
just fmt              # Format with ruff
just lint             # Lint with ruff --fix
just test             # Run pytest
just test-v           # Run pytest -v
```

## Code Conventions

- Python 3.12+ type hints (`list[str]`, `X | None`, etc.)
- Snake_case for functions/variables/files, PascalCase for classes
- Each CLI command module exposes `add_parser(subparsers)` and `run(args)`
- Pure business logic is separated from CLI wiring
- Custom exception hierarchy rooted at `CertManagerError`
- Pydantic models with `@model_validator` for input validation

## Testing

- pytest with fixtures in `tests/conftest.py` and `tests/fixtures/`
- External tools (nebula-cert, sops) are mocked in tests
- Run `just test` before committing; all tests must pass

## Quality Gates

Before submitting changes, run `just check` which runs formatting, linting, and tests in sequence. All three must pass.
