/defense-in-depth
Use when invalid data causes failures deep in execution - validates at every layer data passes through to make bugs structurally impossible rather than temporarily fixed
$ npx -y skills add ed3dai/ed3d-plugins --skill defense-in-depth --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/defense-in-depth
Context preview
The summary Claude sees to decide when to auto-load this skill.
Use when invalid data causes failures deep in execution - validates at every layer data passes through to make bugs structurally impossible rather than temporarily fixed
SKILL.md
defense-in-depth.SKILL.mdname: defense-in-depth
description: Use when invalid data causes failures deep in execution - validates at every layer data passes through to make bugs structurally impossible rather than temporarily fixed
user-invocable: false
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.
When to Use
**Use when:**
- Invalid data caused a bug deep in the call stack
- Data crosses system boundaries (API → service → storage)
- Multiple code paths can reach the same vulnerable code
- Tests mock intermediate layers (bypassing validation)
**Don't use when:**
- Pure internal function with single caller (validate at caller)
- Data already validated by framework/library you trust
- Adding validation would duplicate identical checks at adjacent layers
The Four Layers
Layer 1: Entry Point Validation
**Purpose:** Reject invalid input at API/system boundary
function createProject(name: string, workingDirectory: string) {
if (!workingDirectory?.trim()) {
throw new Error('workingDirectory cannot be empty');
}
if (!existsSync(workingDirectory)) {
throw new Error(`workingDirectory does not exist: ${workingDirectory}`);
}
// ... proceed
}**When needed:** Always. This is your first line of defense.
Layer 2: Business Logic Validation
**Purpose:** Ensure data makes sense for this specific operation
function initializeWorkspace(projectDir: string, sessionId: string) {
if (!projectDir) {
throw new Error('projectDir required for workspace initialization');
}
// ... proceed
}**When needed:** When business rules differ from entry validation, or when mocks might bypass Layer 1.
Layer 3: Environment Guards
**Purpose:** Prevent dangerous operations in specific contexts
async function gitInit(directory: string) {
if (process.env.NODE_ENV === 'test') {
const normalized = normalize(resolve(directory));
if (!normalized.startsWith(tmpdir())) {
throw new Error(`Refusing git init outside temp dir in tests: ${directory}`);
}
}
// ... proceed
}**When needed:** When operation is destructive/irreversible, especially in test environments.
Layer 4: Debug Instrumentation
**Purpose:** Capture context for forensics when other layers fail
async function gitInit(directory: string) {
logger.debug('git init', { directory, cwd: process.cwd(), stack: new Error().stack });
// ... proceed
}**When needed:** When debugging is difficult, or when you need to trace how bad data arrived.
Decision Heuristic
| Situation | Layers Needed | |-----------|---------------| | Public API, simple validation | 1 only | | Data crosses multiple services | 1 + 2 | | Destructive operations (delete, init, write) | 1 + 2 + 3 | | Chasing a hard-to-reproduce bug | 1 + 2 + 3 + 4 | | Tests mock intermediate layers | At minimum: 1 + 3 |
Applying the Pattern
When you find a bug caused by invalid data:
1. **Trace the data flow** - Where does the bad value originate? Where is it used? 2. **Map checkpoints** - List every function/layer the data passes through 3. **Decide which layers** - Use heuristic above 4. **Add validation** - Entry → business → environment → debug 5. **Test each layer** - Verify Layer 2 catches what bypasses Layer 1
Quick Reference
| Layer | Question It Answers | Typical Check | |-------|---------------------|---------------| | Entry | Is input valid? | Non-empty, exists, correct type | | Business | Does it make sense here? | Required for this operation, within bounds | | Environment | Is this safe in this context? | Not in prod, inside temp dir, etc. | | Debug | How did we get here? | Log stack, cwd, inputs |
Common Mistakes
| Mistake | Fix | |---------|-----| | One validation point, call it done | Add at least entry + business layers | | Identical checks at adjacent layers | Make each layer check something different | | Environment guards only in prod | Add them in test too (prevent test pollution) | | Skipping debug logging | Add it during the bug hunt, keep it | | Validation but no useful error message | Include the bad value and expected format |
Key Insight
During testing, each layer catches bugs the others miss:
- Different code paths bypass entry validation
- Mocks bypass business logic checks
- Edge cases need environment guards
- Debug logging identifies structural misuse
**Don't stop at one validation point.** The bug isn't fixed until it's impossible.
Read more
name: defense-in-depth description: Use when invalid data causes failures deep in execution - validates at every layer data passes through to make bugs structurally impossible rather than temporarily fixed user-invocable: false
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.
When to Use
**Use when:**
- Invalid data caused a bug deep in the call stack
- Data crosses system boundaries (API → service → storage)
- Multiple code paths can reach the same vulnerable code
- Tests mock intermediate layers (bypassing validation)
**Don't use when:**
- Pure internal function with single caller (validate at caller)
- Data already validated by framework/library you trust
- Adding validation would duplicate identical checks at adjacent layers
The Four Layers
Layer 1: Entry Point Validation
**Purpose:** Reject invalid input at API/system boundary
function createProject(name: string, workingDirectory: string) {
if (!workingDirectory?.trim()) {
throw new Error('workingDirectory cannot be empty');
}
if (!existsSync(workingDirectory)) {
throw new Error(`workingDirectory does not exist: ${workingDirectory}`);
}
// ... proceed
}**When needed:** Always. This is your first line of defense.
Layer 2: Business Logic Validation
**Purpose:** Ensure data makes sense for this specific operation
function initializeWorkspace(projectDir: string, sessionId: string) {
if (!projectDir) {
throw new Error('projectDir required for workspace initialization');
}
// ... proceed
}**When needed:** When business rules differ from entry validation, or when mocks might bypass Layer 1.
Layer 3: Environment Guards
**Purpose:** Prevent dangerous operations in specific contexts
async function gitInit(directory: string) {
if (process.env.NODE_ENV === 'test') {
const normalized = normalize(resolve(directory));
if (!normalized.startsWith(tmpdir())) {
throw new Error(`Refusing git init outside temp dir in tests: ${directory}`);
}
}
// ... proceed
}**When needed:** When operation is destructive/irreversible, especially in test environments.
Layer 4: Debug Instrumentation
**Purpose:** Capture context for forensics when other layers fail
async function gitInit(directory: string) {
logger.debug('git init', { directory, cwd: process.cwd(), stack: new Error().stack });
// ... proceed
}**When needed:** When debugging is difficult, or when you need to trace how bad data arrived.
Decision Heuristic
| Situation | Layers Needed | |-----------|---------------| | Public API, simple validation | 1 only | | Data crosses multiple services | 1 + 2 | | Destructive operations (delete, init, write) | 1 + 2 + 3 | | Chasing a hard-to-reproduce bug | 1 + 2 + 3 + 4 | | Tests mock intermediate layers | At minimum: 1 + 3 |
Applying the Pattern
When you find a bug caused by invalid data:
1. **Trace the data flow** - Where does the bad value originate? Where is it used? 2. **Map checkpoints** - List every function/layer the data passes through 3. **Decide which layers** - Use heuristic above 4. **Add validation** - Entry → business → environment → debug 5. **Test each layer** - Verify Layer 2 catches what bypasses Layer 1
Quick Reference
| Layer | Question It Answers | Typical Check | |-------|---------------------|---------------| | Entry | Is input valid? | Non-empty, exists, correct type | | Business | Does it make sense here? | Required for this operation, within bounds | | Environment | Is this safe in this context? | Not in prod, inside temp dir, etc. | | Debug | How did we get here? | Log stack, cwd, inputs |
Common Mistakes
| Mistake | Fix | |---------|-----| | One validation point, call it done | Add at least entry + business layers | | Identical checks at adjacent layers | Make each layer check something different | | Environment guards only in prod | Add them in test too (prevent test pollution) | | Skipping debug logging | Add it during the bug hunt, keep it | | Validation but no useful error message | Include the bad value and expected format |
Key Insight
During testing, each layer catches bugs the others miss:
- Different code paths bypass entry validation
- Mocks bypass business logic checks
- Edge cases need environment guards
- Debug logging identifies structural misuse
**Don't stop at one validation point.** The bug isn't fixed until it's impossible.
This is my collection of plugins that I use on a day-to-day basis for getting stuff done with Claude Code. Most of these are development-oriented in some way or another, but also often end up being useful for other things.
Repo: ed3dai/ed3d-plugins
Other skills on ed3d-plugins.
- /doing-a-simple-two-stage-fanout
Use when analyzing a large corpus of text, code, or data that exceeds a single agent's effective context - orchestrates parallel Worker subagents, Critic review subagents, and a final Summarizer subagent with task tracking and failure recovery
Open skill - /using-generic-agents
Use to decide what kind of generic agent you should use
Open skill - /creating-a-plugin
Use when creating a new Claude Code plugin or setting up plugin structure - provides complete file organization, manifest format, and component definitions for commands, agents, skills, hooks, and MCP servers
Open skill - /creating-an-agent
Use when creating specialized subagents for Claude Code plugins or the Task tool - covers description writing for auto-delegation, tool selection, prompt structure, and testing agents
Open skill - /maintaining-a-marketplace
Use when creating, releasing, or maintaining a Claude Code Plugin Marketplace - covers marketplace.json schema, version management, release checklists, changelog conventions, and validation to prevent sync drift between plugin.json and marketplace.json
Open skill - /maintaining-project-context
Use when completing development phases or branches to identify and update CLAUDE.md or AGENTS.md files that may have become stale - analyzes what changed, determines affected contracts and documentation, and coordinates updates
Open skill

