Write down what Stalwart's x:PublicKey registry does, and withdraw the key manager #285

Closed
opened 2026-09-05 07:57:03 +00:00 by jcoffey-dev · 0 comments
Owner

Docs only. Nothing in web/ or server/ differs from maingit diff main is two files.

What happened

This branch started as a revival of #67 (a Settings section for managing public keys, closed unmerged on 2026-08-26), ported onto current main and re-probed against the live 0.16.20. It got as far as working, translated and verified in a browser — and then ran into the reason #67 was closed in the first place, which no amount of probing changes:

Nothing in ihasmail signs, encrypts, decrypts or verifies with a key. A page for managing them is furniture, not a feature. It ends up telling the reader in its own footnote that adding a key does nothing. So it is withdrawn again, deliberately this time.

What stays, and why

The probing was the expensive part, and it is true whether or not a UI ever ships. It spent nine days living only inside a closed pull request, which is exactly why the work got done twice. It now lives in KNOWN-ISSUES.md, consolidated into one entry and framed as what Stalwart does rather than what ihasmail offers.

All confirmed live on 0.16.20 (2026-09-05), full round trip — create, read back, rename, patch, destroy — for both formats:

  • An ordinary user may read and write their own keys, though Stalwart documents every sysPublicKey* permission as administrative. A malformed create is refused invalidProperties naming key, not forbidden — a rejection of the key, not of the person.
  • The registry takes S/MIME certificates as well as OpenPGP keys, and parses both. A real self-signed X.509 certificate registered and removed cleanly; a malformed one gets its own decoder: "Failed to decode X509 certificate: BER decoding error…". Worth checking rather than assuming — every other message the registry returns names OpenPGP, even for input that isn't OpenPGP at all.
  • A key can parse perfectly and still be refused, with different words. A sign-and-certify key — what gpg --quick-generate-key produces — gets "Could not find any suitable keys in OpenPGP public key". That is not a paste error and must not be shown as one.
  • emailAddresses comes back as {} when empty — an object where a JMAP list property should be an array. It type-checks against a hand-written interface, then throws in join() mid-render.
  • A create answers with the id alone, no createdAt. Patching key is allowed, and probably shouldn't be used.
  • expiresAt is the registry's field, not the key's. A certificate valid for a year registers with expiresAt: null.

ROADMAP

Rewritten to say plainly that key management has been built and withdrawn twice, that Stalwart is not the obstacle, and that verifying a signature — which needs only public keys and touches none of the private-key problem — is the shortest route to a key being worth having.

Encryption at rest moves from "not offered yet" to refused. encryptionAtRest is a field on x:AccountSettings (there is no x:EncryptionAtRest object, and its value is a typed object, not a bare string). It is self-service and would be easy to add. It won't be: turning it off does not decrypt what is already there, so enabling it is a one-way door, and a toggle that reads as "make my mail safer" while quietly being irreversible is the wrong thing to hand an ordinary user.

Checks

main's baseline exactly: 1071 web + 142 server tests, typecheck, build and i18n:check clean, catalogues back to 1219/1243 with 24 falling back.

The code, if it is ever wanted, is in this branch's first two commits.

Merged 2026-09-05 as coffey-labs/ihasmail@7aa2e374d4

Rebuilt from: git history, session transcript.

**Docs only.** Nothing in `web/` or `server/` differs from `main` — `git diff main` is two files. ## What happened This branch started as a revival of [#67](https://github.com/Coffey-Labs/ihasmail/pull/67) (a Settings section for managing public keys, closed unmerged on 2026-08-26), ported onto current `main` and re-probed against the live **0.16.20**. It got as far as working, translated and verified in a browser — and then ran into the reason #67 was closed in the first place, which no amount of probing changes: **Nothing in ihasmail signs, encrypts, decrypts or verifies with a key.** A page for managing them is furniture, not a feature. It ends up telling the reader in its own footnote that adding a key does nothing. So it is withdrawn again, deliberately this time. ## What stays, and why The probing was the expensive part, and it is true whether or not a UI ever ships. It spent nine days living only inside a closed pull request, which is exactly why the work got done twice. It now lives in `KNOWN-ISSUES.md`, consolidated into one entry and framed as *what Stalwart does* rather than *what ihasmail offers*. All confirmed live on **0.16.20 (2026-09-05)**, full round trip — create, read back, rename, patch, destroy — for both formats: - **An ordinary user may read *and* write their own keys**, though Stalwart documents every `sysPublicKey*` permission as administrative. A malformed create is refused `invalidProperties` naming `key`, not `forbidden` — a rejection of the key, not of the person. - **The registry takes S/MIME certificates as well as OpenPGP keys, and parses both.** A real self-signed X.509 certificate registered and removed cleanly; a malformed one gets its own decoder: *"Failed to decode X509 certificate: BER decoding error…"*. Worth checking rather than assuming — every *other* message the registry returns names OpenPGP, even for input that isn't OpenPGP at all. - **A key can parse perfectly and still be refused, with different words.** A sign-and-certify key — what `gpg --quick-generate-key` produces — gets *"Could not find any suitable keys in OpenPGP public key"*. That is **not** a paste error and must not be shown as one. - **`emailAddresses` comes back as `{}` when empty** — an object where a JMAP list property should be an array. It type-checks against a hand-written interface, then throws in `join()` mid-render. - **A create answers with the id alone**, no `createdAt`. **Patching `key` is allowed**, and probably shouldn't be used. - **`expiresAt` is the registry's field, not the key's.** A certificate valid for a year registers with `expiresAt: null`. ## ROADMAP Rewritten to say plainly that key management has been built and withdrawn twice, that Stalwart is not the obstacle, and that **verifying a signature** — which needs only public keys and touches none of the private-key problem — is the shortest route to a key being worth having. **Encryption at rest moves from "not offered yet" to refused.** `encryptionAtRest` is a field on `x:AccountSettings` (there is no `x:EncryptionAtRest` object, and its value is a typed object, not a bare string). It is self-service and would be easy to add. It won't be: turning it off does not decrypt what is already there, so enabling it is a one-way door, and a toggle that reads as "make my mail safer" while quietly being irreversible is the wrong thing to hand an ordinary user. ## Checks `main`'s baseline exactly: 1071 web + 142 server tests, typecheck, build and `i18n:check` clean, catalogues back to 1219/1243 with 24 falling back. The code, if it is ever wanted, is in this branch's first two commits. **Merged** 2026-09-05 as coffey-labs/ihasmail@7aa2e374d4cb <sub>Rebuilt from: git history, session transcript.</sub>
This repo is archived. You cannot comment on issues.