3.1 KiB
ADR 0002: Own public contracts behind an internal CLI backend
Status
Accepted.
Date
2026-11-07; consolidates decisions made on 2026-10-06 and 2026-10-09.
Context
CommandKit needs established routing, parsing, and help machinery while retaining control of its consumer contracts. Exposing a backend framework directly would couple applications and integration handlers to that framework's objects and configuration model.
Decision
Use the root commandkit package as the core module's public facade. Optional
integrations own their public contracts in separate modules under
ADR 0004.
Use Cobra with pflag as the internal CLI backend. Confine their types and operations to an internal adapter that translates CommandKit declarations and selected semantics into backend machinery. Registry logic, shared definitions, and standard handlers remain independent of backend structures. Do not mirror the complete backend API through renamed wrappers.
Public types and handles expose deliberate contracts and keep implementation state private. Exports must not reveal internal or backend types through aliases, embedding, signatures, method sets, loosely typed values, or backend-owned syntax errors. Translate those syntax failures into CommandKit diagnostics and outcomes. Caller-supplied objects and errors retain their documented handling; this boundary does not require transforming arbitrary application content.
Standard Go contracts remain appropriate. Deliberate upstream public types may be exposed by integrations that own those dependencies. Implementation may live in the owning public package; introduce internal layers and conversions where they simplify the code or protect the backend boundary.
There is one concrete backend, without a public backend-selection framework. A replacement must preserve public contracts or accompany deliberate compatibility changes. Backend defaults do not independently define CommandKit behavior.
Alternatives considered
- Exposing Cobra directly would reduce adapter work but make the framework part of the consumer contract.
- A forwarding-only facade with duplicate internal representations would enforce layering at the cost of conversions without a demonstrated need.
- pflag alone or the standard flag package would leave more routing and help machinery to implement. Other full CLI frameworks are credible alternatives; Cobra's adoption was the preferred maintenance tradeoff.
- Interchangeable backends would add public assembly and behavior contracts before a concrete need exists.
Consequences
Consumers depend on CommandKit's selected contracts while internal implementation can evolve. The adapter still needs to preserve typed inputs, presence, public error identity, and invocation lifetimes; package placement alone is insufficient.
The architecture policy owns dependency constraints, GoDoc owns exact exports, and the internal overview owns package mechanics. Backend construction and reuse strategies are implementation choices within the invocation-isolation contract.