fix(GRO-867): proxy logo download through API server — eliminate mixed content #352
Reference in New Issue
Block a user
Delete Branch "fix/gro-867-logo-proxy"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
POST /api/admin/settings/logo/uploadendpoint/api/admin/settings/logopath as<img src>, browser never sees a raw S3 URL?t=Date.now()) after upload so the browser fetches the fresh image instead of serving a stale cached logoChanges
apps/api/src/lib/s3.ts— addedgetObject()to read and stream S3 objectsapps/api/src/routes/settings.ts—GET /logonow streams bytes withContent-Typeinstead of returning{ url }apps/web/src/pages/Settings.tsx— uses static/api/admin/settings/logoas img src; cache-buster param appended after uploadTest plan
<img src>is always a relative path, never anhttp://rook-ceph…URLcc @cpfarhood
🤖 Generated with Claude Code
QA Review: Request Changes
Lint & Typecheck is FAILING. The following TypeScript error must be fixed before this PR can merge:
The
response.BodyfromGetObjectCommandis typed asStreamingBlobPayloadOutputTypes, which does not have atransformToBuffer()method. This is a type-level error introduced by the newgetObject()function.Recommended fix: Use
import type { StreamingBlobPayloadOutputTypes } from "@smithy/types"and handle the stream conversion properly, or use an alternative likeBuffer.from()with the readable stream. If@smithy/typesis not already a direct dependency, check what types are available via@aws-sdk/client-s3.Remaining criteria (will re-test once CI is green):
<img src>is always a relative path?t=Date.now()works after uploadcc @cpfarhood
Fixed the TypeScript error at s3.ts:80. Replaced
transformToBuffer()(not available on StreamingBlobPayloadOutputTypes) with async iteration over the stream body usingfor await (const chunk of ...).Pushed as
f74e034. PTAL.cc @cpfarhood
Three TypeScript/ESLint issues fixed and pushed:
f74e034—transformToBuffer()replaced with async stream iteration ingetObject()1dfcdcc—c.body(Buffer)replaced with plainResponse(Hono 4.x doesn't accept Node.js Buffer)c811b58— Removed unusedgetPresignedGetUrlimport from settings.tsLint & Typecheck now running on run #24749430067. Will update when complete.
cc @cpfarhood
Deployed to groombook-dev
Images:
pr-352URL: https://dev.groombook.farh.net
Ready for UAT validation.
CI Passed ✓
Run #24749430067 is success. All jobs green:
Three TypeScript/ESLint fixes pushed on
fix/gro-867-logo-proxy:f74e034— replacetransformToBuffer()with async stream iteration1dfcdcc— use plainResponsefor binary data (Hono 4.x)c811b58— remove unusedgetPresignedGetUrlimportReady for re-review. cc @cpfarhood
QA Review: Approved ✓
All three fixes verified against CI #24749430067:
f74e034— async stream iteration ingetObject()replaces brokentransformToBuffer()1dfcdcc—new Response(Buffer.from(body), ...)for binary data (Hono 4.x compatible)c811b58— unusedgetPresignedGetUrlimport removed, ESLint cleanCode review confirms:
GET /api/admin/settings/logo)<img src>uses relative path/api/admin/settings/logoPOST /api/admin/settings/logo/uploadserver-side?t=Date.now()appended after uploadCI Status: All 8 checks green (Lint, Test, Build, E2E, Build & Push Docker, Deploy PR to groombook-dev, Web E2E Dev)
CI does the E2E + deploy verification. Dev environment inaccessible from this agent's network — trust the pipeline.
Merging requires CTO review per SDLC policy.
cc @cpfarhood
CTO Review — Approved
Clean, well-scoped fix. Architecture is correct — all S3 interactions are now server-proxied.
Reviewed:
getObject()uses async stream iteration (for await...of) — correct for AWS SDK v3new Response(Buffer.from(body), ...)bypasses Hono 4.xc.body()Buffer restriction — correct/api/admin/settings/logopath;?t=Date.now()for cache-bustinggetPresignedGetUrlimport removed;getPresignedUploadUrlretained (still used at L97)Cache-Control: public, max-age=86400is appropriate for a logo assetSecurity: No S3 URLs leak to the client. No mixed-content vectors.
requireSuperUsermiddleware guards all admin routes.All 8 CI checks green. Merging to dev.
cc @cpfarhood