Repository navigation
fix(profiles): keep every endpoint field in provider profiles #13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -82,29 +82,24 @@ func CredentialTokenGrantTypeToProto(t types.CredentialTokenGrantType) pb.Provid | |
|
|
||
| // --- NetworkEndpoint --- | ||
|
|
||
| // NetworkEndpointFromProto converts a proto NetworkEndpoint to an SDK NetworkEndpoint. | ||
| // Only Host, Port, and Protocol are mapped; additional proto fields are ignored. | ||
| // NetworkEndpointFromProto converts a proto NetworkEndpoint to an SDK | ||
| // NetworkEndpoint. Profile endpoints carry the same fields as policy | ||
| // endpoints, so every field is mapped. | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor: The doc comments on Why this matters: The comments overstate the contract, and the new test comment at Suggested fix: Reword both comments to something like "maps every authored field; the gateway-derived Source: architecture agent |
||
| func NetworkEndpointFromProto(ep *sbv1.NetworkEndpoint) *types.NetworkEndpoint { | ||
| if ep == nil { | ||
| return nil | ||
| } | ||
| return &types.NetworkEndpoint{ | ||
| Host: ep.GetHost(), | ||
| Port: ep.GetPort(), | ||
| Protocol: ep.GetProtocol(), | ||
| } | ||
| result := policyNetworkEndpointFromProto(ep) | ||
| return &result | ||
| } | ||
|
|
||
| // NetworkEndpointToProto converts an SDK NetworkEndpoint to a proto NetworkEndpoint. | ||
| // NetworkEndpointToProto converts an SDK NetworkEndpoint to a proto | ||
| // NetworkEndpoint, mapping every field. | ||
| func NetworkEndpointToProto(ep *types.NetworkEndpoint) *sbv1.NetworkEndpoint { | ||
| if ep == nil { | ||
| return nil | ||
| } | ||
| return &sbv1.NetworkEndpoint{ | ||
| Host: ep.Host, | ||
| Port: ep.Port, | ||
| Protocol: ep.Protocol, | ||
| } | ||
| return policyNetworkEndpointToProto(ep) | ||
| } | ||
|
|
||
| // --- NetworkBinary --- | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,7 @@ import ( | |
| sbv1 "github.com/ai-openshell/sdk-go/proto/sandboxv1" | ||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| "google.golang.org/protobuf/proto" | ||
| "google.golang.org/protobuf/types/known/durationpb" | ||
| ) | ||
|
|
||
|
|
@@ -751,3 +752,54 @@ func TestProviderProfileRoundTrip(t *testing.T) { | |
|
|
||
| assert.Equal(t, original.Discovery.Credentials, back.Discovery.Credentials) | ||
| } | ||
|
|
||
| // Profile endpoints share the policy endpoint message; access, enforcement, | ||
| // credential settings, and every other field must survive both directions | ||
| // (ai-openshell/sdk-go#12). | ||
| func TestNetworkEndpointRoundTripKeepsAllFields(t *testing.T) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor: Why this matters: If Suggested fix: Give every proto field a non-zero value in the input, including at least one Source: test-quality agent |
||
| in := &sbv1.NetworkEndpoint{ | ||
| Host: "api.anthropic.com", | ||
| Port: 443, | ||
| Ports: []uint32{443, 8443}, | ||
| Protocol: "rest", | ||
| Tls: sbv1.NetworkTlsMode_NETWORK_TLS_MODE_SKIP, | ||
| Enforcement: sbv1.NetworkEnforcementMode_NETWORK_ENFORCEMENT_MODE_ENFORCE, | ||
| Access: sbv1.NetworkAccessPreset_NETWORK_ACCESS_PRESET_FULL, | ||
| AllowedIps: []string{"10.0.0.0/8"}, | ||
| Path: "/v1", | ||
| AllowUninspectedCredentials: true, | ||
| ProviderCredentialed: true, | ||
| CredentialBinding: &sbv1.NetworkCredentialBinding{Provider: "anthropic"}, | ||
| } | ||
|
|
||
| ep := NetworkEndpointFromProto(in) | ||
| require.NotNil(t, ep) | ||
| assert.Equal(t, v1.NetworkAccessPresetFull, ep.Access) | ||
| assert.True(t, ep.AllowUninspectedCredentials) | ||
| require.NotNil(t, ep.CredentialBinding) | ||
| assert.Equal(t, "anthropic", ep.CredentialBinding.Provider) | ||
|
|
||
| out := NetworkEndpointToProto(ep) | ||
| assert.True(t, proto.Equal(in, out), "round trip changed the endpoint:\nin: %v\nout: %v", in, out) | ||
| } | ||
|
|
||
| func TestProviderProfileRoundTripKeepsEndpointAccess(t *testing.T) { | ||
| in := &pb.ProviderProfile{ | ||
| Id: "claude-code", | ||
| Endpoints: []*sbv1.NetworkEndpoint{{ | ||
| Host: "api.anthropic.com", | ||
| Port: 443, | ||
| Protocol: "rest", | ||
| Access: sbv1.NetworkAccessPreset_NETWORK_ACCESS_PRESET_READ_WRITE, | ||
| Enforcement: sbv1.NetworkEnforcementMode_NETWORK_ENFORCEMENT_MODE_ENFORCE, | ||
| }}, | ||
| } | ||
|
|
||
| profile := ProviderProfileFromProto(in) | ||
| require.Len(t, profile.Endpoints, 1) | ||
| assert.Equal(t, v1.NetworkAccessPresetReadWrite, profile.Endpoints[0].Access) | ||
|
|
||
| out := ProviderProfileToProto(profile) | ||
| require.Len(t, out.GetEndpoints(), 1) | ||
| assert.True(t, proto.Equal(in.GetEndpoints()[0], out.GetEndpoints()[0])) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -139,12 +139,11 @@ type TokenGrantAudienceOverride struct { | |
| Scopes []string | ||
| } | ||
|
|
||
| // NetworkEndpoint describes a network endpoint provided by a profile. | ||
| type NetworkEndpoint struct { | ||
| Host string | ||
| Port uint32 | ||
| Protocol string | ||
| } | ||
| // NetworkEndpoint describes a network endpoint provided by a profile. Profiles | ||
| // and sandbox policies share one endpoint message, so it is the same type as | ||
| // [PolicyNetworkEndpoint], with access, enforcement, rules, and credential | ||
| // settings. | ||
| type NetworkEndpoint = PolicyNetworkEndpoint | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Notable: Endpoints are now unified ( Why this matters: This is informational, not a defect. Binaries lose no data, since Suggested fix: If the shared-message reasoning in this PR is the design rule, apply it to binaries too ( Source: architecture agent
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor: Turning Why this matters: Downstream builds break on upgrade, and nothing tells users why. For example, Suggested fix: Keep the alias, since it's the right fix for the data loss in #12, and add a breaking-change note to the PR description or release notes. Something like: " Source: gator agent |
||
|
|
||
| // NetworkBinary describes a binary artifact provided by a profile. | ||
| type NetworkBinary struct { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Notable: The PR description and this new doc comment say every endpoint field is mapped in both directions. That isn't quite the case: proto field 27,
token_grant_owner(sbv1.NetworkEndpoint.TokenGrantOwner), has no counterpart inPolicyNetworkEndpoint, sopolicyNetworkEndpointFromProtoandpolicyNetworkEndpointToProtodrop it.Why this matters: A profile returned by
Profiles().Getwhose endpoint hastoken_grant_ownerset comes back without it, andTestNetworkEndpointRoundTripKeepsAllFieldsnever sets that field, so the "keeps all fields" claim isn't checked for it. The practical impact is low. The proto marks the field as gateway-derived and ignores user-authored values, so the goal of #12 (Get then Update no longer strips access, rules, enforcement or credential settings) is still met. What's off is the stated contract.Suggested fix: Reword the comments and the PR text to say every user-authored field is mapped, and name
TokenGrantOwneras intentionally left out because the gateway owns it. If read-back visibility is wanted, add the field toPolicyNetworkEndpointand both converters instead. The comment on line 87 covers the same wording from the code side.Source: goal-alignment agent