phase0: add architecture guardrails, CI gates, per-language AGENTS.md

Non-negotiable structural rules that apply to every Claude Code session in
this repo and to every commit, enforced via three defense-in-depth layers:

  1. PreToolUse hook in .claude/settings.json blocks any Write/Edit that
     would push a file past the 500-line hard cap. Auto-loads for any
     Claude session in this repo regardless of who launched it.
  2. scripts/githooks/pre-commit (installed via scripts/install-hooks.sh)
     enforces the LOC cap, freezes migrations/ unless [migration-approved],
     and protects guardrail files unless [guardrail-change] is present.
  3. .gitea/workflows/ci.yaml gets loc-budget + guardrail-integrity jobs,
     plus mypy --strict on new Python packages, tsc --noEmit on Node
     services, and a syft+grype SBOM scan.

Per-language conventions are documented in AGENTS.python.md / AGENTS.go.md /
AGENTS.typescript.md at the repo root — layering (router->service->repo for
Python, hexagonal for Go, colocation for Next.js), tooling baseline, and
explicit "what you may NOT do" lists.

Adds scripts/check-loc.sh (soft 300 / hard 500, reports 205 hard and 161
soft violations in the current codebase) plus .claude/rules/loc-exceptions.txt
(initially empty — the list is designed to shrink over time).

Per-service READMEs for all 10 services + PHASE1_RUNBOOK.md for the
backend-compliance refactor. Skeleton packages (compliance/{domain,
repositories,schemas}) are the landing zone for the clean-arch rewrite that
begins in Phase 1.

CLAUDE.md is prepended with the six non-negotiable rules.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sharang Parnerkar
2026-04-07 13:09:26 +02:00
parent 1dfea51919
commit 512b7a0f6c
25 changed files with 1308 additions and 10 deletions

View File

@@ -0,0 +1,30 @@
"""Domain layer: value objects, enums, and domain exceptions.
Pure Python — no FastAPI, no SQLAlchemy, no HTTP concerns. Upper layers depend on
this package; it depends on nothing except the standard library and small libraries
like ``pydantic`` or ``attrs``.
"""
class DomainError(Exception):
"""Base class for all domain-level errors.
Services raise subclasses of this; the HTTP layer is responsible for mapping
them to status codes. Never raise ``HTTPException`` from a service.
"""
class NotFoundError(DomainError):
"""Requested entity does not exist."""
class ConflictError(DomainError):
"""Operation conflicts with the current state (e.g. duplicate, stale version)."""
class ValidationError(DomainError):
"""Input failed domain-level validation (beyond what Pydantic catches)."""
class PermissionError(DomainError):
"""Caller lacks permission for the operation."""

View File

@@ -0,0 +1,10 @@
"""Repository layer: database access.
Each aggregate gets its own module (e.g. ``dsr_repository.py``) exposing a single
class with intent-named methods. Repositories own SQLAlchemy session usage; they
do not run business logic, and they do not import anything from
``compliance.api`` or ``compliance.services``.
Phase 1 refactor target: ``compliance.db.repository`` (1547 lines) is being
decomposed into per-aggregate modules under this package.
"""

View File

@@ -0,0 +1,11 @@
"""Pydantic schemas, split per domain.
Phase 1 refactor target: the monolithic ``compliance.api.schemas`` module (1899 lines)
is being decomposed into one module per domain under this package. Until every domain
has been migrated, ``compliance.api.schemas`` re-exports from here so existing imports
continue to work unchanged.
New code MUST import from the specific domain module (e.g.
``from compliance.schemas.dsr import DSRRequestCreate``) rather than from
``compliance.api.schemas``.
"""