
Evidencia SOC 2 que se recopila sola en GitLab CI: cada merge emite un bundle firmado, una puerta OPA bloquea las versiones con pruebas faltantes y los auditores reciben un solo enlace en lugar de capturas de pantalla.
Evidencia SOC 2 que se recopila sola en GitLab CI: cada merge emite un bundle firmado, una puerta de Open Policy Agent bloquea las releases con prueba faltante, y un auditor recibe un único enlace al paquete en lugar de capturas de pantalla.
Panel del auditor en vivo · Proyecto de GitLab · Evidencia de demostración · Hoja de ruta
Construí ShipProof porque las ventas empresariales se estancan repetidamente durante la revisión de infosec. Cuando un auditor solicita evidencia de gestión de cambios de SOC 2 Type II, los ingenieros suelen pasar dos semanas buscando capturas de pantalla entre Jira, Slack y Drive.
Quería que la prueba viviera directamente en el pipeline de despliegue. Cada commit de merge en ShipProof crea automáticamente un bundle de evidencia canónico y firmado que cubre ejecuciones de pruebas, escaneos SAST de Semgrep, detección de secretos de Gitleaks, listas de materiales de software de Syft y aprobaciones de CODEOWNERS.
Mi regla de diseño central es estricta: un LLM puede resumir pruebas o redactar descripciones de issues, pero nunca puede aprobar una release. La puerta de release es una evaluación de Open Policy Agent escrita en Rego. Si falta un artefacto o una aprobación parece un sello de goma, la puerta falla de forma cerrada, detiene la release y abre un issue con la ruta de corrección. Cuando la puerta permite el paso, el auditor recibe un único enlace a un sitio estático o a una API autenticada.
Mapeé ShipProof contra el ciclo de vida de DevOps de GitLab. Automatiza las nueve etapas de forma nativa:
| Etapa | Qué automaticé en el pipeline |
|---|---|
| plan | Gestión de work items de brechas en bucle cerrado. Las denegaciones de la puerta abren automáticamente issues de seguimiento estructurados con recuentos de recurrencia; los pipelines posteriores que pasan resuelven y cierran automáticamente los issues con referencias al commit de corrección. |
| create | Revisión de código y gestión de fuentes. CODEOWNERS protege los archivos de políticas; la puerta rechaza aprobaciones tipo sello de goma de menos de cinco minutos; las notas automatizadas de MR guían la revisión; los flujos de Duo narran los comentarios de MR. |
| verify | pytest, Semgrep SAST y Gitleaks se ejecutan en la etapa verify, registrando hashes de artefactos. |
| package | Syft genera SBOMs de CycloneDX en la etapa package y calcula el hash del artefacto dentro del bundle. |
| secure | La puerta determinista de OPA verifica firmas, hashes de cadena y reglas de sello de goma antes de la release. |
| release | El job de puerta de cumplimiento bloquea el despliegue a producción; los jobs de despliegue requieren un veredicto de permiso. |
| configure | Los manifiestos de despliegue de Cloud Run se generan a partir de variables de entorno sin confirmar secretos. |
| monitor | Las comprobaciones posteriores al despliegue verifican que los digests de las imágenes de contenedor en ejecución coincidan con el commit aprobado en el bundle. |
| govern | Un ledger inmutable encadenado por hash alimenta los paquetes para auditores, los issues de brechas y el panel de GitLab Pages. |
Desarrollé ShipProof con Python 3.11 y Node.js 20.
python -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
Ejecuta mi suite de pruebas y las comprobaciones de tipos:
OPA_BIN=/tmp/opa pytest -q && ruff check src tests demo-app scripts && mypy --strict src scripts
Recopila un paquete local para cualquier commit:
PYTHONPATH=src python -m comply.collect --sha aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --out /tmp/bundle.json
El recolector genera una única línea JSON en stdout y escribe el paquete completo en disco junto a policy/inputs.json. Si faltan las pruebas, el paquete registra un estado de denegación.
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
En CI, scripts/gate_bridge.py prepara pipeline.json, mientras que scripts/fetch_approvals.py obtiene los datos de revisión desde la API de GitLab. Los archivos faltantes se registran con estado de faltante en lugar de asumirse como aprobados. Cada registro de stderr incluye el ID de correlación del bundle, y los secretos se enmascaran como ***.
PYTHONPATH=src python -m comply.gate --bundle evidence/bundle.json --ledger logs/ledger.jsonl
El código de salida 0 indica un veredicto de permitir. El código de salida 1 indica una denegación con un error estructurado que nombra el control fallido. El código de salida 2 indica argumentos inválidos. Cuando la puerta bloquea en CI, el pipeline activa python -m comply.gap para abrir un issue de seguimiento.
PYTHONPATH=src python -m comply.packet --ledger logs/ledger.jsonl --release all \
--out packet.json --csv packet.csv --pdf packet.pdf
La exportación CSV contiene once columnas: bundle_id,commit_sha,mr_iid,pipeline_id,control,proof_type,status,artifact_sha,approver_ids,policy_sha,created_at. El PDF se genera a partir de la misma fuente JSON mediante CSS de impresión.
AUDITOR_TOKEN=local-only PYTHONPATH=src uvicorn comply.api:app --port 8000
Consultar paquetes usando autenticación bearer:
curl -H "Authorization: Bearer local-only" "localhost:8000/api/v1/bundles?mr_iid=42"
La API expone endpoints para consultas de bundles, paquetes de versiones y exportaciones de PDF en segundo plano, protegidos por tokens de portador y un límite de velocidad de 60 solicitudes por minuto.
cd auditor && npm install && npm run build
La interfaz está construida con React 19, TypeScript y Tailwind CSS. Se exporta como un sitio estático usando enrutamiento por hash, lo que permite ejecutarse directamente en GitLab Pages sin reescrituras del servidor. Cuando no hay una API de backend presente, utiliza datos de ejemplo de public/fallback/demo-packets.json.