fix(gateway): hash full image data URL for cache key to prevent collision
Root cause: makeImageCacheKey() only hashed the first 128 chars of the
data URL. Since all resized images use the same MIME prefix
('data:image/png;base64,') + identical base64 header bytes, nearly every
image got the same 16-char hash → 'image:<same-hash>' → all images reused
the first cached vision analysis (often a gambling-detection verdict).
Fix: hash the entire data URL instead of just the prefix. Verified
114 stale 'image:' entries + 745 stale 'phash:' entries purged from prod
DB. tsc --noEmit clean, 133 tests pass.
This commit is contained in:
@@ -63,12 +63,15 @@ export function makeCustomEmojiCacheKey(emojiId: string): string {
|
||||
|
||||
/**
|
||||
* Generate a deterministic cache key for an image data URL.
|
||||
* Hashes the first 128 chars of the data URL (enough to identify the image
|
||||
* without storing the full base64 string as the key).
|
||||
* Hashes the FULL data URL — only hashing a prefix (e.g. first 128 chars)
|
||||
* causes hash collisions for images that share the same MIME prefix +
|
||||
* identical base64 header bytes (common when images are resized to the same
|
||||
* dimensions), which makes every image incorrectly reuse the same cached
|
||||
* vision analysis. Hashing the entire data URL guarantees uniqueness per
|
||||
* actual pixel content.
|
||||
*/
|
||||
export function makeImageCacheKey(dataUrl: string): string {
|
||||
const prefix = dataUrl.slice(0, 128);
|
||||
const hash = createHash("sha256").update(prefix).digest("hex").slice(0, 16);
|
||||
const hash = createHash("sha256").update(dataUrl).digest("hex").slice(0, 16);
|
||||
return `image:${hash}`;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user