Older app builds cannot log events after a server update #1060

Closed
opened 2026-10-04 14:36:47 +00:00 by kayg · 5 comments
Owner

Owner report (2026-10-04)

"I still seem to run an older build on the phone which cannot log events anymore."

An installed app running an older build (from before the latest production deploys: rounds 4–6 today, c39ffe5d9) fails to create Log entries / events. The server API changed under the old client, and the old client gets an error it does not explain.

Wanted

  1. Find what an older client sends that the current server rejects (compare the request shape of the log/event create path in builds from the last week against today's API; check the server log on production for 4xx on those routes, read-only). Name the breaking change.
  2. The server keeps accepting the previous client's request shape for the routes the app uses daily (Log entry and Event create/update), or rejects it with a clear, versioned error the client turns into "calternal was updated · Reload" instead of a silent failure. Additive API changes only from now on for these routes, guarded by a contract test that replays the previous release's requests.
  3. Regression test: the previous release's request for creating a Log entry and an Event still succeeds (or yields the reload prompt), never a silent failure.

Related: the long-pull update and update-available toast (separate issue).

## Owner report (2026-10-04) "I still seem to run an older build on the phone which cannot log events anymore." An installed app running an older build (from before the latest production deploys: rounds 4–6 today, c39ffe5d9) fails to create Log entries / events. The server API changed under the old client, and the old client gets an error it does not explain. ## Wanted 1. Find what an older client sends that the current server rejects (compare the request shape of the log/event create path in builds from the last week against today's API; check the server log on production for 4xx on those routes, read-only). Name the breaking change. 2. The server keeps accepting the previous client's request shape for the routes the app uses daily (Log entry and Event create/update), or rejects it with a clear, versioned error the client turns into "calternal was updated · Reload" instead of a silent failure. Additive API changes only from now on for these routes, guarded by a contract test that replays the previous release's requests. 3. Regression test: the previous release's request for creating a Log entry and an Event still succeeds (or yields the reload prompt), never a silent failure. Related: the long-pull update and update-available toast (separate issue).
Author
Owner

Starting #1060 on job/appupdate-1059, base c39ffe5d90126527d7aacf2d8b79507929c80616 (the supplied dev/production base). I will reproduce the previous web client's Log and Event create requests locally against this server, identify the contract break, and add a regression contract test. I will not access production.

Starting #1060 on `job/appupdate-1059`, base `c39ffe5d90126527d7aacf2d8b79507929c80616` (the supplied dev/production base). I will reproduce the previous web client's Log and Event create requests locally against this server, identify the contract break, and add a regression contract test. I will not access production.
Author
Owner

Local reproduction finding: I built the 2026-10-03 web app from cfee85c6b and ran its Composer against a temporary local server built from c39ffe5d9, with a local CalDAV provider. Its previous-release Log batch request returned 201 and appeared in the server's Journal. Its Event create request was POST /api/v1/calendar/events with calendar_id and icalendar, returned 201, and reached the provider. I did not access production. I have not reproduced a breaking request/response change on this client/server pair; I am pinning both accepted request contracts in tests so the compatibility is explicit.

Local reproduction finding: I built the 2026-10-03 web app from `cfee85c6b` and ran its Composer against a temporary local server built from `c39ffe5d9`, with a local CalDAV provider. Its previous-release Log batch request returned 201 and appeared in the server's Journal. Its Event create request was `POST /api/v1/calendar/events` with `calendar_id` and `icalendar`, returned 201, and reached the provider. I did not access production. I have not reproduced a breaking request/response change on this client/server pair; I am pinning both accepted request contracts in tests so the compatibility is explicit.
Author
Owner

Finished #1060 investigation and regression coverage.

Head: 06177e0ae7acc58dd8a50ef78d904a37e1786048

I built the October 3 client from cfee85c6b and replayed its Log and Event create requests against the current local server. Both succeeded (201); I did not reproduce a breaking request/response change, so no compatibility behavior change was needed. Production was not contacted.

Added contract tests that pin and replay the previous release's Log batch request and Calendar Event request through the real plugin routes. The WebKit e2e repeats both requests against the local current server and reported REPLAY previous Log=201 Event=201.

Files: crates/plugins/notes/src/lib.rs, crates/plugins/calendar/src/routes.rs, crates/plugins/calendar/src/feeds/subscriptions.rs (the latter makes an existing IPv6 policy test independent of a process-wide allowlist race), and apps/web/e2e/app-update-1059.mjs.

Gates passed:

cargo fmt --check — exit 0, no output
cargo clippy -p calternal-plugin-calendar --all-targets -- -D warnings — Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 42s
cargo test -p calternal-plugin-calendar — 89 passed; 0 failed; 1 ignored; cache integration 1 passed; protocol integration 3 passed
cargo clippy -p calternal-plugin-notes --all-targets -- -D warnings — Finished `dev` profile [unoptimized + debuginfo] target(s) in 37.14s
cargo test -p calternal-plugin-notes — test result: ok. 193 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 236.57s

The merge-round adversarial matrix remains to be run under the shared verification policy. No production access logs or endpoints were used.

READY FOR MERGE: yes.

Finished #1060 investigation and regression coverage. **Head:** `06177e0ae7acc58dd8a50ef78d904a37e1786048` I built the October 3 client from `cfee85c6b` and replayed its Log and Event create requests against the current local server. Both succeeded (`201`); I did not reproduce a breaking request/response change, so no compatibility behavior change was needed. Production was not contacted. Added contract tests that pin and replay the previous release's Log batch request and Calendar Event request through the real plugin routes. The WebKit e2e repeats both requests against the local current server and reported `REPLAY previous Log=201 Event=201`. Files: `crates/plugins/notes/src/lib.rs`, `crates/plugins/calendar/src/routes.rs`, `crates/plugins/calendar/src/feeds/subscriptions.rs` (the latter makes an existing IPv6 policy test independent of a process-wide allowlist race), and `apps/web/e2e/app-update-1059.mjs`. Gates passed: ```text cargo fmt --check — exit 0, no output cargo clippy -p calternal-plugin-calendar --all-targets -- -D warnings — Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 42s cargo test -p calternal-plugin-calendar — 89 passed; 0 failed; 1 ignored; cache integration 1 passed; protocol integration 3 passed cargo clippy -p calternal-plugin-notes --all-targets -- -D warnings — Finished `dev` profile [unoptimized + debuginfo] target(s) in 37.14s cargo test -p calternal-plugin-notes — test result: ok. 193 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in 236.57s ``` The merge-round adversarial matrix remains to be run under the shared verification policy. No production access logs or endpoints were used. **READY FOR MERGE:** yes.
Author
Owner

Orchestrator note: the job replayed the 2026-10-03 client's Log and Event requests against the current server and both returned 201, so there was no API break. The owner's failing "Send all" (20 s, then a toast) at the same time was the production Notes loop #1062: every write queued behind ~2,500 change events a minute. The hotfix at 19:12 CEST fixed it. Contract tests for the previous request shapes stay as a guard and ship with #1059.

Orchestrator note: the job replayed the 2026-10-03 client's Log and Event requests against the current server and both returned 201, so there was no API break. The owner's failing "Send all" (20 s, then a toast) at the same time was the production Notes loop #1062: every write queued behind ~2,500 change events a minute. The hotfix at 19:12 CEST fixed it. Contract tests for the previous request shapes stay as a guard and ship with #1059.
Author
Owner

Deployed to production 2026-10-05 03:12 CEST in round 8 (2b6c77c14). Staging healthy first; production healthy in 33 s; /api/v1/version reports the build ID; change events 0/30 s.

Deployed to production 2026-10-05 03:12 CEST in round 8 (2b6c77c14). Staging healthy first; production healthy in 33 s; `/api/v1/version` reports the build ID; change events 0/30 s.
kayg closed this issue 2026-10-05 01:13:50 +00:00
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#1060
No description provided.