You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
On the guided face cleanup review page (Face cleanup → cluster → “Faces leaving {name}”), admins only see a tight face crop. There is no way to open the source photo, so similar-looking children and babies cannot be judged in context.
Add a magnifying-glass control on each face tile that opens the full photo in a lightbox, using an admin-gated preview — not the owner-scoped photo viewer.
Current behaviour
Open Face cleanup → Guided cleanup → a person that needs review (e.g. a named cluster with one flagged face).
The grid “Faces leaving {name}” shows cropped face thumbnails only.
Clicking a tile only selects it for a move/stay/lock/etc. action.
The selection dock has no “view original” action either.
The client never receives assetId (or bounding-box metadata). Flagged faces are { assetFaceId, suspectedOwnerId }; rest-of-cluster faces are { assetFaceId } only (FaceRepairPersonFacesDto / FaceRepairClusterFacesResponseDto). Tiles load /admin/face-repair/faces/{assetFaceId}/thumbnail and onclick only toggles selection (web/src/routes/admin/face-cleanup/[personId]/+page.svelte). The same gap exists on the manual review page (face-cleanup/people/[personId]).
Why /photos/{assetId} is the wrong fix
Face cleanup is an admin console. Every /admin/face-repair route is @Authenticated({ admin: true }) with norequireAccess on the asset or person. Admins can already scan, reassign, lock, and detach faces they do not own. That is intentional.
Immich’s photo viewer does not grant admins a bypass of asset.read. Linking to /photos/{id} would work for the admin’s own library and 403 for every other user’s assets — the main job of this console.
The existing thumbnail already uses that privileged path:
GET /admin/face-repair/faces/:assetFaceId/thumbnail
(getAdminFaceThumbnail → getFaceThumbnailSource(face.assetId) → crop). The original-photo view should be the same path without the crop, not the owner-scoped viewer.
Proposed solution
Server
Add a sibling of the thumbnail route, e.g.:
GET /admin/face-repair/faces/:assetFaceId/preview
Same auth as the thumbnail: admin-only, face-keyed, no requireAccess.
Resolve the face the same way as getAdminFaceThumbnail, then return the uncropped preview (the file getFaceThumbnailSource already locates).
Optionally return bounding-box + image size (or overlay data the client can use) so the lightbox can highlight which face was clicked when the photo has several people. Precedent: PersonFaceSuggestionResponseSchema already ships assetId + box + dimensions for the owner-scoped suggestion flow.
Regenerate OpenAPI clients after the route/DTO change.
Web
Magnifying-glass icon on each face tile (flagged grid and rest-of-cluster grid), visible on hover / keyboard focus.
Clicking the icon must not toggle selection.
Open a lightbox/modal (modalManager, same pattern as the rest of this page) with the admin preview.
The flagged tile is currently a <button>; a nested button is invalid HTML. Put the icon as a sibling inside a wrapper div (the rest-of-cluster grid already wraps tiles that way).
Do not put this only in the selection dock: the dock is ambiguous with multi-select, and context is often needed before selecting.
Any new user-facing string must land in all nine maintained locales in the same commit (de · fr · it · nl · pl · es · ru · zh_Hans · zh_Hant), keys alphabetically sorted.
Acceptance criteria
From a guided-review face tile, an admin can open the full source photo without leaving the page.
This works for faces whose assets the admin does not own (same clusters the console already lets them repair).
Opening the original does not select/deselect the tile and does not apply any resolve action.
The same control exists on rest-of-cluster tiles (and ideally on the manual review grid).
The normal /photos/{id} viewer is not used for this; access stays admin-gated and face-keyed.
Keyboard / screen-reader: the magnifier has a labelled control; the lightbox can be dismissed.
Out of scope
Granting admins general asset.read in the library timeline.
Changing who may run face cleanup (still admin-only).
I've done an initial implementation which gives each photo a magnifying glass icon like so:
And when clicked, it opens a new modal that gives a bit more context:
This is available to test already in v5.6.0-rc.0.
In the meantime, I also improved the face suggestions feature to show more info on each photo, and I think I'll match this behaviour to show basically all the info you can see on a photo's Information panel, as well as a link to open the photo directly in a new tab.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
On the guided face cleanup review page (
Face cleanup→ cluster → “Faces leaving {name}”), admins only see a tight face crop. There is no way to open the source photo, so similar-looking children and babies cannot be judged in context.Add a magnifying-glass control on each face tile that opens the full photo in a lightbox, using an admin-gated preview — not the owner-scoped photo viewer.
Current behaviour
The client never receives
assetId(or bounding-box metadata). Flagged faces are{ assetFaceId, suspectedOwnerId }; rest-of-cluster faces are{ assetFaceId }only (FaceRepairPersonFacesDto/FaceRepairClusterFacesResponseDto). Tiles load/admin/face-repair/faces/{assetFaceId}/thumbnailandonclickonly toggles selection (web/src/routes/admin/face-cleanup/[personId]/+page.svelte). The same gap exists on the manual review page (face-cleanup/people/[personId]).Why
/photos/{assetId}is the wrong fixFace cleanup is an admin console. Every
/admin/face-repairroute is@Authenticated({ admin: true })with norequireAccesson the asset or person. Admins can already scan, reassign, lock, and detach faces they do not own. That is intentional.Immich’s photo viewer does not grant admins a bypass of
asset.read. Linking to/photos/{id}would work for the admin’s own library and 403 for every other user’s assets — the main job of this console.The existing thumbnail already uses that privileged path:
(
getAdminFaceThumbnail→getFaceThumbnailSource(face.assetId)→ crop). The original-photo view should be the same path without the crop, not the owner-scoped viewer.Proposed solution
Server
Add a sibling of the thumbnail route, e.g.:
requireAccess.getAdminFaceThumbnail, then return the uncropped preview (the filegetFaceThumbnailSourcealready locates).PersonFaceSuggestionResponseSchemaalready shipsassetId+ box + dimensions for the owner-scoped suggestion flow.Regenerate OpenAPI clients after the route/DTO change.
Web
modalManager, same pattern as the rest of this page) with the admin preview.<button>; a nested button is invalid HTML. Put the icon as a sibling inside a wrapperdiv(the rest-of-cluster grid already wraps tiles that way).Any new user-facing string must land in all nine maintained locales in the same commit (
de·fr·it·nl·pl·es·ru·zh_Hans·zh_Hant), keys alphabetically sorted.Acceptance criteria
/photos/{id}viewer is not used for this; access stays admin-gated and face-keyed.Out of scope
asset.readin the library timeline.Platform
All reactions