claim census: the seven offline move doors are refused fixtures (MV-O20)
CI failed four claim tests in internal/console (TestClaimConsoleRouteCensus, TestClaimConsoleMutationInvariant, TestClaimMovesConsoleRouteCensus, TestClaimRegionHAConsoleRouteCensus): the offline operator move's doors (GET and POST .../move/offline; POST .../abort, finish, flip, open, seal) had no claim fixture. Every offline door answers MV-O20 on a console with host claims or Phase 1 moves on (offlineGate), the posture of the legacy move doors' claimMoveUnsupportedMsg. They are classified the same way: the routes join claim-routes.txt, the sentence joins claimUnsupported with its reason, and each door is a refused fixture in the base table that the moves and region-HA tables merge. Each request is valid. The start names a movable instance and another region, and each verb finds an offline move walked through the record's own transitions to the state it acts on. The runner asserts the exact 409 and no write of any kind. No invariant changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 files changed,
+104
−0
internal/console/claim_invariant_fixtures_test.go+91 −0internal/console/claim_invariant_test.go+6 −0internal/console/testdata/claim-routes.txt+7 −0
CI passed — run details
CI log
=== gate ===
cd launchctx && go vet ./... && go test ./... -count=1
ok amadan.net/carlos/platform.git/launchctx 0.011s
? amadan.net/carlos/platform.git/launchctx/controlname [no test files]
? amadan.net/carlos/platform.git/launchctx/wireid [no test files]
go vet ./...
gofmt -l .: clean
go test ./... -count=1 -timeout 30m
ok github.com/carlosframework/platform 317.159s
? github.com/carlosframework/platform/cmd/changelog [no test files]
ok github.com/carlosframework/platform/cmd/console 2.889s
ok github.com/carlosframework/platform/cmd/moveprobe 92.285s
ok github.com/carlosframework/platform/cmd/zddprobe 0.710s
ok github.com/carlosframework/platform/internal/activator 252.526s
ok github.com/carlosframework/platform/internal/agentsock 0.019s
ok github.com/carlosframework/platform/internal/alerting 0.003s
ok github.com/carlosframework/platform/internal/analytics 0.019s
ok github.com/carlosframework/platform/internal/appconfig 2.484s
ok github.com/carlosframework/platform/internal/apperr 0.072s
ok github.com/carlosframework/platform/internal/applog 0.123s
ok github.com/carlosframework/platform/internal/awsinv 0.003s
ok github.com/carlosframework/platform/internal/boxchoice 0.006s
ok github.com/carlosframework/platform/internal/boxid 0.733s
? github.com/carlosframework/platform/internal/boxid/boxidtest [no test files]
? github.com/carlosframework/platform/internal/boxid/internal/signtest [no test files]
ok github.com/carlosframework/platform/internal/boxvolumes 0.008s
ok github.com/carlosframework/platform/internal/caps 0.014s
ok github.com/carlosframework/platform/internal/certwarm 0.002s
ok github.com/carlosframework/platform/internal/cgroup 0.708s
ok github.com/carlosframework/platform/internal/changelog 0.330s
ok github.com/carlosframework/platform/internal/claimactivation 0.772s
ok github.com/carlosframework/platform/internal/clamd 0.054s
? github.com/carlosframework/platform/internal/cliflag [no test files]
ok github.com/carlosframework/platform/internal/console 412.438s
? github.com/carlosframework/platform/internal/controlname [no test files]
? github.com/carlosframework/platform/internal/controlsock [no test files]
ok github.com/carlosframework/platform/internal/dbdoor 6.466s
ok github.com/carlosframework/platform/internal/dbdoor/dbdoortest 0.009s
ok github.com/carlosframework/platform/internal/dbverify 0.004s
ok github.com/carlosframework/platform/internal/dnsrec 0.003s
ok github.com/carlosframework/platform/internal/docsite 0.005s
ok github.com/carlosframework/platform/internal/domains 2.410s
ok github.com/carlosframework/platform/internal/doorkey 0.009s
ok github.com/carlosframework/platform/internal/economics 0.004s
ok github.com/carlosframework/platform/internal/edge 44.869s
? github.com/carlosframework/platform/internal/edgeproof [no test files]
ok github.com/carlosframework/platform/internal/edgesfile 0.008s
ok github.com/carlosframework/platform/internal/fleetapi 0.133s
ok github.com/carlosframework/platform/internal/gate 1.656s
ok github.com/carlosframework/platform/internal/genselect 0.016s
ok github.com/carlosframework/platform/internal/geo 0.018s
ok github.com/carlosframework/platform/internal/geoip 0.030s
ok github.com/carlosframework/platform/internal/historyreadback 0.153s
ok github.com/carlosframework/platform/internal/host 187.533s
ok github.com/carlosframework/platform/internal/hostactors 6.297s
ok github.com/carlosframework/platform/internal/hostactors/awsmembership 0.004s
ok github.com/carlosframework/platform/internal/hostbox 2.701s
ok github.com/carlosframework/platform/internal/hostclaim 0.586s
ok github.com/carlosframework/platform/internal/hostenv 0.012s
ok github.com/carlosframework/platform/internal/hostevidence 0.012s
ok github.com/carlosframework/platform/internal/hostexec 5.012s
ok github.com/carlosframework/platform/internal/hostfence 0.029s
ok github.com/carlosframework/platform/internal/hostfiles 10.441s
ok github.com/carlosframework/platform/internal/hostfloor 0.015s
ok github.com/carlosframework/platform/internal/hostguard 1.032s
ok github.com/carlosframework/platform/internal/hostops 1.607s
? github.com/carlosframework/platform/internal/hostops/fencerelease [no test files]
ok github.com/carlosframework/platform/internal/hostops/internal/fencerelease 0.012s
ok github.com/carlosframework/platform/internal/hostquarantine 0.012s
ok github.com/carlosframework/platform/internal/hostrelocate 0.481s
ok github.com/carlosframework/platform/internal/hostresolve 0.153s
ok github.com/carlosframework/platform/internal/hostwrite 0.012s
ok github.com/carlosframework/platform/internal/infraview 0.012s
ok github.com/carlosframework/platform/internal/instancectl 5.227s
ok github.com/carlosframework/platform/internal/instanceexec 2.746s
ok github.com/carlosframework/platform/internal/instancefs 0.017s
ok github.com/carlosframework/platform/internal/instancekey 0.014s
ok github.com/carlosframework/platform/internal/instanceupdates 0.019s
ok github.com/carlosframework/platform/internal/layout 1.548s
ok github.com/carlosframework/platform/internal/lbhealth 0.002s
ok github.com/carlosframework/platform/internal/lease 9.893s
ok github.com/carlosframework/platform/internal/lease/leasetest 0.379s
ok github.com/carlosframework/platform/internal/ledger 0.011s
ok github.com/carlosframework/platform/internal/mail 0.178s
ok github.com/carlosframework/platform/internal/maintenance 0.086s
ok github.com/carlosframework/platform/internal/maintenanceexec 5.533s
ok github.com/carlosframework/platform/internal/maintenanceguard 0.083s
ok github.com/carlosframework/platform/internal/metrics 0.005s
ok github.com/carlosframework/platform/internal/moves 21.290s
ok github.com/carlosframework/platform/internal/moves/archive 0.824s
ok github.com/carlosframework/platform/internal/objstore 0.198s
ok github.com/carlosframework/platform/internal/ops 0.176s
ok github.com/carlosframework/platform/internal/park 0.216s
ok github.com/carlosframework/platform/internal/privatefile 0.004s
ok github.com/carlosframework/platform/internal/provision 37.220s
ok github.com/carlosframework/platform/internal/publicrelease 0.010s
? github.com/carlosframework/platform/internal/regionname [no test files]
ok github.com/carlosframework/platform/internal/registry 5.519s
ok github.com/carlosframework/platform/internal/relay 7.253s
ok github.com/carlosframework/platform/internal/release 23.963s
ok github.com/carlosframework/platform/internal/rollout 3.790s
ok github.com/carlosframework/platform/internal/rolloutwords 0.004s
ok github.com/carlosframework/platform/internal/rootaws 0.007s
ok github.com/carlosframework/platform/internal/rootparticipation 0.060s
ok github.com/carlosframework/platform/internal/rootstate 0.026s
ok github.com/carlosframework/platform/internal/runs 0.588s
ok github.com/carlosframework/platform/internal/s3compat 0.006s
ok github.com/carlosframework/platform/internal/safefile 0.004s
ok github.com/carlosframework/platform/internal/schedule 2.490s
ok github.com/carlosframework/platform/internal/seeds 0.012s
ok github.com/carlosframework/platform/internal/sim/hostlife 9.676s
ok github.com/carlosframework/platform/internal/sim/litestreamfacts 3.445s
ok github.com/carlosframework/platform/internal/status 0.061s
ok github.com/carlosframework/platform/internal/steering 0.006s
ok github.com/carlosframework/platform/internal/stopevidence 0.298s
ok github.com/carlosframework/platform/internal/svcrole 0.002s
ok github.com/carlosframework/platform/internal/telemetry 0.004s
ok github.com/carlosframework/platform/internal/termfence 0.004s
ok github.com/carlosframework/platform/internal/tunnelclient 0.004s
ok github.com/carlosframework/platform/internal/unixdial 0.002s
ok github.com/carlosframework/platform/internal/updatewords 0.004s
ok github.com/carlosframework/platform/internal/usage 0.004s
ok github.com/carlosframework/platform/internal/version 0.002s
ok github.com/carlosframework/platform/internal/vet 1.567s
=== cross ===
--- shard 0 of 5 ---
cross-compiling darwin/arm64
--- shard 1 of 5 ---
cross-compiling darwin/amd64
--- shard 2 of 5 ---
cross-compiling linux/arm64
linux/arm64 carlos binary: 49807522 bytes (ceiling 52000000)
--- shard 3 of 5 ---
cross-compiling windows/amd64
--- shard 4 of 5 ---
cross-compiling windows/arm64
=== minio-contract ===
minio contract: arm64, minio RELEASE.2025-09-07T16-13-09Z, mc RELEASE.2025-08-13T08-35-41Z
minio: cached, digest verified
mc: cached, digest verified
minio healthy on 127.0.0.1:20999
Added `local` successfully.
Bucket created successfully `local/contract-bucket`.
Bucket created successfully `local/denied-bucket`.
Created policy `contract-only` successfully.
Added user `scopeduser` successfully.
Attached Policies: [contract-only]
To User: scopeduser
buckets and scoped user ready
=== RUN TestDeliveredContractMinio
=== RUN TestDeliveredContractMinio/put
=== RUN TestDeliveredContractMinio/get_round-trips_the_body
=== RUN TestDeliveredContractMinio/list_shows_the_key
=== RUN TestDeliveredContractMinio/head_and_list_agree_on_the_version
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_its_own_object
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/not_by_PutObjectTagging
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/and_not_by_x-amz-tagging_on_upload
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CreateMultipartUpload
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CopyObject_with_a_REPLACE_tagging_directive
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/but_multipart_itself_is_allowed
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_copy_itself_is_allowed
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/a_POST-policy_forged_tag_with_a_matching_version_is_still_not_a_verdict
=== RUN TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_an_ordinary_tagged-with-something-else_upload_is_allowed
=== RUN TestDeliveredContractMinio/delete_removes_it
=== RUN TestDeliveredContractMinio/cross-bucket_denial
--- PASS: TestDeliveredContractMinio (0.02s)
--- PASS: TestDeliveredContractMinio/put (0.00s)
--- PASS: TestDeliveredContractMinio/get_round-trips_the_body (0.00s)
--- PASS: TestDeliveredContractMinio/list_shows_the_key (0.00s)
--- PASS: TestDeliveredContractMinio/head_and_list_agree_on_the_version (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/not_by_PutObjectTagging (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/and_not_by_x-amz-tagging_on_upload (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route (0.01s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CreateMultipartUpload (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CopyObject_with_a_REPLACE_tagging_directive (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/but_multipart_itself_is_allowed (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_copy_itself_is_allowed (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/a_POST-policy_forged_tag_with_a_matching_version_is_still_not_a_verdict (0.00s)
--- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_an_ordinary_tagged-with-something-else_upload_is_allowed (0.00s)
--- PASS: TestDeliveredContractMinio/delete_removes_it (0.00s)
--- PASS: TestDeliveredContractMinio/cross-bucket_denial (0.00s)
PASS
ok github.com/carlosframework/platform/internal/objstore 0.023s
=== RUN TestT4StorageProbeMinio
2026/10/20 09:23:18 moves: T4: STORE: list: operation error S3: ListObjectsV2, https response error StatusCode: 403, RequestID: 18E032850A171564, HostID: 7c420053e0fbcd7f41653fdd92ffa2802c903d05303b1aa15adc2e8bb65d183f, api error SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method.
--- PASS: TestT4StorageProbeMinio (0.01s)
PASS
ok github.com/carlosframework/platform/internal/host 0.021s
minio contract: PASS
diff --git a/internal/console/claim_invariant_fixtures_test.go b/internal/console/claim_invariant_fixtures_test.go| index 215960ec9..392667d42 100644 |
| --- a/internal/console/claim_invariant_fixtures_test.go |
| +++ b/internal/console/claim_invariant_fixtures_test.go |
| @@ -528,6 +528,43 @@ func (cx *claimCase) stagedMove(t *testing.T, more ...func(*provision.Record) er |
| } |
| } |
| +// claimOfflineMoveID is the offline move offlineMove stages. |
| +const claimOfflineMoveID = "mv_zyxwvutsrqponmlkjihgfedcba" |
| + |
| +// offlineMove is movableInstance with an offline move from ie to uk walked |
| +// through the record's own transitions until it reaches state: the state a |
| +// door acts on, so its request is valid. |
| +func (cx *claimCase) offlineMove(t *testing.T, state string) { |
| + t.Helper() |
| + cx.movableInstance(t) |
| + now := time.Now() |
| + steps := []func(*provision.Record) error{provision.OfflineStart(claimOfflineMoveID, "ie", "uk", claimFxOwner, now)} |
| + switch state { |
| + case provision.OfflineStopping: |
| + case provision.OfflineSealed, provision.OfflineLanded, provision.OfflineOpen: |
| + steps = append(steps, |
| + provision.OfflineSeal(claimOfflineMoveID, "ie-box", []string{"ie-box"}), |
| + provision.OfflineSealedBy(claimOfflineMoveID, "ie-box", provision.MoveSource{})) |
| + if state != provision.OfflineSealed { |
| + steps = append(steps, provision.OfflineFlip(claimOfflineMoveID), provision.OfflineLandedBy(claimOfflineMoveID, "uk")) |
| + } |
| + if state == provision.OfflineOpen { |
| + steps = append(steps, provision.OfflineOpenTransition(claimOfflineMoveID, now)) |
| + } |
| + default: |
| + t.Fatalf("offlineMove: no staging for %s", state) |
| + } |
| + for _, mut := range steps { |
| + if _, err := provision.SetRecordMove(context.Background(), cx.rel, "bab", "titogo", "acme.go.tito.io", mut); err != nil { |
| + t.Fatal(err) |
| + } |
| + } |
| + rec, err := provision.GetRecord(context.Background(), cx.rel, "bab", "titogo", "acme.go.tito.io") |
| + if err != nil || rec.Move == nil || rec.Move.State != state { |
| + t.Fatalf("offlineMove: staged %+v (%v), want %s", rec, err, state) |
| + } |
| +} |
| + |
| // claimSecondSqid is the second account the account-move door moves into. |
| var claimSecondSqid = domains.Sqid(2) |
| @@ -1375,6 +1412,60 @@ var claimFixtures = map[string]claimFixture{ |
| status: http.StatusConflict, |
| msg: claimMoveUnsupportedMsg, |
| }}, |
| + // The offline operator move's doors are intentionally unsupported on a |
| + // claim console (claimUnsupported, MV-O20), as the legacy move doors |
| + // are. Each request is valid: the start names a movable instance and |
| + // another region, and each verb finds the offline move in the state it |
| + // acts on. The status view refuses the same way. |
| + "route GET /api/cli/apps/{account}/{app}/instances/{host}/move/offline": {refused: &claimRefusalFixture{ |
| + apps: claimRefs("bab/titogo"), |
| + setup: func(t *testing.T, cx *claimCase) { cx.offlineMove(t, provision.OfflineStopping) }, |
| + do: claimRefusedAPI(http.MethodGet, "/api/cli/apps/bab/titogo/instances/acme.go.tito.io/move/offline", ""), |
| + status: http.StatusConflict, |
| + msg: claimOfflineMoveUnsupportedMsg, |
| + }}, |
| + "route POST /api/cli/apps/{account}/{app}/instances/{host}/move/offline": {refused: &claimRefusalFixture{ |
| + apps: claimRefs("bab/titogo"), |
| + setup: func(t *testing.T, cx *claimCase) { cx.movableInstance(t) }, |
| + do: claimRefusedAPI(http.MethodPost, "/api/cli/apps/bab/titogo/instances/acme.go.tito.io/move/offline", `{"region":"uk"}`), |
| + status: http.StatusConflict, |
| + msg: claimOfflineMoveUnsupportedMsg, |
| + }}, |
| + "route POST /api/cli/apps/{account}/{app}/instances/{host}/move/offline/abort": {refused: &claimRefusalFixture{ |
| + apps: claimRefs("bab/titogo"), |
| + setup: func(t *testing.T, cx *claimCase) { cx.offlineMove(t, provision.OfflineStopping) }, |
| + do: claimRefusedAPI(http.MethodPost, "/api/cli/apps/bab/titogo/instances/acme.go.tito.io/move/offline/abort", ""), |
| + status: http.StatusConflict, |
| + msg: claimOfflineMoveUnsupportedMsg, |
| + }}, |
| + "route POST /api/cli/apps/{account}/{app}/instances/{host}/move/offline/finish": {refused: &claimRefusalFixture{ |
| + apps: claimRefs("bab/titogo"), |
| + setup: func(t *testing.T, cx *claimCase) { cx.offlineMove(t, provision.OfflineOpen) }, |
| + do: claimRefusedAPI(http.MethodPost, "/api/cli/apps/bab/titogo/instances/acme.go.tito.io/move/offline/finish", ""), |
| + status: http.StatusConflict, |
| + msg: claimOfflineMoveUnsupportedMsg, |
| + }}, |
| + "route POST /api/cli/apps/{account}/{app}/instances/{host}/move/offline/flip": {refused: &claimRefusalFixture{ |
| + apps: claimRefs("bab/titogo"), |
| + setup: func(t *testing.T, cx *claimCase) { cx.offlineMove(t, provision.OfflineSealed) }, |
| + do: claimRefusedAPI(http.MethodPost, "/api/cli/apps/bab/titogo/instances/acme.go.tito.io/move/offline/flip", ""), |
| + status: http.StatusConflict, |
| + msg: claimOfflineMoveUnsupportedMsg, |
| + }}, |
| + "route POST /api/cli/apps/{account}/{app}/instances/{host}/move/offline/open": {refused: &claimRefusalFixture{ |
| + apps: claimRefs("bab/titogo"), |
| + setup: func(t *testing.T, cx *claimCase) { cx.offlineMove(t, provision.OfflineLanded) }, |
| + do: claimRefusedAPI(http.MethodPost, "/api/cli/apps/bab/titogo/instances/acme.go.tito.io/move/offline/open", ""), |
| + status: http.StatusConflict, |
| + msg: claimOfflineMoveUnsupportedMsg, |
| + }}, |
| + "route POST /api/cli/apps/{account}/{app}/instances/{host}/move/offline/seal": {refused: &claimRefusalFixture{ |
| + apps: claimRefs("bab/titogo"), |
| + setup: func(t *testing.T, cx *claimCase) { cx.offlineMove(t, provision.OfflineStopping) }, |
| + do: claimRefusedAPI(http.MethodPost, "/api/cli/apps/bab/titogo/instances/acme.go.tito.io/move/offline/seal", ""), |
| + status: http.StatusConflict, |
| + msg: claimOfflineMoveUnsupportedMsg, |
| + }}, |
| "route POST /api/cli/apps/{account}/{app}/instances/{host}/retry": {door: &claimDoor{ |
| apps: claimRefs("bab/titogo"), |
| setup: func(t *testing.T, cx *claimCase) { cx.heldInstance(t, "web.go.tito.io") }, |
diff --git a/internal/console/claim_invariant_test.go b/internal/console/claim_invariant_test.go| index b28069f71..6f674b7eb 100644 |
| --- a/internal/console/claim_invariant_test.go |
| +++ b/internal/console/claim_invariant_test.go |
| @@ -87,6 +87,10 @@ type claimRefusalFixture struct { |
| msg string |
| } |
| +// claimOfflineMoveUnsupportedMsg is MV-O20, what every offline move door |
| +// answers on a console with host claims or Phase 1 moves on (offlineGate). |
| +const claimOfflineMoveUnsupportedMsg = "offline moves are not available while host claims or Phase 1 moves are on" |
| + |
| // claimUnsupported is the closed list of operations an enabled console |
| // refuses on purpose, keyed by the exact message production answers. Only |
| // these may be a refused fixture; every other app mutator is a door that |
| @@ -97,6 +101,8 @@ var claimUnsupported = map[string]string{ |
| claimHostResolveUnsupportedMsg: "host-loss declaration/readmission changes claim roots; the existing service has no scoped lifecycle grant in this slice", |
| claimMoveUnsupportedMsg: "instance move request, cut and abort rewrite the record's move journal, " + |
| "which only the unbuilt host-claim Moves protocol may do under its own operation", |
| + claimOfflineMoveUnsupportedMsg: "the offline operator move (MV-O20) is only for consoles with host claims and Phase 1 moves off; " + |
| + "every offline door, the status view included, refuses after its operator gate and before it reads evidence or writes the record", |
| claimRefusalText(errClaimAliasDetachUnsupported): "removing an alias-only marker needs its own conditional effect operation; " + |
| "a first-route detach retires its record and is a door", |
| claimRefusalText(errClaimAliasCapabilitiesUnsupported): "wildcard and catch-all claims are written only by the legacy capability path", |
diff --git a/internal/console/testdata/claim-routes.txt b/internal/console/testdata/claim-routes.txt| index fc667b937..a29e86d85 100644 |
| --- a/internal/console/testdata/claim-routes.txt |
| +++ b/internal/console/testdata/claim-routes.txt |
| @@ -57,6 +57,7 @@ route GET /api/cli/apps/{account}/{app}/geo |
| route GET /api/cli/apps/{account}/{app}/instances |
| route GET /api/cli/apps/{account}/{app}/instances/{host} |
| route GET /api/cli/apps/{account}/{app}/instances/{host}/move |
| +route GET /api/cli/apps/{account}/{app}/instances/{host}/move/offline |
| route GET /api/cli/apps/{account}/{app}/instances/{host}/runs/{id} |
| route GET /api/cli/apps/{account}/{app}/ledgers |
| route GET /api/cli/apps/{account}/{app}/ledgers/{ledger}/head |
| @@ -185,6 +186,12 @@ route GET /api/cli/apps/{account}/{app}/instances/{host}/updates |
| route PUT /api/cli/apps/{account}/{app}/instances/{host}/updates |
| route POST /api/cli/apps/{account}/{app}/instances/{host}/move |
| route POST /api/cli/apps/{account}/{app}/instances/{host}/move/cut |
| +route POST /api/cli/apps/{account}/{app}/instances/{host}/move/offline |
| +route POST /api/cli/apps/{account}/{app}/instances/{host}/move/offline/abort |
| +route POST /api/cli/apps/{account}/{app}/instances/{host}/move/offline/finish |
| +route POST /api/cli/apps/{account}/{app}/instances/{host}/move/offline/flip |
| +route POST /api/cli/apps/{account}/{app}/instances/{host}/move/offline/open |
| +route POST /api/cli/apps/{account}/{app}/instances/{host}/move/offline/seal |
| route POST /api/cli/apps/{account}/{app}/instances/{host}/retry |
| route POST /api/cli/apps/{account}/{app}/instances/{host}/runs |
| route POST /api/cli/apps/{account}/{app}/instances/{host}/runs/{id}/ack |