fix(gui,cli,core): offer the CAPTCHA in the browser when the web view cannot start (B195)

The verification window now runs in its own process, so the app survives
when WebKit cannot start its sandbox on secureblue, but the CAPTCHA still
could not be solved there (#29). WebKit binds the journal socket with
`--ro-bind-try`, bubblewrap only skips a missing path, not an unreadable
one, and WebKit has no switch to leave the socket out.

Proton Mail Bridge never uses a web view: it opens verify.proton.me in the
system browser and retries with the original challenge token, typed with
the offered methods. Do the same as a fallback.

- core: `browser_verification_url` and `browser_verified` build the page
  URL and the retry credential from the challenge
- gui: when the verification window fails, a dialog opens the page in the
  browser and continues the sign-in once the user is done
- cli: `pdfs login` handles a CAPTCHA the same way instead of failing
- i18n: translate the new dialog in every catalog
- docs: B195, TROUBLESHOOTING.md, ARCHITECTURE.md, changelog

Fixes #29
This commit is contained in:
nvrl committed 2026-10-08 19:02:29 +02:00
1 parent 07c9b675d3
commit d13e74fc12
16 files changed
+752 -426

No files matched your search

+7 -3
View File
@@ -563,9 +563,13 @@ sequenceDiagram
- The page may post the token as an object or as a JSON string; both are accepted.
- The page runs in a WebKitGTK view inside a child `pdfs-app`. WebKit aborts its process when its
sandbox cannot start, as on hardened systems such as secureblue (B195). In the child, that ends
the verification, and the app says why, instead of closing the app.
- The CLI has no web view. It fails with a message to sign in once with `pdfs-app`; the stored
session then works for the CLI and the service.
the web view, not the app.
- When the child fails, the app offers the page in the user's own browser instead, as Proton Mail
Bridge does. A browser tab cannot post the token back, so the user says when they are done, and
the retry carries the challenge token itself, which the solved page made good. Its type header
lists every offered method (`auth::browser_verified`).
- The CLI has no web view, so it always takes the browser path: it prints the page's URL and waits
for Enter.
---