
Prove SOC 2 che si raccolgono da sole in GitLab CI: ogni merge genera un bundle firmato, un gate OPA blocca le release prive di prove e gli auditor ricevono un unico link invece di screenshot.
Evidenze SOC 2 che si raccolgono da sole in GitLab CI: ogni merge genera un bundle firmato, un gate Open Policy Agent blocca le release con prove mancanti e un auditor riceve un unico link a un pacchetto invece di screenshot.
Dashboard live per gli auditor · Progetto GitLab · Evidenze demo · Roadmap
Ho costruito ShipProof perché le vendite enterprise si bloccano ripetutamente durante la revisione infosec. Quando un auditor chiede evidenze di change management per SOC 2 Type II, gli ingegneri spesso passano due settimane a cercare screenshot tra Jira, Slack e Drive.
Volevo che le prove vivessero direttamente nella pipeline di deployment. Ogni merge commit in ShipProof crea automaticamente un bundle di evidenze canonico e firmato che copre esecuzioni dei test, scansioni SAST con Semgrep, rilevamento di segreti con Gitleaks, software bill of materials con Syft e approvazioni CODEOWNERS.
La mia regola di progettazione centrale è rigorosa: un LLM può riassumere le prove o redigere descrizioni di issue, ma non può mai approvare una release. Il gate di rilascio è una valutazione Open Policy Agent scritta in Rego. Se un artefatto manca o un'approvazione sembra un timbro automatico, il gate fallisce in modo sicuro, interrompe la release e apre una issue con il percorso di correzione. Quando il gate consente il rilascio, l'auditor riceve un unico link a un sito statico o a un'API autenticata.
Ho mappato ShipProof sul ciclo di vita DevOps di GitLab. Automatizza nativamente tutte e nove le fasi:
| Fase | Cosa ho automatizzato nella pipeline |
|---|---|
| plan | Gestione a ciclo chiuso dei work item per le lacune. I dinieghi del gate aprono automaticamente issue di tracciamento strutturate con conteggi di ricorrenza; le pipeline successive che passano risolvono e chiudono automaticamente le issue con riferimenti ai commit di correzione. |
| create | Code review e gestione del codice sorgente. CODEOWNERS protegge i file di policy; il gate rifiuta approvazioni timbro automatico sotto i cinque minuti; note automatiche sulle MR guidano la review; i flussi Duo narrano i commenti delle MR. |
| verify | pytest, Semgrep SAST e Gitleaks vengono eseguiti nella fase verify, registrando gli hash degli artefatti. |
| package | Syft genera SBOM CycloneDX nella fase package e calcola l'hash dell'artefatto nel bundle. |
| secure | Il gate OPA deterministico verifica firme, hash della catena e regole sui timbri automatici prima della release. |
| release | Il job del gate di conformità blocca il deployment in produzione; i job di deploy richiedono un verdetto di autorizzazione. |
| configure | I manifest di deployment su Cloud Run vengono generati da variabili d'ambiente senza committare segreti. |
| monitor | I controlli post-deploy verificano che i digest delle immagini container in esecuzione corrispondano al commit approvato nel bundle. |
| govern | Un ledger immutabile concatenato tramite hash alimenta i pacchetti per gli auditor, le issue per le lacune e la dashboard su GitLab Pages. |
Ho sviluppato ShipProof con Python 3.11 e Node.js 20.
python -m venv .venv && source .venv/bin/activate && pip install -r requirements.txt
Esegui la mia suite di test e i controlli dei tipi:
OPA_BIN=/tmp/opa pytest -q && ruff check src tests demo-app scripts && mypy --strict src scripts
Raccogli un bundle locale per qualsiasi commit:
PYTHONPATH=src python -m comply.collect --sha aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa --out /tmp/bundle.json
Il collector produce una singola riga JSON su stdout e scrive il bundle completo su disco insieme a policy/inputs.json. Se le prove sono mancanti, il bundle registra uno stato di rifiuto.
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
In CI, scripts/gate_bridge.py prepara pipeline.json, mentre scripts/fetch_approvals.py recupera i dati di revisione dall'API di GitLab. I file mancanti vengono registrati come stato mancante anziché essere considerati superati per impostazione predefinita. Ogni log stderr include l'ID di correlazione del bundle e i segreti sono mascherati come ***.
PYTHONPATH=src python -m comply.gate --bundle evidence/bundle.json --ledger logs/ledger.jsonl
Il codice di uscita 0 indica un verdetto di autorizzazione. Il codice di uscita 1 indica un rifiuto con un errore strutturato che nomina il controllo non superato. Il codice di uscita 2 indica argomenti non validi. Quando il gate blocca in CI, la pipeline attiva python -m comply.gap per aprire una issue di tracciamento.
PYTHONPATH=src python -m comply.packet --ledger logs/ledger.jsonl --release all \
--out packet.json --csv packet.csv --pdf packet.pdf
L'esportazione CSV contiene undici colonne: bundle_id,commit_sha,mr_iid,pipeline_id,control,proof_type,status,artifact_sha,approver_ids,policy_sha,created_at. Il PDF viene generato dalla stessa sorgente JSON tramite CSS di stampa.
AUDITOR_TOKEN=local-only PYTHONPATH=src uvicorn comply.api:app --port 8000
Esegui query sui bundle usando l'autenticazione bearer:
curl -H "Authorization: Bearer local-only" "localhost:8000/api/v1/bundles?mr_iid=42"
L'API espone endpoint per query sui bundle, pacchetti di rilascio ed esportazioni PDF in background, protetti da token bearer e con un limite di 60 richieste al minuto.
cd auditor && npm install && npm run build
L'interfaccia è costruita con React 19, TypeScript e Tailwind CSS. Viene esportata come sito statico utilizzando l'hash routing, il che le consente di funzionare direttamente su GitLab Pages senza riscritture lato server. Quando non è presente alcuna API backend, utilizza dati di esempio da public/fallback/demo-packets.json.