Skip to content

feat(backup): issue signed mailbox drop approvals - #1176

Merged
kentcdodds merged 6 commits into
mainfrom
cursor/mailbox-drop-backup-approval
Aug 3, 2026
Merged

kentcdodds merged 6 commits into
mainfrom
cursor/mailbox-drop-backup-approval

Conversation

@kentcdodds

@kentcdodds kentcdodds commented Aug 3, 2026 •

Copy link
Copy Markdown
Owner

Summary

Non-destructive prerequisite for the final legacy email graph drop:

  • dedicated unique same-day DR Workflow for pre-drop D1 exports
  • immutable SQL + standard Ed25519-signed manifest in locked R2 adhoc/
  • pre/post frozen graph and authority health checks
  • full object bytes/ETag/SHA and manifest signature re-verification
  • monotonic, exact-replay-only control-plane approval UPSERT with <=2h expiry
  • migration 0134 creates only the canonical approval table
  • existing scheduled backup payloads remain backward compatible

The destructive drop becomes migration 0135 and trusts only this control-plane-issued row.

System recap — extends backup control plane (medium risk)

Mode: recap · Base: main @ 96e0dc58 · Head: 039c2965

Classification: extends — adds a signed pre-drop backup/approval workflow to the existing production backup primitive.

Primitives touched

Primitive Group Impact
backup-control-plane storage extends — unique export, immutable verification, approval issuer
d1-app-db storage extends — non-destructive approval table
email assistant composes — frozen graph snapshot/count contract

System map

The DR control plane exports and verifies the frozen production D1 snapshot, then atomically issues the only approval migration 0135 will accept.

Legend: green = composes (wiring only) · amber = extended by this PR · red = new primitive · gray = context (unchanged, included only when an edge crosses it).

flowchart LR
  d1["d1-app-db<br/>Frozen USER graph"]:::extended
  backup["backup-control-plane<br/>Signed immutable export"]:::extended
  r2["R2<br/>Locked adhoc/ object"]:::untouched
  approval["d1-app-db<br/>Short-lived approval"]:::extended
  d1 -->|"preflight + unique D1 export"| backup
  backup -->|"bytes/etag/sha + Ed25519 manifest"| r2
  backup -->|"postflight unchanged + monotonic UPSERT"| approval
  classDef touched fill:#1a7f37,color:#fff
  classDef extended fill:#9a6700,color:#fff
  classDef added fill:#cf222e,color:#fff
  classDef untouched fill:#57606a,color:#fff
Loading

Invariants

  • Runtime probes active R2 overwrite protection before export.
  • Source account/database are fixed and allowlisted.
  • Pre/post marker and exact counts must remain unchanged.
  • Approval query rechecks the snapshot atomically.
  • Older workflows cannot replace a newer approval.
  • Approval provenance includes signed-manifest/source/baseline/build fields.

Verification

  • 31 focused backup/migration/security tests pass; full validate passes in independent review
  • Production R2 adhoc/ 35-day lock and lifecycle were manually applied and read back on 2026-08-03; deployment optionally reconciles drift, runtime probe is the canonical trigger gate
  • Two independent reviews found no remaining high/medium issues

Conductor report

  • STATUS: done
  • Sequence step: 5b signed backup approval prerequisite
  • Risk: medium/non-destructive; D1 Edit token remains isolated to DR control plane
  • Merged/deployed: pending self-merge — PR #1176
  • Next: deploy, trigger unique Workflow, verify approval, rebase destructive PR feat(email): drop legacy D1 email graph #1174 as 0135 and stop ready for conductor

Cursor ManagePullRequest is pinned to the original run branch; this fresh-branch PR uses the authenticated Kent helper.


Note

Medium Risk
Extends disaster-recovery and production D1 approval paths with new Workflows, atomic D1 writes, and optional deploy-time R2 policy reconciliation; mistakes could block a legitimate drop or weaken immutability checks, but the change is explicitly non-destructive and heavily gated.

