feat(products): app-served image route — storefront-authorized, immutable cache (SD-0002 §6.4, INV-16)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,7 @@ from .errors import (
|
||||
RunNotFound,
|
||||
)
|
||||
from .models import MAX_DATA_ROWS, MAX_FILE_BYTES
|
||||
from .repo import image_for_serving
|
||||
from .service import (
|
||||
confirm_draft,
|
||||
discard_draft,
|
||||
@@ -41,5 +42,5 @@ __all__ = [
|
||||
"MAX_DATA_ROWS", "MAX_FILE_BYTES", "SAMPLE_CSV_PATH",
|
||||
"import_validate", "get_draft", "get_draft_records", "discard_draft",
|
||||
"confirm_draft", "list_runs", "get_run", "summary", "export_catalog",
|
||||
"run_image_phase", "recover_incomplete_runs",
|
||||
"run_image_phase", "recover_incomplete_runs", "image_for_serving",
|
||||
]
|
||||
|
||||
@@ -453,6 +453,19 @@ def incomplete_runs(conn: psycopg.Connection) -> list[dict]:
|
||||
return [{"id": r[0], "storefront_id": r[1]} for r in rows]
|
||||
|
||||
|
||||
def image_for_serving(conn: psycopg.Connection, storefront_id: int, image_id: int) -> dict | None:
|
||||
"""Storefront-scoped lookup for the serving route: status + rendition keys (INV-14)."""
|
||||
row = conn.execute(
|
||||
"SELECT i.status, i.key_original, i.key_thumb, i.key_card, i.key_detail"
|
||||
" FROM product_image i JOIN product p ON p.id = i.product_id"
|
||||
" WHERE i.id = %s AND p.storefront_id = %s",
|
||||
(image_id, storefront_id),
|
||||
).fetchone()
|
||||
if row is None:
|
||||
return None
|
||||
return {"status": row[0], "original": row[1], "thumb": row[2], "card": row[3], "detail": row[4]}
|
||||
|
||||
|
||||
def run_image_outcomes(conn: psycopg.Connection, run_id: int) -> list[dict]:
|
||||
rows = conn.execute(
|
||||
"SELECT p.handle, i.source_url, i.status, i.failure_reason,"
|
||||
|
||||
Reference in New Issue
Block a user