Harden media usage repair behavior#1850
Conversation
…nd improved snapshot handling
🦋 Changeset detectedLatest commit: 6266fe8 The changes in this PR will be included in the next version bump. This PR includes changesets to release 16 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Scope checkThis PR changes 1,043 lines across 6 files. Large PRs are harder to review and more likely to be closed without review. If this scope is intentional, no action needed. A maintainer will review it. If not, please consider splitting this into smaller PRs. See CONTRIBUTING.md for contribution guidelines. |
@emdash-cms/admin
@emdash-cms/auth
@emdash-cms/auth-atproto
@emdash-cms/blocks
@emdash-cms/cloudflare
@emdash-cms/contentful-to-portable-text
emdash
create-emdash
@emdash-cms/gutenberg-to-portable-text
@emdash-cms/plugin-cli
@emdash-cms/plugin-types
@emdash-cms/registry-client
@emdash-cms/registry-lexicons
@emdash-cms/sandbox-workerd
@emdash-cms/x402
@emdash-cms/plugin-ai-moderation
@emdash-cms/plugin-atproto
@emdash-cms/plugin-audit-log
@emdash-cms/plugin-color
@emdash-cms/plugin-embeds
@emdash-cms/plugin-field-kit
@emdash-cms/plugin-forms
@emdash-cms/plugin-webhook-notifier
commit: |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
emdash-playground | 6266fe8 | Jul 06 2026, 10:17 PM |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
emdash-demo-do | 6266fe8 | Jul 06 2026, 10:19 PM |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ✅ Deployment successful! View logs |
emdash-demo-cache | 6266fe8 | Jul 06 2026, 10:20 PM |
There was a problem hiding this comment.
This PR hardens the collection-scope media usage repair logic ahead of the operator entry point. The approach is sound: it layers generation-guarded deletes, partial-snapshot preservation, conflict-versus-failure classification, and final-status CAS behavior on top of the existing CAS-based repository, which fits EmDash's architecture well.
I reviewed the full diff and the changed source files:
- Repository deletes (
media-usage.ts): SwitchingdeleteSourceIfCurrent,deleteSourceIfMatching, anddeleteSourceIfMatchingContentAbsentto remove only the generation that won the source CAS is correct. Older/unmatched generations become invisible to current-usage queries and are reclaimed by the existing orphan/stale/abandoned cleanup sweepers. This prevents a guarded repair delete from wiping out a fresher concurrent write. ThedeleteSourceKeysunguarded bulk path is left alone, which is right. - Repair conflict handling (
content-repair.ts): Treating rows deleted mid-repair asmissingContentIds/ conflicts rather than source failures is the right semantics.repairedContentIdsneatly removes those IDs from the before/after scan comparison, avoiding a spurious additional conflict. RefactoringrepairSnapshotSourcesand the new partial-snapshot failure path correctly preserve a validcolumnssnapshot even whendraft_overlayloading fails.markRepairConflictwith??=keeps more specific error codes from being overwritten by later conflict markers. - Snapshot partial failures (
content-snapshots.ts): Returning the already-builtcolumnssnapshot along with the failing draft source is a clean way to let repair make forward progress. - Status logic: The updated
determineRepairStatuscorrectly maps {failed, skipped} × {trusted progress} to complete/partial/failed, matching the new regression tests. - Tests: Good coverage of missing drafts, malformed repeater metadata, no-media scopes, concurrent inserts/deletes, stale status races, and generation-preserved deletes. The trigger-based race simulations are dialect-aware.
- Conventions: SQL uses parameterized
sql.ref; no new admin UI strings; no migrations; no API routes. The only conventional gap is the absent changeset, which the author notes is intentional and will be added with Patch 4C when the operator surface ships.
No logic bugs, regressions, or security issues found. The code is well-scoped, well-tested, and consistent with the surrounding media-usage subsystem.
What does this PR do?
Hardens collection-scope content media usage repair before the operator entry point ships.
columnsusage whendraft_overlaysnapshot loading fails.Related: Discussion #1503.
Builds on merged repair foundation PR #1846.
Type of change
Checklist
pnpm typecheckpassespnpm lintpassespnpm testpasses (or targeted tests for my change)pnpm formathas been runAI-generated code disclosure
Screenshots / test output
No screenshots; backend repair hardening only.
Verified on
media-usage-repair-hardening-main:Try this PR
Open a fresh playground →
A full working EmDash site, deployed from this branch. Each visit gets its own session-scoped sandbox: no login needed and no shared state. Try the admin, edit content, hit the public site.
Tracks
media-usage-repair-hardening-main. Updated automatically when the playground redeploys.