feat: add autonomous fiscal control panel
This commit is contained in:
@@ -9,6 +9,15 @@ after a later successful evaluation. Partial processing keeps heartbeat and new
|
||||
jobs healthy. `AUTONOMOUSLY_PROCESSABLE_PRODUCTS=35066` despite
|
||||
`SAFE_BLOCKED_PRODUCTS=194`; no AI or Firebird write is required for operation.
|
||||
|
||||
## Control panel V1 foundation (2026-09-22)
|
||||
|
||||
`CONTROL_PANEL_FOUNDATION_IMPLEMENTED` — the Hub now has persistent installation
|
||||
identity, enriched metadata, snapshots, deterministic health/version drift,
|
||||
redacted structured events with retention, separate human admin sessions with
|
||||
CSRF, paginated control-plane APIs, and Jinja2 operator screens. The panel does
|
||||
not expose Agent tokens as human sessions and cannot enable AI/Firebird writes,
|
||||
execute SQL, or run shell commands.
|
||||
|
||||
## Autonomous fiscal completion V1 (2026-09-22)
|
||||
|
||||
`AUTONOMOUS_FISCAL_COMPLETION_V1_MEASURED` — requiredness matrix and pure
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
# 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 <agent-token>` 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.
|
||||
|
||||
## 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.
|
||||
|
||||
## 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.
|
||||
Reference in New Issue
Block a user