Zig 0.16 · v0.0.2 preview
Named layer policies
Layers assign project files to named architecture areas and express allowed dependencies between those areas. Ordered definitions make overlapping selectors deterministic.
A compiled example
const std = @import("std");
const archunit = @import("archunit");
test "service may depend only on domain" {
var architecture = try archunit.projectLayers(std.testing.allocator, .{});
defer architecture.deinit(std.testing.allocator);
var domain_stage = try architecture.layer("domain");
defer domain_stage.deinit();
var with_domain = try domain_stage.definedBy(.{ .glob = "src/domain/**" });
defer with_domain.deinit(std.testing.allocator);
var service_stage = try with_domain.layer("service");
defer service_stage.deinit();
var with_service = try service_stage.definedBy(.{ .glob = "src/service/**" });
defer with_service.deinit(std.testing.allocator);
var policy_stage = try with_service.whereLayer("service");
defer policy_stage.deinit();
var rule = try policy_stage.mayOnlyDependOnLayers(&.{"domain"});
defer rule.deinit(std.testing.allocator);
try archunit.expectPasses(&rule, .init(.init(std.testing.allocator, std.testing.io)));
}
Compiled source: test/readme/layers.zig
Define layers in ownership order
Create a layered architecture, then add definitions with a stable name and path selectors. The first matching definition owns a file when selectors overlap. Exclusions apply before ownership assignment.
Layer names must be unique and policy references must name existing layers. Definitions and policies are validated before extraction, so configuration errors remain distinct from architecture violations.
Choose the dependency policy
| Policy | Meaning |
|---|---|
mayOnlyDependOn | Outgoing dependencies may target only the named layers (and the same layer). |
mayNotDependOn | Outgoing dependencies must avoid the named layers. |
mayOnlyBeDependedOnBy | Incoming dependencies may originate only in the named layers. |
mayNotBeDependedOnBy | Incoming dependencies must avoid the named layers. |
Strict ownership closes gaps
Enable strict assignment when every connected project file must belong to a named layer. Unassigned sources and targets become structured violations instead of silently living outside the architecture map. For isolated files, combine strict layers with a file callback or repository dogfood rule that names every top-level production folder.
Violation evidence
A layer dependency violation records the policy kind, source and target layer, source and target file, and the underlying dependency evidence. The formatter can therefore explain both the intended boundary and the concrete import that crossed it.