Thumbnails #2
Labels
No labels
agent
blocked
agent
new
agent
review
agent
working
complexity
high
complexity
low
priority
high
priority
low
priority
medium
risk
high
risk
low
risk
medium
type
bug
type
chore
type
feature
type
security
No milestone
No project
No assignees
4 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
tfks/trippin#2
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Thumbnails should be constrained to a width of 256 pixels, letting the height be derived from the optimized photo's dimensions so as not to distort the thumbnail.
Make sure there is a dedicated API endpoint to [re-]generate a thumbnail for a photo. This will be useful in the future (eg backfill thumbnails after a major change).
Make sure that thumbnail processing has its own Task definition.
Create ./wiki/thumbnails.md to record any important details about how we process thumbnails.
Thumbnail dimensionsto ThumbnailsBrief — Developer
Phase: simple. Run
fjx dev prompt simplefor the cycle protocol.Ledger for: agent-pm
Status: closed @ 2026-05-23T04:42:16.070Z
Briefs:
Activity
(PM manages this ledger; agent section unused)
Ledger for: agent-dev
Status: review @ 2026-05-23T03:59:38.620Z
Ledger for: agent-dev
Tasks
generate-thumbnailtask (256px proportional, sourced fromurl_optimized), addPOST /api/photos/:id/regenerate-thumbnail, writewiki/thumbnails.md. PR #20.just validategreen. Commite65312c.just validategreen. Commite3a0bdb(push tofeat/thumbnails).src/lib/pois/tasks.test.ts— 5 tests: 256px proportional output (800×400 → 256×128),withoutEnlargement(100×50 stays 100×50), legacy-path cleanup (.jpg→.avif), no-op whenurl_optimizedis missing, andoptimize-photo → generate-thumbnailenqueue cascade.src/routes/api/photos/curation-endpoints.test.ts— addsregenerate-thumbnailto the per-verb owner-only / 403-stranger / single-enqueue table (asserts the endpoint enqueues exactlygenerate-thumbnail).photos, notpois.Notes for QA
basePathderivation): left as-is. Both handlers operate on canonical paths produced byuploadPhoto(<base>/original.<ext>and<base>/optimized.avif), so the regex no-op case requires hand-edited storage paths or a future refactor. Filing a follow-up issue would be in scope for a hardening pass, not this change.restore-optimizedheader doc drift): the comment is still accurate post-cascade — the endpoint does re-derive both variants viaoptimize-photoenqueueinggenerate-thumbnail. Left untouched.just test::envwrites wrong host ports on supabase CLI 2.98.2; patched.env.testmanually each cycle.Pull request
e3a0bdb test(thumbnails): cover generate-thumbnail handler and regen endpointBrief — QA
Phase: review. Run
fjx qa prompt defaultfor the cycle protocol.Ledger for: agent-qa
Status: concerns @ 2026-05-23T03:34:33.564Z
Ledger for: agent-qa
Action summary
validate.yamlrun 40 — success (html_url). Covers fmt, lint, type-check, full test suite + coverage, audit, secrets, SAST, fuzz on commite65312c.linesFoundgrew 2410 → 2524 (+114) — new code is being measured. Net +91 lines hit.Diff scope
src/lib/pois/tasks.ts— splitsoptimize-photointo two handlers (optimize-photo+generate-thumbnail).THUMBNAIL_WIDTH = 256,withoutEnlargement: true, no crop, sourced fromurl_optimized.src/routes/api/photos/[id]/regenerate-thumbnail.ts— owner-only POST, enqueuesgenerate-thumbnail, returns 202 +task_id. Mirrorsrestore-optimized.tsexactly in shape.wiki/thumbnails.md— policy + pipeline doc.src/main.tsalready imports./lib/pois/tasks.ts, so the newgenerate-thumbnailhandler registers on startup. No wiring gap.Gap analysis (what the actions did not catch)
src/lib/pois/tasks.tsandsrc/routes/api/photos/[id]/regenerate-thumbnail.tsare absent fromcoverage/summary.json'sfilesmap (siblingrestore-optimized.tsis covered). The validate green comes from existing curation/upload tests that touchpois/tasks.tsonly indirectly — none assert the new generate-thumbnail behavior (256-cap, proportional height, no enlargement, sourced from optimized, path replace, legacy delete) or the new endpoint (owner-only 404/403/202, task id returned).basePathderivation is brittle. Both handlers computebasePathviareplace(/\/(original|optimized)\.[^/]+$/, ""). Ifurl_optimizedever lacks the exact/optimized.<ext>suffix (path migration, manual edit, future refactor), the replace is a no-op andthumbnailPathbecomes<full_url>/thumbnail.avif— a silently nested path. Not exploitable today, but a class of bug a test would catch.generate-thumbnailshort-circuits safely whenurl_optimizedis missing. A regen request fired before optimize completes returns 202 and the task silently no-ops; nothing tests that path.restore-optimized.tsheader. Says "re-derive default optimized + thumbnail" — still true via the new cascade, but no longer literal. Cosmetic.photos, notpois. Cosmetic.Confirmed issues
None blocking. All five items above are concerns, not regressions: the actions cover what they were aimed at, and the code matches the issue requirements (256px proportional, dedicated task, dedicated endpoint, wiki doc).
Untested assumptions
optimize-photo→generate-thumbnailenqueue runs in the same transaction as the photos UPDATE (relies onprocessTaskBatchwrapping the handler in a tx — it does, perlib/worker/tasks.ts), so partial-failure orphans should be impossible. Not directly tested for this pair.withoutEnlargement: truefor photos narrower than 256px is sharp's documented behavior; not exercised by any fixture in this diff.generate-thumbnailfor the same photo are idempotent (same path, same UPDATE value); not stressed.Verdict
concerns — implementation matches the issue. Routing back to dev to add minimal coverage for
generate-thumbnailand the new endpoint (mirror therestore-optimizedtest pattern). Items 2–5 are optional follow-ups.