plugins/codebase-audit-suite/skills/ln-642-layer-ownership-boundary-auditor/SKILL.md
Checks layer, resource ownership, and orchestration boundaries. Use when auditing architecture boundary enforcement.
npx skillsauth add levnikolaevich/claude-code-skills ln-642-layer-ownership-boundary-auditorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Paths: File paths (
references/,../ln-*) are relative to this skill directory.
Type: L3 Worker
L3 Worker that audits architectural layer boundaries and detects violations.
Out of Scope:
- architecture_path: string # Path to docs/architecture.md
- codebase_root: string # Root directory to scan
- skip_violations: string[] # Files to skip (legacy)
- output_dir: string # e.g., ".hex-skills/runtime-artifacts/runs/{run_id}/audit-report"
# Domain-aware (optional)
- domain_mode: "global" | "domain-aware" # Default: "global"
- current_domain: string # e.g., "users", "billing" (only if domain-aware)
- scan_path: string # e.g., "src/users/" (only if domain-aware)
When domain_mode="domain-aware": Use scan_path instead of codebase_root for all Grep/Glob operations. Tag all findings with domain field.
Detection policy: use two-layer detection (candidate scan, then context verification); load references/two_layer_detection.md only when the verification method is ambiguous.
Tool policy: follow host AGENTS.md MCP preferences; load references/mcp_tool_preferences.md and references/mcp_integration_patterns.md only when host policy is absent or MCP behavior is unclear.
Use hex-graph first when references, call paths, or architecture coupling materially improve the audit. Use hex-line first for local code and config reads when available. If MCP is unavailable, unsupported, or not indexed, continue with built-in Read/Grep/Glob/Bash and state the fallback in the report.
MANDATORY READ: Load references/layer_rules.md -- use Architecture Presets (fallback), I/O Pattern Boundary Rules (Phase 2), Coverage Checks (Phase 4), Cross-Layer Consistency rules (Phase 3).
Read docs/architecture.md
Extract from Section 4.2 (Top-Level Decomposition):
- architecture_type: "Layered" | "Hexagonal" | "Clean" | "MVC" | etc.
- layers: [{name, directories[], purpose}]
Extract from Section 5.3 (Infrastructure Layer Components):
- infrastructure_components: [{name, responsibility}]
IF architecture.md not found:
Use fallback presets from layer_rules.md
Build ruleset:
FOR EACH layer:
allowed_deps = layers that can be imported
forbidden_deps = layers that cannot be imported
Graph acceleration (if available): IF contextStore.graph_indexed OR .hex-skills/codegraph/index.db exists:
analyze_architecture(path=scan_root, verbosity="full") -- use returned coupling metrics to identify tightly-coupled layers.find_references(symbol) for transaction/session functions -- trace commit/rollback ownership across layers.trace_paths(name="ServiceFn", file="...", path_kind="calls", direction="forward", depth=3, path=scan_root) -- measure chain depth for flat orchestration check from a concrete service symbol.trace_paths from a coarse or module-level selector is not enough to clear a layer; fall back to inspect_symbol or grep/manual review when the selector is broad.scan_root = scan_path IF domain_mode == "domain-aware" ELSE codebase_root
FOR EACH violation_type IN layer_rules.md I/O Pattern Boundary Rules:
grep_pattern = violation_type.detection_grep
forbidden_dirs = violation_type.forbidden_in
matches = Grep(grep_pattern, scan_root, include="*.py,*.ts,*.js")
FOR EACH match IN matches:
IF match.path NOT IN skip_violations:
IF any(forbidden IN match.path FOR forbidden IN forbidden_dirs):
violations.append({
type: "layer_violation",
severity: "HIGH",
pattern: violation_type.name,
file: match.path,
line: match.line,
code: match.context,
allowed_in: violation_type.allowed_in,
suggestion: f"Move to {violation_type.allowed_in}"
})
What: commit()/rollback() called at inconsistent layers (repo + service + API)
Detection:
repo_commits = Grep("\.commit\(\)|\.rollback\(\)", "**/repositories/**/*.py")
service_commits = Grep("\.commit\(\)|\.rollback\(\)", "**/services/**/*.py")
api_commits = Grep("\.commit\(\)|\.rollback\(\)", "**/api/**/*.py")
layers_with_commits = count([repo_commits, service_commits, api_commits].filter(len > 0))
Safe Patterns (ignore):
_callbacks.py (progress notifiers)# UoW boundary commentViolation Rules:
| Condition | Severity | Issue | |-----------|----------|-------| | layers_with_commits >= 3 | CRITICAL | Mixed UoW ownership across all layers | | repo + api commits | HIGH | Transaction control bypasses service layer | | repo + service commits | HIGH | Ambiguous UoW owner (repo vs service) | | service + api commits | MEDIUM | Transaction control spans service + API |
Exception: Saga pattern / distributed transactions with explicit compensating actions -> downgrade CRITICAL to MEDIUM. UoW boundary documented with // architecture decision or ADR -> skip.
Recommendation: Choose single UoW owner (service layer recommended), remove commit() from other layers
Effort: L (requires architectural decision + refactoring)
What: Mixed DI-injected and locally-created sessions in same call chain
Detection:
di_session = Grep("Depends\(get_session\)|Depends\(get_db\)", "**/api/**/*.py")
local_session = Grep("AsyncSessionLocal\(\)|async_sessionmaker", "**/services/**/*.py")
local_in_repo = Grep("AsyncSessionLocal\(\)", "**/repositories/**/*.py")
Violation Rules:
| Condition | Severity | Issue | |-----------|----------|-------| | di_session AND local_in_repo in same module | HIGH | Repo creates own session while API injects different | | local_session in service calling DI-based repo | MEDIUM | Session mismatch in call chain |
Recommendation: Use DI consistently OR use local sessions consistently. Document exceptions (e.g., telemetry)
Effort: M
What: Service-layer functions calling other services that call yet other services -- deep orchestration chains.
Detection: MANDATORY READ: Load references/ai_ready_architecture.md -- map service imports, find chain depth.
Violation Rules:
| Condition | Severity | Issue | |-----------|----------|-------| | Service chain >= 3 (A->B->C->D) | HIGH | Deep orchestration | | Service chain = 2 (A->B->C) | MEDIUM | Consider flattening |
Recommendation: Extract orchestrator calling all services at same level. Each service becomes a sink.
Effort: L
# HTTP Client Coverage
all_http_calls = Grep("httpx\\.|aiohttp\\.|requests\\.", codebase_root)
abstracted_calls = Grep("client\\.(get|post|put|delete)", infrastructure_dirs)
IF len(all_http_calls) > 0:
coverage = len(abstracted_calls) / len(all_http_calls) * 100
IF coverage < 90%:
violations.append({
type: "low_coverage",
severity: "MEDIUM",
pattern: "HTTP Client Abstraction",
coverage: coverage,
uncovered_files: files with direct calls outside infrastructure
})
# Error Handling Duplication
http_error_handlers = Grep("except\\s+(httpx\\.|aiohttp\\.|requests\\.)", codebase_root)
unique_files = set(f.path for f in http_error_handlers)
IF len(unique_files) > 2:
violations.append({
type: "duplication",
severity: "MEDIUM",
pattern: "HTTP Error Handling",
files: list(unique_files),
suggestion: "Centralize in infrastructure layer"
})
MANDATORY READ: Load references/audit_worker_core_contract.md and references/audit_scoring.md.
MANDATORY READ: Load references/templates/audit_worker_report_template.md.
Write JSON summary per references/audit_summary_contract.md. In managed mode the caller passes both runId and summaryArtifactPath; in standalone mode the worker generates its own run-scoped artifact path per shared contract.
# Build markdown report in memory with:
# - AUDIT-META (standard penalty-based: score, counts)
# - Checks table (io_isolation, http_abstraction, error_centralization, transaction_boundary, session_ownership)
# - Findings table (violations sorted by severity)
# - DATA-EXTENDED: {architecture, coverage}
IF domain_mode == "domain-aware":
Write to {output_dir}/642-layer-boundary-{current_domain}.md
ELSE:
Write to {output_dir}/642-layer-boundary.md
Report written: .hex-skills/runtime-artifacts/runs/{run_id}/audit-report/642-layer-boundary-users.md
Score: 4.5/10 | Issues: 8 (C:1 H:3 M:4 L:0)
Apply the already-loaded references/audit_worker_core_contract.md.
MOVE_BOUNDARY, CHOOSE_OWNER, or FLATTEN_ORCHESTRATION.Apply the already-loaded references/audit_worker_core_contract.md.
{output_dir}/642-layer-boundary[-{domain}].md (atomic single Write call)references/layer_rules.mdreferences/audit_scoring.mdVersion: 2.1.0 Last Updated: 2026-02-08
testing
Audits architecture config boundaries: typed settings, scattered env reads, config leakage, and layer ownership. Use for config architecture.
tools
Finds architecture-level modernization opportunities: obsolete custom mechanisms, overbuilt extension points, and simplifiable architecture. Use when auditing architecture evolution.
development
Builds dependency topology, detects cycles, validates import rules, and calculates coupling metrics. Use when auditing architecture topology.
testing
Audits whether one implemented architectural pattern fits project needs and best practices. Use when checking pattern fitness.