Skip to content

Repository files navigation

Algorithm Analyzer — MVP

Analisador de complexidade de algoritmos com recomendação técnica contextualizada por tipo de dado e padrão de distribuição.


Arquitetura

algorithm_analyzer/
│
├── .github/
│   └── workflows/
│       └── ci.yml                   ← CI: lint → SAST → supply chain → testes
│
├── core/                            ← Lógica pura — sem I/O, sem efeitos colaterais
│   ├── parser/
│   │   └── expression_parser.py     ← Compilação segura de expressões via AST
│   ├── analyzer/
│   │   └── complexity_analyzer.py   ← Faixas de dominância + bisseção numérica
│   └── classifier/
│       └── asymptotic_classifier.py ← Classificação assintótica real (O(n), O(n²)…)
│
├── domain/                          ← Regras de negócio
│   ├── types/
│   │   └── models.py                ← Dataclasses, enums, tipos funcionais
│   ├── cost_model/
│   │   └── cost_adjuster.py         ← Fatores de custo por tipo/padrão de dado
│   └── justifier/
│       └── recommendation.py        ← Gerador de recomendação com justificativa técnica
│
├── interface/
│   ├── api/
│   │   ├── fastapi_app.py           ← Application factory (CORS, security headers)
│   │   ├── routes.py                ← Endpoints REST + view HTML
│   │   ├── schemas.py               ← Schemas Pydantic (validação entrada/saída)
│   │   └── charts.py                ← Geração dos gráficos Plotly (servidor)
│   ├── cli/
│   │   └── cli_runner.py            ← Interface de linha de comando
│   └── web/
│       ├── templates/
│       │   └── index.html           ← Template HTML
│       └── static/
│           ├── css/
│           │   └── style.css        ← Estilos (terminal industrial, âmbar)
│           ├── js/
│           │   └── app.js           ← JS puro — zero dependências de runtime
│           └── vendor/
│               └── plotly-basic.min.js   ← Baixar manualmente (ver abaixo)
│
├── tests/
│   ├── unit/
│   │   └── test_core.py             ← 12 testes unitários (core + domain)
│   └── integration/
│       └── test_pipeline.py         ← 11 testes de integração (FastAPI)
│
├── main.py                          ← Entry point (uvicorn)
├── requirements.txt                 ← Dependências de produção (versões fixadas)
├── requirements-dev.txt             ← Ferramentas de dev/CI
├── .bandit                          ← Configuração SAST
├── .flake8                          ← Configuração linter
└── .gitignore

Princípios de arquitetura aplicados

Princípio Onde
SRP (Single Responsibility) Cada arquivo tem exatamente uma responsabilidade
Dependency Rule (Clean Architecture) core não importa domain; domain não importa interface
Imutabilidade dataclass(frozen=True) — sem estado mutável oculto
Fail fast Parser rejeita expressões inválidas imediatamente
Separation of concerns Lógica pura em core/, regras em domain/, I/O em interface/
Application Factory criar_app() em fastapi_app.py — testável e configurável

Setup do Vendor (Plotly)

O arquivo plotly-basic.min.js não está incluso no repositório. Deve ser baixado uma vez e colocado em interface/web/static/vendor/.

Passo 1 — Baixar

# PowerShell
Invoke-WebRequest `
  -Uri "https://github.com/plotly/plotly.js v3.5.0 CDN" `
  -OutFile "interface/web/static/vendor/plotly-basic.min.js"
# Linux / macOS
curl -L -o interface/web/static/vendor/plotly-basic.min.js \
  "https://github.com/plotly/plotly.js v3.5.0 CDN"

Passo 2 — Verificar integridade (SHA-256)

# PowerShell
Get-FileHash interface/web/static/vendor/plotly-basic.min.js -Algorithm SHA256
# Linux / macOS
sha256sum interface/web/static/vendor/plotly-basic.min.js

Hash esperado para v3.5.0:

