carlos / platform Public

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

Plain git — no account needed to clone.

Download

Download this file

1// The healthy history — builds this box has run well (spec
2// 2026-10-06-console-release-defences-design.md §4.5). A sha256 in an app's
3// history is adopted with no proof, which is what lets a requiring box roll
4// back to a build it ran before without waiting on the prover.
5//
6// Root writes it from two places in internal/host: when D1's settle check
7// passes for a restarted named unit (How "settle"), and when a root pass finds
8// a named-unit route's live build bound, active in one invocation for the
9// policy's after, hashed from its running executable and ready (How "live").
10// Every sha256 here was hashed from bytes, never copied from a manifest. It
11// lives in the bake directory, which the sandboxed agent can read.
12package release
13
14import (
15 "encoding/json"
16 "fmt"
17 "log"
18 "path/filepath"
19 "time"
20
21 "github.com/carlosframework/platform/internal/safefile"
22)
23
24const healthyMax = 50
25
26type HealthyBuild struct {
27 SHA256 string `json:"sha256"`
28 Version string `json:"version,omitempty"`
29 How string `json:"how"`
30 At time.Time `json:"at"`
31}
32
33type healthyFile struct {
34 Schema int `json:"schema"`
35 Builds []HealthyBuild `json:"builds"`
36}
37
38func healthyPath(bakeDir, acct, app string) (string, error) {
39 if bakeDir == "" || !ValidAccount(acct) || !ValidApp(app) {
40 return "", fmt.Errorf("healthy history: invalid %q/%q", acct, app)
41 }
42 return filepath.Join(bakeDir, "healthy", acct, app+".json"), nil
43}
44
45func ReadHealthy(bakeDir, acct, app string) []HealthyBuild {
46 if bakeDir == RootHealthyDir {
47 return readRootHealthy(acct, app)
48 }
49 p, err := healthyPath(bakeDir, acct, app)
50 if err != nil {
51 return nil
52 }
53 b, err := safefile.ReadFile(p)
54 if err != nil {
55 return nil
56 }
57 var f healthyFile
58 if err := json.Unmarshal(b, &f); err != nil || f.Schema != 1 {
59 log.Printf("healthy history: %s does not parse (%v), treating it as empty", p, err)
60 return nil
61 }
62 return f.Builds
63}
64
65func IsHealthy(bakeDir, acct, app, sha string) bool {
66 if sha == "" {
67 return false
68 }
69 for _, b := range ReadHealthy(bakeDir, acct, app) {
70 if b.SHA256 == sha {
71 return true
72 }
73 }
74 return false
75}
76
77// RecordHealthy adds b, newest first, keeping the first record of a sha256
78// and the newest healthyMax builds. Written atomically and world-readable,
79// because the reader is the sandboxed agent.
80func RecordHealthy(bakeDir, acct, app string, b HealthyBuild) error {
81 if bakeDir == RootHealthyDir {
82 return recordRootHealthy(acct, app, b)
83 }
84 p, err := healthyPath(bakeDir, acct, app)
85 if err != nil {
86 return err
87 }
88 if !sha256Re.MatchString(b.SHA256) {
89 return fmt.Errorf("healthy history: sha256 %q is not 64 lower-case hex digits", b.SHA256)
90 }
91 have := ReadHealthy(bakeDir, acct, app)
92 for _, h := range have {
93 if h.SHA256 == b.SHA256 {
94 return nil
95 }
96 }
97 builds := append([]HealthyBuild{b}, have...)
98 if len(builds) > healthyMax {
99 builds = builds[:healthyMax]
100 }
101 body, err := json.MarshalIndent(healthyFile{Schema: 1, Builds: builds}, "", " ")
102 if err != nil {
103 return err
104 }
105 if err := safefile.MkdirAll(filepath.Dir(p), 0o755); err != nil {
106 return err
107 }
108 return safefile.WriteFile(p, append(body, '\n'), 0o644)
109}
110