You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 3e143ea
Browse filesBrowse the repository at this point in the historyBrowse files
upload: add the Upload model, migration and real crud (swap the stub) (#198)
* upload: add the Upload model, migration and real crud (swap the stub)
Replaces the no-op crud_upload with the real persistence layer: the Upload
model (one row per accepted upload; sha256 indexed but not unique), a named-FK
migration, and real create/exists_with_sha/get_multi_by_sha/all_shas. find_orphans
is now typed against models.Upload. Restores the deferred tests -- re-upload of
identical bytes is free, a second row is written, find_orphans/detection work.
* upload: close the purpose set, count avatars as usages, check config up front (#199)
Four review findings on the image-upload work, none of which change the shape
of the design.
purpose was a free-form string. The karma gate tests for "figure" and the
read-time misuse detection tests for "avatar", so any third value was an upload
that was neither gated nor detected: karma 0 with purpose="banana" returned 200.
It is now upload_purpose_T, a closed Literal beside editor_T, so anything else
is a 422 at the boundary.
find_usages scanned bodies only, but a purpose="avatar" upload lives in
User.avatar_url and is embedded in no body at all, so every avatar ever
uploaded read as an orphan -- and orphans are the input to any future garbage
collection. Question.description had the same gap. Both avatar columns and both
question description columns join the scan.
is_configured() checked only the endpoint URL while the write path also needs
the bucket (a NOT NULL column) and the public URL base, so a half-configured
deployment 500'd *after* put_image had already stored the object. It now checks
all three, which makes it the 503 it was meant to be, before anything is
written.
s15 shared one PNG fixture across checks, so the "new figure costs 2 coins"
point was uploading bytes an earlier check had already sent -- correctly free,
and reported as XFAIL against a backend that was right. Each check now builds
its own bytes, and every point is a hard assertion rather than a note, so a
regression fails the suite instead of printing a known-failure line.
Claude-Session: https://claude.ai/code/session_01CqbhVfwzFUYGkgJWnWwSk1
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
0 commit comments