Overview
Adds a non-destructive prerequisite for dropping the frozen USER legacy email graph: the DR backup control plane can run a dedicated Workflow that exports D1, verifies integrity, and atomically writes a short-lived singleton approval row—nothing in this PR drops data.

New Workflow and storage lane. kody-mailbox-legacy-graph-pre-drop-backup accepts only server-generated requestId, nonce, and requestedAt. It stores request-unique immutable SQL and a signed v2 manifest under adhoc/mailbox-drop/d1/... (35-day lock/lifecycle), not under daily prefixes. Migration 0134 creates only email_user_graph_drop_approval with CHECK constraints tying keys, hashes, and provenance to that contract.

Fail-closed gates. Before export, the Workflow probes live R2 (destructive overwrite must be rejected). It snapshots frozen-authority markers and exact owner/thread/message/attachment/event counts pre- and post-export, re-reads manifest and SQL from R2, verifies Ed25519 signatures, then UPSERTs approval only if the snapshot still matches—monotonic replay for the same request, no caller-supplied evidence.

Control plane UI and deploy. Access-protected POST /actions/mailbox-pre-drop-backup and status polling enqueue the Workflow with generated params only. Scheduled backup payloads gain a kind discriminator with legacy compatibility for persisted payloads without kind. Production deploy optionally runs backup-resources-reconcile-cli when DR_BACKUP_ADMIN_TOKEN is set; without it, deploy logs a skip while the runtime R2 probe remains the canonical gate. adhoc/ retention is added to backup resource provisioning and path filters for control-plane deploys.

Reviewed by Cursor Bugbot for commit e8ae483. Bugbot is set up for automated code reviews on this repo. Configure here.

Summary by CodeRabbit

  • New Features

    • Added a mailbox pre-drop backup approval workflow with request validation, immutable exports, integrity checks, replay protection, and approval receipts.
    • Added dashboard controls for starting and monitoring backup requests, including automatic status updates.
    • Added 35-day retention support for ad hoc backups.
  • Bug Fixes

    • Improved compatibility for previously stored scheduled backups.
  • Documentation

    • Expanded disaster-recovery runbooks and configuration guidance for the new workflow and deployment safeguards.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@coderabbitai

coderabbitai Bot commented Aug 3, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Mailbox pre-drop backup

