Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
576 changes: 564 additions & 12 deletions dotnet/src/Generated/Rpc.cs

Large diffs are not rendered by default.

204 changes: 204 additions & 0 deletions dotnet/src/Generated/SessionEvents.cs

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions dotnet/src/Types.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3052,15 +3052,14 @@ public sealed class GitHubMcpToolConfig
public bool? DisableFormDeferral { get; set; }
}

/// <summary>
/// Controls whether bypass-permissions mode is available in a managed session.
/// </summary>
[JsonConverter(typeof(JsonStringEnumConverter<DisableBypassPermissionsMode>))]
public enum DisableBypassPermissionsMode
/// <summary>Well-known managed bypass-permissions policies.</summary>
public static class DisableBypassPermissionsModes
{
/// <summary>Turn off bypass-permissions mode.</summary>
[JsonStringEnumMemberName("disable")]
Disable
/// <summary>Turns off bypass-permissions mode entirely.</summary>
public const string Disable = "disable";

/// <summary>Permits automatic bypass but blocks full allow-all.</summary>
public const string AllowAutoOnly = "allow-auto-only";
}

/// <summary>
Expand All @@ -3071,18 +3070,19 @@ public enum DisableBypassPermissionsMode
/// This layer composes restrictively with any server- or device-level managed
/// settings: <see cref="Deny"/> and <see cref="Ask"/> rules are unioned across
/// layers, every present <see cref="Allow"/> list must admit a tool for it to be
/// allowed, and <see cref="DisableBypassPermissionsMode"/> is honored if any
/// layer sets it (deny-wins).
/// allowed, and <see cref="DisableBypassPermissionsMode"/> policies compose to
/// the most restrictive setting.
/// </remarks>
public sealed class ManagedSettingsPermissions
{
/// <summary>
/// When set to <c>"disable"</c>, bypass-permissions mode is turned off for the
/// session regardless of other layers. Serialized as
/// <c>disableBypassPermissionsMode</c>.
/// Restricts bypass-permissions mode for the session regardless of other
/// layers. See <see cref="DisableBypassPermissionsModes"/> for well-known
/// values. Unknown values are forwarded so newer runtime policies fail closed.
/// Serialized as <c>disableBypassPermissionsMode</c>.
Comment thread
ellismg marked this conversation as resolved.
/// </summary>
[JsonPropertyName("disableBypassPermissionsMode")]
public DisableBypassPermissionsMode? DisableBypassPermissionsMode { get; set; }
public string? DisableBypassPermissionsMode { get; set; }

/// <summary>Tool-permission patterns that are always denied.</summary>
[JsonPropertyName("deny")]
Expand Down
2 changes: 1 addition & 1 deletion dotnet/test/E2E/RpcSessionStateE2ETests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ public async Task Should_Set_Auth_Credentials()
});
var login = $"sdk-rpc-{Guid.NewGuid():N}";

var setCredentials = await session.Rpc.GitHubAuth.SetCredentialsAsync(new AuthInfoUser
var setCredentials = await session.Rpc.GitHubAuth.SetCredentialsAsync(new SettableAuthInfoUser
{
CopilotUser = new CopilotUserResponse
{
Expand Down
28 changes: 27 additions & 1 deletion dotnet/test/Unit/ClientSessionLifetimeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,7 @@ public async Task CreateSessionAsync_Serializes_ManagedSettings_Permissions()
{
Permissions = new ManagedSettingsPermissions
{
DisableBypassPermissionsMode = DisableBypassPermissionsMode.Disable,
DisableBypassPermissionsMode = DisableBypassPermissionsModes.Disable,
Deny = ["shell(rm*)"],
Ask = ["write"],
Allow = []
Expand Down Expand Up @@ -585,6 +585,32 @@ public async Task CreateSessionAsync_Serializes_ManagedSettings_Permissions()
Assert.True(invocation.ManagedSettingsEnabled);
}

[Fact]
public async Task CreateSessionAsync_Serializes_Future_ManagedSettings_Bypass_Mode()
{
await using var server = await FakeCopilotServer.StartAsync();
await using var client = new CopilotClient(new CopilotClientOptions { Connection = RuntimeConnection.ForUri(server.Url) });
await client.StartAsync();

await using var session = await client.CreateSessionAsync(new SessionConfig
{
ManagedSettings = new ManagedSettings
{
Permissions = new ManagedSettingsPermissions
{
DisableBypassPermissionsMode = "future-fail-closed-mode"
}
},
OnPermissionRequest = PermissionHandler.ApproveAll
});

var request = Assert.Single(server.Requests, request => request.Method == "session.create");
var permissions = request.Params.GetProperty("managedSettings").GetProperty("permissions");
Assert.Equal(
"future-fail-closed-mode",
permissions.GetProperty("disableBypassPermissionsMode").GetString());
}

[Fact]
public async Task PermissionResponse_Forwards_DecisionContext_As_Sibling_Of_Result()
{
Expand Down
20 changes: 20 additions & 0 deletions go/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3834,6 +3834,26 @@ func TestSessionRequests_ManagedSettings(t *testing.T) {
}
})

t.Run("accepts future bypass-permissions modes", func(t *testing.T) {
req := createSessionRequest{ManagedSettings: &ManagedSettings{
Permissions: &ManagedSettingsPermissions{
DisableBypassPermissionsMode: DisableBypassPermissionsMode("future-fail-closed-mode"),
},
}}
data, err := json.Marshal(req)
if err != nil {
t.Fatalf("Failed to marshal: %v", err)
}
var m map[string]any
if err := json.Unmarshal(data, &m); err != nil {
t.Fatalf("Failed to unmarshal: %v", err)
}
perms := m["managedSettings"].(map[string]any)["permissions"].(map[string]any)
if perms["disableBypassPermissionsMode"] != "future-fail-closed-mode" {
t.Errorf("Expected future mode preserved, got %v", perms["disableBypassPermissionsMode"])
}
})

t.Run("omits managedSettings when nil", func(t *testing.T) {
req := createSessionRequest{}
data, _ := json.Marshal(req)
Expand Down
1 change: 1 addition & 0 deletions go/internal/e2e/rpc_tasks_and_handlers_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ func TestRPCTasksAndHandlersE2E(t *testing.T) {
})

t.Run("should report implemented error for invalid task agent model", func(t *testing.T) {
ctx.ConfigureForTest(t)
session, err := client.CreateSession(t.Context(), &copilot.SessionConfig{
OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
})
Expand Down
Loading
Loading