ADR 0027: Split client CLI from server/runtime binary
Status
Accepted
Context
Kilolock started with a single kl binary that mixed:
- client/operator workflows
- server runtime
- database migrations
- provisioning helpers
That shape was convenient early on, but it blurred an important boundary:
- client CLI should talk only to server APIs
- server/runtime tooling may talk directly to the database
We have already migrated normal CLI workflows (apply, rollback, query, admin, operator, provider, refresh, import, tag) behind backend or control APIs. The remaining direct database access in cmd/kl is now limited to runtime/deployment commands such as:
servemigrateprovision
For first public deployment we want the public contract to be simple and defensible:
klis a client CLI- it does not require direct database connectivity
- server-side binaries own database access
Decision
We split the mixed binary into two roles:
kl- client/operator CLI
- API-driven
- no direct DB requirement for normal usage
kld- server/runtime/deployment binary
- owns:
servemigrateprovision
- may connect directly to the database(s)
klc already fits the server/runtime side of this boundary and continue to talk directly to the control/data plane as services.
Consequences
Positive
- Clear public security boundary
- Cleaner OSS story
- Easier packaging and docs
- Fewer surprises about which commands need private network access
- Lets us state plainly:
klis API-onlykldis infrastructure-side
Tradeoffs
- More than one binary to package
- Some deployment docs/scripts must switch from
kld serve|migrate|provisionto
kld serve|migrate|provision - Short-term code duplication is acceptable while the split settles
Follow-up
- Keep moving docs/scripts to the new binary names
- Consider extracting shared runtime helpers if duplication becomes noisy
- Keep client-facing commands out of
kld