home / skills / yousufjoyian / claude-skills / defense-in-depth

defense-in-depth skill

/debugging/defense-in-depth

This skill enforces defense-in-depth by validating data at entry, business, environment, and debug layers to make bugs structurally impossible.

This is most likely a fork of the defense-in-depth skill from mamba-mental
npx playbooks add skill yousufjoyian/claude-skills --skill defense-in-depth

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

Files (1)
SKILL.md
3.8 KB
---
name: defense-in-depth
description: Validate at every layer data passes through to make bugs impossible
---

# 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 1: Entry Point Validation
**Purpose:** Reject obviously invalid input at API boundary

```typescript
function createProject(name: string, workingDirectory: string) {
  if (!workingDirectory || workingDirectory.trim() === '') {
    throw new Error('workingDirectory cannot be empty');
  }
  if (!existsSync(workingDirectory)) {
    throw new Error(`workingDirectory does not exist: ${workingDirectory}`);
  }
  if (!statSync(workingDirectory).isDirectory()) {
    throw new Error(`workingDirectory is not a directory: ${workingDirectory}`);
  }
  // ... proceed
}
```

### Layer 2: Business Logic Validation
**Purpose:** Ensure data makes sense for this operation

```typescript
function initializeWorkspace(projectDir: string, sessionId: string) {
  if (!projectDir) {
    throw new Error('projectDir required for workspace initialization');
  }
  // ... proceed
}
```

### Layer 3: Environment Guards
**Purpose:** Prevent dangerous operations in specific contexts

```typescript
async function gitInit(directory: string) {
  // In tests, refuse git init outside temp directories
  if (process.env.NODE_ENV === 'test') {
    const normalized = normalize(resolve(directory));
    const tmpDir = normalize(resolve(tmpdir()));

    if (!normalized.startsWith(tmpDir)) {
      throw new Error(
        `Refusing git init outside temp dir during tests: ${directory}`
      );
    }
  }
  // ... proceed
}
```

### Layer 4: Debug Instrumentation
**Purpose:** Capture context for forensics

```typescript
async function gitInit(directory: string) {
  const stack = new Error().stack;
  logger.debug('About to git init', {
    directory,
    cwd: process.cwd(),
    stack,
  });
  // ... proceed
}
```

## Applying the Pattern

When you find a bug:

1. **Trace the data flow** - Where does bad value originate? Where used?
2. **Map all checkpoints** - List every point data passes through
3. **Add validation at each layer** - Entry, business, environment, debug
4. **Test each layer** - Try to bypass layer 1, verify layer 2 catches it

## Example from Session

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

**Data flow:**
1. Test setup → empty string
2. `Project.create(name, '')`
3. `WorkspaceManager.createWorkspace('')`
4. `git init` runs in `process.cwd()`

**Four layers added:**
- Layer 1: `Project.create()` validates not empty/exists/writable
- Layer 2: `WorkspaceManager` validates projectDir not empty
- Layer 3: `WorktreeManager` refuses git init outside tmpdir in tests
- Layer 4: Stack trace logging before git init

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

## Key Insight

All four layers were necessary. During testing, each layer caught bugs the others missed:
- Different code paths bypassed entry validation
- Mocks bypassed business logic checks
- Edge cases on different platforms needed environment guards
- Debug logging identified structural misuse

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

Overview

This skill enforces defense-in-depth validation across all layers that data passes through, making bugs from invalid input structurally impossible. It codifies four complementary checkpoints—entry validation, business logic checks, environment guards, and debug instrumentation—so failures are caught even when one layer is bypassed. The goal is resilient code and faster, deterministic debugging.

How this skill works

The skill inspects code paths and suggests where to add validation at each layer: API/entry points, business logic, environment-specific guards, and debug logging. It provides concrete validation patterns and enforcement rules, plus steps to trace data flow and test that each layer stops invalid values. It flags missing checks, risky assumptions, and contexts (like tests) where extra guards are required.

When to use it

  • When a bug was caused by invalid or missing input
  • When refactoring may create new code paths that bypass checks
  • When tests or mocks can inject unexpected values
  • Before performing environment-sensitive operations (filesystem, network, git)
  • When you need reproducible, forensic data for failures

Best practices

  • Validate at the API boundary: reject obviously invalid input early
  • Duplicate key checks in business logic to enforce operation-specific invariants
  • Add environment guards to refuse dangerous operations in tests or untrusted contexts
  • Log contextual debug info (inputs, cwd, stack) before risky operations for forensics
  • Treat validation as layered insurance, not a single responsibility

Example use cases

  • API endpoint ensuring request fields are present and correctly typed, plus service-layer guards
  • Workspace creation validating directory exists, business logic re-checking non-empty paths, and git-init refusing ops outside temp dirs during tests
  • Preventing destructive filesystem operations by environment-aware guards and pre-op debug logs
  • Adding validation after a bug to make the failure impossible across unit, integration, and CI tests

FAQ

What if redundant checks feel repetitive?

Redundancy is intentional: different layers protect against different bypasses (refactors, mocks, env differences). Keep checks focused and minimal at each layer to avoid noise.

How do I test that layers actually work?

Trace the data flow, write tests that intentionally bypass layer 1 (mocks, direct calls) and verify layer 2 or 3 rejects invalid input; include CI tests that simulate environment contexts like NODE_ENV=test.