Signed WOPC thumbnail in tx-details renders weirdly
Why¶
Owner observation (2026-06-21, verbatim):
"The web app currently shows the signed WOPC thumbnail in the transaction details on the accounting page quite weirdly"
The "weirdly" needs concrete repro before a fix scope can be set β opening this task with the unknowns documented so a future agent doesn't re-discover them from scratch.
What's known about the surface (without the live repro)¶
The thumbnail in question is rendered by WOPCHoverPreview at components/accounting/transactions/TransactionTitleWithLinks.tsx:307-327. It's a popover content component shown when a user hovers a WOPC-matched transaction's title in the Bank Transactions table or detail drawer.
Implementation today:
function WOPCHoverPreview({ transactionId, wopcRefNumber }) {
return (
<DocumentPreviewShell caption={β¦}>
<div style={{ width: "100%", height: DOCUMENT_PREVIEW_FRAME_HEIGHT, β¦ }}>
<iframe
src={`/accounting/payment-confirmation/${transactionId}/preview?standalone=1&embed=1`}
width="100%"
height="100%"
style={{ border: "none" }}
title="WOPC Preview"
/>
</div>
</DocumentPreviewShell>
)
}
Notes that may matter once the bug is reproduced:
- The preview is an
<iframe>loading a route bytransactionId(notwopcRefdirectly). The route renders the WOPC PDF preview inembed=1/standalone=1mode. DOCUMENT_PREVIEW_FRAME_HEIGHTis a shared constant β sibling preview components (ArchivePdfHoverPreviewat line ~295 for Workspace invoices,InvoiceHoverPreviewfor project invoices) use the same shell.- Sibling previews use a different shape β
ArchivePdfHoverPreviewtakes adocumentIddirectly; only WOPC usestransactionId+ route lookup. That asymmetry is a candidate explanation if the WOPC preview behaves differently from the others. - Per AGENTS.md UI conventions: empty/missing data β render as N/A, retrieval failures as Error, unavailable date/numeric as
-. If the route's data fetch fails for atransactionIdwith no resolved WOPC (or no signed PDF on Drive), the iframe may render something visually broken instead of a clear "N/A"/"Error" placeholder. - Adjacent context that may compound: the WOPC's signed-PDF Drive id lives on the signing-request doc (
wopcSigningRequests/{id}.signedDriveFileId) for 30/32 of the 32 production WOPCs β only 2 haveWOPC.pdfFileId/WOPC.pdfStoragePathmirrored on the WOPC doc itself. The preview route likely resolves through both paths.
What this task needs¶
- Reproduce the "weird" rendering in the live app (Records / Bank Transactions tab, hover a WOPC-matched tx, observe the WOPC thumbnail popover). Capture: screenshot, browser console errors, network tab for the
/accounting/payment-confirmation/{txId}/previewrequest, and the affected tx + WOPC ids. - Diagnose β is the issue iframe sizing (height/scrollbar), embed-mode CSS, slow-load placeholder, broken aspect ratio relative to the actual signed PDF, transactionIdβWOPC resolution returning the wrong source, or something else?
- Decide if the fix folds into T-083's Phase 1b accessor migration (the preview's underlying lookup is one of the WOPC reader sites being switched onto the dual-read accessor) or stands alone as a CSS / iframe-config tweak.
Decision log¶
2026-06-21 β task opened (diagnosis pending)¶
- β
Attestation (Accounting (Diagnostics)): read
AGENTS.md(tipe5e90b3a); checked the board scope-not-UID (no existing task covers this β T-055 was a different WOPC bug about quantity/unit display, T-073 covers infra not the preview surface). - Source: Accounting (Diagnostics) Β· https://claude.ai/code/session_01G58Y71noihrYCDEDMexmea (retrofitted 2026-06-21 after the Source-line convention was added to AGENTS.md mid-session)
- What changed: opened T-084 to capture the owner's observation before it gets lost; surface + likely-relevant context documented so the eventual diagnosis is faster.
- Proposed by: the owner.
- Approved by: the owner β opening this follow-up was explicitly directed: "Proceed with T-083 while please create a new task for the transaction thumbnail issue I mentioned previously" (2026-06-21).
- Rationale: AGENTS.md's "Capture the WHY" requires the why be on record at whatever point it becomes known. Opening the task now with the owner's concern + the technical surface captures what's known. The diagnosis (the actual "what's weird") gets added in the next entry once the repro happens.
- Out of scope: any fix work. This task is in
todountil the bug is reproduced and a concrete fix scope can be written.
2026-06-21 β renumbered T-084 β T-086 (UID collision resolved)¶
- β
Attestation (Accounting (Diagnostics)): read
AGENTS.md; renumbering, not editing scope. - Source: Accounting (Diagnostics) Β· https://claude.ai/code/session_01G58Y71noihrYCDEDMexmea
- What changed: task file moved
T-084.mdβT-086.md; frontmatteruid: T-084βuid: T-086;related: [T-083]βrelated: [T-089](the sibling WOPC-restructure task on this branch was renumbered in the same commit). - Why: PR #777 (a fresh branch off nightly, opened while this branch was in draft) took the then-next-free T-084 for the Records expense display regressions, before this branch could merge. Renumbering this task to T-086 frees T-084 for that other PR; commit messages on this branch that still mention "T-084" are historical and stay as-is.
- Proposed by: Accounting (Diagnostics). Approved by: the owner β "proceed on both please" (2026-06-21).
2026-07-01 β reassigned to Accounting (Infrastructure) β diagnosed + fixed β done¶
- β
Attestation (Accounting (Infrastructure)): read
AGENTS.md; the owner routed this to me (relayed via EOP Local Assistance (fork), with the cause pre-pinned from code). Branch signal ismainπ‘π‘ (Vercel, manual) Β·nightlyπ΄ β committed tomainonly, no auto-deploy (Vercel deploys are manual). Mirrored totaskboard. - Source: Accounting (Infrastructure) Β· https://claude.ai/code/session_015P6KzVYsQCLgEmUjR9bMwM
- Diagnosis (confirmed in code):
WOPCHoverPreview(TransactionTitleWithLinks.tsx:307) iframed the full standalone preview PAGE (/accounting/payment-confirmation/{txId}/preview?standalone=1&embed=1) into the fixed 300pxDOCUMENT_PREVIEW_FRAME_HEIGHTbox. That route is a full app page with its own layout/margins, so squeezed into a thumbnail it renders awkwardly. Its siblings (ArchivePdfHoverPreviewfor receipts,WorkspaceInvoiceHoverPreview) instead iframe a raw PDF (β¦?redirect=pdf#toolbar=0&navpanes=0&scrollbar=0), which the browser's PDF viewer fits cleanly into the box. (Aside: the old iframe passed nosigningRequestId, so it rendered the unsigned template anyway β the preview page only composes the signature when that param is present, perpreview/client.tsx:176-181.) - Fix:
WOPCHoverPreviewnow iframes a raw PDF with the same chrome-hiding fragment as its siblings. It prefers the canonical WOPC-PDF resolver keyed by ref (/api/records/wopcs/pdf?ref=<ref>) β which serves the actual signed (or voided) Drive copy when one exists (fast + what "signed WOPC" implies; same source the Records download uses), and falls back to the by-transaction on-the-fly render (/api/accounting/transactions/{txId}/payment-confirmation-pdf,application/pdfinline) whenwopcRefNumberis absent (it's optional at this call site;transactionIdis always present). - Verification:
npx tsc --noEmitclean. Visual confirmation needs the live app (can't render a browser in-sandbox) β the fix mirrors the already-working sibling pattern exactly and both endpoints serveContent-Disposition: inlinePDFs, so confidence is high; owner to eyeball on the next deploy. - Commit(s):
0dd3098aonmain. - Blast radius: one component (
WOPCHoverPreviewinTransactionTitleWithLinks.tsx) β the WOPC hover thumbnail on the Bank Transactions table + detail drawer. No data, no schema, no other surface. Deploy is manual (Vercel) β pushed tomain, not auto-deployed. - Optional follow-up (flagged, not done): if the owner wants the by-transaction fallback to also
show the signed copy (not just the unsigned render),
payment-confirmation-pdf.tswould need to resolve the signed Drive bytes (likewopcs/pdf) rather thanrenderWopcPdfBuffer. Rare path (only when no ref is available), so left out to keep the fix scoped.
2026-07-01 β re-verified against live main (no overlap) + orphaned-endpoint flag¶
- β
Attestation (Accounting (Infrastructure)): read
AGENTS.md; the owner asked me to re-check this against the current repo, since multiple agents committed tomainthis session and T-086 was originally Accounting (Diagnostics)'s task. Branch signalmainπ‘π‘ (Vercel, manual) Β·nightlyπ΄. Mirrored totaskboard. - Source (edit): Accounting (Infrastructure) Β· https://claude.ai/code/session_015P6KzVYsQCLgEmUjR9bMwM
- No overlap β verified.
0dd3098ais the sole change toWOPCHoverPreview; no parallel agent touched it (git log onTransactionTitleWithLinks.tsxshows only my commit, prior touch was T-010 routing, unrelated). The fix is live onmainand intact. - Related-but-separate finding (worth a cleanup, not blocking): there is an orphaned endpoint
pages/api/accounting/transactions/[id]/wopc-thumbnail.tsβ a React-SSR HTML render of the WOPC that nothing references (repo-wide grep forwopc-thumbnailfinds no caller).WOPCHoverPreviewnever used it (it iframed the full preview page before this fix, and the raw PDF after). Note the irony: commitf913bd60(T-073 #2) bumped that endpoint's cache 60sβ600s "to avoid re-rendering on every preview hover" β but it's a dead path, so that optimisation is moot. Suggest whoever owns the WOPC cleanup either wire it up or delete it; left untouched here (out of T-086's scope, and not mine to delete unprompted). - The other
β¦/preview?standalone=1reference atTransactionTitleWithLinks.tsx:~595is the "open full WOPC in a popup window" button (900Γ700), NOT the thumbnail β intentionally the full page there (a real full-window view), so it correctly stays as-is.
Commit index¶
0dd3098a2026-07-01 β fix(T-086): WOPC hover thumbnail β iframe raw PDF, not the full preview page