ADR 0015: Separate customer control plane from core Kilolock backend
- Status: Accepted (partially implemented)
- Date: 2026-05-28
- Decider(s): @davesade (David Kubec)
- Relates to: ADR 0003, ADR 0013, ADR 0014
Context
Kilolock now includes strong backend primitives for hosted operation: tenants, environments, API tokens, and environment-level database routing.
For a paid production service, we also need end-user flows such as:
- organization signup and lifecycle
- self-serve environment creation/deletion
- token issuance/rotation UX
- quotas, billing, and plan enforcement
- support/admin operations and audit experiences
Embedding these product-facing workflows directly into the core backend creates avoidable coupling and risk:
- expands the security surface of the state backend
- mixes fast-moving product concerns with backend runtime concerns
- makes OSS adoption harder for operators who want different business logic
Decision
Kilolock will keep the backend engine and its operator/admin primitives in OSS, while customer onboarding and commercial lifecycle workflows are implemented in a separate control-plane service.
D1. Core backend remains capability-complete in OSS
OSS Kilolock keeps:
- Terraform/OpenTofu backend protocol handling
- state storage/query/refresh/apply features
- tenant/environment/token primitives
- multi-instance data-plane routing primitives
- operator/admin commands for provisioning and diagnostics
No core backend capability is removed to force paid adoption.
D2. Customer-facing service is separate
A separate service (future Web UI + API) owns:
- account/org lifecycle
- self-serve tenant/environment provisioning orchestration
- policy and quota enforcement at product tier level
- billing/metering integration
- customer-facing audit/support workflows
This service talks to Kilolock through explicit admin/operator interfaces.
D3. Publish and stabilize an integration contract
To let anyone run their own "Kilolock shop," we document a stable contract for external control planes:
- required operations (create tenant/env/token, provision, status, rotate/revoke)
- idempotency expectations
- long-running provisioning states (
provisioning,ready,failed) - error classes suitable for retries vs operator action
- minimum authn/authz expectations for admin surfaces
Kilolock remains usable standalone without that service.
D4. Security boundary
In production hosted setups:
- end users should not receive direct unrestricted access to backend admin APIs
- control-plane service holds elevated credentials and performs privileged actions
- Kilolock runtime stays focused on state protocol and execution paths
Consequences
Positive
- cleaner architecture and lower blast radius
- clearer OSS/commercial boundary based on operations, not feature removal
- easier for third parties to build custom portals and business logic
- faster iteration on product UX without destabilizing backend runtime
Negative
- more components to operate in paid deployment
- contract/versioning work is required to avoid integration drift
- eventual consistency between systems must be handled explicitly
Implementation path
- Keep existing admin/operator capabilities in Kilolock OSS.
- Document control-plane integration contract (CLI/API runbook).
- Add contract-focused integration tests (idempotent create/provision/token flows).
- Build separate control-plane service (API first, Web UI second).
- Add versioned compatibility notes for control-plane to backend integration.
Non-goals
- Building billing, signup, and storefront workflows inside
kld. - Hiding current tenant/environment primitives from OSS users.
- Replacing Terraform/OpenTofu workflow semantics with a proprietary runner model.