Skip to content

Run 3b: CORS Integration

Adds crossOrigin="use-credentials" support to ImagePreviewEditor for CDN-hosted images, completing the ImageUploadDialog component updates started in Run 3a. This change requires infrastructure#439 (CloudFront CORS Response Headers Policy) to be deployed before the edit-existing-image flow will work in production. Corresponds to specification.md T-1 change #7.

Author: Claude Code for jmpicnic | Date: 2026-04-07 | Status: Planning

Merge option: If infrastructure#439 is already deployed when Run 3a completes, this run may be merged into the Run 3a session. Execute the tasks below as additional tasks at the end of that session and apply the union of both runs’ exit criteria. There is no need to launch a separate agent session.

When ImageUploadDialog opens in EditExisting state with a CDN-hosted image URL (matching *.assets.arda.cards), the ImagePreviewEditor must set crossOrigin="use-credentials" on the <img> element loaded into the crop canvas. Without this, toBlob() / getCroppedImage() throws a SecurityError due to canvas tainting by cross-origin content.

The attribute must only be set for CDN URLs — local blobs and object URLs must omit it to avoid unnecessary CORS preflights.

#CriterionVerification CommandExpected Output
1Run 3a exit gate passedmake -C /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype check && make -C /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype test && make -C /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype buildAll exit 0
2infrastructure#439 deployedVerify with team — CloudFront CORS Response Headers Policy for https://*.arda.cards with Access-Control-Allow-Credentials: trueConfirmed deployed
3ux-prototype worktree on correct branchgit -C /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype branch --show-currentjmpicnic/image-upload-frontend
4No uncommitted changes in ux-prototypegit -C /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype status --porcelainEmpty (Run 3a changes committed)
#TaskPersonaDepends OnStatusAcceptance Criteria
3b.1Add crossOrigin="use-credentials" to ImagePreviewEditor via react-easy-crop’s mediaProps prop; set only when image source matches CDN URL pattern (*.assets.arda.cards)front-end-engineerPendingCDN URLs set crossOrigin="use-credentials" on the crop image element; local blob URLs do not set crossOrigin; react-easy-crop mediaProps={{ crossOrigin: 'use-credentials' }} used for CDN sources
3b.2Add unit tests for crossOrigin behaviorfront-end-engineer3b.1PendingTest: EditExisting with CDN URL (https://example.assets.arda.cards/img.jpg) sets crossOrigin="use-credentials"; test: EditExisting with local blob URL does NOT set crossOrigin; both tests pass
3b.3Full checks (ux-prototype)front-end-engineer3b.2Pendingmake check (lint + typecheck), make test (all tests including new), make build (Storybook build) all exit 0; Storybook stories render correctly

Single ux-prototype worktree. This run has three small, strictly sequential tasks.

Working directory: /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype Branch: jmpicnic/image-upload-frontend

Sequential only — 3b.2 depends on 3b.1; 3b.3 depends on both.

3b.1 (crossOrigin implementation) → 3b.2 (unit tests) → 3b.3 (full checks)

Single agent; no idle time. This is an intentionally small run.

PersonaAgent NameTasks AssignedWorking DirectorySpawn Order
front-end-engineerfe-cors3b.1 through 3b.3/Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototypeFirst
ArtifactPath (relative to ux-prototype worktree)FormatDescription
Updated ImagePreviewEditorWithin src/components/canary/organisms/shared/image-upload-dialog/TSXConditional crossOrigin="use-credentials" via react-easy-crop mediaProps
crossOrigin unit testsAdjacent to ImagePreviewEditor or ImageUploadDialogTypeScript/VitestCDN URL test + local blob URL test
3b.1 (crossOrigin implementation) ──→ 3b.2 (unit tests) ──→ 3b.3 (full checks)
#CriterionVerification CommandExpected Output
1CDN URL sets crossOriginnpm --prefix <ux-worktree> run test -- --reporter=verbose 2>&1 | grep "crossOrigin"2 test cases PASS
2Local blob URL does not set crossOrigin(same as above — both cases in the test suite)PASS
3No regression in Run 3a changesnpm --prefix <ux-worktree> run testSame or greater test count; all green
4Full checks passmake -C <ux-worktree> check && make -C <ux-worktree> test && make -C <ux-worktree> buildAll exit 0
5Storybook stories renderStorybook build exits 0Exit 0

Where <ux-worktree> = /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype.

Working directory: /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype Use absolute paths for all tool calls.

Implement T-1 change #7 from Phase 3.3: specification.md.

Load skills: ui-component, unit-tests-frontend.

The single change: When ImageUploadDialog opens with a CDN-hosted image URL, ImagePreviewEditor must pass mediaProps={{ crossOrigin: 'use-credentials' }} to react-easy-crop. The URL pattern for CDN images is *.assets.arda.cards. For local blobs (object URLs), mediaProps must not include crossOrigin.

Why CDN only: Cross-origin requests to CDN assets require CORS credentials. Local blobs are same-origin and do not need the header; adding it would cause unnecessary CORS preflights on blob URLs.

Infrastructure dependency: infrastructure#439 must be deployed before the edit-existing-image flow works in production. This run is gated on that deployment. The unit tests verify the attribute is set on the correct image element regardless of whether CloudFront is available.

After 3b.3 (full checks), commit all changes in the ux-prototype worktree.

ArtifactProducer RunPath
Updated ImageUploadDialog (without crossOrigin)Run 3aux-prototype worktree
infrastructure#439 deployedExternalCloudFront — team confirms
ArtifactConsumer RunPath
Complete ImageUploadDialog + ImagePreviewEditor (with crossOrigin)Run 4ux-prototype worktree

STOP: Review crossOrigin behavior and confirm all component changes are complete before proceeding to Run 4 (design system publish).

#QuestionOptionsRecommendationDecision
1Merge Run 3b into Run 3a if infrastructure#439 already deployed?A: always separate, B: merge if infra readyBDecided: B — see note at top of document
  • ImagePreviewEditor sets crossOrigin="use-credentials" via react-easy-crop mediaProps for CDN URLs
  • ImagePreviewEditor does not set crossOrigin for local blob URLs
  • 2 unit tests pass covering both CDN and blob cases
  • No regressions from Run 3a component changes
  • make check, make test, make build all pass
  • Storybook stories render correctly
  • Changes committed in ux-prototype worktree
Risk / BlockerImpactMitigation
infrastructure#439 not yet deployedBlocks this run entirelyDo not start Run 3b until deployment confirmed; proceed with Run 4 prep if the merge option applies
react-easy-crop mediaProps type mismatchLow — library typingCheck react-easy-crop type definitions for mediaProps before implementing
CDN URL pattern matching too broad or too narrowLow — incorrect behaviorUnit tests verify both CDN and blob URL cases; use includes('assets.arda.cards') or regex
FileDescription
changelog.mdSummary of crossOrigin change in Run 3b
learnings.mdObservations about canvas taint, CORS, react-easy-crop

The team’s TaskList is the single source of truth for task status. Follow the protocol at every phase boundary per the team-lead agent definition.

DateEventNotes
2026-04-07Plan created

Copyright: (c) Arda Systems 2025-2026, All rights reserved