Suppress the gosec and revive findings with no fix (closes #61)
Some checks failed
check / check (pull_request) Failing after 59s
Some checks failed
check / check (pull_request) Failing after 59s
Seven findings remain that cannot be fixed without either lying about the code or making a repo-wide naming decision, so each carries a per-site //nolint directive with its justification. gosec G115 (internal/log, internal/ui): term.IsTerminal takes an int and os.File.Fd() returns a uintptr, so the conversion is forced by the API. A file descriptor always fits in an int on every platform Go supports, and a closed file yields -1, which IsTerminal reports as not a terminal. gosec G703 (internal/vaultik/verify.go): the removed path comes from os.CreateTemp a few lines above and never from user input. G703's taint analysis treats every path derived from an *os.File as tainted, so there is no code shape that clears it. revive var-naming (internal/log, internal/crypto, internal/types): fixing these means renaming packages across the whole codebase, which is the repo owner's call, not a lint fix. Neither stdlib log nor stdlib crypto is imported anywhere in the repo, so nothing is actually shadowed today. The rename decision is tracked in issue #76. revive reports a package-name failure only once per package directory, on whichever file it happens to lint first, so every file of the affected packages carries the directive and lists nolintlint alongside revive so the ones that lose the race are not reported as unused. With this, make check exits 0 under the canonical .golangci.yml (sha256 021cc83f4e6fc7c31b95b34b846723dfcf20b66b7baeea1dc40406e643346bcb, unmodified), which also unblocks issue #59. TODO.md: record this work, correct the earlier entry that claimed make check was green when lint was still red, and move the next step on to the stale-branch triage.
This commit is contained in:
23
TODO.md
23
TODO.md
@@ -14,16 +14,29 @@ pre-1.0
|
|||||||
|
|
||||||
# Next Step
|
# Next Step
|
||||||
|
|
||||||
Reconcile the uncommitted ARCHITECTURE.md edits on main: finish and
|
Triage the stale remote branches (issue #71): for each, merge the work
|
||||||
commit, or revert.
|
or delete the branch.
|
||||||
|
|
||||||
# Completed Steps
|
# Completed Steps
|
||||||
|
|
||||||
|
- 2026-08-09: Finished the lint remediation under the canonical
|
||||||
|
`.golangci.yml` (issue #61, which also unblocks issue #59). Fixed the
|
||||||
|
last 80 findings behavior-preservingly — `wsl_v5` 60, `sqlclosecheck`
|
||||||
|
10, `gosec` 4, `prealloc` 3, `revive` 3 — so `make check` now exits 0
|
||||||
|
on `main`. The `sqlclosecheck` sites now close `sql.Rows` in a
|
||||||
|
deferred closure instead of via the `CloseRows` helper, which the
|
||||||
|
linter could not see through; the four `gosec` and three `revive`
|
||||||
|
findings carry per-site `//nolint` directives with justifications, and
|
||||||
|
the package-rename question behind the `revive` ones is tracked in
|
||||||
|
issue #76.
|
||||||
- 2026-08-07: Updated golangci-lint to v2.12.2 everywhere it is pinned
|
- 2026-08-07: Updated golangci-lint to v2.12.2 everywhere it is pinned
|
||||||
(`Dockerfile` lint stage, `Makefile` deps target), replaced
|
(`Dockerfile` lint stage, `Makefile` deps target), replaced
|
||||||
`.golangci.yml` with the canonical config (v2 schema, `default: all`),
|
`.golangci.yml` with the canonical config (v2 schema, `default: all`),
|
||||||
and remediated all lint findings it surfaced (issue #61):
|
and remediated the bulk of the lint findings it surfaced (issue #61):
|
||||||
behavior-preserving fixes across every package, `make check` green.
|
behavior-preserving fixes across every package, 2,990 findings down to
|
||||||
|
80. `make test` and `make fmt-check` were green at that point but
|
||||||
|
`make lint` was still red; the commit message claiming `make check`
|
||||||
|
was green was wrong.
|
||||||
- 2026-08-07: Added the standard `.golangci.yml` and `.editorconfig`
|
- 2026-08-07: Added the standard `.golangci.yml` and `.editorconfig`
|
||||||
(issue #59); lint findings under the new config are tracked in issue
|
(issue #59); lint findings under the new config are tracked in issue
|
||||||
#61. `script/bootstrap` now installs sqlite3 (needed by tests).
|
#61. `script/bootstrap` now installs sqlite3 (needed by tests).
|
||||||
@@ -49,6 +62,4 @@ commit, or revert.
|
|||||||
|
|
||||||
# Future Steps
|
# Future Steps
|
||||||
|
|
||||||
- Review stale local branches (add-godoc-to-cli-package,
|
|
||||||
feature/pluggable-storage-backend) and merge or delete them.
|
|
||||||
- Define remaining scope for a first tagged release and cut v0.1.0.
|
- Define remaining scope for a first tagged release and cut v0.1.0.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Package crypto provides thread-safe age encryption and decryption
|
// Package crypto provides thread-safe age encryption and decryption
|
||||||
// helpers used to protect blob and metadata content.
|
// helpers used to protect blob and metadata content.
|
||||||
package crypto
|
package crypto //nolint:revive,nolintlint // stdlib crypto unused; see #76
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Package log provides the application-wide structured logger: slog
|
// Package log provides the application-wide structured logger: slog
|
||||||
// with a colorized TTY handler on terminals and JSON output otherwise.
|
// with a colorized TTY handler on terminals and JSON output otherwise.
|
||||||
package log
|
package log //nolint:revive,nolintlint // stdlib log unused here; see #76
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -69,8 +69,10 @@ func Initialize(cfg Config) {
|
|||||||
Level: level,
|
Level: level,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if stdout is a TTY
|
// Check if stdout is a TTY. term.IsTerminal takes an int, and a file
|
||||||
if term.IsTerminal(int(os.Stdout.Fd())) {
|
// descriptor always fits in one on every platform Go supports; a
|
||||||
|
// closed file yields -1, which IsTerminal reports as not a terminal.
|
||||||
|
if term.IsTerminal(int(os.Stdout.Fd())) { //nolint:gosec // G115: fd fits in int
|
||||||
// Use colorized TTY handler
|
// Use colorized TTY handler
|
||||||
logger = slog.New(NewTTYHandler(os.Stdout, opts))
|
logger = slog.New(NewTTYHandler(os.Stdout, opts))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package log
|
package log //nolint:revive,nolintlint // stdlib log unused here; see #76
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go.uber.org/fx"
|
"go.uber.org/fx"
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package log
|
package log //nolint:revive,nolintlint // stdlib log unused here; see #76
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// vaultik codebase. Using distinct types for IDs, hashes, paths, and
|
// vaultik codebase. Using distinct types for IDs, hashes, paths, and
|
||||||
// credentials prevents accidental mixing of semantically different values
|
// credentials prevents accidental mixing of semantically different values
|
||||||
// that happen to share the same underlying type.
|
// that happen to share the same underlying type.
|
||||||
package types
|
package types //nolint:revive,nolintlint // rename decision tracked in #76
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"database/sql/driver"
|
"database/sql/driver"
|
||||||
|
|||||||
@@ -113,7 +113,10 @@ func shouldColor(w io.Writer) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return term.IsTerminal(int(f.Fd()))
|
// term.IsTerminal takes an int, and a file descriptor always fits in
|
||||||
|
// one on every platform Go supports; a closed file yields -1, which
|
||||||
|
// IsTerminal reports as not a terminal.
|
||||||
|
return term.IsTerminal(int(f.Fd())) //nolint:gosec // G115: fd fits in int
|
||||||
}
|
}
|
||||||
|
|
||||||
// ───────────────────────── message methods ─────────────────────────
|
// ───────────────────────── message methods ─────────────────────────
|
||||||
|
|||||||
@@ -306,6 +306,10 @@ func (v *Vaultik) decryptAndLoadDatabase(reader io.ReadCloser) (*tempDB, error)
|
|||||||
return nil, fmt.Errorf("failed to create temp file: %w", err)
|
return nil, fmt.Errorf("failed to create temp file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tempPath is generated by os.CreateTemp above and never derives from
|
||||||
|
// user input, but gosec's G703 taint analysis treats every path that
|
||||||
|
// originates from an *os.File as tainted, so the os.Remove calls
|
||||||
|
// below carry per-site nolint directives.
|
||||||
tempPath := tempFile.Name()
|
tempPath := tempFile.Name()
|
||||||
|
|
||||||
// Stream decompress directly to file
|
// Stream decompress directly to file
|
||||||
@@ -314,7 +318,7 @@ func (v *Vaultik) decryptAndLoadDatabase(reader io.ReadCloser) (*tempDB, error)
|
|||||||
written, err := io.Copy(tempFile, decompressor)
|
written, err := io.Copy(tempFile, decompressor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = tempFile.Close()
|
_ = tempFile.Close()
|
||||||
_ = os.Remove(tempPath)
|
_ = os.Remove(tempPath) //nolint:gosec // G703: path from os.CreateTemp
|
||||||
|
|
||||||
return nil, fmt.Errorf("failed to decompress database: %w", err)
|
return nil, fmt.Errorf("failed to decompress database: %w", err)
|
||||||
}
|
}
|
||||||
@@ -326,7 +330,7 @@ func (v *Vaultik) decryptAndLoadDatabase(reader io.ReadCloser) (*tempDB, error)
|
|||||||
// Open the database
|
// Open the database
|
||||||
db, err := sql.Open("sqlite", tempPath)
|
db, err := sql.Open("sqlite", tempPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = os.Remove(tempPath)
|
_ = os.Remove(tempPath) //nolint:gosec // G703: path from os.CreateTemp
|
||||||
|
|
||||||
return nil, fmt.Errorf("failed to open database: %w", err)
|
return nil, fmt.Errorf("failed to open database: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user