docs: record the local-catalogue decision, and what it is not

This commit is contained in:
2026-09-28 17:51:42 +07:00
parent 81637b8502
commit 7ba1e64e7c
+34
View File
@@ -0,0 +1,34 @@
# ADR — Local catalogue, không cloud sync
Trạng thái: chấp nhận · 2026-09-28 · nhánh `recipes-web`
## Bối cảnh
Studio PWA (`docker/frontend`) đọc thư mục trên máy người dùng qua File System Access API.
Bản nháp thiết kế `lightroom_web_app.md` giả định endpoint `/v1/sync/edits` và auth
`Authorization: Bearer localStorage['pro_user_token']`. Backend thật (Fastify + SQLite) chỉ biết
ảnh upload qua `/api/photos` (cap 12/tài khoản) và recipe qua `/api/recipes`; auth bằng cookie
`SESSION_COOKIE` HttpOnly. Không có `photoId` phía server để gắn edit vào — endpoint đó không
thể tồn tại. Tính năng được yêu cầu là *quản lý local*, nên phần sync là YAGNI.
## Quyết định
1. **Freeze scope:** catalog và edit chỉ nằm trên máy người dùng. Không thêm bảng, không endpoint sync.
2. **IndexedDB `recipescam-library`** (version 1), ba store — theo đúng `src/engine/library.ts`:
- `folders` — keyPath `name`
- `photos` — keyPath `id` = `${folder}/${name}`, index `folder`, `taken`
- `edits` — keyPath `photoId`, `{ recipe, updatedAt }`
3. **API cùng origin** qua nginx proxy `/api/` → `fetch(..., { credentials: 'same-origin' })`
(`src/api.ts`). Không `'include'`, không Bearer.
4. **Nhận diện ảnh:** trước mắt chỉ `folder/name`. Khi cần sync thật: partial hash
(first + last 64 KiB + size), và chỉ hash những frame *thực sự có edit*. Lưu ý `scanFolder`
vốn đã đọc trọn bytes mỗi RAW cho `rawThumbnail`, nên "hash đắt vì phải đọc 30–50 MB" không
phải lập luận đúng; cái làm `filename+size+mtime` mất map recipe là rename và copy từ card
(mtime đổi, bytes y hệt).
## Hệ quả
- Không có gì để "cắt Cloud Sync": trong repo chưa từng có code sync.
- Nếu sau này cần: thêm `library_edits (user_id, key, recipe, updated_at)` + `GET/POST
/api/library/edits` (upsert theo batch, LWW theo `updated_at`), client flush khi `online`,
xác thực bằng cookie session, key = partial hash. Ước ~60–80 dòng.