home / skills / lerianstudio / ring / defense-in-depth

defense-in-depth skill

/default/skills/defense-in-depth

This skill enforces defense-in-depth validation across every data layer to prevent bugs by validating at entry, business logic, environment, and debugging

npx playbooks add skill lerianstudio/ring --skill defense-in-depth

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
2.7 KB
---
name: ring:defense-in-depth
description: |
  Multi-layer validation pattern - validates data at EVERY layer it passes through
  to make bugs structurally impossible, not just caught.

trigger: |
  - Bug caused by invalid data reaching deep layers
  - Single validation point can be bypassed
  - Need to prevent bug category, not just instance

skip_when: |
  - Validation already exists at all layers → check other issues
  - Simple input validation sufficient → add single check

related:
  complementary: [root-cause-tracing]
---

# Defense-in-Depth Validation

## Overview

When you fix a bug caused by invalid data, adding validation at one place feels sufficient. But that single check can be bypassed by different code paths, refactoring, or mocks.

**Core principle:** Validate at EVERY layer data passes through. Make the bug structurally impossible.

## Why Multiple Layers

Single validation: "We fixed the bug"
Multiple layers: "We made the bug impossible"

Different layers catch different cases:
- Entry validation catches most bugs
- Business logic catches edge cases
- Environment guards prevent context-specific dangers
- Debug logging helps when other layers fail

## The Four Layers

| Layer | Purpose | Example |
|-------|---------|---------|
| **1. Entry Point** | Reject invalid input at API boundary | `if (!workingDir \|\| !existsSync(workingDir)) throw new Error(...)` |
| **2. Business Logic** | Ensure data makes sense for operation | `if (!projectDir) throw new Error('projectDir required')` |
| **3. Environment Guards** | Prevent dangerous ops in contexts | `if (NODE_ENV === 'test' && !path.startsWith(tmpdir())) throw...` |
| **4. Debug Instrumentation** | Capture context for forensics | `logger.debug('About to git init', { directory, cwd, stack })` |

## Applying the Pattern

**Steps:** (1) Trace data flow (origin → error) (2) Map all checkpoints (3) Add validation at each layer (4) Test each layer (try to bypass layer 1, verify layer 2 catches it)

## Example

**Bug:** Empty `projectDir` caused `git init` in source code

**Flow:** Test setup (`''`) → `Project.create(name, '')` → `WorkspaceManager.createWorkspace('')` → `git init` in `process.cwd()`

**Layers added:** L1: `Project.create()` validates not empty/exists/writable | L2: `WorkspaceManager` validates not empty | L3: Refuse git init outside tmpdir in tests | L4: Stack trace logging

**Result:** 1847 tests passed, bug impossible to reproduce

## Key Insight

All four layers necessary - each caught bugs others missed: different code paths bypassed entry validation | mocks bypassed business logic | edge cases needed environment guards | debug logging identified structural misuse.

**Don't stop at one validation point.** Add checks at every layer.

Overview

This skill enforces a defense-in-depth validation pattern across a workflow system so data is validated at every layer it traverses. It makes bugs structurally impossible by adding complementary checks at entry points, business logic, environment guards, and debug instrumentation. The result is fewer flaky failures and stronger guarantees in CI and agent workflows.

How this skill works

The skill instruments code paths to trace where data originates and which components touch it, then inserts validation checks at four layers: API/entry validation, business-logic assertions, environment/context guards, and debug logging. It runs tests that attempt to bypass earlier layers to ensure later layers reliably catch invalid states. The pattern is language-agnostic but implemented for Go workflows and CI gates in the system.

When to use it

  • On any public API or agent input boundary
  • When a bug is caused by unexpected or malformed data
  • Before enabling operations with side effects (file system, network, subprocesses)
  • In test environments to prevent dangerous leaks or accidental writes
  • When increasing system robustness for CI, deployments, or multi-component flows

Best practices

  • Trace the full data flow from origin to sink before adding checks
  • Add fast-failing validations at entry points to reduce wasted work
  • Place domain-specific assertions inside business logic for contextual guarantees
  • Add environment guards to prevent operations outside safe contexts (tests, CI, prod)
  • Log contextual debug information and stack traces for forensic replay and root cause analysis

Example use cases

  • Prevent git init or file writes when a workspace path is empty or outside a temp dir
  • Reject malformed agent prompts at the API boundary and re-validate before execution
  • Add CI gates that refuse destructive operations unless environment and path checks pass
  • Instrument workflows with debug payloads to reproduce how invalid data bypassed an earlier layer
  • Harden third-party integrations by validating input at entry and immediately before API calls

FAQ

Why validate more than once?

Different code paths, mocks, or refactors can bypass a single check. Multiple layers ensure at least one will catch invalid data.

Won't this slow the system?

Place inexpensive checks at entry points and reserve slightly heavier validations for later layers. The small cost prevents costly failures and is outweighed by reliability gains.

How do I test that layers work?

Intentionally bypass layer 1 in tests and verify layer 2 or 3 catches the invalid state; include tests for environment guards and capture debug logs for failures.