Skip to content

refactor(email): one owner table, one lookupAtOwner; tombstone-safe saveScopedRow - #96

Merged
agreenspan merged 1 commit into
mainfrom
refactor/email-lookup-owner-table
Sep 10, 2026
Merged

refactor(email): one owner table, one lookupAtOwner; tombstone-safe saveScopedRow#96
agreenspan merged 1 commit into
mainfrom
refactor/email-lookup-owner-table

Conversation

@agreenspan

Copy link
Copy Markdown
Contributor

Stacked on #91.

One owner table, one lookup

lookup.ts was the same query written seven times, once per owner tier, and the cascade order was hand-written three more times (lookupTemplate ×2, lookupCascade) plus parentOwner in compose. owner.ts now holds the chain (parentOwner, ownerCascade) and the per-tier where (ownerWhere — the Space→Organization edge carries inheritToSpaces), and lookupAtOwner(templateSlug, componentSlugs, ctx, tier) is the single query. Per-tier predicates are byte-identical to before. 368 lines → 161. Same shape as Zealot's owner.ts + lookupAtOwner, fitted to template's two chains and seven tiers.

saveScopedRow: a re-saved slug must not land on its tombstone

The natural-key read had no live filter, so re-creating a slug whose row had been soft-deleted updated the tombstone in place and returned it: the save reported success, the row stayed deleted, and the new body overwrote the old snapshot's source. Same defect as Zealot #1930; here the partial uniques already scope to live rows, so the read just has to match them. Pinned by a save test.

Validation

packages/email 370/370; api email suites (emailVersioning, deliverEmail, sendEmail, lib/email) 53/53; typecheck + biome clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Uyo2oHpjDz4zjRyqRWH6bP

@agreenspan
agreenspan force-pushed the claude/email-nested-pass-through-rfu4ic branch from 252d8cd to 3fc870e Compare September 10, 2026 03:09
@agreenspan
agreenspan force-pushed the refactor/email-lookup-owner-table branch from e18b0f8 to acf6bf5 Compare September 10, 2026 03:10
@agreenspan
agreenspan force-pushed the claude/email-nested-pass-through-rfu4ic branch from 3fc870e to 213f196 Compare September 10, 2026 14:38
@agreenspan
agreenspan force-pushed the refactor/email-lookup-owner-table branch from acf6bf5 to 79b3fb1 Compare September 10, 2026 14:40
@agreenspan
agreenspan force-pushed the claude/email-nested-pass-through-rfu4ic branch from 213f196 to 00ad124 Compare September 10, 2026 16:07
lookup.ts was the same query written seven times, once per owner tier, and the cascade
order was hand-written three more times across lookupTemplate, lookupCascade, and
compose.parentOwner. owner.ts now holds the chain (parentOwner, ownerCascade) and the
per-tier where (ownerWhere — the Space→Organization edge carries inheritToSpaces), and
lookupAtOwner takes the tier. 368 lines become 161; the per-tier predicates are unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Uyo2oHpjDz4zjRyqRWH6bP
@agreenspan
agreenspan force-pushed the refactor/email-lookup-owner-table branch from 79b3fb1 to 8aac782 Compare September 10, 2026 16:09
@agreenspan
agreenspan changed the base branch from claude/email-nested-pass-through-rfu4ic to main September 10, 2026 16:09
@agreenspan
agreenspan merged commit fb690cd into main Sep 10, 2026
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.

1 participant