Repository navigation
feat: add an egress policy translator for embedded controllers - #3208
codyhartsook wants to merge 43 commits into
Conversation
a1875b6 to
f0fe942
Compare
c6089fd to
0a57ce8
Compare
EItanya
left a comment
There was a problem hiding this comment.
🤖 AI-assisted design feedback.
I like the idea of letting an embedded controller contribute credentials. Can we make this a shared policy translation step before rendering the harness configuration?
The part that feels coupled is that each harness needs to know about the binder. Codex and Claude check whether it exists to allow a missing key, then CompileCredentials returns both all bindings and a separate additions slice so each harness can patch its MCP configuration afterward. The placeholder string also ends up carrying the meaning “this model requires a gateway binding.” I think those are signs that authentication resolution needs to happen earlier.
What if the flow looked like this:
- Resolve model, MCP, and EgressPolicy inputs into a common egress draft, building on
egress.Access. - Apply a policy extension, then validate and normalize the result.
- Render client configuration from the resolved authentication and persist the resolved grant in the revision.
Conceptually, the extension could look like:
type PolicyTranslator interface {
Translate(agent types.NamespacedName, draft PolicyDraft) (PolicyDraft, error)
}The draft would retain the authentication requirements we need during compilation: required header/prefix, existing bindings, and whether explicit authentication prevents additions. Each integration would contribute those requirements where we already understand its behavior. The harness would then consume resolved authentication without needing to distinguish built-in credentials from extension contributions.
We can keep the current restrictions in the shared validation step: no new destinations, no replacement of existing bindings, preserve explicit authentication, and deterministic output. A more general policy interface doesn't need to permit arbitrary changes.
This needs to happen before client configuration is rendered because the gateway only replaces headers the client sends. Updating the final Substrate policy alone wouldn't supply the SDK placeholders or MCP headers. The resolved grant also needs to remain revision-pinned so retries and resume use the same policy.
I think the useful change here is making policy resolution a shared phase with explicit authentication requirements. Putting the current arguments into a Policy struct without changing that flow would leave most of the coupling in place.
f0fe942 to
5d6a8d1
Compare
500554b to
8d55df0
Compare
d78f5b8 to
39b2958
Compare
d94a1c6 to
2957324
Compare
15bee2c to
65d7d59
Compare
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Use a revision-keyed workqueue to serialize publication and replay changes received during an in-flight write. Keep startup actor recovery separate, and require a persisted policy before the store promotes a revision. Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Recover offline Agent deletions through preparation instead of a finalizer. Hash compiled runtime inputs while retaining full source provenance, and keep source actor queries inline in the store. Allow credentials on exact HTTP origins and exercise delivery with a plain HTTP origin, removing shared gateway configuration changes from the e2e fixture. Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Resolve policies independently and retain still-requested last-good grants when additions conflict. Filter only incompatible grants for older revisions, expose EgressPoliciesApplied on Agents and SandboxTemplates, and bound deleted-Agent recovery to retained instances. Signed-off-by: Eitan Yarmush <eitan.yarmush@solo.io>
Signed-off-by: Cody Hartsook <cody.hartsook@solo.io>
Signed-off-by: Cody Hartsook <cody.hartsook@solo.io>
Signed-off-by: Cody Hartsook <cody.hartsook@solo.io>
Signed-off-by: Cody Hartsook <cody.hartsook@solo.io>
Signed-off-by: Cody Hartsook <cody.hartsook@solo.io>
Signed-off-by: Cody Hartsook <cody.hartsook@solo.io>
Signed-off-by: Cody Hartsook <cody.hartsook@solo.io>
Signed-off-by: Cody Hartsook <cody.hartsook@solo.io>
…ition Signed-off-by: Cody Hartsook <cody.hartsook@solo.io>
Signed-off-by: Cody Hartsook <cody.hartsook@solo.io>
eeafd54 to
f0455d6
Compare
c8fec1c to
61288e3
Compare
Adds optional
app.Options.EgressPolicyTranslatorso embedded controllers can bind external credential references to an Agent's existing outbound destinations. Based on #3177.The shared compiler builds a
PolicyDraftfrom model and MCP inputs, applies the extension, and validates the result before rendering client configuration. Harnesses declare model requirements and consume resolved authentication. The extension can add bindings, but cannot change destinations or requirements, replace existing bindings, or override explicit authentication. Resolved bindings are pinned in the revision and take precedence over conflicting EgressPolicy grants, which admission holds.Client authentication uses the final model and MCP Secret bindings plus the extension's:
bedrock-runtimedestination, fixing bearer bindings that previously failed compilation.Extension targets are exact HTTPS model and MCP origins. Keyless Gemini remains deferred. Arbitrary scripts and custom clients must still send the bound header. This adds no CRD fields or credential-provider implementation.
Validation: translator, egress, substrate, app and controller (envtest) race tests pass, as do PostgreSQL revision tests. The pinned linter cannot read Go 1.27 export data. Live provider and gateway integration remains untested.