mirror of
https://github.com/narrrl/narl-workspace.git
synced 2026-11-03 16:41:27 +01:00
The README grew a section per feature and is a good reference, but nothing said where to begin. docs/wiki now has a getting-started page, a guide that walks through one day with the workspace and explains each part where it comes up, and a page per part of the app, each with screenshots of what it describes. Three pages are read out of the code rather than written, so they cannot drift from it: the keys and commands from Help.svelte and commands.ts, the same lists `:help` draws; the settings from .env.example, which gains a heading for the vault, trash and history settings so they no longer sit under mail; and the API from the README's table. `make wiki` writes them, and `--check` fails when one is stale or a link between pages leads nowhere. `--publish` lays the pages out for a GitHub wiki: links without `.md`, images beside them, `[[` escaped so the wiki does not take a command's help text for a link to a page. The screenshots are taken by `make screenshots`: the debug binary on a temporary data directory, with a password made up for the run, filled with an example workspace over the API, and a headless Chromium driven over the DevTools protocol through the views the docs show. Nothing outside the temporary directory is touched but docs/images, and the pictures are cut to 256 colours, a third of their size, which a dark UI does not show. The README opens with the banner, a CI badge, the guide, the features grouped by what they are for, and six of the screenshots.
74 lines
3.3 KiB
Markdown
74 lines
3.3 KiB
Markdown
# The vault
|
|
|
|
Some files deserve more than the login: scans of documents, contracts, health
|
|
records. The vault encrypts them at rest under a password of their own. They
|
|
stay unreadable to anyone without it: someone with a copy of the data directory
|
|
or the Proton account the mirror writes to, and even a logged-in browser while
|
|
the vault is shut.
|
|
|
|
> **There is no recovery.** Forget the vault password and every sealed file is
|
|
> gone, from the server and from every backup. The password is not in `.env`,
|
|
> not in `diary.db` and not in the mirror.
|
|
|
|
## Using it
|
|
|
|
| command | what it does |
|
|
| --- | --- |
|
|
| `:vault` | set the password the first time (ten characters at least); afterwards, say whether the vault is open |
|
|
| `:unlock` / `:lock` | open / close the vault |
|
|
| `:upload!` | upload files sealed, encrypted as they stream in, so the plaintext never touches the disk |
|
|
| `:encrypt` | seal the file under the cursor; on a folder or space, seal it for good |
|
|
| `:decrypt` | take the file, or the sealed folder, back out |
|
|
| `:passwd` | change the password |
|
|
|
|
A sealed file carries a lock in the list, and the bar says `vault open` while it
|
|
is. While the vault is shut, `Enter` on a sealed file asks for the password.
|
|
|
|
## Sealed folders
|
|
|
|
`:encrypt` on a folder or a space seals it for good: every file in it now, and
|
|
every file that lands in it later. An upload, an import, an SFTP write and a
|
|
file moved in are all sealed on the way in. While the vault is shut they are
|
|
refused rather than stored readable. Folders made inside are sealed too.
|
|
`:decrypt` on the folder unseals it with everything in it.
|
|
|
|
Documents are not files and stay readable. Only the bytes of files are sealed;
|
|
the names of sealed files, and the documents around them, are as readable in
|
|
`diary.db` as everything else.
|
|
|
|
## When it closes
|
|
|
|
The vault closes itself after `WORKSPACE_VAULT_IDLE_MIN` minutes with nobody
|
|
using it (15 by default), on logout, and whenever the server restarts. The key
|
|
is dropped from memory then. While it is shut:
|
|
|
|
- a sealed file shows as sealed and nothing more;
|
|
- a share link never serves one, open or not;
|
|
- `:export!` refuses.
|
|
|
|
A sealed file is served with `Cache-Control: no-store`, so the browser keeps no
|
|
copy once the vault shuts. A sealed file is never indexed for search.
|
|
|
|
## Changing the password
|
|
|
|
`:passwd` makes a new master key as well as a new password. The old password
|
|
stops opening anything at once. Every sealed file is then sealed again under the
|
|
new key in the background while the vault is open; `:vault` shows how far it
|
|
has come. After that, an old copy of `diary.db` together with the old password
|
|
opens nothing still kept anywhere.
|
|
|
|
## How it works
|
|
|
|
Argon2id turns the password into a key that seals a random master key; only
|
|
that sealed copy is stored. Each file has a random key of its own, sealed under
|
|
the master key in the file's header together with the file's id. Its bytes are
|
|
AES-256-GCM in 64 KiB records, the last one marked as last, so a file that is
|
|
swapped, cut short or changed refuses to open.
|
|
|
|
Sealing an existing file writes it again under a new id, rewrites the documents
|
|
that embed it, and deletes the plaintext from the disk and from Proton Drive.
|
|
|
|
Over the [SFTP mount](SFTP.md), a key reads sealed files only once it has been
|
|
given vault access with `:sshkey vault <name> on`, and only while the vault is
|
|
open in a browser.
|