From d7a7645b4f42e5d57149eaaa1c2f5c8ebc68db30 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 13 May 2026 02:41:09 +0000 Subject: [PATCH 1/4] ci: pin GitHub Actions to commit SHAs Pin all GitHub Actions referenced in generated workflows (both first-party `actions/*` and third-party) to immutable commit SHAs. Updating pinned actions is now a deliberate codegen-side bump rather than implicit on every workflow run. --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/publish-pypi.yml | 2 +- .github/workflows/release-doctor.yml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fafebca7..ae545691 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/kernel-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: (github.event_name == 'push' || github.event.pull_request.head.repo.fork) && (github.event_name != 'push' || github.event.head_commit.message != 'codegen metadata') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | @@ -46,7 +46,7 @@ jobs: id-token: write runs-on: ${{ github.repository == 'stainless-sdks/kernel-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | @@ -67,7 +67,7 @@ jobs: github.repository == 'stainless-sdks/kernel-python' && !startsWith(github.ref, 'refs/heads/stl/') id: github-oidc - uses: actions/github-script@v8 + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: script: core.setOutput('github_token', await core.getIDToken()); @@ -87,7 +87,7 @@ jobs: runs-on: ${{ github.repository == 'stainless-sdks/kernel-python' && 'depot-ubuntu-24.04' || 'ubuntu-latest' }} if: github.event_name == 'push' || github.event.pull_request.head.repo.fork steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | diff --git a/.github/workflows/publish-pypi.yml b/.github/workflows/publish-pypi.yml index 2e95b5a9..2e7e7190 100644 --- a/.github/workflows/publish-pypi.yml +++ b/.github/workflows/publish-pypi.yml @@ -14,7 +14,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Install Rye run: | diff --git a/.github/workflows/release-doctor.yml b/.github/workflows/release-doctor.yml index 48941b69..057d4a7f 100644 --- a/.github/workflows/release-doctor.yml +++ b/.github/workflows/release-doctor.yml @@ -12,7 +12,7 @@ jobs: if: github.repository == 'kernel/kernel-python-sdk' && (github.event_name == 'push' || github.event_name == 'workflow_dispatch' || startsWith(github.head_ref, 'release-please') || github.head_ref == 'next') steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: Check release environment run: | From 4f16fb073e0d295fd962e8a8aabd55bdf3144e00 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 18:20:27 +0000 Subject: [PATCH 2/4] feat: Polish start URL OpenAPI descriptions --- .stats.yml | 4 +-- src/kernel/resources/browser_pools.py | 32 +++++++------------ src/kernel/resources/browsers/browsers.py | 16 ++++------ src/kernel/types/browser_create_params.py | 8 ++--- src/kernel/types/browser_create_response.py | 5 +-- src/kernel/types/browser_list_response.py | 5 +-- src/kernel/types/browser_pool.py | 8 ++--- .../types/browser_pool_acquire_response.py | 5 +-- .../types/browser_pool_create_params.py | 8 ++--- .../types/browser_pool_update_params.py | 8 ++--- src/kernel/types/browser_retrieve_response.py | 5 +-- src/kernel/types/browser_update_response.py | 5 +-- .../invocation_list_browsers_response.py | 5 +-- 13 files changed, 38 insertions(+), 76 deletions(-) diff --git a/.stats.yml b/.stats.yml index 7915e042..35cab471 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-a33e59aa1758ba51f13538838ecd70b0a23ed69739b3022e8c2ce0622e42b904.yml -openapi_spec_hash: c042d2f6880c927be09aa9fa79d7241e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-b7a19ff1fbd93322c8cffcd0b397ce2536ca8bff91594e0081bd030d4bec879f.yml +openapi_spec_hash: 490520e6f0a8b1ebc89e9c0add46082d config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/kernel/resources/browser_pools.py b/src/kernel/resources/browser_pools.py index 10b23923..682b2936 100644 --- a/src/kernel/resources/browser_pools.py +++ b/src/kernel/resources/browser_pools.py @@ -110,11 +110,9 @@ def create( proxy_id: Optional proxy to associate to the browser session. Must reference a proxy belonging to the caller's org. - start_url: Optional URL to navigate to when a new browser is warmed into the pool. - Best-effort: failures to navigate do not fail pool fill. Only applied to - newly-warmed browsers — browsers reused via release/acquire keep whatever URL - the previous lease left them on. Accepts any URL Chromium can resolve, including - chrome:// pages. + start_url: Optional URL to open when a browser is created for the pool. Navigation is + best-effort, so navigation failures do not prevent the pool from filling. Reused + browsers keep the page left by the previous lease. stealth: If true, launches the browser in stealth mode to reduce detection by anti-bot mechanisms. @@ -261,11 +259,9 @@ def update( proxy_id: Optional proxy to associate to the browser session. Must reference a proxy belonging to the caller's org. - start_url: Optional URL to navigate to when a new browser is warmed into the pool. - Best-effort: failures to navigate do not fail pool fill. Only applied to - newly-warmed browsers — browsers reused via release/acquire keep whatever URL - the previous lease left them on. Accepts any URL Chromium can resolve, including - chrome:// pages. + start_url: Optional URL to open when a browser is created for the pool. Navigation is + best-effort, so navigation failures do not prevent the pool from filling. Reused + browsers keep the page left by the previous lease. stealth: If true, launches the browser in stealth mode to reduce detection by anti-bot mechanisms. @@ -588,11 +584,9 @@ async def create( proxy_id: Optional proxy to associate to the browser session. Must reference a proxy belonging to the caller's org. - start_url: Optional URL to navigate to when a new browser is warmed into the pool. - Best-effort: failures to navigate do not fail pool fill. Only applied to - newly-warmed browsers — browsers reused via release/acquire keep whatever URL - the previous lease left them on. Accepts any URL Chromium can resolve, including - chrome:// pages. + start_url: Optional URL to open when a browser is created for the pool. Navigation is + best-effort, so navigation failures do not prevent the pool from filling. Reused + browsers keep the page left by the previous lease. stealth: If true, launches the browser in stealth mode to reduce detection by anti-bot mechanisms. @@ -739,11 +733,9 @@ async def update( proxy_id: Optional proxy to associate to the browser session. Must reference a proxy belonging to the caller's org. - start_url: Optional URL to navigate to when a new browser is warmed into the pool. - Best-effort: failures to navigate do not fail pool fill. Only applied to - newly-warmed browsers — browsers reused via release/acquire keep whatever URL - the previous lease left them on. Accepts any URL Chromium can resolve, including - chrome:// pages. + start_url: Optional URL to open when a browser is created for the pool. Navigation is + best-effort, so navigation failures do not prevent the pool from filling. Reused + browsers keep the page left by the previous lease. stealth: If true, launches the browser in stealth mode to reduce detection by anti-bot mechanisms. diff --git a/src/kernel/resources/browsers/browsers.py b/src/kernel/resources/browsers/browsers.py index d1dba086..82ee8b85 100644 --- a/src/kernel/resources/browsers/browsers.py +++ b/src/kernel/resources/browsers/browsers.py @@ -197,11 +197,9 @@ def create( proxy_id: Optional proxy to associate to the browser session. Must reference a proxy belonging to the caller's org. - start_url: Optional URL to navigate to immediately after the browser is created. - Best-effort: failures to navigate do not fail browser creation. Any pre-existing - tabs are reduced to a single tab which is then navigated. Accepts any URL - Chromium can resolve, including chrome:// pages. Ignored when reusing an - existing persistent session. + start_url: Optional URL to open when the browser session is created. Navigation is + best-effort, so navigation failures do not prevent the session from being + created. stealth: If true, launches the browser in stealth mode to reduce detection by anti-bot mechanisms. @@ -763,11 +761,9 @@ async def create( proxy_id: Optional proxy to associate to the browser session. Must reference a proxy belonging to the caller's org. - start_url: Optional URL to navigate to immediately after the browser is created. - Best-effort: failures to navigate do not fail browser creation. Any pre-existing - tabs are reduced to a single tab which is then navigated. Accepts any URL - Chromium can resolve, including chrome:// pages. Ignored when reusing an - existing persistent session. + start_url: Optional URL to open when the browser session is created. Navigation is + best-effort, so navigation failures do not prevent the session from being + created. stealth: If true, launches the browser in stealth mode to reduce detection by anti-bot mechanisms. diff --git a/src/kernel/types/browser_create_params.py b/src/kernel/types/browser_create_params.py index 1a4493f0..399ded4c 100644 --- a/src/kernel/types/browser_create_params.py +++ b/src/kernel/types/browser_create_params.py @@ -58,12 +58,10 @@ class BrowserCreateParams(TypedDict, total=False): """ start_url: str - """Optional URL to navigate to immediately after the browser is created. + """Optional URL to open when the browser session is created. - Best-effort: failures to navigate do not fail browser creation. Any pre-existing - tabs are reduced to a single tab which is then navigated. Accepts any URL - Chromium can resolve, including chrome:// pages. Ignored when reusing an - existing persistent session. + Navigation is best-effort, so navigation failures do not prevent the session + from being created. """ stealth: bool diff --git a/src/kernel/types/browser_create_response.py b/src/kernel/types/browser_create_response.py index e63a6896..1c30ee63 100644 --- a/src/kernel/types/browser_create_response.py +++ b/src/kernel/types/browser_create_response.py @@ -69,10 +69,7 @@ class BrowserCreateResponse(BaseModel): """ID of the proxy associated with this browser session, if any.""" start_url: Optional[str] = None - """URL the session was asked to navigate to on creation, if any. - - Recorded for debugging — navigation is best-effort and may have failed. - """ + """Start URL requested for the session, if provided.""" usage: Optional[BrowserUsage] = None """Session usage metrics.""" diff --git a/src/kernel/types/browser_list_response.py b/src/kernel/types/browser_list_response.py index de37e26f..2a172671 100644 --- a/src/kernel/types/browser_list_response.py +++ b/src/kernel/types/browser_list_response.py @@ -69,10 +69,7 @@ class BrowserListResponse(BaseModel): """ID of the proxy associated with this browser session, if any.""" start_url: Optional[str] = None - """URL the session was asked to navigate to on creation, if any. - - Recorded for debugging — navigation is best-effort and may have failed. - """ + """Start URL requested for the session, if provided.""" usage: Optional[BrowserUsage] = None """Session usage metrics.""" diff --git a/src/kernel/types/browser_pool.py b/src/kernel/types/browser_pool.py index a691d0eb..e456fca2 100644 --- a/src/kernel/types/browser_pool.py +++ b/src/kernel/types/browser_pool.py @@ -64,12 +64,10 @@ class BrowserPoolConfig(BaseModel): """ start_url: Optional[str] = None - """Optional URL to navigate to when a new browser is warmed into the pool. + """Optional URL to open when a browser is created for the pool. - Best-effort: failures to navigate do not fail pool fill. Only applied to - newly-warmed browsers — browsers reused via release/acquire keep whatever URL - the previous lease left them on. Accepts any URL Chromium can resolve, including - chrome:// pages. + Navigation is best-effort, so navigation failures do not prevent the pool from + filling. Reused browsers keep the page left by the previous lease. """ stealth: Optional[bool] = None diff --git a/src/kernel/types/browser_pool_acquire_response.py b/src/kernel/types/browser_pool_acquire_response.py index cff8286d..91ea02e7 100644 --- a/src/kernel/types/browser_pool_acquire_response.py +++ b/src/kernel/types/browser_pool_acquire_response.py @@ -69,10 +69,7 @@ class BrowserPoolAcquireResponse(BaseModel): """ID of the proxy associated with this browser session, if any.""" start_url: Optional[str] = None - """URL the session was asked to navigate to on creation, if any. - - Recorded for debugging — navigation is best-effort and may have failed. - """ + """Start URL requested for the session, if provided.""" usage: Optional[BrowserUsage] = None """Session usage metrics.""" diff --git a/src/kernel/types/browser_pool_create_params.py b/src/kernel/types/browser_pool_create_params.py index 99d6c9cd..bc08c3f2 100644 --- a/src/kernel/types/browser_pool_create_params.py +++ b/src/kernel/types/browser_pool_create_params.py @@ -63,12 +63,10 @@ class BrowserPoolCreateParams(TypedDict, total=False): """ start_url: str - """Optional URL to navigate to when a new browser is warmed into the pool. + """Optional URL to open when a browser is created for the pool. - Best-effort: failures to navigate do not fail pool fill. Only applied to - newly-warmed browsers — browsers reused via release/acquire keep whatever URL - the previous lease left them on. Accepts any URL Chromium can resolve, including - chrome:// pages. + Navigation is best-effort, so navigation failures do not prevent the pool from + filling. Reused browsers keep the page left by the previous lease. """ stealth: bool diff --git a/src/kernel/types/browser_pool_update_params.py b/src/kernel/types/browser_pool_update_params.py index 5b069c4c..043eaf85 100644 --- a/src/kernel/types/browser_pool_update_params.py +++ b/src/kernel/types/browser_pool_update_params.py @@ -69,12 +69,10 @@ class BrowserPoolUpdateParams(TypedDict, total=False): """ start_url: str - """Optional URL to navigate to when a new browser is warmed into the pool. + """Optional URL to open when a browser is created for the pool. - Best-effort: failures to navigate do not fail pool fill. Only applied to - newly-warmed browsers — browsers reused via release/acquire keep whatever URL - the previous lease left them on. Accepts any URL Chromium can resolve, including - chrome:// pages. + Navigation is best-effort, so navigation failures do not prevent the pool from + filling. Reused browsers keep the page left by the previous lease. """ stealth: bool diff --git a/src/kernel/types/browser_retrieve_response.py b/src/kernel/types/browser_retrieve_response.py index 80a96d36..63f4da9d 100644 --- a/src/kernel/types/browser_retrieve_response.py +++ b/src/kernel/types/browser_retrieve_response.py @@ -69,10 +69,7 @@ class BrowserRetrieveResponse(BaseModel): """ID of the proxy associated with this browser session, if any.""" start_url: Optional[str] = None - """URL the session was asked to navigate to on creation, if any. - - Recorded for debugging — navigation is best-effort and may have failed. - """ + """Start URL requested for the session, if provided.""" usage: Optional[BrowserUsage] = None """Session usage metrics.""" diff --git a/src/kernel/types/browser_update_response.py b/src/kernel/types/browser_update_response.py index 4d1f61bc..2e30f49d 100644 --- a/src/kernel/types/browser_update_response.py +++ b/src/kernel/types/browser_update_response.py @@ -69,10 +69,7 @@ class BrowserUpdateResponse(BaseModel): """ID of the proxy associated with this browser session, if any.""" start_url: Optional[str] = None - """URL the session was asked to navigate to on creation, if any. - - Recorded for debugging — navigation is best-effort and may have failed. - """ + """Start URL requested for the session, if provided.""" usage: Optional[BrowserUsage] = None """Session usage metrics.""" diff --git a/src/kernel/types/invocation_list_browsers_response.py b/src/kernel/types/invocation_list_browsers_response.py index 71c22a7a..c7b9e394 100644 --- a/src/kernel/types/invocation_list_browsers_response.py +++ b/src/kernel/types/invocation_list_browsers_response.py @@ -69,10 +69,7 @@ class Browser(BaseModel): """ID of the proxy associated with this browser session, if any.""" start_url: Optional[str] = None - """URL the session was asked to navigate to on creation, if any. - - Recorded for debugging — navigation is best-effort and may have failed. - """ + """Start URL requested for the session, if provided.""" usage: Optional[BrowserUsage] = None """Session usage metrics.""" From 9a0655efbeef25e4929397b04f492644339f839e Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 20:32:29 +0000 Subject: [PATCH 3/4] feat: Add health check and auto-reauth controls for managed auth connections --- .stats.yml | 2 +- src/kernel/resources/auth/connections.py | 70 +++++++++++++++++++ .../types/auth/connection_create_params.py | 20 ++++++ .../types/auth/connection_update_params.py | 20 ++++++ src/kernel/types/auth/managed_auth.py | 21 ++++++ tests/api_resources/auth/test_connections.py | 8 +++ 6 files changed, 140 insertions(+), 1 deletion(-) diff --git a/.stats.yml b/.stats.yml index 35cab471..6b78eac1 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 112 openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel/kernel-b7a19ff1fbd93322c8cffcd0b397ce2536ca8bff91594e0081bd030d4bec879f.yml -openapi_spec_hash: 490520e6f0a8b1ebc89e9c0add46082d +openapi_spec_hash: 9dd204b37a357b19032aea9eb4496645 config_hash: 08d55086449943a8fec212b870061a3f diff --git a/src/kernel/resources/auth/connections.py b/src/kernel/resources/auth/connections.py index 4befc6e9..dc912aba 100644 --- a/src/kernel/resources/auth/connections.py +++ b/src/kernel/resources/auth/connections.py @@ -62,8 +62,10 @@ def create( domain: str, profile_name: str, allowed_domains: SequenceNotStr[str] | Omit = omit, + auto_reauth: bool | Omit = omit, credential: connection_create_params.Credential | Omit = omit, health_check_interval: int | Omit = omit, + health_checks: bool | Omit = omit, login_url: str | Omit = omit, proxy: connection_create_params.Proxy | Omit = omit, record_session: bool | Omit = omit, @@ -105,6 +107,15 @@ def create( - OneLogin: \\**.onelogin.com - Ping Identity: _.pingone.com, _.pingidentity.com + auto_reauth: Whether to permit automatic re-authentication when a scheduled health check + detects an expired session. This is an opt-in flag only — it does not check + whether re-auth is actually feasible. Even when true, re-auth only runs when the + system has what it needs to perform it (for example, saved credentials for the + required login fields), and only after a scheduled health check detects an + expired session — so this flag has no effect when `health_checks` is false. When + false, expired sessions are marked as `NEEDS_AUTH` instead of attempting + re-auth. Defaults to true. + credential: Reference to credentials for the auth connection. Use one of: @@ -118,6 +129,11 @@ def create( depends on your plan: Enterprise: 300 (5 minutes), Startup: 1200 (20 minutes), Hobbyist: 3600 (1 hour). + health_checks: Whether to enable periodic health checks. When false, the system will not + automatically verify authentication status, and `auto_reauth` has no effect on + the automatic flow (since re-auth is only triggered by a failed scheduled health + check). Defaults to true. + login_url: Optional login page URL to skip discovery proxy: Proxy selection. Provide either id or name. The proxy must belong to the @@ -144,8 +160,10 @@ def create( "domain": domain, "profile_name": profile_name, "allowed_domains": allowed_domains, + "auto_reauth": auto_reauth, "credential": credential, "health_check_interval": health_check_interval, + "health_checks": health_checks, "login_url": login_url, "proxy": proxy, "record_session": record_session, @@ -199,8 +217,10 @@ def update( id: str, *, allowed_domains: SequenceNotStr[str] | Omit = omit, + auto_reauth: bool | Omit = omit, credential: connection_update_params.Credential | Omit = omit, health_check_interval: int | Omit = omit, + health_checks: bool | Omit = omit, login_url: str | Omit = omit, proxy: connection_update_params.Proxy | Omit = omit, record_session: bool | Omit = omit, @@ -220,6 +240,14 @@ def update( Args: allowed_domains: Additional domains valid for this auth flow (replaces existing list) + auto_reauth: Whether automatic re-authentication is permitted for this connection. This is an + opt-in flag only — it does not check whether re-auth is actually feasible. Even + when true, re-auth only runs when the system has what it needs to perform it + (for example, saved credentials for the required login fields), and only after a + scheduled health check detects an expired session — so this flag has no effect + when `health_checks` is false. When false, expired sessions detected by a health + check are marked as `NEEDS_AUTH` instead of attempting re-auth. + credential: Reference to credentials for the auth connection. Use one of: @@ -229,6 +257,11 @@ def update( health_check_interval: Interval in seconds between automatic health checks + health_checks: Whether periodic health checks are enabled. When set to false, the system will + not automatically verify authentication status, and `auto_reauth` has no effect + on the automatic flow (since re-auth is only triggered by a failed scheduled + health check). + login_url: Login page URL. Set to empty string to clear. proxy: Proxy selection. Provide either id or name. The proxy must belong to the @@ -253,8 +286,10 @@ def update( body=maybe_transform( { "allowed_domains": allowed_domains, + "auto_reauth": auto_reauth, "credential": credential, "health_check_interval": health_check_interval, + "health_checks": health_checks, "login_url": login_url, "proxy": proxy, "record_session": record_session, @@ -544,8 +579,10 @@ async def create( domain: str, profile_name: str, allowed_domains: SequenceNotStr[str] | Omit = omit, + auto_reauth: bool | Omit = omit, credential: connection_create_params.Credential | Omit = omit, health_check_interval: int | Omit = omit, + health_checks: bool | Omit = omit, login_url: str | Omit = omit, proxy: connection_create_params.Proxy | Omit = omit, record_session: bool | Omit = omit, @@ -587,6 +624,15 @@ async def create( - OneLogin: \\**.onelogin.com - Ping Identity: _.pingone.com, _.pingidentity.com + auto_reauth: Whether to permit automatic re-authentication when a scheduled health check + detects an expired session. This is an opt-in flag only — it does not check + whether re-auth is actually feasible. Even when true, re-auth only runs when the + system has what it needs to perform it (for example, saved credentials for the + required login fields), and only after a scheduled health check detects an + expired session — so this flag has no effect when `health_checks` is false. When + false, expired sessions are marked as `NEEDS_AUTH` instead of attempting + re-auth. Defaults to true. + credential: Reference to credentials for the auth connection. Use one of: @@ -600,6 +646,11 @@ async def create( depends on your plan: Enterprise: 300 (5 minutes), Startup: 1200 (20 minutes), Hobbyist: 3600 (1 hour). + health_checks: Whether to enable periodic health checks. When false, the system will not + automatically verify authentication status, and `auto_reauth` has no effect on + the automatic flow (since re-auth is only triggered by a failed scheduled health + check). Defaults to true. + login_url: Optional login page URL to skip discovery proxy: Proxy selection. Provide either id or name. The proxy must belong to the @@ -626,8 +677,10 @@ async def create( "domain": domain, "profile_name": profile_name, "allowed_domains": allowed_domains, + "auto_reauth": auto_reauth, "credential": credential, "health_check_interval": health_check_interval, + "health_checks": health_checks, "login_url": login_url, "proxy": proxy, "record_session": record_session, @@ -681,8 +734,10 @@ async def update( id: str, *, allowed_domains: SequenceNotStr[str] | Omit = omit, + auto_reauth: bool | Omit = omit, credential: connection_update_params.Credential | Omit = omit, health_check_interval: int | Omit = omit, + health_checks: bool | Omit = omit, login_url: str | Omit = omit, proxy: connection_update_params.Proxy | Omit = omit, record_session: bool | Omit = omit, @@ -702,6 +757,14 @@ async def update( Args: allowed_domains: Additional domains valid for this auth flow (replaces existing list) + auto_reauth: Whether automatic re-authentication is permitted for this connection. This is an + opt-in flag only — it does not check whether re-auth is actually feasible. Even + when true, re-auth only runs when the system has what it needs to perform it + (for example, saved credentials for the required login fields), and only after a + scheduled health check detects an expired session — so this flag has no effect + when `health_checks` is false. When false, expired sessions detected by a health + check are marked as `NEEDS_AUTH` instead of attempting re-auth. + credential: Reference to credentials for the auth connection. Use one of: @@ -711,6 +774,11 @@ async def update( health_check_interval: Interval in seconds between automatic health checks + health_checks: Whether periodic health checks are enabled. When set to false, the system will + not automatically verify authentication status, and `auto_reauth` has no effect + on the automatic flow (since re-auth is only triggered by a failed scheduled + health check). + login_url: Login page URL. Set to empty string to clear. proxy: Proxy selection. Provide either id or name. The proxy must belong to the @@ -735,8 +803,10 @@ async def update( body=await async_maybe_transform( { "allowed_domains": allowed_domains, + "auto_reauth": auto_reauth, "credential": credential, "health_check_interval": health_check_interval, + "health_checks": health_checks, "login_url": login_url, "proxy": proxy, "record_session": record_session, diff --git a/src/kernel/types/auth/connection_create_params.py b/src/kernel/types/auth/connection_create_params.py index bdd22681..acde944c 100644 --- a/src/kernel/types/auth/connection_create_params.py +++ b/src/kernel/types/auth/connection_create_params.py @@ -40,6 +40,18 @@ class ConnectionCreateParams(TypedDict, total=False): - Ping Identity: _.pingone.com, _.pingidentity.com """ + auto_reauth: bool + """ + Whether to permit automatic re-authentication when a scheduled health check + detects an expired session. This is an opt-in flag only — it does not check + whether re-auth is actually feasible. Even when true, re-auth only runs when the + system has what it needs to perform it (for example, saved credentials for the + required login fields), and only after a scheduled health check detects an + expired session — so this flag has no effect when `health_checks` is false. When + false, expired sessions are marked as `NEEDS_AUTH` instead of attempting + re-auth. Defaults to true. + """ + credential: Credential """Reference to credentials for the auth connection. Use one of: @@ -57,6 +69,14 @@ class ConnectionCreateParams(TypedDict, total=False): Startup: 1200 (20 minutes), Hobbyist: 3600 (1 hour). """ + health_checks: bool + """Whether to enable periodic health checks. + + When false, the system will not automatically verify authentication status, and + `auto_reauth` has no effect on the automatic flow (since re-auth is only + triggered by a failed scheduled health check). Defaults to true. + """ + login_url: str """Optional login page URL to skip discovery""" diff --git a/src/kernel/types/auth/connection_update_params.py b/src/kernel/types/auth/connection_update_params.py index 23832778..8875f609 100644 --- a/src/kernel/types/auth/connection_update_params.py +++ b/src/kernel/types/auth/connection_update_params.py @@ -13,6 +13,18 @@ class ConnectionUpdateParams(TypedDict, total=False): allowed_domains: SequenceNotStr[str] """Additional domains valid for this auth flow (replaces existing list)""" + auto_reauth: bool + """Whether automatic re-authentication is permitted for this connection. + + This is an opt-in flag only — it does not check whether re-auth is actually + feasible. Even when true, re-auth only runs when the system has what it needs to + perform it (for example, saved credentials for the required login fields), and + only after a scheduled health check detects an expired session — so this flag + has no effect when `health_checks` is false. When false, expired sessions + detected by a health check are marked as `NEEDS_AUTH` instead of attempting + re-auth. + """ + credential: Credential """Reference to credentials for the auth connection. Use one of: @@ -24,6 +36,14 @@ class ConnectionUpdateParams(TypedDict, total=False): health_check_interval: int """Interval in seconds between automatic health checks""" + health_checks: bool + """Whether periodic health checks are enabled. + + When set to false, the system will not automatically verify authentication + status, and `auto_reauth` has no effect on the automatic flow (since re-auth is + only triggered by a failed scheduled health check). + """ + login_url: str """Login page URL. Set to empty string to clear.""" diff --git a/src/kernel/types/auth/managed_auth.py b/src/kernel/types/auth/managed_auth.py index 980d0207..893631d4 100644 --- a/src/kernel/types/auth/managed_auth.py +++ b/src/kernel/types/auth/managed_auth.py @@ -166,6 +166,18 @@ class ManagedAuth(BaseModel): - Ping Identity: _.pingone.com, _.pingidentity.com """ + auto_reauth: Optional[bool] = None + """Whether automatic re-authentication is permitted for this connection. + + This is an opt-in flag only — it does not check whether re-auth is actually + feasible. Even when true, re-auth only runs when the system has what it needs to + perform it (for example, saved credentials for the required login fields), and + only after a scheduled health check detects an expired session — so this flag + has no effect when `health_checks` is false. When false, expired sessions + detected by a health check are marked as `NEEDS_AUTH` instead of attempting + re-auth. + """ + browser_session_id: Optional[str] = None """ ID of the underlying browser session driving the current flow (present when flow @@ -236,6 +248,15 @@ class ManagedAuth(BaseModel): Startup: 1200 (20 minutes), Hobbyist: 3600 (1 hour). """ + health_checks: Optional[bool] = None + """Whether periodic health checks are enabled for this connection. + + When false, the system will not automatically verify authentication status, and + `auto_reauth` has no effect on the automatic flow (since re-auth is only + triggered by a failed scheduled health check). Manually triggering a health + check via the API still works regardless of this setting. + """ + hosted_url: Optional[str] = None """URL to redirect user to for hosted login (present when flow in progress)""" diff --git a/tests/api_resources/auth/test_connections.py b/tests/api_resources/auth/test_connections.py index e3da167f..702207fe 100644 --- a/tests/api_resources/auth/test_connections.py +++ b/tests/api_resources/auth/test_connections.py @@ -38,6 +38,7 @@ def test_method_create_with_all_params(self, client: Kernel) -> None: domain="netflix.com", profile_name="user-123", allowed_domains=["login.netflix.com", "auth.netflix.com"], + auto_reauth=True, credential={ "auto": True, "name": "my-netflix-creds", @@ -45,6 +46,7 @@ def test_method_create_with_all_params(self, client: Kernel) -> None: "provider": "my-1p", }, health_check_interval=3600, + health_checks=True, login_url="https://netflix.com/login", proxy={ "id": "id", @@ -139,6 +141,7 @@ def test_method_update_with_all_params(self, client: Kernel) -> None: connection = client.auth.connections.update( id="id", allowed_domains=["login.netflix.com", "auth.netflix.com"], + auto_reauth=True, credential={ "auto": True, "name": "my-netflix-creds", @@ -146,6 +149,7 @@ def test_method_update_with_all_params(self, client: Kernel) -> None: "provider": "my-1p", }, health_check_interval=3600, + health_checks=True, login_url="https://netflix.com/login", proxy={ "id": "id", @@ -447,6 +451,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncKernel) -> domain="netflix.com", profile_name="user-123", allowed_domains=["login.netflix.com", "auth.netflix.com"], + auto_reauth=True, credential={ "auto": True, "name": "my-netflix-creds", @@ -454,6 +459,7 @@ async def test_method_create_with_all_params(self, async_client: AsyncKernel) -> "provider": "my-1p", }, health_check_interval=3600, + health_checks=True, login_url="https://netflix.com/login", proxy={ "id": "id", @@ -548,6 +554,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncKernel) -> connection = await async_client.auth.connections.update( id="id", allowed_domains=["login.netflix.com", "auth.netflix.com"], + auto_reauth=True, credential={ "auto": True, "name": "my-netflix-creds", @@ -555,6 +562,7 @@ async def test_method_update_with_all_params(self, async_client: AsyncKernel) -> "provider": "my-1p", }, health_check_interval=3600, + health_checks=True, login_url="https://netflix.com/login", proxy={ "id": "id", From b863b1a4fd94e39e151038a8cb70e0a75729a210 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 15 May 2026 20:46:35 +0000 Subject: [PATCH 4/4] release: 0.55.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 9 +++++++++ pyproject.toml | 2 +- src/kernel/_version.py | 2 +- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index c3e01e1e..d940b600 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.53.0" + ".": "0.55.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 122a4e88..c5b40016 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 0.55.0 (2026-05-15) + +Full Changelog: [v0.53.0...v0.55.0](https://github.com/kernel/kernel-python-sdk/compare/v0.53.0...v0.55.0) + +### Features + +* Add health check and auto-reauth controls for managed auth connections ([9a0655e](https://github.com/kernel/kernel-python-sdk/commit/9a0655efbeef25e4929397b04f492644339f839e)) +* Polish start URL OpenAPI descriptions ([4f16fb0](https://github.com/kernel/kernel-python-sdk/commit/4f16fb073e0d295fd962e8a8aabd55bdf3144e00)) + ## 0.53.0 (2026-05-12) Full Changelog: [v0.52.0...v0.53.0](https://github.com/kernel/kernel-python-sdk/compare/v0.52.0...v0.53.0) diff --git a/pyproject.toml b/pyproject.toml index 10375b3b..353f3cd9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "kernel" -version = "0.53.0" +version = "0.55.0" description = "The official Python library for the kernel API" dynamic = ["readme"] license = "Apache-2.0" diff --git a/src/kernel/_version.py b/src/kernel/_version.py index 173fc2c2..b2f051b4 100644 --- a/src/kernel/_version.py +++ b/src/kernel/_version.py @@ -1,4 +1,4 @@ # File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. __title__ = "kernel" -__version__ = "0.53.0" # x-release-please-version +__version__ = "0.55.0" # x-release-please-version