Conversation
Reviewer's guide (collapsed on small PRs)Reviewer's GuideThis PR completes the client profile photo mutation deprecation by removing its resolver, input and generated schema artifacts, while preserving the Upload scalar required by model-derived inputs. Tests now seed photos directly through the model and continue validating the supported presigned upload, resolution, deletion, and imgproxy-rendered query paths; review the draft merge gate carefully before approval. File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
`createClientDocument` was the last multipart upload mutation. The presigned pipeline replaced it in #2018, which deleted the components that called it, and nothing has called it since: no `.graphql` document, no generated operation, no component, and zero occurrences in the compiled mobile bundle — against one occurrence of `updateClientProfilePhoto` in the same bundle, so the search is sound rather than a false negative. Its only remaining consumers were backend test fixtures. Reviewing the previous commit surfaced that this path was also entirely unvalidated — no size limit and no content-type allowlist, because `CLIENT_DOCUMENT_CONFIG` is only ever applied on the presigned side. Rather than add a validator and an exception class to code nobody reaches, remove the path: - the `create_client_document` mutation and `CreateClientDocumentInput` - `create_multipart_attachment`, added in the previous commit and now orphaned - `python-magic`, whose only two call sites were the deleted `Attachment.save()` override and this service `_create_client_document_fixture` now builds its document through the presigned mutations, so the ~28 test call sites keep working. Two tests went with the mutation: `test_create_client_document`, and `test_create_client_document_permission`, which duplicated `test_resolve_client_document_uploads_permission` parameter for parameter. `updateClientProfilePhoto` stays. It is present in the shipped bundle, so it has to outlive the app taking #2406, which moves photo deletion onto `deleteClientProfilePhoto`. #2405 removes it once that rollout is confirmed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2b78694 to
ca8f224
Compare
5c5c626 to
ebd427c
Compare
`createClientDocument` was the last multipart upload mutation. The presigned pipeline replaced it in #2018, which deleted the components that called it, and nothing has called it since: no `.graphql` document, no generated operation, no component, and zero occurrences in the compiled mobile bundle — against one occurrence of `updateClientProfilePhoto` in the same bundle, so the search is sound rather than a false negative. Its only remaining consumers were backend test fixtures. Reviewing the previous commit surfaced that this path was also entirely unvalidated — no size limit and no content-type allowlist, because `CLIENT_DOCUMENT_CONFIG` is only ever applied on the presigned side. Rather than add a validator and an exception class to code nobody reaches, remove the path: - the `create_client_document` mutation and `CreateClientDocumentInput` - `create_multipart_attachment`, added in the previous commit and now orphaned - `python-magic`, whose only two call sites were the deleted `Attachment.save()` override and this service `_create_client_document_fixture` now builds its document through the presigned mutations, so the ~28 test call sites keep working. Two tests went with the mutation: `test_create_client_document`, and `test_create_client_document_permission`, which duplicated `test_resolve_client_document_uploads_permission` parameter for parameter. `updateClientProfilePhoto` stays. It is present in the shipped bundle, so it has to outlive the app taking #2406, which moves photo deletion onto `deleteClientProfilePhoto`. #2405 removes it once that rollout is confirmed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ca8f224 to
4f0643e
Compare
ebd427c to
a57017e
Compare
|
🚀 Expo continuous deployment is ready for betterangels!
iOS Simulator Build: Simulator Build Link |
|
🔍 [betterangels-admin] Preview available at: https://admin.dev.betterangels.la/branches/DEV-warnings-remove-update-client-profile-photo Last updated: 2026-09-10T21:52:40.835Z |
|
🔍 [shelter-web] Preview available at: https://shelter.dev.betterangels.la/branches/DEV-warnings-remove-update-client-profile-photo Last updated: 2026-09-10T21:52:40.835Z |
a57017e to
f4f7c4b
Compare
Uploads moved to generateClientProfilePhotoUpload/resolveClientProfilePhotoUpload and removal to deleteClientProfilePhoto, leaving updateClientProfilePhoto with no caller in the tree. `profilePhoto` also came off the four client-profile inputs. It was derived from `profile_photo: auto` on bases shared by the output types and the inputs, so `createClientProfile`, `updateClientProfile` and their HMIS counterparts all accepted a multipart file with no size limit and no content-type allowlist — the same unvalidated surface `createClientDocument` was deleted for. Declaring the field on the output types only keeps it readable and takes it off the inputs. Nothing sent it. Both call sites stripped it first: `toUpdateClientProfileInputHmis` destructured it away as a "disallowed field", which the type now does for it, and `ClientProfileForm` still deletes it because its own form values carry a photo. `scalar Upload` leaves the schema with it. The test fixture that drove the mutation is replaced by a helper that writes the photo onto the model, since the three remaining call sites only needed a photo to exist. It returns the URL through build_img_url so the seeded value matches what the GraphQL type renders. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
f4f7c4b to
c92dc55
Compare
This is the follow-up #2402 named but deliberately left undone:
Do not take it out of draft until both hold:
main.deleteClientProfilePhotowiring has published, and no active runtime version is still serving a pre-refactor(common)!: remove the dead multipart client-document upload #2402 bundle.An installed binary still running the old bundle sends
updateClientProfilePhoto(photo: null)as its delete path. Merging this before it has taken the update breaks photo deletion for those users.What goes
updateClientProfilePhotowas deprecated in favour ofgenerateClientProfilePhotoUpload/resolveClientProfilePhotoUploadfor uploads anddeleteClientProfilePhotofor removal. #2402 movedProfilePhotoModaloff the last remaining caller, so nothing in the tree references it any more.Removed: the mutation,
ClientProfilePhotoInput, and the now-unusedstrawberry.file_uploads.Uploadimport inclients/types.py.scalar Uploadstays in the schema:CreateClientProfileInput.profilePhotoandCreateHmisClientProfileInput.profilePhotoare auto-derived bystrawberry_djangofrom the model'sImageField. Retiring those is a separate question about model-derived inputs, not part of this change.Test changes
_update_client_profile_photo_fixturehad four call sites. One tested the deleted mutation; the other three only needed a photo to exist:test_update_client_profile_photois deleted. The presigned path it was standing in for is already covered bytest_generate_client_profile_photo_uploadandtest_resolve_client_profile_photo_upload._set_client_profile_photo, which writes the photo onto the model. It returnsbuild_img_url(...)rather thanprofile_photo.url— the GraphQL type renders profile photos through imgproxy, so the seeded value has to be produced the same way the assertions read it.Verification
pytest— 1519 passed, 31 skippedmypyclean (cache cleared first),ruffcleanexpo-betterangelstsc --noEmitcleanschema.graphqlregenerated; frontend types regenerated across all four codegen consumers. The generated diff is confined toClientProfilePhotoInput,MutationUpdateClientProfilePhotoArgs,UpdateClientProfilePhotoPayloadand theMutationfield.🤖 Generated with Claude Code
Summary by Sourcery
Remove the deprecated multipart client profile photo upload path now that the presigned upload and deletion flows are established.
Enhancements:
Tests:
Chores: