feat: add Linux OAuth adapters

Add a bounded libcurl transport with verified TLS, no redirects or retries, sanitized failures, binary-safe requests, and resolved-address enforcement for cleartext loopback traffic.

Add shell-free xdg-open launching and a one-shot IPv4 loopback callback receiver with strict HTTP/query parsing, deadlines, fixed callback path, and RAII cleanup. Token parsing, Secret Service, and Graph remain follow-up phases.
This commit is contained in:
2026-07-18 11:33:06 +01:00
parent dd6e02cb55
commit 295acbc125
12 changed files with 2095 additions and 28 deletions

View File

@@ -183,10 +183,40 @@ consent policy remains authoritative and may require administrator approval or
block consent. A desktop binary distributed as open source is not a confidential
client and must not embed or depend on a client secret.
This boundary does not yet contain a concrete HTTP transport, system-browser or
loopback-listener adapter, token JSON parsing, a Secret Service backend, Graph
requests, or usable account setup. Those concrete desktop, HTTP, and secret
storage adapters are the next slice. Read-only Microsoft Graph calendar
The generic boundary deliberately contains no concrete networking or desktop
code. The Linux adapters below supply the transport, browser launch, and
loopback listener. Token JSON parsing, Secret Service storage, Graph requests,
and usable account setup remain later slices. Read-only Microsoft Graph calendar
discovery and delta synchronization follows; delta links remain opaque and are
persisted only through the calendar/window transaction described above. Remote
writes and conflict resolution come later.
### Concrete Linux adapters
The concrete adapter phase provides a libcurl transport that keeps certificate
and host verification enabled, bounds response bodies and
connection/operation timeouts, and disables automatic redirects. It implements
one request attempt only: neither the adapter nor the generic transport retries.
Cleartext HTTP is accepted solely for explicit loopback tests; provider traffic
uses HTTPS.
The browser adapter launches `xdg-open` directly without a shell, so an
authorization URL is never interpreted as shell syntax. The callback receiver
binds IPv4 `127.0.0.1` on a dynamically assigned port, advertises that port with
the `localhost` host and fixed `/nocal/oauth/callback` path, and handles one
bounded callback before closing. Bounded header/input sizes and a deadline keep
a local peer from holding the authorization process indefinitely.
The Entra registration must configure Nocal as a Mobile and desktop public
client with `http://localhost/nocal/oauth/callback`. Microsoft ignores the port
when matching a `localhost` redirect, which permits the runtime-selected port.
Using an HTTP redirect with the literal `127.0.0.1` host instead requires editing
the application manifest, and IPv6 loopback redirect addresses are currently
unsupported. The advertised `localhost` URL therefore remains distinct from the
IPv4-only listener binding.
Concrete token JSON parsing, Secret Service storage, Graph requests, account UI,
and usable account setup are still absent. libsecret's synchronous calls may
block; the next adapter isolates them behind an off-render-thread boundary
rather than calling them from the TUI loop. Read-only Graph discovery and delta
follow token parsing and secret persistence.