From 5e6db4de76359f8d368e1f6f4286f5eea0b1bf00 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Mon, 2 Nov 2026 01:44:55 +0000 Subject: [PATCH] Record interface contract audit finding --- docs/roadmap/audit/09-interfaces.md | 51 +++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 docs/roadmap/audit/09-interfaces.md diff --git a/docs/roadmap/audit/09-interfaces.md b/docs/roadmap/audit/09-interfaces.md new file mode 100644 index 0000000..4363ccc --- /dev/null +++ b/docs/roadmap/audit/09-interfaces.md @@ -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.