carlos / platform Public

moves: cross-version tests: the floor at the door and at activation, the old abort allowlist (§14.3)

Two table rows on existing tests, per preflight N15:
- TestMoveDoorRefusesTheFleet: a pre-protocol box (no moves_protocol in
  its edges file) with no floor published gets MV-N5's 409.
- TestMoveAbortRefusesStatesItDoesNotKnow: committed, rolling_back,
  reverting and stuck join the refused list, against the real MoveAbort,
  whose allowed cases are v0.22.2's (provision.go:1022-1039 at that tag).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 1de7481d33d91d35ddc135b8445ecc1396b43969 parent 2da46e5
2 files changed, +13 −2
  • internal/console/apiinstancemove_test.go +6 −0
  • internal/provision/provision_test.go +7 −2
diff --git a/internal/console/apiinstancemove_test.go b/internal/console/apiinstancemove_test.go
index af45ff58c..ba1d8b63f 100644
--- a/internal/console/apiinstancemove_test.go
+++ b/internal/console/apiinstancemove_test.go
@@ -471,6 +471,10 @@ func TestMoveDoorRefusesTheFleet(t *testing.T) {
unarmed.FloorUnarmed = true
unverified := ukBox("uk-box")
unverified.Unverified = true
+ // A box from before moves: its edges file has no moves_protocol, which
+ // decodes as 0, the same as an explicit 0 (§14.3).
+ preProtocol := ukBox("uk-box")
+ preProtocol.NoProtocol = true
for _, c := range []struct {
name, floor string
boxes []fleetBox
@@ -482,6 +486,8 @@ func TestMoveDoorRefusesTheFleet(t *testing.T) {
http.StatusBadRequest, "uk has more than one box. Moves between regions with several boxes are not supported yet."},
{"a box that has not armed the floor", floor, []fleetBox{ieBox("ie-box"), unarmed}, "",
http.StatusConflict, "a box in ie or uk is below the moves protocol floor. roll the platform first"},
+ {"a pre-protocol box, no floor published", "", []fleetBox{ieBox("ie-box"), preProtocol}, "",
+ http.StatusConflict, "a box in ie or uk is below the moves protocol floor. roll the platform first"},
{"no verified box in the target", "", []fleetBox{ieBox("ie-box"), unverified}, "",
http.StatusBadRequest, "no box in uk publishes an edges file yet"},
{"no eligible box in the source", "", []fleetBox{ukBox("uk-box"), {Box: "se-box", Placement: "se", AWS: "eu-north-1", EIP: "1.2.3.5", Bucket: "data-se"}}, "",
diff --git a/internal/provision/provision_test.go b/internal/provision/provision_test.go
index e7ba07d95..7b1e1934b 100644
--- a/internal/provision/provision_test.go
+++ b/internal/provision/provision_test.go
@@ -979,9 +979,14 @@ func TestSetRecordMoveTransitions(t *testing.T) {
// Abort names the states it may leave, so a state a newer box writes is
// refused here rather than aborted (G16): "landing" is the target restoring
-// from the staging an abort would delete.
+// from the staging an abort would delete. The Phase 1 states past the cut
+// (committed, rolling_back, reverting, stuck) are refused the same way. This
+// is the real function, not a copy: v0.22.2's MoveAbort
+// (internal/provision/provision.go:1022-1039 at that tag) allows exactly the
+// same cases, preparing and ready, so a v0.22 console refuses all of them too
+// (§14.3).
func TestMoveAbortRefusesStatesItDoesNotKnow(t *testing.T) {
- for _, state := range []string{"landing", "freezing", "done", ""} {
+ for _, state := range []string{MoveLanding, MoveCommitted, MoveRollingBack, MoveReverting, MoveStuck, "freezing", "done", ""} {
rec := &Record{Move: &MoveState{To: "uk", State: state}}
if err := MoveAbort()(rec); !errors.Is(err, ErrMoveConflict) {
t.Errorf("abort from %q = %v, want ErrMoveConflict", state, err)