Este documento foi desenhado para impressão. Ao exportar, o navegador abre o fluxo Guardar como PDF.
Arquitetura técnica, fronteiras de confiança e mapeamento de controlos para uma plataforma de finanças pessoais com cifragem no servidor.
Dossier técnico público
Version
2026.03
Atualizado
7 de março de 2026
Declaração de escopo
Este documento descreve os controlos de segurança visíveis na implementação atual do produto e clarifica tanto as proteções como as premissas de confiança da plataforma.
Ações
Formato: PDF via impressão do navegador
Idioma selecionado: Português
Usó recomendado: due diligence técnica, análise de risco e validação de arquitetura.
Sumário
Principais conclusões
Lista de abreviaturas
AES-GCM
Modo de cifragem simétrica autenticada usado para campos protegidos do utilizador.
API
Application Programming Interface.
CSP
Content Security Policy.
HSTS
HTTP Strict Transport Security.
MFA
Autenticação multifator.
RLS
Row-Level Security.
TLS
Transport Layer Security.
UUID
Identificador único universal.
Lista de tabelas
Tabela 1. Domínios com cifragem na camada da aplicação
Tabela 1 incluída no corpo principal do documento.
Tabela 2. Controlos de pedido e de plataforma
Tabela 2 incluída no corpo principal do documento.
Tabela 3. Resumo da fronteira do modelo de ameaças
Tabela 3 incluída no corpo principal do documento.
Tabela 4. Comparação pública com fintechs selecionadas
Tabela 4 incluída no corpo principal do documento.
A Mova está implementada como uma aplicação Next.js onde o acesso privilegiado aos dados fica concentrado em rotas de API no servidor. O navegador pode autenticar-se com uma sessão do utilizador, mas não deve receber credenciais de serviço da base de dados nem executar operações privilegiadas do Supabase diretamente.
O modelo de segurança combina várias camadas: validação de bearer token, proteção de mesma origem em pedidos mutativos, limitação de pedidos, comportamento estrito de cache, row-level security na base de dados e cifragem na camada da aplicação para campos financeiros do utilizador.
Um pedido protegido normal flui do browser para a API da aplicação, passa pelos controlos de segurança do pedido e só depois atinge o acesso ao Supabase no servidor. A fronteira de confiança é, portanto, o runtime do servidor e não o bundle do cliente. As rotas públicas ficam limitadas a um pequeno conjunto de endpoints de mercado ou health.
Como a service role key permanece apenas no servidor, um bundle frontend copiado ou um URL da base de dados não fornecem o material necessário para leituras privilegiadas. Isto reduz de forma material o blast radius de fugas típicas do lado do cliente.
Nas tabelas financeiras protegidas, os campos seguros são serializados para encrypted_data antes da persistência. O runtime deriva uma chave AES-GCM por utilizador a partir do segredo de serviço, do identificador do utilizador e de um salt único do perfil. A descifragem acontece apenas dentro de pedidos autorizados no servidor.
Este desenho significa que um dump direto das tabelas ainda expõe metadados estruturais como identificadores de linha e timestamps, mas os campos de negócio protegidos permanecem opacos sem o segredo do servidor e sem o caminho de derivação da chave.
O dispatcher da API interna rejeita segmentos inválidos, bloqueia prefixes reservados, aplica verificação de mesma origem em métodos mutativos, impõe um limite de um megabyte para o corpo genérico da API e responde com cabeçalhos no-store para o tráfego de API.
O rate limiting é atualmente implementado em memória do processo, com janela de 60 segundos e chaves por rota derivadas do IP do cliente, do estado de autenticação e do prefixo da rota. É eficaz para uma única instância de runtime e deve ser entendido como controlo prático da aplicação, não como controlo distribuído de edge.
Os uploads de faturas são tratados por rotas dedicadas no servidor em vez de escritas diretas do cliente para o bucket. A rota valida mesma origem, exige utilizador autenticado, restringe MIME types a uma pequena allowlist e limita o upload a dez megabytes.
Os ficheiros ficam guardados em caminhos por utilizador e são depois expostos por URLs assinadas. Isto reduz o risco de enumeração de bucket e evita expor caminhos de objetos como recursos publicamente recuperáveis.
As rotas administrativas são protegidas por autenticação e por verificação de papel admin. Alterações de acesso do utilizador, ações sobre feedback e outros eventos privilegiados são inseridos em admin_audit_logs, garantindo trilha de revisão para operações sensíveis.
A plataforma também inclui fluxos de reencriptação para dados do utilizador. Isto tem valor operacional em migrações, reparação de dados ou manutenção criptográfica porque oferece um procedimento definido em vez de manipulação direta e pontual da base de dados.
Um atacante com acesso apenas ao browser, um bundle do cliente vazado ou um operador da base de dados sem os segredos do servidor não devem conseguir ler em plaintext os campos financeiros protegidos. Esse é o valor prático do desenho com segredo apenas no servidor e blobs cifrados por utilizador.
Um operador privilegiado de produção com acesso ao runtime e ao segredo de serviço continua dentro da fronteira de confiança e pode executar a lógica autorizada de descifragem. Por isso, o desenho não afirma zero-knowledge. Uma revisão de segurança deve tratar isto como modelo de servidor confidencial endurecido e não como criptografia end-to-end com chave do cliente.
As tabelas de comparação deste dossier não afirmam paridade de escopo com plataformas bancárias reguladas. Elas servem para mostrar que a Mova segue famílias de controlo reconhecíveis e descritas publicamente por fintechs estabelecidas: transporte cifrado, sessões protegidas, acesso interno restrito e práticas explícitas de monitorização ou fraude.
As colunas dos fornecedores abaixo baseiam-se em documentação oficial pública disponível em 7 de março de 2026. São ilustrativas e não substituem uma auditoria independente aos fornecedores citados.
Se o produto exigir uma postura de privacidade ainda mais forte contra operadores privilegiados do servidor, o passo seguinte de arquitetura será a adoção de chaves mantidas pelo cliente ou de um desenho zero-knowledge. Isso altera de forma relevante pesquisa, recuperação e workflows administrativos e deve ser tratado como tradeoff de produto, não como um pequeno ajuste.
Se o produto exigir maior resistência a abuso em escala, devem ser adicionados rate limiting distribuído, controlos de anomalia suportados por WAF, workflows dedicados de rotação de segredos e testes externos formais de penetração sobre a base atual.
| Domínio | Famílias de campos protegidos | Motivo da proteção |
|---|---|---|
| Cartões | Nome, tipo, banco, últimos quatro, saldos, taxa de manutenção, periodicidade, cor, moeda | Evita exposição em plaintext de metadados do instrumento de pagamento e dos saldos guardados. |
| Transações | Tipo, montante, descrição, data, moeda, allocations, recorrência e metadados de fatura | Protege detalhes do razão, categorizações e referências de faturas carregadas. |
| Rendimentos e despesas | Nomes, tipos, montantes, frequência, categoria, alertas e moeda | Protege fontes recorrentes de cashflow e lembretes operacionais. |
| Ativos e investimentos | Nomes, tipos, valores, datas de compra, instituição, notas, métricas de retorno e moeda | Protege composição da carteira e histórico de valorizacao. |
| Passivos e metas | Nomes, saldos remanescentes, pagamentos, notas, montantes alvo, datas, prioridades e moeda | Protege estrutura de dívida e objetivos de planeamento financeiro. |
| Registos fiscais | Ano, rendimento bruto, deduções, imposto pago, taxa e notas | Protege inputs sensíveis de conformidade e reporte. |
A base de dados continua a guardar identificadores de linha e alguns metadados operacionais em plaintext; os campos sensíveis acima são persistidos dentro de encrypted_data.
| Controlo | Implementação atual | Objetivo de segurança |
|---|---|---|
| Validação de bearer token | As rotas protegidas exigem bearer token válido do Supabase antes do dispatch. | Rejeitar acesso anónimo a recursos do utilizador ou do admin. |
| Verificação de mesma origem | POST, PATCH, PUT e DELETE são validados contra a origin do host. | Reduzir abuso cross-site para sessões autenticadas no browser. |
| Validação de caminho | Segmentos inseguros e prefixes reservados são rejeitados antes do routing interno. | Reduzir path traversal e exposição acidental de rotas. |
| Limites de corpo | A API genérica é limitada a 1 MB; uploads de fatura ficam limitados a 10 MB. | Conter pressão de memória e abuso por pedidos demasiado grandes. |
| Rate limiting | 180 pedidos por 60 segundos por chave de rota, combinando IP e estado de autenticação. | Travar abuso e reduzir flooding trivial. |
| Cabeçalhos de segurança | CSP, HSTS em produção, frame denial, nosniff, referrer policy estrita e permissions policy limitada. | Endurecer execução no browser e política de transporte. |
| Cache das respostas | As respostas da API são servidas com semântica no-store. | Reduzir persistência de respostas sensíveis em caches partilhadas ou stale. |
| Cenário | Acesso esperado a plaintext | Resistência esperada |
|---|---|---|
| Bundle do browser ou frontend vazado | Sem segredo de serviço e sem leituras privilegiadas diretas. | Resistência forte, assumindo que os segredos do servidor permanecem protegidos. |
| Dump bruto da base de dados sem o segredo do servidor | Os blobs cifrados permanecem ilegíveis nos campos financeiros protegidos. | Resistência forte nos campos cobertos, com metadados estruturais ainda visíveis. |
| Browser comprometido de um utilizador autenticado | O utilizador só consegue aceder aos seus próprios registos descifrados através da aplicação. | Contido por bearer auth e por escopo do utilizador, embora abuso da sessão continue possível. |
| Suporte rotineiro ou dashboard sem privilégios de runtime | Não existe plaintext direto dos blobs cifrados financeiros. | Exposição significativamente reduzida face a sistemas com dados em plaintext at rest. |
| Operador de produção privilegiado com acesso ao segredo e runtime | Pode derivar chaves por utilizador e executar fluxos de descifragem no servidor. | Dentro da fronteira de confiança; risco residual que não é afirmado como impossível. |
| Família de controlo | Mova | Wise | Revolut | Monzo |
|---|---|---|---|---|
| Segredos privilegiados apenas no servidor | Sim. A service role key fica apenas no servidor por desenho. | A documentação pública descreve acesso interno restrito e storage cifrado, mas não explica o modelo de segredo em termos de produto. | A documentação pública descreve tratamento seguro no servidor e acesso restrito. | A documentação pública foca proteções da app e do dispositivo; não descreve o modelo de segredo do servidor em termos de produto. |
| Transporte cifrado e storage protegido | Sim. Transporte via TLS, campos financeiros cifrados na aplicação e RLS na base de dados. | Afirma publicamente cifragem em trânsito e em repouso. | Afirma publicamente que a informação é cifrada e armazenada em servidores seguros. | Afirma publicamente controlos de segurança para acesso à app; o detalhe público sobre cifragem em repouso é mais limitado. |
| Sessões e autenticação do utilizador | Validação de bearer token nas rotas protegidas e verificação admin nas rotas privilegiadas. | Documenta publicamente login em dois passos e controlos de verificação. | Documenta publicamente passcodes, biometria e verificações de segurança. | Documenta publicamente app lock com impressão digital ou Face ID e congelamento instantâneo de cartão. |
| Monitorização, fraude ou operação de segurança | Rate limiting por rota, logs de auditoria e fluxos explícitos de reencriptação/operação. | Documenta publicamente monitorização de segurança, resposta a incidentes e bug bounty. | Documenta publicamente monitorização antifraude e funcionalidades de resposta de segurança 24/7. | Documenta publicamente card freeze e controlos em tempo real na app; o detalhe público sobre monitorização e mais estreito. |
| Alegação de zero-knowledge | Não. Não é afirmado. | Sem alegação pública de zero-knowledge. | Sem alegação pública de zero-knowledge. | Sem alegação pública de zero-knowledge. |
As colunas dos fornecedores baseiam-se em documentação pública de segurança ou privacidade e não em revisões privadas de arquitetura. A comparação é ilustrativa e não exaustiva.
Wise Privacy and Security
Declarações públicas sobre cifragem em trânsito e em repouso, SOC 2 Type 2, PCI DSS, acesso restrito de colaboradores e monitorização de segurança.
https://wise.com/gb/privacy-policyWise Bug Bounty Program
Divulgação pública de reporte coordenado de vulnerabilidades e incentivos de bounty.
https://wise.com/gb/blog/introducing-our-bug-bounty-programmeRevolut Safety and Security
Declarações públicas sobre informação cifrada, servidores seguros, biometria, controlos antifraude e workflows de segurança.
https://www.revolut.com/en-US/how-we-keep-your-money-safe/Monzo Biometrics and App Lock
Declarações públicas sobre biometria do dispositivo e comportamento de bloqueio da app.
https://monzo.com/help/security/biometrics/Monzo Keeping Your Money Safe
Declarações públicas sobre congelamento de cartão e workflows protetivos da conta.
https://monzo.com/help/us-account-and-profile/us-keeping-your-money-safe/Implementação interna da Mova
Caminhos atuais de código e configuração de schema: verificações do gateway da API, cifragem na camada da aplicação, logs de auditoria administrativa e controlos de acesso ao storage na data acima.
https://mova.ao/privacy-policyAviso
Este dossier é técnico mas público. Descreve controlos implementados e premissas de confiança. Não é uma certificação externa formal, um relatório de pentest nem uma garantia absoluta contra todas as classes de comprometimento privilegiado.