From 962d2a02297e19c9d9f98f78ebfd18c4b9ae86bd Mon Sep 17 00:00:00 2001 From: AI Assistant Date: Fri, 27 Feb 2026 22:38:33 +0200 Subject: [PATCH] docs: add base64 payload finding to SESSION-LOG and CLAUDE.md rules --- CLAUDE.md | 4 ++++ SESSION-LOG.md | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index db7bb30..ce604e6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -204,6 +204,10 @@ git push origin main - **ALWAYS** use `storage.exportAll()` (namespaced) or `storage.export(namespace)` (service-level) to batch-load - Filter items client-side after a single fetch: `for (const [key, value] of Object.entries(all)) { ... }` - After mutations (add/update), either do optimistic local state update or a single `refresh()` — never both +- **NEVER store large binary data (base64 files) inside entity JSON** — this makes list loading transfer tens of MB +- For modules with attachments: use `exportAll({ lightweight: true })` for listing, `storage.get()` for single-entry full load +- The API `?lightweight=true` parameter strips `data`/`fileData` strings >1KB from JSON values server-side +- Future: move file data to MinIO; only store metadata (name, size, type, url) in the entity JSON ### Module Development Pattern diff --git a/SESSION-LOG.md b/SESSION-LOG.md index bdf9af2..4582e80 100644 --- a/SESSION-LOG.md +++ b/SESSION-LOG.md @@ -56,6 +56,24 @@ With 6 registry entries + ~10 contacts + ~20 tags, the Registratura page fired * ### Commits - `c45a30e` perf: fix N+1 query pattern across all modules + rack numbering +- `c22848b` perf(registratura): lightweight API mode strips base64 attachments from list + +### Second Root Cause — Base64 Attachment Payloads (found after first fix) + +After deploying the N+1 fix, Registratura STILL loaded in 2+ minutes. Deeper investigation revealed: + +**Root cause:** `RegistryAttachment.data` stores full base64-encoded files directly in JSON. A 5MB PDF = ~6.7MB base64. With 6 entries having attachments, `/api/storage?namespace=registratura` returned **30-60MB of JSON** on every page load. + +**Fix:** Added `?lightweight=true` parameter to the API route. Server-side `stripHeavyFields()` recursively strips large `data` and `fileData` string fields (>1KB) from JSON, replacing with `"__stripped__"`. List loading now transfers ~100KB. Full entry data loaded on-demand only when editing (single entry = manageable). + +**Additional files:** + +- `src/app/api/storage/route.ts` — `stripHeavyFields()` + lightweight param +- `src/core/storage/types.ts` — `export()` accepts `{ lightweight?: boolean }` +- `src/core/storage/adapters/database-adapter.ts` — passes flag to API +- `src/modules/registratura/services/registry-service.ts` — `getAllEntries()` uses `lightweight: true`, new `getFullEntry()` +- `src/modules/registratura/hooks/use-registry.ts` — exports `loadFullEntry()` +- `src/modules/registratura/components/registratura-module.tsx` — `handleEdit` loads full entry on demand ---