Compliance Documentation Guardrails
Verify that required compliance documentation exists, is kept current, and contains required sections. Covers disaster recovery plans and exercise records with support for additional compliance document types planned.
compliance-docs to your lunar-config.yml:uses: github://earthly/lunar-lib/policies/compliance-docs@v1.0.0
Included Guardrails
This policy includes 5 guardrails that enforce standards for your operational readiness.
dr-plan-exists
Verifies that a disaster recovery plan exists in the repository. Every production service should have documented recovery procedures to ensure teams can respond effectively during outages.
dr-plan-rto-rpo-defined
Requires that Recovery Time Objective (RTO) and Recovery Point Objective (RPO) are defined in the DR plan. These targets establish clear expectations for acceptable downtime and data loss during disasters.
dr-plan-required-sections
Ensures the DR plan contains required section headings covering key recovery topics. Configurable via the plan_required_sections input.
dr-exercise-recent
Ensures a DR exercise (tabletop, failover, or full) was conducted within the configured threshold (default: 365 days). Checks the most recent exercise record in the exercises directory.
dr-exercise-required-sections
Ensures the most recent DR exercise record contains required section headings documenting what was tested and the outcomes. Configurable via the exercise_required_sections input.
How Guardrails Fit into Lunar
Lunar guardrails define your engineering standards as code. They evaluate data collected by integrations and produce pass/fail checks with actionable feedback.
Policies support gradual enforcement—from silent scoring to blocking PRs or deployments—letting you roll out standards at your own pace without disrupting existing workflows.
Learn How Lunar Works →Required Integrations
This policy evaluates data gathered by one or more of the following integration(s).
Make sure to enable them in your lunar-config.yml.
Configuration
Configure this policy in your lunar-config.yml.
Inputs
| Input | Required | Default | Description |
|---|---|---|---|
max_days_since_exercise
|
Optional |
365
|
Maximum number of days allowed since the last DR exercise |
plan_required_sections
|
Optional |
Overview,Recovery Steps,Contact List
|
Comma-separated list of required sections in the DR plan |
exercise_required_sections
|
Optional |
Scenario,Recovery Steps Tested,Participants
|
Comma-separated list of required sections in the DR exercise record |
exercises_check_all
|
Optional |
false
|
Check required sections on all exercises (true) or only the latest (false) |
Documentation
View on GitHubCompliance Documentation Guardrails
Enforces that required compliance documentation exists, is kept current, and contains required sections.
Overview
This policy plugin verifies that services maintain required compliance documentation. It covers disaster recovery plans (recovery procedures, RTO/RPO) and a history of DR exercise records (tabletop exercises, failover tests). These policies support compliance frameworks (SOC 2, ISO 27001, NIST) that mandate documented and tested DR procedures.
Policies
This plugin provides the following policies (use include to select a subset):
| Policy | Description | Failure Meaning |
|---|---|---|
dr-plan-exists |
Ensures DR plan document exists in the repository | No DR plan found at expected path |
dr-plan-rto-rpo-defined |
Ensures RTO and RPO values are documented in the plan | Recovery objectives missing from plan frontmatter |
dr-plan-required-sections |
Ensures DR plan contains required sections | Plan is missing one or more required sections |
dr-exercise-recent |
Ensures a DR exercise was conducted within threshold | No exercises found or last exercise is too old |
dr-exercise-required-sections |
Ensures DR exercise records contain required sections (latest or all, via exercises_check_all) |
Exercise is missing one or more required sections |
Required Data
This policy reads from the following Component JSON paths:
| Path | Type | Provided By |
|---|---|---|
.oncall.disaster_recovery.plan.exists |
boolean | dr-docs collector |
.oncall.disaster_recovery.plan.rto_defined |
boolean | dr-docs collector |
.oncall.disaster_recovery.plan.rpo_defined |
boolean | dr-docs collector |
.oncall.disaster_recovery.plan.sections |
array | dr-docs collector |
.oncall.disaster_recovery.exercises[] |
array | dr-docs collector |
.oncall.disaster_recovery.latest_exercise_date |
string | dr-docs collector |
.oncall.disaster_recovery.exercise_count |
number | dr-docs collector |
Note: Ensure the corresponding collector is configured before enabling this policy.
Installation
Add to your lunar-config.yml:
policies:
- uses: github://earthly/lunar-lib/policies/compliance-docs@v1.0.0
on: ["domain:your-domain"] # Or use tags like [production, tier1]
enforcement: report-pr # Options: draft, score, report-pr, block-pr, block-release, block-pr-and-release
# include: [dr-plan-exists, dr-exercise-recent] # Only run specific checks
# with:
# max_days_since_exercise: "365"
# plan_required_sections: "Overview,Recovery Steps,Contact List"
# exercise_required_sections: "Scenario,Recovery Steps Tested,Participants"
# exercises_check_all: "false" # Check sections on all exercises (true) or latest only (false)
Examples
Passing Example
{
"oncall": {
"disaster_recovery": {
"plan": {
"exists": true,
"path": "docs/dr-plan.md",
"rto_defined": true,
"rto_minutes": 60,
"rpo_defined": true,
"rpo_minutes": 15,
"sections": ["Overview", "Recovery Steps", "Contact List", "Dependencies"]
},
"exercises": [
{
"date": "2025-11-15",
"path": "docs/dr-exercises/2025-11-15.md",
"exercise_type": "tabletop",
"sections": ["Scenario", "Recovery Steps Tested", "Participants", "Action Items"]
}
],
"latest_exercise_date": "2025-11-15",
"exercise_count": 1
}
}
}
This example passes all five policies with default configuration.
Failing Examples
DR plan missing (fails dr-plan-exists)
{
"oncall": {
"disaster_recovery": {
"plan": { "exists": false }
}
}
}
Failure message: "DR plan not found (expected docs/dr-plan.md)"
Recovery objectives missing (fails dr-plan-rto-rpo-defined)
{
"oncall": {
"disaster_recovery": {
"plan": {
"exists": true,
"path": "docs/dr-plan.md",
"rto_defined": false,
"rpo_defined": false,
"sections": ["Overview", "Recovery Steps", "Contact List"]
}
}
}
}
Failure message: "Recovery objectives not defined — add rto_minutes and rpo_minutes to DR plan frontmatter"
No exercises found (fails dr-exercise-recent)
{
"oncall": {
"disaster_recovery": {
"exercises": [],
"exercise_count": 0
}
}
}
Failure message: "No DR exercise records found — create docs/dr-exercises/YYYY-MM-DD.md"
Exercise overdue (fails dr-exercise-recent)
{
"oncall": {
"disaster_recovery": {
"exercises": [
{
"date": "2024-06-01",
"path": "docs/dr-exercises/2024-06-01.md",
"sections": ["Scenario", "Recovery Steps Tested", "Participants"]
}
],
"latest_exercise_date": "2024-06-01",
"exercise_count": 1
}
}
}
Failure message: "Last DR exercise was 622 days ago (maximum allowed: 365)"
Latest exercise missing sections (fails dr-exercise-required-sections)
{
"oncall": {
"disaster_recovery": {
"exercises": [
{
"date": "2025-11-15",
"path": "docs/dr-exercises/2025-11-15.md",
"sections": ["Scenario"]
}
],
"latest_exercise_date": "2025-11-15",
"exercise_count": 1
}
}
}
Failure message: "Latest DR exercise (2025-11-15) is missing required sections: Recovery Steps Tested, Participants"
Remediation
dr-plan-exists
Create a disaster recovery plan at docs/dr-plan.md (or your configured path):
---
rto_minutes: 60
rpo_minutes: 15
last_reviewed: 2025-12-01
approver: jane.doe@company.com
---
# Disaster Recovery Plan
## Overview
This document describes the DR procedures for this service...
## Recovery Steps
1. Verify the incident scope...
2. Initiate failover to secondary region...
## Contact List
- Primary on-call: ...
- Engineering manager: ...
## Dependencies
- PostgreSQL (RDS Multi-AZ)
- Redis (ElastiCache)
dr-plan-rto-rpo-defined
Add rto_minutes and rpo_minutes to the DR plan's YAML frontmatter:
- RTO (Recovery Time Objective): Maximum acceptable time from disaster to service restoration. Example:
rto_minutes: 60means restore within 1 hour. - RPO (Recovery Point Objective): Maximum acceptable data loss measured in time. Example:
rpo_minutes: 15means no more than 15 minutes of data loss.
dr-plan-required-sections
Add the missing section headings to the DR plan. Default required sections are Overview, Recovery Steps, and Contact List (configurable via plan_required_sections). Section matching is case-insensitive.
dr-exercise-recent
Create a DR exercise record in docs/dr-exercises/ named with the exercise date:
docs/dr-exercises/2025-11-15.md
---
exercise_type: tabletop
---
# DR Exercise
## Scenario
Simulated complete loss of the primary database in us-east-1...
## Recovery Steps Tested
1. Detected outage via PagerDuty alert on error rate spike
2. Confirmed primary DB was unreachable
3. Initiated manual failover to read replica...
## Participants
- Jane Doe (Engineering Manager)
- Bob Smith (Senior SRE)
## Action Items
- [ ] Automate failover detection with custom health check
- [ ] Schedule follow-up failover exercise for Q2
## Lessons Learned
- Manual failover took 45 minutes vs. 60-minute RTO — within target
- PagerDuty alert fired within 2 minutes — alerting is solid
Exercise types: tabletop (team discussion walkthrough), failover (test actual failover), full (complete end-to-end recovery).
dr-exercise-required-sections
Add the missing section headings to the latest exercise record. Default required sections are Scenario, Recovery Steps Tested, and Participants (configurable via exercise_required_sections). Section matching is case-insensitive.
Open Source
This policy is open source and available on GitHub. Contribute improvements, report issues, or fork it for your own use.
Common Use Cases
Explore how individual guardrails work with specific integrations.
Ready to Automate Your Standards?
See how Lunar can turn your engineering wiki, compliance docs, or postmortem action items into automated guardrails with our 100+ built-in guardrails.