go-yfinance v1.6.1 Maintenance Progress
Last Updated: 2026-08-27
Overview
This document tracks the Go-specific v1.6.1 maintenance release built on the
Python yfinance v1.6.0 parity baseline. It packages the authentication
hardening already merged through go-yfinance PR #13 and adapts the valid parts
of contributor PR #11 onto the current main before Python yfinance v1.7.0
parity work begins.
v1.6.1 does not claim Python yfinance v1.6.1 parity. Its purpose is to release bounded safety and correctness fixes without mixing them into the larger v1.7.0 upstream-parity change set.
Branch Structure
After v1.6.1 is merged, verified on main, and tagged, the v1.7.0 parity
branch must start from that final main commit.
Source And Attribution
- Source proposal: go-yfinance PR #11,
refactor: add data immutability, implement timezone caching, and enhance ..., byshubhbham. - Current baseline:
mainat164f6cb, including PR #13 authentication hardening after the v1.6.0 tag. - Preserve contributor attribution in the implementation commits and release notes. Do not merge PR #11 directly because its branch predates the current authentication implementation and its review findings require rework.
Scope Decision
| Area | Disposition | Reason |
|---|---|---|
| Protobuf bounds | Reimplement | Compare lengths as uint64 before conversion and reject malformed varints without panicking on 32-bit or 64-bit targets. |
| WebSocket lifecycle | Reimplement | Make normal close idempotent and non-erroring; cancel reconnects and stop listener/heartbeat goroutines without channel-close races. |
| Holders/news cache immutability | Reimplement | Return independent values, including nested pointers and slices such as Thumbnail.Resolutions. |
| Multiple cookies | Reassess and implement if representable | Verify how CycleTLS represents repeated Set-Cookie headers; avoid newline-only parsing and Expires comma corruption. Integrate with current PR #13 auth behavior. |
| Timezone location cache | Deferred | This is an unmeasured optimization with global lifetime, growth, and test-isolation questions rather than a correctness fix. Track separately after benchmarking. |
Implementation Plan
Phase 0: Baseline and test design
- [x] Confirm the exact PR #11 diff and current-main overlap for every target file.
- [x] Record current behavior with focused regression tests before changing implementation where practical.
- [x] Keep protobuf, WebSocket, cache, and cookie work independently testable and independently committable.
Phase 1: Protobuf decoder hardening
- [x] Reject overlong and overflowing varints.
- [x] In
readStringand length-delimitedskipField, compare the decodeduint64length with the non-negative remaining byte count before converting toint. - [x] Add truncated, maximum-length, overflow, unknown-field, and no-panic regression tests; include architecture-sensitive cases where feasible.
- [x] Commit independently with contributor attribution (
5055a5b).
Phase 2: WebSocket lifecycle
- [x] Define explicit states and contracts for connect, listen, reconnect, normal close, repeated close, and reuse after close.
- [x] Ensure
Closeduring reconnect delay prevents a later connection. - [x] Ensure normal close makes
Listenreturnnilwithout invoking the error handler. - [x] Stop heartbeat and listener goroutines exactly once and avoid double channel close, blocked reads, and concurrent writes.
- [x] Add deterministic local WebSocket-server tests, including race-focused close/reconnect cases.
- [x] Commit independently with contributor attribution (
31d72c4).
Phase 3: Cache immutability
- [x] Add clone helpers or equivalent focused copying for holders and news return values.
- [x] Copy all mutable nested state, including insider date pointers,
NewsThumbnail,Thumbnail.Resolutions, andRelatedTickerswhere present. - [x] Test both first-fetch and cache-hit paths by mutating returned values and proving subsequent results are unchanged.
- [x] Run focused race tests for the affected package and caller mutation.
- [x] Commit independently with contributor attribution (
7f9ae52).
Phase 4: Cookie representation and extraction
- [x] Inspect the pinned CycleTLS response-header implementation and create fixtures for its actual repeated-header representation.
- [x] Determine whether
Response.Headers map[string]stringpreserves allSet-Cookievalues. If it cannot, fix the response boundary rather than guessing inextractCookies. - [x] Parse multiple cookies without splitting an
Expiresattribute at its comma, preserve distinct cookie names, and retain current error classification and sanitization. - [x] Add tests for multiple cookies, mixed header casing, cookie attributes, replacement, and auth strategy fallback.
- [x] Commit independently with contributor attribution (
42032e0). If the transport representation cannot be fixed safely within v1.6.1, document and defer this item rather than shipping a partial parser.
Phase 5: Cross-verification and release documentation
- [x] Run an independent Claude Code and Codex review when Claude availability
is confirmed. Each verifier should derive findings from the current code and
PR intent without seeing the other's report; reconcile findings against code
and tests.
Result: Claude independently reported eight actionable findings. Seven
implementation findings were accepted and fixed in
dec679e: bounded WebSocket writes without holding the lifecycle mutex, per-listener heartbeat cleanup, positive heartbeat-interval validation, known-field protobuf wire validation, count/tab-aware news caching, cookie collection at every CSRF stage, and deletion of expired empty-value cookies. Its CycleTLS delimiter fixture observation was also applied to the test. Focused race tests passed, and Claude's follow-up confirmed every accepted finding was resolved.
One follow-up suggestion was rejected: skipping a known protobuf field when
its wire type conflicts with the schema would turn malformed or
schema-incompatible input into a partial successful decode. The decoder
intentionally returns an explicit error for a known field with an invalid
wire type; unknown field numbers remain forward-compatible through
skipField.
- [x] Add docs/releases/RELEASE_NOTES_v1.6.1.md and state clearly that this is
a Go-specific maintenance release on the Python yfinance v1.6.0 baseline.
- [x] Update README/docs parity and release navigation only where required,
regenerate GoDoc/API docs, and keep README.md and docs/index.md synced.
- [x] Record deferred timezone caching and any deferred cookie limitation with
reasons.
Verification And Release Gates
Before merging to main or tagging, follow
docs/development/release-readiness-checklist.md in full:
- [x]
GOCACHE=/tmp/go-build-cache go test ./... - [x]
GOCACHE=/tmp/go-build-cache go vet ./... - [x]
GOLANGCI_LINT_CACHE=/tmp/golangci-lint-cache golangci-lint run ./... - [x]
make lint - [x]
GOCACHE=/tmp/go-build-cache go test -v -race -coverprofile=coverage.out ./... - [x]
GOMARKDOC=/tmp/gobin/gomarkdoc make docs - [x]
cp README.md docs/index.md - [x]
make docs-build - [x]
git diff --check - [x] Verify local commands still match
.github/workflows/test.ymland.github/workflows/docs.yml. - [x] Keep generated documentation and workflow corrections in explicit, separate commits.
- [x] Merge the verified branch to
main, confirm remote CI on the finalmaincommit, and only then create and publishv1.6.1.
Verification record
- Local toolchain: Go 1.27.0; the module and CI minimum remain Go 1.22.
go test ./...andgo vet ./...: passed, including live Yahoo integration tests when rerun outside the DNS-restricted sandbox.- Full race and coverage gate: passed for all packages, including live Yahoo integration tests.
- Focused
go test -race ./pkg/live,./pkg/ticker, and./pkg/client: passed. - Linux/386
pkg/livetest binary cross-compilation: passed, covering the architecture-sensitive protobuf conversion path. - golangci-lint v2.13.1 and
make lint: 0 issues. - API generation, README/docs sync, MkDocs build, and
git diff --check: passed. MkDocs emitted only its upstream MkDocs 2.0 advisory and the existing unrecognized relativeLICENSElink notice. - CI drift found and fixed separately in
556b559: both test jobs now use Go 1.22, matchinggo.modand the docs workflow. - Claude/Codex cross-verification findings were reconciled in
dec679e; the post-fix Claude review found no remaining accepted defect. - PR #15 merged to
mainas5478a4b. The merge commit's Tests workflow (test and lint jobs) and Generate Documentation & Deploy Site workflow both completed successfully. The docs workflow then committed its canonical generated API output as247a71e; that commit changes generated docs only.
Guardrails
- Do not merge or cherry-pick PR #11 wholesale.
- Do not include timezone caching in v1.6.1 without a separate measured design decision.
- Do not weaken the PR #13 authentication classification or sanitization.
- Do not treat a passing existing test suite as sufficient for the reviewed PR defects; each accepted behavior needs a regression test.
- Do not move or recreate an existing tag, and do not tag from the feature branch.
- Keep unrelated worktree changes out of maintenance and release commits.