Quarantine and problem reports

Why a ticket an install filed is untrusted until the operator accepts it, the nonce fence, how report_issue drafts a card and sends, scrubbing, the outbox, diagnostics zip and crash files.

01untrusted until accepted#

A ticket made by an install, or carrying an install comment newer than its accept, is untrusted. It can't start a run until the operator accepts it on its page. An install's author has the origin install. A refusal reads ticket_quarantined: <id> came from an install (<name>); accept it on its page first.

The desk puts a card for each open install-filed ticket in the project's manager chat. See cards. An archive pressed from that card is not an accept, because an entry in the accepts file means trusted. It leaves a settle line instead.

02the nonce fence#

Install-written text is wrapped before the conductor reads it. A nonce is 16 hex characters from crypto/rand, made for one fenced build. The fence is an opening tag carrying the nonce, the scrubbed text, and a closing tag with the same nonce. Every occurrence of the nonce is removed from the text and from the tag's attributes, as [nonce removed], so the text can't close the fence early.

The desk wraps only install-origin text:

Tickets and comments from anyone else come back as they are. Where the nonce is chosen for each conductor turn is not checked here.

03report_issue and the send#

report_issue drafts a problem report as a card in the thread. Nothing is sent until the operator presses send. The tool needs a title and text, takes at most 8 screenshots and an optional diagnostics zip, and returns the card's number.

The conductor never holds the install's key. The press that posts a report, /api/desk/report, is the operator's: the crash banner's and the report form's send.

An install links to the report intake once, with a one-time invite code. The key the intake hands back is kept in one file, <data dir>/install/token, never in desk.json or another settings file, and is never logged, shown or returned. The link and report calls are /api/install/link and /api/report under the report url. The setup page does the linking: see setup.

A report made with no link has the status unlinked: it waits in the outbox until the install is linked.

05the report url#

The report url is where reports go. The default is https://smith.boxsie.co.uk. It is set in desk.json report.url, live, and has a row on the settings page. See desk-json and desk-json.

06the outbox#

Every report is written to <data dir>/outbox/ first and leaves it only when the intake answers 202, so a report made offline goes out on a later retry. A report the intake refused for good is in outbox/failed/. The file names, the sidecar, the retry schedule and the log lines are in on-disk.

07scrubbing#

Text is scrubbed before it is logged, shown or bundled. scrub.Text first replaces every literal it is handed, then pattern matches, each as [token]:

A report's title and text are scrubbed with the install's key as a known literal, then capped at 200 for the title and 64 KiB for the text (titleCap and textCap). The desktop app has a port of the same scrubber, desktop/scrub.js. Both run the cases in internal/scrub/testdata/cases.json.

08the diagnostics zip#

Send diagnostics is one zip with what's needed to read a problem on a machine nobody is sitting at: logs, versions, the settings in force and the system page's numbers, and for one run its journal. All text goes through scrub. Your own words and attachments, such as chat and images, stay out unless include_content is set, and then only for the one run asked about.

The preview and the save both come from the same list of parts, so the list the operator confirms is the list that is saved. A save writes to <data dir>/diagnostics and answers with the zip's path. Both are the settings page's own presses, and no tool or card reaches them. The bundle replaces this user's home path with ~ and this computer's name with <host>.

09crash reports#

Crash reports are kept on this machine. The core's, in internal/crash, are written when a goroutine smith started panics, under the data dir and never sent anywhere by that package. A report is named <UTC time>-core.txt and holds the last 200 log lines. At most 20 are kept, and pruning removes a dropped report's .handled marker too.

The desktop app writes its own, <time>-app.txt, into the same folder. They are scrubbed before they are written. A report is handled once the user saved or dismissed it, and that is a <name>.handled marker beside it. The app reads the reports with no marker before the core starts, so only earlier launches' crashes count, and marks them handled. What the start screen shows of them is not checked here.

Sending a crash is the operator's press on the crash banner, which posts through /api/desk/report.