docs: skriv det, der blev bygget, og ret det, der ikke passer længere
To nye sider. Postkasser: at stjerne i Gmail eller flage i iCloud og Fastmail bliver til opgaver, at hver postkasse hører til den, der forbandt den, at app-kodeord er noget andet end ens rigtige, og at Office 365 ikke kan nås ad den vej — sidstnævnte skrevet ned frem for at blive opdaget ved at prøve. Og at logge ind: kodeord, totrinskode og passkeys, med hvorfor en passkey ikke kan laves på en bar IP-adresse. Konfigurationen manglede VERDANDE_SECRET_KEY, som er den, det koster mest ikke at vide noget om: mister man nøglen, skal postkasserne forbindes forfra. Begrundelsen står med — det er kopierne, ikke serveren, der er problemet, for de kan hentes gennem fladen. Og genvejsafsnittet i quick-add beskrev q, t og u, som ikke findes længere. En dokumentation, der lover taster, der ikke gør noget, er værre end ingen: man prøver, der sker intet, og så tror man appen er i stykker. Bygget med --strict; alle krydshenvisninger rammer. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 5
parent
d02d8edfe9
commit
997dffe01c
+36
-2
@@ -55,6 +55,36 @@ One registration serves every user on the instance; each person authorises their
|
||||
own mailbox from **Settings → Gmail**. The redirect URI is derived from
|
||||
`VERDANDE_BASE_URL`, so it cannot drift out of step with what you registered.
|
||||
|
||||
## Secrets
|
||||
|
||||
| Variable | Default | What it does |
|
||||
|---|---|---|
|
||||
| `VERDANDE_SECRET_KEY` | — | Encrypts the mail tokens and mailbox passwords in the database. 32 bytes of base64. |
|
||||
|
||||
Mail tokens and [mailbox](mailboxes.md) passwords are encrypted at rest, and the
|
||||
key does not live in the database. That is the whole point: **backups can be
|
||||
downloaded through the interface**, so a copy that ends up somewhere it should
|
||||
not would otherwise open your mail.
|
||||
|
||||
Leave the variable empty and verdande writes a key to `secret.key` in the data
|
||||
directory on first start, mode `0600`. Backups are a `VACUUM INTO` of the
|
||||
database alone, so the key file is not in them.
|
||||
|
||||
Generate one yourself if you would rather keep it out of the volume entirely:
|
||||
|
||||
```
|
||||
openssl rand -base64 32
|
||||
```
|
||||
|
||||
!!! warning "Lose the key and the mailboxes must be reconnected"
|
||||
Nothing else is lost — tasks, projects, files and history are not encrypted —
|
||||
but a token that cannot be decrypted cannot be used, and there is no way back
|
||||
from a key that is gone. If you restore a database somewhere new, bring
|
||||
`secret.key` with it, or set `VERDANDE_SECRET_KEY` to the same value.
|
||||
|
||||
A database written before there was a key is read as it stands and encrypted the
|
||||
next time each value is written, so turning this on costs nobody a reconnection.
|
||||
|
||||
## Update checks
|
||||
|
||||
| Variable | Default | What it does |
|
||||
@@ -64,9 +94,13 @@ own mailbox from **Settings → Gmail**. The redirect URI is derived from
|
||||
| `VERDANDE_PANEL_TOKEN` | — | An API token from that panel, belonging to somebody with control of this server. |
|
||||
| `VERDANDE_PANEL_SERVER_ID` | — | Which server to restart — the id in the panel's URL. |
|
||||
|
||||
All three together let **Indstillinger → Notifikationer** restart this instance,
|
||||
All three together let **Settings → Notifications** restart this instance,
|
||||
which is also how it picks up a new version: a container cannot replace its own
|
||||
image, so the panel recreates it and pulls `:latest` on the way. Any one of the
|
||||
image, so the panel recreates it and pulls `:latest` on the way. The request asks
|
||||
the panel for a *scheduled* restart rather than an immediate one — an immediate
|
||||
one is carried out while the request is still open, and stopping the container
|
||||
kills the very process waiting for the answer, so the panel never gets to the
|
||||
half that starts it again. Any one of the
|
||||
three alone does nothing, and the page names the ones that are missing.
|
||||
|
||||
The token is a panel credential with control over that server. Anybody who can
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
# Mailboxes
|
||||
|
||||
Star a mail and it becomes a task.
|
||||
|
||||
This is the other direction from [mail to task](mail.md): instead of forwarding
|
||||
something, Verdande reads a mailbox you connect and makes a task out of anything
|
||||
you have flagged. Nothing else in the mailbox is touched, and nothing is ever
|
||||
sent.
|
||||
|
||||
Each mailbox belongs to the person who connected it. Two people on one instance
|
||||
connect their own and see only their own — there is no shared inbox and no
|
||||
administrator who can read yours.
|
||||
|
||||
## Gmail
|
||||
|
||||
**Settings → Integrations → Gmail → Connect.**
|
||||
|
||||
Gmail needs an OAuth client, which is the instance's registration with Google
|
||||
rather than anybody's account — see [Configuration](configuration.md#gmail).
|
||||
Once it is set up, each person connects their own mailbox through it.
|
||||
|
||||
Choose what makes a task:
|
||||
|
||||
| Trigger | What it reads |
|
||||
|---|---|
|
||||
| Starred | Anything you have starred |
|
||||
| Label | Anything carrying a label you name |
|
||||
|
||||
!!! note "The app stays Internal if your client is Internal"
|
||||
An OAuth client registered as *Internal* in a Google Workspace can only be
|
||||
used by accounts in that workspace. A personal `@gmail.com` address will be
|
||||
refused with `org_internal`, and that is the client working as configured.
|
||||
Switching to *External* means refresh tokens that expire every seven days
|
||||
until Google has verified the app — for one personal account, forwarding to
|
||||
your [mail-to-task address](mail.md) is the shorter road.
|
||||
|
||||
## iCloud, Fastmail and anything else over IMAP
|
||||
|
||||
**Settings → Integrations → Mailboxes → Add a mailbox.**
|
||||
|
||||
You need three things:
|
||||
|
||||
| Field | Example |
|
||||
|---|---|
|
||||
| IMAP server | `imap.mail.me.com:993` |
|
||||
| Username | your address |
|
||||
| App password | not your ordinary password — see below |
|
||||
|
||||
The connection is tested before it is saved. A mailbox that cannot be read is
|
||||
refused while you are still looking at the form, rather than accepted and then
|
||||
failing quietly every ten minutes.
|
||||
|
||||
Flag a message — the flag, not unread — and it becomes a task on the next sweep.
|
||||
Unread is a state you are still using yourself, and a sync that consumed it would
|
||||
be taking something away.
|
||||
|
||||
### App passwords
|
||||
|
||||
Every host worth naming issues a separate password for applications, which you
|
||||
can withdraw on its own without changing the one you sign in with. Use that.
|
||||
|
||||
- **iCloud** — [appleid.apple.com](https://appleid.apple.com) → Sign-In and
|
||||
Security → App-Specific Passwords
|
||||
- **Fastmail** — Settings → Privacy & Security → Integrations → New app password
|
||||
|
||||
The password is [encrypted at rest](configuration.md#secrets), and it is never
|
||||
returned by the API once saved.
|
||||
|
||||
### Office 365 does not work here
|
||||
|
||||
Microsoft has closed IMAP to passwords; it wants its own OAuth flow. There is no
|
||||
app password that will get you in, and a mailbox pointed at `outlook.office365.com`
|
||||
will be refused. Forward to your [mail-to-task address](mail.md) instead.
|
||||
|
||||
## How often
|
||||
|
||||
Every ten minutes, in the background. **Fetch now** does it immediately, which is
|
||||
for when you have just connected something and want to see it work.
|
||||
|
||||
A run reads at most twenty-five messages, so a mailbox with years of flagged mail
|
||||
in it fills up over several sweeps rather than in one.
|
||||
|
||||
## Disconnecting
|
||||
|
||||
**Disconnect** on the mailbox. The tasks it made stay — they are your work now,
|
||||
not the mailbox's. Nothing is read after that, and the stored credential is
|
||||
deleted rather than merely disabled.
|
||||
+18
-3
@@ -70,7 +70,22 @@ an error message and a lost thought.
|
||||
write it, and guessing month-first would silently move a date by months rather
|
||||
than failing visibly.
|
||||
|
||||
## The shortcuts
|
||||
## Just start typing
|
||||
|
||||
Press ++q++ to jump to the quick-add box from anywhere, ++t++ for Today, ++u++ for
|
||||
Upcoming, ++cmd+k++ to search, and ++question++ for the full list.
|
||||
There is no shortcut to remember. Press a letter anywhere in the app and you are
|
||||
writing a task, with the letter you pressed already in the field. The thought does
|
||||
not have to survive a journey to find somewhere to put it.
|
||||
|
||||
It only fires when nothing else has focus — a key pressed at a field, a button or
|
||||
a link belongs to that thing.
|
||||
|
||||
Under the field is a line saying what the parser reads: `#` project, `/` section,
|
||||
`@` label, `p1` priority, and an example date. It appears while you are typing,
|
||||
which is the one moment a placeholder cannot help you.
|
||||
|
||||
++cmd+k++ opens the palette — search, and navigation to anywhere in the app.
|
||||
|
||||
!!! note "The single letters used to navigate"
|
||||
++t++ for Today and ++u++ for Upcoming are gone. One keyboard cannot both
|
||||
spell *tal med Anders* and jump to Today on the same ++t++, and capturing is
|
||||
the thing done fifty times a day. The palette does the rest.
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# Signing in
|
||||
|
||||
Three ways in, and you can have all of them at once.
|
||||
|
||||
## A password
|
||||
|
||||
What the first account is created with. Nothing is emailed, nothing is registered
|
||||
anywhere: the first person to open a fresh instance creates the administrator
|
||||
account, and after that people arrive by invite link.
|
||||
|
||||
## A code on top of it
|
||||
|
||||
**Settings → Account → Two-factor.** An ordinary TOTP secret — any authenticator
|
||||
app reads the QR code. Once it is on, the password alone is not enough.
|
||||
|
||||
Recovery codes are shown once, when you turn it on. They are the way back if the
|
||||
phone is gone, and they are not shown again.
|
||||
|
||||
## A passkey
|
||||
|
||||
**Settings → Account → Passkeys → Add a passkey.**
|
||||
|
||||
A key on a device instead of a secret in your head. The private half never leaves
|
||||
the device — a phone's secure element, a laptop's keychain, a hardware key — and
|
||||
the signature is bound to the address it was made for, so a convincing copy of the
|
||||
sign-in page at a different address gets nothing.
|
||||
|
||||
Give each one a name you will recognise later. *min bærbare* is what makes a list
|
||||
of keys reviewable, and a list nobody can read is a list nobody revokes from.
|
||||
|
||||
Passkeys need the address in `VERDANDE_BASE_URL` to be a hostname. Browsers refuse
|
||||
to make one for a bare IP address, so an instance reached at `http://192.168.1.10:8080`
|
||||
will show the passkey section as unavailable rather than failing at the moment
|
||||
somebody tries.
|
||||
|
||||
!!! note "One is enough, two is better"
|
||||
Lose the only device holding your only passkey and you are back to the
|
||||
password. Keep the password, or register a second key — a phone as well as a
|
||||
laptop.
|
||||
@@ -48,12 +48,14 @@ nav:
|
||||
- As a Rune: rune.md
|
||||
- Configuration: configuration.md
|
||||
- Using it:
|
||||
- Signing in: signing-in.md
|
||||
- Quick add: quick-add.md
|
||||
- Filters: filters.md
|
||||
- Importing from Todoist: import.md
|
||||
- Connecting things:
|
||||
- Calendar and CalDAV: caldav.md
|
||||
- Mail to task: mail.md
|
||||
- Mailboxes: mailboxes.md
|
||||
- Claude (MCP): mcp.md
|
||||
- AI features: ai.md
|
||||
# openapi.yaml is deliberately not in the nav: MkDocs copies it to the site as a
|
||||
|
||||
Reference in New Issue
Block a user