Files
OmniRoute/docs/FASE-09-e2e-flow-hardening.md
diegosouzapw 492afc4ff1 refactor: decompose usageDb, handleSingleModelChat, UI components (T-15, T-28, T-29)
T-15 — Decompose usageDb.js (969→40 lines):
- Extract src/lib/usage/migrations.js (legacy + JSON→SQLite migration)
- Extract src/lib/usage/usageHistory.js (tracking, pending, log.txt)
- Extract src/lib/usage/costCalculator.js (pure cost calculation)
- Extract src/lib/usage/usageStats.js (dashboard aggregation)
- Extract src/lib/usage/callLogs.js (structured logs, CRUD, rotation)
- usageDb.js is now a thin facade re-exporting all functions

T-28 — Decompose handleSingleModelChat (183→80 lines):
- Extract handleNoCredentials() — credential error responses
- Extract safeResolveProxy() — proxy resolution with error handling
- Extract safeLogEvents() — fire-and-forget proxy + translation logging
- Also created chatHelpers.js with standalone helper exports

T-29 — Extract shared UI primitives (3230 total lines):
- FilterBar.js — search input + filter chips dropdown
- ColumnToggle.js — table column visibility toggle
- DataTable.js — generic data table with sticky header, loading/empty

Tests: 88/88 pass (no regressions)
2026-02-14 18:53:14 -03:00

5.9 KiB
Raw Blame History

FASE 09 — Hardening de Fluxo Ponta a Ponta

Prioridade: 🟡 Moderado / 🟢 Menor
Estimativa de Complexidade: Média (35 dias)
Dimensões do Relatório: D9 (Fluxo Ponta a Ponta)
Dependências: FASE-04 (correlation ID e error codes), FASE-08 (policy engine e cache)


Objetivo

Endurecer o fluxo completo de requisição (request lifecycle), adicionando state tracking para streams, telemetria por etapa, e extraindo regras de negócio residuais dos controllers para domain services.


Escopo Detalhado

9.1 — State Machine para Streams SSE

Origem no relatório: D9 — Sem State Machine para Processos Longos (🟠 Importante)

Especificação Técnica

  • Criar src/sse/services/streamState.js:

    export const STREAM_STATES = {
      INITIALIZED: "initialized",
      CONNECTING: "connecting",
      STREAMING: "streaming",
      COMPLETED: "completed",
      FAILED: "failed",
      CANCELLED: "cancelled",
    };
    
    export class StreamTracker {
      constructor(requestId) {
        this.requestId = requestId;
        this.state = STREAM_STATES.INITIALIZED;
        this.transitions = [];
      }
      transition(newState, metadata = {}) {
        this.transitions.push({ from: this.state, to: newState, at: Date.now(), ...metadata });
        this.state = newState;
      }
    }
    
  • Integrar no pipeline de streaming em handleSingleModelChat:

    • INITIALIZEDCONNECTING (antes do fetch).
    • CONNECTINGSTREAMING (primeiro chunk recebido).
    • STREAMINGCOMPLETED (stream finalizado).
    • STREAMINGFAILED (erro durante stream).
    • Qualquer → CANCELLED (client disconnect).
  • Logar transições de estado com requestId.

  • Expor estado ativo via endpoint /api/streams/active.

Critérios de Aceite

  • Cada stream tem tracking de estado explícito.
  • Transições são logadas.
  • Endpoint mostra streams ativos e seus estados.
  • Client disconnect detectado e marcado como CANCELLED.

9.2 — Telemetria por Etapa do Request Pipeline

Origem no relatório: D9 — Telemetria por Jornada Ausente (🟡 Moderado)

Especificação Técnica

  • Criar src/shared/utils/requestTelemetry.js:
    • Metrificação por etapa:
      export class RequestTelemetry {
        constructor(requestId) {
          this.requestId = requestId;
          this.timings = {};
        }
        startPhase(phase) {
          this.timings[phase] = { start: performance.now() };
        }
        endPhase(phase) {
          this.timings[phase].end = performance.now();
        }
        getSummary() {
          return Object.entries(this.timings).reduce((acc, [k, v]) => {
            acc[k] = v.end - v.start;
            return acc;
          }, {});
        }
      }
      
    • Fases medidas:
      1. parse — Parse do body e validação.
      2. model_resolution — Resolução de modelo/combo.
      3. credential_selection — Seleção de conta.
      4. translation — Tradução de request.
      5. provider_fetch — Fetch para o provider.
      6. response_translation — Tradução da resposta.
      7. total — End-to-end.
  • Armazenar telemetria no call log (campo timings).
  • Expor via endpoint /api/telemetry/summary — p50, p95, p99 por fase.
  • Exibir no dashboard (gráfico de latência por fase).

Critérios de Aceite

  • Cada request tem telemetria por fase.
  • Call logs armazenam campo timings.
  • Endpoint de summary retorna p50/p95/p99.
  • Dashboard exibe gráfico de latência.

9.3 — Extração de Regras de Negócio Residuais

Origem no relatório: D9 — Regra de Negócio em Controller (🟡 Moderado)

Especificação Técnica

  • Auditar src/sse/handlers/chat.js para regras de negócio em controller:
    • isModelAvailable() → mover para src/domain/modelAvailability.js (FASE-03).
    • Lógica de per-model lockout → mover para src/domain/lockoutPolicy.js.
    • Lógica de "combo resolution" → mover para src/domain/comboResolver.js.
  • Refatorar handler para ser um "thin controller":
    // sse/handlers/chat.js — objetivo final
    async function handleChat(request) {
      const body = parseRequest(request);
      const model = comboResolver.resolve(body.model);
      const credentials = await credentialService.select(model);
      const translated = translator.translate(body, model.format);
      const response = await providerService.execute(credentials, translated);
      return translator.translateResponse(response, body.format);
    }
    
  • Garantir que cada módulo domain tenha testes unitários.

Critérios de Aceite

  • Handler handleChat tem < 50 linhas de lógica.
  • ≥ 3 funções extraídas para domain layer.
  • Domain modules testados unitariamente.
  • Nenhuma regra de negócio no handler.

Pré-Requisitos

  • FASE-04 (correlation ID para integração com telemetria).
  • FASE-03 (domain layer como destino das regras extraídas).
  • FASE-08 (policy engine como parte do pipeline).

Entregáveis

  1. Stream state machine com tracking.
  2. Telemetria por fase com métricas p50/p95/p99.
  3. Handler refatorado como thin controller.

Critérios de Conclusão da Fase

  • Streams com tracking de estado.
  • Telemetria armazenada e acessível.
  • Handler < 50 linhas de lógica de negócio.

Riscos Identificados

Risco Probabilidade Impacto Mitigação
Telemetria overhead em high-throughput Média Médio Sampling configurável (1%, 10%, 100%)
State machine complexidade adicional Baixa Baixo Implementação minimalista; apenas 6 estados
Extração de regras cria regressões Média Médio Testes completos do pipeline antes e depois