We break down what exactly counts as a public API in a Go package: exported names and types, signatures, errors as a contract (including
%w-wrapping), observable behavior, and the order in which data is produced. Using a mini-core
todo as an example, we lock down the
Task model, enforce invariants via a constructor, choose an error strategy (
ErrNotFound,
ValidationError), decide up front about
context.Context, package boundaries and using
internal/, so we can plug in new layers without rewriting the domain.