Commit graph

2 commits

Author SHA1 Message Date
randogoth
9f14c1f651 Add Google OAuth, and let feed URLs come from a secret command
Google requires OAuth for calendar access; app passwords stopped working for
CalDAV, CardDAV and IMAP in March 2025, so there is no simpler path to offer.

- Authorisation code flow over a loopback redirect, which is what Google
  supports for desktop clients now the copy-paste flow is gone, with PKCE so an
  intercepted code is useless without the verifier. Only the refresh token is
  persisted, 0600, in the state directory.
- An expired grant is reported as itself: a consent screen still in Testing has
  its refresh tokens expired after 7 days, and "run calcalist google login" is
  more use than Google's bare invalid_grant.
- doctor reports whether each Google endpoint is still authorised, since an
  installation that worked last week can stop with nothing having changed here.

A webcal URL may now come from a command instead of the config. Google's secret
iCal address grants read access to a whole calendar to anyone holding it, so
writing it into a file described as portable and secret-free was a contradiction.

Fixed a serious defect in the first draft of this module: random_token used
fs::read on /dev/urandom, which reads to end of file. /dev/urandom has no end,
so it allocated until the machine ran out of memory — it took the editor down
with it. It now reads exactly 32 bytes, and a randomness failure is fatal rather
than falling back to the clock, since a guessable state or PKCE verifier defeats
the point of having them.

Verified end to end against a live Posteo CalDAV calendar: pimsync validated the
generated config against the real server, 58 events from a public feed were
mirrored and pushed, and a second run was a no-op.

97 tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-10 13:01:06 +03:00
randogoth
2bc93262f8 Scaffold calcalist: repo, toolchain, config model and doctor
Initialise the project per the approved implementation plan (M0).

- Pin the toolchain with devbox: Rust 1.97.1, pimsync 0.5.11, jujutsu 0.44.0,
  and radicale 3.7.8 for later integration tests.
- Add the configuration model with full referential validation, reporting
  every problem in one pass rather than short-circuiting on the first.
- Add `calcalist doctor`, verifying pimsync's presence and version series,
  the state directory, and the configuration.
- Define the whole CLI surface; only `doctor` acts, the rest exit 2 rather
  than pretending to work.
- Rewrite SPECS.md: Rust naming conventions in place of the JS/TS style
  lines, a `devbox run check` gate instead of a pre-commit hook (jj runs no
  git hooks), and the sync semantics the spec previously left unstated.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 09:31:32 +03:00