daemon_start.go RawHistoryFolder
1package broker
2
3import (
4 "errors"
5 "fmt"
6
7 "github.com/bnema/vev/internal/ports"
8)
9
10// DaemonLaunchAuthority is the policy launch token that explicitly authorizes
11// starting a stopped target daemon. Ports carry it opaquely; the broker is the
12// component that interprets it. Any other token, including every
13// sandbox-private one, fails closed and never starts a daemon.
14const DaemonLaunchAuthority = "explicit"
15
16// RequireLocalDaemonTarget refuses a target that is not the broker-owned local
17// daemon. Only that authority names a daemon this process can start, so a
18// registered host is never started by mistake, even on a local carriage.
19func RequireLocalDaemonTarget(target ports.BrokerDialTarget) error {
20 if !target.Fence.Local {
21 return daemonStartRefused("the target is not the broker-owned local daemon")
22 }
23 return nil
24}
25
26// ClassifyDaemonDialFailure decides whether a failed carriage dial may lead to
27// a start at all. absent reports whether the transport proved the daemon is
28// simply not there; that classification belongs to the carriage adapter and
29// must fail closed.
30//
31// It returns nil only when the daemon is absent under a mode other than
32// ExistingOnly. Otherwise it returns the error to report, and no lock,
33// election, or process may be touched:
34//
35// - ExistingOnly never starts: absence becomes BrokerErrorNoDaemon and every
36// other failure is reported unchanged.
37// - A failure that is not absence (cancellation, a rejected peer, a foreign
38// path, a permission error) is never repaired by starting another daemon.
39func ClassifyDaemonDialFailure(target ports.BrokerDialTarget, dialErr error, absent bool) error {
40 if dialErr == nil {
41 return errors.New("broker: a running daemon is never started again")
42 }
43 if target.StartMode == ports.BrokerDaemonExistingOnly {
44 if absent {
45 return ports.BrokerError{Code: ports.BrokerErrorNoDaemon, Cause: dialErr}
46 }
47 return dialErr
48 }
49 if !absent {
50 return dialErr
51 }
52 return nil
53}
54
55// AuthorizeDaemonLaunch is the final start decision for an absent daemon. The
56// start mode is an authorization, never an obligation, and it can only narrow
57// the policy: the resolved policy must also name DaemonLaunchAuthority.
58func AuthorizeDaemonLaunch(target ports.BrokerDialTarget) error {
59 if target.StartMode != ports.BrokerDaemonStartIfNeeded {
60 return daemonStartRefused("the acquisition does not authorize starting a daemon")
61 }
62 if target.Policy.Launch != DaemonLaunchAuthority {
63 return daemonStartRefused("the resolved policy does not authorize launching")
64 }
65 return nil
66}
67
68// daemonStartRefused reports a refused start as a typed policy conflict. The
69// reason is local diagnostic text, never a message the daemon produced.
70func daemonStartRefused(reason string) error {
71 return ports.BrokerError{
72 Code: ports.BrokerErrorConflictingPolicy,
73 Cause: fmt.Errorf("refusing to start the daemon: %s", reason),
74 }
75}