docs: record Block 2 rate-limiting work and CI coverage

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Cauê Faleiros
2026-09-18 18:55:33 -03:00
parent 5d669cbcce
commit 9b38c9fe3d

View File

@@ -7,9 +7,9 @@
> Update the **Current step** line and the item status every time something moves.
> Add new findings at the bottom of the relevant block rather than rewriting history.
**Current step:** Block 0 closed on 2026-09-18 (0.1–0.6 done and verified against a
live stack). Next: Block 1 needs client inputs for 1.1/1.2, so Block 2 (2.1, 2.2,
2.3) and 5.1 are the ones that can start immediately.
**Current step:** Block 0 closed, plus 2.1, 2.2 and 5.1 (2026-09-18). Next: 2.3
(Docker secret `*_FILE` loading), then 2.4/2.5 (the release gate and its decayed
preflight). Block 1 still waits on client inputs for 1.1/1.2.
**Last audit:** 2026-09-18, full read of `local/`, `dtf-site.html`, `deploy/`,
`.gitea/`, docs and legacy prototypes. Findings below carry their audit IDs.
@@ -171,7 +171,7 @@ and ships only fake adapters, so the deployed system cannot take an order at all
## Block 2 · Security — before any public exposure
### `[ ]` 2.1 — Rate limiting and audit logs are blind to the client `(F5)`
### `[x]` 2.1 — Rate limiting and audit logs are blind to the client `(F5)`
uvicorn runs without trusted proxy headers (`forwarded_allow_ips` defaults to
`127.0.0.1`; nginx is a different container IP), so `request.client.host` is nginx
@@ -184,7 +184,7 @@ record has no attacker IP.
- **Accept:** two clients on different IPs have independent buckets; audit rows
carry the real IP.
### `[ ]` 2.2 — The public site throttles itself `(F6)`
### `[x]` 2.2 — The public site throttles itself `(F6)`
`local/app.py:115` — `rate_limit('guest-sessions', ENVIRONMENT, 120, 900)` is keyed
on the environment name: 120 new visitors per 15 minutes **site-wide** (~8/min).
@@ -332,9 +332,13 @@ charges. Fix as part of 1.1.
## Block 5 · Hygiene and maintenance
- `[ ]` 5.1 — CI coverage `(F33)`. The smoke, workflow, security, retention and
browser suites exist under `local/` and would have caught 0.1 — none run in CI.
Add a compose-backed job. **Highest leverage item in this block.**
- `[x]` 5.1 — CI coverage `(F33)`. An `integration` job now builds the localhost
stack and runs smoke, workflow, security, scanning, retention, runtime security
and both browser suites; `publish-and-deploy` depends on it. Verified by
reintroducing the 0.1 defect: `py_compile` and the unit tests still passed while
`smoke_test` failed on `/session`, blocking the release. Browser tests skip with
a warning when the runner has no Chrome — **install `google-chrome-stable` on the
runner (or set `CHROME_BIN`) to make them gate as well.**
- `[ ]` 5.2 — Remove or archive the dead prototypes `(F30)`: `portal/`, `kanban/`,
`agente/`, root `schema.sql` (~1,500 lines describing an abandoned model). Several
expose unauthenticated endpoints taking the acting user from the request body
@@ -395,6 +399,20 @@ charges. Fix as part of 1.1.
guard that refuses identical credentials in both configuration forms.
- `[x]` Checkout confirmation moved out of the panel the success path hides.
### Block 2 and CI — 2026-09-18
- `[x]` The web gateway overwrites `X-Forwarded-For` with the peer address instead
of appending to it, and `client_ip()` resolves the requester for rate-limit
buckets and security events. Verified: a forged `203.0.113.99` never reaches the
audit trail.
- `[x]` Guest sessions are limited per source. The first attempt used 30/IP, which
the new regression caught as too tight for shared NAT — recreating the original
fault in a narrower form — so the ceiling is 240 per 15 minutes, overridable with
`GUEST_SESSION_LIMIT`.
- `[x]` Security events now carry the source address (`operator_login_failed`,
`customer_login_failed`, `cross_origin_rejected`, `http_security_event`).
- `[x]` CI runs the integration suites against a real stack before publishing.
### Reporting
- `[x]` Week-1 client report (`Relatorio-Semana-1-DTF.docx`), corrected 2026-09-18 to