Skip to content
2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
".": "0.115.0"
".": "0.116.0"
}
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## [0.116.0](https://github.com/kernel/kernel-go-sdk/compare/v0.115.0...v0.116.0) (2026-10-01)


### Features

* chore(stlc): seal custom-code tracking files ([10c4031](https://github.com/kernel/kernel-go-sdk/commit/10c4031082d73b41180adeb54a722f89341907ff))

## [0.115.0](https://github.com/kernel/kernel-go-sdk/compare/v0.114.0...v0.115.0) (2026-09-30)


Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Or to pin the version:
<!-- x-release-please-start-version -->

```sh
go get -u 'github.com/kernel/kernel-go-sdk@v0.115.0'
go get -u 'github.com/kernel/kernel-go-sdk@v0.116.0'
```

<!-- x-release-please-end -->
Expand Down
84 changes: 78 additions & 6 deletions credential.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,23 @@ type CreateCredentialRequestParam struct {
// button, it will be clicked first before filling credential values on the
// identity provider's login page.
SSOProvider param.Opt[string] `json:"sso_provider,omitzero"`
// Base32-encoded TOTP secret for generating one-time passwords. Used for automatic
// 2FA during login.
// Number of digits in generated TOTP codes. Defaults to 6 and is ignored when an
// `otpauth://` URI supplies the digit count.
TotpDigits param.Opt[int64] `json:"totp_digits,omitzero"`
// TOTP rotation period in seconds. Defaults to 30 and is ignored when an
// `otpauth://` URI supplies the period.
TotpPeriod param.Opt[int64] `json:"totp_period,omitzero"`
// Accepts a 16-128 character base32-encoded TOTP secret or an `otpauth://totp/...`
// URI. The range accepts existing shorter seeds and longer seeds regardless of
// HMAC algorithm; RFC 6238 recommends unpadded base32 lengths of 32/52/103 for
// SHA1/SHA256/SHA512. Only URI parameters present override the corresponding
// explicit TOTP fields. Used for automatic 2FA during login.
TotpSecret param.Opt[string] `json:"totp_secret,omitzero"`
// HMAC algorithm used to generate TOTP codes. Defaults to SHA1 and is ignored when
// an `otpauth://` URI supplies the algorithm.
//
// Any of "SHA1", "SHA256", "SHA512".
TotpAlgorithm CreateCredentialRequestTotpAlgorithm `json:"totp_algorithm,omitzero"`
paramObj
}

Expand All @@ -154,6 +168,16 @@ func (r *CreateCredentialRequestParam) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

// HMAC algorithm used to generate TOTP codes. Defaults to SHA1 and is ignored when
// an `otpauth://` URI supplies the algorithm.
type CreateCredentialRequestTotpAlgorithm string

const (
CreateCredentialRequestTotpAlgorithmSha1 CreateCredentialRequestTotpAlgorithm = "SHA1"
CreateCredentialRequestTotpAlgorithmSha256 CreateCredentialRequestTotpAlgorithm = "SHA256"
CreateCredentialRequestTotpAlgorithmSha512 CreateCredentialRequestTotpAlgorithm = "SHA512"
)

// A stored credential for automatic re-authentication
type Credential struct {
// Unique identifier for the credential
Expand All @@ -175,11 +199,22 @@ type Credential struct {
// button, it will be clicked first before filling credential values on the
// identity provider's login page.
SSOProvider string `json:"sso_provider" api:"nullable"`
// Current 6-digit TOTP code. Only included in create/update responses when
// totp_secret was just set.
// HMAC algorithm used to generate TOTP codes. Defaults to SHA1 for credentials
// created before this metadata was stored.
//
// Any of "SHA1", "SHA256", "SHA512".
TotpAlgorithm CredentialTotpAlgorithm `json:"totp_algorithm"`
// Current TOTP code. Only included in create/update responses when totp_secret was
// just set.
TotpCode string `json:"totp_code"`
// When the totp_code expires. Only included when totp_code is present.
TotpCodeExpiresAt time.Time `json:"totp_code_expires_at" format:"date-time"`
// Number of digits in generated TOTP codes. Defaults to 6 for credentials created
// before this metadata was stored.
TotpDigits int64 `json:"totp_digits"`
// TOTP rotation period in seconds. Defaults to 30 for credentials created before
// this metadata was stored.
TotpPeriod int64 `json:"totp_period"`
// The field names stored in this credential's values (e.g., username, password).
// Values themselves are never returned. Included on single-credential responses
// (create, get by id or name, update); omitted from list responses.
Expand All @@ -194,8 +229,11 @@ type Credential struct {
HasTotpSecret respjson.Field
HasValues respjson.Field
SSOProvider respjson.Field
TotpAlgorithm respjson.Field
TotpCode respjson.Field
TotpCodeExpiresAt respjson.Field
TotpDigits respjson.Field
TotpPeriod respjson.Field
ValueKeys respjson.Field
ExtraFields map[string]respjson.Field
raw string
Expand All @@ -208,19 +246,43 @@ func (r *Credential) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

// HMAC algorithm used to generate TOTP codes. Defaults to SHA1 for credentials
// created before this metadata was stored.
type CredentialTotpAlgorithm string

const (
CredentialTotpAlgorithmSha1 CredentialTotpAlgorithm = "SHA1"
CredentialTotpAlgorithmSha256 CredentialTotpAlgorithm = "SHA256"
CredentialTotpAlgorithmSha512 CredentialTotpAlgorithm = "SHA512"
)

// Request to update an existing credential
type UpdateCredentialRequestParam struct {
// If set, indicates this credential should be used with the specified SSO
// provider. Set to empty string or null to remove.
SSOProvider param.Opt[string] `json:"sso_provider,omitzero"`
// New name for the credential
Name param.Opt[string] `json:"name,omitzero"`
// Base32-encoded TOTP secret for generating one-time passwords. Spaces and
// formatting are automatically normalized. Set to empty string to remove.
// Number of digits in generated TOTP codes. Requires totp_secret and is ignored
// when an `otpauth://` URI supplies the digit count.
TotpDigits param.Opt[int64] `json:"totp_digits,omitzero"`
// TOTP rotation period in seconds. Requires totp_secret and is ignored when an
// `otpauth://` URI supplies the period.
TotpPeriod param.Opt[int64] `json:"totp_period,omitzero"`
// Accepts a 16-128 character base32-encoded TOTP secret or an `otpauth://totp/...`
// URI. Only URI parameters present override the corresponding explicit TOTP
// fields. When rotating a raw secret, omitted fields preserve their existing
// values; a new URI defaults unspecified fields to SHA1/6/30. Set to empty string
// to remove the secret and its metadata.
TotpSecret param.Opt[string] `json:"totp_secret,omitzero"`
// Field names to remove from the credential's stored values. Removals are applied
// before `values` are merged, so a key present in both is kept with its new value.
RemoveValueKeys []string `json:"remove_value_keys,omitzero"`
// HMAC algorithm used to generate TOTP codes. Requires totp_secret and is ignored
// when an `otpauth://` URI supplies the algorithm.
//
// Any of "SHA1", "SHA256", "SHA512".
TotpAlgorithm UpdateCredentialRequestTotpAlgorithm `json:"totp_algorithm,omitzero"`
// Field name to value mapping. Values are merged with existing values (new keys
// added, existing keys overwritten).
Values map[string]string `json:"values,omitzero"`
Expand All @@ -235,6 +297,16 @@ func (r *UpdateCredentialRequestParam) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}

// HMAC algorithm used to generate TOTP codes. Requires totp_secret and is ignored
// when an `otpauth://` URI supplies the algorithm.
type UpdateCredentialRequestTotpAlgorithm string

const (
UpdateCredentialRequestTotpAlgorithmSha1 UpdateCredentialRequestTotpAlgorithm = "SHA1"
UpdateCredentialRequestTotpAlgorithmSha256 UpdateCredentialRequestTotpAlgorithm = "SHA256"
UpdateCredentialRequestTotpAlgorithmSha512 UpdateCredentialRequestTotpAlgorithm = "SHA512"
)

type CredentialTotpCodeResponse struct {
// Current 6-digit TOTP code
Code string `json:"code" api:"required"`
Expand Down
10 changes: 8 additions & 2 deletions credential_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,11 @@ func TestCredentialNewWithOptionalParams(t *testing.T) {
"username": "user@example.com",
"password": "mysecretpassword",
},
SSOProvider: kernel.String("google"),
TotpSecret: kernel.String("JBSWY3DPEHPK3PXP"),
SSOProvider: kernel.String("google"),
TotpAlgorithm: kernel.CreateCredentialRequestTotpAlgorithmSha1,
TotpDigits: kernel.Int(6),
TotpPeriod: kernel.Int(30),
TotpSecret: kernel.String("JBSWY3DPEHPK3PXP"),
},
})
if err != nil {
Expand Down Expand Up @@ -91,6 +94,9 @@ func TestCredentialUpdateWithOptionalParams(t *testing.T) {
Name: kernel.String("my-updated-login"),
RemoveValueKeys: []string{"old_field"},
SSOProvider: kernel.String("google"),
TotpAlgorithm: kernel.UpdateCredentialRequestTotpAlgorithmSha1,
TotpDigits: kernel.Int(6),
TotpPeriod: kernel.Int(30),
TotpSecret: kernel.String("JBSWY3DPEHPK3PXP"),
Values: map[string]string{
"username": "user@example.com",
Expand Down
2 changes: 1 addition & 1 deletion internal/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

package internal

const PackageVersion = "0.115.0" // x-release-please-version
const PackageVersion = "0.116.0" // x-release-please-version
64 changes: 51 additions & 13 deletions vaultitem.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,9 @@ type CardVaultItemSpecUnion struct {
Merchant string `json:"merchant"`
// This field is from variant [CardVaultItemSpecAgentcard].
CardID string `json:"card_id"`
JSON struct {
// This field is from variant [CardVaultItemSpecAgentcard].
CheckoutOrigin string `json:"checkout_origin"`
JSON struct {
Amount respjson.Field
Context respjson.Field
Currency respjson.Field
Expand All @@ -451,6 +453,7 @@ type CardVaultItemSpecUnion struct {
Totals respjson.Field
Merchant respjson.Field
CardID respjson.Field
CheckoutOrigin respjson.Field
raw string
} `json:"-"`
}
Expand Down Expand Up @@ -629,8 +632,9 @@ func (r *CardVaultItemSpecLinkTotal) UnmarshalJSON(data []byte) error {
}

// AgentCard reusable live payment card. Test-mode card creation is not supported.
// Each checkout creates an approval-gated authorization for spec.merchant /
// spec.amount. The card stays ready after each authorization.
// Each checkout creates an authorization for spec.merchant / spec.amount that the
// cardholder approves, unless AgentCard runs it under one of the cardholder's
// autopilot rules. The card stays ready after each authorization.
type CardVaultItemSpecAgentcard struct {
// Integer amount in minor currency units.
Amount int64 `json:"amount" api:"required"`
Expand All @@ -644,16 +648,26 @@ type CardVaultItemSpecAgentcard struct {
// through unchanged without assuming a prefix or format. Omitted, the cardholder
// picks on the approval screen.
CardID string `json:"card_id"`
// Origin of the top-level checkout page, such as https://shop.example.com: https,
// a lowercase host, a port only when it is not 443, and no path. http is accepted
// only for localhost test pages. Checkouts without a preparation send it to
// AgentCard, which uses it to match the cardholder's autopilot rules; prepared
// checkouts send the preparation's merchant_origin instead. Kernel sends the
// declared value and does not compare it with the page the browser has open.
// Omitted, those checkouts ask the cardholder to approve. Card updates replace the
// whole spec, so an update that omits it removes it.
CheckoutOrigin string `json:"checkout_origin"`
// JSON contains metadata for fields, check presence with [respjson.Field.Valid].
JSON struct {
Amount respjson.Field
Currency respjson.Field
Merchant respjson.Field
Provider respjson.Field
Wallet respjson.Field
CardID respjson.Field
ExtraFields map[string]respjson.Field
raw string
Amount respjson.Field
Currency respjson.Field
Merchant respjson.Field
Provider respjson.Field
Wallet respjson.Field
CardID respjson.Field
CheckoutOrigin respjson.Field
ExtraFields map[string]respjson.Field
raw string
} `json:"-"`
}

Expand Down Expand Up @@ -768,6 +782,14 @@ func (u CardVaultItemSpecUnionParam) GetCardID() *string {
return nil
}

// Returns a pointer to the underlying variant's property, if present.
func (u CardVaultItemSpecUnionParam) GetCheckoutOrigin() *string {
if vt := u.OfAgentcard; vt != nil && vt.CheckoutOrigin.Valid() {
return &vt.CheckoutOrigin.Value
}
return nil
}

// Returns a pointer to the underlying variant's property, if present.
func (u CardVaultItemSpecUnionParam) GetAmount() *int64 {
if vt := u.OfLink; vt != nil {
Expand Down Expand Up @@ -909,8 +931,9 @@ func (r *CardVaultItemSpecLinkTotalParam) UnmarshalJSON(data []byte) error {
}

// AgentCard reusable live payment card. Test-mode card creation is not supported.
// Each checkout creates an approval-gated authorization for spec.merchant /
// spec.amount. The card stays ready after each authorization.
// Each checkout creates an authorization for spec.merchant / spec.amount that the
// cardholder approves, unless AgentCard runs it under one of the cardholder's
// autopilot rules. The card stays ready after each authorization.
//
// The properties Amount, Currency, Merchant, Provider, Wallet are required.
type CardVaultItemSpecAgentcardParam struct {
Expand All @@ -925,6 +948,15 @@ type CardVaultItemSpecAgentcardParam struct {
// through unchanged without assuming a prefix or format. Omitted, the cardholder
// picks on the approval screen.
CardID param.Opt[string] `json:"card_id,omitzero"`
// Origin of the top-level checkout page, such as https://shop.example.com: https,
// a lowercase host, a port only when it is not 443, and no path. http is accepted
// only for localhost test pages. Checkouts without a preparation send it to
// AgentCard, which uses it to match the cardholder's autopilot rules; prepared
// checkouts send the preparation's merchant_origin instead. Kernel sends the
// declared value and does not compare it with the page the browser has open.
// Omitted, those checkouts ask the cardholder to approve. Card updates replace the
// whole spec, so an update that omits it removes it.
CheckoutOrigin param.Opt[string] `json:"checkout_origin,omitzero"`
// This field can be elided, and will marshal its zero value as "agentcard".
Provider constant.Agentcard `json:"provider" default:"agentcard"`
paramObj
Expand Down Expand Up @@ -3465,6 +3497,8 @@ type VaultItemUnionSpec struct {
Merchant string `json:"merchant"`
// This field is from variant [CardVaultItemSpecUnion].
CardID string `json:"card_id"`
// This field is from variant [CardVaultItemSpecUnion].
CheckoutOrigin string `json:"checkout_origin"`
// This field is from variant [CredentialVaultItemSpecUnion].
Fields []CredentialVaultFieldDefinition `json:"fields"`
// This field is from variant [CredentialVaultItemSpecUnion].
Expand Down Expand Up @@ -3493,6 +3527,7 @@ type VaultItemUnionSpec struct {
Totals respjson.Field
Merchant respjson.Field
CardID respjson.Field
CheckoutOrigin respjson.Field
Fields respjson.Field
Description respjson.Field
Requests respjson.Field
Expand Down Expand Up @@ -4320,6 +4355,8 @@ type VaultItemOperationResponseUnionSpec struct {
Merchant string `json:"merchant"`
// This field is from variant [CardVaultItemSpecUnion].
CardID string `json:"card_id"`
// This field is from variant [CardVaultItemSpecUnion].
CheckoutOrigin string `json:"checkout_origin"`
// This field is from variant [CredentialVaultItemSpecUnion].
Fields []CredentialVaultFieldDefinition `json:"fields"`
// This field is from variant [CredentialVaultItemSpecUnion].
Expand Down Expand Up @@ -4348,6 +4385,7 @@ type VaultItemOperationResponseUnionSpec struct {
Totals respjson.Field
Merchant respjson.Field
CardID respjson.Field
CheckoutOrigin respjson.Field
Fields respjson.Field
Description respjson.Field
Requests respjson.Field
Expand Down
Loading