refactor(arch): clarify transaction control pattern (API-002, SVC-006)

API-002 updated:
- Remove db.commit() from anti-patterns (allowed at endpoint level)
- Add db.delete() to anti-patterns (business logic)
- Clarify that transaction control != business logic

SVC-006 added (new rule):
- Services should NOT call db.commit()
- Transaction control belongs at endpoint level
- Exception: log_service.py for audit log commits
- Severity: warning (to allow gradual migration)

This aligns with industry standard:
- One request = one transaction
- Services do work, endpoints control commits
- Enables composing multiple service calls in single transaction

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-12-03 21:54:23 +01:00
parent a33cf1e95d
commit fde55d8c2b
2 changed files with 73 additions and 4 deletions

View File

@@ -58,12 +58,21 @@ api_endpoint_rules:
description: |
API endpoints should only handle HTTP concerns (validation, auth, response formatting).
All business logic must be delegated to service layer.
Transaction control (db.commit) IS allowed at endpoint level - this is the recommended
pattern for request-scoped transactions. One request = one transaction.
What's NOT allowed:
- db.add() - creating entities is business logic
- db.query() - complex queries are business logic
- db.delete() - deleting entities is business logic
pattern:
file_pattern: "app/api/v1/**/*.py"
anti_patterns:
- "db.add("
- "db.commit()"
- "db.delete("
- "db.query("
# NOTE: db.commit() is intentionally NOT listed - it's allowed for transaction control
- id: "API-003"
name: "Endpoint must NOT raise HTTPException directly"
@@ -166,6 +175,26 @@ service_layer_rules:
file_pattern: "app/services/**/*.py"
check: "vendor_scoping"
- id: "SVC-006"
name: "Service must NOT call db.commit()"
severity: "warning"
description: |
Services should NOT commit transactions. Transaction control belongs at the
API endpoint level where one request = one transaction.
This allows:
- Composing multiple service calls in a single transaction
- Clean rollback on any failure
- Easier testing of services in isolation
The endpoint should call db.commit() after all service operations succeed.
pattern:
file_pattern: "app/services/**/*.py"
anti_patterns:
- "db.commit()"
exceptions:
- "log_service.py" # Audit logs may need immediate commits
# ============================================================================
# MODEL RULES (models/database/*.py, models/schema/*.py)
# ============================================================================