Skip to content

Migrate Google and Spotify action resolution - #248

Draft
ndisidore wants to merge 3 commits into
nathan/action-apply-through-foundationfrom
nathan/action-apply-google
Draft

Migrate Google and Spotify action resolution#248
ndisidore wants to merge 3 commits into
nathan/action-apply-through-foundationfrom
nathan/action-apply-google

Conversation

@ndisidore

Copy link
Copy Markdown
Contributor

Stacked on #238. Migrates the Google (Docs, Gmail, Calendar) and Spotify gatekeepers to applyActionsThrough, using the shared @gadgets/backend-utils/gatekeeper-action helpers. All resolution methods serialize through per-gatekeeper SerialTaskQueues; legacy per-action methods keep their existing semantics.

Google

  • The shared PendingActionStore gains a staged marker: submit() stages the record (still overlaid on reads) and markSubmitted() flips it once submitAction() completes, so the batch sweep never applies an action the overseer hasn't accepted.
  • Docs: the strict in-order gate becomes the batch loop (ascending order satisfies the legacy "approve earlier edit first" check). Vetoing a still-active edit eagerly replays the remaining edits against the stored document snapshot, so soft-invalidations now record the vetoing edit's id (invalidatedBy) and get reported as invalidatedByVeto; without a stored snapshot the read path still invalidates lazily, unattributed, which the contract permits. Already-invalidated edits keep resolving as no-op drops, as on the legacy path.
  • Gmail / Calendar: plain loops — vetoes remove records, then pending actions apply ascending, stopping at the first failure with the specific error as stopped.reason.

Spotify

  • Batch loop treats "failed" records as retryable (matching the legacy path) and skips "staged" ones.
  • The one-hop playlist cascade (vetoing a playlist creation rejects its dependents) now records invalidatedByVeto attribution on the retired records, so repeated requests re-report it; retention rides the existing retired-record pruning window.
  • Fixes a latent resurrection bug in submitActionForApproval: the staged→pending flip now reads the live record only, so a record retired by a concurrent veto cascade can no longer be flipped back to pending through the retired-keyspace fallback.

Tested with pnpm build and pnpm lint:check (neither package has a test suite).

@github-actions github-actions Bot added the gatekeeper Changes to a gatekeeper integration label Aug 17, 2026
@ask-bonk

ask-bonk Bot commented Aug 17, 2026

Copy link
Copy Markdown

github run

@ask-bonk

ask-bonk Bot commented Aug 17, 2026

Copy link
Copy Markdown

@ndisidore Bonk workflow failed. Check the logs for details.

View workflow run · To retry, trigger Bonk again.

@ndisidore

Copy link
Copy Markdown
Contributor Author

Review of #241 turned up a correctness bug in the foundation branch that this PR copies: applyStoredActionsThrough silently skipping an in-range record whose submitAction() has not completed yet (record.state !== "pending" → continue / filter). The driver infers appliedThrough = stopped ? at-1 : actionId, so a silent skip lets it mark the staged action approved without it ever being applied — reachable whenever the batch RPC beats the submitAction() response (the hot path for auto-approved actions).

The foundation branch (#238) has been amended: a "staged" in-range record now returns {...invalidations, stopped: {at: record.id, reason: new Error("This action is still being submitted for approval. Retry in a moment.")}} instead of skipping, with tests pinning it in both gatekeepers.

When rebasing this PR onto the amended foundation, apply the same staged→stopped fix (and matching tests) to the gatekeepers here.

@ndisidore
ndisidore force-pushed the nathan/action-apply-through-foundation branch from 8bbfdfe to f204f6a Compare August 18, 2026 17:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gatekeeper Changes to a gatekeeper integration

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant