package host import ( "context" "crypto/ed25519" "os" "time" "github.com/carlosframework/platform/internal/historyreadback" "github.com/carlosframework/platform/internal/hostactors" "github.com/carlosframework/platform/internal/hostfloor" "github.com/carlosframework/platform/internal/release" ) type historyReadbackPublisher struct { directory hostactors.Directory enrollment hostfloor.Enrollment key func() (ed25519.PrivateKey, error) now func() time.Time } func (p historyReadbackPublisher) publish(ctx context.Context, b release.HistoryBinding, snapshot func(context.Context) (release.HistoryMigrationStatus, error)) error { observed, err := p.directory.Read(ctx) if err != nil { return err } box, ok := observed.Roster.Boxes[p.enrollment.Box] if !ok || box.Enrollment != p.enrollment.Enrollment || p.enrollment.InstanceID == "" || box.Cloud.InstanceID != p.enrollment.InstanceID || p.key == nil || p.now == nil { return os.ErrPermission } key, err := p.key() if err != nil { return err } scope := historyreadback.Scope{Bucket: p.directory.Bucket, Box: p.enrollment.Box, Enrollment: p.enrollment.Enrollment, Binding: b} return historyreadback.Respond(ctx, p.directory, scope, key, p.now(), snapshot) } func publishRootHistoryReadback(ctx context.Context, store release.Store, b release.HistoryBinding, snapshot func(context.Context) (release.HistoryMigrationStatus, error)) error { ctx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() rr, err := readProductionRosterRow(ctx, store, os.Getenv) if err != nil { return err } p := historyReadbackPublisher{directory: rr.directory, enrollment: rr.enrollment, key: func() (ed25519.PrivateKey, error) { return readClaimEvidenceKey("/etc/carlos/host-evidence.key") }, now: time.Now} return p.publish(ctx, b, snapshot) }