Skip to content

Commit 95a39a5

Browse files
Domantasclaude
andcommitted
feat(marketplace): start_marketplace_integration_sign_in, the OAuth sign-in start (route 28)
Sync and async CodeModule gain start_marketplace_integration_sign_in (POST .../integrations/{IntegrationViewId}/oauth/start); the marketplace route table gets its case (27 -> 28, run on both clients) and the docs table its row. Route 29 (the callback) is not in the type metadata. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent c7c7075 commit 95a39a5

3 files changed

Lines changed: 32 additions & 4 deletions

File tree

‎docs/hub/code.md‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Integration ids look like `int_…`.
2929

3030
## Marketplace
3131

32-
The 27 routes of the gateway contract `Code.Marketplace.md` §14: the catalog
32+
The 28 routes of the gateway contract `Code.Marketplace.md` §14: the catalog
3333
of listings, the installed connections (integration ids look like `int_…`),
3434
their secrets and token mappings, and the functions added on a connection
3535
(`func_…`). Every method, its verb, path, query and body are asserted in
@@ -59,6 +59,7 @@ their secrets and token mappings, and the functions added on a connection
5959
| `get_marketplace_integration_access` | `GET` | `/{version}/code/marketplace/integrations/{IntegrationViewId}/access` | `project` | path: `integration_view_id`; returns the access matrix (`roles`, `packages`, `tools`, `functions`) |
6060
| `set_marketplace_integration_role_access` | `PUT` | `/{version}/code/marketplace/integrations/{IntegrationViewId}/access/roles` | `project` | path: `integration_view_id`; JSON body: `roleId`, `package` (`None`, `Viewer`, `FunctionsOnly`, `ReadOnly`, `FullAccess`), `manage`; returns the role id |
6161
| `save_marketplace_integration_custom_access` | `POST` | `/{version}/code/marketplace/integrations/{IntegrationViewId}/access/roles/custom` | `project` | path: `integration_view_id`; JSON body: `roleId`, `basePackage`, `tools`, `functions`, `manage`, `newPolicyForThisRoleOnly`; returns `policyId`, `created`, `usedByRoles` |
62+
| `start_marketplace_integration_sign_in` | `POST` | `/{version}/code/marketplace/integrations/{IntegrationViewId}/oauth/start` | `project` | path: `integration_view_id`; returns `authorizeUrl` (open it in a browser), `redirectUrl`, `expiresAt` |
6263
| `replace_marketplace_integration_secrets` | `PUT` | `/{version}/code/marketplace/integrations/{IntegrationViewId}/secrets` | `project` | path: `integration_view_id`; JSON body: `secrets` |
6364
| `reveal_marketplace_integration_secrets` | `POST` | `/{version}/code/marketplace/integrations/{IntegrationViewId}/secrets/reveal` | `project` | path: `integration_view_id` |
6465
| `set_marketplace_integration_token_mappings` | `PUT` | `/{version}/code/marketplace/integrations/{IntegrationViewId}/token-mappings` | `project` | path: `integration_view_id`; JSON body: `tokenMappings` |

‎src/norbix_python/hub/code.py‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,19 @@ def save_marketplace_integration_custom_access(self, integration_view_id: str, *
425425
bearer_token=bearer_token,
426426
)
427427

