MEGAINFRA-WEBAPP/.superpowers/sdd/2026-09-18-hybrid-delivery-note-ingestion/task-9-report.md

5.8 KiB

Task 9 report: batch stages and split review

Status: complete

RED evidence

The new split-review test was run before the component existed:

npx vitest run src/app/dashboard/financial/delivery-notes/inbox/split-review.test.ts
Failed to load url ./split-review ... Does the file exist?

GREEN evidence

npx vitest run src/app/dashboard/financial/delivery-notes/inbox/split-review.test.ts src/app/api/dn-batches/[id]/pages/[n]/route.test.ts
2 files passed; 18 tests passed

npm run typecheck
passed

git diff --check
passed

Files

  • src/app/dashboard/financial/delivery-notes/inbox/page.tsx maps explicit and legacy batch state through displayBatchStage.
  • src/app/dashboard/financial/delivery-notes/inbox/inbox-board.tsx renders the five required columns and source/page/document counts.
  • src/app/dashboard/financial/delivery-notes/inbox/split-review.tsx adds the interactive page-strip grouping editor, required dismissal reason, 409 reload message, and collapsed technical details.
  • src/app/dashboard/financial/delivery-notes/inbox/split-review.test.ts covers labels, actions, warnings, and technical disclosure.
  • src/app/dashboard/financial/delivery-notes/inbox/[id]/page.tsx loads staged page metadata and uses PocketBase file URLs with legacy route fallback.
  • src/app/dashboard/financial/delivery-notes/inbox/[id]/batch-detail-view.tsx mounts split review without changing posting controls.
  • src/app/api/dn-batches/[id]/pages/[n]/route.ts serves validated persisted dn_batch_pages images and falls back to legacy rendering.
  • src/app/api/dn-batches/[id]/pages/[n]/route.test.ts covers persisted image serving alongside legacy behavior.

Accessibility and touch decisions

  • Page thumbnails use explicit Page N alt text and visible numbered overlays.
  • Actions use existing Button components with large (lg/sm) targets and clear plain-language labels.
  • Open-page and save outcomes use role=alert/role=status; dismissal uses a labelled dialog and a required reason input.
  • Technical check ids remain inside a closed <details> disclosure by default.
  • High-contrast borders, restrained motion (none added), and the existing utility tokens preserve the construction-site workflow tone without changing global navigation or fonts.

Code commit

da45513ead14e47097613c0ebeb6b25d9cb35574 — feat(dn): add staged inbox and split review

Concerns

  • The split-review component uses SSR-compatible react-dom/server tests because the repository has no browser component-test environment.
  • The persisted page route intentionally falls back when staged metadata/image content is missing or has a non-image content type; old batches remain on-demand rendered.

Fix Round 1

Code commit

5c57dcbf5c4384ecb9f038bf81c636c2ba8e7b54 — fix(dn): harden split review and page proxy

RED evidence

Added focused regressions for the review findings: explicit preparing visibility, no empty groups, complete open-page coverage/actions, persisted noncontiguous group pages, dismissed-page rehydration, signed image proxy authorization, and page-count bounds.

GREEN evidence

npx vitest run src/app/dashboard/financial/delivery-notes/inbox/inbox-board.test.ts src/app/dashboard/financial/delivery-notes/inbox/split-review.test.ts src/app/api/dn-batches/[id]/pages/[n]/route.test.ts src/app/api/dn-batches/[id]/assembly/route.test.ts
4 files passed; 41 tests passed

npm run typecheck
passed

git diff --check
passed

Fixes

  • preparing maps to the required Reading photos board column.
  • Group merges filter by group.length > 0; saves reject unresolved pages and include every page exactly once.
  • Open pages render real thumbnails with add-as-document, join-previous-valid-group, and required-reason dismissal actions.
  • Persisted pages arrays preserve noncontiguous note groups; legacy ranges remain the fallback. Persisted dismissed open pages rehydrate locally.
  • Assembly writes dismissal entries with dismissed: true.
  • Browser thumbnails now use signed Next proxy URLs. HMAC uses server-only DN_PAGE_PROXY_SECRET with N8N_INGEST_SECRET fallback, constant-time verification, fail-closed missing secrets, bound batch filters, and positive page_count bounds.

Accessibility/touch decisions

Open-page actions remain explicit, large existing Button targets; unresolved-page save is visibly disabled with a plain-language resolution message. Proxy authorization never exposes PocketBase admin credentials to the browser.

Fix Round 2

Code commit

1d74905a91e432a38d3a3fd9fe9d40d0560a8ca8 — fix(dn): isolate split review model and orphan pages

GREEN evidence

npx vitest run src/app/dashboard/financial/delivery-notes/inbox/inbox-board.test.ts src/app/dashboard/financial/delivery-notes/inbox/split-review.test.ts src/app/api/dn-batches/[id]/pages/[n]/route.test.ts src/app/api/dn-batches/[id]/assembly/route.test.ts
4 files passed; 42 tests passed

npm run typecheck
passed

npm run build
passed; Next 16 production build completed and included /dashboard/financial/delivery-notes/inbox/[id]

git diff --check
passed

Fixes

  • Added server-safe split-review-model.ts for payload cleanup, note-group rehydration, dismissed-page rehydration, and orphan-page derivation. The Server Component and Client Component now import this module directly; no Server Component imports the use client module.
  • deriveOpenPages preserves and deduplicates persisted open_pages, then adds every uncovered page as an actionable not assigned entry, including the no-existing-open-pages case.
  • Added focused coverage for the pure module boundary, missing page 4 derivation, persisted-entry deduplication, and dismissed preservation.

Build note

npm run build emitted the repository's existing metadataBase warning but completed successfully; generated icon/OG assets were unchanged in git.