--- phase: 06-signing-flow plan: "05" subsystem: ui, api tags: [jwt, pdf, signing, next.js, jose, download] # Dependency graph requires: - phase: 06-04 provides: POST /api/sign/[token] returning ok:true + documents.signedFilePath populated - phase: 06-01 provides: token.ts with createSigningToken/verifySigningToken and jose JWT utilities provides: - Confirmation page at /sign/[token]/confirmed — success checkmark, document name, signed timestamp, download button - GET /api/sign/[token]/download — streams signedFilePath PDF using 15-min download JWT (dt query param) - createDownloadToken / verifyDownloadToken in token.ts — short-lived download-only JWTs (no DB record) - router.push navigation to confirmed page after successful POST submit affects: - 07-phase (any future phase referencing signing completion flow) # Tech tracking tech-stack: added: [] patterns: - Short-lived single-purpose JWT (purpose:'download') for client file download authorization, no DB row needed - Server-side download token generation at page render time passed as query param - Uint8Array cast for Buffer -> Response BodyInit compatibility in Next.js 16 key-files: created: - teressa-copeland-homes/src/app/api/sign/[token]/download/route.ts - teressa-copeland-homes/src/app/sign/[token]/confirmed/page.tsx (replaced placeholder) modified: - teressa-copeland-homes/src/lib/signing/token.ts - teressa-copeland-homes/src/app/sign/[token]/_components/SigningPageClient.tsx key-decisions: - "Download token uses purpose:'download' claim — same SIGNING_JWT_SECRET but separate purpose discriminator, no DB storage needed for 15-min TTL" - "Buffer cast to Uint8Array for Response constructor BodyInit type compatibility (Next.js 16 / TypeScript strict)" - "router.push replaces window.location.href for confirmed redirect — SPA navigation, consistent with Next.js patterns" - "Download token generated server-side at confirmed page render; valid 15min from page load" patterns-established: - "Short-lived download JWT pattern: SignJWT({ documentId, purpose: 'download' }) + 15m expiry, no DB row needed for ephemeral download auth" - "Buffer -> Uint8Array cast for Response BodyInit in Next.js 16 API routes" requirements-completed: - SIGN-06 # Metrics duration: 3min completed: 2026-03-20 --- # Phase 06 Plan 05: Post-Signing Confirmation + Client PDF Download Summary **Post-signing confirmation page with document name, signed timestamp, and 15-min download token; GET /api/sign/[token]/download streams signedFilePath PDF authorized by short-lived download JWT** ## Performance - **Duration:** 3 min - **Started:** 2026-03-20T17:40:19Z - **Completed:** 2026-03-20T17:42:56Z - **Tasks:** 2 - **Files modified:** 4 ## Accomplishments - Extended `token.ts` with `createDownloadToken` / `verifyDownloadToken` using `purpose:'download'` claim and 15-min TTL (no DB row) - Created `GET /api/sign/[token]/download` route: validates `dt` query param JWT, path traversal guard, streams `signedFilePath` as `application/pdf` with `Content-Disposition: attachment` - Replaced static placeholder `confirmed/page.tsx` with full server component: verifies signing token, fetches document name + signed timestamp, generates download token, renders success UX per locked design decisions - Updated `SigningPageClient.tsx` to use `router.push` (via `useRouter`) instead of `window.location.href` for confirmed page navigation ## Task Commits Each task was committed atomically: 1. **Task 1: Download token utilities + download API route** - `a276da0` (feat) 2. **Task 2: Confirmation page + redirect from signing client** - `4cdd9ee` (feat) **Plan metadata:** (docs commit — pending final step) ## Files Created/Modified - `teressa-copeland-homes/src/lib/signing/token.ts` - Added `createDownloadToken` and `verifyDownloadToken` exports - `teressa-copeland-homes/src/app/api/sign/[token]/download/route.ts` - New: GET download handler with JWT validation + PDF streaming - `teressa-copeland-homes/src/app/sign/[token]/confirmed/page.tsx` - Replaced static placeholder with full server component (doc name, timestamp, download button) - `teressa-copeland-homes/src/app/sign/[token]/_components/SigningPageClient.tsx` - Switched `window.location.href` to `router.push` for confirmed navigation ## Decisions Made - Download token uses same `SIGNING_JWT_SECRET` but `purpose:'download'` discriminates from signing tokens — no DB record needed for 15-min ephemeral download - `Buffer` cast to `Uint8Array` for `Response` constructor compatibility in Next.js 16 TypeScript strict mode - `router.push` preferred over `window.location.href` for SPA navigation consistency with Next.js App Router ## Deviations from Plan ### Auto-fixed Issues **1. [Rule 1 - Bug] Fixed Buffer type incompatibility with Response BodyInit** - **Found during:** Task 1 (download API route) - **Issue:** `new Response(fileBuffer, ...)` failed TypeScript type check — `Buffer` is not assignable to `BodyInit | null | undefined` in Next.js 16 strict mode - **Fix:** Cast `fileBuffer` as `new Uint8Array(fileBuffer)` before passing to `Response` constructor - **Files modified:** `teressa-copeland-homes/src/app/api/sign/[token]/download/route.ts` - **Verification:** `npm run build` passes cleanly - **Committed in:** a276da0 (Task 1 commit) --- **Total deviations:** 1 auto-fixed (1 type/bug fix) **Impact on plan:** Auto-fix necessary for build correctness. No scope creep. ## Issues Encountered - Next.js 16 TypeScript strict mode rejects `Buffer` as `Response` body — required `Uint8Array` cast (type compatibility, not runtime behavior change). ## User Setup Required None — no external service configuration required. ## Next Phase Readiness - Complete e-signing ceremony is end-to-end: send link -> view PDF -> sign all fields -> submit -> confirmation page -> download signed PDF - SIGN-06 requirement fulfilled: confirmation page with checkmark, document name, timestamp, download button - Phase 6 (signing flow) is fully complete — all 5 plans executed - Ready for Phase 7 or production deployment when DNS/email is configured --- *Phase: 06-signing-flow* *Completed: 2026-03-20* ## Self-Check: PASSED - FOUND: teressa-copeland-homes/src/app/sign/[token]/confirmed/page.tsx - FOUND: teressa-copeland-homes/src/app/api/sign/[token]/download/route.ts - FOUND: .planning/phases/06-signing-flow/06-05-SUMMARY.md - FOUND commit: a276da0 (Task 1) - FOUND commit: 4cdd9ee (Task 2)