carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package hostops
2
3import (
4 "context"
5 "crypto/sha256"
6 "encoding/hex"
7 "errors"
8 "os"
9 "slices"
10
11 "github.com/carlosframework/platform/internal/hostclaim"
12 "github.com/carlosframework/platform/internal/hostfence"
13)
14
15// completionFence is ruling 86: the box a serving claim's undischarged
16// completed relocation names, when that box's termination fence verifies,
17// for a delete or purge to pass to the completion barrier as its exempt
18// box (hostclaim.StartGuard's fencedCompletion), as a failover passes its
19// fenced source. A dead box's participation slot binds nothing on another
20// box; without the exemption a purge that has closed the app's admission
21// waits on a failover that admission refuses (the two-box model, seed
22// 2224).
23//
24// The fence is verified as the failover's start verifies it: the record
25// at the box's current roster enrollment, by its exact digest, through
26// hostclaim.VerifyFence under the claim fence authority, and bound to the
27// box (VerifyFenceForBox). Only that evidence exempts. "" with no error
28// when there is nothing to exempt (no completion, one already discharged,
29// or its box already on lost, which the barrier exempts itself) or no
30// fence to verify (a box not in the roster, or no fence record): the
31// barrier then refuses as before, since absence is never evidence. A fence
32// that cannot be read, or does not verify, is its error and the start is
33// refused. A completion record that cannot be read is left to the
34// barrier, which refuses over it.
35func (a ProductionAuthority) completionFence(ctx context.Context, c *hostclaim.Claim) (string, error) {
36 done, ok, err := hostclaim.ReadCompletedRelocation(c)
37 if err != nil || !ok || done.Discharged || slices.Contains(c.Lost, done.Stop.Box) {
38 return "", nil
39 }
40 if a.Store == nil || a.Now == nil {
41 return "", ErrContract
42 }
43 o, err := a.Directory.Read(ctx)
44 if err != nil {
45 return "", err
46 }
47 b, ok := o.Roster.Boxes[done.Stop.Box]
48 if !ok {
49 return "", nil
50 }
51 key := hostfence.FenceKey(b.Enrollment)
52 raw, _, err := a.Store.Get(ctx, key)
53 if errors.Is(err, os.ErrNotExist) {
54 return "", nil
55 }
56 if err != nil {
57 return "", err
58 }
59 sum := sha256.Sum256(raw)
60 ref := hostclaim.FenceRef{Enrollment: b.Enrollment, Key: key, SHA256: hex.EncodeToString(sum[:])}
61 if err := hostclaim.VerifyFenceForBox(ctx, a.Store, hostfence.ClaimFenceAuthority{Directory: a.Directory, Now: a.Now}, ref, done.Stop.Box); err != nil {
62 return "", err
63 }
64 return done.Stop.Box, nil
65}
66