55 lines
2.6 KiB
Go
55 lines
2.6 KiB
Go
// Package process is a module's own process's connection to the bus (novox/hq ADR 0436 clause 4): it reads
|
|
// the account the controller delivers, connects as it with its pinned fingerprint and its inbox prefix, and
|
|
// offers emitting an event, the module's states with compare-and-set, consuming a work queue, reading the
|
|
// router's records of the module's own asks, and calling a tool or verb — each only as the account's grants
|
|
// allow. It offers no Serve and no way to serve a tool: a process never answers a call. A sibling of stdio,
|
|
// which it imports only for stdio's pure types (ErrChanged, CodeChanged, StateEntry, EmitOptions); it never
|
|
// touches stdio's current, channel or live(), which stay the bundle's own way to the bus.
|
|
package process
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
)
|
|
|
|
// Account is a process's own bus account, exactly as the controller delivers it as the module's own secret
|
|
// broker-<process id> (mesh-controller cmd/mesh-controller/modules.go issueProcess, heldProcessAccount, and
|
|
// issueWith for a module's own broker account, which also carries claims). A process account carries no
|
|
// claims at all; this type reads either file without error.
|
|
type Account struct {
|
|
URL string `json:"url"`
|
|
Fingerprint string `json:"fingerprint,omitempty"`
|
|
Node string `json:"node"`
|
|
Module string `json:"module"`
|
|
User string `json:"user"`
|
|
Password string `json:"password"`
|
|
// Claims rides on a module's own broker account only; a process holds no seat, so its own account
|
|
// carries none (novox/hq ADR 0436 §2, §3). Kept raw: this package never reads it.
|
|
Claims json.RawMessage `json:"claims,omitempty"`
|
|
}
|
|
|
|
// InboxPrefix is this account's own inbox, and nothing wider: `_INBOX.<user>`.
|
|
func (a Account) InboxPrefix() string { return "_INBOX." + a.User }
|
|
|
|
// ReadAccount reads and validates the account file the controller delivers: it refuses a file missing url,
|
|
// user or password, naming the field — never the password, which does not appear in an error.
|
|
func ReadAccount(path string) (Account, error) {
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return Account{}, fmt.Errorf("reading the process account at %s: %w", path, err)
|
|
}
|
|
var a Account
|
|
if err := json.Unmarshal(data, &a); err != nil {
|
|
return Account{}, fmt.Errorf("the process account at %s is not JSON: %w", path, err)
|
|
}
|
|
for _, f := range []struct{ name, value string }{
|
|
{"url", a.URL}, {"user", a.User}, {"password", a.Password},
|
|
} {
|
|
if f.value == "" {
|
|
return Account{}, fmt.Errorf("the process account at %s has no %s", path, f.name)
|
|
}
|
|
}
|
|
return a, nil
|
|
}
|