carlos / platform Public

moves: the park view pins the files live set; the source stays protected until the commit (Plan 5 Task 9a, step 5)

Paul's J2/F4 ruling (#236) by M10's rule: in the authoritative region the
view reads the files manifest of each live generation (the holder's and
the marker's) through hostfiles.Load, by the exact version the listing
names, and pins every listed version of each object it names, under an
older generation's files prefix too. A region pins only what its own live
manifests name (spec §6.6 P6-D3: a target's manifest never references a
source-region object); with no manifest nothing more is pinned. A manifest
naming an object outside the location, or one the bucket does not hold,
refuses.

Seen from the source's region, a landing whose target probe is admitted
keeps the source authoritative until the record commits, so the source's
live set, its files live set among it, stays protected there; after the
commit the source pins nothing and its location park may run.

Tests: TestParkKeepsTheFilesLiveSet (the sweep), and one per destructive
step: TestLandingResidueParkKeepsTheFilesLiveSet (the landing install's
residue park), TestReturnResidueParkKeepsTheFilesLiveSet (the rollback
return's), TestFilesLiveSetIsProtectedOnTheSourceUntilTheCommit (the
source's location park).

Census: versionStore.Put, the view's read-only store, nonrecord.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev a927e15985170a583d6b1b3c032cb2839fc988ea parent 346b5e1
3 files changed, +363 −3
  • internal/host/movesfileslive_test.go +250 −0
  • internal/host/movessources.go +111 −3
  • internal/provision/plan9_b8_census_test.go +2 −0
diff --git a/internal/host/movesfileslive_test.go b/internal/host/movesfileslive_test.go
new file mode 100644
index 000000000..50023ee27
--- /dev/null
+++ b/internal/host/movesfileslive_test.go
@@ -0,0 +1,250 @@
+package host
+
+import (
+ "context"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strings"
+ "testing"
+ "time"
+
+ "github.com/carlosframework/platform/internal/hostbox"
+ "github.com/carlosframework/platform/internal/hostclaim"
+ "github.com/carlosframework/platform/internal/hostfiles"
+ "github.com/carlosframework/platform/internal/lease"
+ "github.com/carlosframework/platform/internal/park"
+ "github.com/carlosframework/platform/internal/provision"
+)
+
+// The files live set (J2/F4, Paul's #236 ruling; M10): every moves park
+// excludes the objects a live generation's files manifest names, in its own
+// region, and the source's are protected on the source until the record
+// commits. Plan 5 Task 9a.
+
+// filesManifest writes a hostfiles manifest at <location>/files/g-<gen>/
+// naming objects, each "path=key".
+func filesManifest(t *testing.T, put func(key string, body []byte), location, gen string, objects ...string) {
+ t.Helper()
+ m := hostfiles.Manifest{V: hostfiles.ManifestVersion, Seq: int64(len(objects)), Entries: map[string]hostfiles.Entry{}, Platform: map[string]hostfiles.Entry{}}
+ for i, o := range objects {
+ path, key, _ := strings.Cut(o, "=")
+ m.Entries[path] = hostfiles.Entry{Object: key, SHA256: fmt.Sprintf("%064x", i+1), Size: 4, Mode: 0o644, Seq: int64(i + 1)}
+ }
+ body, err := json.Marshal(m)
+ if err != nil {
+ t.Fatal(err)
+ }
+ put(hostfiles.ManifestKey(location+"/files/g-"+gen+"/"), body)
+}
+
+// TestParkKeepsTheFilesLiveSet (M10): in the authoritative region the view
+// pins the exact versions a live generation's files manifest names, also
+// under an older generation's files prefix, so the sweep never makes that
+// generation a candidate and its objects stay. Without a manifest nothing
+// more is pinned and the older generation is parked. Seen from another
+// region nothing is read or pinned.
+func TestParkKeepsTheFilesLiveSet(t *testing.T) {
+ setup := func(t *testing.T, manifest bool) (*evFixture, park.Engine, []string) {
+ f := newEvFixture(t)
+ body, err := json.Marshal(map[string]any{"op": evMoveID, "incarnation": f.inc, "host": evHost, "box": "box", "installed_at": evCreated, "manifest_sha256": "x", "snapshot_txid": 1})
+ if err != nil {
+ t.Fatal(err)
+ }
+ f.bucket.Put("data", f.location+"/generation.json", body)
+ old := []string{f.location + "/files/g-old/objects/0000000000000001-aa", f.genKey("old")}
+ for _, k := range old {
+ f.bucket.Put("data", k, []byte("old"))
+ }
+ f.bucket.Put("data", f.location+"/files/g-"+evMoveID+"/objects/0000000000000002-bb", []byte("cur"))
+ if manifest {
+ filesManifest(t, func(k string, b []byte) { f.bucket.Put("data", k, b) }, f.location, evMoveID,
+ "kept.txt="+old[0], "new.txt="+f.location+"/files/g-"+evMoveID+"/objects/0000000000000002-bb")
+ }
+ seq := 0
+ e := park.Engine{Store: f.bucket, Claims: f.claims, Bucket: "data", Region: "ie", Leases: evLeases{}, Now: func() time.Time { return evNow },
+ NewID: func() string { seq++; return fmt.Sprintf("id%d", seq) },
+ View: movesParkView(f.provider().Records, f.bucket, "data", "ie"),
+ Authorize: func(context.Context, hostclaim.Observed, hostclaim.Obligation) error { return nil }}
+ return f, e, old
+ }
+ t.Run("a live manifest names an older generation's object", func(t *testing.T) {
+ f, e, old := setup(t, true)
+ v, err := e.View(t.Context(), f.observe(t))
+ if err != nil {
+ t.Fatal(err)
+ }
+ ver := f.bucket.LatestID("data", old[0])
+ if !v.Pinned[park.Ref{Key: old[0], VersionID: ver}] {
+ t.Fatalf("pins %v; want %s@%s", v.Pinned, old[0], ver)
+ }
+ d, err := e.Sweep(t.Context(), evHost, f.inc, evAt, hostbox.RequestLimit)
+ if err != nil {
+ t.Fatal(err)
+ }
+ for _, c := range d.Candidates {
+ if c.Generation == "old" {
+ t.Fatalf("the generation a live manifest names is a candidate: %+v", d.Candidates)
+ }
+ }
+ for _, k := range old {
+ if _, ok := f.bucket.Current("data", k); !ok {
+ t.Fatalf("%s was parked", k)
+ }
+ }
+ // Seen from a region that is not authoritative, nothing is read.
+ other, err := movesParkView(f.provider().Records, f.bucket, "data", "uk")(t.Context(), f.observe(t))
+ if err != nil || len(other.Pinned) != 0 || other.MarkerKnown {
+ t.Fatalf("the uk view %+v, %v", other, err)
+ }
+ })
+ t.Run("no manifest", func(t *testing.T) {
+ f, e, old := setup(t, false)
+ if _, err := e.Sweep(t.Context(), evHost, f.inc, evAt, hostbox.RequestLimit); err != nil && !errors.Is(err, park.ErrPending) {
+ t.Fatal(err)
+ }
+ for _, k := range old {
+ if _, ok := f.bucket.Current("data", k); ok {
+ t.Fatalf("%s was not parked", k)
+ }
+ }
+ })
+ t.Run("a manifest naming what the location does not hold", func(t *testing.T) {
+ for name, key := range map[string]string{"outside the location": "instances/" + evHost + "/elsewhere/x", "missing": "LOC/files/g-old/objects/0000000000000009-zz"} {
+ f, e, _ := setup(t, false)
+ filesManifest(t, func(k string, b []byte) { f.bucket.Put("data", k, b) }, f.location, evMoveID, "x="+strings.Replace(key, "LOC", f.location, 1))
+ if _, err := e.View(t.Context(), f.observe(t)); !errors.Is(err, park.ErrUnsafe) {
+ t.Fatalf("%s: %v", name, err)
+ }
+ }
+ })
+}
+
+// TestFilesLiveSetIsProtectedOnTheSourceUntilTheCommit (J2/F4): once the
+// target's probe is admitted the target's region is authoritative, but seen
+// from the source's region the source stays authoritative until the record
+// commits, with its own live manifests pinned; after the commit the source
+// pins nothing (P6-D3: the target's manifests name no source object), and
+// its location park may run.
+func TestFilesLiveSetIsProtectedOnTheSourceUntilTheCommit(t *testing.T) {
+ f := newVwFixture(t)
+ f.marker(t, "cur", f.inc)
+ src := f.location + "/files/g-cur/objects/0000000000000001-aa"
+ ver := f.bucket.Put("data", src, []byte("source file"))
+ filesManifest(t, func(k string, b []byte) { f.bucket.Put("data", k, b) }, f.location, "cur", "a.txt="+src)
+ landing := func(phase string) hostclaim.Observed {
+ return vwObs(&hostclaim.Claim{Holder: f.holder(vwMove, "cur@ie", vwMove+"@uk"), Op: hostclaim.Op{Kind: hostclaim.KindLanding, ID: vwMove, Phase: phase, Exec: "uk-box"}})
+ }
+ f.move(provision.MoveLanding)
+ v, err := f.view("ie")(t.Context(), landing(provision.LandProbed))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if v.AuthoritativeRegion != "ie" || !v.Pinned[park.Ref{Key: src, VersionID: ver}] {
+ t.Fatalf("before the commit the source's view %+v", v)
+ }
+ if v, err := f.view("uk")(t.Context(), landing(provision.LandProbed)); err != nil || v.AuthoritativeRegion != "uk" {
+ t.Fatalf("before the commit the target's view %+v, %v", v, err)
+ }
+ f.move(provision.MoveCommitted)
+ v, err = f.view("ie")(t.Context(), landing(hostclaim.PhaseCommitted))
+ if err != nil || v.AuthoritativeRegion != "uk" || len(v.Pinned) != 0 {
+ t.Fatalf("after the commit the source's view %+v, %v", v, err)
+ }
+}
+
+// TestLandingResidueParkKeepsTheFilesLiveSet (M10, the landing install's
+// park): after the target's probe makes its generation live, a residue
+// chore's acknowledgement re-lists the location under the real view. An
+// object of the residue generation that the live generation's manifest names
+// refuses the acknowledgement and stays; without that reference the same
+// object is parked.
+func TestLandingResidueParkKeepsTheFilesLiveSet(t *testing.T) {
+ for _, named := range []bool{true, false} {
+ t.Run(fmt.Sprintf("named %v", named), func(t *testing.T) {
+ ctx := context.Background()
+ h := newLandingHarness(t)
+ h.flip(t)
+ h.residue(t)
+ h.land(t)
+ h.installed(t)
+ // The probe's admission: g-<move id> live in uk, its marker
+ // published, a files manifest that names an object under the
+ // earlier stay's generation (written back after the parking).
+ late := cutRoot + "/files/g-old/objects/0000000000000003-cc"
+ if _, err := h.vs.PutIfAbsent(ctx, "data-uk", late, []byte("kept")); err != nil {
+ t.Fatal(err)
+ }
+ if named {
+ filesManifest(t, func(k string, b []byte) {
+ if _, err := h.vs.PutIfAbsent(ctx, "data-uk", k, b); err != nil {
+ t.Fatal(err)
+ }
+ }, cutRoot, p1ID, "kept.txt="+late)
+ }
+ marker := cutRoot + "/generation.json"
+ markerVer := h.f.nextVersion()
+ body, _ := json.Marshal(map[string]any{"op": p1ID, "incarnation": h.inc, "host": p1Host, "box": "uk-box", "installed_at": h.clock.Now(), "manifest_sha256": "x", "snapshot_txid": 1})
+ h.f.store("data-uk", marker, fakeMoveObject{lease.MirrorObject{ETag: "etag-" + markerVer, Size: int64(len(body))}, string(body)})
+ h.f.setVersion("data-uk", marker, markerVer)
+ rewriteP1Claim(t, h.s, func(c *hostclaim.Claim) {
+ c.Holder.Generation = p1ID
+ c.Holder.Admissions = append(c.Holder.Admissions, hostclaim.AdmissionRecord{Region: "uk", PredecessorRegion: "ie", Session: c.Holder.Session + 1, Box: "uk-box", Generation: p1ID, Predecessor: "cur", Mode: "cold"})
+ })
+ releaseOwnLease(h.lw, p1Host)
+ h.clock.Advance(park.SignatureAge + landingRequestLimit + time.Minute)
+ l := &landingRun{w: h.lw, s: h.s, rec: h.read(t, p1Host), g: provision.MoveGuard{ID: p1ID, Incarnation: h.inc}}
+ eng := park.Engine{Store: h.vs, Claims: h.s, Bucket: "data-uk", Region: "uk", Leases: h.leases, Now: h.clock.Now, NewID: obligationID,
+ View: movesParkView(MovesRecordsFrom(h.s), h.vs, "data-uk", "uk"), Authorize: movesArmAuthorize(allowParkAuthorize, l.authorizeObligation)}
+ var runErr error
+ for _, o := range h.claim(t).Obligations {
+ if o.Kind == "park-generation" && o.Generation == "old" {
+ for i := 0; i < 3; i++ {
+ runErr = eng.Run(ctx, park.Work{Host: p1Host, ID: o.ID, Op: p1ID})
+ }
+ }
+ }
+ _, kept := h.f.buckets["data-uk"][late]
+ if named {
+ if !errors.Is(runErr, park.ErrUnsafe) || !kept {
+ t.Fatalf("a named object: run %v, kept %v", runErr, kept)
+ }
+ return
+ }
+ if kept {
+ t.Fatalf("an unnamed residue object stayed (run %v)", runErr)
+ }
+ })
+ }
+}
+
+// TestReturnResidueParkKeepsTheFilesLiveSet (M10, the rollback return's
+// park): once the source's probe admits the return generation the source is
+// authoritative again, and its live manifest's objects are pinned, also
+// under a pre-move generation; before that admission the target is
+// authoritative and the source pins nothing (the dirty return parks the
+// pre-move generations, D6).
+func TestReturnResidueParkKeepsTheFilesLiveSet(t *testing.T) {
+ f := newVwFixture(t)
+ f.rec.Move = &provision.MoveState{ID: vwMove, Incarnation: f.inc, From: "ie", To: "uk", State: provision.MoveRollingBack,
+ Rollback: &provision.MoveRollback{ID: vwRb, Dirty: true}}
+ body, _ := json.Marshal(map[string]any{"op": vwRb, "incarnation": f.inc, "host": vwHost, "box": "ie-box", "installed_at": vwCreated, "manifest_sha256": "x", "snapshot_txid": 1})
+ f.bucket.Put("data", f.location+"/generation.json", body)
+ pre := f.location + "/files/g-cur/objects/0000000000000001-aa"
+ ver := f.bucket.Put("data", pre, []byte("pre-move"))
+ filesManifest(t, func(k string, b []byte) { f.bucket.Put("data", k, b) }, f.location, vwRb, "a.txt="+pre)
+ restoring := func(gen string, admissions ...string) hostclaim.Observed {
+ return vwObs(&hostclaim.Claim{Holder: f.holder(gen, admissions...), Op: hostclaim.Op{Kind: hostclaim.KindRestoring, ID: vwMove, Phase: hostclaim.PhaseProbing, Exec: "ie-box"}})
+ }
+ v, err := f.view("ie")(t.Context(), restoring(vwRb, "cur@ie", vwMove+"@uk", vwRb+"@ie"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ if v.AuthoritativeRegion != "ie" || !v.Pinned[park.Ref{Key: pre, VersionID: ver}] {
+ t.Fatalf("after the source's admission %+v", v)
+ }
+ v, err = f.view("ie")(t.Context(), restoring(vwMove, "cur@ie", vwMove+"@uk"))
+ if err != nil || v.AuthoritativeRegion != "uk" || len(v.Pinned) != 0 {
+ t.Fatalf("before the source's admission %+v, %v", v, err)
+ }
+}
diff --git a/internal/host/movessources.go b/internal/host/movessources.go
index e08001fa6..6743106f0 100644
--- a/internal/host/movessources.go
+++ b/internal/host/movessources.go
@@ -36,6 +36,7 @@ import (
"encoding/json"
"errors"
"fmt"
+ "os"
"strings"
"time"
@@ -43,6 +44,7 @@ import (
"github.com/carlosframework/platform/internal/genselect"
"github.com/carlosframework/platform/internal/hostbox"
"github.com/carlosframework/platform/internal/hostclaim"
+ "github.com/carlosframework/platform/internal/hostfiles"
"github.com/carlosframework/platform/internal/hostwrite"
"github.com/carlosframework/platform/internal/lease"
"github.com/carlosframework/platform/internal/moves"
@@ -111,7 +113,7 @@ func movesParkView(records MovesRecordReader, data genselect.Reader, bucket, reg
if obs.Absent || obs.Claim == nil || obs.ETag == "" || obs.Host == "" || obs.Claim.Host != obs.Host {
return park.View{}, park.ErrUnsafe
}
- auth, err := movesAuthoritative(ctx, records, obs)
+ auth, err := movesAuthoritative(ctx, records, obs, region)
if err != nil {
return park.View{}, err
}
@@ -132,10 +134,104 @@ func movesParkView(records MovesRecordReader, data genselect.Reader, bucket, reg
if err := readMarker(ctx, data, bucket, obs.Host, location, *h, listing, &v); err != nil {
return park.View{}, err
}
+ if err := pinFilesLiveSet(ctx, data, bucket, location, listing, &v, h.Generation, v.MarkerGeneration); err != nil {
+ return park.View{}, err
+ }
return v, nil
}
}
+// pinFilesLiveSet pins the files live set (J2/F4, Paul's #236 ruling; M10):
+// every exact version an object a live generation's files manifest names,
+// read through hostfiles.Load by the version the listing names. The live
+// generations are the holder's and the marker's. The rule is M10's: spec
+// §6.6 P6-D3 says a target's manifest never references a source-region
+// object, so a manifest in this region's bucket names objects in this
+// region's bucket, and a region pins only what its own live manifests name.
+// With no manifest, nothing more is pinned. A manifest that names an object
+// outside the location, or one the listing does not hold, refuses.
+func pinFilesLiveSet(ctx context.Context, data genselect.Reader, bucket, location string, listing []lease.ObjectVersion, v *park.View, generations ...string) error {
+ seen := map[string]bool{}
+ for _, gen := range generations {
+ if gen == "" || gen == hostclaim.RootGeneration || gen == landingMarkerGeneration || seen[gen] {
+ continue
+ }
+ seen[gen] = true
+ prefix := location + "/files/g-" + gen + "/"
+ key := hostfiles.ManifestKey(prefix)
+ var current *lease.ObjectVersion
+ for i := range listing {
+ if listing[i].Key == key && listing[i].IsLatest {
+ current = &listing[i]
+ }
+ }
+ if current == nil {
+ continue
+ }
+ if current.DeleteMarker || current.VersionID == "" || current.VersionID == "null" {
+ return fmt.Errorf("%w: %s is not a readable version", park.ErrUnsafe, key)
+ }
+ m, found, err := hostfiles.Load(ctx, versionStore{data: data, bucket: bucket, key: key, version: current.VersionID}, prefix)
+ if err != nil || !found {
+ return fmt.Errorf("%w: the files manifest %s: %v", park.ErrUnsafe, key, err)
+ }
+ for _, entries := range []map[string]hostfiles.Entry{m.Entries, m.Platform} {
+ for path, e := range entries {
+ if e.Object == "" || e.Deleted {
+ continue
+ }
+ if !strings.HasPrefix(e.Object, location+"/") {
+ return fmt.Errorf("%w: %s names %s for %s, outside %s", park.ErrUnsafe, key, e.Object, path, location)
+ }
+ if _, ok := v.GenerationOf(park.Ref{Key: e.Object}); !ok {
+ return fmt.Errorf("%w: %s names %s, which belongs to no generation", park.ErrUnsafe, key, e.Object)
+ }
+ pinned := false
+ for _, x := range listing {
+ if x.Key == e.Object && !x.DeleteMarker && x.VersionID != "" {
+ if v.Pinned == nil {
+ v.Pinned = map[park.Ref]bool{}
+ }
+ v.Pinned[park.Ref{Key: x.Key, VersionID: x.VersionID}] = true
+ pinned = true
+ }
+ }
+ if !pinned {
+ return fmt.Errorf("%w: %s names %s, which the bucket does not hold", park.ErrUnsafe, key, e.Object)
+ }
+ }
+ }
+ }
+ return nil
+}
+
+// versionStore is a read-only release.Store over one object read by the
+// exact version a listing named: hostfiles.Load's reader for a manifest.
+type versionStore struct {
+ data genselect.Reader
+ bucket, key, version string
+}
+
+func (s versionStore) Get(ctx context.Context, key string) ([]byte, string, error) {
+ if key != s.key {
+ return nil, "", os.ErrNotExist
+ }
+ body, err := s.data.GetVersion(ctx, s.bucket, key, s.version)
+ return body, s.version, err
+}
+func (versionStore) Put(context.Context, string, []byte, string) (string, error) {
+ return "", errors.New("host: the park view reads only")
+}
+func (versionStore) List(context.Context, string) ([]string, error) {
+ return nil, errors.New("host: the park view reads only")
+}
+func (versionStore) ListDirs(context.Context, string) ([]string, error) {
+ return nil, errors.New("host: the park view reads only")
+}
+func (versionStore) Delete(context.Context, string) error {
+ return errors.New("host: the park view reads only")
+}
+
// readMarker fills the marker and the installed root's pin from the
// location's generation.json, read by the exact version the listing names.
func readMarker(ctx context.Context, data genselect.Reader, bucket, host, location string, h hostclaim.Holder, listing []lease.ObjectVersion, v *park.View) error {
@@ -192,7 +288,10 @@ func readMarker(ctx context.Context, data genselect.Reader, bucket, host, locati
// - moving (before the flip), reverting: the source's, move.from;
// - landing: the source's until the target's probe is admitted into
// holder.generation in move.to, the target's from then on, committed or
-// not; a committed landing with no such admission refuses;
+// not; a committed landing with no such admission refuses. Seen from
+// the source's own region, the source stays authoritative until the
+// record commits (J2/F4: its files live set is protected on the source
+// until the commit);
// - restoring: the region of the newest admission into holder.generation,
// the source's or the target's (a clean return's CAS names the source's
// generation again, a dirty return keeps the target's until the source's
@@ -202,7 +301,7 @@ func readMarker(ctx context.Context, data genselect.Reader, bucket, host, locati
// (the record-first close, M4), when the newest admission decides alone. A
// region the claim's history contradicts refuses. So does any other kind
// (placing, relocating): it has no row in the table.
-func movesAuthoritative(ctx context.Context, records MovesRecordReader, obs hostclaim.Observed) (string, error) {
+func movesAuthoritative(ctx context.Context, records MovesRecordReader, obs hostclaim.Observed, region string) (string, error) {
c := obs.Claim
h := c.Holder
if h == nil {
@@ -263,6 +362,15 @@ func movesAuthoritative(ctx context.Context, records MovesRecordReader, obs host
return "", err
}
if known && admitted == m.To {
+ if region == m.From && c.Op.Phase != hostclaim.PhaseCommitted && m.State != provision.MoveCommitted {
+ // J2/F4 (Paul's #236 ruling): the source's live set, its
+ // files live set among it, stays protected on the source
+ // until the record commits. Seen from the source's region the
+ // source stays authoritative, so the engine protects there
+ // too (and refuses a park of the location, whose current
+ // generation the source's marker does not name).
+ return m.From, nil
+ }
return m.To, nil
}
if c.Op.Phase == hostclaim.PhaseCommitted || m.State == provision.MoveCommitted {
diff --git a/internal/provision/plan9_b8_census_test.go b/internal/provision/plan9_b8_census_test.go
index 8f90460d3..e0af6c4e4 100644
--- a/internal/provision/plan9_b8_census_test.go
+++ b/internal/provision/plan9_b8_census_test.go
@@ -523,6 +523,8 @@ var plan9B8CensusInventory = []censusEntry{
{"internal/host/movessources.go", "holderRecord", "key-site", "key:RecordKey", "84e840552703cd9863c9b27786baa864109e94d15b9e6f3e035c0da18622eb2e"},
// The moves lease set's scope shapes (Plan 5 Task 9a, M6): instances/<host>[/<incarnation>] and moves/<host>[/<op>] are data-bucket lock prefixes; a pure string check.
{"internal/host/movessources.go", "movesLeaseScope", "key-site", "lit:instances", "7a5b9e07b4bb754c9edf0bb5c3e828f79262d195d764e6d51608518e86ed6183"},
+ // The park view's read-only store over one manifest version (Plan 5 Task 9a, M10): Put refuses and writes nothing.
+ {"internal/host/movessources.go", "versionStore.Put", "nonrecord", "def:Put", "a540f7fd383ea728f93a9eacb0d03ec1b8dcefcf20ade117831d0dd28faad2da"},
// Copies config acknowledgements to moves/<account>/<app>/<host>/<op>/config-ack-source.json.
{"internal/host/movesfinal.go", "sourceFinal.configAck", "nonrecord", "sel:Put", "cca53109e6945a73b7f04705d8965b3b0997f2b7d2a82fa6d86cffa4b4174e93"},
// Stamps source_parked_at through SetRecordMove, updateRecord and WriteRecord.