Voltar

SFN — Portal Multi-Secretaria de Fiscalização Municipal

Nasceu como sistema único de fiscalização de obras e evoluiu para uma plataforma multi-secretaria: portal com SSO/LDAP compartilhado, registro de subsistemas e encaminhamento entre equipes. Um subsistema completo em produção (Obras — cadeia Solicitação → Notificação → Embargo → Multa) e outros em expansão (Meio Ambiente, Área Pública, Bem-Estar Animal), cada um com domínio de negócio próprio sobre a mesma base offline-first, PWA e impressão térmica Zebra.

React 19TypeScriptExpress 5PostgreSQL 17LDAP SSOPWAArquitetura Multi-SecretariaZebra ZQ220

Todos os dados exibidos nos screenshots (nomes, endereços, processos) são fictícios — ambiente de demonstração. As telas abaixo são do subsistema SFO (Obras), o mais maduro e em produção — os demais subsistemas ainda estão em levantamento/implementação.

Contexto

O SFN nasceu como um sistema único de fiscalização de obras para a Secretaria de Obras de uma prefeitura municipal, substituindo blocos de papel e planilhas por um pipeline auditável. Com a adesão de novas secretarias, o projeto foi reestruturado de aplicação única para portal multi-secretaria: login único (SSO) na raiz do domínio, cada secretaria com seu próprio subsistema, todos compartilhando a mesma infraestrutura offline-first, PWA e impressão térmica — mas com domínio de negócio e fluxo de trabalho próprios, porque cada secretaria fiscaliza de um jeito diferente.

A plataforma é PWA tablet-first: o fiscal cria o procedimento no local, anexa fotos da vistoria, imprime no Zebra portátil e entrega o documento físico ao autuado — tudo offline-capable, em qualquer subsistema.

Arquitetura do portal

Um domínio único da prefeitura roteia por path para stacks Docker independentes — cada subsistema com seu próprio client, server e (quando aplicável) banco, publicados sob o mesmo domínio via Nginx:

SubsistemaSecretariaPathStatus
SFNPortal (SSO)/Produção — LDAP/AD + JWT, sem banco próprio
SFOInfraestrutura e Obras/obras/Produção — subsistema completo (cadeia abaixo)
SFAMMeio Ambiente e Habitação/meio-ambiente/Em levantamento — 2 equipes (Regularização Fundiária, Meio Ambiente)
SFAPFiscalização de Área Pública/area-publica/Escopo definido — fluxo próprio (ver abaixo)
SFBEABem-Estar AnimalPlanejado — desmembrado do SFAM como subsistema próprio

O portal SFN concentra a autenticação LDAP/AD e emite um JWT (segredo HS256 compartilhado por todos os subsistemas) — o usuário loga uma vez e, se tiver acesso a mais de um subsistema, escolhe qual abrir. Um registro central (SUBSISTEMAS_JSON) mapeia cada subsistema a seu grupo de AD, URL base e credencial de API, e alimenta tanto o seletor de subsistemas quanto o encaminhamento entre eles (abaixo).

Cadeia de procedimentos — subsistema SFO (Obras)

Cada item é registro independente — dados são copiados no momento da criação, alterações posteriores não afetam os demais. A navegação bidirecional mostra origem e gerados.

Solicitação → Notificação → Embargo → Multa

Extensibilidade sem duplicar regra de negócio

Cada novo subsistema parte de uma cópia da stack do SFO, mas a estratégia é reaproveitar a infraestrutura (autenticação/SSO, sync offline-first, sistema de impressão, PWA) e deixar o domínio de negócio livre para divergir — porque cada secretaria fiscaliza de um jeito realmente diferente. O caso mais claro é o SFAP (Área Pública), que diverge do SFO em pontos estruturais:

O SFAM segue o caminho inverso: reaproveita o fluxo linear do SFO, mas com 2 equipes internas (Regularização Fundiária, Meio Ambiente) que devem, cada uma, receber legislação e workflow próprios conforme o levantamento avança.

Recursos principais

Offline-first

O fiscal opera em campo sem rede — criação de procedimentos, fotos, assinatura e impressão funcionam offline, com sincronização automática ao reconectar:

API de Integração Externa e encaminhamento entre subsistemas

API REST autenticada por chave permite que sistemas externos (georreferenciamento, ouvidoria, MP, app cidadão) criem solicitações sem login LDAP — e o mesmo contrato de API é reutilizado internamente para o encaminhamento entre subsistemas do portal.

Stack

CamadaTecnologia
FrontendReact 19, TypeScript 5.9, Vite 8, TailwindCSS 4.2
BackendExpress 5, TypeScript, Node.js 22
BancoPostgreSQL 17 (migrations SQL sequenciais)
AuthLDAP/AD + JWT compartilhado entre subsistemas (SSO)
InfraDocker Compose, Nginx — 1 stack independente por subsistema, roteadas por path no mesmo domínio
ImpressãoZebra ZQ220 Plus (ZPL / jsPDF fallback)

Desafios resolvidos

Galeria

Login — autenticação LDAP/AD com fallback offline (validação local por hash bcrypt após o primeiro acesso).
Dashboard — cards resumo (notificações, embargos, multas, solicitações) e gráficos por status, retorno AR e prazos.
Listagem de Notificações — busca por nome, nº, endereço ou assunto; chips de entrega, prazo e status com paginação.
Detalhe da notificação — cadeia de procedimentos (Solicitação → Multa) e card 'Tipo de Entrega' com status AR (Correios).
Impressão A4 — preview do template oficial com assinatura padronizada antes de imprimir.
Impressão térmica (Zebra ZQ220) — preview do recibo de 72mm com status 'Impressora pronta'.
Configurações · Geral — provedor de mapas, legislação vigente e gestão do cache local offline.
Configurações · Impressão — pareamento Bluetooth da Zebra, diagnóstico de conexão e guia de instalação.
Configurações · Infrações/Multas — categorias de irregularidade com fundamento legal, valor diário e prazo em U.F.M.
Configurações · Origens — cadastro das origens de solicitação/notificação (Ouvidoria, MP, georreferenciamento…) por tipo de uso.
Configurações · Serviços — catálogo de serviços sugeridos ao criar a notificação.
Configurações · Importação — import do cadastro imobiliário (CSV do provedor municipal) e download do cadastro completo para uso offline.
Mapa — localização do imóvel via provedor configurável (Google Maps / Leaflet).
Trilha de auditoria — log de atividade com exportação e impressão.
Administração — relatórios por período, bairro e categoria (produtividade, SLA, cadeia por imóvel) com export CSV/PDF.
Numeração oficial reservada em campo — blocos de números por tipo de procedimento para criação offline.