Skip to main content

max / makenotwork

synckit: document blob content-addressing trust model (ultra-fuzz Run 4 Storage A+) Phase 3 (Storage). The Storage axis's only sub-A cold spot was the OAuth revocation-parity gap, already closed in Phase 2 (108bd59) by the shared assert_token_live gate. The remaining Storage NOTE is the blob re-hash: confirm treats the hash as a content-address label and does not re-hash the bytes. Decision (Max, 2026-06-23): the blast radius is per-user only -- the key is {app_id}/{user_id}/{hash} with UNIQUE(app_id,user_id,hash), so a client can poison only its own dedup namespace; no cross-user effect, no data exposure. The correct A+ fix binds x-amz-checksum-sha256 into the presigned PUT so S3 rejects a mismatched upload at write time with zero server download, but that needs the synckit-client SDK to send the checksum header -- deferred to the SDK's own remediation rather than paying a full object download + re-hash on every confirm. Documented the trust model at the confirm site so it reads as a conscious decision, not an oversight. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-06-23 23:24 UTC
Commit: cc53cb14de25883dafeef4bfc30707c6e91eeb5f
Parent: 108bd59
1 file changed, +13 insertions, -0 deletions
@@ -111,6 +111,19 @@ pub(super) async fn blob_upload_url(
111 111 ///
112 112 /// Verifies the object exists in S3, then records it in the database.
113 113 /// Idempotent: returns success without creating a duplicate.
114 + ///
115 + /// Content-addressing trust model (ultra-fuzz Run 4 Storage NOTE, decision
116 + /// 2026-06-23): the blob `hash` is treated as a content-address LABEL — confirm
117 + /// reads the authoritative `object_size` from S3 but does not re-hash the bytes
118 + /// to prove they match `hash`. The blast radius is per-user only: the key is
119 + /// `{app_id}/{user_id}/{hash}` and storage is `UNIQUE(app_id, user_id, hash)`,
120 + /// so a client that stores mismatched bytes can poison only its OWN dedup
121 + /// namespace — no cross-user effect, no data exposure. The correct A+ fix binds
122 + /// `x-amz-checksum-sha256` into the presigned PUT so S3 itself rejects a
123 + /// mismatched upload at write time (zero server-side download); that requires the
124 + /// `synckit-client` SDK to send the checksum header, so it is deferred to the
125 + /// SDK's own remediation rather than paying a full object download + re-hash on
126 + /// every confirm here.
114 127 #[utoipa::path(post, path = "/api/v1/sync/blobs/confirm", tag = "SyncKit",
115 128 request_body = BlobConfirmRequest,
116 129 responses((status = 204, description = "Upload confirmed")),