Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ad5816dc2d | |||
| 53724c1671 | |||
| 401d4e2717 | |||
| eea54dd203 | |||
| da0f082b45 | |||
| 5e6997cbd6 | |||
| 85db9d14a8 |
+15
-7
@@ -17,21 +17,29 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
run: |
|
||||
apt-get update && apt-get install -y python3 python3-venv || true
|
||||
python3 --version
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
python3 -m venv .venv
|
||||
source .venv/bin/activate
|
||||
pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
pip install -r requirements-dev.txt
|
||||
|
||||
- name: Lint with ruff
|
||||
run: ruff check .
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
ruff check .
|
||||
|
||||
- name: Format check with ruff
|
||||
run: ruff format --check .
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
ruff format --check .
|
||||
|
||||
- name: Run tests
|
||||
run: pytest -q
|
||||
run: |
|
||||
source .venv/bin/activate
|
||||
pytest -q
|
||||
|
||||
+10
@@ -2,12 +2,22 @@
|
||||
.DS_Store
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*.pyo
|
||||
.venv/
|
||||
venv/
|
||||
.*venv*/
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
.ruff_cache/
|
||||
.coverage*
|
||||
coverage.xml
|
||||
.vscode/
|
||||
.idea/
|
||||
memory/
|
||||
*.log
|
||||
*.tmp
|
||||
*.swp
|
||||
*.swo
|
||||
*.bak
|
||||
*.orig
|
||||
*.rej
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# AOC v1.7.15 Release Notes
|
||||
|
||||
**Release Date:** 2026-04-24
|
||||
|
||||
## Security Hardening & Code Quality
|
||||
|
||||
This release continues the security hardening roadmap with async I/O improvements, stricter input validation, and infrastructure lockdown.
|
||||
|
||||
### Async Authentication Refactor
|
||||
|
||||
- `require_auth()` and `_get_jwks()` are now `async def` to avoid blocking the event loop during JWKS fetch and token validation
|
||||
- **Impact:** Eliminates synchronous I/O stalls on authenticated requests under load
|
||||
|
||||
### CSP Tightening
|
||||
|
||||
- Removed `'unsafe-inline'` from the `script-src` directive in the Content-Security-Policy header
|
||||
- All JavaScript is now loaded from external files (`app.js`) or trusted CDNs with SRI hashes
|
||||
- `'unsafe-eval'` is retained for Alpine.js expression evaluation
|
||||
- **Impact:** Mitigates XSS by preventing inline script injection
|
||||
|
||||
### Model Validation Hardening
|
||||
|
||||
Added `Field(min_length=, max_length=)` constraints across request models:
|
||||
|
||||
| Model | Field | Constraints |
|
||||
|-------|-------|-------------|
|
||||
| `TagsUpdateRequest` | `tags` | `max_length=50` |
|
||||
| `BulkTagsRequest` | `tags` | `max_length=50` |
|
||||
| `CommentAddRequest` | `text` | `min_length=1`, `max_length=5000` |
|
||||
| `AlertCondition` | `field` | `max_length=100` |
|
||||
| `AlertRuleResponse` | `conditions` | `max_length=20` |
|
||||
| `AlertRuleResponse` | `message` | `max_length=1000` |
|
||||
| `AskRequest` | `question` | `min_length=1`, `max_length=2000` |
|
||||
| `SavedSearchCreate` | `name` | `min_length=1`, `max_length=200` |
|
||||
|
||||
- **Impact:** Rejects malformed or oversized inputs at the Pydantic/FastAPI layer before they reach business logic
|
||||
|
||||
### Notification SSRF Guard
|
||||
|
||||
- `_validate_webhook_url()` in `notifications.py` now blocks:
|
||||
- Non-HTTP(S) schemes
|
||||
- localhost, private, and link-local IP addresses
|
||||
- **Impact:** Prevents Server-Side Request Forgery via malicious webhook URLs in alert notifications
|
||||
|
||||
### Rate Limiting Improvements
|
||||
|
||||
- New category: `"explain"` → 20 requests per minute
|
||||
- Categories: `fetch=10/hr`, `ask=30/min`, `explain=20/min`, `write=20/min`, `default=120/min`
|
||||
- Fail-closed on Redis/Valkey error: raises `RateLimitExceeded(retry_after=60)`
|
||||
- **Impact:** Prevents abuse of the new explain endpoint and ensures graceful degradation if the rate limit store is unreachable
|
||||
|
||||
### Frontend JavaScript Extraction
|
||||
|
||||
- All inline JavaScript has been extracted from `index.html` into `backend/frontend/app.js`
|
||||
- Alpine.js SPA loads `/app.js?v=1` before Alpine initialization
|
||||
- **Impact:** Enables stricter CSP, improves cacheability, and separates markup from logic
|
||||
|
||||
### Docker Compose Security
|
||||
|
||||
- Backend port binding changed from `"8000:8000"` to `"127.0.0.1:8000:8000"`
|
||||
- **Impact:** Prevents direct external access to the backend when nginx is the intended reverse proxy
|
||||
|
||||
## Files Changed
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `backend/auth.py` | `require_auth()` and `_get_jwks()` made async |
|
||||
| `backend/main.py` | CSP tightened; startup warnings |
|
||||
| `backend/models/api.py` | Added `Field` validation constraints |
|
||||
| `backend/notifications.py` | SSRF guard for webhook URLs |
|
||||
| `backend/rate_limiter.py` | Added `"explain"` rate limit category |
|
||||
| `backend/routes/saved_searches.py` | `SavedSearchCreate` Pydantic model with validation |
|
||||
| `backend/frontend/index.html` | Extracted inline JS to `app.js` |
|
||||
| `backend/frontend/app.js` | New — extracted frontend JavaScript |
|
||||
| `docker-compose.yml` | Backend port bound to `127.0.0.1` only |
|
||||
| `nginx/nginx.conf` | Security headers alignment |
|
||||
| `backend/tests/test_auth.py` | Updated for async `require_auth()` |
|
||||
| `backend/tests/test_api.py` | Updated saved searches validation test |
|
||||
| `backend/tests/test_ask.py` | Updated empty question test for 422 |
|
||||
| `.gitignore` | Added `memory/` |
|
||||
| `VERSION` | Bumped to 1.7.15 |
|
||||
|
||||
## Test Results
|
||||
|
||||
- **80/80 pytest tests passing**
|
||||
- Ruff lint/format clean
|
||||
|
||||
## Docker Image
|
||||
|
||||
```
|
||||
git.cqre.net/cqrenet/aoc-backend:v1.7.15
|
||||
```
|
||||
@@ -0,0 +1,39 @@
|
||||
# AOC v1.7.16 Release Notes
|
||||
|
||||
**Release Date:** 2026-04-24
|
||||
|
||||
## Infrastructure & Maintenance
|
||||
|
||||
### Gitea Actions CI Fix
|
||||
|
||||
The CI workflow (`.gitea/workflows/ci.yml`) has been reworked for compatibility with Gitea Actions (`act_runner`):
|
||||
|
||||
- **Removed** `actions/setup-python@v5` — incompatible with self-hosted Gitea (relies on GitHub's tool cache API)
|
||||
- **Added** system Python installation via `apt-get install python3 python3-venv`
|
||||
- **Uses a virtual environment** inside the job to avoid PEP 668 `externally-managed-environment` errors
|
||||
- All steps (`pip install`, `ruff check`, `ruff format`, `pytest`) now activate the venv explicitly
|
||||
|
||||
### Repository Cleanup
|
||||
|
||||
- **Expanded `.gitignore`** to cover all venv variants (`.*venv*/`), `.ruff_cache/`, and common temp/backup files
|
||||
- **Removed** temporary working directories (`backend/.venv_ci/`, `__pycache__/`)
|
||||
|
||||
## Files Changed
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `.gitea/workflows/ci.yml` | Complete rewrite for Gitea Actions compatibility |
|
||||
| `.gitignore` | Expanded patterns for venvs, caches, temp files |
|
||||
| `VERSION` | Bumped to 1.7.16 |
|
||||
|
||||
## Test Results
|
||||
|
||||
- **80/80 pytest tests passing**
|
||||
- Ruff lint/format clean
|
||||
- CI green on Gitea Actions
|
||||
|
||||
## Docker Image
|
||||
|
||||
```
|
||||
git.cqre.net/cqrenet/aoc-backend:v1.7.16
|
||||
```
|
||||
Reference in New Issue
Block a user