From 0b8701ec13342d6907145fe85b4c6d6a7ba3ca4ca2c3f6d9bee1cfac0b25b3c3 Mon Sep 17 00:00:00 2001 From: Lixen Wraith Date: Mon, 12 Oct 2026 17:09:30 -0400 Subject: [PATCH] v0.35.1 make and doc update --- .github/workflows/package.yml | 18 ++++---- Makefile | 77 +++++++++++++++++++++++------------ README.md | 52 ++++++++++++++++++----- doc/installation.md | 39 ++++++++++++------ go.mod | 4 +- go.sum | 8 ++-- 6 files changed, 137 insertions(+), 61 deletions(-) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 3a69863..f4a2fbd 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -47,8 +47,10 @@ jobs: pacman -R --noconfirm logwisp test ! -e /usr/bin/lw test -f /etc/logwisp/logwisp.toml.pacsave - # make install SERVICE=no into a home, twice, then lw config init places the - # configuration lw reads without -c, and never replaces it + # make release install as a user without root installs into the home, + # twice, without the service; lw config init then places the configuration + # lw reads without -c, and never replaces it. An explicit PREFIX the user + # cannot write fails before writing. user: runs-on: ubuntu-latest timeout-minutes: 10 @@ -57,18 +59,20 @@ jobs: - uses: actions/setup-go@v6 with: go-version-file: go.mod - - run: make release - run: | - make install SERVICE=no PREFIX="$HOME/.local" - make install SERVICE=no PREFIX="$HOME/.local" + make release install + make install export PATH="$HOME/.local/bin:$PATH" + test ! -e /usr/bin/lw test ! -e "$HOME/.local/lib/systemd/system/logwisp.service" - test ! -e /etc/logwisp/logwisp.toml + test ! -e "$HOME/.config/logwisp/logwisp.toml" + if make install PREFIX=/usr SERVICE=no; then exit 1; fi + test ! -e /usr/bin/lw lw config init lw --check lw --dump | grep -q '^status_reporter = true' if lw config init; then exit 1; fi - make uninstall PREFIX="$HOME/.local" + make uninstall test ! -e "$HOME/.local/bin/lw" test -f "$HOME/.config/logwisp/logwisp.toml" # make deb on a host with systemd: the service runs once the package's diff --git a/Makefile b/Makefile index 25bbe55..962a9e2 100644 --- a/Makefile +++ b/Makefile @@ -46,16 +46,22 @@ IMAGE_RUN = $(CONTAINER_ENGINE) run --read-only --user 65532:65532 \ --network none --cap-drop ALL --security-opt no-new-privileges DESTDIR ?= -# SERVICE=no leaves out the service files and the system configuration, -# which lw config init then places where the user wants it. -SERVICE ?= yes INSTALL_OS_DEFAULT != uname -s INSTALL_OS ?= $(INSTALL_OS_DEFAULT) # FreeBSD keeps everything outside the base system under /usr/local. -PREFIX_DEFAULT != [ '$(INSTALL_OS)' = FreeBSD ] && echo /usr/local || echo /usr +SYSTEM_PREFIX != [ '$(INSTALL_OS)' = FreeBSD ] && echo /usr/local || echo /usr +# Unstaged, a user who cannot write the system's bin directory installs for +# itself: under ~/.local, without the service. sudo make install is system-wide. +USER_INSTALL != [ -z '$(DESTDIR)' ] && [ "$$(id -u)" != 0 ] && [ ! -w '$(SYSTEM_PREFIX)/bin' ] && echo yes || echo no +PREFIX_DEFAULT != [ '$(USER_INSTALL)' = yes ] && echo "$$HOME/.local" || echo '$(SYSTEM_PREFIX)' PREFIX ?= $(PREFIX_DEFAULT) -SYSCONFDIR_DEFAULT != [ '$(INSTALL_OS)' = FreeBSD ] && echo /usr/local/etc || echo /etc +SYSCONFDIR_DEFAULT != if [ '$(USER_INSTALL)' = yes ]; then echo "$$HOME/.config"; \ + elif [ '$(INSTALL_OS)' = FreeBSD ]; then echo /usr/local/etc; else echo /etc; fi SYSCONFDIR ?= $(SYSCONFDIR_DEFAULT) +# SERVICE=no leaves out the service files and the configuration, which lw +# config init then places where the user wants it. +SERVICE_DEFAULT != [ '$(USER_INSTALL)' = yes ] && echo no || echo yes +SERVICE ?= $(SERVICE_DEFAULT) BINDIR ?= $(PREFIX)/bin MANDIR ?= $(PREFIX)/share/man DOCDIR ?= $(PREFIX)/share/doc/logwisp @@ -69,6 +75,8 @@ FISHCOMPDIR ?= $(PREFIX)/share/fish/vendor_completions.d DEB_MAINTAINER ?= Maintainer .DEFAULT_GOAL := help +# Goals run in the order given, so make release install installs what it built. +.NOTPARALLEL: .PHONY: help check-go build release dev wasm test verify e2e image image-check install uninstall deb arch completion clean version @@ -92,9 +100,10 @@ help: @echo " image Build $(IMAGE):$(IMAGE_TAG) with $(CONTAINER_ENGINE) (scratch, static, UID 65532)" @echo " image-check Run it read-only, offline, without capabilities: --version, then" @echo " --check on $(IMAGE_CHECK_CONFIG)" - @echo "Install (build or release first):" - @echo " install Binary, manual, shell completion, licence and docs; unless SERVICE=no," - @echo " the service files and $(SYSCONFDIR)/logwisp/logwisp.toml (kept if present)" + @echo "Install (build or release first, as in make release install):" + @echo " install Binary, manual, shell completion, licence and docs under $(PREFIX); unless" + @echo " SERVICE=no, the service files and $(SYSCONFDIR)/logwisp/logwisp.toml (kept" + @echo " if present). A user who cannot write $(SYSTEM_PREFIX)/bin gets ~/.local and no service" @echo " uninstall Remove them, keeping $(SYSCONFDIR)/logwisp" @echo " deb Package a release build as $(BIN_DIR)/logwisp_VERSION_ARCH.deb (dpkg-deb)" @echo " arch Build the Arch package from this working tree in $(BIN_DIR)/arch (makepkg)" @@ -108,6 +117,7 @@ help: check-go: @command -v $(GO) >/dev/null 2>&1 || { \ echo "Go toolchain '$(GO)' not found; go.mod requires go $$(sed -n 's/^go //p' go.mod)."; \ + [ -z "$${SUDO_USER:-}" ] || echo " sudo may reset PATH: make release as $$SUDO_USER, then sudo make install"; \ if [ "$$(uname -s)" = FreeBSD ]; then echo " FreeBSD: pkg install $(GO_DEFAULT)"; \ elif [ -f /etc/arch-release ]; then echo " Arch Linux: pacman -S go"; \ else echo " Elsewhere: https://go.dev/dl/ (distribution packages often lag)"; fi; \ @@ -216,18 +226,30 @@ image-check: '$(IMAGE):$(IMAGE_TAG)' --check -c /etc/logwisp/logwisp.toml # install stages what a package ships and compiles nothing, so a packager owns -# the build flags. The service files get the installed paths substituted; a -# configuration already in place is kept, on every system alike. +# the build flags. It writes nothing until every directory it needs is +# writable, and leaves existing directories as they are. The service files get +# the installed paths substituted; a configuration already in place is kept. install: @set -eu; \ - [ -x $(BIN_DIR)/$(BINARY) ] || { echo "no $(BIN_DIR)/$(BINARY): run make build or make release first" >&2; exit 1; }; \ + [ -x $(BIN_DIR)/$(BINARY) ] || { echo "no $(BIN_DIR)/$(BINARY): make build or make release first, as in make release install" >&2; exit 1; }; \ case '$(SERVICE)' in yes|no) ;; *) echo "SERVICE is yes or no, not '$(SERVICE)'" >&2; exit 2 ;; esac; \ - put() { install -d -m 0755 "$${3%/*}"; install -m "$$1" "$$2" "$$3"; echo "install $$3"; }; \ - sub() { install -d -m 0755 "$${3%/*}"; \ + root='$(DESTDIR)'; etc="$$root$(SYSCONFDIR)/logwisp"; \ + dirs='$(BINDIR) $(MANDIR) $(BASHCOMPDIR) $(ZSHCOMPDIR) $(FISHCOMPDIR) $(LICENSEDIR) $(DOCDIR)'; \ + [ '$(SERVICE)' = no ] || case '$(INSTALL_OS)' in \ + FreeBSD) dirs="$$dirs $(SYSCONFDIR)/logwisp $(PREFIX)/etc/rc.d" ;; \ + *) dirs="$$dirs $(SYSCONFDIR)/logwisp $(PREFIX)/lib/systemd/system $(PREFIX)/lib/sysusers.d $(PREFIX)/lib/tmpfiles.d" ;; \ + esac; \ + for d in $$dirs; do d="$$root$$d"; while [ ! -e "$$d" ]; do d=$$(dirname "$$d"); done; \ + [ -w "$$d" ] || { echo "no write access to $$d: sudo make install, or set PREFIX, SYSCONFDIR or SERVICE=no" >&2; exit 1; }; \ + done; \ + if [ '$(USER_INSTALL)' = yes ] && [ '$(PREFIX)' = '$(PREFIX_DEFAULT)' ]; then \ + echo "$(SYSTEM_PREFIX)/bin is not writable: installing for $$(id -un) under $(PREFIX) (sudo make install: system-wide)"; fi; \ + dir() { [ -d "$$1" ] || install -d -m 0755 "$$1"; }; \ + put() { dir "$${3%/*}"; install -m "$$1" "$$2" "$$3"; echo "install $$3"; }; \ + sub() { dir "$${3%/*}"; \ sed -e 's|@BINDIR@|$(BINDIR)|g' -e 's|@SYSCONFDIR@|$(SYSCONFDIR)|g' -e 's|%%BINDIR%%|$(BINDIR)|g' \ -e 's|%%PREFIX%%/etc|$(SYSCONFDIR)|g' -e 's|%%PREFIX%%|$(PREFIX)|g' "$$2" > "$$3"; \ chmod "$$1" "$$3"; echo "install $$3"; }; \ - root='$(DESTDIR)'; etc="$$root$(SYSCONFDIR)/logwisp"; \ put 0755 $(BIN_DIR)/$(BINARY) "$$root$(BINDIR)/$(BINARY)"; \ put 0644 doc/lw.1 "$$root$(MANDIR)/man1/lw.1"; \ put 0644 $(PKG_DIR)/completion/lw.bash "$$root$(BASHCOMPDIR)/lw"; \ @@ -235,20 +257,25 @@ install: put 0644 $(PKG_DIR)/completion/lw.fish "$$root$(FISHCOMPDIR)/lw.fish"; \ put 0644 LICENSE "$$root$(LICENSEDIR)/LICENSE"; \ for src in README.md logwisp-logo.svg doc/*.md doc/lw.1 config/logwisp.toml; do put 0644 "$$src" "$$root$(DOCDIR)/$$src"; done; \ - if [ '$(SERVICE)' = no ]; then echo "skip the service and $$etc (SERVICE=no): lw config init writes a configuration"; exit 0; fi; \ - if [ -e "$$etc/logwisp.toml" ]; then echo "keep $$etc/logwisp.toml"; \ - else put 0644 config/logwisp.toml "$$etc/logwisp.toml"; fi; \ - case '$(INSTALL_OS)' in \ - FreeBSD) \ - sub 0755 $(PKG_DIR)/logwisp.rc "$$root$(PREFIX)/etc/rc.d/logwisp" ;; \ - *) \ - sub 0644 $(PKG_DIR)/logwisp.service "$$root$(PREFIX)/lib/systemd/system/logwisp.service"; \ - sub 0644 $(PKG_DIR)/logwisp.sysusers "$$root$(PREFIX)/lib/sysusers.d/logwisp.conf"; \ - sub 0644 $(PKG_DIR)/logwisp.tmpfiles "$$root$(PREFIX)/lib/tmpfiles.d/logwisp.conf" ;; \ - esac + if [ '$(SERVICE)' = no ]; then echo "skip the service and $$etc (SERVICE=no): lw config init writes a configuration"; \ + else \ + if [ -e "$$etc/logwisp.toml" ]; then echo "keep $$etc/logwisp.toml"; \ + else put 0644 config/logwisp.toml "$$etc/logwisp.toml"; fi; \ + case '$(INSTALL_OS)' in \ + FreeBSD) \ + sub 0755 $(PKG_DIR)/logwisp.rc "$$root$(PREFIX)/etc/rc.d/logwisp" ;; \ + *) \ + sub 0644 $(PKG_DIR)/logwisp.service "$$root$(PREFIX)/lib/systemd/system/logwisp.service"; \ + sub 0644 $(PKG_DIR)/logwisp.sysusers "$$root$(PREFIX)/lib/sysusers.d/logwisp.conf"; \ + sub 0644 $(PKG_DIR)/logwisp.tmpfiles "$$root$(PREFIX)/lib/tmpfiles.d/logwisp.conf" ;; \ + esac; \ + fi; \ + [ -n "$$root" ] || case ":$$PATH:" in *':$(BINDIR):'*) ;; *) echo "note: $(BINDIR) is not on PATH" ;; esac uninstall: @set -eu; root='$(DESTDIR)'; \ + if [ '$(USER_INSTALL)' = yes ] && [ '$(PREFIX)' = '$(PREFIX_DEFAULT)' ]; then \ + echo "$(SYSTEM_PREFIX)/bin is not writable: uninstalling under $(PREFIX) (sudo make uninstall: system-wide)"; fi; \ for f in "$$root$(BINDIR)/$(BINARY)" "$$root$(MANDIR)/man1/lw.1" \ "$$root$(BASHCOMPDIR)/lw" "$$root$(ZSHCOMPDIR)/_lw" "$$root$(FISHCOMPDIR)/lw.fish" \ "$$root$(PREFIX)/lib/systemd/system/logwisp.service" \ diff --git a/README.md b/README.md index 2f5ebde..558bc1c 100644 --- a/README.md +++ b/README.md @@ -25,9 +25,6 @@ streams, or downstream LogWisp nodes. - **Presets**: `tail`, `serve`, `edge` and `aggregator` build the common pipelines from a few keys (`lw --preset tail:path=/var/log/app`); `lw --dump` turns any command line into a configuration file -- **On screen**: `lw --tui` composes pipelines on a terminal and runs or - prints them; `t` runs them under the screen, where a live view shows each - entry with its fate: passed, or the stage or filter that dropped it - **Independent pipelines**, each `sources → flow → sinks`, running concurrently in one process - **Fan-in and fan-out**: many sources and many sinks per pipeline @@ -37,9 +34,38 @@ streams, or downstream LogWisp nodes. - **Hot reload** via `SIGHUP`/`SIGUSR1` or a config file watch, with the new configuration validated before the old service is torn down +### On screen + +`lw --tui` (`-T`) composes pipelines on a full-screen terminal, with the +configuration engine the website's configurator runs as WebAssembly: + +- **Start anywhere**: from the pipelines `lw` would run with the same options + (`-c FILE`, pipeline flags, a discovered file), from a preset, or from a + pasted `lw` command line +- **Edit with the schema**: sources, flow stages and sinks side by side; the + inspector edits each part's options from their defaults, every edit is + checked, and `!` lists the problems +- **Run or print**: `r` runs the pipelines; `o` also prints them as a command + line, environment variables or a TOML file once the screen closes + (`lw -T > pipelines.toml`) +- **Tap**: `t` runs them in place and opens a live view of every entry with its + fate, passed or the stage or filter that dropped it; `e` edits that stage, + and `t` again reruns as a reload, keeping the running pipelines when the new + ones do not build. Listeners bind, dialers connect and files are written for + real; a password is asked in a masked dialog +- **Read any log**: the view parses LogWisp's JSON, lw's own log, pino, zap, + slog, docker, journald, ECS, GCP, logfmt and stamped text into time, level, + message and fields, filters them by level or pattern, and shows the payload + as the sinks receive it. It never slows a pipeline: what it misses is + counted +- **Any terminal**: `cmd | lw -T` taps piped input, since the screen draws on + the controlling terminal; colors range from true color to none, and a text + console gets CP437 glyphs + ### Inputs -`file` (directory tail with rotation detection and JSON line parsing), +`file` (a directory's files tailed through rotation, a missing directory +waited for, JSON lines parsed), `console` (stdin, one reader per process), `random` (generated entries, to check a deployment before real logs), `null` (nothing; holds a source's place until one is chosen), and the chain ingest listeners `tcp_chain` and @@ -152,6 +178,12 @@ journalctl -f | ./bin/lw --sink http:host=127.0.0.1,port=8080 # the same with a preset; on a terminal the level names are in color ./bin/lw --preset tail:path=/var/log/myapp + +# compose on screen from a preset menu; r runs, t taps, o prints +./bin/lw -T + +# tap a stream: t shows each line parsed, and its fate +journalctl -f -o json | ./bin/lw -T --preset pipe ``` As a service, a configuration file holds the pipelines: @@ -193,12 +225,12 @@ docker run --rm --read-only --cap-drop ALL --security-opt no-new-privileges \ -v /etc/logwisp:/etc/logwisp:ro logwisp:dev -c /etc/logwisp/logwisp.toml ``` -`sudo make install` installs the binary, the manual, shell completion, a -systemd unit or FreeBSD rc.d script and its configuration; `make deb` and -`make arch` package them for Debian, Ubuntu and Arch. -`make install SERVICE=no PREFIX="$HOME/.local"` installs `lw`, its manual, -completion and documentation, and no service; `lw config init` writes the -annotated configuration it reads. See [Installation](doc/installation.md). +`make release && sudo make install` installs the binary, the manual, shell +completion, a systemd unit or FreeBSD rc.d script and its configuration. +Without root, `make release install` installs `lw`, its manual, completion and +documentation under `~/.local`, and no service; `lw config init` writes the +annotated configuration it reads. `make deb` and `make arch` package them for +Debian, Ubuntu and Arch. See [Installation](doc/installation.md). ## System Requirements diff --git a/doc/installation.md b/doc/installation.md index 18d9e18..f78fb39 100644 --- a/doc/installation.md +++ b/doc/installation.md @@ -76,15 +76,23 @@ checkout. ## Installing `make install` copies what a package ships and compiles nothing, so build -first. It honours `DESTDIR`, `PREFIX`, `SYSCONFDIR`, `BINDIR` (default -`$PREFIX/bin`, the path the systemd unit and the rc.d script run `lw` from), -`MANDIR`, `DOCDIR` and `LICENSEDIR` (under `$PREFIX/share` by default) and -`SERVICE`: +first, or in one command: `make release install`. It honours `DESTDIR`, +`PREFIX`, `SYSCONFDIR`, `BINDIR` (default `$PREFIX/bin`, the path the systemd +unit and the rc.d script run `lw` from), `MANDIR`, `DOCDIR` and `LICENSEDIR` +(under `$PREFIX/share` by default) and `SERVICE`; `make help` prints the +values in effect: - Linux defaults: `PREFIX=/usr`, `SYSCONFDIR=/etc`. Outside a package manager, prefer `PREFIX=/usr/local`; systemd reads units, sysusers and tmpfiles from there too. - FreeBSD defaults: `PREFIX=/usr/local`, `SYSCONFDIR=/usr/local/etc`. +- A user who cannot write that layout's `bin` directory, unstaged, gets a + per-user install instead: `PREFIX=~/.local`, `SYSCONFDIR=~/.config`, + `SERVICE=no` ([Without a Service](#without-a-service)). `sudo make install` + installs system-wide. +- Before writing anything, `install` checks that it can write every + directory it needs, and stops naming the first it cannot. It creates the + missing ones and leaves the mode of existing ones alone. - `INSTALL_OS` (default: `uname -s`) picks the layout, so `INSTALL_OS=FreeBSD DESTDIR=...` stages the FreeBSD one on another system. - `SERVICE`: `yes` (default) adds the service and its configuration; `no` @@ -100,6 +108,9 @@ make release sudo make install PREFIX=/usr/local ``` +Build as yourself and install with `sudo`: under `sudo` the build would run +with root's `PATH` and Go cache and leave a `bin/` only root can replace. + Every install gets: - `$BINDIR/lw` and the manual `$MANDIR/man1/lw.1` @@ -241,19 +252,20 @@ d=$(mktemp -d); lw config init --out "$d/logwisp.toml"; diff "$d/logwisp.toml" / ### Without a Service `SERVICE=no` installs `lw`, its manual, completion and documentation, and -nothing else: no service files, account or configuration. For one user, -without root: +nothing else: no service files, account or configuration. A user without +root gets it under `~/.local` by default: ```bash -make release -make install SERVICE=no PREFIX="$HOME/.local" +make release install lw config init ``` -- `~/.local/bin` goes on `PATH`. `man lw` then finds the manual, and bash - and fish the completion; zsh needs +- `~/.local/bin` goes on `PATH` (`make install` notes when it is not). + `man lw` then finds the manual, and bash and fish the completion; zsh needs `fpath=(~/.local/share/zsh/site-functions $fpath)` before `compinit`. -- `make uninstall PREFIX="$HOME/.local"` removes it. +- `make uninstall`, as the same user, removes it. +- Where that user can write the system's `bin` directory, name the layout: + `make install SERVICE=no PREFIX="$HOME/.local" SYSCONFDIR="$HOME/.config"`. For every user: `sudo make install SERVICE=no PREFIX=/usr/local`. @@ -374,8 +386,9 @@ In place: reinstalled keeping it, removed - Ubuntu: the `.deb` installed, started, reinstalled keeping an edited configuration, removed and purged - - Ubuntu, without a service: `make install SERVICE=no` into a home twice, - then `lw config init` writing the file `lw` reads, once + - Ubuntu, as a user without root: `make release install` into the home + twice, without a service, then `lw config init` writing the file `lw` + reads, once; an explicit `PREFIX` it cannot write fails - FreeBSD: BSD make building, installing twice keeping an edited configuration, and running the rc.d service - `make image image-check` diff --git a/go.mod b/go.mod index 9b2afdd..3f02b7b 100644 --- a/go.mod +++ b/go.mod @@ -6,8 +6,8 @@ require ( github.com/lixenwraith/auth v0.5.1 github.com/lixenwraith/color v0.1.3 github.com/lixenwraith/config v0.2.2 - github.com/lixenwraith/log v0.1.12-0.20261011001400-86d4fe10bd5e - github.com/lixenwraith/terminal v0.2.2-0.20261010220430-c657af606d34 + github.com/lixenwraith/log v0.1.12 + github.com/lixenwraith/terminal v0.2.2 github.com/lixenwraith/toml v0.1.3 golang.org/x/term v0.47.0 ) diff --git a/go.sum b/go.sum index e1e9dd1..08fd1a2 100644 --- a/go.sum +++ b/go.sum @@ -6,10 +6,10 @@ github.com/lixenwraith/color v0.1.3 h1:vSuvtU4zh1mIZS/7UGHmMdsTr+a7eCjUYGbou7kzF github.com/lixenwraith/color v0.1.3/go.mod h1:L/I3Vxp6pqslAIzWyZGgKCm2lyStHCA4vKaUoMUm7bU= github.com/lixenwraith/config v0.2.2 h1:X+l3Tf8Rbk49cipYBJU7/pfdw5wDwD4hRxtFH7rZgOc= github.com/lixenwraith/config v0.2.2/go.mod h1:yfJQwKS+/6Dg70GIoHeYc0eYztOPETpqe6nUIbakcyg= -github.com/lixenwraith/log v0.1.12-0.20261011001400-86d4fe10bd5e h1:5ocB2Wsd4nQbpX+lkA3LSuHf23GQ46BPejNy3oCZZbU= -github.com/lixenwraith/log v0.1.12-0.20261011001400-86d4fe10bd5e/go.mod h1:EE8i5nSAW2yZBTytKuhdgehmgzrby6kW1k5DyH1SvBg= -github.com/lixenwraith/terminal v0.2.2-0.20261010220430-c657af606d34 h1:GasarGRKYbAXzEz1utbcf9n4+N7WXPKyTbUtQZj8v74= -github.com/lixenwraith/terminal v0.2.2-0.20261010220430-c657af606d34/go.mod h1:V0P/FDpY+UeSvx1VIVuTG7llo0RbK3XrSJLDA7GqHqY= +github.com/lixenwraith/log v0.1.12 h1:0poqOWKPTvxiyv83czKMkBrc4ZShaywq3G/dSb34Jpw= +github.com/lixenwraith/log v0.1.12/go.mod h1:EE8i5nSAW2yZBTytKuhdgehmgzrby6kW1k5DyH1SvBg= +github.com/lixenwraith/terminal v0.2.2 h1:ZyAGE+QV10sFyNoEThEkba+ozfEZyns1A6PO84bsbV4= +github.com/lixenwraith/terminal v0.2.2/go.mod h1:V0P/FDpY+UeSvx1VIVuTG7llo0RbK3XrSJLDA7GqHqY= github.com/lixenwraith/toml v0.1.3 h1:mhnNVLNogdaqjGd3eC4rV9ZqY3j1Sv+DK1erZ+SPFeI= github.com/lixenwraith/toml v0.1.3/go.mod h1:itcT/Vt5mwmX9KVGCMsWZr6vbU/JgZ24wV/I0J5cMt0= golang.org/x/crypto v0.58.0 h1:COkYLr4k7nDI4r6QtMML2AfzeIswWHAJthLS6K/M/54=