Boundary ports are owned by the inner policy layer
clean-arch-003
Intent
Core policy should define the contracts it needs, and outer adapters should implement them.
Applicability
Applies when the diff adds or materially changes interfaces, abstract classes, protocols, or callback contracts that cross an architectural boundary.
What to inspect
Where the contract is declared, who imports it, and whether the naming and placement reflect policy needs or adapter details.
Pass criteria
The inner layer owns the port and outer implementations depend inward on it.
Fail criteria
Infrastructure or framework code declares the contract and forces the core to depend outward on adapter-owned abstractions.
Do not flag
Truly low-level shared abstractions that are not policy/detail seams.
Confidence guidance
HIGH when the core imports an adapter-owned interface. MEDIUM when ownership is inferred from layout. LOW when the abstraction may not be a real boundary port.
Remediation
Move the port inward, name it in policy terms, and reuse an existing inward seam when one already covers the boundary.
Pass example
type UserLoader interface { Load(ctx context.Context, id string) (User, error) }
Fail example
type SqlUserRepository interface { SelectUser(ctx context.Context, id string) (Row, error) }