Hamburger Cross Icon
Compliance Documentation Guardrails - Lunar Policy for Operational Readiness

Compliance Documentation Guardrails

Policy Stable Operational Readiness

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.

Add 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.

Guardrail

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.

disaster recovery DR plan compliance documentation
View Guardrail
Guardrail

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.

RTO RPO recovery objectives SLA
View Guardrail
Guardrail

dr-plan-required-sections

Ensures the DR plan contains required section headings covering key recovery topics. Configurable via the plan_required_sections input.

DR plan required sections documentation structure
View Guardrail
Guardrail

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 tabletop game day compliance
View Guardrail
Guardrail

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.

DR exercise required sections documentation structure
View Guardrail

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
1
Integrations Gather Data
Collectors extract metadata from code, CI pipelines, tool outputs, and scans
2
{ } Centralized as JSON
All data merged into each component's unified metadata document
3
Guardrails Enforce Standards This Policy
Real-time feedback in PRs and AI workflows

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 GitHub

Compliance 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: 60 means restore within 1 hour.
  • RPO (Recovery Point Objective): Maximum acceptable data loss measured in time. Example: rpo_minutes: 15 means 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.

View Repository

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.

Works with any process
check Infrastructure conventions
check Post-mortem action items
check Security & compliance policies
check Testing & quality requirements
Automate Now
Turn any process doc into guardrails
Book a Demo