Joshua Shay Kricheli NeuroSymbolic AI
v2 v1

Release · v3.14.27

Make the repair script work against a real bucket

fix(storage): make the repair script work against a real bucket

fix v3.14.27 August 18, 2026 Joshua Shay Kricheli e18a84c

Details

Four faults, every one of them found the first time this ran with a
service-role key rather than in review. The script had never been executed.
**Object names contain spaces.** `documents/CIKM 2024 Poster.pdf` went into the
request line unencoded and http.client refused it outright — the very first
object aborted the run. The public URL is now percent-encoded; the copy body
still takes the raw key.
**Copying an object onto its own key is rejected.** `POST /object/copy` answers
`409 KeyAlreadyExists`, so the cheap metadata-only route this script was built
on does not exist. Storage offers no metadata-only update at all, so the object
is re-uploaded over itself with `x-upsert` — one download and one upload each.
**Verification was reading two sources that lie.** The public URL is behind a
CDN and this project's public delivery sends `no-cache` whatever the object
records, so a served header can never confirm a write. `/object/info/...` is
worse: it reported `application/octet-stream` for an object the list endpoint
already showed as `application/pdf`, and still did sixty seconds later — which
made a successful repair look like a silent no-op and aborted the run a second
time. Only the list endpoint's `metadata` tracks a write, so that is what the
script now reads, for both the decision and the read-back.
**The favicon was being rewritten for nothing.** Python answers
`image/vnd.microsoft.icon` where the bucket already served the equivalent
`image/x-icon`, so a correct value was being replaced with another correct
value — and Storage normalising it back would have tripped the verifier. `.ico`
is now pinned to the form already in place.
Run against the live bucket: **21 of 21 objects repaired**, re-scan reports 0
remaining. Documents and images now carry `application/pdf`, `image/png`,
`image/jpeg` and `max-age=3600` instead of `application/octet-stream` and
`no-cache`. A repaired object can still serve its old content-type from a CDN
HIT for up to an hour; the origin is correct immediately.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DAJJ63FFnLoD5XLpu6yJaG

Files changed (3)

backend/supabase_db/DATABASE.md +21 −6
backend/supabase_db/scripts/_db_common.py +6 −0
backend/supabase_db/scripts/repair_storage_metadata.py +90 −53