5BD80F6D8FDD7BC055F8E48099403355FC7223A47F95B1D9193DA24C0BAB6B55

Se o hash calculado não bater com este valor, não use o arquivo. Pode indicar arquivo corrompido ou comprometido no CDN. Nesse caso, siga o Passo 2.1 abaixo para obter o arquivo da fonte oficial.


Passo 2.1 — Hash divergiu? Verificar e obter da fonte oficial (npm)

O CDN pode servir arquivos diferentes do publicado oficialmente — isso já foi observado na prática com este projeto. Se o hash não bater, siga este processo para obter o arquivo diretamente do tarball oficial do npm, que é imutável e possui assinatura criptográfica verificável.

Por que o npm é mais confiável que o CDN? O npm registra o hash SHA-512 de cada pacote no momento do publish e nunca o altera. O CDN é uma camada de distribuição que pode divergir por cache, compressão ou, no pior caso, comprometimento.

# 1. Baixa o tarball oficial diretamente do registro npm
Invoke-WebRequest `
  -Uri "https://registry.npmjs.org/plotly.js-basic-dist-min/-/plotly.js-basic-dist-min-3.5.0.tgz" `
  -OutFile "$env:TEMP\plotly-basic-3.5.0.tgz"

# 2. Extrai o tarball
tar -xzf "$env:TEMP\plotly-basic-3.5.0.tgz" -C "$env:TEMP"

# 3. Verifica o hash do arquivo extraído
Get-FileHash "$env:TEMP\package\plotly-basic.min.js" -Algorithm SHA256
# Deve retornar: 5BD80F6D8FDD7BC055F8E48099403355FC7223A47F95B1D9193DA24C0BAB6B55
# Linux / macOS
curl -L -o /tmp/plotly-basic-3.5.0.tgz \
  "https://registry.npmjs.org/plotly.js-basic-dist-min/-/plotly.js-basic-dist-min-3.5.0.tgz"

tar -xzf /tmp/plotly-basic-3.5.0.tgz -C /tmp

sha256sum /tmp/package/plotly-basic.min.js
# Deve retornar: 5bd80f6d8fdd7bc055f8e48099403355fc7223a47f95b1d9193da24c0bab6b55

Se o hash bater: copie o arquivo extraído para o vendor:

