perf: index the real queries, bound the board, and correct what the Site promises
Some checks failed
Build and deploy / Validate source (push) Successful in 5s
Build and deploy / Integration suite on a real stack (push) Failing after 10m30s
Build and deploy / Secret scan and release gate (push) Successful in 5s
Build and deploy / Publish images and notify Portainer (push) Has been skipped

Five items that needed no decisions.

Indexes: the schema indexed only uploads(owner), so the worker's once-a-second
outbox poll scanned a table that only grows, and every per-customer and
per-order lookup did the same. Ten indexes now follow queries the application
actually issues, and no more, since each one is paid for on every write. The
outbox and live uploads use partial indexes so they stay the size of the backlog
rather than of all history. Confirmed against the database that the planner
chooses them.

Board: /api/operator/board returned every order ever created. Finished orders
are terminal, so they were pure growth. It now returns everything still in
progress however old, plus a window of recent finished ones and the true
finished total, and the Kanban column says "50 de 213" rather than letting the
count read as an all-time figure. An operator cannot lose a card they could act
on.

Dependencies: the root requirements.txt was the prototype's, pinned by wildcard,
listing packages this system does not use, next to the hash-locked lock file.
Deleted. pip was pinned as a runtime dependency, which installed a package
manager into the read-only production image; nothing depended on it, so it is
gone from both the direct list and the lock, and the base image's pip performs
the hash-enforced install.

Retention copy: the Site told customers their artwork was kept 90 days with 12
months of history, and invited them to reorder without uploading again. Files
are kept 30 days. The copy now matches the policy and drops the promise the
system cannot keep.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Cauê Faleiros
2026-09-21 14:29:07 -03:00
parent 91269ce414
commit 543a9a9fb4
9 changed files with 89 additions and 42 deletions

View File

@@ -7,8 +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, plus 2.1–2.6 and 5.1. Next: 2.7 (vendor or
integrity-pin pdf.js), then 2.8–2.11. Block 1 still waits on client inputs for
**Current step:** Block 0 closed; Block 2 closed except 2.9–2.11; 4.1, 4.2, 4.5,
5.1, 5.3, 5.4 and 5.8 done. Remaining work needs decisions (3.1, 3.2, 3.3) or
client inputs (1.1, 1.2, 2.10). 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/`,
@@ -379,13 +380,16 @@ charges. Fix as part of 1.1.
## Block 4 · Scale and performance
- `[ ]` 4.1 — Missing indexes `(F23)`. `local/schema.sql` indexes only
`uploads(owner)`. Add `orders(owner)`, `quotes(owner)`, `order_files(order_id)`,
`movements(order_id)`, and a partial index on
`outbox(available_at) WHERE delivered_at IS NULL` — the worker polls that table
every second and it only grows.
- `[ ]` 4.2 — `/api/operator/board` is unpaginated `(F24)`: every order ever, plus a
per-quote subquery each. Fine at 10 orders, not at 200/day.
- `[x]` 4.1 — Ten indexes added, each matched to a query the application issues,
and no more: every extra index is paid for on each write. The outbox and live
uploads use partial indexes so they stay the size of the backlog rather than of
all history. Verified against the running database — the planner chooses
`outbox_pending` and `orders_owner` for the queries they exist for.
- `[x]` 4.2 — The board returns every order still in progress, however old, plus a
window of recent finished ones (`BOARD_FINISHED_LIMIT`, default 50) and the true
finished total. An operator can never lose a card they could act on; only terminal
ones are trimmed. The Kanban column reads "Finalizado · 50 de 213" when truncated,
so the count is not mistaken for an all-time total. Pending quotes are capped too.
- `[ ]` 4.3 — Scan throughput `(F21)`: one `scan_loop` thread, `worker` at
`replicas: 1`, ClamAV `MaxThreads 2`, browser gives up after 150s.
- `[ ]` 4.4 — Quality grade fallback `(F22)`: when `carregarImagem` fails,
@@ -410,11 +414,15 @@ charges. Fix as part of 1.1.
`agente/`, root `schema.sql` (~1,500 lines describing an abandoned model). Several
expose unauthenticated endpoints taking the acting user from the request body
(`/api/puxar`, `/api/devolver`).
- `[ ]` 5.3 — Root `requirements.txt` is the prototype's `(F31)`: wildcard pins,
unused `sqlmodel`/`pyvips`/`qrcode`/`pillow`, next to the hash-locked
`local/requirements.lock`.
- `[ ]` 5.4 — `pip==26.2.1` pinned as a runtime dependency `(F32)` — pip ships inside
the read-only production image.
- `[x]` 5.3 — Root `requirements.txt` deleted. It pinned by wildcard, listed
packages the system does not use, and sat next to the hash-locked
`local/requirements.lock` inviting the wrong one to be installed. Only historical
documentation referred to it.
- `[x]` 5.4 — `pip` removed from `local/requirements.txt` and from the lock. Nothing
depended on it; it was pinned only because it was listed directly, and installing
it put a package manager inside the read-only runtime image. The base image's own
pip performs the hash-enforced install. Verified: the image builds under
`--require-hashes` and reports the base pip, 25.0.1.
- `[ ]` 5.5 — Doc drift `(F34)`. `README.md`, `CONTEXT.md`, `LOCAL_SETUP.md` and
`SECURITY_REPORT.md` describe a MinIO localhost stack, an API with "no external
network route", a `operator` / `local-operator-only` login the email-validated
@@ -437,11 +445,11 @@ charges. Fix as part of 1.1.
runner has Chrome, so an intermittent failure there blocks releases for no reason.
Suspect Chrome startup timing or a race against stack readiness. Watch it, and if
it recurs add an explicit readiness wait rather than a retry.
- `[ ]` 5.8 — The Site promises retention the system does not honour. The cart aside
still reads *"O arquivo fica guardado por 90 dias e o histórico do pedido por 12
meses"*, while `CONTEXT.md` and the implemented retention are 30 days maximum.
This is a customer-facing commercial promise, so correct the copy or the policy —
do not leave them disagreeing. Found 2026-09-18 while closing Block 0.
- `[x]` 5.8 — The Site claimed 90-day file storage and 12-month history in two
places, and invited customers to reorder "sem subir de novo". Files are kept 30
days. The copy now states 30 days, says a later order needs the file again, and
keeps only the true part: order history remains in the account. Policy unchanged;
the promise was corrected to match it.
---