428+
def start_marketplace_integration_sign_in(self, integration_view_id: str, *, timeout: float | None = None, bearer_token: str | None = None, **request: Any) -> Any:
429+
"""POST /{version}/code/marketplace/integrations/{IntegrationViewId}/oauth/start — start the OAuth sign-in of an MCP connection; returns `authorizeUrl` (open it in a browser), `redirectUrl`, `expiresAt`."""
430+
return self._transport.send(
431+
target="hub",
432+
path="/{version}/code/marketplace/integrations/{IntegrationViewId}/oauth/start",
433+
method="POST",
434+
path_params={"IntegrationViewId": integration_view_id},
435+
request=request,
436+
scope="project",
437+
timeout=timeout,
438+
bearer_token=bearer_token,
439+
)
440+
428441
def replace_marketplace_integration_secrets(self, integration_view_id: str, *, timeout: float | None = None, bearer_token: str | None = None, **request: Any) -> Any:
429442
"""PUT /{version}/code/marketplace/integrations/{IntegrationViewId}/secrets"""
430443
return self._transport.send(
@@ -976,6 +989,19 @@ async def save_marketplace_integration_custom_access(self, integration_view_id:
976989
bearer_token=bearer_token,
977990
)
978991

992+
async def start_marketplace_integration_sign_in(self, integration_view_id: str, *, timeout: float | None = None, bearer_token: str | None = None, **request: Any) -> Any:
993+
"""POST /{version}/code/marketplace/integrations/{IntegrationViewId}/oauth/start — start the OAuth sign-in of an MCP connection; returns `authorizeUrl` (open it in a browser), `redirectUrl`, `expiresAt`."""
994+
return await self._transport.send(
995+
target="hub",
996+
path="/{version}/code/marketplace/integrations/{IntegrationViewId}/oauth/start",
997+
method="POST",
998+
path_params={"IntegrationViewId": integration_view_id},
999+
request=request,
1000+
scope="project",
1001+
timeout=timeout,
1002+
bearer_token=bearer_token,
1003+
)
1004+
9791005
async def replace_marketplace_integration_secrets(self, integration_view_id: str, *, timeout: float | None = None, bearer_token: str | None = None, **request: Any) -> Any:
9801006
"""PUT /{version}/code/marketplace/integrations/{IntegrationViewId}/secrets"""
9811007
return await self._transport.send(

‎tests/hub/test_code.py‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ def test_invoke_code_function_sends_the_function_ref_in_the_body() -> None:
294294
("get_marketplace_integration_access", "GET", "/v3/code/marketplace/integrations/int_6Qp1dW2kRm8NsT4vYc0Hb/access", None, None, lambda m: m.get_marketplace_integration_access("int_6Qp1dW2kRm8NsT4vYc0Hb")),
295295
("set_marketplace_integration_role_access", "PUT", "/v3/code/marketplace/integrations/int_6Qp1dW2kRm8NsT4vYc0Hb/access/roles", None, {'roleId': 'acc_6Qp1dW2kRm8NsT4vYc0Hb_nr_3kLm9QwErTyU', 'package': 'ReadOnly', 'manage': False}, lambda m: m.set_marketplace_integration_role_access("int_6Qp1dW2kRm8NsT4vYc0Hb", roleId='acc_6Qp1dW2kRm8NsT4vYc0Hb_nr_3kLm9QwErTyU', package='ReadOnly', manage=False)),
296296
("save_marketplace_integration_custom_access", "POST", "/v3/code/marketplace/integrations/int_6Qp1dW2kRm8NsT4vYc0Hb/access/roles/custom", None, {'roleId': 'acc_6Qp1dW2kRm8NsT4vYc0Hb_nr_3kLm9QwErTyU', 'basePackage': 'ReadOnly', 'tools': ['create_issue'], 'functions': ['func_4hT2b9QkLm3XcT1yRfGh7a'], 'manage': False, 'newPolicyForThisRoleOnly': True}, lambda m: m.save_marketplace_integration_custom_access("int_6Qp1dW2kRm8NsT4vYc0Hb", roleId='acc_6Qp1dW2kRm8NsT4vYc0Hb_nr_3kLm9QwErTyU', basePackage='ReadOnly', tools=['create_issue'], functions=['func_4hT2b9QkLm3XcT1yRfGh7a'], manage=False, newPolicyForThisRoleOnly=True)),
297+
("start_marketplace_integration_sign_in", "POST", "/v3/code/marketplace/integrations/int_6Qp1dW2kRm8NsT4vYc0Hb/oauth/start", None, None, lambda m: m.start_marketplace_integration_sign_in("int_6Qp1dW2kRm8NsT4vYc0Hb")),
297298
("replace_marketplace_integration_secrets", "PUT", "/v3/code/marketplace/integrations/int_6Qp1dW2kRm8NsT4vYc0Hb/secrets", None, {'secrets': {'botToken': 'xoxb-new'}}, lambda m: m.replace_marketplace_integration_secrets("int_6Qp1dW2kRm8NsT4vYc0Hb", secrets={'botToken': 'xoxb-new'})),
298299
("reveal_marketplace_integration_secrets", "POST", "/v3/code/marketplace/integrations/int_6Qp1dW2kRm8NsT4vYc0Hb/secrets/reveal", None, None, lambda m: m.reveal_marketplace_integration_secrets("int_6Qp1dW2kRm8NsT4vYc0Hb")),
299300
("set_marketplace_integration_token_mappings", "PUT", "/v3/code/marketplace/integrations/int_6Qp1dW2kRm8NsT4vYc0Hb/token-mappings", None, {'tokenMappings': [{'key': 'channel', 'value': '#orders', 'resolver': 'Custom'}]}, lambda m: m.set_marketplace_integration_token_mappings("int_6Qp1dW2kRm8NsT4vYc0Hb", tokenMappings=[{'key': 'channel', 'value': '#orders', 'resolver': 'Custom'}])),
@@ -354,9 +355,9 @@ async def run() -> None:
354355

355356

356357
def test_marketplace_surface_size() -> None:
357-
"""27 marketplace routes in the gateway (Code.Marketplace.md §14; 24 = MCP tool catalog, 25–27 = connection access). A new one changes this count."""
358-
assert len(MARKETPLACE_CASES) == 27
359-
assert len({case[0] for case in MARKETPLACE_CASES}) == 27
358+
"""28 marketplace routes in the gateway (Code.Marketplace.md §14; 24 = MCP tool catalog, 25–27 = connection access, 28 = OAuth sign-in start; 29, the callback, is not in the metadata). A new one changes this count."""
359+
assert len(MARKETPLACE_CASES) == 28
360+
assert len({case[0] for case in MARKETPLACE_CASES}) == 28
360361
client, _ = make_client()
361362
for name, *_ in MARKETPLACE_CASES:
362363
assert callable(getattr(client.hub.code, name)), name

0 commit comments

Comments
 (0)