diff --git a/.golangci.yml b/.golangci.yml index 4229067a..85d47023 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -5,6 +5,7 @@ linters: # Only enable linters that pass with current codebase # Additional linters can be enabled incrementally enable: + - depguard - gocritic - gosec - misspell @@ -38,6 +39,28 @@ linters: - fieldalignment - shadow enable-all: true + depguard: + rules: + application-boundaries: + files: + - internal/application/**/*.go + deny: + - pkg: github.com/altuslabsxyz/devnet-builder/internal/infrastructure + desc: application layer must not import infrastructure + - pkg: github.com/altuslabsxyz/devnet-builder/internal/daemon + desc: application layer must not import daemon + - pkg: github.com/altuslabsxyz/devnet-builder/internal/plugin + desc: application layer must not import plugin + application-ports-boundaries: + files: + - internal/application/ports/**/*.go + deny: + - pkg: github.com/altuslabsxyz/devnet-builder/internal/infrastructure + desc: ports layer must not import infrastructure + - pkg: github.com/altuslabsxyz/devnet-builder/internal/daemon + desc: ports layer must not import daemon + - pkg: github.com/altuslabsxyz/devnet-builder/internal/plugin + desc: ports layer must not import plugin exclusions: generated: lax presets: @@ -63,6 +86,16 @@ linters: - linters: - errcheck text: "Error return value of .*(Run|Wait|Signal|Cleanup|MarkFlagRequired|Save|Sscanf).* is not checked" + # Stage depguard rollout by ignoring known pre-existing boundary debt. + - linters: + - depguard + path: internal/application/(devnet/export|devnet/docker_deploy|devnet/provision|service)\.go + - linters: + - depguard + path: internal/application/ports/provisioner\.go + - linters: + - depguard + path: _test\.go paths: - third_party$ - builtin$ diff --git a/docs/architecture-boundaries.md b/docs/architecture-boundaries.md new file mode 100644 index 00000000..3b8f4ab0 --- /dev/null +++ b/docs/architecture-boundaries.md @@ -0,0 +1,35 @@ +# Architecture Boundaries + +This repository enforces architecture boundaries with `depguard` in `golangci-lint`. + +## Enforced Rules + +1. `internal/application/**` must not import: + - `internal/infrastructure/**` + - `internal/daemon/**` + - `internal/plugin/**` +2. `internal/application/ports/**` must not import: + - `internal/infrastructure/**` + - `internal/daemon/**` + - `internal/plugin/**` + +## Why + +These rules keep dependency direction aligned with clean architecture: + +- Application code depends on abstractions, not infrastructure details. +- Ports remain stable contracts without daemon/plugin coupling. +- Reviewers get automated boundary checks in CI. + +## Existing Debt and Rollout + +A small set of known legacy files are temporarily excluded from depguard in `.golangci.yml`. +New violations outside that allowlist fail CI. + +## Remediation Pattern + +When depguard fails: + +1. Move concrete dependency usage into infrastructure/daemon adapters. +2. Define or extend a port interface in `internal/application/ports`. +3. Inject the dependency through constructors (DI) instead of direct imports.