diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b4e9013..6db19b9 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.16.0" + ".": "0.17.0" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index ffd5937..80060ec 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 106 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/keycard/keycard-api-cdf14bee924cea2eaca3c1aaed26521cb91369d9462d22c21a0306b5786f4706.yml -openapi_spec_hash: d8349acc1adec880977b6167a1e866bc +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/keycard/keycard-api-9a353824f6b68547b91d52205e052e4a5428ae35f37a10fb898aa8a38458efeb.yml +openapi_spec_hash: 846e320252df771be0cb6c47e876bcf1 config_hash: 7adc6b24545570dcc4a1bf0f714aa3e0 diff --git a/CHANGELOG.md b/CHANGELOG.md index cefd0e4..cc6a0f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## 0.17.0 (2026-07-06) + +Full Changelog: [v0.16.0...v0.17.0](https://github.com/keycardai/keycard-python/compare/v0.16.0...v0.17.0) + +### Features + +* filter users by identifier in management list ([147af02](https://github.com/keycardai/keycard-python/commit/147af020e8e8c31678928137fb85386b54dd4ec6)) +* **ID-365:** support additional SSO provider configuration options ([526b229](https://github.com/keycardai/keycard-python/commit/526b22958acc91a11569ba3f8453a004eb03f6f5)) + + +### Bug Fixes + +* **ACC-613:** preserve source order of policies in draft/convert cedar_json ([6d27d21](https://github.com/keycardai/keycard-python/commit/6d27d213ac66fb9f1890409a380924c3edb44b99)) +* exact-match identifier filter on resources management list ([846f24e](https://github.com/keycardai/keycard-python/commit/846f24efdb2492e4ea0741167ebc7153af5d0d1e)) + ## 0.16.0 (2026-06-30) Full Changelog: [v0.15.0...v0.16.0](https://github.com/keycardai/keycard-python/compare/v0.15.0...v0.16.0) diff --git a/pyproject.toml b/pyproject.toml index 0f72996..a2de0a3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "keycardai_api" -version = "0.16.0" +version = "0.17.0" description = "The official Python library for the keycard-api API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/keycardai_api/_version.py b/src/keycardai_api/_version.py index ff81ceb..cb30031 100644 --- a/src/keycardai_api/_version.py +++ b/src/keycardai_api/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "keycardai_api" -__version__ = "0.16.0" # x-release-please-version +__version__ = "0.17.0" # x-release-please-version diff --git a/src/keycardai_api/resources/organizations/sso_connection.py b/src/keycardai_api/resources/organizations/sso_connection.py index 4a8a44f..002dbed 100644 --- a/src/keycardai_api/resources/organizations/sso_connection.py +++ b/src/keycardai_api/resources/organizations/sso_connection.py @@ -104,7 +104,7 @@ def update( client_id: str | Omit = omit, client_secret: str | Omit = omit, identifier: str | Omit = omit, - protocols: Optional[SSOConnectionProtocolParam] | Omit = omit, + protocols: Optional[sso_connection_update_params.Protocols] | Omit = omit, x_client_request_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -125,7 +125,8 @@ def update( identifier: SSO provider identifier (e.g., issuer URL) - protocols: Protocol configuration for SSO connection + protocols: Protocol configuration for an SSO connection update. Omit a protocol to leave it + unchanged. extra_headers: Send extra headers @@ -329,7 +330,7 @@ async def update( client_id: str | Omit = omit, client_secret: str | Omit = omit, identifier: str | Omit = omit, - protocols: Optional[SSOConnectionProtocolParam] | Omit = omit, + protocols: Optional[sso_connection_update_params.Protocols] | Omit = omit, x_client_request_id: str | Omit = omit, # Use the following arguments if you need to pass additional parameters to the API that aren't available via kwargs. # The extra values given here take precedence over values defined on the client or passed to this method. @@ -350,7 +351,8 @@ async def update( identifier: SSO provider identifier (e.g., issuer URL) - protocols: Protocol configuration for SSO connection + protocols: Protocol configuration for an SSO connection update. Omit a protocol to leave it + unchanged. extra_headers: Send extra headers diff --git a/src/keycardai_api/resources/zones/resources.py b/src/keycardai_api/resources/zones/resources.py index 2941cfe..5b19dad 100644 --- a/src/keycardai_api/resources/zones/resources.py +++ b/src/keycardai_api/resources/zones/resources.py @@ -271,6 +271,7 @@ def list( before: str | Omit = omit, credential_provider_id: str | Omit = omit, expand: Union[Literal["total_count"], List[Literal["total_count"]]] | Omit = omit, + filter_identifier: Union[str, SequenceNotStr[str]] | Omit = omit, identifier: str | Omit = omit, limit: int | Omit = omit, slug: str | Omit = omit, @@ -281,8 +282,12 @@ def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ResourceListResponse: - """ - Returns a list of resources in the specified zone + """Returns a list of resources in the specified zone. + + Filter by exact identifier + via `filter[identifier]` (repeatable, OR'd). Matching is exact: identifiers are + unique per zone, so a filter returns at most one resource per value and never + performs URL prefix resolution. Args: after: Cursor for forward pagination @@ -291,6 +296,8 @@ def list( credential_provider_id: Filter resources by credential provider ID + filter_identifier: Filter by exact resource identifier + identifier: Filter resources by identifier limit: Maximum number of items to return @@ -318,6 +325,7 @@ def list( "before": before, "credential_provider_id": credential_provider_id, "expand": expand, + "filter_identifier": filter_identifier, "identifier": identifier, "limit": limit, "slug": slug, @@ -606,6 +614,7 @@ async def list( before: str | Omit = omit, credential_provider_id: str | Omit = omit, expand: Union[Literal["total_count"], List[Literal["total_count"]]] | Omit = omit, + filter_identifier: Union[str, SequenceNotStr[str]] | Omit = omit, identifier: str | Omit = omit, limit: int | Omit = omit, slug: str | Omit = omit, @@ -616,8 +625,12 @@ async def list( extra_body: Body | None = None, timeout: float | httpx.Timeout | None | NotGiven = not_given, ) -> ResourceListResponse: - """ - Returns a list of resources in the specified zone + """Returns a list of resources in the specified zone. + + Filter by exact identifier + via `filter[identifier]` (repeatable, OR'd). Matching is exact: identifiers are + unique per zone, so a filter returns at most one resource per value and never + performs URL prefix resolution. Args: after: Cursor for forward pagination @@ -626,6 +639,8 @@ async def list( credential_provider_id: Filter resources by credential provider ID + filter_identifier: Filter by exact resource identifier + identifier: Filter resources by identifier limit: Maximum number of items to return @@ -653,6 +668,7 @@ async def list( "before": before, "credential_provider_id": credential_provider_id, "expand": expand, + "filter_identifier": filter_identifier, "identifier": identifier, "limit": limit, "slug": slug, diff --git a/src/keycardai_api/resources/zones/users.py b/src/keycardai_api/resources/zones/users.py index 81cd5a1..399df0f 100644 --- a/src/keycardai_api/resources/zones/users.py +++ b/src/keycardai_api/resources/zones/users.py @@ -94,6 +94,7 @@ def list( | Omit = omit, filter_email: Union[str, SequenceNotStr[str]] | Omit = omit, filter_id: Union[str, SequenceNotStr[str]] | Omit = omit, + filter_identifier: Union[str, SequenceNotStr[str]] | Omit = omit, limit: int | Omit = omit, query: Union[str, SequenceNotStr[str]] | Omit = omit, query_email: Union[str, SequenceNotStr[str]] | Omit = omit, @@ -109,27 +110,26 @@ def list( """ Returns a list of users in the specified zone. - **Rollout note:** the paginated/searchable/sortable behavior described below is - gated behind the `user-pagination` feature flag and is currently disabled for - most zones. While the flag is off, the response returns every user in the zone - (capped at 100) in `items` and a fixed pagination envelope where `after_cursor` - and `before_cursor` are `null` and `total_count` is `0`. The query parameters - below are accepted but ignored. The flag is rolled out per-zone in Datadog and - will become the default once Console adopts the paginated contract. + Note: cursor pagination, search, and sort are not yet enabled for all zones. + Where they are not enabled, the response returns all users in the zone (capped + at 100) in `items`, with `after_cursor` and `before_cursor` set to `null` and + `total_count` of `0`; `filter[email]` and `filter[identifier]` are still + applied, while the pagination, search, and sort parameters below are accepted + but ignored. Use cursor pagination via `after`/`before`. Sort: comma-separated field list; prefix with `-` for descending. Use `expand[]=total_count` to include the matching row count, `expand[]=session_count` to include per-user session counts, `expand[]=grant_count` to include per-user delegated-grant counts, and `expand[]=role-assignments` to include each user's structured role grants. - Filter by exact email via `filter[email]`; search via `query[email]` / - `query[subject]` / `query[]` (substring match, OR'd across repeated values). - `query[]` matches against email and federation credential subject. Pass - `filter[id]` (repeatable, max 100) to restrict results to a known set of users — - mutually exclusive with `after`/`before` (returns 400 if combined). When - `filter[id]` is set, `limit` is ignored and the response contains every - requested user that exists in the zone, in a single page. IDs not in the zone - are silently omitted. + Filter by exact email via `filter[email]` and by exact identifier via + `filter[identifier]`; search via `query[email]` / `query[subject]` / `query[]` + (substring match, OR'd across repeated values). `query[]` matches against email + and federation credential subject. Pass `filter[id]` (repeatable, max 100) to + restrict results to a known set of users — mutually exclusive with + `after`/`before` (returns 400 if combined). When `filter[id]` is set, `limit` is + ignored and the response contains every requested user that exists in the zone, + in a single page. IDs not in the zone are silently omitted. Args: after: Cursor for forward pagination @@ -141,6 +141,8 @@ def list( filter_id: Restrict results to users with this publicId. Repeatable, max 100. Mutually exclusive with after/before. + filter_identifier: Filter by exact user identifier + limit: Maximum number of items to return query: Search across email and credential subject (substring match) @@ -176,6 +178,7 @@ def list( "expand": expand, "filter_email": filter_email, "filter_id": filter_id, + "filter_identifier": filter_identifier, "limit": limit, "query": query, "query_email": query_email, @@ -258,6 +261,7 @@ async def list( | Omit = omit, filter_email: Union[str, SequenceNotStr[str]] | Omit = omit, filter_id: Union[str, SequenceNotStr[str]] | Omit = omit, + filter_identifier: Union[str, SequenceNotStr[str]] | Omit = omit, limit: int | Omit = omit, query: Union[str, SequenceNotStr[str]] | Omit = omit, query_email: Union[str, SequenceNotStr[str]] | Omit = omit, @@ -273,27 +277,26 @@ async def list( """ Returns a list of users in the specified zone. - **Rollout note:** the paginated/searchable/sortable behavior described below is - gated behind the `user-pagination` feature flag and is currently disabled for - most zones. While the flag is off, the response returns every user in the zone - (capped at 100) in `items` and a fixed pagination envelope where `after_cursor` - and `before_cursor` are `null` and `total_count` is `0`. The query parameters - below are accepted but ignored. The flag is rolled out per-zone in Datadog and - will become the default once Console adopts the paginated contract. + Note: cursor pagination, search, and sort are not yet enabled for all zones. + Where they are not enabled, the response returns all users in the zone (capped + at 100) in `items`, with `after_cursor` and `before_cursor` set to `null` and + `total_count` of `0`; `filter[email]` and `filter[identifier]` are still + applied, while the pagination, search, and sort parameters below are accepted + but ignored. Use cursor pagination via `after`/`before`. Sort: comma-separated field list; prefix with `-` for descending. Use `expand[]=total_count` to include the matching row count, `expand[]=session_count` to include per-user session counts, `expand[]=grant_count` to include per-user delegated-grant counts, and `expand[]=role-assignments` to include each user's structured role grants. - Filter by exact email via `filter[email]`; search via `query[email]` / - `query[subject]` / `query[]` (substring match, OR'd across repeated values). - `query[]` matches against email and federation credential subject. Pass - `filter[id]` (repeatable, max 100) to restrict results to a known set of users — - mutually exclusive with `after`/`before` (returns 400 if combined). When - `filter[id]` is set, `limit` is ignored and the response contains every - requested user that exists in the zone, in a single page. IDs not in the zone - are silently omitted. + Filter by exact email via `filter[email]` and by exact identifier via + `filter[identifier]`; search via `query[email]` / `query[subject]` / `query[]` + (substring match, OR'd across repeated values). `query[]` matches against email + and federation credential subject. Pass `filter[id]` (repeatable, max 100) to + restrict results to a known set of users — mutually exclusive with + `after`/`before` (returns 400 if combined). When `filter[id]` is set, `limit` is + ignored and the response contains every requested user that exists in the zone, + in a single page. IDs not in the zone are silently omitted. Args: after: Cursor for forward pagination @@ -305,6 +308,8 @@ async def list( filter_id: Restrict results to users with this publicId. Repeatable, max 100. Mutually exclusive with after/before. + filter_identifier: Filter by exact user identifier + limit: Maximum number of items to return query: Search across email and credential subject (substring match) @@ -340,6 +345,7 @@ async def list( "expand": expand, "filter_email": filter_email, "filter_id": filter_id, + "filter_identifier": filter_identifier, "limit": limit, "query": query, "query_email": query_email, diff --git a/src/keycardai_api/types/organizations/sso_connection_protocol.py b/src/keycardai_api/types/organizations/sso_connection_protocol.py index 5767f80..42ae9b7 100644 --- a/src/keycardai_api/types/organizations/sso_connection_protocol.py +++ b/src/keycardai_api/types/organizations/sso_connection_protocol.py @@ -1,6 +1,6 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. -from typing import List, Optional +from typing import Dict, List, Optional from ..._models import BaseModel @@ -13,6 +13,13 @@ class Oauth2(BaseModel): authorization_endpoint: Optional[str] = None """OAuth 2.0 authorization endpoint""" + authorization_parameters: Optional[Dict[str, str]] = None + """Custom query parameters appended to authorization redirect URLs. + + Use for non-standard providers (e.g. Google prompt=consent, + access_type=offline). + """ + code_challenge_methods_supported: Optional[List[str]] = None """Supported PKCE code challenge methods""" @@ -32,6 +39,18 @@ class Oauth2(BaseModel): class Openid(BaseModel): """OpenID Connect protocol configuration for SSO connection""" + scopes: Optional[List[str]] = None + """Additional OIDC scopes to request from this provider during authentication (e.g. + + "groups"). Merged with the default scopes (openid, profile, email). + """ + + user_identifier_claim: Optional[str] = None + """ + Name of a top-level string claim in the provider's ID Token to use as the user + identifier on user creation. When not set, the user's Keycard ID is used. + """ + userinfo_endpoint: Optional[str] = None """OpenID Connect UserInfo endpoint""" diff --git a/src/keycardai_api/types/organizations/sso_connection_protocol_param.py b/src/keycardai_api/types/organizations/sso_connection_protocol_param.py index 84d6074..2183279 100644 --- a/src/keycardai_api/types/organizations/sso_connection_protocol_param.py +++ b/src/keycardai_api/types/organizations/sso_connection_protocol_param.py @@ -2,7 +2,7 @@ from __future__ import annotations -from typing import Optional +from typing import Dict, Optional from typing_extensions import TypedDict from ..._types import SequenceNotStr @@ -16,6 +16,13 @@ class Oauth2(TypedDict, total=False): authorization_endpoint: Optional[str] """OAuth 2.0 authorization endpoint""" + authorization_parameters: Optional[Dict[str, str]] + """Custom query parameters appended to authorization redirect URLs. + + Use for non-standard providers (e.g. Google prompt=consent, + access_type=offline). + """ + code_challenge_methods_supported: Optional[SequenceNotStr[str]] """Supported PKCE code challenge methods""" @@ -35,6 +42,18 @@ class Oauth2(TypedDict, total=False): class Openid(TypedDict, total=False): """OpenID Connect protocol configuration for SSO connection""" + scopes: Optional[SequenceNotStr[str]] + """Additional OIDC scopes to request from this provider during authentication (e.g. + + "groups"). Merged with the default scopes (openid, profile, email). + """ + + user_identifier_claim: Optional[str] + """ + Name of a top-level string claim in the provider's ID Token to use as the user + identifier on user creation. When not set, the user's Keycard ID is used. + """ + userinfo_endpoint: Optional[str] """OpenID Connect UserInfo endpoint""" diff --git a/src/keycardai_api/types/organizations/sso_connection_update_params.py b/src/keycardai_api/types/organizations/sso_connection_update_params.py index e8d852e..93c8454 100644 --- a/src/keycardai_api/types/organizations/sso_connection_update_params.py +++ b/src/keycardai_api/types/organizations/sso_connection_update_params.py @@ -2,13 +2,13 @@ from __future__ import annotations -from typing import Optional +from typing import Dict, Optional from typing_extensions import Annotated, TypedDict +from ..._types import SequenceNotStr from ..._utils import PropertyInfo -from .sso_connection_protocol_param import SSOConnectionProtocolParam -__all__ = ["SSOConnectionUpdateParams"] +__all__ = ["SSOConnectionUpdateParams", "Protocols", "ProtocolsOauth2", "ProtocolsOpenid"] class SSOConnectionUpdateParams(TypedDict, total=False): @@ -21,7 +21,86 @@ class SSOConnectionUpdateParams(TypedDict, total=False): identifier: str """SSO provider identifier (e.g., issuer URL)""" - protocols: Optional[SSOConnectionProtocolParam] - """Protocol configuration for SSO connection""" + protocols: Optional[Protocols] + """Protocol configuration for an SSO connection update. + + Omit a protocol to leave it unchanged. + """ x_client_request_id: Annotated[str, PropertyInfo(alias="X-Client-Request-ID")] + + +class ProtocolsOauth2(TypedDict, total=False): + """OAuth 2.0 protocol configuration for an SSO connection update. + + Each field is tri-state, omit to leave unchanged, send null to clear, send a value to set. + """ + + authorization_endpoint: Optional[str] + """OAuth 2.0 authorization endpoint. Set to null to clear.""" + + authorization_parameters: Optional[Dict[str, str]] + """Custom query parameters appended to authorization redirect URLs. + + Use for non-standard providers (e.g. Google prompt=consent, + access_type=offline). Set to null to clear. + """ + + code_challenge_methods_supported: Optional[SequenceNotStr[str]] + """Supported PKCE code challenge methods. Set to null to clear.""" + + jwks_uri: Optional[str] + """JSON Web Key Set endpoint. Set to null to clear.""" + + registration_endpoint: Optional[str] + """OAuth 2.0 registration endpoint. Set to null to clear.""" + + scopes_supported: Optional[SequenceNotStr[str]] + """Supported OAuth 2.0 scopes. Set to null to clear.""" + + token_endpoint: Optional[str] + """OAuth 2.0 token endpoint. Set to null to clear.""" + + +class ProtocolsOpenid(TypedDict, total=False): + """OpenID Connect protocol configuration for an SSO connection update. + + Each field is tri-state, omit to leave unchanged, send null to clear, send a value to set. + """ + + scopes: Optional[SequenceNotStr[str]] + """Additional OIDC scopes to request from this provider during authentication (e.g. + + "groups"). Merged with the default scopes (openid, profile, email). Set to null + to clear. + """ + + user_identifier_claim: Optional[str] + """ + Name of a top-level string claim in the provider's ID Token to use as the user + identifier on user creation. Set to null to clear. + """ + + userinfo_endpoint: Optional[str] + """OpenID Connect UserInfo endpoint. Set to null to clear.""" + + +class Protocols(TypedDict, total=False): + """Protocol configuration for an SSO connection update. + + Omit a protocol to leave it unchanged. + """ + + oauth2: Optional[ProtocolsOauth2] + """OAuth 2.0 protocol configuration for an SSO connection update. + + Each field is tri-state, omit to leave unchanged, send null to clear, send a + value to set. + """ + + openid: Optional[ProtocolsOpenid] + """OpenID Connect protocol configuration for an SSO connection update. + + Each field is tri-state, omit to leave unchanged, send null to clear, send a + value to set. + """ diff --git a/src/keycardai_api/types/zones/policies/policy_version.py b/src/keycardai_api/types/zones/policies/policy_version.py index f9982be..d8683af 100644 --- a/src/keycardai_api/types/zones/policies/policy_version.py +++ b/src/keycardai_api/types/zones/policies/policy_version.py @@ -43,7 +43,9 @@ class PolicyVersion(BaseModel): """Cedar policy in JSON representation. Populated by default and when `format=json` is passed; null when `format=cedar` - narrows the response to the text representation only. + narrows the response to the text representation only. Serialized verbatim from + the stored Cedar so the order of `staticPolicies` matches the source policy + order (ACC-613). """ cedar_raw: Optional[str] = None diff --git a/src/keycardai_api/types/zones/resource_list_params.py b/src/keycardai_api/types/zones/resource_list_params.py index 05e841a..04dacee 100644 --- a/src/keycardai_api/types/zones/resource_list_params.py +++ b/src/keycardai_api/types/zones/resource_list_params.py @@ -5,6 +5,7 @@ from typing import List, Union from typing_extensions import Literal, Annotated, TypedDict +from ..._types import SequenceNotStr from ..._utils import PropertyInfo __all__ = ["ResourceListParams"] @@ -22,6 +23,9 @@ class ResourceListParams(TypedDict, total=False): expand: Annotated[Union[Literal["total_count"], List[Literal["total_count"]]], PropertyInfo(alias="expand[]")] + filter_identifier: Annotated[Union[str, SequenceNotStr[str]], PropertyInfo(alias="filter[identifier]")] + """Filter by exact resource identifier""" + identifier: str """Filter resources by identifier""" diff --git a/src/keycardai_api/types/zones/user_list_params.py b/src/keycardai_api/types/zones/user_list_params.py index dfcc914..b95f1d2 100644 --- a/src/keycardai_api/types/zones/user_list_params.py +++ b/src/keycardai_api/types/zones/user_list_params.py @@ -35,6 +35,9 @@ class UserListParams(TypedDict, total=False): Repeatable, max 100. Mutually exclusive with after/before. """ + filter_identifier: Annotated[Union[str, SequenceNotStr[str]], PropertyInfo(alias="filter[identifier]")] + """Filter by exact user identifier""" + limit: int """Maximum number of items to return""" diff --git a/tests/api_resources/organizations/test_sso_connection.py b/tests/api_resources/organizations/test_sso_connection.py index 8be8143..dee8785 100644 --- a/tests/api_resources/organizations/test_sso_connection.py +++ b/tests/api_resources/organizations/test_sso_connection.py @@ -90,13 +90,18 @@ def test_method_update_with_all_params(self, client: KeycardAPI) -> None: protocols={ "oauth2": { "authorization_endpoint": "https://example.com", + "authorization_parameters": {"foo": "string"}, "code_challenge_methods_supported": ["string"], "jwks_uri": "https://example.com", "registration_endpoint": "https://example.com", "scopes_supported": ["string"], "token_endpoint": "https://example.com", }, - "openid": {"userinfo_endpoint": "https://example.com"}, + "openid": { + "scopes": ["string"], + "user_identifier_claim": "user_identifier_claim", + "userinfo_endpoint": "https://example.com", + }, }, x_client_request_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) @@ -208,13 +213,18 @@ def test_method_enable_with_all_params(self, client: KeycardAPI) -> None: protocols={ "oauth2": { "authorization_endpoint": "https://example.com", + "authorization_parameters": {"foo": "string"}, "code_challenge_methods_supported": ["string"], "jwks_uri": "https://example.com", "registration_endpoint": "https://example.com", "scopes_supported": ["string"], "token_endpoint": "https://example.com", }, - "openid": {"userinfo_endpoint": "https://example.com"}, + "openid": { + "scopes": ["string"], + "user_identifier_claim": "user_identifier_claim", + "userinfo_endpoint": "https://example.com", + }, }, x_client_request_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) @@ -337,13 +347,18 @@ async def test_method_update_with_all_params(self, async_client: AsyncKeycardAPI protocols={ "oauth2": { "authorization_endpoint": "https://example.com", + "authorization_parameters": {"foo": "string"}, "code_challenge_methods_supported": ["string"], "jwks_uri": "https://example.com", "registration_endpoint": "https://example.com", "scopes_supported": ["string"], "token_endpoint": "https://example.com", }, - "openid": {"userinfo_endpoint": "https://example.com"}, + "openid": { + "scopes": ["string"], + "user_identifier_claim": "user_identifier_claim", + "userinfo_endpoint": "https://example.com", + }, }, x_client_request_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) @@ -455,13 +470,18 @@ async def test_method_enable_with_all_params(self, async_client: AsyncKeycardAPI protocols={ "oauth2": { "authorization_endpoint": "https://example.com", + "authorization_parameters": {"foo": "string"}, "code_challenge_methods_supported": ["string"], "jwks_uri": "https://example.com", "registration_endpoint": "https://example.com", "scopes_supported": ["string"], "token_endpoint": "https://example.com", }, - "openid": {"userinfo_endpoint": "https://example.com"}, + "openid": { + "scopes": ["string"], + "user_identifier_claim": "user_identifier_claim", + "userinfo_endpoint": "https://example.com", + }, }, x_client_request_id="182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e", ) diff --git a/tests/api_resources/zones/test_resources.py b/tests/api_resources/zones/test_resources.py index da273d4..4e820a7 100644 --- a/tests/api_resources/zones/test_resources.py +++ b/tests/api_resources/zones/test_resources.py @@ -234,6 +234,7 @@ def test_method_list_with_all_params(self, client: KeycardAPI) -> None: before="x", credential_provider_id="credentialProviderId", expand="total_count", + filter_identifier="string", identifier="identifier", limit=1, slug="slug", @@ -546,6 +547,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncKeycardAPI) before="x", credential_provider_id="credentialProviderId", expand="total_count", + filter_identifier="string", identifier="identifier", limit=1, slug="slug", diff --git a/tests/api_resources/zones/test_users.py b/tests/api_resources/zones/test_users.py index 1a256ef..ffc908a 100644 --- a/tests/api_resources/zones/test_users.py +++ b/tests/api_resources/zones/test_users.py @@ -87,6 +87,7 @@ def test_method_list_with_all_params(self, client: KeycardAPI) -> None: expand="total_count", filter_email="dev@stainless.com", filter_id="string", + filter_identifier="string", limit=1, query="x", query_email="x", @@ -205,6 +206,7 @@ async def test_method_list_with_all_params(self, async_client: AsyncKeycardAPI) expand="total_count", filter_email="dev@stainless.com", filter_id="string", + filter_identifier="string", limit=1, query="x", query_email="x",