Discovered while reviewing PR #673 (#607). Pre-existing — landed in #434 (2026-06-30), not introduced by #673.
Symptom
PDF attachment screening fails for all `application/pdf` inputs. Every PDF is reported as `PDF "" could not be processed. It may be corrupt or use unsupported features.` — indistinguishable from a genuinely corrupt file, so the failure is silent.
Root cause
`cdk/src/types/pdf-parse.d.ts` is an ambient `declare module 'pdf-parse'` describing the v1 API:
```ts
function pdfParse(data: Buffer, options?: { max?: number }): Promise;
export = pdfParse;
```
The installed package is `pdf-parse@2.4.5`, which exports no callable default:
```
$ node -e "const m=require('pdf-parse'); console.log(Object.keys(m)); console.log(typeof m.default)"
[ 'AbortException', ..., 'PDFParse', 'VerbosityLevel', 'getException' ]
undefined
```
The ambient declaration overrides v2's real bundled types (`dist/pdf-parse/cjs/index.d.cts`), so `tsc` stays green against a shape that no longer exists. At runtime, in `cdk/src/handlers/shared/attachment-screening.ts`:
- `pdfParseFn = (mod as any).default ?? mod` resolves to the module namespace object (no default export).
- Calling `pdfParseFn(content, { max })` throws `TypeError: pdfParseFn is not a function`, which is caught and rewrapped as the generic "could not be processed" error.
The test at `cdk/test/handlers/shared/attachment-screening.test.ts:365` uses a `{ virtual: true }` mock supplying `{ __esModule: true, default: jest.fn() }` — a v1 shape that no longer exists — so the suite cannot catch this.
Fix
- Delete `cdk/src/types/pdf-parse.d.ts` and let v2's own bundled types apply.
- Rewrite the call site to the v2 API: `new PDFParse({ data: content }).getText()` returning a `TextResult`.
- Replace the virtual mock with one reflecting the real v2 module (a `PDFParse` class with a `getText()` method), and add a test that exercises a real (small) PDF end-to-end so a future API mismatch fails loudly.
Discovered while reviewing PR #673 (#607). Pre-existing — landed in #434 (2026-06-30), not introduced by #673.
Symptom
PDF attachment screening fails for all `application/pdf` inputs. Every PDF is reported as `PDF "" could not be processed. It may be corrupt or use unsupported features.` — indistinguishable from a genuinely corrupt file, so the failure is silent.
Root cause
`cdk/src/types/pdf-parse.d.ts` is an ambient `declare module 'pdf-parse'` describing the v1 API:
```ts
function pdfParse(data: Buffer, options?: { max?: number }): Promise;
export = pdfParse;
```
The installed package is `pdf-parse@2.4.5`, which exports no callable default:
```
$ node -e "const m=require('pdf-parse'); console.log(Object.keys(m)); console.log(typeof m.default)"
[ 'AbortException', ..., 'PDFParse', 'VerbosityLevel', 'getException' ]
undefined
```
The ambient declaration overrides v2's real bundled types (`dist/pdf-parse/cjs/index.d.cts`), so `tsc` stays green against a shape that no longer exists. At runtime, in `cdk/src/handlers/shared/attachment-screening.ts`:
The test at `cdk/test/handlers/shared/attachment-screening.test.ts:365` uses a `{ virtual: true }` mock supplying `{ __esModule: true, default: jest.fn() }` — a v1 shape that no longer exists — so the suite cannot catch this.
Fix