pkg vs internal Boundaries
Flowbot treats pkg/ as shared application libraries that must stay independent of internal/ implementation details. Product orchestration and ORM bindings live under internal/.
This is an architectural rule (enforced by internal/server/pkg_deps_test.go), not Go's internal/ visibility rule (same-module imports are legal).
Rules
pkg/*must not importinternal/*, except packages on the migration allowlist ininternal/server/pkg_deps_test.go.pkgpublic APIs and templates must not expose*gen.*orinternal/storefacades — usepkg/types/pkg/types/modeland inject interfaces frominternal/server.- Domain enums used outside the store layer live in
pkg/types(e.g. Instruct*, FormState, PipelineState, WorkflowRunState, ResourceRef);ent/schemamay type-alias them — do not redefine parallel constants. internal/storecontinues to return*gen.*to product layers; mapping topkg/typeshappens in adapters / web services — not inside store facades.
Positive examples already clean: pkg/capability, pkg/agent (orchestration in internal/server/chatagent).
Migration waves
| Wave | Scope | Target shape |
|---|---|---|
| L1 (done) | pkg/types, pkg/providers, pkg/media |
Injected stores; no internal imports; architecture gate + AGENTS |
| L3 (done) | pkg/views |
Stay in pkg; templates only consume pkg/types/model; mapping in internal/modules/web; drop ent/gen and internal/server/chatagent imports |
| L2 (done) | pkg/route, pkg/module, pkg/event, pkg/notify |
Contracts stay in pkg; inject store interfaces from internal/server |
| L4 (done) | pkg/pipeline, pkg/workflow |
Engine contracts stay in pkg; DTO interfaces + internal/store adapters; no *gen.* in pkg |
After each wave, remove the cleaned packages from the architecture-test allowlist. The allowlist is now empty.
Gate
go test ./internal/server -run TestPkgMustNotImportInternal
Standing order (one line, links here): root AGENTS.md.