From f2d5542c7324fe5e5e9d98e2a757865e20ea641d Mon Sep 17 00:00:00 2001 From: William Bergamin Date: Thu, 22 Oct 2026 18:01:04 -0400 Subject: [PATCH 1/2] feat: add user_connections to the app manifest features model Adds AppManifest.UserConnections (isEnabled, authHosts) on Features so apps.manifest.create, update and export keep the standardized app authentication settings instead of dropping them. The export json-logs sample and SampleObjects carry the field so generated response types pick it up. Co-Authored-By: Claude --- .../samples/api/apps.manifest.export.json | 8 ++++- .../sample_json_generation/SampleObjects.java | 3 ++ .../slack/api/model/manifest/AppManifest.java | 10 ++++++ .../api/model/AppManifestTest.java | 32 +++++++++++++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) diff --git a/json-logs/samples/api/apps.manifest.export.json b/json-logs/samples/api/apps.manifest.export.json index faa652640..7bb049cad 100644 --- a/json-logs/samples/api/apps.manifest.export.json +++ b/json-logs/samples/api/apps.manifest.export.json @@ -68,7 +68,13 @@ ], "unfurl_domains": [ "" - ] + ], + "user_connections": { + "is_enabled": false, + "auth_hosts": [ + "" + ] + } }, "oauth_config": { "scopes": { diff --git a/slack-api-client/src/test/java/util/sample_json_generation/SampleObjects.java b/slack-api-client/src/test/java/util/sample_json_generation/SampleObjects.java index 11d0596a8..ab629a8df 100644 --- a/slack-api-client/src/test/java/util/sample_json_generation/SampleObjects.java +++ b/slack-api-client/src/test/java/util/sample_json_generation/SampleObjects.java @@ -466,6 +466,9 @@ public static File initFileObject() { .shortcuts(Arrays.asList(initProperties(AppManifest.Shortcut.builder().build()))) .slashCommands(Arrays.asList(initProperties(AppManifest.SlashCommand.builder().build()))) .unfurlDomains(Arrays.asList("")) + .userConnections(initProperties(AppManifest.UserConnections.builder() + .authHosts(Arrays.asList("")) + .build())) .build())) .settings(initProperties(AppManifest.Settings.builder() .allowedIpAddressRanges(Arrays.asList("")) diff --git a/slack-api-model/src/main/java/com/slack/api/model/manifest/AppManifest.java b/slack-api-model/src/main/java/com/slack/api/model/manifest/AppManifest.java index e44dd82e9..2bc772d4c 100644 --- a/slack-api-model/src/main/java/com/slack/api/model/manifest/AppManifest.java +++ b/slack-api-model/src/main/java/com/slack/api/model/manifest/AppManifest.java @@ -91,6 +91,7 @@ public static class Features { private List shortcuts; private List slashCommands; private List unfurlDomains; + private UserConnections userConnections; } @Data @@ -112,6 +113,15 @@ public static class BotUser { private Boolean alwaysOnline; } + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class UserConnections { + private Boolean isEnabled; + private List authHosts; + } + @Data @Builder @NoArgsConstructor diff --git a/slack-api-model/src/test/java/test_locally/api/model/AppManifestTest.java b/slack-api-model/src/test/java/test_locally/api/model/AppManifestTest.java index 760870cc8..75aebdf28 100644 --- a/slack-api-model/src/test/java/test_locally/api/model/AppManifestTest.java +++ b/slack-api-model/src/test/java/test_locally/api/model/AppManifestTest.java @@ -1,9 +1,13 @@ package test_locally.api.model; +import com.google.gson.Gson; import com.slack.api.model.manifest.AppManifest; import org.junit.Test; import test_locally.unit.GsonFactory; +import java.util.Arrays; + +import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.notNullValue; import static org.hamcrest.MatcherAssert.assertThat; @@ -103,4 +107,32 @@ public void parser() { .fromJson(json, AppManifest.class); assertThat(appManifest.getSettings(), is(notNullValue())); } + + @Test + public void userConnections() { + String json = "{\n" + + " \"display_information\": {\n" + + " \"name\": \"connector\"\n" + + " },\n" + + " \"features\": {\n" + + " \"user_connections\": {\n" + + " \"is_enabled\": true,\n" + + " \"auth_hosts\": [\n" + + " \"example.com\",\n" + + " \"auth.example.com\"\n" + + " ]\n" + + " }\n" + + " }\n" + + "}"; + + Gson gson = GsonFactory.createSnakeCase(true, true); + AppManifest appManifest = gson.fromJson(json, AppManifest.class); + AppManifest.UserConnections userConnections = appManifest.getFeatures().getUserConnections(); + assertThat(userConnections.getIsEnabled(), is(true)); + assertThat(userConnections.getAuthHosts(), is(Arrays.asList("example.com", "auth.example.com"))); + + String serialized = gson.toJson(appManifest); + assertThat(serialized, containsString( + "\"user_connections\":{\"is_enabled\":true,\"auth_hosts\":[\"example.com\",\"auth.example.com\"]}")); + } } From 74219dd4d20b462941f017a14ff1cace2e02740e Mon Sep 17 00:00:00 2001 From: William Bergamin Date: Fri, 23 Oct 2026 09:51:35 -0400 Subject: [PATCH 2/2] feat: add user_connections to the app manifest request params apps.manifest.create, update and validate take AppManifestParams, not AppManifest, so the feature could be read from an export but not sent. Co-Authored-By: Claude --- .../api/model/manifest/AppManifestParams.java | 10 ++++++++++ .../test_locally/api/model/AppManifestTest.java | 17 +++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/slack-api-model/src/main/java/com/slack/api/model/manifest/AppManifestParams.java b/slack-api-model/src/main/java/com/slack/api/model/manifest/AppManifestParams.java index 4a168325e..73a17a778 100644 --- a/slack-api-model/src/main/java/com/slack/api/model/manifest/AppManifestParams.java +++ b/slack-api-model/src/main/java/com/slack/api/model/manifest/AppManifestParams.java @@ -87,6 +87,7 @@ public static class Features { private List shortcuts; private List slashCommands; private List unfurlDomains; + private UserConnections userConnections; } @Data @@ -108,6 +109,15 @@ public static class BotUser { private Boolean alwaysOnline; } + @Data + @Builder + @NoArgsConstructor + @AllArgsConstructor + public static class UserConnections { + private Boolean isEnabled; + private List authHosts; + } + @Data @Builder @NoArgsConstructor diff --git a/slack-api-model/src/test/java/test_locally/api/model/AppManifestTest.java b/slack-api-model/src/test/java/test_locally/api/model/AppManifestTest.java index 75aebdf28..0ab14e741 100644 --- a/slack-api-model/src/test/java/test_locally/api/model/AppManifestTest.java +++ b/slack-api-model/src/test/java/test_locally/api/model/AppManifestTest.java @@ -2,6 +2,7 @@ import com.google.gson.Gson; import com.slack.api.model.manifest.AppManifest; +import com.slack.api.model.manifest.AppManifestParams; import org.junit.Test; import test_locally.unit.GsonFactory; @@ -135,4 +136,20 @@ public void userConnections() { assertThat(serialized, containsString( "\"user_connections\":{\"is_enabled\":true,\"auth_hosts\":[\"example.com\",\"auth.example.com\"]}")); } + + @Test + public void userConnectionsParams() { + AppManifestParams params = AppManifestParams.builder() + .features(AppManifestParams.Features.builder() + .userConnections(AppManifestParams.UserConnections.builder() + .isEnabled(false) + .authHosts(Arrays.asList("example.com")) + .build()) + .build()) + .build(); + + String serialized = GsonFactory.createSnakeCase(true, true).toJson(params); + assertThat(serialized, containsString( + "\"user_connections\":{\"is_enabled\":false,\"auth_hosts\":[\"example.com\"]}")); + } }