Files
photoanalyzer/photo_pipeline/models/exif.py

34 lines
1.5 KiB
Python

"""The durable EXIF projection per asset and stage (concept §3, US07-03).
One row per ``(asset_id, stage)``: what the stage wanted written, what the file
looked like afterwards, and whether anything outside the stage's ownership moved.
``state = divergent`` is the whole point of the table — it survives restarts, keeps
the asset out of stages that require verified metadata, and gives a human something
to look at instead of a silent repair.
"""
from __future__ import annotations
from datetime import datetime
from sqlalchemy import DateTime, ForeignKey, Integer, String
from sqlalchemy.orm import Mapped, mapped_column
from photo_pipeline.db import Base
class ExifProjection(Base):
__tablename__ = "exif_projections"
asset_id: Mapped[str] = mapped_column(ForeignKey("assets.id"), primary_key=True)
stage: Mapped[str] = mapped_column(String, primary_key=True) # safety | analysis
id: Mapped[str] = mapped_column(String, nullable=False)
projection_version: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
desired_json: Mapped[str | None] = mapped_column(String)
divergent_fields: Mapped[str | None] = mapped_column(String) # JSON array
result_file_sha256: Mapped[str | None] = mapped_column(String)
state: Mapped[str] = mapped_column(String, nullable=False) # verified|divergent|failed
error_code: Mapped[str | None] = mapped_column(String)
verified_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))
updated_at: Mapped[datetime | None] = mapped_column(DateTime(timezone=True))