carlos / platform Public

host: the prepared manifest's installation stamp is validated apart from the admitted session's (whole-branch fixes, item 2)

openPrepared held the journalled binding to the current holder's stamp.
A dirty return's install ran at the source installation's stamp S, and
the recovery's cold admission then issues a new stamp, so the legitimate
prepared manifest was refused. installationStamp is the immutable
installation binding's stamp: for a restoring or reverting op the
claim's journalled source_stamp (S, under which the return's local ran),
validated separately from the admitted session's authority; for a
landing the flip's stamp, which the first probe's admission keeps.

Regression: the dirty return's installation (the prepared manifest built
at S and journalled under the rollback id), the real admission through
the writer (a new stamp) and the real C8 materialization together
establish P's manifest; a binding at the admitted session's stamp, or
any other, is refused.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 0003187ada5ffa9a2644c7df184c6dca8f49deca parent aa46cb3
2 files changed, +80 −1
  • internal/host/movesfiles.go +30 −1
  • internal/host/movesrecoveryowners_test.go +50 −0
diff --git a/internal/host/movesfiles.go b/internal/host/movesfiles.go
index a51557cce..521b1883e 100644
--- a/internal/host/movesfiles.go
+++ b/internal/host/movesfiles.go
@@ -15,6 +15,7 @@ import (
"reflect"
"slices"
"sort"
+ "strconv"
"strings"
"github.com/carlosframework/platform/internal/hostbox"
@@ -588,7 +589,11 @@ func (f *movesFiles) openPrepared(ctx context.Context, files release.Store, o ho
return nil, fmt.Errorf("%w: the op journal of %s/%s has no prepared files manifest", errLandingChanged, o.Host, gen)
}
key := hostfiles.ManifestKey(prefix)
- pm, err := decodePreparedManifest(raw, key, o.Claim.Op.ID, h.Stamp)
+ stamp, err := installationStamp(o.Claim)
+ if err != nil {
+ return nil, err
+ }
+ pm, err := decodePreparedManifest(raw, key, o.Claim.Op.ID, stamp)
if err != nil {
return nil, err
}
@@ -641,6 +646,30 @@ func (f *movesFiles) openPrepared(ctx context.Context, files release.Store, o ho
return p, nil
}
+// installationStamp is the stamp the installation that wrote P's prepared
+// manifest captured (ir.capture at local), validated apart from the
+// admitted session's authority (whole-branch fixes, item 2). A return's
+// install (restoring, or a revert's) ran at the source installation's
+// stamp S, which the claim journals at the flip (source_stamp) and the
+// recovery's cold admission then replaces with a new one; a landing's
+// install ran at the flip's stamp, which the first probe's admission
+// keeps (KeepStamp, since no writer was admitted between the installing
+// CAS and the probe), so it is the holder's.
+func installationStamp(c *hostclaim.Claim) (uint64, error) {
+ switch c.Op.Kind {
+ case hostclaim.KindRestoring, hostclaim.KindReverting:
+ stamp, err := strconv.ParseUint(c.Op.Journal[hostclaim.JournalSourceStamp], 10, 64)
+ if err != nil || stamp == 0 {
+ return 0, fmt.Errorf("%w: the claim journals no source installation stamp for %s", errLandingChanged, c.Op.ID)
+ }
+ return stamp, nil
+ }
+ if c.Holder == nil || c.Holder.Stamp == 0 {
+ return 0, fmt.Errorf("%w: the holder has no installation stamp", errLandingChanged)
+ }
+ return c.Holder.Stamp, nil
+}
+
// 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
diff --git a/internal/host/movesrecoveryowners_test.go b/internal/host/movesrecoveryowners_test.go
index 5140430ec..08bea426e 100644
--- a/internal/host/movesrecoveryowners_test.go
+++ b/internal/host/movesrecoveryowners_test.go
@@ -15,6 +15,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/hostguard"
"github.com/carlosframework/platform/internal/hostwrite"
"github.com/carlosframework/platform/internal/moves"
@@ -323,6 +324,55 @@ func TestDirtyReturnProbeIssuesANewStamp(t *testing.T) {
}
}
+// The dirty return's installation, its real admission and the real C8
+// materialization together (whole-branch fixes, item 2): local built the
+// prepared manifest at the source installation's stamp S (the claim's
+// journalled source_stamp, under which the return's local ran) and
+// journalled its binding; the recovery's cold admission issues a new
+// stamp; Establish validates the binding's immutable installation stamp
+// against S, separately from the admitted session's, and establishes P's
+// manifest with the minted env file. A binding at the admitted session's
+// stamp, or any other, is not the installation's and is refused.
+func TestDirtyReturnEstablishesThePreparedManifestThroughC8(t *testing.T) {
+ f := newRCFixture(t, rcDirty)
+ ctx := t.Context()
+ f.owners.Files = f.realC8()
+ pm := f.preparedManifestJournalled(rpRB, poOp, rcS)
+ o := f.read()
+ in := f.selectAdmission(o)
+ admitted := f.admitThroughWriter(o, in)
+ h := admitted.Claim.Holder
+ if h.Stamp == rcS || !in.Prepared {
+ t.Fatalf("the dirty admission kept the stamp or is not prepared: %+v %v", h, in.Prepared)
+ }
+ if err := f.owners.Materialize(ctx, admitted, in, poWork{action: "spawn", f: f.poFixture}); err != nil {
+ t.Fatalf("the dirty return's materialization: %v", err)
+ }
+ // The env file is the prepared item's (the recovery's start gate holds
+ // the restored tree, env included, to the recorded digest) and there is
+ // no adoption item, so the establishment reads the prepared bytes back
+ // at sequence 0 and publishes nothing; what it proved is the binding.
+ m, found, err := hostfiles.Load(ctx, casBucketStore{b: f.bucket, bucket: "data"}, movesFilesPrefix("instances/"+poHost, rpRB))
+ if err != nil || !found || m.Seq != 0 || m.Platform[hostfiles.EnvItem].SHA256 == "" {
+ t.Fatalf("P's manifest after the dirty return's probe: %+v %v %v", m, found, err)
+ }
+ if raw, _ := f.bucket.Current("data", pm.Key); sha(raw) != pm.SHA256 || f.bucket.LatestID("data", pm.Key) != pm.Version {
+ t.Fatal("the prepared manifest is not the journalled version")
+ }
+ // A binding at the admitted session's stamp, or another, is refused.
+ for name, stamp := range map[string]uint64{"the admitted session's stamp": h.Stamp, "another stamp": 99} {
+ g := newRCFixture(t, rcDirty)
+ g.owners.Files = g.realC8()
+ g.preparedManifestJournalled(rpRB, poOp, stamp)
+ o := g.read()
+ in := g.selectAdmission(o)
+ admitted := g.admitThroughWriter(o, in)
+ if err := g.owners.Materialize(ctx, admitted, in, poWork{action: "spawn", f: g.poFixture}); !errors.Is(err, errLandingChanged) {
+ t.Fatalf("%s: %v", name, err)
+ }
+ }
+}
+
// Plan 4 Task 9: a clean return's probe is a cold admission into a fresh
// generation restored from src_gen in this region, its coverage
// clean-return: the admission records no writes lost.