Layer / File(s) Summary
Approval contracts and persistence
packages/shared/src/mailbox-pre-drop-approval.ts, packages/worker/migrations/..., packages/backup-control-plane/mailbox-pre-drop-persistence.ts
Defines canonical approval evidence, database constraints, migration coverage, and atomic replay-safe persistence.
Scheduled runtime compatibility
packages/backup-control-plane/backup-types.ts, packages/backup-control-plane/backup-policy.ts, packages/backup-control-plane/backup-runtime.ts, packages/backup-control-plane/backup-workflow.ts, packages/backup-control-plane/workflow-trigger.ts
Adds typed scheduled and mailbox payload variants, legacy scheduled-payload support, payload-based object-key generation, and updated scheduled workflow contracts.
Mailbox workflow and approval execution
packages/backup-control-plane/mailbox-pre-drop-*.ts, packages/backup-control-plane/control-plane-*.ts, packages/backup-control-plane/worker.ts, packages/backup-control-plane/wrangler.jsonc
Adds request validation, graph snapshots, R2 policy checks, signed manifest verification, approval creation, Cloudflare workflow execution, UI routes, status polling, and tests.
DR resource reconciliation and deployment
tools/ci/backup-resources*, .github/workflows/deploy.yml, docs/contributing/*, packages/backup-control-plane/readme.md
Adds adhoc/ retention and read-back proof, runs reconciliation before deployment, updates workflow bindings and triggers, and documents the mailbox pre-drop procedure.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AdminUI
  participant ControlPlane
  participant MailboxWorkflow
  participant SourceD1
  participant R2
  participant ApprovalD1
  AdminUI->>ControlPlane: request mailbox pre-drop backup
  ControlPlane->>MailboxWorkflow: enqueue request with server-generated values
  MailboxWorkflow->>SourceD1: capture and validate preflight snapshot
  MailboxWorkflow->>R2: verify immutable adhoc policy
  MailboxWorkflow->>SourceD1: export mailbox graph
  MailboxWorkflow->>R2: verify manifest, signature, and SQL object
  MailboxWorkflow->>SourceD1: compare postflight snapshot
  MailboxWorkflow->>ApprovalD1: persist two-hour approval receipt
  ApprovalD1-->>ControlPlane: return receipt and status
  ControlPlane-->>AdminUI: render workflow status
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly identifies the main change: issuing signed mailbox drop approvals.
Description check ✅ Passed The description states the intent, summarizes changes, documents testing and system impact, and identifies deployment status.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/mailbox-drop-backup-approval

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

cursoragent and others added 2 commits August 3, 2026 18:06
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@kentcdodds
kentcdodds marked this pull request as ready for review August 3, 2026 18:11
@github-actions

github-actions Bot commented Aug 3, 2026 •

Copy link
Copy Markdown
Contributor

🔎 Preview deployed: https://kody-pr-1176.kody-a99.workers.dev

Worker: kody-pr-1176
D1: kody-pr-1176-db
KV: kody-pr-1176-oauth-kv

Mocks:

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Nitpick comments (6)
packages/shared/src/mailbox-pre-drop-approval.ts (1)

252-262: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Derive the expected key names from canonicalRelation.

mailboxPreDropApprovalContract.canonicalRelation declares manifestFilename and sqlFilename, but this function hardcodes both filenames. The two definitions can drift. Read the values from the contract.

♻️ Proposed refactor
-	const expectedManifestKey = `${objectPrefix}/manifest.json`
-	const expectedSqlObjectKey = `${objectPrefix}/backup-request.sql`
+	const { manifestFilename, sqlFilename } =
+		mailboxPreDropApprovalContract.canonicalRelation
+	const expectedManifestKey = `${objectPrefix}/${manifestFilename}`
+	const expectedSqlObjectKey = `${objectPrefix}/${sqlFilename}`
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/shared/src/mailbox-pre-drop-approval.ts` around lines 252 - 262,
Update assertMailboxPreDropApprovalCanonicalRelation to derive the manifest and
SQL object filenames from mailboxPreDropApprovalContract.canonicalRelation
instead of hardcoding manifest.json and backup-request.sql, while preserving the
existing objectPrefix-based key construction.
packages/backup-control-plane/backup-runtime.node.test.ts (1)

103-138: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a negative test for the new kind gate.

This test covers the accepted legacy path. validatePayload also adds a rejection path: a legacy payload without kind combined with payloadKind: 'mailbox-legacy-graph-pre-drop' must fail with invalid-workflow-payload-kind. Add a case for that branch so the mailbox workflow cannot silently accept legacy scheduled params.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/backup-control-plane/backup-runtime.node.test.ts` around lines 103 -
138, The existing test only covers acceptance of a legacy scheduled payload
without kind. Add a separate test exercising validatePayload with the same
legacy payload and payloadKind set to mailbox-legacy-graph-pre-drop, and assert
that runBackupRuntime rejects with invalid-workflow-payload-kind, ensuring
mailbox workflows cannot accept legacy scheduled parameters.
tools/ci/backup-resources.node.test.ts (1)

483-531: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Add a symmetric fail-closed case for insufficient lifecycle retention.

The loop tests a missing lock rule, a disabled lifecycle rule, and an under-retention lock rule (34 days). It does not test an under-retention lifecycle rule, even though assertAdhocBackupPolicyReadback checks lifecycleRule.deleteObjectsTransition.condition.maxAge < adhocRetentionSeconds symmetrically to the lock check. Add a mirrored case to cover that branch.

🧪 Proposed additional test case
 		{
 			lockPolicy: {
 				rules: desired.lockPolicy.rules.map((rule) =>
 					rule.prefix === 'adhoc/'
 						? {
 								...rule,
 								condition: {
 									type: 'Age' as const,
 									maxAgeSeconds: 34 * 86_400,
 								},
 							}
 						: rule,
 				),
 			},
 			lifecyclePolicy: desired.lifecyclePolicy,
 		},
+		{
+			lockPolicy: desired.lockPolicy,
+			lifecyclePolicy: {
+				rules: desired.lifecyclePolicy.rules.map((rule) =>
+					rule.conditions.prefix === 'adhoc/'
+						? {
+								...rule,
+								deleteObjectsTransition: {
+									condition: {
+										type: 'Age' as const,
+										maxAge: 34 * 86_400,
+									},
+								},
+							}
+						: rule,
+				),
+			},
+		},
 	]) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/ci/backup-resources.node.test.ts` around lines 483 - 531, Add a fourth
fail-closed input to the loop in the “adhoc policy proof fails closed…” test
that preserves the desired lock policy but changes the `adhoc/` lifecycle rule’s
retention condition to below the required threshold, mirroring the existing
under-retention lock-policy case. Ensure `assertAdhocBackupPolicyReadback` is
expected to throw for this insufficient lifecycle retention case.
packages/backup-control-plane/mailbox-pre-drop-runtime.ts (1)

50-107: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Fail fast on non-retryable BackupError inside the steps.

step.do callbacks throw plain BackupError. The Workflows engine cannot see retryable, so a fail-closed validation error such as mailbox-pre-drop-preflight-failed or mailbox-pre-drop-approval-write-failed consumes all 3 attempts with exponential backoff before run converts it. The retries: { limit: 0 } setting on the R2 policy step already expresses the fail-fast intent for the same class of error.

Wrap the step callbacks so a BackupError with retryable === false becomes a NonRetryableError at the step boundary. Retryable errors keep the current behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/backup-control-plane/mailbox-pre-drop-runtime.ts` around lines 50 -
107, Update the step.do callbacks in the mailbox pre-drop flow, including
mailbox-pre-drop-preflight, mailbox-pre-drop-verify-live-r2-policy,
mailbox-pre-drop-postflight, mailbox-pre-drop-reread-and-verify, and
mailbox-pre-drop-atomic-approval, to convert BackupError instances with
retryable === false into NonRetryableError at the step boundary. Preserve
retryable errors unchanged and retain the existing step retry configuration.
packages/backup-control-plane/control-plane-fetch.ts (1)

164-174: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Rename the local request to avoid shadowing the handler parameter.

Line 165 declares const request inside the case block. handleAuthenticated already has a request: Request parameter at line 74. The parameter is not used later in this block, so the current code runs correctly. Any future reference to the outer request inside this block would throw a ReferenceError from the temporal dead zone instead of resolving to the parameter.

Use a distinct name.

♻️ Proposed rename
 		case '/actions/mailbox-pre-drop-backup': {
-			const request = {
+			const backupRequest = {
 				requestId: crypto.randomUUID(),
 				nonce: randomNonce(),
 				requestedAt: new Date().toISOString(),
 			}
-			const instanceId = mailboxPreDropWorkflowInstanceId(request)
+			const instanceId = mailboxPreDropWorkflowInstanceId(backupRequest)
 			await env.MAILBOX_PRE_DROP_BACKUP_WORKFLOW.create({
 				id: instanceId,
-				params: request,
+				params: backupRequest,
 			})
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/backup-control-plane/control-plane-fetch.ts` around lines 164 - 174,
Rename the local request object in the /actions/mailbox-pre-drop-backup case
within handleAuthenticated to a distinct name, and update its uses in
mailboxPreDropWorkflowInstanceId and the workflow create call. Preserve the
handler’s request: Request parameter without shadowing it.
packages/backup-control-plane/control-plane-fetch.node.test.ts (1)

138-144: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert that the instance id embeds the generated requestId.

Line 143 checks only the mailbox-pre-drop- prefix. The workflow rejects params whose requestId does not match the instance id, per readme line 173. Bind the two values in the assertion so a future change that decouples them fails here.

♻️ Proposed stricter assertion
-	assert.match(created.id, /^mailbox-pre-drop-/u)
+	assert.equal(created.id, `mailbox-pre-drop-${String(created.params.requestId)}`)
 	assert.doesNotMatch(JSON.stringify(created), /caller-value/u)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/backup-control-plane/control-plane-fetch.node.test.ts` around lines
138 - 144, Strengthen the instance ID assertion in the test around
created.params and created.id so it verifies that created.id contains the
generated requestId after the existing mailbox-pre-drop- prefix, while
preserving the current parameter and caller-value assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/backup-control-plane/backup-runtime.ts`:
- Around line 153-165: Update the `mailbox-legacy-graph-pre-drop` branch to call
`mailboxPreDropRuntimePayload` with only the three approved request fields,
rather than spreading or passing the entire `payload`; preserve the existing
scheduled branch and exact-key comparison so extra mailbox keys are rejected.
- Around line 112-126: In the legacy scheduled-payload branch guarded by
!('kind' in payload), validate payload.scheduledAt before passing it to
backupPayload; reject omitted or otherwise unsupported values, including values
that would produce an unintended default Date. Preserve the existing allowedKind
check and only construct the Date and expected payload after scheduledAt
validation.

In `@packages/backup-control-plane/mailbox-pre-drop-workflow.node.test.ts`:
- Around line 382-383: Add cleanup to the test containing the consoleError
call-count assertion so the console.error spy is restored with
consoleError.mockRestore() after assertions complete. Ensure cleanup runs even
when the test fails, preserving independent exact call-count assertions in later
tests.

In `@packages/backup-control-plane/mailbox-pre-drop-workflow.ts`:
- Around line 30-35: Update the non-retryable error conversion in the catch
block to expose the original BackupError code through the workflow exit surface:
include error.code in the NonRetryableError message or assign it to a separate
machine-readable field consumed by the control-plane UI, while preserving the
existing message and retryability behavior.

In `@packages/backup-control-plane/readme.md`:
- Around line 159-162: Update the retention documentation around the adhoc/
lifecycle description to state that pre-drop manifests use the fixed
retentionTier daily while their objects remain under the adhoc/ prefix, and
clarify that the 35-day adhoc lifecycle rule applies.

In `@tools/ci/backup-resources.ts`:
- Around line 629-664: Update the error message in
assertAdhocBackupPolicyReadback to avoid directing reconciliation failures
exclusively to backup-resources-cli.ts or the raw CLOUDFLARE_API_TOKEN name.
Make the message generic about rerunning the applicable backup-resource command
with the DR backup admin token, or explicitly mention both
backup-resources-cli.ts apply and backup-resources-reconcile-cli.ts entry
points.

---

Nitpick comments:
In `@packages/backup-control-plane/backup-runtime.node.test.ts`:
- Around line 103-138: The existing test only covers acceptance of a legacy
scheduled payload without kind. Add a separate test exercising validatePayload
with the same legacy payload and payloadKind set to
mailbox-legacy-graph-pre-drop, and assert that runBackupRuntime rejects with
invalid-workflow-payload-kind, ensuring mailbox workflows cannot accept legacy
scheduled parameters.

In `@packages/backup-control-plane/control-plane-fetch.node.test.ts`:
- Around line 138-144: Strengthen the instance ID assertion in the test around
created.params and created.id so it verifies that created.id contains the
generated requestId after the existing mailbox-pre-drop- prefix, while
preserving the current parameter and caller-value assertions.

In `@packages/backup-control-plane/control-plane-fetch.ts`:
- Around line 164-174: Rename the local request object in the
/actions/mailbox-pre-drop-backup case within handleAuthenticated to a distinct
name, and update its uses in mailboxPreDropWorkflowInstanceId and the workflow
create call. Preserve the handler’s request: Request parameter without shadowing
it.

In `@packages/backup-control-plane/mailbox-pre-drop-runtime.ts`:
- Around line 50-107: Update the step.do callbacks in the mailbox pre-drop flow,
including mailbox-pre-drop-preflight, mailbox-pre-drop-verify-live-r2-policy,
mailbox-pre-drop-postflight, mailbox-pre-drop-reread-and-verify, and
mailbox-pre-drop-atomic-approval, to convert BackupError instances with
retryable === false into NonRetryableError at the step boundary. Preserve
retryable errors unchanged and retain the existing step retry configuration.

In `@packages/shared/src/mailbox-pre-drop-approval.ts`:
- Around line 252-262: Update assertMailboxPreDropApprovalCanonicalRelation to
derive the manifest and SQL object filenames from
mailboxPreDropApprovalContract.canonicalRelation instead of hardcoding
manifest.json and backup-request.sql, while preserving the existing
objectPrefix-based key construction.

In `@tools/ci/backup-resources.node.test.ts`:
- Around line 483-531: Add a fourth fail-closed input to the loop in the “adhoc
policy proof fails closed…” test that preserves the desired lock policy but
changes the `adhoc/` lifecycle rule’s retention condition to below the required
threshold, mirroring the existing under-retention lock-policy case. Ensure
`assertAdhocBackupPolicyReadback` is expected to throw for this insufficient
lifecycle retention case.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: caf4cfb3-c232-44d9-b1dd-ffb2d0257786

📥 Commits

Reviewing files that changed from the base of the PR and between 96e0dc5 and 039c296.

📒 Files selected for processing (34)
  • .github/workflows/deploy.yml
  • docs/contributing/disaster-recovery.md
  • docs/contributing/environment-variables.md
  • packages/backup-control-plane/backup-control-plane-test-support.ts
  • packages/backup-control-plane/backup-policy.ts
  • packages/backup-control-plane/backup-runtime.node.test.ts
  • packages/backup-control-plane/backup-runtime.ts
  • packages/backup-control-plane/backup-types.ts
  • packages/backup-control-plane/backup-workflow.ts
  • packages/backup-control-plane/control-plane-fetch.node.test.ts
  • packages/backup-control-plane/control-plane-fetch.ts
  • packages/backup-control-plane/control-plane-ui.ts
  • packages/backup-control-plane/mailbox-pre-drop-approval.node.test.ts
  • packages/backup-control-plane/mailbox-pre-drop-approval.ts
  • packages/backup-control-plane/mailbox-pre-drop-persistence.ts
  • packages/backup-control-plane/mailbox-pre-drop-policy.ts
  • packages/backup-control-plane/mailbox-pre-drop-r2-policy.ts
  • packages/backup-control-plane/mailbox-pre-drop-runtime.ts
  • packages/backup-control-plane/mailbox-pre-drop-snapshot.ts
  • packages/backup-control-plane/mailbox-pre-drop-verification.ts
  • packages/backup-control-plane/mailbox-pre-drop-workflow.node.test.ts
  • packages/backup-control-plane/mailbox-pre-drop-workflow.ts
  • packages/backup-control-plane/readme.md
  • packages/backup-control-plane/worker.ts
  • packages/backup-control-plane/workflow-trigger.node.test.ts
  • packages/backup-control-plane/workflow-trigger.ts
  • packages/backup-control-plane/wrangler.jsonc
  • packages/shared/src/mailbox-pre-drop-approval.ts
  • packages/worker/migrations/0134-email-user-graph-drop-approval.sql
  • packages/worker/src/email/user-graph-drop-approval-migration.node.test.ts
  • tools/ci/backup-resources-reconcile-cli.ts
  • tools/ci/backup-resources.node.test.ts
  • tools/ci/backup-resources.ts
  • tools/migration-ledger.json

Comment thread packages/backup-control-plane/backup-runtime.ts Outdated
Comment thread packages/backup-control-plane/backup-runtime.ts
Comment thread packages/backup-control-plane/mailbox-pre-drop-workflow.ts
Comment thread packages/backup-control-plane/readme.md
Comment thread tools/ci/backup-resources.ts
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 07128ae. Configure here.

Comment thread packages/backup-control-plane/control-plane-fetch.ts
cursoragent and others added 2 commits August 3, 2026 18:48
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@kentcdodds
kentcdodds merged commit fe1ca27 into main Aug 3, 2026
10 checks passed
@kentcdodds
kentcdodds deleted the cursor/mailbox-drop-backup-approval branch August 3, 2026 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants