From a291bbe344e9a197085335fbf53a689996032506 Mon Sep 17 00:00:00 2001 From: sjmiller609 <7516283+sjmiller609@users.noreply.github.com> Date: Fri, 7 Aug 2026 18:40:13 +0000 Subject: [PATCH 1/4] Build SDK Stainless-Generated-From: c3154a77aed79d47586b251ff42bd0ae8afccb77 --- .stats.yml | 2 +- api.md | 21 ++ auditlog.go | 3 + auditlogexportdestination.go | 391 ++++++++++++++++++++++++++++++ auditlogexportdestination_test.go | 178 ++++++++++++++ 5 files changed, 594 insertions(+), 1 deletion(-) create mode 100644 auditlogexportdestination.go create mode 100644 auditlogexportdestination_test.go diff --git a/.stats.yml b/.stats.yml index 71c320f..4bb27f8 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1 +1 @@ -configured_endpoints: 127 +configured_endpoints: 133 diff --git a/api.md b/api.md index bbd5b3c..3842c2e 100644 --- a/api.md +++ b/api.md @@ -438,6 +438,27 @@ Methods: - client.AuditLogs.List(ctx context.Context, query kernel.AuditLogListParams) (\*pagination.PageTokenPagination[kernel.AuditLogEntry], error) - client.AuditLogs.ExportChunk(ctx context.Context, query kernel.AuditLogExportChunkParams) (\*http.Response, error) +## ExportDestinations + +Params Types: + +- kernel.CreateAuditLogExportDestinationRequestParam +- kernel.UpdateAuditLogExportDestinationRequestParam + +Response Types: + +- kernel.AuditLogExportDestination +- kernel.AuditLogExportDestinationTestResult + +Methods: + +- client.AuditLogs.ExportDestinations.New(ctx context.Context, body kernel.AuditLogExportDestinationNewParams) (\*kernel.AuditLogExportDestination, error) +- client.AuditLogs.ExportDestinations.Get(ctx context.Context, id string) (\*kernel.AuditLogExportDestination, error) +- client.AuditLogs.ExportDestinations.Update(ctx context.Context, id string, body kernel.AuditLogExportDestinationUpdateParams) (\*kernel.AuditLogExportDestination, error) +- client.AuditLogs.ExportDestinations.List(ctx context.Context, query kernel.AuditLogExportDestinationListParams) (\*pagination.OffsetPagination[kernel.AuditLogExportDestination], error) +- client.AuditLogs.ExportDestinations.Delete(ctx context.Context, id string) error +- client.AuditLogs.ExportDestinations.Test(ctx context.Context, id string) (\*kernel.AuditLogExportDestinationTestResult, error) + # APIKeys Response Types: diff --git a/auditlog.go b/auditlog.go index 9096e7c..665df86 100644 --- a/auditlog.go +++ b/auditlog.go @@ -28,6 +28,8 @@ import ( // the [NewAuditLogService] method instead. type AuditLogService struct { Options []option.RequestOption + // Read audit log records for the authenticated organization. + ExportDestinations AuditLogExportDestinationService } // NewAuditLogService generates a new service that applies the given options to @@ -36,6 +38,7 @@ type AuditLogService struct { func NewAuditLogService(opts ...option.RequestOption) (r AuditLogService) { r = AuditLogService{} r.Options = opts + r.ExportDestinations = NewAuditLogExportDestinationService(opts...) return } diff --git a/auditlogexportdestination.go b/auditlogexportdestination.go new file mode 100644 index 0000000..db967d3 --- /dev/null +++ b/auditlogexportdestination.go @@ -0,0 +1,391 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +package kernel + +import ( + "context" + "errors" + "fmt" + "net/http" + "net/url" + "slices" + "time" + + "github.com/kernel/kernel-go-sdk/internal/apijson" + "github.com/kernel/kernel-go-sdk/internal/apiquery" + shimjson "github.com/kernel/kernel-go-sdk/internal/encoding/json" + "github.com/kernel/kernel-go-sdk/internal/requestconfig" + "github.com/kernel/kernel-go-sdk/option" + "github.com/kernel/kernel-go-sdk/packages/pagination" + "github.com/kernel/kernel-go-sdk/packages/param" + "github.com/kernel/kernel-go-sdk/packages/respjson" +) + +// Read audit log records for the authenticated organization. +// +// AuditLogExportDestinationService contains methods and other services that help +// with interacting with the kernel API. +// +// Note, unlike clients, this service does not read variables from the environment +// automatically. You should not instantiate this service directly, and instead use +// the [NewAuditLogExportDestinationService] method instead. +type AuditLogExportDestinationService struct { + Options []option.RequestOption +} + +// NewAuditLogExportDestinationService generates a new service that applies the +// given options to each request. These options are applied after the parent +// client's options (if there is one), and before any request-specific options. +func NewAuditLogExportDestinationService(opts ...option.RequestOption) (r AuditLogExportDestinationService) { + r = AuditLogExportDestinationService{} + r.Options = opts + return +} + +// Create a paused destination. Activate it with a status update once the +// destination test passes. Requires an active Enterprise plan. +func (r *AuditLogExportDestinationService) New(ctx context.Context, body AuditLogExportDestinationNewParams, opts ...option.RequestOption) (res *AuditLogExportDestination, err error) { + opts = slices.Concat(r.Options, opts) + path := "audit-logs/export/destinations" + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) + return res, err +} + +// Retrieve details for a single audit log export destination by its ID. +func (r *AuditLogExportDestinationService) Get(ctx context.Context, id string, opts ...option.RequestOption) (res *AuditLogExportDestination, err error) { + opts = slices.Concat(r.Options, opts) + if id == "" { + err = errors.New("missing required id parameter") + return nil, err + } + path := fmt.Sprintf("audit-logs/export/destinations/%s", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...) + return res, err +} + +// Apply a partial update to a destination. Requires an active Enterprise plan. +// Returns 409 when the destination was changed concurrently, because the merged +// configuration this request validated is no longer the one that would be stored; +// retry against fresh state. Pausing prevents new delivery attempts, but an S3 +// upload already in progress may complete after the response. +func (r *AuditLogExportDestinationService) Update(ctx context.Context, id string, body AuditLogExportDestinationUpdateParams, opts ...option.RequestOption) (res *AuditLogExportDestination, err error) { + opts = slices.Concat(r.Options, opts) + if id == "" { + err = errors.New("missing required id parameter") + return nil, err + } + path := fmt.Sprintf("audit-logs/export/destinations/%s", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPatch, path, body, &res, opts...) + return res, err +} + +// List audit log export destinations for the organization with pagination support. +func (r *AuditLogExportDestinationService) List(ctx context.Context, query AuditLogExportDestinationListParams, opts ...option.RequestOption) (res *pagination.OffsetPagination[AuditLogExportDestination], err error) { + var raw *http.Response + opts = slices.Concat(r.Options, opts) + opts = append([]option.RequestOption{option.WithResponseInto(&raw)}, opts...) + path := "audit-logs/export/destinations" + cfg, err := requestconfig.NewRequestConfig(ctx, http.MethodGet, path, query, &res, opts...) + if err != nil { + return nil, err + } + err = cfg.Execute() + if err != nil { + return nil, err + } + res.SetPageConfig(cfg, raw) + return res, nil +} + +// List audit log export destinations for the organization with pagination support. +func (r *AuditLogExportDestinationService) ListAutoPaging(ctx context.Context, query AuditLogExportDestinationListParams, opts ...option.RequestOption) *pagination.OffsetPaginationAutoPager[AuditLogExportDestination] { + return pagination.NewOffsetPaginationAutoPager(r.List(ctx, query, opts...)) +} + +// Soft delete the destination and prevent new delivery attempts. An S3 upload +// already in progress may complete after the response. +func (r *AuditLogExportDestinationService) Delete(ctx context.Context, id string, opts ...option.RequestOption) (err error) { + opts = slices.Concat(r.Options, opts) + opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...) + if id == "" { + err = errors.New("missing required id parameter") + return err + } + path := fmt.Sprintf("audit-logs/export/destinations/%s", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, nil, nil, opts...) + return err +} + +// Verify the destination is writable by assuming the configured role and uploading +// a temporary probe object with the same request metadata as a real delivery. +// Requires an active Enterprise plan. +func (r *AuditLogExportDestinationService) Test(ctx context.Context, id string, opts ...option.RequestOption) (res *AuditLogExportDestinationTestResult, err error) { + opts = slices.Concat(r.Options, opts) + if id == "" { + err = errors.New("missing required id parameter") + return nil, err + } + path := fmt.Sprintf("audit-logs/export/destinations/%s/test", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, &res, opts...) + return res, err +} + +// An organization-scoped audit log export destination. +// +// Delivery is at-least-once for rows visible when their window is committed: a +// delivery that is retried rewrites the same object, and the same `event_id` can +// appear in more than one object, so consumers must deduplicate on `event_id`. +// Each event-time window is held for ten minutes before it commits; a row that +// becomes visible after its window is committed may not be delivered. +// +// Objects are written as +// `/destination_id=/org_id=/date=/hour=/-.jsonl.gz`, +// where `date` and `hour` are the UTC calendar hour that fully contains every row +// in the object, so the layout is safe to register as a Hive-partitioned table. +// The object name is derived from the rows it holds, so a retried delivery +// rewrites its own object. +type AuditLogExportDestination struct { + ID string `json:"id" api:"required"` + Bucket string `json:"bucket" api:"required"` + ConsecutiveFailures int64 `json:"consecutive_failures" api:"required"` + CreatedAt time.Time `json:"created_at" api:"required" format:"date-time"` + ExternalID string `json:"external_id" api:"required"` + // Any of "jsonl.gz". + Format AuditLogExportDestinationFormat `json:"format" api:"required"` + // The Kernel role that assumes `role_arn` in your account to deliver logs. Allow + // this role as the principal in your role's trust policy, and require + // `external_id` as the `sts:ExternalId` condition. + // + // Recreating a destination issues a new `external_id`, which the trust policy has + // to be updated to match. + KernelRoleArn string `json:"kernel_role_arn" api:"required"` + Prefix string `json:"prefix" api:"required"` + Region string `json:"region" api:"required"` + RoleArn string `json:"role_arn" api:"required"` + // Pausing prevents new delivery attempts. An S3 upload already in progress may + // complete after the pause response; its rows can appear again after the + // destination is resumed. + // + // Any of "active", "paused". + Status AuditLogExportDestinationStatus `json:"status" api:"required"` + // Any of "s3". + Type AuditLogExportDestinationType `json:"type" api:"required"` + UpdatedAt time.Time `json:"updated_at" api:"required" format:"date-time"` + KmsKeyID string `json:"kms_key_id"` + // Sanitized description of the most recent delivery failure. + LastError string `json:"last_error"` + LastErrorAt time.Time `json:"last_error_at" format:"date-time"` + // Opaque, versioned checkpoint for forward-only continuous export. This value is + // not compatible with audit-log list page tokens. + // + // Delivery starts at the moment the destination is activated, so events recorded + // before that are not delivered. Pausing stops delivery and resuming starts again + // from the time of the resume: events recorded while a destination was paused are + // never exported, and pausing is not a way to defer delivery. + LastExportedCursor string `json:"last_exported_cursor"` + LastSuccessAt time.Time `json:"last_success_at" format:"date-time"` + NextAttemptAt time.Time `json:"next_attempt_at" format:"date-time"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + Bucket respjson.Field + ConsecutiveFailures respjson.Field + CreatedAt respjson.Field + ExternalID respjson.Field + Format respjson.Field + KernelRoleArn respjson.Field + Prefix respjson.Field + Region respjson.Field + RoleArn respjson.Field + Status respjson.Field + Type respjson.Field + UpdatedAt respjson.Field + KmsKeyID respjson.Field + LastError respjson.Field + LastErrorAt respjson.Field + LastExportedCursor respjson.Field + LastSuccessAt respjson.Field + NextAttemptAt respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AuditLogExportDestination) RawJSON() string { return r.JSON.raw } +func (r *AuditLogExportDestination) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type AuditLogExportDestinationFormat string + +const ( + AuditLogExportDestinationFormatJSONLGz AuditLogExportDestinationFormat = "jsonl.gz" +) + +// Pausing prevents new delivery attempts. An S3 upload already in progress may +// complete after the pause response; its rows can appear again after the +// destination is resumed. +type AuditLogExportDestinationStatus string + +const ( + AuditLogExportDestinationStatusActive AuditLogExportDestinationStatus = "active" + AuditLogExportDestinationStatusPaused AuditLogExportDestinationStatus = "paused" +) + +type AuditLogExportDestinationType string + +const ( + AuditLogExportDestinationTypeS3 AuditLogExportDestinationType = "s3" +) + +type AuditLogExportDestinationTestResult struct { + // Any of "assume_role", "put_object", "complete". + Stage AuditLogExportDestinationTestResultStage `json:"stage" api:"required"` + Success bool `json:"success" api:"required"` + Error AuditLogExportDestinationTestResultError `json:"error"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Stage respjson.Field + Success respjson.Field + Error respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AuditLogExportDestinationTestResult) RawJSON() string { return r.JSON.raw } +func (r *AuditLogExportDestinationTestResult) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type AuditLogExportDestinationTestResultStage string + +const ( + AuditLogExportDestinationTestResultStageAssumeRole AuditLogExportDestinationTestResultStage = "assume_role" + AuditLogExportDestinationTestResultStagePutObject AuditLogExportDestinationTestResultStage = "put_object" + AuditLogExportDestinationTestResultStageComplete AuditLogExportDestinationTestResultStage = "complete" +) + +type AuditLogExportDestinationTestResultError struct { + // Any of "assume_role_failed", "put_object_failed". + Code string `json:"code" api:"required"` + Message string `json:"message" api:"required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Code respjson.Field + Message respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AuditLogExportDestinationTestResultError) RawJSON() string { return r.JSON.raw } +func (r *AuditLogExportDestinationTestResultError) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// The properties Bucket, Format, Prefix, Region, RoleArn, Type are required. +type CreateAuditLogExportDestinationRequestParam struct { + Bucket string `json:"bucket" api:"required"` + // Any of "jsonl.gz". + Format CreateAuditLogExportDestinationRequestFormat `json:"format,omitzero" api:"required"` + Prefix string `json:"prefix" api:"required"` + Region string `json:"region" api:"required"` + RoleArn string `json:"role_arn" api:"required"` + // Any of "s3". + Type CreateAuditLogExportDestinationRequestType `json:"type,omitzero" api:"required"` + KmsKeyID param.Opt[string] `json:"kms_key_id,omitzero"` + paramObj +} + +func (r CreateAuditLogExportDestinationRequestParam) MarshalJSON() (data []byte, err error) { + type shadow CreateAuditLogExportDestinationRequestParam + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *CreateAuditLogExportDestinationRequestParam) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type CreateAuditLogExportDestinationRequestFormat string + +const ( + CreateAuditLogExportDestinationRequestFormatJSONLGz CreateAuditLogExportDestinationRequestFormat = "jsonl.gz" +) + +type CreateAuditLogExportDestinationRequestType string + +const ( + CreateAuditLogExportDestinationRequestTypeS3 CreateAuditLogExportDestinationRequestType = "s3" +) + +type UpdateAuditLogExportDestinationRequestParam struct { + Bucket param.Opt[string] `json:"bucket,omitzero"` + // KMS key ID, alias, or ARN. Set to an empty string to remove the configured KMS + // key; omit or send null to leave unchanged. + KmsKeyID param.Opt[string] `json:"kms_key_id,omitzero"` + Prefix param.Opt[string] `json:"prefix,omitzero"` + Region param.Opt[string] `json:"region,omitzero"` + RoleArn param.Opt[string] `json:"role_arn,omitzero"` + // Any of "active", "paused". + Status UpdateAuditLogExportDestinationRequestStatus `json:"status,omitzero"` + paramObj +} + +func (r UpdateAuditLogExportDestinationRequestParam) MarshalJSON() (data []byte, err error) { + type shadow UpdateAuditLogExportDestinationRequestParam + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *UpdateAuditLogExportDestinationRequestParam) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type UpdateAuditLogExportDestinationRequestStatus string + +const ( + UpdateAuditLogExportDestinationRequestStatusActive UpdateAuditLogExportDestinationRequestStatus = "active" + UpdateAuditLogExportDestinationRequestStatusPaused UpdateAuditLogExportDestinationRequestStatus = "paused" +) + +type AuditLogExportDestinationNewParams struct { + CreateAuditLogExportDestinationRequest CreateAuditLogExportDestinationRequestParam + paramObj +} + +func (r AuditLogExportDestinationNewParams) MarshalJSON() (data []byte, err error) { + return shimjson.Marshal(r.CreateAuditLogExportDestinationRequest) +} +func (r *AuditLogExportDestinationNewParams) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type AuditLogExportDestinationUpdateParams struct { + UpdateAuditLogExportDestinationRequest UpdateAuditLogExportDestinationRequestParam + paramObj +} + +func (r AuditLogExportDestinationUpdateParams) MarshalJSON() (data []byte, err error) { + return shimjson.Marshal(r.UpdateAuditLogExportDestinationRequest) +} +func (r *AuditLogExportDestinationUpdateParams) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type AuditLogExportDestinationListParams struct { + // Limit the number of destinations to return. + Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` + // Offset the number of destinations to return. + Offset param.Opt[int64] `query:"offset,omitzero" json:"-"` + paramObj +} + +// URLQuery serializes [AuditLogExportDestinationListParams]'s query parameters as +// `url.Values`. +func (r AuditLogExportDestinationListParams) URLQuery() (v url.Values, err error) { + return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{ + ArrayFormat: apiquery.ArrayQueryFormatComma, + NestedFormat: apiquery.NestedQueryFormatBrackets, + }) +} diff --git a/auditlogexportdestination_test.go b/auditlogexportdestination_test.go new file mode 100644 index 0000000..b9ceb30 --- /dev/null +++ b/auditlogexportdestination_test.go @@ -0,0 +1,178 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +package kernel_test + +import ( + "context" + "errors" + "os" + "testing" + + "github.com/kernel/kernel-go-sdk" + "github.com/kernel/kernel-go-sdk/internal/testutil" + "github.com/kernel/kernel-go-sdk/option" +) + +func TestAuditLogExportDestinationNewWithOptionalParams(t *testing.T) { + t.Skip("Mock server tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + _, err := client.AuditLogs.ExportDestinations.New(context.TODO(), kernel.AuditLogExportDestinationNewParams{ + CreateAuditLogExportDestinationRequest: kernel.CreateAuditLogExportDestinationRequestParam{ + Bucket: "xxx", + Format: kernel.CreateAuditLogExportDestinationRequestFormatJSONLGz, + Prefix: "prefix", + Region: "x", + RoleArn: "x", + Type: kernel.CreateAuditLogExportDestinationRequestTypeS3, + KmsKeyID: kernel.String("kms_key_id"), + }, + }) + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + +func TestAuditLogExportDestinationGet(t *testing.T) { + t.Skip("Mock server tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + _, err := client.AuditLogs.ExportDestinations.Get(context.TODO(), "id") + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + +func TestAuditLogExportDestinationUpdateWithOptionalParams(t *testing.T) { + t.Skip("Mock server tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + _, err := client.AuditLogs.ExportDestinations.Update( + context.TODO(), + "id", + kernel.AuditLogExportDestinationUpdateParams{ + UpdateAuditLogExportDestinationRequest: kernel.UpdateAuditLogExportDestinationRequestParam{ + Bucket: kernel.String("xxx"), + KmsKeyID: kernel.String("kms_key_id"), + Prefix: kernel.String("prefix"), + Region: kernel.String("x"), + RoleArn: kernel.String("x"), + Status: kernel.UpdateAuditLogExportDestinationRequestStatusActive, + }, + }, + ) + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + +func TestAuditLogExportDestinationListWithOptionalParams(t *testing.T) { + t.Skip("Mock server tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + _, err := client.AuditLogs.ExportDestinations.List(context.TODO(), kernel.AuditLogExportDestinationListParams{ + Limit: kernel.Int(1), + Offset: kernel.Int(0), + }) + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + +func TestAuditLogExportDestinationDelete(t *testing.T) { + t.Skip("Mock server tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + err := client.AuditLogs.ExportDestinations.Delete(context.TODO(), "id") + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} + +func TestAuditLogExportDestinationTest(t *testing.T) { + t.Skip("Mock server tests are disabled") + baseURL := "http://localhost:4010" + if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok { + baseURL = envURL + } + if !testutil.CheckTestServer(t, baseURL) { + return + } + client := kernel.NewClient( + option.WithBaseURL(baseURL), + option.WithAPIKey("My API Key"), + ) + _, err := client.AuditLogs.ExportDestinations.Test(context.TODO(), "id") + if err != nil { + var apierr *kernel.Error + if errors.As(err, &apierr) { + t.Log(string(apierr.DumpRequest(true))) + } + t.Fatalf("err should be nil: %s", err.Error()) + } +} From 4e924dfdce39fb1110e8f935c2061c24da60cf6f Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Sat, 8 Aug 2026 19:56:25 +0000 Subject: [PATCH 2/4] feat: Forward egress deploy owner attribution Stainless-Generated-From: bf54567a8acdc52aeb3c888518c493f38306bc23 --- api.md | 7 + authconnection.go | 369 +++++++++++++++++++++++++++++++++++------ authconnection_test.go | 147 ++++++++++++++++ browser.go | 186 ++++++++++++++++++++- browser_test.go | 10 ++ browserpool.go | 8 +- invocation.go | 8 +- 7 files changed, 675 insertions(+), 60 deletions(-) diff --git a/api.md b/api.md index 9b2b461..7bb412f 100644 --- a/api.md +++ b/api.md @@ -69,11 +69,16 @@ Methods: Params Types: +- kernel.BrowserProxyConfigParam +- kernel.BrowserProxyMode - kernel.Tags Response Types: - kernel.BrowserPoolRef +- kernel.BrowserProxy +- kernel.BrowserProxyConfig +- kernel.BrowserProxyMode - kernel.BrowserUsage - kernel.Profile - kernel.Tags @@ -287,6 +292,7 @@ Methods: Params Types: +- kernel.ManagedAuthBrowserConfigParam - kernel.ManagedAuthCreateRequestParam - kernel.ManagedAuthUpdateRequestParam - kernel.SubmitFieldsRequestParam @@ -295,6 +301,7 @@ Response Types: - kernel.LoginResponse - kernel.ManagedAuth +- kernel.ManagedAuthBrowserConfig - kernel.ManagedAuthTimelineEvent - kernel.SubmitFieldsResponse - kernel.AuthConnectionFollowResponseUnion diff --git a/authconnection.go b/authconnection.go index f3c6d5b..fcf5202 100644 --- a/authconnection.go +++ b/authconnection.go @@ -288,13 +288,17 @@ type ManagedAuth struct { // 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"` + // Default browser configuration for login, reauthentication, and health-check + // sessions. + Browser ManagedAuthBrowserConfig `json:"browser"` // 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. BrowserSessionID string `json:"browser_session_id" api:"nullable"` - // Browser telemetry configuration used by this connection's browser sessions by - // default. The exact create-browser configuration is preserved and can be - // overridden per-login. + // Deprecated. Use browser.telemetry. Retained during migration for existing + // clients. + // + // Deprecated: deprecated BrowserTelemetry ManagedAuthBrowserTelemetry `json:"browser_telemetry" api:"nullable"` // Whether Kernel can automatically re-authenticate this connection when the // session expires. Requires a prior successful login plus either a Kernel @@ -415,7 +419,10 @@ type ManagedAuth struct { PendingSSOButtons []ManagedAuthPendingSSOButton `json:"pending_sso_buttons" api:"nullable"` // URL where the browser landed after successful login PostLoginURL string `json:"post_login_url" format:"uri"` - // ID of the proxy associated with this connection, if any. + // Deprecated. Read browser.proxy instead. Retained during migration for existing + // clients. + // + // Deprecated: deprecated ProxyID string `json:"proxy_id"` // Non-MFA choices presented during the auth flow, such as account selection or org // pickers (present when flow_step=awaiting_input; may also be present with @@ -436,6 +443,7 @@ type ManagedAuth struct { Status respjson.Field AllowedDomains respjson.Field AutoReauth respjson.Field + Browser respjson.Field BrowserSessionID respjson.Field BrowserTelemetry respjson.Field CanReauth respjson.Field @@ -484,9 +492,10 @@ const ( ManagedAuthStatusNeedsAuth ManagedAuthStatus = "NEEDS_AUTH" ) -// Browser telemetry configuration used by this connection's browser sessions by -// default. The exact create-browser configuration is preserved and can be -// overridden per-login. +// Deprecated. Use browser.telemetry. Retained during migration for existing +// clients. +// +// Deprecated: deprecated type ManagedAuthBrowserTelemetry struct { // Per-category capture flags. The operational categories (control, connection, // system, captcha) are captured whenever telemetry is enabled; set one to @@ -897,6 +906,263 @@ func (r *ManagedAuthSignInOption) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } +// Browser configuration applied to browser sessions created for a managed auth +// connection. Managed auth controls the profile, headless mode, timeout, start +// URL, kiosk mode, and viewport. +type ManagedAuthBrowserConfig struct { + // Proxy configuration for managed auth browser sessions. Omit on create to derive + // the default from stealth, or on update and login to preserve or inherit the + // connection default. + Proxy BrowserProxyConfig `json:"proxy"` + // Whether managed auth browser sessions use stealth mode. Defaults to true when + // omitted. + Stealth bool `json:"stealth"` + // Browser telemetry configuration using the same semantics as browser create. + Telemetry ManagedAuthBrowserConfigTelemetry `json:"telemetry" api:"nullable"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Proxy respjson.Field + Stealth respjson.Field + Telemetry respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ManagedAuthBrowserConfig) RawJSON() string { return r.JSON.raw } +func (r *ManagedAuthBrowserConfig) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// ToParam converts this ManagedAuthBrowserConfig to a +// ManagedAuthBrowserConfigParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// ManagedAuthBrowserConfigParam.Overrides() +func (r ManagedAuthBrowserConfig) ToParam() ManagedAuthBrowserConfigParam { + return param.Override[ManagedAuthBrowserConfigParam](json.RawMessage(r.RawJSON())) +} + +// Browser telemetry configuration using the same semantics as browser create. +type ManagedAuthBrowserConfigTelemetry struct { + // Per-category capture flags. The operational categories (control, connection, + // system, captcha) are captured whenever telemetry is enabled; set one to + // enabled=false to opt out. The CDP categories (console, network, page, + // interaction) and screenshot are off by default; set enabled=true to opt in. On + // create, provided categories layer onto the default set. On update, provided + // categories merge onto the session's current config; when no telemetry is active + // this falls back to the default set (matching create). If browser is omitted or + // empty, the default set is used. A browser config that disables every category + // stops capture on update and starts no capture on create. + Browser BrowserTelemetryCategoriesConfig `json:"browser"` + // Request shortcut for browser telemetry capture. True enables capture; with no + // browser category settings it captures the default set (control, connection, + // system, captcha), and any browser category settings are layered onto that + // default set. On update, enabled=true resolves the config fresh from the default + // set plus any provided categories, replacing the session's current selection + // rather than merging onto it; omit enabled to merge categories onto the current + // selection instead. False stops capture on update and starts no capture on + // create. enabled=false cannot be combined with browser category settings. + Enabled bool `json:"enabled"` + // Where to export this session's captured telemetry. Omit to capture without + // exporting. + Export ManagedAuthBrowserConfigTelemetryExport `json:"export"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Browser respjson.Field + Enabled respjson.Field + Export respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ManagedAuthBrowserConfigTelemetry) RawJSON() string { return r.JSON.raw } +func (r *ManagedAuthBrowserConfigTelemetry) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Where to export this session's captured telemetry. Omit to capture without +// exporting. +type ManagedAuthBrowserConfigTelemetryExport struct { + // Export captured telemetry over OTLP to one of the org's configured destinations. + Otlp ManagedAuthBrowserConfigTelemetryExportOtlp `json:"otlp"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Otlp respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ManagedAuthBrowserConfigTelemetryExport) RawJSON() string { return r.JSON.raw } +func (r *ManagedAuthBrowserConfigTelemetryExport) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Export captured telemetry over OTLP to one of the org's configured destinations. +type ManagedAuthBrowserConfigTelemetryExportOtlp struct { + // OTLP destination to export this session's captured telemetry to. Provide either + // id or name. Requires telemetry capture to be enabled. + Destination ManagedAuthBrowserConfigTelemetryExportOtlpDestination `json:"destination"` + // Whether to export captured telemetry over OTLP. Setting destination implies + // enabled=true, so this only needs to be set explicitly to disable export + // (enabled=false with a destination is rejected). + Enabled bool `json:"enabled"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Destination respjson.Field + Enabled respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ManagedAuthBrowserConfigTelemetryExportOtlp) RawJSON() string { return r.JSON.raw } +func (r *ManagedAuthBrowserConfigTelemetryExportOtlp) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// OTLP destination to export this session's captured telemetry to. Provide either +// id or name. Requires telemetry capture to be enabled. +type ManagedAuthBrowserConfigTelemetryExportOtlpDestination struct { + // OTLP destination ID + ID string `json:"id"` + // OTLP destination name + Name string `json:"name"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + Name respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ManagedAuthBrowserConfigTelemetryExportOtlpDestination) RawJSON() string { return r.JSON.raw } +func (r *ManagedAuthBrowserConfigTelemetryExportOtlpDestination) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Browser configuration applied to browser sessions created for a managed auth +// connection. Managed auth controls the profile, headless mode, timeout, start +// URL, kiosk mode, and viewport. +type ManagedAuthBrowserConfigParam struct { + // Whether managed auth browser sessions use stealth mode. Defaults to true when + // omitted. + Stealth param.Opt[bool] `json:"stealth,omitzero"` + // Browser telemetry configuration using the same semantics as browser create. + Telemetry ManagedAuthBrowserConfigTelemetryParam `json:"telemetry,omitzero"` + // Proxy configuration for managed auth browser sessions. Omit on create to derive + // the default from stealth, or on update and login to preserve or inherit the + // connection default. + Proxy BrowserProxyConfigParam `json:"proxy,omitzero"` + paramObj +} + +func (r ManagedAuthBrowserConfigParam) MarshalJSON() (data []byte, err error) { + type shadow ManagedAuthBrowserConfigParam + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *ManagedAuthBrowserConfigParam) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Browser telemetry configuration using the same semantics as browser create. +type ManagedAuthBrowserConfigTelemetryParam struct { + // Request shortcut for browser telemetry capture. True enables capture; with no + // browser category settings it captures the default set (control, connection, + // system, captcha), and any browser category settings are layered onto that + // default set. On update, enabled=true resolves the config fresh from the default + // set plus any provided categories, replacing the session's current selection + // rather than merging onto it; omit enabled to merge categories onto the current + // selection instead. False stops capture on update and starts no capture on + // create. enabled=false cannot be combined with browser category settings. + Enabled param.Opt[bool] `json:"enabled,omitzero"` + // Per-category capture flags. The operational categories (control, connection, + // system, captcha) are captured whenever telemetry is enabled; set one to + // enabled=false to opt out. The CDP categories (console, network, page, + // interaction) and screenshot are off by default; set enabled=true to opt in. On + // create, provided categories layer onto the default set. On update, provided + // categories merge onto the session's current config; when no telemetry is active + // this falls back to the default set (matching create). If browser is omitted or + // empty, the default set is used. A browser config that disables every category + // stops capture on update and starts no capture on create. + Browser BrowserTelemetryCategoriesConfigParam `json:"browser,omitzero"` + // Where to export this session's captured telemetry. Omit to capture without + // exporting. + Export ManagedAuthBrowserConfigTelemetryExportParam `json:"export,omitzero"` + paramObj +} + +func (r ManagedAuthBrowserConfigTelemetryParam) MarshalJSON() (data []byte, err error) { + type shadow ManagedAuthBrowserConfigTelemetryParam + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *ManagedAuthBrowserConfigTelemetryParam) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Where to export this session's captured telemetry. Omit to capture without +// exporting. +type ManagedAuthBrowserConfigTelemetryExportParam struct { + // Export captured telemetry over OTLP to one of the org's configured destinations. + Otlp ManagedAuthBrowserConfigTelemetryExportOtlpParam `json:"otlp,omitzero"` + paramObj +} + +func (r ManagedAuthBrowserConfigTelemetryExportParam) MarshalJSON() (data []byte, err error) { + type shadow ManagedAuthBrowserConfigTelemetryExportParam + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *ManagedAuthBrowserConfigTelemetryExportParam) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Export captured telemetry over OTLP to one of the org's configured destinations. +type ManagedAuthBrowserConfigTelemetryExportOtlpParam struct { + // Whether to export captured telemetry over OTLP. Setting destination implies + // enabled=true, so this only needs to be set explicitly to disable export + // (enabled=false with a destination is rejected). + Enabled param.Opt[bool] `json:"enabled,omitzero"` + // OTLP destination to export this session's captured telemetry to. Provide either + // id or name. Requires telemetry capture to be enabled. + Destination ManagedAuthBrowserConfigTelemetryExportOtlpDestinationParam `json:"destination,omitzero"` + paramObj +} + +func (r ManagedAuthBrowserConfigTelemetryExportOtlpParam) MarshalJSON() (data []byte, err error) { + type shadow ManagedAuthBrowserConfigTelemetryExportOtlpParam + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *ManagedAuthBrowserConfigTelemetryExportOtlpParam) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// OTLP destination to export this session's captured telemetry to. Provide either +// id or name. Requires telemetry capture to be enabled. +type ManagedAuthBrowserConfigTelemetryExportOtlpDestinationParam struct { + // OTLP destination ID + ID param.Opt[string] `json:"id,omitzero"` + // OTLP destination name + Name param.Opt[string] `json:"name,omitzero"` + paramObj +} + +func (r ManagedAuthBrowserConfigTelemetryExportOtlpDestinationParam) MarshalJSON() (data []byte, err error) { + type shadow ManagedAuthBrowserConfigTelemetryExportOtlpDestinationParam + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *ManagedAuthBrowserConfigTelemetryExportOtlpDestinationParam) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + // Request to create an auth connection for a profile and domain // // The properties Domain, ProfileName are required. @@ -934,9 +1200,10 @@ type ManagedAuthCreateRequestParam struct { // Whether to save credentials after every successful login. Defaults to true. // One-time codes (TOTP, SMS, etc.) are not saved. SaveCredentials param.Opt[bool] `json:"save_credentials,omitzero"` - // Browser telemetry configuration used by this connection's browser sessions by - // default. Uses the exact create-browser configuration. Can be overridden - // per-login. + // Deprecated. Use browser.telemetry. Retained during migration for existing + // clients. + // + // Deprecated: deprecated BrowserTelemetry ManagedAuthCreateRequestBrowserTelemetryParam `json:"browser_telemetry,omitzero"` // Additional domains valid for this auth flow (besides the primary domain). Useful // when login pages redirect to different domains. @@ -956,16 +1223,18 @@ type ManagedAuthCreateRequestParam struct { // - OneLogin: \*.onelogin.com // - Ping Identity: _.pingone.com, _.pingidentity.com AllowedDomains []string `json:"allowed_domains,omitzero"` + // Default browser configuration for login, reauthentication, and health-check + // sessions. + Browser ManagedAuthBrowserConfigParam `json:"browser,omitzero"` // Reference to credentials for the auth connection. Use one of: // // - { name } for Kernel credentials // - { provider, path } for external provider item // - { provider, auto: true } for external provider domain lookup Credential ManagedAuthCreateRequestCredentialParam `json:"credential,omitzero"` - // Proxy selection. Provide either id or name. The proxy must be in the same - // project as the resource referencing it. When selecting by name, the name must - // match exactly one active proxy in the project. Ambiguous names return a 400; use - // id for stable references. + // Deprecated. Use browser.proxy. Retained during migration for existing clients. + // + // Deprecated: deprecated Proxy ManagedAuthCreateRequestProxyParam `json:"proxy,omitzero"` paramObj } @@ -978,9 +1247,10 @@ func (r *ManagedAuthCreateRequestParam) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -// Browser telemetry configuration used by this connection's browser sessions by -// default. Uses the exact create-browser configuration. Can be overridden -// per-login. +// Deprecated. Use browser.telemetry. Retained during migration for existing +// clients. +// +// Deprecated: deprecated type ManagedAuthCreateRequestBrowserTelemetryParam struct { // Request shortcut for browser telemetry capture. True enables capture; with no // browser category settings it captures the default set (control, connection, @@ -1094,10 +1364,9 @@ func (r *ManagedAuthCreateRequestCredentialParam) UnmarshalJSON(data []byte) err return apijson.UnmarshalRoot(data, r) } -// Proxy selection. Provide either id or name. The proxy must be in the same -// project as the resource referencing it. When selecting by name, the name must -// match exactly one active proxy in the project. Ambiguous names return a 400; use -// id for stable references. +// Deprecated. Use browser.proxy. Retained during migration for existing clients. +// +// Deprecated: deprecated type ManagedAuthCreateRequestProxyParam struct { // Proxy ID ID param.Opt[string] `json:"id,omitzero"` @@ -1257,22 +1526,25 @@ type ManagedAuthUpdateRequestParam struct { RecordSession param.Opt[bool] `json:"record_session,omitzero"` // Whether to save credentials after every successful login SaveCredentials param.Opt[bool] `json:"save_credentials,omitzero"` - // Browser telemetry configuration used by future browser sessions for this - // connection. Uses the exact create-browser configuration. Set enabled to false to - // disable telemetry. + // Deprecated. Use browser.telemetry. Retained during migration for existing + // clients. + // + // Deprecated: deprecated BrowserTelemetry ManagedAuthUpdateRequestBrowserTelemetryParam `json:"browser_telemetry,omitzero"` // Additional domains valid for this auth flow (replaces existing list) AllowedDomains []string `json:"allowed_domains,omitzero"` + // Browser configuration updates for future login, reauthentication, and + // health-check sessions. Omitted properties remain unchanged. + Browser ManagedAuthBrowserConfigParam `json:"browser,omitzero"` // Reference to credentials for the auth connection. Use one of: // // - { name } for Kernel credentials // - { provider, path } for external provider item // - { provider, auto: true } for external provider domain lookup Credential ManagedAuthUpdateRequestCredentialParam `json:"credential,omitzero"` - // Proxy selection. Provide either id or name. The proxy must be in the same - // project as the resource referencing it. When selecting by name, the name must - // match exactly one active proxy in the project. Ambiguous names return a 400; use - // id for stable references. + // Deprecated. Use browser.proxy. Retained during migration for existing clients. + // + // Deprecated: deprecated Proxy ManagedAuthUpdateRequestProxyParam `json:"proxy,omitzero"` paramObj } @@ -1285,9 +1557,10 @@ func (r *ManagedAuthUpdateRequestParam) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -// Browser telemetry configuration used by future browser sessions for this -// connection. Uses the exact create-browser configuration. Set enabled to false to -// disable telemetry. +// Deprecated. Use browser.telemetry. Retained during migration for existing +// clients. +// +// Deprecated: deprecated type ManagedAuthUpdateRequestBrowserTelemetryParam struct { // Request shortcut for browser telemetry capture. True enables capture; with no // browser category settings it captures the default set (control, connection, @@ -1401,10 +1674,9 @@ func (r *ManagedAuthUpdateRequestCredentialParam) UnmarshalJSON(data []byte) err return apijson.UnmarshalRoot(data, r) } -// Proxy selection. Provide either id or name. The proxy must be in the same -// project as the resource referencing it. When selecting by name, the name must -// match exactly one active proxy in the project. Ambiguous names return a 400; use -// id for stable references. +// Deprecated. Use browser.proxy. Retained during migration for existing clients. +// +// Deprecated: deprecated type ManagedAuthUpdateRequestProxyParam struct { // Proxy ID ID param.Opt[string] `json:"id,omitzero"` @@ -1933,14 +2205,13 @@ type AuthConnectionLoginParams struct { // Override the connection's default for recording this login's browser session. // When omitted, the connection's record_session default is used. RecordSession param.Opt[bool] `json:"record_session,omitzero"` - // Override the connection's default browser telemetry configuration for this - // login. When omitted, the connection's browser_telemetry default is used. Uses - // the exact create-browser configuration. + // Deprecated. Use browser.telemetry. Retained during migration for existing + // clients. BrowserTelemetry AuthConnectionLoginParamsBrowserTelemetry `json:"browser_telemetry,omitzero"` - // Proxy selection. Provide either id or name. The proxy must be in the same - // project as the resource referencing it. When selecting by name, the name must - // match exactly one active proxy in the project. Ambiguous names return a 400; use - // id for stable references. + // Browser configuration override for this login. Omitted properties inherit the + // connection defaults. + Browser ManagedAuthBrowserConfigParam `json:"browser,omitzero"` + // Deprecated. Use browser.proxy. Retained during migration for existing clients. Proxy AuthConnectionLoginParamsProxy `json:"proxy,omitzero"` paramObj } @@ -1953,9 +2224,10 @@ func (r *AuthConnectionLoginParams) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -// Override the connection's default browser telemetry configuration for this -// login. When omitted, the connection's browser_telemetry default is used. Uses -// the exact create-browser configuration. +// Deprecated. Use browser.telemetry. Retained during migration for existing +// clients. +// +// Deprecated: deprecated type AuthConnectionLoginParamsBrowserTelemetry struct { // Request shortcut for browser telemetry capture. True enables capture; with no // browser category settings it captures the default set (control, connection, @@ -2044,10 +2316,9 @@ func (r *AuthConnectionLoginParamsBrowserTelemetryExportOtlpDestination) Unmarsh return apijson.UnmarshalRoot(data, r) } -// Proxy selection. Provide either id or name. The proxy must be in the same -// project as the resource referencing it. When selecting by name, the name must -// match exactly one active proxy in the project. Ambiguous names return a 400; use -// id for stable references. +// Deprecated. Use browser.proxy. Retained during migration for existing clients. +// +// Deprecated: deprecated type AuthConnectionLoginParamsProxy struct { // Proxy ID ID param.Opt[string] `json:"id,omitzero"` diff --git a/authconnection_test.go b/authconnection_test.go index b8b1c8b..aefb2ba 100644 --- a/authconnection_test.go +++ b/authconnection_test.go @@ -32,6 +32,55 @@ func TestAuthConnectionNewWithOptionalParams(t *testing.T) { ProfileName: "user-123", AllowedDomains: []string{"login.netflix.com", "auth.netflix.com"}, AutoReauth: kernel.Bool(true), + Browser: kernel.ManagedAuthBrowserConfigParam{ + Proxy: kernel.BrowserProxyConfigParam{ + ID: kernel.String("x"), + Mode: kernel.BrowserProxyModeDirect, + Name: kernel.String("x"), + }, + Stealth: kernel.Bool(false), + Telemetry: kernel.ManagedAuthBrowserConfigTelemetryParam{ + Browser: kernel.BrowserTelemetryCategoriesConfigParam{ + Captcha: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Connection: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Console: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Control: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Interaction: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Network: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Page: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Screenshot: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + System: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + }, + Enabled: kernel.Bool(true), + Export: kernel.ManagedAuthBrowserConfigTelemetryExportParam{ + Otlp: kernel.ManagedAuthBrowserConfigTelemetryExportOtlpParam{ + Destination: kernel.ManagedAuthBrowserConfigTelemetryExportOtlpDestinationParam{ + ID: kernel.String("id"), + Name: kernel.String("name"), + }, + Enabled: kernel.Bool(true), + }, + }, + }, + }, BrowserTelemetry: kernel.ManagedAuthCreateRequestBrowserTelemetryParam{ Browser: kernel.BrowserTelemetryCategoriesConfigParam{ Captcha: kernel.BrowserTelemetryCategoryConfigParam{ @@ -142,6 +191,55 @@ func TestAuthConnectionUpdateWithOptionalParams(t *testing.T) { ManagedAuthUpdateRequest: kernel.ManagedAuthUpdateRequestParam{ AllowedDomains: []string{"login.netflix.com", "auth.netflix.com"}, AutoReauth: kernel.Bool(true), + Browser: kernel.ManagedAuthBrowserConfigParam{ + Proxy: kernel.BrowserProxyConfigParam{ + ID: kernel.String("x"), + Mode: kernel.BrowserProxyModeDirect, + Name: kernel.String("x"), + }, + Stealth: kernel.Bool(false), + Telemetry: kernel.ManagedAuthBrowserConfigTelemetryParam{ + Browser: kernel.BrowserTelemetryCategoriesConfigParam{ + Captcha: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Connection: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Console: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Control: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Interaction: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Network: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Page: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Screenshot: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + System: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + }, + Enabled: kernel.Bool(true), + Export: kernel.ManagedAuthBrowserConfigTelemetryExportParam{ + Otlp: kernel.ManagedAuthBrowserConfigTelemetryExportOtlpParam{ + Destination: kernel.ManagedAuthBrowserConfigTelemetryExportOtlpDestinationParam{ + ID: kernel.String("id"), + Name: kernel.String("name"), + }, + Enabled: kernel.Bool(true), + }, + }, + }, + }, BrowserTelemetry: kernel.ManagedAuthUpdateRequestBrowserTelemetryParam{ Browser: kernel.BrowserTelemetryCategoriesConfigParam{ Captcha: kernel.BrowserTelemetryCategoryConfigParam{ @@ -279,6 +377,55 @@ func TestAuthConnectionLoginWithOptionalParams(t *testing.T) { context.TODO(), "id", kernel.AuthConnectionLoginParams{ + Browser: kernel.ManagedAuthBrowserConfigParam{ + Proxy: kernel.BrowserProxyConfigParam{ + ID: kernel.String("x"), + Mode: kernel.BrowserProxyModeDirect, + Name: kernel.String("x"), + }, + Stealth: kernel.Bool(false), + Telemetry: kernel.ManagedAuthBrowserConfigTelemetryParam{ + Browser: kernel.BrowserTelemetryCategoriesConfigParam{ + Captcha: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Connection: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Console: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Control: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Interaction: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Network: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Page: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + Screenshot: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + System: kernel.BrowserTelemetryCategoryConfigParam{ + Enabled: kernel.Bool(true), + }, + }, + Enabled: kernel.Bool(true), + Export: kernel.ManagedAuthBrowserConfigTelemetryExportParam{ + Otlp: kernel.ManagedAuthBrowserConfigTelemetryExportOtlpParam{ + Destination: kernel.ManagedAuthBrowserConfigTelemetryExportOtlpDestinationParam{ + ID: kernel.String("id"), + Name: kernel.String("name"), + }, + Enabled: kernel.Bool(true), + }, + }, + }, + }, BrowserTelemetry: kernel.AuthConnectionLoginParamsBrowserTelemetry{ Browser: kernel.BrowserTelemetryCategoriesConfigParam{ Captcha: kernel.BrowserTelemetryCategoryConfigParam{ diff --git a/browser.go b/browser.go index 1fb4801..bcdca34 100644 --- a/browser.go +++ b/browser.go @@ -5,6 +5,7 @@ package kernel import ( "bytes" "context" + "encoding/json" "errors" "fmt" "io" @@ -186,6 +187,131 @@ func (r *BrowserPoolRef) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } +// Resolved proxy configuration for a browser session. Selected proxies are +// returned by stable ID. +type BrowserProxy struct { + // Selected proxy ID. + ID string `json:"id"` + // Proxy egress mode. direct forces no proxy regardless of stealth. default uses + // the browser's stealth-derived default: Kernel's default stealth proxy when + // stealth=true, or direct egress when stealth=false. default is primarily useful + // on browser update to restore the browser default after selected-proxy egress. + // + // Any of "direct", "default". + Mode BrowserProxyMode `json:"mode"` + // Selected proxy name. + Name string `json:"name"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + Mode respjson.Field + Name respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BrowserProxy) RawJSON() string { return r.JSON.raw } +func (r *BrowserProxy) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Browser proxy configuration. Provide exactly one of mode, id, or name; an empty +// object is invalid. Set mode to direct for no proxy regardless of stealth. Set +// mode to default to use the browser's stealth-derived default: Kernel's default +// stealth proxy when stealth=true, or direct egress when stealth=false. Select id +// or name to use that proxy regardless of stealth. The selected proxy must be in +// the same project as the browser. Names must match exactly one active proxy; use +// id for stable references. Proxy configuration changes only egress and does not +// change stealth or CAPTCHA solver behavior. A stealth browser using mode=direct +// still runs in stealth mode with the CAPTCHA solver enabled. When proxy is +// omitted on browser creation, stealth browsers use Kernel's default stealth proxy +// and non-stealth browsers use direct egress. When omitted on update, the current +// configuration is unchanged. +type BrowserProxyConfig struct { + // Proxy ID. + ID string `json:"id"` + // Proxy egress mode. direct forces no proxy regardless of stealth. default uses + // the browser's stealth-derived default: Kernel's default stealth proxy when + // stealth=true, or direct egress when stealth=false. default is primarily useful + // on browser update to restore the browser default after selected-proxy egress. + // + // Any of "direct", "default". + Mode BrowserProxyMode `json:"mode"` + // Proxy name. Must match exactly one active proxy in the project. + Name string `json:"name"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + Mode respjson.Field + Name respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r BrowserProxyConfig) RawJSON() string { return r.JSON.raw } +func (r *BrowserProxyConfig) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// ToParam converts this BrowserProxyConfig to a BrowserProxyConfigParam. +// +// Warning: the fields of the param type will not be present. ToParam should only +// be used at the last possible moment before sending a request. Test for this with +// BrowserProxyConfigParam.Overrides() +func (r BrowserProxyConfig) ToParam() BrowserProxyConfigParam { + return param.Override[BrowserProxyConfigParam](json.RawMessage(r.RawJSON())) +} + +// Browser proxy configuration. Provide exactly one of mode, id, or name; an empty +// object is invalid. Set mode to direct for no proxy regardless of stealth. Set +// mode to default to use the browser's stealth-derived default: Kernel's default +// stealth proxy when stealth=true, or direct egress when stealth=false. Select id +// or name to use that proxy regardless of stealth. The selected proxy must be in +// the same project as the browser. Names must match exactly one active proxy; use +// id for stable references. Proxy configuration changes only egress and does not +// change stealth or CAPTCHA solver behavior. A stealth browser using mode=direct +// still runs in stealth mode with the CAPTCHA solver enabled. When proxy is +// omitted on browser creation, stealth browsers use Kernel's default stealth proxy +// and non-stealth browsers use direct egress. When omitted on update, the current +// configuration is unchanged. +type BrowserProxyConfigParam struct { + // Proxy ID. + ID param.Opt[string] `json:"id,omitzero"` + // Proxy name. Must match exactly one active proxy in the project. + Name param.Opt[string] `json:"name,omitzero"` + // Proxy egress mode. direct forces no proxy regardless of stealth. default uses + // the browser's stealth-derived default: Kernel's default stealth proxy when + // stealth=true, or direct egress when stealth=false. default is primarily useful + // on browser update to restore the browser default after selected-proxy egress. + // + // Any of "direct", "default". + Mode BrowserProxyMode `json:"mode,omitzero"` + paramObj +} + +func (r BrowserProxyConfigParam) MarshalJSON() (data []byte, err error) { + type shadow BrowserProxyConfigParam + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *BrowserProxyConfigParam) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Proxy egress mode. direct forces no proxy regardless of stealth. default uses +// the browser's stealth-derived default: Kernel's default stealth proxy when +// stealth=true, or direct egress when stealth=false. default is primarily useful +// on browser update to restore the browser default after selected-proxy egress. +type BrowserProxyMode string + +const ( + BrowserProxyModeDirect BrowserProxyMode = "direct" + BrowserProxyModeDefault BrowserProxyMode = "default" +) + // Session usage metrics. type BrowserUsage struct { // Time in milliseconds the session was actively running. @@ -276,7 +402,12 @@ type BrowserNewResponse struct { // Whether changes made during this browser session are saved back to its profile // when the session ends. Omitted when no profile is attached. ProfileSaveChanges bool `json:"profile_save_changes"` - // ID of the proxy associated with this browser session, if any. + // Resolved proxy configuration for this browser session. + Proxy BrowserProxy `json:"proxy"` + // ID of the proxy associated with this browser session, if any. Deprecated in + // favor of proxy. + // + // Deprecated: deprecated ProxyID string `json:"proxy_id"` // URL the session was asked to navigate to on creation, if any. Recorded for // debugging. Navigation is fire-and-forget — the URL is dispatched to the browser @@ -323,6 +454,7 @@ type BrowserNewResponse struct { Pool respjson.Field Profile respjson.Field ProfileSaveChanges respjson.Field + Proxy respjson.Field ProxyID respjson.Field StartURL respjson.Field Tags respjson.Field @@ -380,7 +512,12 @@ type BrowserGetResponse struct { // Whether changes made during this browser session are saved back to its profile // when the session ends. Omitted when no profile is attached. ProfileSaveChanges bool `json:"profile_save_changes"` - // ID of the proxy associated with this browser session, if any. + // Resolved proxy configuration for this browser session. + Proxy BrowserProxy `json:"proxy"` + // ID of the proxy associated with this browser session, if any. Deprecated in + // favor of proxy. + // + // Deprecated: deprecated ProxyID string `json:"proxy_id"` // URL the session was asked to navigate to on creation, if any. Recorded for // debugging. Navigation is fire-and-forget — the URL is dispatched to the browser @@ -427,6 +564,7 @@ type BrowserGetResponse struct { Pool respjson.Field Profile respjson.Field ProfileSaveChanges respjson.Field + Proxy respjson.Field ProxyID respjson.Field StartURL respjson.Field Tags respjson.Field @@ -484,7 +622,12 @@ type BrowserUpdateResponse struct { // Whether changes made during this browser session are saved back to its profile // when the session ends. Omitted when no profile is attached. ProfileSaveChanges bool `json:"profile_save_changes"` - // ID of the proxy associated with this browser session, if any. + // Resolved proxy configuration for this browser session. + Proxy BrowserProxy `json:"proxy"` + // ID of the proxy associated with this browser session, if any. Deprecated in + // favor of proxy. + // + // Deprecated: deprecated ProxyID string `json:"proxy_id"` // URL the session was asked to navigate to on creation, if any. Recorded for // debugging. Navigation is fire-and-forget — the URL is dispatched to the browser @@ -531,6 +674,7 @@ type BrowserUpdateResponse struct { Pool respjson.Field Profile respjson.Field ProfileSaveChanges respjson.Field + Proxy respjson.Field ProxyID respjson.Field StartURL respjson.Field Tags respjson.Field @@ -588,7 +732,12 @@ type BrowserListResponse struct { // Whether changes made during this browser session are saved back to its profile // when the session ends. Omitted when no profile is attached. ProfileSaveChanges bool `json:"profile_save_changes"` - // ID of the proxy associated with this browser session, if any. + // Resolved proxy configuration for this browser session. + Proxy BrowserProxy `json:"proxy"` + // ID of the proxy associated with this browser session, if any. Deprecated in + // favor of proxy. + // + // Deprecated: deprecated ProxyID string `json:"proxy_id"` // URL the session was asked to navigate to on creation, if any. Recorded for // debugging. Navigation is fire-and-forget — the URL is dispatched to the browser @@ -635,6 +784,7 @@ type BrowserListResponse struct { Pool respjson.Field Profile respjson.Field ProfileSaveChanges respjson.Field + Proxy respjson.Field ProxyID respjson.Field StartURL respjson.Field Tags respjson.Field @@ -696,14 +846,17 @@ type BrowserNewParams struct { // changed later via PATCH /browsers/{id_or_name}. Name param.Opt[string] `json:"name,omitzero"` // Optional proxy to associate to the browser session. Must reference a proxy in - // the same project as the browser session. + // the same project as the browser session. Deprecated in favor of proxy. ProxyID param.Opt[string] `json:"proxy_id,omitzero"` // 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. + // If true, launches the browser in stealth mode and enables the CAPTCHA solver. + // Defaults to false. When proxy is omitted, stealth browsers use Kernel's default + // stealth proxy and non-stealth browsers use direct egress. An explicit proxy + // configuration changes only egress; it does not enable or disable stealth or the + // CAPTCHA solver. Stealth param.Opt[bool] `json:"stealth,omitzero"` // The number of seconds of inactivity before the browser session is terminated. // Activity includes CDP connections and live view connections. Defaults to 60 @@ -728,6 +881,14 @@ type BrowserNewParams struct { // specified, the matching profile will be loaded into the browser session. // Profiles must be created beforehand. Profile shared.BrowserProfileParam `json:"profile,omitzero"` + // Proxy configuration for the browser session. Cannot be combined with proxy_id. + // Omit to use the browser default: stealth browsers use Kernel's default stealth + // proxy, while non-stealth browsers use direct egress. Set mode to direct to force + // direct egress regardless of stealth. Set mode to default to explicitly use the + // browser default: Kernel's default stealth proxy when stealth=true, or direct + // egress when stealth=false. Select id or name to use that proxy regardless of + // stealth. Proxy selection does not change stealth or CAPTCHA solver behavior. + Proxy BrowserProxyConfigParam `json:"proxy,omitzero"` // Optional user-defined key-value tags for the browser session, used to find and // group sessions later. Can be changed later via PATCH /browsers/{id_or_name}. Up // to 50 pairs. @@ -869,10 +1030,10 @@ type BrowserUpdateParams struct { // within the project. Name param.Opt[string] `json:"name,omitzero"` // ID of the proxy to use. Omit to leave unchanged, set to empty string to remove - // proxy. + // proxy. Deprecated in favor of proxy. ProxyID param.Opt[string] `json:"proxy_id,omitzero"` // If true, stealth browsers connect directly instead of using the default stealth - // proxy. + // proxy. Deprecated in favor of proxy.mode. DisableDefaultProxy param.Opt[bool] `json:"disable_default_proxy,omitzero"` // Telemetry configuration. Omit, set to null, or set to an empty object ({}) to // leave the existing configuration unchanged. Set enabled to true to enable @@ -883,6 +1044,13 @@ type BrowserUpdateParams struct { // Profile to load into the browser session. Only allowed if the session does not // already have a profile loaded. Profile shared.BrowserProfileParam `json:"profile,omitzero"` + // Proxy configuration to apply. Omit to leave the current configuration unchanged. + // Cannot be combined with proxy_id or disable_default_proxy. Set mode to direct to + // switch to direct egress regardless of stealth. Set mode to default to restore + // the browser default after using a selected proxy: Kernel's default stealth proxy + // for a stealth browser, or direct egress for a non-stealth browser. Updating + // proxy does not change stealth or CAPTCHA solver behavior. + Proxy BrowserProxyConfigParam `json:"proxy,omitzero"` // User-defined key-value tags for the browser session. Omit to leave unchanged. // Provide a map to replace the entire tag set (full replace, not a merge). Set to // an empty object ({}) to clear all tags. Up to 50 pairs. diff --git a/browser_test.go b/browser_test.go index ee23508..57df42a 100644 --- a/browser_test.go +++ b/browser_test.go @@ -47,6 +47,11 @@ func TestBrowserNewWithOptionalParams(t *testing.T) { Name: kernel.String("name"), SaveChanges: kernel.Bool(true), }, + Proxy: kernel.BrowserProxyConfigParam{ + ID: kernel.String("x"), + Mode: kernel.BrowserProxyModeDirect, + Name: kernel.String("x"), + }, ProxyID: kernel.String("proxy_id"), StartURL: kernel.String("https://example.com"), Stealth: kernel.Bool(true), @@ -164,6 +169,11 @@ func TestBrowserUpdateWithOptionalParams(t *testing.T) { Name: kernel.String("name"), SaveChanges: kernel.Bool(true), }, + Proxy: kernel.BrowserProxyConfigParam{ + ID: kernel.String("x"), + Mode: kernel.BrowserProxyModeDirect, + Name: kernel.String("x"), + }, ProxyID: kernel.String("proxy_id"), Tags: kernel.Tags{ "team": "backend", diff --git a/browserpool.go b/browserpool.go index 641cc2d..cc3a240 100644 --- a/browserpool.go +++ b/browserpool.go @@ -363,7 +363,12 @@ type BrowserPoolAcquireResponse struct { // Whether changes made during this browser session are saved back to its profile // when the session ends. Omitted when no profile is attached. ProfileSaveChanges bool `json:"profile_save_changes"` - // ID of the proxy associated with this browser session, if any. + // Resolved proxy configuration for this browser session. + Proxy BrowserProxy `json:"proxy"` + // ID of the proxy associated with this browser session, if any. Deprecated in + // favor of proxy. + // + // Deprecated: deprecated ProxyID string `json:"proxy_id"` // URL the session was asked to navigate to on creation, if any. Recorded for // debugging. Navigation is fire-and-forget — the URL is dispatched to the browser @@ -410,6 +415,7 @@ type BrowserPoolAcquireResponse struct { Pool respjson.Field Profile respjson.Field ProfileSaveChanges respjson.Field + Proxy respjson.Field ProxyID respjson.Field StartURL respjson.Field Tags respjson.Field diff --git a/invocation.go b/invocation.go index a2bb44a..12b708d 100644 --- a/invocation.go +++ b/invocation.go @@ -577,7 +577,12 @@ type InvocationListBrowsersResponseBrowser struct { // Whether changes made during this browser session are saved back to its profile // when the session ends. Omitted when no profile is attached. ProfileSaveChanges bool `json:"profile_save_changes"` - // ID of the proxy associated with this browser session, if any. + // Resolved proxy configuration for this browser session. + Proxy BrowserProxy `json:"proxy"` + // ID of the proxy associated with this browser session, if any. Deprecated in + // favor of proxy. + // + // Deprecated: deprecated ProxyID string `json:"proxy_id"` // URL the session was asked to navigate to on creation, if any. Recorded for // debugging. Navigation is fire-and-forget — the URL is dispatched to the browser @@ -624,6 +629,7 @@ type InvocationListBrowsersResponseBrowser struct { Pool respjson.Field Profile respjson.Field ProfileSaveChanges respjson.Field + Proxy respjson.Field ProxyID respjson.Field StartURL respjson.Field Tags respjson.Field From cd3e117dbbb8518688e2547de93da8ccf6f67089 Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Sun, 9 Aug 2026 16:32:38 +0000 Subject: [PATCH 3/4] feat: Persist CUA-TS reauth blockers before failure Stainless-Generated-From: 565691687ba43cd2d5fb88d72e0d25d506372cd6 --- authconnection.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/authconnection.go b/authconnection.go index fcf5202..166884f 100644 --- a/authconnection.go +++ b/authconnection.go @@ -334,12 +334,15 @@ type ManagedAuth struct { // automatically // - `requires_email_code` — flow needs an email code that cannot be received // automatically + // - `requires_customer_input` — flow needs another field or choice that is + // unavailable during unattended re-authentication // // Any of "external_credential", "cua_has_credential", "has_credential", // "viable_plans_found", "no_requirements_recorded", "requirements_satisfiable", // "no_prior_successful_login", "no_credential", "no_viable_plans", // "viable_plans_require_external_action", "requires_external_action", - // "requires_totp_without_secret", "requires_sms_code", "requires_email_code". + // "requires_totp_without_secret", "requires_sms_code", "requires_email_code", + // "requires_customer_input". CanReauthReason ManagedAuthCanReauthReason `json:"can_reauth_reason"` // Canonical choices awaiting selection. Prefer this over pending_sso_buttons, // mfa_options, and sign_in_options when present. @@ -629,6 +632,8 @@ func (r *ManagedAuthBrowserTelemetryExportOtlpDestination) UnmarshalJSON(data [] // automatically // - `requires_email_code` — flow needs an email code that cannot be received // automatically +// - `requires_customer_input` — flow needs another field or choice that is +// unavailable during unattended re-authentication type ManagedAuthCanReauthReason string const ( @@ -646,6 +651,7 @@ const ( ManagedAuthCanReauthReasonRequiresTotpWithoutSecret ManagedAuthCanReauthReason = "requires_totp_without_secret" ManagedAuthCanReauthReasonRequiresSMSCode ManagedAuthCanReauthReason = "requires_sms_code" ManagedAuthCanReauthReasonRequiresEmailCode ManagedAuthCanReauthReason = "requires_email_code" + ManagedAuthCanReauthReasonRequiresCustomerInput ManagedAuthCanReauthReason = "requires_customer_input" ) // Canonical auth-flow choice awaiting user selection. From 5819723ab49da6980dad983bd63ccc1565278e8c Mon Sep 17 00:00:00 2001 From: "kernel-internal[bot]" <260533166+kernel-internal[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 16:33:28 +0000 Subject: [PATCH 4/4] feat: Managed auth: free-plan connections (cap 3), credentials, 6h floor (packaging PR 5) Stainless-Generated-From: b03c04a8bb6d23ef4f4c6c2ce046991524c168ca --- authconnection.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/authconnection.go b/authconnection.go index 166884f..5ee635c 100644 --- a/authconnection.go +++ b/authconnection.go @@ -386,9 +386,10 @@ type ManagedAuth struct { FlowType ManagedAuthFlowType `json:"flow_type" api:"nullable"` // 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). + // if needed. Maximum is 86400 (24 hours). Default is 3600 (1 hour) or your plan + // minimum, whichever is larger. The minimum depends on your plan: Enterprise: 300 + // (5 minutes), Startup: 1200 (20 minutes), Hobbyist: 3600 (1 hour), Free: 21600 (6 + // hours). 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` @@ -1189,9 +1190,10 @@ type ManagedAuthCreateRequestParam struct { 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). + // if needed. Maximum is 86400 (24 hours). Default is 3600 (1 hour) or your plan + // minimum, whichever is larger. The minimum depends on your plan: Enterprise: 300 + // (5 minutes), Startup: 1200 (20 minutes), Hobbyist: 3600 (1 hour), Free: 21600 (6 + // hours). 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