34 lines
1.5 KiB
Python
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))
|