v0.4.1 · disposable previews · mesh isolation · bucket websites Agents ship · humans inspect
← Engineering log

Mechanics sheds its transports

Ten releases moved every external-system transport (Forgejo, OpenBao, GitHub, S3, VictoriaMetrics, OCI registries, Kubernetes) into operation-based mechanics-sdk providers, and the kubectl binary is gone.

Between 0.3.23 and 0.3.32, Mechanics ran the same refactor seven times: take one external system's transport (HTTP calls, DTOs, auth flows, error mapping), move it into an operation-based provider in mechanics-sdk, and delete the internal client with no compatibility wrapper. Forgejo, OpenBao, GitHub, S3, VictoriaMetrics, OCI registries, and finally Kubernetes itself.

Providers own transport, Mechanics owns meaning

The split is strict. A provider knows how to talk to a system: Device Flow against GitHub, signed ListObjectsV2 against S3, manifest reads with the right Accept headers against an OCI registry. Mechanics keeps what the calls mean: signup state, workspace attribution, PromQL construction, pull credential policy, command output. Each provider is consumed through a narrow ports layer such as internal/forgejoops, internal/openbaoops, and internal/kubernetesops, and architecture tests fail the build if a deleted client package ever comes back.

The kubectl binary is gone

The largest step was ADR-037/ADR-040: the Kubernetes provider first replaced the internal kubectl transport package, then replaced kubectl process execution with client-go: discovery-based resolution, server-side apply, SPDY exec and port-forward streams, TokenRequest tokens. The kubectl binary is no longer a runtime dependency of the service, and exec arguments travel in API request bodies instead of child argv.

Safety came along for free

Centralizing transport centralized redaction: provider errors scrub credential-bearing response bodies and key=value fragments such as PGPASSWORD=... before they can reach diagnostics. Operations return stable names, run IDs, and timing metadata, and the providers share one verb contract: converging operations report Created/Changed, and deletes tolerate absent targets, so Mechanics stopped sniffing "AlreadyExists" strings to decide what happened.

the boundary, in module form

gitea.andreygubarev.com/mechanics.run/mechanics-sdk/provider/forgejo
gitea.andreygubarev.com/mechanics.run/mechanics-sdk/provider/openbao
gitea.andreygubarev.com/mechanics.run/mechanics-sdk/provider/github
gitea.andreygubarev.com/mechanics.run/mechanics-sdk/provider/s3
gitea.andreygubarev.com/mechanics.run/mechanics-sdk/provider/victoriametrics
gitea.andreygubarev.com/mechanics.run/mechanics-sdk/provider/oci
gitea.andreygubarev.com/mechanics.run/mechanics-sdk/provider/kubernetes
Ten releases, seven providers, zero compatibility wrappers, and a control plane that finally contains no HTTP client it has to apologize for.