Files
BanGUI/Docs/Instructions.md
Lukas 0f261e31c2 Fix infinite re-fetch loop in useJailConfigs
The hook was passing an inline onSuccess callback to useListData, which
included onSuccess in its internal refresh function's dependency array.
This caused refresh to be recreated on each render, which triggered the
useEffect, which fired the fetch, which completed and caused a re-render,
creating an infinite loop.

Wrap onSuccess in useCallback with empty dependencies so it maintains a
stable reference across renders. This allows refresh to be stable when
its dependencies don't change, breaking the cycle.

Add documentation to Refactoring.md explaining the onSuccess stability
requirement for useListData callers.

Also add tests for useJailConfigs to verify it doesn't trigger infinite
refetches with stable onSuccess callback.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-04-22 21:16:42 +02:00

211 lines
9.7 KiB
Markdown

# 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](Backend-Development.md) |
| **Frontend** | TypeScript, React, Fluent UI v9, Vite | [Web-Development.md](Web-Development.md) |
Supporting documentation you must know and respect:
| Document | Purpose |
|---|---|
| [Features.md](Features.md) | Complete feature list and expected behaviour |
| [Architekture.md](Architekture.md) | System architecture, component relationships, data flow |
| [Web-Design.md](Web-Design.md) | Visual design rules, theming, layout, spacing, motion |
| [Backend-Development.md](Backend-Development.md) | Backend coding rules, project structure, conventions |
| [Web-Development.md](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](Backend-Development.md) — strict typing, async only, structlog, Pydantic models, layered architecture (routers → services → repositories).
- Frontend code follows [Web-Development.md](Web-Development.md) — strict TypeScript, Fluent UI v9 only, `makeStyles` for styling, typed API calls, hooks for state.
- Visual decisions follow [Web-Design.md](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 `any` in TypeScript. No `Any` in 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](Features.md) and [Architekture.md](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 — 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 2 — Write Code
- Implement the feature or fix following the plan.
- Follow all rules from the relevant development docs:
- Backend → [Backend-Development.md](Backend-Development.md)
- Frontend → [Web-Development.md](Web-Development.md)
- Design → [Web-Design.md](Web-Design.md)
- Architecture → [Architekture.md](Architekture.md)
- Write clean, well-structured, fully typed code.
- Keep commits atomic — one logical change per commit.
### Step 3 — 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: `info` for operational events, `warning` for recoverable issues, `error` for failures.
- Never log sensitive data (passwords, tokens, session IDs).
### Step 4 — Write Tests
- Write tests for every new or changed piece of functionality.
- Backend: use `pytest` + `pytest-asyncio` + `httpx.AsyncClient`. See [Backend-Development.md § 9](Backend-Development.md).
- 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 5 — Review Your Code
Run a thorough self-review before considering the task done. Check **all** of the following:
#### 5.1 — Warnings and Errors
- Backend: run `ruff check` and `mypy --strict` (or `pyright --strict`). Fix every warning and error.
- Frontend: run `tsc --noEmit` and `eslint`. Fix every warning and error.
- Zero warnings, zero errors — no exceptions.
#### 5.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.
#### 5.3 — Coding Principles
Verify your code against the coding principles defined in [Backend-Development.md § 13](Backend-Development.md) and [Web-Development.md](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: ignore` without justification.
#### 5.4 — Architecture Compliance
Verify against [Architekture.md](Architekture.md) and the project structure rules:
- [ ] Files are in the correct directories (routers in `routers/`, services in `services/`, components in `components/`, 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 6 — Update Documentation
- If your change introduces new features, new endpoints, new components, or changes existing behaviour, update the relevant docs:
- [Features.md](Features.md) — if feature behaviour changed.
- [Architekture.md](Architekture.md) — if new modules, services, or data flows were added.
- [Backend-Development.md](Backend-Development.md) or [Web-Development.md](Web-Development.md) — if new conventions were established.
- Keep documentation accurate and in sync with the code. Outdated docs are worse than no docs.
## 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
```bash
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 initial setup password must be at least 8 characters long and include one uppercase letter, one number, and one special character from `!@#$%^&*()`.
The session cookie is named `bangui_session`.
```bash
# 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
```