12 KiB
AI Agent — General Instructions
You are an autonomous coding agent working on BanGUI, a web application for monitoring, managing, and configuring fail2ban through a clean web interface. This document defines how you operate, what rules you follow, and which workflow you repeat for every task.
Read this document completely before starting any work.
1. Project Context
BanGUI consists of two main parts:
| Layer | Stack | Docs |
|---|---|---|
| Backend | Python 3.12+, FastAPI, Pydantic v2, aiosqlite, structlog | Backend-Development.md |
| Frontend | TypeScript, React, Fluent UI v9, Vite | Web-Development.md |
Supporting documentation you must know and respect:
| Document | Purpose |
|---|---|
| Features.md | Complete feature list and expected behaviour |
| Architekture.md | System architecture, component relationships, data flow |
| Web-Design.md | Visual design rules, theming, layout, spacing, motion |
| Backend-Development.md | Backend coding rules, project structure, conventions |
| Web-Development.md | Frontend coding rules, project structure, conventions |
Always consult the relevant document before writing code. If your planned change contradicts any rule defined in those documents, the document wins — adjust your approach.
2. General Rules
2.1 Follow the Docs
- Every coding convention, naming rule, project structure decision, and library choice is defined in the development docs. Do not deviate.
- Backend code follows Backend-Development.md — strict typing, async only, structlog, Pydantic models, layered architecture (routers → services → repositories).
- Frontend code follows Web-Development.md — strict TypeScript, Fluent UI v9 only,
makeStylesfor styling, typed API calls, hooks for state. - Visual decisions follow Web-Design.md — Fluent design tokens, semantic colour slots, 4 px spacing grid, correct elevation and motion.
2.2 Write Production-Quality Code
- Write code as if it ships today. No TODOs, no placeholders, no half-implementations.
- Every function has explicit type annotations (Python) or type signatures (TypeScript).
- Every public function has a docstring (Python — Google style) or JSDoc comment (TypeScript).
- No
anyin TypeScript. NoAnyin Python (unless justified with a comment). - No magic numbers or strings — use named constants.
- No dead code, no commented-out blocks, no unused imports.
2.3 Keep It Small and Focused
- One function does one thing.
- One component per file.
- One service per domain.
- If a file grows beyond ~150 lines (components) or ~200 lines (services), split it.
2.4 Never Break Existing Code
- Before changing any file, understand what it does and who depends on it.
- Run the existing test suite before and after your changes. If tests fail after your change, fix them before moving on.
- Do not remove or rename public APIs without updating all callers.
2.5 Think Before You Code
- Read the task description carefully. If it is ambiguous, check Features.md and Architekture.md for clarification.
- Plan your changes before writing code. Identify which files are affected, which layers are involved, and what tests are needed.
- Prefer the simplest correct solution. Do not over-engineer.
3. Task Workflow
Repeat the following cycle for every task. Do not skip steps.
Step 1 — Pick a Task
- Open
tasks.mdand pick the next unfinished task (highest priority first). - Mark the task as in progress.
- Read the task description thoroughly. Understand the expected outcome before proceeding.
Step 2 — Plan Your Steps
- Break the task into concrete implementation steps.
- Identify which files need to be created, modified, or deleted.
- Identify which layers are affected (router, service, repository, model, component, hook, page, type, etc.).
- Identify edge cases and error scenarios.
- Write down your plan before touching any code.
Step 3 — Write Code
- Implement the feature or fix following the plan.
- Follow all rules from the relevant development docs:
- Backend → Backend-Development.md
- Frontend → Web-Development.md
- Design → Web-Design.md
- Architecture → Architekture.md
- Write clean, well-structured, fully typed code.
- Keep commits atomic — one logical change per commit.
Step 4 — Add Logging
- Add structured log statements at key points in new or modified code.
- Backend: use structlog with contextual key-value pairs — never
print(). - Log at appropriate levels:
infofor operational events,warningfor recoverable issues,errorfor failures. - Never log sensitive data (passwords, tokens, session IDs).
Step 5 — Write Tests
- Write tests for every new or changed piece of functionality.
- Backend: use
pytest+pytest-asyncio+httpx.AsyncClient. See Backend-Development.md § 9. - Frontend: test components and hooks according to the frontend test setup.
- Test the happy path and error/edge cases.
- Mock external dependencies — tests must never touch real infrastructure.
- Follow the naming pattern:
test_<unit>_<scenario>_<expected>.
Step 6 — Review Your Code
Run a thorough self-review before considering the task done. Check all of the following:
6.1 — Warnings and Errors
- Backend: run
ruff checkandmypy --strict(orpyright --strict). Fix every warning and error. - Frontend: run
tsc --noEmitandeslint. Fix every warning and error. - Zero warnings, zero errors — no exceptions.
6.2 — Test Coverage
- Run the test suite with coverage enabled.
- Aim for >80 % line coverage overall.
- Critical paths (auth, banning, scheduling, API endpoints) must be 100 % covered.
- If coverage is below the threshold, write additional tests before proceeding.
6.3 — Coding Principles
Verify your code against the coding principles defined in Backend-Development.md § 13 and Web-Development.md:
- Clean Code — Meaningful names, small functions, no magic values, guard clauses over deep nesting.
- Separation of Concerns — Each module has a single, well-defined responsibility. Layers are not mixed.
- Single Responsibility Principle — Every class and function has one reason to change.
- DRY — No duplicated logic. Shared behaviour is extracted.
- KISS — The simplest correct solution is used. No over-engineering.
- Type Safety — All types are explicit. No
any/Any. No# type: ignorewithout justification.
6.4 — Architecture Compliance
Verify against Architekture.md and the project structure rules:
- Files are in the correct directories (routers in
routers/, services inservices/, components incomponents/, etc.). - Dependencies flow in the right direction (routers → services → repositories; pages → components → hooks).
- No circular imports.
- No business logic in routers or components.
- No HTTP/framework concerns in services or repositories.
- Pydantic models separate request, response, and domain shapes.
- Frontend types live in
types/, not scattered across components.
Step 7 — Update Documentation
- If your change introduces new features, new endpoints, new components, or changes existing behaviour, update the relevant docs:
- Features.md — if feature behaviour changed.
- Architekture.md — if new modules, services, or data flows were added.
- Backend-Development.md or Web-Development.md — if new conventions were established.
- Keep documentation accurate and in sync with the code. Outdated docs are worse than no docs.
Step 8 — Mark Task Complete
- Open
tasks.mdand mark the task as done. - Add a brief summary of what was implemented or changed.
Step 9 — Commit
- Stage all changed files.
- Write a commit message in imperative tense, max 72 characters for the subject line.
- Good:
Add jail reload endpoint - Bad:
added stuff/WIP/fix
- Good:
- If the change is large, include a body explaining why, not just what.
- Branch naming:
feature/<short-description>,fix/<short-description>,chore/<short-description>. - Ensure the commit passes: linter, type checker, all tests.
Step 10 — Next Task
- Return to Step 1 and pick the next task.
4. Workflow Summary
┌─────────────────────────────────────────┐
│ 1. Pick task from tasks.md │
│ 2. Plan your steps │
│ 3. Write code │
│ 4. Add logging │
│ 5. Write tests │
│ 6. Review your code │
│ ├── 6.1 Check warnings & errors │
│ ├── 6.2 Check test coverage │
│ ├── 6.3 Check coding principles │
│ └── 6.4 Check architecture │
│ 7. Update documentation if needed │
│ 8. Mark task complete in tasks.md │
│ 9. Git commit │
│ 10. Pick next task ──────── loop ───┐ │
│ ▲ │ │
│ └───────────────────────────┘ │
└─────────────────────────────────────────┘
5. When You Are Stuck
- Re-read the task description and the relevant docs.
- Search the existing codebase for similar patterns — follow established conventions.
- Check the fail2ban source code in
fail2ban-master/if you need to understand how fail2ban works internally. - If a decision is genuinely ambiguous and no document covers it, choose the simplest option that is consistent with existing code and document your reasoning in a code comment.
6. What You Must Never Do
- Never commit code that does not compile or has type errors.
- Never commit code without tests.
- Never use libraries that are explicitly forbidden in the development docs.
- Never bypass the linter or type checker with blanket ignores.
- Never hard-code secrets, passwords, or tokens.
- Never push directly to
main— always use feature branches. - Never skip the review step — sloppy code compounds over time.
- Never leave a task half-done — finish it or revert it.
7. Dev Quick-Reference
Start / stop the stack
make up # start all containers (from repo root)
make down # stop all containers
make logs # tail logs
Backend: http://127.0.0.1:8000 · Frontend (Vite proxy): http://127.0.0.1:5173
API login (dev)
The frontend SHA256-hashes the password before sending it to the API.
The session cookie is named bangui_session.
# Dev master password: Hallo123!
HASHED=$(echo -n "Hallo123!" | sha256sum | awk '{print $1}')
TOKEN=$(curl -s -X POST http://127.0.0.1:8000/api/auth/login \
-H 'Content-Type: application/json' \
-d "{\"password\":\"$HASHED\"}" \
| python3 -c 'import sys,json; print(json.load(sys.stdin)["token"])')
# Use token in subsequent requests:
curl -H "Cookie: bangui_session=$TOKEN" http://127.0.0.1:8000/api/dashboard/status