fix: overlay legacy evidence labels instead of shadowing the whole descriptor

Review finding I1: the static-key-first resolution order protected the
entire legacy fixture (image and labels), when only the hand-authored labels
ever needed protecting -- ResolvedAsset carries no label fields, so nothing
else could recover them, but a real descriptor's publicPath/width/height were
never actually at risk of mismatching. Narrowed resolveWith so a resolved
descriptor's data fields always win; the legacy registry only overlays
triggerLabel/dialogLabel for keys it recognizes, and only supplies the full
descriptor when nothing else resolves the key at all. A future backend asset
colliding with the legacy key now degrades to a wrong caption, never a wrong
image.

Review finding I2: renamed and rewrote a test whose title claimed a
READY-vs-QUARANTINED same-key guarantee its body never constructed. It now
puts both a QUARANTINED and a READY entry under one assetKey and asserts the
READY one wins.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
DongHyeonka
2026-08-18 04:03:43 +09:00
co-authored by Claude Opus 5
parent 9d91001a31
commit e2c1d076f4
2 changed files with 62 additions and 11 deletions
@@ -60,19 +60,36 @@ function fromDescriptor(descriptor: ResolvedAssetLike): EvidenceAsset {
}
/**
* Shared resolution order for both factories below: the legacy static key always
* wins on a match (protects the one pre-existing hardcoded fixture from splitting
* across render surfaces mid-migration), then the caller-supplied lookup (the real
* backend-sourced descriptor), then the safe placeholder.
* Shared resolution order for both factories below. The legacy registry only
* needs to protect the *labels* it hand-authored for the one pre-existing key
* (`ResolvedAsset` carries no label fields at all, so nothing else can supply
* them) -- the image itself always comes from whichever descriptor actually
* resolved the key, catalog or server block, when one exists. This way a future
* backend `Asset` whose `assetKey` collides with the legacy slug degrades to,
* at worst, a wrong caption on the right image -- never a wrong image shown
* under a right caption. Only when no descriptor resolves the key at all does
* the legacy registry supply the image too (today's actual Instant Preview
* fallback path, with no catalog to consult).
*/
function resolveWith(
key: string,
lookup: (key: string) => ResolvedAssetLike | undefined,
): EvidenceAsset {
const legacy = LEGACY_STATIC_EVIDENCE_ASSETS[key];
if (legacy) return legacy;
const descriptor = lookup(key);
return descriptor ? fromDescriptor(descriptor) : MISSING_EVIDENCE_ASSET;
if (descriptor) {
const resolved = fromDescriptor(descriptor);
return legacy
? Object.freeze({
...resolved,
triggerLabel: legacy.triggerLabel,
dialogLabel: legacy.dialogLabel,
})
: resolved;
}
return legacy ?? MISSING_EVIDENCE_ASSET;
}
/** Instant Preview: resolves against the Asset list the editor has loaded. */