test: complete control panel fixture UX coverage

This commit is contained in:
gti
2026-09-22 20:49:04 -03:00
parent 0eeb7d159c
commit 4ba0fa8a53
4 changed files with 214 additions and 16 deletions
+150
View File
@@ -0,0 +1,150 @@
# Control Panel Operational UX V1
This document defines the operator-facing contracts for the existing
server-rendered GTI Fiscal control panel. It complements
[`CONTROL_PANEL_V1.md`](CONTROL_PANEL_V1.md), which documents architecture,
identity, authentication, APIs, retention, and the explicit fixture command.
The UX work does not change fiscal rules, the Hub/Agent protocol, Firebird
access, AI write controls, or deployment.
## Dashboard health and fiscal metrics
Technical health is summarized by exactly five states: `ONLINE`, `DEGRADED`,
`OFFLINE`, `FAILED`, and `UNKNOWN`. The dashboard total is reconciled from those
state counts and must always satisfy:
```text
agents_total = online + degraded + offline + failed + unknown
```
Technical health describes Agent/installation availability and processing
failures. Fiscal status and fiscal completion are separate: safe-blocked fiscal
work does not make an otherwise healthy Agent technically degraded or failed.
Agent views show product total, fiscally complete count, safe-blocked count,
failed count, and fiscal completion percentage. The percentage is
`fiscally_complete / total_products * 100`, rounded to one decimal place and
bounded to 0–100; when the total is zero, the stored coverage percentage is
used. The fiscal status badge is `BLOCKED` when safe-blocked work exists,
`COMPLETE` when all products are complete, and otherwise `INCOMPLETE`.
Two blocker counts must remain distinct:
- **Safe-blocked products**: distinct open `(tenant_id, product_code)` pairs.
- **Open blockers**: open blocker rows; one product can have multiple rows for
different fields or evidence.
Dashboard attention is limited to ten items. Items are ordered by technical
health (`FAILED`, `DEGRADED`, `OFFLINE`, `UNKNOWN`), required-field blockers,
then outdated Agent versions; ties are stable. Safe-blocked products and
outdated versions do not imply technical failure. Failed jobs and outdated
Agents are also shown in compact sections, each with an explicit empty state
when there is no data. Dashboard health and fiscal summary cards remain visible
when lists are empty.
## Identity and time presentation
Agents, jobs, and blockers lead with human identity: client, installation
display name, and hostname where available. Technical numeric IDs and UUIDs
remain secondary details. Agent tables distinguish technical health from
fiscal status and provide a worst-fiscal-coverage sort. Job rows identify the
client and installation and show job ID, kind, status, timestamps, duration,
and error. Blocker rows identify the client/installation, product, field,
blocker type, operational priority, age, and detail link.
Database and API timestamps remain UTC. UI timestamps render in
`UI_TIMEZONE`, defaulting to `America/Bahia`, as `DD/MM/YYYY HH:MM` with a
relative age alongside them; a full technical timestamp is available in the
element title where applicable. Missing timestamps render as `-`. Job duration
uses start/finish timestamps (`em andamento` if not finished, `-` if not
started); it does not replace UTC persistence or API values.
## Blocker list, summary, and operational priority
The blocker page applies filters on the server: client, installation, field,
blocker type, status, age, and product/search. The filtered summary reports
open blocker rows, distinct affected `(tenant_id, product_code)` products,
distinct affected clients, and row breakdown by `CFOP`, `ST`, `ICMS`, `CSOSN`,
`NCM`, and `OTHER`. Filtered rows and their summary use the same filter set.
Priority is deterministic and operational only; it does not represent tax
severity, fiscal risk, legal consequence, or a tax recommendation. The current
tiers are:
- `CRITICAL`: known technical/connection/job-failure blockers or technical and
timeout reasons that prevent processing.
- `HIGH`: missing-evidence blocker types that require operator attention.
- `NORMAL`: recognized fiscal fields (`CFOP`, `ST`, `ICMS`, `CSOSN`, `NCM`) or
insufficient/no-evidence reasons without a higher operational tier.
- `LOW`: other optional or reference-enrichment cases.
The tier changes ordering/triage only. It must not be described as invented tax
severity.
## Details, events, and safe operations
Agent details present client, display name, and hostname before technical IDs,
separate technical/fiscal/version badges, and show human-formatted last-seen
time plus company context. Fiscal summary links to filtered blockers. Event
history supports server-side severity, type, date, job, and product filters
with pagination; event rows expose related job/product links when present.
Blocker details show evidence, first/last seen, retry count, related
events/jobs, and resolution audit history when available.
Resolving a blocker means saving validated operator context and queueing
reprocessing for that product; it does not directly write fiscal data or
immediately mark historical blocker evidence resolved. The workflow requires a
human-authenticated session and valid CSRF token. Accepted scopes are
`PRODUCT`, `GROUP`, and `COMPANY`; the scope/key/value are validated using the
existing context-key rules, including enum restrictions, and the required
reason/note is length-limited. `PRODUCT` scope must use the blocker product
code as its scope key. Arbitrary fields or keys are rejected.
The transaction creates or updates the validated context entry, creates a
`REPROCESS_PRODUCTS` job whose product list contains only the blocker product,
and records an audit event. The audit context includes operator/admin ID,
tenant/client, company key, installation identifiers, product code, blocker ID,
context key/scope/scope key/value, reason, before/after values, reprocess job
ID, and request IP when available. Validation or persistence failure rolls back
the operation. The action cannot write to Firebird, execute SQL/shell, or
enable AI writes.
Installation-wide reprocessing has its own confirmation page at
`/agents/{agent_id}/reprocess-confirmation`; only an explicit confirmed POST
with CSRF creates or reuses the pending full-reprocess job and records an audit
event. The confirmation page is part of the operator workflow, not a browser
`window.confirm` dialog.
## Authentication policy
Production administrator creation always requires the strong password policy.
Short/weak local development passwords are accepted only when
`ALLOW_WEAK_DEV_PASSWORD=1` and `APP_ENV` is not `production`. The flag never
weakens production policy. Existing local administrator credentials are not
changed by the control panel.
## Limits, responsive behavior, and boundaries
Dashboard metrics and lists use snapshots and bounded queries; the dashboard
does not scan product tables. List pagination is capped at 100 rows per page;
the UI requests 50 rows for Agents, Jobs, and Blockers, and 25 event rows per
Agent detail page. Dashboard attention is capped at ten; recent failed-job rows
are capped at ten. Blocker detail loads at most 100 related events/jobs/audits,
and displays a compact subset of event/job rows. Filters and pagination are
server-side.
The interface remains server-rendered with project-local CSS and minimal
progressive enhancement. Layouts adapt to desktop, tablet, and narrow screens;
wide data tables remain horizontally scrollable, focus states remain visible,
and health/status meaning is not communicated by color alone. Empty states
explain when there are no failed jobs, outdated Agents, blockers, or related
events/jobs.
The explicit non-production fixture is generated with:
```text
python -m central.scripts.generate_control_panel_fixture --agents 100 --confirm-non-production
```
The command preserves its non-production confirmation gate and is never run at
startup or migration time. This UX introduces no AI writes, Firebird writes,
production database changes, or deployment actions.
+15 -5
View File
@@ -84,13 +84,23 @@ The UI pages are `/`, `/agents`, `/agents/{agent_id}`, `/blockers`, `/jobs` and
`/login`. Primary rows show client, display name and hostname; UUIDs remain in
technical detail.
For dashboard semantics, operator workflows, timestamp presentation, bounded
filters, and responsive behavior, see
[`CONTROL_PANEL_OPERATIONAL_UX_V1.md`](CONTROL_PANEL_OPERATIONAL_UX_V1.md).
## Safe Actions
Human actions require a session, CSRF, explicit confirmation and an
`audit_events` row. The panel can create reprocess jobs and resolve blockers
only with explicit context. It cannot enable Firebird/AI writes, alter
credentials/path/CRT, execute SQL or shell commands, restart Windows services,
or update Agents automatically.
Human actions require a session and CSRF; mutating actions are audited in
`audit_events`. The panel can create reprocess jobs and save blocker context
only through their validated workflows. It cannot enable Firebird/AI writes,
alter credentials/path/CRT, execute SQL or shell commands, restart Windows
services, or update Agents automatically.
Reprocessing an installation presents a separate confirmation page before the
POST. Saving blocker context is a separate authenticated, CSRF-protected
workflow that validates the context and queues reprocessing for only that
blocker's product. See the operational UX contract for validation and audit
details.
## Fixture