# PowerShell
Copy-Item "$env:TEMP\package\plotly-basic.min.js" `
  -Destination "interface\web\static\vendor\plotly-basic.min.js" -Force
# Linux / macOS
cp /tmp/package/plotly-basic.min.js interface/web/static/vendor/plotly-basic.min.js

Se o hash não bater: não use o arquivo. Abra uma issue no repositório informando o hash que você obteve — pode indicar um problema de integridade no registro npm para a versão 3.5.0.

Limpeza após verificação — os arquivos temporários não são mais necessários:

# PowerShell — limpa arquivos temporários do processo de verificação
Remove-Item "$env:TEMP\plotly-basic-3.5.0.tgz" -Force
Remove-Item "$env:TEMP\package" -Recurse -Force
# Linux / macOS
rm /tmp/plotly-basic-3.5.0.tgz
rm -rf /tmp/package

ℹ️ Esses arquivos ficam em %TEMP% (Windows) ou /tmp (Linux/macOS). Não representam risco de segurança — são arquivos públicos baixados de fonte oficial. A limpeza é boa prática de higiene do sistema.

⚠ Se o hash não bater, não use o arquivo. Baixe novamente de outra rede ou verifique a release oficial em https://github.com/plotly/plotly.js/releases

Por que vendor local e não CDN?

CDNs introduzem supply chain risk: um atacante comprometendo o CDN pode injetar código malicioso em todos os usuários. Com vendor local e hash verificado, a superfície de ataque é eliminada.


Instalação e execução

Pré-requisitos

  • Python 3.9 ou superior
  • pip atualizado

Windows (PowerShell)

# 1. Criar e ativar virtualenv
python -m venv .venv
.venv\Scripts\Activate.ps1

# 2. Instalar dependências
pip install -r requirements.txt

# 3. Baixar Plotly (ver seção Setup do Vendor acima)

# 4. Iniciar servidor
python main.py

Linux / macOS

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python main.py

Acessar

http://127.0.0.1:8000          ← Interface web
http://127.0.0.1:8000/docs     ← Documentação automática FastAPI (Swagger UI)
http://127.0.0.1:8000/redoc    ← Documentação alternativa (ReDoc)

Testes

Instalar dependências de dev

pip install -r requirements-dev.txt

Rodar testes unitários

pytest tests/unit/ -v --cov=core --cov=domain --cov-report=term-missing

Rodar testes de integração

pytest tests/integration/ -v

Rodar todos

pytest tests/ -v

Rodar sem pytest (runner manual)

python tests/unit/test_core.py
python tests/integration/test_pipeline.py

CI — GitHub Actions

O pipeline .github/workflows/ci.yml executa 5 jobs em ordem:

lint ──────────────────────────────── flake8 + flake8-bugbear
sast ──────────────────────────────── bandit (SAST — falha se severity HIGH)
supply-chain ──────────────────────── pip-audit (falha se CVE em prod deps)
      └── tests ──────────────────── pytest unit + integration (cov ≥ 80%)
compatibility ─────────────────────── Python 3.9, 3.11, 3.12 em paralelo

Boas práticas de segurança no CI:

  • permissions: contents: read — princípio do menor privilégio
  • Todas as actions/ fixadas por SHA de commit — sem supply chain attack via tag mutável
  • pip-audit bloqueia build se CVE encontrada em requirements.txt
  • bandit bloqueia build se issue de severidade HIGH encontrada

API REST

POST /api/analisar

Request:

{
  "algoritmos": [
    {"nome": "Quicksort", "expressao": "n*log2(n)"},
    {"nome": "Bubblesort", "expressao": "n**2"}
  ],
  "n":      50000,
  "tipo":   "string",
  "padrao": "quase_ordenado"
}

Valores aceitos para tipo: int float string objeto

Valores aceitos para padrao: aleatorio quase_ordenado ordenado invertido muitas_duplicatas

Response 200:

{
  "recomendacao": {
    "algoritmo_ideal":    "timsort",
    "classe_assintotica": "O(n log n)",
    "custo_estimado":     234145.0,
    "justificativa":      "Timsort é especialmente eficiente...",
    "aviso":              null,
    "proximo_cruzamento": "em n ≈ 120.000, mergesort passa a vencer",
    "ranking": [
      {"nome": "timsort",    "custo": 234145.0},
      {"nome": "quicksort",  "custo": 830000.0}
    ]
  },
  "faixas": [
    {"algoritmo": "timsort", "n_inicio": 1, "n_fim": 9999, "cruzamento": 47.2}
  ],
  "ordem_assintotica": [
    {"algoritmo": "timsort", "classe": "O(n log n)", "indice": 4}
  ],
  "grafico_curvas": "{ ...JSON Plotly... }",
  "grafico_faixas": "{ ...JSON Plotly... }"
}

Erros:

Status Situação
400 tipo ou padrao inválido
422 Expressão matemática inválida, termo proibido, ou N fora do range

Segurança

Parser de expressões

  • Usa ast.parse + whitelist de nós AST — sem eval livre
  • __builtins__ bloqueados na execução
  • Nomes permitidos: apenas n, log, log2, exp, sqrt
  • Termos proibidos validados no cliente (JS) e no servidor (Pydantic)

HTTP

  • Headers de segurança em toda resposta: X-Content-Type-Options, X-Frame-Options, X-XSS-Protection, Content-Security-Policy
  • MAX_CONTENT_LENGTH limitado a 64KB
  • CORS restrito a localhost:8000

Supply chain

  • Todas as dependências Python com versão == fixada
  • Sem dependências JS externas em runtime
  • Plotly vendorizado localmente com verificação de hash SHA-256
  • pip-audit no CI bloqueia CVEs em produção

Fases futuras

Fase Descrição O que muda na arquitetura
2 Benchmark real na máquina Novo módulo core/benchmark/ com timeit; endpoint async /api/benchmark
3 Complexidade de espaço Campo espaco no modelo Algoritmo; novo bloco no frontend
4 Perfil de acesso ao vetor Enum PadraoAcesso em domain/types/; ajuste em cost_adjuster.py
5 Inferência via análise estática Novo módulo core/static_analyzer/ com ast walker de loops

Cada fase adiciona módulos sem modificar os existentes — respeitando o Open/Closed Principle (OCP) da Clean Architecture.


Pipeline de Segurança — Padrão Ouro

Visão geral do CI

secret-scanning ──── Gitleaks (histórico git completo)     ┐
lint            ──── flake8 + flake8-bugbear               ├─ paralelo
sast            ──── Bandit + Semgrep                      │
sca             ──── pip-audit + SBOM CycloneDX            ┘
                         │
                    todos passam?
                         │
tests           ──── pytest unit + integração (cov ≥ 80%)  ┐ sequencial
compatibility   ──── Python 3.9, 3.11, 3.12                ┘

SAST (Teste Estático de Segurança de Aplicações)

Ferramenta O que detecta
Bandit eval/exec livre, subprocess com shell=True, hashes fracos (MD5, SHA1), assert em produção
Semgrep p/python Bugs comuns, uso incorreto de APIs, type confusion
Semgrep p/security-audit Path traversal, f-string injection, open redirect, deserialização insegura

Configuração Bandit: .bandit Bloqueia build se: qualquer finding de severidade HIGH (Bandit) ou ERROR (Semgrep)

Rodar localmente:

bandit -r . -c .bandit
semgrep scan --config p/python --config p/security-audit --severity ERROR .

SCA (Análise de Composição de Software)

Ferramenta O que faz
pip-audit Verifica CVEs no NVD e PyPI Advisory Database para cada dependência
cyclonedx-bom Gera SBOM (Software Bill of Materials) em formato CycloneDX v1.4 JSON

O SBOM é exigido por:

  • NIST SP 800-161 (supply chain risk management)
  • Executive Order 14028 (EUA, 2021)
  • ISO 27001 e SOC 2 (auditorias de compliance)

Bloqueia build se: qualquer CVE encontrada em requirements.txt Não bloqueia: CVEs em requirements-dev.txt (reporta apenas) SBOM retido: 90 dias como artefato auditável

Rodar localmente:

pip-audit -r requirements.txt --strict
cyclonedx-py environment --output-format json --output-file sbom.cyclonedx.json

Secret Scanning

Ferramenta O que detecta
Gitleaks Chaves AWS/GCP/Azure, tokens GitHub/Slack/Stripe, senhas hardcoded, certificados privados, JWTs

Varre todo o histórico git (fetch-depth: 0), não só o commit atual. Bloqueia build imediatamente se qualquer segredo for detectado.

Rodar localmente (requer Docker):

docker run -v ${PWD}:/path zricethezav/gitleaks detect --source /path

DAST (Teste Dinâmico de Segurança de Aplicações) — Fase 2

Não implementado no MVP — requer app rodando em container isolado no CI. Será adicionado na Fase 2 com:

  • Docker + docker-compose no CI
  • OWASP ZAP (Zed Attack Proxy) ou Nuclei contra endpoints reais
  • Testa: XSS, CSRF, headers ausentes, endpoints expostos, injeção

Resumo de cobertura

Camada Ferramenta Status
Código estático Bandit + Semgrep ✅
Dependências pip-audit ✅
Inventário (SBOM) CycloneDX ✅
Segredos no código Gitleaks ✅

About

Algorithm Complexity Analyzer — Algorithm complexity analyzer with technical recommendations contextualized by data type and distribution pattern.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages