1.6 KiB
AGENTS.md
Dev commands (always run all three)
uv run pytest -v # 35 tests, all mocked (no live API calls)
uv run ruff check # lint
uv run pyright # strict type checking
Order matters: fix lint/typecheck errors before touching tests.
Architecture
main.py— entry point: load config → fetch public IPs → process rules → NTFY notifyunifi_firewall.py— UniFi Network API v1 client (TypedDicts matchnetwork_v10.4.57_openapi.json)ip_lookup.py— fetches public IPv4/IPv6 viacurl ifconfig.meconfig/rules.yaml— rule definitions (zones, IPs, ports, actions)
API base: {UNIFI_HOST}/proxy/network/integration/v1/sites/{UNIFI_SITE_ID}. Auth: X-API-Key header.
Env vars
Required: UNIFI_HOST, UNIFI_SITE_ID, UNIFI_API_TOKEN
Optional: CONFIG_FILE (default: config/rules.yaml), UNIFI_VERIFY_SSL, LOG_LEVEL, DEBUG, NTFY_URL, NTFY_TOPIC, NTFY_API_KEY
See .env.example for full list. Shared UniFi creds with ../ddns.
Testing
All tests are unit tests with mocks. No live API calls, no external services needed.
To run a single file: uv run pytest tests/test_unifi_firewall.py -v
To run a single test: uv run pytest tests/test_unifi_firewall.py::TestBuildPolicyPayload::test_with_dest_ports -v
Containerfile
Builds with podman, uses uv to sync deps. CMD runs main.py as a one-shot. Config is baked in at build time via COPY config/.
OpenAPI spec
network_v10.4.57_openapi.json is the source of truth for API schemas. TypedDicts in unifi_firewall.py must match it. When adding fields, verify against the spec first.