skills/yonatangross/orchestkit/backend-architecture-enforcer

backend-architecture-enforcer

Installation
SKILL.md
Contains Hooks

This skill uses Claude hooks which can execute code automatically in response to events. Review carefully before installing.

Enforce FastAPI Clean Architecture with BLOCKING validation.

Architecture Overview

+-------------------------------------------------------------------+
|                        ROUTERS LAYER                               |
|  HTTP concerns only: request parsing, response formatting          |
|  Files: router_*.py, routes_*.py, api_*.py                        |
+-------------------------------------------------------------------+
|                        SERVICES LAYER                              |
|  Business logic: orchestration, validation, transformations        |
|  Files: *_service.py                                              |
+-------------------------------------------------------------------+
|                      REPOSITORIES LAYER                            |
|  Data access: database queries, external API calls                 |
|  Files: *_repository.py, *_repo.py                                |
+-------------------------------------------------------------------+
|                        MODELS LAYER                                |
|  Data structures: SQLAlchemy models, Pydantic schemas             |
|  Files: *_model.py (ORM), *_schema.py (Pydantic)                 |
+-------------------------------------------------------------------+

Validation Rules (BLOCKING)

Rule Check Layer
No DB in Routers Database operations blocked routers/
No HTTP in Services HTTPException blocked services/
No Business Logic in Routers Complex logic blocked routers/
Use Depends() Direct instantiation blocked routers/
Async Consistency Sync calls in async blocked all
File Naming Must follow naming convention all

File Naming Conventions

Quick Reference

Layer Allowed Patterns Blocked Patterns
Routers router_*.py, routes_*.py, api_*.py, deps.py users.py, UserRouter.py
Services *_service.py users.py, UserService.py, service_*.py
Repositories *_repository.py, *_repo.py users.py, repository_*.py
Schemas *_schema.py, *_dto.py, *_request.py, *_response.py users.py, UserSchema.py
Models *_model.py, *_entity.py, *_orm.py, base.py users.py, UserModel.py

Layer Separation Summary

Routers (HTTP Only)

  • Request parsing and response formatting
  • HTTP status codes and auth checks
  • Delegate to services via Depends()

Services (Business Logic)

  • Validation and orchestration
  • Data transformations
  • Raise domain exceptions (NOT HTTPException)

Repositories (Data Access)

  • Database queries and persistence
  • External API calls
  • Return domain objects or None

Dependency Injection Quick Reference

# deps.py - Dependency providers
def get_user_repository(
    db: AsyncSession = Depends(get_db),
) -> UserRepository:
    return UserRepository(db)

def get_user_service(
    repo: UserRepository = Depends(get_user_repository),
) -> UserService:
    return UserService(repo)

# router_users.py - Usage
@router.get("/{user_id}")
async def get_user(
    user_id: int,
    service: UserService = Depends(get_user_service),
):
    return await service.get_user(user_id)

Blocked DI Patterns

# BLOCKED - Direct instantiation
service = UserService()

# BLOCKED - Global instance
user_service = UserService()

# BLOCKED - Missing Depends()
async def get_users(db: AsyncSession):  # Missing Depends()

Common Violations

Violation Detection Fix
DB in router db.add, db.execute in routers/ Move to repository
HTTPException in service raise HTTPException in services/ Use domain exceptions
Direct instantiation Service() without Depends Use Depends(get_service)
Wrong naming Missing suffix/prefix Rename per convention
Sync in async Missing await Add await or use executor

Exception Pattern

# Domain exceptions (services/repositories)
class UserNotFoundError(DomainException):
    def __init__(self, user_id: int):
        super().__init__(f"User {user_id} not found")

# Router converts to HTTP
@router.get("/{user_id}")
async def get_user(user_id: int, service: UserService = Depends(get_user_service)):
    try:
        return await service.get_user(user_id)
    except UserNotFoundError:
        raise HTTPException(404, "User not found")

Async Rules

# GOOD - Async all the way
result = await db.execute(select(User))

# BLOCKED - Sync in async function
result = db.execute(select(User))  # Missing await

# For sync code, use executor
await loop.run_in_executor(None, sync_function)

References

For detailed patterns and examples, see:

Reference Content
layer-rules.md Detailed layer separation rules with code examples
dependency-injection.md DI patterns, authentication, testing with overrides
violation-examples.md Common violations with proper patterns and auto-fix suggestions

Related Skills

  • clean-architecture - DDD patterns
  • fastapi-advanced - Advanced FastAPI patterns
  • dependency-injection - DI patterns
  • project-structure-enforcer - Folder structure

Capability Details

layer-separation

Keywords: router, service, repository, layer, clean architecture, separation Solves:

  • Prevent database operations in routers
  • Block business logic in route handlers
  • Ensure proper layer boundaries

dependency-injection

Keywords: depends, dependency injection, DI, fastapi depends, inject Solves:

  • Enforce use of FastAPI Depends() pattern
  • Block direct instantiation in routers
  • Ensure testable code structure

file-naming

Keywords: naming convention, file name, router_, _service, _repository Solves:

  • Enforce consistent file naming patterns
  • Validate router/service/repository naming
  • Maintain codebase consistency

async-patterns

Keywords: async, await, sync, blocking call, asyncio Solves:

  • Detect sync calls in async functions
  • Prevent blocking operations in async code
  • Ensure async consistency
Weekly Installs
13
GitHub Stars
150
First Seen
Jan 22, 2026
Installed on
claude-code10
gemini-cli8
antigravity8
windsurf7
opencode7
codex6