carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1package host
2
3import (
4 "context"
5
6 "github.com/carlosframework/platform/internal/hostbox"
7 "github.com/carlosframework/platform/internal/hostguard"
8)
9
10type servingParkDisposition uint8
11
12const (
13 servingParkRefuse servingParkDisposition = iota
14 servingParkArtifactFree
15 servingParkDiscard
16 servingParkRetain
17)
18
19// servingGenerationParkDisposition is a root-side decision made after source
20// capture and stop authentication. The database must exist to own the slot.
21// A prelaunch record alone proves no tenant started. Once a main-role launch
22// was intended, missing start evidence is ambiguous: StartedUnit is recorded
23// after the process may have run. Preserve that source and refuse retirement.
24// Task 0R's filesystem driver must persist this decision with its source
25// identities before either replacing the slot or discarding a restore.
26func servingGenerationParkDisposition(ctx context.Context, journal *hostbox.LaunchJournal, prior servingArtifactIdentity, receipts []hostguard.FenceReceipt, databasePresent bool) (servingParkDisposition, error) {
27 if ctx == nil || journal == nil || prior.Host == "" || prior.Box == "" || prior.Region == "" || prior.Incarnation == "" || prior.Generation == "" || prior.Stamp == 0 || prior.Session == 0 || len(receipts) == 0 {
28 return servingParkRefuse, hostbox.ErrChanged
29 }
30 launched := false
31 for _, receipt := range receipts {
32 t := receipt.Target
33 if t.Host != prior.Host || t.Box != prior.Box || t.Region != prior.Region || t.Incarnation != prior.Incarnation || t.Stamp != prior.Stamp || t.Session != prior.Session || t.Op != "" || t.Phase != "" || t.ObligationID != "" || verifyRetirementReceipt(ctx, receipt) != nil {
34 return servingParkRefuse, ErrClaimStopReceipt
35 }
36 }
37 if databasePresent {
38 t := receipts[0].Target
39 records, err := journal.RootSessionLaunches(ctx, prior.Host, prior.Incarnation, prior.Stamp, prior.Session, prior.Box, t.Enrollment)
40 if err != nil {
41 return servingParkRefuse, err
42 }
43 if len(records) != 1 {
44 return servingParkRefuse, hostbox.ErrChanged
45 }
46 record := records[0]
47 matched := false
48 for _, receipt := range receipts {
49 matched = matched || hostbox.SameLaunchOwner(record.Target, receipt.Target)
50 }
51 if !matched {
52 return servingParkRefuse, hostbox.ErrChanged
53 }
54 seen := make(map[string]bool)
55 for _, reservation := range record.Reservations {
56 if reservation.Role != "main" {
57 continue
58 }
59 if reservation.ID == "" || seen[reservation.ID] || !hostbox.SameLaunchOwner(reservation.Target, record.Target) {
60 return servingParkRefuse, hostbox.ErrChanged
61 }
62 seen[reservation.ID] = true
63 if reservation.NeverIntended && record.WritersClosed && reservation.State == hostbox.UnitSettled && reservation.PID == 0 && reservation.ProcessStart == "" && reservation.Group.InvocationID == "" && reservation.Group.Device == 0 && reservation.Group.Inode == 0 {
64 continue
65 }
66 if !hostbox.IsUnitReservation(reservation) || reservation.State != hostbox.UnitSettled || reservation.PID <= 0 || reservation.ProcessStart == "" || reservation.Group.InvocationID == "" || reservation.Group.Device == 0 || reservation.Group.Inode == 0 || reservation.Executable.Device == 0 || reservation.Executable.Inode == 0 {
67 return servingParkRefuse, hostbox.ErrChanged
68 }
69 launched = true
70 }
71 }
72 if !databasePresent {
73 return servingParkArtifactFree, nil
74 }
75 if launched {
76 return servingParkRetain, nil
77 }
78 return servingParkDiscard, nil
79}
80