
Evidências SOC 2 que se coletam sozinhas no GitLab CI: cada merge emite um bundle assinado, um gate OPA bloqueia releases com provas ausentes, e os auditores recebem um único link em vez de capturas de tela.
Evidências SOC 2 que se coletam sozinhas no GitLab CI: cada merge emite um bundle assinado, um gate do Open Policy Agent bloqueia releases com provas ausentes, e um auditor recebe um único link de pacote em vez de capturas de tela.
Painel do auditor ao vivo · Projeto no GitLab · Evidências de demonstração · Roadmap
Construí o ShipProof porque as vendas corporativas travam repetidamente durante a revisão de segurança da informação. Quando um auditor pede evidências de gestão de mudanças do SOC 2 Type II, os engenheiros costumam passar duas semanas caçando capturas de tela pelo Jira, Slack e Drive.
Eu queria que as provas vivessem diretamente no pipeline de implantação. Cada commit de merge no ShipProof cria automaticamente um bundle de evidências canônico e assinado, cobrindo execuções de testes, varreduras SAST do Semgrep, detecção de segredos do Gitleaks, listas de materiais de software do Syft e aprovações do CODEOWNERS.
Minha regra de design central é rígida: um LLM pode resumir provas ou redigir descrições de issues, mas nunca pode aprovar um release. O gate de release é uma avaliação do Open Policy Agent escrita em Rego. Se um artefato estiver ausente ou uma aprovação parecer um carimbo, o gate falha de forma fechada, interrompe o release e abre uma issue com o caminho de correção. Quando o gate permite, o auditor recebe um único link para um site estático ou uma API autenticada.
Mapeei o ShipProof em relação ao ciclo de vida DevOps do GitLab. Ele automatiza todos os nove estágios nativamente:
| Estágio | O que automatizei no pipeline |
|---|---|
| plan | Gestão de itens de trabalho de lacunas em ciclo fechado. As negações do gate abrem automaticamente issues de rastreamento estruturadas com contagens de recorrência; pipelines subsequentes que passam resolvem e fecham automaticamente as issues com referências aos commits de correção. |
| create | Revisão de código e gestão de código-fonte. O CODEOWNERS protege os arquivos de política; o gate rejeita aprovações de carimbo em menos de cinco minutos; notas automatizadas de MR orientam a revisão; fluxos do Duo narram os comentários de MR. |
| verify | pytest, Semgrep SAST e Gitleaks são executados no estágio verify, registrando hashes de artefatos. |
| package | O Syft gera SBOMs CycloneDX no estágio package e calcula o hash do artefato no bundle. |
| secure | O gate determinístico do OPA verifica assinaturas, hashes de cadeia e regras de carimbo antes do release. |
| release | O job de gate de conformidade bloqueia a implantação em produção; os jobs de deploy exigem um veredito de permissão. |
| configure | Os manifestos de implantação no Cloud Run são renderizados a partir de variáveis de ambiente sem commitar segredos. |
| monitor | Verificações pós-deploy confirmam que os digests das imagens de contêiner em execução correspondem ao commit aprovado no bundle. |
| govern | Um ledger imutável encadeado por hash alimenta os pacotes para auditores, as issues de lacunas e o painel do GitLab Pages. |
Desenvolvi o ShipProof com Python 3.11 e Node.js 20.
python -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
Execute minha suíte de testes e verificações de tipos:
OPA_BIN=/tmp/opa pytest -q && ruff check src tests demo-app scripts && mypy --strict src scripts
Coletar um bundle local para qualquer commit:
PYTHONPATH=src python -m comply.collect --sha aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --out /tmp/bundle.json
O coletor gera uma única linha JSON para stdout e grava o bundle completo em disco junto com policy/inputs.json. Se as provas estiverem ausentes, o bundle registra um status de negação.
PYTHONPATH=src python -m comply.collect --sha <40-hex-sha> --out evidence/bundle.json \
--mr-iid 42 --pipeline-id 1001 --project group/project \
--pipeline-file pipeline.json --approvals-file approvals.json
No CI, scripts/gate_bridge.py prepara pipeline.json, enquanto scripts/fetch_approvals.py obtém dados de revisão da API do GitLab. Arquivos ausentes são registrados com status de ausente em vez de assumidos como aprovados. Todo log de stderr inclui o ID de correlação do bundle, e segredos são mascarados como ***.
PYTHONPATH=src python -m comply.gate --bundle evidence/bundle.json --ledger logs/ledger.jsonl
O código de saída 0 indica um veredito de permissão. O código de saída 1 indica uma negação com um erro estruturado que nomeia o controle que falhou. O código de saída 2 indica argumentos inválidos. Quando o gate bloqueia no CI, o pipeline aciona python -m comply.gap para abrir uma issue de acompanhamento.
PYTHONPATH=src python -m comply.packet --ledger logs/ledger.jsonl --release all \
--out packet.json --csv packet.csv --pdf packet.pdf
O export CSV contém onze colunas: bundle_id,commit_sha,mr_iid,pipeline_id,control,proof_type,status,artifact_sha,approver_ids,policy_sha,created_at. O PDF é renderizado a partir da mesma fonte JSON através de CSS de impressão.
AUDITOR_TOKEN=local-only PYTHONPATH=src uvicorn comply.api:app --port 8000
Consultar bundles usando autenticação bearer:
curl -H "Authorization: Bearer local-only" "localhost:8000/api/v1/bundles?mr_iid=42"
A API expõe endpoints para consultas de bundles, pacotes de release e exportações de PDF em segundo plano, protegidos por bearer tokens e um limite de taxa de 60 requisições por minuto.
cd auditor && npm install && npm run build
A interface é construída com React 19, TypeScript e Tailwind CSS. Ela é exportada como um site estático usando hash routing, permitindo que seja executada diretamente no GitLab Pages sem reescritas no servidor. Quando não há uma API de backend presente, ela usa dados de exemplo de public/fallback/demo-packets.json.