← Portfólio / Engenharia
Maio 2026 · win-desktop-main
Documentação Técnica Completa

Engenharia do
Vetorizador

Uma revista técnica sobre a arquitetura, módulos, contratos e evolução do Vetorizador — software desktop para produção geoespacial e documental com núcleo determinístico Rust/WASM.

📅Maio 2026
🌿win-desktop-main
🦀Rust + WASM
Electron v41 + Vite 8
📦14 módulos ativos
Capítulo 01

Visão Geral da Arquitetura

O Vetorizador é um sistema desktop composto por renderer local em Electron, serviços locais em Node/Python e um núcleo determinístico de vetorização em Rust/WebAssembly. A arquitetura prioriza entrega operacional local-first.

6Subsistemas
14Módulos ativos
4Fontes de polígono
WASMNúcleo soberano

Fluxo arquitetural principal

1

UI Leaflet + Controles

Usuário localiza área, desenha ROI e configura preset.

2

Pré-processamento JS

Realce de contraste, Sobel, Otsu, morfologia e DBSCAN opcional.

3

vetoriza_imagem (Rust/WASM)

Núcleo determinístico converte imagem em polígonos GeoJSON.

4

Seleção, revisão e desambiguação

Guardrails por preset, regularização geométrica, modal de desambiguação entre fontes sobrepostas, Shift multi-select cruzado.

5

Exportação / Persistência local

GeoJSON, Shapefile, memorial DOCX ou relatório PDF. No confronto SIGEF, ZIP com SHP de polígono + pontos de vértice (DE/PARA). Runs e feedback persistidos em IndexedDB.

Princípio central: todo o fluxo ativo de vetorização é deterministico e WASM-only — sem dependência de inferência externa no caminho principal de geração de polígonos.
Capítulo 02

Subsistemas

O produto é organizado em 6 subsistemas com responsabilidades bem delimitadas.

🗺️

Shell principal de interface

index.html, style.css, app.js — mapa, navegação entre modos, exibição de resultados e embed do PDFSpliter.

⚙️

Pipeline de vetorização

app.js, geo-postprocess.js, scene-classifier.js, vetoriza/src/lib.rs — captura ROI → WASM → pós-processamento → exportação.

💾

Persistência e estado

app-boundary-manager.js + trechos de app.js — IndexedDB operacional, localStorage, camada de referência APP local por instalação.

📡

Serviços embarcados e APIs

