Skip to content

feat(api): image embedding and projection cache tables + records service - #34

Open
lstein wants to merge 1 commit into
mainfrom
feat/image-map-01-schema
Open

feat(api): image embedding and projection cache tables + records service#34
lstein wants to merge 1 commit into
mainfrom
feat/image-map-01-schema

Conversation

@lstein

@lstein lstein commented Aug 2, 2026

Copy link
Copy Markdown
Collaborator

Summary

First PR in the Image Map stack (semantic UMAP gallery panel + semantic search; 11 PRs planned). This one adds the dormant storage layer:

  • Migration 34 creates two tables:
    • image_embeddings — one row per (image_name, model_id) where model_id is the embedding model's content hash (stable across reinstalls). Embeddings are float32, L2-normalized BLOBs. ON DELETE CASCADE against images.
    • image_projections — one cached 2D UMAP projection per (user_id, model_id), with a scope_hash fingerprinting the accessible image set so staleness is detected by re-derivation, not bookkeeping. ON DELETE CASCADE against users.
  • New image_index records service (base/common/sqlite): embedding CRUD, backfill listing, index status counts, projection cache get/set, and per-user access scoping (own images + shared/public boards + boards individually shared via shared_boards; admin sees all) mirroring the board-listing access model.
  • Wired into InvocationServices/ApiDependencies; dormant — nothing writes to it until the indexer worker lands in the next PR of the stack.
  • Drive-by fix: gallery_maintenance.py now enables PRAGMA foreign_keys on its connection so its image deletions honor the cascades (previously it orphaned board_images rows too).

An adversarial review of this diff was run; confirmed findings (per-user shared_boards scoping, raw IntegrityError leaking on image/user delete races, FK-off maintenance script, duplicate-input double-counting, read-only coords arrays) are fixed and covered by tests.

Testing

  • 24 new tests in tests/app/services/image_index/test_image_index_records.py: blob round-trips, upsert/get/delete, FK cascade on image delete, chunked (501-name) fetches, eligibility filtering, the full access matrix (own/private/shared/public/individually-shared/admin), delete-race no-ops, projection cache round-trips.
  • tests/test_sqlite_migrator.py + both multiuser router suites pass (177 tests).

🤖 Generated with Claude Code

Adds the storage layer for the semantic image map feature:

- Migration 34 creates `image_embeddings` (one row per image + embedding
  model content hash, float32 L2-normalized BLOB) and `image_projections`
  (per-user cached 2D UMAP coordinates with a scope hash fingerprinting
  the accessible image set).
- New `image_index` records service (base/common/sqlite) with embedding
  CRUD, backfill listing, index status counts, per-user accessible-image
  scoping (own images + shared/public boards, admin sees all), and
  projection cache get/set.
- Wired into InvocationServices and ApiDependencies; dormant until the
  indexer service lands in a follow-up.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Review fix: the access scope now matches the gallery 'all' listing semantics
(board-owner arm and archived-board exclusion), with regression tests.
@lstein
lstein force-pushed the feat/image-map-01-schema branch from b3f4618 to 712ed53 Compare August 4, 2026 05:37
@lstein
lstein changed the base branch from v7 to main August 4, 2026 05:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant