From 6515346f7f982d79a5fe7f85fe117559e1dec219 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 4 Jun 2026 12:48:50 +0200 Subject: [PATCH 01/22] chore(deps): upgrade go-libs to v5 --- cmd/root.go | 39 +++++++------- cmd/serve.go | 28 +++++----- cmd/worker.go | 18 +++---- go.mod | 23 ++------ go.sum | 54 ++++--------------- internal/api/backend.go | 2 +- internal/api/backend_generated.go | 18 +++---- internal/api/handler_info.go | 2 +- internal/api/module.go | 4 +- internal/api/module_test.go | 9 ++-- internal/api/router.go | 4 +- .../api/v1/handler_abort_workflow_instance.go | 2 +- internal/api/v1/handler_create_trigger.go | 2 +- internal/api/v1/handler_create_workflow.go | 2 +- internal/api/v1/handler_delete_trigger.go | 2 +- internal/api/v1/handler_delete_workflow.go | 2 +- .../api/v1/handler_delete_workflow_test.go | 2 +- internal/api/v1/handler_get_trigger.go | 2 +- internal/api/v1/handler_list_instances.go | 2 +- .../api/v1/handler_list_instances_test.go | 4 +- internal/api/v1/handler_list_triggers.go | 4 +- .../v1/handler_list_triggers_occurrences.go | 2 +- internal/api/v1/handler_list_workflows.go | 4 +- internal/api/v1/handler_post_event.go | 2 +- internal/api/v1/handler_read_instance.go | 2 +- .../api/v1/handler_read_instance_history.go | 2 +- internal/api/v1/handler_read_instance_test.go | 4 +- internal/api/v1/handler_read_stage_history.go | 2 +- internal/api/v1/handler_read_workflow.go | 2 +- internal/api/v1/handler_run_workflow.go | 2 +- internal/api/v1/handler_run_workflow_test.go | 2 +- internal/api/v1/main_test.go | 18 +++---- internal/api/v1/router.go | 6 +-- .../api/v2/handler_abort_workflow_instance.go | 2 +- internal/api/v2/handler_create_trigger.go | 2 +- internal/api/v2/handler_create_workflow.go | 2 +- internal/api/v2/handler_delete_trigger.go | 2 +- internal/api/v2/handler_delete_workflow.go | 2 +- .../api/v2/handler_delete_workflow_test.go | 2 +- internal/api/v2/handler_get_trigger.go | 2 +- internal/api/v2/handler_list_instances.go | 4 +- .../api/v2/handler_list_instances_test.go | 4 +- internal/api/v2/handler_list_triggers.go | 4 +- .../v2/handler_list_triggers_occurrences.go | 4 +- internal/api/v2/handler_list_workflows.go | 4 +- internal/api/v2/handler_post_event.go | 2 +- internal/api/v2/handler_read_instance.go | 2 +- .../api/v2/handler_read_instance_history.go | 2 +- internal/api/v2/handler_read_instance_test.go | 2 +- internal/api/v2/handler_read_stage_history.go | 2 +- internal/api/v2/handler_read_workflow.go | 2 +- internal/api/v2/handler_run_workflow.go | 2 +- internal/api/v2/handler_run_workflow_test.go | 2 +- internal/api/v2/handler_test_trigger.go | 2 +- internal/api/v2/handler_test_trigger_test.go | 4 +- internal/api/v2/main_test.go | 18 +++---- internal/api/v2/router.go | 6 +-- internal/schema/map.go | 2 +- internal/storage/main_test.go | 8 +-- internal/storage/migrations.go | 2 +- internal/storage/migrations_test.go | 6 +-- internal/temporalworker/module.go | 2 +- internal/triggers/activities.go | 4 +- internal/triggers/expression.go | 4 +- internal/triggers/listener.go | 8 +-- internal/triggers/listener_test.go | 10 ++-- internal/triggers/main_test.go | 8 +-- internal/triggers/manager.go | 2 +- internal/triggers/module.go | 2 +- internal/triggers/trigger.go | 2 +- internal/triggers/workflow_trigger.go | 4 +- internal/triggers/workflow_trigger_test.go | 10 ++-- internal/workflow/activities/activity.go | 2 +- .../activity_ledger_create_transaction.go | 2 +- .../activities/activity_wallet_credit.go | 2 +- .../activities/activity_wallet_debit.go | 2 +- .../activities/activity_wallet_list.go | 2 +- internal/workflow/activities_test.go | 8 +-- internal/workflow/main_test.go | 10 ++-- internal/workflow/manager.go | 4 +- internal/workflow/manager_test.go | 8 +-- internal/workflow/stage.go | 2 +- internal/workflow/stages/delay/delay.go | 2 +- internal/workflow/stages/delay/run.go | 2 +- internal/workflow/stages/delay/run_test.go | 2 +- internal/workflow/stages/send/run.go | 6 +-- internal/workflow/stages/send/run_test.go | 4 +- internal/workflow/stages/send/send.go | 4 +- pkg/events/events.go | 2 +- 89 files changed, 224 insertions(+), 267 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index cb4ff5a..45e4a99 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -5,16 +5,17 @@ import ( "fmt" "net/http" - "github.com/formancehq/go-libs/v3/auth" - "github.com/formancehq/go-libs/v3/bun/bunconnect" - "github.com/formancehq/go-libs/v3/bun/bunmigrate" - "github.com/formancehq/go-libs/v3/licence" - "github.com/formancehq/go-libs/v3/otlp" - "github.com/formancehq/go-libs/v3/otlp/otlpmetrics" - "github.com/formancehq/go-libs/v3/otlp/otlptraces" - "github.com/formancehq/go-libs/v3/publish" - "github.com/formancehq/go-libs/v3/service" - "github.com/formancehq/go-libs/v3/temporal" + "github.com/formancehq/go-libs/v5/pkg/fx/authnfx" + "github.com/formancehq/go-libs/v5/pkg/fx/messagingfx" + "github.com/formancehq/go-libs/v5/pkg/fx/observefx" + "github.com/formancehq/go-libs/v5/pkg/fx/storagefx" + "github.com/formancehq/go-libs/v5/pkg/fx/workflowfx" + otlp "github.com/formancehq/go-libs/v5/pkg/observe" + otlptraces "github.com/formancehq/go-libs/v5/pkg/observe/traces" + "github.com/formancehq/go-libs/v5/pkg/service" + bunconnect "github.com/formancehq/go-libs/v5/pkg/storage/bun/connect" + bunmigrate "github.com/formancehq/go-libs/v5/pkg/storage/bun/migrate" + "github.com/formancehq/go-libs/v5/pkg/workflow/temporal" "github.com/formancehq/orchestration/internal/storage" "github.com/formancehq/orchestration/internal/temporalworker" "github.com/formancehq/orchestration/internal/tracer" @@ -70,7 +71,7 @@ func Execute() { } func commonOptions(cmd *cobra.Command) (fx.Option, error) { - connectionOptions, err := bunconnect.ConnectionOptionsFromFlags(cmd) + connectionOptions, err := bunconnect.ConnectionOptionsFromFlags(cmd.Flags(), cmd.Context()) if err != nil { return nil, err } @@ -79,9 +80,9 @@ func commonOptions(cmd *cobra.Command) (fx.Option, error) { temporalTaskQueue, _ := cmd.Flags().GetString(temporal.TemporalTaskQueueFlag) return fx.Options( - otlp.FXModuleFromFlags(cmd), - otlptraces.FXModuleFromFlags(cmd), - temporal.FXModuleFromFlags( + observefx.ResourceModuleFromFlags(cmd), + observefx.TracesModuleFromFlags(cmd), + workflowfx.TemporalClientModuleFromFlags( cmd, tracer.Tracer, temporal.SearchAttributes{ @@ -91,11 +92,11 @@ func commonOptions(cmd *cobra.Command) (fx.Option, error) { ), }, ), - otlpmetrics.FXModuleFromFlags(cmd), - bunconnect.Module(*connectionOptions, service.IsDebug(cmd)), - publish.FXModuleFromFlags(cmd, service.IsDebug(cmd)), - auth.FXModuleFromFlags(cmd), - licence.FXModuleFromFlags(cmd, ServiceName), + observefx.MetricsModuleFromFlags(cmd), + storagefx.BunConnectModule(*connectionOptions, service.IsDebug(cmd)), + messagingfx.PublishModuleFromFlags(cmd, service.IsDebug(cmd)), + authnfx.JWTModuleFromFlags(cmd), + authnfx.LicenceModuleFromFlags(cmd, ServiceName), workflow.NewModule(stack, temporalTaskQueue), triggers.NewModule(stack, temporalTaskQueue), fx.Provide(func() *bunconnect.ConnectionOptions { diff --git a/cmd/serve.go b/cmd/serve.go index 6339f47..54e8acb 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -3,16 +3,18 @@ package cmd import ( "context" - "github.com/formancehq/go-libs/v3/auth" - "github.com/formancehq/go-libs/v3/aws/iam" - "github.com/formancehq/go-libs/v3/bun/bunconnect" - "github.com/formancehq/go-libs/v3/health" - "github.com/formancehq/go-libs/v3/httpserver" - "github.com/formancehq/go-libs/v3/licence" - "github.com/formancehq/go-libs/v3/otlp/otlpmetrics" - "github.com/formancehq/go-libs/v3/publish" - "github.com/formancehq/go-libs/v3/service" - "github.com/formancehq/go-libs/v3/temporal" + auth "github.com/formancehq/go-libs/v5/pkg/authn/jwt" + "github.com/formancehq/go-libs/v5/pkg/authn/licence" + "github.com/formancehq/go-libs/v5/pkg/cloud/aws/iam" + "github.com/formancehq/go-libs/v5/pkg/fx/servicefx" + "github.com/formancehq/go-libs/v5/pkg/fx/transportfx" + "github.com/formancehq/go-libs/v5/pkg/messaging/publish" + otlpmetrics "github.com/formancehq/go-libs/v5/pkg/observe/metrics" + "github.com/formancehq/go-libs/v5/pkg/service" + "github.com/formancehq/go-libs/v5/pkg/service/health" + bunconnect "github.com/formancehq/go-libs/v5/pkg/storage/bun/connect" + "github.com/formancehq/go-libs/v5/pkg/transport/httpserver" + "github.com/formancehq/go-libs/v5/pkg/workflow/temporal" "github.com/formancehq/orchestration/internal/api" v1 "github.com/formancehq/orchestration/internal/api/v1" v2 "github.com/formancehq/orchestration/internal/api/v2" @@ -25,8 +27,8 @@ import ( func healthCheckModule() fx.Option { return fx.Options( - health.Module(), - health.ProvideHealthCheck(func() health.NamedCheck { + servicefx.HealthModule(), + servicefx.ProvideHealthCheck(func() health.NamedCheck { return health.NewNamedCheck("default", health.CheckFn(func(ctx context.Context) error { return nil })) @@ -64,7 +66,7 @@ func newServeCommand() *cobra.Command { }), api.NewModule(service.IsDebug(cmd)), fx.Invoke(func(lc fx.Lifecycle, router *chi.Mux) { - lc.Append(httpserver.NewHook(router, httpserver.WithAddress(listen))) + lc.Append(transportfx.FXHook(httpserver.NewHook(router, httpserver.WithAddress(listen)))) }), } worker, _ := cmd.Flags().GetBool(workerFlag) diff --git a/cmd/worker.go b/cmd/worker.go index 150d3b7..e5db6c2 100644 --- a/cmd/worker.go +++ b/cmd/worker.go @@ -4,13 +4,13 @@ import ( "net/http" sdk "github.com/formancehq/formance-sdk-go/v3" - "github.com/formancehq/go-libs/v3/aws/iam" - "github.com/formancehq/go-libs/v3/bun/bunconnect" - "github.com/formancehq/go-libs/v3/licence" - "github.com/formancehq/go-libs/v3/otlp/otlpmetrics" - "github.com/formancehq/go-libs/v3/publish" - "github.com/formancehq/go-libs/v3/service" - "github.com/formancehq/go-libs/v3/temporal" + "github.com/formancehq/go-libs/v5/pkg/authn/licence" + "github.com/formancehq/go-libs/v5/pkg/cloud/aws/iam" + "github.com/formancehq/go-libs/v5/pkg/messaging/publish" + otlpmetrics "github.com/formancehq/go-libs/v5/pkg/observe/metrics" + "github.com/formancehq/go-libs/v5/pkg/service" + bunconnect "github.com/formancehq/go-libs/v5/pkg/storage/bun/connect" + "github.com/formancehq/go-libs/v5/pkg/workflow/temporal" "github.com/formancehq/orchestration/internal/temporalworker" "github.com/formancehq/orchestration/internal/triggers" "github.com/spf13/cobra" @@ -35,13 +35,13 @@ func workerOptions(cmd *cobra.Command) fx.Option { stack, _ := cmd.Flags().GetString(stackFlag) temporalTaskQueue, _ := cmd.Flags().GetString(temporal.TemporalTaskQueueFlag) - temporalMaxParallelActivities, _ := cmd.Flags().GetInt(temporal.TemporalMaxParallelActivitiesFlag) + temporalMaxParallelActivities, _ := cmd.Flags().GetFloat64(temporal.TemporalMaxParallelActivitiesFlag) topics, _ := cmd.Flags().GetStringSlice(topicsFlag) return fx.Options( stackClientModule(cmd), temporalworker.NewWorkerModule(temporalTaskQueue, worker.Options{ - TaskQueueActivitiesPerSecond: float64(temporalMaxParallelActivities), + TaskQueueActivitiesPerSecond: temporalMaxParallelActivities, }), triggers.NewListenerModule( stack, diff --git a/go.mod b/go.mod index 51b62cd..f1f29e8 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,6 @@ require ( github.com/ThreeDotsLabs/watermill v1.5.1 github.com/expr-lang/expr v1.17.7 github.com/formancehq/formance-sdk-go/v3 v3.2.0 - github.com/formancehq/go-libs/v3 v3.3.0 github.com/formancehq/go-libs/v5 v5.7.0 github.com/go-chi/chi/v5 v5.2.5 github.com/go-playground/validator/v10 v10.24.0 @@ -42,6 +41,7 @@ require ( github.com/ajg/form v1.7.1 // indirect github.com/aws/aws-msk-iam-sasl-signer-go v1.0.4 // indirect github.com/aws/aws-sdk-go-v2 v1.41.5 // indirect + github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect github.com/aws/aws-sdk-go-v2/config v1.32.12 // indirect github.com/aws/aws-sdk-go-v2/credentials v1.19.12 // indirect github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.20 // indirect @@ -49,8 +49,12 @@ require ( github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.21 // indirect github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 // indirect github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 // indirect + github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3 // indirect github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 // indirect github.com/aws/aws-sdk-go-v2/service/sns v1.39.14 // indirect github.com/aws/aws-sdk-go-v2/service/sqs v1.42.24 // indirect @@ -67,7 +71,6 @@ require ( github.com/containerd/errdefs v1.0.0 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect - github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect github.com/distribution/reference v0.6.0 // indirect github.com/dnwe/otelsarama v0.0.0-20240308230250-9388d9d40bc0 // indirect github.com/docker/cli v29.3.0+incompatible // indirect @@ -79,7 +82,6 @@ require ( github.com/ebitengine/purego v0.10.0 // indirect github.com/ericlagergren/decimal v0.0.0-20240411145413-00de7ca16731 // indirect github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect - github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/gabriel-vasile/mimetype v1.4.8 // indirect github.com/getkin/kin-openapi v0.134.0 // indirect @@ -96,7 +98,6 @@ require ( github.com/go-sql-driver/mysql v1.9.3 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/go-viper/mapstructure/v2 v2.5.0 // indirect - github.com/goccy/go-json v0.10.4 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v5 v5.3.1 // indirect github.com/golang/mock v1.7.0-rc.1 // indirect @@ -104,13 +105,11 @@ require ( github.com/google/pprof v0.0.0-20260302011040-a15ffb7f9dcc // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/gorilla/mux v1.8.1 // indirect - github.com/gorilla/schema v1.4.1 // indirect github.com/gorilla/securecookie v1.1.2 // indirect github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.3 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect - github.com/hashicorp/go-hclog v1.6.3 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-retryablehttp v0.7.8 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect @@ -131,17 +130,9 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/klauspost/compress v1.18.4 // indirect github.com/leodido/go-urn v1.4.0 // indirect - github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect - github.com/lestrrat-go/blackmagic v1.0.2 // indirect - github.com/lestrrat-go/httpcc v1.0.1 // indirect - github.com/lestrrat-go/iter v1.0.2 // indirect - github.com/lestrrat-go/jwx v1.2.31 // indirect - github.com/lestrrat-go/option v1.0.1 // indirect github.com/lithammer/shortuuid/v3 v3.0.7 // indirect github.com/lufia/plan9stats v0.0.0-20260216142805-b3301c5f2a88 // indirect github.com/mailru/easyjson v0.9.2 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/moby/api v1.54.0 // indirect github.com/moby/moby/client v0.3.0 // indirect @@ -149,7 +140,6 @@ require ( github.com/moby/term v0.5.2 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/muhlemmer/gu v0.3.1 // indirect - github.com/muhlemmer/httpforwarded v0.1.0 // indirect github.com/nats-io/nats.go v1.49.0 // indirect github.com/nats-io/nkeys v0.4.15 // indirect github.com/nats-io/nuid v1.0.1 // indirect @@ -171,7 +161,6 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect github.com/riandyrn/otelchi v0.12.2 // indirect github.com/robfig/cron v1.2.0 // indirect - github.com/rs/cors v1.11.1 // indirect github.com/shirou/gopsutil/v4 v4.26.2 // indirect github.com/sirupsen/logrus v1.9.4 // indirect github.com/stretchr/objx v0.5.3 // indirect @@ -195,7 +184,6 @@ require ( github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xo/dburl v0.24.2 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect - github.com/zitadel/oidc/v2 v2.12.2 // indirect github.com/zitadel/oidc/v3 v3.45.3 // indirect github.com/zitadel/schema v1.3.2 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect @@ -232,5 +220,4 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20260401024825-9d38bb4040a9 // indirect google.golang.org/grpc v1.80.0 // indirect google.golang.org/protobuf v1.36.11 // indirect - gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect ) diff --git a/go.sum b/go.sum index ae9be3a..d380f7f 100644 --- a/go.sum +++ b/go.sum @@ -31,6 +31,8 @@ github.com/aws/aws-msk-iam-sasl-signer-go v1.0.4 h1:2jAwFwA0Xgcx94dUId+K24yFabsK github.com/aws/aws-msk-iam-sasl-signer-go v1.0.4/go.mod h1:MVYeeOhILFFemC/XlYTClvBjYZrg/EPd3ts885KrNTI= github.com/aws/aws-sdk-go-v2 v1.41.5 h1:dj5kopbwUsVUVFgO4Fi5BIT3t4WyqIDjGKCangnV/yY= github.com/aws/aws-sdk-go-v2 v1.41.5/go.mod h1:mwsPRE8ceUUpiTgF7QmQIJ7lgsKUPQOUl3o72QBrE1o= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o= +github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI= github.com/aws/aws-sdk-go-v2/config v1.32.12 h1:O3csC7HUGn2895eNrLytOJQdoL2xyJy0iYXhoZ1OmP0= github.com/aws/aws-sdk-go-v2/config v1.32.12/go.mod h1:96zTvoOFR4FURjI+/5wY1vc1ABceROO4lWgWJuxgy0g= github.com/aws/aws-sdk-go-v2/credentials v1.19.12 h1:oqtA6v+y5fZg//tcTWahyN9PEn5eDU/Wpvc2+kJ4aY8= @@ -45,10 +47,18 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21 h1:PEgGVtPoB6NTpPrBgq github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.21/go.mod h1:p+hz+PRAYlY3zcpJhPwXlLC4C+kqn70WIHwnzAfs6ps= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6 h1:qYQ4pzQ2Oz6WpQ8T3HvGHnZydA72MnLuFK9tJwmrbHw= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.6/go.mod h1:O3h0IK87yXci+kg6flUKzJnWeziQUKciKrLjcatSNcY= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22 h1:rWyie/PxDRIdhNf4DzRk0lvjVOqFJuNnO8WwaIRVxzQ= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.22/go.mod h1:zd/JsJ4P7oGfUhXn1VyLqaRZwPmZwg44Jf2dS84Dm3Y= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7 h1:5EniKhLZe4xzL7a+fU3C2tfUN4nWIqlLesfrjkuPFTY= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.7/go.mod h1:x0nZssQ3qZSnIcePWLvcoFisRXJzcTVvYpAAdYX8+GI= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13 h1:JRaIgADQS/U6uXDqlPiefP32yXTda7Kqfx+LgspooZM= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.13/go.mod h1:CEuVn5WqOMilYl+tbccq8+N2ieCy0gVn3OtRb0vBNNM= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21 h1:c31//R3xgIJMSC8S6hEVq+38DcvUlgFY0FM6mSI5oto= github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.21/go.mod h1:r6+pf23ouCB718FUxaqzZdbpYFyDtehyZcmP5KL9FkA= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21 h1:ZlvrNcHSFFWURB8avufQq9gFsheUgjVD9536obIknfM= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.21/go.mod h1:cv3TNhVrssKR0O/xxLJVRfd2oazSnZnkUeTf6ctUwfQ= +github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3 h1:HwxWTbTrIHm5qY+CAEur0s/figc3qwvLWsNkF4RPToo= +github.com/aws/aws-sdk-go-v2/service/s3 v1.97.3/go.mod h1:uoA43SdFwacedBfSgfFSjjCvYe8aYBS7EnU5GZ/YKMM= github.com/aws/aws-sdk-go-v2/service/signin v1.0.8 h1:0GFOLzEbOyZABS3PhYfBIx2rNBACYcKty+XGkTgw1ow= github.com/aws/aws-sdk-go-v2/service/signin v1.0.8/go.mod h1:LXypKvk85AROkKhOG6/YEcHFPoX+prKTowKnVdcaIxE= github.com/aws/aws-sdk-go-v2/service/sns v1.39.14 h1:p8WdWDh5AwSZdp19Haa3XMyPCICi9Z375a/Nu3IIEZY= @@ -86,8 +96,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc= -github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/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/dnwe/otelsarama v0.0.0-20240308230250-9388d9d40bc0 h1:R2zQhFwSCyyd7L43igYjDrH0wkC/i+QBPELuY0HOu84= @@ -112,15 +120,12 @@ github.com/expr-lang/expr v1.17.7 h1:Q0xY/e/2aCIp8g9s/LGvMDCC5PxYlvHgDZRQ4y16JX8 github.com/expr-lang/expr v1.17.7/go.mod h1:8/vRC7+7HBzESEqt5kKpYXxrxkr31SaO8r40VO/1IT4= github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw= github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA= -github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/formancehq/formance-sdk-go/v3 v3.2.0 h1:3zxYSu71jjCj5XMBvT6bTm2HlbZWvm3txYcuONJUbWw= github.com/formancehq/formance-sdk-go/v3 v3.2.0/go.mod h1:XivkqQzjOtR3W7hqIFYcUN11UIf+X8/V1yoPPnGBQVU= -github.com/formancehq/go-libs/v3 v3.3.0 h1:Qs6oPRNHJbR4xu3Lzl2zGAiQD94XLpabAFYPq3YBqK0= -github.com/formancehq/go-libs/v3 v3.3.0/go.mod h1:kr5pgap99LPdSVcYWgI+mCN51wr5D+YxEnt9A6JUiFU= github.com/formancehq/go-libs/v5 v5.7.0 h1:2Z2S3vtOJr45tKpofhPqd0qKrPr6KB/LZZ+EfL1PARw= github.com/formancehq/go-libs/v5 v5.7.0/go.mod h1:+jfCYWJ4Z10NGbhmbfon0hGoLe5pysbVQgePrg8M8W4= github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= @@ -171,8 +176,6 @@ github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro= github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= -github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= -github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= @@ -200,8 +203,6 @@ 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/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E= -github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= @@ -254,8 +255,6 @@ github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh6 github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs= github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY= github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc= -github.com/jeremija/gosubmit v0.2.8 h1:mmSITBz9JxVtu8eqbN+zmmwX7Ij2RidQxhcwRVI4wqA= -github.com/jeremija/gosubmit v0.2.8/go.mod h1:Ui+HS073lCFREXBbdfrJzMB57OI/bdxTiLtrDHHhFPI= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= @@ -272,19 +271,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/lestrrat-go/backoff/v2 v2.0.8 h1:oNb5E5isby2kiro9AgdHLv5N5tint1AnDVVf2E2un5A= -github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y= -github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k= -github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= -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/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI= -github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4= -github.com/lestrrat-go/jwx v1.2.31 h1:/OM9oNl/fzyldpv5HKZ9m7bTywa7COUfg8gujd9nJ54= -github.com/lestrrat-go/jwx v1.2.31/go.mod h1:eQJKoRwWcLg4PfD5CFA5gIZGxhPgoPYq9pZISdxLf0c= -github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= -github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= -github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lithammer/shortuuid/v3 v3.0.7 h1:trX0KTHy4Pbwo/6ia8fscyHoGA+mf1jWbPJVuvyJQQ8= @@ -295,12 +281,8 @@ github.com/mailru/easyjson v0.9.2 h1:dX8U45hQsZpxd80nLvDGihsQ/OxlvTkVUXH2r/8cb2M github.com/mailru/easyjson v0.9.2/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= -github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= -github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= 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.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 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/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= @@ -321,8 +303,6 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9 github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= github.com/muhlemmer/gu v0.3.1 h1:7EAqmFrW7n3hETvuAdmFmn4hS8W+z3LgKtrnow+YzNM= github.com/muhlemmer/gu v0.3.1/go.mod h1:YHtHR+gxM+bKEIIs7Hmi9sPT3ZDUvTN/i88wQpZkrdM= -github.com/muhlemmer/httpforwarded v0.1.0 h1:x4DLrzXdliq8mprgUMR0olDvHGkou5BJsK/vWUetyzY= -github.com/muhlemmer/httpforwarded v0.1.0/go.mod h1:yo9czKedo2pdZhoXe+yDkGVbU0TJ0q9oQ90BVoDEtw0= github.com/nats-io/jwt/v2 v2.8.1 h1:V0xpGuD/N8Mi+fQNDynXohVvp7ZztevW5io8CUWlPmU= github.com/nats-io/jwt/v2 v2.8.1/go.mod h1:nWnOEEiVMiKHQpnAy4eXlizVEtSfzacZ1Q43LIRavZg= github.com/nats-io/nats-server/v2 v2.12.6 h1:Egbx9Vl7Ch8wTtpXPGqbehkZ+IncKqShUxvrt1+Enc8= @@ -374,8 +354,6 @@ github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= 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/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= -github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shirou/gopsutil/v4 v4.26.2 h1:X8i6sicvUFih4BmYIGT1m2wwgw2VG9YgrDTi7cIRGUI= github.com/shirou/gopsutil/v4 v4.26.2/go.mod h1:LZ6ewCSkBqUpvSOf+LsTGnRinC6iaNUNMGBtDkJBaLQ= @@ -393,10 +371,8 @@ github.com/stretchr/objx v0.5.3 h1:jmXUvGomnU1o3W/V5h2VEradbpJDwGrzugQQvL0POH4= github.com/stretchr/objx v0.5.3/go.mod h1:rDQraq+vQZU7Fde9LOZLr8Tax6zZvy4kuNKF+QYS+U0= 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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 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.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= @@ -460,8 +436,6 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 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= -github.com/zitadel/oidc/v2 v2.12.2 h1:3kpckg4rurgw7w7aLJrq7yvRxb2pkNOtD08RH42vPEs= -github.com/zitadel/oidc/v2 v2.12.2/go.mod h1:vhP26g1g4YVntcTi0amMYW3tJuid70nxqxf+kb6XKgg= github.com/zitadel/oidc/v3 v3.45.3 h1:iaicqH5M7L5a973DTaG9UVSE14Z6Nj6hN41pp7kYBIw= github.com/zitadel/oidc/v3 v3.45.3/go.mod h1:yerW4/1YA5rUgjSjHsJ4HRnMbaKsyeIJkzyQrwDQ4t8= github.com/zitadel/schema v1.3.2 h1:gfJvt7dOMfTmxzhscZ9KkapKo3Nei3B6cAxjav+lyjI= @@ -561,23 +535,17 @@ golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= 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-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/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-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 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-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.45.0 h1:dO4czNzziLiiXplLQgBCEpCvXQ3dnkn0SdaZSYdQ+FY= golang.org/x/sys v0.45.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -618,8 +586,6 @@ google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/go-jose/go-jose.v2 v2.6.3 h1:nt80fvSDlhKWQgSWyHyy5CfmlQr+asih51R8PTWNKKs= -gopkg.in/go-jose/go-jose.v2 v2.6.3/go.mod h1:zzZDPkNNw/c9IE7Z9jr11mBZQhKQTMzoEEIoEdZlFBI= gopkg.in/yaml.v2 v2.2.2/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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= diff --git a/internal/api/backend.go b/internal/api/backend.go index 2fb14c6..dff2277 100644 --- a/internal/api/backend.go +++ b/internal/api/backend.go @@ -3,7 +3,7 @@ package api import ( "context" - "github.com/formancehq/go-libs/v3/bun/bunpaginate" + bunpaginate "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" "github.com/formancehq/orchestration/internal/triggers" "github.com/formancehq/orchestration/internal/workflow" diff --git a/internal/api/backend_generated.go b/internal/api/backend_generated.go index 73c8685..ff37c87 100644 --- a/internal/api/backend_generated.go +++ b/internal/api/backend_generated.go @@ -13,7 +13,7 @@ import ( context "context" reflect "reflect" - bunpaginate "github.com/formancehq/go-libs/v3/bun/bunpaginate" + paginate "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" triggers "github.com/formancehq/orchestration/internal/triggers" workflow "github.com/formancehq/orchestration/internal/workflow" gomock "go.uber.org/mock/gomock" @@ -146,10 +146,10 @@ func (mr *MockBackendMockRecorder) GetTrigger(ctx, triggerID any) *gomock.Call { } // ListInstances mocks base method. -func (m *MockBackend) ListInstances(ctx context.Context, pagination workflow.ListInstancesQuery) (*bunpaginate.Cursor[workflow.Instance], error) { +func (m *MockBackend) ListInstances(ctx context.Context, pagination workflow.ListInstancesQuery) (*paginate.Cursor[workflow.Instance], error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ListInstances", ctx, pagination) - ret0, _ := ret[0].(*bunpaginate.Cursor[workflow.Instance]) + ret0, _ := ret[0].(*paginate.Cursor[workflow.Instance]) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -161,10 +161,10 @@ func (mr *MockBackendMockRecorder) ListInstances(ctx, pagination any) *gomock.Ca } // ListTriggers mocks base method. -func (m *MockBackend) ListTriggers(ctx context.Context, query triggers.ListTriggersQuery) (*bunpaginate.Cursor[triggers.Trigger], error) { +func (m *MockBackend) ListTriggers(ctx context.Context, query triggers.ListTriggersQuery) (*paginate.Cursor[triggers.Trigger], error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ListTriggers", ctx, query) - ret0, _ := ret[0].(*bunpaginate.Cursor[triggers.Trigger]) + ret0, _ := ret[0].(*paginate.Cursor[triggers.Trigger]) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -176,10 +176,10 @@ func (mr *MockBackendMockRecorder) ListTriggers(ctx, query any) *gomock.Call { } // ListTriggersOccurrences mocks base method. -func (m *MockBackend) ListTriggersOccurrences(ctx context.Context, query triggers.ListTriggersOccurrencesQuery) (*bunpaginate.Cursor[triggers.Occurrence], error) { +func (m *MockBackend) ListTriggersOccurrences(ctx context.Context, query triggers.ListTriggersOccurrencesQuery) (*paginate.Cursor[triggers.Occurrence], error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ListTriggersOccurrences", ctx, query) - ret0, _ := ret[0].(*bunpaginate.Cursor[triggers.Occurrence]) + ret0, _ := ret[0].(*paginate.Cursor[triggers.Occurrence]) ret1, _ := ret[1].(error) return ret0, ret1 } @@ -191,10 +191,10 @@ func (mr *MockBackendMockRecorder) ListTriggersOccurrences(ctx, query any) *gomo } // ListWorkflows mocks base method. -func (m *MockBackend) ListWorkflows(ctx context.Context, query bunpaginate.OffsetPaginatedQuery[any]) (*bunpaginate.Cursor[workflow.Workflow], error) { +func (m *MockBackend) ListWorkflows(ctx context.Context, query paginate.OffsetPaginatedQuery[any]) (*paginate.Cursor[workflow.Workflow], error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ListWorkflows", ctx, query) - ret0, _ := ret[0].(*bunpaginate.Cursor[workflow.Workflow]) + ret0, _ := ret[0].(*paginate.Cursor[workflow.Workflow]) ret1, _ := ret[1].(error) return ret0, ret1 } diff --git a/internal/api/handler_info.go b/internal/api/handler_info.go index 983ca3a..1dfed4a 100644 --- a/internal/api/handler_info.go +++ b/internal/api/handler_info.go @@ -3,7 +3,7 @@ package api import ( "net/http" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" ) type ServiceInfo struct { diff --git a/internal/api/module.go b/internal/api/module.go index a0429ec..41a5e45 100644 --- a/internal/api/module.go +++ b/internal/api/module.go @@ -2,8 +2,8 @@ package api import ( "github.com/ThreeDotsLabs/watermill/message" - "github.com/formancehq/go-libs/v3/auth" - "github.com/formancehq/go-libs/v3/health" + auth "github.com/formancehq/go-libs/v5/pkg/authn/jwt" + "github.com/formancehq/go-libs/v5/pkg/service/health" "github.com/go-chi/chi/v5" "go.uber.org/fx" ) diff --git a/internal/api/module_test.go b/internal/api/module_test.go index c71fcc1..5e467f0 100644 --- a/internal/api/module_test.go +++ b/internal/api/module_test.go @@ -8,12 +8,13 @@ import ( "github.com/ThreeDotsLabs/watermill/message" "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/bun/bunpaginate" + sharedapi "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" - "github.com/formancehq/go-libs/v3/auth" + auth "github.com/formancehq/go-libs/v5/pkg/authn/jwt" - "github.com/formancehq/go-libs/v3/health" + "github.com/formancehq/go-libs/v5/pkg/fx/authnfx" "github.com/formancehq/go-libs/v5/pkg/messaging/publish" + "github.com/formancehq/go-libs/v5/pkg/service/health" "github.com/formancehq/orchestration/internal/api" v1 "github.com/formancehq/orchestration/internal/api/v1" v2 "github.com/formancehq/orchestration/internal/api/v2" @@ -31,7 +32,7 @@ func TestModule(t *testing.T) { var mux *chi.Mux app := fxtest.New(t, - auth.Module(auth.ModuleConfig{Enabled: false}), + authnfx.JWTModule(auth.Config{Enabled: false}), fx.Supply(&health.HealthController{}), fx.Supply(api.ServiceInfo{}), fx.Provide(func() message.Publisher { return publish.InMemory() }), diff --git a/internal/api/router.go b/internal/api/router.go index 8868db5..5821f9c 100644 --- a/internal/api/router.go +++ b/internal/api/router.go @@ -6,9 +6,9 @@ import ( "sort" "github.com/ThreeDotsLabs/watermill/message" - "github.com/formancehq/go-libs/v3/auth" - "github.com/formancehq/go-libs/v3/health" "github.com/formancehq/go-libs/v5/pkg/audit/httpaudit" + auth "github.com/formancehq/go-libs/v5/pkg/authn/jwt" + "github.com/formancehq/go-libs/v5/pkg/service/health" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" ) diff --git a/internal/api/v1/handler_abort_workflow_instance.go b/internal/api/v1/handler_abort_workflow_instance.go index ea151fe..f5bc524 100644 --- a/internal/api/v1/handler_abort_workflow_instance.go +++ b/internal/api/v1/handler_abort_workflow_instance.go @@ -5,7 +5,7 @@ import ( api2 "github.com/formancehq/orchestration/internal/api" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" ) func abortWorkflowInstance(backend api2.Backend) http.HandlerFunc { diff --git a/internal/api/v1/handler_create_trigger.go b/internal/api/v1/handler_create_trigger.go index 359f93a..4985d9b 100644 --- a/internal/api/v1/handler_create_trigger.go +++ b/internal/api/v1/handler_create_trigger.go @@ -6,7 +6,7 @@ import ( "github.com/formancehq/orchestration/internal/api" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/triggers" "github.com/pkg/errors" ) diff --git a/internal/api/v1/handler_create_workflow.go b/internal/api/v1/handler_create_workflow.go index 926f637..b72eb3b 100644 --- a/internal/api/v1/handler_create_workflow.go +++ b/internal/api/v1/handler_create_workflow.go @@ -6,7 +6,7 @@ import ( "gopkg.in/yaml.v3" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" api2 "github.com/formancehq/orchestration/internal/api" "github.com/formancehq/orchestration/internal/workflow" "github.com/pkg/errors" diff --git a/internal/api/v1/handler_delete_trigger.go b/internal/api/v1/handler_delete_trigger.go index a10787d..be34b1d 100644 --- a/internal/api/v1/handler_delete_trigger.go +++ b/internal/api/v1/handler_delete_trigger.go @@ -6,7 +6,7 @@ import ( "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/api" "github.com/pkg/errors" ) diff --git a/internal/api/v1/handler_delete_workflow.go b/internal/api/v1/handler_delete_workflow.go index a187a47..34a6afc 100644 --- a/internal/api/v1/handler_delete_workflow.go +++ b/internal/api/v1/handler_delete_workflow.go @@ -6,7 +6,7 @@ import ( "github.com/go-playground/validator/v10" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" api2 "github.com/formancehq/orchestration/internal/api" "github.com/formancehq/orchestration/internal/workflow" ) diff --git a/internal/api/v1/handler_delete_workflow_test.go b/internal/api/v1/handler_delete_workflow_test.go index 6a78b98..3a6fb8b 100644 --- a/internal/api/v1/handler_delete_workflow_test.go +++ b/internal/api/v1/handler_delete_workflow_test.go @@ -9,7 +9,7 @@ import ( "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/testing/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/testing/api" "github.com/formancehq/orchestration/internal/api" "github.com/formancehq/orchestration/internal/workflow" diff --git a/internal/api/v1/handler_get_trigger.go b/internal/api/v1/handler_get_trigger.go index 1bdb81e..7bb2a03 100644 --- a/internal/api/v1/handler_get_trigger.go +++ b/internal/api/v1/handler_get_trigger.go @@ -6,7 +6,7 @@ import ( "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/api" "github.com/pkg/errors" ) diff --git a/internal/api/v1/handler_list_instances.go b/internal/api/v1/handler_list_instances.go index 0aa5a68..e2a7ea0 100644 --- a/internal/api/v1/handler_list_instances.go +++ b/internal/api/v1/handler_list_instances.go @@ -7,7 +7,7 @@ import ( api "github.com/formancehq/orchestration/internal/api" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" ) func listInstances(backend api.Backend) http.HandlerFunc { diff --git a/internal/api/v1/handler_list_instances_test.go b/internal/api/v1/handler_list_instances_test.go index 4421d12..1447306 100644 --- a/internal/api/v1/handler_list_instances_test.go +++ b/internal/api/v1/handler_list_instances_test.go @@ -7,11 +7,11 @@ import ( "testing" "time" - "github.com/formancehq/go-libs/v3/logging" + "github.com/formancehq/go-libs/v5/pkg/observe/log" "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/testing/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/testing/api" "github.com/google/uuid" diff --git a/internal/api/v1/handler_list_triggers.go b/internal/api/v1/handler_list_triggers.go index cba54a6..c948100 100644 --- a/internal/api/v1/handler_list_triggers.go +++ b/internal/api/v1/handler_list_triggers.go @@ -3,12 +3,12 @@ package v1 import ( "net/http" - "github.com/formancehq/go-libs/v3/bun/bunpaginate" + bunpaginate "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" "github.com/formancehq/orchestration/internal/triggers" "github.com/formancehq/orchestration/internal/api" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" ) func listTriggers(backend api.Backend) func(writer http.ResponseWriter, request *http.Request) { diff --git a/internal/api/v1/handler_list_triggers_occurrences.go b/internal/api/v1/handler_list_triggers_occurrences.go index beda917..84cf312 100644 --- a/internal/api/v1/handler_list_triggers_occurrences.go +++ b/internal/api/v1/handler_list_triggers_occurrences.go @@ -5,7 +5,7 @@ import ( "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/api" "github.com/formancehq/orchestration/internal/triggers" ) diff --git a/internal/api/v1/handler_list_workflows.go b/internal/api/v1/handler_list_workflows.go index fd72af0..b7c6aa4 100644 --- a/internal/api/v1/handler_list_workflows.go +++ b/internal/api/v1/handler_list_workflows.go @@ -3,11 +3,11 @@ package v1 import ( "net/http" - "github.com/formancehq/go-libs/v3/bun/bunpaginate" + bunpaginate "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" api2 "github.com/formancehq/orchestration/internal/api" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" ) func listWorkflows(backend api2.Backend) http.HandlerFunc { diff --git a/internal/api/v1/handler_post_event.go b/internal/api/v1/handler_post_event.go index 5d5ce64..9349666 100644 --- a/internal/api/v1/handler_post_event.go +++ b/internal/api/v1/handler_post_event.go @@ -6,7 +6,7 @@ import ( api2 "github.com/formancehq/orchestration/internal/api" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/workflow" ) diff --git a/internal/api/v1/handler_read_instance.go b/internal/api/v1/handler_read_instance.go index d0b94a8..4e27292 100644 --- a/internal/api/v1/handler_read_instance.go +++ b/internal/api/v1/handler_read_instance.go @@ -5,7 +5,7 @@ import ( api2 "github.com/formancehq/orchestration/internal/api" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" ) func readInstance(backend api2.Backend) http.HandlerFunc { diff --git a/internal/api/v1/handler_read_instance_history.go b/internal/api/v1/handler_read_instance_history.go index 4fc6de9..1617fc9 100644 --- a/internal/api/v1/handler_read_instance_history.go +++ b/internal/api/v1/handler_read_instance_history.go @@ -5,7 +5,7 @@ import ( api2 "github.com/formancehq/orchestration/internal/api" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" ) func readInstanceHistory(backend api2.Backend) http.HandlerFunc { diff --git a/internal/api/v1/handler_read_instance_test.go b/internal/api/v1/handler_read_instance_test.go index 00f88ca..6e751a6 100644 --- a/internal/api/v1/handler_read_instance_test.go +++ b/internal/api/v1/handler_read_instance_test.go @@ -10,9 +10,9 @@ import ( "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/testing/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/testing/api" - "github.com/formancehq/go-libs/v3/logging" + "github.com/formancehq/go-libs/v5/pkg/observe/log" "github.com/google/uuid" "github.com/formancehq/orchestration/internal/api" diff --git a/internal/api/v1/handler_read_stage_history.go b/internal/api/v1/handler_read_stage_history.go index 0865357..6f6906a 100644 --- a/internal/api/v1/handler_read_stage_history.go +++ b/internal/api/v1/handler_read_stage_history.go @@ -6,7 +6,7 @@ import ( "github.com/go-chi/chi/v5" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" api2 "github.com/formancehq/orchestration/internal/api" "github.com/formancehq/orchestration/internal/workflow" "github.com/pkg/errors" diff --git a/internal/api/v1/handler_read_workflow.go b/internal/api/v1/handler_read_workflow.go index e00432c..0af13a8 100644 --- a/internal/api/v1/handler_read_workflow.go +++ b/internal/api/v1/handler_read_workflow.go @@ -5,7 +5,7 @@ import ( api2 "github.com/formancehq/orchestration/internal/api" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" ) func readWorkflow(backend api2.Backend) http.HandlerFunc { diff --git a/internal/api/v1/handler_run_workflow.go b/internal/api/v1/handler_run_workflow.go index a0ac1a2..10a71e8 100644 --- a/internal/api/v1/handler_run_workflow.go +++ b/internal/api/v1/handler_run_workflow.go @@ -7,7 +7,7 @@ import ( api2 "github.com/formancehq/orchestration/internal/api" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/workflow" ) diff --git a/internal/api/v1/handler_run_workflow_test.go b/internal/api/v1/handler_run_workflow_test.go index c89bd98..d220b9b 100644 --- a/internal/api/v1/handler_run_workflow_test.go +++ b/internal/api/v1/handler_run_workflow_test.go @@ -9,7 +9,7 @@ import ( "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/testing/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/testing/api" "github.com/formancehq/orchestration/internal/api" "github.com/formancehq/orchestration/internal/workflow" diff --git a/internal/api/v1/main_test.go b/internal/api/v1/main_test.go index 0853ede..eb8c5d5 100644 --- a/internal/api/v1/main_test.go +++ b/internal/api/v1/main_test.go @@ -6,15 +6,15 @@ import ( "net/http" "testing" - "github.com/formancehq/go-libs/v3/auth" - "github.com/formancehq/go-libs/v3/bun/bunconnect" - "github.com/formancehq/go-libs/v3/bun/bundebug" - "github.com/formancehq/go-libs/v3/logging" - "github.com/formancehq/go-libs/v3/publish" - "github.com/formancehq/go-libs/v3/temporal" - "github.com/formancehq/go-libs/v3/testing/docker" - "github.com/formancehq/go-libs/v3/testing/platform/pgtesting" - "github.com/formancehq/go-libs/v3/testing/utils" + auth "github.com/formancehq/go-libs/v5/pkg/authn/jwt" + "github.com/formancehq/go-libs/v5/pkg/messaging/publish" + "github.com/formancehq/go-libs/v5/pkg/observe/log" + bunconnect "github.com/formancehq/go-libs/v5/pkg/storage/bun/connect" + bundebug "github.com/formancehq/go-libs/v5/pkg/storage/bun/debug" + "github.com/formancehq/go-libs/v5/pkg/testing/docker" + "github.com/formancehq/go-libs/v5/pkg/testing/platform/pgtesting" + "github.com/formancehq/go-libs/v5/pkg/testing/utils" + "github.com/formancehq/go-libs/v5/pkg/workflow/temporal" "github.com/formancehq/orchestration/internal/api" "github.com/formancehq/orchestration/internal/storage" "github.com/formancehq/orchestration/internal/temporalworker" diff --git a/internal/api/v1/router.go b/internal/api/v1/router.go index e8f2f3d..f0cf564 100644 --- a/internal/api/v1/router.go +++ b/internal/api/v1/router.go @@ -5,9 +5,9 @@ import ( "github.com/go-chi/chi/v5" - "github.com/formancehq/go-libs/v3/service" + "github.com/formancehq/go-libs/v5/pkg/transport/httpserver" - "github.com/formancehq/go-libs/v3/auth" + auth "github.com/formancehq/go-libs/v5/pkg/authn/jwt" "github.com/formancehq/orchestration/internal/api" ) @@ -16,7 +16,7 @@ func newRouter(backend api.Backend, authenticator auth.Authenticator, debug bool r.Group(func(r chi.Router) { // Plug middleware to handle traces r.Use(auth.Middleware(authenticator)) - r.Use(service.OTLPMiddleware("orchestration", debug)) + r.Use(httpserver.OTLPMiddleware("orchestration", debug)) r.Route("/triggers", func(r chi.Router) { r.Get("/", listTriggers(backend)) r.Post("/", createTrigger(backend)) diff --git a/internal/api/v2/handler_abort_workflow_instance.go b/internal/api/v2/handler_abort_workflow_instance.go index 4d16f8e..05cb2e1 100644 --- a/internal/api/v2/handler_abort_workflow_instance.go +++ b/internal/api/v2/handler_abort_workflow_instance.go @@ -5,7 +5,7 @@ import ( api2 "github.com/formancehq/orchestration/internal/api" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" ) func abortWorkflowInstance(backend api2.Backend) http.HandlerFunc { diff --git a/internal/api/v2/handler_create_trigger.go b/internal/api/v2/handler_create_trigger.go index 8ca5c20..d774f83 100644 --- a/internal/api/v2/handler_create_trigger.go +++ b/internal/api/v2/handler_create_trigger.go @@ -6,7 +6,7 @@ import ( "github.com/formancehq/orchestration/internal/api" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/triggers" "github.com/pkg/errors" ) diff --git a/internal/api/v2/handler_create_workflow.go b/internal/api/v2/handler_create_workflow.go index 0fe7292..9cbbaec 100644 --- a/internal/api/v2/handler_create_workflow.go +++ b/internal/api/v2/handler_create_workflow.go @@ -6,7 +6,7 @@ import ( "gopkg.in/yaml.v3" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/api" "github.com/formancehq/orchestration/internal/workflow" "github.com/pkg/errors" diff --git a/internal/api/v2/handler_delete_trigger.go b/internal/api/v2/handler_delete_trigger.go index 40572f2..cce2673 100644 --- a/internal/api/v2/handler_delete_trigger.go +++ b/internal/api/v2/handler_delete_trigger.go @@ -6,7 +6,7 @@ import ( "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/api" "github.com/pkg/errors" ) diff --git a/internal/api/v2/handler_delete_workflow.go b/internal/api/v2/handler_delete_workflow.go index daf6d2f..5be4e0b 100644 --- a/internal/api/v2/handler_delete_workflow.go +++ b/internal/api/v2/handler_delete_workflow.go @@ -6,7 +6,7 @@ import ( "github.com/go-playground/validator/v10" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" api2 "github.com/formancehq/orchestration/internal/api" "github.com/formancehq/orchestration/internal/workflow" ) diff --git a/internal/api/v2/handler_delete_workflow_test.go b/internal/api/v2/handler_delete_workflow_test.go index 47e590f..ffa73f1 100644 --- a/internal/api/v2/handler_delete_workflow_test.go +++ b/internal/api/v2/handler_delete_workflow_test.go @@ -9,7 +9,7 @@ import ( "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/testing/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/testing/api" "github.com/formancehq/orchestration/internal/api" "github.com/formancehq/orchestration/internal/workflow" diff --git a/internal/api/v2/handler_get_trigger.go b/internal/api/v2/handler_get_trigger.go index c62651a..4dfcfa6 100644 --- a/internal/api/v2/handler_get_trigger.go +++ b/internal/api/v2/handler_get_trigger.go @@ -6,7 +6,7 @@ import ( "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/api" "github.com/pkg/errors" ) diff --git a/internal/api/v2/handler_list_instances.go b/internal/api/v2/handler_list_instances.go index 4cb5513..7586ab0 100644 --- a/internal/api/v2/handler_list_instances.go +++ b/internal/api/v2/handler_list_instances.go @@ -3,12 +3,12 @@ package v2 import ( "net/http" - "github.com/formancehq/go-libs/v3/bun/bunpaginate" + bunpaginate "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" "github.com/formancehq/orchestration/internal/workflow" api "github.com/formancehq/orchestration/internal/api" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" ) func listInstances(backend api.Backend) http.HandlerFunc { diff --git a/internal/api/v2/handler_list_instances_test.go b/internal/api/v2/handler_list_instances_test.go index 9915810..59cf6ab 100644 --- a/internal/api/v2/handler_list_instances_test.go +++ b/internal/api/v2/handler_list_instances_test.go @@ -10,9 +10,9 @@ import ( "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/testing/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/testing/api" - "github.com/formancehq/go-libs/v3/bun/bunpaginate" + bunpaginate "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" "github.com/google/uuid" diff --git a/internal/api/v2/handler_list_triggers.go b/internal/api/v2/handler_list_triggers.go index 78c240f..1b1607f 100644 --- a/internal/api/v2/handler_list_triggers.go +++ b/internal/api/v2/handler_list_triggers.go @@ -3,12 +3,12 @@ package v2 import ( "net/http" - "github.com/formancehq/go-libs/v3/bun/bunpaginate" + bunpaginate "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" "github.com/formancehq/orchestration/internal/triggers" "github.com/formancehq/orchestration/internal/api" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" ) func listTriggers(backend api.Backend) func(writer http.ResponseWriter, request *http.Request) { diff --git a/internal/api/v2/handler_list_triggers_occurrences.go b/internal/api/v2/handler_list_triggers_occurrences.go index fc4e39c..e024d03 100644 --- a/internal/api/v2/handler_list_triggers_occurrences.go +++ b/internal/api/v2/handler_list_triggers_occurrences.go @@ -5,10 +5,10 @@ import ( "github.com/go-chi/chi/v5" - "github.com/formancehq/go-libs/v3/bun/bunpaginate" + bunpaginate "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" "github.com/formancehq/orchestration/internal/triggers" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/api" ) diff --git a/internal/api/v2/handler_list_workflows.go b/internal/api/v2/handler_list_workflows.go index e28e840..c302a7b 100644 --- a/internal/api/v2/handler_list_workflows.go +++ b/internal/api/v2/handler_list_workflows.go @@ -3,11 +3,11 @@ package v2 import ( "net/http" - "github.com/formancehq/go-libs/v3/bun/bunpaginate" + bunpaginate "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" "github.com/formancehq/orchestration/internal/api" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" ) func listWorkflows(backend api.Backend) http.HandlerFunc { diff --git a/internal/api/v2/handler_post_event.go b/internal/api/v2/handler_post_event.go index 2f6afea..d314f6b 100644 --- a/internal/api/v2/handler_post_event.go +++ b/internal/api/v2/handler_post_event.go @@ -6,7 +6,7 @@ import ( api2 "github.com/formancehq/orchestration/internal/api" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/workflow" ) diff --git a/internal/api/v2/handler_read_instance.go b/internal/api/v2/handler_read_instance.go index 2ac07d4..6fee757 100644 --- a/internal/api/v2/handler_read_instance.go +++ b/internal/api/v2/handler_read_instance.go @@ -5,7 +5,7 @@ import ( "github.com/formancehq/orchestration/internal/api" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" ) func readInstance(backend api.Backend) http.HandlerFunc { diff --git a/internal/api/v2/handler_read_instance_history.go b/internal/api/v2/handler_read_instance_history.go index 11a25be..2f9f2e0 100644 --- a/internal/api/v2/handler_read_instance_history.go +++ b/internal/api/v2/handler_read_instance_history.go @@ -5,7 +5,7 @@ import ( api2 "github.com/formancehq/orchestration/internal/api" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" ) func readInstanceHistory(backend api2.Backend) http.HandlerFunc { diff --git a/internal/api/v2/handler_read_instance_test.go b/internal/api/v2/handler_read_instance_test.go index a881b31..1edbe50 100644 --- a/internal/api/v2/handler_read_instance_test.go +++ b/internal/api/v2/handler_read_instance_test.go @@ -10,7 +10,7 @@ import ( "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/testing/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/testing/api" "github.com/formancehq/orchestration/internal/api" "github.com/formancehq/orchestration/internal/workflow" diff --git a/internal/api/v2/handler_read_stage_history.go b/internal/api/v2/handler_read_stage_history.go index 9244218..78ab12a 100644 --- a/internal/api/v2/handler_read_stage_history.go +++ b/internal/api/v2/handler_read_stage_history.go @@ -6,7 +6,7 @@ import ( "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/api" "github.com/formancehq/orchestration/internal/workflow" "github.com/pkg/errors" diff --git a/internal/api/v2/handler_read_workflow.go b/internal/api/v2/handler_read_workflow.go index 024e772..2d6ec38 100644 --- a/internal/api/v2/handler_read_workflow.go +++ b/internal/api/v2/handler_read_workflow.go @@ -5,7 +5,7 @@ import ( api2 "github.com/formancehq/orchestration/internal/api" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" ) func readWorkflow(backend api2.Backend) http.HandlerFunc { diff --git a/internal/api/v2/handler_run_workflow.go b/internal/api/v2/handler_run_workflow.go index 8bc56ab..801a5a3 100644 --- a/internal/api/v2/handler_run_workflow.go +++ b/internal/api/v2/handler_run_workflow.go @@ -7,7 +7,7 @@ import ( api2 "github.com/formancehq/orchestration/internal/api" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/workflow" ) diff --git a/internal/api/v2/handler_run_workflow_test.go b/internal/api/v2/handler_run_workflow_test.go index 9cbbc61..53eaa51 100644 --- a/internal/api/v2/handler_run_workflow_test.go +++ b/internal/api/v2/handler_run_workflow_test.go @@ -9,7 +9,7 @@ import ( "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/testing/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/testing/api" "github.com/formancehq/orchestration/internal/api" "github.com/formancehq/orchestration/internal/workflow" diff --git a/internal/api/v2/handler_test_trigger.go b/internal/api/v2/handler_test_trigger.go index 152537e..a4be567 100644 --- a/internal/api/v2/handler_test_trigger.go +++ b/internal/api/v2/handler_test_trigger.go @@ -6,7 +6,7 @@ import ( "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/api" ) diff --git a/internal/api/v2/handler_test_trigger_test.go b/internal/api/v2/handler_test_trigger_test.go index ed55f89..add8743 100644 --- a/internal/api/v2/handler_test_trigger_test.go +++ b/internal/api/v2/handler_test_trigger_test.go @@ -10,9 +10,9 @@ import ( "github.com/go-chi/chi/v5" - sharedapi "github.com/formancehq/go-libs/v3/testing/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/testing/api" - "github.com/formancehq/go-libs/v3/pointer" + "github.com/formancehq/go-libs/v5/pkg/types/pointer" "github.com/formancehq/orchestration/internal/triggers" "github.com/formancehq/orchestration/internal/api" diff --git a/internal/api/v2/main_test.go b/internal/api/v2/main_test.go index 7f2d2df..bd28b32 100644 --- a/internal/api/v2/main_test.go +++ b/internal/api/v2/main_test.go @@ -6,15 +6,15 @@ import ( "net/http" "testing" - "github.com/formancehq/go-libs/v3/auth" - "github.com/formancehq/go-libs/v3/bun/bunconnect" - "github.com/formancehq/go-libs/v3/bun/bundebug" - "github.com/formancehq/go-libs/v3/logging" - "github.com/formancehq/go-libs/v3/publish" - "github.com/formancehq/go-libs/v3/temporal" - "github.com/formancehq/go-libs/v3/testing/docker" - "github.com/formancehq/go-libs/v3/testing/platform/pgtesting" - "github.com/formancehq/go-libs/v3/testing/utils" + auth "github.com/formancehq/go-libs/v5/pkg/authn/jwt" + "github.com/formancehq/go-libs/v5/pkg/messaging/publish" + "github.com/formancehq/go-libs/v5/pkg/observe/log" + bunconnect "github.com/formancehq/go-libs/v5/pkg/storage/bun/connect" + bundebug "github.com/formancehq/go-libs/v5/pkg/storage/bun/debug" + "github.com/formancehq/go-libs/v5/pkg/testing/docker" + "github.com/formancehq/go-libs/v5/pkg/testing/platform/pgtesting" + "github.com/formancehq/go-libs/v5/pkg/testing/utils" + "github.com/formancehq/go-libs/v5/pkg/workflow/temporal" "github.com/formancehq/orchestration/internal/api" "github.com/formancehq/orchestration/internal/storage" "github.com/formancehq/orchestration/internal/temporalworker" diff --git a/internal/api/v2/router.go b/internal/api/v2/router.go index 1058a02..1126022 100644 --- a/internal/api/v2/router.go +++ b/internal/api/v2/router.go @@ -5,9 +5,9 @@ import ( "github.com/go-chi/chi/v5" - "github.com/formancehq/go-libs/v3/service" + "github.com/formancehq/go-libs/v5/pkg/transport/httpserver" - "github.com/formancehq/go-libs/v3/auth" + auth "github.com/formancehq/go-libs/v5/pkg/authn/jwt" "github.com/formancehq/orchestration/internal/api" ) @@ -16,7 +16,7 @@ func newRouter(backend api.Backend, authenticator auth.Authenticator, debug bool r.Group(func(r chi.Router) { // Plug middleware to handle traces r.Use(auth.Middleware(authenticator)) - r.Use(service.OTLPMiddleware("orchestration", debug)) + r.Use(httpserver.OTLPMiddleware("orchestration", debug)) r.Route("/triggers", func(r chi.Router) { r.Get("/", listTriggers(backend)) r.Post("/", createTrigger(backend)) diff --git a/internal/schema/map.go b/internal/schema/map.go index 8586a2f..ae2dc8d 100644 --- a/internal/schema/map.go +++ b/internal/schema/map.go @@ -8,7 +8,7 @@ import ( "strconv" "strings" - "github.com/formancehq/go-libs/v3/time" + "github.com/formancehq/go-libs/v5/pkg/types/time" "github.com/formancehq/orchestration/internal/workflow/stages" "github.com/pkg/errors" diff --git a/internal/storage/main_test.go b/internal/storage/main_test.go index 230d333..b612c31 100644 --- a/internal/storage/main_test.go +++ b/internal/storage/main_test.go @@ -3,11 +3,11 @@ package storage import ( "testing" - "github.com/formancehq/go-libs/v3/logging" - "github.com/formancehq/go-libs/v3/testing/docker" - "github.com/formancehq/go-libs/v3/testing/utils" + "github.com/formancehq/go-libs/v5/pkg/observe/log" + "github.com/formancehq/go-libs/v5/pkg/testing/docker" + "github.com/formancehq/go-libs/v5/pkg/testing/utils" - "github.com/formancehq/go-libs/v3/testing/platform/pgtesting" + "github.com/formancehq/go-libs/v5/pkg/testing/platform/pgtesting" ) var srv *pgtesting.PostgresServer diff --git a/internal/storage/migrations.go b/internal/storage/migrations.go index 33ff453..3e0131c 100644 --- a/internal/storage/migrations.go +++ b/internal/storage/migrations.go @@ -3,7 +3,7 @@ package storage import ( "context" - "github.com/formancehq/go-libs/v3/migrations" + "github.com/formancehq/go-libs/v5/pkg/storage/migrations" "github.com/uptrace/bun" ) diff --git a/internal/storage/migrations_test.go b/internal/storage/migrations_test.go index 5918cec..098b0c1 100644 --- a/internal/storage/migrations_test.go +++ b/internal/storage/migrations_test.go @@ -3,11 +3,11 @@ package storage import ( "testing" - "github.com/formancehq/go-libs/v3/bun/bundebug" + bundebug "github.com/formancehq/go-libs/v5/pkg/storage/bun/debug" "github.com/uptrace/bun" - "github.com/formancehq/go-libs/v3/bun/bunconnect" - "github.com/formancehq/go-libs/v3/logging" + "github.com/formancehq/go-libs/v5/pkg/observe/log" + bunconnect "github.com/formancehq/go-libs/v5/pkg/storage/bun/connect" "github.com/stretchr/testify/require" ) diff --git a/internal/temporalworker/module.go b/internal/temporalworker/module.go index d7e6bad..bacb42f 100644 --- a/internal/temporalworker/module.go +++ b/internal/temporalworker/module.go @@ -3,7 +3,7 @@ package temporalworker import ( "context" - "github.com/formancehq/go-libs/v3/logging" + "github.com/formancehq/go-libs/v5/pkg/observe/log" "go.temporal.io/api/enums/v1" "go.temporal.io/sdk/activity" "go.temporal.io/sdk/client" diff --git a/internal/triggers/activities.go b/internal/triggers/activities.go index d4eedd1..4a8e820 100644 --- a/internal/triggers/activities.go +++ b/internal/triggers/activities.go @@ -5,8 +5,8 @@ import ( "strings" "github.com/ThreeDotsLabs/watermill/message" - "github.com/formancehq/go-libs/v3/collectionutils" - "github.com/formancehq/go-libs/v3/pointer" + collectionutils "github.com/formancehq/go-libs/v5/pkg/types/collections" + "github.com/formancehq/go-libs/v5/pkg/types/pointer" "github.com/formancehq/orchestration/internal/temporalworker" "github.com/formancehq/orchestration/internal/tracer" "github.com/formancehq/orchestration/internal/workflow" diff --git a/internal/triggers/expression.go b/internal/triggers/expression.go index b9ccd85..5f7c13c 100644 --- a/internal/triggers/expression.go +++ b/internal/triggers/expression.go @@ -7,10 +7,10 @@ import ( "go.temporal.io/sdk/temporal" - "github.com/formancehq/go-libs/v3/collectionutils" + collectionutils "github.com/formancehq/go-libs/v5/pkg/types/collections" "github.com/expr-lang/expr" - "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/pkg/errors" ) diff --git a/internal/triggers/listener.go b/internal/triggers/listener.go index de0cc17..ffa265d 100644 --- a/internal/triggers/listener.go +++ b/internal/triggers/listener.go @@ -9,19 +9,19 @@ import ( "go.temporal.io/api/enums/v1" - "github.com/formancehq/go-libs/v3/collectionutils" + collectionutils "github.com/formancehq/go-libs/v5/pkg/types/collections" "github.com/formancehq/orchestration/internal/tracer" "github.com/formancehq/orchestration/internal/workflow" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" - "github.com/formancehq/go-libs/v3/pointer" + "github.com/formancehq/go-libs/v5/pkg/types/pointer" "go.temporal.io/api/serviceerror" - "github.com/formancehq/go-libs/v3/logging" + "github.com/formancehq/go-libs/v5/pkg/observe/log" "github.com/ThreeDotsLabs/watermill/message" - "github.com/formancehq/go-libs/v3/publish" + "github.com/formancehq/go-libs/v5/pkg/messaging/publish" "github.com/pkg/errors" "github.com/uptrace/bun" "go.temporal.io/sdk/client" diff --git a/internal/triggers/listener_test.go b/internal/triggers/listener_test.go index fb25dfd..5a7e959 100644 --- a/internal/triggers/listener_test.go +++ b/internal/triggers/listener_test.go @@ -4,11 +4,11 @@ import ( "testing" "time" - "github.com/formancehq/go-libs/v3/bun/bunconnect" - "github.com/formancehq/go-libs/v3/bun/bundebug" - "github.com/formancehq/go-libs/v3/logging" - "github.com/formancehq/go-libs/v3/pointer" - "github.com/formancehq/go-libs/v3/publish" + "github.com/formancehq/go-libs/v5/pkg/messaging/publish" + "github.com/formancehq/go-libs/v5/pkg/observe/log" + bunconnect "github.com/formancehq/go-libs/v5/pkg/storage/bun/connect" + bundebug "github.com/formancehq/go-libs/v5/pkg/storage/bun/debug" + "github.com/formancehq/go-libs/v5/pkg/types/pointer" "github.com/formancehq/orchestration/internal/storage" "github.com/formancehq/orchestration/internal/temporalworker" "github.com/formancehq/orchestration/internal/workflow" diff --git a/internal/triggers/main_test.go b/internal/triggers/main_test.go index 42cad95..ff0a2a5 100644 --- a/internal/triggers/main_test.go +++ b/internal/triggers/main_test.go @@ -3,14 +3,14 @@ package triggers import ( "testing" - "github.com/formancehq/go-libs/v3/testing/docker" - "github.com/formancehq/go-libs/v3/testing/utils" + "github.com/formancehq/go-libs/v5/pkg/testing/docker" + "github.com/formancehq/go-libs/v5/pkg/testing/utils" "github.com/stretchr/testify/require" - "github.com/formancehq/go-libs/v3/logging" + "github.com/formancehq/go-libs/v5/pkg/observe/log" "go.temporal.io/sdk/testsuite" - "github.com/formancehq/go-libs/v3/testing/platform/pgtesting" + "github.com/formancehq/go-libs/v5/pkg/testing/platform/pgtesting" ) var ( diff --git a/internal/triggers/manager.go b/internal/triggers/manager.go index 5d35766..2111367 100644 --- a/internal/triggers/manager.go +++ b/internal/triggers/manager.go @@ -5,7 +5,7 @@ import ( "database/sql" "time" - "github.com/formancehq/go-libs/v3/bun/bunpaginate" + bunpaginate "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" "github.com/formancehq/orchestration/internal/workflow" "github.com/pkg/errors" diff --git a/internal/triggers/module.go b/internal/triggers/module.go index e512770..02070f6 100644 --- a/internal/triggers/module.go +++ b/internal/triggers/module.go @@ -7,7 +7,7 @@ import ( "github.com/formancehq/orchestration/internal/temporalworker" "github.com/ThreeDotsLabs/watermill/message" - "github.com/formancehq/go-libs/v3/logging" + "github.com/formancehq/go-libs/v5/pkg/observe/log" "github.com/formancehq/orchestration/internal/workflow" "github.com/uptrace/bun" "go.temporal.io/sdk/client" diff --git a/internal/triggers/trigger.go b/internal/triggers/trigger.go index ad2860c..85a4dcf 100644 --- a/internal/triggers/trigger.go +++ b/internal/triggers/trigger.go @@ -6,7 +6,7 @@ import ( "github.com/formancehq/orchestration/internal/workflow" - "github.com/formancehq/go-libs/v3/publish" + "github.com/formancehq/go-libs/v5/pkg/messaging/publish" "github.com/expr-lang/expr" "github.com/google/uuid" diff --git a/internal/triggers/workflow_trigger.go b/internal/triggers/workflow_trigger.go index 16bbf2a..47543b9 100644 --- a/internal/triggers/workflow_trigger.go +++ b/internal/triggers/workflow_trigger.go @@ -3,8 +3,8 @@ package triggers import ( "time" - "github.com/formancehq/go-libs/v3/pointer" - "github.com/formancehq/go-libs/v3/publish" + "github.com/formancehq/go-libs/v5/pkg/messaging/publish" + "github.com/formancehq/go-libs/v5/pkg/types/pointer" "github.com/formancehq/orchestration/internal/temporalworker" "github.com/formancehq/orchestration/internal/workflow" "go.temporal.io/api/enums/v1" diff --git a/internal/triggers/workflow_trigger_test.go b/internal/triggers/workflow_trigger_test.go index eb2be47..e928b02 100644 --- a/internal/triggers/workflow_trigger_test.go +++ b/internal/triggers/workflow_trigger_test.go @@ -4,11 +4,11 @@ import ( "testing" "time" - "github.com/formancehq/go-libs/v3/bun/bunconnect" - "github.com/formancehq/go-libs/v3/bun/bundebug" - "github.com/formancehq/go-libs/v3/logging" - "github.com/formancehq/go-libs/v3/pointer" - "github.com/formancehq/go-libs/v3/publish" + "github.com/formancehq/go-libs/v5/pkg/messaging/publish" + "github.com/formancehq/go-libs/v5/pkg/observe/log" + bunconnect "github.com/formancehq/go-libs/v5/pkg/storage/bun/connect" + bundebug "github.com/formancehq/go-libs/v5/pkg/storage/bun/debug" + "github.com/formancehq/go-libs/v5/pkg/types/pointer" "github.com/formancehq/orchestration/internal/storage" "github.com/formancehq/orchestration/internal/temporalworker" "github.com/formancehq/orchestration/internal/workflow" diff --git a/internal/workflow/activities/activity.go b/internal/workflow/activities/activity.go index a762050..bdd8fcd 100644 --- a/internal/workflow/activities/activity.go +++ b/internal/workflow/activities/activity.go @@ -5,7 +5,7 @@ import ( "fmt" sdk "github.com/formancehq/formance-sdk-go/v3" - "github.com/formancehq/go-libs/v3/pointer" + "github.com/formancehq/go-libs/v5/pkg/types/pointer" "github.com/formancehq/orchestration/internal/temporalworker" "github.com/pkg/errors" "go.temporal.io/sdk/activity" diff --git a/internal/workflow/activities/activity_ledger_create_transaction.go b/internal/workflow/activities/activity_ledger_create_transaction.go index bbf9436..32a6ac1 100644 --- a/internal/workflow/activities/activity_ledger_create_transaction.go +++ b/internal/workflow/activities/activity_ledger_create_transaction.go @@ -5,7 +5,7 @@ import ( stdtime "time" "github.com/formancehq/formance-sdk-go/v3/pkg/models/sdkerrors" - "github.com/formancehq/go-libs/v3/time" + "github.com/formancehq/go-libs/v5/pkg/types/time" "github.com/formancehq/formance-sdk-go/v3/pkg/models/operations" "github.com/formancehq/formance-sdk-go/v3/pkg/models/shared" diff --git a/internal/workflow/activities/activity_wallet_credit.go b/internal/workflow/activities/activity_wallet_credit.go index 0256d88..229497d 100644 --- a/internal/workflow/activities/activity_wallet_credit.go +++ b/internal/workflow/activities/activity_wallet_credit.go @@ -4,7 +4,7 @@ import ( "context" stdtime "time" - "github.com/formancehq/go-libs/v3/time" + "github.com/formancehq/go-libs/v5/pkg/types/time" "github.com/formancehq/formance-sdk-go/v3/pkg/models/operations" "github.com/formancehq/formance-sdk-go/v3/pkg/models/shared" diff --git a/internal/workflow/activities/activity_wallet_debit.go b/internal/workflow/activities/activity_wallet_debit.go index 3f84ba6..a57ba95 100644 --- a/internal/workflow/activities/activity_wallet_debit.go +++ b/internal/workflow/activities/activity_wallet_debit.go @@ -7,7 +7,7 @@ import ( "github.com/formancehq/formance-sdk-go/v3/pkg/models/sdkerrors" "github.com/pkg/errors" - "github.com/formancehq/go-libs/v3/time" + "github.com/formancehq/go-libs/v5/pkg/types/time" "github.com/formancehq/formance-sdk-go/v3/pkg/models/operations" "github.com/formancehq/formance-sdk-go/v3/pkg/models/shared" diff --git a/internal/workflow/activities/activity_wallet_list.go b/internal/workflow/activities/activity_wallet_list.go index 182d34a..5b61284 100644 --- a/internal/workflow/activities/activity_wallet_list.go +++ b/internal/workflow/activities/activity_wallet_list.go @@ -3,7 +3,7 @@ package activities import ( "context" - "github.com/formancehq/go-libs/v3/pointer" + "github.com/formancehq/go-libs/v5/pkg/types/pointer" "github.com/formancehq/formance-sdk-go/v3/pkg/models/operations" "github.com/formancehq/formance-sdk-go/v3/pkg/models/shared" diff --git a/internal/workflow/activities_test.go b/internal/workflow/activities_test.go index 413adc6..5c229aa 100644 --- a/internal/workflow/activities_test.go +++ b/internal/workflow/activities_test.go @@ -3,12 +3,12 @@ package workflow import ( "testing" - "github.com/formancehq/go-libs/v3/bun/bundebug" + bundebug "github.com/formancehq/go-libs/v5/pkg/storage/bun/debug" "github.com/uptrace/bun" - "github.com/formancehq/go-libs/v3/bun/bunconnect" - "github.com/formancehq/go-libs/v3/logging" - "github.com/formancehq/go-libs/v3/publish" + "github.com/formancehq/go-libs/v5/pkg/messaging/publish" + "github.com/formancehq/go-libs/v5/pkg/observe/log" + bunconnect "github.com/formancehq/go-libs/v5/pkg/storage/bun/connect" "github.com/stretchr/testify/require" "go.temporal.io/sdk/testsuite" ) diff --git a/internal/workflow/main_test.go b/internal/workflow/main_test.go index 3404e9c..f2b7fdd 100644 --- a/internal/workflow/main_test.go +++ b/internal/workflow/main_test.go @@ -4,11 +4,11 @@ import ( "context" "testing" - "github.com/formancehq/go-libs/v3/logging" - "github.com/formancehq/go-libs/v3/temporal" - "github.com/formancehq/go-libs/v3/testing/docker" - "github.com/formancehq/go-libs/v3/testing/platform/pgtesting" - "github.com/formancehq/go-libs/v3/testing/utils" + "github.com/formancehq/go-libs/v5/pkg/observe/log" + "github.com/formancehq/go-libs/v5/pkg/testing/docker" + "github.com/formancehq/go-libs/v5/pkg/testing/platform/pgtesting" + "github.com/formancehq/go-libs/v5/pkg/testing/utils" + "github.com/formancehq/go-libs/v5/pkg/workflow/temporal" "github.com/stretchr/testify/require" "go.temporal.io/sdk/testsuite" ) diff --git a/internal/workflow/manager.go b/internal/workflow/manager.go index 8460c61..f405986 100644 --- a/internal/workflow/manager.go +++ b/internal/workflow/manager.go @@ -7,12 +7,12 @@ import ( "fmt" "time" - "github.com/formancehq/go-libs/v3/pointer" + "github.com/formancehq/go-libs/v5/pkg/types/pointer" enums "go.temporal.io/api/enums/v1" history "go.temporal.io/api/history/v1" - "github.com/formancehq/go-libs/v3/bun/bunpaginate" + bunpaginate "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" "github.com/pkg/errors" "github.com/uptrace/bun" diff --git a/internal/workflow/manager_test.go b/internal/workflow/manager_test.go index 1ce2646..e616f81 100644 --- a/internal/workflow/manager_test.go +++ b/internal/workflow/manager_test.go @@ -4,17 +4,17 @@ import ( "testing" "time" - "github.com/formancehq/go-libs/v3/bun/bundebug" + bundebug "github.com/formancehq/go-libs/v5/pkg/storage/bun/debug" "github.com/uptrace/bun" "go.temporal.io/sdk/worker" - "github.com/formancehq/go-libs/v3/logging" - "github.com/formancehq/go-libs/v3/publish" + "github.com/formancehq/go-libs/v5/pkg/messaging/publish" + "github.com/formancehq/go-libs/v5/pkg/observe/log" "github.com/formancehq/orchestration/internal/temporalworker" "github.com/formancehq/orchestration/internal/workflow/stages" "github.com/google/uuid" - "github.com/formancehq/go-libs/v3/bun/bunconnect" + bunconnect "github.com/formancehq/go-libs/v5/pkg/storage/bun/connect" "github.com/formancehq/orchestration/internal/storage" "github.com/stretchr/testify/require" diff --git a/internal/workflow/stage.go b/internal/workflow/stage.go index 5131b63..406f1db 100644 --- a/internal/workflow/stage.go +++ b/internal/workflow/stage.go @@ -4,7 +4,7 @@ import ( "fmt" "time" - "github.com/formancehq/go-libs/v3/pointer" + "github.com/formancehq/go-libs/v5/pkg/types/pointer" "github.com/uptrace/bun" ) diff --git a/internal/workflow/stages/delay/delay.go b/internal/workflow/stages/delay/delay.go index 9ed7f82..5015f80 100644 --- a/internal/workflow/stages/delay/delay.go +++ b/internal/workflow/stages/delay/delay.go @@ -1,7 +1,7 @@ package delay import ( - "github.com/formancehq/go-libs/v3/time" + "github.com/formancehq/go-libs/v5/pkg/types/time" "github.com/formancehq/orchestration/internal/schema" "github.com/formancehq/orchestration/internal/workflow/stages" ) diff --git a/internal/workflow/stages/delay/run.go b/internal/workflow/stages/delay/run.go index a8c087c..c851f7c 100644 --- a/internal/workflow/stages/delay/run.go +++ b/internal/workflow/stages/delay/run.go @@ -1,7 +1,7 @@ package delay import ( - "github.com/formancehq/go-libs/v3/time" + "github.com/formancehq/go-libs/v5/pkg/types/time" "go.temporal.io/sdk/workflow" ) diff --git a/internal/workflow/stages/delay/run_test.go b/internal/workflow/stages/delay/run_test.go index a6e98a7..a146cca 100644 --- a/internal/workflow/stages/delay/run_test.go +++ b/internal/workflow/stages/delay/run_test.go @@ -3,7 +3,7 @@ package delay import ( "testing" - "github.com/formancehq/go-libs/v3/time" + "github.com/formancehq/go-libs/v5/pkg/types/time" "github.com/formancehq/orchestration/internal/schema" "github.com/formancehq/orchestration/internal/workflow/stages/internal/stagestesting" diff --git a/internal/workflow/stages/send/run.go b/internal/workflow/stages/send/run.go index 4270353..e024413 100644 --- a/internal/workflow/stages/send/run.go +++ b/internal/workflow/stages/send/run.go @@ -5,10 +5,10 @@ import ( "reflect" "strings" - "github.com/formancehq/go-libs/v3/time" + "github.com/formancehq/go-libs/v5/pkg/types/time" - "github.com/formancehq/go-libs/v3/collectionutils" - "github.com/formancehq/go-libs/v3/metadata" + collectionutils "github.com/formancehq/go-libs/v5/pkg/types/collections" + "github.com/formancehq/go-libs/v5/pkg/types/metadata" "github.com/formancehq/formance-sdk-go/v3/pkg/models/shared" "github.com/formancehq/orchestration/internal/workflow/activities" diff --git a/internal/workflow/stages/send/run_test.go b/internal/workflow/stages/send/run_test.go index 24a0a15..9270cd0 100644 --- a/internal/workflow/stages/send/run_test.go +++ b/internal/workflow/stages/send/run_test.go @@ -4,10 +4,10 @@ import ( "math/big" "testing" - "github.com/formancehq/go-libs/v3/time" + "github.com/formancehq/go-libs/v5/pkg/types/time" "github.com/formancehq/formance-sdk-go/v3/pkg/models/shared" - "github.com/formancehq/go-libs/v3/pointer" + "github.com/formancehq/go-libs/v5/pkg/types/pointer" "github.com/formancehq/orchestration/internal/workflow/activities" "github.com/formancehq/orchestration/internal/workflow/stages/internal/stagestesting" "github.com/stretchr/testify/mock" diff --git a/internal/workflow/stages/send/send.go b/internal/workflow/stages/send/send.go index 329db11..fa50c0e 100644 --- a/internal/workflow/stages/send/send.go +++ b/internal/workflow/stages/send/send.go @@ -2,8 +2,8 @@ package send import ( "github.com/formancehq/formance-sdk-go/v3/pkg/models/shared" - "github.com/formancehq/go-libs/v3/metadata" - "github.com/formancehq/go-libs/v3/time" + "github.com/formancehq/go-libs/v5/pkg/types/metadata" + "github.com/formancehq/go-libs/v5/pkg/types/time" "github.com/formancehq/orchestration/internal/schema" "github.com/formancehq/orchestration/internal/workflow/stages" ) diff --git a/pkg/events/events.go b/pkg/events/events.go index 420d765..ad20bcb 100644 --- a/pkg/events/events.go +++ b/pkg/events/events.go @@ -5,7 +5,7 @@ import ( "time" "github.com/ThreeDotsLabs/watermill/message" - "github.com/formancehq/go-libs/v3/publish" + "github.com/formancehq/go-libs/v5/pkg/messaging/publish" ) const ( From e5311739576546cd27cf6e09096f9b0c490163dd Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 11 Jun 2026 09:47:56 +0200 Subject: [PATCH 02/22] fix(triggers): repair broken name filter in ListTriggers The name filter used Where("Name ILIKE '%?%';", name): bun substitutes the ? placeholder even inside the string literal, producing invalid SQL (the value is quoted inside the literal and the stray ; lands mid-WHERE). Any GET /triggers?name=... request therefore returned a 500. Use a proper parameterized predicate with the wildcards on the argument, and add an integration test covering substring/case-insensitive matching. --- internal/triggers/manager.go | 2 +- internal/triggers/manager_test.go | 74 +++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 internal/triggers/manager_test.go diff --git a/internal/triggers/manager.go b/internal/triggers/manager.go index 2111367..dc2e711 100644 --- a/internal/triggers/manager.go +++ b/internal/triggers/manager.go @@ -41,7 +41,7 @@ func (m *TriggerManager) ListTriggers(ctx context.Context, paramsQuery ListTrigg func(query *bun.SelectQuery) *bun.SelectQuery { if paramsQuery.Options.Name != "" { - query = query.Where("Name ILIKE '%?%';", paramsQuery.Options.Name) + query = query.Where("name ILIKE ?", "%"+paramsQuery.Options.Name+"%") } return query.Where("deleted_at is null") }) diff --git a/internal/triggers/manager_test.go b/internal/triggers/manager_test.go new file mode 100644 index 0000000..cbe03fc --- /dev/null +++ b/internal/triggers/manager_test.go @@ -0,0 +1,74 @@ +package triggers + +import ( + "testing" + "time" + + "github.com/formancehq/go-libs/v3/logging" + "github.com/google/uuid" + "github.com/stretchr/testify/require" + "github.com/uptrace/bun" +) + +func insertNamedTrigger(t *testing.T, db *bun.DB, workflowID, name string) Trigger { + t.Helper() + + trigger := Trigger{ + TriggerData: TriggerData{ + Name: name, + Event: "NEW_TRANSACTION", + WorkflowID: workflowID, + }, + ID: uuid.NewString(), + CreatedAt: time.Now().Round(time.Microsecond).UTC(), + } + _, err := db.NewInsert().Model(&trigger).Exec(logging.TestingContext()) + require.NoError(t, err) + + return trigger +} + +func TestListTriggersNameFilter(t *testing.T) { + t.Parallel() + + db := setupTestDB(t) + w := insertNoOpWorkflow(t, db) + insertNamedTrigger(t, db, w.ID, "payment-processor") + insertNamedTrigger(t, db, w.ID, "ledger-sync") + + manager := &TriggerManager{db: db} + + listWithName := func(name string) []Trigger { + t.Helper() + cursor, err := manager.ListTriggers(logging.TestingContext(), ListTriggersQuery{ + PageSize: 15, + Options: ListTriggerParams{Name: name}, + }) + require.NoError(t, err) + return cursor.Data + } + + t.Run("substring match", func(t *testing.T) { + got := listWithName("payment") + require.Len(t, got, 1) + require.Equal(t, "payment-processor", got[0].Name) + }) + + t.Run("case insensitive", func(t *testing.T) { + got := listWithName("LEDGER") + require.Len(t, got, 1) + require.Equal(t, "ledger-sync", got[0].Name) + }) + + t.Run("no match", func(t *testing.T) { + require.Empty(t, listWithName("does-not-exist")) + }) + + t.Run("no filter returns all", func(t *testing.T) { + cursor, err := manager.ListTriggers(logging.TestingContext(), ListTriggersQuery{ + PageSize: 15, + }) + require.NoError(t, err) + require.Len(t, cursor.Data, 2) + }) +} From 258cebacfc6452e6d1b2a8097004b102a022b5bf Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 11 Jun 2026 09:55:02 +0200 Subject: [PATCH 03/22] fix(triggers): restrict link() to an allow-listed host (SSRF/token leak) The link() expression function performed an HTTP GET using the fx-provided *http.Client, which in production is the OAuth2 client-credentials client carrying the stack bearer token (broad ledger/wallets/payments scopes). Because link() targets a URI taken from a user-controlled trigger expression (reachable via POST /v2/triggers/{id}/test, which also returns the response body), an authenticated caller could point it at an arbitrary host and exfiltrate the stack token, or reach internal-only services (SSRF). Restrict link() to an allow-listed host (the configured stack URL), reject non-http(s) schemes, and close the response body. With no allow-listed host configured, link() network calls are denied. The allowlist is threaded through triggers.NewModule(stack, stackURL, taskQueue). --- cmd/root.go | 3 +- internal/triggers/expression.go | 56 +++++++++++++++++++++++++++++-- internal/triggers/module.go | 4 +-- internal/triggers/trigger_test.go | 43 +++++++++++++++++++++++- 4 files changed, 100 insertions(+), 6 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 45e4a99..c2282bc 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -77,6 +77,7 @@ func commonOptions(cmd *cobra.Command) (fx.Option, error) { } stack, _ := cmd.Flags().GetString(stackFlag) + stackURL, _ := cmd.Flags().GetString(stackURLFlag) temporalTaskQueue, _ := cmd.Flags().GetString(temporal.TemporalTaskQueueFlag) return fx.Options( @@ -98,7 +99,7 @@ func commonOptions(cmd *cobra.Command) (fx.Option, error) { authnfx.JWTModuleFromFlags(cmd), authnfx.LicenceModuleFromFlags(cmd, ServiceName), workflow.NewModule(stack, temporalTaskQueue), - triggers.NewModule(stack, temporalTaskQueue), + triggers.NewModule(stack, stackURL, temporalTaskQueue), fx.Provide(func() *bunconnect.ConnectionOptions { return connectionOptions }), diff --git a/internal/triggers/expression.go b/internal/triggers/expression.go index 5f7c13c..ccd0990 100644 --- a/internal/triggers/expression.go +++ b/internal/triggers/expression.go @@ -4,6 +4,8 @@ import ( "encoding/json" "fmt" "net/http" + "net/url" + "strings" "go.temporal.io/sdk/temporal" @@ -16,6 +18,34 @@ import ( type expressionEvaluator struct { httpClient *http.Client + // allowedHosts is the set of hosts link() is permitted to call. It exists + // to prevent the (credential-bearing) HTTP client from being pointed at an + // arbitrary, attacker-controlled host via a user-defined trigger + // expression (SSRF + bearer-token exfiltration). An empty set denies every + // network call. + allowedHosts map[string]struct{} +} + +// checkLinkURL enforces that a link() target uses an http(s) scheme and points +// at an allow-listed host (typically the stack gateway the HTTP client is +// scoped to). +func (h *expressionEvaluator) checkLinkURL(raw string) error { + u, err := url.Parse(raw) + if err != nil { + return temporal.NewNonRetryableApplicationError( + fmt.Sprintf("invalid link url: %s", raw), "APPLICATION", err) + } + if u.Scheme != "http" && u.Scheme != "https" { + return temporal.NewNonRetryableApplicationError( + fmt.Sprintf("link url scheme not allowed: %q", u.Scheme), "APPLICATION", + fmt.Errorf("scheme %q not allowed", u.Scheme)) + } + if _, ok := h.allowedHosts[strings.ToLower(u.Host)]; !ok { + return temporal.NewNonRetryableApplicationError( + fmt.Sprintf("link url host not allowed: %q", u.Host), "APPLICATION", + fmt.Errorf("host %q is not in the allowlist", u.Host)) + } + return nil } func (h *expressionEvaluator) link(params ...any) (any, error) { @@ -54,10 +84,16 @@ func (h *expressionEvaluator) link(params ...any) (any, error) { fmt.Errorf("link '%s' not defined for object", rel), ) case 1: + if err := h.checkLinkURL(filteredLinks[0].URI); err != nil { + return nil, err + } rsp, err := h.httpClient.Get(filteredLinks[0].URI) if err != nil { return nil, errors.Wrapf(err, "reading resource: %s", filteredLinks[0].URI) } + defer func() { + _ = rsp.Body.Close() + }() if rsp.StatusCode >= 400 { return nil, fmt.Errorf("unexpected status code when reading resource: %d", rsp.StatusCode) } @@ -141,9 +177,25 @@ func (h *expressionEvaluator) evalVariables(rawObject any, vars map[string]strin return results, nil } -func NewExpressionEvaluator(httpClient *http.Client) *expressionEvaluator { +// NewExpressionEvaluator builds an evaluator whose link() function may only +// reach the provided hosts. Each entry may be a bare host ("example.com:8080") +// or a full URL, in which case only its host is retained. With no allowed host, +// link() network calls are denied. +func NewExpressionEvaluator(httpClient *http.Client, allowedHosts ...string) *expressionEvaluator { + hosts := make(map[string]struct{}, len(allowedHosts)) + for _, h := range allowedHosts { + if h == "" { + continue + } + if u, err := url.Parse(h); err == nil && u.Host != "" { + hosts[strings.ToLower(u.Host)] = struct{}{} + continue + } + hosts[strings.ToLower(h)] = struct{}{} + } return &expressionEvaluator{ - httpClient: httpClient, + httpClient: httpClient, + allowedHosts: hosts, } } diff --git a/internal/triggers/module.go b/internal/triggers/module.go index 02070f6..8e5af8e 100644 --- a/internal/triggers/module.go +++ b/internal/triggers/module.go @@ -14,11 +14,11 @@ import ( "go.uber.org/fx" ) -func NewModule(stack, taskQueue string) fx.Option { +func NewModule(stack, stackURL, taskQueue string) fx.Option { return fx.Options( fx.Provide(NewManager), fx.Provide(func(httpClient *http.Client) *expressionEvaluator { - return NewExpressionEvaluator(httpClient) + return NewExpressionEvaluator(httpClient, stackURL) }), fx.Provide(func() *triggerWorkflow { return NewWorkflow(stack, taskQueue, true) diff --git a/internal/triggers/trigger_test.go b/internal/triggers/trigger_test.go index 635c2e1..2789b00 100644 --- a/internal/triggers/trigger_test.go +++ b/internal/triggers/trigger_test.go @@ -168,10 +168,51 @@ func TestEvalVariables(t *testing.T) { } { testCase := testCase t.Run(testCase.name, func(t *testing.T) { - e := NewExpressionEvaluator(http.DefaultClient) + e := NewExpressionEvaluator(http.DefaultClient, srv.URL) evaluated, err := e.evalVariables(testCase.rawObject, testCase.variables) require.NoError(t, err) require.Equal(t, testCase.expectedResult, evaluated) }) } } + +func TestLinkHostAllowlist(t *testing.T) { + var hit bool + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + hit = true + _, _ = w.Write([]byte(`{"data": {"role": "admin"}}`)) + })) + t.Cleanup(srv.Close) + + rawObject := map[string]any{ + "links": []map[string]any{ + {"name": "source_account", "uri": srv.URL}, + }, + } + variables := map[string]string{"role": `link(event, "source_account").role`} + + t.Run("denied when host not allowlisted", func(t *testing.T) { + hit = false + e := NewExpressionEvaluator(http.DefaultClient, "allowed.example.com") + _, err := e.evalVariables(rawObject, variables) + require.Error(t, err) + require.False(t, hit, "a non-allowlisted host must never be contacted") + }) + + t.Run("denied with empty allowlist", func(t *testing.T) { + hit = false + e := NewDefaultExpressionEvaluator() + _, err := e.evalVariables(rawObject, variables) + require.Error(t, err) + require.False(t, hit) + }) + + t.Run("allowed when host matches", func(t *testing.T) { + hit = false + e := NewExpressionEvaluator(http.DefaultClient, srv.URL) + result, err := e.evalVariables(rawObject, variables) + require.NoError(t, err) + require.Equal(t, map[string]string{"role": "admin"}, result) + require.True(t, hit) + }) +} From 5a3828a7a57caa0135e0b2b5532f1ce237ef3585 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 11 Jun 2026 10:02:11 +0200 Subject: [PATCH 04/22] fix(workflow): target the -main run in Wait and AbortRun, fix error handling Initiate starts the real Run workflow as a detached child with id "-main" (ParentClosePolicy ABANDON) and returns as soon as that child has started. The Initiate workflow (id == instanceID) is thus already completed by the time the API calls Wait/AbortRun: - AbortRun cancelled the completed Initiate execution, so cancellation never reached the running stages (wait_event/delay were unabortable). - Wait returned immediately on the completed Initiate execution, so ?wait=true returned a non-terminated instance. Both now target "-main" (matching ReadInstanceHistory). Wait also mishandled errors: errors.Is(err, &serviceerror.NotFound{}) can never match (no Is/Unwrap on that type) and errors.Unwrap(err) returned nil for non-wrapped errors, turning a failure into a success. Use errors.As for NotFound and return the original error otherwise. Adds TestWait covering both the terminate-wait and not-found paths. --- internal/workflow/manager.go | 16 ++++++--- internal/workflow/manager_test.go | 55 +++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 4 deletions(-) diff --git a/internal/workflow/manager.go b/internal/workflow/manager.go index f405986..ecca898 100644 --- a/internal/workflow/manager.go +++ b/internal/workflow/manager.go @@ -117,13 +117,18 @@ func (m *WorkflowManager) RunWorkflow(ctx context.Context, id string, variables } func (m *WorkflowManager) Wait(ctx context.Context, instanceID string) error { + // The actual work runs in the detached child workflow "-main"; + // the Initiate workflow (id == instanceID) completes as soon as that child + // has started. Waiting on instanceID would therefore return immediately, + // before the run is terminated, so we wait on the running child. if err := m.temporalClient. - GetWorkflow(ctx, instanceID, ""). + GetWorkflow(ctx, instanceID+"-main", ""). Get(ctx, nil); err != nil { - if errors.Is(err, &serviceerror.NotFound{}) { + var notFound *serviceerror.NotFound + if errors.As(err, ¬Found) { return ErrInstanceNotFound } - return errors.Unwrap(err) + return err } return nil } @@ -176,7 +181,10 @@ func (m *WorkflowManager) AbortRun(ctx context.Context, instanceID string) error return errors.Wrap(err, "retrieving workflow execution") } - return m.temporalClient.CancelWorkflow(ctx, instanceID, "") + // Cancel the detached child workflow that carries the actual run; the + // Initiate workflow (id == instanceID) has already completed, so cancelling + // it would be a no-op and never reach the running stages. + return m.temporalClient.CancelWorkflow(ctx, instanceID+"-main", "") } func (m *WorkflowManager) ListInstances(ctx context.Context, pagination ListInstancesQuery) (*bunpaginate.Cursor[Instance], error) { diff --git a/internal/workflow/manager_test.go b/internal/workflow/manager_test.go index e616f81..dc2a7a3 100644 --- a/internal/workflow/manager_test.go +++ b/internal/workflow/manager_test.go @@ -76,3 +76,58 @@ func TestConfig(t *testing.T) { return len(updatedInstance.Statuses) == 1 }, 2*time.Second, 100*time.Millisecond) } + +func TestWait(t *testing.T) { + t.Parallel() + + database := srv.NewDatabase(t) + db, err := bunconnect.OpenSQLDB(logging.TestingContext(), bunconnect.ConnectionOptions{ + DatabaseSourceName: database.ConnString(), + }) + require.NoError(t, err) + t.Cleanup(func() { + _ = db.Close() + }) + require.NoError(t, storage.Migrate(logging.TestingContext(), db)) + + taskQueue := uuid.NewString() + w := temporalworker.New(logging.Testing(), devServer.Client(), taskQueue, + []temporalworker.DefinitionSet{ + NewWorkflows("test", false).DefinitionSet(), + temporalworker.NewDefinitionSet().Append(temporalworker.Definition{ + Name: "NoOp", + Func: (&stages.NoOp{}).GetWorkflow(), + }), + }, + []temporalworker.DefinitionSet{ + NewActivities(publish.NoOpPublisher, db).DefinitionSet(), + }, + worker.Options{}, + ) + require.NoError(t, w.Start()) + t.Cleanup(w.Stop) + + manager := NewManager(db, devServer.Client(), "test", taskQueue, false) + + t.Run("waits for the -main run to terminate", func(t *testing.T) { + config := Config{Stages: []RawStage{{"noop": map[string]any{}}}} + wf, err := manager.Create(logging.TestingContext(), config) + require.NoError(t, err) + i, err := manager.RunWorkflow(logging.TestingContext(), wf.ID, map[string]string{}) + require.NoError(t, err) + + // Wait must block on the detached "-main" child, not the Initiate + // workflow (which returns immediately). Once it returns, the instance + // must already be terminated. + require.NoError(t, manager.Wait(logging.TestingContext(), i.ID)) + + updated, err := manager.GetInstance(logging.TestingContext(), i.ID) + require.NoError(t, err) + require.True(t, updated.Terminated) + }) + + t.Run("unknown instance returns ErrInstanceNotFound", func(t *testing.T) { + err := manager.Wait(logging.TestingContext(), "does-not-exist") + require.ErrorIs(t, err, ErrInstanceNotFound) + }) +} From 5703bf5098be68b63aa708200f911b346146b6bf Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 11 Jun 2026 10:10:41 +0200 Subject: [PATCH 05/22] fix(triggers): make event processing idempotent under redelivery and retries The event bus is at-least-once. Previously only SAVED_PAYMENT/SAVED_ACCOUNT got a deterministic, dedup-ing Temporal workflow id; every other event type ran with a server-generated id, so a redelivery (or a partial-failure NACK after some triggers had already started) re-executed triggers and replayed side-effecting stages such as money movements. - listener: derive a deterministic workflow id for ALL events (taskIDPrefix-triggerID-) with REJECT_DUPLICATE, so a redelivery is rejected as a duplicate instead of starting a second run. (H1) - occurrence id: ExecuteTrigger built the occurrence with uuid.NewString() in workflow code, yielding a different id on every Temporal replay. Use the (deterministic) workflow execution id instead. (M4) - insert activities: InsertNewInstance, InsertNewStage and InsertTriggerOccurrence now use ON CONFLICT DO NOTHING. With deterministic primary keys, a retry after a lost ack (row committed, result lost) would otherwise fail forever on the duplicate key and wedge the workflow. (M2) Adds a redelivery regression test for a non-payment event. --- internal/triggers/activities.go | 5 ++++ internal/triggers/listener.go | 24 ++++++++++++----- internal/triggers/listener_test.go | 38 +++++++++++++++++++++++++++ internal/triggers/trigger.go | 8 ++++-- internal/triggers/workflow_trigger.go | 6 ++++- internal/workflow/activities.go | 9 +++++++ 6 files changed, 80 insertions(+), 10 deletions(-) diff --git a/internal/triggers/activities.go b/internal/triggers/activities.go index 4a8e820..8044ce9 100644 --- a/internal/triggers/activities.go +++ b/internal/triggers/activities.go @@ -81,8 +81,13 @@ func (a Activities) EvalTriggerVariables(ctx context.Context, trigger Trigger, r } func (a Activities) InsertTriggerOccurrence(ctx context.Context, occurrence Occurrence) error { + // Idempotent: a Temporal retry after a lost ack (row committed but the + // activity result never reached the server) must not fail on the duplicate + // primary key. The occurrence id is deterministic (see + // NewTriggerOccurrence), so DO NOTHING is safe. _, err := a.db.NewInsert(). Model(pointer.For(occurrence)). + On("CONFLICT DO NOTHING"). Exec(ctx) return err } diff --git a/internal/triggers/listener.go b/internal/triggers/listener.go index ffa265d..6108e17 100644 --- a/internal/triggers/listener.go +++ b/internal/triggers/listener.go @@ -148,14 +148,24 @@ func handleMessage( searchAttributes[workflow.SearchAttributeTriggerID] = trigger.ID } - options := client.StartWorkflowOptions{ - TaskQueue: taskQueue, - SearchAttributes: searchAttributes, - } + // Derive a deterministic workflow ID so an at-least-once redelivery of + // the same event does not start a second trigger execution (which would + // replay side-effecting stages such as money movements). For + // SAVED_PAYMENT/SAVED_ACCOUNT we key on the object id (dedup across + // distinct deliveries of the same object); for every other event type + // we fall back to the message UUID, which is preserved across + // redeliveries. + dedupKey := msg.UUID if objectID != nil { - options.ID = taskIDPrefix + "-" + trigger.ID + "-" + *objectID - options.WorkflowIDReusePolicy = enums.WORKFLOW_ID_REUSE_POLICY_REJECT_DUPLICATE - options.WorkflowExecutionErrorWhenAlreadyStarted = true + dedupKey = *objectID + } + + options := client.StartWorkflowOptions{ + TaskQueue: taskQueue, + SearchAttributes: searchAttributes, + ID: taskIDPrefix + "-" + trigger.ID + "-" + dedupKey, + WorkflowIDReusePolicy: enums.WORKFLOW_ID_REUSE_POLICY_REJECT_DUPLICATE, + WorkflowExecutionErrorWhenAlreadyStarted: true, } _, execErr := temporalClient.ExecuteWorkflow(ctx, options, ExecuteTrigger, ProcessEventRequest{ diff --git a/internal/triggers/listener_test.go b/internal/triggers/listener_test.go index 5a7e959..8769709 100644 --- a/internal/triggers/listener_test.go +++ b/internal/triggers/listener_test.go @@ -379,4 +379,42 @@ func TestHandleMessage(t *testing.T) { require.NoError(t, err) require.Equal(t, 1, count) }) + + t.Run("redelivery of a non-payment event is skipped", func(t *testing.T) { + t.Parallel() + + db := setupTestDB(t) + taskQueue := setupWorker(t, db) + + w := insertNoOpWorkflow(t, db) + insertTrigger(t, db, w.ID, "NEW_TRANSACTION", nil, nil) + + event := makeMessage("NEW_TRANSACTION", "v1", map[string]any{}) + evaluator := NewDefaultExpressionEvaluator() + + // Simulate an at-least-once redelivery: the broker re-delivers the same + // message, preserving its UUID. + msg1 := publish.NewMessage(logging.TestingContext(), *event) + msg2 := publish.NewMessage(logging.TestingContext(), *event) + msg2.UUID = msg1.UUID + + require.NoError(t, handleMessage(devServer.Client(), db, evaluator, "test", "test", taskQueue, false, msg1)) + require.Eventually(t, func() bool { + count, err := db.NewSelect(). + Model((*Occurrence)(nil)). + Count(logging.TestingContext()) + return err == nil && count == 1 + }, 10*time.Second, 200*time.Millisecond) + + require.NoError(t, handleMessage(devServer.Client(), db, evaluator, "test", "test", taskQueue, false, msg2)) + + // The deterministic workflow id (keyed on the message UUID) must reject + // the duplicate, so no second trigger execution / occurrence is created. + time.Sleep(2 * time.Second) + count, err := db.NewSelect(). + Model((*Occurrence)(nil)). + Count(logging.TestingContext()) + require.NoError(t, err) + require.Equal(t, 1, count) + }) } diff --git a/internal/triggers/trigger.go b/internal/triggers/trigger.go index 85a4dcf..4ab1b47 100644 --- a/internal/triggers/trigger.go +++ b/internal/triggers/trigger.go @@ -112,9 +112,13 @@ type Occurrence struct { Error *string `json:"error,omitempty" bun:"error"` } -func NewTriggerOccurrence(triggerID string, event publish.EventMessage, at time.Time) Occurrence { +// NewTriggerOccurrence builds an occurrence with a caller-provided id. The id +// must be deterministic when called from workflow code (e.g. the workflow +// execution id) so that it stays stable across Temporal replays — generating a +// random uuid here would yield a different occurrence id on every replay. +func NewTriggerOccurrence(id, triggerID string, event publish.EventMessage, at time.Time) Occurrence { return Occurrence{ - ID: uuid.NewString(), + ID: id, TriggerID: triggerID, Date: at, Event: event, diff --git a/internal/triggers/workflow_trigger.go b/internal/triggers/workflow_trigger.go index 47543b9..10a4384 100644 --- a/internal/triggers/workflow_trigger.go +++ b/internal/triggers/workflow_trigger.go @@ -68,7 +68,11 @@ func (w triggerWorkflow) RunTrigger(ctx temporalworkflow.Context, req ProcessEve func (w triggerWorkflow) ExecuteTrigger(ctx temporalworkflow.Context, req ProcessEventRequest, trigger Trigger) error { vars := make(map[string]string) - occurrence := NewTriggerOccurrence(trigger.ID, req.Event, temporalworkflow.Now(ctx)) + // Use the (deterministic, replay-stable) workflow execution id as the + // occurrence id rather than a random uuid generated in workflow code. + occurrence := NewTriggerOccurrence( + temporalworkflow.GetInfo(ctx).WorkflowExecution.ID, + trigger.ID, req.Event, temporalworkflow.Now(ctx)) err := temporalworkflow.ExecuteActivity( temporalworkflow.WithActivityOptions(ctx, temporalworkflow.ActivityOptions{ StartToCloseTimeout: 10 * time.Second, diff --git a/internal/workflow/activities.go b/internal/workflow/activities.go index b06d487..79e4d65 100644 --- a/internal/workflow/activities.go +++ b/internal/workflow/activities.go @@ -70,9 +70,14 @@ func (a Activities) SendWorkflowStageTerminationEvent(ctx context.Context, insta func (a Activities) InsertNewInstance(ctx context.Context, workflowID string) (*Instance, error) { instance := NewInstance(activity.GetInfo(ctx).WorkflowExecution.ID, workflowID) + // Idempotent: the primary key is the (deterministic) workflow execution id, + // so a Temporal retry after a lost ack must not fail on the duplicate key. + // The returned instance is rebuilt deterministically, so it is correct even + // when the row already exists. if _, err := a.db. NewInsert(). Model(&instance). + On("CONFLICT DO NOTHING"). Exec(ctx); err != nil { return nil, err } @@ -90,8 +95,12 @@ func (a Activities) UpdateInstance(ctx context.Context, instance *Instance) erro func (a Activities) InsertNewStage(ctx context.Context, instance Instance, ind int) (*Stage, error) { stage := NewStage(instance.ID, activity.GetInfo(ctx).WorkflowExecution.RunID, ind) + // Idempotent: the primary key is deterministic (instance id + run id + + // index), so a Temporal retry after a lost ack must not fail on the + // duplicate key. if _, err := a.db.NewInsert(). Model(&stage). + On("CONFLICT DO NOTHING"). Exec(ctx); err != nil { return nil, err } From 56ca433fc6de4f5047ad452156de82d428baf3b9 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 11 Jun 2026 10:15:54 +0200 Subject: [PATCH 06/22] fix(triggers): surface listener panics as errors instead of dropping events handleMessage had an unnamed error return, so its recover() returned nil and watermill ACKed the message. getWorkflowIDFromEvent deliberately panicked on (un)marshal failures (e.g. a SAVED_PAYMENT payload whose id is not a string), so a malformed event was permanently dropped with only a stdout print. - getWorkflowIDFromEvent now returns an error instead of panicking. - handleMessage uses a named return so a recovered panic is converted into a returned error (NACK + redelivery/DLQ) and logged with its stack via the structured logger. Adds a test asserting a malformed payment payload returns an error. Note: overlaps internal/triggers/listener.go with #184 (idempotence); the two are independent and may need a trivial merge. --- internal/triggers/listener.go | 24 +++++++++++++++--------- internal/triggers/listener_test.go | 20 ++++++++++++++++++++ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/internal/triggers/listener.go b/internal/triggers/listener.go index 6108e17..ad21273 100644 --- a/internal/triggers/listener.go +++ b/internal/triggers/listener.go @@ -28,12 +28,12 @@ import ( ) // Quick hack to filter already processed events -func getWorkflowIDFromEvent(event publish.EventMessage) *string { +func getWorkflowIDFromEvent(event publish.EventMessage) (*string, error) { switch event.Type { case "SAVED_PAYMENT", "SAVED_ACCOUNT": data, err := json.Marshal(event.Payload) if err != nil { - panic(err) + return nil, errors.Wrap(err, "marshalling event payload") } type object struct { @@ -41,12 +41,12 @@ func getWorkflowIDFromEvent(event publish.EventMessage) *string { } o := &object{} if err := json.Unmarshal(data, o); err != nil { - panic(err) + return nil, errors.Wrap(err, "unmarshalling event payload") } - return pointer.For(o.ID) + return pointer.For(o.ID), nil default: - return nil + return nil, nil } } @@ -96,11 +96,14 @@ func handleMessage( stack, taskIDPrefix, taskQueue string, includeSearchAttributes bool, msg *message.Message, -) error { +) (err error) { defer func() { if e := recover(); e != nil { - fmt.Println(e) - debug.PrintStack() + // Convert a panic into a returned error so the message is NACKed + // (and redelivered / dead-lettered) instead of being silently + // acked and lost. + err = fmt.Errorf("panic while handling event: %v", e) + logging.FromContext(msg.Context()).Errorf("%s\n%s", err, debug.Stack()) } }() @@ -138,7 +141,10 @@ func handleMessage( return nil } - objectID := getWorkflowIDFromEvent(*event) + objectID, err := getWorkflowIDFromEvent(*event) + if err != nil { + return errors.Wrap(err, "extracting workflow id from event") + } for _, trigger := range matched { searchAttributes := map[string]interface{}{ diff --git a/internal/triggers/listener_test.go b/internal/triggers/listener_test.go index 8769709..ffc4f34 100644 --- a/internal/triggers/listener_test.go +++ b/internal/triggers/listener_test.go @@ -417,4 +417,24 @@ func TestHandleMessage(t *testing.T) { require.NoError(t, err) require.Equal(t, 1, count) }) + + t.Run("malformed payment payload returns an error instead of being dropped", func(t *testing.T) { + t.Parallel() + + db := setupTestDB(t) + taskQueue := setupWorker(t, db) + + w := insertNoOpWorkflow(t, db) + insertTrigger(t, db, w.ID, "SAVED_PAYMENT", nil, nil) + + // "id" is a number, so extracting the dedup id fails. This used to + // panic and be silently acked; it must now surface as an error so the + // message is NACKed. + event := makeMessage("SAVED_PAYMENT", "v1", map[string]any{"id": 123}) + msg := publish.NewMessage(logging.TestingContext(), *event) + + evaluator := NewDefaultExpressionEvaluator() + err := handleMessage(devServer.Client(), db, evaluator, "test", "test", taskQueue, false, msg) + require.Error(t, err) + }) } From eaa577949279d0accfeb2d1b6ceaf9cdd50cc3c2 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 11 Jun 2026 10:20:27 +0200 Subject: [PATCH 07/22] fix(wait_event): drain signals with a blocking Receive loop RunWaitEvent called channel.ReceiveAsync inside a workflow.Await predicate. An Await predicate is only evaluated once per workflow-task wakeup, so if a non-matching signal and the matching signal were delivered in the same workflow task, the predicate consumed the non-matching one, returned false, and the matching signal stayed buffered with nothing left to re-wake the coroutine -- blocking the stage forever. Non-matching events were also silently destroyed. Replace it with the canonical blocking Receive loop that drains signals one at a time until the expected event arrives. Adds a regression test signaling a non-matching then matching event in the same task. --- internal/workflow/stages/wait_event/run.go | 22 +++++++++-------- .../stages/wait_event/wait_event_test.go | 24 +++++++++++++++++++ 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/internal/workflow/stages/wait_event/run.go b/internal/workflow/stages/wait_event/run.go index fd42208..6f90327 100644 --- a/internal/workflow/stages/wait_event/run.go +++ b/internal/workflow/stages/wait_event/run.go @@ -7,16 +7,18 @@ import ( func RunWaitEvent(ctx workflow.Context, waitEvent WaitEvent) error { channel := workflow.GetSignalChannel(ctx, internalWorkflow.EventSignalName) - return workflow.Await(ctx, func() bool { + // Drain the signal channel one signal at a time until the expected event + // arrives. Using a blocking Receive loop (rather than ReceiveAsync inside + // an Await predicate) guarantees no buffered signal is consumed and + // dropped: an Await predicate is only evaluated once per workflow-task + // wakeup, so two signals delivered in the same task would leave the second + // one buffered with nothing left to re-wake the coroutine, blocking forever. + for { var signal internalWorkflow.Event - ok := channel.ReceiveAsync(&signal) - if !ok { - return false + channel.Receive(ctx, &signal) + if signal.Name == waitEvent.Event { + return nil } - if signal.Name != waitEvent.Event { - workflow.GetLogger(ctx).Debug("receive unexpected event", "event", signal.Name) - return false - } - return true - }) + workflow.GetLogger(ctx).Debug("received unexpected event, still waiting", "event", signal.Name) + } } diff --git a/internal/workflow/stages/wait_event/wait_event_test.go b/internal/workflow/stages/wait_event/wait_event_test.go index 7eed168..610a867 100644 --- a/internal/workflow/stages/wait_event/wait_event_test.go +++ b/internal/workflow/stages/wait_event/wait_event_test.go @@ -49,5 +49,29 @@ func TestWaitEvent(t *testing.T) { }}, Name: "nominal", }, + { + Stage: WaitEvent{ + Event: "test", + }, + DelayedCallbacks: []stagestesting.DelayedCallback{{ + Fn: func(environment *testsuite.TestWorkflowEnvironment) func() { + return func() { + // Two signals delivered in the same workflow task: a + // non-matching one followed by the matching one. The + // stage must consume the first, keep the second, and + // complete (the previous ReceiveAsync-in-Await + // implementation would drop the buffered match and hang). + environment.SignalWorkflow(workflow.EventSignalName, workflow.Event{ + Name: "other", + }) + environment.SignalWorkflow(workflow.EventSignalName, workflow.Event{ + Name: "test", + }) + } + }, + Duration: 100 * time.Millisecond, + }}, + Name: "ignores non-matching event delivered in the same task", + }, }...) } From 8beb773ece2483756efdec7ff24eb5d7e9f7074e Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 11 Jun 2026 10:26:33 +0200 Subject: [PATCH 08/22] fix(workflow): run termination bookkeeping on a cancellation-safe context When a Run workflow is cancelled, config.run returns a CanceledError and the run context is already cancelled. The subsequent UpdateStage / SendWorkflowStageTerminationEvent and UpdateInstance / SendWorkflowTerminationEvent activities were executed on that cancelled context, so they failed immediately: the instance/stage rows were left stuck "running" and no FAILED_WORKFLOW(_STAGE) event was published. Add terminationContext(), which returns the original context normally but a workflow.NewDisconnectedContext when the workflow has been cancelled, and use it for the terminal bookkeeping activities in both run() and Run. The normal (non-cancelled) path is unchanged (still uses the live context); covered by the existing end-to-end TestConfig. --- internal/workflow/config.go | 26 ++++++++++++++++++++++---- internal/workflow/run.go | 13 +++++++++---- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/internal/workflow/config.go b/internal/workflow/config.go index 90b0b9b..e485bb1 100644 --- a/internal/workflow/config.go +++ b/internal/workflow/config.go @@ -10,6 +10,20 @@ import ( "go.temporal.io/sdk/workflow" ) +// terminationContext returns a context safe for running terminal bookkeeping +// activities (status updates, termination events). When the workflow has been +// cancelled, the supplied context is already cancelled and any activity started +// on it fails immediately -- which would leave the instance/stage rows stuck +// "running" and skip the termination event. In that case a disconnected context +// is returned so the bookkeeping still runs. +func terminationContext(ctx workflow.Context) workflow.Context { + if ctx.Err() == nil { + return ctx + } + disconnected, _ := workflow.NewDisconnectedContext(ctx) + return disconnected +} + type RawStage map[string]map[string]any type Config struct { @@ -85,16 +99,20 @@ func (c *Config) run(ctx workflow.Context, instance Instance, variables map[stri } stage.SetTerminated(runError, workflow.Now(ctx).Round(time.Nanosecond)) - err = workflow.ExecuteActivity(workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ + // Record the stage termination on a context that survives cancellation, + // otherwise a cancelled stage would never be marked terminated. + cleanupCtx := terminationContext(ctx) + + err = workflow.ExecuteActivity(workflow.WithActivityOptions(cleanupCtx, workflow.ActivityOptions{ StartToCloseTimeout: 10 * time.Second, - }), UpdateStageActivity, stage).Get(ctx, nil) + }), UpdateStageActivity, stage).Get(cleanupCtx, nil) if err != nil { return err } - err = workflow.ExecuteActivity(workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ + err = workflow.ExecuteActivity(workflow.WithActivityOptions(cleanupCtx, workflow.ActivityOptions{ StartToCloseTimeout: 10 * time.Second, - }), SendWorkflowStageTerminationEventActivity, instance, stage).Get(ctx, nil) + }), SendWorkflowStageTerminationEventActivity, instance, stage).Get(cleanupCtx, nil) if err != nil { return err } diff --git a/internal/workflow/run.go b/internal/workflow/run.go index 267da96..1bc0262 100644 --- a/internal/workflow/run.go +++ b/internal/workflow/run.go @@ -74,16 +74,21 @@ func (w Workflows) Run(ctx workflow.Context, i Input, instance Instance) error { instance.SetTerminated(workflow.Now(ctx)) } - err = workflow.ExecuteActivity(workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ + // Record the instance termination on a context that survives cancellation, + // otherwise a cancelled run would never be marked terminated and no + // termination event would be published. + cleanupCtx := terminationContext(ctx) + + err = workflow.ExecuteActivity(workflow.WithActivityOptions(cleanupCtx, workflow.ActivityOptions{ StartToCloseTimeout: 10 * time.Second, - }), UpdateInstanceActivity, instance).Get(ctx, nil) + }), UpdateInstanceActivity, instance).Get(cleanupCtx, nil) if err != nil { return err } - err = workflow.ExecuteActivity(workflow.WithActivityOptions(ctx, workflow.ActivityOptions{ + err = workflow.ExecuteActivity(workflow.WithActivityOptions(cleanupCtx, workflow.ActivityOptions{ StartToCloseTimeout: 10 * time.Second, - }), SendWorkflowTerminationEventActivity, instance).Get(ctx, nil) + }), SendWorkflowTerminationEventActivity, instance).Get(cleanupCtx, nil) if err != nil { return err } From 9360f097d15ac2453cf876b322f161a7ff465dc3 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 11 Jun 2026 10:31:44 +0200 Subject: [PATCH 09/22] fix(workflow): stop using soft-deleted workflows RunWorkflow and ReadWorkflow selected by id only, so a soft-deleted workflow could still be executed (POST /workflows/{id}/instances) and read. DeleteWorkflow had no deleted_at guard, so re-deleting rewrote the timestamp instead of returning not-found. And the trigger-matching queries filtered only trigger.deleted_at, so triggers attached to a deleted workflow kept firing instances forever. - RunWorkflow / ReadWorkflow: add deleted_at IS NULL. - DeleteWorkflow: add deleted_at IS NULL guard (re-delete -> ErrWorkflowNotFound). - listMatchingTriggers / Activities.ListTriggers: exclude triggers whose workflow is soft-deleted. Tests: TestListMatchingTriggers gains a soft-deleted-workflow case, and TestSoftDeletedWorkflowIsNotUsable covers read/run/re-delete. --- internal/triggers/activities.go | 1 + internal/triggers/listener.go | 1 + internal/triggers/listener_test.go | 17 +++++++++++++++ internal/workflow/manager.go | 4 +++- internal/workflow/manager_test.go | 35 ++++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 1 deletion(-) diff --git a/internal/triggers/activities.go b/internal/triggers/activities.go index 8044ce9..32b2e23 100644 --- a/internal/triggers/activities.go +++ b/internal/triggers/activities.go @@ -58,6 +58,7 @@ func (a Activities) ListTriggers(ctx context.Context, request ProcessEventReques Model(&triggers). Relation("Workflow"). Where("trigger.deleted_at is null"). + Where("workflow_id IN (SELECT id FROM workflows WHERE deleted_at IS NULL)"). Where("event = ?", request.Event.Type). Where("CASE WHEN trigger.version IS NULL THEN true ELSE trigger.version = ? END", request.Event.Version). Scan(ctx); err != nil { diff --git a/internal/triggers/listener.go b/internal/triggers/listener.go index ad21273..0244708 100644 --- a/internal/triggers/listener.go +++ b/internal/triggers/listener.go @@ -56,6 +56,7 @@ func listMatchingTriggers(ctx context.Context, db *bun.DB, evaluator *expression Model(&triggers). Relation("Workflow"). Where("trigger.deleted_at is null"). + Where("workflow_id IN (SELECT id FROM workflows WHERE deleted_at IS NULL)"). Where("event = ?", event.Type). Where("CASE WHEN trigger.version IS NULL THEN true ELSE trigger.version = ? END", event.Version). Scan(ctx); err != nil { diff --git a/internal/triggers/listener_test.go b/internal/triggers/listener_test.go index ffc4f34..ef89147 100644 --- a/internal/triggers/listener_test.go +++ b/internal/triggers/listener_test.go @@ -218,6 +218,23 @@ func TestListMatchingTriggers(t *testing.T) { }, expectedMatched: 0, }, + { + name: "trigger of soft deleted workflow excluded", + triggers: func(t *testing.T, db *bun.DB, workflowID string) { + insertTrigger(t, db, workflowID, "NEW_TRANSACTION", nil, nil) + _, err := db.NewUpdate(). + Model(&workflow.Workflow{}). + Where("id = ?", workflowID). + Set("deleted_at = ?", time.Now()). + Exec(logging.TestingContext()) + require.NoError(t, err) + }, + event: publish.EventMessage{ + Type: "NEW_TRANSACTION", + Version: "v1", + }, + expectedMatched: 0, + }, } for _, tc := range testCases { diff --git a/internal/workflow/manager.go b/internal/workflow/manager.go index ecca898..f605010 100644 --- a/internal/workflow/manager.go +++ b/internal/workflow/manager.go @@ -63,7 +63,7 @@ func (m *WorkflowManager) DeleteWorkflow(ctx context.Context, id string) error { var workflow Workflow - res, err := m.db.NewUpdate().Model(&workflow).Where("id = ?", id).Set("deleted_at = ?", time.Now()).Exec(ctx) + res, err := m.db.NewUpdate().Model(&workflow).Where("id = ?", id).Where("deleted_at IS NULL").Set("deleted_at = ?", time.Now()).Exec(ctx) if err != nil { return err @@ -85,6 +85,7 @@ func (m *WorkflowManager) RunWorkflow(ctx context.Context, id string, variables workflow := Workflow{} if err := m.db.NewSelect(). Where("id = ?", id). + Where("deleted_at IS NULL"). Model(&workflow). Scan(ctx); err != nil { return nil, err @@ -147,6 +148,7 @@ func (m *WorkflowManager) ReadWorkflow(ctx context.Context, id string) (Workflow if err := m.db.NewSelect(). Model(&workflow). Where("id = ?", id). + Where("deleted_at IS NULL"). Scan(ctx); err != nil { return Workflow{}, err } diff --git a/internal/workflow/manager_test.go b/internal/workflow/manager_test.go index dc2a7a3..3e37e8c 100644 --- a/internal/workflow/manager_test.go +++ b/internal/workflow/manager_test.go @@ -131,3 +131,38 @@ func TestWait(t *testing.T) { require.ErrorIs(t, err, ErrInstanceNotFound) }) } + +func TestSoftDeletedWorkflowIsNotUsable(t *testing.T) { + t.Parallel() + + database := srv.NewDatabase(t) + db, err := bunconnect.OpenSQLDB(logging.TestingContext(), bunconnect.ConnectionOptions{ + DatabaseSourceName: database.ConnString(), + }, []bun.QueryHook{}) + require.NoError(t, err) + require.NoError(t, storage.Migrate(logging.TestingContext(), db)) + + manager := NewManager(db, devServer.Client(), "test", uuid.NewString(), false) + + w, err := manager.Create(logging.TestingContext(), Config{ + Stages: []RawStage{{"noop": map[string]any{}}}, + }) + require.NoError(t, err) + require.NoError(t, manager.DeleteWorkflow(logging.TestingContext(), w.ID)) + + t.Run("ReadWorkflow excludes it", func(t *testing.T) { + _, err := manager.ReadWorkflow(logging.TestingContext(), w.ID) + require.Error(t, err) + }) + + t.Run("RunWorkflow refuses it", func(t *testing.T) { + // The select filters deleted_at, so this fails before reaching Temporal. + _, err := manager.RunWorkflow(logging.TestingContext(), w.ID, map[string]string{}) + require.Error(t, err) + }) + + t.Run("re-delete returns not found", func(t *testing.T) { + err := manager.DeleteWorkflow(logging.TestingContext(), w.ID) + require.ErrorIs(t, err, ErrWorkflowNotFound) + }) +} From 87a3e993ff795be03fc3f7c4ff7db70204673e97 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 11 Jun 2026 10:37:15 +0200 Subject: [PATCH 10/22] fix(workflow): return errors instead of panicking in history readers ReadInstanceHistory and ReadStageHistory ran inside HTTP handlers but panicked on json.Unmarshal failures and on any DescribeWorkflowExecution error other than NotFound, and indexed Input.Payloads[0] / Result.Payloads[0] without a length check (index out of range when a workflow/activity was started with no payload). chi's Recoverer turned each into an opaque 500. - Add unmarshalFirstPayload(), which tolerates a nil/empty payload set and returns the decode error instead of panicking. - Replace all four panic sites with wrapped returned errors; the DescribeWorkflowExecution NotFound case still maps to ErrInstanceNotFound. Adds TestUnmarshalFirstPayload (nil/empty/malformed/well-formed). Note: overlaps internal/workflow/manager.go with other PRs in this series (different functions); independent. --- internal/workflow/manager.go | 25 ++++++++++++++++++------- internal/workflow/manager_test.go | 22 ++++++++++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/internal/workflow/manager.go b/internal/workflow/manager.go index f605010..d8ca880 100644 --- a/internal/workflow/manager.go +++ b/internal/workflow/manager.go @@ -9,6 +9,7 @@ import ( "github.com/formancehq/go-libs/v5/pkg/types/pointer" + common "go.temporal.io/api/common/v1" enums "go.temporal.io/api/enums/v1" history "go.temporal.io/api/history/v1" @@ -219,6 +220,16 @@ type StageHistory struct { TerminatedAt *time.Time `json:"terminatedAt,omitempty"` } +// unmarshalFirstPayload decodes the first Temporal payload into v. It tolerates +// a nil/empty payload set (leaving v untouched) instead of panicking on an +// out-of-range index, and returns the decode error rather than panicking. +func unmarshalFirstPayload(payloads *common.Payloads, v any) error { + if payloads == nil || len(payloads.Payloads) == 0 { + return nil + } + return json.Unmarshal(payloads.Payloads[0].Data, v) +} + func (m *WorkflowManager) ReadInstanceHistory(ctx context.Context, instanceID string) ([]StageHistory, error) { historyIterator := m.temporalClient.GetWorkflowHistory(ctx, instanceID+"-main", "", @@ -233,8 +244,8 @@ func (m *WorkflowManager) ReadInstanceHistory(ctx context.Context, instanceID st case enums.EVENT_TYPE_START_CHILD_WORKFLOW_EXECUTION_INITIATED: attributes := event.Attributes.(*history.HistoryEvent_StartChildWorkflowExecutionInitiatedEventAttributes) input := make(map[string]any) - if err := json.Unmarshal(attributes.StartChildWorkflowExecutionInitiatedEventAttributes.Input.Payloads[0].Data, &input); err != nil { - panic(err) + if err := unmarshalFirstPayload(attributes.StartChildWorkflowExecutionInitiatedEventAttributes.Input, &input); err != nil { + return nil, errors.Wrap(err, "unmarshalling stage input") } stageHistory := StageHistory{ Name: attributes.StartChildWorkflowExecutionInitiatedEventAttributes.WorkflowType.Name, @@ -291,7 +302,7 @@ func (m *WorkflowManager) ReadStageHistory(ctx context.Context, instanceID strin if _, ok := err.(*serviceerror.NotFound); ok { return nil, ErrInstanceNotFound } - panic(err) + return nil, errors.Wrap(err, "describing workflow execution") } historyIterator := m.temporalClient.GetWorkflowHistory(ctx, stageID, "", @@ -306,8 +317,8 @@ func (m *WorkflowManager) ReadStageHistory(ctx context.Context, instanceID strin case enums.EVENT_TYPE_ACTIVITY_TASK_SCHEDULED: activityTaskScheduledEventAttributes := event.Attributes.(*history.HistoryEvent_ActivityTaskScheduledEventAttributes).ActivityTaskScheduledEventAttributes input := make(map[string]any) - if err := json.Unmarshal(activityTaskScheduledEventAttributes.Input.Payloads[0].Data, &input); err != nil { - panic(err) + if err := unmarshalFirstPayload(activityTaskScheduledEventAttributes.Input, &input); err != nil { + return nil, errors.Wrap(err, "unmarshalling activity input") } activityHistory := &ActivityHistory{ @@ -344,8 +355,8 @@ func (m *WorkflowManager) ReadStageHistory(ctx context.Context, instanceID strin result := event.Attributes.(*history.HistoryEvent_ActivityTaskCompletedEventAttributes).ActivityTaskCompletedEventAttributes.Result if result != nil && len(result.Payloads) > 0 { output := make(map[string]any) - if err := json.Unmarshal(result.Payloads[0].Data, &output); err != nil { - panic(err) + if err := unmarshalFirstPayload(result, &output); err != nil { + return nil, errors.Wrap(err, "unmarshalling activity output") } // notes(gfyrag): keep compat with format from ledger v1 (since we have moved to ledger v2 api) diff --git a/internal/workflow/manager_test.go b/internal/workflow/manager_test.go index 3e37e8c..24d7b1c 100644 --- a/internal/workflow/manager_test.go +++ b/internal/workflow/manager_test.go @@ -18,8 +18,30 @@ import ( "github.com/formancehq/orchestration/internal/storage" "github.com/stretchr/testify/require" + common "go.temporal.io/api/common/v1" ) +func TestUnmarshalFirstPayload(t *testing.T) { + t.Parallel() + + var v map[string]any + // nil and empty payload sets are tolerated (no panic, no error). + require.NoError(t, unmarshalFirstPayload(nil, &v)) + require.NoError(t, unmarshalFirstPayload(&common.Payloads{}, &v)) + + // A malformed payload returns an error instead of panicking. + err := unmarshalFirstPayload(&common.Payloads{ + Payloads: []*common.Payload{{Data: []byte("{not-json")}}, + }, &v) + require.Error(t, err) + + // A well-formed payload decodes. + require.NoError(t, unmarshalFirstPayload(&common.Payloads{ + Payloads: []*common.Payload{{Data: []byte(`{"a":"b"}`)}}, + }, &v)) + require.Equal(t, map[string]any{"a": "b"}, v) +} + func TestConfig(t *testing.T) { t.Parallel() From 6762188e232e21da1797a3be8915f1b1a208ca84 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 11 Jun 2026 10:49:50 +0200 Subject: [PATCH 11/22] fix(api): map backend errors to 400/404 instead of 500 Most read/write handlers mapped every backend error to 500, and the trigger/workflow create+test handlers returned 500 for malformed request bodies. Unknown ids therefore looked like server faults and bad client payloads were misclassified. - Add api.WriteError(), mapping sql.ErrNoRows, the workflow not-found sentinels and Temporal NotFound to 404, ErrInvalidConfig to 400, and everything else to 500. Use it in readInstance, readWorkflow, runWorkflow, postEvent, abortWorkflowInstance, readInstanceHistory and testTrigger (v1 + v2). - createTrigger / testTrigger: malformed body -> 400 (was 500). - createWorkflow: wrap validation failures as workflow.ErrInvalidConfig so they surface as 400; drop two panics (post-wait GetInstance, json.Marshal) in favour of returned error responses. Tests: TestGetInstanceNotFound (404) and TestCreateWorkflowValidationError (400). Note: edits internal/workflow/manager.go (Create + new sentinel) and many v1/v2 handlers shared with other PRs in this series; independent, different regions. --- internal/api/errors.go | 32 +++++++++++++++++++ .../api/v1/handler_abort_workflow_instance.go | 2 +- internal/api/v1/handler_create_trigger.go | 2 +- internal/api/v1/handler_create_workflow.go | 5 +-- internal/api/v1/handler_post_event.go | 2 +- internal/api/v1/handler_read_instance.go | 2 +- .../api/v1/handler_read_instance_history.go | 2 +- internal/api/v1/handler_read_workflow.go | 2 +- internal/api/v1/handler_run_workflow.go | 5 +-- .../api/v2/handler_abort_workflow_instance.go | 2 +- internal/api/v2/handler_create_trigger.go | 2 +- internal/api/v2/handler_create_workflow.go | 5 +-- .../api/v2/handler_create_workflow_test.go | 13 ++++++++ internal/api/v2/handler_post_event.go | 2 +- internal/api/v2/handler_read_instance.go | 2 +- .../api/v2/handler_read_instance_history.go | 2 +- internal/api/v2/handler_read_instance_test.go | 11 +++++++ internal/api/v2/handler_read_workflow.go | 2 +- internal/api/v2/handler_run_workflow.go | 5 +-- internal/api/v2/handler_test_trigger.go | 4 +-- internal/workflow/manager.go | 5 ++- 21 files changed, 86 insertions(+), 23 deletions(-) create mode 100644 internal/api/errors.go diff --git a/internal/api/errors.go b/internal/api/errors.go new file mode 100644 index 0000000..2c2ae4b --- /dev/null +++ b/internal/api/errors.go @@ -0,0 +1,32 @@ +package api + +import ( + "database/sql" + "net/http" + + sharedapi "github.com/formancehq/go-libs/v3/api" + "github.com/formancehq/orchestration/internal/workflow" + "github.com/pkg/errors" + "go.temporal.io/api/serviceerror" +) + +// WriteError maps a backend error to the appropriate HTTP response: +// - 404 for not-found errors: sql.ErrNoRows, the workflow not-found +// sentinels, and Temporal NotFound (raised when reading the history of an +// unknown instance/stage); +// - 400 for invalid workflow configuration; +// - 500 otherwise. +func WriteError(w http.ResponseWriter, r *http.Request, err error) { + var temporalNotFound *serviceerror.NotFound + switch { + case errors.As(err, &temporalNotFound), + errors.Is(err, sql.ErrNoRows), + errors.Is(err, workflow.ErrInstanceNotFound), + errors.Is(err, workflow.ErrWorkflowNotFound): + sharedapi.NotFound(w, err) + case errors.Is(err, workflow.ErrInvalidConfig): + sharedapi.BadRequest(w, "VALIDATION", err) + default: + sharedapi.InternalServerError(w, r, err) + } +} diff --git a/internal/api/v1/handler_abort_workflow_instance.go b/internal/api/v1/handler_abort_workflow_instance.go index f5bc524..4aa5bbf 100644 --- a/internal/api/v1/handler_abort_workflow_instance.go +++ b/internal/api/v1/handler_abort_workflow_instance.go @@ -11,7 +11,7 @@ import ( func abortWorkflowInstance(backend api2.Backend) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if err := backend.AbortRun(r.Context(), instanceID(r)); err != nil { - api.InternalServerError(w, r, err) + api2.WriteError(w, r, err) return } api.NoContent(w) diff --git a/internal/api/v1/handler_create_trigger.go b/internal/api/v1/handler_create_trigger.go index 4985d9b..5ac3279 100644 --- a/internal/api/v1/handler_create_trigger.go +++ b/internal/api/v1/handler_create_trigger.go @@ -16,7 +16,7 @@ func createTrigger(backend api.Backend) func(writer http.ResponseWriter, request data := triggers.TriggerData{} if err := json.NewDecoder(r.Body).Decode(&data); err != nil { - sharedapi.InternalServerError(w, r, err) + sharedapi.BadRequest(w, "VALIDATION", err) return } diff --git a/internal/api/v1/handler_create_workflow.go b/internal/api/v1/handler_create_workflow.go index b72eb3b..1e67e4c 100644 --- a/internal/api/v1/handler_create_workflow.go +++ b/internal/api/v1/handler_create_workflow.go @@ -25,7 +25,8 @@ func createWorkflow(m api2.Backend) http.HandlerFunc { asJson, err := json.Marshal(payload) if err != nil { - panic(err) + api.InternalServerError(w, r, err) + return } if err := json.Unmarshal(asJson, &config); err != nil { @@ -41,7 +42,7 @@ func createWorkflow(m api2.Backend) http.HandlerFunc { workflow, err := m.Create(r.Context(), config) if err != nil { - api.InternalServerError(w, r, errors.Wrap(err, "creating workflow")) + api2.WriteError(w, r, errors.Wrap(err, "creating workflow")) return } diff --git a/internal/api/v1/handler_post_event.go b/internal/api/v1/handler_post_event.go index 9349666..863fa9f 100644 --- a/internal/api/v1/handler_post_event.go +++ b/internal/api/v1/handler_post_event.go @@ -19,7 +19,7 @@ func postEventToWorkflowInstance(backend api2.Backend) http.HandlerFunc { } if err := backend.PostEvent(r.Context(), instanceID(r), event); err != nil { - api.InternalServerError(w, r, err) + api2.WriteError(w, r, err) return } diff --git a/internal/api/v1/handler_read_instance.go b/internal/api/v1/handler_read_instance.go index 4e27292..2ecd733 100644 --- a/internal/api/v1/handler_read_instance.go +++ b/internal/api/v1/handler_read_instance.go @@ -12,7 +12,7 @@ func readInstance(backend api2.Backend) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { workflows, err := backend.GetInstance(r.Context(), instanceID(r)) if err != nil { - api.InternalServerError(w, r, err) + api2.WriteError(w, r, err) return } diff --git a/internal/api/v1/handler_read_instance_history.go b/internal/api/v1/handler_read_instance_history.go index 1617fc9..e33f4f0 100644 --- a/internal/api/v1/handler_read_instance_history.go +++ b/internal/api/v1/handler_read_instance_history.go @@ -12,7 +12,7 @@ func readInstanceHistory(backend api2.Backend) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { workflows, err := backend.ReadInstanceHistory(r.Context(), instanceID(r)) if err != nil { - api.InternalServerError(w, r, err) + api2.WriteError(w, r, err) return } diff --git a/internal/api/v1/handler_read_workflow.go b/internal/api/v1/handler_read_workflow.go index 0af13a8..3350b48 100644 --- a/internal/api/v1/handler_read_workflow.go +++ b/internal/api/v1/handler_read_workflow.go @@ -12,7 +12,7 @@ func readWorkflow(backend api2.Backend) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { workflow, err := backend.ReadWorkflow(r.Context(), workflowID(r)) if err != nil { - api.InternalServerError(w, r, err) + api2.WriteError(w, r, err) return } diff --git a/internal/api/v1/handler_run_workflow.go b/internal/api/v1/handler_run_workflow.go index 10a71e8..f8bad53 100644 --- a/internal/api/v1/handler_run_workflow.go +++ b/internal/api/v1/handler_run_workflow.go @@ -22,7 +22,7 @@ func runWorkflow(backend api2.Backend) http.HandlerFunc { } instance, err := backend.RunWorkflow(r.Context(), workflowID(r), input) if err != nil { - api.InternalServerError(w, r, err) + api2.WriteError(w, r, err) return } @@ -38,7 +38,8 @@ func runWorkflow(backend api2.Backend) http.HandlerFunc { } ret.Instance, err = backend.GetInstance(r.Context(), instance.ID) if err != nil { - panic(err) + api2.WriteError(w, r, err) + return } api.Created(w, ret) diff --git a/internal/api/v2/handler_abort_workflow_instance.go b/internal/api/v2/handler_abort_workflow_instance.go index 05cb2e1..a45188a 100644 --- a/internal/api/v2/handler_abort_workflow_instance.go +++ b/internal/api/v2/handler_abort_workflow_instance.go @@ -11,7 +11,7 @@ import ( func abortWorkflowInstance(backend api2.Backend) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if err := backend.AbortRun(r.Context(), instanceID(r)); err != nil { - api.InternalServerError(w, r, err) + api2.WriteError(w, r, err) return } api.NoContent(w) diff --git a/internal/api/v2/handler_create_trigger.go b/internal/api/v2/handler_create_trigger.go index d774f83..124094a 100644 --- a/internal/api/v2/handler_create_trigger.go +++ b/internal/api/v2/handler_create_trigger.go @@ -16,7 +16,7 @@ func createTrigger(backend api.Backend) func(writer http.ResponseWriter, request data := triggers.TriggerData{} if err := json.NewDecoder(r.Body).Decode(&data); err != nil { - sharedapi.InternalServerError(w, r, err) + sharedapi.BadRequest(w, "VALIDATION", err) return } diff --git a/internal/api/v2/handler_create_workflow.go b/internal/api/v2/handler_create_workflow.go index 9cbbaec..02db8c4 100644 --- a/internal/api/v2/handler_create_workflow.go +++ b/internal/api/v2/handler_create_workflow.go @@ -25,7 +25,8 @@ func createWorkflow(m api.Backend) http.HandlerFunc { asJson, err := json.Marshal(payload) if err != nil { - panic(err) + sharedapi.InternalServerError(w, r, err) + return } if err := json.Unmarshal(asJson, &config); err != nil { @@ -41,7 +42,7 @@ func createWorkflow(m api.Backend) http.HandlerFunc { workflow, err := m.Create(r.Context(), config) if err != nil { - sharedapi.InternalServerError(w, r, errors.Wrap(err, "creating workflow")) + api.WriteError(w, r, errors.Wrap(err, "creating workflow")) return } diff --git a/internal/api/v2/handler_create_workflow_test.go b/internal/api/v2/handler_create_workflow_test.go index 7a80f21..1ec0c3b 100644 --- a/internal/api/v2/handler_create_workflow_test.go +++ b/internal/api/v2/handler_create_workflow_test.go @@ -23,3 +23,16 @@ func TestCreateWorkflow(t *testing.T) { require.Equal(t, http.StatusCreated, rec.Result().StatusCode) }) } + +func TestCreateWorkflowValidationError(t *testing.T) { + test(t, func(router *chi.Mux, m api.Backend, db *bun.DB) { + // An empty stage specification fails config validation; the API must + // answer 400, not 500. + req := httptest.NewRequest(http.MethodPost, "/workflows", bytes.NewBufferString(`{"stages": [{}]}`)) + rec := httptest.NewRecorder() + + router.ServeHTTP(rec, req) + + require.Equal(t, http.StatusBadRequest, rec.Result().StatusCode) + }) +} diff --git a/internal/api/v2/handler_post_event.go b/internal/api/v2/handler_post_event.go index d314f6b..8931978 100644 --- a/internal/api/v2/handler_post_event.go +++ b/internal/api/v2/handler_post_event.go @@ -19,7 +19,7 @@ func postEventToWorkflowInstance(backend api2.Backend) http.HandlerFunc { } if err := backend.PostEvent(r.Context(), instanceID(r), event); err != nil { - api.InternalServerError(w, r, err) + api2.WriteError(w, r, err) return } diff --git a/internal/api/v2/handler_read_instance.go b/internal/api/v2/handler_read_instance.go index 6fee757..476c82b 100644 --- a/internal/api/v2/handler_read_instance.go +++ b/internal/api/v2/handler_read_instance.go @@ -12,7 +12,7 @@ func readInstance(backend api.Backend) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { workflows, err := backend.GetInstance(r.Context(), instanceID(r)) if err != nil { - sharedapi.InternalServerError(w, r, err) + api.WriteError(w, r, err) return } diff --git a/internal/api/v2/handler_read_instance_history.go b/internal/api/v2/handler_read_instance_history.go index 2f9f2e0..8a48dc0 100644 --- a/internal/api/v2/handler_read_instance_history.go +++ b/internal/api/v2/handler_read_instance_history.go @@ -12,7 +12,7 @@ func readInstanceHistory(backend api2.Backend) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { workflows, err := backend.ReadInstanceHistory(r.Context(), instanceID(r)) if err != nil { - api.InternalServerError(w, r, err) + api2.WriteError(w, r, err) return } diff --git a/internal/api/v2/handler_read_instance_test.go b/internal/api/v2/handler_read_instance_test.go index 1edbe50..7bff496 100644 --- a/internal/api/v2/handler_read_instance_test.go +++ b/internal/api/v2/handler_read_instance_test.go @@ -52,3 +52,14 @@ func TestGetInstance(t *testing.T) { require.Len(t, retrievedInstance.Statuses, 10) }) } + +func TestGetInstanceNotFound(t *testing.T) { + test(t, func(router *chi.Mux, m api.Backend, db *bun.DB) { + req := httptest.NewRequest(http.MethodGet, "/instances/does-not-exist", nil) + rec := httptest.NewRecorder() + + router.ServeHTTP(rec, req) + + require.Equal(t, http.StatusNotFound, rec.Result().StatusCode) + }) +} diff --git a/internal/api/v2/handler_read_workflow.go b/internal/api/v2/handler_read_workflow.go index 2d6ec38..6889d6d 100644 --- a/internal/api/v2/handler_read_workflow.go +++ b/internal/api/v2/handler_read_workflow.go @@ -12,7 +12,7 @@ func readWorkflow(backend api2.Backend) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { workflow, err := backend.ReadWorkflow(r.Context(), workflowID(r)) if err != nil { - api.InternalServerError(w, r, err) + api2.WriteError(w, r, err) return } diff --git a/internal/api/v2/handler_run_workflow.go b/internal/api/v2/handler_run_workflow.go index 801a5a3..e89cce0 100644 --- a/internal/api/v2/handler_run_workflow.go +++ b/internal/api/v2/handler_run_workflow.go @@ -22,7 +22,7 @@ func runWorkflow(backend api2.Backend) http.HandlerFunc { } instance, err := backend.RunWorkflow(r.Context(), workflowID(r), input) if err != nil { - api.InternalServerError(w, r, err) + api2.WriteError(w, r, err) return } @@ -38,7 +38,8 @@ func runWorkflow(backend api2.Backend) http.HandlerFunc { } ret.Instance, err = backend.GetInstance(r.Context(), instance.ID) if err != nil { - panic(err) + api2.WriteError(w, r, err) + return } api.Created(w, ret) diff --git a/internal/api/v2/handler_test_trigger.go b/internal/api/v2/handler_test_trigger.go index a4be567..5f253d7 100644 --- a/internal/api/v2/handler_test_trigger.go +++ b/internal/api/v2/handler_test_trigger.go @@ -15,13 +15,13 @@ func testTrigger(backend api.Backend) http.HandlerFunc { data := make(map[string]any) if err := json.NewDecoder(r.Body).Decode(&data); err != nil { - sharedapi.InternalServerError(w, r, err) + sharedapi.BadRequest(w, "VALIDATION", err) return } o, err := backend.TestTrigger(r.Context(), chi.URLParam(r, "triggerID"), data) if err != nil { - sharedapi.InternalServerError(w, r, err) + api.WriteError(w, r, err) return } diff --git a/internal/workflow/manager.go b/internal/workflow/manager.go index d8ca880..3b8c588 100644 --- a/internal/workflow/manager.go +++ b/internal/workflow/manager.go @@ -24,6 +24,9 @@ import ( var ( ErrInstanceNotFound = errors.New("Instance not found") ErrWorkflowNotFound = errors.New("Workflow not found") + // ErrInvalidConfig wraps workflow configuration validation failures so the + // API can map them to 400 instead of 500. + ErrInvalidConfig = errors.New("invalid workflow configuration") ) const ( @@ -45,7 +48,7 @@ type WorkflowManager struct { func (m *WorkflowManager) Create(ctx context.Context, config Config) (*Workflow, error) { if err := config.Validate(); err != nil { - return nil, err + return nil, fmt.Errorf("%w: %s", ErrInvalidConfig, err) } workflow := New(config) From ddf480af32371ba33d98941c8b2c37c6c5d30afa Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 11 Jun 2026 10:58:26 +0200 Subject: [PATCH 12/22] fix(worker): honour temporal-max-parallel-activities flag The flag is registered as a float64 in go-libs, but it was read with GetInt, which fails on a float64 flag and returns 0. The worker option was therefore always 0 (Temporal default = unlimited), so the operator-set limit never took effect. Read it with GetFloat64, and wire it to MaxConcurrentActivityExecutionSize (activity concurrency) rather than TaskQueueActivitiesPerSecond (a queue-wide rate limit), which is what "max parallel activities" means. Behavioural note: the default (10) now actually caps activity concurrency where it previously had no effect. --- cmd/worker.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmd/worker.go b/cmd/worker.go index e5db6c2..3752a1f 100644 --- a/cmd/worker.go +++ b/cmd/worker.go @@ -35,13 +35,18 @@ func workerOptions(cmd *cobra.Command) fx.Option { stack, _ := cmd.Flags().GetString(stackFlag) temporalTaskQueue, _ := cmd.Flags().GetString(temporal.TemporalTaskQueueFlag) + // The flag is registered as a float64 in go-libs; reading it with GetInt + // silently fails and yields 0, so the configured limit was never applied. temporalMaxParallelActivities, _ := cmd.Flags().GetFloat64(temporal.TemporalMaxParallelActivitiesFlag) topics, _ := cmd.Flags().GetStringSlice(topicsFlag) return fx.Options( stackClientModule(cmd), temporalworker.NewWorkerModule(temporalTaskQueue, worker.Options{ - TaskQueueActivitiesPerSecond: temporalMaxParallelActivities, + // "max parallel activities" caps concurrency, which maps to + // MaxConcurrentActivityExecutionSize, not the queue-wide rate limit + // TaskQueueActivitiesPerSecond it was previously wired to. + MaxConcurrentActivityExecutionSize: int(temporalMaxParallelActivities), }), triggers.NewListenerModule( stack, From 89cde185e93c414c2066fe516579bb1e1be61e77 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 11 Jun 2026 11:03:26 +0200 Subject: [PATCH 13/22] fix(client): remove stray duplicate generation so the SDK module compiles pkg/client is a separate (nested) Go module, so neither the root build nor CI ever compiled it. It was left inconsistent between two Speakeasy generations: formance.go declared 'package client' with github.com/formancehq/flows/pkg/client/... import paths, while sdk.go and the rest declare 'package openapi' (matching .speakeasy/gen.yaml's packageName: openapi and the README's openapi.New entrypoint). formance.go was a leftover duplicate of sdk.go (same ServerList, sdkConfiguration, helpers; SDK renamed to Formance) and nothing referenced it. Remove it and run 'go mod tidy' to restore the missing go.sum entries (cenkalti/backoff/v4, ericlagergren/decimal). The module now builds and vets cleanly. Note: this module is not covered by CI (nested module); verified locally with 'go build ./...' and 'go vet ./...' inside pkg/client. --- pkg/client/formance.go | 178 ----------------------------------------- pkg/client/go.mod | 4 +- pkg/client/go.sum | 3 +- 3 files changed, 3 insertions(+), 182 deletions(-) delete mode 100644 pkg/client/formance.go diff --git a/pkg/client/formance.go b/pkg/client/formance.go deleted file mode 100644 index 5785518..0000000 --- a/pkg/client/formance.go +++ /dev/null @@ -1,178 +0,0 @@ -// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. - -package client - -import ( - "context" - "fmt" - "github.com/formancehq/flows/pkg/client/internal/hooks" - "github.com/formancehq/flows/pkg/client/internal/utils" - "github.com/formancehq/flows/pkg/client/models/components" - "github.com/formancehq/flows/pkg/client/retry" - "net/http" - "time" -) - -// ServerList contains the list of servers available to the SDK -var ServerList = []string{ - "http://localhost:8080/", -} - -// HTTPClient provides an interface for suplying the SDK with a custom HTTP client -type HTTPClient interface { - Do(req *http.Request) (*http.Response, error) -} - -// String provides a helper function to return a pointer to a string -func String(s string) *string { return &s } - -// Bool provides a helper function to return a pointer to a bool -func Bool(b bool) *bool { return &b } - -// Int provides a helper function to return a pointer to an int -func Int(i int) *int { return &i } - -// Int64 provides a helper function to return a pointer to an int64 -func Int64(i int64) *int64 { return &i } - -// Float32 provides a helper function to return a pointer to a float32 -func Float32(f float32) *float32 { return &f } - -// Float64 provides a helper function to return a pointer to a float64 -func Float64(f float64) *float64 { return &f } - -type sdkConfiguration struct { - Client HTTPClient - Security func(context.Context) (interface{}, error) - ServerURL string - ServerIndex int - Language string - OpenAPIDocVersion string - SDKVersion string - GenVersion string - UserAgent string - RetryConfig *retry.Config - Hooks *hooks.Hooks - Timeout *time.Duration -} - -func (c *sdkConfiguration) GetServerDetails() (string, map[string]string) { - if c.ServerURL != "" { - return c.ServerURL, nil - } - - return ServerList[c.ServerIndex], nil -} - -type Formance struct { - Orchestration *Orchestration - - sdkConfiguration sdkConfiguration -} - -type SDKOption func(*Formance) - -// WithServerURL allows the overriding of the default server URL -func WithServerURL(serverURL string) SDKOption { - return func(sdk *Formance) { - sdk.sdkConfiguration.ServerURL = serverURL - } -} - -// WithTemplatedServerURL allows the overriding of the default server URL with a templated URL populated with the provided parameters -func WithTemplatedServerURL(serverURL string, params map[string]string) SDKOption { - return func(sdk *Formance) { - if params != nil { - serverURL = utils.ReplaceParameters(serverURL, params) - } - - sdk.sdkConfiguration.ServerURL = serverURL - } -} - -// WithServerIndex allows the overriding of the default server by index -func WithServerIndex(serverIndex int) SDKOption { - return func(sdk *Formance) { - if serverIndex < 0 || serverIndex >= len(ServerList) { - panic(fmt.Errorf("server index %d out of range", serverIndex)) - } - - sdk.sdkConfiguration.ServerIndex = serverIndex - } -} - -// WithClient allows the overriding of the default HTTP client used by the SDK -func WithClient(client HTTPClient) SDKOption { - return func(sdk *Formance) { - sdk.sdkConfiguration.Client = client - } -} - -// WithSecurity configures the SDK to use the provided security details -func WithSecurity(security components.Security) SDKOption { - return func(sdk *Formance) { - sdk.sdkConfiguration.Security = utils.AsSecuritySource(security) - } -} - -// WithSecuritySource configures the SDK to invoke the Security Source function on each method call to determine authentication -func WithSecuritySource(security func(context.Context) (components.Security, error)) SDKOption { - return func(sdk *Formance) { - sdk.sdkConfiguration.Security = func(ctx context.Context) (interface{}, error) { - return security(ctx) - } - } -} - -func WithRetryConfig(retryConfig retry.Config) SDKOption { - return func(sdk *Formance) { - sdk.sdkConfiguration.RetryConfig = &retryConfig - } -} - -// WithTimeout Optional request timeout applied to each operation -func WithTimeout(timeout time.Duration) SDKOption { - return func(sdk *Formance) { - sdk.sdkConfiguration.Timeout = &timeout - } -} - -// New creates a new instance of the SDK with the provided options -func New(opts ...SDKOption) *Formance { - sdk := &Formance{ - sdkConfiguration: sdkConfiguration{ - Language: "go", - OpenAPIDocVersion: "0.1.0", - SDKVersion: "0.8.0", - GenVersion: "2.409.8", - UserAgent: "speakeasy-sdk/go 0.8.0 2.409.8 0.1.0 github.com/formancehq/flows/pkg/client", - Hooks: hooks.New(), - }, - } - for _, opt := range opts { - opt(sdk) - } - - if sdk.sdkConfiguration.Security == nil { - var envVarSecurity components.Security - if utils.PopulateSecurityFromEnv(&envVarSecurity) { - sdk.sdkConfiguration.Security = utils.AsSecuritySource(envVarSecurity) - } - } - - // Use WithClient to override the default client if you would like to customize the timeout - if sdk.sdkConfiguration.Client == nil { - sdk.sdkConfiguration.Client = &http.Client{Timeout: 60 * time.Second} - } - - currentServerURL, _ := sdk.sdkConfiguration.GetServerDetails() - serverURL := currentServerURL - serverURL, sdk.sdkConfiguration.Client = sdk.sdkConfiguration.Hooks.SDKInit(currentServerURL, sdk.sdkConfiguration.Client) - if serverURL != currentServerURL { - sdk.sdkConfiguration.ServerURL = serverURL - } - - sdk.Orchestration = newOrchestration(sdk.sdkConfiguration) - - return sdk -} diff --git a/pkg/client/go.mod b/pkg/client/go.mod index 180f4dd..e7cb4ec 100644 --- a/pkg/client/go.mod +++ b/pkg/client/go.mod @@ -1,10 +1,8 @@ - module openapi go 1.20 require ( github.com/cenkalti/backoff/v4 v4.2.0 - github.com/ericlagergren/decimal v0.0.0-20221120152707-495c53812d05 - github.com/spyzhov/ajson v0.8.0 + github.com/ericlagergren/decimal v0.0.0-20221120152707-495c53812d05 ) diff --git a/pkg/client/go.sum b/pkg/client/go.sum index 0fee03f..f955779 100644 --- a/pkg/client/go.sum +++ b/pkg/client/go.sum @@ -1,3 +1,4 @@ +github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4= github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/ericlagergren/decimal v0.0.0-20221120152707-495c53812d05 h1:S92OBrGuLLZsyM5ybUzgc/mPjIYk2AZqufieooe98uw= github.com/ericlagergren/decimal v0.0.0-20221120152707-495c53812d05/go.mod h1:M9R1FoZ3y//hwwnJtO51ypFGwm8ZfpxPT/ZLtO1mcgQ= -github.com/spyzhov/ajson v0.8.0/go.mod h1:63V+CGM6f1Bu/p4nLIN8885ojBdt88TbLoSFzyqMuVA= From 28c44e658460d0763f83f753783e8a3d2ad65b0e Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 11 Jun 2026 11:08:26 +0200 Subject: [PATCH 14/22] fix(api): bound v1 list endpoints with a page size The v1 listInstances and listWorkflows handlers passed a zero-value query, and bunpaginate applies no LIMIT when PageSize == 0 -- so each request loaded the entire workflow_instances / workflows table into memory. Read the page size via bunpaginate.GetPageSize (default 15, max 100, overridable with ?pageSize=), as the v2 handlers already do, while keeping the v1 flat-array response shape. Behavioural note: v1 list responses are now bounded to one page; clients needing more pass ?pageSize=. Adds TestListInstancesIsBounded. --- internal/api/v1/handler_list_instances.go | 10 ++++++ .../api/v1/handler_list_instances_test.go | 35 +++++++++++++++++++ internal/api/v1/handler_list_workflows.go | 12 ++++++- 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/internal/api/v1/handler_list_instances.go b/internal/api/v1/handler_list_instances.go index e2a7ea0..1f9cf8a 100644 --- a/internal/api/v1/handler_list_instances.go +++ b/internal/api/v1/handler_list_instances.go @@ -3,6 +3,7 @@ package v1 import ( "net/http" + "github.com/formancehq/go-libs/v3/bun/bunpaginate" "github.com/formancehq/orchestration/internal/workflow" api "github.com/formancehq/orchestration/internal/api" @@ -13,7 +14,16 @@ import ( func listInstances(backend api.Backend) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { + // Bound the query: without a page size, bunpaginate applies no LIMIT, + // loading the entire workflow_instances table per request. + pageSize, err := bunpaginate.GetPageSize(r) + if err != nil { + sharedapi.BadRequest(w, "VALIDATION", err) + return + } + runs, err := backend.ListInstances(r.Context(), workflow.ListInstancesQuery{ + PageSize: pageSize, Options: workflow.ListInstancesOptions{ WorkflowID: r.URL.Query().Get("workflowID"), Running: sharedapi.QueryParamBool(r, "running"), diff --git a/internal/api/v1/handler_list_instances_test.go b/internal/api/v1/handler_list_instances_test.go index 1447306..d79c093 100644 --- a/internal/api/v1/handler_list_instances_test.go +++ b/internal/api/v1/handler_list_instances_test.go @@ -90,3 +90,38 @@ func TestListInstances(t *testing.T) { require.Len(t, instances, 0) }) } + +func TestListInstancesIsBounded(t *testing.T) { + ctx := logging.TestingContext() + + test(t, func(router *chi.Mux, m api.Backend, db *bun.DB) { + w := workflow.New(workflow.Config{}) + _, err := db.NewInsert().Model(&w).Exec(ctx) + require.NoError(t, err) + + for i := 0; i < 20; i++ { + instance := workflow.NewInstance(uuid.NewString(), w.ID) + _, err := db.NewInsert().Model(&instance).Exec(ctx) + require.NoError(t, err) + } + + // Without a page size the default (15) bounds the result instead of + // loading the whole table. + req := httptest.NewRequest(http.MethodGet, "/instances", nil) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + require.Equal(t, http.StatusOK, rec.Result().StatusCode) + instances := make([]workflow.Instance, 0) + sharedapi.ReadResponse(t, rec, &instances) + require.Len(t, instances, 15) + + // An explicit page size is honoured. + req = httptest.NewRequest(http.MethodGet, "/instances?pageSize=5", nil) + rec = httptest.NewRecorder() + router.ServeHTTP(rec, req) + require.Equal(t, http.StatusOK, rec.Result().StatusCode) + instances = make([]workflow.Instance, 0) + sharedapi.ReadResponse(t, rec, &instances) + require.Len(t, instances, 5) + }) +} diff --git a/internal/api/v1/handler_list_workflows.go b/internal/api/v1/handler_list_workflows.go index b7c6aa4..b9ac73d 100644 --- a/internal/api/v1/handler_list_workflows.go +++ b/internal/api/v1/handler_list_workflows.go @@ -13,7 +13,17 @@ import ( func listWorkflows(backend api2.Backend) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - workflows, err := backend.ListWorkflows(r.Context(), bunpaginate.OffsetPaginatedQuery[any]{}) + // Bound the query: without a page size, bunpaginate applies no LIMIT, + // loading the entire workflows table per request. + pageSize, err := bunpaginate.GetPageSize(r) + if err != nil { + api.BadRequest(w, "VALIDATION", err) + return + } + + workflows, err := backend.ListWorkflows(r.Context(), bunpaginate.OffsetPaginatedQuery[any]{ + PageSize: pageSize, + }) if err != nil { api.InternalServerError(w, r, err) return From 6807b996f6aff03f01847957b807ef81717a1700 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 11 Jun 2026 11:12:59 +0200 Subject: [PATCH 15/22] fix(storage): index triggers_occurrences(trigger_id, date) Migration 8 dropped the (trigger_id, event_id) primary key in favour of (id), leaving trigger_id unindexed. ListTriggersOccurrences filters WHERE trigger_id = ? ordered by date, so every page was a sequential scan over an ever-growing table. Add a migration creating the composite index, built CONCURRENTLY (the migrator runs each migration on a dedicated non-transactional connection) and IF NOT EXISTS for idempotency. --- internal/storage/migrations.go | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/internal/storage/migrations.go b/internal/storage/migrations.go index 3e0131c..4b7e460 100644 --- a/internal/storage/migrations.go +++ b/internal/storage/migrations.go @@ -172,6 +172,22 @@ var _migrations = []migrations.Migration{ return nil }, }, + { + // Migration 8 dropped the (trigger_id, event_id) primary key in favour + // of (id), leaving trigger_id unindexed. ListTriggersOccurrences filters + // WHERE trigger_id = ? and orders by date, so without this index every + // page is a sequential scan over an ever-growing table. Built + // CONCURRENTLY to avoid blocking writes during deploy. + Up: func(ctx context.Context, tx bun.IDB) error { + if _, err := tx.ExecContext(ctx, ` + create index concurrently if not exists triggers_occurrences_trigger_id_date_idx + on triggers_occurrences (trigger_id, date); + `); err != nil { + return err + } + return nil + }, + }, } func Migrate(ctx context.Context, db *bun.DB) error { From cd45ca6504fb7d9958f6882576a84a500b0b78de Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Wed, 5 Aug 2026 13:13:00 +0200 Subject: [PATCH 16/22] fix: resolve consolidated reliability blockers --- internal/api/errors.go | 2 +- internal/api/v1/handler_list_instances.go | 2 +- .../v1/handler_list_triggers_occurrences.go | 8 ++ .../handler_list_triggers_occurrences_test.go | 68 ++++++++++++ internal/triggers/expression.go | 21 +++- internal/triggers/manager_test.go | 2 +- internal/triggers/trigger_test.go | 24 +++++ internal/workflow/activities.go | 34 ++++-- internal/workflow/activities_test.go | 34 ++++++ internal/workflow/manager_test.go | 2 +- pkg/client/README.md | 34 +++--- pkg/client/USAGE.md | 4 +- pkg/client/docs/sdks/v1/README.md | 94 ++++++++-------- pkg/client/docs/sdks/v2/README.md | 102 +++++++++--------- pkg/client/go.mod | 2 +- .../internal/hooks/clientcredentials.go | 2 +- pkg/client/internal/utils/form.go | 2 +- pkg/client/internal/utils/json.go | 2 +- pkg/client/internal/utils/pathparams.go | 2 +- pkg/client/internal/utils/queryparams.go | 2 +- pkg/client/internal/utils/retries.go | 2 +- .../components/activitystripetransfer.go | 2 +- pkg/client/models/components/assetholder.go | 2 +- .../models/components/creditwalletrequest.go | 2 +- .../models/components/debitwalletrequest.go | 2 +- pkg/client/models/components/monetary.go | 2 +- pkg/client/models/components/payment.go | 2 +- .../models/components/paymentadjustment.go | 2 +- pkg/client/models/components/posting.go | 2 +- .../models/components/posttransaction.go | 2 +- pkg/client/models/components/security.go | 2 +- pkg/client/models/components/stage.go | 2 +- pkg/client/models/components/stagedelay.go | 2 +- pkg/client/models/components/stagesend.go | 2 +- pkg/client/models/components/stagestatus.go | 2 +- pkg/client/models/components/subject.go | 2 +- pkg/client/models/components/transaction.go | 2 +- pkg/client/models/components/trigger.go | 2 +- .../models/components/triggeroccurrence.go | 2 +- .../components/v2activitystripetransfer.go | 2 +- pkg/client/models/components/v2assetholder.go | 2 +- .../components/v2creditwalletrequest.go | 2 +- .../models/components/v2debitwalletrequest.go | 2 +- pkg/client/models/components/v2monetary.go | 2 +- pkg/client/models/components/v2payment.go | 2 +- .../models/components/v2paymentadjustment.go | 2 +- pkg/client/models/components/v2posting.go | 2 +- .../models/components/v2posttransaction.go | 2 +- pkg/client/models/components/v2stage.go | 2 +- pkg/client/models/components/v2stagedelay.go | 2 +- pkg/client/models/components/v2stagesend.go | 2 +- pkg/client/models/components/v2stagestatus.go | 2 +- pkg/client/models/components/v2subject.go | 2 +- pkg/client/models/components/v2transaction.go | 2 +- pkg/client/models/components/v2trigger.go | 2 +- .../models/components/v2triggeroccurrence.go | 2 +- pkg/client/models/components/v2volume.go | 2 +- pkg/client/models/components/v2wallet.go | 2 +- .../models/components/v2walletwithbalances.go | 2 +- pkg/client/models/components/v2workflow.go | 2 +- .../models/components/v2workflowinstance.go | 2 +- .../components/v2workflowinstancehistory.go | 2 +- .../v2workflowinstancehistorystage.go | 2 +- pkg/client/models/components/volume.go | 2 +- pkg/client/models/components/wallet.go | 2 +- .../models/components/walletwithbalances.go | 2 +- pkg/client/models/components/workflow.go | 2 +- .../models/components/workflowinstance.go | 2 +- .../components/workflowinstancehistory.go | 2 +- .../workflowinstancehistorystage.go | 2 +- pkg/client/models/operations/cancelevent.go | 2 +- pkg/client/models/operations/createtrigger.go | 2 +- .../models/operations/createworkflow.go | 2 +- pkg/client/models/operations/deletetrigger.go | 2 +- .../models/operations/deleteworkflow.go | 2 +- pkg/client/models/operations/getinstance.go | 2 +- .../models/operations/getinstancehistory.go | 2 +- .../operations/getinstancestagehistory.go | 2 +- pkg/client/models/operations/getserverinfo.go | 2 +- pkg/client/models/operations/getworkflow.go | 2 +- pkg/client/models/operations/listinstances.go | 2 +- pkg/client/models/operations/listtriggers.go | 2 +- .../operations/listtriggersoccurrences.go | 2 +- pkg/client/models/operations/listworkflows.go | 2 +- pkg/client/models/operations/options.go | 4 +- pkg/client/models/operations/readtrigger.go | 2 +- pkg/client/models/operations/runworkflow.go | 2 +- pkg/client/models/operations/sendevent.go | 2 +- pkg/client/models/operations/testtrigger.go | 2 +- pkg/client/models/operations/v2cancelevent.go | 2 +- .../models/operations/v2createtrigger.go | 2 +- .../models/operations/v2createworkflow.go | 2 +- .../models/operations/v2deletetrigger.go | 2 +- .../models/operations/v2deleteworkflow.go | 2 +- pkg/client/models/operations/v2getinstance.go | 2 +- .../models/operations/v2getinstancehistory.go | 2 +- .../operations/v2getinstancestagehistory.go | 2 +- .../models/operations/v2getserverinfo.go | 2 +- pkg/client/models/operations/v2getworkflow.go | 2 +- .../models/operations/v2listinstances.go | 2 +- .../models/operations/v2listtriggers.go | 2 +- .../operations/v2listtriggersoccurrences.go | 2 +- .../models/operations/v2listworkflows.go | 2 +- pkg/client/models/operations/v2readtrigger.go | 2 +- pkg/client/models/operations/v2runworkflow.go | 2 +- pkg/client/models/operations/v2sendevent.go | 2 +- pkg/client/sdk.go | 8 +- pkg/client/v1.go | 10 +- pkg/client/v2.go | 10 +- 109 files changed, 408 insertions(+), 237 deletions(-) create mode 100644 internal/api/v1/handler_list_triggers_occurrences_test.go diff --git a/internal/api/errors.go b/internal/api/errors.go index 2c2ae4b..43a753a 100644 --- a/internal/api/errors.go +++ b/internal/api/errors.go @@ -4,7 +4,7 @@ import ( "database/sql" "net/http" - sharedapi "github.com/formancehq/go-libs/v3/api" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" "github.com/formancehq/orchestration/internal/workflow" "github.com/pkg/errors" "go.temporal.io/api/serviceerror" diff --git a/internal/api/v1/handler_list_instances.go b/internal/api/v1/handler_list_instances.go index 1f9cf8a..a96a1fb 100644 --- a/internal/api/v1/handler_list_instances.go +++ b/internal/api/v1/handler_list_instances.go @@ -3,7 +3,7 @@ package v1 import ( "net/http" - "github.com/formancehq/go-libs/v3/bun/bunpaginate" + bunpaginate "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" "github.com/formancehq/orchestration/internal/workflow" api "github.com/formancehq/orchestration/internal/api" diff --git a/internal/api/v1/handler_list_triggers_occurrences.go b/internal/api/v1/handler_list_triggers_occurrences.go index 84cf312..874b718 100644 --- a/internal/api/v1/handler_list_triggers_occurrences.go +++ b/internal/api/v1/handler_list_triggers_occurrences.go @@ -3,6 +3,7 @@ package v1 import ( "net/http" + bunpaginate "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" "github.com/go-chi/chi/v5" sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" @@ -12,7 +13,14 @@ import ( func listTriggersOccurrences(backend api.Backend) func(writer http.ResponseWriter, request *http.Request) { return func(w http.ResponseWriter, r *http.Request) { + pageSize, err := bunpaginate.GetPageSize(r) + if err != nil { + sharedapi.BadRequest(w, "VALIDATION", err) + return + } + triggersOccurrences, err := backend.ListTriggersOccurrences(r.Context(), triggers.ListTriggersOccurrencesQuery{ + PageSize: pageSize, Options: triggers.ListTriggersOccurrencesOptions{ TriggerID: chi.URLParam(r, "triggerID"), }, diff --git a/internal/api/v1/handler_list_triggers_occurrences_test.go b/internal/api/v1/handler_list_triggers_occurrences_test.go new file mode 100644 index 0000000..8761a4d --- /dev/null +++ b/internal/api/v1/handler_list_triggers_occurrences_test.go @@ -0,0 +1,68 @@ +package v1 + +import ( + "net/http" + "net/http/httptest" + "testing" + "time" + + "github.com/formancehq/go-libs/v5/pkg/messaging/publish" + "github.com/formancehq/go-libs/v5/pkg/observe/log" + sharedapi "github.com/formancehq/go-libs/v5/pkg/testing/api" + "github.com/formancehq/orchestration/internal/api" + "github.com/formancehq/orchestration/internal/triggers" + "github.com/formancehq/orchestration/internal/workflow" + "github.com/go-chi/chi/v5" + "github.com/google/uuid" + "github.com/stretchr/testify/require" + "github.com/uptrace/bun" +) + +func TestListTriggersOccurrencesIsBounded(t *testing.T) { + ctx := logging.TestingContext() + + test(t, func(router *chi.Mux, _ api.Backend, db *bun.DB) { + workflowModel := workflow.New(workflow.Config{}) + _, err := db.NewInsert().Model(&workflowModel).Exec(ctx) + require.NoError(t, err) + + trigger, err := triggers.NewTrigger(triggers.TriggerData{ + Event: "TEST_EVENT", + WorkflowID: workflowModel.ID, + }) + require.NoError(t, err) + _, err = db.NewInsert().Model(trigger).Exec(ctx) + require.NoError(t, err) + + for i := 0; i < 20; i++ { + occurrence := triggers.NewTriggerOccurrence( + uuid.NewString(), + trigger.ID, + publish.EventMessage{Type: "TEST_EVENT", Version: "v1"}, + time.Now().Add(time.Duration(i)*time.Second), + ) + _, err = db.NewInsert().Model(&occurrence).Exec(ctx) + require.NoError(t, err) + } + + for _, testCase := range []struct { + name string + query string + expected int + }{ + {name: "default page size", expected: 15}, + {name: "explicit page size", query: "?pageSize=5", expected: 5}, + } { + t.Run(testCase.name, func(t *testing.T) { + req := httptest.NewRequest(http.MethodGet, "/triggers/"+trigger.ID+"/occurrences"+testCase.query, nil) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + require.Equal(t, http.StatusOK, rec.Result().StatusCode) + + occurrences := make([]triggers.Occurrence, 0) + sharedapi.ReadResponse(t, rec, &occurrences) + require.Len(t, occurrences, testCase.expected) + }) + } + }) +} diff --git a/internal/triggers/expression.go b/internal/triggers/expression.go index ccd0990..02e1a54 100644 --- a/internal/triggers/expression.go +++ b/internal/triggers/expression.go @@ -182,6 +182,10 @@ func (h *expressionEvaluator) evalVariables(rawObject any, vars map[string]strin // or a full URL, in which case only its host is retained. With no allowed host, // link() network calls are denied. func NewExpressionEvaluator(httpClient *http.Client, allowedHosts ...string) *expressionEvaluator { + if httpClient == nil { + httpClient = http.DefaultClient + } + hosts := make(map[string]struct{}, len(allowedHosts)) for _, h := range allowedHosts { if h == "" { @@ -193,10 +197,23 @@ func NewExpressionEvaluator(httpClient *http.Client, allowedHosts ...string) *ex } hosts[strings.ToLower(h)] = struct{}{} } - return &expressionEvaluator{ - httpClient: httpClient, + client := *httpClient + evaluator := &expressionEvaluator{ + httpClient: &client, allowedHosts: hosts, } + previousCheckRedirect := client.CheckRedirect + client.CheckRedirect = func(req *http.Request, via []*http.Request) error { + if err := evaluator.checkLinkURL(req.URL.String()); err != nil { + return err + } + if previousCheckRedirect != nil { + return previousCheckRedirect(req, via) + } + return nil + } + + return evaluator } func NewDefaultExpressionEvaluator() *expressionEvaluator { diff --git a/internal/triggers/manager_test.go b/internal/triggers/manager_test.go index cbe03fc..f577b2e 100644 --- a/internal/triggers/manager_test.go +++ b/internal/triggers/manager_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - "github.com/formancehq/go-libs/v3/logging" + "github.com/formancehq/go-libs/v5/pkg/observe/log" "github.com/google/uuid" "github.com/stretchr/testify/require" "github.com/uptrace/bun" diff --git a/internal/triggers/trigger_test.go b/internal/triggers/trigger_test.go index 2789b00..20e3012 100644 --- a/internal/triggers/trigger_test.go +++ b/internal/triggers/trigger_test.go @@ -215,4 +215,28 @@ func TestLinkHostAllowlist(t *testing.T) { require.Equal(t, map[string]string{"role": "admin"}, result) require.True(t, hit) }) + + t.Run("denied when an allowed host redirects to a non-allowlisted host", func(t *testing.T) { + redirectTargetHit := false + redirectTarget := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + redirectTargetHit = true + _, _ = w.Write([]byte(`{"data": {"role": "admin"}}`)) + })) + t.Cleanup(redirectTarget.Close) + + redirector := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + http.Redirect(w, r, redirectTarget.URL, http.StatusFound) + })) + t.Cleanup(redirector.Close) + + redirectedObject := map[string]any{ + "links": []map[string]any{ + {"name": "source_account", "uri": redirector.URL}, + }, + } + e := NewExpressionEvaluator(http.DefaultClient, redirector.URL) + _, err := e.evalVariables(redirectedObject, variables) + require.Error(t, err) + require.False(t, redirectTargetHit, "a redirect target must be checked before it is contacted") + }) } diff --git a/internal/workflow/activities.go b/internal/workflow/activities.go index 79e4d65..f0c49a6 100644 --- a/internal/workflow/activities.go +++ b/internal/workflow/activities.go @@ -72,15 +72,25 @@ func (a Activities) InsertNewInstance(ctx context.Context, workflowID string) (* instance := NewInstance(activity.GetInfo(ctx).WorkflowExecution.ID, workflowID) // Idempotent: the primary key is the (deterministic) workflow execution id, // so a Temporal retry after a lost ack must not fail on the duplicate key. - // The returned instance is rebuilt deterministically, so it is correct even - // when the row already exists. - if _, err := a.db. + // On a duplicate, reload the persisted row so timestamps from the first + // attempt are preserved. + result, err := a.db. NewInsert(). Model(&instance). On("CONFLICT DO NOTHING"). - Exec(ctx); err != nil { + Exec(ctx) + if err != nil { + return nil, err + } + rowsAffected, err := result.RowsAffected() + if err != nil { return nil, err } + if rowsAffected == 0 { + if err := a.db.NewSelect().Model(&instance).WherePK().Scan(ctx); err != nil { + return nil, err + } + } return &instance, nil } @@ -97,13 +107,23 @@ func (a Activities) InsertNewStage(ctx context.Context, instance Instance, ind i stage := NewStage(instance.ID, activity.GetInfo(ctx).WorkflowExecution.RunID, ind) // Idempotent: the primary key is deterministic (instance id + run id + // index), so a Temporal retry after a lost ack must not fail on the - // duplicate key. - if _, err := a.db.NewInsert(). + // duplicate key. Reload duplicates to preserve the original StartedAt. + result, err := a.db.NewInsert(). Model(&stage). On("CONFLICT DO NOTHING"). - Exec(ctx); err != nil { + Exec(ctx) + if err != nil { + return nil, err + } + rowsAffected, err := result.RowsAffected() + if err != nil { return nil, err } + if rowsAffected == 0 { + if err := a.db.NewSelect().Model(&stage).WherePK().Scan(ctx); err != nil { + return nil, err + } + } return &stage, nil } diff --git a/internal/workflow/activities_test.go b/internal/workflow/activities_test.go index 5c229aa..41f71cb 100644 --- a/internal/workflow/activities_test.go +++ b/internal/workflow/activities_test.go @@ -2,6 +2,7 @@ package workflow import ( "testing" + "time" bundebug "github.com/formancehq/go-libs/v5/pkg/storage/bun/debug" "github.com/uptrace/bun" @@ -9,6 +10,7 @@ import ( "github.com/formancehq/go-libs/v5/pkg/messaging/publish" "github.com/formancehq/go-libs/v5/pkg/observe/log" bunconnect "github.com/formancehq/go-libs/v5/pkg/storage/bun/connect" + "github.com/formancehq/orchestration/internal/storage" "github.com/stretchr/testify/require" "go.temporal.io/sdk/testsuite" ) @@ -31,6 +33,7 @@ func TestActivities(t *testing.T) { publisher := publish.InMemory() activities := NewActivities(publisher, db) + require.NoError(t, storage.Migrate(logging.TestingContext(), db)) testSuite := &testsuite.WorkflowTestSuite{} env := testSuite.NewTestActivityEnvironment() @@ -38,4 +41,35 @@ func TestActivities(t *testing.T) { _, err = env.ExecuteActivity(SendWorkflowTerminationEventActivity, NewInstance("vvv", "xxx")) require.NoError(t, err) require.NotEmpty(t, publisher.AllMessages()) + + env.RegisterActivity(activities.InsertNewInstance) + workflowModel := New(Config{}) + _, err = db.NewInsert().Model(&workflowModel).Exec(logging.TestingContext()) + require.NoError(t, err) + + firstValue, err := env.ExecuteActivity(InsertNewInstanceActivity, workflowModel.ID) + require.NoError(t, err) + var firstInstance Instance + require.NoError(t, firstValue.Get(&firstInstance)) + + time.Sleep(time.Millisecond) + secondValue, err := env.ExecuteActivity(InsertNewInstanceActivity, workflowModel.ID) + require.NoError(t, err) + var secondInstance Instance + require.NoError(t, secondValue.Get(&secondInstance)) + require.True(t, firstInstance.CreatedAt.Equal(secondInstance.CreatedAt)) + require.True(t, firstInstance.UpdatedAt.Equal(secondInstance.UpdatedAt)) + + env.RegisterActivity(activities.InsertNewStage) + firstStageValue, err := env.ExecuteActivity(InsertNewStageActivity, firstInstance, 0) + require.NoError(t, err) + var firstStage Stage + require.NoError(t, firstStageValue.Get(&firstStage)) + + time.Sleep(time.Millisecond) + secondStageValue, err := env.ExecuteActivity(InsertNewStageActivity, firstInstance, 0) + require.NoError(t, err) + var secondStage Stage + require.NoError(t, secondStageValue.Get(&secondStage)) + require.True(t, firstStage.StartedAt.Equal(secondStage.StartedAt)) } diff --git a/internal/workflow/manager_test.go b/internal/workflow/manager_test.go index 24d7b1c..ca03788 100644 --- a/internal/workflow/manager_test.go +++ b/internal/workflow/manager_test.go @@ -160,7 +160,7 @@ func TestSoftDeletedWorkflowIsNotUsable(t *testing.T) { database := srv.NewDatabase(t) db, err := bunconnect.OpenSQLDB(logging.TestingContext(), bunconnect.ConnectionOptions{ DatabaseSourceName: database.ConnString(), - }, []bun.QueryHook{}) + }) require.NoError(t, err) require.NoError(t, storage.Migrate(logging.TestingContext(), db)) diff --git a/pkg/client/README.md b/pkg/client/README.md index 1860f83..9602a5b 100644 --- a/pkg/client/README.md +++ b/pkg/client/README.md @@ -35,8 +35,8 @@ package main import ( "context" "log" - "openapi" - "openapi/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/components" ) func main() { @@ -118,9 +118,9 @@ import ( "context" "log" "models/operations" - "openapi" - "openapi/models/components" - "openapi/retry" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client/retry" ) func main() { @@ -160,9 +160,9 @@ package main import ( "context" "log" - "openapi" - "openapi/models/components" - "openapi/retry" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client/retry" ) func main() { @@ -216,9 +216,9 @@ import ( "context" "errors" "log" - "openapi" - "openapi/models/components" - "openapi/models/sdkerrors" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client/models/sdkerrors" ) func main() { @@ -269,8 +269,8 @@ package main import ( "context" "log" - "openapi" - "openapi/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/components" ) func main() { @@ -304,8 +304,8 @@ package main import ( "context" "log" - "openapi" - "openapi/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/components" ) func main() { @@ -378,8 +378,8 @@ package main import ( "context" "log" - "openapi" - "openapi/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/components" ) func main() { diff --git a/pkg/client/USAGE.md b/pkg/client/USAGE.md index 8ad1029..7903cd1 100644 --- a/pkg/client/USAGE.md +++ b/pkg/client/USAGE.md @@ -5,8 +5,8 @@ package main import ( "context" "log" - "openapi" - "openapi/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/components" ) func main() { diff --git a/pkg/client/docs/sdks/v1/README.md b/pkg/client/docs/sdks/v1/README.md index 6fd4a1a..0afd2b2 100644 --- a/pkg/client/docs/sdks/v1/README.md +++ b/pkg/client/docs/sdks/v1/README.md @@ -31,8 +31,8 @@ Get server info package main import( - "openapi/models/components" - "openapi" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" "context" "log" ) @@ -82,9 +82,9 @@ List triggers package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -135,8 +135,8 @@ Create trigger package main import( - "openapi/models/components" - "openapi" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" "context" "log" ) @@ -187,9 +187,9 @@ Read trigger package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -242,9 +242,9 @@ Read trigger package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -297,9 +297,9 @@ List triggers occurrences package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -352,8 +352,8 @@ List registered workflows package main import( - "openapi/models/components" - "openapi" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" "context" "log" ) @@ -403,8 +403,8 @@ Create a workflow package main import( - "openapi/models/components" - "openapi" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" "context" "log" ) @@ -455,9 +455,9 @@ Get a flow by id package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -510,9 +510,9 @@ Delete a flow by id package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -565,9 +565,9 @@ Run workflow package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -620,9 +620,9 @@ List instances of a workflow package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -676,9 +676,9 @@ Get a workflow instance by id package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -731,9 +731,9 @@ Send an event to a running workflow package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -786,9 +786,9 @@ Cancel a running workflow package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -841,9 +841,9 @@ Get a workflow instance history by id package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -896,9 +896,9 @@ Get a workflow instance stage history package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) diff --git a/pkg/client/docs/sdks/v2/README.md b/pkg/client/docs/sdks/v2/README.md index e230fcb..4e54f70 100644 --- a/pkg/client/docs/sdks/v2/README.md +++ b/pkg/client/docs/sdks/v2/README.md @@ -32,8 +32,8 @@ Get server info package main import( - "openapi/models/components" - "openapi" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" "context" "log" ) @@ -83,9 +83,9 @@ List triggers package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -139,8 +139,8 @@ Create trigger package main import( - "openapi/models/components" - "openapi" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" "context" "log" ) @@ -191,9 +191,9 @@ Read trigger package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -246,9 +246,9 @@ Read trigger package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -301,9 +301,9 @@ Test trigger package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -356,9 +356,9 @@ List triggers occurrences package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -413,9 +413,9 @@ List registered workflows package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -469,8 +469,8 @@ Create a workflow package main import( - "openapi/models/components" - "openapi" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" "context" "log" ) @@ -521,9 +521,9 @@ Get a flow by id package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -576,9 +576,9 @@ Delete a flow by id package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -631,9 +631,9 @@ Run workflow package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -686,9 +686,9 @@ List instances of a workflow package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -744,9 +744,9 @@ Get a workflow instance by id package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -799,9 +799,9 @@ Send an event to a running workflow package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -854,9 +854,9 @@ Cancel a running workflow package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -909,9 +909,9 @@ Get a workflow instance history by id package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) @@ -964,9 +964,9 @@ Get a workflow instance stage history package main import( - "openapi/models/components" - "openapi" - "openapi/models/operations" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) diff --git a/pkg/client/go.mod b/pkg/client/go.mod index e7cb4ec..33a5dbc 100644 --- a/pkg/client/go.mod +++ b/pkg/client/go.mod @@ -1,4 +1,4 @@ -module openapi +module github.com/formancehq/flows/pkg/client go 1.20 diff --git a/pkg/client/internal/hooks/clientcredentials.go b/pkg/client/internal/hooks/clientcredentials.go index cde7c67..8ffa2e6 100644 --- a/pkg/client/internal/hooks/clientcredentials.go +++ b/pkg/client/internal/hooks/clientcredentials.go @@ -9,10 +9,10 @@ import ( "encoding/hex" "encoding/json" "fmt" + "github.com/formancehq/flows/pkg/client/models/components" "io" "net/http" "net/url" - "openapi/models/components" "strings" "time" ) diff --git a/pkg/client/internal/utils/form.go b/pkg/client/internal/utils/form.go index a01d3a4..3c52b01 100644 --- a/pkg/client/internal/utils/form.go +++ b/pkg/client/internal/utils/form.go @@ -12,7 +12,7 @@ import ( "github.com/ericlagergren/decimal" - "openapi/types" + "github.com/formancehq/flows/pkg/client/types" ) func populateForm(paramName string, explode bool, objType reflect.Type, objValue reflect.Value, delimiter string, getFieldName func(reflect.StructField) string) url.Values { diff --git a/pkg/client/internal/utils/json.go b/pkg/client/internal/utils/json.go index f740dcd..3fdfd68 100644 --- a/pkg/client/internal/utils/json.go +++ b/pkg/client/internal/utils/json.go @@ -13,7 +13,7 @@ import ( "time" "unsafe" - "openapi/types" + "github.com/formancehq/flows/pkg/client/types" "github.com/ericlagergren/decimal" ) diff --git a/pkg/client/internal/utils/pathparams.go b/pkg/client/internal/utils/pathparams.go index a01f74d..36b464d 100644 --- a/pkg/client/internal/utils/pathparams.go +++ b/pkg/client/internal/utils/pathparams.go @@ -13,7 +13,7 @@ import ( "github.com/ericlagergren/decimal" - "openapi/types" + "github.com/formancehq/flows/pkg/client/types" ) func GenerateURL(_ context.Context, serverURL, path string, pathParams interface{}, globals interface{}) (string, error) { diff --git a/pkg/client/internal/utils/queryparams.go b/pkg/client/internal/utils/queryparams.go index 6bd2b1a..eb52f38 100644 --- a/pkg/client/internal/utils/queryparams.go +++ b/pkg/client/internal/utils/queryparams.go @@ -14,7 +14,7 @@ import ( "github.com/ericlagergren/decimal" - "openapi/types" + "github.com/formancehq/flows/pkg/client/types" ) func PopulateQueryParams(_ context.Context, req *http.Request, queryParams interface{}, globals interface{}) error { diff --git a/pkg/client/internal/utils/retries.go b/pkg/client/internal/utils/retries.go index 03549bf..ebcd076 100644 --- a/pkg/client/internal/utils/retries.go +++ b/pkg/client/internal/utils/retries.go @@ -7,9 +7,9 @@ import ( "errors" "fmt" "github.com/cenkalti/backoff/v4" + "github.com/formancehq/flows/pkg/client/retry" "net/http" "net/url" - "openapi/retry" "strconv" "strings" "time" diff --git a/pkg/client/models/components/activitystripetransfer.go b/pkg/client/models/components/activitystripetransfer.go index 9e09771..f1f4ceb 100644 --- a/pkg/client/models/components/activitystripetransfer.go +++ b/pkg/client/models/components/activitystripetransfer.go @@ -3,8 +3,8 @@ package components import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" ) // Metadata - A set of key/value pairs that you can attach to a transfer object. diff --git a/pkg/client/models/components/assetholder.go b/pkg/client/models/components/assetholder.go index 7a1a2b3..455e265 100644 --- a/pkg/client/models/components/assetholder.go +++ b/pkg/client/models/components/assetholder.go @@ -3,8 +3,8 @@ package components import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" ) type AssetHolder struct { diff --git a/pkg/client/models/components/creditwalletrequest.go b/pkg/client/models/components/creditwalletrequest.go index 91857d8..dc772b4 100644 --- a/pkg/client/models/components/creditwalletrequest.go +++ b/pkg/client/models/components/creditwalletrequest.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/debitwalletrequest.go b/pkg/client/models/components/debitwalletrequest.go index ccd9535..dfe8252 100644 --- a/pkg/client/models/components/debitwalletrequest.go +++ b/pkg/client/models/components/debitwalletrequest.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/monetary.go b/pkg/client/models/components/monetary.go index c2e4ac6..daa2629 100644 --- a/pkg/client/models/components/monetary.go +++ b/pkg/client/models/components/monetary.go @@ -3,8 +3,8 @@ package components import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" ) type Monetary struct { diff --git a/pkg/client/models/components/payment.go b/pkg/client/models/components/payment.go index a0665f4..d1c92a7 100644 --- a/pkg/client/models/components/payment.go +++ b/pkg/client/models/components/payment.go @@ -5,8 +5,8 @@ package components import ( "encoding/json" "fmt" + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" "time" ) diff --git a/pkg/client/models/components/paymentadjustment.go b/pkg/client/models/components/paymentadjustment.go index d605ef1..873b365 100644 --- a/pkg/client/models/components/paymentadjustment.go +++ b/pkg/client/models/components/paymentadjustment.go @@ -3,8 +3,8 @@ package components import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" "time" ) diff --git a/pkg/client/models/components/posting.go b/pkg/client/models/components/posting.go index 2a37eed..7eeb3cd 100644 --- a/pkg/client/models/components/posting.go +++ b/pkg/client/models/components/posting.go @@ -3,8 +3,8 @@ package components import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" ) type Posting struct { diff --git a/pkg/client/models/components/posttransaction.go b/pkg/client/models/components/posttransaction.go index 1bb8ea3..b233d18 100644 --- a/pkg/client/models/components/posttransaction.go +++ b/pkg/client/models/components/posttransaction.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/security.go b/pkg/client/models/components/security.go index 575119c..a3b9c69 100644 --- a/pkg/client/models/components/security.go +++ b/pkg/client/models/components/security.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" ) type Security struct { diff --git a/pkg/client/models/components/stage.go b/pkg/client/models/components/stage.go index 957d906..47d89e1 100644 --- a/pkg/client/models/components/stage.go +++ b/pkg/client/models/components/stage.go @@ -5,7 +5,7 @@ package components import ( "errors" "fmt" - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" ) type StageType string diff --git a/pkg/client/models/components/stagedelay.go b/pkg/client/models/components/stagedelay.go index 6202e66..c11d528 100644 --- a/pkg/client/models/components/stagedelay.go +++ b/pkg/client/models/components/stagedelay.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/stagesend.go b/pkg/client/models/components/stagesend.go index 0a71505..30e8bda 100644 --- a/pkg/client/models/components/stagesend.go +++ b/pkg/client/models/components/stagesend.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/stagestatus.go b/pkg/client/models/components/stagestatus.go index 8654083..3ae595a 100644 --- a/pkg/client/models/components/stagestatus.go +++ b/pkg/client/models/components/stagestatus.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/subject.go b/pkg/client/models/components/subject.go index 04a51be..c181615 100644 --- a/pkg/client/models/components/subject.go +++ b/pkg/client/models/components/subject.go @@ -6,7 +6,7 @@ import ( "encoding/json" "errors" "fmt" - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" ) type SubjectType string diff --git a/pkg/client/models/components/transaction.go b/pkg/client/models/components/transaction.go index 77e2396..d7aed46 100644 --- a/pkg/client/models/components/transaction.go +++ b/pkg/client/models/components/transaction.go @@ -3,8 +3,8 @@ package components import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" "time" ) diff --git a/pkg/client/models/components/trigger.go b/pkg/client/models/components/trigger.go index 9f0492b..cf95dd4 100644 --- a/pkg/client/models/components/trigger.go +++ b/pkg/client/models/components/trigger.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/triggeroccurrence.go b/pkg/client/models/components/triggeroccurrence.go index e1f4352..fde22b8 100644 --- a/pkg/client/models/components/triggeroccurrence.go +++ b/pkg/client/models/components/triggeroccurrence.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2activitystripetransfer.go b/pkg/client/models/components/v2activitystripetransfer.go index 7def3bd..90ad08f 100644 --- a/pkg/client/models/components/v2activitystripetransfer.go +++ b/pkg/client/models/components/v2activitystripetransfer.go @@ -3,8 +3,8 @@ package components import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" ) // V2ActivityStripeTransferMetadata - A set of key/value pairs that you can attach to a transfer object. diff --git a/pkg/client/models/components/v2assetholder.go b/pkg/client/models/components/v2assetholder.go index aef51b8..2c5184b 100644 --- a/pkg/client/models/components/v2assetholder.go +++ b/pkg/client/models/components/v2assetholder.go @@ -3,8 +3,8 @@ package components import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" ) type V2AssetHolder struct { diff --git a/pkg/client/models/components/v2creditwalletrequest.go b/pkg/client/models/components/v2creditwalletrequest.go index c766487..6bf531e 100644 --- a/pkg/client/models/components/v2creditwalletrequest.go +++ b/pkg/client/models/components/v2creditwalletrequest.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2debitwalletrequest.go b/pkg/client/models/components/v2debitwalletrequest.go index 195bf87..666018d 100644 --- a/pkg/client/models/components/v2debitwalletrequest.go +++ b/pkg/client/models/components/v2debitwalletrequest.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2monetary.go b/pkg/client/models/components/v2monetary.go index d7445ed..39a3a74 100644 --- a/pkg/client/models/components/v2monetary.go +++ b/pkg/client/models/components/v2monetary.go @@ -3,8 +3,8 @@ package components import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" ) type V2Monetary struct { diff --git a/pkg/client/models/components/v2payment.go b/pkg/client/models/components/v2payment.go index a69d42a..723f191 100644 --- a/pkg/client/models/components/v2payment.go +++ b/pkg/client/models/components/v2payment.go @@ -5,8 +5,8 @@ package components import ( "encoding/json" "fmt" + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2paymentadjustment.go b/pkg/client/models/components/v2paymentadjustment.go index 80240d6..627780f 100644 --- a/pkg/client/models/components/v2paymentadjustment.go +++ b/pkg/client/models/components/v2paymentadjustment.go @@ -3,8 +3,8 @@ package components import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2posting.go b/pkg/client/models/components/v2posting.go index c0204f8..75a8520 100644 --- a/pkg/client/models/components/v2posting.go +++ b/pkg/client/models/components/v2posting.go @@ -3,8 +3,8 @@ package components import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" ) type V2Posting struct { diff --git a/pkg/client/models/components/v2posttransaction.go b/pkg/client/models/components/v2posttransaction.go index 7c2a928..1b7bfdd 100644 --- a/pkg/client/models/components/v2posttransaction.go +++ b/pkg/client/models/components/v2posttransaction.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2stage.go b/pkg/client/models/components/v2stage.go index 76941f6..c8b6e61 100644 --- a/pkg/client/models/components/v2stage.go +++ b/pkg/client/models/components/v2stage.go @@ -5,7 +5,7 @@ package components import ( "errors" "fmt" - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" ) type V2StageType string diff --git a/pkg/client/models/components/v2stagedelay.go b/pkg/client/models/components/v2stagedelay.go index 3fb7f73..0c3f75d 100644 --- a/pkg/client/models/components/v2stagedelay.go +++ b/pkg/client/models/components/v2stagedelay.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2stagesend.go b/pkg/client/models/components/v2stagesend.go index 7c9e834..c7b24e0 100644 --- a/pkg/client/models/components/v2stagesend.go +++ b/pkg/client/models/components/v2stagesend.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2stagestatus.go b/pkg/client/models/components/v2stagestatus.go index 02cbd13..d4bcec4 100644 --- a/pkg/client/models/components/v2stagestatus.go +++ b/pkg/client/models/components/v2stagestatus.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2subject.go b/pkg/client/models/components/v2subject.go index b0f9e50..84fa255 100644 --- a/pkg/client/models/components/v2subject.go +++ b/pkg/client/models/components/v2subject.go @@ -6,7 +6,7 @@ import ( "encoding/json" "errors" "fmt" - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" ) type V2SubjectType string diff --git a/pkg/client/models/components/v2transaction.go b/pkg/client/models/components/v2transaction.go index 7a8e803..9f74673 100644 --- a/pkg/client/models/components/v2transaction.go +++ b/pkg/client/models/components/v2transaction.go @@ -3,8 +3,8 @@ package components import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2trigger.go b/pkg/client/models/components/v2trigger.go index 5d3a503..5a67cd1 100644 --- a/pkg/client/models/components/v2trigger.go +++ b/pkg/client/models/components/v2trigger.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2triggeroccurrence.go b/pkg/client/models/components/v2triggeroccurrence.go index 9b99452..077c43c 100644 --- a/pkg/client/models/components/v2triggeroccurrence.go +++ b/pkg/client/models/components/v2triggeroccurrence.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2volume.go b/pkg/client/models/components/v2volume.go index 9c89aed..89a24cc 100644 --- a/pkg/client/models/components/v2volume.go +++ b/pkg/client/models/components/v2volume.go @@ -3,8 +3,8 @@ package components import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" ) type V2Volume struct { diff --git a/pkg/client/models/components/v2wallet.go b/pkg/client/models/components/v2wallet.go index 2743b27..9d0e9a6 100644 --- a/pkg/client/models/components/v2wallet.go +++ b/pkg/client/models/components/v2wallet.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2walletwithbalances.go b/pkg/client/models/components/v2walletwithbalances.go index d3e0664..946af98 100644 --- a/pkg/client/models/components/v2walletwithbalances.go +++ b/pkg/client/models/components/v2walletwithbalances.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2workflow.go b/pkg/client/models/components/v2workflow.go index 07527a8..c823d98 100644 --- a/pkg/client/models/components/v2workflow.go +++ b/pkg/client/models/components/v2workflow.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2workflowinstance.go b/pkg/client/models/components/v2workflowinstance.go index b83bbc5..9cf631c 100644 --- a/pkg/client/models/components/v2workflowinstance.go +++ b/pkg/client/models/components/v2workflowinstance.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2workflowinstancehistory.go b/pkg/client/models/components/v2workflowinstancehistory.go index affcc79..0034a94 100644 --- a/pkg/client/models/components/v2workflowinstancehistory.go +++ b/pkg/client/models/components/v2workflowinstancehistory.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/v2workflowinstancehistorystage.go b/pkg/client/models/components/v2workflowinstancehistorystage.go index 3a05930..9dc5676 100644 --- a/pkg/client/models/components/v2workflowinstancehistorystage.go +++ b/pkg/client/models/components/v2workflowinstancehistorystage.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/volume.go b/pkg/client/models/components/volume.go index cfbe4f5..cfa8427 100644 --- a/pkg/client/models/components/volume.go +++ b/pkg/client/models/components/volume.go @@ -3,8 +3,8 @@ package components import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "math/big" - "openapi/internal/utils" ) type Volume struct { diff --git a/pkg/client/models/components/wallet.go b/pkg/client/models/components/wallet.go index 24eb6dd..01123a2 100644 --- a/pkg/client/models/components/wallet.go +++ b/pkg/client/models/components/wallet.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/walletwithbalances.go b/pkg/client/models/components/walletwithbalances.go index 94e13dc..0252604 100644 --- a/pkg/client/models/components/walletwithbalances.go +++ b/pkg/client/models/components/walletwithbalances.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/workflow.go b/pkg/client/models/components/workflow.go index 2c4eb09..bac2b2a 100644 --- a/pkg/client/models/components/workflow.go +++ b/pkg/client/models/components/workflow.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/workflowinstance.go b/pkg/client/models/components/workflowinstance.go index 12a7047..e0ddc77 100644 --- a/pkg/client/models/components/workflowinstance.go +++ b/pkg/client/models/components/workflowinstance.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/workflowinstancehistory.go b/pkg/client/models/components/workflowinstancehistory.go index 4c5deea..2cb9713 100644 --- a/pkg/client/models/components/workflowinstancehistory.go +++ b/pkg/client/models/components/workflowinstancehistory.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/components/workflowinstancehistorystage.go b/pkg/client/models/components/workflowinstancehistorystage.go index 229315c..bb6c6a5 100644 --- a/pkg/client/models/components/workflowinstancehistorystage.go +++ b/pkg/client/models/components/workflowinstancehistorystage.go @@ -3,7 +3,7 @@ package components import ( - "openapi/internal/utils" + "github.com/formancehq/flows/pkg/client/internal/utils" "time" ) diff --git a/pkg/client/models/operations/cancelevent.go b/pkg/client/models/operations/cancelevent.go index 91bcf9a..69968c2 100644 --- a/pkg/client/models/operations/cancelevent.go +++ b/pkg/client/models/operations/cancelevent.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type CancelEventRequest struct { diff --git a/pkg/client/models/operations/createtrigger.go b/pkg/client/models/operations/createtrigger.go index b924137..b1c5119 100644 --- a/pkg/client/models/operations/createtrigger.go +++ b/pkg/client/models/operations/createtrigger.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type CreateTriggerResponse struct { diff --git a/pkg/client/models/operations/createworkflow.go b/pkg/client/models/operations/createworkflow.go index fb47f79..1256e10 100644 --- a/pkg/client/models/operations/createworkflow.go +++ b/pkg/client/models/operations/createworkflow.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type CreateWorkflowResponse struct { diff --git a/pkg/client/models/operations/deletetrigger.go b/pkg/client/models/operations/deletetrigger.go index 70b186c..d12c6e2 100644 --- a/pkg/client/models/operations/deletetrigger.go +++ b/pkg/client/models/operations/deletetrigger.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type DeleteTriggerRequest struct { diff --git a/pkg/client/models/operations/deleteworkflow.go b/pkg/client/models/operations/deleteworkflow.go index 02494b8..087cf2f 100644 --- a/pkg/client/models/operations/deleteworkflow.go +++ b/pkg/client/models/operations/deleteworkflow.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type DeleteWorkflowRequest struct { diff --git a/pkg/client/models/operations/getinstance.go b/pkg/client/models/operations/getinstance.go index d85f2d1..9cf9dba 100644 --- a/pkg/client/models/operations/getinstance.go +++ b/pkg/client/models/operations/getinstance.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type GetInstanceRequest struct { diff --git a/pkg/client/models/operations/getinstancehistory.go b/pkg/client/models/operations/getinstancehistory.go index 62248da..0ca4c17 100644 --- a/pkg/client/models/operations/getinstancehistory.go +++ b/pkg/client/models/operations/getinstancehistory.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type GetInstanceHistoryRequest struct { diff --git a/pkg/client/models/operations/getinstancestagehistory.go b/pkg/client/models/operations/getinstancestagehistory.go index 9a75d26..6e25681 100644 --- a/pkg/client/models/operations/getinstancestagehistory.go +++ b/pkg/client/models/operations/getinstancestagehistory.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type GetInstanceStageHistoryRequest struct { diff --git a/pkg/client/models/operations/getserverinfo.go b/pkg/client/models/operations/getserverinfo.go index be93577..e9f1549 100644 --- a/pkg/client/models/operations/getserverinfo.go +++ b/pkg/client/models/operations/getserverinfo.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type GetServerInfoResponse struct { diff --git a/pkg/client/models/operations/getworkflow.go b/pkg/client/models/operations/getworkflow.go index 86159c7..552703b 100644 --- a/pkg/client/models/operations/getworkflow.go +++ b/pkg/client/models/operations/getworkflow.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type GetWorkflowRequest struct { diff --git a/pkg/client/models/operations/listinstances.go b/pkg/client/models/operations/listinstances.go index 2a7fb59..9a503a5 100644 --- a/pkg/client/models/operations/listinstances.go +++ b/pkg/client/models/operations/listinstances.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type ListInstancesRequest struct { diff --git a/pkg/client/models/operations/listtriggers.go b/pkg/client/models/operations/listtriggers.go index 64fbd4e..72edf2c 100644 --- a/pkg/client/models/operations/listtriggers.go +++ b/pkg/client/models/operations/listtriggers.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type ListTriggersRequest struct { diff --git a/pkg/client/models/operations/listtriggersoccurrences.go b/pkg/client/models/operations/listtriggersoccurrences.go index 58ffc01..0b0637e 100644 --- a/pkg/client/models/operations/listtriggersoccurrences.go +++ b/pkg/client/models/operations/listtriggersoccurrences.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type ListTriggersOccurrencesRequest struct { diff --git a/pkg/client/models/operations/listworkflows.go b/pkg/client/models/operations/listworkflows.go index 77e863b..ea9f10b 100644 --- a/pkg/client/models/operations/listworkflows.go +++ b/pkg/client/models/operations/listworkflows.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type ListWorkflowsResponse struct { diff --git a/pkg/client/models/operations/options.go b/pkg/client/models/operations/options.go index db37fac..9f2db90 100644 --- a/pkg/client/models/operations/options.go +++ b/pkg/client/models/operations/options.go @@ -4,8 +4,8 @@ package operations import ( "errors" - "openapi/internal/utils" - "openapi/retry" + "github.com/formancehq/flows/pkg/client/internal/utils" + "github.com/formancehq/flows/pkg/client/retry" "time" ) diff --git a/pkg/client/models/operations/readtrigger.go b/pkg/client/models/operations/readtrigger.go index cd30d8d..9b7daf0 100644 --- a/pkg/client/models/operations/readtrigger.go +++ b/pkg/client/models/operations/readtrigger.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type ReadTriggerRequest struct { diff --git a/pkg/client/models/operations/runworkflow.go b/pkg/client/models/operations/runworkflow.go index ba194f7..32808d6 100644 --- a/pkg/client/models/operations/runworkflow.go +++ b/pkg/client/models/operations/runworkflow.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type RunWorkflowRequest struct { diff --git a/pkg/client/models/operations/sendevent.go b/pkg/client/models/operations/sendevent.go index 53aacd5..34df589 100644 --- a/pkg/client/models/operations/sendevent.go +++ b/pkg/client/models/operations/sendevent.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type SendEventRequestBody struct { diff --git a/pkg/client/models/operations/testtrigger.go b/pkg/client/models/operations/testtrigger.go index db41c2a..94f1f6e 100644 --- a/pkg/client/models/operations/testtrigger.go +++ b/pkg/client/models/operations/testtrigger.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type TestTriggerRequest struct { diff --git a/pkg/client/models/operations/v2cancelevent.go b/pkg/client/models/operations/v2cancelevent.go index 33b81a6..1146ce5 100644 --- a/pkg/client/models/operations/v2cancelevent.go +++ b/pkg/client/models/operations/v2cancelevent.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2CancelEventRequest struct { diff --git a/pkg/client/models/operations/v2createtrigger.go b/pkg/client/models/operations/v2createtrigger.go index a22f497..86120a6 100644 --- a/pkg/client/models/operations/v2createtrigger.go +++ b/pkg/client/models/operations/v2createtrigger.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2CreateTriggerResponse struct { diff --git a/pkg/client/models/operations/v2createworkflow.go b/pkg/client/models/operations/v2createworkflow.go index c5ae3c0..c3beece 100644 --- a/pkg/client/models/operations/v2createworkflow.go +++ b/pkg/client/models/operations/v2createworkflow.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2CreateWorkflowResponse struct { diff --git a/pkg/client/models/operations/v2deletetrigger.go b/pkg/client/models/operations/v2deletetrigger.go index a91bac2..034d167 100644 --- a/pkg/client/models/operations/v2deletetrigger.go +++ b/pkg/client/models/operations/v2deletetrigger.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2DeleteTriggerRequest struct { diff --git a/pkg/client/models/operations/v2deleteworkflow.go b/pkg/client/models/operations/v2deleteworkflow.go index aacbb14..b17b7a7 100644 --- a/pkg/client/models/operations/v2deleteworkflow.go +++ b/pkg/client/models/operations/v2deleteworkflow.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2DeleteWorkflowRequest struct { diff --git a/pkg/client/models/operations/v2getinstance.go b/pkg/client/models/operations/v2getinstance.go index c2c9628..5095356 100644 --- a/pkg/client/models/operations/v2getinstance.go +++ b/pkg/client/models/operations/v2getinstance.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2GetInstanceRequest struct { diff --git a/pkg/client/models/operations/v2getinstancehistory.go b/pkg/client/models/operations/v2getinstancehistory.go index 097e29d..f944651 100644 --- a/pkg/client/models/operations/v2getinstancehistory.go +++ b/pkg/client/models/operations/v2getinstancehistory.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2GetInstanceHistoryRequest struct { diff --git a/pkg/client/models/operations/v2getinstancestagehistory.go b/pkg/client/models/operations/v2getinstancestagehistory.go index 7b817c0..1a4cc81 100644 --- a/pkg/client/models/operations/v2getinstancestagehistory.go +++ b/pkg/client/models/operations/v2getinstancestagehistory.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2GetInstanceStageHistoryRequest struct { diff --git a/pkg/client/models/operations/v2getserverinfo.go b/pkg/client/models/operations/v2getserverinfo.go index 109b13c..0dc868b 100644 --- a/pkg/client/models/operations/v2getserverinfo.go +++ b/pkg/client/models/operations/v2getserverinfo.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2GetServerInfoResponse struct { diff --git a/pkg/client/models/operations/v2getworkflow.go b/pkg/client/models/operations/v2getworkflow.go index 88269d1..1b264c4 100644 --- a/pkg/client/models/operations/v2getworkflow.go +++ b/pkg/client/models/operations/v2getworkflow.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2GetWorkflowRequest struct { diff --git a/pkg/client/models/operations/v2listinstances.go b/pkg/client/models/operations/v2listinstances.go index a481c22..394cc47 100644 --- a/pkg/client/models/operations/v2listinstances.go +++ b/pkg/client/models/operations/v2listinstances.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2ListInstancesRequest struct { diff --git a/pkg/client/models/operations/v2listtriggers.go b/pkg/client/models/operations/v2listtriggers.go index 78451e8..21f35f0 100644 --- a/pkg/client/models/operations/v2listtriggers.go +++ b/pkg/client/models/operations/v2listtriggers.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2ListTriggersRequest struct { diff --git a/pkg/client/models/operations/v2listtriggersoccurrences.go b/pkg/client/models/operations/v2listtriggersoccurrences.go index 4da007a..ae1e0b2 100644 --- a/pkg/client/models/operations/v2listtriggersoccurrences.go +++ b/pkg/client/models/operations/v2listtriggersoccurrences.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2ListTriggersOccurrencesRequest struct { diff --git a/pkg/client/models/operations/v2listworkflows.go b/pkg/client/models/operations/v2listworkflows.go index a849397..ed4d77b 100644 --- a/pkg/client/models/operations/v2listworkflows.go +++ b/pkg/client/models/operations/v2listworkflows.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2ListWorkflowsRequest struct { diff --git a/pkg/client/models/operations/v2readtrigger.go b/pkg/client/models/operations/v2readtrigger.go index 3d279cc..8ebaf50 100644 --- a/pkg/client/models/operations/v2readtrigger.go +++ b/pkg/client/models/operations/v2readtrigger.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2ReadTriggerRequest struct { diff --git a/pkg/client/models/operations/v2runworkflow.go b/pkg/client/models/operations/v2runworkflow.go index 9a9ca09..f258376 100644 --- a/pkg/client/models/operations/v2runworkflow.go +++ b/pkg/client/models/operations/v2runworkflow.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2RunWorkflowRequest struct { diff --git a/pkg/client/models/operations/v2sendevent.go b/pkg/client/models/operations/v2sendevent.go index 9599ef3..fe18716 100644 --- a/pkg/client/models/operations/v2sendevent.go +++ b/pkg/client/models/operations/v2sendevent.go @@ -3,7 +3,7 @@ package operations import ( - "openapi/models/components" + "github.com/formancehq/flows/pkg/client/models/components" ) type V2SendEventRequestBody struct { diff --git a/pkg/client/sdk.go b/pkg/client/sdk.go index 7226a21..2ca0925 100644 --- a/pkg/client/sdk.go +++ b/pkg/client/sdk.go @@ -5,11 +5,11 @@ package openapi import ( "context" "fmt" + "github.com/formancehq/flows/pkg/client/internal/hooks" + "github.com/formancehq/flows/pkg/client/internal/utils" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client/retry" "net/http" - "openapi/internal/hooks" - "openapi/internal/utils" - "openapi/models/components" - "openapi/retry" "time" ) diff --git a/pkg/client/v1.go b/pkg/client/v1.go index 1ad16bc..5cd9992 100644 --- a/pkg/client/v1.go +++ b/pkg/client/v1.go @@ -7,14 +7,14 @@ import ( "context" "fmt" "github.com/cenkalti/backoff/v4" + "github.com/formancehq/flows/pkg/client/internal/hooks" + "github.com/formancehq/flows/pkg/client/internal/utils" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client/models/operations" + "github.com/formancehq/flows/pkg/client/models/sdkerrors" "io" "net/http" "net/url" - "openapi/internal/hooks" - "openapi/internal/utils" - "openapi/models/components" - "openapi/models/operations" - "openapi/models/sdkerrors" ) type V1 struct { diff --git a/pkg/client/v2.go b/pkg/client/v2.go index f9bc834..0141fcb 100644 --- a/pkg/client/v2.go +++ b/pkg/client/v2.go @@ -7,14 +7,14 @@ import ( "context" "fmt" "github.com/cenkalti/backoff/v4" + "github.com/formancehq/flows/pkg/client/internal/hooks" + "github.com/formancehq/flows/pkg/client/internal/utils" + "github.com/formancehq/flows/pkg/client/models/components" + "github.com/formancehq/flows/pkg/client/models/operations" + "github.com/formancehq/flows/pkg/client/models/sdkerrors" "io" "net/http" "net/url" - "openapi/internal/hooks" - "openapi/internal/utils" - "openapi/models/components" - "openapi/models/operations" - "openapi/models/sdkerrors" ) type V2 struct { From 44c5fcdc5e0a069902cf6bdd2e1b6e3691e4695d Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Wed, 5 Aug 2026 13:18:32 +0200 Subject: [PATCH 17/22] test: compare retries with persisted timestamps --- internal/workflow/activities_test.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/internal/workflow/activities_test.go b/internal/workflow/activities_test.go index 41f71cb..36cd0a3 100644 --- a/internal/workflow/activities_test.go +++ b/internal/workflow/activities_test.go @@ -51,25 +51,33 @@ func TestActivities(t *testing.T) { require.NoError(t, err) var firstInstance Instance require.NoError(t, firstValue.Get(&firstInstance)) + persistedInstance := Instance{ID: firstInstance.ID} + require.NoError(t, db.NewSelect().Model(&persistedInstance).WherePK().Scan(logging.TestingContext())) time.Sleep(time.Millisecond) secondValue, err := env.ExecuteActivity(InsertNewInstanceActivity, workflowModel.ID) require.NoError(t, err) var secondInstance Instance require.NoError(t, secondValue.Get(&secondInstance)) - require.True(t, firstInstance.CreatedAt.Equal(secondInstance.CreatedAt)) - require.True(t, firstInstance.UpdatedAt.Equal(secondInstance.UpdatedAt)) + require.True(t, persistedInstance.CreatedAt.Equal(secondInstance.CreatedAt)) + require.True(t, persistedInstance.UpdatedAt.Equal(secondInstance.UpdatedAt)) env.RegisterActivity(activities.InsertNewStage) firstStageValue, err := env.ExecuteActivity(InsertNewStageActivity, firstInstance, 0) require.NoError(t, err) var firstStage Stage require.NoError(t, firstStageValue.Get(&firstStage)) + persistedStage := Stage{ + InstanceID: firstStage.InstanceID, + TemporalRunID: firstStage.TemporalRunID, + Number: firstStage.Number, + } + require.NoError(t, db.NewSelect().Model(&persistedStage).WherePK().Scan(logging.TestingContext())) time.Sleep(time.Millisecond) secondStageValue, err := env.ExecuteActivity(InsertNewStageActivity, firstInstance, 0) require.NoError(t, err) var secondStage Stage require.NoError(t, secondStageValue.Get(&secondStage)) - require.True(t, firstStage.StartedAt.Equal(secondStage.StartedAt)) + require.True(t, persistedStage.StartedAt.Equal(secondStage.StartedAt)) } From 5af27ee365aaa06f2f7fb02482dd5a164884ef1d Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Wed, 5 Aug 2026 13:33:09 +0200 Subject: [PATCH 18/22] fix(api): expose v1 pagination metadata --- cmd/root.go | 49 +++--- cmd/root_test.go | 26 +++ cmd/worker.go | 4 +- internal/api/v1/handler_list_instances.go | 24 +-- .../api/v1/handler_list_instances_test.go | 31 +++- internal/api/v1/handler_list_triggers.go | 2 +- .../v1/handler_list_triggers_occurrences.go | 25 ++- .../handler_list_triggers_occurrences_test.go | 36 +++-- internal/api/v1/handler_list_workflows.go | 14 +- internal/api/v1/pagination.go | 26 +++ internal/triggers/module.go | 7 +- openapi.yaml | 103 +++++++++--- openapi/v1.yaml | 72 ++++++++- pkg/client/.speakeasy/gen.lock | 19 ++- pkg/client/.speakeasy/gen.yaml | 4 +- pkg/client/README.md | 52 +++--- pkg/client/USAGE.md | 6 +- .../activitycreatetransferinitiation.md | 17 ++ ...ctivitycreatetransferinitiationmetadata.md | 10 ++ .../activitycreatetransferinitiationtype.md | 14 ++ .../models/components/listrunsresponse.md | 6 +- .../listtriggersoccurrencesresponse.md | 6 +- .../models/components/listtriggersresponse.md | 6 +- .../components/listworkflowsresponse.md | 6 +- pkg/client/docs/models/components/payment.md | 2 +- .../docs/models/components/paymenttype.md | 11 ++ .../components/stagesenddestinationaccount.md | 10 +- .../components/stagesenddestinationpayment.md | 8 +- .../components/stagesendsourceaccount.md | 10 +- .../components/stagesendsourcepayment.md | 10 +- pkg/client/docs/models/components/type.md | 9 +- .../v2activitycreatetransferinitiation.md | 17 ++ ...ctivitycreatetransferinitiationmetadata.md | 10 ++ .../v2activitycreatetransferinitiationtype.md | 14 ++ .../v2stagesenddestinationaccount.md | 10 +- .../v2stagesenddestinationpayment.md | 8 +- .../v2stagesenddestinationpaymenttype.md | 14 ++ .../components/v2stagesendsourceaccount.md | 10 +- .../components/v2stagesendsourcepayment.md | 10 +- .../v2workflowinstancehistorystageinput.md | 27 ++-- .../workflowinstancehistorystageinput.md | 29 ++-- .../models/operations/listinstancesrequest.md | 10 +- .../listtriggersoccurrencesrequest.md | 8 +- .../models/operations/listtriggersrequest.md | 8 +- .../models/operations/listworkflowsrequest.md | 9 ++ pkg/client/docs/sdks/v1/README.md | 98 +++++++----- pkg/client/docs/sdks/v2/README.md | 92 +++++------ .../activitycreatetransferinitiation.go | 149 ++++++++++++++++++ .../models/components/listrunsresponse.go | 34 +++- .../listtriggersoccurrencesresponse.go | 34 +++- .../models/components/listtriggersresponse.go | 34 +++- .../components/listworkflowsresponse.go | 34 +++- pkg/client/models/components/payment.go | 24 +-- .../components/stagesenddestinationaccount.go | 41 +++++ .../components/stagesenddestinationpayment.go | 72 +++++++++ .../components/stagesendsourceaccount.go | 41 +++++ .../components/stagesendsourcepayment.go | 59 +++++++ .../v2activitycreatetransferinitiation.go | 149 ++++++++++++++++++ .../v2stagesenddestinationaccount.go | 41 +++++ .../v2stagesenddestinationpayment.go | 72 +++++++++ .../components/v2stagesendsourceaccount.go | 41 +++++ .../components/v2stagesendsourcepayment.go | 59 +++++++ .../v2workflowinstancehistorystageinput.go | 30 ++-- .../workflowinstancehistorystageinput.go | 32 ++-- pkg/client/models/operations/listinstances.go | 35 ++++ pkg/client/models/operations/listtriggers.go | 35 ++++ .../operations/listtriggersoccurrences.go | 35 ++++ pkg/client/models/operations/listworkflows.go | 38 +++++ .../models/operations/v2listinstances.go | 14 +- .../models/operations/v2listtriggers.go | 14 +- .../operations/v2listtriggersoccurrences.go | 14 +- .../models/operations/v2listworkflows.go | 14 +- pkg/client/orchestration.go | 2 +- pkg/client/sdk.go | 6 +- pkg/client/v1.go | 12 +- pkg/client/v2.go | 2 +- 76 files changed, 1829 insertions(+), 337 deletions(-) create mode 100644 cmd/root_test.go create mode 100644 internal/api/v1/pagination.go create mode 100644 pkg/client/docs/models/components/activitycreatetransferinitiation.md create mode 100644 pkg/client/docs/models/components/activitycreatetransferinitiationmetadata.md create mode 100644 pkg/client/docs/models/components/activitycreatetransferinitiationtype.md create mode 100644 pkg/client/docs/models/components/paymenttype.md create mode 100644 pkg/client/docs/models/components/v2activitycreatetransferinitiation.md create mode 100644 pkg/client/docs/models/components/v2activitycreatetransferinitiationmetadata.md create mode 100644 pkg/client/docs/models/components/v2activitycreatetransferinitiationtype.md create mode 100644 pkg/client/docs/models/components/v2stagesenddestinationpaymenttype.md create mode 100644 pkg/client/docs/models/operations/listworkflowsrequest.md create mode 100644 pkg/client/models/components/activitycreatetransferinitiation.go create mode 100644 pkg/client/models/components/v2activitycreatetransferinitiation.go diff --git a/cmd/root.go b/cmd/root.go index c2282bc..3153151 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -44,6 +44,7 @@ const ( topicsFlag = "topics" listenFlag = "listen" workerFlag = "worker" + stackHTTPClientName = "stack" ) func NewRootCommand() *cobra.Command { @@ -70,6 +71,30 @@ func Execute() { service.Execute(NewRootCommand()) } +func stackHTTPClientModule(cmd *cobra.Command) fx.Option { + return fx.Provide(fx.Annotate(func() *http.Client { + httpClient := &http.Client{ + Transport: otlp.NewRoundTripper(http.DefaultTransport, service.IsDebug(cmd)), + } + + stackClientID, _ := cmd.Flags().GetString(stackClientIDFlag) + stackClientSecret, _ := cmd.Flags().GetString(stackClientSecretFlag) + stackURL, _ := cmd.Flags().GetString(stackURLFlag) + + if stackClientID == "" { + return httpClient + } + oauthConfig := clientcredentials.Config{ + ClientID: stackClientID, + ClientSecret: stackClientSecret, + TokenURL: fmt.Sprintf("%s/api/auth/oauth/token", stackURL), + Scopes: []string{"openid", "ledger:read", "ledger:write", "wallets:read", "wallets:write", "payments:read", "payments:write"}, + } + return oauthConfig.Client(context.WithValue(context.Background(), + oauth2.HTTPClient, httpClient)) + }, fx.ResultTags(`name:"stack"`))) +} + func commonOptions(cmd *cobra.Command) (fx.Option, error) { connectionOptions, err := bunconnect.ConnectionOptionsFromFlags(cmd.Flags(), cmd.Context()) if err != nil { @@ -99,30 +124,10 @@ func commonOptions(cmd *cobra.Command) (fx.Option, error) { authnfx.JWTModuleFromFlags(cmd), authnfx.LicenceModuleFromFlags(cmd, ServiceName), workflow.NewModule(stack, temporalTaskQueue), - triggers.NewModule(stack, stackURL, temporalTaskQueue), + triggers.NewModule(stack, stackURL, temporalTaskQueue, stackHTTPClientName), fx.Provide(func() *bunconnect.ConnectionOptions { return connectionOptions }), - fx.Provide(func() *http.Client { - httpClient := &http.Client{ - Transport: otlp.NewRoundTripper(http.DefaultTransport, service.IsDebug(cmd)), - } - - stackClientID, _ := cmd.Flags().GetString(stackClientIDFlag) - stackClientSecret, _ := cmd.Flags().GetString(stackClientSecretFlag) - stackURL, _ := cmd.Flags().GetString(stackURLFlag) - - if stackClientID == "" { - return httpClient - } - oauthConfig := clientcredentials.Config{ - ClientID: stackClientID, - ClientSecret: stackClientSecret, - TokenURL: fmt.Sprintf("%s/api/auth/oauth/token", stackURL), - Scopes: []string{"openid", "ledger:read", "ledger:write", "wallets:read", "wallets:write", "payments:read", "payments:write"}, - } - return oauthConfig.Client(context.WithValue(context.Background(), - oauth2.HTTPClient, httpClient)) - }), + stackHTTPClientModule(cmd), ), nil } diff --git a/cmd/root_test.go b/cmd/root_test.go new file mode 100644 index 0000000..3b127a5 --- /dev/null +++ b/cmd/root_test.go @@ -0,0 +1,26 @@ +package cmd + +import ( + "net/http" + "testing" + + "github.com/formancehq/go-libs/v5/pkg/fx/authnfx" + "github.com/stretchr/testify/require" + "go.uber.org/fx" +) + +func TestCommonOptionsBuildsWithJWTAndStackHTTPClients(t *testing.T) { + cmd := newServeCommand() + app := fx.New( + fx.NopLogger, + authnfx.JWTModuleFromFlags(cmd), + stackHTTPClientModule(cmd), + fx.Invoke(fx.Annotate( + func(stackClient *http.Client) { + require.NotNil(t, stackClient) + }, + fx.ParamTags(`name:"stack"`), + )), + ) + require.NoError(t, app.Err()) +} diff --git a/cmd/worker.go b/cmd/worker.go index 3752a1f..1fd17de 100644 --- a/cmd/worker.go +++ b/cmd/worker.go @@ -22,12 +22,12 @@ func stackClientModule(cmd *cobra.Command) fx.Option { stackURL, _ := cmd.Flags().GetString(stackURLFlag) return fx.Options( - fx.Provide(func(httpClient *http.Client) *sdk.Formance { + fx.Provide(fx.Annotate(func(httpClient *http.Client) *sdk.Formance { return sdk.New( sdk.WithClient(httpClient), sdk.WithServerURL(stackURL), ) - }), + }, fx.ParamTags(`name:"stack"`))), ) } diff --git a/internal/api/v1/handler_list_instances.go b/internal/api/v1/handler_list_instances.go index a96a1fb..f4ada37 100644 --- a/internal/api/v1/handler_list_instances.go +++ b/internal/api/v1/handler_list_instances.go @@ -16,23 +16,29 @@ func listInstances(backend api.Backend) http.HandlerFunc { // Bound the query: without a page size, bunpaginate applies no LIMIT, // loading the entire workflow_instances table per request. - pageSize, err := bunpaginate.GetPageSize(r) + query, err := bunpaginate.Extract[workflow.ListInstancesQuery](r, func() (*workflow.ListInstancesQuery, error) { + pageSize, err := bunpaginate.GetPageSize(r) + if err != nil { + return nil, err + } + return &workflow.ListInstancesQuery{ + PageSize: pageSize, + Options: workflow.ListInstancesOptions{ + WorkflowID: r.URL.Query().Get("workflowID"), + Running: sharedapi.QueryParamBool(r, "running"), + }, + }, nil + }) if err != nil { sharedapi.BadRequest(w, "VALIDATION", err) return } - runs, err := backend.ListInstances(r.Context(), workflow.ListInstancesQuery{ - PageSize: pageSize, - Options: workflow.ListInstancesOptions{ - WorkflowID: r.URL.Query().Get("workflowID"), - Running: sharedapi.QueryParamBool(r, "running"), - }, - }) + runs, err := backend.ListInstances(r.Context(), *query) if err != nil { sharedapi.InternalServerError(w, r, err) return } - sharedapi.Ok(w, runs.Data) + renderCursor(w, *runs) } } diff --git a/internal/api/v1/handler_list_instances_test.go b/internal/api/v1/handler_list_instances_test.go index d79c093..7b525fd 100644 --- a/internal/api/v1/handler_list_instances_test.go +++ b/internal/api/v1/handler_list_instances_test.go @@ -1,9 +1,11 @@ package v1 import ( + "encoding/json" "fmt" "net/http" "net/http/httptest" + "net/url" "testing" "time" @@ -111,16 +113,37 @@ func TestListInstancesIsBounded(t *testing.T) { rec := httptest.NewRecorder() router.ServeHTTP(rec, req) require.Equal(t, http.StatusOK, rec.Result().StatusCode) - instances := make([]workflow.Instance, 0) - sharedapi.ReadResponse(t, rec, &instances) - require.Len(t, instances, 15) + var firstPage struct { + Data []workflow.Instance `json:"data"` + PageSize int `json:"pageSize"` + HasMore bool `json:"hasMore"` + Next string `json:"next"` + } + require.NoError(t, json.NewDecoder(rec.Body).Decode(&firstPage)) + require.Len(t, firstPage.Data, 15) + require.Equal(t, 15, firstPage.PageSize) + require.True(t, firstPage.HasMore) + require.NotEmpty(t, firstPage.Next) + + // The continuation cursor makes the remaining records retrievable. + req = httptest.NewRequest(http.MethodGet, "/instances?cursor="+url.QueryEscape(firstPage.Next), nil) + rec = httptest.NewRecorder() + router.ServeHTTP(rec, req) + require.Equal(t, http.StatusOK, rec.Result().StatusCode) + var secondPage struct { + Data []workflow.Instance `json:"data"` + HasMore bool `json:"hasMore"` + } + require.NoError(t, json.NewDecoder(rec.Body).Decode(&secondPage)) + require.Len(t, secondPage.Data, 5) + require.False(t, secondPage.HasMore) // An explicit page size is honoured. req = httptest.NewRequest(http.MethodGet, "/instances?pageSize=5", nil) rec = httptest.NewRecorder() router.ServeHTTP(rec, req) require.Equal(t, http.StatusOK, rec.Result().StatusCode) - instances = make([]workflow.Instance, 0) + instances := make([]workflow.Instance, 0) sharedapi.ReadResponse(t, rec, &instances) require.Len(t, instances, 5) }) diff --git a/internal/api/v1/handler_list_triggers.go b/internal/api/v1/handler_list_triggers.go index c948100..e76f03b 100644 --- a/internal/api/v1/handler_list_triggers.go +++ b/internal/api/v1/handler_list_triggers.go @@ -38,6 +38,6 @@ func listTriggers(backend api.Backend) func(writer http.ResponseWriter, request return } - sharedapi.Ok(w, triggers.Data) + renderCursor(w, *triggers) } } diff --git a/internal/api/v1/handler_list_triggers_occurrences.go b/internal/api/v1/handler_list_triggers_occurrences.go index 874b718..5537948 100644 --- a/internal/api/v1/handler_list_triggers_occurrences.go +++ b/internal/api/v1/handler_list_triggers_occurrences.go @@ -13,23 +13,32 @@ import ( func listTriggersOccurrences(backend api.Backend) func(writer http.ResponseWriter, request *http.Request) { return func(w http.ResponseWriter, r *http.Request) { - pageSize, err := bunpaginate.GetPageSize(r) + query, err := bunpaginate.Extract[triggers.ListTriggersOccurrencesQuery](r, func() (*triggers.ListTriggersOccurrencesQuery, error) { + pageSize, err := bunpaginate.GetPageSize(r) + if err != nil { + return nil, err + } + return &triggers.ListTriggersOccurrencesQuery{ + PageSize: pageSize, + Options: triggers.ListTriggersOccurrencesOptions{ + TriggerID: chi.URLParam(r, "triggerID"), + }, + }, nil + }) if err != nil { sharedapi.BadRequest(w, "VALIDATION", err) return } + // The path parameter is authoritative even when the pagination cursor is + // supplied by the client. + query.Options.TriggerID = chi.URLParam(r, "triggerID") - triggersOccurrences, err := backend.ListTriggersOccurrences(r.Context(), triggers.ListTriggersOccurrencesQuery{ - PageSize: pageSize, - Options: triggers.ListTriggersOccurrencesOptions{ - TriggerID: chi.URLParam(r, "triggerID"), - }, - }) + triggersOccurrences, err := backend.ListTriggersOccurrences(r.Context(), *query) if err != nil { sharedapi.InternalServerError(w, r, err) return } - sharedapi.Ok(w, triggersOccurrences.Data) + renderCursor(w, *triggersOccurrences) } } diff --git a/internal/api/v1/handler_list_triggers_occurrences_test.go b/internal/api/v1/handler_list_triggers_occurrences_test.go index 8761a4d..f9b5b1d 100644 --- a/internal/api/v1/handler_list_triggers_occurrences_test.go +++ b/internal/api/v1/handler_list_triggers_occurrences_test.go @@ -1,14 +1,15 @@ package v1 import ( + "encoding/json" "net/http" "net/http/httptest" + "net/url" "testing" "time" "github.com/formancehq/go-libs/v5/pkg/messaging/publish" "github.com/formancehq/go-libs/v5/pkg/observe/log" - sharedapi "github.com/formancehq/go-libs/v5/pkg/testing/api" "github.com/formancehq/orchestration/internal/api" "github.com/formancehq/orchestration/internal/triggers" "github.com/formancehq/orchestration/internal/workflow" @@ -45,6 +46,22 @@ func TestListTriggersOccurrencesIsBounded(t *testing.T) { require.NoError(t, err) } + type occurrencePage struct { + Data []triggers.Occurrence `json:"data"` + PageSize int `json:"pageSize"` + HasMore bool `json:"hasMore"` + Next string `json:"next"` + } + requestPage := func(query string) occurrencePage { + req := httptest.NewRequest(http.MethodGet, "/triggers/"+trigger.ID+"/occurrences"+query, nil) + rec := httptest.NewRecorder() + router.ServeHTTP(rec, req) + require.Equal(t, http.StatusOK, rec.Result().StatusCode) + var page occurrencePage + require.NoError(t, json.NewDecoder(rec.Body).Decode(&page)) + return page + } + for _, testCase := range []struct { name string query string @@ -54,15 +71,16 @@ func TestListTriggersOccurrencesIsBounded(t *testing.T) { {name: "explicit page size", query: "?pageSize=5", expected: 5}, } { t.Run(testCase.name, func(t *testing.T) { - req := httptest.NewRequest(http.MethodGet, "/triggers/"+trigger.ID+"/occurrences"+testCase.query, nil) - rec := httptest.NewRecorder() - router.ServeHTTP(rec, req) - require.Equal(t, http.StatusOK, rec.Result().StatusCode) - - occurrences := make([]triggers.Occurrence, 0) - sharedapi.ReadResponse(t, rec, &occurrences) - require.Len(t, occurrences, testCase.expected) + page := requestPage(testCase.query) + require.Len(t, page.Data, testCase.expected) }) } + + firstPage := requestPage("") + require.True(t, firstPage.HasMore) + require.NotEmpty(t, firstPage.Next) + secondPage := requestPage("?cursor=" + url.QueryEscape(firstPage.Next)) + require.Len(t, secondPage.Data, 5) + require.False(t, secondPage.HasMore) }) } diff --git a/internal/api/v1/handler_list_workflows.go b/internal/api/v1/handler_list_workflows.go index b9ac73d..2388b24 100644 --- a/internal/api/v1/handler_list_workflows.go +++ b/internal/api/v1/handler_list_workflows.go @@ -15,20 +15,24 @@ func listWorkflows(backend api2.Backend) http.HandlerFunc { // Bound the query: without a page size, bunpaginate applies no LIMIT, // loading the entire workflows table per request. - pageSize, err := bunpaginate.GetPageSize(r) + query, err := bunpaginate.Extract[bunpaginate.OffsetPaginatedQuery[any]](r, func() (*bunpaginate.OffsetPaginatedQuery[any], error) { + pageSize, err := bunpaginate.GetPageSize(r) + if err != nil { + return nil, err + } + return &bunpaginate.OffsetPaginatedQuery[any]{PageSize: pageSize}, nil + }) if err != nil { api.BadRequest(w, "VALIDATION", err) return } - workflows, err := backend.ListWorkflows(r.Context(), bunpaginate.OffsetPaginatedQuery[any]{ - PageSize: pageSize, - }) + workflows, err := backend.ListWorkflows(r.Context(), *query) if err != nil { api.InternalServerError(w, r, err) return } - api.Ok(w, workflows.Data) + renderCursor(w, *workflows) } } diff --git a/internal/api/v1/pagination.go b/internal/api/v1/pagination.go new file mode 100644 index 0000000..1c43f23 --- /dev/null +++ b/internal/api/v1/pagination.go @@ -0,0 +1,26 @@ +package v1 + +import ( + "net/http" + + bunpaginate "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" + sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" +) + +// renderCursor preserves the v1 {"data": [...]} response shape while adding +// enough metadata for clients to detect and retrieve subsequent pages. +func renderCursor[T any](w http.ResponseWriter, cursor bunpaginate.Cursor[T]) { + sharedapi.RawOk(w, struct { + Data []T `json:"data"` + PageSize int `json:"pageSize"` + HasMore bool `json:"hasMore"` + Previous string `json:"previous,omitempty"` + Next string `json:"next,omitempty"` + }{ + Data: cursor.Data, + PageSize: cursor.PageSize, + HasMore: cursor.HasMore, + Previous: cursor.Previous, + Next: cursor.Next, + }) +} diff --git a/internal/triggers/module.go b/internal/triggers/module.go index 8e5af8e..5d64f63 100644 --- a/internal/triggers/module.go +++ b/internal/triggers/module.go @@ -14,12 +14,13 @@ import ( "go.uber.org/fx" ) -func NewModule(stack, stackURL, taskQueue string) fx.Option { +func NewModule(stack, stackURL, taskQueue, httpClientName string) fx.Option { + httpClientTag := `name:"` + httpClientName + `"` return fx.Options( fx.Provide(NewManager), - fx.Provide(func(httpClient *http.Client) *expressionEvaluator { + fx.Provide(fx.Annotate(func(httpClient *http.Client) *expressionEvaluator { return NewExpressionEvaluator(httpClient, stackURL) - }), + }, fx.ParamTags(httpClientTag))), fx.Provide(func() *triggerWorkflow { return NewWorkflow(stack, taskQueue, true) }), diff --git a/openapi.yaml b/openapi.yaml index a3afab3..834ca91 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -35,6 +35,8 @@ paths: required: false schema: type: string + - $ref: '#/components/parameters/PageSize' + - $ref: '#/components/parameters/Cursor' responses: '200': description: List of triggers @@ -118,6 +120,8 @@ paths: schema: type: string required: true + - $ref: '#/components/parameters/PageSize' + - $ref: '#/components/parameters/Cursor' get: summary: List triggers occurrences operationId: listTriggersOccurrences @@ -143,6 +147,9 @@ paths: description: List registered workflows tags: - orchestration.v1 + parameters: + - $ref: '#/components/parameters/PageSize' + - $ref: '#/components/parameters/Cursor' responses: '200': description: List of workflows @@ -278,6 +285,8 @@ paths: type: boolean example: true required: false + - $ref: '#/components/parameters/PageSize' + - $ref: '#/components/parameters/Cursor' tags: - orchestration.v1 responses: @@ -1105,8 +1114,18 @@ components: items: $ref: '#/components/schemas/Workflow' type: array + pageSize: + type: integer + hasMore: + type: boolean + previous: + type: string + next: + type: string required: - data + - pageSize + - hasMore TriggerData: type: object required: @@ -1167,8 +1186,18 @@ components: items: $ref: '#/components/schemas/TriggerOccurrence' type: array + pageSize: + type: integer + hasMore: + type: boolean + previous: + type: string + next: + type: string required: - data + - pageSize + - hasMore ListTriggersResponse: type: object properties: @@ -1176,8 +1205,18 @@ components: items: $ref: '#/components/schemas/Trigger' type: array + pageSize: + type: integer + hasMore: + type: boolean + previous: + type: string + next: + type: string required: - data + - pageSize + - hasMore CreateWorkflowRequest: $ref: '#/components/schemas/WorkflowConfig' CreateWorkflowResponse: @@ -1206,13 +1245,24 @@ components: data: $ref: '#/components/schemas/WorkflowInstance' ListRunsResponse: - required: - - data + type: object properties: data: items: $ref: '#/components/schemas/WorkflowInstance' type: array + pageSize: + type: integer + hasMore: + type: boolean + previous: + type: string + next: + type: string + required: + - data + - pageSize + - hasMore GetWorkflowResponse: type: object required: @@ -3554,6 +3604,32 @@ components: type: string error: type: string + parameters: + PageSize: + name: pageSize + in: query + description: | + The maximum number of results to return per page. + required: false + schema: + type: integer + minimum: 1 + maximum: 1000 + default: 15 + format: int64 + example: 100 + Cursor: + name: cursor + in: query + description: | + Parameter used in pagination requests. + Set to the value of next for the next page of results. + Set to the value of previous for the previous page of results. + No other parameters can be set when this parameter is set. + required: false + schema: + type: string + example: aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ== responses: ErrorResponse: description: General error @@ -3567,29 +3643,6 @@ components: application/json: schema: $ref: '#/components/schemas/V2Error' - parameters: - Cursor: - name: cursor - in: query - description: | - Parameter used in pagination requests. - Set to the value of next for the next page of results. - Set to the value of previous for the previous page of results. - No other parameters can be set when this parameter is set. - schema: - type: string - example: aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ== - PageSize: - name: pageSize - in: query - description: | - The maximum number of results to return per page. - example: 100 - schema: - type: integer - format: int64 - minimum: 1 - maximum: 1000 securitySchemes: Authorization: type: oauth2 diff --git a/openapi/v1.yaml b/openapi/v1.yaml index 0b71127..b4b52a5 100644 --- a/openapi/v1.yaml +++ b/openapi/v1.yaml @@ -35,6 +35,8 @@ paths: required: false schema: type: string + - $ref: '#/components/parameters/PageSize' + - $ref: '#/components/parameters/Cursor' responses: '200': description: List of triggers @@ -118,6 +120,8 @@ paths: schema: type: string required: true + - $ref: '#/components/parameters/PageSize' + - $ref: '#/components/parameters/Cursor' get: summary: List triggers occurrences operationId: listTriggersOccurrences @@ -143,6 +147,9 @@ paths: description: List registered workflows tags: - orchestration.v1 + parameters: + - $ref: '#/components/parameters/PageSize' + - $ref: '#/components/parameters/Cursor' responses: '200': description: List of workflows @@ -278,6 +285,8 @@ paths: type: boolean example: true required: false + - $ref: '#/components/parameters/PageSize' + - $ref: '#/components/parameters/Cursor' tags: - orchestration.v1 responses: @@ -609,8 +618,18 @@ components: items: $ref: '#/components/schemas/Workflow' type: array + pageSize: + type: integer + hasMore: + type: boolean + previous: + type: string + next: + type: string required: - data + - pageSize + - hasMore TriggerData: type: object required: @@ -671,8 +690,18 @@ components: items: $ref: '#/components/schemas/TriggerOccurrence' type: array + pageSize: + type: integer + hasMore: + type: boolean + previous: + type: string + next: + type: string required: - data + - pageSize + - hasMore ListTriggersResponse: type: object properties: @@ -680,8 +709,18 @@ components: items: $ref: '#/components/schemas/Trigger' type: array + pageSize: + type: integer + hasMore: + type: boolean + previous: + type: string + next: + type: string required: - data + - pageSize + - hasMore CreateWorkflowRequest: $ref: '#/components/schemas/WorkflowConfig' CreateWorkflowResponse: @@ -710,13 +749,24 @@ components: data: $ref: '#/components/schemas/WorkflowInstance' ListRunsResponse: - required: - - data + type: object properties: data: items: $ref: '#/components/schemas/WorkflowInstance' type: array + pageSize: + type: integer + hasMore: + type: boolean + previous: + type: string + next: + type: string + required: + - data + - pageSize + - hasMore GetWorkflowResponse: type: object required: @@ -1701,6 +1751,24 @@ components: input: 100 output: 10 balance: 90 + parameters: + PageSize: + name: pageSize + in: query + description: The maximum number of results to return per page. + required: false + schema: + type: integer + minimum: 1 + maximum: 100 + default: 15 + Cursor: + name: cursor + in: query + description: The continuation cursor returned by the previous page. + required: false + schema: + type: string responses: ErrorResponse: description: General error diff --git a/pkg/client/.speakeasy/gen.lock b/pkg/client/.speakeasy/gen.lock index cbc786c..a3cddfb 100644 --- a/pkg/client/.speakeasy/gen.lock +++ b/pkg/client/.speakeasy/gen.lock @@ -1,12 +1,12 @@ lockVersion: 2.0.0 id: e26e5b37-4391-4462-9a20-c517a83a166a management: - docChecksum: dfc3ed9eb806fc9e8c6629a3d2a0a637 + docChecksum: 2f9e40aaba40047b5af65e5371fea57c docVersion: 0.1.0 speakeasyVersion: 1.351.0 generationVersion: 2.384.1 - releaseVersion: 0.1.4 - configChecksum: c78571211c83f4afeeaed43ac964a7c8 + releaseVersion: 0.1.6 + configChecksum: 28d06aa57052e26c02ec2310398ec34d features: go: additionalDependencies: 0.1.0 @@ -157,6 +157,7 @@ generatedFiles: - /models/components/creditwalletrequest.go - /models/components/activityconfirmhold.go - /models/components/activitygetpayment.go + - /models/components/activitycreatetransferinitiation.go - /models/components/activitystripetransfer.go - /models/components/activityreverttransaction.go - /models/components/activitycreatetransaction.go @@ -236,6 +237,7 @@ generatedFiles: - /models/components/v2creditwalletrequest.go - /models/components/v2activityconfirmhold.go - /models/components/v2activitygetpayment.go + - /models/components/v2activitycreatetransferinitiation.go - /models/components/v2activitystripetransfer.go - /models/components/v2activitycreatetransaction.go - /models/components/v2posttransaction.go @@ -254,6 +256,7 @@ generatedFiles: - docs/models/operations/deletetriggerresponse.md - docs/models/operations/listtriggersoccurrencesrequest.md - docs/models/operations/listtriggersoccurrencesresponse.md + - docs/models/operations/listworkflowsrequest.md - docs/models/operations/listworkflowsresponse.md - docs/models/operations/createworkflowresponse.md - docs/models/operations/getworkflowrequest.md @@ -338,6 +341,7 @@ generatedFiles: - docs/models/components/stagesendsourceaccount.md - docs/models/components/stagesendsourcewallet.md - docs/models/components/stagesenddestination.md + - docs/models/components/type.md - docs/models/components/stagesenddestinationpayment.md - docs/models/components/stagesenddestinationaccount.md - docs/models/components/stagesenddestinationwallet.md @@ -362,7 +366,7 @@ generatedFiles: - docs/models/components/ledgeraccountsubject.md - docs/models/components/walletsubject.md - docs/models/components/activitygetpaymentoutput.md - - docs/models/components/type.md + - docs/models/components/paymenttype.md - docs/models/components/scheme.md - docs/models/components/raw.md - docs/models/components/payment.md @@ -388,6 +392,9 @@ generatedFiles: - docs/models/components/creditwalletrequest.md - docs/models/components/activityconfirmhold.md - docs/models/components/activitygetpayment.md + - docs/models/components/activitycreatetransferinitiationtype.md + - docs/models/components/activitycreatetransferinitiationmetadata.md + - docs/models/components/activitycreatetransferinitiation.md - docs/models/components/metadata.md - docs/models/components/activitystripetransfer.md - docs/models/components/activityreverttransaction.md @@ -432,6 +439,7 @@ generatedFiles: - docs/models/components/v2stagesendsourceaccount.md - docs/models/components/v2stagesendsourcewallet.md - docs/models/components/v2stagesenddestination.md + - docs/models/components/v2stagesenddestinationpaymenttype.md - docs/models/components/v2stagesenddestinationpayment.md - docs/models/components/v2stagesenddestinationaccount.md - docs/models/components/v2stagesenddestinationwallet.md @@ -481,6 +489,9 @@ generatedFiles: - docs/models/components/v2creditwalletrequest.md - docs/models/components/v2activityconfirmhold.md - docs/models/components/v2activitygetpayment.md + - docs/models/components/v2activitycreatetransferinitiationtype.md + - docs/models/components/v2activitycreatetransferinitiationmetadata.md + - docs/models/components/v2activitycreatetransferinitiation.md - docs/models/components/v2activitystripetransfermetadata.md - docs/models/components/v2activitystripetransfer.md - docs/models/components/v2activitycreatetransaction.md diff --git a/pkg/client/.speakeasy/gen.yaml b/pkg/client/.speakeasy/gen.yaml index cf3767f..ec38020 100644 --- a/pkg/client/.speakeasy/gen.yaml +++ b/pkg/client/.speakeasy/gen.yaml @@ -12,7 +12,7 @@ generation: auth: oAuth2ClientCredentialsEnabled: true go: - version: 0.1.4 + version: 0.1.6 additionalDependencies: {} allowUnknownFieldsInWeakUnions: false clientServerStatusCodesAsErrors: true @@ -29,5 +29,5 @@ go: maxMethodParams: 0 methodArguments: require-security-and-request outputModelSuffix: output - packageName: openapi + packageName: github.com/formancehq/flows/pkg/client responseFormat: envelope-http diff --git a/pkg/client/README.md b/pkg/client/README.md index 9602a5b..beb8f5b 100644 --- a/pkg/client/README.md +++ b/pkg/client/README.md @@ -20,7 +20,7 @@ It has been generated successfully based on your OpenAPI spec. However, it is no ## SDK Installation ```bash -go get openapi +go get github.com/formancehq/flows/pkg/client ``` @@ -34,14 +34,14 @@ package main import ( "context" - "log" "github.com/formancehq/flows/pkg/client" "github.com/formancehq/flows/pkg/client/models/components" + "log" ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -116,16 +116,16 @@ package main import ( "context" - "log" - "models/operations" "github.com/formancehq/flows/pkg/client" "github.com/formancehq/flows/pkg/client/models/components" "github.com/formancehq/flows/pkg/client/retry" + "log" + "models/operations" ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -159,15 +159,15 @@ package main import ( "context" - "log" "github.com/formancehq/flows/pkg/client" "github.com/formancehq/flows/pkg/client/models/components" "github.com/formancehq/flows/pkg/client/retry" + "log" ) func main() { - s := openapi.New( - openapi.WithRetryConfig( + s := client.New( + client.WithRetryConfig( retry.Config{ Strategy: "backoff", Backoff: &retry.BackoffStrategy{ @@ -178,7 +178,7 @@ func main() { }, RetryConnectionErrors: false, }), - openapi.WithSecurity(components.Security{ + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -215,15 +215,15 @@ package main import ( "context" "errors" - "log" "github.com/formancehq/flows/pkg/client" "github.com/formancehq/flows/pkg/client/models/components" "github.com/formancehq/flows/pkg/client/models/sdkerrors" + "log" ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -268,15 +268,15 @@ package main import ( "context" - "log" "github.com/formancehq/flows/pkg/client" "github.com/formancehq/flows/pkg/client/models/components" + "log" ) func main() { - s := openapi.New( - openapi.WithServerIndex(0), - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithServerIndex(0), + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -303,15 +303,15 @@ package main import ( "context" - "log" "github.com/formancehq/flows/pkg/client" "github.com/formancehq/flows/pkg/client/models/components" + "log" ) func main() { - s := openapi.New( - openapi.WithServerURL("http://localhost:8080/"), - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithServerURL("http://localhost:8080/"), + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -377,14 +377,14 @@ package main import ( "context" - "log" "github.com/formancehq/flows/pkg/client" "github.com/formancehq/flows/pkg/client/models/components" + "log" ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), diff --git a/pkg/client/USAGE.md b/pkg/client/USAGE.md index 7903cd1..5fedf1a 100644 --- a/pkg/client/USAGE.md +++ b/pkg/client/USAGE.md @@ -4,14 +4,14 @@ package main import ( "context" - "log" "github.com/formancehq/flows/pkg/client" "github.com/formancehq/flows/pkg/client/models/components" + "log" ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), diff --git a/pkg/client/docs/models/components/activitycreatetransferinitiation.md b/pkg/client/docs/models/components/activitycreatetransferinitiation.md new file mode 100644 index 0000000..f6cf9ed --- /dev/null +++ b/pkg/client/docs/models/components/activitycreatetransferinitiation.md @@ -0,0 +1,17 @@ +# ActivityCreateTransferInitiation + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `ConnectorID` | **string* | :heavy_minus_sign: | N/A | | +| `Provider` | **string* | :heavy_minus_sign: | Payment service provider name (e.g., stripe, wise, mangopay).
Validated by the Payments service based on installed connectors.
| stripe | +| `Amount` | [*big.Int](https://pkg.go.dev/math/big#Int) | :heavy_minus_sign: | N/A | 100 | +| `Asset` | **string* | :heavy_minus_sign: | N/A | USD | +| `Destination` | **string* | :heavy_minus_sign: | Destination account ID | acct_1Gqj58KZcSIg2N2q | +| `Source` | **string* | :heavy_minus_sign: | Source account ID (required for TRANSFER type) | | +| `Type` | [*components.ActivityCreateTransferInitiationType](../../models/components/activitycreatetransferinitiationtype.md) | :heavy_minus_sign: | Type of transfer initiation:
- TRANSFER: Internal to internal account transfer
- PAYOUT: Internal to external account payout
| | +| `Description` | **string* | :heavy_minus_sign: | Description for the transfer initiation | | +| `WaitingValidation` | **bool* | :heavy_minus_sign: | N/A | false | +| `Metadata` | [*components.ActivityCreateTransferInitiationMetadata](../../models/components/activitycreatetransferinitiationmetadata.md) | :heavy_minus_sign: | A set of key/value pairs that you can attach to a transfer object. It can be useful for storing additional information about the transfer in a structured format.
| {
"order_id": "6735"
} | \ No newline at end of file diff --git a/pkg/client/docs/models/components/activitycreatetransferinitiationmetadata.md b/pkg/client/docs/models/components/activitycreatetransferinitiationmetadata.md new file mode 100644 index 0000000..e6c69e5 --- /dev/null +++ b/pkg/client/docs/models/components/activitycreatetransferinitiationmetadata.md @@ -0,0 +1,10 @@ +# ActivityCreateTransferInitiationMetadata + +A set of key/value pairs that you can attach to a transfer object. It can be useful for storing additional information about the transfer in a structured format. + + + +## Fields + +| Field | Type | Required | Description | +| ----------- | ----------- | ----------- | ----------- | \ No newline at end of file diff --git a/pkg/client/docs/models/components/activitycreatetransferinitiationtype.md b/pkg/client/docs/models/components/activitycreatetransferinitiationtype.md new file mode 100644 index 0000000..011d457 --- /dev/null +++ b/pkg/client/docs/models/components/activitycreatetransferinitiationtype.md @@ -0,0 +1,14 @@ +# ActivityCreateTransferInitiationType + +Type of transfer initiation: +- TRANSFER: Internal to internal account transfer +- PAYOUT: Internal to external account payout + + + +## Values + +| Name | Value | +| ---------------------------------------------- | ---------------------------------------------- | +| `ActivityCreateTransferInitiationTypeTransfer` | TRANSFER | +| `ActivityCreateTransferInitiationTypePayout` | PAYOUT | \ No newline at end of file diff --git a/pkg/client/docs/models/components/listrunsresponse.md b/pkg/client/docs/models/components/listrunsresponse.md index 466213c..0460049 100644 --- a/pkg/client/docs/models/components/listrunsresponse.md +++ b/pkg/client/docs/models/components/listrunsresponse.md @@ -5,4 +5,8 @@ | Field | Type | Required | Description | | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | -| `Data` | [][components.WorkflowInstance](../../models/components/workflowinstance.md) | :heavy_check_mark: | N/A | \ No newline at end of file +| `Data` | [][components.WorkflowInstance](../../models/components/workflowinstance.md) | :heavy_check_mark: | N/A | +| `PageSize` | *int64* | :heavy_check_mark: | N/A | +| `HasMore` | *bool* | :heavy_check_mark: | N/A | +| `Previous` | **string* | :heavy_minus_sign: | N/A | +| `Next` | **string* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/pkg/client/docs/models/components/listtriggersoccurrencesresponse.md b/pkg/client/docs/models/components/listtriggersoccurrencesresponse.md index 367c2f8..8342e37 100644 --- a/pkg/client/docs/models/components/listtriggersoccurrencesresponse.md +++ b/pkg/client/docs/models/components/listtriggersoccurrencesresponse.md @@ -5,4 +5,8 @@ | Field | Type | Required | Description | | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------ | -| `Data` | [][components.TriggerOccurrence](../../models/components/triggeroccurrence.md) | :heavy_check_mark: | N/A | \ No newline at end of file +| `Data` | [][components.TriggerOccurrence](../../models/components/triggeroccurrence.md) | :heavy_check_mark: | N/A | +| `PageSize` | *int64* | :heavy_check_mark: | N/A | +| `HasMore` | *bool* | :heavy_check_mark: | N/A | +| `Previous` | **string* | :heavy_minus_sign: | N/A | +| `Next` | **string* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/pkg/client/docs/models/components/listtriggersresponse.md b/pkg/client/docs/models/components/listtriggersresponse.md index bf4eae6..94ea974 100644 --- a/pkg/client/docs/models/components/listtriggersresponse.md +++ b/pkg/client/docs/models/components/listtriggersresponse.md @@ -5,4 +5,8 @@ | Field | Type | Required | Description | | ---------------------------------------------------------- | ---------------------------------------------------------- | ---------------------------------------------------------- | ---------------------------------------------------------- | -| `Data` | [][components.Trigger](../../models/components/trigger.md) | :heavy_check_mark: | N/A | \ No newline at end of file +| `Data` | [][components.Trigger](../../models/components/trigger.md) | :heavy_check_mark: | N/A | +| `PageSize` | *int64* | :heavy_check_mark: | N/A | +| `HasMore` | *bool* | :heavy_check_mark: | N/A | +| `Previous` | **string* | :heavy_minus_sign: | N/A | +| `Next` | **string* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/pkg/client/docs/models/components/listworkflowsresponse.md b/pkg/client/docs/models/components/listworkflowsresponse.md index d521bec..c80cdce 100644 --- a/pkg/client/docs/models/components/listworkflowsresponse.md +++ b/pkg/client/docs/models/components/listworkflowsresponse.md @@ -5,4 +5,8 @@ | Field | Type | Required | Description | | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | -| `Data` | [][components.Workflow](../../models/components/workflow.md) | :heavy_check_mark: | N/A | \ No newline at end of file +| `Data` | [][components.Workflow](../../models/components/workflow.md) | :heavy_check_mark: | N/A | +| `PageSize` | *int64* | :heavy_check_mark: | N/A | +| `HasMore` | *bool* | :heavy_check_mark: | N/A | +| `Previous` | **string* | :heavy_minus_sign: | N/A | +| `Next` | **string* | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/pkg/client/docs/models/components/payment.md b/pkg/client/docs/models/components/payment.md index 99f603e..dc3f49a 100644 --- a/pkg/client/docs/models/components/payment.md +++ b/pkg/client/docs/models/components/payment.md @@ -11,7 +11,7 @@ | `DestinationAccountID` | *string* | :heavy_check_mark: | N/A | | | `ConnectorID` | *string* | :heavy_check_mark: | N/A | | | `Provider` | [*components.Connector](../../models/components/connector.md) | :heavy_minus_sign: | N/A | | -| `Type` | [components.Type](../../models/components/type.md) | :heavy_check_mark: | N/A | | +| `Type` | [components.PaymentType](../../models/components/paymenttype.md) | :heavy_check_mark: | N/A | | | `Status` | [components.PaymentStatus](../../models/components/paymentstatus.md) | :heavy_check_mark: | N/A | | | `InitialAmount` | [*big.Int](https://pkg.go.dev/math/big#Int) | :heavy_check_mark: | N/A | 100 | | `Scheme` | [components.Scheme](../../models/components/scheme.md) | :heavy_check_mark: | N/A | | diff --git a/pkg/client/docs/models/components/paymenttype.md b/pkg/client/docs/models/components/paymenttype.md new file mode 100644 index 0000000..dfc9842 --- /dev/null +++ b/pkg/client/docs/models/components/paymenttype.md @@ -0,0 +1,11 @@ +# PaymentType + + +## Values + +| Name | Value | +| --------------------- | --------------------- | +| `PaymentTypePayIn` | PAY-IN | +| `PaymentTypePayout` | PAYOUT | +| `PaymentTypeTransfer` | TRANSFER | +| `PaymentTypeOther` | OTHER | \ No newline at end of file diff --git a/pkg/client/docs/models/components/stagesenddestinationaccount.md b/pkg/client/docs/models/components/stagesenddestinationaccount.md index de0e831..7b32335 100644 --- a/pkg/client/docs/models/components/stagesenddestinationaccount.md +++ b/pkg/client/docs/models/components/stagesenddestinationaccount.md @@ -3,7 +3,9 @@ ## Fields -| Field | Type | Required | Description | -| ------------------ | ------------------ | ------------------ | ------------------ | -| `ID` | *string* | :heavy_check_mark: | N/A | -| `Ledger` | **string* | :heavy_minus_sign: | N/A | \ No newline at end of file +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ID` | *string* | :heavy_check_mark: | N/A | | +| `Ledger` | **string* | :heavy_minus_sign: | N/A | | +| `ThroughAccount` | **string* | :heavy_minus_sign: | Account used when this ledger account interacts with external systems (payments, cross-ledger).
- As SOURCE going to payment: funds are sent to this account (e.g., "liabilities:payouts-pending")
- As DESTINATION from payment: funds come from this account (e.g., "assets:stripe:incoming")
- For cross-ledger transfers: replaces "world" on both sides
| liabilities:payouts-pending | +| `AllowOverdraft` | **bool* | :heavy_minus_sign: | Enables unbounded overdraft on the throughAccount when set to true.
This is useful when the throughAccount represents a liability or bridge account
that needs to go negative (e.g., "liabilities:payouts-pending").
Only applies when throughAccount is not "world" (which already has unbounded overdraft).
| true | \ No newline at end of file diff --git a/pkg/client/docs/models/components/stagesenddestinationpayment.md b/pkg/client/docs/models/components/stagesenddestinationpayment.md index 44bfc23..9505c0b 100644 --- a/pkg/client/docs/models/components/stagesenddestinationpayment.md +++ b/pkg/client/docs/models/components/stagesenddestinationpayment.md @@ -3,6 +3,8 @@ ## Fields -| Field | Type | Required | Description | -| ------------------ | ------------------ | ------------------ | ------------------ | -| `Psp` | *string* | :heavy_check_mark: | N/A | \ No newline at end of file +| Field | Type | Required | Description | Example | +| -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Psp` | *string* | :heavy_check_mark: | Payment service provider name (e.g., stripe, wise, mangopay).
Validated by the Payments service based on installed connectors.
| stripe | +| `Type` | [*components.Type](../../models/components/type.md) | :heavy_minus_sign: | Type of transfer initiation:
- TRANSFER: Internal to internal account transfer
- PAYOUT: Internal to external account payout
| PAYOUT | +| `SourceAccount` | **string* | :heavy_minus_sign: | Formance Payments account ID for the source (internal PSP account).
If not specified, the Payments service may use a default account for the connector.
| | \ No newline at end of file diff --git a/pkg/client/docs/models/components/stagesendsourceaccount.md b/pkg/client/docs/models/components/stagesendsourceaccount.md index 2330e55..1b851ff 100644 --- a/pkg/client/docs/models/components/stagesendsourceaccount.md +++ b/pkg/client/docs/models/components/stagesendsourceaccount.md @@ -3,7 +3,9 @@ ## Fields -| Field | Type | Required | Description | -| ------------------ | ------------------ | ------------------ | ------------------ | -| `ID` | *string* | :heavy_check_mark: | N/A | -| `Ledger` | **string* | :heavy_minus_sign: | N/A | \ No newline at end of file +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ID` | *string* | :heavy_check_mark: | N/A | | +| `Ledger` | **string* | :heavy_minus_sign: | N/A | | +| `ThroughAccount` | **string* | :heavy_minus_sign: | Account used when this ledger account interacts with external systems (payments, cross-ledger).
- As SOURCE going to payment: funds are sent to this account (e.g., "liabilities:payouts-pending")
- As DESTINATION from payment: funds come from this account (e.g., "assets:stripe:incoming")
- For cross-ledger transfers: replaces "world" on both sides
| liabilities:payouts-pending | +| `AllowOverdraft` | **bool* | :heavy_minus_sign: | Enables unbounded overdraft on the throughAccount when set to true.
This is useful when the throughAccount represents a liability or bridge account
that needs to go negative (e.g., "liabilities:payouts-pending").
Only applies when throughAccount is not "world" (which already has unbounded overdraft).
| true | \ No newline at end of file diff --git a/pkg/client/docs/models/components/stagesendsourcepayment.md b/pkg/client/docs/models/components/stagesendsourcepayment.md index e884994..37cda39 100644 --- a/pkg/client/docs/models/components/stagesendsourcepayment.md +++ b/pkg/client/docs/models/components/stagesendsourcepayment.md @@ -3,6 +3,10 @@ ## Fields -| Field | Type | Required | Description | -| ------------------ | ------------------ | ------------------ | ------------------ | -| `ID` | *string* | :heavy_check_mark: | N/A | \ No newline at end of file +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ID` | *string* | :heavy_check_mark: | N/A | +| `Ledger` | **string* | :heavy_minus_sign: | Ledger to use for payment ingestion.
Defaults to the internal orchestration ledger.
| +| `HoldingAccount` | **string* | :heavy_minus_sign: | Intermediate account where payment funds are held.
Defaults to "payment:{paymentID}" format.
| +| `ThroughAccount` | **string* | :heavy_minus_sign: | Source account for the payment ingestion transaction.
Defaults to "world".
| +| `AllowOverdraft` | **bool* | :heavy_minus_sign: | Enables unbounded overdraft on the throughAccount when set to true.
Only applies when throughAccount is not "world" (which already has unbounded overdraft).
| \ No newline at end of file diff --git a/pkg/client/docs/models/components/type.md b/pkg/client/docs/models/components/type.md index 5c514be..0b56eb1 100644 --- a/pkg/client/docs/models/components/type.md +++ b/pkg/client/docs/models/components/type.md @@ -1,11 +1,14 @@ # Type +Type of transfer initiation: +- TRANSFER: Internal to internal account transfer +- PAYOUT: Internal to external account payout + + ## Values | Name | Value | | -------------- | -------------- | -| `TypePayIn` | PAY-IN | -| `TypePayout` | PAYOUT | | `TypeTransfer` | TRANSFER | -| `TypeOther` | OTHER | \ No newline at end of file +| `TypePayout` | PAYOUT | \ No newline at end of file diff --git a/pkg/client/docs/models/components/v2activitycreatetransferinitiation.md b/pkg/client/docs/models/components/v2activitycreatetransferinitiation.md new file mode 100644 index 0000000..3d2badf --- /dev/null +++ b/pkg/client/docs/models/components/v2activitycreatetransferinitiation.md @@ -0,0 +1,17 @@ +# V2ActivityCreateTransferInitiation + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `ConnectorID` | **string* | :heavy_minus_sign: | N/A | | +| `Provider` | **string* | :heavy_minus_sign: | Payment service provider name (e.g., stripe, wise, mangopay).
Validated by the Payments service based on installed connectors.
| stripe | +| `Amount` | [*big.Int](https://pkg.go.dev/math/big#Int) | :heavy_minus_sign: | N/A | 100 | +| `Asset` | **string* | :heavy_minus_sign: | N/A | USD | +| `Destination` | **string* | :heavy_minus_sign: | Destination account ID | acct_1Gqj58KZcSIg2N2q | +| `Source` | **string* | :heavy_minus_sign: | Source account ID (required for TRANSFER type) | | +| `Type` | [*components.V2ActivityCreateTransferInitiationType](../../models/components/v2activitycreatetransferinitiationtype.md) | :heavy_minus_sign: | Type of transfer initiation:
- TRANSFER: Internal to internal account transfer
- PAYOUT: Internal to external account payout
| | +| `Description` | **string* | :heavy_minus_sign: | Description for the transfer initiation | | +| `WaitingValidation` | **bool* | :heavy_minus_sign: | N/A | false | +| `Metadata` | [*components.V2ActivityCreateTransferInitiationMetadata](../../models/components/v2activitycreatetransferinitiationmetadata.md) | :heavy_minus_sign: | A set of key/value pairs that you can attach to a transfer object. It can be useful for storing additional information about the transfer in a structured format.
| {
"order_id": "6735"
} | \ No newline at end of file diff --git a/pkg/client/docs/models/components/v2activitycreatetransferinitiationmetadata.md b/pkg/client/docs/models/components/v2activitycreatetransferinitiationmetadata.md new file mode 100644 index 0000000..58cc736 --- /dev/null +++ b/pkg/client/docs/models/components/v2activitycreatetransferinitiationmetadata.md @@ -0,0 +1,10 @@ +# V2ActivityCreateTransferInitiationMetadata + +A set of key/value pairs that you can attach to a transfer object. It can be useful for storing additional information about the transfer in a structured format. + + + +## Fields + +| Field | Type | Required | Description | +| ----------- | ----------- | ----------- | ----------- | \ No newline at end of file diff --git a/pkg/client/docs/models/components/v2activitycreatetransferinitiationtype.md b/pkg/client/docs/models/components/v2activitycreatetransferinitiationtype.md new file mode 100644 index 0000000..edf2150 --- /dev/null +++ b/pkg/client/docs/models/components/v2activitycreatetransferinitiationtype.md @@ -0,0 +1,14 @@ +# V2ActivityCreateTransferInitiationType + +Type of transfer initiation: +- TRANSFER: Internal to internal account transfer +- PAYOUT: Internal to external account payout + + + +## Values + +| Name | Value | +| ------------------------------------------------ | ------------------------------------------------ | +| `V2ActivityCreateTransferInitiationTypeTransfer` | TRANSFER | +| `V2ActivityCreateTransferInitiationTypePayout` | PAYOUT | \ No newline at end of file diff --git a/pkg/client/docs/models/components/v2stagesenddestinationaccount.md b/pkg/client/docs/models/components/v2stagesenddestinationaccount.md index 09f432f..fc0e7bd 100644 --- a/pkg/client/docs/models/components/v2stagesenddestinationaccount.md +++ b/pkg/client/docs/models/components/v2stagesenddestinationaccount.md @@ -3,7 +3,9 @@ ## Fields -| Field | Type | Required | Description | -| ------------------ | ------------------ | ------------------ | ------------------ | -| `ID` | *string* | :heavy_check_mark: | N/A | -| `Ledger` | **string* | :heavy_minus_sign: | N/A | \ No newline at end of file +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ID` | *string* | :heavy_check_mark: | N/A | | +| `Ledger` | **string* | :heavy_minus_sign: | N/A | | +| `ThroughAccount` | **string* | :heavy_minus_sign: | Account used when this ledger account interacts with external systems (payments, cross-ledger).
- As SOURCE going to payment: funds are sent to this account (e.g., "liabilities:payouts-pending")
- As DESTINATION from payment: funds come from this account (e.g., "assets:stripe:incoming")
- For cross-ledger transfers: replaces "world" on both sides
| liabilities:payouts-pending | +| `AllowOverdraft` | **bool* | :heavy_minus_sign: | Enables unbounded overdraft on the throughAccount when set to true.
This is useful when the throughAccount represents a liability or bridge account
that needs to go negative (e.g., "liabilities:payouts-pending").
Only applies when throughAccount is not "world" (which already has unbounded overdraft).
| true | \ No newline at end of file diff --git a/pkg/client/docs/models/components/v2stagesenddestinationpayment.md b/pkg/client/docs/models/components/v2stagesenddestinationpayment.md index e37e485..680d9a2 100644 --- a/pkg/client/docs/models/components/v2stagesenddestinationpayment.md +++ b/pkg/client/docs/models/components/v2stagesenddestinationpayment.md @@ -3,6 +3,8 @@ ## Fields -| Field | Type | Required | Description | -| ------------------ | ------------------ | ------------------ | ------------------ | -| `Psp` | *string* | :heavy_check_mark: | N/A | \ No newline at end of file +| Field | Type | Required | Description | Example | +| -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `Psp` | *string* | :heavy_check_mark: | Payment service provider name (e.g., stripe, wise, mangopay).
Validated by the Payments service based on installed connectors.
| stripe | +| `Type` | [*components.V2StageSendDestinationPaymentType](../../models/components/v2stagesenddestinationpaymenttype.md) | :heavy_minus_sign: | Type of transfer initiation:
- TRANSFER: Internal to internal account transfer
- PAYOUT: Internal to external account payout
| PAYOUT | +| `SourceAccount` | **string* | :heavy_minus_sign: | Formance Payments account ID for the source (internal PSP account).
If not specified, the Payments service may use a default account for the connector.
| | \ No newline at end of file diff --git a/pkg/client/docs/models/components/v2stagesenddestinationpaymenttype.md b/pkg/client/docs/models/components/v2stagesenddestinationpaymenttype.md new file mode 100644 index 0000000..a1e9bdd --- /dev/null +++ b/pkg/client/docs/models/components/v2stagesenddestinationpaymenttype.md @@ -0,0 +1,14 @@ +# V2StageSendDestinationPaymentType + +Type of transfer initiation: +- TRANSFER: Internal to internal account transfer +- PAYOUT: Internal to external account payout + + + +## Values + +| Name | Value | +| ------------------------------------------- | ------------------------------------------- | +| `V2StageSendDestinationPaymentTypeTransfer` | TRANSFER | +| `V2StageSendDestinationPaymentTypePayout` | PAYOUT | \ No newline at end of file diff --git a/pkg/client/docs/models/components/v2stagesendsourceaccount.md b/pkg/client/docs/models/components/v2stagesendsourceaccount.md index e590db4..4b304ba 100644 --- a/pkg/client/docs/models/components/v2stagesendsourceaccount.md +++ b/pkg/client/docs/models/components/v2stagesendsourceaccount.md @@ -3,7 +3,9 @@ ## Fields -| Field | Type | Required | Description | -| ------------------ | ------------------ | ------------------ | ------------------ | -| `ID` | *string* | :heavy_check_mark: | N/A | -| `Ledger` | **string* | :heavy_minus_sign: | N/A | \ No newline at end of file +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ID` | *string* | :heavy_check_mark: | N/A | | +| `Ledger` | **string* | :heavy_minus_sign: | N/A | | +| `ThroughAccount` | **string* | :heavy_minus_sign: | Account used when this ledger account interacts with external systems (payments, cross-ledger).
- As SOURCE going to payment: funds are sent to this account (e.g., "liabilities:payouts-pending")
- As DESTINATION from payment: funds come from this account (e.g., "assets:stripe:incoming")
- For cross-ledger transfers: replaces "world" on both sides
| liabilities:payouts-pending | +| `AllowOverdraft` | **bool* | :heavy_minus_sign: | Enables unbounded overdraft on the throughAccount when set to true.
This is useful when the throughAccount represents a liability or bridge account
that needs to go negative (e.g., "liabilities:payouts-pending").
Only applies when throughAccount is not "world" (which already has unbounded overdraft).
| true | \ No newline at end of file diff --git a/pkg/client/docs/models/components/v2stagesendsourcepayment.md b/pkg/client/docs/models/components/v2stagesendsourcepayment.md index 2548411..3e7f9c8 100644 --- a/pkg/client/docs/models/components/v2stagesendsourcepayment.md +++ b/pkg/client/docs/models/components/v2stagesendsourcepayment.md @@ -3,6 +3,10 @@ ## Fields -| Field | Type | Required | Description | -| ------------------ | ------------------ | ------------------ | ------------------ | -| `ID` | *string* | :heavy_check_mark: | N/A | \ No newline at end of file +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ID` | *string* | :heavy_check_mark: | N/A | +| `Ledger` | **string* | :heavy_minus_sign: | Ledger to use for payment ingestion.
Defaults to the internal orchestration ledger.
| +| `HoldingAccount` | **string* | :heavy_minus_sign: | Intermediate account where payment funds are held.
Defaults to "payment:{paymentID}" format.
| +| `ThroughAccount` | **string* | :heavy_minus_sign: | Source account for the payment ingestion transaction.
Defaults to "world".
| +| `AllowOverdraft` | **bool* | :heavy_minus_sign: | Enables unbounded overdraft on the throughAccount when set to true.
Only applies when throughAccount is not "world" (which already has unbounded overdraft).
| \ No newline at end of file diff --git a/pkg/client/docs/models/components/v2workflowinstancehistorystageinput.md b/pkg/client/docs/models/components/v2workflowinstancehistorystageinput.md index e4737f7..8173184 100644 --- a/pkg/client/docs/models/components/v2workflowinstancehistorystageinput.md +++ b/pkg/client/docs/models/components/v2workflowinstancehistorystageinput.md @@ -3,16 +3,17 @@ ## Fields -| Field | Type | Required | Description | -| --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- | -| `GetAccount` | [*components.V2ActivityGetAccount](../../models/components/v2activitygetaccount.md) | :heavy_minus_sign: | N/A | -| `AddAccountMetadata` | [*components.V2ActivityAddAccountMetadata](../../models/components/v2activityaddaccountmetadata.md) | :heavy_minus_sign: | N/A | -| `CreateTransaction` | [*components.V2ActivityCreateTransaction](../../models/components/v2activitycreatetransaction.md) | :heavy_minus_sign: | N/A | -| `StripeTransfer` | [*components.V2ActivityStripeTransfer](../../models/components/v2activitystripetransfer.md) | :heavy_minus_sign: | N/A | -| `GetPayment` | [*components.V2ActivityGetPayment](../../models/components/v2activitygetpayment.md) | :heavy_minus_sign: | N/A | -| `ConfirmHold` | [*components.V2ActivityConfirmHold](../../models/components/v2activityconfirmhold.md) | :heavy_minus_sign: | N/A | -| `CreditWallet` | [*components.V2ActivityCreditWallet](../../models/components/v2activitycreditwallet.md) | :heavy_minus_sign: | N/A | -| `DebitWallet` | [*components.V2ActivityDebitWallet](../../models/components/v2activitydebitwallet.md) | :heavy_minus_sign: | N/A | -| `GetWallet` | [*components.V2ActivityGetWallet](../../models/components/v2activitygetwallet.md) | :heavy_minus_sign: | N/A | -| `VoidHold` | [*components.V2ActivityVoidHold](../../models/components/v2activityvoidhold.md) | :heavy_minus_sign: | N/A | -| `ListWallets` | [*components.V2ActivityListWallets](../../models/components/v2activitylistwallets.md) | :heavy_minus_sign: | N/A | \ No newline at end of file +| Field | Type | Required | Description | +| --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | +| `GetAccount` | [*components.V2ActivityGetAccount](../../models/components/v2activitygetaccount.md) | :heavy_minus_sign: | N/A | +| `AddAccountMetadata` | [*components.V2ActivityAddAccountMetadata](../../models/components/v2activityaddaccountmetadata.md) | :heavy_minus_sign: | N/A | +| `CreateTransaction` | [*components.V2ActivityCreateTransaction](../../models/components/v2activitycreatetransaction.md) | :heavy_minus_sign: | N/A | +| `StripeTransfer` | [*components.V2ActivityStripeTransfer](../../models/components/v2activitystripetransfer.md) | :heavy_minus_sign: | N/A | +| `CreateTransferInitiation` | [*components.V2ActivityCreateTransferInitiation](../../models/components/v2activitycreatetransferinitiation.md) | :heavy_minus_sign: | N/A | +| `GetPayment` | [*components.V2ActivityGetPayment](../../models/components/v2activitygetpayment.md) | :heavy_minus_sign: | N/A | +| `ConfirmHold` | [*components.V2ActivityConfirmHold](../../models/components/v2activityconfirmhold.md) | :heavy_minus_sign: | N/A | +| `CreditWallet` | [*components.V2ActivityCreditWallet](../../models/components/v2activitycreditwallet.md) | :heavy_minus_sign: | N/A | +| `DebitWallet` | [*components.V2ActivityDebitWallet](../../models/components/v2activitydebitwallet.md) | :heavy_minus_sign: | N/A | +| `GetWallet` | [*components.V2ActivityGetWallet](../../models/components/v2activitygetwallet.md) | :heavy_minus_sign: | N/A | +| `VoidHold` | [*components.V2ActivityVoidHold](../../models/components/v2activityvoidhold.md) | :heavy_minus_sign: | N/A | +| `ListWallets` | [*components.V2ActivityListWallets](../../models/components/v2activitylistwallets.md) | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/pkg/client/docs/models/components/workflowinstancehistorystageinput.md b/pkg/client/docs/models/components/workflowinstancehistorystageinput.md index a05289e..521c99e 100644 --- a/pkg/client/docs/models/components/workflowinstancehistorystageinput.md +++ b/pkg/client/docs/models/components/workflowinstancehistorystageinput.md @@ -3,17 +3,18 @@ ## Fields -| Field | Type | Required | Description | -| ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | -| `GetAccount` | [*components.ActivityGetAccount](../../models/components/activitygetaccount.md) | :heavy_minus_sign: | N/A | -| `AddAccountMetadata` | [*components.ActivityAddAccountMetadata](../../models/components/activityaddaccountmetadata.md) | :heavy_minus_sign: | N/A | -| `CreateTransaction` | [*components.ActivityCreateTransaction](../../models/components/activitycreatetransaction.md) | :heavy_minus_sign: | N/A | -| `RevertTransaction` | [*components.ActivityRevertTransaction](../../models/components/activityreverttransaction.md) | :heavy_minus_sign: | N/A | -| `StripeTransfer` | [*components.ActivityStripeTransfer](../../models/components/activitystripetransfer.md) | :heavy_minus_sign: | N/A | -| `GetPayment` | [*components.ActivityGetPayment](../../models/components/activitygetpayment.md) | :heavy_minus_sign: | N/A | -| `ConfirmHold` | [*components.ActivityConfirmHold](../../models/components/activityconfirmhold.md) | :heavy_minus_sign: | N/A | -| `CreditWallet` | [*components.ActivityCreditWallet](../../models/components/activitycreditwallet.md) | :heavy_minus_sign: | N/A | -| `DebitWallet` | [*components.ActivityDebitWallet](../../models/components/activitydebitwallet.md) | :heavy_minus_sign: | N/A | -| `GetWallet` | [*components.ActivityGetWallet](../../models/components/activitygetwallet.md) | :heavy_minus_sign: | N/A | -| `VoidHold` | [*components.ActivityVoidHold](../../models/components/activityvoidhold.md) | :heavy_minus_sign: | N/A | -| `ListWallets` | [*components.ActivityListWallets](../../models/components/activitylistwallets.md) | :heavy_minus_sign: | N/A | \ No newline at end of file +| Field | Type | Required | Description | +| ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------- | +| `GetAccount` | [*components.ActivityGetAccount](../../models/components/activitygetaccount.md) | :heavy_minus_sign: | N/A | +| `AddAccountMetadata` | [*components.ActivityAddAccountMetadata](../../models/components/activityaddaccountmetadata.md) | :heavy_minus_sign: | N/A | +| `CreateTransaction` | [*components.ActivityCreateTransaction](../../models/components/activitycreatetransaction.md) | :heavy_minus_sign: | N/A | +| `RevertTransaction` | [*components.ActivityRevertTransaction](../../models/components/activityreverttransaction.md) | :heavy_minus_sign: | N/A | +| `StripeTransfer` | [*components.ActivityStripeTransfer](../../models/components/activitystripetransfer.md) | :heavy_minus_sign: | N/A | +| `CreateTransferInitiation` | [*components.ActivityCreateTransferInitiation](../../models/components/activitycreatetransferinitiation.md) | :heavy_minus_sign: | N/A | +| `GetPayment` | [*components.ActivityGetPayment](../../models/components/activitygetpayment.md) | :heavy_minus_sign: | N/A | +| `ConfirmHold` | [*components.ActivityConfirmHold](../../models/components/activityconfirmhold.md) | :heavy_minus_sign: | N/A | +| `CreditWallet` | [*components.ActivityCreditWallet](../../models/components/activitycreditwallet.md) | :heavy_minus_sign: | N/A | +| `DebitWallet` | [*components.ActivityDebitWallet](../../models/components/activitydebitwallet.md) | :heavy_minus_sign: | N/A | +| `GetWallet` | [*components.ActivityGetWallet](../../models/components/activitygetwallet.md) | :heavy_minus_sign: | N/A | +| `VoidHold` | [*components.ActivityVoidHold](../../models/components/activityvoidhold.md) | :heavy_minus_sign: | N/A | +| `ListWallets` | [*components.ActivityListWallets](../../models/components/activitylistwallets.md) | :heavy_minus_sign: | N/A | \ No newline at end of file diff --git a/pkg/client/docs/models/operations/listinstancesrequest.md b/pkg/client/docs/models/operations/listinstancesrequest.md index 4ae85d5..cc11efd 100644 --- a/pkg/client/docs/models/operations/listinstancesrequest.md +++ b/pkg/client/docs/models/operations/listinstancesrequest.md @@ -3,7 +3,9 @@ ## Fields -| Field | Type | Required | Description | Example | -| ------------------------ | ------------------------ | ------------------------ | ------------------------ | ------------------------ | -| `WorkflowID` | **string* | :heavy_minus_sign: | A workflow id | xxx | -| `Running` | **bool* | :heavy_minus_sign: | Filter running instances | true | \ No newline at end of file +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `WorkflowID` | **string* | :heavy_minus_sign: | A workflow id | xxx | +| `Running` | **bool* | :heavy_minus_sign: | Filter running instances | true | +| `PageSize` | **int64* | :heavy_minus_sign: | The maximum number of results to return per page.
| 100 | +| `Cursor` | **string* | :heavy_minus_sign: | Parameter used in pagination requests.
Set to the value of next for the next page of results.
Set to the value of previous for the previous page of results.
No other parameters can be set when this parameter is set.
| aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ== | \ No newline at end of file diff --git a/pkg/client/docs/models/operations/listtriggersoccurrencesrequest.md b/pkg/client/docs/models/operations/listtriggersoccurrencesrequest.md index ee2406b..e026e59 100644 --- a/pkg/client/docs/models/operations/listtriggersoccurrencesrequest.md +++ b/pkg/client/docs/models/operations/listtriggersoccurrencesrequest.md @@ -3,6 +3,8 @@ ## Fields -| Field | Type | Required | Description | -| ------------------ | ------------------ | ------------------ | ------------------ | -| `TriggerID` | *string* | :heavy_check_mark: | The trigger id | \ No newline at end of file +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `TriggerID` | *string* | :heavy_check_mark: | The trigger id | | +| `PageSize` | **int64* | :heavy_minus_sign: | The maximum number of results to return per page.
| 100 | +| `Cursor` | **string* | :heavy_minus_sign: | Parameter used in pagination requests.
Set to the value of next for the next page of results.
Set to the value of previous for the previous page of results.
No other parameters can be set when this parameter is set.
| aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ== | \ No newline at end of file diff --git a/pkg/client/docs/models/operations/listtriggersrequest.md b/pkg/client/docs/models/operations/listtriggersrequest.md index cfc708a..9e1047d 100644 --- a/pkg/client/docs/models/operations/listtriggersrequest.md +++ b/pkg/client/docs/models/operations/listtriggersrequest.md @@ -3,6 +3,8 @@ ## Fields -| Field | Type | Required | Description | -| ------------------ | ------------------ | ------------------ | ------------------ | -| `Name` | **string* | :heavy_minus_sign: | search by name | \ No newline at end of file +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `Name` | **string* | :heavy_minus_sign: | search by name | | +| `PageSize` | **int64* | :heavy_minus_sign: | The maximum number of results to return per page.
| 100 | +| `Cursor` | **string* | :heavy_minus_sign: | Parameter used in pagination requests.
Set to the value of next for the next page of results.
Set to the value of previous for the previous page of results.
No other parameters can be set when this parameter is set.
| aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ== | \ No newline at end of file diff --git a/pkg/client/docs/models/operations/listworkflowsrequest.md b/pkg/client/docs/models/operations/listworkflowsrequest.md new file mode 100644 index 0000000..e5bc8c3 --- /dev/null +++ b/pkg/client/docs/models/operations/listworkflowsrequest.md @@ -0,0 +1,9 @@ +# ListWorkflowsRequest + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `PageSize` | **int64* | :heavy_minus_sign: | The maximum number of results to return per page.
| 100 | +| `Cursor` | **string* | :heavy_minus_sign: | Parameter used in pagination requests.
Set to the value of next for the next page of results.
Set to the value of previous for the previous page of results.
No other parameters can be set when this parameter is set.
| aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ== | \ No newline at end of file diff --git a/pkg/client/docs/sdks/v1/README.md b/pkg/client/docs/sdks/v1/README.md index 0afd2b2..2e97d33 100644 --- a/pkg/client/docs/sdks/v1/README.md +++ b/pkg/client/docs/sdks/v1/README.md @@ -38,8 +38,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -90,13 +90,16 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), ) - request := operations.ListTriggersRequest{} + request := operations.ListTriggersRequest{ + PageSize: client.Int64(100), + Cursor: client.String("aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ=="), + } ctx := context.Background() res, err := s.Orchestration.V1.ListTriggers(ctx, request) if err != nil { @@ -142,8 +145,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -195,8 +198,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -250,8 +253,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -305,14 +308,16 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), ) request := operations.ListTriggersOccurrencesRequest{ TriggerID: "", + PageSize: client.Int64(100), + Cursor: client.String("aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ=="), } ctx := context.Background() res, err := s.Orchestration.V1.ListTriggersOccurrences(ctx, request) @@ -354,20 +359,24 @@ package main import( "github.com/formancehq/flows/pkg/client/models/components" "github.com/formancehq/flows/pkg/client" + "github.com/formancehq/flows/pkg/client/models/operations" "context" "log" ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), ) - + request := operations.ListWorkflowsRequest{ + PageSize: client.Int64(100), + Cursor: client.String("aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ=="), + } ctx := context.Background() - res, err := s.Orchestration.V1.ListWorkflows(ctx) + res, err := s.Orchestration.V1.ListWorkflows(ctx, request) if err != nil { log.Fatal(err) } @@ -379,10 +388,11 @@ func main() { ### Parameters -| Parameter | Type | Required | Description | -| -------------------------------------------------------- | -------------------------------------------------------- | -------------------------------------------------------- | -------------------------------------------------------- | -| `ctx` | [context.Context](https://pkg.go.dev/context#Context) | :heavy_check_mark: | The context to use for the request. | -| `opts` | [][operations.Option](../../models/operations/option.md) | :heavy_minus_sign: | The options for this request. | +| Parameter | Type | Required | Description | +| ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | +| `ctx` | [context.Context](https://pkg.go.dev/context#Context) | :heavy_check_mark: | The context to use for the request. | +| `request` | [operations.ListWorkflowsRequest](../../models/operations/listworkflowsrequest.md) | :heavy_check_mark: | The request object to use for the request. | +| `opts` | [][operations.Option](../../models/operations/option.md) | :heavy_minus_sign: | The options for this request. | ### Response @@ -410,8 +420,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -463,8 +473,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -518,8 +528,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -573,8 +583,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -628,15 +638,17 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), ) request := operations.ListInstancesRequest{ - WorkflowID: openapi.String("xxx"), - Running: openapi.Bool(true), + WorkflowID: client.String("xxx"), + Running: client.Bool(true), + PageSize: client.Int64(100), + Cursor: client.String("aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ=="), } ctx := context.Background() res, err := s.Orchestration.V1.ListInstances(ctx, request) @@ -684,8 +696,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -739,8 +751,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -794,8 +806,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -849,8 +861,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -904,8 +916,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), diff --git a/pkg/client/docs/sdks/v2/README.md b/pkg/client/docs/sdks/v2/README.md index 4e54f70..f725b56 100644 --- a/pkg/client/docs/sdks/v2/README.md +++ b/pkg/client/docs/sdks/v2/README.md @@ -39,8 +39,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -91,15 +91,15 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), ) request := operations.V2ListTriggersRequest{ - Cursor: openapi.String("aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ=="), - PageSize: openapi.Int64(100), + Cursor: client.String("aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ=="), + PageSize: client.Int64(100), } ctx := context.Background() res, err := s.Orchestration.V2.ListTriggers(ctx, request) @@ -146,8 +146,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -199,8 +199,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -254,8 +254,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -309,8 +309,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -364,16 +364,16 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), ) request := operations.V2ListTriggersOccurrencesRequest{ TriggerID: "", - Cursor: openapi.String("aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ=="), - PageSize: openapi.Int64(100), + Cursor: client.String("aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ=="), + PageSize: client.Int64(100), } ctx := context.Background() res, err := s.Orchestration.V2.ListTriggersOccurrences(ctx, request) @@ -421,15 +421,15 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), ) request := operations.V2ListWorkflowsRequest{ - Cursor: openapi.String("aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ=="), - PageSize: openapi.Int64(100), + Cursor: client.String("aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ=="), + PageSize: client.Int64(100), } ctx := context.Background() res, err := s.Orchestration.V2.ListWorkflows(ctx, request) @@ -476,8 +476,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -529,8 +529,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -584,8 +584,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -639,8 +639,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -694,17 +694,17 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), ) request := operations.V2ListInstancesRequest{ - Cursor: openapi.String("aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ=="), - PageSize: openapi.Int64(100), - WorkflowID: openapi.String("xxx"), - Running: openapi.Bool(true), + Cursor: client.String("aHR0cHM6Ly9nLnBhZ2UvTmVrby1SYW1lbj9zaGFyZQ=="), + PageSize: client.Int64(100), + WorkflowID: client.String("xxx"), + Running: client.Bool(true), } ctx := context.Background() res, err := s.Orchestration.V2.ListInstances(ctx, request) @@ -752,8 +752,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -807,8 +807,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -862,8 +862,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -917,8 +917,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), @@ -972,8 +972,8 @@ import( ) func main() { - s := openapi.New( - openapi.WithSecurity(components.Security{ + s := client.New( + client.WithSecurity(components.Security{ ClientID: "", ClientSecret: "", }), diff --git a/pkg/client/models/components/activitycreatetransferinitiation.go b/pkg/client/models/components/activitycreatetransferinitiation.go new file mode 100644 index 0000000..c625c4c --- /dev/null +++ b/pkg/client/models/components/activitycreatetransferinitiation.go @@ -0,0 +1,149 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package components + +import ( + "encoding/json" + "fmt" + "github.com/formancehq/flows/pkg/client/internal/utils" + "math/big" +) + +// ActivityCreateTransferInitiationType - Type of transfer initiation: +// - TRANSFER: Internal to internal account transfer +// - PAYOUT: Internal to external account payout +type ActivityCreateTransferInitiationType string + +const ( + ActivityCreateTransferInitiationTypeTransfer ActivityCreateTransferInitiationType = "TRANSFER" + ActivityCreateTransferInitiationTypePayout ActivityCreateTransferInitiationType = "PAYOUT" +) + +func (e ActivityCreateTransferInitiationType) ToPointer() *ActivityCreateTransferInitiationType { + return &e +} +func (e *ActivityCreateTransferInitiationType) UnmarshalJSON(data []byte) error { + var v string + if err := json.Unmarshal(data, &v); err != nil { + return err + } + switch v { + case "TRANSFER": + fallthrough + case "PAYOUT": + *e = ActivityCreateTransferInitiationType(v) + return nil + default: + return fmt.Errorf("invalid value for ActivityCreateTransferInitiationType: %v", v) + } +} + +// ActivityCreateTransferInitiationMetadata - A set of key/value pairs that you can attach to a transfer object. It can be useful for storing additional information about the transfer in a structured format. +type ActivityCreateTransferInitiationMetadata struct { +} + +type ActivityCreateTransferInitiation struct { + ConnectorID *string `json:"connectorID,omitempty"` + // Payment service provider name (e.g., stripe, wise, mangopay). + // Validated by the Payments service based on installed connectors. + // + Provider *string `json:"provider,omitempty"` + Amount *big.Int `json:"amount,omitempty"` + Asset *string `json:"asset,omitempty"` + // Destination account ID + Destination *string `json:"destination,omitempty"` + // Source account ID (required for TRANSFER type) + Source *string `json:"source,omitempty"` + // Type of transfer initiation: + // - TRANSFER: Internal to internal account transfer + // - PAYOUT: Internal to external account payout + // + Type *ActivityCreateTransferInitiationType `default:"TRANSFER" json:"type"` + // Description for the transfer initiation + Description *string `json:"description,omitempty"` + WaitingValidation *bool `default:"false" json:"waitingValidation"` + // A set of key/value pairs that you can attach to a transfer object. It can be useful for storing additional information about the transfer in a structured format. + // + Metadata *ActivityCreateTransferInitiationMetadata `json:"metadata,omitempty"` +} + +func (a ActivityCreateTransferInitiation) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(a, "", false) +} + +func (a *ActivityCreateTransferInitiation) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &a, "", false, false); err != nil { + return err + } + return nil +} + +func (o *ActivityCreateTransferInitiation) GetConnectorID() *string { + if o == nil { + return nil + } + return o.ConnectorID +} + +func (o *ActivityCreateTransferInitiation) GetProvider() *string { + if o == nil { + return nil + } + return o.Provider +} + +func (o *ActivityCreateTransferInitiation) GetAmount() *big.Int { + if o == nil { + return nil + } + return o.Amount +} + +func (o *ActivityCreateTransferInitiation) GetAsset() *string { + if o == nil { + return nil + } + return o.Asset +} + +func (o *ActivityCreateTransferInitiation) GetDestination() *string { + if o == nil { + return nil + } + return o.Destination +} + +func (o *ActivityCreateTransferInitiation) GetSource() *string { + if o == nil { + return nil + } + return o.Source +} + +func (o *ActivityCreateTransferInitiation) GetType() *ActivityCreateTransferInitiationType { + if o == nil { + return nil + } + return o.Type +} + +func (o *ActivityCreateTransferInitiation) GetDescription() *string { + if o == nil { + return nil + } + return o.Description +} + +func (o *ActivityCreateTransferInitiation) GetWaitingValidation() *bool { + if o == nil { + return nil + } + return o.WaitingValidation +} + +func (o *ActivityCreateTransferInitiation) GetMetadata() *ActivityCreateTransferInitiationMetadata { + if o == nil { + return nil + } + return o.Metadata +} diff --git a/pkg/client/models/components/listrunsresponse.go b/pkg/client/models/components/listrunsresponse.go index 5af27ef..e3c8776 100644 --- a/pkg/client/models/components/listrunsresponse.go +++ b/pkg/client/models/components/listrunsresponse.go @@ -3,7 +3,11 @@ package components type ListRunsResponse struct { - Data []WorkflowInstance `json:"data"` + Data []WorkflowInstance `json:"data"` + PageSize int64 `json:"pageSize"` + HasMore bool `json:"hasMore"` + Previous *string `json:"previous,omitempty"` + Next *string `json:"next,omitempty"` } func (o *ListRunsResponse) GetData() []WorkflowInstance { @@ -12,3 +16,31 @@ func (o *ListRunsResponse) GetData() []WorkflowInstance { } return o.Data } + +func (o *ListRunsResponse) GetPageSize() int64 { + if o == nil { + return 0 + } + return o.PageSize +} + +func (o *ListRunsResponse) GetHasMore() bool { + if o == nil { + return false + } + return o.HasMore +} + +func (o *ListRunsResponse) GetPrevious() *string { + if o == nil { + return nil + } + return o.Previous +} + +func (o *ListRunsResponse) GetNext() *string { + if o == nil { + return nil + } + return o.Next +} diff --git a/pkg/client/models/components/listtriggersoccurrencesresponse.go b/pkg/client/models/components/listtriggersoccurrencesresponse.go index 06368b3..7993513 100644 --- a/pkg/client/models/components/listtriggersoccurrencesresponse.go +++ b/pkg/client/models/components/listtriggersoccurrencesresponse.go @@ -3,7 +3,11 @@ package components type ListTriggersOccurrencesResponse struct { - Data []TriggerOccurrence `json:"data"` + Data []TriggerOccurrence `json:"data"` + PageSize int64 `json:"pageSize"` + HasMore bool `json:"hasMore"` + Previous *string `json:"previous,omitempty"` + Next *string `json:"next,omitempty"` } func (o *ListTriggersOccurrencesResponse) GetData() []TriggerOccurrence { @@ -12,3 +16,31 @@ func (o *ListTriggersOccurrencesResponse) GetData() []TriggerOccurrence { } return o.Data } + +func (o *ListTriggersOccurrencesResponse) GetPageSize() int64 { + if o == nil { + return 0 + } + return o.PageSize +} + +func (o *ListTriggersOccurrencesResponse) GetHasMore() bool { + if o == nil { + return false + } + return o.HasMore +} + +func (o *ListTriggersOccurrencesResponse) GetPrevious() *string { + if o == nil { + return nil + } + return o.Previous +} + +func (o *ListTriggersOccurrencesResponse) GetNext() *string { + if o == nil { + return nil + } + return o.Next +} diff --git a/pkg/client/models/components/listtriggersresponse.go b/pkg/client/models/components/listtriggersresponse.go index 7e06bbb..7b05a6a 100644 --- a/pkg/client/models/components/listtriggersresponse.go +++ b/pkg/client/models/components/listtriggersresponse.go @@ -3,7 +3,11 @@ package components type ListTriggersResponse struct { - Data []Trigger `json:"data"` + Data []Trigger `json:"data"` + PageSize int64 `json:"pageSize"` + HasMore bool `json:"hasMore"` + Previous *string `json:"previous,omitempty"` + Next *string `json:"next,omitempty"` } func (o *ListTriggersResponse) GetData() []Trigger { @@ -12,3 +16,31 @@ func (o *ListTriggersResponse) GetData() []Trigger { } return o.Data } + +func (o *ListTriggersResponse) GetPageSize() int64 { + if o == nil { + return 0 + } + return o.PageSize +} + +func (o *ListTriggersResponse) GetHasMore() bool { + if o == nil { + return false + } + return o.HasMore +} + +func (o *ListTriggersResponse) GetPrevious() *string { + if o == nil { + return nil + } + return o.Previous +} + +func (o *ListTriggersResponse) GetNext() *string { + if o == nil { + return nil + } + return o.Next +} diff --git a/pkg/client/models/components/listworkflowsresponse.go b/pkg/client/models/components/listworkflowsresponse.go index 8b734b1..07c8bee 100644 --- a/pkg/client/models/components/listworkflowsresponse.go +++ b/pkg/client/models/components/listworkflowsresponse.go @@ -3,7 +3,11 @@ package components type ListWorkflowsResponse struct { - Data []Workflow `json:"data"` + Data []Workflow `json:"data"` + PageSize int64 `json:"pageSize"` + HasMore bool `json:"hasMore"` + Previous *string `json:"previous,omitempty"` + Next *string `json:"next,omitempty"` } func (o *ListWorkflowsResponse) GetData() []Workflow { @@ -12,3 +16,31 @@ func (o *ListWorkflowsResponse) GetData() []Workflow { } return o.Data } + +func (o *ListWorkflowsResponse) GetPageSize() int64 { + if o == nil { + return 0 + } + return o.PageSize +} + +func (o *ListWorkflowsResponse) GetHasMore() bool { + if o == nil { + return false + } + return o.HasMore +} + +func (o *ListWorkflowsResponse) GetPrevious() *string { + if o == nil { + return nil + } + return o.Previous +} + +func (o *ListWorkflowsResponse) GetNext() *string { + if o == nil { + return nil + } + return o.Next +} diff --git a/pkg/client/models/components/payment.go b/pkg/client/models/components/payment.go index d1c92a7..d2654ca 100644 --- a/pkg/client/models/components/payment.go +++ b/pkg/client/models/components/payment.go @@ -10,19 +10,19 @@ import ( "time" ) -type Type string +type PaymentType string const ( - TypePayIn Type = "PAY-IN" - TypePayout Type = "PAYOUT" - TypeTransfer Type = "TRANSFER" - TypeOther Type = "OTHER" + PaymentTypePayIn PaymentType = "PAY-IN" + PaymentTypePayout PaymentType = "PAYOUT" + PaymentTypeTransfer PaymentType = "TRANSFER" + PaymentTypeOther PaymentType = "OTHER" ) -func (e Type) ToPointer() *Type { +func (e PaymentType) ToPointer() *PaymentType { return &e } -func (e *Type) UnmarshalJSON(data []byte) error { +func (e *PaymentType) UnmarshalJSON(data []byte) error { var v string if err := json.Unmarshal(data, &v); err != nil { return err @@ -35,10 +35,10 @@ func (e *Type) UnmarshalJSON(data []byte) error { case "TRANSFER": fallthrough case "OTHER": - *e = Type(v) + *e = PaymentType(v) return nil default: - return fmt.Errorf("invalid value for Type: %v", v) + return fmt.Errorf("invalid value for PaymentType: %v", v) } } @@ -126,7 +126,7 @@ type Payment struct { DestinationAccountID string `json:"destinationAccountID"` ConnectorID string `json:"connectorID"` Provider *Connector `json:"provider,omitempty"` - Type Type `json:"type"` + Type PaymentType `json:"type"` Status PaymentStatus `json:"status"` InitialAmount *big.Int `json:"initialAmount"` Scheme Scheme `json:"scheme"` @@ -190,9 +190,9 @@ func (o *Payment) GetProvider() *Connector { return o.Provider } -func (o *Payment) GetType() Type { +func (o *Payment) GetType() PaymentType { if o == nil { - return Type("") + return PaymentType("") } return o.Type } diff --git a/pkg/client/models/components/stagesenddestinationaccount.go b/pkg/client/models/components/stagesenddestinationaccount.go index a782592..b721092 100644 --- a/pkg/client/models/components/stagesenddestinationaccount.go +++ b/pkg/client/models/components/stagesenddestinationaccount.go @@ -2,9 +2,36 @@ package components +import ( + "github.com/formancehq/flows/pkg/client/internal/utils" +) + type StageSendDestinationAccount struct { ID string `json:"id"` Ledger *string `json:"ledger,omitempty"` + // Account used when this ledger account interacts with external systems (payments, cross-ledger). + // - As SOURCE going to payment: funds are sent to this account (e.g., "liabilities:payouts-pending") + // - As DESTINATION from payment: funds come from this account (e.g., "assets:stripe:incoming") + // - For cross-ledger transfers: replaces "world" on both sides + // + ThroughAccount *string `default:"world" json:"throughAccount"` + // Enables unbounded overdraft on the throughAccount when set to true. + // This is useful when the throughAccount represents a liability or bridge account + // that needs to go negative (e.g., "liabilities:payouts-pending"). + // Only applies when throughAccount is not "world" (which already has unbounded overdraft). + // + AllowOverdraft *bool `default:"false" json:"allowOverdraft"` +} + +func (s StageSendDestinationAccount) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(s, "", false) +} + +func (s *StageSendDestinationAccount) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &s, "", false, false); err != nil { + return err + } + return nil } func (o *StageSendDestinationAccount) GetID() string { @@ -20,3 +47,17 @@ func (o *StageSendDestinationAccount) GetLedger() *string { } return o.Ledger } + +func (o *StageSendDestinationAccount) GetThroughAccount() *string { + if o == nil { + return nil + } + return o.ThroughAccount +} + +func (o *StageSendDestinationAccount) GetAllowOverdraft() *bool { + if o == nil { + return nil + } + return o.AllowOverdraft +} diff --git a/pkg/client/models/components/stagesenddestinationpayment.go b/pkg/client/models/components/stagesenddestinationpayment.go index 74394b6..4e7d9df 100644 --- a/pkg/client/models/components/stagesenddestinationpayment.go +++ b/pkg/client/models/components/stagesenddestinationpayment.go @@ -2,8 +2,66 @@ package components +import ( + "encoding/json" + "fmt" + "github.com/formancehq/flows/pkg/client/internal/utils" +) + +// Type of transfer initiation: +// - TRANSFER: Internal to internal account transfer +// - PAYOUT: Internal to external account payout +type Type string + +const ( + TypeTransfer Type = "TRANSFER" + TypePayout Type = "PAYOUT" +) + +func (e Type) ToPointer() *Type { + return &e +} +func (e *Type) UnmarshalJSON(data []byte) error { + var v string + if err := json.Unmarshal(data, &v); err != nil { + return err + } + switch v { + case "TRANSFER": + fallthrough + case "PAYOUT": + *e = Type(v) + return nil + default: + return fmt.Errorf("invalid value for Type: %v", v) + } +} + type StageSendDestinationPayment struct { + // Payment service provider name (e.g., stripe, wise, mangopay). + // Validated by the Payments service based on installed connectors. + // Psp string `json:"psp"` + // Type of transfer initiation: + // - TRANSFER: Internal to internal account transfer + // - PAYOUT: Internal to external account payout + // + Type *Type `default:"TRANSFER" json:"type"` + // Formance Payments account ID for the source (internal PSP account). + // If not specified, the Payments service may use a default account for the connector. + // + SourceAccount *string `json:"sourceAccount,omitempty"` +} + +func (s StageSendDestinationPayment) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(s, "", false) +} + +func (s *StageSendDestinationPayment) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &s, "", false, false); err != nil { + return err + } + return nil } func (o *StageSendDestinationPayment) GetPsp() string { @@ -12,3 +70,17 @@ func (o *StageSendDestinationPayment) GetPsp() string { } return o.Psp } + +func (o *StageSendDestinationPayment) GetType() *Type { + if o == nil { + return nil + } + return o.Type +} + +func (o *StageSendDestinationPayment) GetSourceAccount() *string { + if o == nil { + return nil + } + return o.SourceAccount +} diff --git a/pkg/client/models/components/stagesendsourceaccount.go b/pkg/client/models/components/stagesendsourceaccount.go index 0e459b6..ae0df1c 100644 --- a/pkg/client/models/components/stagesendsourceaccount.go +++ b/pkg/client/models/components/stagesendsourceaccount.go @@ -2,9 +2,36 @@ package components +import ( + "github.com/formancehq/flows/pkg/client/internal/utils" +) + type StageSendSourceAccount struct { ID string `json:"id"` Ledger *string `json:"ledger,omitempty"` + // Account used when this ledger account interacts with external systems (payments, cross-ledger). + // - As SOURCE going to payment: funds are sent to this account (e.g., "liabilities:payouts-pending") + // - As DESTINATION from payment: funds come from this account (e.g., "assets:stripe:incoming") + // - For cross-ledger transfers: replaces "world" on both sides + // + ThroughAccount *string `default:"world" json:"throughAccount"` + // Enables unbounded overdraft on the throughAccount when set to true. + // This is useful when the throughAccount represents a liability or bridge account + // that needs to go negative (e.g., "liabilities:payouts-pending"). + // Only applies when throughAccount is not "world" (which already has unbounded overdraft). + // + AllowOverdraft *bool `default:"false" json:"allowOverdraft"` +} + +func (s StageSendSourceAccount) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(s, "", false) +} + +func (s *StageSendSourceAccount) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &s, "", false, false); err != nil { + return err + } + return nil } func (o *StageSendSourceAccount) GetID() string { @@ -20,3 +47,17 @@ func (o *StageSendSourceAccount) GetLedger() *string { } return o.Ledger } + +func (o *StageSendSourceAccount) GetThroughAccount() *string { + if o == nil { + return nil + } + return o.ThroughAccount +} + +func (o *StageSendSourceAccount) GetAllowOverdraft() *bool { + if o == nil { + return nil + } + return o.AllowOverdraft +} diff --git a/pkg/client/models/components/stagesendsourcepayment.go b/pkg/client/models/components/stagesendsourcepayment.go index 49b85c3..d985c44 100644 --- a/pkg/client/models/components/stagesendsourcepayment.go +++ b/pkg/client/models/components/stagesendsourcepayment.go @@ -2,8 +2,39 @@ package components +import ( + "github.com/formancehq/flows/pkg/client/internal/utils" +) + type StageSendSourcePayment struct { ID string `json:"id"` + // Ledger to use for payment ingestion. + // Defaults to the internal orchestration ledger. + // + Ledger *string `json:"ledger,omitempty"` + // Intermediate account where payment funds are held. + // Defaults to "payment:{paymentID}" format. + // + HoldingAccount *string `json:"holdingAccount,omitempty"` + // Source account for the payment ingestion transaction. + // Defaults to "world". + // + ThroughAccount *string `default:"world" json:"throughAccount"` + // Enables unbounded overdraft on the throughAccount when set to true. + // Only applies when throughAccount is not "world" (which already has unbounded overdraft). + // + AllowOverdraft *bool `default:"false" json:"allowOverdraft"` +} + +func (s StageSendSourcePayment) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(s, "", false) +} + +func (s *StageSendSourcePayment) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &s, "", false, false); err != nil { + return err + } + return nil } func (o *StageSendSourcePayment) GetID() string { @@ -12,3 +43,31 @@ func (o *StageSendSourcePayment) GetID() string { } return o.ID } + +func (o *StageSendSourcePayment) GetLedger() *string { + if o == nil { + return nil + } + return o.Ledger +} + +func (o *StageSendSourcePayment) GetHoldingAccount() *string { + if o == nil { + return nil + } + return o.HoldingAccount +} + +func (o *StageSendSourcePayment) GetThroughAccount() *string { + if o == nil { + return nil + } + return o.ThroughAccount +} + +func (o *StageSendSourcePayment) GetAllowOverdraft() *bool { + if o == nil { + return nil + } + return o.AllowOverdraft +} diff --git a/pkg/client/models/components/v2activitycreatetransferinitiation.go b/pkg/client/models/components/v2activitycreatetransferinitiation.go new file mode 100644 index 0000000..83e8cb8 --- /dev/null +++ b/pkg/client/models/components/v2activitycreatetransferinitiation.go @@ -0,0 +1,149 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package components + +import ( + "encoding/json" + "fmt" + "github.com/formancehq/flows/pkg/client/internal/utils" + "math/big" +) + +// V2ActivityCreateTransferInitiationType - Type of transfer initiation: +// - TRANSFER: Internal to internal account transfer +// - PAYOUT: Internal to external account payout +type V2ActivityCreateTransferInitiationType string + +const ( + V2ActivityCreateTransferInitiationTypeTransfer V2ActivityCreateTransferInitiationType = "TRANSFER" + V2ActivityCreateTransferInitiationTypePayout V2ActivityCreateTransferInitiationType = "PAYOUT" +) + +func (e V2ActivityCreateTransferInitiationType) ToPointer() *V2ActivityCreateTransferInitiationType { + return &e +} +func (e *V2ActivityCreateTransferInitiationType) UnmarshalJSON(data []byte) error { + var v string + if err := json.Unmarshal(data, &v); err != nil { + return err + } + switch v { + case "TRANSFER": + fallthrough + case "PAYOUT": + *e = V2ActivityCreateTransferInitiationType(v) + return nil + default: + return fmt.Errorf("invalid value for V2ActivityCreateTransferInitiationType: %v", v) + } +} + +// V2ActivityCreateTransferInitiationMetadata - A set of key/value pairs that you can attach to a transfer object. It can be useful for storing additional information about the transfer in a structured format. +type V2ActivityCreateTransferInitiationMetadata struct { +} + +type V2ActivityCreateTransferInitiation struct { + ConnectorID *string `json:"connectorID,omitempty"` + // Payment service provider name (e.g., stripe, wise, mangopay). + // Validated by the Payments service based on installed connectors. + // + Provider *string `json:"provider,omitempty"` + Amount *big.Int `json:"amount,omitempty"` + Asset *string `json:"asset,omitempty"` + // Destination account ID + Destination *string `json:"destination,omitempty"` + // Source account ID (required for TRANSFER type) + Source *string `json:"source,omitempty"` + // Type of transfer initiation: + // - TRANSFER: Internal to internal account transfer + // - PAYOUT: Internal to external account payout + // + Type *V2ActivityCreateTransferInitiationType `default:"TRANSFER" json:"type"` + // Description for the transfer initiation + Description *string `json:"description,omitempty"` + WaitingValidation *bool `default:"false" json:"waitingValidation"` + // A set of key/value pairs that you can attach to a transfer object. It can be useful for storing additional information about the transfer in a structured format. + // + Metadata *V2ActivityCreateTransferInitiationMetadata `json:"metadata,omitempty"` +} + +func (v V2ActivityCreateTransferInitiation) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(v, "", false) +} + +func (v *V2ActivityCreateTransferInitiation) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &v, "", false, false); err != nil { + return err + } + return nil +} + +func (o *V2ActivityCreateTransferInitiation) GetConnectorID() *string { + if o == nil { + return nil + } + return o.ConnectorID +} + +func (o *V2ActivityCreateTransferInitiation) GetProvider() *string { + if o == nil { + return nil + } + return o.Provider +} + +func (o *V2ActivityCreateTransferInitiation) GetAmount() *big.Int { + if o == nil { + return nil + } + return o.Amount +} + +func (o *V2ActivityCreateTransferInitiation) GetAsset() *string { + if o == nil { + return nil + } + return o.Asset +} + +func (o *V2ActivityCreateTransferInitiation) GetDestination() *string { + if o == nil { + return nil + } + return o.Destination +} + +func (o *V2ActivityCreateTransferInitiation) GetSource() *string { + if o == nil { + return nil + } + return o.Source +} + +func (o *V2ActivityCreateTransferInitiation) GetType() *V2ActivityCreateTransferInitiationType { + if o == nil { + return nil + } + return o.Type +} + +func (o *V2ActivityCreateTransferInitiation) GetDescription() *string { + if o == nil { + return nil + } + return o.Description +} + +func (o *V2ActivityCreateTransferInitiation) GetWaitingValidation() *bool { + if o == nil { + return nil + } + return o.WaitingValidation +} + +func (o *V2ActivityCreateTransferInitiation) GetMetadata() *V2ActivityCreateTransferInitiationMetadata { + if o == nil { + return nil + } + return o.Metadata +} diff --git a/pkg/client/models/components/v2stagesenddestinationaccount.go b/pkg/client/models/components/v2stagesenddestinationaccount.go index 75a7b5c..c487be8 100644 --- a/pkg/client/models/components/v2stagesenddestinationaccount.go +++ b/pkg/client/models/components/v2stagesenddestinationaccount.go @@ -2,9 +2,36 @@ package components +import ( + "github.com/formancehq/flows/pkg/client/internal/utils" +) + type V2StageSendDestinationAccount struct { ID string `json:"id"` Ledger *string `json:"ledger,omitempty"` + // Account used when this ledger account interacts with external systems (payments, cross-ledger). + // - As SOURCE going to payment: funds are sent to this account (e.g., "liabilities:payouts-pending") + // - As DESTINATION from payment: funds come from this account (e.g., "assets:stripe:incoming") + // - For cross-ledger transfers: replaces "world" on both sides + // + ThroughAccount *string `default:"world" json:"throughAccount"` + // Enables unbounded overdraft on the throughAccount when set to true. + // This is useful when the throughAccount represents a liability or bridge account + // that needs to go negative (e.g., "liabilities:payouts-pending"). + // Only applies when throughAccount is not "world" (which already has unbounded overdraft). + // + AllowOverdraft *bool `default:"false" json:"allowOverdraft"` +} + +func (v V2StageSendDestinationAccount) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(v, "", false) +} + +func (v *V2StageSendDestinationAccount) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &v, "", false, false); err != nil { + return err + } + return nil } func (o *V2StageSendDestinationAccount) GetID() string { @@ -20,3 +47,17 @@ func (o *V2StageSendDestinationAccount) GetLedger() *string { } return o.Ledger } + +func (o *V2StageSendDestinationAccount) GetThroughAccount() *string { + if o == nil { + return nil + } + return o.ThroughAccount +} + +func (o *V2StageSendDestinationAccount) GetAllowOverdraft() *bool { + if o == nil { + return nil + } + return o.AllowOverdraft +} diff --git a/pkg/client/models/components/v2stagesenddestinationpayment.go b/pkg/client/models/components/v2stagesenddestinationpayment.go index 9ce969e..6893507 100644 --- a/pkg/client/models/components/v2stagesenddestinationpayment.go +++ b/pkg/client/models/components/v2stagesenddestinationpayment.go @@ -2,8 +2,66 @@ package components +import ( + "encoding/json" + "fmt" + "github.com/formancehq/flows/pkg/client/internal/utils" +) + +// V2StageSendDestinationPaymentType - Type of transfer initiation: +// - TRANSFER: Internal to internal account transfer +// - PAYOUT: Internal to external account payout +type V2StageSendDestinationPaymentType string + +const ( + V2StageSendDestinationPaymentTypeTransfer V2StageSendDestinationPaymentType = "TRANSFER" + V2StageSendDestinationPaymentTypePayout V2StageSendDestinationPaymentType = "PAYOUT" +) + +func (e V2StageSendDestinationPaymentType) ToPointer() *V2StageSendDestinationPaymentType { + return &e +} +func (e *V2StageSendDestinationPaymentType) UnmarshalJSON(data []byte) error { + var v string + if err := json.Unmarshal(data, &v); err != nil { + return err + } + switch v { + case "TRANSFER": + fallthrough + case "PAYOUT": + *e = V2StageSendDestinationPaymentType(v) + return nil + default: + return fmt.Errorf("invalid value for V2StageSendDestinationPaymentType: %v", v) + } +} + type V2StageSendDestinationPayment struct { + // Payment service provider name (e.g., stripe, wise, mangopay). + // Validated by the Payments service based on installed connectors. + // Psp string `json:"psp"` + // Type of transfer initiation: + // - TRANSFER: Internal to internal account transfer + // - PAYOUT: Internal to external account payout + // + Type *V2StageSendDestinationPaymentType `default:"TRANSFER" json:"type"` + // Formance Payments account ID for the source (internal PSP account). + // If not specified, the Payments service may use a default account for the connector. + // + SourceAccount *string `json:"sourceAccount,omitempty"` +} + +func (v V2StageSendDestinationPayment) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(v, "", false) +} + +func (v *V2StageSendDestinationPayment) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &v, "", false, false); err != nil { + return err + } + return nil } func (o *V2StageSendDestinationPayment) GetPsp() string { @@ -12,3 +70,17 @@ func (o *V2StageSendDestinationPayment) GetPsp() string { } return o.Psp } + +func (o *V2StageSendDestinationPayment) GetType() *V2StageSendDestinationPaymentType { + if o == nil { + return nil + } + return o.Type +} + +func (o *V2StageSendDestinationPayment) GetSourceAccount() *string { + if o == nil { + return nil + } + return o.SourceAccount +} diff --git a/pkg/client/models/components/v2stagesendsourceaccount.go b/pkg/client/models/components/v2stagesendsourceaccount.go index 9320921..a09e47f 100644 --- a/pkg/client/models/components/v2stagesendsourceaccount.go +++ b/pkg/client/models/components/v2stagesendsourceaccount.go @@ -2,9 +2,36 @@ package components +import ( + "github.com/formancehq/flows/pkg/client/internal/utils" +) + type V2StageSendSourceAccount struct { ID string `json:"id"` Ledger *string `json:"ledger,omitempty"` + // Account used when this ledger account interacts with external systems (payments, cross-ledger). + // - As SOURCE going to payment: funds are sent to this account (e.g., "liabilities:payouts-pending") + // - As DESTINATION from payment: funds come from this account (e.g., "assets:stripe:incoming") + // - For cross-ledger transfers: replaces "world" on both sides + // + ThroughAccount *string `default:"world" json:"throughAccount"` + // Enables unbounded overdraft on the throughAccount when set to true. + // This is useful when the throughAccount represents a liability or bridge account + // that needs to go negative (e.g., "liabilities:payouts-pending"). + // Only applies when throughAccount is not "world" (which already has unbounded overdraft). + // + AllowOverdraft *bool `default:"false" json:"allowOverdraft"` +} + +func (v V2StageSendSourceAccount) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(v, "", false) +} + +func (v *V2StageSendSourceAccount) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &v, "", false, false); err != nil { + return err + } + return nil } func (o *V2StageSendSourceAccount) GetID() string { @@ -20,3 +47,17 @@ func (o *V2StageSendSourceAccount) GetLedger() *string { } return o.Ledger } + +func (o *V2StageSendSourceAccount) GetThroughAccount() *string { + if o == nil { + return nil + } + return o.ThroughAccount +} + +func (o *V2StageSendSourceAccount) GetAllowOverdraft() *bool { + if o == nil { + return nil + } + return o.AllowOverdraft +} diff --git a/pkg/client/models/components/v2stagesendsourcepayment.go b/pkg/client/models/components/v2stagesendsourcepayment.go index 3590fca..3cd6bc9 100644 --- a/pkg/client/models/components/v2stagesendsourcepayment.go +++ b/pkg/client/models/components/v2stagesendsourcepayment.go @@ -2,8 +2,39 @@ package components +import ( + "github.com/formancehq/flows/pkg/client/internal/utils" +) + type V2StageSendSourcePayment struct { ID string `json:"id"` + // Ledger to use for payment ingestion. + // Defaults to the internal orchestration ledger. + // + Ledger *string `json:"ledger,omitempty"` + // Intermediate account where payment funds are held. + // Defaults to "payment:{paymentID}" format. + // + HoldingAccount *string `json:"holdingAccount,omitempty"` + // Source account for the payment ingestion transaction. + // Defaults to "world". + // + ThroughAccount *string `default:"world" json:"throughAccount"` + // Enables unbounded overdraft on the throughAccount when set to true. + // Only applies when throughAccount is not "world" (which already has unbounded overdraft). + // + AllowOverdraft *bool `default:"false" json:"allowOverdraft"` +} + +func (v V2StageSendSourcePayment) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(v, "", false) +} + +func (v *V2StageSendSourcePayment) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &v, "", false, false); err != nil { + return err + } + return nil } func (o *V2StageSendSourcePayment) GetID() string { @@ -12,3 +43,31 @@ func (o *V2StageSendSourcePayment) GetID() string { } return o.ID } + +func (o *V2StageSendSourcePayment) GetLedger() *string { + if o == nil { + return nil + } + return o.Ledger +} + +func (o *V2StageSendSourcePayment) GetHoldingAccount() *string { + if o == nil { + return nil + } + return o.HoldingAccount +} + +func (o *V2StageSendSourcePayment) GetThroughAccount() *string { + if o == nil { + return nil + } + return o.ThroughAccount +} + +func (o *V2StageSendSourcePayment) GetAllowOverdraft() *bool { + if o == nil { + return nil + } + return o.AllowOverdraft +} diff --git a/pkg/client/models/components/v2workflowinstancehistorystageinput.go b/pkg/client/models/components/v2workflowinstancehistorystageinput.go index d179e20..1a20e26 100644 --- a/pkg/client/models/components/v2workflowinstancehistorystageinput.go +++ b/pkg/client/models/components/v2workflowinstancehistorystageinput.go @@ -3,17 +3,18 @@ package components type V2WorkflowInstanceHistoryStageInput struct { - GetAccount *V2ActivityGetAccount `json:"GetAccount,omitempty"` - AddAccountMetadata *V2ActivityAddAccountMetadata `json:"AddAccountMetadata,omitempty"` - CreateTransaction *V2ActivityCreateTransaction `json:"CreateTransaction,omitempty"` - StripeTransfer *V2ActivityStripeTransfer `json:"StripeTransfer,omitempty"` - GetPayment *V2ActivityGetPayment `json:"GetPayment,omitempty"` - ConfirmHold *V2ActivityConfirmHold `json:"ConfirmHold,omitempty"` - CreditWallet *V2ActivityCreditWallet `json:"CreditWallet,omitempty"` - DebitWallet *V2ActivityDebitWallet `json:"DebitWallet,omitempty"` - GetWallet *V2ActivityGetWallet `json:"GetWallet,omitempty"` - VoidHold *V2ActivityVoidHold `json:"VoidHold,omitempty"` - ListWallets *V2ActivityListWallets `json:"ListWallets,omitempty"` + GetAccount *V2ActivityGetAccount `json:"GetAccount,omitempty"` + AddAccountMetadata *V2ActivityAddAccountMetadata `json:"AddAccountMetadata,omitempty"` + CreateTransaction *V2ActivityCreateTransaction `json:"CreateTransaction,omitempty"` + StripeTransfer *V2ActivityStripeTransfer `json:"StripeTransfer,omitempty"` + CreateTransferInitiation *V2ActivityCreateTransferInitiation `json:"CreateTransferInitiation,omitempty"` + GetPayment *V2ActivityGetPayment `json:"GetPayment,omitempty"` + ConfirmHold *V2ActivityConfirmHold `json:"ConfirmHold,omitempty"` + CreditWallet *V2ActivityCreditWallet `json:"CreditWallet,omitempty"` + DebitWallet *V2ActivityDebitWallet `json:"DebitWallet,omitempty"` + GetWallet *V2ActivityGetWallet `json:"GetWallet,omitempty"` + VoidHold *V2ActivityVoidHold `json:"VoidHold,omitempty"` + ListWallets *V2ActivityListWallets `json:"ListWallets,omitempty"` } func (o *V2WorkflowInstanceHistoryStageInput) GetGetAccount() *V2ActivityGetAccount { @@ -44,6 +45,13 @@ func (o *V2WorkflowInstanceHistoryStageInput) GetStripeTransfer() *V2ActivityStr return o.StripeTransfer } +func (o *V2WorkflowInstanceHistoryStageInput) GetCreateTransferInitiation() *V2ActivityCreateTransferInitiation { + if o == nil { + return nil + } + return o.CreateTransferInitiation +} + func (o *V2WorkflowInstanceHistoryStageInput) GetGetPayment() *V2ActivityGetPayment { if o == nil { return nil diff --git a/pkg/client/models/components/workflowinstancehistorystageinput.go b/pkg/client/models/components/workflowinstancehistorystageinput.go index a247f6d..cacc1f5 100644 --- a/pkg/client/models/components/workflowinstancehistorystageinput.go +++ b/pkg/client/models/components/workflowinstancehistorystageinput.go @@ -3,18 +3,19 @@ package components type WorkflowInstanceHistoryStageInput struct { - GetAccount *ActivityGetAccount `json:"GetAccount,omitempty"` - AddAccountMetadata *ActivityAddAccountMetadata `json:"AddAccountMetadata,omitempty"` - CreateTransaction *ActivityCreateTransaction `json:"CreateTransaction,omitempty"` - RevertTransaction *ActivityRevertTransaction `json:"RevertTransaction,omitempty"` - StripeTransfer *ActivityStripeTransfer `json:"StripeTransfer,omitempty"` - GetPayment *ActivityGetPayment `json:"GetPayment,omitempty"` - ConfirmHold *ActivityConfirmHold `json:"ConfirmHold,omitempty"` - CreditWallet *ActivityCreditWallet `json:"CreditWallet,omitempty"` - DebitWallet *ActivityDebitWallet `json:"DebitWallet,omitempty"` - GetWallet *ActivityGetWallet `json:"GetWallet,omitempty"` - VoidHold *ActivityVoidHold `json:"VoidHold,omitempty"` - ListWallets *ActivityListWallets `json:"ListWallets,omitempty"` + GetAccount *ActivityGetAccount `json:"GetAccount,omitempty"` + AddAccountMetadata *ActivityAddAccountMetadata `json:"AddAccountMetadata,omitempty"` + CreateTransaction *ActivityCreateTransaction `json:"CreateTransaction,omitempty"` + RevertTransaction *ActivityRevertTransaction `json:"RevertTransaction,omitempty"` + StripeTransfer *ActivityStripeTransfer `json:"StripeTransfer,omitempty"` + CreateTransferInitiation *ActivityCreateTransferInitiation `json:"CreateTransferInitiation,omitempty"` + GetPayment *ActivityGetPayment `json:"GetPayment,omitempty"` + ConfirmHold *ActivityConfirmHold `json:"ConfirmHold,omitempty"` + CreditWallet *ActivityCreditWallet `json:"CreditWallet,omitempty"` + DebitWallet *ActivityDebitWallet `json:"DebitWallet,omitempty"` + GetWallet *ActivityGetWallet `json:"GetWallet,omitempty"` + VoidHold *ActivityVoidHold `json:"VoidHold,omitempty"` + ListWallets *ActivityListWallets `json:"ListWallets,omitempty"` } func (o *WorkflowInstanceHistoryStageInput) GetGetAccount() *ActivityGetAccount { @@ -52,6 +53,13 @@ func (o *WorkflowInstanceHistoryStageInput) GetStripeTransfer() *ActivityStripeT return o.StripeTransfer } +func (o *WorkflowInstanceHistoryStageInput) GetCreateTransferInitiation() *ActivityCreateTransferInitiation { + if o == nil { + return nil + } + return o.CreateTransferInitiation +} + func (o *WorkflowInstanceHistoryStageInput) GetGetPayment() *ActivityGetPayment { if o == nil { return nil diff --git a/pkg/client/models/operations/listinstances.go b/pkg/client/models/operations/listinstances.go index 9a503a5..c53a7da 100644 --- a/pkg/client/models/operations/listinstances.go +++ b/pkg/client/models/operations/listinstances.go @@ -3,6 +3,7 @@ package operations import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "github.com/formancehq/flows/pkg/client/models/components" ) @@ -11,6 +12,26 @@ type ListInstancesRequest struct { WorkflowID *string `queryParam:"style=form,explode=true,name=workflowID"` // Filter running instances Running *bool `queryParam:"style=form,explode=true,name=running"` + // The maximum number of results to return per page. + // + PageSize *int64 `default:"15" queryParam:"style=form,explode=true,name=pageSize"` + // Parameter used in pagination requests. + // Set to the value of next for the next page of results. + // Set to the value of previous for the previous page of results. + // No other parameters can be set when this parameter is set. + // + Cursor *string `queryParam:"style=form,explode=true,name=cursor"` +} + +func (l ListInstancesRequest) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(l, "", false) +} + +func (l *ListInstancesRequest) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &l, "", false, false); err != nil { + return err + } + return nil } func (o *ListInstancesRequest) GetWorkflowID() *string { @@ -27,6 +48,20 @@ func (o *ListInstancesRequest) GetRunning() *bool { return o.Running } +func (o *ListInstancesRequest) GetPageSize() *int64 { + if o == nil { + return nil + } + return o.PageSize +} + +func (o *ListInstancesRequest) GetCursor() *string { + if o == nil { + return nil + } + return o.Cursor +} + type ListInstancesResponse struct { HTTPMeta components.HTTPMetadata `json:"-"` // List of workflow instances diff --git a/pkg/client/models/operations/listtriggers.go b/pkg/client/models/operations/listtriggers.go index 72edf2c..63897da 100644 --- a/pkg/client/models/operations/listtriggers.go +++ b/pkg/client/models/operations/listtriggers.go @@ -3,12 +3,33 @@ package operations import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "github.com/formancehq/flows/pkg/client/models/components" ) type ListTriggersRequest struct { // search by name Name *string `queryParam:"style=form,explode=true,name=name"` + // The maximum number of results to return per page. + // + PageSize *int64 `default:"15" queryParam:"style=form,explode=true,name=pageSize"` + // Parameter used in pagination requests. + // Set to the value of next for the next page of results. + // Set to the value of previous for the previous page of results. + // No other parameters can be set when this parameter is set. + // + Cursor *string `queryParam:"style=form,explode=true,name=cursor"` +} + +func (l ListTriggersRequest) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(l, "", false) +} + +func (l *ListTriggersRequest) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &l, "", false, false); err != nil { + return err + } + return nil } func (o *ListTriggersRequest) GetName() *string { @@ -18,6 +39,20 @@ func (o *ListTriggersRequest) GetName() *string { return o.Name } +func (o *ListTriggersRequest) GetPageSize() *int64 { + if o == nil { + return nil + } + return o.PageSize +} + +func (o *ListTriggersRequest) GetCursor() *string { + if o == nil { + return nil + } + return o.Cursor +} + type ListTriggersResponse struct { HTTPMeta components.HTTPMetadata `json:"-"` // List of triggers diff --git a/pkg/client/models/operations/listtriggersoccurrences.go b/pkg/client/models/operations/listtriggersoccurrences.go index 0b0637e..9b9445e 100644 --- a/pkg/client/models/operations/listtriggersoccurrences.go +++ b/pkg/client/models/operations/listtriggersoccurrences.go @@ -3,12 +3,33 @@ package operations import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "github.com/formancehq/flows/pkg/client/models/components" ) type ListTriggersOccurrencesRequest struct { // The trigger id TriggerID string `pathParam:"style=simple,explode=false,name=triggerID"` + // The maximum number of results to return per page. + // + PageSize *int64 `default:"15" queryParam:"style=form,explode=true,name=pageSize"` + // Parameter used in pagination requests. + // Set to the value of next for the next page of results. + // Set to the value of previous for the previous page of results. + // No other parameters can be set when this parameter is set. + // + Cursor *string `queryParam:"style=form,explode=true,name=cursor"` +} + +func (l ListTriggersOccurrencesRequest) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(l, "", false) +} + +func (l *ListTriggersOccurrencesRequest) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &l, "", false, false); err != nil { + return err + } + return nil } func (o *ListTriggersOccurrencesRequest) GetTriggerID() string { @@ -18,6 +39,20 @@ func (o *ListTriggersOccurrencesRequest) GetTriggerID() string { return o.TriggerID } +func (o *ListTriggersOccurrencesRequest) GetPageSize() *int64 { + if o == nil { + return nil + } + return o.PageSize +} + +func (o *ListTriggersOccurrencesRequest) GetCursor() *string { + if o == nil { + return nil + } + return o.Cursor +} + type ListTriggersOccurrencesResponse struct { HTTPMeta components.HTTPMetadata `json:"-"` // List of triggers occurrences diff --git a/pkg/client/models/operations/listworkflows.go b/pkg/client/models/operations/listworkflows.go index ea9f10b..7b99f1d 100644 --- a/pkg/client/models/operations/listworkflows.go +++ b/pkg/client/models/operations/listworkflows.go @@ -3,9 +3,47 @@ package operations import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "github.com/formancehq/flows/pkg/client/models/components" ) +type ListWorkflowsRequest struct { + // The maximum number of results to return per page. + // + PageSize *int64 `default:"15" queryParam:"style=form,explode=true,name=pageSize"` + // Parameter used in pagination requests. + // Set to the value of next for the next page of results. + // Set to the value of previous for the previous page of results. + // No other parameters can be set when this parameter is set. + // + Cursor *string `queryParam:"style=form,explode=true,name=cursor"` +} + +func (l ListWorkflowsRequest) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(l, "", false) +} + +func (l *ListWorkflowsRequest) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &l, "", false, false); err != nil { + return err + } + return nil +} + +func (o *ListWorkflowsRequest) GetPageSize() *int64 { + if o == nil { + return nil + } + return o.PageSize +} + +func (o *ListWorkflowsRequest) GetCursor() *string { + if o == nil { + return nil + } + return o.Cursor +} + type ListWorkflowsResponse struct { HTTPMeta components.HTTPMetadata `json:"-"` // List of workflows diff --git a/pkg/client/models/operations/v2listinstances.go b/pkg/client/models/operations/v2listinstances.go index 394cc47..9ce001f 100644 --- a/pkg/client/models/operations/v2listinstances.go +++ b/pkg/client/models/operations/v2listinstances.go @@ -3,6 +3,7 @@ package operations import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "github.com/formancehq/flows/pkg/client/models/components" ) @@ -15,13 +16,24 @@ type V2ListInstancesRequest struct { Cursor *string `queryParam:"style=form,explode=true,name=cursor"` // The maximum number of results to return per page. // - PageSize *int64 `queryParam:"style=form,explode=true,name=pageSize"` + PageSize *int64 `default:"15" queryParam:"style=form,explode=true,name=pageSize"` // A workflow id WorkflowID *string `queryParam:"style=form,explode=true,name=workflowID"` // Filter running instances Running *bool `queryParam:"style=form,explode=true,name=running"` } +func (v V2ListInstancesRequest) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(v, "", false) +} + +func (v *V2ListInstancesRequest) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &v, "", false, false); err != nil { + return err + } + return nil +} + func (o *V2ListInstancesRequest) GetCursor() *string { if o == nil { return nil diff --git a/pkg/client/models/operations/v2listtriggers.go b/pkg/client/models/operations/v2listtriggers.go index 21f35f0..b37050a 100644 --- a/pkg/client/models/operations/v2listtriggers.go +++ b/pkg/client/models/operations/v2listtriggers.go @@ -3,6 +3,7 @@ package operations import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "github.com/formancehq/flows/pkg/client/models/components" ) @@ -15,11 +16,22 @@ type V2ListTriggersRequest struct { Cursor *string `queryParam:"style=form,explode=true,name=cursor"` // The maximum number of results to return per page. // - PageSize *int64 `queryParam:"style=form,explode=true,name=pageSize"` + PageSize *int64 `default:"15" queryParam:"style=form,explode=true,name=pageSize"` // search by name Name *string `queryParam:"style=form,explode=true,name=name"` } +func (v V2ListTriggersRequest) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(v, "", false) +} + +func (v *V2ListTriggersRequest) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &v, "", false, false); err != nil { + return err + } + return nil +} + func (o *V2ListTriggersRequest) GetCursor() *string { if o == nil { return nil diff --git a/pkg/client/models/operations/v2listtriggersoccurrences.go b/pkg/client/models/operations/v2listtriggersoccurrences.go index ae1e0b2..6234d92 100644 --- a/pkg/client/models/operations/v2listtriggersoccurrences.go +++ b/pkg/client/models/operations/v2listtriggersoccurrences.go @@ -3,6 +3,7 @@ package operations import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "github.com/formancehq/flows/pkg/client/models/components" ) @@ -17,7 +18,18 @@ type V2ListTriggersOccurrencesRequest struct { Cursor *string `queryParam:"style=form,explode=true,name=cursor"` // The maximum number of results to return per page. // - PageSize *int64 `queryParam:"style=form,explode=true,name=pageSize"` + PageSize *int64 `default:"15" queryParam:"style=form,explode=true,name=pageSize"` +} + +func (v V2ListTriggersOccurrencesRequest) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(v, "", false) +} + +func (v *V2ListTriggersOccurrencesRequest) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &v, "", false, false); err != nil { + return err + } + return nil } func (o *V2ListTriggersOccurrencesRequest) GetTriggerID() string { diff --git a/pkg/client/models/operations/v2listworkflows.go b/pkg/client/models/operations/v2listworkflows.go index ed4d77b..ac9a3f7 100644 --- a/pkg/client/models/operations/v2listworkflows.go +++ b/pkg/client/models/operations/v2listworkflows.go @@ -3,6 +3,7 @@ package operations import ( + "github.com/formancehq/flows/pkg/client/internal/utils" "github.com/formancehq/flows/pkg/client/models/components" ) @@ -15,7 +16,18 @@ type V2ListWorkflowsRequest struct { Cursor *string `queryParam:"style=form,explode=true,name=cursor"` // The maximum number of results to return per page. // - PageSize *int64 `queryParam:"style=form,explode=true,name=pageSize"` + PageSize *int64 `default:"15" queryParam:"style=form,explode=true,name=pageSize"` +} + +func (v V2ListWorkflowsRequest) MarshalJSON() ([]byte, error) { + return utils.MarshalJSON(v, "", false) +} + +func (v *V2ListWorkflowsRequest) UnmarshalJSON(data []byte) error { + if err := utils.UnmarshalJSON(data, &v, "", false, false); err != nil { + return err + } + return nil } func (o *V2ListWorkflowsRequest) GetCursor() *string { diff --git a/pkg/client/orchestration.go b/pkg/client/orchestration.go index 75c97e3..847e9c9 100644 --- a/pkg/client/orchestration.go +++ b/pkg/client/orchestration.go @@ -1,6 +1,6 @@ // Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. -package openapi +package client type Orchestration struct { V1 *V1 diff --git a/pkg/client/sdk.go b/pkg/client/sdk.go index 2ca0925..7a55d41 100644 --- a/pkg/client/sdk.go +++ b/pkg/client/sdk.go @@ -1,6 +1,6 @@ // Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. -package openapi +package client import ( "context" @@ -143,9 +143,9 @@ func New(opts ...SDKOption) *SDK { sdkConfiguration: sdkConfiguration{ Language: "go", OpenAPIDocVersion: "0.1.0", - SDKVersion: "0.1.4", + SDKVersion: "0.1.6", GenVersion: "2.384.1", - UserAgent: "speakeasy-sdk/go 0.1.4 2.384.1 0.1.0 openapi", + UserAgent: "speakeasy-sdk/go 0.1.6 2.384.1 0.1.0 github.com/formancehq/flows/pkg/client", Hooks: hooks.New(), }, } diff --git a/pkg/client/v1.go b/pkg/client/v1.go index 5cd9992..1c29f53 100644 --- a/pkg/client/v1.go +++ b/pkg/client/v1.go @@ -1,6 +1,6 @@ // Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. -package openapi +package client import ( "bytes" @@ -971,6 +971,10 @@ func (s *V1) ListTriggersOccurrences(ctx context.Context, request operations.Lis req.Header.Set("Accept", "application/json") req.Header.Set("User-Agent", s.sdkConfiguration.UserAgent) + if err := utils.PopulateQueryParams(ctx, req, request, nil); err != nil { + return nil, fmt.Errorf("error populating query params: %w", err) + } + if err := utils.PopulateSecurity(ctx, req, s.sdkConfiguration.Security); err != nil { return nil, err } @@ -1107,7 +1111,7 @@ func (s *V1) ListTriggersOccurrences(ctx context.Context, request operations.Lis // ListWorkflows - List registered workflows // List registered workflows -func (s *V1) ListWorkflows(ctx context.Context, opts ...operations.Option) (*operations.ListWorkflowsResponse, error) { +func (s *V1) ListWorkflows(ctx context.Context, request operations.ListWorkflowsRequest, opts ...operations.Option) (*operations.ListWorkflowsResponse, error) { hookCtx := hooks.HookContext{ Context: ctx, OperationID: "listWorkflows", @@ -1151,6 +1155,10 @@ func (s *V1) ListWorkflows(ctx context.Context, opts ...operations.Option) (*ope req.Header.Set("Accept", "application/json") req.Header.Set("User-Agent", s.sdkConfiguration.UserAgent) + if err := utils.PopulateQueryParams(ctx, req, request, nil); err != nil { + return nil, fmt.Errorf("error populating query params: %w", err) + } + if err := utils.PopulateSecurity(ctx, req, s.sdkConfiguration.Security); err != nil { return nil, err } diff --git a/pkg/client/v2.go b/pkg/client/v2.go index 0141fcb..03b75e1 100644 --- a/pkg/client/v2.go +++ b/pkg/client/v2.go @@ -1,6 +1,6 @@ // Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. -package openapi +package client import ( "bytes" From a8e1175afd26939cf2419ad535b3afb5dafa9010 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Wed, 5 Aug 2026 13:36:56 +0200 Subject: [PATCH 19/22] fix: address automated review findings --- cmd/serve.go | 6 +++++- cmd/worker.go | 22 ++++++++++++++++---- cmd/worker_test.go | 32 ++++++++++++++++++++++++++++++ internal/triggers/expression.go | 27 ++++++++++++++++--------- internal/triggers/listener.go | 3 +++ internal/triggers/listener_test.go | 26 ++++++++++++++++++++++++ internal/triggers/trigger_test.go | 5 +++++ internal/workflow/manager_test.go | 3 +++ 8 files changed, 110 insertions(+), 14 deletions(-) create mode 100644 cmd/worker_test.go diff --git a/cmd/serve.go b/cmd/serve.go index 54e8acb..84430f1 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -71,7 +71,11 @@ func newServeCommand() *cobra.Command { } worker, _ := cmd.Flags().GetBool(workerFlag) if worker { - options = append(options, workerOptions(cmd)) + workerOptions, err := workerOptions(cmd) + if err != nil { + return err + } + options = append(options, workerOptions) } return service.New(cmd.OutOrStdout(), options...).Run(cmd) diff --git a/cmd/worker.go b/cmd/worker.go index 1fd17de..cccc31d 100644 --- a/cmd/worker.go +++ b/cmd/worker.go @@ -1,6 +1,8 @@ package cmd import ( + "fmt" + "math" "net/http" sdk "github.com/formancehq/formance-sdk-go/v3" @@ -31,13 +33,21 @@ func stackClientModule(cmd *cobra.Command) fx.Option { ) } -func workerOptions(cmd *cobra.Command) fx.Option { +func workerOptions(cmd *cobra.Command) (fx.Option, error) { stack, _ := cmd.Flags().GetString(stackFlag) temporalTaskQueue, _ := cmd.Flags().GetString(temporal.TemporalTaskQueueFlag) // The flag is registered as a float64 in go-libs; reading it with GetInt // silently fails and yields 0, so the configured limit was never applied. - temporalMaxParallelActivities, _ := cmd.Flags().GetFloat64(temporal.TemporalMaxParallelActivitiesFlag) + temporalMaxParallelActivities, err := cmd.Flags().GetFloat64(temporal.TemporalMaxParallelActivitiesFlag) + if err != nil { + return nil, err + } + if temporalMaxParallelActivities <= 0 || + math.Trunc(temporalMaxParallelActivities) != temporalMaxParallelActivities || + temporalMaxParallelActivities > float64(math.MaxInt) { + return nil, fmt.Errorf("%s must be a positive whole number", temporal.TemporalMaxParallelActivitiesFlag) + } topics, _ := cmd.Flags().GetStringSlice(topicsFlag) return fx.Options( @@ -55,7 +65,7 @@ func workerOptions(cmd *cobra.Command) fx.Option { true, topics, ), - ) + ), nil } func newWorkerCommand() *cobra.Command { @@ -66,8 +76,12 @@ func newWorkerCommand() *cobra.Command { if err != nil { return err } + workerOptions, err := workerOptions(cmd) + if err != nil { + return err + } - return service.New(cmd.OutOrStdout(), commonOptions, workerOptions(cmd)).Run(cmd) + return service.New(cmd.OutOrStdout(), commonOptions, workerOptions).Run(cmd) }, } ret.Flags().String(stackURLFlag, "", "Stack url") diff --git a/cmd/worker_test.go b/cmd/worker_test.go new file mode 100644 index 0000000..54d35c8 --- /dev/null +++ b/cmd/worker_test.go @@ -0,0 +1,32 @@ +package cmd + +import ( + "testing" + + "github.com/formancehq/go-libs/v5/pkg/workflow/temporal" + "github.com/stretchr/testify/require" +) + +func TestWorkerOptionsValidatesMaxParallelActivities(t *testing.T) { + for _, testCase := range []struct { + name string + value string + wantErr bool + }{ + {name: "positive integer", value: "10"}, + {name: "zero", value: "0", wantErr: true}, + {name: "negative", value: "-1", wantErr: true}, + {name: "fractional", value: "0.5", wantErr: true}, + } { + t.Run(testCase.name, func(t *testing.T) { + cmd := newWorkerCommand() + require.NoError(t, cmd.Flags().Set(temporal.TemporalMaxParallelActivitiesFlag, testCase.value)) + _, err := workerOptions(cmd) + if testCase.wantErr { + require.Error(t, err) + return + } + require.NoError(t, err) + }) + } +} diff --git a/internal/triggers/expression.go b/internal/triggers/expression.go index 02e1a54..0033bce 100644 --- a/internal/triggers/expression.go +++ b/internal/triggers/expression.go @@ -18,7 +18,11 @@ import ( type expressionEvaluator struct { httpClient *http.Client - // allowedHosts is the set of hosts link() is permitted to call. It exists + // allowedHosts permits bare-host configuration for callers that do not have + // a canonical stack URL. allowedOrigins is preferred and pins both scheme + // and host, preventing redirects from downgrading an HTTPS stack to HTTP. + allowedOrigins map[string]struct{} + // The allowlist exists // to prevent the (credential-bearing) HTTP client from being pointed at an // arbitrary, attacker-controlled host via a user-defined trigger // expression (SSRF + bearer-token exfiltration). An empty set denies every @@ -40,7 +44,10 @@ func (h *expressionEvaluator) checkLinkURL(raw string) error { fmt.Sprintf("link url scheme not allowed: %q", u.Scheme), "APPLICATION", fmt.Errorf("scheme %q not allowed", u.Scheme)) } - if _, ok := h.allowedHosts[strings.ToLower(u.Host)]; !ok { + origin := strings.ToLower(u.Scheme + "://" + u.Host) + _, originAllowed := h.allowedOrigins[origin] + _, hostAllowed := h.allowedHosts[strings.ToLower(u.Host)] + if !originAllowed && !hostAllowed { return temporal.NewNonRetryableApplicationError( fmt.Sprintf("link url host not allowed: %q", u.Host), "APPLICATION", fmt.Errorf("host %q is not in the allowlist", u.Host)) @@ -178,29 +185,31 @@ func (h *expressionEvaluator) evalVariables(rawObject any, vars map[string]strin } // NewExpressionEvaluator builds an evaluator whose link() function may only -// reach the provided hosts. Each entry may be a bare host ("example.com:8080") -// or a full URL, in which case only its host is retained. With no allowed host, -// link() network calls are denied. +// reach the provided targets. A full URL pins both scheme and host; a bare host +// permits either HTTP scheme for callers without a canonical stack URL. With +// no allowed target, link() network calls are denied. func NewExpressionEvaluator(httpClient *http.Client, allowedHosts ...string) *expressionEvaluator { if httpClient == nil { httpClient = http.DefaultClient } hosts := make(map[string]struct{}, len(allowedHosts)) + origins := make(map[string]struct{}, len(allowedHosts)) for _, h := range allowedHosts { if h == "" { continue } - if u, err := url.Parse(h); err == nil && u.Host != "" { - hosts[strings.ToLower(u.Host)] = struct{}{} + if u, err := url.Parse(h); err == nil && u.Scheme != "" && u.Host != "" { + origins[strings.ToLower(u.Scheme+"://"+u.Host)] = struct{}{} continue } hosts[strings.ToLower(h)] = struct{}{} } client := *httpClient evaluator := &expressionEvaluator{ - httpClient: &client, - allowedHosts: hosts, + httpClient: &client, + allowedOrigins: origins, + allowedHosts: hosts, } previousCheckRedirect := client.CheckRedirect client.CheckRedirect = func(req *http.Request, via []*http.Request) error { diff --git a/internal/triggers/listener.go b/internal/triggers/listener.go index 0244708..a13e46b 100644 --- a/internal/triggers/listener.go +++ b/internal/triggers/listener.go @@ -43,6 +43,9 @@ func getWorkflowIDFromEvent(event publish.EventMessage) (*string, error) { if err := json.Unmarshal(data, o); err != nil { return nil, errors.Wrap(err, "unmarshalling event payload") } + if o.ID == "" { + return nil, errors.New("event payload id is required") + } return pointer.For(o.ID), nil default: diff --git a/internal/triggers/listener_test.go b/internal/triggers/listener_test.go index ef89147..da65ee4 100644 --- a/internal/triggers/listener_test.go +++ b/internal/triggers/listener_test.go @@ -40,6 +40,32 @@ func setupTestDB(t *testing.T) *bun.DB { return db } +func TestGetWorkflowIDFromEvent(t *testing.T) { + for _, testCase := range []struct { + name string + payload any + }{ + {name: "missing id", payload: map[string]any{}}, + {name: "null id", payload: map[string]any{"id": nil}}, + {name: "empty id", payload: map[string]any{"id": ""}}, + } { + t.Run(testCase.name, func(t *testing.T) { + _, err := getWorkflowIDFromEvent(publish.EventMessage{ + Type: "SAVED_PAYMENT", + Payload: testCase.payload, + }) + require.Error(t, err) + }) + } + + id, err := getWorkflowIDFromEvent(publish.EventMessage{ + Type: "SAVED_PAYMENT", + Payload: map[string]any{"id": "payment-id"}, + }) + require.NoError(t, err) + require.Equal(t, "payment-id", *id) +} + func insertNoOpWorkflow(t *testing.T, db *bun.DB) workflow.Workflow { t.Helper() diff --git a/internal/triggers/trigger_test.go b/internal/triggers/trigger_test.go index 20e3012..7860c63 100644 --- a/internal/triggers/trigger_test.go +++ b/internal/triggers/trigger_test.go @@ -207,6 +207,11 @@ func TestLinkHostAllowlist(t *testing.T) { require.False(t, hit) }) + t.Run("configured origin rejects a scheme downgrade", func(t *testing.T) { + e := NewExpressionEvaluator(http.DefaultClient, "https://allowed.example.com") + require.Error(t, e.checkLinkURL("http://allowed.example.com/resource")) + }) + t.Run("allowed when host matches", func(t *testing.T) { hit = false e := NewExpressionEvaluator(http.DefaultClient, srv.URL) diff --git a/internal/workflow/manager_test.go b/internal/workflow/manager_test.go index ca03788..0d74d67 100644 --- a/internal/workflow/manager_test.go +++ b/internal/workflow/manager_test.go @@ -162,6 +162,9 @@ func TestSoftDeletedWorkflowIsNotUsable(t *testing.T) { DatabaseSourceName: database.ConnString(), }) require.NoError(t, err) + t.Cleanup(func() { + _ = db.Close() + }) require.NoError(t, storage.Migrate(logging.TestingContext(), db)) manager := NewManager(db, devServer.Client(), "test", uuid.NewString(), false) From 49f29160e31aeb4ab3fb65f32e9ed81c6e506698 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Wed, 5 Aug 2026 16:22:12 +0200 Subject: [PATCH 20/22] fix(worker): reject activity concurrency overflow --- cmd/worker.go | 4 +++- cmd/worker_test.go | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/cmd/worker.go b/cmd/worker.go index cccc31d..f23d826 100644 --- a/cmd/worker.go +++ b/cmd/worker.go @@ -4,6 +4,7 @@ import ( "fmt" "math" "net/http" + "strconv" sdk "github.com/formancehq/formance-sdk-go/v3" "github.com/formancehq/go-libs/v5/pkg/authn/licence" @@ -43,9 +44,10 @@ func workerOptions(cmd *cobra.Command) (fx.Option, error) { if err != nil { return nil, err } + maxIntExclusive := math.Exp2(float64(strconv.IntSize - 1)) if temporalMaxParallelActivities <= 0 || math.Trunc(temporalMaxParallelActivities) != temporalMaxParallelActivities || - temporalMaxParallelActivities > float64(math.MaxInt) { + temporalMaxParallelActivities >= maxIntExclusive { return nil, fmt.Errorf("%s must be a positive whole number", temporal.TemporalMaxParallelActivitiesFlag) } topics, _ := cmd.Flags().GetStringSlice(topicsFlag) diff --git a/cmd/worker_test.go b/cmd/worker_test.go index 54d35c8..2f3d405 100644 --- a/cmd/worker_test.go +++ b/cmd/worker_test.go @@ -17,6 +17,7 @@ func TestWorkerOptionsValidatesMaxParallelActivities(t *testing.T) { {name: "zero", value: "0", wantErr: true}, {name: "negative", value: "-1", wantErr: true}, {name: "fractional", value: "0.5", wantErr: true}, + {name: "int overflow", value: "9223372036854775808", wantErr: true}, } { t.Run(testCase.name, func(t *testing.T) { cmd := newWorkerCommand() From ff2e4aa6c57156a65bef76003147d506d8a9407b Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 6 Aug 2026 09:59:03 +0200 Subject: [PATCH 21/22] fix(api): enforce pagination bounds from cursors --- internal/api/v1/handler_list_instances.go | 1 + .../api/v1/handler_list_instances_test.go | 33 +++++++++++++++++++ internal/api/v1/handler_list_triggers.go | 1 + .../v1/handler_list_triggers_occurrences.go | 1 + internal/api/v1/handler_list_workflows.go | 1 + internal/api/v1/pagination.go | 13 ++++++++ openapi.yaml | 2 +- openapi/v2.yaml | 2 +- pkg/client/.speakeasy/gen.lock | 6 ++-- pkg/client/.speakeasy/gen.yaml | 2 +- pkg/client/sdk.go | 4 +-- 11 files changed, 58 insertions(+), 8 deletions(-) diff --git a/internal/api/v1/handler_list_instances.go b/internal/api/v1/handler_list_instances.go index f4ada37..0ce1d81 100644 --- a/internal/api/v1/handler_list_instances.go +++ b/internal/api/v1/handler_list_instances.go @@ -33,6 +33,7 @@ func listInstances(backend api.Backend) http.HandlerFunc { sharedapi.BadRequest(w, "VALIDATION", err) return } + query.PageSize = normalizePageSize(query.PageSize) runs, err := backend.ListInstances(r.Context(), *query) if err != nil { diff --git a/internal/api/v1/handler_list_instances_test.go b/internal/api/v1/handler_list_instances_test.go index 7b525fd..2263ffe 100644 --- a/internal/api/v1/handler_list_instances_test.go +++ b/internal/api/v1/handler_list_instances_test.go @@ -10,6 +10,7 @@ import ( "time" "github.com/formancehq/go-libs/v5/pkg/observe/log" + bunpaginate "github.com/formancehq/go-libs/v5/pkg/storage/bun/paginate" "github.com/go-chi/chi/v5" @@ -138,6 +139,38 @@ func TestListInstancesIsBounded(t *testing.T) { require.Len(t, secondPage.Data, 5) require.False(t, secondPage.HasMore) + // Cursors are client-controlled base64 JSON. A forged zero page size must + // be normalized to the default instead of disabling LIMIT entirely. + forgedCursor := bunpaginate.EncodeCursor(workflow.ListInstancesQuery{}) + req = httptest.NewRequest(http.MethodGet, "/instances?cursor="+url.QueryEscape(forgedCursor), nil) + rec = httptest.NewRecorder() + router.ServeHTTP(rec, req) + require.Equal(t, http.StatusOK, rec.Result().StatusCode) + var forgedPage struct { + Data []workflow.Instance `json:"data"` + PageSize int `json:"pageSize"` + } + require.NoError(t, json.NewDecoder(rec.Body).Decode(&forgedPage)) + require.Len(t, forgedPage.Data, bunpaginate.QueryDefaultPageSize) + require.Equal(t, bunpaginate.QueryDefaultPageSize, forgedPage.PageSize) + + // Oversized page sizes embedded in cursors are capped just like explicit + // pageSize query parameters. + forgedCursor = bunpaginate.EncodeCursor(workflow.ListInstancesQuery{ + PageSize: bunpaginate.MaxPageSize + 1, + }) + req = httptest.NewRequest(http.MethodGet, "/instances?cursor="+url.QueryEscape(forgedCursor), nil) + rec = httptest.NewRecorder() + router.ServeHTTP(rec, req) + require.Equal(t, http.StatusOK, rec.Result().StatusCode) + forgedPage = struct { + Data []workflow.Instance `json:"data"` + PageSize int `json:"pageSize"` + }{} + require.NoError(t, json.NewDecoder(rec.Body).Decode(&forgedPage)) + require.Len(t, forgedPage.Data, 20) + require.Equal(t, bunpaginate.MaxPageSize, forgedPage.PageSize) + // An explicit page size is honoured. req = httptest.NewRequest(http.MethodGet, "/instances?pageSize=5", nil) rec = httptest.NewRecorder() diff --git a/internal/api/v1/handler_list_triggers.go b/internal/api/v1/handler_list_triggers.go index e76f03b..49613f2 100644 --- a/internal/api/v1/handler_list_triggers.go +++ b/internal/api/v1/handler_list_triggers.go @@ -31,6 +31,7 @@ func listTriggers(backend api.Backend) func(writer http.ResponseWriter, request sharedapi.BadRequest(w, "VALIDATION", err) return } + query.PageSize = normalizePageSize(query.PageSize) triggers, err := backend.ListTriggers(r.Context(), *query) if err != nil { diff --git a/internal/api/v1/handler_list_triggers_occurrences.go b/internal/api/v1/handler_list_triggers_occurrences.go index 5537948..9ee854e 100644 --- a/internal/api/v1/handler_list_triggers_occurrences.go +++ b/internal/api/v1/handler_list_triggers_occurrences.go @@ -29,6 +29,7 @@ func listTriggersOccurrences(backend api.Backend) func(writer http.ResponseWrite sharedapi.BadRequest(w, "VALIDATION", err) return } + query.PageSize = normalizePageSize(query.PageSize) // The path parameter is authoritative even when the pagination cursor is // supplied by the client. query.Options.TriggerID = chi.URLParam(r, "triggerID") diff --git a/internal/api/v1/handler_list_workflows.go b/internal/api/v1/handler_list_workflows.go index 2388b24..4ae8ed8 100644 --- a/internal/api/v1/handler_list_workflows.go +++ b/internal/api/v1/handler_list_workflows.go @@ -26,6 +26,7 @@ func listWorkflows(backend api2.Backend) http.HandlerFunc { api.BadRequest(w, "VALIDATION", err) return } + query.PageSize = normalizePageSize(query.PageSize) workflows, err := backend.ListWorkflows(r.Context(), *query) if err != nil { diff --git a/internal/api/v1/pagination.go b/internal/api/v1/pagination.go index 1c43f23..04692e3 100644 --- a/internal/api/v1/pagination.go +++ b/internal/api/v1/pagination.go @@ -7,6 +7,19 @@ import ( sharedapi "github.com/formancehq/go-libs/v5/pkg/transport/api" ) +// normalizePageSize applies the same bounds to decoded cursors as GetPageSize +// applies to explicit query parameters. Cursors are client-controlled base64 +// JSON, so their embedded page size cannot be trusted. +func normalizePageSize(pageSize uint64) uint64 { + if pageSize == 0 { + return bunpaginate.QueryDefaultPageSize + } + if pageSize > bunpaginate.MaxPageSize { + return bunpaginate.MaxPageSize + } + return pageSize +} + // renderCursor preserves the v1 {"data": [...]} response shape while adding // enough metadata for clients to detect and retrieve subsequent pages. func renderCursor[T any](w http.ResponseWriter, cursor bunpaginate.Cursor[T]) { diff --git a/openapi.yaml b/openapi.yaml index 834ca91..1a33f0b 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -3614,7 +3614,7 @@ components: schema: type: integer minimum: 1 - maximum: 1000 + maximum: 100 default: 15 format: int64 example: 100 diff --git a/openapi/v2.yaml b/openapi/v2.yaml index 0f87545..97f2569 100644 --- a/openapi/v2.yaml +++ b/openapi/v2.yaml @@ -519,7 +519,7 @@ components: type: integer format: int64 minimum: 1 - maximum: 1000 + maximum: 100 schemas: V2ServerInfo: type: object diff --git a/pkg/client/.speakeasy/gen.lock b/pkg/client/.speakeasy/gen.lock index a3cddfb..dd84bf3 100644 --- a/pkg/client/.speakeasy/gen.lock +++ b/pkg/client/.speakeasy/gen.lock @@ -1,12 +1,12 @@ lockVersion: 2.0.0 id: e26e5b37-4391-4462-9a20-c517a83a166a management: - docChecksum: 2f9e40aaba40047b5af65e5371fea57c + docChecksum: aec6b9bcce4eb2538e129ed17e2a5589 docVersion: 0.1.0 speakeasyVersion: 1.351.0 generationVersion: 2.384.1 - releaseVersion: 0.1.6 - configChecksum: 28d06aa57052e26c02ec2310398ec34d + releaseVersion: 0.1.7 + configChecksum: ef44e4268063f8dbf9a2b5a9ec677b65 features: go: additionalDependencies: 0.1.0 diff --git a/pkg/client/.speakeasy/gen.yaml b/pkg/client/.speakeasy/gen.yaml index ec38020..091373d 100644 --- a/pkg/client/.speakeasy/gen.yaml +++ b/pkg/client/.speakeasy/gen.yaml @@ -12,7 +12,7 @@ generation: auth: oAuth2ClientCredentialsEnabled: true go: - version: 0.1.6 + version: 0.1.7 additionalDependencies: {} allowUnknownFieldsInWeakUnions: false clientServerStatusCodesAsErrors: true diff --git a/pkg/client/sdk.go b/pkg/client/sdk.go index 7a55d41..e0f43b3 100644 --- a/pkg/client/sdk.go +++ b/pkg/client/sdk.go @@ -143,9 +143,9 @@ func New(opts ...SDKOption) *SDK { sdkConfiguration: sdkConfiguration{ Language: "go", OpenAPIDocVersion: "0.1.0", - SDKVersion: "0.1.6", + SDKVersion: "0.1.7", GenVersion: "2.384.1", - UserAgent: "speakeasy-sdk/go 0.1.6 2.384.1 0.1.0 github.com/formancehq/flows/pkg/client", + UserAgent: "speakeasy-sdk/go 0.1.7 2.384.1 0.1.0 github.com/formancehq/flows/pkg/client", Hooks: hooks.New(), }, } From b4a5da63e07d579b5f8dc774cef89e3d53d045a1 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 6 Aug 2026 10:05:36 +0200 Subject: [PATCH 22/22] fix(wait-event): handle workflow cancellation --- internal/workflow/stages/wait_event/run.go | 13 ++++++++++++- .../workflow/stages/wait_event/wait_event_test.go | 14 ++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/internal/workflow/stages/wait_event/run.go b/internal/workflow/stages/wait_event/run.go index 6f90327..0945489 100644 --- a/internal/workflow/stages/wait_event/run.go +++ b/internal/workflow/stages/wait_event/run.go @@ -15,7 +15,18 @@ func RunWaitEvent(ctx workflow.Context, waitEvent WaitEvent) error { // one buffered with nothing left to re-wake the coroutine, blocking forever. for { var signal internalWorkflow.Event - channel.Receive(ctx, &signal) + canceled := false + selector := workflow.NewSelector(ctx) + selector.AddReceive(channel, func(channel workflow.ReceiveChannel, _ bool) { + channel.Receive(ctx, &signal) + }) + selector.AddReceive(ctx.Done(), func(workflow.ReceiveChannel, bool) { + canceled = true + }) + selector.Select(ctx) + if canceled { + return ctx.Err() + } if signal.Name == waitEvent.Event { return nil } diff --git a/internal/workflow/stages/wait_event/wait_event_test.go b/internal/workflow/stages/wait_event/wait_event_test.go index 610a867..a094c02 100644 --- a/internal/workflow/stages/wait_event/wait_event_test.go +++ b/internal/workflow/stages/wait_event/wait_event_test.go @@ -6,6 +6,8 @@ import ( "github.com/formancehq/orchestration/internal/workflow" "github.com/formancehq/orchestration/internal/workflow/stages/internal/stagestesting" + "github.com/stretchr/testify/require" + "go.temporal.io/sdk/temporal" "go.temporal.io/sdk/testsuite" ) @@ -75,3 +77,15 @@ func TestWaitEvent(t *testing.T) { }, }...) } + +func TestWaitEventCancellation(t *testing.T) { + testSuite := &testsuite.WorkflowTestSuite{} + env := testSuite.NewTestWorkflowEnvironment() + env.RegisterDelayedCallback(env.CancelWorkflow, 100*time.Millisecond) + + env.ExecuteWorkflow(RunWaitEvent, WaitEvent{Event: "test"}) + + require.True(t, env.IsWorkflowCompleted()) + require.Error(t, env.GetWorkflowError()) + require.True(t, temporal.IsCanceledError(env.GetWorkflowError())) +}