diff --git a/backend/app/services/ml/allowlist.py b/backend/app/services/ml/allowlist.py index dc8aeab..08a6ac7 100644 --- a/backend/app/services/ml/allowlist.py +++ b/backend/app/services/ml/allowlist.py @@ -9,7 +9,7 @@ from sqlalchemy import delete, select from sqlalchemy.dialects.postgresql import insert from sqlalchemy.ext.asyncio import AsyncSession -from ...models import Tag, TagAllowlist, TagSuggestionRejection +from ...models import MLSettings, Tag, TagAllowlist, TagSuggestionRejection from ...models.tag import image_tag from .aliases import AliasService @@ -91,12 +91,25 @@ class AllowlistService: ) await self.dismiss(image_id, tag_id) + async def _store_floor(self) -> float: + return ( + await self.session.execute( + select(MLSettings.tagger_store_floor).where(MLSettings.id == 1) + ) + ).scalar_one() + async def update_threshold( self, tag_id: int, min_confidence: float ) -> None: row = await self.session.get(TagAllowlist, tag_id) if row is not None: - row.min_confidence = min_confidence + # An allowlist tag can't auto-apply more permissively than the + # ingest store floor — predictions below tagger_store_floor aren't + # stored, so a lower min_confidence would behave identically to the + # floor. Clamp so the stored threshold matches actual behavior + # (#764). + floor = await self._store_floor() + row.min_confidence = max(min_confidence, floor) async def remove(self, tag_id: int) -> None: await self.session.execute( diff --git a/frontend/src/components/settings/AllowlistTable.vue b/frontend/src/components/settings/AllowlistTable.vue index 9448125..2ac386d 100644 --- a/frontend/src/components/settings/AllowlistTable.vue +++ b/frontend/src/components/settings/AllowlistTable.vue @@ -10,7 +10,7 @@ @@ -25,23 +25,32 @@