← Portfólio / Engenharia
Julho 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.

📅Julho 2026
🌿win-desktop-main
🦀Rust + WASM
Electron v43 + Vite 8
📦33 módulos catalogados
Capítulo 01

Visão Geral da Arquitetura

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

6Subsistemas
33Módulos catalogados
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.

4A

Cobertura integral da ROI

Após a geração base (inalterada), uma etapa complementar fecha lacunas residuais em qualquer preset, com processamento assíncrono em fatias para manter a UI fluida mesmo em ROIs grandes.

5

Exportação / Persistência local

GeoJSON, Shapefile, memorial DOCX, planilha XLSX 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.
Contrato de cobertura da ROI: a saída final deve cobrir 100% da ROI em qualquer preset, preservando a lógica atual da geração base de polígonos e aplicando apenas preenchimento complementar de lacunas com execução cooperativa para evitar travamento da interface.
Capítulo 02

Subsistemas

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

🗺️

Shell principal de interface

Features carregadas por consulta WFS ao Acervo Fundiário INCRA ou por importação local SHP/CSV.

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/* — PDFtoArcGIS determinístico, parsing local e conversão SHP.

🧾

Confrontação SIGEF & Memorial

sigef-wfs.js, sigef-memorial.js, app.js — consulta WFS, importação SIGEF por SHP/CSV, seleção/desambiguação de referência, confronto de vértices com prioridade por QRCODE em ambiguidades, geração de DOCX/XLSX 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 e por importação local SHP/CSV.

Helpers do pipeline novos

Função Papel
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

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 v43)

🚀

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

Endpoint Destino real Motivo do proxy
/api/proxy/nominatim-reverse nominatim.openstreetmap.org CORS/CSP no renderer
/api/proxy/nominatim-search nominatim.openstreetmap.org CORS/CSP no renderer
/api/proxy/incra-wfs WFS SIGEF INCRA por UF CORS/CSP no renderer
/api/proxy/elevation api.opentopodata.org (SRTM 30m) CORS/CSP no renderer
/api/pdf-to-geojson — (local) Parser/normalização local (OCR executado no frontend)
/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 com prioridade por QRCODE em ambiguidades, cota Z via SRTM, geração de DOCX/XLSX 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 e orçamento para evitar etapas topológicas caras em lote.

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 executa rota classMap como caminho principal: K-means + calibração por paleta RGB + ajuste por vizinhança de cor + tesselação direta. Fallback por máscara/WASM é apenas de contingência e a topologia pesada só roda dentro do orçamento de tempo/features.
Capítulo 10

Confrontação SIGEF & Memorial Descritivo

01

Camada SIGEF ativa (WFS ou arquivo local)

O confronto opera com camada SIGEF ativa por consulta WFS (ROI + UF detectada automaticamente, via proxy local /api/proxy/incra-wfs) ou por importação local SHP/CSV.

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/nome SIGEF). Com múltiplas camadas SIGEF ativas, ambiguidades de ponto priorizam candidatos com QRCODE e depois menor distância. Haversine > 5 m → vértice novo (sequência derivada do número-base digitado no prefixo).

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 e planilha XLSX com azimute, distância (haversine), área geodésica (ha) e cota Z por vértice. O XLSX exporta coordenadas em DMS e inclui GEOMETRIA_WKT. 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; prioridade por QRCODE na resolução de nomes SIGEF em cenários com múltiplas camadas CSV; fallback de prefixo apenas para vértices sem correspondência SIGEF.
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.

Campo Tipo Papel
edgeThreshold number Limiar de borda Sobel/Otsu
morphologySize number Kernel de morfologia (closing)
minArea number Área mínima candidata (pixels)
simplification number Tolerância Douglas-Peucker
contrastBoost number Fator de amplificação de contraste
minQualityScore number Score mínimo para aceite
mergeDistance number Distância de fusão
clusteringEnabled boolean Habilita agrupamento DBSCAN
clusterEps number Raio DBSCAN
clusterMinPts number Densidade mínima DBSCAN
presetProfile string Perfil ativo

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

Campo Tipo Papel
modoVetorizacao 'auto'|'manual' Modo operacional ativo
geojsonFeatures array Features de vetorização automática
manualPolygonFeatures array Features de desenho manual
activeRunId string/null ID da execução corrente
currentSelectionMaskFeature Feature/null Má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

Chave Módulo Propósito
vetorizador_app_boundary_v2 app-boundary-manager Cache da camada de referência (APP)
vetorizador_app_boundary_v1 app-boundary-manager Chave legada — lida apenas para migração automática para _v2
vetorizador_feature_flags_v1 feature-flag-manager Feature flags persistidas
vetorizador_backend_refine_audit_v1 feature-flag-manager Auditoria operacional de flags
vetorizador_assist_telemetry_v1 app.js Telemetria leve de uso
vetorizador_multiselect_hint_v1 app.js Flag 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âmetro Tipo Descrição
base64_png string PNG 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 (281 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: Julho 2026 · win-desktop-main

30RF mapeados
30Implementados
0Parciais
0Pendentes
ID Nome Status Módulo
RF-01 Busca cartográfica Implementado app.js → Nominatim
RF-02 Captura de coordenada Implementado app.js, index.html
RF-03 Delimitação da área de interesse Implementado app.js, Leaflet.Draw
RF-04 Alternância de modo operacional Implementado app.js, state-manager.js
RF-05 Desenho manual de feição topográfica Implementado app.js, Leaflet.Draw
RF-06 Seleção de preset profissional Implementado preset-manager.js
RF-07 Ajuste avançado de parâmetros Implementado app.js, index.html
RF-08 Captura da ROI Implementado app.js, vectorization-pipeline.js
RF-09 Pré-processamento da imagem Implementado vectorization-pipeline.js
RF-10 Agrupamento DBSCAN Implementado app.js
RF-11 Vetorização determinística Implementado vetoriza/src/lib.rs
RF-12 Pós-processamento geométrico Implementado geo-postprocess.js
RF-13 Operação WASM-only Implementado feature-flag-manager.js, app.js, vetoriza/src/lib.rs
RF-14 Exibição de resultados Implementado app.js, index.html
RF-15 Edição e rejeição operacional Implementado app.js
RF-16 Exportação GeoJSON Implementado app.js
RF-17 Exportação Shapefile Implementado app.js, shpwrite
RF-18 Relatório de interseção com camada de referência Implementado app.js
RF-19 Carregamento e limpeza de camada de referência Implementado app-boundary-manager.js
RF-20 Persistência local runs Implementado IndexedDB vetorizador_learning_db
RF-21 Persistência local de feedback operacional Implementado app.js → IndexedDB
RF-22 Serviço de persistência local da camada de referência Implementado app-boundary-manager.js
RF-23 Operação sem autenticação remota Implementado app.js, app-boundary-manager.js
RF-24 Restauração da camada de referência no bootstrap Implementado app-boundary-manager.js
RF-25 Resiliência offline Implementado IndexedDB + localStorage
RF-26 Módulo PDF Implementado pdfspliter/ via iframe
RF-27 Conversão documental geoespacial Implementado api/pdf-to-geojson, api/shp-to-geojson
RF-28 Runtime desktop Implementado desktop/main.cjs
RF-29 Saúde operacional local Implementado desktop/app-server.cjs
RF-30 Telemetria e auditoria Implementado diagnostic-logger.js, feature-flag-manager.js
Capítulo 18

Requisitos Não Funcionais

14RNF mapeados
12Implementados
2Parciais
ID Nome Status Observação
RNF-01 Consistência geométrica Implementado Polígonos fechados garantidos pelo WASM
RNF-02 Determinismo do núcleo Implementado WASM como única fonte de extração
RNF-03 Desempenho operacional Parcial Meta < 60s/imagem documentada; sem benchmark automatizado formal
RNF-04 Qualidade mínima Parcial F1 ≥ 0,70 e IoU ≥ 0,60 definidos; sem regressão automatizada
RNF-05 Continuidade offline Implementado Fluxos locais independentes de conectividade
RNF-06 Usabilidade por perfis distintos Implementado Modo simples (presets) e avançado (sliders) na mesma UX
RNF-07 Observabilidade Implementado 281 call sites migrados para window.DIAG?.*; categorias APP, GEO, SCENE, PRESET, BOUNDARY; fallback para libs externas
RNF-08 Portabilidade Implementado Runtime Electron para Windows (desktop)
RNF-09 Robustez a falhas de dependência Implementado Fallback e mensagens de erro para WASM e libs de exportação
RNF-10 Manutenibilidade Implementado 5 módulos extraídos; desacoplamento fino fase 2 pendente
RNF-11 Segurança operacional Implementado Dados sensíveis permanecem locais no desktop
RNF-12 Compatibilidade de integração Implementado GeoJSON e Shapefile compatíveis com ecossistemas GIS
RNF-13 Escalabilidade funcional moderada Implementado Presets e endpoints com expansão incremental por contrato
RNF-14 Auditabilidade Implementado Logs de decisão, auditoria de flags, telemetria local
Capítulo 19

Evolução & Escala

Etapas de modularização

Etapa Status Descrição
Etapa 1 — Modularização Concluída 5 módulos extraídos de app.js: AppBoundaryManager, FeatureFlagManager, PresetManager, StateManager, VectorizationPipeline
Etapa 1 fase 2 Pendente StateManager fase 2 (callsites remanescentes); VectorizationPipeline fase 2 (extração do core por subetapas)
Etapa 2 — Contratos Concluída 4 contratos em docs/contratos/: wasm-contract, storage-keys, api-schemas, app-boundary
Etapa 3 — Observabilidade Concluída 281 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

Evolução arquitetural contínua. O produto segue em modularização progressiva para manter previsibilidade operacional, contratos claros por subsistema e menor acoplamento entre camadas.
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 ou npm run dist:win:store.