api/pdf-to-geojson/*, api/shp-to-geojson/* — OCR, PDFtoArcGIS, conversão SHP local.

🧾

Confrontação SIGEF & Memorial

sigef-wfs.js, sigef-memorial.js, app.js — consulta WFS, importação SHP SIGEF (polígono ou pontos), seleção/desambiguação de referência, confronto de vértices, geração de DOCX e exportação SHP dupla (polígono + pontos) com cota Z.

🖥️

Runtime desktop

desktop/main.cjs, desktop/app-server.cjs, desktop/preload.cjs — janela Electron, servidor HTTP local, proxies e instalador Windows.

Capítulo 03

Pipeline de Seleção de Polígonos

Todo clique em polígono no mapa passa por um pipeline unificado que opera sobre 4 fontes simultâneas com suporte a desambiguação e multi-seleção por Shift.

As 4 fontes de candidatos

🤖

geojsonFeatures

Polígonos vetorizados automaticamente pelo pipeline WASM.

✏️

manualPolygonFeatures

Polígonos desenhados manualmente pelo usuário com Leaflet.Draw.

📂

Camada de referência (APP)

Shapefile importado gerenciado pelo app-boundary-manager.

🏛️

Parcelas SIGEF

Features carregadas por consulta WFS ao Acervo Fundiário INCRA.

Helpers do pipeline novos

FunçãoPapel
aplicarSelecaoCandidataNoMapa(item, layer, evt)Ponto único de despacho após desambiguação ou clique direto; roteia para SIGEF, referência importada ou polígono regular.
aplicarSelecaoSigefNoMapa(idx, multiSelect)Toggle de seleção SIGEF com atualização de estilo e chamada a atualizarExportSigefUi().
_buscarLayerPorFeatureId(featureId)Localiza layer Leaflet pelo ID da feature em drawnItems.
_mostrarDicaMultiSelecao()Exibe notificação educativa sobre Shift+clique (uma única vez por instalação).

Variáveis globais críticas

let _selecaoMemorialAtiva = false;       // true quando aguardando clique para memorial
let _selecaoMemorialClickHandler = null;  // handler registrado durante seleção de memorial
let selectedFeatureId = null;            // feature ativa (single)
const selectedFeatureIds = new Set();     // features selecionadas (multi)
let sigefSelectedIds = new Set();         // índices SIGEF selecionados
let suppressMapClickDeselectUntil = 0;   // timestamp para suprimir deselect
Shift multi-select: funciona em todas as 4 fontes simultaneamente. Shift+clique adiciona ao conjunto sem desselecionar os demais. Na primeira seleção simples, uma notificação educativa é exibida (chave vetorizador_multiselect_hint_v1).
Capítulo 04

Fronteiras Arquiteturais

Contratos que devem ser preservados em qualquer refatoração ou extensão do sistema.

🦀 Fronteira 1 — WASM soberano

vetorizar_imagem continua sendo a única fonte de extração geométrica. O fluxo ativo permanece determinístico (WASM-only). Saída obrigatória: GeoJSON Polygon com anel fechado, coordenadas normalizadas em pixels [0.0, 1.0].

💾 Fronteira 2 — Camada de referência local por instalação

A camada de referência topográfica (APP) permanece local no desktop. No fluxo de memorial SIGEF, exatamente 1 polígono de referência é escolhido por clique (com desambiguação se necessário), com candidatos das 4 fontes disponíveis no mapa.

⚡ Fronteira 3 — CONFIG como contrato central

Parâmetros do pipeline dependem de CONFIG em app.js. Qualquer novo parâmetro precisa refletir: controles de UI, sincronizarControle, aplicarPreset e resetarParametros.

🖥️ Fronteira 4 — Desktop como produto de primeira classe

O instalador Windows não é acessório. O build desktop carrega frontend compilado, endpoints locais e artefatos WASM. Firebase/Firestore foram removidos; toda persistência é local-first.

Capítulo 05

Padrões de Design GoF

Padrões identificados por contrato reverso no codebase atual.

Singleton

Evidências: app-boundary-manager.js mantém estado da camada de referência em escopo de módulo; CONFIG em app.js é fonte única de parâmetros; cache de módulos dinâmicos em _modulosDinamicos.

Limitação: uso acoplado a variáveis globais dificulta testes isolados e injeção de dependência. Melhoria recomendada: introduzir AppContext explícito.

Strategy

Evidências: seleção de comportamento por preset (cobertura, uso_solo, manual); guardrails por cenário em geo-postprocess.js; pontuação de cena em scene-classifier.js.

Status de melhoria: PresetManager já extraído com contrato estável. Estratégias de pipeline ainda espalhadas como condicionais em app.js.

Template Method

Evidências: pipeline principal com sequência fixa (captura → Sobel → Otsu → morfologia → DBSCAN → WASM → pós-processamento → exportação); scene-classifier.js com roteiro estável; vetoriza/src/lib.rs com sequência determinística.

Factory Method

Evidências: createAppBoundaryManager(), createFeatureFlagManager(), createPresetManager(deps), createStateManager(), createVectorizationPipeline({ executeCore }) — todos recebem dependências injetadas e retornam instâncias com API pública estável.

Observer

Evidências: listeners de eventos Leaflet (layer.on('click'), map.on('draw:created')); interceptação de console.* pelo sistema de diagnóstico; window.addEventListener para erros globais e beforeunload.

Capítulo 06

Módulos Core do Frontend

app.js

Orquestrador principal (~12 000 linhas)

Inicialização do shell, estado global, pipeline de configuração, integração mapa-WASM-persistência. Pipeline de seleção unificado para 4 fontes. Helpers novos: aplicarSelecaoCandidataNoMapa, aplicarSelecaoSigefNoMapa, _buscarLayerPorFeatureId.

crítico seleção multi-fonte shift multi-select snap auto-vertex
index.html

Shell da interface principal

Containers, painéis, botões, modais. Ordem de carregamento: CDN libs → vetoriza/pkg/vetoriza.jsapp.js. Modal #seletorPoligonoModal para desambiguação global.

ordem de script crítica
geo-postprocess.js

Pós-processamento geométrico

Supressão de redundância geométrica, filtros por área/bbox/IoU, guardrails por preset, refinamento de features. Não depende de DOM.

sem DOM
scene-classifier.js

Classificação de cena

Classifica a cena da ROI para apoiar seleção automática de preset e definir limites de comportamento determinístico por cenário.

sem DOM
Capítulo 07

Módulos de Suporte

app-boundary-manager.js

Gerenciador da camada de referência (APP)

Concentra o ciclo de vida da camada de referência topográfica por instalação. Normaliza GeoJSON, persiste cache em localStorage (vetorizador_app_boundary_v2), exibe no mapa. O callback onFeatureClick delega para lidarCliquePoligono tornando a camada participante da desambiguação global.

local-firstfactory
feature-flag-manager.js

Gerenciador de feature flags

Flags persistidas em localStorage, guardrails WASM-only, auditoria operacional, BENCHMARK_APROVACAO_PRESET por preset. Inicialização: initFeatureFlagManager({ syncConfigField }).

wasm-only guardrailauditoria
preset-manager.js

Gerenciador de presets

PRESET_DEFINITIONS, PRESET_PIPELINE_RULES, PRESET_POLY_QUALITY_DEFAULTS, CONFIG_RESET_DEFAULTS. Factory: createPresetManager(deps). Presets visíveis na UI: cobertura e uso_solo; perfil manual normalizado para cobertura.

factorypresets
state-manager.js

Gerenciador de estado de sessão

Centraliza estado mutável da sessão: modoVetorizacao, geojsonFeatures, manualPolygonFeatures, activeRunId, activeRunStartedAt, currentSelectionMaskFeature. Mantém estabilidade de referência dos arrays para compatibilidade de callsites.

factoryestado central
vectorization-pipeline.js

Fronteira explícita do pipeline

Factory createVectorizationPipeline({ executeCore }). Expõe processarAreaDesenhada delegando a implementação core para executeCore injetado. Permite evolução do desacoplamento interno sem quebrar a interface pública.

factoryfronteira limpa
selection-policy.js

Política de seleção (UX)

Centraliza regras de UX de seleção no mapa. Exporta shouldOpenPopupForSelection({ multiSelect }) — retorna true apenas quando não é Shift+clique. Ponto único de decisão sobre abertura de popup para todas as 4 fontes.

ux policysem DOM
flow-diagnostics.js

Telemetria de fluxos operacionais

Exporta flowStart(name, details), flowSuccess(name, details) e flowError(name, error) para rastreamento padronizado de início/sucesso/erro de fluxos via window.DIAG?.section('FLOW', ...). Dependência opcional — inerte quando DIAG não está disponível.

observabilidadesem DOM
diagnostic-logger.js

Sistema de diagnóstico total

Buffer circular de 8 000 entradas. Módulos internos emitem diretamente via window.DIAG?.* com categorias estruturadas. Cobertura ampliada para importação SIGEF, desambiguação de rótulos, memorial e exportação SHP confrontado (com flowStart/flowSuccess/flowError). Interceptação de console.* captura libs externas como fallback. Archive em IndexedDB, exportação consolidada. API:

DIAG.log(cat, msg, data)       // 3 params — SEMPRE
DIAG.warn(cat, msg, data)      // 3 params
DIAG.error(cat, msg, data)     // 3 params
DIAG.funcEntry(funcName, data)
DIAG.uiEvent(element, eventType, details)
DIAG.section(cat, name, data)
observabilidadeIndexedDB archive
Capítulo 08

Desktop & APIs Auxiliares

Runtime desktop (Electron v41)

🚀

desktop/main.cjs

Bootstrap Electron, ciclo de vida da aplicação, criação da janela principal, sandbox + contextIsolation.

🌐

desktop/app-server.cjs

Servidor HTTP local (porta 3210), exposição do frontend compilado, proxies para WFS INCRA, Nominatim e elevação SRTM.

🔌

desktop/preload.cjs

Ponte controlada entre renderer e capacidades do Electron.

Proxies do backend local

EndpointDestino realMotivo do proxy
/api/proxy/nominatim-reversenominatim.openstreetmap.orgCORS/CSP no renderer
/api/proxy/nominatim-searchnominatim.openstreetmap.orgCORS/CSP no renderer
/api/proxy/incra-wfsWFS SIGEF INCRA por UFCORS/CSP no renderer
/api/proxy/elevationapi.opentopodata.org (SRTM 30m)CORS/CSP no renderer
/api/pdf-to-geojson— (local)OCR + parser local
/api/shp-to-geojson— (local)Conversão shapefile
/api/sigef-imoveis— (local)Consulta e download SIGEF WFS

SIGEF & Memorial (módulos independentes)

📡

sigef-wfs.js

Consulta WFS público INCRA, detecção automática de UF pela ROI, normalização GeoJSON, roteamento pelo proxy desktop.

📜

sigef-memorial.js

Comparação de vértices (haversine 5 m), herança de coordenadas SIGEF, cota Z via SRTM, geração de DOCX e exportação SHP confrontado.

Capítulo 09

Fluxo de Vetorização Automática

01

Localizar e capturar

Busca por endereço (Nominatim) ou coordenada. Desenho da ROI com Leaflet.Draw.

02

Pré-processar imagem

Realce de contraste (contrastBoost), Sobel, Otsu, morfologia (morphologySize), DBSCAN opcional (clusterEps, clusterMinPts).

03

vetorizar_imagem (WASM)

Base64 PNG → núcleo Rust → FeatureCollection GeoJSON em pixel-space [0,1].

04

Pós-processamento geométrico

geo-postprocess.js: NMS, filtro por área/bbox/IoU, guardrails por preset, simplificação, regularização.

05

Conversão pixel → coordenada

Transformação de pixel-space para lat/lng com base nos bounds da ROI.

06

Revisão visual + exportação

Polígonos exibidos no mapa com código de cor por qualidade. Exportação GeoJSON, Shapefile, relatório APP.

preset uso_solo inclui etapas adicionais: classificação de cor por cluster (HSL/ExG), mapa de classes suavizado, componentes por classe com 8-conectividade, cookie-cutter entre classes e guardrails de orçamento para ROI grandes.
Capítulo 10

Confrontação SIGEF & Memorial Descritivo

01

Consulta WFS SIGEF

UF detectada automaticamente pela ROI. Requisição via proxy local /api/proxy/incra-wfs. Parcelas carregadas como camada Leaflet selecionável.

02

Carregar imóvel de referência

Shapefile compactado ZIP → conversão local → app-boundary-manager. Cache em vetorizador_app_boundary_v2.

03

Modo de seleção de referência

_selecaoMemorialAtiva = true, cursor crosshair. Clique no mapa ativa _selecaoMemorialClickHandler. Candidatos: 4 fontes de polígono. Sobreposição → modal de desambiguação.

04

Confronto de vértices

Haversine ≤ 5 m → vértice certificado (herda coordenadas SIGEF, prefixo do campo rt/RT). Haversine > 5 m → vértice novo (prefixo NV-001).

05

Cota Z

Prioridade: metadados SIGEF → coord[2] do polígono → SRTM 30m via /api/proxy/elevation. coord[2] === 0 tratado como ausente. Campo altitudeSource: SIGEF, POLIGONO_CARREGADO ou SRTM.

06

Geração e exportação

Memorial DOCX com azimute, distância (haversine), área geodésica (ha) e cota Z por vértice. SHP confrontado com campos COTA_N_MIN/MAX/MED, COTA_S_MIN/MAX/MED e COTA_FONTE.

Correções aplicadas em sigef-memorial.js: distância haversine (era Math.hypot em graus → 0,00 m); área geodésica (era signedArea em graus → 0,00 ha); tolerância de certificação (era 0,00005° ≈ 0,05 mm → agora 5 m); Z=0 do WFS tratado como ausente.
Capítulo 11

Desambiguação Global de Sobreposição

Quando um clique no mapa intercepta 2 ou mais polígonos de qualquer fonte, o modal de desambiguação é acionado automaticamente para garantir escolha explícita.

Lógica de escolherComDesambiguacaoGlobal()

Promise-based. Recebe array de candidatos { key, source, feature, label, featureId?, boundaryIdx?, featureIdx? }, ordena por área crescente (menor = mais específico primeiro) e exibe swatches de cor 44×44 px em grid. Cancela com reject(); escolha com resolve(item).

DIAG registra 3 fases: modal-aberto, escolhido e cancelado.

Estilo de seleção

aplicarEstiloSelecao(baseStyle, isSelected) retorna: color: '#00e5ff', weight+2, opacity: 1, dashArray: null (sem tracejado — borda sólida).

SIGEF selecionado: SIGEF_STYLE_SELECTED = { color: '#b71c1c', fillColor: '#ef5350', fillOpacity: 0.50, weight: 3 }.

Capítulo 12

Snap & Auto-vertex por Shift

Durante o desenho de polígonos de atributos, pontos magnéticos de snap são exibidos. Segurar Shift ativa inserção automática de vértices a cada ponto detectado.

Variáveis de controle

let _snapShiftAutoActive = false;  // Shift pressionado = auto-inserção ativa
let _snapLastAutoPoint = null;     // último ponto auto-inserido (deduplicação)

Ciclo de vida

1

mousemove

Se _snapShiftAutoActive && snap && snap !== _snapLastAutoPoint → insere vértice automaticamente e atualiza _snapLastAutoPoint.

2

keydown Shift

_snapShiftAutoActive = true. Hint atualizado: "Segure Shift = auto-snap". Cliques ignorados enquanto Shift estiver pressionado (evita duplicata).

3

keyup Shift

_snapShiftAutoActive = false. Retorna ao modo manual.

4

_pararDesenhoPoligonoAtributos()

Remove listener keyup, reinicia _snapShiftAutoActive = false e _snapLastAutoPoint = null.

Capítulo 13

CONFIG & Estado de Sessão

Estrutura CONFIG (app.js)

Fonte única de parâmetros do pipeline. Todo novo campo exige atualização em 4 lugares.

CampoTipoPapel
edgeThresholdnumberLimiar de borda Sobel/Otsu
morphologySizenumberKernel de morfologia (closing)
minAreanumberÁrea mínima candidata (pixels)
simplificationnumberTolerância Douglas-Peucker
contrastBoostnumberFator de amplificação de contraste
minQualityScorenumberScore mínimo para aceite
mergeDistancenumberDistância de fusão
clusteringEnabledbooleanHabilita agrupamento DBSCAN
clusterEpsnumberRaio DBSCAN
clusterMinPtsnumberDensidade mínima DBSCAN
presetProfilestringPerfil ativo

Estado de sessão (state-manager.js)

CampoTipoPapel
modoVetorizacao'auto'|'manual'Modo operacional ativo
geojsonFeaturesarrayFeatures de vetorização automática
manualPolygonFeaturesarrayFeatures de desenho manual
activeRunIdstring/nullID da execução corrente
currentSelectionMaskFeatureFeature/nullMáscara de seleção ativa
Capítulo 14

Persistência Local

IndexedDB — vetorizador_learning_db

📦

runs

Snapshot de execução: bounds, config, relatório, features. Apenas execuções modoVetorizacao = auto.

💬

feedback

Validações do usuário e marcações de qualidade por feature. Índices: runId e featureId.

IndexedDB — vetorizador_diagnostic_archive_db

📋

entries

Eventos de diagnóstico por sequência. Retenção controlada em modo session-only.

🗂️

sessions

Metadados de sessão de diagnóstico. Máx. 4 sessões + 24h de retenção.

Chaves localStorage

ChaveMóduloPropósito
vetorizador_app_boundary_v2app-boundary-managerCache da camada de referência (APP)
vetorizador_app_boundary_v1app-boundary-managerChave legada — lida apenas para migração automática para _v2
vetorizador_feature_flags_v1feature-flag-managerFeature flags persistidas
vetorizador_backend_refine_audit_v1feature-flag-managerAuditoria operacional de flags
vetorizador_assist_telemetry_v1app.jsTelemetria leve de uso
vetorizador_multiselect_hint_v1app.jsFlag notificação educativa Shift multi-select
Capítulo 15

Contrato WASM

Interface formal da função exportada pelo módulo Rust vetoriza/src/lib.rs.

Assinatura

vetorizar_imagem(base64_png: string) → string // JSON serializado
ParâmetroTipoDescrição
base64_pngstringPNG codificado Base64, sem prefixo data URI. Deve ser escala de cinza, sem alpha, pré-processado.

Saída — FeatureCollection GeoJSON

{
  "type": "FeatureCollection",
  "features": [{
    "type": "Feature",
    "geometry": {
      "type": "Polygon",
      "coordinates": [[[lon, lat], ..., [lon, lat]]]
    },
    "properties": {}
  }]
}

Invariantes garantidos

🔒

Anel fechado

Último ponto = primeiro ponto. Sempre.

📐

Sem furos

Cada Polygon tem exatamente um anel externo.

📏

Pixel-space [0, 1]

Coordenadas normalizadas. Conversão para lat/lng em app.js.

Inicialização

// index.html — ordem crítica
<script src="vetoriza/pkg/vetoriza.js"></script>

// app.js
await wasm_bindgen(wasmUrl);
vetorizar_imagem = wasm_bindgen.vetorizar_imagem;

Rebuild WASM após mudanças em vetoriza/src/lib.rs: wasm-pack build --target no-modules --release

Capítulo 16

Sistema de Diagnóstico

Capacidades

🔄

Buffer circular

8 000 entradas em memória com sequência, timestamp e categoria.

Telemetria direta

Módulos internos chamam window.DIAG?.* diretamente (186 call sites). console.* interceptado como fallback para libs externas (Leaflet, Turf, shpwrite).

💾

Archive IndexedDB

Flush periódico para vetorizador_diagnostic_archive_db. Retenção session-only, máx. 4 sessões.

📤

Exportação consolidada

Botão único exporta: buffer + archive + contexto expandido em JSON auditável offline.

Categorias de log registradas

APP GEO SCENE PRESET BOUNDARY WASM NET ROI EXPORT MAP CONFIG SESSION CONSOLE GLOBAL UI SECTION BACKEND
Atenção: DIAG.log() aceita exatamente 3 parâmetros (category, message, data). Chamadas com 4 parâmetros são incorretas e devem ser corrigidas.
Capítulo 17

Rastreabilidade de Requisitos Funcionais

Referência: Abril 2026 · Branch win-desktop-main

30RF total
26Implementados
3Parciais
0Pendentes
IDNomeStatusMódulo
RF-01Busca cartográficaImplementadoapp.js → Nominatim
RF-03Delimitação da ROIImplementadoapp.js, Leaflet.Draw
RF-04Alternância de modoImplementadostate-manager.js
RF-06Seleção de presetImplementadopreset-manager.js
RF-09Pré-processamento da imagemImplementadovectorization-pipeline.js
RF-10Agrupamento DBSCANImplementadoapp.js
RF-11Vetorização determinísticaImplementadovetoriza/src/lib.rs
RF-12Pós-processamento geométricoImplementadogeo-postprocess.js
RF-13Operação WASM-onlyParcialfeature-flag-manager.js
RF-16Exportação GeoJSONImplementadoapp.js
RF-17Exportação ShapefileImplementadoapp.js, shpwrite
RF-19Camada de referênciaImplementadoapp-boundary-manager.js
RF-20Persistência local runsImplementadoIndexedDB vetorizador_learning_db
RF-23Operação sem autenticaçãoImplementadoapp.js, app-boundary-manager.js
RF-25Resiliência offlineImplementadoIndexedDB + localStorage
RF-26Módulo PDFImplementadopdfspliter/ via iframe
RF-28Runtime desktopImplementadodesktop/main.cjs
RF-30Telemetria e auditoriaParcialdiagnostic-logger.js
Capítulo 18

Requisitos Não Funcionais

14RNF total
11Implementados
3Parciais
IDNomeStatusObservação
RNF-01Consistência geométricaImplementadoPolígonos fechados garantidos pelo WASM
RNF-02Determinismo do núcleoImplementadoWASM como única fonte de extração
RNF-03Desempenho operacionalParcialMeta < 60s/imagem documentada; sem benchmark automatizado formal
RNF-04Qualidade mínimaParcialF1 ≥ 0,70 e IoU ≥ 0,60 definidos; sem regressão automatizada
RNF-05Continuidade offlineImplementadoFluxos locais independentes de conectividade
RNF-07ObservabilidadeImplementado186 call sites migrados para window.DIAG?.*; categorias APP, GEO, SCENE, PRESET, BOUNDARY; fallback para libs externas
RNF-08PortabilidadeImplementadoRuntime Electron para Windows (desktop)
RNF-10ManutenibilidadeImplementado5 módulos extraídos; desacoplamento fino fase 2 pendente
RNF-11Segurança operacionalImplementadoDados sensíveis permanecem locais no desktop
RNF-14AuditabilidadeImplementadoLogs de decisão, auditoria de flags, telemetria local
Capítulo 19

Evolução & Escala

Etapas de modularização

EtapaStatusDescrição
Etapa 1 — ModularizaçãoConcluída5 módulos extraídos de app.js: AppBoundaryManager, FeatureFlagManager, PresetManager, StateManager, VectorizationPipeline
Etapa 1 fase 2PendenteStateManager fase 2 (callsites remanescentes); VectorizationPipeline fase 2 (extração do core por subetapas)
Etapa 2 — ContratosConcluída4 contratos em docs/contratos/: wasm-contract, storage-keys, api-schemas, app-boundary
Etapa 3 — ObservabilidadeConcluída186 call sites migrados para window.DIAG?.* com categorias estruturadas; telemetria direta sem DevTools; exportação consolidada no painel lateral desktop

O que precisa ser protegido

🦀

WASM soberano

O pipeline principal precisa continuar operável e auditável com o WASM como fonte de extração geométrica.

🖥️

Desktop relevante

Canal de distribuição ativo. Build desktop deve continuar levando WASM + frontend + APIs locais.

💾

Local-first

Persistência local prioritária. Sem dependências de autenticação ou sincronização remota no fluxo operacional.

📂

APP por instalação

Camada de referência topográfica permanece local por instalação no desktop.

Principais passivos arquiteturais

app.js ainda grande demais. Estado, UI, persistência e regras de negócio se cruzam no mesmo módulo. A direção é gradual: módulos de domínio mais explícitos, contratos por subsistema, menos dependência de globais window.*.
Capítulo 20

Build & Runbooks

Comandos principais

npm install           # instalar dependências
npm run dev           # servidor de desenvolvimento Vite
npm run lint          # ESLint
npm run build         # build produção
npm run preview       # preview do build
npm run desktop:dev   # Electron + Vite em desenvolvimento
npm run desktop:start # Electron sobre build existente
npm run dist:win      # empacotamento Windows (.exe)

Rebuild do WASM

Sempre que houver mudança em vetoriza/src/lib.rs:

cd vetoriza
wasm-pack build --target no-modules --release

Após o rebuild, validar novamente o build do frontend com npm run lint && npm run build.

Runbooks de diagnóstico rápido

🔨

Build falha

Verificar: erros de lint → warnings do bundler → artefatos WASM ausentes → type="module" no Vite → node_modules.

🦀

WASM não carrega

Verificar: presença de vetoriza/pkg/vetoriza.js e vetoriza_bg.wasm → ordem de script → disponibilidade de wasm_bindgen.vetorizar_imagem.

🌐

API local falha

Verificar: desktop/app-server.cjs → portas ocupadas → api/local.settings.json → endpoints de health.

🧾

SIGEF não carrega

Verificar: disponibilidade do WFS INCRA por UF → proxy /api/proxy/incra-wfs → metadados de consulta em sigefQueryMetadata.

Fluxo recomendado: desenvolvimento com npm run dev → validar com npm run lint && npm run build → testar desktop com npm run desktop:dev → empacotar com npm run dist:win.