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 <noreply@anthropic.com>
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
|
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.
|
`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
|
## Update checks
|
||||||
|
|
||||||
| Variable | Default | What it does |
|
| 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_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. |
|
| `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
|
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.
|
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
|
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
|
write it, and guessing month-first would silently move a date by months rather
|
||||||
than failing visibly.
|
than failing visibly.
|
||||||
|
|
||||||
## The shortcuts
|
## Just start typing
|
||||||
|
|
||||||
Press ++q++ to jump to the quick-add box from anywhere, ++t++ for Today, ++u++ for
|
There is no shortcut to remember. Press a letter anywhere in the app and you are
|
||||||
Upcoming, ++cmd+k++ to search, and ++question++ for the full list.
|
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
|
- As a Rune: rune.md
|
||||||
- Configuration: configuration.md
|
- Configuration: configuration.md
|
||||||
- Using it:
|
- Using it:
|
||||||
|
- Signing in: signing-in.md
|
||||||
- Quick add: quick-add.md
|
- Quick add: quick-add.md
|
||||||
- Filters: filters.md
|
- Filters: filters.md
|
||||||
- Importing from Todoist: import.md
|
- Importing from Todoist: import.md
|
||||||
- Connecting things:
|
- Connecting things:
|
||||||
- Calendar and CalDAV: caldav.md
|
- Calendar and CalDAV: caldav.md
|
||||||
- Mail to task: mail.md
|
- Mail to task: mail.md
|
||||||
|
- Mailboxes: mailboxes.md
|
||||||
- Claude (MCP): mcp.md
|
- Claude (MCP): mcp.md
|
||||||
- AI features: ai.md
|
- AI features: ai.md
|
||||||
# openapi.yaml is deliberately not in the nav: MkDocs copies it to the site as a
|
# openapi.yaml is deliberately not in the nav: MkDocs copies it to the site as a
|
||||||
|
|||||||
Reference in New Issue
Block a user