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.
User Request
Section titled “User Request”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.
Entry Criteria
Section titled “Entry Criteria”| # | Criterion | Verification Command | Expected Output |
|---|---|---|---|
| 1 | Run 3a exit gate passed | make -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 build | All exit 0 |
| 2 | infrastructure#439 deployed | Verify with team — CloudFront CORS Response Headers Policy for https://*.arda.cards with Access-Control-Allow-Credentials: true | Confirmed deployed |
| 3 | ux-prototype worktree on correct branch | git -C /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype branch --show-current | jmpicnic/image-upload-frontend |
| 4 | No uncommitted changes in ux-prototype | git -C /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype status --porcelain | Empty (Run 3a changes committed) |
Decomposition
Section titled “Decomposition”Task List
Section titled “Task List”| # | Task | Persona | Depends On | Status | Acceptance Criteria |
|---|---|---|---|---|---|
| 3b.1 | Add 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-engineer | — | Pending | CDN 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.2 | Add unit tests for crossOrigin behavior | front-end-engineer | 3b.1 | Pending | Test: 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.3 | Full checks (ux-prototype) | front-end-engineer | 3b.2 | Pending | make check (lint + typecheck), make test (all tests including new), make build (Storybook build) all exit 0; Storybook stories render correctly |
Worktree Strategy
Section titled “Worktree Strategy”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
Parallelization
Section titled “Parallelization”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)Idle Agent Strategy
Section titled “Idle Agent Strategy”Single agent; no idle time. This is an intentionally small run.
Personas Required
Section titled “Personas Required”| Persona | Agent Name | Tasks Assigned | Working Directory | Spawn Order |
|---|---|---|---|---|
| front-end-engineer | fe-cors | 3b.1 through 3b.3 | /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype | First |
Artifact Specifications
Section titled “Artifact Specifications”| Artifact | Path (relative to ux-prototype worktree) | Format | Description |
|---|---|---|---|
Updated ImagePreviewEditor | Within src/components/canary/organisms/shared/image-upload-dialog/ | TSX | Conditional crossOrigin="use-credentials" via react-easy-crop mediaProps |
crossOrigin unit tests | Adjacent to ImagePreviewEditor or ImageUploadDialog | TypeScript/Vitest | CDN URL test + local blob URL test |
Internal Dependency Graph
Section titled “Internal Dependency Graph”3b.1 (crossOrigin implementation) ──→ 3b.2 (unit tests) ──→ 3b.3 (full checks)Exit Criteria
Section titled “Exit Criteria”| # | Criterion | Verification Command | Expected Output |
|---|---|---|---|
| 1 | CDN URL sets crossOrigin | npm --prefix <ux-worktree> run test -- --reporter=verbose 2>&1 | grep "crossOrigin" | 2 test cases PASS |
| 2 | Local blob URL does not set crossOrigin | (same as above — both cases in the test suite) | PASS |
| 3 | No regression in Run 3a changes | npm --prefix <ux-worktree> run test | Same or greater test count; all green |
| 4 | Full checks pass | make -C <ux-worktree> check && make -C <ux-worktree> test && make -C <ux-worktree> build | All exit 0 |
| 5 | Storybook stories render | Storybook build exits 0 | Exit 0 |
Where <ux-worktree> = /Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototype.
Agent Prompt Templates
Section titled “Agent Prompt Templates”front-end-engineer — fe-cors
Section titled “front-end-engineer — fe-cors”Working directory:
/Users/jmp/code/arda/projects/image-upload-frontend-worktrees/ux-prototypeUse 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
ImageUploadDialogopens with a CDN-hosted image URL,ImagePreviewEditormust passmediaProps={{ crossOrigin: 'use-credentials' }}toreact-easy-crop. The URL pattern for CDN images is*.assets.arda.cards. For local blobs (object URLs),mediaPropsmust not includecrossOrigin.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.
Handoff
Section titled “Handoff”Artifacts Consumed (from previous runs)
Section titled “Artifacts Consumed (from previous runs)”| Artifact | Producer Run | Path |
|---|---|---|
Updated ImageUploadDialog (without crossOrigin) | Run 3a | ux-prototype worktree |
| infrastructure#439 deployed | External | CloudFront — team confirms |
Artifacts Produced (for subsequent runs)
Section titled “Artifacts Produced (for subsequent runs)”| Artifact | Consumer Run | Path |
|---|---|---|
Complete ImageUploadDialog + ImagePreviewEditor (with crossOrigin) | Run 4 | ux-prototype worktree |
STOP: Review crossOrigin behavior and confirm all component changes are
complete before proceeding to Run 4 (design system publish).
Open Questions and Decisions
Section titled “Open Questions and Decisions”| # | Question | Options | Recommendation | Decision |
|---|---|---|---|---|
| 1 | Merge Run 3b into Run 3a if infrastructure#439 already deployed? | A: always separate, B: merge if infra ready | B | Decided: B — see note at top of document |
Acceptance Criteria
Section titled “Acceptance Criteria”-
ImagePreviewEditorsetscrossOrigin="use-credentials"viareact-easy-cropmediaPropsfor CDN URLs -
ImagePreviewEditordoes not setcrossOriginfor 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 buildall pass - Storybook stories render correctly
- Changes committed in ux-prototype worktree
Risks and Blockers
Section titled “Risks and Blockers”| Risk / Blocker | Impact | Mitigation |
|---|---|---|
| infrastructure#439 not yet deployed | Blocks this run entirely | Do not start Run 3b until deployment confirmed; proceed with Run 4 prep if the merge option applies |
react-easy-crop mediaProps type mismatch | Low — library typing | Check react-easy-crop type definitions for mediaProps before implementing |
| CDN URL pattern matching too broad or too narrow | Low — incorrect behavior | Unit tests verify both CDN and blob URL cases; use includes('assets.arda.cards') or regex |
Project Completion Artifacts
Section titled “Project Completion Artifacts”Byproducts (byproducts/)
Section titled “Byproducts (byproducts/)”| File | Description |
|---|---|
changelog.md | Summary of crossOrigin change in Run 3b |
learnings.md | Observations about canvas taint, CORS, react-easy-crop |
Task Tracking Protocol
Section titled “Task Tracking Protocol”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.
Progress Log
Section titled “Progress Log”| Date | Event | Notes |
|---|---|---|
| 2026-04-07 | Plan created |
Copyright: (c) Arda Systems 2025-2026, All rights reserved
Copyright: © Arda Systems 2025-2026, All rights reserved