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 accept. Accepts are kept in
ticket-accepts.jsonin the core data dir, a map from ticket id to the time and a digest (;). See on-disk. - The digest. It is the sha256 of the ticket body, then for each comment in time order (then id) a line break, the comment id, a line break and its body.
- A newer install comment. A comment by an install after the accept's time makes the ticket untrusted again. A comment that is not from an install doesn't.
- The press. Accept is the ticket page's own press,
/api/desk/tickets/accept. No tool or card reaches it. It records the accept only when the ticket still reads as the card showed it, by sha256. Otherwise it answers 409ticket_changed. When the ticket was untrusted, the project's pinned manager is told it was accepted.
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:
- an install-created ticket's body, in a
ticket_sourcetag with the id, title, author and origin; - an install-written comment, in a
commenttag with its kind, time, author and origin; - the same wrapping on pages of tickets and on search hits.
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.
- Screenshots are png or jpg files inside the shell data folder or the asset folders (
<core data dir>/assets/folders), at most 4 MiB each (shotPath). A path outside both, or resolving out of the one it is in through a link, is refused, and the refusal names both folders. The namewindowasks the app for a capture of its window, written underreports/shots/in the data dir. - The operator edits the title and text on the card, and the chat goes in only when they tick include this conversation: the last 40 KiB of operator and conductor messages, scrubbed.
- Send needs a linked install. Without one the card answers
not_linked: link this install in settings › system, then send again. - Send waits 25 seconds for the intake. A report that hasn't gone by then is in the outbox. The card ends as filed as
smith/<id>, saved to the outbox, or couldn't send.
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.
04the install link#
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]:
- the value of an
AuthorizationorCookieheader, as http text or a json field; - a bearer credential;
- a
key: valueorkey=valuepair where the key contains token,_key, apikey, secret, password, passwd or cookie; - a token that shows itself by its prefix:
sk-,ghp_and its siblings,xoxandAKIA.
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.