-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path.coderabbit.yaml
More file actions
190 lines (177 loc) · 10.7 KB
/
Copy path.coderabbit.yaml
File metadata and controls
190 lines (177 loc) · 10.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# =============================================================================
# .coderabbit.yaml — Configuration for CodeRabbit AI reviews
# =============================================================================
# Language is English (US) — all code comments, docs, and UI already use English.
language: en-US
reviews:
# ---------------------------------------------------------------------------
# profile: "assertive" because this is an infra/ops repo with root-level
# shell scripts and a security-sensitive Flask app. False negatives in
# security and correctness reviews are more dangerous than false positives.
# ---------------------------------------------------------------------------
profile: assertive
# ---------------------------------------------------------------------------
# Global review instructions — encode domain knowledge and suppress noise
# from issues already caught by linters.
# ---------------------------------------------------------------------------
instructions: |
## Stack overview
This repo has two components:
1. **vm/nut-vm.sh** — Bash script run as root on a Proxmox host. Sources
`api.func`, `vm-core.func`, and `cloud-init.func` at runtime via curl
from community-scripts/ProxmoxVED. Uses the standard community-scripts
`msg_*` helpers; fatal errors use `{ msg_error "..."; exit; }` since
the sourced `msg_error` logs and returns rather than exiting.
2. **src/backend/** — NutWatch (Flask SPA: app.py, auth.py, config.py,
utils.py, parsers/, services/, routes/, static/) that runs inside the VM
on port 8081 as a systemd service. Manages NUT config files in /etc/nut/
via a REST API. Can also be deployed standalone on any Linux system.
## What NOT to comment on (linters already enforce these)
- Shell quoting/bracing issues — shellcheck catches these via `make lint`
- Shell indentation style — shfmt enforces 2-space indentation via `make fmt`
- Python syntax errors — `make lint-python` (py_compile) catches these
- Missing test coverage for parser roundtrips — `tests/test_parsers.py`
covers parse/serialize roundtrips; flag only regressions, not missing cases
- Sourcing `build.func` / `cloud-init.func` via curl — shellcheck is
intentionally disabled for these via `# shellcheck disable=SC1090`
and `.shellcheckrc` sets `external-sources=true`
## Domain-specific patterns to validate
- **Password handling**: NUT passwords are written directly into config
files via `--upload` inside `virt-customize`. Do not suggest inlining
passwords into `--run-command` strings where shell expansion could
mangle special characters.
- **Atomic config writes**: `write_file()` in app.py uses `tempfile.mkstemp`
+ `os.replace`. Do not suggest simpler `open(..., 'w')` patterns.
- **IDENTIFIER_REGEX**: NUT section names and usernames are validated with
`^[A-Za-z][A-Za-z0-9._-]{0,127}$`. Flag any route that accepts a name
parameter without this check.
- **Duplicate UPS models**: `detect_ups()` falls back to bus-port notation
(`host=4-1`) when multiple devices share the same vendor:product ID.
This is intentional, not a bug.
- **Image caching**: The cloud image is intentionally NOT deleted after
import. It stays at `/var/lib/vz/template/cache` for re-runs. Do not
suggest deleting it.
- **msg_error exit behavior**: The sourced `msg_error` logs and returns.
Fatal error paths must append `exit` (e.g., `{ msg_error "..."; exit; }`).
Never suggest replacing with a local wrapper that calls `exit 1` inside
`msg_error` — that would break community-scripts `error_handler`.
- **Cloud-init password**: The VM password is set via Proxmox's built-in
cloud-init (`qm set --cipassword`) after `setup_cloud_init`. Do not
suggest vendor snippets in `/var/lib/vz/snippets/`.
- **NUT driver service name**: Probes `nut-driver-enumerator`, then
`nut-driver@`, then `nut-driver` — handles across Ubuntu releases.
Do not simplify to a single service name.
- **virt-customize cleanup**: The working disk image (`/tmp/nut-vm-${VM_ID}-work.img`)
must be removed on success, failure, or interrupt. Flag if `rm -f` is missing
from any error path or `trap` cleanup.
# ---------------------------------------------------------------------------
# path_instructions: folder-specific review rules
# ---------------------------------------------------------------------------
path_instructions:
# Shell script run as root on Proxmox hosts. Security-critical:
# handles passwords, qm commands, cloud-init injection, virt-customize.
- path: vm/**.sh
instructions: |
- This script runs as root on Proxmox. Flag any unquoted variable
in a command that reaches the system (qm, virt-customize, curl).
shellcheck may miss these in eval-like contexts.
- The sourced `msg_error` logs and returns. Fatal errors must use
`{ msg_error "..."; exit; }`. Do not suggest wrapping `msg_error`
to call `exit` internally.
- NUT config files are written via `--upload` in `virt-customize`,
not via heredoc or shell expansion. Passwords must never appear
in `--run-command` arguments where shell expansion could mangle
special characters.
- Verify that any new whiptail prompt has `|| { msg_error "Cancelled
by user"; exit; }` — users pressing Cancel must abort, not continue.
- Verify `trap EXIT` cleanup removes the working disk image
(`${TEMP_DIR}/nut-vm-${VMID}-work.img`) on interrupt or failure.
`cleanup` is sourced from `vm-core.func` and runs on `EXIT`.
- Verify SIGINT/SIGTERM traps call `post_update_to_api "failed" "..."`
and then `exit 130` / `exit 143` so the EXIT trap fires.
- Flag new `curl | sh` patterns — the script only sources
`api.func`, `vm-core.func`, and `cloud-init.func` from the
community-scripts org; new external fetches need a checksum or
pinned commit.
- Standard VM variable names: `VMID` (not `VM_ID`), `HN` (hostname,
not `VM_NAME`), `BRG` (bridge, not `VM_BRIDGE`), `RAM_SIZE`,
`CORE_COUNT`, `DISK_SIZE`, `STORAGE`.
- The script uses a standard inline entry point (not a `main()`
function). It calls `check_root`, `pve_check`, `ssh_check`,
`start_script`, `post_to_api_vm`, then the creation flow.
- `post_to_api_vm` must be called after `start_script` and before
any destructive work. `post_update_to_api "done" "none"` must
appear at the end on success.
# Flask API modules that write /etc/nut/ configs and run system commands.
# Auth: accounts (admin/viewer) + per-user API keys, resolved in auth.py.
- path: src/backend/**/*.py
instructions: |
- Auth resolves a principal from a session cookie or a per-user
`Authorization: Bearer <key>` API key (`auth.resolve_principal()` in
`auth.py`; accounts/keys live in `services/auth_db.py`). A key
inherits its owner's role (admin/viewer). If no accounts exist yet,
auth is disabled (all requests allowed) — the bootstrap-open rule.
The `@require_admin` / `@require_auth` decorators live in `auth.py`.
Flag any new mutating route that lacks `@require_admin`.
- Config writes must use `write_file()` from `utils.py` (atomic tempfile
+ os.replace). Never suggest `open(path, 'w')` for NUT config files.
- `IDENTIFIER_REGEX` and `ALLOWED_CONFIGS` live in `config.py`. All
name/path parameters in routes must be validated with one of these.
Flag any unvalidated input passed to `os.path.join` or
`subprocess.run`.
- `upsd.users` is read-only via the `/api/config/` endpoint (enforced in
`routes/system.py`). Flag any PR that removes this guard.
- Passwords are masked (••••••) in API responses. Never suggest logging
or returning plaintext passwords unnecessarily.
- `run_cmd` lives in `utils.py` and uses `subprocess.run` with a timeout.
Flag any new subprocess call that bypasses this (e.g., `os.system`,
`shell=True`).
# React SPA built with Vite in src/frontend/
- path: src/frontend/src/**
instructions: |
- React SPA built with Vite. The source lives in src/frontend/src/
and the build output goes to src/backend/static/. Do not suggest
adding frameworks or changing the build tool. XSS: JSX auto-escapes
by default — flag any dangerouslySetInnerHTML usage. API calls use
fetch('/api/...') — relative URLs are correct for same-origin
deployment.
# Install script for NutWatch inside the VM.
- path: scripts/install.sh
instructions: |
- This runs as root inside the VM. Flag any `curl | sh` without
checksum verification. The script pins `NUTWATCH_REF` (a git tag like
v1.0.0) — flag changes that use a branch name or remove the pin.
- The script downloads a single tarball (`nutwatch.tar.gz`) and
unpacks it. Do not suggest restoring the old dual-mode behavior
(local file copy vs remote curl); that was intentionally removed.
# Parser roundtrip tests.
- path: src/backend/tests/**
instructions: |
- Tests import from the package directly (e.g., `from parsers import
...`, `from utils import ...`) because they run from `src/backend/`.
Do not suggest adding `__init__.py` or restructuring import paths.
- Focus on: roundtrip correctness (parse → serialize → parse),
edge cases in NUT config syntax (comments, blank lines, extra
directives), and not on test framework choices.
# ---------------------------------------------------------------------------
# path_filters: exclude generated/vendored/cache directories from review
# ---------------------------------------------------------------------------
path_filters:
- "!**/.pytest_cache/**"
- "!**/__pycache__/**"
- "!**/node_modules/**"
- "!**/.agents/**"
- "!**/.git/**"
# ---------------------------------------------------------------------------
# auto_review: enable on PRs, disable on drafts unless explicit.
# ---------------------------------------------------------------------------
auto_review:
enabled: true
auto_incremental_review: true
drafts: false
# =============================================================================
# knowledge_base: auto-detect patterns from PR history
# =============================================================================
knowledge_base:
learnings:
scope: auto