Skip to content
Merged
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
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ jobs:
github.repository == 'stainless-sdks/kernel-go' &&
(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: Get GitHub OIDC Token
if: |-
github.repository == 'stainless-sdks/kernel-go' &&
!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());

Expand All @@ -53,10 +53,10 @@ jobs:
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: Setup go
uses: actions/setup-go@v5
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
with:
go-version-file: ./go.mod

Expand All @@ -68,10 +68,10 @@ jobs:
runs-on: ${{ github.repository == 'stainless-sdks/kernel-go' && '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: Setup go
uses: actions/setup-go@v5
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
with:
go-version-file: ./go.mod

Expand Down
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.53.0"
".": "0.55.0"
}
4 changes: 2 additions & 2 deletions .stats.yml
Original file line number Diff line number Diff line change
@@ -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: 9dd204b37a357b19032aea9eb4496645
config_hash: 08d55086449943a8fec212b870061a3f
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## 0.55.0 (2026-05-15)

Full Changelog: [v0.53.0...v0.55.0](https://github.com/kernel/kernel-go-sdk/compare/v0.53.0...v0.55.0)

### Features

* Add health check and auto-reauth controls for managed auth connections ([e381d8e](https://github.com/kernel/kernel-go-sdk/commit/e381d8ed28c0d4fe978c0d27d724c0bc9b43d3d5))
* **client:** optimize json encoder for internal types ([e7f4365](https://github.com/kernel/kernel-go-sdk/commit/e7f436591debbdedd4150a0a4b2fcbdce2320cd1))
* Polish start URL OpenAPI descriptions ([2d82565](https://github.com/kernel/kernel-go-sdk/commit/2d82565e34904922fa4a6b87e076bb1790af43bd))

## 0.53.0 (2026-05-12)

Full Changelog: [v0.52.0...v0.53.0](https://github.com/kernel/kernel-go-sdk/compare/v0.52.0...v0.53.0)
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Or to pin the version:
<!-- x-release-please-start-version -->

```sh
go get -u 'github.com/kernel/kernel-go-sdk@v0.53.0'
go get -u 'github.com/kernel/kernel-go-sdk@v0.55.0'
```

<!-- x-release-please-end -->
Expand Down
43 changes: 43 additions & 0 deletions authconnection.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,14 @@ type ManagedAuth struct {
// - OneLogin: \*.onelogin.com
// - Ping Identity: _.pingone.com, _.pingidentity.com
AllowedDomains []string `json:"allowed_domains"`
// 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.
AutoReauth bool `json:"auto_reauth"`
// ID of the underlying browser session driving the current flow (present when flow
// in progress). Use this to inspect or terminate the browser session via the
// `/browsers` API.
Expand Down Expand Up @@ -298,6 +306,12 @@ type ManagedAuth struct {
// depends on your plan: Enterprise: 300 (5 minutes), Startup: 1200 (20 minutes),
// Hobbyist: 3600 (1 hour).
HealthCheckInterval int64 `json:"health_check_interval" api:"nullable"`
// 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.
HealthChecks bool `json:"health_checks"`
// URL to redirect user to for hosted login (present when flow in progress)
HostedURL string `json:"hosted_url" api:"nullable" format:"uri"`
// Deprecated alias for `last_auth_check_at`. Despite the name, this is the last
Expand Down Expand Up @@ -344,6 +358,7 @@ type ManagedAuth struct {
SaveCredentials respjson.Field
Status respjson.Field
AllowedDomains respjson.Field
AutoReauth respjson.Field
BrowserSessionID respjson.Field
CanReauth respjson.Field
CanReauthReason respjson.Field
Expand All @@ -357,6 +372,7 @@ type ManagedAuth struct {
FlowStep respjson.Field
FlowType respjson.Field
HealthCheckInterval respjson.Field
HealthChecks respjson.Field
HostedURL respjson.Field
LastAuthAt respjson.Field
LastAuthCheckAt respjson.Field
Expand Down Expand Up @@ -583,12 +599,26 @@ type ManagedAuthCreateRequestParam struct {
// Name of the profile to manage authentication for. If the profile does not exist,
// it is created automatically.
ProfileName string `json:"profile_name" api:"required"`
// 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.
AutoReauth param.Opt[bool] `json:"auto_reauth,omitzero"`
// Interval in seconds between automatic health checks. When set, the system
// periodically verifies the authentication status and triggers re-authentication
// if needed. Maximum is 86400 (24 hours). Default is 3600 (1 hour). The minimum
// depends on your plan: Enterprise: 300 (5 minutes), Startup: 1200 (20 minutes),
// Hobbyist: 3600 (1 hour).
HealthCheckInterval param.Opt[int64] `json:"health_check_interval,omitzero"`
// 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.
HealthChecks param.Opt[bool] `json:"health_checks,omitzero"`
// Optional login page URL to skip discovery
LoginURL param.Opt[string] `json:"login_url,omitzero" format:"uri"`
// Whether to record browser sessions for this connection by default. Useful for
Expand Down Expand Up @@ -680,8 +710,21 @@ func (r *ManagedAuthCreateRequestProxyParam) UnmarshalJSON(data []byte) error {

// Request to update an auth connection's configuration
type ManagedAuthUpdateRequestParam struct {
// 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.
AutoReauth param.Opt[bool] `json:"auto_reauth,omitzero"`
// Interval in seconds between automatic health checks
HealthCheckInterval param.Opt[int64] `json:"health_check_interval,omitzero"`
// 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).
HealthChecks param.Opt[bool] `json:"health_checks,omitzero"`
// Login page URL. Set to empty string to clear.
LoginURL param.Opt[string] `json:"login_url,omitzero" format:"uri"`
// Whether to record browser sessions for this connection by default
Expand Down
4 changes: 4 additions & 0 deletions authconnection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ func TestAuthConnectionNewWithOptionalParams(t *testing.T) {
Domain: "netflix.com",
ProfileName: "user-123",
AllowedDomains: []string{"login.netflix.com", "auth.netflix.com"},
AutoReauth: kernel.Bool(true),
Credential: kernel.ManagedAuthCreateRequestCredentialParam{
Auto: kernel.Bool(true),
Name: kernel.String("my-netflix-creds"),
Path: kernel.String("Personal/Netflix"),
Provider: kernel.String("my-1p"),
},
HealthCheckInterval: kernel.Int(3600),
HealthChecks: kernel.Bool(true),
LoginURL: kernel.String("https://netflix.com/login"),
Proxy: kernel.ManagedAuthCreateRequestProxyParam{
ID: kernel.String("id"),
Expand Down Expand Up @@ -98,13 +100,15 @@ func TestAuthConnectionUpdateWithOptionalParams(t *testing.T) {
kernel.AuthConnectionUpdateParams{
ManagedAuthUpdateRequest: kernel.ManagedAuthUpdateRequestParam{
AllowedDomains: []string{"login.netflix.com", "auth.netflix.com"},
AutoReauth: kernel.Bool(true),
Credential: kernel.ManagedAuthUpdateRequestCredentialParam{
Auto: kernel.Bool(true),
Name: kernel.String("my-netflix-creds"),
Path: kernel.String("Personal/Netflix"),
Provider: kernel.String("my-1p"),
},
HealthCheckInterval: kernel.Int(3600),
HealthChecks: kernel.Bool(true),
LoginURL: kernel.String("https://netflix.com/login"),
Proxy: kernel.ManagedAuthUpdateRequestProxyParam{
ID: kernel.String("id"),
Expand Down
20 changes: 7 additions & 13 deletions browser.go
Original file line number Diff line number Diff line change
Expand Up @@ -328,8 +328,7 @@ type BrowserNewResponse struct {
Profile Profile `json:"profile"`
// ID of the proxy associated with this browser session, if any.
ProxyID string `json:"proxy_id"`
// 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.
StartURL string `json:"start_url"`
// Session usage metrics.
Usage BrowserUsage `json:"usage"`
Expand Down Expand Up @@ -415,8 +414,7 @@ type BrowserGetResponse struct {
Profile Profile `json:"profile"`
// ID of the proxy associated with this browser session, if any.
ProxyID string `json:"proxy_id"`
// 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.
StartURL string `json:"start_url"`
// Session usage metrics.
Usage BrowserUsage `json:"usage"`
Expand Down Expand Up @@ -502,8 +500,7 @@ type BrowserUpdateResponse struct {
Profile Profile `json:"profile"`
// ID of the proxy associated with this browser session, if any.
ProxyID string `json:"proxy_id"`
// 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.
StartURL string `json:"start_url"`
// Session usage metrics.
Usage BrowserUsage `json:"usage"`
Expand Down Expand Up @@ -589,8 +586,7 @@ type BrowserListResponse struct {
Profile Profile `json:"profile"`
// ID of the proxy associated with this browser session, if any.
ProxyID string `json:"proxy_id"`
// 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.
StartURL string `json:"start_url"`
// Session usage metrics.
Usage BrowserUsage `json:"usage"`
Expand Down Expand Up @@ -681,11 +677,9 @@ type BrowserNewParams struct {
// Optional proxy to associate to the browser session. Must reference a proxy
// belonging to the caller's org.
ProxyID param.Opt[string] `json:"proxy_id,omitzero"`
// 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.
// 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.
StartURL param.Opt[string] `json:"start_url,omitzero"`
// If true, launches the browser in stealth mode to reduce detection by anti-bot
// mechanisms.
Expand Down
27 changes: 10 additions & 17 deletions browserpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,9 @@ type BrowserPoolBrowserPoolConfig struct {
// Optional proxy to associate to the browser session. Must reference a proxy
// belonging to the caller's org.
ProxyID string `json:"proxy_id"`
// 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.
// 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.
StartURL string `json:"start_url"`
// If true, launches the browser in stealth mode to reduce detection by anti-bot
// mechanisms.
Expand Down Expand Up @@ -284,8 +282,7 @@ type BrowserPoolAcquireResponse struct {
Profile Profile `json:"profile"`
// ID of the proxy associated with this browser session, if any.
ProxyID string `json:"proxy_id"`
// 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.
StartURL string `json:"start_url"`
// Session usage metrics.
Usage BrowserUsage `json:"usage"`
Expand Down Expand Up @@ -351,11 +348,9 @@ type BrowserPoolNewParams struct {
// Optional proxy to associate to the browser session. Must reference a proxy
// belonging to the caller's org.
ProxyID param.Opt[string] `json:"proxy_id,omitzero"`
// 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.
// 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.
StartURL param.Opt[string] `json:"start_url,omitzero"`
// If true, launches the browser in stealth mode to reduce detection by anti-bot
// mechanisms.
Expand Down Expand Up @@ -418,11 +413,9 @@ type BrowserPoolUpdateParams struct {
// Optional proxy to associate to the browser session. Must reference a proxy
// belonging to the caller's org.
ProxyID param.Opt[string] `json:"proxy_id,omitzero"`
// 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.
// 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.
StartURL param.Opt[string] `json:"start_url,omitzero"`
// If true, launches the browser in stealth mode to reduce detection by anti-bot
// mechanisms.
Expand Down
21 changes: 15 additions & 6 deletions internal/encoding/json/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,15 +173,21 @@ import (
// JSON cannot represent cyclic data structures and Marshal does not
// handle them. Passing cyclic structures to Marshal will result in
// an error.
func Marshal(v any) ([]byte, error) {
// EDIT(begin): add optimization options
func Marshal(v any, opts ...Option) ([]byte, error) {
// EDIT(end): add optimization options
e := newEncodeState()
defer encodeStatePool.Put(e)

// SHIM(begin): don't escape HTML by default
err := e.marshal(v, encOpts{escapeHTML: shims.EscapeHTMLByDefault})
// EDIT(begin): don't escape HTML by default, and apply options
encOpts := encOpts{escapeHTML: shims.EscapeHTMLByDefault}
if opts != nil {
encOpts = encOpts.apply(opts...)
}
err := e.marshal(v, encOpts)
// ORIGINAL:
// err := e.marshal(v, encOpts{escapeHTML: true})
// SHIM(end)
// EDIT(end)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -352,6 +358,9 @@ type encOpts struct {
// EDIT(begin): save the timefmt
timefmt string
// EDIT(end)
// EDIT(begin): add optimization to skip compaction
skipCompaction bool
// EDIT(end)
}

type encoderFunc func(e *encodeState, v reflect.Value, opts encOpts)
Expand Down Expand Up @@ -483,7 +492,7 @@ func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
if err == nil {
e.Grow(len(b))
out := e.AvailableBuffer()
out, err = appendCompact(out, b, opts.escapeHTML)
out, err = appendCompact(out, b, opts)
e.Buffer.Write(out)
}
if err != nil {
Expand All @@ -509,7 +518,7 @@ func addrMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
if err == nil {
e.Grow(len(b))
out := e.AvailableBuffer()
out, err = appendCompact(out, b, opts.escapeHTML)
out, err = appendCompact(out, b, opts)
e.Buffer.Write(out)
}
if err != nil {
Expand Down
Loading
Loading