Record interface contract audit finding

This commit is contained in:
2026-11-02 01:44:55 +00:00
parent b345bc0ec4
commit 5e6db4de76

View File

@@ -0,0 +1,51 @@
# API and interface contract audit
Reviewed baseline: `b345bc0` on `main`. The review compared the public Go
facades, CLI and profile behavior, and internal Git, process, validation,
build, and forge interfaces with their documented contracts and callers.
The existing [correctness](01-correctness.md), [concurrency](04-concurrency.md),
[resource](05-resources.md), [error-handling](06-error-handling.md), and
[security](07-security.md) audits already record related contract violations;
they remain pending and are not repeated here.
The compiled public API and dependency-boundary check passed. The finding
below was reproduced through the public API in an isolated temporary Git
repository with a controlled Go-command wrapper. No production code or
repository tests were modified.
## A partial build result can contain an artifact without its promised digest
**Relevant interfaces and code:** [BuildArtifact and BuildResult](../../../build.go),
[BuildResolved and hashArtifact](../../../internal/build/build.go), and the
build failure presentation in [the CLI](../../../cmd/releasekit/main.go).
`BuildArtifact.SHA256` is documented as the lowercase digest of the complete
file, and `BuildResult.Artifacts` describes completed outputs, including
partial success. After a compiler reports success, `BuildResolved` appends the
artifact to its result before opening and hashing the file. If opening or
reading that output fails, it returns the partial result with that artifact's
`SHA256` still empty. The public conversion forwards the entry unchanged; the
CLI also prints it among the built outputs without a digest.
This can occur if the generated file becomes unavailable or unreadable before
or during hashing, or if the filesystem reports a read failure. A caller
examining partial results cannot treat every returned artifact as carrying the
documented digest, and an unavailable path may be presented as an output. The
operation does return an error and does not claim a successful complete build;
this finding concerns the contents of its partial result.
**Evidence:** A temporary clean module and a wrapper around the real Go
command simulated a file disappearing after a successful compilation. The public
`Build` call returned an error and one artifact with `SHA256` equal to the
empty string. This controlled probe exercised the failure boundary, not a real
filesystem fault.
**Potential approaches:** Decide how callers should learn about a compiled
output whose digest could not be obtained. One option is appending an artifact
to the completed list only after hashing succeeds, while preserving earlier
completed artifacts and explaining the affected path in the error. If
reporting the unverified output is required for recovery, represent that state
explicitly and document the corresponding partial-result contract. Preserve
the failure cause and existing partial outputs; do not silently claim a digest
or delete caller-owned output. A focused regression can inject a post-build
read failure and verify the public result and CLI presentation.