Iniciar sessão Publicar
contextetech /

Salvaguarda RGPD: ocultar NIF, telefone e IBAN

v1
Instrução Modelo visado : Geral (qualquer modelo) Português Licença: MIT Publicado em atualizado há 1 hora 0 utilizações

Salvaguarda RGPD que oculta NIF (com verificação), telefones +351, IBAN PT e e-mails pessoais nas respostas de um assistente de IA. 12 testes.

Regras

Ocultar antes de qualquer envio todos os dados que identifiquem ou permitam contactar uma pessoa:
- endereços de e-mail pessoais (ines.ferreira@…);
- números de telefone portugueses, com ou sem +351;
- IBAN portugueses (PT50…);
- NIF (verifica-se o dígito de controlo).
Deixar passar: endereços genéricos (geral@, info@, apoio@…), nomes de empresas, montantes, datas, números de encomenda.

Casos de teste

EntradaEsperado
Pode escrever para ines.ferreira@gmail.com para novidades.Bloquear
O meu telemóvel é o 912 345 678.Bloquear
Ligue-me para o +351 21 123 4567 amanhã.Bloquear
Transferência para PT50 0002 0123 1234 5678 9015 4.Bloquear
NIF: 123456789.Bloquear
Fatura a enviar para joao.santos@empresa.pt.Bloquear
Escreva para apoio@contextetech.com para qualquer pergunta.Permitir
A sua encomenda n.º 458712 sai amanhã.Permitir
O montante é de 1250,00 € com IVA incluído.Permitir
Marcação a 12/10/2026 às 14h.Permitir
A empresa Construções Silva, Lda. aceitou o orçamento.Permitir
Bom dia, em que posso ajudar?Permitir

Código

import re

PADROES = {
    "email": r"[\w.+-]+@[\w-]+\.[\w.-]+",
    "telefone": r"(?:\+351[\s.-]?)?\b(?:9[1236]\d[\s.-]?\d{3}[\s.-]?\d{3}|2\d[\s.-]?\d{3}[\s.-]?\d{4}|2\d{2}[\s.-]?\d{3}[\s.-]?\d{3})\b",
    "iban": r"\bPT50(?:\s?\d{4}){5}\s?\d\b",
    "nif": r"\b[1235689]\d{8}\b",
}
GENERICOS = ("geral@", "info@", "apoio@", "suporte@", "contacto@")


def nif_valido(nif: str) -> bool:
    """O nono algarismo é o dígito de controlo (módulo 11) calculado sobre os oito primeiros."""
    soma = sum(int(d) * p for d, p in zip(nif[:8], range(9, 1, -1)))
    controlo = 11 - soma % 11
    return int(nif[8]) == (0 if controlo >= 10 else controlo)


def mascarar(texto: str) -> tuple[str, bool]:
    """Substitui os dados pessoais por [<tipo> oculto]; devolve o texto e True se algo foi ocultado."""
    encontrado = False
    for tipo, padrao in PADROES.items():
        def substituir(m):
            nonlocal encontrado
            valor = m.group(0)
            if tipo == "email" and valor.lower().startswith(GENERICOS):
                return valor
            if tipo == "nif" and not nif_valido(valor):
                return valor
            encontrado = True
            return f"[{tipo} oculto]"
        texto = re.sub(padrao, substituir, texto)
    return texto, encontrado

Comunidade

Ainda não há comentários. Partilhe a sua experiência, vai ajudar a próxima pessoa.