mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 21:10:59 +00:00
feat(documents): preview thumbnails in the vault overview
Render a small JPEG preview for each stored document and show it at the card's leading edge, falling back to the kind icon when none exists. - Generate previews in the background on upload (new document-thumbnail pg-boss queue) plus a boot-time corpus backfill for existing documents; upload never blocks on or fails because of it. Images are downscaled via @napi-rs/canvas, a PDF's first page is rasterised then downscaled, every other type is skipped. Generation never throws. - Store the preview encrypted at rest in a 1:1 DocumentThumbnail side table (migration 0236) so the list/detail queries that omit the original blob never drag the preview either. Same AES-256-GCM string codec + fail-closed decrypt as the content index; wired into the key-rotation walk. - Serve it through an owner-scoped GET /api/documents/inbound/[id]/thumbnail (auth + module gate + userId-scoped query + fail-closed decrypt), always image/jpeg + nosniff + private, no-store; 404 on miss. The card renders an authed lazy <img>, onError falls back to the icon. - Add hasThumbnail to the document DTO so the card only fetches a preview that exists. Also drop the "search looks inside your documents" caption from the overview (the index-all prompt stays) and the per-card searchable marker; both were noise. Remove the now-unused i18n keys across all six locales.
This commit is contained in:
1 parent
54c78b527e
commit
ee76672798
34 files changed
+1342
-160
No files matched your search
+37
-2
@@ -9374,6 +9374,34 @@ paths:
|
||||
"401": *a1
|
||||
"422": *a3
|
||||
"429": *a4
|
||||
/api/documents/inbound/{id}/thumbnail:
|
||||
get:
|
||||
tags:
|
||||
- Documents
|
||||
summary: View the document preview thumbnail
|
||||
description: "Decrypts and serves the document's small JPEG preview thumbnail (~320px long edge), rendered in the
|
||||
background from the original and stored encrypted at rest under `DocumentThumbnail.thumbnailEncrypted`.
|
||||
Owner-scoped + gated on the opt-in `inboundDocuments` module. Always `Content-Type: image/jpeg` + `nosniff` +
|
||||
`Cache-Control: private, no-store`; loaded as an `<img>` subresource. 404 when no thumbnail exists yet (freshly
|
||||
uploaded / still rendering / unsupported type) — the caller shows a placeholder. Fails closed (500) on a decrypt
|
||||
error — it never returns the ciphertext."
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: The decrypted JPEG preview thumbnail bytes.
|
||||
content:
|
||||
image/jpeg:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
"401": *a1
|
||||
"422": *a3
|
||||
"429": *a4
|
||||
/api/documents/inbound/{id}/extract:
|
||||
post:
|
||||
tags:
|
||||
@@ -26923,6 +26951,8 @@ components:
|
||||
- local-pdf
|
||||
- local-ocr
|
||||
- type: "null"
|
||||
hasThumbnail:
|
||||
type: boolean
|
||||
createdAt:
|
||||
type: string
|
||||
updatedAt:
|
||||
@@ -26945,6 +26975,7 @@ components:
|
||||
- servingClass
|
||||
- hasContentIndex
|
||||
- contentIndexSource
|
||||
- hasThumbnail
|
||||
- createdAt
|
||||
- updatedAt
|
||||
additionalProperties: false
|
||||
@@ -26955,8 +26986,9 @@ components:
|
||||
download-only (`attachment`); render/download by it, never by MIME guess. `hasContentIndex` is true when the
|
||||
document has a content-search index (auto-indexed on upload); `contentIndexSource` says how that index was
|
||||
produced — `vision` means an AI provider read the original, the other values are provider-free local
|
||||
extractions, and it is null when `hasContentIndex` is false. Treat an unknown `kind` value as OTHER when
|
||||
decoding.
|
||||
extractions, and it is null when `hasContentIndex` is false. `hasThumbnail` is true when a preview thumbnail has
|
||||
been rendered in the background (fetch it from `/api/documents/inbound/{id}/thumbnail`); false means no preview
|
||||
yet or an unsupported type — show a placeholder. Treat an unknown `kind` value as OTHER when decoding.
|
||||
DocumentConditionLink:
|
||||
type: object
|
||||
properties:
|
||||
@@ -27242,6 +27274,8 @@ components:
|
||||
- local-pdf
|
||||
- local-ocr
|
||||
- type: "null"
|
||||
hasThumbnail:
|
||||
type: boolean
|
||||
createdAt:
|
||||
type: string
|
||||
updatedAt:
|
||||
@@ -27268,6 +27302,7 @@ components:
|
||||
- servingClass
|
||||
- hasContentIndex
|
||||
- contentIndexSource
|
||||
- hasThumbnail
|
||||
- createdAt
|
||||
- updatedAt
|
||||
- facts
|
||||
|
||||
Reference in new issue
Block a user