Arquitetura

Componentes, sequências e jobs assíncronos.

Visão de componentes

+---------------------------------------------------------------+
|                       CLIENTES                                |
|  +------------------+      +----------------+      +-------+  |
|  |  PWA (tablet)    |      | Leitor 1D/2D   |      | Zebra |  |
|  |  React + Vite    |<---->| HID Keyboard   |      | ZD220 |  |
|  +--------+---------+      +----------------+      +---+---+  |
|           | HTTPS                                       ^      |
|           v                                             |      |
|       Cloudflare CDN/WAF                          ZPL raw     |
|           |                                       (window.print)
+-----------+---------------------------------------------+-----+
            v
+---------------------------------------------------------------+
|                  CLOUDFLARE WORKERS (Hono)                     |
|  +--------------+ +-----------+ +----------+ +--------------+ |
|  | Rotas REST   | | Auth (JWT)| | FSM core | | Idempotency  | |
|  | /v1/*        | | PBKDF2    | | lifecycle| | KV / D1      | |
|  +------+-------+ +-----------+ +----------+ +--------------+ |
|         |                                                      |
|         v                                                      |
|  +--------------+    +--------+   +-----------+   +---------+ |
|  | D1 (SQLite)  |    | R2     |   | Queues    |   | KV      | |
|  | multi-tenant |    | photos |   | jobs/dlq  |   | cache   | |
|  +--------------+    +--------+   +-----------+   +---------+ |
|                                       |                        |
|                                       v                        |
|                              +------------------+             |
|                              | Queue consumer   |             |
|                              | REPORT / RECALL  |             |
|                              | ERP_WEBHOOK ...  |             |
|                              +--------+---------+             |
+---------------------------------------+----------------------+
                                        |
                                        v HTTPS + HMAC
                                  +----------------+
                                  |  ERP / CCIH    |
                                  |  (externo)     |
                                  +----------------+
      

Sequência: lifecycle scan

Único ponto de entrada para qualquer leitura de código de barras/QR no chão operacional.

PWA               Worker (Hono)               D1                FSM
 |  POST /v1/lifecycle/scan                    |                 |
 |  { barcode, target_phase, context }         |                 |
 |---------------->|                           |                 |
 |                 | requireAuth + idempotency |                 |
 |                 |---------- SELECT ------>  |                 |
 |                 |  (item, kit, equipamento, batch corrente)   |
 |                 |<--------- rows ---------  |                 |
 |                 |  transition(entity, currentStatus, event)   |
 |                 |---------------------------------------------->|
 |                 |<--- newStatus | Error (regra térmica/peso/quarentena/recall)
 |                 |  INSERT ict_lifecycle_events                |
 |                 |---------- INSERT ------>  |                 |
 |                 |  audit('lifecycle.scan')                    |
 |                 |---------- INSERT ------>  |                 |
 |  200 { ok: true, new_status }               |                 |
 |<----------------|                           |                 |
      

Sequência: recall biológico em cascata

Supervisor              Worker                  Queue                 ERP
 |  POST /v1/recall (botão pânico, 2x confirmação)
 |--------------------->|
 |                      | INSERT ict_recall_events (OPEN)
 |                      | enqueue { type: 'RECALL_CASCADE', recall_id }
 |                      |-------------------------->|
 |  200 { id }          |                           |
 |<---------------------|                           |
                                                    v
                                            +------------------+
                                            | Queue consumer   |
                                            | expandBatch()    |
                                            |  batch -> kits   |
                                            |  kits -> cirurgias
                                            |  cir. -> pacientes
                                            +--------+---------+
                                                     |
                                                     v
                                            UPDATE kit_instances
                                            SET is_quarantined = 1
                                            UPDATE ict_recall_events
                                            SET status = 'IN_PROGRESS'
                                                     |
                                                     v enqueue ERP_WEBHOOK
                                            +------------------+
                                            | Webhook delivery |
                                            | HMAC-SHA256      |
                                            +--------+---------+
                                                     |
                                                     v POST + retry exp.
                                                  ERP / CCIH
                                                     |
                                                     v 2xx
                                            UPDATE ict_recall_events
                                            SET status = 'CLOSED'
      

Sequência: troca de organização (matriz → filial)

PWA                   Worker                          D1
 | GET /v1/auth/accessible-orgs
 |--------------------->|
 |                      | SELECT orgs WHERE id = home OR parent_org_id = home
 |                      |  (ADMIN ve todas; demais apenas concedidas via ict_user_org_access)
 |  { items: [...] }    |
 |<---------------------|
 | usuário escolhe filial X
 | POST /v1/auth/switch-org { target_org_id: X }
 |--------------------->|
 |                      | valida X.parent_org_id = home OR role = ADMIN
 |                      | re-assina JWT com org_id = X, home_org_id = home
 |  { token, org: X }   |
 |<---------------------|
 | reseta TanStack Query e refetch /v1/me
      

Crons

Schedule (UTC)JobEfeito
0 4 * * *Bowie-Dick diárioMarca autoclaves vapor como BLOCKED_BOWIE_DICK; RT precisa liberar.
30 */6 * * *BI readyVarre indicadores biológicos com incubação finalizada; gera alerta.
45 */6 * * *Manutenção preventivaItens cujo cycles_count ≥ vida_util_estimada entram em passivação obrigatória.

Tipos de job na fila

Hierarquia matriz/filial em D1

ict_organizations
+----+--------+----------+-----------+---------------+
| id | slug   | legal_   | org_type  | parent_org_id |
|    |        | name     |           |               |
+----+--------+----------+-----------+---------------+
| HQ | matriz | "Rede X" | HQ        | NULL          |
| B1 | sp-1   | "Filial" | BRANCH    | HQ            |
| B2 | rj-1   | "Filial" | BRANCH    | HQ            |
+----+--------+----------+-----------+---------------+

ict_user_org_access  (concessões cruzadas)
+----+---------+--------------+-----------------+--------+
| id | user_id | home_org_id  | target_org_id   | role   |
+----+---------+--------------+-----------------+--------+
| .. | U1      | HQ           | B1              | NURSE  |
| .. | U1      | HQ           | B2              | NURSE  |
+----+---------+--------------+-----------------+--------+

JWT após switch-org:
{
  sub: U1, role: NURSE,
  org_id: B1, org_slug: "sp-1",
  home_org_id: HQ, home_org_slug: "matriz"
}