# GTI Fiscal Control Panel V1 ## Architecture The existing FastAPI Hub is the single control plane. The web interface is server-rendered with Jinja2, project CSS, and small vanilla JavaScript. There is no SPA, React/Vue application, Node build chain, raw log upload, or remote shell path. The operational hierarchy is: ```text client -> installation -> agent -> company -> Firebird -> health -> coverage -> blockers -> jobs -> events ``` ## Identity Every Agent state database receives one UUID in `installation_identity`. `installation_id` is sent on heartbeat/registration and remains stable across restarts. `agent_id` is the Hub Agent record; hostname, display name and IP are metadata only. A conflicting installation UUID is rejected rather than silently reassigned. Registration metadata includes display name, customer code, hostname, Agent and Windows version, machine fingerprint, company context, masked CNPJ, Firebird version/ODS, sanitized database identifier, capabilities, fiscal engine, dataset versions and lifecycle times. Passwords, tokens, API keys and full connection strings are never persisted. ## Authentication Agents use the existing `Authorization: Bearer ` flow. Human users use `/login` and a separate `gti_admin_session` HttpOnly cookie backed by a server-side session hash. The CSRF value is separate and checked for every mutating human action. Create the first admin locally with: ```text python -m central.scripts.create_admin ``` Passwords are PBKDF2-HMAC-SHA256 hashes with random salts. Agent tokens are not accepted as web sessions. ## Health And Snapshots The Hub stores one `agent_snapshots` row per installation, containing product counts, completion, safe blockers, technical failures, coverage, blocker aggregates, job timestamps, health and version drift. The dashboard reads this snapshot instead of scanning product tables. - `ONLINE`: recent heartbeat and no technical failure. - `DEGRADED`: recent technical/job failure while processing remains possible. - `OFFLINE`: heartbeat older than `AGENT_OFFLINE_AFTER_SECONDS`, or three heartbeat intervals when that value is unset. - `FAILED`: persistent technical failure that prevents processing. - `UNKNOWN`: no usable heartbeat or snapshot. `SAFE_BLOCKED` is fiscal work isolation and does not itself make an Agent degraded or failed. Version drift is `CURRENT`, `OUTDATED` or `UNKNOWN` against `CURRENT_SERVER_VERSION`. ## Events And Retention Agents submit structured events at `POST /v1/agents/events`. Event types are allowlisted and messages/nested JSON are redacted and size-limited before storage. Raw log files are never uploaded. The default retention is 90 days (`AGENT_EVENT_RETENTION_DAYS`). Run `python -m central.scripts.maintain_events` for cleanup, or use `--dry-run` to inspect the command without deletion. Audit events, blocker history, critical events and write audit records are preserved. ## APIs And Screens Agent routes remain Bearer authenticated: `POST /v1/agents/register`, `POST /v1/agents/heartbeat`, and `POST /v1/agents/events`. Human panel APIs provide `/v1/dashboard/summary`, `/v1/agents`, `/v1/agents/{agent_id}` plus health, coverage, blockers, jobs and events, global `/v1/blockers/global` and `/v1/jobs/global`, and confirmed reprocess or blocker-resolution actions. Lists use bounded pagination and filters. 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 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 The explicit non-production fixture command is: ```text python -m central.scripts.generate_control_panel_fixture --agents 100 --confirm-non-production ``` It creates varied health states, snapshots, blockers, jobs and events, and is never invoked at startup or migration time.