// The slack module's Go tools bundle (novox/hq ADR 0188, ADR 0193, ADR 0208): the Slack desktop app // in the operator's session, served by the node's runtime as the operator account. The module holds // no seat, so every tool is its own. // // Slack's sessions are the operator's: the tools never read its cookies, local storage or the key in // Local State, and no answer carries a token, a cookie, a message, or the name of a person, channel // or workspace. Accounts and workspaces are counted, never named. package main import ( "fmt" "os" stdio "git.novox.be/novox/mesh-sdk/go" ) func main() { if err := stdio.Serve("", tools()); err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } var machine = NewMachine() func tools() []stdio.Tool { return []stdio.Tool{ { Name: "slack_status", Description: "Slack: whether it runs (the main process's pid, since, and the scope it runs in; how " + "many helper processes), the installed version and whether it is outside the official " + "repositories, where its output goes, whether its icon sits in a tray, who shows its " + "notifications, its launch and tray switches and notification method, how many accounts and " + "workspaces it is signed in to (counted, never named), and what starts it at login. (r)", Run: func(map[string]any) (any, error) { return machine.Status() }, }, { Name: "slack_log", Description: "The last lines of Slack's own log: source browser (the main process, the default) or " + "webapp (the web app's console). With problems, only error and warn entries. Tokens, cookies, " + "message and notification text, and the names of people, channels and workspaces are " + "replaced by . (r)", Input: map[string]any{ "lines": map[string]any{"type": "integer", "description": "how many lines (default 100, at most 2000)"}, "source": map[string]any{"type": "string", "enum": []string{"browser", "webapp"}, "description": "browser (default) or webapp"}, "problems": map[string]any{"type": "boolean", "description": "only error and warn entries (default false)"}, }, Run: func(args map[string]any) (any, error) { n, err := whole(args, "lines", 100, 1, 2000) if err != nil { return nil, err } source, err := text(args, "source", false) if err != nil { return nil, err } if source == "" { source = "browser" } problems, err := flag(args, "problems", false) if err != nil { return nil, err } return machine.Log(source, n, problems) }, }, { Name: "slack_restart", Description: "End Slack (asked first, then forced after 8 s) and start it again to the tray in the " + "operator's desktop session, under the account's service manager, its output in the journal. " + "Answers the pids ended and the new main process. Needs someone logged in to the desktop. (a)", Run: func(map[string]any) (any, error) { return machine.Restart() }, }, { Name: "slack_check", Description: "Check what the module promises: Slack is installed; it has exactly one start (the " + "module's line in i3's configuration; no XDG autostart entry, no other exec); the window rules " + "are the module's, not repeated in a file of the operator's; one Slack runs in the session with " + "its output read (a pipe nobody reads makes its writes fail with EPIPE); its icon is in a tray; " + "a notifier owns the session bus's notification name. Answers ok and each finding with what to do. (r)", Run: func(map[string]any) (any, error) { return machine.Check() }, }, } }