feat: add PKCE OAuth boundary

Introduce provider-neutral HTTP contracts and public-client authorization-code orchestration with PKCE S256, strict HTTPS and loopback validation, constant-time state checks, secure OpenSSL entropy, and single-send token exchange semantics.

Add independent protocol and adversarial suites covering RFC 7636, RFC3986 encoding, callback failures, response redaction, and no-retry behavior. Concrete networking, browser/listener, token parsing, Secret Service, and Graph integration remain separate follow-up slices.
This commit is contained in:
2026-07-18 11:11:28 +01:00
parent 787daf00dd
commit dd6e02cb55
11 changed files with 1572 additions and 25 deletions

View File

@@ -164,9 +164,29 @@ Conflict resolution is deterministic: unchanged side wins; otherwise retain
both versions and mark a conflict for the user. Network work happens outside the
render loop and publishes immutable snapshots to it.
The first provider-facing step after the cache is verified is an injectable HTTP
boundary, browser-based authorization-code flow with PKCE, and fake transports
for deterministic authentication and failure tests. Read-only Microsoft Graph
calendar discovery and delta synchronization follows. Graph delta links remain
opaque and are persisted only through the calendar/window transaction described
above; remote writes and conflict resolution come later.
### HTTP and OAuth boundary
Provider code depends on generic request/response and injected transport
interfaces rather than a concrete networking library. Deterministic fakes make
success, protocol failure, transport failure, cancellation, and malformed input
testable without network access. The generic layer performs no automatic
retries: only a provider knows whether an operation is idempotent and how to
interpret service-specific throttling or retry guidance.
Microsoft authentication is designed for a public desktop client. It uses the
system browser and authorization-code flow, a fresh PKCE verifier and `S256`
challenge, and a loopback redirect. The Entra application registration is
multitenant and selects the intended organizational and personal Microsoft
account audience. The initial read-only Graph scope is the delegated
`Calendars.Read` permission. It normally permits user consent, while tenant
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
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.

View File

@@ -129,11 +129,25 @@ offline writes, but remote mutation behavior is not part of this phase. OAuth
tokens and other credentials never belong in the calendar database; account
secrets will be held by the Freedesktop Secret Service.
This foundation does not make Office 365 usable yet: Nocal currently performs no
OAuth flow, HTTP request, or Microsoft Graph synchronization. The next product
slice introduces injectable HTTP and PKCE authentication with fake transports,
then adds read-only Graph delta synchronization. Remote writes remain gated on
the durability and conflict paths being exercised end to end.
The Microsoft sign-in design treats Nocal as a public desktop client: sign-in
will open the system browser, use the authorization-code flow with PKCE `S256`,
and return through a loopback redirect. Its application registration must be
multitenant for the intended organizational and personal Microsoft account
audience. Initial synchronization requests only delegated `Calendars.Read`, not
write access. Users can normally consent to that delegated permission, but
their organization's tenant policy may still require administrator consent or
deny the application. Nocal never embeds a client secret in its open-source
desktop binary.
The provider-neutral HTTP seam accepts an injected transport and can therefore
be exercised with deterministic fakes. It intentionally owns no generic retry
policy; provider operations must decide whether a retry is safe. This phase does
not make Office 365 usable yet. It includes no concrete HTTP transport, real
browser/loopback adapter, token JSON parser, Secret Service backend, Graph call,
or usable account setup. The next product slice supplies concrete desktop,
network, and secret-storage adapters, followed by read-only Graph calendar
discovery and delta synchronization. Remote writes remain gated on the
durability and conflict paths being exercised end to end.
## Local file interchange

View File

@@ -35,10 +35,21 @@ Completed cache foundation:
- Normalized event instances for immutable snapshots
- Reserved transactional outbox and conflict records for later remote writes
Completed HTTP/OAuth boundary:
- Generic injected HTTP transport and deterministic fakes, with retries left to
provider operations
- Public-desktop OAuth authorization code design with PKCE `S256`, system
browser, and loopback redirect
- Multitenant Microsoft account audience and delegated least-privilege
`Calendars.Read`; tenant policy may still require administrator consent or
block user consent
- No client secret in the open-source desktop binary
Next provider-boundary slices:
- Injectable HTTP, PKCE authentication, and deterministic fake transports
- Secret Service credentials; OAuth secrets are never stored in SQLite
- Concrete HTTP, browser/loopback, token JSON, and Secret Service adapters
- OAuth secrets in Secret Service, never SQLite
- Generic `SyncProvider` contract and observable sync status
## 0.3 — CalDAV
@@ -54,10 +65,12 @@ Next provider-boundary slices:
ETag-aware remote writes after the conflict boundary is proven
- Account/calendar management UI and per-calendar ANSI identity
The current cache work is only the prerequisite durable boundary. No network,
OAuth, or Graph synchronization is implemented in that phase. After the cache
passes its verification gates, the immediate sequence is injectable HTTP plus
PKCE and fake transports, then read-only Microsoft Graph delta synchronization.
The cache and generic HTTP/OAuth boundaries are prerequisites, not usable
Microsoft 365 integration. The boundary phase has no concrete HTTP transport,
real browser/loopback adapter, token parser, Secret Service backend, Graph call,
or account setup. The immediate sequence is concrete desktop, HTTP, and Secret
Service adapters, then read-only Microsoft Graph discovery and delta
synchronization.
## 1.0 — distribution quality