fix: repair-commit/repair-snapshot/repair-object get right-sized body limits (musehub#228)
repair-commit's payload is a single WireCommit record (commit metadata + structured_delta), not a full mpack — it fell under ContentSizeLimitMiddleware's generic 10 MB API_MAX_BYTES cap, not the 500 MB PUSH_MAX_BYTES reserved for push endpoints. A commit whose structured_delta is large enough (observed: 15.6 MB JSON payload on gabriel/muse commit sha256:2f17e90958a3a39216322972274314b4c495ed995ea0edf4d24a777d171226f7, the one commit out of 1,080 corrupted-signature rows the muse#107/#108 bulk repair effort could not fix) got rejected with 413 before the handler ever ran.
Phase 1 audit (beyond the ticket's own scope) found repair-object and repair-snapshot share the identical exposure: - repair-object carries arbitrary raw object bytes — fundamentally unbounded by nature, the same risk profile as a push payload, not a small metadata record. - repair-snapshot carries a manifest (path -> object_id for every tracked file) — bounded by file count, not raw content, but can still exceed 10 MB for a repo with enough files.
Design confirmed with gabriel: three tiers, not two. PUSH_MAX_BYTES (500 MB) — push/*, repair-object (joins push tier: raw bytes, push-scale risk) REPAIR_MAX_BYTES (100 MB) — repair-commit, repair-snapshot (new tier: metadata payloads, ~6x headroom over the observed 15.6 MB worst case without reaching push-scale) API_MAX_BYTES ( 10 MB) — everything else, unchanged
Sized REPAIR_MAX_BYTES from real data, not an arbitrary guess: queried the local dev DB directly (pg_column_size on musehub_commits.structured_delta, length(manifest_blob) on musehub_snapshots) to confirm realistic scale before picking 100 MB as comfortable headroom over the one known 15.6 MB production case.
nginx's client_max_body_size (500m, deploy/nginx-cf.conf) is unaffected — 100 MB is below it, so nothing changes there.
New tests/test_repair_commit_body_size_limit.py (8 tests): the exact 15.6 MB reproduction case now passes, 20 MB on repair-commit/repair-snapshot (over old API cap, under new repair cap) allowed, >100 MB on repair-commit/ repair-snapshot still correctly rejected (ceiling isn't removed, only right-sized), repair-object allowed up to 150 MB (over repair tier, under push tier) and still rejected over 500 MB.
Confirmed genuine RED: reverting the middleware change makes the whole test file fail to even import (REPAIR_MAX_BYTES doesn't exist) — restored, all 8 green.
Regression: 43 tests across repair/content-size/wire-push suites, plus 131 across the full wire fetch/push/tags suite — all green, no regressions.
Not yet done (deferred per the agreed every-5-tickets staging deploy cadence): Phase 5's live verification — running deploy/repair_commit_signatures.py against staging's gabriel/muse to confirm the one remaining corrupted-signature commit now repairs end-to-end, and a follow-up `muse verify` showing 0 signature failures. This requires the fix to actually be deployed to staging first; will run as part of the next batched staging deploy (2 of 5 since musehub#229).
Semantic Changes
19 symbols
Files Changed
+1
~1
1099 in snapshot
0 comments
muse hub commit comment sha256:12b077920a78fb8440555add7bdea5509ff80049f1e4cba9cdcebb4ea69c51fc --body "your comment"
No comments yet. Be the first to start the discussion.