Callbacks service docs updated
This commit is contained in:
33
api/edge/bff/interface/api/sresponse/callback.go
Normal file
33
api/edge/bff/interface/api/sresponse/callback.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
package sresponse
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/tech/sendico/pkg/api/http/response"
|
||||||
|
"github.com/tech/sendico/pkg/mlogger"
|
||||||
|
"github.com/tech/sendico/pkg/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type callbackWriteResponse struct {
|
||||||
|
AccessToken TokenData `json:"accessToken"`
|
||||||
|
Callbacks []model.Callback `json:"callbacks"`
|
||||||
|
GeneratedSigningSecret string `json:"generatedSigningSecret,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Callback(
|
||||||
|
logger mlogger.Logger,
|
||||||
|
callback *model.Callback,
|
||||||
|
accessToken *TokenData,
|
||||||
|
generatedSecret string,
|
||||||
|
created bool,
|
||||||
|
) http.HandlerFunc {
|
||||||
|
resp := callbackWriteResponse{
|
||||||
|
AccessToken: *accessToken,
|
||||||
|
Callbacks: []model.Callback{*callback},
|
||||||
|
GeneratedSigningSecret: generatedSecret,
|
||||||
|
}
|
||||||
|
if created {
|
||||||
|
return response.Created(logger, resp)
|
||||||
|
}
|
||||||
|
return response.Ok(logger, resp)
|
||||||
|
}
|
||||||
@@ -42,9 +42,7 @@ func PrepareRefreshToken(
|
|||||||
}
|
}
|
||||||
|
|
||||||
token := &model.RefreshToken{
|
token := &model.RefreshToken{
|
||||||
AccountBoundBase: model.AccountBoundBase{
|
AccountRef: account.GetID(),
|
||||||
AccountRef: account.GetID(),
|
|
||||||
},
|
|
||||||
ClientRefreshToken: model.ClientRefreshToken{
|
ClientRefreshToken: model.ClientRefreshToken{
|
||||||
SessionIdentifier: *session,
|
SessionIdentifier: *session,
|
||||||
RefreshToken: refreshToken,
|
RefreshToken: refreshToken,
|
||||||
|
|||||||
47
api/edge/bff/internal/server/callbacksimp/create.go
Normal file
47
api/edge/bff/internal/server/callbacksimp/create.go
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package callbacksimp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/tech/sendico/pkg/api/http/response"
|
||||||
|
"github.com/tech/sendico/pkg/model"
|
||||||
|
"github.com/tech/sendico/server/interface/api/sresponse"
|
||||||
|
mutil "github.com/tech/sendico/server/internal/mutil/param"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *CallbacksAPI) create(r *http.Request, account *model.Account, accessToken *sresponse.TokenData) http.HandlerFunc {
|
||||||
|
organizationRef, err := a.Oph.GetRef(r)
|
||||||
|
if err != nil {
|
||||||
|
a.Logger.Warn("Failed to parse organization reference", zap.Error(err), mutil.PLog(a.Oph, r))
|
||||||
|
return response.BadReference(a.Logger, a.Name(), a.Oph.Name(), a.Oph.GetID(r), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var callback model.Callback
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&callback); err != nil {
|
||||||
|
a.Logger.Warn("Failed to decode callback payload", zap.Error(err))
|
||||||
|
return response.BadPayload(a.Logger, a.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
mutation, err := a.normalizeAndPrepare(r.Context(), &callback, organizationRef, "", true)
|
||||||
|
if err != nil {
|
||||||
|
return response.Auto(a.Logger, a.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := a.tf.CreateTransaction().Execute(r.Context(), func(ctx context.Context) (any, error) {
|
||||||
|
if err := a.DB.Create(ctx, *account.GetID(), organizationRef, &callback); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := a.applySigningSecretMutation(ctx, *account.GetID(), *callback.GetID(), mutation); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}); err != nil {
|
||||||
|
a.Logger.Warn("Failed to create callback transaction", zap.Error(err))
|
||||||
|
return response.Auto(a.Logger, a.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.callbackResponse(&callback, accessToken, mutation.Generated, true)
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ package callbacksimp
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -16,68 +16,10 @@ import (
|
|||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
type callbackWriteResponse struct {
|
type signingSecretMutation struct {
|
||||||
AccessToken sresponse.TokenData `json:"accessToken"`
|
SetSecretRef string
|
||||||
Callbacks []model.Callback `json:"callbacks"`
|
Clear bool
|
||||||
GeneratedSigningSecret string `json:"generatedSigningSecret,omitempty"`
|
Generated string
|
||||||
}
|
|
||||||
|
|
||||||
func (a *CallbacksAPI) create(r *http.Request, account *model.Account, accessToken *sresponse.TokenData) http.HandlerFunc {
|
|
||||||
organizationRef, err := a.Oph.GetRef(r)
|
|
||||||
if err != nil {
|
|
||||||
a.Logger.Warn("Failed to parse organization reference", zap.Error(err), mutil.PLog(a.Oph, r))
|
|
||||||
return response.BadReference(a.Logger, a.Name(), a.Oph.Name(), a.Oph.GetID(r), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var callback model.Callback
|
|
||||||
if err := json.NewDecoder(r.Body).Decode(&callback); err != nil {
|
|
||||||
a.Logger.Warn("Failed to decode callback payload", zap.Error(err))
|
|
||||||
return response.BadPayload(a.Logger, a.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
generatedSecret, err := a.normalizeAndPrepare(r.Context(), &callback, organizationRef, true)
|
|
||||||
if err != nil {
|
|
||||||
return response.Auto(a.Logger, a.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := a.DB.Create(r.Context(), *account.GetID(), organizationRef, &callback); err != nil {
|
|
||||||
a.Logger.Warn("Failed to create callback", zap.Error(err))
|
|
||||||
return response.Auto(a.Logger, a.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.callbackResponse(&callback, accessToken, generatedSecret, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *CallbacksAPI) update(r *http.Request, account *model.Account, accessToken *sresponse.TokenData) http.HandlerFunc {
|
|
||||||
var input model.Callback
|
|
||||||
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
|
|
||||||
a.Logger.Warn("Failed to decode callback payload", zap.Error(err))
|
|
||||||
return response.BadPayload(a.Logger, a.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
callbackRef := *input.GetID()
|
|
||||||
if callbackRef.IsZero() {
|
|
||||||
return response.Auto(a.Logger, a.Name(), merrors.InvalidArgument("callback id is required", "id"))
|
|
||||||
}
|
|
||||||
|
|
||||||
var existing model.Callback
|
|
||||||
if err := a.db.Get(r.Context(), *account.GetID(), callbackRef, &existing); err != nil {
|
|
||||||
a.Logger.Warn("Failed to fetch callback before update", zap.Error(err))
|
|
||||||
return response.Auto(a.Logger, a.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
mergeCallbackMutable(&existing, &input)
|
|
||||||
generatedSecret, err := a.normalizeAndPrepare(r.Context(), &existing, existing.OrganizationRef, true)
|
|
||||||
if err != nil {
|
|
||||||
return response.Auto(a.Logger, a.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := a.DB.Update(r.Context(), *account.GetID(), &existing); err != nil {
|
|
||||||
a.Logger.Warn("Failed to update callback", zap.Error(err))
|
|
||||||
return response.Auto(a.Logger, a.Name(), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.callbackResponse(&existing, accessToken, generatedSecret, false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *CallbacksAPI) rotateSecret(r *http.Request, account *model.Account, accessToken *sresponse.TokenData) http.HandlerFunc {
|
func (a *CallbacksAPI) rotateSecret(r *http.Request, account *model.Account, accessToken *sresponse.TokenData) http.HandlerFunc {
|
||||||
@@ -102,10 +44,8 @@ func (a *CallbacksAPI) rotateSecret(r *http.Request, account *model.Account, acc
|
|||||||
a.Logger.Warn("Failed to rotate callback signing secret", zap.Error(err))
|
a.Logger.Warn("Failed to rotate callback signing secret", zap.Error(err))
|
||||||
return response.Auto(a.Logger, a.Name(), err)
|
return response.Auto(a.Logger, a.Name(), err)
|
||||||
}
|
}
|
||||||
callback.RetryPolicy.SecretRef = secretRef
|
if err := a.db.SetSigningSecretRef(r.Context(), *account.GetID(), callbackRef, secretRef); err != nil {
|
||||||
|
a.Logger.Warn("Failed to persist rotated callback signing secret reference", zap.Error(err))
|
||||||
if err := a.DB.Update(r.Context(), *account.GetID(), &callback); err != nil {
|
|
||||||
a.Logger.Warn("Failed to persist rotated callback secret reference", zap.Error(err))
|
|
||||||
return response.Auto(a.Logger, a.Name(), err)
|
return response.Auto(a.Logger, a.Name(), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,29 +56,25 @@ func (a *CallbacksAPI) normalizeAndPrepare(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
callback *model.Callback,
|
callback *model.Callback,
|
||||||
organizationRef bson.ObjectID,
|
organizationRef bson.ObjectID,
|
||||||
|
existingSecretRef string,
|
||||||
allowSecretGeneration bool,
|
allowSecretGeneration bool,
|
||||||
) (string, error) {
|
) (signingSecretMutation, error) {
|
||||||
if callback == nil {
|
if callback == nil {
|
||||||
return "", merrors.InvalidArgument("callback payload is required")
|
return signingSecretMutation{}, merrors.InvalidArgument("callback payload is required")
|
||||||
}
|
}
|
||||||
if organizationRef.IsZero() {
|
if organizationRef.IsZero() {
|
||||||
return "", merrors.InvalidArgument("organization reference is required", "organizationRef")
|
return signingSecretMutation{}, merrors.InvalidArgument("organization reference is required", "organizationRef")
|
||||||
}
|
}
|
||||||
|
|
||||||
callback.SetOrganizationRef(organizationRef)
|
|
||||||
callback.Name = strings.TrimSpace(callback.Name)
|
callback.Name = strings.TrimSpace(callback.Name)
|
||||||
callback.Description = trimDescription(callback.Description)
|
callback.Description = trimDescription(callback.Description)
|
||||||
callback.ClientID = strings.TrimSpace(callback.ClientID)
|
|
||||||
if callback.ClientID == "" {
|
|
||||||
callback.ClientID = organizationRef.Hex()
|
|
||||||
}
|
|
||||||
|
|
||||||
callback.URL = strings.TrimSpace(callback.URL)
|
callback.URL = strings.TrimSpace(callback.URL)
|
||||||
if callback.URL == "" {
|
if callback.URL == "" {
|
||||||
return "", merrors.InvalidArgument("url is required", "url")
|
return signingSecretMutation{}, merrors.InvalidArgument("url is required", "url")
|
||||||
}
|
}
|
||||||
if err := validateCallbackURL(callback.URL); err != nil {
|
if err := validateCallbackURL(callback.URL); err != nil {
|
||||||
return "", err
|
return signingSecretMutation{}, err
|
||||||
}
|
}
|
||||||
if callback.Name == "" {
|
if callback.Name == "" {
|
||||||
callback.Name = callback.URL
|
callback.Name = callback.URL
|
||||||
@@ -146,15 +82,15 @@ func (a *CallbacksAPI) normalizeAndPrepare(
|
|||||||
|
|
||||||
status, err := normalizeStatus(callback.Status, a.config.DefaultStatus)
|
status, err := normalizeStatus(callback.Status, a.config.DefaultStatus)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return signingSecretMutation{}, err
|
||||||
}
|
}
|
||||||
callback.Status = status
|
callback.Status = status
|
||||||
callback.EventTypes = normalizeEventTypes(callback.EventTypes, a.config.DefaultEventTypes)
|
callback.EventTypes = normalizeEventTypes(callback.EventTypes, a.config.DefaultEventTypes)
|
||||||
|
|
||||||
callback.RetryPolicy.MinDelayMS = defaultInt(callback.RetryPolicy.MinDelayMS, defaultRetryMinDelayMS)
|
callback.RetryPolicy.Backoff.MinDelayMS = defaultInt(callback.RetryPolicy.Backoff.MinDelayMS, defaultRetryMinDelayMS)
|
||||||
callback.RetryPolicy.MaxDelayMS = defaultInt(callback.RetryPolicy.MaxDelayMS, defaultRetryMaxDelayMS)
|
callback.RetryPolicy.Backoff.MaxDelayMS = defaultInt(callback.RetryPolicy.Backoff.MaxDelayMS, defaultRetryMaxDelayMS)
|
||||||
if callback.RetryPolicy.MaxDelayMS < callback.RetryPolicy.MinDelayMS {
|
if callback.RetryPolicy.Backoff.MaxDelayMS < callback.RetryPolicy.Backoff.MinDelayMS {
|
||||||
callback.RetryPolicy.MaxDelayMS = callback.RetryPolicy.MinDelayMS
|
callback.RetryPolicy.Backoff.MaxDelayMS = callback.RetryPolicy.Backoff.MinDelayMS
|
||||||
}
|
}
|
||||||
callback.RetryPolicy.MaxAttempts = defaultInt(callback.RetryPolicy.MaxAttempts, defaultRetryMaxAttempts)
|
callback.RetryPolicy.MaxAttempts = defaultInt(callback.RetryPolicy.MaxAttempts, defaultRetryMaxAttempts)
|
||||||
callback.RetryPolicy.RequestTimeoutMS = defaultInt(callback.RetryPolicy.RequestTimeoutMS, defaultRetryRequestTimeoutMS)
|
callback.RetryPolicy.RequestTimeoutMS = defaultInt(callback.RetryPolicy.RequestTimeoutMS, defaultRetryRequestTimeoutMS)
|
||||||
@@ -162,36 +98,55 @@ func (a *CallbacksAPI) normalizeAndPrepare(
|
|||||||
|
|
||||||
mode, err := normalizeSigningMode(callback.RetryPolicy.SigningMode)
|
mode, err := normalizeSigningMode(callback.RetryPolicy.SigningMode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return signingSecretMutation{}, err
|
||||||
}
|
}
|
||||||
callback.RetryPolicy.SigningMode = mode
|
callback.RetryPolicy.SigningMode = mode
|
||||||
|
|
||||||
callback.RetryPolicy.SecretRef = strings.TrimSpace(callback.RetryPolicy.SecretRef)
|
existingSecretRef = strings.TrimSpace(existingSecretRef)
|
||||||
switch callback.RetryPolicy.SigningMode {
|
switch callback.RetryPolicy.SigningMode {
|
||||||
case model.CallbackSigningModeNone:
|
case model.CallbackSigningModeNone:
|
||||||
callback.RetryPolicy.SecretRef = ""
|
return signingSecretMutation{Clear: existingSecretRef != ""}, nil
|
||||||
return "", nil
|
|
||||||
case model.CallbackSigningModeHMACSHA256:
|
case model.CallbackSigningModeHMACSHA256:
|
||||||
if callback.RetryPolicy.SecretRef != "" {
|
if existingSecretRef != "" {
|
||||||
return "", nil
|
return signingSecretMutation{SetSecretRef: existingSecretRef}, nil
|
||||||
}
|
}
|
||||||
if !allowSecretGeneration {
|
if !allowSecretGeneration {
|
||||||
return "", merrors.InvalidArgument("secretRef is required for hmac_sha256 callbacks", "retryPolicy.secretRef")
|
return signingSecretMutation{}, merrors.InvalidArgument("signing secret is required for hmac_sha256 callbacks", "retryPolicy.signingMode")
|
||||||
}
|
}
|
||||||
if callback.GetID().IsZero() {
|
if callback.GetID().IsZero() {
|
||||||
callback.SetID(bson.NewObjectID())
|
callback.SetID(bson.NewObjectID())
|
||||||
}
|
}
|
||||||
secretRef, generatedSecret, err := a.secrets.Provision(ctx, organizationRef, *callback.GetID())
|
secretRef, generatedSecret, err := a.secrets.Provision(ctx, organizationRef, *callback.GetID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return signingSecretMutation{}, err
|
||||||
}
|
}
|
||||||
callback.RetryPolicy.SecretRef = secretRef
|
return signingSecretMutation{SetSecretRef: secretRef, Generated: generatedSecret}, nil
|
||||||
return generatedSecret, nil
|
|
||||||
default:
|
default:
|
||||||
return "", merrors.InvalidArgument("unsupported signing mode", "retryPolicy.signingMode")
|
return signingSecretMutation{}, merrors.InvalidArgument("unsupported signing mode", "retryPolicy.signingMode")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *CallbacksAPI) applySigningSecretMutation(
|
||||||
|
ctx context.Context,
|
||||||
|
accountRef,
|
||||||
|
callbackRef bson.ObjectID,
|
||||||
|
mutation signingSecretMutation,
|
||||||
|
) error {
|
||||||
|
if callbackRef.IsZero() {
|
||||||
|
return merrors.InvalidArgument("callback reference is required", "callbackRef")
|
||||||
|
}
|
||||||
|
if strings.TrimSpace(mutation.SetSecretRef) != "" {
|
||||||
|
return a.db.SetSigningSecretRef(ctx, accountRef, callbackRef, mutation.SetSecretRef)
|
||||||
|
}
|
||||||
|
if mutation.Clear {
|
||||||
|
err := a.db.ClearSigningSecretRef(ctx, accountRef, callbackRef)
|
||||||
|
if err != nil && !errors.Is(err, merrors.ErrNoData) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (a *CallbacksAPI) callbackResponse(
|
func (a *CallbacksAPI) callbackResponse(
|
||||||
callback *model.Callback,
|
callback *model.Callback,
|
||||||
accessToken *sresponse.TokenData,
|
accessToken *sresponse.TokenData,
|
||||||
@@ -202,15 +157,7 @@ func (a *CallbacksAPI) callbackResponse(
|
|||||||
return response.Internal(a.Logger, a.Name(), merrors.Internal("failed to build callback response"))
|
return response.Internal(a.Logger, a.Name(), merrors.Internal("failed to build callback response"))
|
||||||
}
|
}
|
||||||
|
|
||||||
resp := callbackWriteResponse{
|
return sresponse.Callback(a.Logger, callback, accessToken, generatedSecret, created)
|
||||||
AccessToken: *accessToken,
|
|
||||||
Callbacks: []model.Callback{*callback},
|
|
||||||
GeneratedSigningSecret: generatedSecret,
|
|
||||||
}
|
|
||||||
if created {
|
|
||||||
return response.Created(a.Logger, resp)
|
|
||||||
}
|
|
||||||
return response.Ok(a.Logger, resp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func normalizeStatus(raw, fallback model.CallbackStatus) (model.CallbackStatus, error) {
|
func normalizeStatus(raw, fallback model.CallbackStatus) (model.CallbackStatus, error) {
|
||||||
@@ -286,16 +233,17 @@ func normalizeHeaders(headers map[string]string) map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func mergeCallbackMutable(dst, src *model.Callback) {
|
func mergeCallbackMutable(dst, src *model.Callback) {
|
||||||
|
dst.OrganizationRef = src.OrganizationRef
|
||||||
dst.Describable = src.Describable
|
dst.Describable = src.Describable
|
||||||
dst.ClientID = src.ClientID
|
|
||||||
dst.Status = src.Status
|
dst.Status = src.Status
|
||||||
dst.URL = src.URL
|
dst.URL = src.URL
|
||||||
dst.EventTypes = append([]string(nil), src.EventTypes...)
|
dst.EventTypes = append([]string(nil), src.EventTypes...)
|
||||||
dst.RetryPolicy = model.CallbackRetryPolicy{
|
dst.RetryPolicy = model.CallbackRetryPolicy{
|
||||||
MinDelayMS: src.RetryPolicy.MinDelayMS,
|
Backoff: model.CallbackBackoff{
|
||||||
MaxDelayMS: src.RetryPolicy.MaxDelayMS,
|
MinDelayMS: src.RetryPolicy.Backoff.MinDelayMS,
|
||||||
|
MaxDelayMS: src.RetryPolicy.Backoff.MaxDelayMS,
|
||||||
|
},
|
||||||
SigningMode: src.RetryPolicy.SigningMode,
|
SigningMode: src.RetryPolicy.SigningMode,
|
||||||
SecretRef: src.RetryPolicy.SecretRef,
|
|
||||||
Headers: normalizeHeaders(src.RetryPolicy.Headers),
|
Headers: normalizeHeaders(src.RetryPolicy.Headers),
|
||||||
MaxAttempts: src.RetryPolicy.MaxAttempts,
|
MaxAttempts: src.RetryPolicy.MaxAttempts,
|
||||||
RequestTimeoutMS: src.RetryPolicy.RequestTimeoutMS,
|
RequestTimeoutMS: src.RetryPolicy.RequestTimeoutMS,
|
||||||
@@ -81,7 +81,7 @@ func newSigningSecretManager(logger mlogger.Logger, cfg callbacksConfig) (signin
|
|||||||
}
|
}
|
||||||
|
|
||||||
if isVaultConfigEmpty(cfg.Vault) {
|
if isVaultConfigEmpty(cfg.Vault) {
|
||||||
manager.logger.Warn("Callbacks Vault config is not set; secret generation requires explicit secretRef in payloads")
|
manager.logger.Warn("Callbacks Vault config is not set; hmac signing secret generation is disabled")
|
||||||
ensureSigningSecretMetrics()
|
ensureSigningSecretMetrics()
|
||||||
return manager, nil
|
return manager, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
api "github.com/tech/sendico/pkg/api/http"
|
api "github.com/tech/sendico/pkg/api/http"
|
||||||
"github.com/tech/sendico/pkg/db/callbacks"
|
"github.com/tech/sendico/pkg/db/callbacks"
|
||||||
|
"github.com/tech/sendico/pkg/db/transaction"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
"github.com/tech/sendico/pkg/model"
|
"github.com/tech/sendico/pkg/model"
|
||||||
"github.com/tech/sendico/pkg/mservice"
|
"github.com/tech/sendico/pkg/mservice"
|
||||||
@@ -16,6 +17,7 @@ import (
|
|||||||
type CallbacksAPI struct {
|
type CallbacksAPI struct {
|
||||||
papitemplate.ProtectedAPI[model.Callback]
|
papitemplate.ProtectedAPI[model.Callback]
|
||||||
db callbacks.DB
|
db callbacks.DB
|
||||||
|
tf transaction.Factory
|
||||||
secrets signingSecretManager
|
secrets signingSecretManager
|
||||||
config callbacksConfig
|
config callbacksConfig
|
||||||
}
|
}
|
||||||
@@ -35,6 +37,7 @@ func CreateAPI(apiCtx eapi.API) (*CallbacksAPI, error) {
|
|||||||
|
|
||||||
res := &CallbacksAPI{
|
res := &CallbacksAPI{
|
||||||
config: newCallbacksConfig(apiCtx.Config().Callbacks),
|
config: newCallbacksConfig(apiCtx.Config().Callbacks),
|
||||||
|
tf: apiCtx.DBFactory().TransactionFactory(),
|
||||||
}
|
}
|
||||||
|
|
||||||
p, err := papitemplate.CreateAPI(apiCtx, dbFactory, mservice.Organizations, mservice.Callbacks)
|
p, err := papitemplate.CreateAPI(apiCtx, dbFactory, mservice.Organizations, mservice.Callbacks)
|
||||||
|
|||||||
59
api/edge/bff/internal/server/callbacksimp/update.go
Normal file
59
api/edge/bff/internal/server/callbacksimp/update.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
package callbacksimp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/tech/sendico/pkg/api/http/response"
|
||||||
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
|
"github.com/tech/sendico/pkg/model"
|
||||||
|
"github.com/tech/sendico/server/interface/api/sresponse"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (a *CallbacksAPI) update(r *http.Request, account *model.Account, accessToken *sresponse.TokenData) http.HandlerFunc {
|
||||||
|
var input model.Callback
|
||||||
|
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
|
||||||
|
a.Logger.Warn("Failed to decode callback payload", zap.Error(err))
|
||||||
|
return response.BadPayload(a.Logger, a.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
callbackRef := *input.GetID()
|
||||||
|
if callbackRef.IsZero() {
|
||||||
|
return response.Auto(a.Logger, a.Name(), merrors.InvalidArgument("callback ref is required", "id"))
|
||||||
|
}
|
||||||
|
|
||||||
|
var existing model.Callback
|
||||||
|
if err := a.db.Get(r.Context(), *account.GetID(), callbackRef, &existing); err != nil {
|
||||||
|
a.Logger.Warn("Failed to fetch callback before update", zap.Error(err))
|
||||||
|
return response.Auto(a.Logger, a.Name(), err)
|
||||||
|
}
|
||||||
|
existingSecretRef, err := a.db.GetSigningSecretRef(r.Context(), *account.GetID(), callbackRef)
|
||||||
|
if err != nil && !errors.Is(err, merrors.ErrNoData) {
|
||||||
|
a.Logger.Warn("Failed to fetch callback signing secret metadata", zap.Error(err))
|
||||||
|
return response.Auto(a.Logger, a.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
mergeCallbackMutable(&existing, &input)
|
||||||
|
mutation, err := a.normalizeAndPrepare(r.Context(), &existing, existing.OrganizationRef, existingSecretRef, true)
|
||||||
|
if err != nil {
|
||||||
|
return response.Auto(a.Logger, a.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := a.tf.CreateTransaction().Execute(r.Context(), func(ctx context.Context) (any, error) {
|
||||||
|
if err := a.DB.Update(ctx, *account.GetID(), &existing); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := a.applySigningSecretMutation(ctx, *account.GetID(), callbackRef, mutation); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, nil
|
||||||
|
}); err != nil {
|
||||||
|
a.Logger.Warn("Failed to update callback transaction", zap.Error(err))
|
||||||
|
return response.Auto(a.Logger, a.Name(), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return a.callbackResponse(&existing, accessToken, mutation.Generated, false)
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/tech/sendico/edge/callbacks/internal/model"
|
||||||
"github.com/tech/sendico/edge/callbacks/internal/signing"
|
"github.com/tech/sendico/edge/callbacks/internal/signing"
|
||||||
"github.com/tech/sendico/edge/callbacks/internal/storage"
|
"github.com/tech/sendico/edge/callbacks/internal/storage"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
@@ -154,7 +155,7 @@ func (s *service) runWorker(ctx context.Context, workerID string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) handleTask(ctx context.Context, workerID string, task *storage.Task) {
|
func (s *service) handleTask(ctx context.Context, workerID string, task *model.Task) {
|
||||||
started := time.Now()
|
started := time.Now()
|
||||||
statusCode := 0
|
statusCode := 0
|
||||||
result := "failed"
|
result := "failed"
|
||||||
|
|||||||
@@ -4,16 +4,18 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Envelope is the canonical incoming event envelope.
|
// Envelope is the canonical incoming event envelope.
|
||||||
type Envelope struct {
|
type Envelope struct {
|
||||||
EventID string `json:"event_id"`
|
EventID string `json:"event_id"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
ClientID string `json:"client_id"`
|
OrganizationRef bson.ObjectID `json:"organization_ref"`
|
||||||
OccurredAt time.Time `json:"occurred_at"`
|
OccurredAt time.Time `json:"occurred_at"`
|
||||||
PublishedAt time.Time `json:"published_at,omitempty"`
|
PublishedAt time.Time `json:"published_at,omitempty"`
|
||||||
Data json.RawMessage `json:"data"`
|
Data json.RawMessage `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Service parses incoming messages and builds outbound payload bytes.
|
// Service parses incoming messages and builds outbound payload bytes.
|
||||||
@@ -24,10 +26,10 @@ type Service interface {
|
|||||||
|
|
||||||
// Payload is the stable outbound JSON body.
|
// Payload is the stable outbound JSON body.
|
||||||
type Payload struct {
|
type Payload struct {
|
||||||
EventID string `json:"event_id"`
|
EventID string `json:"event_id"`
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
ClientID string `json:"client_id"`
|
OrganizationRef bson.ObjectID `json:"organization_ref"`
|
||||||
OccurredAt string `json:"occurred_at"`
|
OccurredAt string `json:"occurred_at"`
|
||||||
PublishedAt string `json:"published_at,omitempty"`
|
PublishedAt string `json:"published_at,omitempty"`
|
||||||
Data json.RawMessage `json:"data"`
|
Data json.RawMessage `json:"data"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
"github.com/tech/sendico/pkg/mlogger"
|
"github.com/tech/sendico/pkg/mlogger"
|
||||||
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -39,8 +40,8 @@ func (s *parserService) Parse(data []byte) (*Envelope, error) {
|
|||||||
if strings.TrimSpace(envelope.Type) == "" {
|
if strings.TrimSpace(envelope.Type) == "" {
|
||||||
return nil, merrors.InvalidArgument("type is required", "type")
|
return nil, merrors.InvalidArgument("type is required", "type")
|
||||||
}
|
}
|
||||||
if strings.TrimSpace(envelope.ClientID) == "" {
|
if envelope.OrganizationRef == bson.NilObjectID {
|
||||||
return nil, merrors.InvalidArgument("client_id is required", "client_id")
|
return nil, merrors.InvalidArgument("organization_ref is required", "organization_ref")
|
||||||
}
|
}
|
||||||
if envelope.OccurredAt.IsZero() {
|
if envelope.OccurredAt.IsZero() {
|
||||||
return nil, merrors.InvalidArgument("occurred_at is required", "occurred_at")
|
return nil, merrors.InvalidArgument("occurred_at is required", "occurred_at")
|
||||||
@@ -51,7 +52,6 @@ func (s *parserService) Parse(data []byte) (*Envelope, error) {
|
|||||||
|
|
||||||
envelope.EventID = strings.TrimSpace(envelope.EventID)
|
envelope.EventID = strings.TrimSpace(envelope.EventID)
|
||||||
envelope.Type = strings.TrimSpace(envelope.Type)
|
envelope.Type = strings.TrimSpace(envelope.Type)
|
||||||
envelope.ClientID = strings.TrimSpace(envelope.ClientID)
|
|
||||||
envelope.OccurredAt = envelope.OccurredAt.UTC()
|
envelope.OccurredAt = envelope.OccurredAt.UTC()
|
||||||
if !envelope.PublishedAt.IsZero() {
|
if !envelope.PublishedAt.IsZero() {
|
||||||
envelope.PublishedAt = envelope.PublishedAt.UTC()
|
envelope.PublishedAt = envelope.PublishedAt.UTC()
|
||||||
@@ -66,11 +66,11 @@ func (s *parserService) BuildPayload(_ context.Context, envelope *Envelope) ([]b
|
|||||||
}
|
}
|
||||||
|
|
||||||
payload := Payload{
|
payload := Payload{
|
||||||
EventID: envelope.EventID,
|
EventID: envelope.EventID,
|
||||||
Type: envelope.Type,
|
Type: envelope.Type,
|
||||||
ClientID: envelope.ClientID,
|
OrganizationRef: envelope.OrganizationRef,
|
||||||
OccurredAt: envelope.OccurredAt.UTC().Format(time.RFC3339Nano),
|
OccurredAt: envelope.OccurredAt.UTC().Format(time.RFC3339Nano),
|
||||||
Data: envelope.Data,
|
Data: envelope.Data,
|
||||||
}
|
}
|
||||||
if !envelope.PublishedAt.IsZero() {
|
if !envelope.PublishedAt.IsZero() {
|
||||||
payload.PublishedAt = envelope.PublishedAt.UTC().Format(time.RFC3339Nano)
|
payload.PublishedAt = envelope.PublishedAt.UTC().Format(time.RFC3339Nano)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
np "github.com/tech/sendico/pkg/messaging/notifications/processor"
|
np "github.com/tech/sendico/pkg/messaging/notifications/processor"
|
||||||
"github.com/tech/sendico/pkg/mlogger"
|
"github.com/tech/sendico/pkg/mlogger"
|
||||||
"github.com/tech/sendico/pkg/model"
|
"github.com/tech/sendico/pkg/model"
|
||||||
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -178,7 +179,7 @@ func (s *service) handlePaymentStatusUpdated(ctx context.Context, msg *model.Pay
|
|||||||
result = ingestResultEmptyPayload
|
result = ingestResultEmptyPayload
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if strings.TrimSpace(msg.EventID) == "" || strings.TrimSpace(msg.ClientID) == "" || msg.OccurredAt.IsZero() {
|
if strings.TrimSpace(msg.EventID) == "" || msg.Data.OrganizationRef == bson.NilObjectID || msg.OccurredAt.IsZero() {
|
||||||
result = ingestResultInvalidEvent
|
result = ingestResultInvalidEvent
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -195,15 +196,15 @@ func (s *service) handlePaymentStatusUpdated(ctx context.Context, msg *model.Pay
|
|||||||
}
|
}
|
||||||
|
|
||||||
parsed := &events.Envelope{
|
parsed := &events.Envelope{
|
||||||
EventID: strings.TrimSpace(msg.EventID),
|
EventID: strings.TrimSpace(msg.EventID),
|
||||||
Type: eventType,
|
Type: eventType,
|
||||||
ClientID: strings.TrimSpace(msg.ClientID),
|
OrganizationRef: msg.Data.OrganizationRef,
|
||||||
OccurredAt: msg.OccurredAt.UTC(),
|
OccurredAt: msg.OccurredAt.UTC(),
|
||||||
PublishedAt: msg.PublishedAt.UTC(),
|
PublishedAt: msg.PublishedAt.UTC(),
|
||||||
Data: data,
|
Data: data,
|
||||||
}
|
}
|
||||||
|
|
||||||
inserted, err := s.deps.InboxRepo.TryInsert(ctx, parsed.EventID, parsed.ClientID, parsed.Type, time.Now().UTC())
|
inserted, err := s.deps.InboxRepo.TryInsert(ctx, parsed.EventID, parsed.Type, parsed.OrganizationRef, time.Now().UTC())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result = ingestResultInboxError
|
result = ingestResultInboxError
|
||||||
return err
|
return err
|
||||||
@@ -213,7 +214,7 @@ func (s *service) handlePaymentStatusUpdated(ctx context.Context, msg *model.Pay
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints, err := s.deps.Resolver.Resolve(ctx, parsed.ClientID, parsed.Type)
|
endpoints, err := s.deps.Resolver.Resolve(ctx, parsed.Type, parsed.OrganizationRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result = ingestResultResolveError
|
result = ingestResultResolveError
|
||||||
return err
|
return err
|
||||||
|
|||||||
8
api/edge/callbacks/internal/model/callback.go
Normal file
8
api/edge/callbacks/internal/model/callback.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import pmodel "github.com/tech/sendico/pkg/model"
|
||||||
|
|
||||||
|
type CallbackInternal struct {
|
||||||
|
pmodel.Callback `bson:",inline" json:",inline"`
|
||||||
|
SecretRef string `bson:"secretRef"`
|
||||||
|
}
|
||||||
22
api/edge/callbacks/internal/model/endpoint.go
Normal file
22
api/edge/callbacks/internal/model/endpoint.go
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tech/sendico/pkg/db/storable"
|
||||||
|
pmodel "github.com/tech/sendico/pkg/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Endpoint describes one target callback endpoint.
|
||||||
|
type Endpoint struct {
|
||||||
|
storable.Base
|
||||||
|
pmodel.OrganizationBoundBase
|
||||||
|
URL string
|
||||||
|
SigningMode string
|
||||||
|
SecretRef string
|
||||||
|
Headers map[string]string
|
||||||
|
MaxAttempts int
|
||||||
|
MinDelay time.Duration
|
||||||
|
MaxDelay time.Duration
|
||||||
|
RequestTimeout time.Duration
|
||||||
|
}
|
||||||
37
api/edge/callbacks/internal/model/task.go
Normal file
37
api/edge/callbacks/internal/model/task.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tech/sendico/pkg/db/storable"
|
||||||
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TaskStatus tracks delivery task lifecycle.
|
||||||
|
type TaskStatus string
|
||||||
|
|
||||||
|
const (
|
||||||
|
TaskStatusPending TaskStatus = "PENDING"
|
||||||
|
TaskStatusRetry TaskStatus = "RETRY"
|
||||||
|
TaskStatusDelivered TaskStatus = "DELIVERED"
|
||||||
|
TaskStatusFailed TaskStatus = "FAILED"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Task is one callback delivery job.
|
||||||
|
type Task struct {
|
||||||
|
storable.Base
|
||||||
|
EventID string
|
||||||
|
EndpointRef bson.ObjectID
|
||||||
|
EndpointURL string
|
||||||
|
SigningMode string
|
||||||
|
SecretRef string
|
||||||
|
Headers map[string]string
|
||||||
|
Payload []byte
|
||||||
|
Attempt int
|
||||||
|
MaxAttempts int
|
||||||
|
MinDelay time.Duration
|
||||||
|
MaxDelay time.Duration
|
||||||
|
RequestTimeout time.Duration
|
||||||
|
Status TaskStatus
|
||||||
|
NextAttemptAt time.Time
|
||||||
|
}
|
||||||
@@ -4,54 +4,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/tech/sendico/edge/callbacks/internal/model"
|
||||||
"github.com/tech/sendico/pkg/db"
|
"github.com/tech/sendico/pkg/db"
|
||||||
"github.com/tech/sendico/pkg/mlogger"
|
"github.com/tech/sendico/pkg/mlogger"
|
||||||
"go.mongodb.org/mongo-driver/v2/bson"
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TaskStatus tracks delivery task lifecycle.
|
|
||||||
type TaskStatus string
|
|
||||||
|
|
||||||
const (
|
|
||||||
TaskStatusPending TaskStatus = "PENDING"
|
|
||||||
TaskStatusRetry TaskStatus = "RETRY"
|
|
||||||
TaskStatusDelivered TaskStatus = "DELIVERED"
|
|
||||||
TaskStatusFailed TaskStatus = "FAILED"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Endpoint describes one target callback endpoint.
|
|
||||||
type Endpoint struct {
|
|
||||||
ID bson.ObjectID
|
|
||||||
ClientID string
|
|
||||||
URL string
|
|
||||||
SigningMode string
|
|
||||||
SecretRef string
|
|
||||||
Headers map[string]string
|
|
||||||
MaxAttempts int
|
|
||||||
MinDelay time.Duration
|
|
||||||
MaxDelay time.Duration
|
|
||||||
RequestTimeout time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
// Task is one callback delivery job.
|
|
||||||
type Task struct {
|
|
||||||
ID bson.ObjectID
|
|
||||||
EventID string
|
|
||||||
EndpointID bson.ObjectID
|
|
||||||
EndpointURL string
|
|
||||||
SigningMode string
|
|
||||||
SecretRef string
|
|
||||||
Headers map[string]string
|
|
||||||
Payload []byte
|
|
||||||
Attempt int
|
|
||||||
MaxAttempts int
|
|
||||||
MinDelay time.Duration
|
|
||||||
MaxDelay time.Duration
|
|
||||||
RequestTimeout time.Duration
|
|
||||||
Status TaskStatus
|
|
||||||
NextAttemptAt time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// TaskDefaults are applied when creating tasks.
|
// TaskDefaults are applied when creating tasks.
|
||||||
type TaskDefaults struct {
|
type TaskDefaults struct {
|
||||||
MaxAttempts int
|
MaxAttempts int
|
||||||
@@ -69,18 +27,18 @@ type Options struct {
|
|||||||
|
|
||||||
// InboxRepo controls event dedupe state.
|
// InboxRepo controls event dedupe state.
|
||||||
type InboxRepo interface {
|
type InboxRepo interface {
|
||||||
TryInsert(ctx context.Context, eventID, clientID, eventType string, at time.Time) (bool, error)
|
TryInsert(ctx context.Context, eventID, ceventType string, organizationRef bson.ObjectID, at time.Time) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// EndpointRepo resolves endpoints for events.
|
// EndpointRepo resolves endpoints for events.
|
||||||
type EndpointRepo interface {
|
type EndpointRepo interface {
|
||||||
FindActiveByClientAndType(ctx context.Context, clientID, eventType string) ([]Endpoint, error)
|
FindActive(ctx context.Context, eventType string, organizationRef bson.ObjectID) ([]model.Endpoint, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TaskRepo manages callback tasks.
|
// TaskRepo manages callback tasks.
|
||||||
type TaskRepo interface {
|
type TaskRepo interface {
|
||||||
UpsertTasks(ctx context.Context, eventID string, endpoints []Endpoint, payload []byte, defaults TaskDefaults, at time.Time) error
|
UpsertTasks(ctx context.Context, eventID string, endpoints []model.Endpoint, payload []byte, defaults TaskDefaults, at time.Time) error
|
||||||
LockNextTask(ctx context.Context, now time.Time, workerID string, lockTTL time.Duration) (*Task, error)
|
LockNextTask(ctx context.Context, now time.Time, workerID string, lockTTL time.Duration) (*model.Task, error)
|
||||||
MarkDelivered(ctx context.Context, taskID bson.ObjectID, httpCode int, latency time.Duration, at time.Time) error
|
MarkDelivered(ctx context.Context, taskID bson.ObjectID, httpCode int, latency time.Duration, at time.Time) error
|
||||||
MarkRetry(ctx context.Context, taskID bson.ObjectID, attempt int, nextAttemptAt time.Time, lastError string, httpCode int, at time.Time) error
|
MarkRetry(ctx context.Context, taskID bson.ObjectID, attempt int, nextAttemptAt time.Time, lastError string, httpCode int, at time.Time) error
|
||||||
MarkFailed(ctx context.Context, taskID bson.ObjectID, attempt int, lastError string, httpCode int, at time.Time) error
|
MarkFailed(ctx context.Context, taskID bson.ObjectID, attempt int, lastError string, httpCode int, at time.Time) error
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/tech/sendico/edge/callbacks/internal/model"
|
||||||
"github.com/tech/sendico/pkg/db"
|
"github.com/tech/sendico/pkg/db"
|
||||||
"github.com/tech/sendico/pkg/db/repository"
|
"github.com/tech/sendico/pkg/db/repository"
|
||||||
"github.com/tech/sendico/pkg/db/repository/builder"
|
"github.com/tech/sendico/pkg/db/repository/builder"
|
||||||
@@ -13,6 +14,7 @@ import (
|
|||||||
"github.com/tech/sendico/pkg/db/storable"
|
"github.com/tech/sendico/pkg/db/storable"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
"github.com/tech/sendico/pkg/mlogger"
|
"github.com/tech/sendico/pkg/mlogger"
|
||||||
|
pmodel "github.com/tech/sendico/pkg/model"
|
||||||
"github.com/tech/sendico/pkg/mservice"
|
"github.com/tech/sendico/pkg/mservice"
|
||||||
mutil "github.com/tech/sendico/pkg/mutil/db"
|
mutil "github.com/tech/sendico/pkg/mutil/db"
|
||||||
"go.mongodb.org/mongo-driver/v2/bson"
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
@@ -39,10 +41,10 @@ type mongoRepository struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type inboxDoc struct {
|
type inboxDoc struct {
|
||||||
storable.Base `bson:",inline"`
|
storable.Base `bson:",inline"`
|
||||||
EventID string `bson:"event_id"`
|
pmodel.OrganizationBoundBase `bson:",inline"`
|
||||||
ClientID string `bson:"client_id"`
|
EventID string `bson:"event_id"`
|
||||||
EventType string `bson:"event_type"`
|
EventType string `bson:"event_type"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *inboxDoc) Collection() string {
|
func (d *inboxDoc) Collection() string {
|
||||||
@@ -64,12 +66,12 @@ type deliveryPolicy struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type endpointDoc struct {
|
type endpointDoc struct {
|
||||||
storable.Base `bson:",inline"`
|
storable.Base `bson:",inline"`
|
||||||
deliveryPolicy `bson:"retry_policy"`
|
pmodel.OrganizationBoundBase `bson:",inline"`
|
||||||
ClientID string `bson:"client_id"`
|
deliveryPolicy `bson:"retry_policy"`
|
||||||
Status string `bson:"status"`
|
Status string `bson:"status"`
|
||||||
URL string `bson:"url"`
|
URL string `bson:"url"`
|
||||||
EventTypes []string `bson:"event_types"`
|
EventTypes []string `bson:"event_types"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *endpointDoc) Collection() string {
|
func (d *endpointDoc) Collection() string {
|
||||||
@@ -79,18 +81,18 @@ func (d *endpointDoc) Collection() string {
|
|||||||
type taskDoc struct {
|
type taskDoc struct {
|
||||||
storable.Base `bson:",inline"`
|
storable.Base `bson:",inline"`
|
||||||
deliveryPolicy `bson:"retry_policy"`
|
deliveryPolicy `bson:"retry_policy"`
|
||||||
EventID string `bson:"event_id"`
|
EventID string `bson:"event_id"`
|
||||||
EndpointID bson.ObjectID `bson:"endpoint_id"`
|
EndpointRef bson.ObjectID `bson:"endpoint_ref"`
|
||||||
EndpointURL string `bson:"endpoint_url"`
|
EndpointURL string `bson:"endpoint_url"`
|
||||||
Payload []byte `bson:"payload"`
|
Payload []byte `bson:"payload"`
|
||||||
Status TaskStatus `bson:"status"`
|
Status model.TaskStatus `bson:"status"`
|
||||||
Attempt int `bson:"attempt"`
|
Attempt int `bson:"attempt"`
|
||||||
LastError string `bson:"last_error,omitempty"`
|
LastError string `bson:"last_error,omitempty"`
|
||||||
LastHTTPCode int `bson:"last_http_code,omitempty"`
|
LastHTTPCode int `bson:"last_http_code,omitempty"`
|
||||||
NextAttemptAt time.Time `bson:"next_attempt_at"`
|
NextAttemptAt time.Time `bson:"next_attempt_at"`
|
||||||
LockedUntil *time.Time `bson:"locked_until,omitempty"`
|
LockedUntil *time.Time `bson:"locked_until,omitempty"`
|
||||||
WorkerID string `bson:"worker_id,omitempty"`
|
WorkerID string `bson:"worker_id,omitempty"`
|
||||||
DeliveredAt *time.Time `bson:"delivered_at,omitempty"`
|
DeliveredAt *time.Time `bson:"delivered_at,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *taskDoc) Collection() string {
|
func (d *taskDoc) Collection() string {
|
||||||
@@ -152,7 +154,7 @@ func (m *mongoRepository) ensureIndexes() error {
|
|||||||
Unique: true,
|
Unique: true,
|
||||||
Keys: []ri.Key{
|
Keys: []ri.Key{
|
||||||
{Field: "event_id", Sort: ri.Asc},
|
{Field: "event_id", Sort: ri.Asc},
|
||||||
{Field: "endpoint_id", Sort: ri.Asc},
|
{Field: "endpoint_ref", Sort: ri.Asc},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -172,7 +174,7 @@ func (m *mongoRepository) ensureIndexes() error {
|
|||||||
if err := m.endpointsRepo.CreateIndex(&ri.Definition{
|
if err := m.endpointsRepo.CreateIndex(&ri.Definition{
|
||||||
Name: "idx_client_event",
|
Name: "idx_client_event",
|
||||||
Keys: []ri.Key{
|
Keys: []ri.Key{
|
||||||
{Field: "client_id", Sort: ri.Asc},
|
{Field: "organization_ref", Sort: ri.Asc},
|
||||||
{Field: "status", Sort: ri.Asc},
|
{Field: "status", Sort: ri.Asc},
|
||||||
{Field: "event_types", Sort: ri.Asc},
|
{Field: "event_types", Sort: ri.Asc},
|
||||||
},
|
},
|
||||||
@@ -188,11 +190,11 @@ type inboxStore struct {
|
|||||||
repo repository.Repository
|
repo repository.Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *inboxStore) TryInsert(ctx context.Context, eventID, clientID, eventType string, at time.Time) (bool, error) {
|
func (r *inboxStore) TryInsert(ctx context.Context, eventID, eventType string, organizationRef bson.ObjectID, at time.Time) (bool, error) {
|
||||||
doc := &inboxDoc{
|
doc := &inboxDoc{
|
||||||
EventID: strings.TrimSpace(eventID),
|
OrganizationBoundBase: pmodel.OrganizationBoundBase{OrganizationRef: organizationRef},
|
||||||
ClientID: strings.TrimSpace(clientID),
|
EventID: strings.TrimSpace(eventID),
|
||||||
EventType: strings.TrimSpace(eventType),
|
EventType: strings.TrimSpace(eventType),
|
||||||
}
|
}
|
||||||
|
|
||||||
filter := repository.Filter("event_id", doc.EventID)
|
filter := repository.Filter("event_id", doc.EventID)
|
||||||
@@ -212,21 +214,20 @@ type endpointStore struct {
|
|||||||
repo repository.Repository
|
repo repository.Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *endpointStore) FindActiveByClientAndType(ctx context.Context, clientID, eventType string) ([]Endpoint, error) {
|
func (r *endpointStore) FindActive(ctx context.Context, eventType string, organizationRef bson.ObjectID) ([]model.Endpoint, error) {
|
||||||
clientID = strings.TrimSpace(clientID)
|
|
||||||
eventType = strings.TrimSpace(eventType)
|
eventType = strings.TrimSpace(eventType)
|
||||||
if clientID == "" {
|
if organizationRef == bson.NilObjectID {
|
||||||
return nil, merrors.InvalidArgument("client_id is required", "client_id")
|
return nil, merrors.InvalidArgument("organization_ref is required", "organization_ref")
|
||||||
}
|
}
|
||||||
if eventType == "" {
|
if eventType == "" {
|
||||||
return nil, merrors.InvalidArgument("event type is required", "event_type")
|
return nil, merrors.InvalidArgument("event type is required", "event_type")
|
||||||
}
|
}
|
||||||
|
|
||||||
query := repository.Query().
|
query := repository.Query().
|
||||||
Filter(repository.Field("client_id"), clientID).
|
Filter(repository.OrgField(), organizationRef).
|
||||||
In(repository.Field("status"), "active", "enabled")
|
In(repository.Field("status"), "active", "enabled")
|
||||||
|
|
||||||
out := make([]Endpoint, 0)
|
out := make([]model.Endpoint, 0)
|
||||||
err := r.repo.FindManyByFilter(ctx, query, func(cur *mongo.Cursor) error {
|
err := r.repo.FindManyByFilter(ctx, query, func(cur *mongo.Cursor) error {
|
||||||
doc := &endpointDoc{}
|
doc := &endpointDoc{}
|
||||||
if err := cur.Decode(doc); err != nil {
|
if err := cur.Decode(doc); err != nil {
|
||||||
@@ -238,17 +239,17 @@ func (r *endpointStore) FindActiveByClientAndType(ctx context.Context, clientID,
|
|||||||
if !supportsEventType(doc.EventTypes, eventType) {
|
if !supportsEventType(doc.EventTypes, eventType) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
out = append(out, Endpoint{
|
out = append(out, model.Endpoint{
|
||||||
ID: doc.ID,
|
Base: doc.Base,
|
||||||
ClientID: doc.ClientID,
|
OrganizationBoundBase: doc.OrganizationBoundBase,
|
||||||
URL: strings.TrimSpace(doc.URL),
|
URL: strings.TrimSpace(doc.URL),
|
||||||
SigningMode: strings.TrimSpace(doc.SigningMode),
|
SigningMode: strings.TrimSpace(doc.SigningMode),
|
||||||
SecretRef: strings.TrimSpace(doc.SecretRef),
|
SecretRef: strings.TrimSpace(doc.SecretRef),
|
||||||
Headers: cloneHeaders(doc.Headers),
|
Headers: cloneHeaders(doc.Headers),
|
||||||
MaxAttempts: doc.MaxAttempts,
|
MaxAttempts: doc.MaxAttempts,
|
||||||
MinDelay: time.Duration(doc.MinDelayMS) * time.Millisecond,
|
MinDelay: time.Duration(doc.MinDelayMS) * time.Millisecond,
|
||||||
MaxDelay: time.Duration(doc.MaxDelayMS) * time.Millisecond,
|
MaxDelay: time.Duration(doc.MaxDelayMS) * time.Millisecond,
|
||||||
RequestTimeout: time.Duration(doc.RequestTimeoutMS) * time.Millisecond,
|
RequestTimeout: time.Duration(doc.RequestTimeoutMS) * time.Millisecond,
|
||||||
})
|
})
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@@ -281,7 +282,7 @@ type taskStore struct {
|
|||||||
repo repository.Repository
|
repo repository.Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *taskStore) UpsertTasks(ctx context.Context, eventID string, endpoints []Endpoint, payload []byte, defaults TaskDefaults, at time.Time) error {
|
func (r *taskStore) UpsertTasks(ctx context.Context, eventID string, endpoints []model.Endpoint, payload []byte, defaults TaskDefaults, at time.Time) error {
|
||||||
eventID = strings.TrimSpace(eventID)
|
eventID = strings.TrimSpace(eventID)
|
||||||
if eventID == "" {
|
if eventID == "" {
|
||||||
return merrors.InvalidArgument("event id is required", "event_id")
|
return merrors.InvalidArgument("event id is required", "event_id")
|
||||||
@@ -292,7 +293,7 @@ func (r *taskStore) UpsertTasks(ctx context.Context, eventID string, endpoints [
|
|||||||
|
|
||||||
now := at.UTC()
|
now := at.UTC()
|
||||||
for _, endpoint := range endpoints {
|
for _, endpoint := range endpoints {
|
||||||
if endpoint.ID == bson.NilObjectID {
|
if endpoint.GetID() == nil || *endpoint.GetID() == bson.NilObjectID {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,13 +328,13 @@ func (r *taskStore) UpsertTasks(ctx context.Context, eventID string, endpoints [
|
|||||||
|
|
||||||
doc := &taskDoc{}
|
doc := &taskDoc{}
|
||||||
doc.EventID = eventID
|
doc.EventID = eventID
|
||||||
doc.EndpointID = endpoint.ID
|
doc.EndpointRef = *endpoint.GetID()
|
||||||
doc.EndpointURL = strings.TrimSpace(endpoint.URL)
|
doc.EndpointURL = strings.TrimSpace(endpoint.URL)
|
||||||
doc.SigningMode = strings.TrimSpace(endpoint.SigningMode)
|
doc.SigningMode = strings.TrimSpace(endpoint.SigningMode)
|
||||||
doc.SecretRef = strings.TrimSpace(endpoint.SecretRef)
|
doc.SecretRef = strings.TrimSpace(endpoint.SecretRef)
|
||||||
doc.Headers = cloneHeaders(endpoint.Headers)
|
doc.Headers = cloneHeaders(endpoint.Headers)
|
||||||
doc.Payload = append([]byte(nil), payload...)
|
doc.Payload = append([]byte(nil), payload...)
|
||||||
doc.Status = TaskStatusPending
|
doc.Status = model.TaskStatusPending
|
||||||
doc.Attempt = 0
|
doc.Attempt = 0
|
||||||
doc.MaxAttempts = maxAttempts
|
doc.MaxAttempts = maxAttempts
|
||||||
doc.MinDelayMS = int(minDelay / time.Millisecond)
|
doc.MinDelayMS = int(minDelay / time.Millisecond)
|
||||||
@@ -341,7 +342,7 @@ func (r *taskStore) UpsertTasks(ctx context.Context, eventID string, endpoints [
|
|||||||
doc.RequestTimeoutMS = int(requestTimeout / time.Millisecond)
|
doc.RequestTimeoutMS = int(requestTimeout / time.Millisecond)
|
||||||
doc.NextAttemptAt = now
|
doc.NextAttemptAt = now
|
||||||
|
|
||||||
filter := repository.Filter("event_id", eventID).And(repository.Filter("endpoint_id", endpoint.ID))
|
filter := repository.Filter("event_id", eventID).And(repository.Filter("endpoint_ref", endpoint.ID))
|
||||||
if err := r.repo.Insert(ctx, doc, filter); err != nil {
|
if err := r.repo.Insert(ctx, doc, filter); err != nil {
|
||||||
if errors.Is(err, merrors.ErrDataConflict) {
|
if errors.Is(err, merrors.ErrDataConflict) {
|
||||||
continue
|
continue
|
||||||
@@ -353,7 +354,7 @@ func (r *taskStore) UpsertTasks(ctx context.Context, eventID string, endpoints [
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *taskStore) LockNextTask(ctx context.Context, now time.Time, workerID string, lockTTL time.Duration) (*Task, error) {
|
func (r *taskStore) LockNextTask(ctx context.Context, now time.Time, workerID string, lockTTL time.Duration) (*model.Task, error) {
|
||||||
workerID = strings.TrimSpace(workerID)
|
workerID = strings.TrimSpace(workerID)
|
||||||
if workerID == "" {
|
if workerID == "" {
|
||||||
return nil, merrors.InvalidArgument("worker id is required", "worker_id")
|
return nil, merrors.InvalidArgument("worker id is required", "worker_id")
|
||||||
@@ -368,7 +369,7 @@ func (r *taskStore) LockNextTask(ctx context.Context, now time.Time, workerID st
|
|||||||
)
|
)
|
||||||
|
|
||||||
query := repository.Query().
|
query := repository.Query().
|
||||||
In(repository.Field("status"), string(TaskStatusPending), string(TaskStatusRetry)).
|
In(repository.Field("status"), string(model.TaskStatusPending), string(model.TaskStatusRetry)).
|
||||||
Comparison(repository.Field("next_attempt_at"), builder.Lte, now).
|
Comparison(repository.Field("next_attempt_at"), builder.Lte, now).
|
||||||
And(lockFilter).
|
And(lockFilter).
|
||||||
Sort(repository.Field("next_attempt_at"), true).
|
Sort(repository.Field("next_attempt_at"), true).
|
||||||
@@ -390,7 +391,7 @@ func (r *taskStore) LockNextTask(ctx context.Context, now time.Time, workerID st
|
|||||||
Set(repository.Field("worker_id"), workerID)
|
Set(repository.Field("worker_id"), workerID)
|
||||||
|
|
||||||
conditional := repository.IDFilter(candidate.ID).And(
|
conditional := repository.IDFilter(candidate.ID).And(
|
||||||
repository.Query().In(repository.Field("status"), string(TaskStatusPending), string(TaskStatusRetry)),
|
repository.Query().In(repository.Field("status"), string(model.TaskStatusPending), string(model.TaskStatusRetry)),
|
||||||
repository.Query().Comparison(repository.Field("next_attempt_at"), builder.Lte, now),
|
repository.Query().Comparison(repository.Field("next_attempt_at"), builder.Lte, now),
|
||||||
lockFilter,
|
lockFilter,
|
||||||
)
|
)
|
||||||
@@ -427,7 +428,7 @@ func (r *taskStore) MarkDelivered(ctx context.Context, taskID bson.ObjectID, htt
|
|||||||
}
|
}
|
||||||
|
|
||||||
patch := repository.Patch().
|
patch := repository.Patch().
|
||||||
Set(repository.Field("status"), TaskStatusDelivered).
|
Set(repository.Field("status"), model.TaskStatusDelivered).
|
||||||
Set(repository.Field("last_http_code"), httpCode).
|
Set(repository.Field("last_http_code"), httpCode).
|
||||||
Set(repository.Field("delivered_at"), time.Now()).
|
Set(repository.Field("delivered_at"), time.Now()).
|
||||||
Set(repository.Field("locked_until"), nil).
|
Set(repository.Field("locked_until"), nil).
|
||||||
@@ -446,7 +447,7 @@ func (r *taskStore) MarkRetry(ctx context.Context, taskID bson.ObjectID, attempt
|
|||||||
}
|
}
|
||||||
|
|
||||||
patch := repository.Patch().
|
patch := repository.Patch().
|
||||||
Set(repository.Field("status"), TaskStatusRetry).
|
Set(repository.Field("status"), model.TaskStatusRetry).
|
||||||
Set(repository.Field("attempt"), attempt).
|
Set(repository.Field("attempt"), attempt).
|
||||||
Set(repository.Field("next_attempt_at"), nextAttemptAt.UTC()).
|
Set(repository.Field("next_attempt_at"), nextAttemptAt.UTC()).
|
||||||
Set(repository.Field("last_error"), strings.TrimSpace(lastError)).
|
Set(repository.Field("last_error"), strings.TrimSpace(lastError)).
|
||||||
@@ -466,7 +467,7 @@ func (r *taskStore) MarkFailed(ctx context.Context, taskID bson.ObjectID, attemp
|
|||||||
}
|
}
|
||||||
|
|
||||||
patch := repository.Patch().
|
patch := repository.Patch().
|
||||||
Set(repository.Field("status"), TaskStatusFailed).
|
Set(repository.Field("status"), model.TaskStatusFailed).
|
||||||
Set(repository.Field("attempt"), attempt).
|
Set(repository.Field("attempt"), attempt).
|
||||||
Set(repository.Field("last_error"), strings.TrimSpace(lastError)).
|
Set(repository.Field("last_error"), strings.TrimSpace(lastError)).
|
||||||
Set(repository.Field("last_http_code"), httpCode).
|
Set(repository.Field("last_http_code"), httpCode).
|
||||||
@@ -479,14 +480,14 @@ func (r *taskStore) MarkFailed(ctx context.Context, taskID bson.ObjectID, attemp
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapTaskDoc(doc *taskDoc) *Task {
|
func mapTaskDoc(doc *taskDoc) *model.Task {
|
||||||
if doc == nil {
|
if doc == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return &Task{
|
return &model.Task{
|
||||||
ID: doc.ID,
|
Base: doc.Base,
|
||||||
EventID: doc.EventID,
|
EventID: doc.EventID,
|
||||||
EndpointID: doc.EndpointID,
|
EndpointRef: doc.EndpointRef,
|
||||||
EndpointURL: doc.EndpointURL,
|
EndpointURL: doc.EndpointURL,
|
||||||
SigningMode: doc.SigningMode,
|
SigningMode: doc.SigningMode,
|
||||||
SecretRef: doc.SecretRef,
|
SecretRef: doc.SecretRef,
|
||||||
|
|||||||
@@ -3,12 +3,14 @@ package subscriptions
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/tech/sendico/edge/callbacks/internal/model"
|
||||||
"github.com/tech/sendico/edge/callbacks/internal/storage"
|
"github.com/tech/sendico/edge/callbacks/internal/storage"
|
||||||
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Resolver resolves active webhook endpoints for an event.
|
// Resolver resolves active webhook endpoints for an event.
|
||||||
type Resolver interface {
|
type Resolver interface {
|
||||||
Resolve(ctx context.Context, clientID, eventType string) ([]storage.Endpoint, error)
|
Resolve(ctx context.Context, eventType string, organizationRef bson.ObjectID) ([]model.Endpoint, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dependencies defines subscriptions resolver dependencies.
|
// Dependencies defines subscriptions resolver dependencies.
|
||||||
|
|||||||
@@ -4,8 +4,10 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/tech/sendico/edge/callbacks/internal/model"
|
||||||
"github.com/tech/sendico/edge/callbacks/internal/storage"
|
"github.com/tech/sendico/edge/callbacks/internal/storage"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
)
|
)
|
||||||
|
|
||||||
type service struct {
|
type service struct {
|
||||||
@@ -21,15 +23,15 @@ func New(deps Dependencies) (Resolver, error) {
|
|||||||
return &service{repo: deps.EndpointRepo}, nil
|
return &service{repo: deps.EndpointRepo}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *service) Resolve(ctx context.Context, clientID, eventType string) ([]storage.Endpoint, error) {
|
func (s *service) Resolve(ctx context.Context, eventType string, organizationRef bson.ObjectID) ([]model.Endpoint, error) {
|
||||||
if strings.TrimSpace(clientID) == "" {
|
if organizationRef == bson.NilObjectID {
|
||||||
return nil, merrors.InvalidArgument("subscriptions: client id is required", "clientID")
|
return nil, merrors.InvalidArgument("subscriptions: client id is required", "clientID")
|
||||||
}
|
}
|
||||||
if strings.TrimSpace(eventType) == "" {
|
if strings.TrimSpace(eventType) == "" {
|
||||||
return nil, merrors.InvalidArgument("subscriptions: event type is required", "eventType")
|
return nil, merrors.InvalidArgument("subscriptions: event type is required", "eventType")
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints, err := s.repo.FindActiveByClientAndType(ctx, clientID, eventType)
|
endpoints, err := s.repo.FindActive(ctx, eventType, organizationRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260225065256-91dd007ecddc // indirect
|
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260302101851-b43f15d4ea3b // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.24.4 // indirect
|
github.com/bits-and-blooms/bitset v1.24.4 // indirect
|
||||||
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
|
|||||||
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260225065256-91dd007ecddc h1:1stW1OipdBj8Me+nj26SzT8yil7OYve0r3cWobzk1JQ=
|
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260302101851-b43f15d4ea3b h1:zoMPWbn27kscAQflTWzSHhm9fuex5SXSpyMlhCFPfxk=
|
||||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260225065256-91dd007ecddc/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
|
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260302101851-b43f15d4ea3b/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
|
||||||
github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0=
|
github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0=
|
||||||
github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU=
|
github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ require (
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260225065256-91dd007ecddc // indirect
|
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260302101851-b43f15d4ea3b // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.24.4 // indirect
|
github.com/bits-and-blooms/bitset v1.24.4 // indirect
|
||||||
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
|
|||||||
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260225065256-91dd007ecddc h1:1stW1OipdBj8Me+nj26SzT8yil7OYve0r3cWobzk1JQ=
|
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260302101851-b43f15d4ea3b h1:zoMPWbn27kscAQflTWzSHhm9fuex5SXSpyMlhCFPfxk=
|
||||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260225065256-91dd007ecddc/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
|
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260302101851-b43f15d4ea3b/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
|
||||||
github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0=
|
github.com/VictoriaMetrics/fastcache v1.13.0 h1:AW4mheMR5Vd9FkAPUv+NH6Nhw+fmbTMGMsNAoA/+4G0=
|
||||||
github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU=
|
github.com/VictoriaMetrics/fastcache v1.13.0/go.mod h1:hHXhl4DA2fTL2HTZDJFXWgW0LNjo6B+4aj2Wmng3TjU=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
|||||||
@@ -81,11 +81,10 @@ func (p *brokerPaymentStatusPublisher) Publish(_ context.Context, in paymentStat
|
|||||||
message := &model.PaymentStatusUpdated{
|
message := &model.PaymentStatusUpdated{
|
||||||
EventID: buildPaymentStatusEventID(paymentRef, payment.Version, in.CurrentState),
|
EventID: buildPaymentStatusEventID(paymentRef, payment.Version, in.CurrentState),
|
||||||
Type: model.PaymentStatusUpdatedType,
|
Type: model.PaymentStatusUpdatedType,
|
||||||
ClientID: payment.OrganizationRef.Hex(),
|
|
||||||
OccurredAt: occurredAt,
|
OccurredAt: occurredAt,
|
||||||
PublishedAt: time.Now().UTC(),
|
PublishedAt: time.Now().UTC(),
|
||||||
Data: model.PaymentStatusUpdatedData{
|
Data: model.PaymentStatusUpdatedData{
|
||||||
OrganizationRef: payment.OrganizationRef.Hex(),
|
OrganizationRef: payment.OrganizationRef,
|
||||||
PaymentRef: paymentRef,
|
PaymentRef: paymentRef,
|
||||||
QuotationRef: strings.TrimSpace(payment.QuotationRef),
|
QuotationRef: strings.TrimSpace(payment.QuotationRef),
|
||||||
ClientPaymentRef: strings.TrimSpace(payment.ClientPaymentRef),
|
ClientPaymentRef: strings.TrimSpace(payment.ClientPaymentRef),
|
||||||
|
|||||||
@@ -12,4 +12,7 @@ type DB interface {
|
|||||||
auth.ProtectedDB[*model.Callback]
|
auth.ProtectedDB[*model.Callback]
|
||||||
SetArchived(ctx context.Context, accountRef, organizationRef, callbackRef bson.ObjectID, archived, cascade bool) error
|
SetArchived(ctx context.Context, accountRef, organizationRef, callbackRef bson.ObjectID, archived, cascade bool) error
|
||||||
List(ctx context.Context, accountRef, organizationRef, _ bson.ObjectID, cursor *model.ViewCursor) ([]model.Callback, error)
|
List(ctx context.Context, accountRef, organizationRef, _ bson.ObjectID, cursor *model.ViewCursor) ([]model.Callback, error)
|
||||||
|
GetSigningSecretRef(ctx context.Context, accountRef, callbackRef bson.ObjectID) (string, error)
|
||||||
|
SetSigningSecretRef(ctx context.Context, accountRef, callbackRef bson.ObjectID, secretRef string) error
|
||||||
|
ClearSigningSecretRef(ctx context.Context, accountRef, callbackRef bson.ObjectID) error
|
||||||
}
|
}
|
||||||
|
|||||||
8
api/pkg/db/internal/mongo/callbacksdb/callback.go
Normal file
8
api/pkg/db/internal/mongo/callbacksdb/callback.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package callbacksdb
|
||||||
|
|
||||||
|
import "github.com/tech/sendico/pkg/model"
|
||||||
|
|
||||||
|
type callbackInternal struct {
|
||||||
|
model.Callback `bson:",inline" json:",inline"`
|
||||||
|
SecretRef string `bson:"secret_ref" json:"-"`
|
||||||
|
}
|
||||||
@@ -2,14 +2,12 @@ package callbacksdb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/tech/sendico/pkg/auth"
|
"github.com/tech/sendico/pkg/auth"
|
||||||
"github.com/tech/sendico/pkg/db/callbacks"
|
"github.com/tech/sendico/pkg/db/callbacks"
|
||||||
"github.com/tech/sendico/pkg/db/policy"
|
"github.com/tech/sendico/pkg/db/policy"
|
||||||
ri "github.com/tech/sendico/pkg/db/repository/index"
|
ri "github.com/tech/sendico/pkg/db/repository/index"
|
||||||
"github.com/tech/sendico/pkg/db/storable"
|
"github.com/tech/sendico/pkg/db/storable"
|
||||||
"github.com/tech/sendico/pkg/merrors"
|
|
||||||
"github.com/tech/sendico/pkg/mlogger"
|
"github.com/tech/sendico/pkg/mlogger"
|
||||||
"github.com/tech/sendico/pkg/model"
|
"github.com/tech/sendico/pkg/model"
|
||||||
"github.com/tech/sendico/pkg/mservice"
|
"github.com/tech/sendico/pkg/mservice"
|
||||||
@@ -29,10 +27,6 @@ func Create(
|
|||||||
pdb policy.DB,
|
pdb policy.DB,
|
||||||
db *mongo.Database,
|
db *mongo.Database,
|
||||||
) (*CallbacksDB, error) {
|
) (*CallbacksDB, error) {
|
||||||
if err := ensureBuiltInPolicy(ctx, logger, pdb); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
p, err := auth.CreateDBImp[*model.Callback](ctx, logger, pdb, enforcer, mservice.Callbacks, db)
|
p, err := auth.CreateDBImp[*model.Callback](ctx, logger, pdb, enforcer, mservice.Callbacks, db)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -43,7 +37,7 @@ func Create(
|
|||||||
Name: "uq_callbacks_client_url",
|
Name: "uq_callbacks_client_url",
|
||||||
Keys: []ri.Key{
|
Keys: []ri.Key{
|
||||||
{Field: storable.OrganizationRefField, Sort: ri.Asc},
|
{Field: storable.OrganizationRefField, Sort: ri.Asc},
|
||||||
{Field: "client_id", Sort: ri.Asc},
|
{Field: "organization_ref", Sort: ri.Asc},
|
||||||
{Field: "url", Sort: ri.Asc},
|
{Field: "url", Sort: ri.Asc},
|
||||||
},
|
},
|
||||||
Unique: true,
|
Unique: true,
|
||||||
@@ -82,31 +76,4 @@ func Create(
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureBuiltInPolicy(ctx context.Context, logger mlogger.Logger, pdb policy.DB) error {
|
|
||||||
var existing model.PolicyDescription
|
|
||||||
if err := pdb.GetBuiltInPolicy(ctx, mservice.Callbacks, &existing); err == nil {
|
|
||||||
return nil
|
|
||||||
} else if !errors.Is(err, merrors.ErrNoData) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
description := "Callbacks subscription management"
|
|
||||||
resourceTypes := []mservice.Type{mservice.Callbacks}
|
|
||||||
policyDescription := &model.PolicyDescription{
|
|
||||||
Describable: model.Describable{
|
|
||||||
Name: "Callbacks",
|
|
||||||
Description: &description,
|
|
||||||
},
|
|
||||||
ResourceTypes: &resourceTypes,
|
|
||||||
}
|
|
||||||
if err := pdb.Create(ctx, policyDescription); err != nil && !errors.Is(err, merrors.ErrDataConflict) {
|
|
||||||
if logger != nil {
|
|
||||||
logger.Warn("Failed to create built-in callbacks policy", zap.Error(err))
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return pdb.GetBuiltInPolicy(ctx, mservice.Callbacks, &existing)
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ callbacks.DB = (*CallbacksDB)(nil)
|
var _ callbacks.DB = (*CallbacksDB)(nil)
|
||||||
|
|||||||
60
api/pkg/db/internal/mongo/callbacksdb/secretref.go
Normal file
60
api/pkg/db/internal/mongo/callbacksdb/secretref.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package callbacksdb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/tech/sendico/pkg/db/repository"
|
||||||
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
|
"github.com/tech/sendico/pkg/model"
|
||||||
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (db *CallbacksDB) GetSigningSecretRef(ctx context.Context, accountRef, callbackRef bson.ObjectID) (string, error) {
|
||||||
|
if callbackRef.IsZero() {
|
||||||
|
return "", merrors.InvalidArgument("callback reference is required", "callbackRef")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enforce read permissions through the public callback object first.
|
||||||
|
var callback model.Callback
|
||||||
|
if err := db.Get(ctx, accountRef, callbackRef, &callback); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
internal := &callbackInternal{}
|
||||||
|
if err := db.DBImp.Repository.Get(ctx, callbackRef, internal); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimSpace(internal.SecretRef), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *CallbacksDB) SetSigningSecretRef(ctx context.Context, accountRef, callbackRef bson.ObjectID, secretRef string) error {
|
||||||
|
if callbackRef.IsZero() {
|
||||||
|
return merrors.InvalidArgument("callback reference is required", "callbackRef")
|
||||||
|
}
|
||||||
|
value := strings.TrimSpace(secretRef)
|
||||||
|
if value == "" {
|
||||||
|
return merrors.InvalidArgument("secret reference is required", "secretRef")
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.Patch(
|
||||||
|
ctx,
|
||||||
|
accountRef,
|
||||||
|
callbackRef,
|
||||||
|
repository.Patch().Set(repository.Field("secretRef"), value),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (db *CallbacksDB) ClearSigningSecretRef(ctx context.Context, accountRef, callbackRef bson.ObjectID) error {
|
||||||
|
if callbackRef.IsZero() {
|
||||||
|
return merrors.InvalidArgument("callback reference is required", "callbackRef")
|
||||||
|
}
|
||||||
|
|
||||||
|
return db.Patch(
|
||||||
|
ctx,
|
||||||
|
accountRef,
|
||||||
|
callbackRef,
|
||||||
|
repository.Patch().Unset(repository.Field("secretRef")),
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/tech/sendico/pkg/merrors"
|
"github.com/tech/sendico/pkg/merrors"
|
||||||
"github.com/tech/sendico/pkg/model"
|
"github.com/tech/sendico/pkg/model"
|
||||||
mutil "github.com/tech/sendico/pkg/mutil/db"
|
mutil "github.com/tech/sendico/pkg/mutil/db"
|
||||||
|
"github.com/tech/sendico/pkg/mutil/mzap"
|
||||||
"go.mongodb.org/mongo-driver/v2/bson"
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
@@ -54,7 +55,6 @@ func (db *verificationDB) Consume(
|
|||||||
zap.String("purpose", string(purpose)),
|
zap.String("purpose", string(purpose)),
|
||||||
zap.Bool("account_scoped", accountScoped),
|
zap.Bool("account_scoped", accountScoped),
|
||||||
zap.String("account_ref", accountRefHex),
|
zap.String("account_ref", accountRefHex),
|
||||||
zap.Any("scope_filter", scopeFilter.BuildQuery()),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// 1) Fast path for magic-link tokens: hash is deterministic and globally unique.
|
// 1) Fast path for magic-link tokens: hash is deterministic and globally unique.
|
||||||
@@ -69,7 +69,6 @@ func (db *verificationDB) Consume(
|
|||||||
zap.String("purpose", string(purpose)),
|
zap.String("purpose", string(purpose)),
|
||||||
zap.Bool("account_scoped", accountScoped),
|
zap.Bool("account_scoped", accountScoped),
|
||||||
zap.String("account_ref", accountRefHex),
|
zap.String("account_ref", accountRefHex),
|
||||||
zap.Any("magic_filter", magicFilter.BuildQuery()),
|
|
||||||
)
|
)
|
||||||
var direct model.VerificationToken
|
var direct model.VerificationToken
|
||||||
err := db.DBImp.FindOne(ctx, magicFilter, &direct)
|
err := db.DBImp.FindOne(ctx, magicFilter, &direct)
|
||||||
@@ -152,7 +151,7 @@ func (db *verificationDB) Consume(
|
|||||||
db.Logger.Debug("Verification consume OTP candidate evaluated",
|
db.Logger.Debug("Verification consume OTP candidate evaluated",
|
||||||
zap.Int("candidate_index", i),
|
zap.Int("candidate_index", i),
|
||||||
zap.Int("candidate_total", len(tokens)),
|
zap.Int("candidate_total", len(tokens)),
|
||||||
zap.String("candidate_id", t.ID.Hex()),
|
mzap.ObjRef("candidate_ref", t.ID),
|
||||||
zap.Bool("candidate_has_salt", t.Salt != nil),
|
zap.Bool("candidate_has_salt", t.Salt != nil),
|
||||||
zap.Bool("candidate_used", t.UsedAt != nil),
|
zap.Bool("candidate_used", t.UsedAt != nil),
|
||||||
zap.Time("candidate_expires_at", t.ExpiresAt),
|
zap.Time("candidate_expires_at", t.ExpiresAt),
|
||||||
@@ -181,7 +180,6 @@ func (db *verificationDB) Consume(
|
|||||||
zap.String("purpose", string(purpose)),
|
zap.String("purpose", string(purpose)),
|
||||||
zap.Bool("account_scoped", accountScoped),
|
zap.Bool("account_scoped", accountScoped),
|
||||||
zap.String("account_ref", accountRefHex),
|
zap.String("account_ref", accountRefHex),
|
||||||
zap.Any("active_filter", activeFilter.BuildQuery()),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
incremented, patchErr := db.DBImp.PatchMany(
|
incremented, patchErr := db.DBImp.PatchMany(
|
||||||
@@ -271,8 +269,7 @@ func (db *verificationDB) Consume(
|
|||||||
zap.String("purpose", string(purpose)),
|
zap.String("purpose", string(purpose)),
|
||||||
zap.Bool("account_scoped", accountScoped),
|
zap.Bool("account_scoped", accountScoped),
|
||||||
zap.String("account_ref", accountRefHex),
|
zap.String("account_ref", accountRefHex),
|
||||||
zap.String("token_id", token.ID.Hex()),
|
mzap.StorableRef(token),
|
||||||
zap.Any("consume_filter", consumeFilter.BuildQuery()),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
updated, err := db.DBImp.PatchMany(
|
updated, err := db.DBImp.PatchMany(
|
||||||
@@ -285,7 +282,7 @@ func (db *verificationDB) Consume(
|
|||||||
zap.String("purpose", string(purpose)),
|
zap.String("purpose", string(purpose)),
|
||||||
zap.Bool("account_scoped", accountScoped),
|
zap.Bool("account_scoped", accountScoped),
|
||||||
zap.String("account_ref", accountRefHex),
|
zap.String("account_ref", accountRefHex),
|
||||||
zap.String("token_id", token.ID.Hex()),
|
mzap.StorableRef(token),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -294,7 +291,7 @@ func (db *verificationDB) Consume(
|
|||||||
zap.String("purpose", string(purpose)),
|
zap.String("purpose", string(purpose)),
|
||||||
zap.Bool("account_scoped", accountScoped),
|
zap.Bool("account_scoped", accountScoped),
|
||||||
zap.String("account_ref", accountRefHex),
|
zap.String("account_ref", accountRefHex),
|
||||||
zap.String("token_id", token.ID.Hex()),
|
mzap.StorableRef(token),
|
||||||
zap.Int("updated_count", updated),
|
zap.Int("updated_count", updated),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -322,7 +319,7 @@ func (db *verificationDB) Consume(
|
|||||||
zap.String("purpose", string(purpose)),
|
zap.String("purpose", string(purpose)),
|
||||||
zap.Bool("account_scoped", accountScoped),
|
zap.Bool("account_scoped", accountScoped),
|
||||||
zap.String("account_ref", accountRefHex),
|
zap.String("account_ref", accountRefHex),
|
||||||
zap.String("token_id", token.ID.Hex()),
|
mzap.StorableRef(token),
|
||||||
zap.Error(incrementErr),
|
zap.Error(incrementErr),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@@ -330,7 +327,7 @@ func (db *verificationDB) Consume(
|
|||||||
zap.String("purpose", string(purpose)),
|
zap.String("purpose", string(purpose)),
|
||||||
zap.Bool("account_scoped", accountScoped),
|
zap.Bool("account_scoped", accountScoped),
|
||||||
zap.String("account_ref", accountRefHex),
|
zap.String("account_ref", accountRefHex),
|
||||||
zap.String("token_id", token.ID.Hex()),
|
mzap.StorableRef(token),
|
||||||
zap.Int("updated_count", incremented),
|
zap.Int("updated_count", incremented),
|
||||||
zap.String("transaction_note", "this update occurs inside transaction and may roll back depending on returned error"),
|
zap.String("transaction_note", "this update occurs inside transaction and may roll back depending on returned error"),
|
||||||
)
|
)
|
||||||
@@ -343,7 +340,7 @@ func (db *verificationDB) Consume(
|
|||||||
zap.String("purpose", string(purpose)),
|
zap.String("purpose", string(purpose)),
|
||||||
zap.Bool("account_scoped", accountScoped),
|
zap.Bool("account_scoped", accountScoped),
|
||||||
zap.String("account_ref", accountRefHex),
|
zap.String("account_ref", accountRefHex),
|
||||||
zap.String("token_id", token.ID.Hex()),
|
mzap.StorableRef(token),
|
||||||
zap.Error(err),
|
zap.Error(err),
|
||||||
)
|
)
|
||||||
return nil, merrors.Internal("failed to re-check token state")
|
return nil, merrors.Internal("failed to re-check token state")
|
||||||
@@ -353,7 +350,7 @@ func (db *verificationDB) Consume(
|
|||||||
zap.String("purpose", string(purpose)),
|
zap.String("purpose", string(purpose)),
|
||||||
zap.Bool("account_scoped", accountScoped),
|
zap.Bool("account_scoped", accountScoped),
|
||||||
zap.String("account_ref", accountRefHex),
|
zap.String("account_ref", accountRefHex),
|
||||||
zap.String("token_id", token.ID.Hex()),
|
mzap.StorableRef(token),
|
||||||
}, tokenStateFields(&fresh)...,
|
}, tokenStateFields(&fresh)...,
|
||||||
)...,
|
)...,
|
||||||
)
|
)
|
||||||
@@ -363,7 +360,7 @@ func (db *verificationDB) Consume(
|
|||||||
zap.String("purpose", string(purpose)),
|
zap.String("purpose", string(purpose)),
|
||||||
zap.Bool("account_scoped", accountScoped),
|
zap.Bool("account_scoped", accountScoped),
|
||||||
zap.String("account_ref", accountRefHex),
|
zap.String("account_ref", accountRefHex),
|
||||||
zap.String("token_id", token.ID.Hex()),
|
mzap.StorableRef(token),
|
||||||
)
|
)
|
||||||
return nil, verification.ErorrTokenAlreadyUsed()
|
return nil, verification.ErorrTokenAlreadyUsed()
|
||||||
}
|
}
|
||||||
@@ -372,7 +369,7 @@ func (db *verificationDB) Consume(
|
|||||||
zap.String("purpose", string(purpose)),
|
zap.String("purpose", string(purpose)),
|
||||||
zap.Bool("account_scoped", accountScoped),
|
zap.Bool("account_scoped", accountScoped),
|
||||||
zap.String("account_ref", accountRefHex),
|
zap.String("account_ref", accountRefHex),
|
||||||
zap.String("token_id", token.ID.Hex()),
|
mzap.StorableRef(token),
|
||||||
zap.Time("now_utc", now),
|
zap.Time("now_utc", now),
|
||||||
zap.Time("token_expires_at", fresh.ExpiresAt),
|
zap.Time("token_expires_at", fresh.ExpiresAt),
|
||||||
)
|
)
|
||||||
@@ -383,7 +380,7 @@ func (db *verificationDB) Consume(
|
|||||||
zap.String("purpose", string(purpose)),
|
zap.String("purpose", string(purpose)),
|
||||||
zap.Bool("account_scoped", accountScoped),
|
zap.Bool("account_scoped", accountScoped),
|
||||||
zap.String("account_ref", accountRefHex),
|
zap.String("account_ref", accountRefHex),
|
||||||
zap.String("token_id", token.ID.Hex()),
|
mzap.StorableRef(token),
|
||||||
zap.Int("token_attempts", fresh.Attempts),
|
zap.Int("token_attempts", fresh.Attempts),
|
||||||
zap.Int("token_max_retries", *fresh.MaxRetries),
|
zap.Int("token_max_retries", *fresh.MaxRetries),
|
||||||
)
|
)
|
||||||
@@ -394,7 +391,7 @@ func (db *verificationDB) Consume(
|
|||||||
zap.String("purpose", string(purpose)),
|
zap.String("purpose", string(purpose)),
|
||||||
zap.Bool("account_scoped", accountScoped),
|
zap.Bool("account_scoped", accountScoped),
|
||||||
zap.String("account_ref", accountRefHex),
|
zap.String("account_ref", accountRefHex),
|
||||||
zap.String("token_id", token.ID.Hex()),
|
mzap.StorableRef(token),
|
||||||
)
|
)
|
||||||
return nil, verification.ErorrTokenNotFound()
|
return nil, verification.ErorrTokenNotFound()
|
||||||
},
|
},
|
||||||
@@ -457,8 +454,8 @@ func tokenIsDigitsOnly(value string) bool {
|
|||||||
|
|
||||||
func tokenStateFields(token *model.VerificationToken) []zap.Field {
|
func tokenStateFields(token *model.VerificationToken) []zap.Field {
|
||||||
fields := []zap.Field{
|
fields := []zap.Field{
|
||||||
zap.String("token_id", token.ID.Hex()),
|
mzap.StorableRef(token),
|
||||||
zap.String("token_account_ref", token.AccountRef.Hex()),
|
mzap.ObjRef("token_account_ref", token.AccountRef),
|
||||||
zap.String("token_purpose", string(token.Purpose)),
|
zap.String("token_purpose", string(token.Purpose)),
|
||||||
zap.Bool("token_has_target", strings.TrimSpace(token.Target) != ""),
|
zap.Bool("token_has_target", strings.TrimSpace(token.Target) != ""),
|
||||||
zap.Bool("token_has_idempotency_key", token.IdempotencyKey != nil),
|
zap.Bool("token_has_idempotency_key", token.IdempotencyKey != nil),
|
||||||
|
|||||||
@@ -29,14 +29,6 @@ func syntheticIdempotencyKey() string {
|
|||||||
return "auto:" + bson.NewObjectID().Hex()
|
return "auto:" + bson.NewObjectID().Hex()
|
||||||
}
|
}
|
||||||
|
|
||||||
func verificationContextFilter(request *verification.Request) builder.Query {
|
|
||||||
return repository.Query().And(
|
|
||||||
repository.Filter("accountRef", request.AccountRef),
|
|
||||||
repository.Filter("purpose", request.Purpose),
|
|
||||||
repository.Filter("target", request.Target),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func activeContextFilter(request *verification.Request, now time.Time) builder.Query {
|
func activeContextFilter(request *verification.Request, now time.Time) builder.Query {
|
||||||
return repository.Query().And(
|
return repository.Query().And(
|
||||||
repository.Filter("accountRef", request.AccountRef),
|
repository.Filter("accountRef", request.AccountRef),
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ require (
|
|||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
|
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260225065256-91dd007ecddc // indirect
|
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260302101851-b43f15d4ea3b // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.24.4 // indirect
|
github.com/bits-and-blooms/bitset v1.24.4 // indirect
|
||||||
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
|
github.com/bmatcuk/doublestar/v4 v4.10.0 // indirect
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25
|
|||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260225065256-91dd007ecddc h1:1stW1OipdBj8Me+nj26SzT8yil7OYve0r3cWobzk1JQ=
|
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260302101851-b43f15d4ea3b h1:zoMPWbn27kscAQflTWzSHhm9fuex5SXSpyMlhCFPfxk=
|
||||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260225065256-91dd007ecddc/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
|
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260302101851-b43f15d4ea3b/go.mod h1:ioLG6R+5bUSO1oeGSDxOV3FADARuMoytZCSX6MEMQkI=
|
||||||
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
|
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
|
||||||
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
|
github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
|||||||
@@ -16,11 +16,14 @@ const (
|
|||||||
CallbackSigningModeHMACSHA256 CallbackSigningMode = "hmac_sha256"
|
CallbackSigningModeHMACSHA256 CallbackSigningMode = "hmac_sha256"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type CallbackBackoff struct {
|
||||||
|
MinDelayMS int `bson:"min_ms" json:"minDelayMs"`
|
||||||
|
MaxDelayMS int `bson:"max_ms" json:"maxDelayMs"`
|
||||||
|
}
|
||||||
|
|
||||||
type CallbackRetryPolicy struct {
|
type CallbackRetryPolicy struct {
|
||||||
MinDelayMS int `bson:"min_ms" json:"minDelayMs"`
|
Backoff CallbackBackoff `bson:"backoff" json:"backoff"`
|
||||||
MaxDelayMS int `bson:"max_ms" json:"maxDelayMs"`
|
|
||||||
SigningMode CallbackSigningMode `bson:"signing_mode" json:"signingMode"`
|
SigningMode CallbackSigningMode `bson:"signing_mode" json:"signingMode"`
|
||||||
SecretRef string `bson:"secret_ref,omitempty" json:"secretRef,omitempty"`
|
|
||||||
Headers map[string]string `bson:"headers,omitempty" json:"headers,omitempty"`
|
Headers map[string]string `bson:"headers,omitempty" json:"headers,omitempty"`
|
||||||
MaxAttempts int `bson:"max_attempts" json:"maxAttempts"`
|
MaxAttempts int `bson:"max_attempts" json:"maxAttempts"`
|
||||||
RequestTimeoutMS int `bson:"request_timeout_ms" json:"requestTimeoutMs"`
|
RequestTimeoutMS int `bson:"request_timeout_ms" json:"requestTimeoutMs"`
|
||||||
@@ -29,7 +32,6 @@ type CallbackRetryPolicy struct {
|
|||||||
type Callback struct {
|
type Callback struct {
|
||||||
PermissionBound `bson:",inline" json:",inline"`
|
PermissionBound `bson:",inline" json:",inline"`
|
||||||
Describable `bson:",inline" json:",inline"`
|
Describable `bson:",inline" json:",inline"`
|
||||||
ClientID string `bson:"client_id" json:"clientId"`
|
|
||||||
Status CallbackStatus `bson:"status" json:"status"`
|
Status CallbackStatus `bson:"status" json:"status"`
|
||||||
URL string `bson:"url" json:"url"`
|
URL string `bson:"url" json:"url"`
|
||||||
EventTypes []string `bson:"event_types" json:"eventTypes"`
|
EventTypes []string `bson:"event_types" json:"eventTypes"`
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
package model
|
package model
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
PaymentStatusUpdatedType = "payment.status.updated"
|
PaymentStatusUpdatedType = "payment.status.updated"
|
||||||
@@ -9,21 +13,20 @@ const (
|
|||||||
type PaymentStatusUpdated struct {
|
type PaymentStatusUpdated struct {
|
||||||
EventID string `json:"event_id,omitempty"`
|
EventID string `json:"event_id,omitempty"`
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
ClientID string `json:"client_id,omitempty"`
|
|
||||||
OccurredAt time.Time `json:"occurred_at,omitempty"`
|
OccurredAt time.Time `json:"occurred_at,omitempty"`
|
||||||
PublishedAt time.Time `json:"published_at,omitempty"`
|
PublishedAt time.Time `json:"published_at,omitempty"`
|
||||||
Data PaymentStatusUpdatedData `json:"data"`
|
Data PaymentStatusUpdatedData `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PaymentStatusUpdatedData struct {
|
type PaymentStatusUpdatedData struct {
|
||||||
OrganizationRef string `json:"organization_ref,omitempty"`
|
OrganizationRef bson.ObjectID `json:"organization_ref,omitempty"`
|
||||||
PaymentRef string `json:"payment_ref,omitempty"`
|
PaymentRef string `json:"payment_ref,omitempty"`
|
||||||
QuotationRef string `json:"quotation_ref,omitempty"`
|
QuotationRef string `json:"quotation_ref,omitempty"`
|
||||||
ClientPaymentRef string `json:"client_payment_ref,omitempty"`
|
ClientPaymentRef string `json:"client_payment_ref,omitempty"`
|
||||||
IdempotencyKey string `json:"idempotency_key,omitempty"`
|
IdempotencyKey string `json:"idempotency_key,omitempty"`
|
||||||
State string `json:"state,omitempty"`
|
State string `json:"state,omitempty"`
|
||||||
PreviousState string `json:"previous_state,omitempty"`
|
PreviousState string `json:"previous_state,omitempty"`
|
||||||
Version uint64 `json:"version,omitempty"`
|
Version uint64 `json:"version,omitempty"`
|
||||||
IsTerminal bool `json:"is_terminal"`
|
IsTerminal bool `json:"is_terminal"`
|
||||||
Event string `json:"event,omitempty"`
|
Event string `json:"event,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ package model
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/tech/sendico/pkg/db/storable"
|
||||||
"github.com/tech/sendico/pkg/mservice"
|
"github.com/tech/sendico/pkg/mservice"
|
||||||
|
"go.mongodb.org/mongo-driver/v2/bson"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ClientRefreshToken struct {
|
type ClientRefreshToken struct {
|
||||||
@@ -12,13 +14,14 @@ type ClientRefreshToken struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type RefreshToken struct {
|
type RefreshToken struct {
|
||||||
AccountBoundBase `bson:",inline" json:",inline"`
|
storable.Base `bson:",inline" json:",inline"`
|
||||||
ClientRefreshToken `bson:",inline" json:",inline"`
|
ClientRefreshToken `bson:",inline" json:",inline"`
|
||||||
ExpiresAt time.Time `bson:"expiresAt"`
|
AccountRef *bson.ObjectID `bson:"accountRef,omitempty" json:"accountRef,omitempty"`
|
||||||
IsRevoked bool `bson:"isRevoked"`
|
ExpiresAt time.Time `bson:"expiresAt"`
|
||||||
LastUsedAt time.Time `bson:"lastUsedAt,omitempty"`
|
IsRevoked bool `bson:"isRevoked"`
|
||||||
UserAgent string `bson:"userAgent"`
|
LastUsedAt time.Time `bson:"lastUsedAt,omitempty"`
|
||||||
IPAddress string `bson:"ipAddress"`
|
UserAgent string `bson:"userAgent"`
|
||||||
|
IPAddress string `bson:"ipAddress"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*RefreshToken) Collection() string {
|
func (*RefreshToken) Collection() string {
|
||||||
|
|||||||
@@ -1,388 +0,0 @@
|
|||||||
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
|
|
||||||
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
|
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU=
|
|
||||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
|
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
|
||||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
|
||||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
|
||||||
github.com/aws/aws-sdk-go-v2 v1.41.2 h1:LuT2rzqNQsauaGkPK/7813XxcZ3o3yePY0Iy891T2ls=
|
|
||||||
github.com/aws/aws-sdk-go-v2 v1.41.2/go.mod h1:IvvlAZQXvTXznUPfRVfryiG1fbzE2NGK6m9u39YQ+S4=
|
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.5 h1:zWFmPmgw4sveAYi1mRqG+E/g0461cJ5M4bJ8/nc6d3Q=
|
|
||||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.5/go.mod h1:nVUlMLVV8ycXSb7mSkcNu9e3v/1TJq2RTlrPwhYWr5c=
|
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.32.10 h1:9DMthfO6XWZYLfzZglAgW5Fyou2nRI5CuV44sTedKBI=
|
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.32.10/go.mod h1:2rUIOnA2JaiqYmSKYmRJlcMWy6qTj1vuRFscppSBMcw=
|
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.10 h1:EEhmEUFCE1Yhl7vDhNOI5OCL/iKMdkkYFTRpZXNw7m8=
|
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.19.10/go.mod h1:RnnlFCAlxQCkN2Q379B67USkBMu1PipEEiibzYN5UTE=
|
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.18 h1:Ii4s+Sq3yDfaMLpjrJsqD6SmG/Wq/P5L/hw2qa78UAY=
|
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.18/go.mod h1:6x81qnY++ovptLE6nWQeWrpXxbnlIex+4H4eYYGcqfc=
|
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.18 h1:F43zk1vemYIqPAwhjTjYIz0irU2EY7sOb/F5eJ3HuyM=
|
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.18/go.mod h1:w1jdlZXrGKaJcNoL+Nnrj+k5wlpGXqnNrKoP22HvAug=
|
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18 h1:xCeWVjj0ki0l3nruoyP2slHsGArMxeiiaoPN5QZH6YQ=
|
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18/go.mod h1:r/eLGuGCBw6l36ZRWiw6PaZwPXb6YOj+i/7MizNl5/k=
|
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk=
|
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc=
|
|
||||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.18 h1:eZioDaZGJ0tMM4gzmkNIO2aAoQd+je7Ug7TkvAzlmkU=
|
|
||||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.18/go.mod h1:CCXwUKAJdoWr6/NcxZ+zsiPr6oH/Q5aTooRGYieAyj4=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5 h1:CeY9LUdur+Dxoeldqoun6y4WtJ3RQtzk0JMP2gfUay0=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5/go.mod h1:AZLZf2fMaahW5s/wMRciu1sYbdsikT/UHwbUjOdEVTc=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.10 h1:fJvQ5mIBVfKtiyx0AHY6HeWcRX5LGANLpq8SVR+Uazs=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.10/go.mod h1:Kzm5e6OmNH8VMkgK9t+ry5jEih4Y8whqs+1hrkxim1I=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18 h1:LTRCYFlnnKFlKsyIQxKhJuDuA3ZkrDQMRYm6rXiHlLY=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18/go.mod h1:XhwkgGG6bHSd00nO/mexWTcTjgd6PjuvWQMqSn2UaEk=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.18 h1:/A/xDuZAVD2BpsS2fftFRo/NoEKQJ8YTnJDEHBy2Gtg=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.18/go.mod h1:hWe9b4f+djUQGmyiGEeOnZv69dtMSgpDRIvNMvuvzvY=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.2 h1:M1A9AjcFwlxTLuf0Faj88L8Iqw0n/AJHjpZTQzMMsSc=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.2/go.mod h1:KsdTV6Q9WKUZm2mNJnUFmIoXfZux91M3sr/a4REX8e0=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/signin v1.0.6 h1:MzORe+J94I+hYu2a6XmV5yC9huoTv8NRcCrUNedDypQ=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/signin v1.0.6/go.mod h1:hXzcHLARD7GeWnifd8j9RWqtfIgxj4/cAtIVIK7hg8g=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.30.11 h1:7oGD8KPfBOJGXiCoRKrrrQkbvCp8N++u36hrLMPey6o=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.30.11/go.mod h1:0DO9B5EUJQlIDif+XJRWCljZRKsAFKh3gpFz7UnDtOo=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.15 h1:edCcNp9eGIUDUCrzoCu1jWAXLGFIizeqkdkKgRlJwWc=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.15/go.mod h1:lyRQKED9xWfgkYC/wmmYfv7iVIM68Z5OQ88ZdcV1QbU=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.41.7 h1:NITQpgo9A5NrDZ57uOWj+abvXSb83BbyggcUBVksN7c=
|
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.41.7/go.mod h1:sks5UWBhEuWYDPdwlnRFn1w7xWdH29Jcpe+/PJQefEs=
|
|
||||||
github.com/aws/smithy-go v1.24.1 h1:VbyeNfmYkWoxMVpGUAbQumkODcYmfMRfZ8yQiH30SK0=
|
|
||||||
github.com/aws/smithy-go v1.24.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
|
|
||||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
|
||||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
|
||||||
github.com/bmatcuk/doublestar/v4 v4.10.0 h1:zU9WiOla1YA122oLM6i4EXvGW62DvKZVxIe6TYWexEs=
|
|
||||||
github.com/bmatcuk/doublestar/v4 v4.10.0/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
|
||||||
github.com/casbin/casbin/v2 v2.135.0 h1:6BLkMQiGotYyS5yYeWgW19vxqugUlvHFkFiLnLR/bxk=
|
|
||||||
github.com/casbin/casbin/v2 v2.135.0/go.mod h1:FmcfntdXLTcYXv/hxgNntcRPqAbwOG9xsism0yXT+18=
|
|
||||||
github.com/casbin/govaluate v1.3.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
|
||||||
github.com/casbin/govaluate v1.10.0 h1:ffGw51/hYH3w3rZcxO/KcaUIDOLP84w7nsidMVgaDG0=
|
|
||||||
github.com/casbin/govaluate v1.10.0/go.mod h1:G/UnbIjZk/0uMNaLwZZmFQrR72tYRZWQkO70si/iR7A=
|
|
||||||
github.com/casbin/mongodb-adapter/v4 v4.3.0 h1:yYXky9v1by6vj/0QK7OyHyd/xpz4vzh0lCi7JKrS4qQ=
|
|
||||||
github.com/casbin/mongodb-adapter/v4 v4.3.0/go.mod h1:bOTSYZUjX7I9E0ExEvgq46m3mcDNRII7g8iWjrM1BHE=
|
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
|
||||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
|
||||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
|
||||||
github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A=
|
|
||||||
github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw=
|
|
||||||
github.com/cpuguy83/dockercfg v0.3.2 h1:DlJTyZGBDlXqUZ2Dk2Q3xHs/FtnooJJVaad2S9GKorA=
|
|
||||||
github.com/cpuguy83/dockercfg v0.3.2/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc=
|
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
|
||||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
|
||||||
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
|
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 h1:5RVFMOWjMyRy8cARdy79nAmgYw3hK/4HUq48LQ6Wwqo=
|
|
||||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
|
|
||||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
|
||||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
|
||||||
github.com/docker/docker v27.3.1+incompatible h1:KttF0XoteNTicmUtBO0L2tP+J7FGRFTjaEF4k6WdhfI=
|
|
||||||
github.com/docker/docker v27.3.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
|
||||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
|
||||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
|
||||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
|
||||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
|
||||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
|
||||||
github.com/go-chi/chi v1.5.4/go.mod h1:uaf8YgoFazUOkPBG7fxPftUylNumIev9awIWOENIuEg=
|
|
||||||
github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE=
|
|
||||||
github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw=
|
|
||||||
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
|
||||||
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
|
||||||
github.com/go-chi/cors v1.2.2 h1:Jmey33TE+b+rB7fT8MUy1u0I4L+NARQlK6LhzKPSyQE=
|
|
||||||
github.com/go-chi/cors v1.2.2/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
|
||||||
github.com/go-chi/jwtauth/v5 v5.4.0 h1:Ieh0xMJsFvqylqJ02/mQHKzbbKO9DYNBh4DPKCwTwYI=
|
|
||||||
github.com/go-chi/jwtauth/v5 v5.4.0/go.mod h1:w6yjqUUXz1b8+oiJel64Sz1KJwduQM6qUA5QNzO5+bQ=
|
|
||||||
github.com/go-chi/metrics v0.1.1 h1:CXhbnkAVVjb0k73EBRQ6Z2YdWFnbXZgNtg1Mboguibk=
|
|
||||||
github.com/go-chi/metrics v0.1.1/go.mod h1:mcGTM1pPalP7WCtb+akNYFO/lwNwBBLCuedepqjoPn4=
|
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
|
||||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
|
||||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
|
||||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
|
||||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
|
||||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
|
||||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
|
||||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
|
||||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
|
||||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
|
||||||
github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
|
|
||||||
github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
|
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
|
||||||
github.com/klauspost/compress v1.18.4 h1:RPhnKRAQ4Fh8zU2FY/6ZFDwTVTxgJ/EMydqSTzE9a2c=
|
|
||||||
github.com/klauspost/compress v1.18.4/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
|
||||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
|
||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
|
||||||
github.com/lestrrat-go/blackmagic v1.0.4 h1:IwQibdnf8l2KoO+qC3uT4OaTWsW7tuRQXy9TRN9QanA=
|
|
||||||
github.com/lestrrat-go/blackmagic v1.0.4/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw=
|
|
||||||
github.com/lestrrat-go/dsig v1.0.0 h1:OE09s2r9Z81kxzJYRn07TFM9XA4akrUdoMwr0L8xj38=
|
|
||||||
github.com/lestrrat-go/dsig v1.0.0/go.mod h1:dEgoOYYEJvW6XGbLasr8TFcAxoWrKlbQvmJgCR0qkDo=
|
|
||||||
github.com/lestrrat-go/dsig-secp256k1 v1.0.0 h1:JpDe4Aybfl0soBvoVwjqDbp+9S1Y2OM7gcrVVMFPOzY=
|
|
||||||
github.com/lestrrat-go/dsig-secp256k1 v1.0.0/go.mod h1:CxUgAhssb8FToqbL8NjSPoGQlnO4w3LG1P0qPWQm/NU=
|
|
||||||
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
|
|
||||||
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
|
|
||||||
github.com/lestrrat-go/httprc/v3 v3.0.4 h1:pXyH2ppK8GYYggygxJ3TvxpCZnbEUWc9qSwRTTApaLA=
|
|
||||||
github.com/lestrrat-go/httprc/v3 v3.0.4/go.mod h1:mSMtkZW92Z98M5YoNNztbRGxbXHql7tSitCvaxvo9l0=
|
|
||||||
github.com/lestrrat-go/jwx/v3 v3.0.13 h1:AdHKiPIYeCSnOJtvdpipPg/0SuFh9rdkN+HF3O0VdSk=
|
|
||||||
github.com/lestrrat-go/jwx/v3 v3.0.13/go.mod h1:2m0PV1A9tM4b/jVLMx8rh6rBl7F6WGb3EG2hufN9OQU=
|
|
||||||
github.com/lestrrat-go/option/v2 v2.0.0 h1:XxrcaJESE1fokHy3FpaQ/cXW8ZsIdWcdFzzLOcID3Ss=
|
|
||||||
github.com/lestrrat-go/option/v2 v2.0.0/go.mod h1:oSySsmzMoR0iRzCDCaUfsCzxQHUEuhOViQObyy7S6Vg=
|
|
||||||
github.com/lufia/plan9stats v0.0.0-20250827001030-24949be3fa54 h1:mFWunSatvkQQDhpdyuFAYwyAan3hzCuma+Pz8sqvOfg=
|
|
||||||
github.com/lufia/plan9stats v0.0.0-20250827001030-24949be3fa54/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
|
|
||||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
|
||||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
|
||||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
|
||||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
|
||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
|
||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
|
||||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
|
||||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
|
||||||
github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk=
|
|
||||||
github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc=
|
|
||||||
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
|
||||||
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
|
|
||||||
github.com/moby/sys/user v0.3.0 h1:9ni5DlcW5an3SvRSx4MouotOygvzaXbaSrc/wGDFWPo=
|
|
||||||
github.com/moby/sys/user v0.3.0/go.mod h1:bG+tYYYJgaMtRKgEmuueC0hJEAZWwtIbZTB+85uoHjs=
|
|
||||||
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
|
||||||
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
|
||||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
|
||||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0=
|
|
||||||
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
|
|
||||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
|
||||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
|
||||||
github.com/nats-io/nats.go v1.49.0 h1:yh/WvY59gXqYpgl33ZI+XoVPKyut/IcEaqtsiuTJpoE=
|
|
||||||
github.com/nats-io/nats.go v1.49.0/go.mod h1:fDCn3mN5cY8HooHwE2ukiLb4p4G4ImmzvXyJt+tGwdw=
|
|
||||||
github.com/nats-io/nkeys v0.4.15 h1:JACV5jRVO9V856KOapQ7x+EY8Jo3qw1vJt/9Jpwzkk4=
|
|
||||||
github.com/nats-io/nkeys v0.4.15/go.mod h1:CpMchTXC9fxA5zrMo4KpySxNjiDVvr8ANOSZdiNfUrs=
|
|
||||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
|
|
||||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
|
||||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
|
||||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
|
||||||
github.com/pkg/diff v0.0.0-20200914180035-5b29258ca4f7/go.mod h1:zO8QMzTeZd5cpnIkz/Gn6iK0jDfGicM1nynOkkPIl28=
|
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
|
||||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
|
||||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
|
||||||
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
|
||||||
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
|
||||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
|
||||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
|
||||||
github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4=
|
|
||||||
github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw=
|
|
||||||
github.com/prometheus/procfs v0.20.0 h1:AA7aCvjxwAquZAlonN7888f2u4IN8WVeFgBi4k82M4Q=
|
|
||||||
github.com/prometheus/procfs v0.20.0/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo=
|
|
||||||
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
|
||||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
|
||||||
github.com/segmentio/asm v1.2.1 h1:DTNbBqs57ioxAD4PrArqftgypG4/qNpXoJx8TVXxPR0=
|
|
||||||
github.com/segmentio/asm v1.2.1/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
|
||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
|
||||||
github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI=
|
|
||||||
github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk=
|
|
||||||
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
|
|
||||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
|
||||||
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
|
||||||
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
|
||||||
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
|
|
||||||
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
|
||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
|
||||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
|
||||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
|
||||||
github.com/tailscale/depaware v0.0.0-20210622194025-720c4b409502/go.mod h1:p9lPsd+cx33L3H9nNoecRRxPssFKUwwI50I3pZ0yT+8=
|
|
||||||
github.com/testcontainers/testcontainers-go v0.33.0 h1:zJS9PfXYT5O0ZFXM2xxXfk4J5UMw/kRiISng037Gxdw=
|
|
||||||
github.com/testcontainers/testcontainers-go v0.33.0/go.mod h1:W80YpTa8D5C3Yy16icheD01UTDu+LmXIA2Keo+jWtT8=
|
|
||||||
github.com/testcontainers/testcontainers-go/modules/mongodb v0.33.0 h1:iXVA84s5hKMS5gn01GWOYHE3ymy/2b+0YkpFeTxB2XY=
|
|
||||||
github.com/testcontainers/testcontainers-go/modules/mongodb v0.33.0/go.mod h1:R6tMjTojRiaoo89fh/hf7tOmfzohdqSU17R9DwSVSog=
|
|
||||||
github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA=
|
|
||||||
github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI=
|
|
||||||
github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw=
|
|
||||||
github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ=
|
|
||||||
github.com/valyala/fastjson v1.6.10 h1:/yjJg8jaVQdYR3arGxPE2X5z89xrlhS0eGXdv+ADTh4=
|
|
||||||
github.com/valyala/fastjson v1.6.10/go.mod h1:e6FubmQouUNP73jtMLmcbxS6ydWIpOfhz34TSfO3JaE=
|
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
|
|
||||||
github.com/xdg-go/scram v1.2.0 h1:bYKF2AEwG5rqd1BumT4gAnvwU/M9nBp2pTSxeZw7Wvs=
|
|
||||||
github.com/xdg-go/scram v1.2.0/go.mod h1:3dlrS0iBaWKYVt2ZfA4cj48umJZ+cAEbR6/SjLA88I8=
|
|
||||||
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
|
|
||||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
|
||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
|
|
||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
|
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
|
||||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
|
||||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
|
||||||
go.mongodb.org/mongo-driver v1.17.8 h1:BDP3+U3Y8K0vTrpqDJIRaXNhb/bKyoVeg6tIJsW5EhM=
|
|
||||||
go.mongodb.org/mongo-driver v1.17.8/go.mod h1:LlOhpH5NUEfhxcAwG0UEkMqwYcc4JU18gtCdGudk/tQ=
|
|
||||||
go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE=
|
|
||||||
go.mongodb.org/mongo-driver/v2 v2.5.0/go.mod h1:yOI9kBsufol30iFsl1slpdq1I0eHPzybRWdyYUs8K/0=
|
|
||||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
|
||||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s=
|
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM=
|
|
||||||
go.opentelemetry.io/otel v1.40.0 h1:oA5YeOcpRTXq6NN7frwmwFR0Cn3RhTVZvXsP4duvCms=
|
|
||||||
go.opentelemetry.io/otel v1.40.0/go.mod h1:IMb+uXZUKkMXdPddhwAHm6UfOwJyh4ct1ybIlV14J0g=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0 h1:QKdN8ly8zEMrByybbQgv8cWBcdAarwmIPZ6FThrWXJs=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.40.0/go.mod h1:bTdK1nhqF76qiPoCCdyFIV+N/sRHYXYCTQc+3VCi3MI=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
|
|
||||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
|
|
||||||
go.opentelemetry.io/otel/metric v1.40.0 h1:rcZe317KPftE2rstWIBitCdVp89A2HqjkxR3c11+p9g=
|
|
||||||
go.opentelemetry.io/otel/metric v1.40.0/go.mod h1:ib/crwQH7N3r5kfiBZQbwrTge743UDc7DTFVZrrXnqc=
|
|
||||||
go.opentelemetry.io/otel/sdk v1.40.0 h1:KHW/jUzgo6wsPh9At46+h4upjtccTmuZCFAc9OJ71f8=
|
|
||||||
go.opentelemetry.io/otel/sdk v1.40.0/go.mod h1:Ph7EFdYvxq72Y8Li9q8KebuYUr2KoeyHx0DRMKrYBUE=
|
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.40.0 h1:mtmdVqgQkeRxHgRv4qhyJduP3fYJRMX4AtAlbuWdCYw=
|
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.40.0/go.mod h1:4Z2bGMf0KSK3uRjlczMOeMhKU2rhUqdWNoKcYrtcBPg=
|
|
||||||
go.opentelemetry.io/otel/trace v1.40.0 h1:WA4etStDttCSYuhwvEa8OP8I5EWu24lkOzp+ZYblVjw=
|
|
||||||
go.opentelemetry.io/otel/trace v1.40.0/go.mod h1:zeAhriXecNGP/s2SEG3+Y8X9ujcJOTqQ5RgdEJcawiA=
|
|
||||||
go.opentelemetry.io/proto/otlp v1.9.0 h1:l706jCMITVouPOqEnii2fIAuO3IVGBRPV5ICjceRb/A=
|
|
||||||
go.opentelemetry.io/proto/otlp v1.9.0/go.mod h1:xE+Cx5E/eEHw+ISFkwPLwCZefwVjY+pqKg1qcK03+/4=
|
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
|
||||||
go.uber.org/atomic v1.8.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
|
||||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
|
||||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
|
||||||
go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
|
|
||||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
|
||||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
|
||||||
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
|
|
||||||
go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc=
|
|
||||||
go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
|
||||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
|
||||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
|
||||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
|
||||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
|
||||||
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
|
||||||
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
|
||||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
|
||||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
|
||||||
golang.org/x/term v0.40.0 h1:36e4zGLqU4yhjlmxEaagx2KuYbJq3EwY8K943ZsHcvg=
|
|
||||||
golang.org/x/term v0.40.0/go.mod h1:w2P8uVp06p2iyKKuvXIm7N/y0UCRt3UfJTfZ7oOpglM=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|
||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
|
||||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
|
||||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
|
||||||
golang.org/x/time v0.14.0 h1:MRx4UaLrDotUKUdCIqzPC48t1Y9hANFKIRpNx+Te8PI=
|
|
||||||
golang.org/x/time v0.14.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4=
|
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
|
||||||
golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
|
||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
|
|
||||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171 h1:tu/dtnW1o3wfaxCOjSLn5IRX4YDcJrtlpzYkhHhGaC4=
|
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20260226221140-a57be14db171/go.mod h1:M5krXqk4GhBKvB596udGL3UyjL4I1+cTbK0orROM9ng=
|
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171 h1:ggcbiqK8WWh6l1dnltU4BgWGIGo+EVYxCaAPih/zQXQ=
|
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260226221140-a57be14db171/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
|
||||||
google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY=
|
|
||||||
google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
|
|
||||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
|
||||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU=
|
|
||||||
gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
|
||||||
moul.io/chizap v1.0.3 h1:mliXvvuS5HVo3QP8qPXczWtRM5dQ9UmK3bBVIkZo6ek=
|
|
||||||
moul.io/chizap v1.0.3/go.mod h1:pq4R9kGLwz4XjBc4hodQYuoE7Yc9RUabLBFyyi2uErk=
|
|
||||||
@@ -26,8 +26,8 @@ WORKDIR /src
|
|||||||
COPY --from=builder /src/api/proto ./api/proto
|
COPY --from=builder /src/api/proto ./api/proto
|
||||||
COPY --from=builder /src/api/pkg ./api/pkg
|
COPY --from=builder /src/api/pkg ./api/pkg
|
||||||
|
|
||||||
# Copy vault-aware entrypoint wrapper
|
# Copy dev-specific entrypoint script
|
||||||
COPY api/edge/callbacks/entrypoint.sh /app/entrypoint.sh
|
COPY ci/dev/entrypoints/callbacks.sh /app/entrypoint.sh
|
||||||
RUN chmod +x /app/entrypoint.sh
|
RUN chmod +x /app/entrypoint.sh
|
||||||
|
|
||||||
# Source code will be mounted at runtime
|
# Source code will be mounted at runtime
|
||||||
|
|||||||
17
ci/dev/entrypoints/callbacks.sh
Normal file
17
ci/dev/entrypoints/callbacks.sh
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# Load Vault token from file if VAULT_TOKEN_FILE is set
|
||||||
|
if [ -n "${VAULT_TOKEN_FILE:-}" ] && [ -f "${VAULT_TOKEN_FILE}" ]; then
|
||||||
|
token="$(cat "${VAULT_TOKEN_FILE}" 2>/dev/null | tr -d '[:space:]')"
|
||||||
|
if [ -n "${token}" ]; then
|
||||||
|
export VAULT_TOKEN="${token}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "${VAULT_TOKEN:-}" ]; then
|
||||||
|
echo "[entrypoint] VAULT_TOKEN is not set; expected Vault Agent sink to write a token to ${VAULT_TOKEN_FILE:-/run/vault/token}" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Execute the command passed as arguments (e.g., air)
|
||||||
|
exec "$@"
|
||||||
@@ -89,8 +89,6 @@ paths:
|
|||||||
$ref: ./api/payments/quote.yaml
|
$ref: ./api/payments/quote.yaml
|
||||||
/payments/multiquote/{organizations_ref}:
|
/payments/multiquote/{organizations_ref}:
|
||||||
$ref: ./api/payments/multiquote.yaml
|
$ref: ./api/payments/multiquote.yaml
|
||||||
/payments/immediate/{organizations_ref}:
|
|
||||||
$ref: ./api/payments/immediate.yaml
|
|
||||||
/payments/by-quote/{organizations_ref}:
|
/payments/by-quote/{organizations_ref}:
|
||||||
$ref: ./api/payments/by_quote.yaml
|
$ref: ./api/payments/by_quote.yaml
|
||||||
/payments/by-multiquote/{organizations_ref}:
|
/payments/by-multiquote/{organizations_ref}:
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
components:
|
components:
|
||||||
requestBodies:
|
requestBodies:
|
||||||
LoginBody:
|
LoginBody:
|
||||||
|
description: JSON credentials payload for standard login.
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: ../request/auth.yaml#/components/schemas/LoginRequest
|
$ref: ../request/auth.yaml#/components/schemas/LoginRequest
|
||||||
ApiLoginBody:
|
ApiLoginBody:
|
||||||
|
description: JSON credentials payload for API client login.
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
@@ -14,6 +16,7 @@ components:
|
|||||||
$ref: ../request/auth.yaml#/components/schemas/ApiLoginRequest
|
$ref: ../request/auth.yaml#/components/schemas/ApiLoginRequest
|
||||||
|
|
||||||
RefreshTokenBody:
|
RefreshTokenBody:
|
||||||
|
description: JSON payload containing session and refresh token data.
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ components:
|
|||||||
description: Client identifier bound to refresh token lifecycle and client policy checks.
|
description: Client identifier bound to refresh token lifecycle and client policy checks.
|
||||||
deviceId:
|
deviceId:
|
||||||
type: string
|
type: string
|
||||||
|
description: Device/server identifier associated with the client session.
|
||||||
login:
|
login:
|
||||||
$ref: ../../../models/auth/login_data.yaml#/components/schemas/LoginData
|
$ref: ../../../models/auth/login_data.yaml#/components/schemas/LoginData
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
AccountAuthData:
|
AccountAuthData:
|
||||||
|
description: Authentication response containing account profile and access token.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -8,11 +9,14 @@ components:
|
|||||||
- account
|
- account
|
||||||
properties:
|
properties:
|
||||||
accessToken:
|
accessToken:
|
||||||
|
description: Access token used for authenticated requests.
|
||||||
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
||||||
account:
|
account:
|
||||||
|
description: Authenticated account data.
|
||||||
$ref: ../../../models/account/account.yaml#/components/schemas/AccountData
|
$ref: ../../../models/account/account.yaml#/components/schemas/AccountData
|
||||||
|
|
||||||
LoginData:
|
LoginData:
|
||||||
|
description: Full login response including access and refresh tokens.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -21,13 +25,17 @@ components:
|
|||||||
- refreshToken
|
- refreshToken
|
||||||
properties:
|
properties:
|
||||||
accessToken:
|
accessToken:
|
||||||
|
description: Access token used for authenticated requests.
|
||||||
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
||||||
account:
|
account:
|
||||||
|
description: Authenticated account data.
|
||||||
$ref: ../../../models/account/account.yaml#/components/schemas/AccountData
|
$ref: ../../../models/account/account.yaml#/components/schemas/AccountData
|
||||||
refreshToken:
|
refreshToken:
|
||||||
|
description: Refresh token used to obtain a new access token.
|
||||||
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
||||||
|
|
||||||
PendingLoginData:
|
PendingLoginData:
|
||||||
|
description: Pending login response requiring additional verification.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -36,14 +44,19 @@ components:
|
|||||||
- target
|
- target
|
||||||
properties:
|
properties:
|
||||||
account:
|
account:
|
||||||
|
description: Interim authentication payload prepared for verification completion.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
accessToken:
|
accessToken:
|
||||||
|
description: Temporary access token issued before verification is completed.
|
||||||
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
||||||
account:
|
account:
|
||||||
|
description: Account data associated with the pending login flow.
|
||||||
$ref: ../../../models/account/account.yaml#/components/schemas/AccountData
|
$ref: ../../../models/account/account.yaml#/components/schemas/AccountData
|
||||||
pendingToken:
|
pendingToken:
|
||||||
|
description: Token proving the pending verification session.
|
||||||
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
||||||
target:
|
target:
|
||||||
|
description: Verification target destination (for example email or phone).
|
||||||
type: string
|
type: string
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
components:
|
components:
|
||||||
requestBodies:
|
requestBodies:
|
||||||
CallbackBody:
|
CallbackBody:
|
||||||
|
description: JSON body containing callback endpoint configuration.
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: ../request/callback.yaml#/components/schemas/CallbackRequest
|
$ref: ../request/callback.yaml#/components/schemas/CallbackRequest
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
CallbackRequest:
|
CallbackRequest:
|
||||||
$ref: ../../../models/callback/callback.yaml#/components/schemas/Callback
|
description: Request payload used to create or update a callback configuration.
|
||||||
|
$ref: ../../../models/callback/callback.yaml#/components/schemas/CallbackContent
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
CallbacksAuthData:
|
CallbacksAuthData:
|
||||||
|
description: Authenticated response payload containing callback configurations.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -8,12 +9,14 @@ components:
|
|||||||
- callbacks
|
- callbacks
|
||||||
properties:
|
properties:
|
||||||
accessToken:
|
accessToken:
|
||||||
|
description: Refreshed access token to be used in subsequent API calls.
|
||||||
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
||||||
callbacks:
|
callbacks:
|
||||||
|
description: Collection of callbacks configured for the authenticated scope.
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: ../../../models/callback/callback.yaml#/components/schemas/Callback
|
$ref: ../../../models/callback/callback.yaml#/components/schemas/Callback
|
||||||
generatedSigningSecret:
|
generatedSigningSecret:
|
||||||
|
description: Newly generated signing secret when secret rotation is requested.
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
post:
|
post:
|
||||||
tags: [Callbacks]
|
tags: [Callbacks]
|
||||||
summary: Rotate callback signing secret
|
summary: Rotate callback signing secret
|
||||||
description: Generates and stores a new HMAC secret for the callback in Vault and returns it once.
|
description: Generates and stores a new HMAC secret for the callback and returns it once.
|
||||||
operationId: callbacksRotateSecret
|
operationId: callbacksRotateSecret
|
||||||
security:
|
security:
|
||||||
- bearerAuth: []
|
- bearerAuth: []
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
OrganizationsAuthData:
|
OrganizationsAuthData:
|
||||||
|
description: Authenticated response payload containing organizations.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -8,8 +9,10 @@ components:
|
|||||||
- organizations
|
- organizations
|
||||||
properties:
|
properties:
|
||||||
accessToken:
|
accessToken:
|
||||||
|
description: Refreshed access token to be used in subsequent API calls.
|
||||||
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
||||||
organizations:
|
organizations:
|
||||||
|
description: Collection of organizations available to the authenticated account.
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: ../../../models/organization/organization.yaml#/components/schemas/Organization
|
$ref: ../../../models/organization/organization.yaml#/components/schemas/Organization
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ components:
|
|||||||
name: callbacks_ref
|
name: callbacks_ref
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
description: Callback subscription reference (Mongo ObjectId, 24 hex chars).
|
description: Callback subscription reference, 24 hex chars.
|
||||||
schema:
|
schema:
|
||||||
$ref: ../../models/objectid.yaml#/components/schemas/ObjectId
|
$ref: ../../models/objectid.yaml#/components/schemas/ObjectId
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ components:
|
|||||||
name: org_ref
|
name: org_ref
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
description: Organization reference in BFF route format (Mongo ObjectId, 24 hex chars).
|
description: Organization reference in BFF route format, 24 hex chars.
|
||||||
schema:
|
schema:
|
||||||
$ref: ../../models/objectid.yaml#/components/schemas/ObjectId
|
$ref: ../../models/objectid.yaml#/components/schemas/ObjectId
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ components:
|
|||||||
name: payment_methods_ref
|
name: payment_methods_ref
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
description: Payment method reference (Mongo ObjectId, 24 hex chars).
|
description: Payment method reference, 24 hex chars.
|
||||||
schema:
|
schema:
|
||||||
$ref: ../../models/objectid.yaml#/components/schemas/ObjectId
|
$ref: ../../models/objectid.yaml#/components/schemas/ObjectId
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ components:
|
|||||||
name: recipients_ref
|
name: recipients_ref
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
description: Recipient reference (Mongo ObjectId, 24 hex chars).
|
description: Recipient reference, 24 hex chars.
|
||||||
schema:
|
schema:
|
||||||
$ref: ../../models/objectid.yaml#/components/schemas/ObjectId
|
$ref: ../../models/objectid.yaml#/components/schemas/ObjectId
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
requestBodies:
|
requestBodies:
|
||||||
PaymentMethodBody:
|
PaymentMethodBody:
|
||||||
|
description: JSON body containing a payment method definition.
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
PaymentMethodRequest:
|
PaymentMethodRequest:
|
||||||
|
description: Request payload used to create or update a payment method.
|
||||||
$ref: ../../../models/payment_method/payment_method.yaml#/components/schemas/PaymentMethod
|
$ref: ../../../models/payment_method/payment_method.yaml#/components/schemas/PaymentMethod
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
Payment MethodsAuthData:
|
Payment MethodsAuthData:
|
||||||
|
description: Authenticated response payload containing payment methods.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -8,8 +9,10 @@ components:
|
|||||||
- payment_methods
|
- payment_methods
|
||||||
properties:
|
properties:
|
||||||
accessToken:
|
accessToken:
|
||||||
|
description: Refreshed access token to be used in subsequent API calls.
|
||||||
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
||||||
payment_methods:
|
payment_methods:
|
||||||
|
description: Collection of payment methods available to the authenticated account.
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: ../../../models/payment_method/payment_method.yaml#/components/schemas/PaymentMethod
|
$ref: ../../../models/payment_method/payment_method.yaml#/components/schemas/PaymentMethod
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
requestBodies:
|
requestBodies:
|
||||||
QuotePaymentBody:
|
QuotePaymentBody:
|
||||||
|
description: JSON payload used to request a quote for one payment intent.
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
@@ -8,6 +9,7 @@ components:
|
|||||||
$ref: ../request/payment.yaml#/components/schemas/QuotePaymentRequest
|
$ref: ../request/payment.yaml#/components/schemas/QuotePaymentRequest
|
||||||
|
|
||||||
QuotePaymentsBody:
|
QuotePaymentsBody:
|
||||||
|
description: JSON payload used to request quotes for multiple payment intents.
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
@@ -15,6 +17,7 @@ components:
|
|||||||
$ref: ../request/payment.yaml#/components/schemas/QuotePaymentsRequest
|
$ref: ../request/payment.yaml#/components/schemas/QuotePaymentsRequest
|
||||||
|
|
||||||
InitiatePaymentBody:
|
InitiatePaymentBody:
|
||||||
|
description: JSON payload used to initiate a single payment.
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
@@ -22,6 +25,7 @@ components:
|
|||||||
$ref: ../request/payment.yaml#/components/schemas/InitiatePaymentRequest
|
$ref: ../request/payment.yaml#/components/schemas/InitiatePaymentRequest
|
||||||
|
|
||||||
InitiatePaymentsBody:
|
InitiatePaymentsBody:
|
||||||
|
description: JSON payload used to initiate multiple payments from a quote reference.
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
|
|||||||
@@ -1,33 +1,41 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
PaymentBase:
|
PaymentBase:
|
||||||
|
description: Base fields shared by payment initiation request payloads.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- idempotencyKey
|
- idempotencyKey
|
||||||
properties:
|
properties:
|
||||||
idempotencyKey:
|
idempotencyKey:
|
||||||
|
description: Client-supplied key used to safely deduplicate requests.
|
||||||
type: string
|
type: string
|
||||||
metadata:
|
metadata:
|
||||||
|
description: Optional request metadata forwarded through payment processing.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
QuotePaymentRequest:
|
QuotePaymentRequest:
|
||||||
|
description: Request payload to quote a single payment intent.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- intent
|
- intent
|
||||||
properties:
|
properties:
|
||||||
idempotencyKey:
|
idempotencyKey:
|
||||||
|
description: Idempotency key used when persisting quote context.
|
||||||
type: string
|
type: string
|
||||||
metadata:
|
metadata:
|
||||||
|
description: Optional metadata associated with the quote request.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
intent:
|
intent:
|
||||||
|
description: Payment intent to be priced.
|
||||||
$ref: ../../../models/payment/payment.yaml#/components/schemas/PaymentIntent
|
$ref: ../../../models/payment/payment.yaml#/components/schemas/PaymentIntent
|
||||||
previewOnly:
|
previewOnly:
|
||||||
|
description: If true, returns a preview quote without requiring idempotency.
|
||||||
type: boolean
|
type: boolean
|
||||||
allOf:
|
allOf:
|
||||||
- if:
|
- if:
|
||||||
@@ -45,23 +53,28 @@ components:
|
|||||||
- idempotencyKey
|
- idempotencyKey
|
||||||
|
|
||||||
QuotePaymentsRequest:
|
QuotePaymentsRequest:
|
||||||
|
description: Request payload to quote multiple payment intents in a single call.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- intents
|
- intents
|
||||||
properties:
|
properties:
|
||||||
idempotencyKey:
|
idempotencyKey:
|
||||||
|
description: Idempotency key used when persisting batch quote context.
|
||||||
type: string
|
type: string
|
||||||
metadata:
|
metadata:
|
||||||
|
description: Optional metadata associated with the quote request.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
intents:
|
intents:
|
||||||
|
description: List of payment intents to be priced.
|
||||||
type: array
|
type: array
|
||||||
minItems: 1
|
minItems: 1
|
||||||
items:
|
items:
|
||||||
$ref: ../../../models/payment/payment.yaml#/components/schemas/PaymentIntent
|
$ref: ../../../models/payment/payment.yaml#/components/schemas/PaymentIntent
|
||||||
previewOnly:
|
previewOnly:
|
||||||
|
description: If true, returns preview quotes without requiring idempotency.
|
||||||
type: boolean
|
type: boolean
|
||||||
allOf:
|
allOf:
|
||||||
- if:
|
- if:
|
||||||
@@ -79,6 +92,7 @@ components:
|
|||||||
- idempotencyKey
|
- idempotencyKey
|
||||||
|
|
||||||
InitiatePaymentRequest:
|
InitiatePaymentRequest:
|
||||||
|
description: Request payload to initiate a single payment.
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: ./payment.yaml#/components/schemas/PaymentBase
|
- $ref: ./payment.yaml#/components/schemas/PaymentBase
|
||||||
- type: object
|
- type: object
|
||||||
@@ -88,11 +102,14 @@ components:
|
|||||||
- required: [quoteRef]
|
- required: [quoteRef]
|
||||||
properties:
|
properties:
|
||||||
intent:
|
intent:
|
||||||
|
description: Payment intent to execute directly.
|
||||||
$ref: ../../../models/payment/payment.yaml#/components/schemas/PaymentIntent
|
$ref: ../../../models/payment/payment.yaml#/components/schemas/PaymentIntent
|
||||||
quoteRef:
|
quoteRef:
|
||||||
|
description: Reference to a previously generated quote to execute.
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
InitiatePaymentsRequest:
|
InitiatePaymentsRequest:
|
||||||
|
description: Request payload to initiate multiple payments from a multi-quote reference.
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: ./payment.yaml#/components/schemas/PaymentBase
|
- $ref: ./payment.yaml#/components/schemas/PaymentBase
|
||||||
- type: object
|
- type: object
|
||||||
@@ -101,4 +118,5 @@ components:
|
|||||||
- quoteRef
|
- quoteRef
|
||||||
properties:
|
properties:
|
||||||
quoteRef:
|
quoteRef:
|
||||||
|
description: Reference to a previously generated multi-quote.
|
||||||
type: string
|
type: string
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
PaymentQuoteData:
|
PaymentQuoteData:
|
||||||
|
description: Response payload for a single payment quote.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -8,13 +9,17 @@ components:
|
|||||||
- quote
|
- quote
|
||||||
properties:
|
properties:
|
||||||
accessToken:
|
accessToken:
|
||||||
|
description: Refreshed access token to be used in subsequent API calls.
|
||||||
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
||||||
idempotencyKey:
|
idempotencyKey:
|
||||||
|
description: Idempotency key associated with the quote response.
|
||||||
type: string
|
type: string
|
||||||
quote:
|
quote:
|
||||||
|
description: Generated quote data for the requested payment intent.
|
||||||
$ref: ../../../models/payment/payment.yaml#/components/schemas/PaymentQuote
|
$ref: ../../../models/payment/payment.yaml#/components/schemas/PaymentQuote
|
||||||
|
|
||||||
PaymentQuotesData:
|
PaymentQuotesData:
|
||||||
|
description: Response payload for a batch quote request.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -22,21 +27,27 @@ components:
|
|||||||
- quote
|
- quote
|
||||||
properties:
|
properties:
|
||||||
accessToken:
|
accessToken:
|
||||||
|
description: Refreshed access token to be used in subsequent API calls.
|
||||||
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
||||||
quote:
|
quote:
|
||||||
|
description: Batch quote summary and quoted items.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
idempotencyKey:
|
idempotencyKey:
|
||||||
|
description: Idempotency key associated with the batch quote response.
|
||||||
type: string
|
type: string
|
||||||
quoteRef:
|
quoteRef:
|
||||||
|
description: Reference to the generated batch quote.
|
||||||
type: string
|
type: string
|
||||||
items:
|
items:
|
||||||
|
description: Collection of quotes for each requested payment intent.
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: ../../../models/payment/payment.yaml#/components/schemas/PaymentQuote
|
$ref: ../../../models/payment/payment.yaml#/components/schemas/PaymentQuote
|
||||||
|
|
||||||
PaymentsData:
|
PaymentsData:
|
||||||
|
description: Response payload containing a list of payments.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -44,15 +55,19 @@ components:
|
|||||||
- payments
|
- payments
|
||||||
properties:
|
properties:
|
||||||
accessToken:
|
accessToken:
|
||||||
|
description: Refreshed access token to be used in subsequent API calls.
|
||||||
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
||||||
payments:
|
payments:
|
||||||
|
description: Collection of payment records.
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: ../../../models/payment/payment.yaml#/components/schemas/Payment
|
$ref: ../../../models/payment/payment.yaml#/components/schemas/Payment
|
||||||
page:
|
page:
|
||||||
|
description: Pagination cursor metadata for payment listing endpoints.
|
||||||
$ref: ../../../models/common/pagination.yaml#/components/schemas/CursorPageResponse
|
$ref: ../../../models/common/pagination.yaml#/components/schemas/CursorPageResponse
|
||||||
|
|
||||||
PaymentData:
|
PaymentData:
|
||||||
|
description: Response payload containing a single payment record.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -60,6 +75,8 @@ components:
|
|||||||
- payment
|
- payment
|
||||||
properties:
|
properties:
|
||||||
accessToken:
|
accessToken:
|
||||||
|
description: Refreshed access token to be used in subsequent API calls.
|
||||||
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
||||||
payment:
|
payment:
|
||||||
|
description: Requested payment record.
|
||||||
$ref: ../../../models/payment/payment.yaml#/components/schemas/Payment
|
$ref: ../../../models/payment/payment.yaml#/components/schemas/Payment
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
requestBodies:
|
requestBodies:
|
||||||
RecipientBody:
|
RecipientBody:
|
||||||
|
description: JSON body containing recipient details.
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
RecipientRequest:
|
RecipientRequest:
|
||||||
|
description: Request payload used to create or update a recipient.
|
||||||
$ref: ../../../models/recipient/recipient.yaml#/components/schemas/Recipient
|
$ref: ../../../models/recipient/recipient.yaml#/components/schemas/Recipient
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
RecipientsAuthData:
|
RecipientsAuthData:
|
||||||
|
description: Authenticated response payload containing recipients.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -8,8 +9,10 @@ components:
|
|||||||
- recipients
|
- recipients
|
||||||
properties:
|
properties:
|
||||||
accessToken:
|
accessToken:
|
||||||
|
description: Refreshed access token to be used in subsequent API calls.
|
||||||
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
$ref: ../../../models/auth/token_data.yaml#/components/schemas/TokenData
|
||||||
recipients:
|
recipients:
|
||||||
|
description: Collection of recipients available to the authenticated account.
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: ../../../models/recipient/recipient.yaml#/components/schemas/Recipient
|
$ref: ../../../models/recipient/recipient.yaml#/components/schemas/Recipient
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
ApiError:
|
ApiError:
|
||||||
|
description: Standard API error envelope with optional debugging details.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -9,11 +10,15 @@ components:
|
|||||||
- source
|
- source
|
||||||
properties:
|
properties:
|
||||||
code:
|
code:
|
||||||
|
description: Application-specific numeric error code.
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
error:
|
error:
|
||||||
|
description: Human-readable error summary.
|
||||||
type: string
|
type: string
|
||||||
source:
|
source:
|
||||||
|
description: Component or subsystem that produced the error.
|
||||||
type: string
|
type: string
|
||||||
details:
|
details:
|
||||||
|
description: Optional detailed message providing additional failure context.
|
||||||
type: string
|
type: string
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
requestBodies:
|
requestBodies:
|
||||||
VerificationCodeBody:
|
VerificationCodeBody:
|
||||||
|
description: JSON payload used to request a new verification code.
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
@@ -8,6 +9,7 @@ components:
|
|||||||
$ref: ../request/verification.yaml#/components/schemas/VerificationCodeRequest
|
$ref: ../request/verification.yaml#/components/schemas/VerificationCodeRequest
|
||||||
|
|
||||||
VerifyCodeBody:
|
VerifyCodeBody:
|
||||||
|
description: JSON payload containing a verification code to validate.
|
||||||
required: true
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
VerificationResponseData:
|
VerificationResponseData:
|
||||||
|
description: Response data returned after requesting a verification code.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -10,17 +11,22 @@ components:
|
|||||||
- target
|
- target
|
||||||
properties:
|
properties:
|
||||||
idempotencyKey:
|
idempotencyKey:
|
||||||
|
description: Idempotency key associated with the verification request.
|
||||||
type: string
|
type: string
|
||||||
ttl_seconds:
|
ttl_seconds:
|
||||||
|
description: Verification code validity period in seconds.
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
cooldown_seconds:
|
cooldown_seconds:
|
||||||
|
description: Cooldown period before another code can be requested.
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
target:
|
target:
|
||||||
|
description: Destination where the verification code was sent.
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
VerifyResultData:
|
VerifyResultData:
|
||||||
|
description: Result payload returned after code verification succeeds.
|
||||||
oneOf:
|
oneOf:
|
||||||
- $ref: ../../accounts/response/auth.yaml#/components/schemas/LoginData
|
- $ref: ../../accounts/response/auth.yaml#/components/schemas/LoginData
|
||||||
- $ref: ../../response/response.yaml#/components/schemas/SuccessResultData
|
- $ref: ../../response/response.yaml#/components/schemas/SuccessResultData
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
AccountData:
|
AccountData:
|
||||||
|
description: Extended account payload including visibility-specific metadata.
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: ./account_public.yaml#/components/schemas/AccountPublic
|
- $ref: ./account_public.yaml#/components/schemas/AccountPublic
|
||||||
- type: object
|
- type: object
|
||||||
|
description: Account attributes that are not part of the public profile.
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- isAnonymous
|
- isAnonymous
|
||||||
properties:
|
properties:
|
||||||
isAnonymous:
|
isAnonymous:
|
||||||
|
description: Indicates whether the account is marked as anonymous.
|
||||||
type: boolean
|
type: boolean
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
AccountPublic:
|
AccountPublic:
|
||||||
|
description: Public account profile data exposed in API responses.
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: ../storable.yaml#/components/schemas/Storable
|
- $ref: ../storable.yaml#/components/schemas/Storable
|
||||||
- $ref: ../common/describable.yaml#/components/schemas/Describable
|
- $ref: ../common/describable.yaml#/components/schemas/Describable
|
||||||
- type: object
|
- type: object
|
||||||
|
description: Account-specific public attributes.
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- login
|
- login
|
||||||
@@ -13,14 +15,19 @@ components:
|
|||||||
- isArchived
|
- isArchived
|
||||||
properties:
|
properties:
|
||||||
login:
|
login:
|
||||||
|
description: Account login identifier represented as an email address.
|
||||||
type: string
|
type: string
|
||||||
format: email
|
format: email
|
||||||
locale:
|
locale:
|
||||||
|
description: Preferred locale used for account-facing content.
|
||||||
type: string
|
type: string
|
||||||
lastName:
|
lastName:
|
||||||
|
description: Account holder last name.
|
||||||
type: string
|
type: string
|
||||||
avatarUrl:
|
avatarUrl:
|
||||||
|
description: Optional URL of the account avatar image.
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
isArchived:
|
isArchived:
|
||||||
|
description: Indicates whether the account is archived and inactive.
|
||||||
type: boolean
|
type: boolean
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
ClientRefreshToken:
|
ClientRefreshToken:
|
||||||
|
description: Refresh token bound to a specific client and device session.
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: ./session_identifier.yaml#/components/schemas/SessionIdentifier
|
- $ref: ./session_identifier.yaml#/components/schemas/SessionIdentifier
|
||||||
- type: object
|
- type: object
|
||||||
|
description: Refresh-token payload associated with the session identifier.
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- token
|
- token
|
||||||
properties:
|
properties:
|
||||||
token:
|
token:
|
||||||
|
description: Long-lived token used to obtain a new access token.
|
||||||
type: string
|
type: string
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
LoginData:
|
LoginData:
|
||||||
|
description: Credentials and optional locale used during user sign-in.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -8,10 +9,13 @@ components:
|
|||||||
- password
|
- password
|
||||||
properties:
|
properties:
|
||||||
login:
|
login:
|
||||||
|
description: User login identifier, represented as an email address.
|
||||||
type: string
|
type: string
|
||||||
format: email
|
format: email
|
||||||
password:
|
password:
|
||||||
|
description: User password submitted for authentication.
|
||||||
type: string
|
type: string
|
||||||
format: password
|
format: password
|
||||||
locale:
|
locale:
|
||||||
|
description: Optional locale preference provided at login time.
|
||||||
type: string
|
type: string
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
SessionIdentifier:
|
SessionIdentifier:
|
||||||
|
description: Identifies an authentication session by client and device.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -8,6 +9,8 @@ components:
|
|||||||
- deviceId
|
- deviceId
|
||||||
properties:
|
properties:
|
||||||
clientId:
|
clientId:
|
||||||
|
description: Client application identifier associated with the session.
|
||||||
type: string
|
type: string
|
||||||
deviceId:
|
deviceId:
|
||||||
|
description: Device/server identifier associated with the client session.
|
||||||
type: string
|
type: string
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
TokenData:
|
TokenData:
|
||||||
|
description: Authentication token payload with expiration metadata.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -8,7 +9,9 @@ components:
|
|||||||
- expiration
|
- expiration
|
||||||
properties:
|
properties:
|
||||||
token:
|
token:
|
||||||
|
description: Issued authentication token value.
|
||||||
type: string
|
type: string
|
||||||
expiration:
|
expiration:
|
||||||
|
description: RFC 3339 timestamp when the token expires.
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
|
|||||||
@@ -1,67 +1,89 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
CallbackRetryPolicy:
|
CallbackBackoff:
|
||||||
|
description: Backoff window used between callback retry attempts.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- minDelayMs
|
- minDelayMs
|
||||||
- maxDelayMs
|
- maxDelayMs
|
||||||
|
properties:
|
||||||
|
minDelayMs:
|
||||||
|
description: Minimum delay in milliseconds before scheduling a retry attempt.
|
||||||
|
type: integer
|
||||||
|
minimum: 1
|
||||||
|
maxDelayMs:
|
||||||
|
description: Maximum delay in milliseconds before scheduling a retry attempt.
|
||||||
|
type: integer
|
||||||
|
minimum: 1
|
||||||
|
|
||||||
|
CallbackRetryPolicy:
|
||||||
|
description: Retry and delivery behavior for callback requests.
|
||||||
|
type: object
|
||||||
|
additionalProperties: false
|
||||||
|
required:
|
||||||
|
- backoff
|
||||||
- signingMode
|
- signingMode
|
||||||
- maxAttempts
|
- maxAttempts
|
||||||
- requestTimeoutMs
|
- requestTimeoutMs
|
||||||
properties:
|
properties:
|
||||||
minDelayMs:
|
backoff:
|
||||||
type: integer
|
description: Delay boundaries used to compute retry backoff between attempts.
|
||||||
minimum: 1
|
$ref: '#/components/schemas/CallbackBackoff'
|
||||||
maxDelayMs:
|
|
||||||
type: integer
|
|
||||||
minimum: 1
|
|
||||||
signingMode:
|
signingMode:
|
||||||
|
description: Request-signing strategy applied when dispatching callback payloads.
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
- none
|
- none
|
||||||
- hmac_sha256
|
- hmac_sha256
|
||||||
secretRef:
|
|
||||||
type: string
|
|
||||||
nullable: true
|
|
||||||
headers:
|
headers:
|
||||||
|
description: Additional HTTP headers included with every callback request.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
maxAttempts:
|
maxAttempts:
|
||||||
|
description: Maximum number of delivery attempts before marking dispatch as failed.
|
||||||
type: integer
|
type: integer
|
||||||
minimum: 1
|
minimum: 1
|
||||||
requestTimeoutMs:
|
requestTimeoutMs:
|
||||||
|
description: Per-request timeout in milliseconds for callback HTTP calls.
|
||||||
type: integer
|
type: integer
|
||||||
minimum: 1
|
minimum: 1
|
||||||
|
|
||||||
Callback:
|
CallbackContent:
|
||||||
|
description: Callback endpoint configuration and delivery parameters.
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: ../permission_bound.yaml#/components/schemas/PermissionBound
|
|
||||||
- $ref: ../common/describable.yaml#/components/schemas/Describable
|
|
||||||
- type: object
|
- type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- clientId
|
|
||||||
- status
|
- status
|
||||||
- url
|
- url
|
||||||
- eventTypes
|
- eventTypes
|
||||||
- retryPolicy
|
- retryPolicy
|
||||||
properties:
|
properties:
|
||||||
clientId:
|
|
||||||
type: string
|
|
||||||
status:
|
status:
|
||||||
|
description: Operational state controlling whether callback delivery is enabled.
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
- active
|
- active
|
||||||
- disabled
|
- disabled
|
||||||
url:
|
url:
|
||||||
|
description: Absolute HTTPS endpoint URL that receives callback events.
|
||||||
type: string
|
type: string
|
||||||
format: uri
|
format: uri
|
||||||
eventTypes:
|
eventTypes:
|
||||||
|
description: Event type names that trigger callback delivery to this endpoint.
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
type: string
|
type: string
|
||||||
retryPolicy:
|
retryPolicy:
|
||||||
|
description: Retry and timeout parameters used when dispatching callback events.
|
||||||
$ref: '#/components/schemas/CallbackRetryPolicy'
|
$ref: '#/components/schemas/CallbackRetryPolicy'
|
||||||
|
|
||||||
|
|
||||||
|
Callback:
|
||||||
|
description: Stored callback configuration bound to an organization permission scope.
|
||||||
|
allOf:
|
||||||
|
- $ref: ../permission_bound.yaml#/components/schemas/PermissionBound
|
||||||
|
- $ref: ../common/describable.yaml#/components/schemas/Describable
|
||||||
|
- $ref: '#/components/schemas/CallbackContent'
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
Describable:
|
Describable:
|
||||||
|
description: Common naming metadata for user-defined entities.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
|
description: Human-readable name of the entity.
|
||||||
type: string
|
type: string
|
||||||
description:
|
description:
|
||||||
|
description: Optional free-form description of the entity.
|
||||||
type: string
|
type: string
|
||||||
nullable: true
|
nullable: true
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
Money:
|
Money:
|
||||||
|
description: Monetary value represented by a decimal amount and ISO currency code.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -12,5 +13,6 @@ components:
|
|||||||
description: Decimal string amount.
|
description: Decimal string amount.
|
||||||
example: '125.50'
|
example: '125.50'
|
||||||
currency:
|
currency:
|
||||||
|
description: ISO 4217 currency code for the provided amount.
|
||||||
type: string
|
type: string
|
||||||
example: USD
|
example: USD
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
CursorPageResponse:
|
CursorPageResponse:
|
||||||
|
description: Cursor-based pagination metadata returned with list responses.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
next_cursor:
|
next_cursor:
|
||||||
|
description: Opaque cursor to request the next page; omitted when no more items exist.
|
||||||
type: string
|
type: string
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
ObjectId:
|
ObjectId:
|
||||||
|
description: Object identifier represented as a 24-character hexadecimal string.
|
||||||
type: string
|
type: string
|
||||||
|
format: objectid
|
||||||
pattern: '^[a-fA-F0-9]{24}$'
|
pattern: '^[a-fA-F0-9]{24}$'
|
||||||
examples:
|
examples:
|
||||||
- 64f85f5f4c7dbf7cfb8f3f10
|
- 64f85f5f4c7dbf7cfb8f3f10
|
||||||
|
|||||||
@@ -7,11 +7,8 @@ components:
|
|||||||
- type: object
|
- type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- tenantRef
|
|
||||||
- timeZone
|
- timeZone
|
||||||
properties:
|
properties:
|
||||||
tenantRef:
|
|
||||||
$ref: ../objectid.yaml#/components/schemas/ObjectId
|
|
||||||
timeZone:
|
timeZone:
|
||||||
type: string
|
type: string
|
||||||
logoUrl:
|
logoUrl:
|
||||||
|
|||||||
@@ -1,39 +1,50 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
Asset:
|
Asset:
|
||||||
|
description: Blockchain asset identifier used for on-chain transfers.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
chain:
|
chain:
|
||||||
|
description: Chain/network where the asset exists.
|
||||||
$ref: ../../external/chain_network.yaml#/components/schemas/ChainNetwork
|
$ref: ../../external/chain_network.yaml#/components/schemas/ChainNetwork
|
||||||
token_symbol:
|
token_symbol:
|
||||||
|
description: Symbol of the token on the selected chain.
|
||||||
type: string
|
type: string
|
||||||
contract_address:
|
contract_address:
|
||||||
|
description: Smart-contract address for tokenized assets.
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
LedgerEndpoint:
|
LedgerEndpoint:
|
||||||
|
description: Internal ledger-based endpoint used as payment source or destination.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- ledger_account_ref
|
- ledger_account_ref
|
||||||
properties:
|
properties:
|
||||||
ledger_account_ref:
|
ledger_account_ref:
|
||||||
|
description: Reference of the primary ledger account.
|
||||||
type: string
|
type: string
|
||||||
contra_ledger_account_ref:
|
contra_ledger_account_ref:
|
||||||
|
description: Optional contra ledger account reference for balancing entries.
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
ManagedWalletEndpoint:
|
ManagedWalletEndpoint:
|
||||||
|
description: Endpoint referencing a managed wallet within the platform.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- managed_wallet_ref
|
- managed_wallet_ref
|
||||||
properties:
|
properties:
|
||||||
managed_wallet_ref:
|
managed_wallet_ref:
|
||||||
|
description: Reference of the managed wallet.
|
||||||
type: string
|
type: string
|
||||||
asset:
|
asset:
|
||||||
|
description: Asset details for the managed wallet transfer.
|
||||||
$ref: ./payment.yaml#/components/schemas/Asset
|
$ref: ./payment.yaml#/components/schemas/Asset
|
||||||
|
|
||||||
ExternalChainEndpoint:
|
ExternalChainEndpoint:
|
||||||
|
description: Endpoint representing an external blockchain address.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -41,56 +52,72 @@ components:
|
|||||||
- address
|
- address
|
||||||
properties:
|
properties:
|
||||||
asset:
|
asset:
|
||||||
|
description: Asset to be transferred to or from the external address.
|
||||||
$ref: ./payment.yaml#/components/schemas/Asset
|
$ref: ./payment.yaml#/components/schemas/Asset
|
||||||
address:
|
address:
|
||||||
|
description: Target blockchain address.
|
||||||
type: string
|
type: string
|
||||||
memo:
|
memo:
|
||||||
|
description: Optional destination memo or tag required by some chains.
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
CardEndpoint:
|
CardEndpoint:
|
||||||
|
description: Raw card details endpoint used for card-based payment flows.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- pan
|
- pan
|
||||||
properties:
|
properties:
|
||||||
pan:
|
pan:
|
||||||
|
description: Primary account number of the card.
|
||||||
type: string
|
type: string
|
||||||
firstName:
|
firstName:
|
||||||
|
description: Cardholder first name.
|
||||||
type: string
|
type: string
|
||||||
lastName:
|
lastName:
|
||||||
|
description: Cardholder last name.
|
||||||
type: string
|
type: string
|
||||||
exp_month:
|
exp_month:
|
||||||
|
description: Card expiration month.
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
minimum: 0
|
minimum: 0
|
||||||
exp_year:
|
exp_year:
|
||||||
|
description: Card expiration year.
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
minimum: 0
|
minimum: 0
|
||||||
country:
|
country:
|
||||||
|
description: Card issuing country code.
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
CardTokenEndpoint:
|
CardTokenEndpoint:
|
||||||
|
description: Tokenized card endpoint used instead of raw PAN details.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- token
|
- token
|
||||||
properties:
|
properties:
|
||||||
token:
|
token:
|
||||||
|
description: Provider-issued card token.
|
||||||
type: string
|
type: string
|
||||||
masked_pan:
|
masked_pan:
|
||||||
|
description: Masked PAN representation for display and auditing.
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
WalletEndpoint:
|
WalletEndpoint:
|
||||||
|
description: Generic wallet endpoint identified by wallet ID.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- walletId
|
- walletId
|
||||||
properties:
|
properties:
|
||||||
walletId:
|
walletId:
|
||||||
|
description: Unique identifier of the wallet.
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
Endpoint:
|
Endpoint:
|
||||||
|
description: Polymorphic payment endpoint definition.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -98,8 +125,10 @@ components:
|
|||||||
- data
|
- data
|
||||||
properties:
|
properties:
|
||||||
type:
|
type:
|
||||||
|
description: Endpoint type determining the shape of the `data` field.
|
||||||
$ref: ../../external/endpoint_type.yaml#/components/schemas/EndpointType
|
$ref: ../../external/endpoint_type.yaml#/components/schemas/EndpointType
|
||||||
data:
|
data:
|
||||||
|
description: Endpoint payload corresponding to the selected endpoint type.
|
||||||
oneOf:
|
oneOf:
|
||||||
- $ref: ./payment.yaml#/components/schemas/LedgerEndpoint
|
- $ref: ./payment.yaml#/components/schemas/LedgerEndpoint
|
||||||
- $ref: ./payment.yaml#/components/schemas/ManagedWalletEndpoint
|
- $ref: ./payment.yaml#/components/schemas/ManagedWalletEndpoint
|
||||||
@@ -108,36 +137,49 @@ components:
|
|||||||
- $ref: ./payment.yaml#/components/schemas/CardTokenEndpoint
|
- $ref: ./payment.yaml#/components/schemas/CardTokenEndpoint
|
||||||
- $ref: ./payment.yaml#/components/schemas/WalletEndpoint
|
- $ref: ./payment.yaml#/components/schemas/WalletEndpoint
|
||||||
metadata:
|
metadata:
|
||||||
|
description: Optional key-value metadata attached to the endpoint.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
Customer:
|
Customer:
|
||||||
|
description: Customer identity and address attributes for compliance and routing.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
|
description: External or internal customer identifier.
|
||||||
type: string
|
type: string
|
||||||
first_name:
|
first_name:
|
||||||
|
description: Customer first name.
|
||||||
type: string
|
type: string
|
||||||
middle_name:
|
middle_name:
|
||||||
|
description: Customer middle name.
|
||||||
type: string
|
type: string
|
||||||
last_name:
|
last_name:
|
||||||
|
description: Customer last name.
|
||||||
type: string
|
type: string
|
||||||
ip:
|
ip:
|
||||||
|
description: Source IP address associated with the payment request.
|
||||||
type: string
|
type: string
|
||||||
zip:
|
zip:
|
||||||
|
description: Postal or ZIP code.
|
||||||
type: string
|
type: string
|
||||||
country:
|
country:
|
||||||
|
description: Country code of customer residence or billing address.
|
||||||
type: string
|
type: string
|
||||||
state:
|
state:
|
||||||
|
description: State or region.
|
||||||
type: string
|
type: string
|
||||||
city:
|
city:
|
||||||
|
description: City name.
|
||||||
type: string
|
type: string
|
||||||
address:
|
address:
|
||||||
|
description: Street address line.
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
CurrencyPair:
|
CurrencyPair:
|
||||||
|
description: Foreign-exchange currency pair.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -145,11 +187,14 @@ components:
|
|||||||
- quote
|
- quote
|
||||||
properties:
|
properties:
|
||||||
base:
|
base:
|
||||||
|
description: Base currency code.
|
||||||
type: string
|
type: string
|
||||||
quote:
|
quote:
|
||||||
|
description: Quote currency code.
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
FxIntent:
|
FxIntent:
|
||||||
|
description: FX execution preferences associated with a payment.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -157,21 +202,28 @@ components:
|
|||||||
- side
|
- side
|
||||||
properties:
|
properties:
|
||||||
pair:
|
pair:
|
||||||
|
description: Currency pair for FX conversion.
|
||||||
$ref: ./payment.yaml#/components/schemas/CurrencyPair
|
$ref: ./payment.yaml#/components/schemas/CurrencyPair
|
||||||
side:
|
side:
|
||||||
|
description: Side of the FX trade intent.
|
||||||
$ref: ../../external/fx_side.yaml#/components/schemas/FxSide
|
$ref: ../../external/fx_side.yaml#/components/schemas/FxSide
|
||||||
firm:
|
firm:
|
||||||
|
description: Whether a firm quote is required.
|
||||||
type: boolean
|
type: boolean
|
||||||
ttl_ms:
|
ttl_ms:
|
||||||
|
description: Desired quote time-to-live in milliseconds.
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
preferred_provider:
|
preferred_provider:
|
||||||
|
description: Preferred FX liquidity provider identifier.
|
||||||
type: string
|
type: string
|
||||||
max_age_ms:
|
max_age_ms:
|
||||||
|
description: Maximum accepted quote age in milliseconds.
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
|
|
||||||
PaymentIntent:
|
PaymentIntent:
|
||||||
|
description: Requested payment execution parameters before processing.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -181,160 +233,219 @@ components:
|
|||||||
- amount
|
- amount
|
||||||
properties:
|
properties:
|
||||||
kind:
|
kind:
|
||||||
|
description: High-level payment kind that drives orchestration behavior.
|
||||||
$ref: ../../external/payment_kind.yaml#/components/schemas/PaymentKind
|
$ref: ../../external/payment_kind.yaml#/components/schemas/PaymentKind
|
||||||
source:
|
source:
|
||||||
|
description: Source endpoint from which funds are debited.
|
||||||
$ref: ./payment.yaml#/components/schemas/Endpoint
|
$ref: ./payment.yaml#/components/schemas/Endpoint
|
||||||
destination:
|
destination:
|
||||||
|
description: Destination endpoint to which funds are credited.
|
||||||
$ref: ./payment.yaml#/components/schemas/Endpoint
|
$ref: ./payment.yaml#/components/schemas/Endpoint
|
||||||
amount:
|
amount:
|
||||||
|
description: Requested payment amount.
|
||||||
$ref: ../common/money.yaml#/components/schemas/Money
|
$ref: ../common/money.yaml#/components/schemas/Money
|
||||||
fx:
|
fx:
|
||||||
|
description: Optional FX preferences when conversion is needed.
|
||||||
$ref: ./payment.yaml#/components/schemas/FxIntent
|
$ref: ./payment.yaml#/components/schemas/FxIntent
|
||||||
settlement_mode:
|
settlement_mode:
|
||||||
|
description: Settlement strategy for the transfer.
|
||||||
$ref: ../../external/settlement_mode.yaml#/components/schemas/SettlementMode
|
$ref: ../../external/settlement_mode.yaml#/components/schemas/SettlementMode
|
||||||
fee_treatment:
|
fee_treatment:
|
||||||
|
description: How fees should be applied to source/destination amounts.
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
- unspecified
|
- unspecified
|
||||||
- add_to_source
|
- add_to_source
|
||||||
- deduct_from_destination
|
- deduct_from_destination
|
||||||
attributes:
|
attributes:
|
||||||
|
description: Additional key-value attributes used by downstream processors.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
customer:
|
customer:
|
||||||
|
description: Optional customer information attached to the payment intent.
|
||||||
$ref: ./payment.yaml#/components/schemas/Customer
|
$ref: ./payment.yaml#/components/schemas/Customer
|
||||||
|
|
||||||
FeeLine:
|
FeeLine:
|
||||||
|
description: Single fee component included in a payment quote.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
ledgerAccountRef:
|
ledgerAccountRef:
|
||||||
|
description: Ledger account reference receiving or charging this fee.
|
||||||
type: string
|
type: string
|
||||||
amount:
|
amount:
|
||||||
|
description: Monetary amount of the fee line.
|
||||||
$ref: ../common/money.yaml#/components/schemas/Money
|
$ref: ../common/money.yaml#/components/schemas/Money
|
||||||
lineType:
|
lineType:
|
||||||
|
description: Fee line classification.
|
||||||
type: string
|
type: string
|
||||||
side:
|
side:
|
||||||
|
description: Indicates whether the fee applies on debit or credit side.
|
||||||
type: string
|
type: string
|
||||||
meta:
|
meta:
|
||||||
|
description: Optional metadata for fee calculation traceability.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
QuoteFees:
|
QuoteFees:
|
||||||
|
description: Collection of fee lines for a quoted payment.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
lines:
|
lines:
|
||||||
|
description: List of individual quoted fee lines.
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: ./payment.yaml#/components/schemas/FeeLine
|
$ref: ./payment.yaml#/components/schemas/FeeLine
|
||||||
|
|
||||||
QuoteAmounts:
|
QuoteAmounts:
|
||||||
|
description: Amount breakdown returned with a payment quote.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
sourcePrincipal:
|
sourcePrincipal:
|
||||||
|
description: Principal amount debited from the source before fees.
|
||||||
$ref: ../common/money.yaml#/components/schemas/Money
|
$ref: ../common/money.yaml#/components/schemas/Money
|
||||||
sourceDebitTotal:
|
sourceDebitTotal:
|
||||||
|
description: Total amount debited from the source including adjustments.
|
||||||
$ref: ../common/money.yaml#/components/schemas/Money
|
$ref: ../common/money.yaml#/components/schemas/Money
|
||||||
destinationSettlement:
|
destinationSettlement:
|
||||||
|
description: Net amount expected to settle at the destination.
|
||||||
$ref: ../common/money.yaml#/components/schemas/Money
|
$ref: ../common/money.yaml#/components/schemas/Money
|
||||||
|
|
||||||
FxQuote:
|
FxQuote:
|
||||||
|
description: FX quote details used to price converted payment amounts.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
quoteRef:
|
quoteRef:
|
||||||
|
description: Identifier of the FX quote.
|
||||||
type: string
|
type: string
|
||||||
baseCurrency:
|
baseCurrency:
|
||||||
|
description: Base currency of the quote pair.
|
||||||
type: string
|
type: string
|
||||||
quoteCurrency:
|
quoteCurrency:
|
||||||
|
description: Quote currency of the quote pair.
|
||||||
type: string
|
type: string
|
||||||
side:
|
side:
|
||||||
|
description: FX side used for pricing.
|
||||||
type: string
|
type: string
|
||||||
price:
|
price:
|
||||||
|
description: Quoted FX price as a decimal string.
|
||||||
type: string
|
type: string
|
||||||
baseAmount:
|
baseAmount:
|
||||||
|
description: Base currency amount covered by this quote.
|
||||||
$ref: ../common/money.yaml#/components/schemas/Money
|
$ref: ../common/money.yaml#/components/schemas/Money
|
||||||
quoteAmount:
|
quoteAmount:
|
||||||
|
description: Quote currency amount corresponding to the base amount.
|
||||||
$ref: ../common/money.yaml#/components/schemas/Money
|
$ref: ../common/money.yaml#/components/schemas/Money
|
||||||
expiresAtUnixMs:
|
expiresAtUnixMs:
|
||||||
|
description: Quote expiration timestamp in Unix milliseconds.
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
pricedAtUnixMs:
|
pricedAtUnixMs:
|
||||||
|
description: Quote pricing timestamp in Unix milliseconds.
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
format: int64
|
||||||
provider:
|
provider:
|
||||||
|
description: Provider that supplied the FX quote.
|
||||||
type: string
|
type: string
|
||||||
rateRef:
|
rateRef:
|
||||||
|
description: Provider-specific rate reference identifier.
|
||||||
type: string
|
type: string
|
||||||
firm:
|
firm:
|
||||||
|
description: Indicates whether the FX quote is firm.
|
||||||
type: boolean
|
type: boolean
|
||||||
|
|
||||||
PaymentQuote:
|
PaymentQuote:
|
||||||
|
description: Pricing result for a specific payment intent.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
quoteRef:
|
quoteRef:
|
||||||
|
description: Unique identifier of the payment quote.
|
||||||
type: string
|
type: string
|
||||||
intentRef:
|
intentRef:
|
||||||
|
description: Reference to the payment intent used for quoting.
|
||||||
type: string
|
type: string
|
||||||
amounts:
|
amounts:
|
||||||
|
description: Amount breakdown for source and destination values.
|
||||||
$ref: ./payment.yaml#/components/schemas/QuoteAmounts
|
$ref: ./payment.yaml#/components/schemas/QuoteAmounts
|
||||||
fees:
|
fees:
|
||||||
|
description: Fee breakdown included in the quote.
|
||||||
$ref: ./payment.yaml#/components/schemas/QuoteFees
|
$ref: ./payment.yaml#/components/schemas/QuoteFees
|
||||||
fxQuote:
|
fxQuote:
|
||||||
|
description: Associated FX quote when conversion is part of the payment.
|
||||||
$ref: ./payment.yaml#/components/schemas/FxQuote
|
$ref: ./payment.yaml#/components/schemas/FxQuote
|
||||||
|
|
||||||
PaymentOperation:
|
PaymentOperation:
|
||||||
|
description: Execution step record captured during payment processing.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
stepRef:
|
stepRef:
|
||||||
|
description: Identifier of the orchestration step.
|
||||||
type: string
|
type: string
|
||||||
code:
|
code:
|
||||||
|
description: Operation code representing the executed action.
|
||||||
type: string
|
type: string
|
||||||
state:
|
state:
|
||||||
|
description: Current state of the operation.
|
||||||
type: string
|
type: string
|
||||||
label:
|
label:
|
||||||
|
description: Human-readable operation label.
|
||||||
type: string
|
type: string
|
||||||
failureCode:
|
failureCode:
|
||||||
|
description: Machine-readable failure code when operation fails.
|
||||||
type: string
|
type: string
|
||||||
failureReason:
|
failureReason:
|
||||||
|
description: Human-readable failure reason when operation fails.
|
||||||
type: string
|
type: string
|
||||||
startedAt:
|
startedAt:
|
||||||
|
description: RFC 3339 timestamp when execution of the operation started.
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
completedAt:
|
completedAt:
|
||||||
|
description: RFC 3339 timestamp when execution of the operation completed.
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
|
|
||||||
Payment:
|
Payment:
|
||||||
|
description: Persisted payment aggregate with status, quote, and operation history.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
properties:
|
properties:
|
||||||
paymentRef:
|
paymentRef:
|
||||||
|
description: Unique payment reference identifier.
|
||||||
type: string
|
type: string
|
||||||
idempotencyKey:
|
idempotencyKey:
|
||||||
|
description: Idempotency key used to safely deduplicate create requests.
|
||||||
type: string
|
type: string
|
||||||
state:
|
state:
|
||||||
|
description: Current lifecycle state of the payment.
|
||||||
$ref: ../../external/payment_state.yaml#/components/schemas/PaymentState
|
$ref: ../../external/payment_state.yaml#/components/schemas/PaymentState
|
||||||
failureCode:
|
failureCode:
|
||||||
|
description: Failure code set when the payment cannot be completed.
|
||||||
type: string
|
type: string
|
||||||
failureReason:
|
failureReason:
|
||||||
|
description: Human-readable explanation of the failure.
|
||||||
type: string
|
type: string
|
||||||
operations:
|
operations:
|
||||||
|
description: Chronological list of operations executed for this payment.
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: ./payment.yaml#/components/schemas/PaymentOperation
|
$ref: ./payment.yaml#/components/schemas/PaymentOperation
|
||||||
lastQuote:
|
lastQuote:
|
||||||
|
description: Most recent payment quote used or generated for the payment.
|
||||||
$ref: ./payment.yaml#/components/schemas/PaymentQuote
|
$ref: ./payment.yaml#/components/schemas/PaymentQuote
|
||||||
createdAt:
|
createdAt:
|
||||||
|
description: RFC 3339 timestamp when the payment was created.
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
meta:
|
meta:
|
||||||
|
description: Additional metadata captured for the payment.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
PermissionBound:
|
PermissionBound:
|
||||||
|
description: Association between an organization and a permission, including archival state.
|
||||||
allOf:
|
allOf:
|
||||||
- $ref: ./storable.yaml#/components/schemas/Storable
|
- $ref: ./storable.yaml#/components/schemas/Storable
|
||||||
- type: object
|
- type: object
|
||||||
|
description: Permission binding details scoped to an organization.
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
- organizationRef
|
- organizationRef
|
||||||
@@ -11,8 +13,11 @@ components:
|
|||||||
- isArchived
|
- isArchived
|
||||||
properties:
|
properties:
|
||||||
organizationRef:
|
organizationRef:
|
||||||
|
description: Identifier of the organization that owns this permission binding.
|
||||||
$ref: ./objectid.yaml#/components/schemas/ObjectId
|
$ref: ./objectid.yaml#/components/schemas/ObjectId
|
||||||
permissionRef:
|
permissionRef:
|
||||||
|
description: Identifier of the permission granted to the organization.
|
||||||
$ref: ./objectid.yaml#/components/schemas/ObjectId
|
$ref: ./objectid.yaml#/components/schemas/ObjectId
|
||||||
isArchived:
|
isArchived:
|
||||||
|
description: Indicates whether this object is archived and inactive.
|
||||||
type: boolean
|
type: boolean
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
Storable:
|
Storable:
|
||||||
|
description: Common persistence metadata included on stored entities.
|
||||||
type: object
|
type: object
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
required:
|
required:
|
||||||
@@ -9,10 +10,13 @@ components:
|
|||||||
- updatedAt
|
- updatedAt
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
|
description: Unique identifier assigned to the stored entity.
|
||||||
$ref: ./objectid.yaml#/components/schemas/ObjectId
|
$ref: ./objectid.yaml#/components/schemas/ObjectId
|
||||||
createdAt:
|
createdAt:
|
||||||
|
description: RFC 3339 timestamp indicating when the entity was created.
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
updatedAt:
|
updatedAt:
|
||||||
|
description: RFC 3339 timestamp indicating the most recent entity update.
|
||||||
type: string
|
type: string
|
||||||
format: date-time
|
format: date-time
|
||||||
|
|||||||
Reference in New Issue
Block a user