Skip to content

feat(builder): enforce BuildRequest.output_directory is absolute (#333) - #335

Merged
antoinetoussaint-byte merged 2 commits into
mainfrom
fix/enforce-buildrequest-output-directory-absolute
Aug 21, 2026
Merged

feat(builder): enforce BuildRequest.output_directory is absolute (#333)#335
antoinetoussaint-byte merged 2 commits into
mainfrom
fix/enforce-buildrequest-output-directory-absolute

Conversation

@antoinetoussaint-byte

@antoinetoussaint-byteantoinetoussaint-byte commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Closes#333.

Summary

  • The proto documents BuildRequest.output_directory as "an absolute destination owned by the caller", but nothing asserted absoluteness. A relative path would resolve against the agent's working directory while the caller expects an absolute location it owns — the recipe handshake would then break silently, with no error.
  • Enforcement is wired into BuilderWrapper.DockerBuildRequest — the universal chokepoint every agent runner routes a BuildRequest through (golang + rust), which already validates the build-context kind. So the invariant is guarded on every agent build, not left to a caller that might never call it.
  • The guard is BuildRequest-specific, so it rejects only contract-violating callers (relative, non-empty) and never a valid one. Empty stays valid (legacy in-agent build). This is why the check lives here and not in BuildDockerBuildPlan: that helper takes a bare destination and its WalkDir inventory is relative-safe, so a guard there would reject valid callers of a generic function rather than catch the violation at the request boundary.
  • ValidateBuildRequestOutputDirectory is exported so the CLI can also resolve-and-validate before sending, but enforcement no longer depends on that.

Test plan

  • go test ./agents/services/ passes
  • TestValidateBuildRequestOutputDirectory covers nil (valid), empty (valid), absolute (valid), relative (rejected)
  • TestDockerBuildRequestEnforcesAbsoluteOutputDirectory proves the boundary rejects a relative destination and passes absolute + empty through
  • go vet ./agents/services/ and go build ./runners/... clean

🤖 Generated with Claude Code

Expose a shared guard that enforces the BuildRequest.output_directory
contract — when set, the destination must be absolute; empty selects the
legacy in-agent build. The guard lives next to the recipe contract in core
(where the proto is defined) so the CLI, which populates the field in a
separate repo, imports and calls it before sending a BuildRequest.
The invariant cannot be enforced in BuildDockerBuildPlan: its tree walk is
relative-safe, so an IsAbs guard there would reject valid callers rather
than catch the real failure at the point the field is set.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fe7p9irTPJPkQBcpRVYJzg
…dary (#333)
The prior change only exported ValidateBuildRequestOutputDirectory; nothing
in core called it, so merging enforced nothing and closing #333 would have
declared victory before any code path guarded the invariant. A relative
output_directory would still sail through: the agent resolves it against its
own working directory while the caller expects an absolute location it owns,
so the recipe handshake breaks silently with no error.
Wire the guard into BuilderWrapper.DockerBuildRequest — the universal
chokepoint every agent runner routes a BuildRequest through, which already
validates the build-context kind. It is BuildRequest-specific, so it rejects
only contract-violating callers (relative, non-empty), never a valid one;
this refutes the "wrong layer" objection that applies to the generic
BuildDockerBuildPlan tree walk. Enforcement is now real on every agent build.
Also pin the nil-request boundary case in the validator test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fe7p9irTPJPkQBcpRVYJzg
@antoinetoussaint-byte
antoinetoussaint-byte merged commit e35c878 into mainAug 21, 2026
1 check passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

builder: enforce BuildRequest.output_directory is absolute at the CLI boundary

1 participant

@antoinetoussaint-byte