
September 12, 2026
13 min read
By Kokil Thapa | Last reviewed: September 2026
Manual compliance checklists fail the moment your team ships faster than your auditor can review spreadsheets. Compliance as Code Explained is the practice of encoding regulatory, security, and operational rules as version-controlled artifacts that run automatically in pipelines—much like infrastructure as code defines servers. On production Laravel and WordPress systems I maintain, compliance drift often appears first in deployment config, not in application logic. This guide maps the concept, the tooling stack, and the patterns that actually hold up under audit.
What Is Compliance as Code and How Does It Differ from Policy as Code?
Compliance as code is the umbrella. Policy as code is one implementation layer inside it. Think of compliance as the outcome auditors care about. Policy as code is how you express individual rules.
A SOC 2 control might require encrypted database connections. You encode that rule in Rego for Open Policy Agent (OPA). The pipeline evaluates every Terraform plan against it. A failed check blocks the merge. That is compliance as code in action.
The distinction matters when you scope a project. Policy as code handles individual allow/deny decisions. Compliance as code adds traceability, evidence collection, control mapping, and remediation workflows on top.
Core artifact types
- Policy definitions — Rego, Sentinel HCL, or YAML rules that express must-pass conditions.
- Compliance tests — Automated checks tied to specific control IDs (CC6.1, GDPR Art. 32, etc.).
- Evidence collectors — Scripts or pipeline jobs that export logs, scan results, and config snapshots.
- Control matrices — YAML or JSON files mapping framework requirements to automated checks.
On a legal-tech portal I built, document retention rules lived in application code. The auditor wanted proof those rules were enforced consistently. Moving retention logic into tested, versioned policy files closed that gap faster than any policy PDF.
Why Should Teams Adopt Compliance as Code Instead of Manual Audits?
Manual audits snapshot a point in time. Production changes every day. Compliance as code gives you continuous assurance between audit cycles.
| Dimension | Manual compliance | Compliance as code |
|---|---|---|
| Timing | Quarterly or annual review | Every commit and deploy |
| Evidence | Screenshots, spreadsheets | Machine-readable JSON, SARIF, signed artifacts |
| Drift detection | Found late, often by auditor | Blocked at merge or deploy gate |
| Cost at scale | Linear with systems and headcount | Fixed pipeline cost, marginal per service |
| Developer friction | Last-minute fire drills | Fast feedback in familiar CI tools |
| Audit prep time | Weeks of evidence gathering | Export from evidence store in hours |
Startups chasing SOC 2 compliance feel this pain early. Enterprise clients ask for evidence before contract signature. Manual collection does not scale when you deploy ten times a week.
For Nepal-based SaaS companies, data residency requirements add another layer. Encoding region constraints in Terraform policy prevents accidental provisioning in the wrong AWS region. That single automated check beats a quarterly spreadsheet review.
How Do You Implement Compliance as Code in a CI/CD Pipeline?
Start small. Pick one high-risk control. Automate it. Expand from there. A common mistake is trying to map an entire SOC 2 framework before a single pipeline gate works.
Step 1: Map controls to automatable checks
Export your framework control list. SOC 2, ISO 27001, GDPR, PCI DSS, or Nepal-specific rules from eCommerce legal compliance guides. Mark each control as automated, partially automated, or manual-only.
Most security and change-management controls automate well. Physical security and HR background checks stay manual. Be honest about the split. Auditors respect accurate control matrices over inflated automation claims.
Step 2: Write the first policy file
Here is a minimal OPA Rego policy that denies public S3 buckets. Save it as policies/s3_public_access.rego:
package terraform.s3
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket"
resource.change.after.acl == "public-read"
msg := sprintf("S3 bucket %s must not be public", [resource.address])
}
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_s3_bucket_public_access_block"
not resource.change.after.block_public_acls
msg := "Public access block must enable block_public_acls"
} Run it with Conftest against a Terraform plan JSON file. The official Open Policy Agent documentation covers Rego syntax and testing patterns in detail.
Step 3: Wire the check into GitLab CI or GitHub Actions
A GitLab CI job for a Laravel 13 project on PHP 8.3 might look like this:
compliance:terraform-policy:
stage: test
image: openpolicyagent/conftest:latest
script:
- terraform init -backend=false
- terraform plan -out=plan.tfplan
- terraform show -json plan.tfplan > plan.json
- conftest test plan.json -p policies/ --output json > policy-results.json
artifacts:
paths:
- policy-results.json
expire_in: 1 year
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event" Store artifacts for at least one audit cycle. Many teams keep twelve months. Align retention with your framework requirements and contract terms.
Step 4: Add application-level compliance tests
Infrastructure policy is not enough. Application code carries privacy and access-control obligations too. On Laravel apps I maintain, I add PHPUnit tests that verify authorization policies and data export endpoints.
public function test_user_cannot_download_another_users_document(): void
{
$owner = User::factory()->create();
$intruder = User::factory()->create();
$document = Document::factory()->for($owner)->create();
$response = $this->actingAs($intruder)
->get(route('documents.download', $document));
$response->assertForbidden();
} Tag these tests with a @group compliance annotation. Run them in a dedicated CI job. Export JUnit XML as evidence. This pairs well with code coverage gates in CI when you tie coverage thresholds to security-critical modules.
Step 5: Collect and index evidence
Each passing pipeline run produces artifacts. Scan reports, policy results, test output, dependency audit logs. Push them to an immutable store. S3 with Object Lock, GCS with retention policies, or a dedicated compliance platform.
Structure evidence by control ID. A JSON index file makes auditor queries fast:
{
"control_id": "CC6.1",
"framework": "SOC2",
"automated_check": "terraform-s3-public-access-policy",
"last_pass": "2026-09-08T14:22:00Z",
"pipeline_url": "https://gitlab.example.com/project/-/pipelines/12345",
"artifact_path": "s3://compliance-evidence/2026/09/CC6.1-12345.json"
} The approach mirrors what I describe in automating SOC 2 compliance evidence in CI. The difference at scale is consistent naming and retention from day one.
Which Tools and Frameworks Support Compliance as Code?
No single tool covers every compliance domain. Mature teams assemble a stack. Each layer handles a different artifact type.
- Open Policy Agent (OPA) — General-purpose policy engine. Works with Terraform, Kubernetes, API gateways, and custom JSON inputs. See also policy as code with OPA and Conftest.
- HashiCorp Sentinel — Embedded in Terraform Cloud. Good if you already use HashiCorp stack. Covered in Sentinel policy as code for Terraform.
- OpenSCAP — Runs CIS and STIG benchmarks against Linux servers. Useful for Linux system administration hardening on Ubuntu 22/24 hosts.
- InSpec — Ruby-based compliance language for server and container configuration testing.
- SAST and dependency scanners — SonarQube, Semgrep,
composer audit,npm auditfor supply-chain controls. - Evidence platforms — Vanta, Drata, Secureframe for SOC 2. Or roll your own with S3 and a searchable index.
For multi-cloud setups, read multi-cloud governance and policy as code. The same OPA policies can evaluate AWS, Azure, and GCP resource plans with minor input adapters.
The NIST Cybersecurity Framework gives a useful taxonomy for organizing controls. Map your automated checks to Identify, Protect, Detect, Respond, and Recover categories. Auditors recognize the structure even when your tooling is custom.
What Does Compliance as Code Look Like on a Real Production System?
Abstract patterns become clearer with a concrete walkthrough. Consider a Laravel 12 booking platform on AWS with MySQL 8.4, Redis 8.10, and GitLab CI.
Projects like Mijar Law Associates and Notary Nepal handle sensitive client documents. Compliance as code for these systems spans three layers.
Infrastructure layer. Terraform policies enforce encrypted RDS instances, private subnets, and no public security group rules. OpenSCAP scans the Ubuntu EC2 host against CIS Level 1.
Application layer. PHPUnit tests verify RBAC with Spatie Laravel Permission. Feature tests confirm audit log entries on document download. A scheduled job test proves retention purge runs and respects configurable periods.
Runtime layer. A Deployer 7 post-deploy hook validates APP_DEBUG=false and APP_ENV=production in the live .env. This catches the gotcha shown above. Infrastructure can be perfect while application config drifts.
For WordPress 7.1 and WooCommerce 11.1 shops, compliance as code looks different. Plugin vulnerability scans, file integrity checks, and GDPR cookie consent tests replace Terraform policy. See WordPress GDPR compliance checklist for the control list.
Nepal-specific finance controls add another dimension. A SaaS billing in NPR must produce VAT-compliant invoices. Business rules belong in code with tests. Cross-check calculations with the Nepal salary calculator pattern—deterministic logic, versioned, testable. Read Nepal VAT and tax compliance for SaaS businesses for the regulatory context.
Encoding a retention policy in Laravel
// app/Console/Commands/PurgeExpiredDocuments.php
public function handle(): int
{
$retentionDays = (int) config('compliance.document_retention_days', 2555);
$expired = Document::query()
->where('created_at', '<', now()->subDays($retentionDays))
->whereNull('legal_hold_at')
->get();
foreach ($expired as $document) {
$document->delete(); // triggers media library cleanup
activity()->performedOn($document)->log('retention_purge');
}
return self::SUCCESS;
} Pair this with a test and a CI job. Export the activity log query result as quarterly evidence. The auditor sees automated purges happened on schedule.
How Do You Avoid Common Compliance as Code Mistakes?
Teams new to this approach repeat the same failures. Most are process problems, not tool problems.
- Automating low-value controls first. Start with high-risk items: public exposure, unencrypted data, missing auth checks. Leave office-visitor-log automation for later.
- Treating a passing scan as full compliance. Automated checks cover a subset of controls. Document which remain manual. Auditors will ask.
- No evidence retention policy. Pipeline artifacts expire in thirty days by default. Extend retention before your first audit.
- Policy files outside code review. Compliance rules must go through the same MR process as application code. No side-channel edits in the production console.
- Ignoring developer ergonomics. Cryptic Rego errors frustrate teams. Write clear denial messages. Add
conftest verifylocally. Use the JSON formatter to debug plan output and the regex tester for log parsing rules. - Skipping runtime validation. IaC policy at plan time does not catch manual console changes or bad
.envvalues. Add periodic drift detection withterraform plan -detailed-exitcodeor scheduled OpenSCAP runs.
I've seen GitLab CI pipelines pass every policy check while cron jobs pointed at stale release paths after a Deployer symlink swap. Compliance as code must include operational checks, not just pre-merge gates. That lesson applies across the sister sites I maintain on shared EC2 infrastructure.
Engage your auditor early. Show them a sample evidence export and control matrix before the formal audit. Adjust naming and retention based on their feedback. This saves rework and builds trust.
For teams without in-house DevOps capacity, testing and optimization services or enterprise application development can bootstrap the first control set. The goal is a maintainable baseline your team owns afterward.
Key Takeaways
- Compliance as code encodes audit requirements as version-controlled, executable rules—not static PDF checklists.
- Start with one high-risk control, automate it in CI, store the evidence, then expand the control matrix incrementally.
- Combine infrastructure policy (OPA/Sentinel), application tests (PHPUnit/feature tests), and runtime validation (deploy hooks, OpenSCAP).
- Map every automated check to a framework control ID and retain artifacts for at least one full audit cycle.
- Legal-tech, eCommerce, and SaaS systems in Nepal need both global frameworks (SOC 2, GDPR) and local rules (VAT, data residency).
- Treat compliance policies like production code: code review, tests, clear error messages, and no manual console exceptions.
People Also Ask
Is compliance as code only for large enterprises?
No. Startups benefit most because they build automation habits before complexity grows. A five-person team with GitLab CI and ten OPA policies can produce cleaner SOC 2 evidence than a fifty-person team relying on quarterly manual reviews.
Can compliance as code replace an external auditor?
It cannot. Auditors still evaluate control design and operating effectiveness. Compliance as code reduces evidence-gathering time and proves continuous operation. It makes audits faster and cheaper, not unnecessary.
How does compliance as code relate to Infrastructure as Code?
Infrastructure as Code defines what your servers and networks should look like. Compliance as Code validates that those definitions—and the resulting deployments—meet regulatory and security requirements. IaC is the input; compliance checks are the guardrails.
What frameworks work best with compliance as code?
SOC 2, ISO 27001, CIS Benchmarks, and PCI DSS map well because their controls are specific and testable. GDPR and Nepal VAT rules work for application-level and business-logic checks. Physical and HR controls remain manual by nature.
Build Compliance Into Your Pipeline From Day One
Compliance as Code Explained is not a enterprise-only buzzword. It is how small teams stay audit-ready while shipping weekly on Laravel 13, WordPress 7.1, or custom platforms. Encode your highest-risk controls first. Wire them into CI. Store the evidence. Expand the matrix as your product and client requirements grow.
If you need help mapping controls to a concrete pipeline for a legal portal, eCommerce store, or SaaS product, review the Court Marriage In Nepal and Nepal Divorce Services portfolio entries for examples of compliance-sensitive workflows. For hands-on implementation, explore custom software development or reach out via contact us to discuss your control matrix and CI setup.
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.

