fix(authors): author photo URL fetch logs correct author_id (bookshelf-0u50.2) #1386
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "bd-bookshelf-0u50.2"
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?
Fixes a minor observability bug from PR #1350 round-2 review:
wirePhotoUpload'sfetchURLclosure hardcoded0as the ID argument to the sharedcover.DownloadCoverProductiondownloader, so structured logs for author photoURL fetches (e.g.
POST /authors/{id}/photowith a{"url":...}body) showedbook_id=0instead of the author being updated.fetchURL's signature is nowfunc(context.Context, int64, string) ([]byte, error)and the author ID is threaded through
PhotoUploadHandler->readPhotoFromURL-> the download closure, so the shared downloader's
book_idlog key now carriesthe correct author ID for this call path.
Test plan
PhotoUploadHandler > URL variant > calls fetchURL with the author ID (not 0) for log attributionininternal/authors/manage_handler_test.go.go test ./internal/authors/...— passmake coverage— 100% gate holdsgolangci-lint run ./internal/authors/...— 0 issuesDocs: N/A because internal observability fix, no user-facing surface.
Closes bead bookshelf-0u50.2 on merge.
[BLOCKER] none
[MAJOR] none
[MINOR] none
Reviewed the diff only (internal/authors/wire.go, manage_handler.go, manage_handler_test.go). This threads the already-validated
authorID(parsed viastrconv.ParseInt(r.PathValue("id"))and used earlier in the same handler for the ownership/lock check) through thefetchURLclosure so it reachescover.DownloadCoverProductionas the log-attribution ID instead of a hardcoded0.Checked:
cover.DownloadCoverProduction(internal/cover/download.go) — safeTransport/safeCheckRedirect, scheme allowlist, size cap, content-type + magic-byte validation — is untouched by this diff. Only the ID argument value changes; the guard chain is identical.getAuthor/PhotoLockedauthorization check before reachingreadPhotoFromURL. No new authz implication — it is a log field only, per the code comment.int64, not an attacker-controlled string — no injection surface.req.URLunchanged), and no new log statement was added in the diff.Proportionate, low-risk change. No findings.
REVIEW VERDICT: 0 blocker, 0 major, 0 minor
Code Review: bookshelf-0u50.2 (PR #1386)
[MAJOR] internal/authors/wire.go:107-111 — log field is still literally
book_idfor an author-photo fetchcover.DownloadCoverProduction's downloader (internal/cover/download.go) hardcodes the slog key"book_id"(and the wrapped error textbook_id=%d) for its second int64 parameter, regardless of caller. This PR threadsauthorIDinto that param instead of a hardcoded0, which is a real improvement (no morebook_id=0for every author photo fetch), but the resulting log/error output will now read e.g.book_id=7when author 7's photo fetch fails — still a mislabeled field, just non-zero. Anyone triaging logs/dashboards bybook_idwill now see spurious-looking book IDs that are actually author IDs, risking false correlation with real book-download failures. The PR's own doc comment at wire.go:105-108 acknowledges this ("dl's second arg is logged under the keybook_id... but here we thread the authorID through") — so it's a known, not hidden, tradeoff, but it only half-closes the observability bug the bead describes (book_id=0 for every fetch → fixed to book_id=, still the wrong key). Suggested fix (small, in-scope): bind an author-context logger before constructingdl, e.g.dl := cover.DownloadCoverProduction(30*time.Second, d.Logger.With("entity", "author")), so log lines carry both the (still misleadingly-named)book_idvalue and anentity=authordisambiguator — or file a fast follow-up bead to make the shared downloader take a genericentityKind/entityIDpair instead of a hardcodedbook_idname. Note the same shared downloader is also reused unmodified a few lines below inwireAudnexus'sdownloadImagefor Audnexus author-photo fetches (pre-existing, not introduced by this diff, but the identical defect — worth folding into the same follow-up).[MINOR] internal/authors/manage_handler_test.go:426,447-450,551 —
fetchURLCalledis a misleading name for anint64The variable stores the
authorIDargument the fakefetchURLclosure was invoked with, not a boolean "was it called" flag; the...Calledsuffix reads as a call-count/bool convention. SuggestfetchURLAuthorID(orcapturedAuthorID) to match what it actually holds. Pure readability, no behavioral impact.Everything else checks out:
authorIDis correctly threaded fromreadPhotoFromURLall the way throughfetchURL/wirePhotoUpload/cover.DownloadCoverProduction's existingbookIDparameter, with no behavior change to the actual download (same timeout, same SSRF guard, same transport); the curried-functional-argument convention is preserved (no interfaces introduced); the test file stays black-box (package authors_test); the newItblock asserts exactly one thing (fetchURLCalled == 1) per the one-Expect-per-It rule; and no coverage exclusion was added.REVIEW VERDICT: 0 blocker, 1 major, 1 minor
52609be33c3338c7f902Security re-review of PR #1386 (bookshelf-0u50.2) — fix that parameterized the SSRF-guarded cover downloader's log label (entityKey/entityID).
Verified via
git diff origin/main...origin/bd-bookshelf-0u50.2:internal/cover/download.go(safeTransport/safeDialContext private-IP block, safeCheckRedirect bounded redirects, scheme allowlist, LimitReader body-size cap, Content-Type allowlist, magic-byte validation) is byte-for-byte unchanged in control flow. Every diff hunk inside the returned closure only swaps the hardcoded"book_id"slog key/error label for theentityKey/entityIDparams — no conditional, ordering, or validation logic changed.entityKeyis always a hardcoded string literal at every call site ("book_id"in app.go, build_extended_deps.go, build_llm_deps.go, bookdrop/wire.go, cover/wire.go, cover/download_test.go;"author_id"in authors/wire.go) — never derived from request/user input. No log-injection or format-string risk.entityID(formerlybookID) isint64everywhere.internal/authors/manage_handler.go'sreadPhotoFromURLnow threads the realauthorIDintofetchURLinstead of a hardcoded0— improves log attribution only, does not touch the URL being fetched or any validation step.logURL(rawURL)(query/fragment-stripped) is still called at every log site — not dropped by the refactor.No blockers, majors, or minors found — this is a pure logging-label parameterization; the SSRF guard chain is intact.
REVIEW VERDICT: 0 blocker, 0 major, 0 minor
Re-review of the in-PR fix for the earlier code-review MAJOR (hardcoded "book_id" log key in the shared cover downloader), PR #1386 (bookshelf-0u50.2).
Verified against the current diff (origin/main...origin/bd-bookshelf-0u50.2):
No blockers/majors/minors found. The original MAJOR is fully resolved.
REVIEW VERDICT: 0 blocker, 0 major, 0 minor
3338c7f902b9175b7fbd