Documentation
¶
Overview ¶
Package archcheck enforces Kram's architectural layer boundaries — the project's single most valuable and hardest-to-retrofit property — so a stray import can't silently breach a layer in a future PR and still compile and pass every other test.
The boundaries it locks (all verified to hold when this was written):
- internal/cli/** never imports internal/daemon/**, internal/gateway, or internal/router. The CLI talks to the daemon and gateway only over HTTP, via the client packages under internal/cli — never by reaching into server-side internals.
- internal/daemon/** never imports internal/gateway. The daemon reaches the gateway only over HTTP, via internal/daemon/gatewayclient — the gateway's own server/router internals stay off-limits.
The rule-evaluation logic (Analyze) is a pure function, unit-tested with synthetic import graphs; Load feeds it the real graph via `go list`, swept across every platform Kram ships (so a breach hidden behind an OS build tag can't slip past a single-OS CI runner — see buildTargets), and the package's own integration test asserts the real module has zero violations. See DECISIONS.md.
Index ¶
Constants ¶
const Module = "github.com/codexmark/kram"
Module is Kram's module path — the prefix stripped to turn a full import path into the module-relative path the rules are written against.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type PackageImports ¶
PackageImports is one package's full import path and the full import paths it directly depends on (production and test imports both — a test file breaching a layer is still a breach).
func Load ¶
func Load(ctx context.Context, pattern string) ([]PackageImports, error)
Load builds the real import graph for pattern (e.g. Module+"/...") by shelling out to `go list` once per build target and unioning the results. It collects each package's production and test imports, since a boundary breach in a _test.go file is still a breach worth catching.
type Rule ¶
type Rule struct {
From string
To string
Except []string // module-relative prefixes under To that are allowed anyway
Why string // printed when the rule is violated, so the failure explains itself
}
Rule forbids packages under From from importing packages under To. From, To, and each Except entry are module-relative package-path prefixes (e.g. "internal/cli"), matched on whole path segments: "internal/gateway" matches "internal/gateway" and "internal/gateway/x" but NOT "internal/gatewayclient" or "internal/gatewayconfig".
func DefaultRules ¶
func DefaultRules() []Rule
DefaultRules is Kram's layer policy — the single source of truth shared by the integration test and any external runner.
type Violation ¶
Violation is one forbidden edge: Package (full import path) imports Import (full import path) in breach of Rule.
func Analyze ¶
func Analyze(pkgs []PackageImports, rules []Rule) []Violation
Analyze returns every rule violation in pkgs, deterministically ordered (by package, then import, then rule). It's pure: no I/O, no globals — the import graph is entirely supplied by the caller.