
September 12, 2026
10 min read
By Kokil Thapa | Last reviewed: September 2026
Compliance as Code: Automate Evidence Collection replaces the quarterly scramble for screenshots with pipelines that prove controls on every merge. Auditors still want change logs, access reviews, backup proof, and vulnerability scans. Manual collection breaks the moment your team ships weekly. Treat evidence like deploy artifacts: versioned, timestamped, and reproducible. This guide maps controls to code, with examples from compliance as code foundations through production Laravel and GitLab CI workflows I use on client systems.
What Is Compliance as Code and Why Automate Evidence Collection?
Compliance as code expresses security and governance rules in machine-readable form. Evidence collection is the output side: proof that those rules ran and passed. Together they close the loop auditors expect.
Traditional audits ask engineers to reconstruct three months of reality from Slack threads. That fails under SOC 2 pressure on startups and on Nepal fintech teams facing data residency expectations. Automated evidence gives you a folder per control, refreshed on schedule, not a panic folder the night before the call.
The model mirrors infrastructure as code. Your Terraform plan is evidence that network rules changed through review. Your PHPUnit suite with coverage gates in CI proves testing controls ran before deploy. Auditors care about consistency more than fancy dashboards.
How Do You Map Audit Controls to Automated Evidence Jobs?
Start with the control catalog your framework requires. SOC 2 CC6 covers logical access. CC7 covers change management. PCI DSS 10.x covers logging. HIPAA asks for access reviews and encryption proof. Each control becomes one or more collectors.
Build a control-to-collector matrix
List every auditor question you answered manually last cycle. Pair each question with a script, CI job, or scheduled task. Store outputs in a predictable path such as evidence/{control_id}/{YYYY-MM-DD}/.
| Control theme | Auditor question | Automated collector | Frequency |
|---|---|---|---|
| Change management | Were prod deploys reviewed? | GitLab merge request API export + deploy manifest | Every release |
| Vulnerability mgmt | Were deps scanned? | composer audit --format=json in CI | Every build |
| Access control | Who had admin last quarter? | RBAC export from Spatie Permission + DB snapshot | Weekly |
| Backup / recovery | Did backups succeed? | Cron log parser + restore drill report | Daily |
| Logging | Are auth events retained? | Audit log row count + sample hash | Daily |
| Encryption | Is TLS current? | Cert expiry check script output | Weekly |
On legal-tech portals like Mijar Law Associates, document access and payment logs matter as much as infra controls. Map client-facing actions to the same evidence store so one audit pack covers app and server layers.
How Do You Implement Evidence Collection in CI/CD Pipelines?
Your pipeline already runs tests and deploys. Add a final stage that never blocks release on first rollout, but always uploads artifacts. Once stable, turn failed evidence uploads into hard gates.
GitLab CI example for a Laravel 13 app
This pattern matches Deployer 7 pipelines I maintain on shared EC2 hosts. PHP 8.3 or 8.5, Composer 2.10, and GitLab CI stages stay familiar to small Nepal teams without dedicated compliance staff.
# .gitlab-ci.yml excerpt
stages:
- test
- security
- deploy
- evidence
composer_audit:
stage: security
script:
- composer audit --format=json > composer-audit.json
artifacts:
paths:
- composer-audit.json
expire_in: 1 year
export_access_matrix:
stage: evidence
script:
- php artisan compliance:export-access-matrix --output=access-matrix.csv
- php artisan compliance:export-audit-sample --days=7 --output=audit-sample.json
artifacts:
paths:
- access-matrix.csv
- audit-sample.json
expire_in: 1 year
upload_evidence:
stage: evidence
script:
- ./scripts/upload-evidence.sh "$CI_COMMIT_SHA" "$CI_PIPELINE_ID"
only:
- main
The upload script pushes to object storage with server-side encryption. Include commit SHA, pipeline ID, and ISO timestamp in the object key. Auditors love immutable paths. See automating SOC 2 evidence in CI for storage layout details.
Laravel artisan collector sketch
Keep collectors thin. Query the database, write CSV or JSON, exit zero on success. Validate output with your JSON formatter tool during development so malformed exports fail fast locally.
// app/Console/Commands/ExportAccessMatrix.php
public function handle(): int
{
$rows = User::query()
->with('roles.permissions')
->get()
->map(fn ($u) => [
'email' => $u->email,
'roles' => $u->roles->pluck('name')->join('|'),
'exported_at' => now()->toIso8601String(),
]);
$path = $this->option('output');
file_put_contents($path, $this->toCsv($rows));
return self::SUCCESS;
}
Schedule weekly exports via Laravel's task scheduler. Point cron at php artisan schedule:run on the same path you use after Deployer symlink swaps. Stale cron paths are a common post-deploy failure I've debugged on sister legal-tech sites.
Which Tools and Frameworks Support Policy-as-Code Evidence?
Evidence automation sits on three layers: policy definition, enforcement, and export. Mix tools to match team size. A five-person Nepal agency does not need the same stack as a US SaaS vendor targeting SOC 2 Type II.
Open Policy Agent with Conftest evaluates Terraform and Kubernetes manifests before apply. A denied policy is evidence that a control blocked bad config. Pair OPA with SonarQube gates in CI for application-layer proof. The Open Policy Agent documentation covers Rego basics and CI integration patterns.
For infrastructure proof, Terraform state backups and plan files stored alongside automated database backups satisfy many CC8-style recovery questions. Tag backup objects with retention metadata your auditor can read without SSH access.
GitLab's native artifact and compliance features document pipeline provenance. See the GitLab CI/CD documentation for artifact retention and environment-scoped variables. If you run GitHub Actions instead, the pattern is identical: a dedicated evidence job and long-lived artifact storage.
What Evidence Should Nepal-Based Teams Prioritize?
Global frameworks still apply when you sell abroad or host on AWS Singapore. Local context adds layers. Payment integrations with eSewa, Khalti, or ConnectIPS need callback logs and reconciliation exports. Legal portals need document access trails.
eCommerce legal compliance in Nepal covers PAN/VAT display rules. Your evidence pack should include config snapshots proving pricing pages show required tax text. That is a static config export, not a meeting note.
- Map frameworks first: SOC 2, PCI, client contract, or Nepal data handling expectations.
- Automate what repeats every sprint: dependency scans, deploy manifests, test reports.
- Schedule what repeats monthly: access reviews, cert checks, backup restore drills.
- Store everything in one bucket with consistent naming and seven-year retention tags where required.
- Run a dry-run audit quarterly: can a new engineer build the pack in under four hours?
Teams without dedicated GRC staff benefit from testing and optimization services that wire CI gates before the first formal audit. Treat compliance automation as part of enterprise application development, not a post-launch patch.
How Do You Package Evidence for Auditors Without Losing Integrity?
Collecting files is half the job. Auditors need to trust they were not edited yesterday. Sign manifests, restrict write access to the evidence bucket, and enable object versioning.
Manifest and hash pattern
#!/usr/bin/env bash
# scripts/upload-evidence.sh
set -euo pipefail
COMMIT_SHA="$1"
PIPELINE_ID="$2"
STAMP="$(date -u +%Y-%m-%dT%H:%M:%SZ)"
DIR="evidence/${COMMIT_SHA}/${PIPELINE_ID}"
sha256sum composer-audit.json access-matrix.csv > "${DIR}/checksums.txt"
jq -n \
--arg sha "$COMMIT_SHA" \
--arg pipe "$PIPELINE_ID" \
--arg at "$STAMP" \
'{commit:$sha,pipeline:$pipe,exported_at:$at,files:["composer-audit.json","access-matrix.csv"]}' \
> "${DIR}/manifest.json"
aws s3 sync "${DIR}/" "s3://company-evidence/${DIR}/" --sse AES256
Enable S3 Object Lock or equivalent WORM storage if your auditor requires tamper evidence. For on-prem Ubuntu hosts, I've used separate backup accounts with read-only IAM for auditor login. Linux administration and bucket policy work often land in the same engagement as the app build.
The NIST Cybersecurity Framework's Identify and Detect functions align well with evidence automation. The NIST Cybersecurity Framework gives auditors familiar language for your control mapping spreadsheet.
Ongoing proof needs ongoing ops. Support and maintenance retainers should include evidence job health checks. A silent failure in a weekly RBAC export creates the same gap as a broken backup cron.
Key Takeaways
- Map each audit control to one automated collector with a fixed output path and retention tag.
- Run evidence jobs in CI on every merge to main, plus scheduled exports for access and backups.
- Sign manifests with SHA-256 hashes and store artifacts in versioned, encrypted object storage.
- Start with dependency scans, deploy manifests, and RBAC exports before adding OPA policy gates.
- Quarterly dry-run audits prove a new engineer can assemble the pack in hours, not weeks.
- Wire compliance automation during build, especially for legal-tech and payment-heavy Nepal apps.
People Also Ask
What is compliance as code in simple terms?
It means writing security and governance rules as version-controlled code—CI checks, OPA policies, infrastructure tests—that run automatically instead of living in PDF checklists nobody opens until audit season.
How often should automated compliance evidence run?
Run build-time collectors on every pipeline. Schedule access reviews, backup verifications, and certificate checks weekly or daily. Match frequency to the control's audit sampling window so you always have overlapping proof.
Can small teams afford compliance evidence automation?
Yes. Composer audit, GitLab artifacts, and a single S3 bucket cost far less than manual audit prep. Most Laravel teams can ship a baseline pack in one sprint using existing CI and a few artisan commands.
Does automated evidence replace human audit review?
No. Automation produces trustworthy raw material. Auditors still evaluate control design and sample exceptions. You remove collection toil so humans focus on judgment calls, not screenshot hunting.
Ship Audit-Ready Pipelines, Not Panic Folders
Compliance as Code: Automate Evidence Collection turns audit season from a morale hit into a query against your evidence store. Start with three collectors this week: dependency scan JSON, merge-request deploy manifest, and weekly access matrix CSV. Expand into policy-as-code once those run clean for a month. If you want help wiring collectors into a Laravel or legal-tech platform you already run, contact us for a scoped review—or browse the blog and about page for related DevOps and compliance writing.
Frequently Asked Questions
0 Comments
Leave a comment
Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

