Documentation
¶
Overview ¶
Package daemon implements the long-lived ppz daemon: IPC server, on-disk state, NATS connection, and HTTP client to ppz-server.
Index ¶
- Variables
- func Call(sock, method string, params, result any) error
- func CursorKey(orgID, handle, channel string) string
- func IsAlive(pid int) bool
- func PIDFromHome(home string) int
- type Credentials
- type Daemon
- type RefreshFn
- type RefreshLoop
- type State
- func (s *State) ClearCurrent(session string) error
- func (s *State) Credentials() (*Credentials, bool)
- func (s *State) Current(session string) string
- func (s *State) Home() string
- func (s *State) KeyPrefix() string
- func (s *State) KnowsPipe(handle string) bool
- func (s *State) LoadFromDisk() error
- func (s *State) LoginCheck() string
- func (s *State) OrgID() string
- func (s *State) OrgName() string
- func (s *State) RememberPipe(handle string)
- func (s *State) ResetPipes(handles []string)
- func (s *State) SetCurrent(session, handle string) error
- func (s *State) SetLogin(creds Credentials, orgID, orgName, keyPrefix string) error
- func (s *State) SetLoginCheck(state string)
- func (s *State) SetOrgID(id string)
Constants ¶
This section is empty.
Variables ¶
var ErrCredsRequired = errors.New("credentials required")
ErrUnauthorized is what RefreshFn returns when the bearer was revoked / expired — distinct from transient network failures (which the loop retries). Triggers OnUnauthorized + stop.
Functions ¶
func Call ¶
Call sends one request to the daemon over a fresh connection and decodes either result or error.
func PIDFromHome ¶
PIDFromHome reads $PPZ_HOME/daemon.pid. Returns 0 if absent.
Types ¶
type Credentials ¶
type Credentials struct {
URL string `json:"url"`
APIKey string `json:"api_key"`
OrgID string `json:"org_id,omitempty"`
OrgName string `json:"org_name,omitempty"`
// Auth V2 Phase 3 — short-lived NATS user credentials.
// Re-fetched periodically by the daemon's refresh goroutine.
NATSUserJWT string `json:"nats_user_jwt,omitempty"`
NATSUserSeed string `json:"nats_user_seed,omitempty"`
}
Credentials are persisted at $PPZ_HOME/credentials (mode 0600). OrgID + OrgName are stored alongside URL+APIKey so a SIGHUP / file-poller reload doesn't drop the resolved org info (the alternative would be re-calling /auth/exchange after every reload).
type Daemon ¶
type Daemon struct {
Home string
Sock string
State *State
HTTP *http.Client
NC *nats.Conn // nil until Login
NATSURL string
Cursors *cursors
// Phase 3.5 — JWT refresh loop. Started on Login (and restored
// in ensureNATS for daemon restarts), holds the latest minted
// (jwt, seed) for the current org, and re-runs /auth/exchange
// at exp-30s. nats.Connect's UserJWT callback reads from
// Refresh.Current() so reconnects pick up fresh credentials.
// Stopped on Logout / replaced on Login.
Refresh *RefreshLoop
}
Daemon is the singleton process per $PPZ_HOME.
type RefreshFn ¶
RefreshFn is the work the refresh loop calls when a JWT is about to expire. Implementations re-run POST /api/v1/auth/exchange and return the new (jwt, seed). orgID lets a multi-org daemon route to the right account.
type RefreshLoop ¶
type RefreshLoop struct {
OrgID string
Refresh RefreshFn
// contains filtered or unexported fields
}
RefreshLoop monitors one (org, JWT) pair and refreshes it before expiry. Concurrency: Current() may be called from any goroutine; Start/Stop must be called from the same goroutine.
func (*RefreshLoop) Current ¶
func (r *RefreshLoop) Current() (jwt, seed string)
Current returns the freshest (jwt, seed) — used by nats.UserJWT() callbacks on every NATS (re)connect.
func (*RefreshLoop) Start ¶
Start begins the refresh goroutine with an initial credential. expUnix is the JWT's `exp` claim in unix seconds.
func (*RefreshLoop) Stop ¶
func (r *RefreshLoop) Stop()
Stop halts the refresh goroutine. Idempotent.
type State ¶
type State struct {
// contains filtered or unexported fields
}
State is the daemon's in-memory mirror of on-disk credentials + current handle. "current" is keyed by session id (tty / $PPZ_SESSION) so each terminal window has its own current source — same scoping as cursors, avoids the "new terminal silently inherits a stale current set hours ago in another window" footgun.
func (*State) ClearCurrent ¶
ClearCurrent drops this session's current. Used by `ppz disconnect`. Idempotent — clearing an already-clear session is a no-op.
func (*State) Credentials ¶
func (s *State) Credentials() (*Credentials, bool)
func (*State) LoadFromDisk ¶
LoadFromDisk reads credentials and current from $PPZ_HOME. Called at startup and on SIGHUP. Missing files mean "not logged in" / "no current".
`current.json` is the session→handle map. The legacy plain-text `current` file (pre-per-session) is migrated into session "default" if both exist.
func (*State) LoginCheck ¶
LoginCheck returns the cached server-validation result. "" means "not observed yet" — callers (e.g. status) should probe.
func (*State) RememberPipe ¶
func (*State) ResetPipes ¶
func (*State) SetCurrent ¶
func (*State) SetLogin ¶
func (s *State) SetLogin(creds Credentials, orgID, orgName, keyPrefix string) error
func (*State) SetLoginCheck ¶
SetLoginCheck records the latest server-validation result. Called from callServer based on response status. Idempotent — same value twice is fine, but transitions (ok→invalid, invalid→ok) are kept.