faces: include bbox on /faces/embeddings response

Apollo's cluster suggester wants to render a *face*-cropped thumbnail
for each cluster's representative — a multi-person photo with the
cluster about 'one' of them was unreadable when the thumb showed the
whole image. Plumbing bbox through means the UI can crop to the rep
face without an extra round-trip per cluster.

FaceEmbeddingRow gains bbox_x/y/w/h (Optional<f32>, mirrors the column
nullability — for status='detected' rows the CHECK constraint
guarantees they're populated, but the type stays nullable as
documentation). list_embeddings already loaded these from the
underlying FaceDetectionRow; this commit just stops dropping them
when constructing the response.

No DB changes; no behavior change for existing callers (the new
fields are additive).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Cameron Cordes
2026-04-29 21:01:58 +00:00
parent a24fac5511
commit 0e160f5d22

View File

@@ -154,6 +154,14 @@ pub struct FaceEmbeddingRow {
pub model_version: String,
/// base64 of 2048 bytes (512×f32 LE).
pub embedding: String,
/// Normalized bbox 0..1, included so the cluster suggester UI can
/// crop a face thumbnail without an extra round-trip per cluster.
/// Shouldn't be NULL for `status='detected'` rows (CHECK constraint
/// in the migration), but the DB type is nullable so we mirror it.
pub bbox_x: Option<f32>,
pub bbox_y: Option<f32>,
pub bbox_w: Option<f32>,
pub bbox_h: Option<f32>,
}
#[derive(Serialize, Debug, Default)]
@@ -1846,6 +1854,10 @@ async fn embeddings_handler<D: FaceDao>(
person_id: r.person_id,
model_version: r.model_version,
embedding: b64,
bbox_x: r.bbox_x,
bbox_y: r.bbox_y,
bbox_w: r.bbox_w,
bbox_h: r.bbox_h,
})
.collect();
HttpResponse::Ok().json(out)