Tisty 1.5.0
Nothing is turned away for what it holds any more.
A document brought in by an assistant used to be refused if it looked like it
carried a credential, and what that came down to was two lines with an equals
sign whose left side was all capitals and whose right side ran past twelve
bytes. It never looked at the value. Documentation that merely explained which
environment variables an application reads was refused, and so was the same
documentation with every value already replaced by the word REDACTED — the word
is long enough to trip it. Of two hundred and forty documents migrated out of
Notion and Craft, eleven were locked out; three of them held no credential at
all. The refusal said only that the file held a key or a password, so there was
nothing to do but guess which line it meant.
The reasoning behind that guard does not survive contact with what the guard
protects. The document goes into the person's own store, from a file already on
their own disk, and the assistant that called for it could have read that file
by itself anyway. It defended nothing and cost real work. So the guard is gone,
and what replaces it is a notice: when Tisty sees something shaped like a live
credential, the document comes in exactly as it was written, with a warning
added at the top naming what it saw. The person reads it, and decides — delete
the secret, change it, leave it, delete the warning. That is a decision Tisty
was never in a position to make for them.
Placing that notice turned out to be the hard part. Written naively it destroys
the document: markdown continues a quote onto the line below it, so a callout
with no blank line after it swallows the paragraph — or the whole table — that
follows, and the editor then writes that back to disk with the quote marks baked
in. Put above a document that does not open with a heading, it becomes the
title, since the title is the first line with words in it. Inserted on every
write, it stacks: an assistant that reads a document and writes it back finds
the same secret and adds another copy, without limit. Appended to a document
whose code fence was left open, it lands inside the code and is never seen at
all. The notice now looks for a place where none of that can happen, checks the
title is still the title, and checks the result is something the editor can
still open. There is exactly one, however many secrets it found.
Any kind of file can be attached now. The old list named thirty-four extensions
and refused everything else, which meant a Python script, a JSON file, a
Terraform plan or a dotfile could not be kept beside the document that discussed
them. Nothing an attachment contains is executed by Tisty — the only things the
window renders are the ones already allowed — so the list was guarding a door
onto a wall. What remains is the one check that earns its keep: a file whose
bytes are not the kind its name claims is still refused, because what came back
out of Tisty would not open.
A markdown file written on Windows comes in. Every one of them carried carriage
returns, and every one of them was refused as holding control characters — the
tidying step did strip them, but only for files that failed validation first, so
a perfectly good document kept its returns right up until the check that killed
it.
The detector that remains reads the value rather than its shape. A reference
like '\', a placeholder, a plain URL, anything short: none of them are
credentials. A provider's prefix, a connection string with a password inside it,
or a webhook address is one on sight, and it no longer needs to be assigned to
anything to be spotted. What it reports names the line and the variable, and
never repeats the value. And the tools stopped promising what they no longer do:
the instructions an assistant reads used to state that a key or a password never
comes in, whatever it is named.
Full Changelog: v1.4.1...v1.5.0