Phase 2: abuse resistance and information leakage (frontend) - #3
Merged
Conversation
Cloudinary rebuilds the signature from the parameters it recognises and ignores the rest, so an extra field makes the upload fail with 401 Invalid Signature rather than being harmlessly dropped. max_file_size is not an Upload API parameter, and sending it broke every upload -- verified against the live API, which reported the string it had signed with the field absent. Now posts the server-issued public_id, which pins the asset to this seller and is checked again when the listing is submitted, and allowed_formats, which Cloudinary does enforce. The file-type check narrows from any image/* to the three formats the backend allows, so the browser refuses what Cloudinary would refuse anyway rather than uploading it first. The 5 MB check stays a courtesy: it saves a doomed upload and a token from the signature route's hourly budget, but Cloudinary's Upload API has no per-request size cap, so nothing server-side enforces it and the backend no longer publishes it as policy. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JcxUSuo3zd4z4TRHh58iop
Two defects found by driving the real UI, not by tests. A validation failure answers with a constant top-level `error` -- "Validation error" -- and puts the actionable part in `details`, a field -> messages map. services/api.ts did not carry `details` in its response type at all and threw away everything but `error`, so every field-level rejection in the app rendered as the same unactionable sentence. Rejecting "password123" showed "Validation error" while the server had said "Choose a less common password". Phase 2 widened this vocabulary considerably -- password strength, length caps, the emoji limit, money bounds -- so what was already wrong became a lot more visible. Fixed where the error is constructed rather than at each call site, so every screen benefits and no screen has to remember to. Separately, the create-listing dropzone advertised "Max 10 MB" in two places while the check beneath it rejected anything over MAX_IMAGE_BYTES, 5 MB. A 7 MB photo was refused by a rule the screen never stated. The label is now derived from the constant so the two cannot drift again. Verified live: the change-password form now reads "Choose a less common password" against the field that caused it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AW5Zp1KXWzEvG1KNviCfTh
Backend now revokes every session on a password change, including the caller's, and hands back a fresh pair with the confirmation (contract 2.1.0). Without storing it, the stale refresh token in localStorage signs the user out on the next silent refresh -- their own successful password change logging them out minutes later, mid-task. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0114vatC9EkHGSUN9zGfAT3G
…y had Only BuyerProfile could change its own password -- no admin or seller screen offered it, and no route existed for a seller one at all. Admin gets a Security card inline in the existing Settings page, next to the read-only Admin Profile card. Seller gets a new Profile screen (mirroring BuyerProfile's layout: stats, account info, recent listings, quick links) reachable the same way Buyer's is -- clicking the avatar/name in the navbar, which SellerNavbar's did not link anywhere before this. Both Security cards are the same inline form buyer's already has, copied rather than extracted into a shared component: each lives in a screen with its own loading/error handling and its own header, and the three copies are three fields and two handlers, not enough to justify the indirection. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0114vatC9EkHGSUN9zGfAT3G
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Frontend companion to bidvault-backend's Phase 2 PR.
Test plan
Generated with Claude Code
https://claude.ai/code/session_0151oceeiAyJdi6T273spk4P