[codex] acknowledge terminal Gmail OAuth watch failures - #930
Conversation
|
Codex review: needs maintainer review before merge. Reviewed July 27, 2026, 1:16 PM ET / 17:16 UTC. ClawSweeper reviewWhat this changesThe PR records terminal Gmail OAuth refresh failures as recovery state, acknowledges the affected Pub/Sub delivery without advancing the Gmail history cursor, and preserves that cursor across watch renewal for catch-up after reauthentication. Merge readinessThis PR remains necessary: current Priority: P1 Review scores
Verification
How this fits togetherGmail watch receives Gmail/Pub/Sub notifications, fetches Gmail history, and sends resulting messages to an optional hook. Its persistent watch state tracks the last successful history cursor so retries, registrations, and recovery survive process restarts. flowchart LR
A[Gmail mailbox change] --> B[Pub/Sub notification]
B --> C[Gmail watch consumer]
C --> D[OAuth and Gmail history fetch]
D --> E[Persistent watch state]
D --> F[Configured hook delivery]
E --> G[Retry or reauthentication recovery]
F --> H[Downstream automation]
Decision needed
Why: This is an intentional delivery-policy tradeoff: it prevents unbounded retry storms but makes reauthentication plus watch renewal the required operator recovery path. Before merge
Agent review detailsSecurityNone. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Adopt the durable-marker acknowledgement contract if maintainers accept explicit reauthentication and watch renewal as the recovery path, retaining the documented cursor-preservation and retry-on-state-write-failure safeguards. Do we have a high-confidence way to reproduce the issue? Yes, at source level: an OAuth refresh returning Is this the best way to solve the issue? Unclear: the implementation is a focused and well-tested solution to retry storms, but whether terminal credential failures should be acknowledged rather than redelivered is an operator-facing delivery-policy choice that maintainers must explicitly accept. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 83cc6dd34d8a. LabelsLabel justifications:
EvidenceWhat I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (5 earlier review cycles)
|
Co-authored-by: Alex Tang <alextangli@outlook.com>
7b32e33 to
647d762
Compare
|
Maintainer decision accepted: terminal Gmail OAuth failures are acknowledged only after the recovery marker is durably persisted, with the last successfully processed history cursor retained for catch-up after reauthentication. Landed candidate: Proof on that exact candidate:
The commit preserves contributor credit with |
Summary
watch startandwatch renewRoot cause
The Gmail watch consumers treated every non-rate-limit processing failure as retryable. When the OAuth refresh token returned
invalid_grant, push delivery responded with HTTP 500 and pull delivery nacked the message. Pub/Sub then redelivered a failure that cannot recover without operator re-authentication, producing an unbounded retry and log storm.Recovery contract
Terminal OAuth failures are acknowledged only after
authRecoveryPendingand the failure timestamp/reason are saved without advancinghistoryIdorlastPushMessageId. A state write failure remains a normal processing error, so Pub/Sub keeps the delivery retryable.After re-authenticating, run
gog gmail watch renewor rerungog gmail watch start. Successful registration preserves the old successful cursor while recovery is pending. Gmail sends an immediate notification for a successful watch registration, so the consumer catches up from that cursor without waiting for another mailbox change. Advancing history successfully clears the recovery marker.gog gmail watch statusexposes the pending recovery state.Temporary API failures, rate limits, and hook delivery failures retain their existing retry behavior.
Validation
go test ./internal/gmailwatchinternal/cmdtests covering start, renew, status, push acknowledgement, pull acknowledgement, persistence failure, and catch-upmake fmt-checkmake lintmake deadcodemake buildThe broader
internal/cmdGmail-watch test selection still has pre-existing shared-state failures when run as one package on this machine. The same failures reproduce on unmodifiedupstream/main; the focused regression tests above pass.Redacted live Gmail/Pub/Sub evidence
Run on 2026-07-19 with commit
7b32e33be8a5. The run used:--homeand encrypted file keyringwatch start, pull acknowledgement,watch renew, immediate Gmail notification, history fetch, and hook delivery pathsOnly the isolated refresh token was replaced with an invalid value. The production token was never revoked or modified.
The invalid-token pull logged
Gmail authorization requires re-authentication; acknowledging pull without advancing historyafter Google OAuth returnedinvalid_grant. After restoring the isolated token,watch renewretained the old cursor and pending marker. Gmail's immediate registration notification arrived through the temporary Pub/Sub subscription; the consumer fetched the retained history, delivered three message records to a local 204 hook, advanced the cursor, cleared the marker, and acknowledged the notification.Account addresses, project/topic/subscription names, history IDs, Pub/Sub message IDs, Gmail message IDs, label IDs, endpoints, and all credential material are omitted. Cleanup was verified: no temporary process, directory, subscription, label, or credential copy remains.
Related OpenClaw lifecycle fix: openclaw/openclaw#96202.