tecnopopular-audit / models.py
TecnoPopular's picture
Publicação do Protocolo de Auditoria Cívica TecnoPopular (CTP-1.0)
4bcb8ad verified
Raw History Blame Contribute Delete
7.85 kB
"""
Modelos Pydantic (TypeSafe AI) para o Protocolo de Auditoria Civica TecnoPopular (CTP-1.0).
Define a taxonomia de governanca em dois niveis, as 5 dimensoes tecnicas e o guia acionavel.
"""
from datetime import datetime, timezone
from enum import Enum
from typing import Dict, List, Optional
from pydantic import BaseModel, Field
class AuditLevel(str, Enum):
"""Niveis de governanca e reconhecimento do ecossistema TecnoPopular."""
CATALOGADO = "catalogado" # Nivel 1: Diretorio Aberto (Elegibilidade basica de utilidade publica)
AUDITADO = "auditado" # Nivel 2: Certificacao TecnoPopular (Aprovado no Protocolo CTP)
EM_REVISAO = "em_revisao" # Pendencia documental ou tecnica identificada
REJEITADO = "rejeitado" # Descumprimento grave de privacidade, phishing ou finalidade espuria
class DimensionType(str, Enum):
"""As 5 dimensoes avaliadas na regua de certificacao civica."""
PROVENIENCIA_DADOS = "proveniencia_dados" # Peso 25%: TSE, IBGE, CGU, LAI
PRIVACIDADE_SOBERANIA = "privacidade_e_soberania" # Peso 25%: Zero trackers comerciais, zero dados pessoais
CODIGO_ABERTO_FLOSS = "codigo_aberto_floss" # Peso 20%: Repositorio publico e licenca livre
ENQUADRAMENTO_REPUBLICANO = "enquadramento_republicano" # Peso 15%: George Lakoff, despolarizacao e Marco Civil
ACESSIBILIDADE_DESEMPENHO = "acessibilidade_desempenho" # Peso 15%: Baixa largura de banda, WCAG AAA, zero dark patterns
class ActionableGuidance(BaseModel):
"""Instrucao didatica e imediata para o mantenedor/voluntario elevar a nota da aplicacao."""
dimension: DimensionType
what_is_evaluated: str = Field(..., description="O que o algoritmo avalia no codigo ou na pagina")
why_it_matters: str = Field(..., description="Por que essa exigencia protege o cidadao ou a democracia")
how_to_fix: str = Field(..., description="Passo a passo pratico de 5 minutos para resolver no codigo")
class DimensionScore(BaseModel):
"""Pontuacao detalhada de uma dimensao especifica da auditoria."""
dimension: DimensionType
weight_percentage: float = Field(..., description="Peso percentual da dimensao no score final (ex: 25.0)")
raw_score: float = Field(..., ge=0.0, le=100.0, description="Nota bruta obtida na dimensao (0 a 100)")
weighted_score: float = Field(..., description="Nota ponderada calculada: raw_score * (weight / 100)")
is_passing: bool = Field(..., description="Indica se atingiu a nota de corte minima na dimensao")
findings: List[str] = Field(default_factory=list, description="Evidencias empiricas constatadas na inspecao")
recommendations: List[str] = Field(default_factory=list, description="Orientacoes tecnicas para aprimoramento")
guidance: Optional[ActionableGuidance] = None
class ProvenanceDetail(BaseModel):
"""Detalhamento tecnico da proveniencia documental de dados (Aos Fatos / LAI)."""
declared_sources: List[str] = Field(default_factory=list, description="Fontes declaradas (ex: TSE, IBGE, CGU)")
official_links_detected: List[str] = Field(default_factory=list, description="Hiperlinks para dominios *.gov.br / *.jus.br")
has_speculative_claims: bool = False
reproducibility_documented: bool = True
class PrivacyDetail(BaseModel):
"""Detalhamento tecnico da postura de privacidade e soberania (LGPD)."""
detected_commercial_trackers: List[str] = Field(default_factory=list, description="GA4, Meta Pixel, Hotjar, Clarity, etc.")
collects_sensitive_pII: bool = False # Ex: formularios com CPF, e-mail obrigatorio, telefone
enforces_login: bool = False # Exige conta para consulta de dados publicos
has_privacy_policy: bool = False
is_local_first_or_ephemeral: bool = True
class FlossDetail(BaseModel):
"""Detalhamento tecnico de codigo aberto e auditabilidade."""
public_repository_url: Optional[str] = None
spdx_license_detected: Optional[str] = None # MIT, GPL-3.0, Apache-2.0, etc.
is_osi_approved: bool = False
has_recent_commits: bool = True
class FramingDetail(BaseModel):
"""Detalhamento semantico do enquadramento e conformidade republicana (Lakoff)."""
affirmative_public_value: bool = True # Foco em direitos, servicos publicos e custos materiais
polarizing_risk_keywords: List[str] = Field(default_factory=list)
respects_civil_framework: bool = True # Conformidade com Art. 19 do Marco Civil (sem calunia/difamacao)
mitigates_backfire_effect: bool = True # Foco propositivo vs reativacao reativa de fakes
class PerformanceDetail(BaseModel):
"""Detalhamento de acessibilidade e desempenho em conexoes perifericas."""
response_time_ms: int = 0
html_payload_bytes: int = 0
is_low_bandwidth_friendly: bool = True # < 500KB de carga total inicial
has_commercial_paywall: bool = False
has_ad_banners: bool = False
class CivicAuditReport(BaseModel):
"""Relatorio final emitido pelo Protocolo de Auditoria Civica TecnoPopular para uma iniciativa civica."""
tool_id: str = Field(..., description="Identificador unico (slug da ferramenta)")
tool_name: str
target_url: str
evaluated_at: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
evaluator_version: str = "Protocolo TecnoPopular CTP-1.0"
status: AuditLevel
total_score: float = Field(..., ge=0.0, le=100.0, description="Nota consolidada de 0 a 100")
# Bloqueadores criticos (ex: presenca de Meta Pixel ou formulario abusivo de CPF anula a certificacao)
has_critical_blocker: bool = False
critical_blockers: List[str] = Field(default_factory=list)
# Detalhamento por dimensao
dimension_scores: Dict[DimensionType, DimensionScore] = Field(default_factory=dict)
# Sub-analises especializadas
provenance: ProvenanceDetail = Field(default_factory=ProvenanceDetail)
privacy: PrivacyDetail = Field(default_factory=PrivacyDetail)
floss: FlossDetail = Field(default_factory=FlossDetail)
framing: FramingDetail = Field(default_factory=FramingDetail)
performance: PerformanceDetail = Field(default_factory=PerformanceDetail)
badge_label: str = Field(..., description="Rotulo legivel (ex: 'Certificado TecnoPopular' ou 'Catalogado no Diretorio')")
summary_markdown: str = Field(..., description="Sintese tecnica auditavel para publicacao publica")
class ToolMetadata(BaseModel):
"""Metadados canonicos de uma ferramenta para o catalogo."""
id: str
nome: str
categoria: str
descricao: str
url: str
repo_url: Optional[str] = None
licenca: Optional[str] = None
fontes_primarias: List[str] = Field(default_factory=list)
status_auditoria: AuditLevel = AuditLevel.CATALOGADO
score_auditoria: Optional[float] = None
certificado_tecnopopular: bool = False
class AuditRubric(BaseModel):
"""Configuracao dos pesos e notas de corte da governanca TecnoPopular."""
weights: Dict[DimensionType, float] = {
DimensionType.PROVENIENCIA_DADOS: 25.0,
DimensionType.PRIVACIDADE_SOBERANIA: 25.0,
DimensionType.CODIGO_ABERTO_FLOSS: 20.0,
DimensionType.ENQUADRAMENTO_REPUBLICANO: 15.0,
DimensionType.ACESSIBILIDADE_DESEMPENHO: 15.0,
}
# Notas de corte minimas por dimensao
min_dimension_score: Dict[DimensionType, float] = {
DimensionType.PROVENIENCIA_DADOS: 60.0,
DimensionType.PRIVACIDADE_SOBERANIA: 80.0, # Rigor maximo em privacidade
DimensionType.CODIGO_ABERTO_FLOSS: 50.0,
DimensionType.ENQUADRAMENTO_REPUBLICANO: 60.0,
DimensionType.ACESSIBILIDADE_DESEMPENHO: 50.0,
}
seal_threshold: float = 80.0 # Nota minima para receber a Certificacao TecnoPopular
directory_threshold: float = 50.0 # Nota minima para manter-se elegivel no catalogo aberto