molecule-core/workspace-server/internal/provisioner
Hongming Wang e081c8335f refactor(handlers): widen WorkspaceHandler.provisioner to LocalProvisionerAPI interface (#2369)
Symmetric with the existing CPProvisionerAPI interface. Closes the
asymmetry where the SaaS provisioner field was an interface (mockable
in tests) but the Docker provisioner field was a concrete pointer
(not).

## Changes

- New ``provisioner.LocalProvisionerAPI`` interface — the 7 methods
  WorkspaceHandler / TeamHandler call on h.provisioner today: Start,
  Stop, IsRunning, ExecRead, RemoveVolume, VolumeHasFile,
  WriteAuthTokenToVolume. Compile-time assertion confirms *Provisioner
  satisfies it. Mirror of cp_provisioner.go's CPProvisionerAPI block.
- ``WorkspaceHandler.provisioner`` and ``TeamHandler.provisioner``
  re-typed from ``*provisioner.Provisioner`` to
  ``provisioner.LocalProvisionerAPI``. Constructor parameter type is
  unchanged — the assignment widens to the interface, so the 200+
  callers of ``NewWorkspaceHandler`` / ``NewTeamHandler`` are
  unaffected.
- Constructors gain a ``if p != nil`` guard before assigning to the
  interface field. Without this, ``NewWorkspaceHandler(..., nil, ...)``
  (the test fixture pattern across 200+ tests) yields a typed-nil
  interface value where ``h.provisioner != nil`` evaluates *true*,
  and the SaaS-vs-Docker fork incorrectly routes nil-fixture tests
  into the Docker code path. Documented inline with reference to
  the Go FAQ.
- Hardened the 5 Provisioner methods that lacked nil-receiver guards
  (Start, ExecRead, WriteAuthTokenToVolume, RemoveVolume,
  VolumeHasFile) — return ErrNoBackend on nil receiver instead of
  panicking on p.cli dereference. Symmetric with Stop/IsRunning
  (already hardened in #1813). Defensive cleanup so a future caller
  that bypasses the constructor's nil-elision still degrades
  cleanly.
- Extended TestZeroValuedBackends_NoPanic with 5 new sub-tests
  covering the newly-hardened nil-receiver paths. Defense-in-depth:
  a future refactor that drops one of the nil-checks fails red here
  before reaching production.

## Why now

- Provisioner orchestration has been touched in #2366 / #2368 — the
  interface symmetry is the natural follow-up captured in #2369.
- Future work (CP fleet redeploy endpoint, multi-backend
  provisioners) wants this in place. Memory note
  ``project_provisioner_abstraction.md`` calls out pluggable
  backends as a north-star.
- Memory note ``feedback_long_term_robust_automated.md`` —
  compile-time gates + ErrNoBackend symmetry > runtime panics.

## Verification

- ``go build ./...`` clean.
- ``go test ./...`` clean — 1300+ tests pass, including the
  previously-flaky Create-with-nil-provisioner paths that now
  exercise the constructor's nil-elision correctly.
- ``go test ./internal/provisioner/ -run TestZeroValuedBackends_NoPanic
  -v`` — all 11 nil-receiver subtests green (was 6, +5 for the
  newly-hardened methods).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 09:18:16 -07:00
..
architecture_test.go test(arch): codify 4 module boundaries as architecture tests (#2344) 2026-04-29 22:12:58 -07:00
backend_contract_test.go refactor(handlers): widen WorkspaceHandler.provisioner to LocalProvisionerAPI interface (#2369) 2026-04-30 09:18:16 -07:00
cp_provisioner_instance_id_test.go test: regression guard for #1738 — cp-provisioner uses real instance_id 2026-04-23 17:45:13 -07:00
cp_provisioner_test.go fix(cp-provisioner): look up real EC2 instance_id for Stop + IsRunning (#1738) 2026-04-23 18:25:29 +00:00
cp_provisioner.go fix(a2a): detect dead EC2 agents on upstream 5xx + reactive auto-restart for SaaS 2026-04-30 00:28:22 -07:00
isrunning_test.go fix(provisioner): treat "removal already in progress" as no-op success 2026-04-27 13:25:32 -07:00
local_provisioner_api.go refactor(handlers): widen WorkspaceHandler.provisioner to LocalProvisionerAPI interface (#2369) 2026-04-30 09:18:16 -07:00
platform_test.go fix(provisioner): force linux/amd64 pull + create on Apple Silicon hosts (#1875) 2026-04-23 14:55:34 -07:00
provisioner_test.go feat(provisioner): pull workspace-template images from GHCR 2026-04-22 12:39:56 -07:00
provisioner.go refactor(handlers): widen WorkspaceHandler.provisioner to LocalProvisionerAPI interface (#2369) 2026-04-30 09:18:16 -07:00