Document upload moved to backend-issued presigned PUT URLs; Cognito Identity Pool removed

dropthejase replaced multipart upload through the Lambda with a three-step prepare/upload/register flow using presigned S3 PUT URLs generated by the backend. The browser uploads directly to S3 with no AWS credentials. Once that was in place, the Cognito Identity Pool had no remaining purpose and was removed entirely.

securityinfrastructure

The new flow: POST /single-documents/prepare creates a DB row with status='processing', generates a presigned PutObject URL with a 15-minute TTL, and returns { docId, uploadKey, uploadUrl }. The browser PUTs the file directly to S3 via XHR - no SDK, no credentials. Then POST /single-documents/:documentId/register creates the document_versions row, sets current_version_id, and marks status='ready'. The Conversion Lambda fires via EventBridge on the S3 object creation event and handles DOCX-to-PDF in the background.

The same prepare/register split applies to project-scoped uploads at POST /projects/:projectId/documents/prepare and /:documentId/register. The multipart-through-Lambda path and handleDocumentUpload are removed.

Before this change, the frontend used Amplify uploadData with Identity Pool temporary credentials. After a brief intermediate state where both paths coexisted, 703ad3a deletes the AwsContext.tsx provider (87 lines that fetched and cached Identity Pool credentials), removes VITE_IDENTITY_POOL_ID from env examples, and strips the Cognito Identity Pool from AuthStack entirely. The authenticated IAM role retains GetObject/DeleteObject scoped to the user's prefix for potential future use.

The S3 path prefix changes too: the Identity Pool used ${cognito-identity.amazonaws.com:sub} (the identity ID, not the user pool sub). Presigned URL generation uses the user pool sub directly, since the API Lambda reads that from the validated JWT.

So what Worth a look even if you keep your own auth and DB choices. Backend-issued presigned PUT URLs eliminate browser-side AWS credentials and simplify the frontend considerably. The three-step flow is slightly more round-trips than multipart through Lambda, but the Lambda never touches file bytes. If you import this pattern, do not import the Identity Pool wiring from post 352 alongside it - they conflict.

View this fork on GitHub →

Spotted something wrong? Or know the PR text has fresher detail than the writeup above?

Commits in this thread

7 commits from dropthejase/louis, oldest first. Source extracted verbatim from the harvested git log.

SHA Subject Author Date
3985ac4f feat: replace multipart upload with direct S3 prepare/upload/register flow Jason Lee 2026-05-11 ↗ GitHub
commit body
- Add POST /single-documents/prepare and /:documentId/register
- Add POST /projects/:projectId/documents/prepare and /documents/:documentId/register
- Remove handleDocumentUpload, extractStructureTree, countPdfPages
- Remove multipart POST / and POST /:projectId/documents routes
- Replace uploadStandaloneDocument and uploadProjectDocument in mikeApi.ts
  with 3-step prepare→S3 uploadData→register flow
c8ebfa45 docs: mark upload refactor complete in FEATURE-PARITY.md Jason Lee 2026-05-11 ↗ GitHub
af14662b docs: update ARCHITECTURE.md upload flow to reflect direct S3 prepare/register Jason Lee 2026-05-11 ↗ GitHub
61e73c12 fix(upload): replace Amplify Identity Pool upload with backend presigned S3 PUT URLs Jason Lee 2026-05-12 ↗ GitHub
commit body
- /prepare endpoints now generate presigned PutObject URLs (15 min TTL)
- Frontend uploads via XHR PUT to presigned URL - no AWS credentials on client
- Revert IAM auth role to original cognito-identity sub variable; remove PutObject
- S3 paths stay as user pool sub (consistent with DB user_id)
- Update ARCHITECTURE.md and FEATURE-PARITY.md to reflect new upload flow
f14a2d96 Merge main into development Jason Lee 2026-05-16 ↗ GitHub
703ad3a2 refactor(auth): remove Cognito Identity Pool - uploads use presigned URLs Jason Lee 2026-05-16 ↗ GitHub
commit body
Identity Pool credentials were issued but never consumed. All uploads
go through backend-generated presigned URLs (mikeApi.ts). Removes:
- CfnIdentityPool, AuthenticatedRole, per-user S3 bucket policy (AuthStack)
- AwsContext.tsx, credentials.ts, storage.ts (dead frontend code)
- VITE_IDENTITY_POOL_ID env var and amplifyConfig Storage/identityPoolId

Also updates README highlight to reflect AgentCore microVM isolation
instead of the now-removed Identity Pool isolation claim.
04adf9ac Merge development into main Jason Lee 2026-05-16 ↗ GitHub

Capture this thread into my fork

Download a single Markdown prompt that tells Claude how to port every commit above into your working tree — adapting paths and structure to match your repo. Run it via claude -p < capture-thread-341.md from inside the repo you want the changes in.

⬇ Download capture-thread-341.md