diff --git a/.release-please-manifest.json b/.release-please-manifest.json index f81bf99..8305d4a 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.31.0" + ".": "0.31.1" } \ No newline at end of file diff --git a/.stats.yml b/.stats.yml index 91fd3b6..2964321 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ -configured_endpoints: 100 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-a6d93dc291278035c96add38bb6150ec2b9ba8bbabb4676e3dbbb8444cf3b1e4.yml -openapi_spec_hash: 694bcc56d94fd0ff0d1f7b0fc1dae8ba -config_hash: 62e33cf2ed8fe0b4ceebba63367481ad +configured_endpoints: 108 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/kernel%2Fkernel-3fbe762c99e8a120c426ac22bc1fa257c9127d631b12a38a6440a37f52935543.yml +openapi_spec_hash: 5a190df210ed90b20a71c5061ff43917 +config_hash: 38c9b3b355025daf9bb643040e4af94e diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bb8760..19d195d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Changelog +## 0.31.1 (2026-02-06) + +Full Changelog: [v0.31.0...v0.31.1](https://github.com/kernel/kernel-go-sdk/compare/v0.31.0...v0.31.1) + +### Chores + +* add Managed Auth API planning doc ([fe6c74f](https://github.com/kernel/kernel-go-sdk/commit/fe6c74f86576f1939a61e5ea78a0480837629c81)) + ## 0.31.0 (2026-02-06) Full Changelog: [v0.30.0...v0.31.0](https://github.com/kernel/kernel-go-sdk/compare/v0.30.0...v0.31.0) diff --git a/README.md b/README.md index 467688c..7096145 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Or to pin the version: ```sh -go get -u 'github.com/kernel/kernel-go-sdk@v0.31.0' +go get -u 'github.com/kernel/kernel-go-sdk@v0.31.1' ``` diff --git a/agentauth.go b/agentauth.go index f34761d..fb05f0c 100644 --- a/agentauth.go +++ b/agentauth.go @@ -43,10 +43,13 @@ func NewAgentAuthService(opts ...option.RequestOption) (r AgentAuthService) { return } -// Creates a new auth agent for the specified domain and profile combination, or -// returns an existing one if it already exists. This is idempotent - calling with -// the same domain and profile will return the same agent. Does NOT start an -// invocation - use POST /agents/auth/invocations to start an auth flow. +// **Deprecated: Use POST /auth/connections instead.** Creates a new auth agent for +// the specified domain and profile combination, or returns an existing one if it +// already exists. This is idempotent - calling with the same domain and profile +// will return the same agent. Does NOT start an invocation - use POST +// /agents/auth/invocations to start an auth flow. +// +// Deprecated: deprecated func (r *AgentAuthService) New(ctx context.Context, body AgentAuthNewParams, opts ...option.RequestOption) (res *AuthAgent, err error) { opts = slices.Concat(r.Options, opts) path := "agents/auth" @@ -54,8 +57,10 @@ func (r *AgentAuthService) New(ctx context.Context, body AgentAuthNewParams, opt return } -// Retrieve an auth agent by its ID. Returns the current authentication status of -// the managed profile. +// **Deprecated: Use GET /auth/connections/{id} instead.** Retrieve an auth agent +// by its ID. Returns the current authentication status of the managed profile. +// +// Deprecated: deprecated func (r *AgentAuthService) Get(ctx context.Context, id string, opts ...option.RequestOption) (res *AuthAgent, err error) { opts = slices.Concat(r.Options, opts) if id == "" { @@ -67,7 +72,10 @@ func (r *AgentAuthService) Get(ctx context.Context, id string, opts ...option.Re return } -// List auth agents with optional filters for profile_name and domain. +// **Deprecated: Use GET /auth/connections instead.** List auth agents with +// optional filters for profile_name and domain. +// +// Deprecated: deprecated func (r *AgentAuthService) List(ctx context.Context, query AgentAuthListParams, opts ...option.RequestOption) (res *pagination.OffsetPagination[AuthAgent], err error) { var raw *http.Response opts = slices.Concat(r.Options, opts) @@ -85,16 +93,22 @@ func (r *AgentAuthService) List(ctx context.Context, query AgentAuthListParams, return res, nil } -// List auth agents with optional filters for profile_name and domain. +// **Deprecated: Use GET /auth/connections instead.** List auth agents with +// optional filters for profile_name and domain. +// +// Deprecated: deprecated func (r *AgentAuthService) ListAutoPaging(ctx context.Context, query AgentAuthListParams, opts ...option.RequestOption) *pagination.OffsetPaginationAutoPager[AuthAgent] { return pagination.NewOffsetPaginationAutoPager(r.List(ctx, query, opts...)) } -// Deletes an auth agent and terminates its workflow. This will: +// **Deprecated: Use DELETE /auth/connections/{id} instead.** Deletes an auth agent +// and terminates its workflow. This will: // // - Soft delete the auth agent record // - Gracefully terminate the agent's Temporal workflow // - Cancel any in-progress invocations +// +// Deprecated: deprecated func (r *AgentAuthService) 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...) @@ -124,13 +138,12 @@ type AgentAuthInvocationResponse struct { // Any of "initialized", "discovering", "awaiting_input", // "awaiting_external_action", "submitting", "completed", "expired". Step AgentAuthInvocationResponseStep `json:"step,required"` - // The invocation type: + // The session type: // - // - login: First-time authentication - // - reauth: Re-authentication for previously authenticated agents - // - auto_login: Legacy type (no longer created, kept for backward compatibility) + // - login: User-initiated authentication + // - reauth: System-triggered re-authentication (via health check) // - // Any of "login", "auto_login", "reauth". + // Any of "login", "reauth". Type AgentAuthInvocationResponseType `json:"type,required"` // Error message explaining why the invocation failed (present when status=FAILED) ErrorMessage string `json:"error_message,nullable"` @@ -201,26 +214,24 @@ const ( AgentAuthInvocationResponseStepExpired AgentAuthInvocationResponseStep = "expired" ) -// The invocation type: +// The session type: // -// - login: First-time authentication -// - reauth: Re-authentication for previously authenticated agents -// - auto_login: Legacy type (no longer created, kept for backward compatibility) +// - login: User-initiated authentication +// - reauth: System-triggered re-authentication (via health check) type AgentAuthInvocationResponseType string const ( - AgentAuthInvocationResponseTypeLogin AgentAuthInvocationResponseType = "login" - AgentAuthInvocationResponseTypeAutoLogin AgentAuthInvocationResponseType = "auto_login" - AgentAuthInvocationResponseTypeReauth AgentAuthInvocationResponseType = "reauth" + AgentAuthInvocationResponseTypeLogin AgentAuthInvocationResponseType = "login" + AgentAuthInvocationResponseTypeReauth AgentAuthInvocationResponseType = "reauth" ) // An MFA method option for verification type AgentAuthInvocationResponseMfaOption struct { // The visible option text Label string `json:"label,required"` - // The MFA delivery method type + // The MFA delivery method type (includes password for auth method selection pages) // - // Any of "sms", "call", "email", "totp", "push", "security_key". + // Any of "sms", "call", "email", "totp", "push", "password". Type string `json:"type,required"` // Additional instructions from the site Description string `json:"description,nullable"` @@ -301,14 +312,34 @@ type AuthAgent struct { // Additional domains that are valid for this auth agent's authentication flow // (besides the primary domain). Useful when login pages redirect to different // domains. + // + // The following SSO/OAuth provider domains are automatically allowed by default + // and do not need to be specified: + // + // - Google: accounts.google.com + // - Microsoft/Azure AD: login.microsoftonline.com, login.live.com + // - Okta: _.okta.com, _.oktapreview.com + // - Auth0: _.auth0.com, _.us.auth0.com, _.eu.auth0.com, _.au.auth0.com + // - Apple: appleid.apple.com + // - GitHub: github.com + // - Facebook/Meta: www.facebook.com + // - LinkedIn: www.linkedin.com + // - Amazon Cognito: \*.amazoncognito.com + // - OneLogin: \*.onelogin.com + // - Ping Identity: _.pingone.com, _.pingidentity.com AllowedDomains []string `json:"allowed_domains"` // Whether automatic re-authentication is possible (has credential_id, selectors, // and login_url) CanReauth bool `json:"can_reauth"` - // ID of the linked credential for automatic re-authentication + // Reference to credentials for managed auth. Use one of: + // + // - { name } for Kernel credentials + // - { provider, path } for external provider item + // - { provider, auto: true } for external provider domain lookup + Credential AuthAgentCredential `json:"credential"` + // ID of the linked Kernel credential for automatic re-authentication (deprecated, + // use credential) CredentialID string `json:"credential_id"` - // Name of the linked credential for automatic re-authentication - CredentialName string `json:"credential_name"` // Whether this auth agent has stored selectors for deterministic re-authentication HasSelectors bool `json:"has_selectors"` // When the last authentication check was performed @@ -324,8 +355,8 @@ type AuthAgent struct { Status respjson.Field AllowedDomains respjson.Field CanReauth respjson.Field + Credential respjson.Field CredentialID respjson.Field - CredentialName respjson.Field HasSelectors respjson.Field LastAuthCheckAt respjson.Field PostLoginURL respjson.Field @@ -348,6 +379,37 @@ const ( AuthAgentStatusNeedsAuth AuthAgentStatus = "NEEDS_AUTH" ) +// Reference to credentials for managed auth. Use one of: +// +// - { name } for Kernel credentials +// - { provider, path } for external provider item +// - { provider, auto: true } for external provider domain lookup +type AuthAgentCredential struct { + // If true, lookup by domain from the specified provider + Auto bool `json:"auto"` + // Kernel credential name + Name string `json:"name"` + // Provider-specific path (e.g., "VaultName/ItemName" for 1Password) + Path string `json:"path"` + // External provider name (e.g., "my-1p") + Provider string `json:"provider"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Auto respjson.Field + Name respjson.Field + Path respjson.Field + Provider respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AuthAgentCredential) RawJSON() string { return r.JSON.raw } +func (r *AuthAgentCredential) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + // Request to create or find an auth agent // // The properties Domain, ProfileName are required. @@ -366,6 +428,21 @@ type AuthAgentCreateRequestParam struct { // Additional domains that are valid for this auth agent's authentication flow // (besides the primary domain). Useful when login pages redirect to different // domains. + // + // The following SSO/OAuth provider domains are automatically allowed by default + // and do not need to be specified: + // + // - Google: accounts.google.com + // - Microsoft/Azure AD: login.microsoftonline.com, login.live.com + // - Okta: _.okta.com, _.oktapreview.com + // - Auth0: _.auth0.com, _.us.auth0.com, _.eu.auth0.com, _.au.auth0.com + // - Apple: appleid.apple.com + // - GitHub: github.com + // - Facebook/Meta: www.facebook.com + // - LinkedIn: www.linkedin.com + // - Amazon Cognito: \*.amazoncognito.com + // - OneLogin: \*.onelogin.com + // - Ping Identity: _.pingone.com, _.pingidentity.com AllowedDomains []string `json:"allowed_domains,omitzero"` // Optional proxy configuration Proxy AuthAgentCreateRequestProxyParam `json:"proxy,omitzero"` @@ -426,13 +503,12 @@ type AuthAgentInvocationCreateResponse struct { HostedURL string `json:"hosted_url,required" format:"uri"` // Unique identifier for the invocation. InvocationID string `json:"invocation_id,required"` - // The invocation type: + // The session type: // - // - login: First-time authentication - // - reauth: Re-authentication for previously authenticated agents - // - auto_login: Legacy type (no longer created, kept for backward compatibility) + // - login: User-initiated authentication + // - reauth: System-triggered re-authentication (via health check) // - // Any of "login", "auto_login", "reauth". + // Any of "login", "reauth". Type AuthAgentInvocationCreateResponseType `json:"type,required"` // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. JSON struct { @@ -452,17 +528,15 @@ func (r *AuthAgentInvocationCreateResponse) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -// The invocation type: +// The session type: // -// - login: First-time authentication -// - reauth: Re-authentication for previously authenticated agents -// - auto_login: Legacy type (no longer created, kept for backward compatibility) +// - login: User-initiated authentication +// - reauth: System-triggered re-authentication (via health check) type AuthAgentInvocationCreateResponseType string const ( - AuthAgentInvocationCreateResponseTypeLogin AuthAgentInvocationCreateResponseType = "login" - AuthAgentInvocationCreateResponseTypeAutoLogin AuthAgentInvocationCreateResponseType = "auto_login" - AuthAgentInvocationCreateResponseTypeReauth AuthAgentInvocationCreateResponseType = "reauth" + AuthAgentInvocationCreateResponseTypeLogin AuthAgentInvocationCreateResponseType = "login" + AuthAgentInvocationCreateResponseTypeReauth AuthAgentInvocationCreateResponseType = "reauth" ) // A discovered form field @@ -477,20 +551,26 @@ type DiscoveredField struct { // // Any of "text", "email", "password", "tel", "number", "url", "code", "totp". Type DiscoveredFieldType `json:"type,required"` + // If this field is associated with an MFA option, the type of that option (e.g., + // password field linked to "Enter password" option) + // + // Any of "sms", "call", "email", "totp", "push", "password". + LinkedMfaType DiscoveredFieldLinkedMfaType `json:"linked_mfa_type,nullable"` // Field placeholder Placeholder string `json:"placeholder"` // Whether field is required Required bool `json:"required"` // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. JSON struct { - Label respjson.Field - Name respjson.Field - Selector respjson.Field - Type respjson.Field - Placeholder respjson.Field - Required respjson.Field - ExtraFields map[string]respjson.Field - raw string + Label respjson.Field + Name respjson.Field + Selector respjson.Field + Type respjson.Field + LinkedMfaType respjson.Field + Placeholder respjson.Field + Required respjson.Field + ExtraFields map[string]respjson.Field + raw string } `json:"-"` } @@ -514,6 +594,19 @@ const ( DiscoveredFieldTypeTotp DiscoveredFieldType = "totp" ) +// If this field is associated with an MFA option, the type of that option (e.g., +// password field linked to "Enter password" option) +type DiscoveredFieldLinkedMfaType string + +const ( + DiscoveredFieldLinkedMfaTypeSMS DiscoveredFieldLinkedMfaType = "sms" + DiscoveredFieldLinkedMfaTypeCall DiscoveredFieldLinkedMfaType = "call" + DiscoveredFieldLinkedMfaTypeEmail DiscoveredFieldLinkedMfaType = "email" + DiscoveredFieldLinkedMfaTypeTotp DiscoveredFieldLinkedMfaType = "totp" + DiscoveredFieldLinkedMfaTypePush DiscoveredFieldLinkedMfaType = "push" + DiscoveredFieldLinkedMfaTypePassword DiscoveredFieldLinkedMfaType = "password" +) + type AgentAuthNewParams struct { // Request to create or find an auth agent AuthAgentCreateRequest AuthAgentCreateRequestParam diff --git a/agentauthinvocation.go b/agentauthinvocation.go index 91acce7..7226c53 100644 --- a/agentauthinvocation.go +++ b/agentauthinvocation.go @@ -37,9 +37,11 @@ func NewAgentAuthInvocationService(opts ...option.RequestOption) (r AgentAuthInv return } -// Creates a new authentication invocation for the specified auth agent. This -// starts the auth flow and returns a hosted URL for the user to complete -// authentication. +// **Deprecated: Use POST /auth/connections/{id}/login instead.** Creates a new +// authentication invocation for the specified auth agent. This starts the auth +// flow and returns a hosted URL for the user to complete authentication. +// +// Deprecated: deprecated func (r *AgentAuthInvocationService) New(ctx context.Context, body AgentAuthInvocationNewParams, opts ...option.RequestOption) (res *AuthAgentInvocationCreateResponse, err error) { opts = slices.Concat(r.Options, opts) path := "agents/auth/invocations" @@ -47,8 +49,11 @@ func (r *AgentAuthInvocationService) New(ctx context.Context, body AgentAuthInvo return } -// Returns invocation details including status, app_name, and domain. Supports both -// API key and JWT (from exchange endpoint) authentication. +// **Deprecated: Use GET /auth/connections/{id} instead.** Returns invocation +// details including status, app_name, and domain. Supports both API key and JWT +// (from exchange endpoint) authentication. +// +// Deprecated: deprecated func (r *AgentAuthInvocationService) Get(ctx context.Context, invocationID string, opts ...option.RequestOption) (res *AgentAuthInvocationResponse, err error) { opts = slices.Concat(r.Options, opts) if invocationID == "" { @@ -60,8 +65,11 @@ func (r *AgentAuthInvocationService) Get(ctx context.Context, invocationID strin return } -// Validates the handoff code and returns a JWT token for subsequent requests. No -// authentication required (the handoff code serves as the credential). +// **Deprecated: Use POST /auth/connections/{id}/exchange instead.** Validates the +// handoff code and returns a JWT token for subsequent requests. No authentication +// required (the handoff code serves as the credential). +// +// Deprecated: deprecated func (r *AgentAuthInvocationService) Exchange(ctx context.Context, invocationID string, body AgentAuthInvocationExchangeParams, opts ...option.RequestOption) (res *AgentAuthInvocationExchangeResponse, err error) { opts = slices.Concat(r.Options, opts) if invocationID == "" { @@ -73,9 +81,11 @@ func (r *AgentAuthInvocationService) Exchange(ctx context.Context, invocationID return } -// Submits field values for the discovered login form. Returns immediately after -// submission is accepted. Poll the invocation endpoint to track progress and get -// results. +// **Deprecated: Use POST /auth/connections/{id}/submit instead.** Submits field +// values for the discovered login form. Returns immediately after submission is +// accepted. Poll the invocation endpoint to track progress and get results. +// +// Deprecated: deprecated func (r *AgentAuthInvocationService) Submit(ctx context.Context, invocationID string, body AgentAuthInvocationSubmitParams, opts ...option.RequestOption) (res *AgentAuthSubmitResponse, err error) { opts = slices.Concat(r.Options, opts) if invocationID == "" { @@ -190,9 +200,9 @@ func (r *AgentAuthInvocationSubmitParamsBodySSOButton) UnmarshalJSON(data []byte // The property SelectedMfaType is required. type AgentAuthInvocationSubmitParamsBodySelectedMfaType struct { - // The MFA delivery method type + // The MFA delivery method type (includes password for auth method selection pages) // - // Any of "sms", "call", "email", "totp", "push", "security_key". + // Any of "sms", "call", "email", "totp", "push", "password". SelectedMfaType string `json:"selected_mfa_type,omitzero,required"` paramObj } @@ -207,6 +217,6 @@ func (r *AgentAuthInvocationSubmitParamsBodySelectedMfaType) UnmarshalJSON(data func init() { apijson.RegisterFieldValidator[AgentAuthInvocationSubmitParamsBodySelectedMfaType]( - "selected_mfa_type", "sms", "call", "email", "totp", "push", "security_key", + "selected_mfa_type", "sms", "call", "email", "totp", "push", "password", ) } diff --git a/api.md b/api.md index 0c0e1a9..72fd646 100644 --- a/api.md +++ b/api.md @@ -207,6 +207,33 @@ Methods: - client.Profiles.Delete(ctx context.Context, idOrName string) error - client.Profiles.Download(ctx context.Context, idOrName string) (\*http.Response, error) +# Auth + +## Connections + +Params Types: + +- kernel.LoginRequestParam +- kernel.ManagedAuthCreateRequestParam +- kernel.SubmitFieldsRequestParam + +Response Types: + +- kernel.LoginResponse +- kernel.ManagedAuth +- kernel.SubmitFieldsResponse +- kernel.AuthConnectionFollowResponseUnion + +Methods: + +- client.Auth.Connections.New(ctx context.Context, body kernel.AuthConnectionNewParams) (\*kernel.ManagedAuth, error) +- client.Auth.Connections.Get(ctx context.Context, id string) (\*kernel.ManagedAuth, error) +- client.Auth.Connections.List(ctx context.Context, query kernel.AuthConnectionListParams) (\*pagination.OffsetPagination[kernel.ManagedAuth], error) +- client.Auth.Connections.Delete(ctx context.Context, id string) error +- client.Auth.Connections.Follow(ctx context.Context, id string) (\*kernel.AuthConnectionFollowResponseUnion, error) +- client.Auth.Connections.Login(ctx context.Context, id string, body kernel.AuthConnectionLoginParams) (\*kernel.LoginResponse, error) +- client.Auth.Connections.Submit(ctx context.Context, id string, body kernel.AuthConnectionSubmitParams) (\*kernel.SubmitFieldsResponse, error) + # Proxies Response Types: @@ -325,13 +352,16 @@ Params Types: Response Types: - kernel.CredentialProvider +- kernel.CredentialProviderItem - kernel.CredentialProviderTestResult +- kernel.CredentialProviderListItemsResponse Methods: -- client.CredentialProviders.New(ctx context.Context, body kernel.CredentialProviderNewParams) (\*kernel.CredentialProvider, error) -- client.CredentialProviders.Get(ctx context.Context, id string) (\*kernel.CredentialProvider, error) -- client.CredentialProviders.Update(ctx context.Context, id string, body kernel.CredentialProviderUpdateParams) (\*kernel.CredentialProvider, error) -- client.CredentialProviders.List(ctx context.Context) (\*[]kernel.CredentialProvider, error) -- client.CredentialProviders.Delete(ctx context.Context, id string) error -- client.CredentialProviders.Test(ctx context.Context, id string) (\*kernel.CredentialProviderTestResult, error) +- client.CredentialProviders.New(ctx context.Context, body kernel.CredentialProviderNewParams) (\*kernel.CredentialProvider, error) +- client.CredentialProviders.Get(ctx context.Context, id string) (\*kernel.CredentialProvider, error) +- client.CredentialProviders.Update(ctx context.Context, id string, body kernel.CredentialProviderUpdateParams) (\*kernel.CredentialProvider, error) +- client.CredentialProviders.List(ctx context.Context) (\*[]kernel.CredentialProvider, error) +- client.CredentialProviders.Delete(ctx context.Context, id string) error +- client.CredentialProviders.ListItems(ctx context.Context, id string) (\*kernel.CredentialProviderListItemsResponse, error) +- client.CredentialProviders.Test(ctx context.Context, id string) (\*kernel.CredentialProviderTestResult, error) diff --git a/auth.go b/auth.go new file mode 100644 index 0000000..0469989 --- /dev/null +++ b/auth.go @@ -0,0 +1,28 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +package kernel + +import ( + "github.com/kernel/kernel-go-sdk/option" +) + +// AuthService 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 [NewAuthService] method instead. +type AuthService struct { + Options []option.RequestOption + Connections AuthConnectionService +} + +// NewAuthService 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 NewAuthService(opts ...option.RequestOption) (r AuthService) { + r = AuthService{} + r.Options = opts + r.Connections = NewAuthConnectionService(opts...) + return +} diff --git a/authconnection.go b/authconnection.go new file mode 100644 index 0000000..6d7a9aa --- /dev/null +++ b/authconnection.go @@ -0,0 +1,878 @@ +// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details. + +package kernel + +import ( + "context" + "encoding/json" + "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" + "github.com/kernel/kernel-go-sdk/packages/ssestream" + "github.com/kernel/kernel-go-sdk/shared" + "github.com/kernel/kernel-go-sdk/shared/constant" +) + +// AuthConnectionService 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 [NewAuthConnectionService] method instead. +type AuthConnectionService struct { + Options []option.RequestOption +} + +// NewAuthConnectionService 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 NewAuthConnectionService(opts ...option.RequestOption) (r AuthConnectionService) { + r = AuthConnectionService{} + r.Options = opts + return +} + +// Creates managed authentication for a profile and domain combination. Returns 409 +// Conflict if managed auth already exists for the given profile and domain. +func (r *AuthConnectionService) New(ctx context.Context, body AuthConnectionNewParams, opts ...option.RequestOption) (res *ManagedAuth, err error) { + opts = slices.Concat(r.Options, opts) + path := "auth/connections" + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) + return +} + +// Retrieve managed auth by its ID. Includes current flow state if a login is in +// progress. +func (r *AuthConnectionService) Get(ctx context.Context, id string, opts ...option.RequestOption) (res *ManagedAuth, err error) { + opts = slices.Concat(r.Options, opts) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("auth/connections/%s", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...) + return +} + +// List managed auths with optional filters for profile_name and domain. +func (r *AuthConnectionService) List(ctx context.Context, query AuthConnectionListParams, opts ...option.RequestOption) (res *pagination.OffsetPagination[ManagedAuth], err error) { + var raw *http.Response + opts = slices.Concat(r.Options, opts) + opts = append([]option.RequestOption{option.WithResponseInto(&raw)}, opts...) + path := "auth/connections" + 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 managed auths with optional filters for profile_name and domain. +func (r *AuthConnectionService) ListAutoPaging(ctx context.Context, query AuthConnectionListParams, opts ...option.RequestOption) *pagination.OffsetPaginationAutoPager[ManagedAuth] { + return pagination.NewOffsetPaginationAutoPager(r.List(ctx, query, opts...)) +} + +// Deletes managed auth and terminates its workflow. This will: +// +// - Delete the managed auth record +// - Terminate the Temporal workflow +// - Cancel any in-progress login flows +func (r *AuthConnectionService) 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 + } + path := fmt.Sprintf("auth/connections/%s", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, nil, nil, opts...) + return +} + +// Establishes a Server-Sent Events (SSE) stream that delivers real-time login flow +// state updates. The stream terminates automatically once the flow reaches a +// terminal state (SUCCESS, FAILED, EXPIRED, CANCELED). +func (r *AuthConnectionService) FollowStreaming(ctx context.Context, id string, opts ...option.RequestOption) (stream *ssestream.Stream[AuthConnectionFollowResponseUnion]) { + var ( + raw *http.Response + err error + ) + opts = slices.Concat(r.Options, opts) + opts = append([]option.RequestOption{option.WithHeader("Accept", "text/event-stream")}, opts...) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("auth/connections/%s/events", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &raw, opts...) + return ssestream.NewStream[AuthConnectionFollowResponseUnion](ssestream.NewDecoder(raw), err) +} + +// Starts a login flow for the managed auth. Returns immediately with a hosted URL +// for the user to complete authentication, or triggers automatic re-auth if +// credentials are stored. +func (r *AuthConnectionService) Login(ctx context.Context, id string, body AuthConnectionLoginParams, opts ...option.RequestOption) (res *LoginResponse, err error) { + opts = slices.Concat(r.Options, opts) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("auth/connections/%s/login", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) + return +} + +// Submits field values for the login form. Poll the managed auth to track progress +// and get results. +func (r *AuthConnectionService) Submit(ctx context.Context, id string, body AuthConnectionSubmitParams, opts ...option.RequestOption) (res *SubmitFieldsResponse, err error) { + opts = slices.Concat(r.Options, opts) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("auth/connections/%s/submit", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) + return +} + +// Request to start a login flow +type LoginRequestParam struct { + // If provided, saves credentials under this name upon successful login + SaveCredentialAs param.Opt[string] `json:"save_credential_as,omitzero"` + paramObj +} + +func (r LoginRequestParam) MarshalJSON() (data []byte, err error) { + type shadow LoginRequestParam + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *LoginRequestParam) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Response from starting a login flow +type LoginResponse struct { + // Managed auth ID + ID string `json:"id,required"` + // When the login flow expires + FlowExpiresAt time.Time `json:"flow_expires_at,required" format:"date-time"` + // Type of login flow started + // + // Any of "LOGIN", "REAUTH". + FlowType LoginResponseFlowType `json:"flow_type,required"` + // URL to redirect user to for login + HostedURL string `json:"hosted_url,required" format:"uri"` + // One-time code for handoff (internal use) + HandoffCode string `json:"handoff_code"` + // Browser live view URL for watching the login flow + LiveViewURL string `json:"live_view_url" format:"uri"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + FlowExpiresAt respjson.Field + FlowType respjson.Field + HostedURL respjson.Field + HandoffCode respjson.Field + LiveViewURL respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r LoginResponse) RawJSON() string { return r.JSON.raw } +func (r *LoginResponse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Type of login flow started +type LoginResponseFlowType string + +const ( + LoginResponseFlowTypeLogin LoginResponseFlowType = "LOGIN" + LoginResponseFlowTypeReauth LoginResponseFlowType = "REAUTH" +) + +// Managed authentication that keeps a profile logged into a specific domain. Flow +// fields (flow_status, flow_step, discovered_fields, mfa_options) reflect the most +// recent login flow and are null when no flow has been initiated. +type ManagedAuth struct { + // Unique identifier for the managed auth + ID string `json:"id,required"` + // Target domain for authentication + Domain string `json:"domain,required"` + // Name of the profile associated with this managed auth + ProfileName string `json:"profile_name,required"` + // Current authentication status of the managed profile + // + // Any of "AUTHENTICATED", "NEEDS_AUTH". + Status ManagedAuthStatus `json:"status,required"` + // Additional domains that are valid for this auth flow (besides the primary + // domain). Useful when login pages redirect to different domains. + // + // The following SSO/OAuth provider domains are automatically allowed by default + // and do not need to be specified: + // + // - Google: accounts.google.com + // - Microsoft/Azure AD: login.microsoftonline.com, login.live.com + // - Okta: _.okta.com, _.oktapreview.com + // - Auth0: _.auth0.com, _.us.auth0.com, _.eu.auth0.com, _.au.auth0.com + // - Apple: appleid.apple.com + // - GitHub: github.com + // - Facebook/Meta: www.facebook.com + // - LinkedIn: www.linkedin.com + // - Amazon Cognito: \*.amazoncognito.com + // - OneLogin: \*.onelogin.com + // - Ping Identity: _.pingone.com, _.pingidentity.com + AllowedDomains []string `json:"allowed_domains"` + // Whether automatic re-authentication is possible (has credential, selectors, and + // login_url) + CanReauth bool `json:"can_reauth"` + // Reference to credentials for managed auth. Use one of: + // + // - { name } for Kernel credentials + // - { provider, path } for external provider item + // - { provider, auto: true } for external provider domain lookup + Credential ManagedAuthCredential `json:"credential"` + // Fields awaiting input (present when flow_step=awaiting_input) + DiscoveredFields []DiscoveredField `json:"discovered_fields,nullable"` + // Error message (present when flow_status=failed) + ErrorMessage string `json:"error_message,nullable"` + // Instructions for external action (present when + // flow_step=awaiting_external_action) + ExternalActionMessage string `json:"external_action_message,nullable"` + // When the current flow expires (null when no flow in progress) + FlowExpiresAt time.Time `json:"flow_expires_at,nullable" format:"date-time"` + // Current flow status (null when no flow in progress) + // + // Any of "IN_PROGRESS", "SUCCESS", "FAILED", "EXPIRED", "CANCELED". + FlowStatus ManagedAuthFlowStatus `json:"flow_status,nullable"` + // Current step in the flow (null when no flow in progress) + // + // Any of "DISCOVERING", "AWAITING_INPUT", "AWAITING_EXTERNAL_ACTION", + // "SUBMITTING", "COMPLETED". + FlowStep ManagedAuthFlowStep `json:"flow_step,nullable"` + // Type of the current flow (null when no flow in progress) + // + // Any of "LOGIN", "REAUTH". + FlowType ManagedAuthFlowType `json:"flow_type,nullable"` + // Interval in seconds between automatic health checks. When set, the system + // periodically verifies the authentication status and triggers re-authentication + // if needed. Must be between 300 (5 minutes) and 86400 (24 hours). Default is 3600 + // (1 hour). + HealthCheckInterval int64 `json:"health_check_interval,nullable"` + // URL to redirect user to for hosted login (present when flow in progress) + HostedURL string `json:"hosted_url,nullable" format:"uri"` + // When the profile was last successfully authenticated + LastAuthAt time.Time `json:"last_auth_at" format:"date-time"` + // Browser live view URL for debugging (present when flow in progress) + LiveViewURL string `json:"live_view_url,nullable" format:"uri"` + // MFA method options (present when flow_step=awaiting_input and MFA selection + // required) + MfaOptions []ManagedAuthMfaOption `json:"mfa_options,nullable"` + // SSO buttons available (present when flow_step=awaiting_input) + PendingSSOButtons []ManagedAuthPendingSSOButton `json:"pending_sso_buttons,nullable"` + // URL where the browser landed after successful login + PostLoginURL string `json:"post_login_url" format:"uri"` + // SSO provider being used (e.g., google, github, microsoft) + SSOProvider string `json:"sso_provider,nullable"` + // Visible error message from the website (e.g., 'Incorrect password'). Present + // when the website displays an error during login. + WebsiteError string `json:"website_error,nullable"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + Domain respjson.Field + ProfileName respjson.Field + Status respjson.Field + AllowedDomains respjson.Field + CanReauth respjson.Field + Credential respjson.Field + DiscoveredFields respjson.Field + ErrorMessage respjson.Field + ExternalActionMessage respjson.Field + FlowExpiresAt respjson.Field + FlowStatus respjson.Field + FlowStep respjson.Field + FlowType respjson.Field + HealthCheckInterval respjson.Field + HostedURL respjson.Field + LastAuthAt respjson.Field + LiveViewURL respjson.Field + MfaOptions respjson.Field + PendingSSOButtons respjson.Field + PostLoginURL respjson.Field + SSOProvider respjson.Field + WebsiteError respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ManagedAuth) RawJSON() string { return r.JSON.raw } +func (r *ManagedAuth) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Current authentication status of the managed profile +type ManagedAuthStatus string + +const ( + ManagedAuthStatusAuthenticated ManagedAuthStatus = "AUTHENTICATED" + ManagedAuthStatusNeedsAuth ManagedAuthStatus = "NEEDS_AUTH" +) + +// Reference to credentials for managed auth. Use one of: +// +// - { name } for Kernel credentials +// - { provider, path } for external provider item +// - { provider, auto: true } for external provider domain lookup +type ManagedAuthCredential struct { + // If true, lookup by domain from the specified provider + Auto bool `json:"auto"` + // Kernel credential name + Name string `json:"name"` + // Provider-specific path (e.g., "VaultName/ItemName" for 1Password) + Path string `json:"path"` + // External provider name (e.g., "my-1p") + Provider string `json:"provider"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Auto respjson.Field + Name respjson.Field + Path respjson.Field + Provider respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ManagedAuthCredential) RawJSON() string { return r.JSON.raw } +func (r *ManagedAuthCredential) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Current flow status (null when no flow in progress) +type ManagedAuthFlowStatus string + +const ( + ManagedAuthFlowStatusInProgress ManagedAuthFlowStatus = "IN_PROGRESS" + ManagedAuthFlowStatusSuccess ManagedAuthFlowStatus = "SUCCESS" + ManagedAuthFlowStatusFailed ManagedAuthFlowStatus = "FAILED" + ManagedAuthFlowStatusExpired ManagedAuthFlowStatus = "EXPIRED" + ManagedAuthFlowStatusCanceled ManagedAuthFlowStatus = "CANCELED" +) + +// Current step in the flow (null when no flow in progress) +type ManagedAuthFlowStep string + +const ( + ManagedAuthFlowStepDiscovering ManagedAuthFlowStep = "DISCOVERING" + ManagedAuthFlowStepAwaitingInput ManagedAuthFlowStep = "AWAITING_INPUT" + ManagedAuthFlowStepAwaitingExternalAction ManagedAuthFlowStep = "AWAITING_EXTERNAL_ACTION" + ManagedAuthFlowStepSubmitting ManagedAuthFlowStep = "SUBMITTING" + ManagedAuthFlowStepCompleted ManagedAuthFlowStep = "COMPLETED" +) + +// Type of the current flow (null when no flow in progress) +type ManagedAuthFlowType string + +const ( + ManagedAuthFlowTypeLogin ManagedAuthFlowType = "LOGIN" + ManagedAuthFlowTypeReauth ManagedAuthFlowType = "REAUTH" +) + +// An MFA method option for verification +type ManagedAuthMfaOption struct { + // The visible option text + Label string `json:"label,required"` + // The MFA delivery method type (includes password for auth method selection pages) + // + // Any of "sms", "call", "email", "totp", "push", "password". + Type string `json:"type,required"` + // Additional instructions from the site + Description string `json:"description,nullable"` + // The masked destination (phone/email) if shown + Target string `json:"target,nullable"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Label respjson.Field + Type respjson.Field + Description respjson.Field + Target respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ManagedAuthMfaOption) RawJSON() string { return r.JSON.raw } +func (r *ManagedAuthMfaOption) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// An SSO button for signing in with an external identity provider +type ManagedAuthPendingSSOButton struct { + // Visible button text + Label string `json:"label,required"` + // Identity provider name + Provider string `json:"provider,required"` + // XPath selector for the button + Selector string `json:"selector,required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Label respjson.Field + Provider respjson.Field + Selector respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r ManagedAuthPendingSSOButton) RawJSON() string { return r.JSON.raw } +func (r *ManagedAuthPendingSSOButton) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Request to create managed auth for a profile and domain +// +// The properties Domain, ProfileName are required. +type ManagedAuthCreateRequestParam struct { + // Domain for authentication + Domain string `json:"domain,required"` + // Name of the profile to manage authentication for + ProfileName string `json:"profile_name,required"` + // Interval in seconds between automatic health checks. When set, the system + // periodically verifies the authentication status and triggers re-authentication + // if needed. Must be between 300 (5 minutes) and 86400 (24 hours). Default is 3600 + // (1 hour). + HealthCheckInterval param.Opt[int64] `json:"health_check_interval,omitzero"` + // Optional login page URL to skip discovery + LoginURL param.Opt[string] `json:"login_url,omitzero" format:"uri"` + // Additional domains valid for this auth flow (besides the primary domain). Useful + // when login pages redirect to different domains. + // + // The following SSO/OAuth provider domains are automatically allowed by default + // and do not need to be specified: + // + // - Google: accounts.google.com + // - Microsoft/Azure AD: login.microsoftonline.com, login.live.com + // - Okta: _.okta.com, _.oktapreview.com + // - Auth0: _.auth0.com, _.us.auth0.com, _.eu.auth0.com, _.au.auth0.com + // - Apple: appleid.apple.com + // - GitHub: github.com + // - Facebook/Meta: www.facebook.com + // - LinkedIn: www.linkedin.com + // - Amazon Cognito: \*.amazoncognito.com + // - OneLogin: \*.onelogin.com + // - Ping Identity: _.pingone.com, _.pingidentity.com + AllowedDomains []string `json:"allowed_domains,omitzero"` + // Reference to credentials for managed auth. 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"` + // Optional proxy configuration + Proxy ManagedAuthCreateRequestProxyParam `json:"proxy,omitzero"` + paramObj +} + +func (r ManagedAuthCreateRequestParam) MarshalJSON() (data []byte, err error) { + type shadow ManagedAuthCreateRequestParam + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *ManagedAuthCreateRequestParam) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Reference to credentials for managed auth. Use one of: +// +// - { name } for Kernel credentials +// - { provider, path } for external provider item +// - { provider, auto: true } for external provider domain lookup +type ManagedAuthCreateRequestCredentialParam struct { + // If true, lookup by domain from the specified provider + Auto param.Opt[bool] `json:"auto,omitzero"` + // Kernel credential name + Name param.Opt[string] `json:"name,omitzero"` + // Provider-specific path (e.g., "VaultName/ItemName" for 1Password) + Path param.Opt[string] `json:"path,omitzero"` + // External provider name (e.g., "my-1p") + Provider param.Opt[string] `json:"provider,omitzero"` + paramObj +} + +func (r ManagedAuthCreateRequestCredentialParam) MarshalJSON() (data []byte, err error) { + type shadow ManagedAuthCreateRequestCredentialParam + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *ManagedAuthCreateRequestCredentialParam) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Optional proxy configuration +type ManagedAuthCreateRequestProxyParam struct { + // ID of the proxy to use + ProxyID param.Opt[string] `json:"proxy_id,omitzero"` + paramObj +} + +func (r ManagedAuthCreateRequestProxyParam) MarshalJSON() (data []byte, err error) { + type shadow ManagedAuthCreateRequestProxyParam + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *ManagedAuthCreateRequestProxyParam) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Request to submit field values for login +// +// The property Fields is required. +type SubmitFieldsRequestParam struct { + // Map of field name to value + Fields map[string]string `json:"fields,omitzero,required"` + // Optional MFA option ID if user selected an MFA method + MfaOptionID param.Opt[string] `json:"mfa_option_id,omitzero"` + // Optional XPath selector if user chose to click an SSO button instead + SSOButtonSelector param.Opt[string] `json:"sso_button_selector,omitzero"` + paramObj +} + +func (r SubmitFieldsRequestParam) MarshalJSON() (data []byte, err error) { + type shadow SubmitFieldsRequestParam + return param.MarshalObject(r, (*shadow)(&r)) +} +func (r *SubmitFieldsRequestParam) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// Response from submitting field values +type SubmitFieldsResponse struct { + // Whether the submission was accepted for processing + Accepted bool `json:"accepted,required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Accepted respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r SubmitFieldsResponse) RawJSON() string { return r.JSON.raw } +func (r *SubmitFieldsResponse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// AuthConnectionFollowResponseUnion contains all possible properties and values +// from [AuthConnectionFollowResponseManagedAuthState], [shared.ErrorEvent], +// [shared.HeartbeatEvent]. +// +// Use the [AuthConnectionFollowResponseUnion.AsAny] method to switch on the +// variant. +// +// Use the methods beginning with 'As' to cast the union to one of its variants. +type AuthConnectionFollowResponseUnion struct { + // Any of "managed_auth_state", "error", "sse_heartbeat". + Event string `json:"event"` + // This field is from variant [AuthConnectionFollowResponseManagedAuthState]. + FlowStatus string `json:"flow_status"` + // This field is from variant [AuthConnectionFollowResponseManagedAuthState]. + FlowStep string `json:"flow_step"` + Timestamp time.Time `json:"timestamp"` + // This field is from variant [AuthConnectionFollowResponseManagedAuthState]. + DiscoveredFields []DiscoveredField `json:"discovered_fields"` + // This field is from variant [AuthConnectionFollowResponseManagedAuthState]. + ErrorMessage string `json:"error_message"` + // This field is from variant [AuthConnectionFollowResponseManagedAuthState]. + ExternalActionMessage string `json:"external_action_message"` + // This field is from variant [AuthConnectionFollowResponseManagedAuthState]. + FlowType string `json:"flow_type"` + // This field is from variant [AuthConnectionFollowResponseManagedAuthState]. + HostedURL string `json:"hosted_url"` + // This field is from variant [AuthConnectionFollowResponseManagedAuthState]. + LiveViewURL string `json:"live_view_url"` + // This field is from variant [AuthConnectionFollowResponseManagedAuthState]. + MfaOptions []AuthConnectionFollowResponseManagedAuthStateMfaOption `json:"mfa_options"` + // This field is from variant [AuthConnectionFollowResponseManagedAuthState]. + PendingSSOButtons []AuthConnectionFollowResponseManagedAuthStatePendingSSOButton `json:"pending_sso_buttons"` + // This field is from variant [AuthConnectionFollowResponseManagedAuthState]. + PostLoginURL string `json:"post_login_url"` + // This field is from variant [AuthConnectionFollowResponseManagedAuthState]. + WebsiteError string `json:"website_error"` + // This field is from variant [shared.ErrorEvent]. + Error shared.ErrorModel `json:"error"` + JSON struct { + Event respjson.Field + FlowStatus respjson.Field + FlowStep respjson.Field + Timestamp respjson.Field + DiscoveredFields respjson.Field + ErrorMessage respjson.Field + ExternalActionMessage respjson.Field + FlowType respjson.Field + HostedURL respjson.Field + LiveViewURL respjson.Field + MfaOptions respjson.Field + PendingSSOButtons respjson.Field + PostLoginURL respjson.Field + WebsiteError respjson.Field + Error respjson.Field + raw string + } `json:"-"` +} + +// anyAuthConnectionFollowResponse is implemented by each variant of +// [AuthConnectionFollowResponseUnion] to add type safety for the return type of +// [AuthConnectionFollowResponseUnion.AsAny] +type anyAuthConnectionFollowResponse interface { + ImplAuthConnectionFollowResponseUnion() +} + +func (AuthConnectionFollowResponseManagedAuthState) ImplAuthConnectionFollowResponseUnion() {} + +// Use the following switch statement to find the correct variant +// +// switch variant := AuthConnectionFollowResponseUnion.AsAny().(type) { +// case kernel.AuthConnectionFollowResponseManagedAuthState: +// case shared.ErrorEvent: +// case shared.HeartbeatEvent: +// default: +// fmt.Errorf("no variant present") +// } +func (u AuthConnectionFollowResponseUnion) AsAny() anyAuthConnectionFollowResponse { + switch u.Event { + case "managed_auth_state": + return u.AsManagedAuthState() + case "error": + return u.AsError() + case "sse_heartbeat": + return u.AsSseHeartbeat() + } + return nil +} + +func (u AuthConnectionFollowResponseUnion) AsManagedAuthState() (v AuthConnectionFollowResponseManagedAuthState) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +func (u AuthConnectionFollowResponseUnion) AsError() (v shared.ErrorEvent) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +func (u AuthConnectionFollowResponseUnion) AsSseHeartbeat() (v shared.HeartbeatEvent) { + apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v) + return +} + +// Returns the unmodified JSON received from the API +func (u AuthConnectionFollowResponseUnion) RawJSON() string { return u.JSON.raw } + +func (r *AuthConnectionFollowResponseUnion) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// An event representing the current state of a managed auth flow. +type AuthConnectionFollowResponseManagedAuthState struct { + // Event type identifier (always "managed_auth_state"). + Event constant.ManagedAuthState `json:"event,required"` + // Current flow status. + // + // Any of "IN_PROGRESS", "SUCCESS", "FAILED", "EXPIRED", "CANCELED". + FlowStatus string `json:"flow_status,required"` + // Current step in the flow. + // + // Any of "DISCOVERING", "AWAITING_INPUT", "AWAITING_EXTERNAL_ACTION", + // "SUBMITTING", "COMPLETED". + FlowStep string `json:"flow_step,required"` + // Time the state was reported. + Timestamp time.Time `json:"timestamp,required" format:"date-time"` + // Fields awaiting input (present when flow_step=AWAITING_INPUT). + DiscoveredFields []DiscoveredField `json:"discovered_fields"` + // Error message (present when flow_status=FAILED). + ErrorMessage string `json:"error_message"` + // Instructions for external action (present when + // flow_step=AWAITING_EXTERNAL_ACTION). + ExternalActionMessage string `json:"external_action_message"` + // Type of the current flow. + // + // Any of "LOGIN", "REAUTH". + FlowType string `json:"flow_type"` + // URL to redirect user to for hosted login. + HostedURL string `json:"hosted_url" format:"uri"` + // Browser live view URL for debugging. + LiveViewURL string `json:"live_view_url" format:"uri"` + // MFA method options (present when flow_step=AWAITING_INPUT and MFA selection + // required). + MfaOptions []AuthConnectionFollowResponseManagedAuthStateMfaOption `json:"mfa_options"` + // SSO buttons available (present when flow_step=AWAITING_INPUT). + PendingSSOButtons []AuthConnectionFollowResponseManagedAuthStatePendingSSOButton `json:"pending_sso_buttons"` + // URL where the browser landed after successful login. + PostLoginURL string `json:"post_login_url" format:"uri"` + // Visible error message from the website (e.g., 'Incorrect password'). Present + // when the website displays an error during login. + WebsiteError string `json:"website_error"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Event respjson.Field + FlowStatus respjson.Field + FlowStep respjson.Field + Timestamp respjson.Field + DiscoveredFields respjson.Field + ErrorMessage respjson.Field + ExternalActionMessage respjson.Field + FlowType respjson.Field + HostedURL respjson.Field + LiveViewURL respjson.Field + MfaOptions respjson.Field + PendingSSOButtons respjson.Field + PostLoginURL respjson.Field + WebsiteError respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AuthConnectionFollowResponseManagedAuthState) RawJSON() string { return r.JSON.raw } +func (r *AuthConnectionFollowResponseManagedAuthState) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// An MFA method option for verification +type AuthConnectionFollowResponseManagedAuthStateMfaOption struct { + // The visible option text + Label string `json:"label,required"` + // The MFA delivery method type (includes password for auth method selection pages) + // + // Any of "sms", "call", "email", "totp", "push", "password". + Type string `json:"type,required"` + // Additional instructions from the site + Description string `json:"description,nullable"` + // The masked destination (phone/email) if shown + Target string `json:"target,nullable"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Label respjson.Field + Type respjson.Field + Description respjson.Field + Target respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AuthConnectionFollowResponseManagedAuthStateMfaOption) RawJSON() string { return r.JSON.raw } +func (r *AuthConnectionFollowResponseManagedAuthStateMfaOption) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +// An SSO button for signing in with an external identity provider +type AuthConnectionFollowResponseManagedAuthStatePendingSSOButton struct { + // Visible button text + Label string `json:"label,required"` + // Identity provider name + Provider string `json:"provider,required"` + // XPath selector for the button + Selector string `json:"selector,required"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Label respjson.Field + Provider respjson.Field + Selector respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r AuthConnectionFollowResponseManagedAuthStatePendingSSOButton) RawJSON() string { + return r.JSON.raw +} +func (r *AuthConnectionFollowResponseManagedAuthStatePendingSSOButton) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + +type AuthConnectionNewParams struct { + // Request to create managed auth for a profile and domain + ManagedAuthCreateRequest ManagedAuthCreateRequestParam + paramObj +} + +func (r AuthConnectionNewParams) MarshalJSON() (data []byte, err error) { + return shimjson.Marshal(r.ManagedAuthCreateRequest) +} +func (r *AuthConnectionNewParams) UnmarshalJSON(data []byte) error { + return json.Unmarshal(data, &r.ManagedAuthCreateRequest) +} + +type AuthConnectionListParams struct { + // Filter by domain + Domain param.Opt[string] `query:"domain,omitzero" json:"-"` + // Maximum number of results to return + Limit param.Opt[int64] `query:"limit,omitzero" json:"-"` + // Number of results to skip + Offset param.Opt[int64] `query:"offset,omitzero" json:"-"` + // Filter by profile name + ProfileName param.Opt[string] `query:"profile_name,omitzero" json:"-"` + paramObj +} + +// URLQuery serializes [AuthConnectionListParams]'s query parameters as +// `url.Values`. +func (r AuthConnectionListParams) URLQuery() (v url.Values, err error) { + return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{ + ArrayFormat: apiquery.ArrayQueryFormatComma, + NestedFormat: apiquery.NestedQueryFormatBrackets, + }) +} + +type AuthConnectionLoginParams struct { + // Request to start a login flow + LoginRequest LoginRequestParam + paramObj +} + +func (r AuthConnectionLoginParams) MarshalJSON() (data []byte, err error) { + return shimjson.Marshal(r.LoginRequest) +} +func (r *AuthConnectionLoginParams) UnmarshalJSON(data []byte) error { + return json.Unmarshal(data, &r.LoginRequest) +} + +type AuthConnectionSubmitParams struct { + // Request to submit field values for login + SubmitFieldsRequest SubmitFieldsRequestParam + paramObj +} + +func (r AuthConnectionSubmitParams) MarshalJSON() (data []byte, err error) { + return shimjson.Marshal(r.SubmitFieldsRequest) +} +func (r *AuthConnectionSubmitParams) UnmarshalJSON(data []byte) error { + return json.Unmarshal(data, &r.SubmitFieldsRequest) +} diff --git a/authconnection_test.go b/authconnection_test.go new file mode 100644 index 0000000..d619ada --- /dev/null +++ b/authconnection_test.go @@ -0,0 +1,195 @@ +// 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 TestAuthConnectionNewWithOptionalParams(t *testing.T) { + t.Skip("Prism 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.Auth.Connections.New(context.TODO(), kernel.AuthConnectionNewParams{ + ManagedAuthCreateRequest: kernel.ManagedAuthCreateRequestParam{ + Domain: "netflix.com", + ProfileName: "user-123", + AllowedDomains: []string{"login.netflix.com", "auth.netflix.com"}, + 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), + LoginURL: kernel.String("https://netflix.com/login"), + Proxy: kernel.ManagedAuthCreateRequestProxyParam{ + ProxyID: kernel.String("proxy_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 TestAuthConnectionGet(t *testing.T) { + t.Skip("Prism 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.Auth.Connections.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 TestAuthConnectionListWithOptionalParams(t *testing.T) { + t.Skip("Prism 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.Auth.Connections.List(context.TODO(), kernel.AuthConnectionListParams{ + Domain: kernel.String("domain"), + Limit: kernel.Int(100), + Offset: kernel.Int(0), + ProfileName: kernel.String("profile_name"), + }) + 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 TestAuthConnectionDelete(t *testing.T) { + t.Skip("Prism 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.Auth.Connections.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 TestAuthConnectionLoginWithOptionalParams(t *testing.T) { + t.Skip("Prism 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.Auth.Connections.Login( + context.TODO(), + "id", + kernel.AuthConnectionLoginParams{ + LoginRequest: kernel.LoginRequestParam{ + SaveCredentialAs: kernel.String("my-netflix-login"), + }, + }, + ) + 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 TestAuthConnectionSubmitWithOptionalParams(t *testing.T) { + t.Skip("Prism 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.Auth.Connections.Submit( + context.TODO(), + "id", + kernel.AuthConnectionSubmitParams{ + SubmitFieldsRequest: kernel.SubmitFieldsRequestParam{ + Fields: map[string]string{ + "email": "user@example.com", + "password": "secret", + }, + MfaOptionID: kernel.String("sms"), + SSOButtonSelector: kernel.String("xpath=//button[contains(text(), 'Continue with Google')]"), + }, + }, + ) + 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()) + } +} diff --git a/client.go b/client.go index a1ac662..4106fd4 100644 --- a/client.go +++ b/client.go @@ -22,6 +22,7 @@ type Client struct { Invocations InvocationService Browsers BrowserService Profiles ProfileService + Auth AuthService Proxies ProxyService Extensions ExtensionService BrowserPools BrowserPoolService @@ -57,6 +58,7 @@ func NewClient(opts ...option.RequestOption) (r Client) { r.Invocations = NewInvocationService(opts...) r.Browsers = NewBrowserService(opts...) r.Profiles = NewProfileService(opts...) + r.Auth = NewAuthService(opts...) r.Proxies = NewProxyService(opts...) r.Extensions = NewExtensionService(opts...) r.BrowserPools = NewBrowserPoolService(opts...) diff --git a/credentialprovider.go b/credentialprovider.go index ded8c4f..2e6c172 100644 --- a/credentialprovider.go +++ b/credentialprovider.go @@ -42,7 +42,7 @@ func NewCredentialProviderService(opts ...option.RequestOption) (r CredentialPro // credential lookup. func (r *CredentialProviderService) New(ctx context.Context, body CredentialProviderNewParams, opts ...option.RequestOption) (res *CredentialProvider, err error) { opts = slices.Concat(r.Options, opts) - path := "org/credential-providers" + path := "org/credential_providers" err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...) return } @@ -54,7 +54,7 @@ func (r *CredentialProviderService) Get(ctx context.Context, id string, opts ... err = errors.New("missing required id parameter") return } - path := fmt.Sprintf("org/credential-providers/%s", id) + path := fmt.Sprintf("org/credential_providers/%s", id) err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...) return } @@ -66,7 +66,7 @@ func (r *CredentialProviderService) Update(ctx context.Context, id string, body err = errors.New("missing required id parameter") return } - path := fmt.Sprintf("org/credential-providers/%s", id) + path := fmt.Sprintf("org/credential_providers/%s", id) err = requestconfig.ExecuteNewRequest(ctx, http.MethodPatch, path, body, &res, opts...) return } @@ -74,7 +74,7 @@ func (r *CredentialProviderService) Update(ctx context.Context, id string, body // List external credential providers configured for the organization. func (r *CredentialProviderService) List(ctx context.Context, opts ...option.RequestOption) (res *[]CredentialProvider, err error) { opts = slices.Concat(r.Options, opts) - path := "org/credential-providers" + path := "org/credential_providers" err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...) return } @@ -87,11 +87,24 @@ func (r *CredentialProviderService) Delete(ctx context.Context, id string, opts err = errors.New("missing required id parameter") return } - path := fmt.Sprintf("org/credential-providers/%s", id) + path := fmt.Sprintf("org/credential_providers/%s", id) err = requestconfig.ExecuteNewRequest(ctx, http.MethodDelete, path, nil, nil, opts...) return } +// Returns available credential items (e.g., 1Password login items) from the +// provider. +func (r *CredentialProviderService) ListItems(ctx context.Context, id string, opts ...option.RequestOption) (res *CredentialProviderListItemsResponse, err error) { + opts = slices.Concat(r.Options, opts) + if id == "" { + err = errors.New("missing required id parameter") + return + } + path := fmt.Sprintf("org/credential_providers/%s/items", id) + err = requestconfig.ExecuteNewRequest(ctx, http.MethodGet, path, nil, &res, opts...) + return +} + // Validate the credential provider's token and list accessible vaults. func (r *CredentialProviderService) Test(ctx context.Context, id string, opts ...option.RequestOption) (res *CredentialProviderTestResult, err error) { opts = slices.Concat(r.Options, opts) @@ -99,17 +112,19 @@ func (r *CredentialProviderService) Test(ctx context.Context, id string, opts .. err = errors.New("missing required id parameter") return } - path := fmt.Sprintf("org/credential-providers/%s/test", id) + path := fmt.Sprintf("org/credential_providers/%s/test", id) err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, nil, &res, opts...) return } // Request to create an external credential provider // -// The properties Token, ProviderType are required. +// The properties Token, Name, ProviderType are required. type CreateCredentialProviderRequestParam struct { // Service account token for the provider (e.g., 1Password service account token) Token string `json:"token,required"` + // Human-readable name for this provider instance (unique per org) + Name string `json:"name,required"` // Type of credential provider // // Any of "onepassword". @@ -143,6 +158,8 @@ type CredentialProvider struct { CreatedAt time.Time `json:"created_at,required" format:"date-time"` // Whether the provider is enabled for credential lookups Enabled bool `json:"enabled,required"` + // Human-readable name for this provider instance + Name string `json:"name,required"` // Priority order for credential lookups (lower numbers are checked first) Priority int64 `json:"priority,required"` // Type of credential provider @@ -156,6 +173,7 @@ type CredentialProvider struct { ID respjson.Field CreatedAt respjson.Field Enabled respjson.Field + Name respjson.Field Priority respjson.Field ProviderType respjson.Field UpdatedAt respjson.Field @@ -177,6 +195,39 @@ const ( CredentialProviderProviderTypeOnepassword CredentialProviderProviderType = "onepassword" ) +// A credential item from an external provider (e.g., a 1Password login item) +type CredentialProviderItem struct { + // Unique identifier for the item within the provider + ID string `json:"id,required"` + // Path to reference this item (VaultName/ItemTitle format) + Path string `json:"path,required"` + // Display name of the credential item + Title string `json:"title,required"` + // ID of the vault containing this item + VaultID string `json:"vault_id,required"` + // Name of the vault containing this item + VaultName string `json:"vault_name,required"` + // URLs associated with this credential + URLs []string `json:"urls"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + ID respjson.Field + Path respjson.Field + Title respjson.Field + VaultID respjson.Field + VaultName respjson.Field + URLs respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CredentialProviderItem) RawJSON() string { return r.JSON.raw } +func (r *CredentialProviderItem) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + // Result of testing a credential provider connection type CredentialProviderTestResult struct { // Whether the connection test was successful @@ -229,6 +280,8 @@ type UpdateCredentialProviderRequestParam struct { CacheTtlSeconds param.Opt[int64] `json:"cache_ttl_seconds,omitzero"` // Whether the provider is enabled for credential lookups Enabled param.Opt[bool] `json:"enabled,omitzero"` + // Human-readable name for this provider instance + Name param.Opt[string] `json:"name,omitzero"` // Priority order for credential lookups (lower numbers are checked first) Priority param.Opt[int64] `json:"priority,omitzero"` paramObj @@ -242,6 +295,22 @@ func (r *UpdateCredentialProviderRequestParam) UnmarshalJSON(data []byte) error return apijson.UnmarshalRoot(data, r) } +type CredentialProviderListItemsResponse struct { + Items []CredentialProviderItem `json:"items"` + // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. + JSON struct { + Items respjson.Field + ExtraFields map[string]respjson.Field + raw string + } `json:"-"` +} + +// Returns the unmodified JSON received from the API +func (r CredentialProviderListItemsResponse) RawJSON() string { return r.JSON.raw } +func (r *CredentialProviderListItemsResponse) UnmarshalJSON(data []byte) error { + return apijson.UnmarshalRoot(data, r) +} + type CredentialProviderNewParams struct { // Request to create an external credential provider CreateCredentialProviderRequest CreateCredentialProviderRequestParam diff --git a/credentialprovider_test.go b/credentialprovider_test.go index 18e4a02..296378c 100644 --- a/credentialprovider_test.go +++ b/credentialprovider_test.go @@ -29,6 +29,7 @@ func TestCredentialProviderNewWithOptionalParams(t *testing.T) { _, err := client.CredentialProviders.New(context.TODO(), kernel.CredentialProviderNewParams{ CreateCredentialProviderRequest: kernel.CreateCredentialProviderRequestParam{ Token: "ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", + Name: "my-1password", ProviderType: kernel.CreateCredentialProviderRequestProviderTypeOnepassword, CacheTtlSeconds: kernel.Int(300), }, @@ -86,6 +87,7 @@ func TestCredentialProviderUpdateWithOptionalParams(t *testing.T) { Token: kernel.String("ops_eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."), CacheTtlSeconds: kernel.Int(300), Enabled: kernel.Bool(true), + Name: kernel.String("my-1password"), Priority: kernel.Int(0), }, }, @@ -145,6 +147,29 @@ func TestCredentialProviderDelete(t *testing.T) { } } +func TestCredentialProviderListItems(t *testing.T) { + t.Skip("Prism 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.CredentialProviders.ListItems(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 TestCredentialProviderTest(t *testing.T) { t.Skip("Prism tests are disabled") baseURL := "http://localhost:4010" diff --git a/internal/version.go b/internal/version.go index d26ea0a..becd05d 100644 --- a/internal/version.go +++ b/internal/version.go @@ -2,4 +2,4 @@ package internal -const PackageVersion = "0.31.0" // x-release-please-version +const PackageVersion = "0.31.1" // x-release-please-version diff --git a/shared/constant/constants.go b/shared/constant/constants.go index 38af58e..104ffd3 100644 --- a/shared/constant/constants.go +++ b/shared/constant/constants.go @@ -24,6 +24,7 @@ type DeploymentState string // Always "deployment_state" type Error string // Always "error" type InvocationState string // Always "invocation_state" type Log string // Always "log" +type ManagedAuthState string // Always "managed_auth_state" type SseHeartbeat string // Always "sse_heartbeat" func (c AppVersionSummary) Default() AppVersionSummary { return "app_version_summary" } @@ -32,6 +33,7 @@ func (c DeploymentState) Default() DeploymentState { return "deployment_stat func (c Error) Default() Error { return "error" } func (c InvocationState) Default() InvocationState { return "invocation_state" } func (c Log) Default() Log { return "log" } +func (c ManagedAuthState) Default() ManagedAuthState { return "managed_auth_state" } func (c SseHeartbeat) Default() SseHeartbeat { return "sse_heartbeat" } func (c AppVersionSummary) MarshalJSON() ([]byte, error) { return marshalString(c) } @@ -40,6 +42,7 @@ func (c DeploymentState) MarshalJSON() ([]byte, error) { return marshalString( func (c Error) MarshalJSON() ([]byte, error) { return marshalString(c) } func (c InvocationState) MarshalJSON() ([]byte, error) { return marshalString(c) } func (c Log) MarshalJSON() ([]byte, error) { return marshalString(c) } +func (c ManagedAuthState) MarshalJSON() ([]byte, error) { return marshalString(c) } func (c SseHeartbeat) MarshalJSON() ([]byte, error) { return marshalString(c) } type constant[T any] interface { diff --git a/shared/shared.go b/shared/shared.go index fe7b089..d5248c3 100644 --- a/shared/shared.go +++ b/shared/shared.go @@ -260,7 +260,8 @@ func (r *ErrorEvent) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (ErrorEvent) ImplInvocationFollowResponseUnion() {} +func (ErrorEvent) ImplInvocationFollowResponseUnion() {} +func (ErrorEvent) ImplAuthConnectionFollowResponseUnion() {} type ErrorModel struct { // Application-specific error code (machine-readable) @@ -308,7 +309,8 @@ func (r *HeartbeatEvent) UnmarshalJSON(data []byte) error { return apijson.UnmarshalRoot(data, r) } -func (HeartbeatEvent) ImplInvocationFollowResponseUnion() {} +func (HeartbeatEvent) ImplInvocationFollowResponseUnion() {} +func (HeartbeatEvent) ImplAuthConnectionFollowResponseUnion() {} // A log entry from the application. type LogEvent struct {