Repository navigation
feat(email): add Mailbox inbound ledger CAS RPCs - #1156
Conversation
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Restore deleteEmailMessageById to D1 batch then immediate R2 cleanup with no Mailbox env/waitUntil/mirror. Restore insertEmailMessageWithAttachments signature without mirror forwarding. Drop PR-only delete mirror tests and update data-storage.md: live explicit/retention deletes are repaired by parity purge/rebuild; direct delete wiring remains pending. Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
📝 WalkthroughWalkthroughThe PR adds Mailbox inbound delivery and effect ledgers with owner-bound CAS RPCs, lease fencing, reconciliation, retry handling, and schema v2 indexes. It retains D1 authority and compatibility paths while adding worker and node test coverage. ChangesMailbox inbound ledger
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant MailboxBase
participant InboundDeliveryLedger
participant InboundEffectLedger
participant SqlStorage
MailboxBase->>InboundDeliveryLedger: claim storage lease
InboundDeliveryLedger->>SqlStorage: update delivery with CAS
MailboxBase->>InboundDeliveryLedger: finalize received delivery
InboundDeliveryLedger->>SqlStorage: store finalization and effect state
MailboxBase->>InboundEffectLedger: claim effect
InboundEffectLedger->>SqlStorage: update effect lease with CAS
InboundEffectLedger-->>MailboxBase: complete, retry, or dead-letter result
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
|
🔎 Preview deployed: https://kody-pr-1156.kody-a99.workers.dev Worker: Mocks:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
packages/worker/src/email/mailbox-schema.ts (1)
334-338: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winTie the dedupe-provider literal to the shared constant.
The predicate hard-codes
'cloudflare-email-routing-dedupe'. The same value is defined asmailboxInboundDedupeProviderinpackages/worker/src/email/mailbox-inbound-ledger-shared.ts(Line 16). If the constant changes, this partial index stops matching the prune and window queries, and the change is silent. A SQLite partial-index predicate cannot be parameterized, so interpolate the constant into the DDL string instead.♻️ Proposed change
sql.exec( `CREATE INDEX IF NOT EXISTS idx_email_delivery_events_dedupe_provider_expires ON email_delivery_events(provider, dedupe_expires_at ASC, id ASC) - WHERE provider = 'cloudflare-email-routing-dedupe' + WHERE provider = '${mailboxInboundDedupeProvider}' AND dedupe_expires_at IS NOT NULL`, )Add the import at the top of the file:
import { mailboxInboundDedupeProvider } from './mailbox-inbound-ledger-shared.ts'🤖 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/worker/src/email/mailbox-schema.ts` around lines 334 - 338, Update the partial-index DDL in the mailbox schema setup to interpolate the shared mailboxInboundDedupeProvider constant instead of hard-coding the provider literal. Import mailboxInboundDedupeProvider from mailbox-inbound-ledger-shared.ts and preserve the existing SQL predicate and index behavior.packages/worker/src/email/mailbox-inbound-ledger.workers.test.ts (1)
71-96: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winBoth schema-v2 index checks verify only part of the index set. The tests query or drop the full set of v2 indexes but assert a subset, so a partial regression in
initializeMailboxSchemacan pass.
packages/worker/src/email/mailbox-inbound-ledger.workers.test.ts#L71-L96: addtoContainassertions foridx_email_delivery_events_state_createdandidx_email_delivery_events_dedupe_expires, which the query already selects.packages/worker/src/email/mailbox-inbound-ledger.workers.test.ts#L826-L833: widen the lookup to all five dropped v2 index names and assert a count of five.🤖 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/worker/src/email/mailbox-inbound-ledger.workers.test.ts` around lines 71 - 96, Strengthen the schema-v2 index coverage in packages/worker/src/email/mailbox-inbound-ledger.workers.test.ts:71-96 by asserting the queried indexes include idx_email_delivery_events_state_created and idx_email_delivery_events_dedupe_expires. At packages/worker/src/email/mailbox-inbound-ledger.workers.test.ts:826-833, update the dropped-index lookup to include all five v2 index names and assert that five indexes are found.packages/worker/src/email/mailbox-inbound-ledger.ts (1)
419-422: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winReject non-finite numeric inputs before binding them to SQL.
Math.floor(NaN)returnsNaN, andMath.max(0, NaN)also returnsNaN. The value is then bound toexpected_attachment_count. The same pattern exists inmarkMailboxInboundDeliveryReceivedforusageDurationMsandusageBytes(Lines 664-665). Every other input in this file is validated with an explicit assertion. Add a finite-number assertion for parity.♻️ Proposed guard
+function assertMailboxFiniteNumber(value: number, label: string): number { + if (typeof value !== 'number' || !Number.isFinite(value)) { + throw new Error(`Mailbox ${label} must be a finite number.`) + } + return value +} + const expectedAttachmentCount = Math.max( 0, - Math.floor(input.expectedAttachmentCount), + Math.floor( + assertMailboxFiniteNumber( + input.expectedAttachmentCount, + 'expectedAttachmentCount', + ), + ), )🤖 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/worker/src/email/mailbox-inbound-ledger.ts` around lines 419 - 422, Add explicit finite-number assertions before normalizing numeric inputs in the inbound ledger flow: validate input.expectedAttachmentCount before Math.floor/Math.max, and validate usageDurationMs and usageBytes in markMailboxInboundDeliveryReceived before their normalization or SQL binding. Use the file’s existing assertion pattern and preserve the current clamping behavior for finite values.
🤖 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/worker/src/email/mailbox-inbound-effect-ledger.ts`:
- Around line 155-180: Nullable lease and state predicates exclude eligible rows
due to SQL three-valued logic. In
packages/worker/src/email/mailbox-inbound-effect-ledger.ts lines 155-180, update
the usage lease guard to admit NULL lease timestamps; in lines 366-372, let the
subscription processing arm claim rows with NULL subscription_effect_lease_at;
and in lines 629-632, explicitly admit NULL subscription_effect_state and
subscription_effect_lease_at while preserving the existing due-work conditions.
---
Nitpick comments:
In `@packages/worker/src/email/mailbox-inbound-ledger.ts`:
- Around line 419-422: Add explicit finite-number assertions before normalizing
numeric inputs in the inbound ledger flow: validate
input.expectedAttachmentCount before Math.floor/Math.max, and validate
usageDurationMs and usageBytes in markMailboxInboundDeliveryReceived before
their normalization or SQL binding. Use the file’s existing assertion pattern
and preserve the current clamping behavior for finite values.
In `@packages/worker/src/email/mailbox-inbound-ledger.workers.test.ts`:
- Around line 71-96: Strengthen the schema-v2 index coverage in
packages/worker/src/email/mailbox-inbound-ledger.workers.test.ts:71-96 by
asserting the queried indexes include idx_email_delivery_events_state_created
and idx_email_delivery_events_dedupe_expires. At
packages/worker/src/email/mailbox-inbound-ledger.workers.test.ts:826-833, update
the dropped-index lookup to include all five v2 index names and assert that five
indexes are found.
In `@packages/worker/src/email/mailbox-schema.ts`:
- Around line 334-338: Update the partial-index DDL in the mailbox schema setup
to interpolate the shared mailboxInboundDedupeProvider constant instead of
hard-coding the provider literal. Import mailboxInboundDedupeProvider from
mailbox-inbound-ledger-shared.ts and preserve the existing SQL predicate and
index behavior.
🪄 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: 4189b4a4-0c74-4866-8d79-1c4cdae2a7fb
📒 Files selected for processing (11)
docs/contributing/architecture/data-storage.mdpackages/worker/src/email/mailbox-do.tspackages/worker/src/email/mailbox-inbound-effect-ledger.tspackages/worker/src/email/mailbox-inbound-ledger-shared.tspackages/worker/src/email/mailbox-inbound-ledger.node.test.tspackages/worker/src/email/mailbox-inbound-ledger.tspackages/worker/src/email/mailbox-inbound-ledger.workers.test.tspackages/worker/src/email/mailbox-reconcile.node.test.tspackages/worker/src/email/mailbox-schema.tspackages/worker/src/email/mailbox-store.tspackages/worker/src/email/mailbox-types.ts
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
packages/worker/src/email/mailbox-inbound-ledger.node.test.ts (1)
49-62: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winExercise the production lease path in this test.
This test rebuilds the timestamp comparison instead of calling the Mailbox lease predicate or a public lease-claim operation. A regression in the production lease logic can pass. Test the actual operation, including the exact expiry boundary, or rename this test to document that it covers only timestamp arithmetic.
🤖 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/worker/src/email/mailbox-inbound-ledger.node.test.ts` around lines 49 - 62, Update the test around “storage lease takeover predicate matches D1 stale window” to invoke the production Mailbox lease predicate or public lease-claim operation rather than comparing timestamps directly. Cover fresh, exactly-expired, and stale lease timestamps, asserting the operation’s actual takeover behavior; otherwise rename the test to explicitly describe timestamp arithmetic only.packages/worker/src/email/mailbox-inbound-ledger.workers.test.ts (2)
826-853: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winThis block repeats the same
schemaV2Indexesarray and hardcoded SQLIN (...)clause as Line 71-96. See that comment for the shared root cause and proposed fix; this instance will be listed in the consolidated comment.🤖 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/worker/src/email/mailbox-inbound-ledger.workers.test.ts` around lines 826 - 853, Reuse the shared index-name definition and query helper established for the earlier schema validation instead of redeclaring schemaV2Indexes and repeating the hardcoded SQL IN clause in this test block. Keep the existing sorted-order and duplicate-count assertions using the shared result.
71-96: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winParameterize the schema-v2 index check instead of duplicating index names.
schemaV2Indexes(Line 71-77) lists the five expected index names, and the SQLIN (...)clause repeats the same five literal strings again. If a future migration adds a sixth index, an update toschemaV2Indexeswithout a matching update to the SQL string leaves the query silently excluding the new index from the uniqueness and presence check, instead of failing loudly.Bind the query directly from the array to keep the two lists from drifting apart.
♻️ Proposed fix to bind index names from the array
+ const placeholders = schemaV2Indexes.map(() => '?').join(', ') const indexes = state.storage.sql .exec<{ name: string }>( `SELECT name FROM sqlite_master WHERE type = 'index' - AND name IN ( - 'idx_email_delivery_events_reconcile_after', - 'idx_email_delivery_events_usage_effect_retry', - 'idx_email_delivery_events_subscription_effect_retry', - 'idx_email_delivery_events_stale_state', - 'idx_email_delivery_events_dedupe_provider_expires' - ) - ORDER BY name ASC`, + AND name IN (${placeholders}) + ORDER BY name ASC`, + ...schemaV2Indexes, ) .toArray() .map((row) => row.name)The identical duplication also exists at Line 826-853; this comment will be consolidated with that occurrence.
🤖 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/worker/src/email/mailbox-inbound-ledger.workers.test.ts` around lines 71 - 96, Update both schema-v2 index checks to build the SQL IN-clause placeholders and bound parameters directly from the corresponding index-name arrays, including the occurrence near the later migration test. Remove duplicated index literals from the SQL so adding an index to the array automatically includes it in the query and presence/uniqueness 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/worker/src/email/mailbox-inbound-ledger-shared.ts`:
- Around line 378-385: Update assertMailboxInboundNonNegativeFiniteNumber to
reject values less than zero alongside non-number and non-finite inputs, and
report that the value must be a non-negative finite number. Remove the Math.max
clamping so valid inputs are returned unchanged.
---
Nitpick comments:
In `@packages/worker/src/email/mailbox-inbound-ledger.node.test.ts`:
- Around line 49-62: Update the test around “storage lease takeover predicate
matches D1 stale window” to invoke the production Mailbox lease predicate or
public lease-claim operation rather than comparing timestamps directly. Cover
fresh, exactly-expired, and stale lease timestamps, asserting the operation’s
actual takeover behavior; otherwise rename the test to explicitly describe
timestamp arithmetic only.
In `@packages/worker/src/email/mailbox-inbound-ledger.workers.test.ts`:
- Around line 826-853: Reuse the shared index-name definition and query helper
established for the earlier schema validation instead of redeclaring
schemaV2Indexes and repeating the hardcoded SQL IN clause in this test block.
Keep the existing sorted-order and duplicate-count assertions using the shared
result.
- Around line 71-96: Update both schema-v2 index checks to build the SQL
IN-clause placeholders and bound parameters directly from the corresponding
index-name arrays, including the occurrence near the later migration test.
Remove duplicated index literals from the SQL so adding an index to the array
automatically includes it in the query and presence/uniqueness assertions.
🪄 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: 14b324b1-15be-45ab-93ec-2d57bca9d37d
📒 Files selected for processing (6)
packages/worker/src/email/mailbox-inbound-effect-ledger.tspackages/worker/src/email/mailbox-inbound-ledger-shared.tspackages/worker/src/email/mailbox-inbound-ledger.node.test.tspackages/worker/src/email/mailbox-inbound-ledger.tspackages/worker/src/email/mailbox-inbound-ledger.workers.test.tspackages/worker/src/email/mailbox-schema.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- packages/worker/src/email/mailbox-schema.ts
- packages/worker/src/email/mailbox-inbound-effect-ledger.ts
- packages/worker/src/email/mailbox-inbound-ledger.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
packages/worker/src/email/mailbox-inbound-effect-ledger.workers.test.ts (2)
371-395: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd the fresh-lease with stale-token case to complete the fence matrix.
The test covers stale-lease/stale-token and stale-lease/fresh-token. It does not cover fresh-lease/stale-token. A regression that drops the
expectedFinalizationTokencheck but keeps the lease check would still pass this test. Add one assertion that usesfreshUsageClaim.delivery.usageEffectLeasewithstaleTokenand expects a rejection status.♻️ Proposed addition after the fresh usage claim
if (freshUsageClaim.status !== 'claimed') { throw new Error('expected fresh usage claim') } + // Fresh lease + stale token must also lose. + expect( + ( + await mailbox.completeInboundUsageEffect({ + ownerId, + deliveryId: delivery.deliveryId, + usageEffectLease: freshUsageClaim.delivery.usageEffectLease!, + expectedFinalizationToken: staleToken, + mode: 'recorded', + usageMonth: '2026-07', + usageBytes: 16, + usageDurationMs: 9, + now: '2026-07-22T00:01:03.000Z', + }) + ).status, + ).toBe('lease-lost') expect(🤖 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/worker/src/email/mailbox-inbound-effect-ledger.workers.test.ts` around lines 371 - 395, Add a completion assertion after the fresh claim in the test covering the fresh-lease/stale-token combination: call completeInboundUsageEffect with freshUsageClaim.delivery.usageEffectLease and staleToken, preserving the existing completion parameters, and assert the returned status is the expected rejection status. Keep the subsequent fresh-token completion assertion unchanged.
463-488: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winBoth legacy-row SQL setups can match zero rows without failing. Each test mutates a row with raw SQL and then asserts ledger behavior. If
WHERE id = ? AND provider = ?matches no row, the UPDATE succeeds silently and the test asserts against a normal received row instead of the legacy or stale row it intends to create. Capture the cursor fromstate.storage.sql.execand assert the rows-written count at both sites.
packages/worker/src/email/mailbox-inbound-effect-ledger.workers.test.ts#L463-L488: assert that the UPDATE which nullsusage_effect_lease_at,subscription_effect_state, andsubscription_effect_lease_atwrote exactly one row.packages/worker/src/email/mailbox-inbound-effect-ledger.workers.test.ts#L563-L581: assert that the UPDATE which setssubscription_effect_state = 'processing'with a nullsubscription_effect_lease_atwrote exactly one row.🤖 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/worker/src/email/mailbox-inbound-effect-ledger.workers.test.ts` around lines 463 - 488, Both raw SQL legacy-row setups must verify that exactly one row was updated; in packages/worker/src/email/mailbox-inbound-effect-ledger.workers.test.ts lines 463-488 and 563-581, capture the cursor returned by state.storage.sql.exec and assert its rows-written count is one after each UPDATE.
🤖 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/worker/src/email/mailbox-inbound-ledger-test-helpers.ts`:
- Around line 4-20: Update insertInput so the returned rawMimeKey uses
overrides.rawMimeKey when provided, falling back to emailRawMimeKey(ownerId,
messageId) otherwise. Preserve the existing derived-key behavior when no
override is supplied.
---
Nitpick comments:
In `@packages/worker/src/email/mailbox-inbound-effect-ledger.workers.test.ts`:
- Around line 371-395: Add a completion assertion after the fresh claim in the
test covering the fresh-lease/stale-token combination: call
completeInboundUsageEffect with freshUsageClaim.delivery.usageEffectLease and
staleToken, preserving the existing completion parameters, and assert the
returned status is the expected rejection status. Keep the subsequent
fresh-token completion assertion unchanged.
- Around line 463-488: Both raw SQL legacy-row setups must verify that exactly
one row was updated; in
packages/worker/src/email/mailbox-inbound-effect-ledger.workers.test.ts lines
463-488 and 563-581, capture the cursor returned by state.storage.sql.exec and
assert its rows-written count is one after each UPDATE.
🪄 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: 50385b20-303d-4ace-ab5d-3e2e5dc9613b
📒 Files selected for processing (3)
packages/worker/src/email/mailbox-inbound-effect-ledger.workers.test.tspackages/worker/src/email/mailbox-inbound-ledger-test-helpers.tspackages/worker/src/email/mailbox-inbound-ledger.workers.test.ts
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 36c1370. Configure here.
Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

Summary
Adds the complete owner-bound Mailbox inbound delivery/effect CAS surface and schema-v2 indexes without changing live authority:
system:emailremains D1; no live call site flippedSystem recap — extends Mailbox (medium risk)
Mode: recap · Base:
main@68028d74· Head:a6fd1ad2Classification: extends — adds atomic inbound ledger/effect state-machine contracts to the existing per-user Mailbox primitive; live authority remains unchanged.
Primitives touched
mailboxSystem map
Inbound transition callers can use atomic owner-bound Mailbox RPCs in the next deploy; this PR only establishes the storage contract.
Legend: green = composes (wiring only) · amber = extended by this PR · red = new primitive · gray = context (unchanged, included only when an edge crosses it).
Invariants
system:emailremains D1-only.Verification
Conductor report
system:emailD1 branchSummary by CodeRabbit
New Features
Documentation
Tests