carlos / platform Public

host: a prepared replay must be exactly what this establishment writes, derived from the baseline (Task 6 fix round 3, finding 6)

establishedOver built the expected env object from the replay entry's
own sequence, so a manifest with valid Origins, the prepared entries,
sequence 99 for the manifest and the env entry, the right digest, size
and mode, and P/objects/0000000000000099-<digest> passed although that
object did not exist, and the digest match then let StagePlatform skip
the write.

The expected manifest is now derived from the prepared baseline and the
establishment's own operations by the publisher's rules: from the
prepared sequence, a new env object at the next sequence when the env
bytes differ from the prepared env item, the sequence after for the
adoption item's deletion when the prepared manifest carried one, the
manifest at the last sequence handed out, the entries and other platform
items the prepared ones, the carried set the admitted one. The replay
must equal it field for field, and the env object must be at its key
with the env's digest and size. Nothing is taken from the replay's own
numbers.

Test: the negative cases carry correct Origins (another location,
another generation, the wrong size, torn), plus fabricated sequences
99 and 2 with otherwise valid Origins, and the genuine bytes with their
env object gone; all refused and left as they were. The genuine replay
is accepted and writes nothing.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 404f81fabeb3ccdb3d8e0d941b0ed4df02b4812e parent 31b5919
2 files changed, +94 −65
  • internal/host/movesfiles.go +48 −45
  • internal/host/movesfiles_test.go +46 −20
diff --git a/internal/host/movesfiles.go b/internal/host/movesfiles.go
index a5cb86ef2..a3778611e 100644
--- a/internal/host/movesfiles.go
+++ b/internal/host/movesfiles.go
@@ -545,7 +545,7 @@ func (f *movesFiles) openPrepared(ctx context.Context, files release.Store, o ho
if err != nil || !found {
return nil, fmt.Errorf("host: the files manifest %s: %v", key, err)
}
- if err := establishedOver(h.Location, prefix, allowed, current, prepared, env); err != nil {
+ if err := establishedOver(ctx, files, h.Location, prefix, allowed, current, prepared, env); err != nil {
return nil, fmt.Errorf("%w: the files manifest %s is neither the prepared manifest %s nor this box's establishment of it: %v", hostbox.ErrChanged, key, pm.Version, err)
}
}
@@ -557,44 +557,47 @@ func (f *movesFiles) openPrepared(ctx context.Context, files release.Store, o ho
return p, nil
}
-// establishedOver reports whether cur is an establishment of prepared by
-// this box, in full (fix round 2, finding 6): a later sequence; the same
-// entries and the same platform items apart from the env file and the
-// adoption item; the adoption item gone; cur's origins holding the
-// location rule and every entry validating against them; and the env
-// adoption item gone; the carried origin set exactly the admitted one; cur's origins holding the
-// location rule and every entry validating against them; and the env
-// entry with the complete shape of the object this box's establishment
-// wrote, not merely its digest: the object key under P at the entry's own
-// sequence and digest (what Publisher.put writes), a sequence after the
-// prepared one, env's size and mode, not deleted, torn or skipped. A
-// manifest whose env entry names an object elsewhere, or a different
-// object under P, is not this box's establishment, however its digest
-// reads.
-func establishedOver(location, prefix string, allowed []string, cur, prepared hostfiles.Manifest, env []byte) error {
- if cur.Seq <= prepared.Seq {
- return fmt.Errorf("sequence %d is not after the prepared %d", cur.Seq, prepared.Seq)
- }
- if !reflect.DeepEqual(cur.Origins, allowed) {
- return fmt.Errorf("the carried origin set %v is not the admitted one %v", cur.Origins, allowed)
- }
- if !reflect.DeepEqual(cur.Entries, prepared.Entries) {
- return errors.New("the entries are not the prepared manifest's")
- }
- if _, has := cur.Platform[instancekey.AdoptionItem]; has {
- return errors.New("the adoption item is still carried")
- }
- rest := func(m hostfiles.Manifest) map[string]hostfiles.Entry {
- out := map[string]hostfiles.Entry{}
- for k, v := range m.Platform {
- if k != hostfiles.EnvItem && k != instancekey.AdoptionItem {
- out[k] = v
- }
- }
- return out
- }
- if !reflect.DeepEqual(rest(cur), rest(prepared)) {
- return errors.New("the platform items are not the prepared manifest's")
+// establishedOver reports whether cur is this box's establishment of
+// prepared, in full (fix round 2 finding 6, fix round 3): exactly what
+// this establishment would have written, derived from the prepared
+// baseline and the establishment's own operations by the publisher's
+// rules, never from the replay's own numbers. From prepared's sequence,
+// the env file's bytes take a new object at the next sequence when they
+// differ from prepared's env item; the adoption item's deletion takes the
+// sequence after when prepared carried one; the manifest's sequence is
+// the last handed out; the entries and other platform items are
+// prepared's; the carried set is the admitted one. cur must equal that
+// manifest field for field, and the env object must be at its key with
+// the env's digest. A replay whose env entry names an object elsewhere, a
+// different object under P, or a fabricated sequence whose object does
+// not exist, is not this box's establishment however its digest reads.
+func establishedOver(ctx context.Context, files release.Store, location, prefix string, allowed []string, cur, prepared hostfiles.Manifest, env []byte) error {
+ want := hostfiles.Manifest{V: hostfiles.ManifestVersion, Entries: map[string]hostfiles.Entry{}, Platform: map[string]hostfiles.Entry{}, Origins: allowed}
+ for k, v := range prepared.Entries {
+ want.Entries[k] = v
+ }
+ for k, v := range prepared.Platform {
+ want.Platform[k] = v
+ }
+ next := prepared.Seq
+ envSHA := hostfilesSum(env)
+ if e, ok := prepared.Platform[hostfiles.EnvItem]; !ok || e.SHA256 != envSHA {
+ next++
+ want.Platform[hostfiles.EnvItem] = hostfiles.Entry{Object: fmt.Sprintf("%sobjects/%016d-%s", prefix, next, envSHA), SHA256: envSHA, Size: int64(len(env)), Mode: 0o600, Seq: next}
+ }
+ if _, has := prepared.Platform[instancekey.AdoptionItem]; has {
+ next++
+ delete(want.Platform, instancekey.AdoptionItem)
+ }
+ want.Seq = next
+ if cur.Entries == nil {
+ cur.Entries = map[string]hostfiles.Entry{}
+ }
+ if cur.Platform == nil {
+ cur.Platform = map[string]hostfiles.Entry{}
+ }
+ if !reflect.DeepEqual(cur, want) {
+ return fmt.Errorf("the manifest %+v is not what this establishment writes over the prepared one (%+v)", cur, want)
}
if _, err := movesFilesOrigins(location, prefix, cur); err != nil {
return err
@@ -602,13 +605,13 @@ func establishedOver(location, prefix string, allowed []string, cur, prepared ho
if err := hostfiles.ValidateManifest(cur, allowed); err != nil {
return err
}
- e, ok := cur.Platform[hostfiles.EnvItem]
- if !ok {
- return errors.New("no env item")
+ e := want.Platform[hostfiles.EnvItem]
+ body, _, err := files.Get(ctx, e.Object)
+ if err != nil {
+ return fmt.Errorf("the env object %s: %w", e.Object, err)
}
- want := hostfiles.Entry{Object: fmt.Sprintf("%sobjects/%016d-%s", prefix, e.Seq, hostfilesSum(env)), SHA256: hostfilesSum(env), Size: int64(len(env)), Mode: 0o600, Seq: e.Seq}
- if e != want || e.Seq <= prepared.Seq || e.Seq > cur.Seq {
- return fmt.Errorf("the env item %+v is not the object this box's establishment writes (%+v)", e, want)
+ if hostfilesSum(body) != e.SHA256 || int64(len(body)) != e.Size {
+ return fmt.Errorf("the env object %s is not the env file's bytes", e.Object)
}
return nil
}
diff --git a/internal/host/movesfiles_test.go b/internal/host/movesfiles_test.go
index eb28b2c39..30574cb47 100644
--- a/internal/host/movesfiles_test.go
+++ b/internal/host/movesfiles_test.go
@@ -642,17 +642,23 @@ func TestEstablishPublishesOnlyOverTheBytesItChecked(t *testing.T) {
}
}
-// A prepared replay is accepted only as this box's own establishment, in
-// full (fix round 2, finding 6): the current manifest's origins hold the
-// location rule and the env entry has the complete shape of the object
-// the establishment wrote (under P, at the expected sequence and size,
-// not torn, not skipped), not merely the digest. A bumped sequence whose
-// env entry carries the expected digest but an object under another
-// location, or the wrong size, is refused and left as it is.
+// A prepared replay is accepted only as exactly what this establishment
+// would have written (fix round 2 finding 6, fix round 3): from the
+// prepared baseline and the establishment's own operations, the env
+// object at the sequence after the prepared one, the manifest at that
+// sequence, the carried set the admitted one, the entries and other
+// platform items unchanged, the adoption item gone; and the env object
+// present at its key with the env's digest. Nothing is taken from the
+// replay's own numbers. With correct Origins, an env entry under another
+// location or generation, of the wrong size, torn, or at a fabricated
+// sequence (99, or 2 where the establishment writes 1) whose object does
+// not exist, is refused and left as it is. The genuine replay is accepted
+// and writes nothing.
func TestEstablishRefusesAForeignEnvEntryOnPreparedReplay(t *testing.T) {
x, pm, o, in := preparedFixture(t)
ctx := context.Background()
- envSHA := sha([]byte("K=1\nCARLOS_INSTANCE_KEY=abc\n"))
+ envBytes := []byte("K=1\nCARLOS_INSTANCE_KEY=abc\n")
+ envSHA := sha(envBytes)
raw, err := x.bucket.GetVersion(ctx, "data", pm.Key, pm.Version)
if err != nil {
t.Fatal(err)
@@ -661,31 +667,51 @@ func TestEstablishRefusesAForeignEnvEntryOnPreparedReplay(t *testing.T) {
if err := json.Unmarshal(raw, &prepared); err != nil {
t.Fatal(err)
}
- for name, entry := range map[string]hostfiles.Entry{
- "another location": {Object: "instances/other/files/g-mv1/objects/0000000000000001-" + envSHA, SHA256: envSHA, Size: 30, Mode: 0o600, Seq: 1},
- "another generation": {Object: movesFilesPrefix(filesLoc, "cur") + "objects/0000000000000001-" + envSHA, SHA256: envSHA, Size: 30, Mode: 0o600, Seq: 1},
- "the wrong size": {Object: movesFilesPrefix(filesLoc, "mv1") + "objects/0000000000000001-" + envSHA, SHA256: envSHA, Size: 3, Mode: 0o600, Seq: 1},
- "torn": {Object: movesFilesPrefix(filesLoc, "mv1") + "objects/0000000000000001-" + envSHA, SHA256: envSHA, Size: 30, Mode: 0o600, Seq: 1, Torn: true},
+ // The genuine establishment first: what this box writes, and the set it
+ // carries, are the shape every replay is held to.
+ if err := x.f.Establish(ctx, o, in, x); err != nil {
+ t.Fatal(err)
+ }
+ genuine, _ := x.manifest("mv1")
+ genuineRaw, _ := x.bucket.Current("data", pm.Key)
+ if genuine.Seq != 1 || genuine.Platform[hostfiles.EnvItem].Seq != 1 || len(genuine.Origins) == 0 {
+ t.Fatalf("the genuine establishment: %+v", genuine)
+ }
+ under := func(prefix string, seq int64) string { return fmt.Sprintf("%sobjects/%016d-%s", prefix, seq, envSHA) }
+ for name, tc := range map[string]struct {
+ seq int64
+ entry hostfiles.Entry
+ }{
+ "another location": {1, hostfiles.Entry{Object: under("instances/other/files/g-mv1/", 1), SHA256: envSHA, Size: int64(len(envBytes)), Mode: 0o600, Seq: 1}},
+ "another generation": {1, hostfiles.Entry{Object: under(movesFilesPrefix(filesLoc, "cur"), 1), SHA256: envSHA, Size: int64(len(envBytes)), Mode: 0o600, Seq: 1}},
+ "the wrong size": {1, hostfiles.Entry{Object: under(movesFilesPrefix(filesLoc, "mv1"), 1), SHA256: envSHA, Size: 3, Mode: 0o600, Seq: 1}},
+ "torn": {1, hostfiles.Entry{Object: under(movesFilesPrefix(filesLoc, "mv1"), 1), SHA256: envSHA, Size: int64(len(envBytes)), Mode: 0o600, Seq: 1, Torn: true}},
+ "a fabricated sequence 99": {99, hostfiles.Entry{Object: under(movesFilesPrefix(filesLoc, "mv1"), 99), SHA256: envSHA, Size: int64(len(envBytes)), Mode: 0o600, Seq: 99}},
+ "a fabricated sequence 2": {2, hostfiles.Entry{Object: under(movesFilesPrefix(filesLoc, "mv1"), 2), SHA256: envSHA, Size: int64(len(envBytes)), Mode: 0o600, Seq: 2}},
} {
- bumped := hostfiles.Manifest{V: hostfiles.ManifestVersion, Seq: 1, Entries: prepared.Entries, Platform: map[string]hostfiles.Entry{}}
+ bumped := hostfiles.Manifest{V: hostfiles.ManifestVersion, Seq: tc.seq, Entries: prepared.Entries, Platform: map[string]hostfiles.Entry{}, Origins: genuine.Origins}
for k, v := range prepared.Platform {
bumped.Platform[k] = v
}
- bumped.Platform[hostfiles.EnvItem] = entry
+ bumped.Platform[hostfiles.EnvItem] = tc.entry
body := mustJSON(t, bumped)
x.bucket.Put("data", pm.Key, body)
if err := x.f.Establish(ctx, o, in, x); err == nil {
- t.Fatalf("%s: a foreign env entry was accepted as this box's establishment", name)
+ t.Fatalf("%s: accepted as this box's establishment", name)
}
if cur, _ := x.bucket.Current("data", pm.Key); string(cur) != string(body) {
t.Fatalf("%s: the manifest was replaced: %s", name, cur)
}
}
- // This box's own establishment, in full, is accepted and left as it is.
- x.bucket.Put("data", pm.Key, raw)
- if err := x.f.Establish(ctx, o, in, x); err != nil {
- t.Fatal(err)
+ // The genuine bytes with their env object gone: refused too.
+ x.bucket.Put("data", pm.Key, genuineRaw)
+ x.bucket.BareDelete("data", genuine.Platform[hostfiles.EnvItem].Object)
+ if err := x.f.Establish(ctx, o, in, x); err == nil {
+ t.Fatal("accepted a replay whose env object is gone")
}
+ x.bucket.Put("data", genuine.Platform[hostfiles.EnvItem].Object, envBytes)
+ // The genuine replay is accepted and writes nothing.
+ x.bucket.Put("data", pm.Key, genuineRaw)
seq1 := x.bucket.LatestID("data", pm.Key)
if err := x.f.Establish(ctx, o, in, x); err != nil || x.bucket.LatestID("data", pm.Key) != seq1 {
t.Fatalf("the genuine replay: %v, revision moved %v", err, x.bucket.LatestID("data", pm.Key) != seq1)