docs: specify operational control panel ux

This commit is contained in:
gti
2026-09-22 16:43:20 -03:00
parent 35642959c0
commit 8bbfaf6ac6
@@ -0,0 +1,111 @@
# Control Panel Operational UX Refinement V1
## Scope
Refine the existing FastAPI/Jinja2 control panel for daily GTI operations. The
panel must answer which client/server needs attention, why, and which safe
operator action is available. This work does not change fiscal rules, the
Hub/Agent protocol, Firebird access, AI write controls, or deployment.
## Design Choices
The implementation keeps the existing server-rendered architecture:
- `control_plane.py` remains the bounded query/view-model layer.
- A small presentation helper formats UTC timestamps using a configurable UI
timezone, defaulting to `America/Bahia`.
- Existing models are reused. `FiscalContextEntry` stores validated operator
context, `Job` schedules reprocessing, and `AuditEvent` records the complete
action context. No new write capability is introduced.
- Jinja2 templates receive operational view models, not raw ORM rows. Technical
IDs remain secondary detail information.
- CSS remains project-local and JavaScript is limited to progressive enhancement;
blocker resolution is a server-rendered form, not a `window.confirm` action.
## Dashboard Semantics
Health cards include `ONLINE`, `DEGRADED`, `OFFLINE`, `FAILED`, and `UNKNOWN`.
The query layer exposes a reconciled total and tests enforce:
`agents_total == online + degraded + offline + failed + unknown`.
Fiscal metrics are separate:
- `safe_blocked_products`: distinct active products represented by open blockers.
- `open_blockers`: active blocker rows.
The dashboard labels these independently and never presents one as the other.
Attention items are a deterministic maximum of ten, ordered by `FAILED`,
`DEGRADED`, `OFFLINE`, `UNKNOWN`, required blockers, and important version
drift. Each item contains client, display name, hostname, main problem, age,
and a safe detail/filter link. Failed jobs and outdated Agents are compact
sections with empty states.
## Presentation
UTC remains the storage/API representation. The UI renders both a human short
form (`22/09/2026 16:11`) and relative age (`há 8 min`); the full technical
timestamp is available as a `title` attribute. The timezone comes from
`UI_TIMEZONE`, with `America/Bahia` as the development default.
Agents lead with client, display name, and hostname. Technical health and fiscal
status are separate badges. Fiscal coverage includes total, complete, safe
blocked, failed, and percentage with a worst-coverage sort option.
Jobs show client, installation/display name, hostname, job ID, kind, status,
human timestamps, duration, and error. Blockers show client/installation,
product, field, type, deterministic operational priority, age, and links to a
detail page.
## Blocker Operations
The blockers page has visible server-side filters for client, installation,
field, blocker type, status, age, and product/search. Its summary reports open
blockers, distinct affected products, distinct affected clients, and field
breakdown (`CFOP`, `ST`, `ICMS`, `CSOSN`, `NCM`, `OTHER`).
Priority is operational only and deterministic:
- `CRITICAL`: technical/unsafe condition that prevents processing.
- `HIGH`: required field missing for an active product or a relevant conflict.
- `NORMAL`: safe blocker without immediate operational urgency.
- `LOW`: optional/reference enrichment.
Clicking a blocker opens a detail page with evidence, first/last seen, retry
count, related events/jobs, and resolution history. The resolution form shows
the client, server, product, description, field, type, reason, evidence, and
current value. It accepts a validated context key, value, scope (`PRODUCT`,
`GROUP`, or `COMPANY`), and reason/note. Known enum keys are validated by the
existing `context_keys` rules; arbitrary context values cannot bypass backend
validation.
On save, the transaction creates/updates the validated `FiscalContextEntry`,
creates a bounded reprocess job for the product, and records an audit event
containing operator, timestamp, client, installation, product, blocker,
context key/scope/value, reason, before/after values, and reprocess job ID.
The operation remains protected by human auth, CSRF, and authorization. It
cannot enable AI writes, Firebird writes, SQL, or shell execution.
## Detail Pages and Events
Agent detail shows client/display name/hostname first, technical/fiscal/version
badges, human last-seen, version, company, UF, CRT, and secondary technical IDs.
Fiscal summary is bounded and links to filtered blockers. Event rows have human
timestamps, severity, event type, message, and related job/product links, with
server-side severity/type/date/job/product filters and pagination.
## Password Policy
Weak local development passwords are allowed only when explicitly enabled by
`ALLOW_WEAK_DEV_PASSWORD=1` and only when `APP_ENV` is not `production`.
Production always requires the strong password policy. The existing local admin
credential is not changed.
## Verification
Tests cover health reconciliation, metrics distinction, timestamps, attention
ordering/limit, fiscal percentage, human job identity/duration, blocker filters
and detail, resolution validation/audit/CSRF/authorization, events, and
environment-aware password policy. Full `tests`, `central/tests`, and
`agent/tests` regressions plus local route/runtime and bounded performance
smokes are required before completion.