Package / arch (push) Canceled after 0s
Package / user (push) Canceled after 0s
Package / deb (push) Canceled after 0s
Package / freebsd (push) Canceled after 0s
Package / image (push) Canceled after 0s
Test / test (push) Canceled after 0s
Test / e2e (push) Canceled after 0s
13 KiB
13 KiB
To Do
Planned work, in order of priority. Each item names what to build, how it fits the existing seams, and how to verify it. Finished items move to the design doc they belong to.
1. Packaging: AUR, FreeBSD ports, Debian
The foundation exists:
- The
lwbinary name, free in Arch (official repositories and AUR), Ubuntu 24.04 and 26.04, and the FreeBSD 15.1 ports tree. - The canonical module path
github.com/lixenwraith/logwisp, whichgo install, FreeBSD'sUSES=go:modulesand Debian's dh-golang expect. make installwithDESTDIR,PREFIX,SYSCONFDIRandSERVICE: the binary, thedoc/lw.1manual, bash, zsh and fish completion generated fromcmd/lw'sshortsandcommandstables, and the service files indeploy/package/(systemd unit, sysusers, tmpfiles, FreeBSD rc.d script) with the configuration, kept on reinstall.make deb, a binary package built withdpkg-deb, andmake arch, the PKGBUILD built from the working tree.- Skeletons in
deploy/package/arch/anddeploy/package/freebsd/. .github/workflows/package.yml:make arch, the.deband BSD make on FreeBSD 15.1, each reinstalled over an edited configuration; the systemd and rc.d services run; a home install withSERVICE=noandlw config init; andmake image image-check.
What remains is the maintainer's: it needs push rights, an identity or a release tag, and both skeletons download the tagged source.
- Tag the release on the merged main commit,
vX.Y.Z:git tag -a vX.Y.Z -m vX.Y.Z # git tag -s signs it with your key git push origin vX.Y.Zmakethen stampsvX.Y.Z(fromgit describe), andgo install github.com/lixenwraith/logwisp/cmd/lw@vX.Y.Zworks.- A GitHub release for the tag is optional; the tag alone serves
archive/vX.Y.Z.tar.gz, which the PKGBUILD downloads.
- Arch (AUR),
deploy/package/arch/PKGBUILD:pkgver=X.Y.Zand the# Maintainer: Name <email>line.updpkgsums(pacman-contrib) replacessha256sums=('SKIP')with the tarball's checksum.namcap PKGBUILD, thenmakepkg -si(builds, runscheck(), installs), thenmakepkg --printsrcinfo > .SRCINFO.- Push
PKGBUILDand.SRCINFOtossh://aur@aur.archlinux.org/logwisp.git; optionally alogwisp-gitpackage built from the main branch.
- FreeBSD,
deploy/package/freebsd/(sysutils/logwisp):DISTVERSION=X.Y.ZandMAINTAINER=your address.make makesumwritesdistinfo: the module zip that the Go proxy serves forGO_MODULEat the tag.- The
logwispuser needs an ID registered in the ports tree. Take a number below 1000 that is free in both/usr/ports/UIDsand/usr/ports/GIDs, and add to the same patch:UIDs: logwisp:*:NNN:NNN::0:0:LogWisp daemon:/nonexistent:/usr/sbin/nologin GIDs: logwisp:*:NNN: portlint -AC,poudriere testporton 14.x and 15.x jails, then a Bugzilla report with the port directory and the UIDs/GIDs diff.
- Debian:
make debserves direct installs. A PPA builds from a signed source package without network access: adebian/directory (changelog, control, rules) and the Go modules vendored into the source tarball.- The archive wants every Go dependency packaged (dh-golang); the four
lixenwraithlibraries are not. lintianon themake debpackage reportsno-changelog(a source package'sdebian/changelogprovides it),statically-linked-binary(lw is static by design) andmaintainer-script-calls-systemctl(dh's scripts usedeb-systemd-helperinstead).
- With a tag, the packaging workflow's FreeBSD job can build the port itself
from a ports tree (
make stage check-plistin a copy ofdeploy/package/freebsd/), rather than BSD make on the checkout.
2. lw --tui and the configuration engine it shares with lixen.com
lw --tui composes pipelines in a full-screen terminal UI, then either runs
them at once or prints one form of them, chosen on exit: a command line,
environment variables, or a configuration file. Its logic is a pure engine that
lixen.com's planned Configure tab (lixencom doc/todo.md) runs as WebAssembly,
so no part of LogWisp is rewritten in JavaScript.
What exists:
- Option structs with toml tags for every plugin and flow stage
(
internal/config/config.go), presets as rows with typed parameters (preset.go), the command-line and environment grammar (spec.go),ValidateConfig,--checkand--dump. internal/configalready compiles forGOOS=js; it links no net/http, crypto/tls or terminal code.github.com/lixenwraith/terminal(pinned) and itstuipackage: regions, layout, boxes, List, Tree, TabBar, StatusBar, TextField, Form, Modal, ConfirmDialog, scrolling, mouse.github.com/lixenwraith/color: RGB, blending, RGBTo256, RGBTo16.
What is missing:
- A machine-readable option schema. Defaults, enums and required checks live
inside the plugin constructors (about 50
Default*constants, 24 inline validators);doc/sources.md,doc/sinks.md,config/logwisp.tomland the site's catalogue copy them by hand, and the site's copy already lags. - Offline plugin validation: the constructors mix their checks with reading certificates, credentials and files.
- Typed command-line values:
lw --sink http,port=8080 --dumpprintsport = "8080", a fileport = 8080. - A host-independent preset:
fileSource(preset.go) decides directory or pattern withos.Stat, so off the target hostpath=/var/logexpands to directory/var, patternlog. - Emitters: only parsers exist for the three forms.
Steps:
- Schema, in
internal/config, as the one source of truth.- Tags on the option structs:
default:,help:, andlw:for required, enum, min and max, what zero means (default, none, unlimited), hints (path, regex, file) and roles (listener, dialer) on the shared tls, auth and acl tables. - One catalogue table, one row per plugin type: role, network role, single
instance, summary, option struct.
RegisterSource/RegisterSinkpanic on a type without a row. Decode[T](role, type, map)applies defaults, unknown-key and tag checks, then the struct's pureCheck(). Every constructor decodes through it and keeps only I/O; theDefault*constants and inline validators go.- Pure cross-field checks become methods that tlsx, authz and netacl call first: TLS role rules, auth bindings without file reads, ACL parsing, the http sink's paths, filter regexes.
Coerceconverts command-line and environment strings, and JSON floats, to the declared kinds;spec.gouses it, so a command line dumps typed.ValidateConfigadds unique plugin ids per pipeline and decodes every plugin, naming the path (pipelines[0].plugin_sinks[view].config.port). It opens nothing;lw --checkstays the authority on files.- Keep under test what moves: file sink
min_disk_free_mb(negative means 100, 0 means none), a backoff maximum below the minimum, formattext.
- Tags on the option structs:
- Engine,
internal/compose.- Imports internal/config, internal/version and lixenwraith/toml only; a
test fails when
go list -depsshows net, crypto/tls, os/exec, os/signal, x/term or the auth, log and terminal modules. - Starts: empty; a preset, with a
statfunction that is nil off the host (the UI then asks "directory or file pattern"); a loaded configuration; a pasted command line (wrappingcliSpecsandbuildPipelines). - Operations: add or remove a source, sink or filter; set or unset an option; move a filter; validate.
- Emitters, one form per call:
- Command line:
--pipeline NAME,id=, the rate limit policy and heartbeatenabledalways explicit (their command-line defaults differ from the file's);--key=valuewhen a value starts with-;,=\escaped; POSIX-quoted. - Environment:
LOGWISP_SOURCE_1and the rest, single-quotedKEY='value'lines; an error for more than one pipeline, which the environment form cannot hold. - File: the TOML
lw --dumpprints for those pipelines.
- Command line:
- Imports internal/config, internal/version and lixenwraith/toml only; a
test fails when
lw --schema, a parser switch like--help(not a Config field, so no file or environment can trigger it). It prints one JSON document: version; settings with kind, default, enum, flag and variable; the pipeline flags; flow stage order; the tls, auth and acl tables; sources, sinks, presets. The site generates its catalogue from it.- In
lixenwraith/terminal, released and pinned before the TUI:- Full-screen 8- and 16-color output (SGR 30-37, 90-97, 40-47) and the default colors 39/49; it emits only 256-color and truecolor today.
- Detection as
inlinedoes it: 16 colors on text consoles, none underNO_COLOR, refusal onTERM=dumb, and an override for LogWisp'scolorkey. - Drawing on
/dev/tty, solw --tui > logwisp.tomlandcmd | lw --tuikeep stdin and stdout as data. - Bracketed paste into text fields.
tuiwidgets the site's controls have: segmented choice, filterable option list, toggle, typed fields (default as placeholder, required mark, error and help line, folded groups), a focus ring; every widget styled from onetui.Theme.- In
color, optional: export the 16 xterm reference shades. RGBTo16 maps the site's hues badly (green to cyan, red to bright black), so the 8-color tier is chosen by hand.
lw --tui.- A parser switch,
-Tfor short (-tis--check). With-c FILE, pipeline flags orLOGWISP_SOURCEit starts from that composition, and never rewrites FILE (TOML encoding drops its comments); bare, it opens the preset menu (pipe, tail, serve, edge, aggregator, empty). - The pipeline as the site draws it: SOURCES, FLOW, SINKS; a node is a
tinted bar, its type, listens or dials, and a summary line; the four flow
stages in order inside a dashed box, the ones off dimmed; wires drawn from
per-cell connectivity so every junction is right. The inspector sits
below at 80 to 109 columns, beside at 110 and over; under 64 columns the
stages stack, as on the site.
● SOURCES ● FLOW ● SINKS ▌ file ─┐ ╭╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╮ ┌─▌ http listens ▌ /var/log *.log │ ╎ ▌ rate_limit 400/s ╎ │ ▌ :8080 /stream █ tcp_chain listens─┴─►╎ ▌ filters -TRACE ╎─►┤ █ :9000 tls scram ╎ ▌ format txt ╎ └─▌ console ╎ ○ heartbeat off ╎ ▌ stdout ╰╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╯ ── tcp_chain · source · id src-2 ─────────────────── ⏎ edit tab next ── host 0.0.0.0 default format raw [txt] json port * 9000▌ tls ▸ on (auth, acl folded) ✓ valid a add d delete ␣ on/off J/K move p preset o output ? help - Keys: arrows or hjkl move, Enter edits,
aadds from the catalogue,ddeletes, Space switches a flow stage,J/Kreorder filters,ppresets,[]switch pipelines,clists errors,ooutput,?help,qquits. - Theme: the site's dark tokens as one role table in four tiers. Truecolor
and 256 colors paint the site's background; 8 colors and mono keep the
terminal's. Sources cyan, flow violet, sinks green, accent blue, muted
grey, errors red. A selection always changes a glyph (bar,
▸, underline), never only a shade. Glyphs: Unicode, a CP437 set on text consoles, ASCII outside UTF-8. - Output,
o: Run handsconfig.Argsbuilt from the composition to the usualconfig.Load, after the terminal is released and before anything reads stdin; reloads keep the pipelines, and--tui --checkand--tui --dumpfollow. Or exactly one of command line, environment and file, printed to stdout once the screen closes.
- A parser switch,
- WebAssembly:
cmd/lwconf(js && wasm) exposes schema, preset, parse, validate and emit to the page as JSON strings.make wasmbuildsbin/lwconf.wasmwith the version stamped, copies the toolchain'swasm_exec.js, and prints both checksums. A prototype measured about 6 MB, 1.7 MB gzipped, ready in about 60 ms in Chromium;wasm_exec.jsuses no eval, so the page needs only'wasm-unsafe-eval'in itsscript-src.
Verify:
- A Go test in
cmd/lw: for every preset, an edge and aggregator pair, escaped values and two pipelines, the pipelines loaded from the emitted command line, file and environment (one pipeline) are equal. It runs in an empty directory with theLOGWISP_environment cleared, since a discovered file would add settings. - A schema test: every option has a kind, every enum values, every catalogue
row a factory;
TestEveryPluginRejectsUnknownKeysstill passes. - CI builds
cmd/lwconfforGOOS=jsand runs a node test of its calls. - The diagram rendered into a cell buffer at 80x24 and 64x24, per tier; a scripted session on a pseudo-terminal for Run and each output.