fix(scan): address 6 review minors from PR #993 (bookshelf-h7yv) #1066
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "bd-bookshelf-h7yv"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Addresses the 6 actionable review minors deferred at PR #993 merge (2 security, 1 security-logging, 1 doc, 1 test-hygiene, 1 error-classification). CSS and JS test-rename minors were already on main.
BookID==0(race window ~13ms after 202), return{"status":"pending"}rather than skipping the ownership check and exposing{"status":"running"}to a user whose ownership hasn't been verified yet.r.ContentLength > 0instead of!= 0; an empty chunked body (ContentLength==-1) no longer hits json EOF → 400.partial.RawatDebuginstead ofInfoto avoid storing potentially copyrighted OCR-extracted book text in Seq on every extraction failure.maxRenderPages (8); the const is5.Expectcalls in the LLMScanWorkflow integrationItinto oneExpect(detail.Result, detailErr).getProviderCfgas real errors instead of mapping them toErrLLMDisabled(permanent sentinel);ExtractMetadataitself returnsErrLLMDisabledwhen config is unconfigured.Test plan
BookID==0→status:pendingandContentLength==-1→ 202make testgreen (3835 specs)make coveragegreen (100%)golangci-lintclean on changed packagesCloses bead bookshelf-h7yv on merge.
Security minors (metadata_llm_scan_handler.go): - Return {status:"pending"} when BookID==0 instead of skipping the ownership check and exposing {status:"running"} during the ~13ms race window after the 202 response. - Use r.ContentLength > 0 instead of != 0 so empty chunked bodies (ContentLength==-1) are treated as absent rather than triggering a json EOF 400. Security minor (llm_scan_workflow.go): - Log partial.Raw at Debug instead of Info on extraction errors to avoid storing potentially copyrighted book text in Seq on every failure (log-retention PII concern). Code review minors: - pdf_page_images.go: fix stale doc comment that said maxRenderPages (8); const is 5. - engine_integration_test.go: fold two separate Expect calls in the LLMScanWorkflow registration It into one Expect(result, err). - build_extended_deps.go: propagate transient DB errors from getProviderCfg instead of masking them as ErrLLMDisabled (permanent); ExtractMetadata itself returns ErrLLMDisabled when the resolved config is unconfigured. Tests added for the two handler behavior changes (BookID==0 path and ContentLength=-1 path). CSS minor (min-height token) and JS test rename were already on main. Closes bead bookshelf-h7yv on merge. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>CODE REVIEW: APPROVED
Reviewed diff
origin/main...origin/bd-bookshelf-h7yv. CI is the source of behavioral truth; tests were not re-run locally.Finding #1 —
metadata_llm_scan_handler.go:180— BookID==0 returns{status:"pending"}Logic split is correct: the old
if s.BookID != 0 && s.BookID != idlet BookID==0 fall through to the running-status path without ownership validation. The new pair:correctly short-circuits before any ownership assertion. The 200+
{"status":"pending"}response is consistent with the other status values (all 200). The user already passed the book-access check (checkBookAccess) before reaching this code, which limits exposure of the pending state to users with at least one valid book access.Test: inner
BeforeEachoverridesgetLLMScanResult→BookID: 0; outerJustBeforeEachexecutes the handler;Expect(result.Status, err).To(Equal("pending"))folds the nil-error and value checks per project convention. Black-box (package books_test), one Expect per It. CORRECT.Finding #2 —
metadata_llm_scan_handler.go:84—ContentLength > 0guard!= 0→> 0correctly prevents thejson.EOF400 on empty chunked bodies (ContentLength==-1, empty pipe). The original review offered> 0as an explicit option, and the implementer chose it. Note: a chunked request with ContentLength==-1 that carries actual JSON would also skip decode and silently use the default provider. In practice HTTP clients sending a JSON body set Content-Length explicitly, making this case theoretical. No security impact; behaviour degrades gracefully to default-provider rather than an error. CORRECT for the stated intent.Test: pipe body forces ContentLength==-1; writer closed immediately (empty); expects 202.
//nolint:errcheckonpw.Close()in test is acceptable (test context). Black-box, one Expect per It. CORRECT.Finding #3 —
llm_scan_workflow.go:185—wrapExtractErrlog level Info → Debugpartial.Raw(the model's raw OCR/text output) may contain copyright title-page text. Downgrading to Debug avoids retaining potentially copyrighted book content in Seq on every extraction failure. Comment in the diff is accurate. No correctness impact. CORRECT.Finding #4 —
pdf_page_images.go:67— doc comment(8)→(5)Actual constant:
const maxRenderPages = 5(line 23). Comment was stale at(8). Now matches the code. CORRECT.Finding #5 —
engine_integration_test.go— fold two ExpectsGomega multi-actual form: asserts
detailErr == nilANDdetail.Resultdoes not contain the substring. Follows project convention ("fold the no-error check into the value assertion"). CORRECT.Finding #6 —
build_extended_deps.go:1510— propagate real DB errorOld:
return metalllm.ExtractResult{}, metalllm.ErrLLMDisabled— misclassified a transient DB error as a permanent sentinel, causing the activity to fail immediately with no-retry.New:
return metalllm.ExtractResult{}, fmt.Errorf("read llm provider config: %w", err)— the real error propagates.isPermanentLLMErrdoes not match it (it checkserrors.Is(err, llm.ErrLLMDisabled)etc.), so the activity is correctly treated as transient and retried. The error message ("read llm provider config: connection refused") reachesErrMsgin the status response only if all retry attempts exhaust, and is exposed only to the authenticated job owner — acceptable in a self-hosted context. CORRECT.Skipped "already fixed on main" items: The bead completion comment states CSS and JS rename were already on
main. No items from the bead's 6-point description are missing from the diff — all 6 are present and addressed.REVIEW VERDICT: 0 blocker, 0 major, 0 minor
ecce5bc9b02c6ee60c5b