feat(runnerhub): agent forge-call relay legs (RIG-2170) - #405
Open
rigel-mintaka wants to merge 2 commits into
Open
feat(runnerhub): agent forge-call relay legs (RIG-2170)#405rigel-mintaka wants to merge 2 commits into
rigel-mintaka wants to merge 2 commits into
Conversation
Add the Runner->Server relay for agent-initiated forge calls, the structural sibling of the board/lifecycle/comms relay legs. `Hub.RelayForgeCall` resolves the relayed session_id to its bound agent account server-side and delegates to a `ForgeCaller` under that resolved caller, passing the session id through — the Runner asserts no account. Guard order is fail-closed, identical to the sibling legs: no ForgeCaller wired -> CodeUnavailable (before session resolution); an unbound session -> CodeNotFound (never a stale account, never the bootstrap admin); a tool-level failure rides back in-band on the ForgeCallResult error arm so a single failed call never tears down the transport. `ForgeCaller` is defined here as the narrow seam the forge service (T4) implements; it is wired post-construction via `Hub.SetForgeCaller` (mirrors SetBoardCaller), breaking the hub<->service construction cycle. `Gateway.Forge` is the in-container agent's door: it maps the container to its one bound session and forwards RelayForgeCall, failing closed CodePermissionDenied before a session is bound (never a forward with an empty session id). The gateway threads a new `ForgeRelay` client through its Deps struct beside Lifecycle. Hub tests (mirroring relay_board_test): nil-caller Unavailable for bound and unbound sessions, unbound NotFound, resolved-account attribution delivered to a fake ForgeCaller, in-band error passthrough, call_id echo. Gateway tests (mirroring lifecycle_test): unbound/empty-session PermissionDenied, verbatim session-id forward, nil-result CodeInternal. Refs RIG-2237. Co-authored-by: Matt Wilkinson <matt@sealedsecurity.com>
|
Compass engineering docs preview: https://compass-server-rig-2237-forg.compass-eng-docs.pages.dev Deployed from |
…2237 review) Review M1: the production gateway construction (runner/host.go) omitted the new Forge dep while AgentGateway.Forge is a now-live route (Gateway.Forge shadows the embedded Unimplemented handler). An in-container agent calling Forge would hit a nil ForgeRelay and nil-panic (fail-to-500) instead of the fail-closed behaviour the design mandates. Wire Forge: h.link.client into the Deps literal, exactly as the sibling Lifecycle leg is wired (h.link.client already satisfies ForgeRelay via RunnerServiceClient.RelayForgeCall). Review M2: RelayForgeCall's success arm dereferenced the ForgeCaller's result without a nil check. The sibling board/lifecycle legs are immune to a (nil, nil) caller by construction (their internal executor always builds a fresh non-nil result); the forge leg calls the external ForgeCaller directly, so a nil result on the nil-error arm would nil-deref on the security-critical resolution edge. Guard it: a nil result is surfaced in-band as CodeInternal (errForgeNoResult) with the call_id echoed, never a panic. Review L1: add TestRelayForgeCallNilResultIsInternalErrorInBand pinning the M2 guard (a bound session, fake caller returning (nil, nil), asserts an in-band internal error with call_id round-trip rather than a panic). Refs RIG-2237. Co-authored-by: Matt Wilkinson <matt@sealedsecurity.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Add the Runner->Server relay for agent-initiated forge calls, the structural sibling of the board/lifecycle/comms relay legs.
Hub.RelayForgeCallresolves the relayed session_id to its bound agent account server-side and delegates to aForgeCallerunder that resolved caller, passing the session id through — the Runner asserts no account. Guard order is fail-closed, identical to the sibling legs: no ForgeCaller wired -> CodeUnavailable (before session resolution); an unbound session -> CodeNotFound (never a stale account, never the bootstrap admin); a tool-level failure rides back in-band on the ForgeCallResult error arm so a single failed call never tears down the transport.ForgeCalleris defined here as the narrow seam the forge service (T4) implements; it is wired post-construction viaHub.SetForgeCaller(mirrors SetBoardCaller), breaking the hub<->service construction cycle.Gateway.Forgeis the in-container agent's door: it maps the container to its one bound session and forwards RelayForgeCall, failing closed CodePermissionDenied before a session is bound (never a forward with an empty session id). The gateway threads a newForgeRelayclient through its Deps struct beside Lifecycle.Hub tests (mirroring relay_board_test): nil-caller Unavailable for bound and unbound sessions, unbound NotFound, resolved-account attribution delivered to a fake ForgeCaller, in-band error passthrough, call_id echo. Gateway tests (mirroring lifecycle_test): unbound/empty-session PermissionDenied, verbatim session-id forward, nil-result CodeInternal.
Refs RIG-2237.
Co-authored-by: Matt Wilkinson matt@sealedsecurity.com