TazHelper
=========

Guided testing of SliTaz cooking ISOs. On a live desktop TazHelper runs
automatic checks, walks the tester through a short checklist, shows the
exact report and, only when the tester clicks Send, posts it anonymously
to the SliTaz servers. The dev team then fixes what testers actually hit.

The test format and the report format below are the contract of the
project. All the logic lives in lib/libtazhelper.sh, driven by the
tazhelper script (CLI). The GTK3 client gui/tazhelper-gtk holds no
logic: it runs the tazhelper script for every action.

The full manual, for testers, developers and test writers, is
doc/tazhelper.en.html (installed in /usr/share/doc/tazhelper, online at
https://lab.slitaz.org/tazhelper/). Reports are read and triaged with
server/tazhelper-reports, on foyer or on a local copy.


GUI
---

Three steps, in a GTK3 window:

  1. Checks        The automatic tests run at start, results show live
  2. Applications  Each manual test: Open, then Works / Partly / Broken
                   and an optional comment (click again to take it back)
  3. Send          General comment, the exact report, Save to file, Send

Every choice is stored at once (tazhelper mark/comment): closing and
opening the window again keeps the answers. Build it with "make" (needs
gtk+3-dev). Without X or without tazhelper-gtk, tazhelper falls back to
the interactive CLI.


Usage
-----

  tazhelper              GUI, interactive CLI without X
  tazhelper cli          Interactive CLI
  tazhelper auto         Run the automatic tests, print the results
  tazhelper list         List the available tests
  tazhelper mark <id> <ok|partial|fail|none> [comment]
  tazhelper comment <text>
  tazhelper report       Print the report exactly as it will be sent
  tazhelper send [file]  Send the report, or a report saved earlier
  tazhelper save [file]  Save the report to a file (USB key, no network)
  tazhelper reset        Forget the results of this session

For the GUI: "tests" prints id, type, title and desc separated by TABs,
"results" prints the stored results without running anything.

Run from a source checkout, ./tazhelper uses its own lib/, tests/ and
etc/tazhelper.conf (when /etc/slitaz/tazhelper.conf does not exist).

Session results live in ~/.cache/tazhelper (TAZHELPER_STATE), in RAM on
a live CD. Configuration: /etc/slitaz/tazhelper.conf (URL, TIMEOUT).


Test format
-----------

One test = one file. Drop a file in tests/auto/ or tests/manual/ and it
shows up, nothing else to change. A .test file is a shell fragment,
sourced in a subshell, which sets:

  ID="network"            Unique, [a-z0-9_-] only: used in report keys
  TITLE="Network connection"
  PRIORITY="1"            1 = test first. Tests sort by PRIORITY, then ID
  DESC="Short instruction shown to the tester"

An automatic test (tests/auto/) also defines run(). It prints one line
of result (only the first line is kept) and returns:

  0 = ok    1 = fail    2 = partial

run() is called in its own shell with a timeout (TIMEOUT, 20 s). It
needs no user action and no root. It must not print personal data
(MAC/IP address, hostname, user name, serial): the report is filtered
anyway, but do not count on it.

  run() {
      [ -f /proc/asound/cards ] || { echo "no ALSA"; return 1; }
      echo "$(sed -n 's/^ *[0-9]* \[[^]]*\]: //p' /proc/asound/cards)"
  }

A manual test (tests/manual/) sets LAUNCH, the command started by the
"Launch" button (run with sh -c, in the background). The tester then
picks OK / Partial / Failed and may add a comment.

  LAUNCH="subox tazinst-gtk"


Report format
-------------

Plain text, one key=value per line, UTF-8, at most 16 KiB. Keys match
[a-z0-9][a-z0-9_.-]*, values hold no control character and at most 500
bytes (1024 accepted by the server). The first line is always the
version. System lines, then results in test order, then the comment:

  tazhelper_version=0.1
  date=2026-10-02              UTC day, no time
  release=cooking              /etc/slitaz-release
  flavor=core                  /etc/slitaz/flavor, else "unknown"
  arch=x86_64
  kernel=6.12.89-slitaz
  boot=efi                     efi or bios
  live=yes                     yes = running from the initramfs
  cpu=13th Gen Intel(R) Core(TM) i7-13700H
  cpu_cores=20
  ram_mb=15639
  gpu=8086:a7a0 i915           PCI vendor:device and driver
  locale=fr_CH.UTF-8
  test.network=ok              ok, partial or fail
  test.network.info=wlan0 wireless iwlwifi, mirror reachable
  test.browser=partial
  test.browser.comment=Fonts are blurry
  comment=General comment of the tester

A manual test the tester did not do has no line. New keys may be added;
readers must ignore keys they do not know.

Privacy: no MAC address, hostname, user name, IP address or serial
number is collected. Values also go through a filter that blanks MAC and
IPv4 addresses, /home/<user> paths, the user and host names. The tester
sees the whole report before sending and nothing leaves without a click.


Server
------

server/tazhelper.cgi is a shell CGI. It accepts a POST of at most 16 KiB
made only of key=value lines starting with tazhelper_version=, and stores
it as REPORTS/<release>/<UTC timestamp>-<random>.txt (REPORTS defaults
to /var/lib/tazhelper/reports, TAZHELPER_REPORTS overrides it). It
answers "OK <release>/<id>" or "ERROR <reason>".

The body is treated as hostile: it is checked with grep and moved to a
file, never sourced, evaluated or executed. A bad release name goes to
"unknown". The CGI does not store the client IP: keep it out of the web
server access log for this URL too.

Local test with busybox httpd (an empty config: the SliTaz default
/etc/httpd.conf maps *.cgi to /bin/sh, which breaks a relative script):

  mkdir -p www/cgi-bin && cp server/tazhelper.cgi www/cgi-bin/
  : > httpd.conf
  TAZHELPER_REPORTS=$PWD/reports busybox httpd -f -c httpd.conf \
      -p 127.0.0.1:8099 -h $PWD/www &
  TAZHELPER_URL=http://127.0.0.1:8099/cgi-bin/tazhelper.cgi tazhelper send

"make check" runs sh -n on every file and feeds good and bad reports to
the CGI.


Not done yet
------------

Autostart on first boot, translations, a page summing up reports,
anti-abuse (per-ISO token, rate limit), the wok package, a flavor marker
in the ISO (/etc/slitaz/flavor).
