carlos / platform Public

host: movesOriginProof is the only route to origin proof, bound to the observation (Task 6 fix round 4)

Chain prefixes entered the allowed set directly and the prepared path
appended its generation to that unchecked chain, so a proof answering
false or an error for them was ignored. Every accepted origin now goes
through proveOrigin, which asks movesOriginProof: the candidate
generations (the retained chain and the generation the admission opens
or the prepared one), every origin the manifest names and every origin
it carries; the empty and never-published starts prove the new
generation the same way. chainOriginProof still proves them today; a
different proof, claim Plan 15's, has the final say.

platform-1e's condition: chainOriginProof never accepts a bare
Admission.NewGeneration supplied on its own. A generation is proven
only when the bound observation's retained chain records it, which the
post-admission observation Materialize is given does (the CAS result
Writer.Admit returns, BindWakeRetrySession's result, or the resumed
recovery's current observation checked against its journal). The
Establish tests now model that observation: the holder at the admitted
generation with its admission recorded.

Regressions: a proof answering false, and one answering an error, for a
chain-prefix origin and for the prepared generation's origin, each
refusing with nothing written; a free-standing generation with no bound
observation refused at the proof and by Establish; the Plan 15 stand-in
in the pruned-ancestor test records the admitted generation too.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 6bb9d4171e5e4fcf7e2130a89ed403c88bf4c5bf parent 1b35a7a
2 files changed, +208 −51
  • internal/host/movesfiles.go +66 −32
  • internal/host/movesfiles_test.go +142 −19
diff --git a/internal/host/movesfiles.go b/internal/host/movesfiles.go
index c6057687e..d62d33396 100644
--- a/internal/host/movesfiles.go
+++ b/internal/host/movesfiles.go
@@ -398,7 +398,7 @@ func (f *movesFiles) newestManifest(ctx context.Context, o hostclaim.Observed, i
if !found {
return hostfiles.Manifest{}, nil, false, fmt.Errorf("host: the files manifest %s@%s is not readable", key, version)
}
- allowed, err := f.movesFilesAllowed(ctx, o, in, location, chain, m)
+ allowed, err := f.movesFilesAllowed(ctx, o, in, location, append(append([]string(nil), chain...), in.NewGeneration), m)
if err != nil {
return hostfiles.Manifest{}, nil, false, fmt.Errorf("host: the files manifest %s@%s: %w", key, version, err)
}
@@ -420,18 +420,21 @@ type movesOriginProof interface {
Proven(ctx context.Context, o hostclaim.Observed, in hostclaim.Admission, generation string) (bool, error)
}
-// chainOriginProof proves a generation by the retained admission chain
-// (movesFilesChain: the holder's generation and each cold admission's
-// predecessor in this region), and the generation the admission in hand
-// opens: the claim's AdmitWriter CAS recorded that admission before the
-// start's Materialize runs.
+// chainOriginProof proves a generation by the retained admission chain of
+// the bound observation alone (movesFilesChain: the observed holder's
+// generation and each cold admission's predecessor in this region). It
+// never accepts a bare Admission.NewGeneration supplied on its own
+// (platform-1e's condition, fix round 4): the generation an admission
+// opens is proven only once the observation the caller holds records it,
+// which is the observation Materialize is given (the CAS result
+// Writer.Admit returns, BindWakeRetrySession's result, or the resumed
+// recovery's current observation checked against its journal), where the
+// holder's generation is that one. A free-standing generation with no such
+// observation is not proven.
type chainOriginProof struct{ home, region string }
-func (p chainOriginProof) Proven(_ context.Context, o hostclaim.Observed, in hostclaim.Admission, generation string) (bool, error) {
- if generation != "" && generation == in.NewGeneration {
- return true, nil
- }
- if o.Claim == nil || o.Claim.Holder == nil {
+func (p chainOriginProof) Proven(_ context.Context, o hostclaim.Observed, _ hostclaim.Admission, generation string) (bool, error) {
+ if generation == "" || o.Absent || o.Claim == nil || o.Claim.Holder == nil {
return false, nil
}
return slices.Contains(movesFilesChain(o.Claim.Holder, p.home, p.region), generation), nil
@@ -444,20 +447,47 @@ func (f *movesFiles) proof() movesOriginProof {
return chainOriginProof{home: f.HomeRegion, region: f.Region}
}
+// proveOrigin is the one route to origin proof (fix round 4): the
+// generation's files prefix under location enters an allowed set only
+// when movesOriginProof proves the generation. A proof that answers false
+// is ErrOrigin; an error is the error. Nothing enters a set any other way,
+// so a different proof (claim Plan 15's) has the final say over the
+// chain's generations and the prepared generation as over every other.
+func (f *movesFiles) proveOrigin(ctx context.Context, o hostclaim.Observed, in hostclaim.Admission, location, gen string) (string, error) {
+ if !movesFilesGeneration(gen) {
+ return "", fmt.Errorf("%w: %q is not a generation name", hostfiles.ErrOrigin, gen)
+ }
+ origin := movesFilesPrefix(location, gen)
+ proven, err := f.proof().Proven(ctx, o, in, gen)
+ if err != nil {
+ return "", fmt.Errorf("prove the origin %s: %w", origin, err)
+ }
+ if !proven {
+ return "", fmt.Errorf("%w: %s is not proven by the claim's recorded admissions", hostfiles.ErrOrigin, origin)
+ }
+ return origin, nil
+}
+
// movesFilesAllowed is the origin set an admission allows for m, the
-// manifest it establishes from: every origin m's entries name, every
-// origin m carries (Manifest.Origins, a hint and nothing more), and the
-// generations admitted in the current chain, each proven against the
-// claim's records (movesOriginProof) after the location rule
-// (movesFilesOrigins). A named or carried origin the claim cannot prove is
-// ErrOrigin, whatever its name and whether an entry uses it: a manifest
-// that adds a never-granted origin to its own set is refused. Then
-// ValidateManifest over the proven set. The new manifest's set is this plus
-// its own prefix (SetOrigins).
-func (f *movesFiles) movesFilesAllowed(ctx context.Context, o hostclaim.Observed, in hostclaim.Admission, location string, chain []string, m hostfiles.Manifest) ([]string, error) {
+// manifest it establishes from: the candidate generations (the admitted
+// chain, and the generation this admission opens or the prepared one),
+// every origin m's entries name, and every origin m carries
+// (Manifest.Origins, a hint and nothing more), each proven against the
+// claim's records through proveOrigin, the chain's generations included,
+// after the location rule (movesFilesOrigins). A generation or origin the
+// proof cannot prove is ErrOrigin, whatever its name and whether an entry
+// uses it: a manifest that adds a never-granted origin to its own set is
+// refused, and so is a chain the proof no longer vouches for. Then
+// ValidateManifest over the proven set, which is the new manifest's set
+// (SetOrigins).
+func (f *movesFiles) movesFilesAllowed(ctx context.Context, o hostclaim.Observed, in hostclaim.Admission, location string, candidates []string, m hostfiles.Manifest) ([]string, error) {
set := map[string]bool{}
- for _, g := range chain {
- set[movesFilesPrefix(location, g)] = true
+ for _, g := range candidates {
+ origin, err := f.proveOrigin(ctx, o, in, location, g)
+ if err != nil {
+ return nil, err
+ }
+ set[origin] = true
}
named, err := movesFilesOrigins(location, "", m)
if err != nil {
@@ -473,12 +503,8 @@ func (f *movesFiles) movesFilesAllowed(ctx context.Context, o hostclaim.Observed
if !under || !slash || !movesFilesGeneration(gen) {
return nil, fmt.Errorf("%w: %s is not a generation's files prefix of %s", hostfiles.ErrOrigin, origin, location)
}
- proven, err := f.proof().Proven(ctx, o, in, gen)
- if err != nil {
- return nil, fmt.Errorf("prove the origin %s: %w", origin, err)
- }
- if !proven {
- return nil, fmt.Errorf("%w: %s is not proven by the claim's recorded admissions", hostfiles.ErrOrigin, origin)
+ if _, err := f.proveOrigin(ctx, o, in, location, gen); err != nil {
+ return nil, err
}
set[origin] = true
}
@@ -790,11 +816,15 @@ func (f *movesFiles) Establish(ctx context.Context, o hostclaim.Observed, in Cla
return err
}
case in.Empty:
+ own, err := f.proveOrigin(ctx, o, in.Admission, h.Location, gen)
+ if err != nil {
+ return err
+ }
p, err = hostfiles.NewFromCopy(files, prefix, emptyManifest(), nil)
if err != nil {
return err
}
- p.SetOrigins([]string{prefix})
+ p.SetOrigins([]string{own})
default:
base, origins, found, err := f.newestManifest(ctx, o, in.Admission, h.Location, movesFilesChain(h, f.HomeRegion, f.Region))
if err != nil {
@@ -812,13 +842,17 @@ func (f *movesFiles) Establish(ctx context.Context, o hostclaim.Observed, in Cla
if !never {
return fmt.Errorf("%w: no files manifest in the admitted predecessor chain of %s (%s)", hostfiles.ErrNoEvidence, o.Host, h.Generation)
}
- base, origins = emptyManifest(), nil
+ own, err := f.proveOrigin(ctx, o, in.Admission, h.Location, gen)
+ if err != nil {
+ return err
+ }
+ base, origins = emptyManifest(), []string{own}
}
p, err = hostfiles.NewFromCopy(files, prefix, base, origins)
if err != nil {
return err
}
- p.SetOrigins(append(origins, prefix))
+ p.SetOrigins(origins)
}
if err := p.StagePlatform(ctx, hostfiles.EnvItem, env); err != nil {
return err
diff --git a/internal/host/movesfiles_test.go b/internal/host/movesfiles_test.go
index 1e8f882c8..cf8e51ce6 100644
--- a/internal/host/movesfiles_test.go
+++ b/internal/host/movesfiles_test.go
@@ -450,7 +450,7 @@ func TestEstablishCopiesTheNewestValidManifestByExactVersion(t *testing.T) {
if g1.Seq != 3 {
t.Fatalf("g1 at seq %d", g1.Seq)
}
- o := servingObserved("g2", "g1:uk:@root:uk", "g2:uk:g1:uk")
+ o := servingObserved("g3", "g1:uk:@root:uk", "g2:uk:g1:uk", "g3:uk:g2:uk")
if err := x.f.Establish(ctx, o, launchInputs("g3"), x); err != nil {
t.Fatal(err)
}
@@ -527,12 +527,13 @@ func TestEstablishKeepsOriginsPastAdmissionPruning(t *testing.T) {
prev, _ = x.manifest(gen)
gens = append(gens, gen)
}
- // The holder at g10 with the eight newest admissions only: g3..g10.
+ // The observation Materialize is given: g11 admitted, the holder at
+ // g11, the eight newest admissions only: g4..g11.
var chain []string
- for i := 3; i <= 10; i++ {
+ for i := 4; i <= 11; i++ {
chain = append(chain, fmt.Sprintf("g%d:uk:g%d:uk", i, i-1))
}
- o := servingObserved("g10", chain...)
+ o := servingObserved("g11", chain...)
if len(o.Claim.Holder.Admissions) != 8 {
t.Fatalf("%d admissions", len(o.Claim.Holder.Admissions))
}
@@ -548,7 +549,7 @@ func TestEstablishKeepsOriginsPastAdmissionPruning(t *testing.T) {
if _, found := x.manifest("g11"); found {
t.Fatal("a manifest was written over an unproven ancestor")
}
- x.f.Proof = recordedOrigins{"g1": true, "g2": true, "g3": true, "g4": true, "g5": true, "g6": true, "g7": true, "g8": true, "g9": true, "g10": true}
+ x.f.Proof = recordedOrigins{"g1": true, "g2": true, "g3": true, "g4": true, "g5": true, "g6": true, "g7": true, "g8": true, "g9": true, "g10": true, "g11": true}
if err := x.f.Establish(ctx, o, launchInputs("g11"), x); err != nil {
t.Fatalf("establish past pruning with the claim's record: %v", err)
}
@@ -624,7 +625,7 @@ func preparedFixture(t *testing.T) (*filesFixture, preparedManifest, hostclaim.O
}
x.journal("mv1", pm)
x.writeEnv("K=1\nCARLOS_INSTANCE_KEY=abc\n")
- o := servingObserved("cur", "cur:ie:@root:ie")
+ o := servingObserved("mv1", "cur:ie:@root:ie", "mv1:uk:cur:ie")
o.Claim.Op = hostclaim.Op{Kind: hostclaim.KindLanding, ID: "mv1", Phase: "probing", Exec: "uk-box"}
in := launchInputs("mv1")
in.Prepared = true
@@ -778,7 +779,7 @@ func TestEstablishPublishesOutsideTheStartsWork(t *testing.T) {
})
st := &stallingStore{Store: x.files, key: hostfiles.ManifestKey(movesFilesPrefix(filesLoc, "g2")), stalled: make(chan struct{}), release: make(chan struct{})}
x.f.Files = st
- o := servingObserved("g1", "g1:uk:@root:uk")
+ o := servingObserved("g2", "g1:uk:@root:uk", "g2:uk:g1:uk")
done := make(chan error, 1)
go func() { done <- x.f.Establish(ctx, o, launchInputs("g2"), x) }()
select {
@@ -836,7 +837,7 @@ func TestEstablishRefusesANeverAdmittedOrigin(t *testing.T) {
t.Fatal(err)
}
})
- o := servingObserved("g1", "g1:uk:@root:uk")
+ o := servingObserved("g2", "g1:uk:@root:uk", "g2:uk:g1:uk")
never := movesFilesPrefix(filesLoc, "never") + "objects/0000000000000001-" + sha([]byte("N"))
x.bucket.Put("data", never, []byte("N"))
for name, origins := range map[string][]string{"no carried set": nil, "a carried set without it": {movesFilesPrefix(filesLoc, "g1")}} {
@@ -907,7 +908,7 @@ func TestEstablishSeedsALegacyLocationsOriginSet(t *testing.T) {
if old.Origins != nil {
t.Fatalf("the legacy manifest carries a set: %v", old.Origins)
}
- o := servingObserved("g1", "g1:uk:@root:uk")
+ o := servingObserved("g2", "g1:uk:@root:uk", "g2:uk:g1:uk")
o.Claim.Holder.Location = legacy
if err := x.f.Establish(ctx, o, launchInputs("g2"), x); err != nil {
t.Fatal(err)
@@ -921,8 +922,11 @@ func TestEstablishSeedsALegacyLocationsOriginSet(t *testing.T) {
}
bad := old
bad.Entries = map[string]hostfiles.Entry{"n.txt": {Object: loc("never") + "objects/0000000000000001-" + sha([]byte("N")), SHA256: sha([]byte("N")), Size: 1, Seq: 1}}
- x.bucket.Put("data", hostfiles.ManifestKey(loc("g1")), mustJSON(t, bad))
- if err := x.f.Establish(ctx, o, launchInputs("g3"), x); !errors.Is(err, hostfiles.ErrOrigin) {
+ // Planted at g2, the newest manifest the chain from g3 reads.
+ x.bucket.Put("data", hostfiles.ManifestKey(loc("g2")), mustJSON(t, bad))
+ o3 := servingObserved("g3", "g1:uk:@root:uk", "g2:uk:g1:uk", "g3:uk:g2:uk")
+ o3.Claim.Holder.Location = legacy
+ if err := x.f.Establish(ctx, o3, launchInputs("g3"), x); !errors.Is(err, hostfiles.ErrOrigin) {
t.Fatalf("never admitted under a legacy location: %v", err)
}
}
@@ -936,6 +940,126 @@ func (r recordedOrigins) Proven(_ context.Context, _ hostclaim.Observed, _ hostc
return r[generation], nil
}
+// answeringProof is a claim-backed origin proof with an answer per
+// generation: proven, not proven, or an error; a generation it does not
+// name is not proven.
+type answeringProof struct {
+ proven map[string]bool
+ errs map[string]error
+}
+
+func (a answeringProof) Proven(_ context.Context, _ hostclaim.Observed, _ hostclaim.Admission, generation string) (bool, error) {
+ if err := a.errs[generation]; err != nil {
+ return false, err
+ }
+ return a.proven[generation], nil
+}
+
+// movesOriginProof is the only route to origin proof (fix round 4): the
+// chain's prefixes and the prepared generation go through Proven like
+// every other origin, so a different proof (claim Plan 15's) has the final
+// say. A proof that answers false, or an error, for a chain-prefix origin
+// or for the prepared generation's origin refuses the establishment and
+// nothing is written.
+func TestEstablishProvesEveryOriginThroughTheProof(t *testing.T) {
+ ctx := context.Background()
+ for name, mk := range map[string]func(gen string) answeringProof{
+ "not proven": func(gen string) answeringProof { return answeringProof{proven: map[string]bool{}} },
+ "an error": func(gen string) answeringProof {
+ return answeringProof{errs: map[string]error{gen: errors.New("the record is unreadable")}}
+ },
+ } {
+ t.Run("a chain prefix, "+name, func(t *testing.T) {
+ x := newFilesFixture(t)
+ x.writeEnv("K=1\n")
+ x.publish("g1", func(p *hostfiles.Publisher) {
+ if err := p.Stage(ctx, "a.txt", []byte("A"), 0o600, false); err != nil {
+ t.Fatal(err)
+ }
+ })
+ o := servingObserved("g2", "g1:uk:@root:uk", "g2:uk:g1:uk")
+ proof := mk("g1")
+ proof.proven = map[string]bool{"g2": true}
+ x.f.Proof = proof
+ err := x.f.Establish(ctx, o, launchInputs("g2"), x)
+ if err == nil || (name == "not proven" && !errors.Is(err, hostfiles.ErrOrigin)) {
+ t.Fatalf("a chain prefix the proof does not prove: %v", err)
+ }
+ if _, found := x.manifest("g2"); found {
+ t.Fatal("a manifest was written over an unproven chain prefix")
+ }
+ // The new generation itself is proven through the proof too.
+ x.f.Proof = answeringProof{proven: map[string]bool{"g1": true}}
+ if err := x.f.Establish(ctx, o, launchInputs("g2"), x); !errors.Is(err, hostfiles.ErrOrigin) {
+ t.Fatalf("the new generation the proof does not prove: %v", err)
+ }
+ x.f.Proof = answeringProof{proven: map[string]bool{"g1": true, "g2": true}}
+ if err := x.f.Establish(ctx, o, launchInputs("g2"), x); err != nil {
+ t.Fatalf("everything proven: %v", err)
+ }
+ })
+ t.Run("the prepared generation, "+name, func(t *testing.T) {
+ x, pm, o, in := preparedFixture(t)
+ proof := mk("mv1")
+ proof.proven = map[string]bool{"cur": true}
+ x.f.Proof = proof
+ err := x.f.Establish(ctx, o, in, x)
+ if err == nil || (name == "not proven" && !errors.Is(err, hostfiles.ErrOrigin)) {
+ t.Fatalf("the prepared generation the proof does not prove: %v", err)
+ }
+ if x.bucket.LatestID("data", pm.Key) != pm.Version {
+ t.Fatal("the prepared manifest was published over")
+ }
+ x.f.Proof = answeringProof{proven: map[string]bool{"cur": true, "mv1": true}}
+ if err := x.f.Establish(ctx, o, in, x); err != nil {
+ t.Fatalf("everything proven: %v", err)
+ }
+ })
+ }
+}
+
+// chainOriginProof never accepts a bare Admission.NewGeneration supplied
+// on its own (platform-1e's condition, fix round 4): a generation is
+// proven only when the bound observation's retained chain records it, as
+// the post-admission observation Materialize is given does. A
+// free-standing generation, named by the admission but by no observation,
+// is refused at the proof and by Establish, and nothing is written.
+func TestChainProofRefusesAFreeStandingGeneration(t *testing.T) {
+ ctx := context.Background()
+ proof := chainOriginProof{home: "ie", region: "uk"}
+ before := servingObserved("g1", "g1:uk:@root:uk") // the observation before g2's admission
+ in := hostclaim.Admission{Box: "uk-box", Mode: "cold", NewGeneration: "g2", Region: "uk"}
+ if ok, err := proof.Proven(ctx, before, in, "g2"); ok || err != nil {
+ t.Fatalf("a free-standing generation proven: %v %v", ok, err)
+ }
+ if ok, err := proof.Proven(ctx, hostclaim.Observed{Host: filesHost, Absent: true}, in, "g2"); ok || err != nil {
+ t.Fatalf("proven with no claim: %v %v", ok, err)
+ }
+ if ok, _ := proof.Proven(ctx, before, in, "g1"); !ok {
+ t.Fatal("the observed holder's generation is not proven")
+ }
+ after := servingObserved("g2", "g1:uk:@root:uk", "g2:uk:g1:uk") // the CAS result the writer's admission returns
+ if ok, _ := proof.Proven(ctx, after, in, "g2"); !ok {
+ t.Fatal("the admitted generation the observation records is not proven")
+ }
+ x := newFilesFixture(t)
+ x.writeEnv("K=1\n")
+ x.publish("g1", func(p *hostfiles.Publisher) {
+ if err := p.Stage(ctx, "a.txt", []byte("A"), 0o600, false); err != nil {
+ t.Fatal(err)
+ }
+ })
+ if err := x.f.Establish(ctx, before, launchInputs("g2"), x); !errors.Is(err, hostfiles.ErrOrigin) {
+ t.Fatalf("establish with an observation that does not record the admission: %v", err)
+ }
+ if _, found := x.manifest("g2"); found {
+ t.Fatal("a manifest was written for a free-standing generation")
+ }
+ if err := x.f.Establish(ctx, after, launchInputs("g2"), x); err != nil {
+ t.Fatalf("establish with the bound observation: %v", err)
+ }
+}
+
// The instance key rule (O1'): the manifest Establish leaves carries the
// env file with exactly the bytes on disk when it runs, staged and
// committed before it returns, and no adoption item; the local adoption
@@ -957,7 +1081,7 @@ func TestEstablishCarriesTheEnvBytesAndDropsTheAdoptionItem(t *testing.T) {
if err := os.WriteFile(adoption, []byte(`{"v":2}`), 0o600); err != nil {
t.Fatal(err)
}
- o := servingObserved("g1", "g1:uk:@root:uk")
+ o := servingObserved("g2", "g1:uk:@root:uk", "g2:uk:g1:uk")
x.workErr = hostbox.ErrChanged
if err := x.f.Establish(ctx, o, launchInputs("g2"), x); !errors.Is(err, hostbox.ErrChanged) {
t.Fatalf("refused work: %v", err)
@@ -998,7 +1122,7 @@ func TestEstablishCarriesTheEnvBytesAndDropsTheAdoptionItem(t *testing.T) {
if err := os.Remove(x.envPath()); err != nil {
t.Fatal(err)
}
- if err := x.f.Establish(ctx, servingObserved("g2", "g1:uk:@root:uk", "g2:uk:g1:uk"), launchInputs("g3"), x); err == nil {
+ if err := x.f.Establish(ctx, servingObserved("g3", "g1:uk:@root:uk", "g2:uk:g1:uk", "g3:uk:g2:uk"), launchInputs("g3"), x); err == nil {
t.Fatal("established without an env file")
}
if _, found := x.manifest("g3"); found {
@@ -1016,7 +1140,7 @@ func TestEstablishNeverBootstrapsEmpty(t *testing.T) {
x := newFilesFixture(t)
ctx := context.Background()
x.writeEnv("K=1\n")
- o := servingObserved("g2", "g1:uk:@root:uk", "g2:uk:g1:uk")
+ o := servingObserved("g3", "g1:uk:@root:uk", "g2:uk:g1:uk", "g3:uk:g2:uk")
// No manifest anywhere, no evidence.
if err := x.f.Establish(ctx, o, launchInputs("g3"), x); !errors.Is(err, hostfiles.ErrNoEvidence) {
t.Fatalf("no manifest, no pin: %v", err)
@@ -1048,7 +1172,7 @@ func TestEstablishNeverBootstrapsEmpty(t *testing.T) {
}
// The predecessor lives in another region: its manifest is not in this
// bucket and the chain is not followed there.
- far := servingObserved("g5", "g5:uk:g1:ie")
+ far := servingObserved("g6", "g5:uk:g1:ie", "g6:uk:g5:uk")
if err := x.f.Establish(ctx, far, launchInputs("g6"), x); !errors.Is(err, hostfiles.ErrNoEvidence) {
t.Fatalf("predecessor in another region: %v", err)
}
@@ -1074,7 +1198,7 @@ func TestEstablishHostThatNeverPublishedFiles(t *testing.T) {
x.f.Evidence = func(context.Context, hostclaim.Observed) (hostfiles.PinnedFiles, bool, error) {
return hostfiles.PinnedFiles{}, true, nil
}
- o := servingObserved("g2", "g1:uk:@root:uk", "g2:uk:g1:uk")
+ o := servingObserved("g3", "g1:uk:@root:uk", "g2:uk:g1:uk", "g3:uk:g2:uk")
if err := x.f.Establish(ctx, o, launchInputs("g3"), x); err != nil {
t.Fatal(err)
}
@@ -1085,8 +1209,7 @@ func TestEstablishHostThatNeverPublishedFiles(t *testing.T) {
// The claim's own empty bootstrap: a created incarnation before its
// first writer, admitted after EmptyAuthority.
x.f.Evidence = nil
- empty := servingObserved("")
- empty.Claim.Holder.Session, empty.Claim.Holder.WriterBox = 0, ""
+ empty := servingObserved("g1", "g1:uk:@root:uk") // admitted: the holder at g1 after EmptyAuthority
in := launchInputs("g1")
in.Empty = true
if err := x.f.Establish(ctx, empty, in, x); err != nil {
@@ -1152,7 +1275,7 @@ func TestEstablishOnThePreparedGenerationContinuesFromSequenceZero(t *testing.T)
}
x.journal("mv1", pm)
x.writeEnv("K=1\nCARLOS_INSTANCE_KEY=abc\n")
- o := servingObserved("cur", "cur:ie:@root:ie")
+ o := servingObserved("mv1", "cur:ie:@root:ie", "mv1:uk:cur:ie")
o.Claim.Op = hostclaim.Op{Kind: hostclaim.KindLanding, ID: "mv1", Phase: "probing", Exec: "uk-box"}
in := launchInputs("mv1")
in.Prepared = true