Mail, files, calendar and contacts for the ordner suite, from the shell — each protocol is a plugin

Accounts, credentials and keychain; all four protocols implemented #16

Open pipobscure.com
targeting main from accounts-and-protocols
Open opened by and assigned to pipobscure.com
targeting main from accounts-and-protocols

Accounts, credentials and the platform keychain, and real implementations of all four protocols (mail, webdav, calendar, contacts) against the ordner suite.

Not yet run against a live server. Every plugin is tested against an in-process fake built from the suite's own source (ordner.fyi). The first real run with app passwords is what this PR is for.

Accounts and credentials #

  • Passwords live in the platform keychain: libsecret (secret-tool) or KWallet on Linux, the macOS keychain, the Windows Credential Manager. A secret only ever reaches those tools on stdin, never in argv. The config file holds no secrets.
  • Each protocol has named accounts, one of them the default. Every protocol command takes --account/-a.
  • ordner <protocol> account list | add | edit | rm | default | password
  • ordner credential list | add | edit | rm | password: a user plus one app password, stored once and shared by any number of accounts. One all-scoped app password then sets up all four protocols with a single prompt:
    ordner credential add lab --user <you>
    ordner mail account add lab --url https://lab.ordner.fyi --credential lab   # likewise webdav, calendar, contacts
    
  • A password is asked for once, then tried against the server: the protocol's check runs with it. A refused password stores nothing. --no-verify skips the trial.
  • Account management stays in the app. Plugins are handed one resolved Account {protocol, name, url, user, password} and never see the config or the keychain.

Protocols #

commands app password scope
mail (JMAP) search, get, send, move, mailboxes, check imap (sending included)
webdav ls, get, put, mkdir, rm, check webdav
calendar (JMAP) list, create, update, rm, calendars, check calendar
contacts (JMAP) search, get, create, update, rm, books, check contacts
  • For every protocol, an account url can be just the origin (https://lab.ordner.fyi). JMAP goes through /.well-known/jmap; webdav finds your files folder via current-user-principal.
  • The suite's jmap-client, ical and xml are vendored under packages/cli/src/vendor/. vendor/README.md records the upstream commits and every local change (Basic auth for app passwords in jmap-client).

Fixes along the way #

  • --json: every failure, usage errors included, now prints the {ok:false, error:{code, message}} envelope with the plugin's own code.
  • Tab completion never worked below the top level from a real shell: the program name and the -- separator reached the parser.
  • The skill generator went only one level deep, so SKILL.md documented no leaf commands.
  • --help listed options that have a short alias twice.

Tests #

  • 88 tests. They use a fake secret-tool (which also logs its argv, so a test can prove no password reached a command line) and fake suite servers.
  • npm test and smoke run under packages/cli/test/loopback-only.ts, which refuses any non-loopback connection. During development one smoke run sent a single session GET to lab.ordner.fyi, with a dummy password, before the fixture URLs were fixed. The guard makes that impossible now.
  • typecheck, test, pack and smoke all pass.

Known gaps, not checked against a real server #

  • That Authorization survives the same-origin 301 from /.well-known/jmap.
  • The exact 401 and wrong-scope responses.
  • WebDAV discovery behind the proxy.
  • Chunked uploads from stdin.
  • Shared or delegated mailboxes, calendars, address books and folders are not reached; only the primary account is used.
  • No creating recurring events, no WebDAV COPY/MOVE.
  • The KWallet, macOS and Windows keychain backends are untested (libsecret was tested against a real gnome-keyring).
Commits 0