From 3428a70ccebf409868dce421cb5dc8c37e15144a Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Fri, 13 Mar 2026 17:08:59 +0100 Subject: [PATCH 01/11] feat: bump component versions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Ledger v2.3.1 → v2.4.0 - Payments v3.0.18 → v3.2.0 - Auth v2.4.0 → v2.4.3 - Orchestration v2.4.0 → v2.4.1 - Reconciliation v2.2.1 → v2.2.2 - Gateway v2.1.0 → v2.2.0 --- Earthfile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Earthfile b/Earthfile index d23148cb09..18c096fe62 100644 --- a/Earthfile +++ b/Earthfile @@ -3,15 +3,15 @@ PROJECT FormanceHQ/stack IMPORT github.com/formancehq/earthly:tags/v0.15.0 AS core -ARG LEDGER_VERSION=v2.3.1 -ARG PAYMENTS_VERSION=v3.0.18 +ARG LEDGER_VERSION=v2.4.0 +ARG PAYMENTS_VERSION=v3.2.0 ARG WALLETS_VERSION=v2.1.5 ARG WEBHOOKS_VERSION=v2.2.0 -ARG AUTH_VERSION=v2.4.0 +ARG AUTH_VERSION=v2.4.3 ARG SEARCH_VERSION=v2.1.0 -ARG ORCHESTRATION_VERSION=v2.4.0 -ARG RECONCILIATION_VERSION=v2.2.1 -ARG GATEWAY_VERSION=v2.1.0 +ARG ORCHESTRATION_VERSION=v2.4.1 +ARG RECONCILIATION_VERSION=v2.2.2 +ARG GATEWAY_VERSION=v2.2.0 sources: FROM core+base-image From 3bf4c46f2977ec48ee514939fed752d36121fe09 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Fri, 13 Mar 2026 17:15:02 +0100 Subject: [PATCH 02/11] fix: use literal block scalar for multi-line gh release upload --- .github/workflows/releases.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index 73b20ff191..e906f3711a 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -27,7 +27,7 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Add the OpenAPI file to the release assets - run: > + run: | gh release upload ${{github.ref_name}} ./releases/build/generate.json#openapi.json gh release upload ${{github.ref_name}} ./events/generated/all.json#events.json env: From ce61c79ef9e2d8432cabbdbb31690b110b312960 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Mon, 16 Mar 2026 10:48:09 +0100 Subject: [PATCH 03/11] feat: Update config --- Earthfile | 40 +++++++++++++++++------------------ releases/openapi-overlay.json | 13 ++++++++++++ 2 files changed, 33 insertions(+), 20 deletions(-) diff --git a/Earthfile b/Earthfile index 18c096fe62..7f640d4fc0 100644 --- a/Earthfile +++ b/Earthfile @@ -3,15 +3,15 @@ PROJECT FormanceHQ/stack IMPORT github.com/formancehq/earthly:tags/v0.15.0 AS core -ARG LEDGER_VERSION=v2.4.0 -ARG PAYMENTS_VERSION=v3.2.0 -ARG WALLETS_VERSION=v2.1.5 -ARG WEBHOOKS_VERSION=v2.2.0 -ARG AUTH_VERSION=v2.4.3 -ARG SEARCH_VERSION=v2.1.0 -ARG ORCHESTRATION_VERSION=v2.4.1 -ARG RECONCILIATION_VERSION=v2.2.2 -ARG GATEWAY_VERSION=v2.2.0 +ARG --global LEDGER_VERSION=v2.4.0 +ARG --global PAYMENTS_VERSION=v3.2.0 +ARG --global WALLETS_VERSION=v2.1.5 +ARG --global WEBHOOKS_VERSION=v2.2.0 +ARG --global AUTH_VERSION=v2.4.3 +ARG --global SEARCH_VERSION=v2.1.0 +ARG --global ORCHESTRATION_VERSION=v2.4.1 +ARG --global RECONCILIATION_VERSION=v2.2.2 +ARG --global GATEWAY_VERSION=v2.2.0 sources: FROM core+base-image @@ -21,7 +21,7 @@ sources: build-final-spec: FROM core+base-image - RUN apk update && apk add yarn nodejs npm jq curl + RUN apk update && apk add yarn nodejs npm jq WORKDIR /src/releases COPY releases/package.* . RUN npm install @@ -34,19 +34,19 @@ build-final-spec: WORKDIR /src/components # Download OpenAPI specs from GitHub releases - RUN curl -L https://github.com/formancehq/ledger/releases/download/${LEDGER_VERSION}/openapi.yaml -o ledger.openapi.yaml - RUN curl -L https://github.com/formancehq/payments/releases/download/${PAYMENTS_VERSION}/openapi.yaml -o payments.openapi.yaml - RUN curl -L https://github.com/formancehq/gateway/releases/download/${GATEWAY_VERSION}/openapi.yaml -o gateway.openapi.yaml - RUN curl -L https://github.com/formancehq/auth/releases/download/${AUTH_VERSION}/openapi.yaml -o auth.openapi.yaml - RUN curl -L https://github.com/formancehq/search/releases/download/${SEARCH_VERSION}/openapi.yaml -o search.openapi.yaml - RUN curl -L https://github.com/formancehq/webhooks/releases/download/${WEBHOOKS_VERSION}/openapi.yaml -o webhooks.openapi.yaml - RUN curl -L https://github.com/formancehq/wallets/releases/download/${WALLETS_VERSION}/openapi.yaml -o wallets.openapi.yaml - RUN curl -L https://github.com/formancehq/reconciliation/releases/download/${RECONCILIATION_VERSION}/openapi.yaml -o reconciliation.openapi.yaml - RUN curl -L https://github.com/formancehq/flows/releases/download/${ORCHESTRATION_VERSION}/openapi.yaml -o orchestration.openapi.yaml + RUN wget -q https://github.com/formancehq/ledger/releases/download/${LEDGER_VERSION}/openapi.yaml -O ledger.openapi.yaml + RUN wget -q https://github.com/formancehq/payments/releases/download/${PAYMENTS_VERSION}/openapi.yaml -O payments.openapi.yaml + RUN wget -q https://github.com/formancehq/gateway/releases/download/${GATEWAY_VERSION}/openapi.yaml -O gateway.openapi.yaml + RUN wget -q https://github.com/formancehq/auth/releases/download/${AUTH_VERSION}/openapi.yaml -O auth.openapi.yaml + RUN wget -q https://github.com/formancehq/search/releases/download/${SEARCH_VERSION}/openapi.yaml -O search.openapi.yaml + RUN wget -q https://github.com/formancehq/webhooks/releases/download/${WEBHOOKS_VERSION}/openapi.yaml -O webhooks.openapi.yaml + RUN wget -q https://github.com/formancehq/wallets/releases/download/${WALLETS_VERSION}/openapi.yaml -O wallets.openapi.yaml + RUN wget -q https://github.com/formancehq/reconciliation/releases/download/${RECONCILIATION_VERSION}/openapi.yaml -O reconciliation.openapi.yaml + RUN wget -q https://github.com/formancehq/flows/releases/download/${ORCHESTRATION_VERSION}/openapi.yaml -O orchestration.openapi.yaml WORKDIR /src/releases RUN npm run build - RUN jq -s '.[0] * .[1]' build/generate.json openapi-overlay.json > build/latest.json + RUN jq -s '.[0] * .[1] | del(.components.schemas.V2QueryParams.properties.sort."$ref")' build/generate.json openapi-overlay.json > build/latest.json ARG version=v0.0.0 IF [ "$version" = "v0.0.0" ] RUN sed -i 's/SDK_VERSION/v0.0.0/g' build/latest.json diff --git a/releases/openapi-overlay.json b/releases/openapi-overlay.json index 02680a1f6b..13ef2481ee 100644 --- a/releases/openapi-overlay.json +++ b/releases/openapi-overlay.json @@ -3,5 +3,18 @@ "x-speakeasy-errors": { "statusCodes": ["default"] } + }, + "components": { + "schemas": { + "V2QueryParams": { + "properties": { + "sort": { + "type": "string", + "description": "Sort results using a field name and order (ascending or descending).\nFormat: `:`, where `` is the field name and `` is either `asc` or `desc`.\n", + "example": "id:desc" + } + } + } + } } } \ No newline at end of file From 77766d74d2c3a77d0e1fc321abdb584da9524a85 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Mon, 16 Mar 2026 12:38:53 +0100 Subject: [PATCH 04/11] feat: centralize OpenAPI spec management with Speakeasy Registry Remove NoAuthorization security scheme from base.yaml and add a shared overlay to clean up the merged spec (remove requestBody on GET/HEAD, fix /versions security). Publish the overlaid spec to the Speakeasy Registry via a new workflow job so all SDK repos consume a single corrected source. --- .github/workflows/releases.yml | 9 ++++ .speakeasy/workflow.lock | 23 +++++++++ .speakeasy/workflow.yaml | 12 +++++ releases/base.yaml | 7 --- releases/overlays/shared.overlay.yaml | 72 +++++++++++++++++++++++++++ 5 files changed, 116 insertions(+), 7 deletions(-) create mode 100644 .speakeasy/workflow.lock create mode 100644 .speakeasy/workflow.yaml create mode 100644 releases/overlays/shared.overlay.yaml diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index e906f3711a..ec4c6211c3 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -32,3 +32,12 @@ jobs: gh release upload ${{github.ref_name}} ./events/generated/all.json#events.json env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + publish-registry: + needs: OpenAPI + uses: speakeasy-api/sdk-generation-action/.github/workflows/tag.yaml@v15 + with: + registry_tags: ${{ github.ref_name }} + secrets: + github_access_token: ${{ secrets.GITHUB_TOKEN }} + speakeasy_api_key: ${{ secrets.SPEAKEASY_API_KEY }} diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock new file mode 100644 index 0000000000..dd0cdc58ba --- /dev/null +++ b/.speakeasy/workflow.lock @@ -0,0 +1,23 @@ +speakeasyVersion: 1.755.0 +sources: + stacks-source: + sourceNamespace: stacks-source + sourceRevisionDigest: sha256:5f3efcd6d57a3d10c6117dc8652e196b181e1535d33294062cfb5f997c8abff0 + sourceBlobDigest: sha256:9e907dbdf2d4f42763a7a8d9e384a155be7a9443e612fa924108231587f827ad + tags: + - latest + - v0.0.0 +targets: {} +workflow: + workflowVersion: 1.0.0 + speakeasyVersion: latest + sources: + stacks-source: + inputs: + - location: ./releases/build/generate.json + overlays: + - location: ./releases/overlays/shared.overlay.yaml + output: ./releases/build/openapi-overlaid.yaml + registry: + location: registry.speakeasyapi.dev/formance/formance/stacks-source + targets: {} diff --git a/.speakeasy/workflow.yaml b/.speakeasy/workflow.yaml new file mode 100644 index 0000000000..d31773e9ba --- /dev/null +++ b/.speakeasy/workflow.yaml @@ -0,0 +1,12 @@ +workflowVersion: 1.0.0 +speakeasyVersion: latest +sources: + stacks-source: + inputs: + - location: ./releases/build/generate.json + overlays: + - location: ./releases/overlays/shared.overlay.yaml + output: ./releases/build/openapi-overlaid.yaml + registry: + location: registry.speakeasyapi.dev/formance/formance/stacks-source +targets: {} diff --git a/releases/base.yaml b/releases/base.yaml index 4f949017cd..6109ad0065 100644 --- a/releases/base.yaml +++ b/releases/base.yaml @@ -61,13 +61,6 @@ components: tokenUrl: "/api/auth/oauth/token" refreshUrl: "/api/auth/oauth/token" scopes: {} - NoAuthorization: - type: oauth2 - flows: - clientCredentials: - tokenUrl: "/api/auth/oauth/token" - refreshUrl: "/api/auth/oauth/token" - scopes: {} x-tagGroups: - name: Auth diff --git a/releases/overlays/shared.overlay.yaml b/releases/overlays/shared.overlay.yaml new file mode 100644 index 0000000000..5249ccd26a --- /dev/null +++ b/releases/overlays/shared.overlay.yaml @@ -0,0 +1,72 @@ +overlay: 1.0.0 +info: + title: Shared overlay for Formance Stack OpenAPI spec + version: 0.0.1 +actions: + # Remove the NoAuthorization securityScheme definition (injected by component merge) + - target: $.components.securitySchemes.NoAuthorization + remove: true + + # Remove existing security on GET /versions and replace with empty requirement + - target: $.paths['/versions'].get.security + remove: true + - target: $.paths['/versions'].get + update: + security: + - {} + + # Remove requestBody on Ledger v2 GET/HEAD operations + - target: $.paths['/api/ledger/v2'].get.requestBody + remove: true + - target: $.paths['/api/ledger/v2/{ledger}/accounts'].get.requestBody + remove: true + - target: $.paths['/api/ledger/v2/{ledger}/accounts'].head.requestBody + remove: true + - target: $.paths['/api/ledger/v2/{ledger}/transactions'].get.requestBody + remove: true + - target: $.paths['/api/ledger/v2/{ledger}/transactions'].head.requestBody + remove: true + - target: $.paths['/api/ledger/v2/{ledger}/aggregate/balances'].get.requestBody + remove: true + - target: $.paths['/api/ledger/v2/{ledger}/volumes'].get.requestBody + remove: true + - target: $.paths['/api/ledger/v2/{ledger}/logs'].get.requestBody + remove: true + + # Remove requestBody on Payments v1 GET operations + - target: $.paths['/api/payments/accounts'].get.requestBody + remove: true + + # Remove requestBody on Payments v3 GET operations + - target: $.paths['/api/payments/v3/accounts'].get.requestBody + remove: true + - target: $.paths['/api/payments/v3/bank-accounts'].get.requestBody + remove: true + - target: $.paths['/api/payments/v3/connectors'].get.requestBody + remove: true + - target: $.paths['/api/payments/v3/connectors/{connectorID}/schedules'].get.requestBody + remove: true + - target: $.paths['/api/payments/v3/payments'].get.requestBody + remove: true + - target: $.paths['/api/payments/v3/payment-initiations'].get.requestBody + remove: true + - target: $.paths['/api/payments/v3/payment-initiations/{paymentInitiationID}/adjustments'].get.requestBody + remove: true + - target: $.paths['/api/payments/v3/payment-initiations/{paymentInitiationID}/payments'].get.requestBody + remove: true + - target: $.paths['/api/payments/v3/payment-service-users'].get.requestBody + remove: true + - target: $.paths['/api/payments/v3/payment-service-users/{paymentServiceUserID}/connections'].get.requestBody + remove: true + - target: $.paths['/api/payments/v3/payment-service-users/{paymentServiceUserID}/connectors/{connectorID}/connections'].get.requestBody + remove: true + - target: $.paths['/api/payments/v3/payment-service-users/{paymentServiceUserID}/connectors/{connectorID}/link-attempts'].get.requestBody + remove: true + - target: $.paths['/api/payments/v3/pools'].get.requestBody + remove: true + + # Remove requestBody on Reconciliation GET operations + - target: $.paths['/api/reconciliation/policies'].get.requestBody + remove: true + - target: $.paths['/api/reconciliation/reconciliations'].get.requestBody + remove: true From 847ee9b6ea4041bdb1177b17c8d8a68669efe1e1 Mon Sep 17 00:00:00 2001 From: Ragot Geoffrey Date: Thu, 19 Mar 2026 12:14:20 +0100 Subject: [PATCH 05/11] fix: remove global open api overlay which MUST be kept typescript side (#1982) --- releases/overlays/shared.overlay.yaml | 58 +-------------------------- 1 file changed, 1 insertion(+), 57 deletions(-) diff --git a/releases/overlays/shared.overlay.yaml b/releases/overlays/shared.overlay.yaml index 5249ccd26a..91393b721e 100644 --- a/releases/overlays/shared.overlay.yaml +++ b/releases/overlays/shared.overlay.yaml @@ -13,60 +13,4 @@ actions: - target: $.paths['/versions'].get update: security: - - {} - - # Remove requestBody on Ledger v2 GET/HEAD operations - - target: $.paths['/api/ledger/v2'].get.requestBody - remove: true - - target: $.paths['/api/ledger/v2/{ledger}/accounts'].get.requestBody - remove: true - - target: $.paths['/api/ledger/v2/{ledger}/accounts'].head.requestBody - remove: true - - target: $.paths['/api/ledger/v2/{ledger}/transactions'].get.requestBody - remove: true - - target: $.paths['/api/ledger/v2/{ledger}/transactions'].head.requestBody - remove: true - - target: $.paths['/api/ledger/v2/{ledger}/aggregate/balances'].get.requestBody - remove: true - - target: $.paths['/api/ledger/v2/{ledger}/volumes'].get.requestBody - remove: true - - target: $.paths['/api/ledger/v2/{ledger}/logs'].get.requestBody - remove: true - - # Remove requestBody on Payments v1 GET operations - - target: $.paths['/api/payments/accounts'].get.requestBody - remove: true - - # Remove requestBody on Payments v3 GET operations - - target: $.paths['/api/payments/v3/accounts'].get.requestBody - remove: true - - target: $.paths['/api/payments/v3/bank-accounts'].get.requestBody - remove: true - - target: $.paths['/api/payments/v3/connectors'].get.requestBody - remove: true - - target: $.paths['/api/payments/v3/connectors/{connectorID}/schedules'].get.requestBody - remove: true - - target: $.paths['/api/payments/v3/payments'].get.requestBody - remove: true - - target: $.paths['/api/payments/v3/payment-initiations'].get.requestBody - remove: true - - target: $.paths['/api/payments/v3/payment-initiations/{paymentInitiationID}/adjustments'].get.requestBody - remove: true - - target: $.paths['/api/payments/v3/payment-initiations/{paymentInitiationID}/payments'].get.requestBody - remove: true - - target: $.paths['/api/payments/v3/payment-service-users'].get.requestBody - remove: true - - target: $.paths['/api/payments/v3/payment-service-users/{paymentServiceUserID}/connections'].get.requestBody - remove: true - - target: $.paths['/api/payments/v3/payment-service-users/{paymentServiceUserID}/connectors/{connectorID}/connections'].get.requestBody - remove: true - - target: $.paths['/api/payments/v3/payment-service-users/{paymentServiceUserID}/connectors/{connectorID}/link-attempts'].get.requestBody - remove: true - - target: $.paths['/api/payments/v3/pools'].get.requestBody - remove: true - - # Remove requestBody on Reconciliation GET operations - - target: $.paths['/api/reconciliation/policies'].get.requestBody - remove: true - - target: $.paths['/api/reconciliation/reconciliations'].get.requestBody - remove: true + - {} \ No newline at end of file From b159ba9b188f631a9be0a0bac89ac6083a29ba65 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Wed, 25 Mar 2026 13:31:20 +0100 Subject: [PATCH 06/11] feat: migrate from Earthly to Nix + Speakeasy for OpenAPI build pipeline - Replace Earthly with Nix dev shell (flake.nix) and Just task runner - Use Speakeasy CLI v1.759.2 for OpenAPI spec merging with modelNamespace support, replacing openapi-merge-cli (npm) - Path prepending handled by yq-go instead of openapi-merge-cli - Consolidate overlays into shared.overlay.yaml (Speakeasy overlay format) - Fix Speakeasy registry publish: specs are now properly published and tagged (previously only tagging an old registry image) - Add LATEST_RELEASE tag alongside version tag on registry publish - Remove Earthly, Docker/QEMU setup action, and npm build dependencies - Add .envrc for direnv integration --- .earthlyignore | 55 ------- .envrc | 3 + .github/actions/env/action.yml | 20 --- .github/workflows/releases.yml | 27 +--- .gitignore | 6 +- .speakeasy/workflow.lock | 30 +++- .speakeasy/workflow.yaml | 22 ++- Earthfile | 69 -------- Justfile | 55 +++++++ events/Earthfile | 60 ------- flake.lock | 25 +++ flake.nix | 81 ++++++++++ releases/openapi-merge.json | 98 ------------ releases/openapi-overlay.json | 20 --- releases/overlays/shared.overlay.yaml | 20 ++- releases/package-lock.json | 221 -------------------------- releases/package.json | 11 -- 17 files changed, 238 insertions(+), 585 deletions(-) delete mode 100644 .earthlyignore create mode 100644 .envrc delete mode 100644 .github/actions/env/action.yml delete mode 100644 Earthfile create mode 100644 Justfile delete mode 100644 events/Earthfile create mode 100644 flake.lock create mode 100644 flake.nix delete mode 100644 releases/openapi-merge.json delete mode 100644 releases/openapi-overlay.json delete mode 100644 releases/package-lock.json delete mode 100644 releases/package.json diff --git a/.earthlyignore b/.earthlyignore deleted file mode 100644 index e3b7c5ad38..0000000000 --- a/.earthlyignore +++ /dev/null @@ -1,55 +0,0 @@ -vendor -.idea -*.num -dist/ -autocomplete.* -coverage.* -completions -.idea -openapi/build/generate.json-e -openapi/build/generate.json.bak -coverage.out -dist -vendor -.gitpod/_output -.garden -go.work -go.work.sum -worktrees - -**/*.out -**/*.out -**/*.test -**/*.stats - -.direnv -.cache -.env - - -# Earthly -.tmp-earthly-out - -# Ignore SDKS -sdks -.DS_Store - -docs/node_modules -docs/.docusaurus -docs/build - -# Components -agent -auth -gateway -ledger -operator -orchestration -payments -search -stargate -wallets -webhooks - -# Operator tooling -components/operator/bin \ No newline at end of file diff --git a/.envrc b/.envrc new file mode 100644 index 0000000000..e52f52dead --- /dev/null +++ b/.envrc @@ -0,0 +1,3 @@ +source_env_if_exists ".envrc.local" +use flake . --impure +dotenv_if_exists ".env" diff --git a/.github/actions/env/action.yml b/.github/actions/env/action.yml deleted file mode 100644 index 1e1ec6f051..0000000000 --- a/.github/actions/env/action.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Setup Env -description: Setup Env for Linux x64 -runs: - using: composite - steps: - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 - - name: "Put back the git branch into git (Earthly uses it for tagging)" - shell: bash - run: | - branch="" - if [ -n "$GITHUB_HEAD_REF" ]; then - branch="$GITHUB_HEAD_REF" - else - branch="${GITHUB_REF##*/}" - fi - git checkout -b "$branch" || true - diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index ec4c6211c3..c3e84b99f4 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -7,21 +7,15 @@ permissions: contents: write jobs: - OpenAPI: + Release: runs-on: "ubuntu-latest" steps: - - uses: earthly/actions-setup@v1 - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - version: "latest" - uses: "actions/checkout@v4" with: fetch-depth: 0 - - name: Setup Env - uses: ./.github/actions/env - - name: Generate OpenAPI final specification - run: > - earthly +build-final-spec --version=${{github.ref_name}} + - uses: cachix/install-nix-action@v31 + - name: Build OpenAPI spec and events + run: nix develop --impure --command just build ${{github.ref_name}} - name: Create Release run: gh release create ${{github.ref_name}} --generate-notes env: @@ -32,12 +26,7 @@ jobs: gh release upload ${{github.ref_name}} ./events/generated/all.json#events.json env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - publish-registry: - needs: OpenAPI - uses: speakeasy-api/sdk-generation-action/.github/workflows/tag.yaml@v15 - with: - registry_tags: ${{ github.ref_name }} - secrets: - github_access_token: ${{ secrets.GITHUB_TOKEN }} - speakeasy_api_key: ${{ secrets.SPEAKEASY_API_KEY }} + - name: Publish OpenAPI to Speakeasy Registry + run: nix develop --impure --command speakeasy run -s all --registry-tags ${{github.ref_name}},LATEST_RELEASE + env: + SPEAKEASY_API_KEY: ${{ secrets.SPEAKEASY_API_KEY }} diff --git a/.gitignore b/.gitignore index c37041316e..20103b5f51 100644 --- a/.gitignore +++ b/.gitignore @@ -27,10 +27,10 @@ worktrees .env -# Earthly -.tmp-earthly-out +# Downloaded OpenAPI specs +components/ .DS_Store -openapi/node_modules +node_modules/ .kubeconfig diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index dd0cdc58ba..767abe3875 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -1,12 +1,12 @@ -speakeasyVersion: 1.755.0 +speakeasyVersion: 1.759.2 sources: stacks-source: sourceNamespace: stacks-source - sourceRevisionDigest: sha256:5f3efcd6d57a3d10c6117dc8652e196b181e1535d33294062cfb5f997c8abff0 - sourceBlobDigest: sha256:9e907dbdf2d4f42763a7a8d9e384a155be7a9443e612fa924108231587f827ad + sourceRevisionDigest: sha256:55cacc53f19d56070c775a281f59a76932d9d24a1a20af46d16243cc2bef9fb1 + sourceBlobDigest: sha256:3b3e29bfb7abe6a0e8e1cb9c0601add2558863329b78c6b4759d77ecd5602db7 tags: - latest - - v0.0.0 + - RECONCILIATION_VERSION targets: {} workflow: workflowVersion: 1.0.0 @@ -14,10 +14,28 @@ workflow: sources: stacks-source: inputs: - - location: ./releases/build/generate.json + - location: ./releases/base.yaml + - location: ./components/auth.openapi.yaml + modelNamespace: auth + - location: ./components/gateway.openapi.yaml + modelNamespace: gateway + - location: ./components/ledger.openapi.yaml + modelNamespace: ledger + - location: ./components/payments.openapi.yaml + modelNamespace: payments + - location: ./components/search.openapi.yaml + modelNamespace: search + - location: ./components/webhooks.openapi.yaml + modelNamespace: webhooks + - location: ./components/wallets.openapi.yaml + modelNamespace: wallets + - location: ./components/orchestration.openapi.yaml + modelNamespace: orchestration + - location: ./components/reconciliation.openapi.yaml + modelNamespace: reconciliation overlays: - location: ./releases/overlays/shared.overlay.yaml - output: ./releases/build/openapi-overlaid.yaml + output: ./releases/build/generate.json registry: location: registry.speakeasyapi.dev/formance/formance/stacks-source targets: {} diff --git a/.speakeasy/workflow.yaml b/.speakeasy/workflow.yaml index d31773e9ba..9a547abf86 100644 --- a/.speakeasy/workflow.yaml +++ b/.speakeasy/workflow.yaml @@ -3,10 +3,28 @@ speakeasyVersion: latest sources: stacks-source: inputs: - - location: ./releases/build/generate.json + - location: ./releases/base.yaml + - location: ./components/auth.openapi.yaml + modelNamespace: auth + - location: ./components/gateway.openapi.yaml + modelNamespace: gateway + - location: ./components/ledger.openapi.yaml + modelNamespace: ledger + - location: ./components/payments.openapi.yaml + modelNamespace: payments + - location: ./components/search.openapi.yaml + modelNamespace: search + - location: ./components/webhooks.openapi.yaml + modelNamespace: webhooks + - location: ./components/wallets.openapi.yaml + modelNamespace: wallets + - location: ./components/orchestration.openapi.yaml + modelNamespace: orchestration + - location: ./components/reconciliation.openapi.yaml + modelNamespace: reconciliation overlays: - location: ./releases/overlays/shared.overlay.yaml - output: ./releases/build/openapi-overlaid.yaml + output: ./releases/build/generate.json registry: location: registry.speakeasyapi.dev/formance/formance/stacks-source targets: {} diff --git a/Earthfile b/Earthfile deleted file mode 100644 index 7f640d4fc0..0000000000 --- a/Earthfile +++ /dev/null @@ -1,69 +0,0 @@ -VERSION 0.8 -PROJECT FormanceHQ/stack - -IMPORT github.com/formancehq/earthly:tags/v0.15.0 AS core - -ARG --global LEDGER_VERSION=v2.4.0 -ARG --global PAYMENTS_VERSION=v3.2.0 -ARG --global WALLETS_VERSION=v2.1.5 -ARG --global WEBHOOKS_VERSION=v2.2.0 -ARG --global AUTH_VERSION=v2.4.3 -ARG --global SEARCH_VERSION=v2.1.0 -ARG --global ORCHESTRATION_VERSION=v2.4.1 -ARG --global RECONCILIATION_VERSION=v2.2.2 -ARG --global GATEWAY_VERSION=v2.2.0 - -sources: - FROM core+base-image - ARG --required LOCATION - COPY ${LOCATION} out - SAVE ARTIFACT out - -build-final-spec: - FROM core+base-image - RUN apk update && apk add yarn nodejs npm jq - WORKDIR /src/releases - COPY releases/package.* . - RUN npm install - - WORKDIR /src/releases - COPY releases/base.yaml . - COPY releases/openapi-overlay.json . - COPY releases/openapi-merge.json . - RUN mkdir ./build - - WORKDIR /src/components - # Download OpenAPI specs from GitHub releases - RUN wget -q https://github.com/formancehq/ledger/releases/download/${LEDGER_VERSION}/openapi.yaml -O ledger.openapi.yaml - RUN wget -q https://github.com/formancehq/payments/releases/download/${PAYMENTS_VERSION}/openapi.yaml -O payments.openapi.yaml - RUN wget -q https://github.com/formancehq/gateway/releases/download/${GATEWAY_VERSION}/openapi.yaml -O gateway.openapi.yaml - RUN wget -q https://github.com/formancehq/auth/releases/download/${AUTH_VERSION}/openapi.yaml -O auth.openapi.yaml - RUN wget -q https://github.com/formancehq/search/releases/download/${SEARCH_VERSION}/openapi.yaml -O search.openapi.yaml - RUN wget -q https://github.com/formancehq/webhooks/releases/download/${WEBHOOKS_VERSION}/openapi.yaml -O webhooks.openapi.yaml - RUN wget -q https://github.com/formancehq/wallets/releases/download/${WALLETS_VERSION}/openapi.yaml -O wallets.openapi.yaml - RUN wget -q https://github.com/formancehq/reconciliation/releases/download/${RECONCILIATION_VERSION}/openapi.yaml -O reconciliation.openapi.yaml - RUN wget -q https://github.com/formancehq/flows/releases/download/${ORCHESTRATION_VERSION}/openapi.yaml -O orchestration.openapi.yaml - - WORKDIR /src/releases - RUN npm run build - RUN jq -s '.[0] * .[1] | del(.components.schemas.V2QueryParams.properties.sort."$ref")' build/generate.json openapi-overlay.json > build/latest.json - ARG version=v0.0.0 - IF [ "$version" = "v0.0.0" ] - RUN sed -i 's/SDK_VERSION/v0.0.0/g' build/latest.json - SAVE ARTIFACT build/latest.json AS LOCAL releases/build/latest.json - ELSE - RUN sed -i 's/SDK_VERSION/'$version'/g' build/latest.json - SAVE ARTIFACT build/latest.json AS LOCAL releases/build/generate.json - END - SAVE ARTIFACT build/latest.json - - -build: - LOCALLY - BUILD --pass-args +build-final-spec - BUILD --pass-args ./events+generate - -pre-commit: # Generate the final spec and run all the pre-commit hooks - LOCALLY - BUILD +build-final-spec - BUILD ./events+pre-commit diff --git a/Justfile b/Justfile new file mode 100644 index 0000000000..d932320f15 --- /dev/null +++ b/Justfile @@ -0,0 +1,55 @@ +# Component versions +LEDGER_VERSION := "v2.4.0" +PAYMENTS_VERSION := "v3.2.0" +WALLETS_VERSION := "v2.1.5" +WEBHOOKS_VERSION := "v2.2.0" +AUTH_VERSION := "v2.4.3" +SEARCH_VERSION := "v2.1.0" +ORCHESTRATION_VERSION := "v2.4.1" +RECONCILIATION_VERSION := "v2.2.2" +GATEWAY_VERSION := "v2.2.0" + +# Download all component OpenAPI specs from GitHub releases +download-specs: + mkdir -p components + wget -q https://github.com/formancehq/ledger/releases/download/{{LEDGER_VERSION}}/openapi.yaml -O components/ledger.openapi.yaml + wget -q https://github.com/formancehq/payments/releases/download/{{PAYMENTS_VERSION}}/openapi.yaml -O components/payments.openapi.yaml + wget -q https://github.com/formancehq/gateway/releases/download/{{GATEWAY_VERSION}}/openapi.yaml -O components/gateway.openapi.yaml + wget -q https://github.com/formancehq/auth/releases/download/{{AUTH_VERSION}}/openapi.yaml -O components/auth.openapi.yaml + wget -q https://github.com/formancehq/search/releases/download/{{SEARCH_VERSION}}/openapi.yaml -O components/search.openapi.yaml + wget -q https://github.com/formancehq/webhooks/releases/download/{{WEBHOOKS_VERSION}}/openapi.yaml -O components/webhooks.openapi.yaml + wget -q https://github.com/formancehq/wallets/releases/download/{{WALLETS_VERSION}}/openapi.yaml -O components/wallets.openapi.yaml + wget -q https://github.com/formancehq/reconciliation/releases/download/{{RECONCILIATION_VERSION}}/openapi.yaml -O components/reconciliation.openapi.yaml + wget -q https://github.com/formancehq/flows/releases/download/{{ORCHESTRATION_VERSION}}/openapi.yaml -O components/orchestration.openapi.yaml + +# Prepend API path prefix to each component spec +prepend-paths: download-specs + yq -i '.paths |= (to_entries | map(select(.key == "/*").key = "/api/auth" + .key) | from_entries)' components/auth.openapi.yaml + yq -i '.paths |= (to_entries | map(select(.key == "/*").key = "/api/ledger" + .key) | from_entries)' components/ledger.openapi.yaml + yq -i '.paths |= (to_entries | map(select(.key == "/*").key = "/api/payments" + .key) | from_entries)' components/payments.openapi.yaml + yq -i '.paths |= (to_entries | map(select(.key == "/*").key = "/api/search" + .key) | from_entries)' components/search.openapi.yaml + yq -i '.paths |= (to_entries | map(select(.key == "/*").key = "/api/webhooks" + .key) | from_entries)' components/webhooks.openapi.yaml + yq -i '.paths |= (to_entries | map(select(.key == "/*").key = "/api/wallets" + .key) | from_entries)' components/wallets.openapi.yaml + yq -i '.paths |= (to_entries | map(select(.key == "/*").key = "/api/orchestration" + .key) | from_entries)' components/orchestration.openapi.yaml + yq -i '.paths |= (to_entries | map(select(.key == "/*").key = "/api/reconciliation" + .key) | from_entries)' components/reconciliation.openapi.yaml + +# Build the merged OpenAPI spec using Speakeasy +build-openapi version="v0.0.0": prepend-paths + mkdir -p releases/build + speakeasy run -s all + cd releases && sed -i'' -e 's/SDK_VERSION/{{version}}/g' build/generate.json + +# Generate event schemas +generate-events: + cd events && npm install + cd events && node index.js + +# Build everything (OpenAPI spec + events) +build version="v0.0.0": (build-openapi version) generate-events + +# Publish OpenAPI spec to Speakeasy Registry +publish-speakeasy version: prepend-paths + speakeasy run -s all --registry-tags {{version}},LATEST_RELEASE + +# Pre-commit: build spec and generate events +pre-commit: (build-openapi) generate-events diff --git a/events/Earthfile b/events/Earthfile deleted file mode 100644 index df53d71bee..0000000000 --- a/events/Earthfile +++ /dev/null @@ -1,60 +0,0 @@ -VERSION 0.8 - -IMPORT github.com/formancehq/earthly:tags/v0.15.0 AS core - -FROM core+base-image - -GO_LINT: - FUNCTION - COPY (+sources/out --LOCATION=.golangci.yml) .golangci.yml - ARG GOPROXY - RUN --mount=type=cache,id=gomod,target=${GOPATH}/pkg/mod \ - --mount=type=cache,id=gobuild,target=/root/.cache/go-build \ - --mount=type=cache,id=golangci,target=/root/.cache/golangci-lint \ - golangci-lint run --fix ./... - -GO_TIDY: - FUNCTION - ARG GOPROXY - RUN --mount=type=cache,id=gomod,target=${GOPATH}/pkg/mod \ - --mount=type=cache,id=gobuild,target=/root/.cache/go-build \ - go mod tidy - SAVE ARTIFACT go.* AS LOCAL . - -go-sources: - COPY events.go go.* base.yaml /src/ - COPY --dir services /src/ - WORKDIR /src - SAVE ARTIFACT /src - -tidy: - FROM core+builder-image - COPY (+go-sources/*) /src - WORKDIR /src - DO --pass-args +GO_TIDY - SAVE ARTIFACT go.* AS LOCAL ./ - -lint: - FROM core+builder-image - COPY (+go-sources/*) /src - WORKDIR /src - COPY --pass-args +tidy/go.* . - DO --pass-args +GO_LINT - SAVE ARTIFACT * AS LOCAL ./ - -generate: - RUN apk add nodejs npm - WORKDIR /src - COPY package* . - RUN npm install - RUN mkdir generated - COPY index.js base.yaml . - COPY --dir services . - RUN node index.js - SAVE ARTIFACT generated AS LOCAL ./generated - -pre-commit: - WAIT - BUILD --pass-args +tidy - END - BUILD --pass-args +generate diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000000..4ed898576d --- /dev/null +++ b/flake.lock @@ -0,0 +1,25 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1774244481, + "narHash": "sha256-4XfMXU0DjN83o6HWZoKG9PegCvKvIhNUnRUI19vzTcQ=", + "rev": "4590696c8693fea477850fe379a01544293ca4e2", + "revCount": 909850, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.2511.909850%2Brev-4590696c8693fea477850fe379a01544293ca4e2/019d1bd2-524a-765a-8cf7-a03d7c852855/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/NixOS/nixpkgs/0.2511" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000000..a9c7e4887a --- /dev/null +++ b/flake.nix @@ -0,0 +1,81 @@ +{ + description = "Formance Stack - OpenAPI spec build and publish environment"; + + inputs = { + nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.2511"; + }; + + outputs = { self, nixpkgs }: + let + supportedSystems = [ + "x86_64-linux" + "aarch64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; + + forEachSupportedSystem = f: + nixpkgs.lib.genAttrs supportedSystems (system: + let + pkgs = import nixpkgs { inherit system; }; + in + f { pkgs = pkgs; system = system; } + ); + + speakeasyVersion = "1.759.2"; + speakeasyPlatforms = { + "x86_64-linux" = "linux_amd64"; + "aarch64-linux" = "linux_arm64"; + "x86_64-darwin" = "darwin_amd64"; + "aarch64-darwin" = "darwin_arm64"; + }; + speakeasyHashes = { + "x86_64-linux" = "9234e2e9138f03ac18f0ca034d0c5a0a7b8749ea91b16814b4a643afd680d8fd"; + "aarch64-linux" = "ba92a8c5799ed14acba94d317694ed32e35883e9439a07b28c58f7c8c0ea16f5"; + "x86_64-darwin" = "b4cfe13627e8822718b5820c68898f51b6381e604c9578650c9b0c3f40f800b0"; + "aarch64-darwin" = "dda057dbbd83bdaa47f9ccf3311e455013d957d11f45d8336b97b91ba2a56d6d"; + }; + + in + { + packages = forEachSupportedSystem ({ pkgs, system }: + { + speakeasy = pkgs.stdenv.mkDerivation { + pname = "speakeasy"; + version = speakeasyVersion; + + src = pkgs.fetchurl { + url = "https://github.com/speakeasy-api/speakeasy/releases/download/v${speakeasyVersion}/speakeasy_${speakeasyPlatforms.${system}}.zip"; + sha256 = speakeasyHashes.${system}; + }; + + nativeBuildInputs = [ pkgs.unzip ]; + dontUnpack = true; + + installPhase = '' + mkdir -p $out/bin + unzip $src + install -m755 speakeasy $out/bin/ + ''; + + name = "speakeasy"; + }; + } + ); + + devShells = forEachSupportedSystem ({ pkgs, system }: + { + default = pkgs.mkShell { + packages = [ + pkgs.jq + pkgs.just + pkgs.nodejs_22 + pkgs.wget + pkgs.yq-go + self.packages.${system}.speakeasy + ]; + }; + } + ); + }; +} diff --git a/releases/openapi-merge.json b/releases/openapi-merge.json deleted file mode 100644 index 3c60dd26b2..0000000000 --- a/releases/openapi-merge.json +++ /dev/null @@ -1,98 +0,0 @@ -{ - "inputs": [ - { - "inputFile": "./base.yaml" - }, - { - "inputFile": "./../components/auth.openapi.yaml", - "pathModification": { - "prepend": "/api/auth" - }, - "dispute": { - "prefix": "auth" - } - }, - { - "inputFile": "./../components/gateway.openapi.yaml", - "dispute": { - "prefix": "gateway" - } - }, - { - "inputFile": "./../components/ledger.openapi.yaml", - "pathModification": { - "prepend": "/api/ledger" - }, - "dispute": { - "prefix": "ledger" - } - }, - { - "inputFile": "./../components/payments.openapi.yaml", - "pathModification": { - "prepend": "/api/payments" - }, - "dispute": { - "prefix": "payments" - } - }, - { - "inputFile": "./../components/search.openapi.yaml", - "pathModification": { - "prepend": "/api/search" - }, - "dispute": { - "prefix": "search" - } - }, - { - "inputFile": "./../components/webhooks.openapi.yaml", - "pathModification": { - "prepend": "/api/webhooks" - }, - "operationSelection": { - "excludeTags": ["Health"] - }, - "dispute": { - "prefix": "webhooks" - } - }, - { - "inputFile": "./../components/wallets.openapi.yaml", - "pathModification": { - "prepend": "/api/wallets" - }, - "operationSelection": { - "excludeTags": ["Health"] - }, - "dispute": { - "prefix": "wallets" - } - }, - { - "inputFile": "./../components/orchestration.openapi.yaml", - "pathModification": { - "prepend": "/api/orchestration" - }, - "operationSelection": { - "excludeTags": ["Health"] - }, - "dispute": { - "prefix": "orchestration" - } - }, - { - "inputFile": "./../components/reconciliation.openapi.yaml", - "pathModification": { - "prepend": "/api/reconciliation" - }, - "operationSelection": { - "excludeTags": ["Health"] - }, - "dispute": { - "prefix": "reconciliation" - } - } - ], - "output": "./build/generate.json" -} diff --git a/releases/openapi-overlay.json b/releases/openapi-overlay.json deleted file mode 100644 index 13ef2481ee..0000000000 --- a/releases/openapi-overlay.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "paths": { - "x-speakeasy-errors": { - "statusCodes": ["default"] - } - }, - "components": { - "schemas": { - "V2QueryParams": { - "properties": { - "sort": { - "type": "string", - "description": "Sort results using a field name and order (ascending or descending).\nFormat: `:`, where `` is the field name and `` is either `asc` or `desc`.\n", - "example": "id:desc" - } - } - } - } - } -} \ No newline at end of file diff --git a/releases/overlays/shared.overlay.yaml b/releases/overlays/shared.overlay.yaml index 91393b721e..28daea633c 100644 --- a/releases/overlays/shared.overlay.yaml +++ b/releases/overlays/shared.overlay.yaml @@ -13,4 +13,22 @@ actions: - target: $.paths['/versions'].get update: security: - - {} \ No newline at end of file + - {} + + # Fix ledger_V2QueryParams.sort: replace $ref with inline definition + - target: $.components.schemas.ledger_V2QueryParams.properties.sort + update: + type: string + description: | + Sort results using a field name and order (ascending or descending). + Format: `:`, where `` is the field name and `` is either `asc` or `desc`. + example: "id:desc" + - target: $.components.schemas.ledger_V2QueryParams.properties.sort.$ref + remove: true + + # Speakeasy error handling + - target: $.paths + update: + x-speakeasy-errors: + statusCodes: + - default diff --git a/releases/package-lock.json b/releases/package-lock.json deleted file mode 100644 index 7dcaa61467..0000000000 --- a/releases/package-lock.json +++ /dev/null @@ -1,221 +0,0 @@ -{ - "name": "openapi", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "openapi", - "version": "1.0.0", - "dependencies": { - "openapi-merge-cli": "^1.3.1" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/atlassian-openapi": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/atlassian-openapi/-/atlassian-openapi-1.0.17.tgz", - "integrity": "sha512-8aW0Xgl9mVdL9dCABSZAvCayMPyh6uVu86UzOat8Kc1qDMUtXn2OxcwDsJfm/qCtBSeZ+GE/PkFxx3ZRIp3hFg==", - "dependencies": { - "jsonpointer": "^5.0.0", - "urijs": "^1.19.10" - } - }, - "node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "engines": { - "node": ">= 6" - } - }, - "node_modules/es6-promise": { - "version": "4.2.8", - "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", - "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==" - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/isomorphic-fetch": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz", - "integrity": "sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==", - "dependencies": { - "node-fetch": "^2.6.1", - "whatwg-fetch": "^3.4.1" - } - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/jsonpointer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", - "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/openapi-merge": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/openapi-merge/-/openapi-merge-1.3.2.tgz", - "integrity": "sha512-qRWBwPMiKIUrAcKW6lstMPKpFEWy32dBbP1UjHH9jlWgw++2BCqOVbsjO5Wa4H1Ll3c4cn+lyi4TinUy8iswzw==", - "dependencies": { - "atlassian-openapi": "^1.0.8", - "lodash": "^4.17.15", - "ts-is-present": "^1.1.1" - } - }, - "node_modules/openapi-merge-cli": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/openapi-merge-cli/-/openapi-merge-cli-1.3.1.tgz", - "integrity": "sha512-YGBkzuYrDc4kTMVoGrNTCI/eNCKtE5JcCGmcmkhtl0M7+hNXm4kP+n83ilZ+kCxa7/xicTj0cww/q1P4KxlQ8Q==", - "dependencies": { - "ajv": "^6.12.2", - "commander": "^5.1.0", - "es6-promise": "^4.2.8", - "isomorphic-fetch": "^3", - "js-yaml": "^3.14.0", - "openapi-merge": "^1.2.0" - }, - "bin": { - "openapi-merge-cli": "dist/cli.js" - } - }, - "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "engines": { - "node": ">=6" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/ts-is-present": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ts-is-present/-/ts-is-present-1.2.2.tgz", - "integrity": "sha512-cA5MPLWGWYXvnlJb4TamUUx858HVHBsxxdy8l7jxODOLDyGYnQOllob2A2jyDghGa5iJHs2gzFNHvwGJ0ZfR8g==" - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/urijs": { - "version": "1.19.11", - "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", - "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==" - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" - }, - "node_modules/whatwg-fetch": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", - "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - } - } -} diff --git a/releases/package.json b/releases/package.json deleted file mode 100644 index 32bdf639fc..0000000000 --- a/releases/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "openapi", - "version": "1.0.0", - "dependencies": { - "openapi-merge-cli": "^1.3.1" - }, - "private": true, - "scripts": { - "build": "openapi-merge-cli" - } -} From 175c0cabef3b75ccd3651bb82d510ad4d291e4fc Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Wed, 25 Mar 2026 13:38:24 +0100 Subject: [PATCH 07/11] fix: restore info.version in overlay after last-wins merge --- releases/overlays/shared.overlay.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/releases/overlays/shared.overlay.yaml b/releases/overlays/shared.overlay.yaml index 28daea633c..210dfcec13 100644 --- a/releases/overlays/shared.overlay.yaml +++ b/releases/overlays/shared.overlay.yaml @@ -3,6 +3,11 @@ info: title: Shared overlay for Formance Stack OpenAPI spec version: 0.0.1 actions: + # Restore info.version (overwritten by last-wins merge from component specs) + - target: $.info + update: + version: SDK_VERSION + # Remove the NoAuthorization securityScheme definition (injected by component merge) - target: $.components.securitySchemes.NoAuthorization remove: true From 1a49dd29bddac39e7e9c654981cb4c6ed7459299 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Wed, 25 Mar 2026 13:41:10 +0100 Subject: [PATCH 08/11] fix: pass SPEAKEASY_API_KEY to build step --- .github/workflows/releases.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/releases.yml b/.github/workflows/releases.yml index c3e84b99f4..93a0834269 100644 --- a/.github/workflows/releases.yml +++ b/.github/workflows/releases.yml @@ -16,6 +16,8 @@ jobs: - uses: cachix/install-nix-action@v31 - name: Build OpenAPI spec and events run: nix develop --impure --command just build ${{github.ref_name}} + env: + SPEAKEASY_API_KEY: ${{ secrets.SPEAKEASY_API_KEY }} - name: Create Release run: gh release create ${{github.ref_name}} --generate-notes env: From 38f1a53eedb8e00c52821392c22ba4249b680e45 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 26 Mar 2026 13:42:19 +0100 Subject: [PATCH 09/11] feat: update spekeasy config --- .speakeasy/workflow.lock | 6 ++--- .speakeasy/workflow.yaml | 52 ++++++++++++++++++++-------------------- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 767abe3875..4f120e68e1 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -2,11 +2,11 @@ speakeasyVersion: 1.759.2 sources: stacks-source: sourceNamespace: stacks-source - sourceRevisionDigest: sha256:55cacc53f19d56070c775a281f59a76932d9d24a1a20af46d16243cc2bef9fb1 - sourceBlobDigest: sha256:3b3e29bfb7abe6a0e8e1cb9c0601add2558863329b78c6b4759d77ecd5602db7 + sourceRevisionDigest: sha256:9759a5b722fd64e2bba1328cb5dc0721bb585ab43981bd8e0cd37cb8c45a7e2c + sourceBlobDigest: sha256:a4c19e079552ce6285a89a01d183df722c4f2cc18cf9f941255f653ffc135c6c tags: - latest - - RECONCILIATION_VERSION + - SDK_VERSION targets: {} workflow: workflowVersion: 1.0.0 diff --git a/.speakeasy/workflow.yaml b/.speakeasy/workflow.yaml index 9a547abf86..8d995d9f6d 100644 --- a/.speakeasy/workflow.yaml +++ b/.speakeasy/workflow.yaml @@ -1,30 +1,30 @@ workflowVersion: 1.0.0 speakeasyVersion: latest sources: - stacks-source: - inputs: - - location: ./releases/base.yaml - - location: ./components/auth.openapi.yaml - modelNamespace: auth - - location: ./components/gateway.openapi.yaml - modelNamespace: gateway - - location: ./components/ledger.openapi.yaml - modelNamespace: ledger - - location: ./components/payments.openapi.yaml - modelNamespace: payments - - location: ./components/search.openapi.yaml - modelNamespace: search - - location: ./components/webhooks.openapi.yaml - modelNamespace: webhooks - - location: ./components/wallets.openapi.yaml - modelNamespace: wallets - - location: ./components/orchestration.openapi.yaml - modelNamespace: orchestration - - location: ./components/reconciliation.openapi.yaml - modelNamespace: reconciliation - overlays: - - location: ./releases/overlays/shared.overlay.yaml - output: ./releases/build/generate.json - registry: - location: registry.speakeasyapi.dev/formance/formance/stacks-source + stacks-source: + inputs: + - location: ./components/auth.openapi.yaml + modelNamespace: auth + - location: ./components/gateway.openapi.yaml + modelNamespace: gateway + - location: ./components/ledger.openapi.yaml + modelNamespace: ledger + - location: ./components/payments.openapi.yaml + modelNamespace: payments + - location: ./components/search.openapi.yaml + modelNamespace: search + - location: ./components/webhooks.openapi.yaml + modelNamespace: webhooks + - location: ./components/wallets.openapi.yaml + modelNamespace: wallets + - location: ./components/orchestration.openapi.yaml + modelNamespace: orchestration + - location: ./components/reconciliation.openapi.yaml + modelNamespace: reconciliation + - location: ./releases/base.yaml + overlays: + - location: ./releases/overlays/shared.overlay.yaml + output: ./releases/build/generate.json + registry: + location: registry.speakeasyapi.dev/formance/formance/stacks-source targets: {} From f80116a4e27fd2323491714ef3e0d3e655310d71 Mon Sep 17 00:00:00 2001 From: Maxence Maireaux Date: Thu, 26 Mar 2026 13:42:32 +0100 Subject: [PATCH 10/11] feat: Update overlay for Golang --- releases/overlays/shared.overlay.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/releases/overlays/shared.overlay.yaml b/releases/overlays/shared.overlay.yaml index 210dfcec13..467dfeba6f 100644 --- a/releases/overlays/shared.overlay.yaml +++ b/releases/overlays/shared.overlay.yaml @@ -31,6 +31,15 @@ actions: - target: $.components.schemas.ledger_V2QueryParams.properties.sort.$ref remove: true + # Fix Go import cycle: tag inline cursor objects with ledger namespace + # so Speakeasy keeps extracted types in the ledger package instead of operations + - target: $.components.schemas.ledger_V2ExportersCursorResponse.properties.cursor + update: + x-speakeasy-model-namespace: ledger + - target: $.components.schemas.ledger_V2PipelinesCursorResponse.properties.cursor + update: + x-speakeasy-model-namespace: ledger + # Speakeasy error handling - target: $.paths update: From fad7990197752e20dc5f320e97c9910e98a69c80 Mon Sep 17 00:00:00 2001 From: Geoffrey Ragot Date: Fri, 27 Mar 2026 10:42:43 +0100 Subject: [PATCH 11/11] chore: upgrade ledger --- .speakeasy/workflow.lock | 8 +++---- .speakeasy/workflow.yaml | 52 ++++++++++++++++++++-------------------- Justfile | 2 +- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 4f120e68e1..850fbc3fe3 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -1,9 +1,9 @@ -speakeasyVersion: 1.759.2 +speakeasyVersion: 1.759.3 sources: stacks-source: sourceNamespace: stacks-source - sourceRevisionDigest: sha256:9759a5b722fd64e2bba1328cb5dc0721bb585ab43981bd8e0cd37cb8c45a7e2c - sourceBlobDigest: sha256:a4c19e079552ce6285a89a01d183df722c4f2cc18cf9f941255f653ffc135c6c + sourceRevisionDigest: sha256:cbe386daae9f188190ef706592b7d8f47d08842b64db2b7425a5f26192c3b80d + sourceBlobDigest: sha256:43596c6d78adb93167d2c34236981efe1f1ed199738110e3e2e9f2b194128db5 tags: - latest - SDK_VERSION @@ -14,7 +14,6 @@ workflow: sources: stacks-source: inputs: - - location: ./releases/base.yaml - location: ./components/auth.openapi.yaml modelNamespace: auth - location: ./components/gateway.openapi.yaml @@ -33,6 +32,7 @@ workflow: modelNamespace: orchestration - location: ./components/reconciliation.openapi.yaml modelNamespace: reconciliation + - location: ./releases/base.yaml overlays: - location: ./releases/overlays/shared.overlay.yaml output: ./releases/build/generate.json diff --git a/.speakeasy/workflow.yaml b/.speakeasy/workflow.yaml index 8d995d9f6d..1be3f38d05 100644 --- a/.speakeasy/workflow.yaml +++ b/.speakeasy/workflow.yaml @@ -1,30 +1,30 @@ workflowVersion: 1.0.0 speakeasyVersion: latest sources: - stacks-source: - inputs: - - location: ./components/auth.openapi.yaml - modelNamespace: auth - - location: ./components/gateway.openapi.yaml - modelNamespace: gateway - - location: ./components/ledger.openapi.yaml - modelNamespace: ledger - - location: ./components/payments.openapi.yaml - modelNamespace: payments - - location: ./components/search.openapi.yaml - modelNamespace: search - - location: ./components/webhooks.openapi.yaml - modelNamespace: webhooks - - location: ./components/wallets.openapi.yaml - modelNamespace: wallets - - location: ./components/orchestration.openapi.yaml - modelNamespace: orchestration - - location: ./components/reconciliation.openapi.yaml - modelNamespace: reconciliation - - location: ./releases/base.yaml - overlays: - - location: ./releases/overlays/shared.overlay.yaml - output: ./releases/build/generate.json - registry: - location: registry.speakeasyapi.dev/formance/formance/stacks-source + stacks-source: + inputs: + - location: ./components/auth.openapi.yaml + modelNamespace: auth + - location: ./components/gateway.openapi.yaml + modelNamespace: gateway + - location: ./components/ledger.openapi.yaml + modelNamespace: ledger + - location: ./components/payments.openapi.yaml + modelNamespace: payments + - location: ./components/search.openapi.yaml + modelNamespace: search + - location: ./components/webhooks.openapi.yaml + modelNamespace: webhooks + - location: ./components/wallets.openapi.yaml + modelNamespace: wallets + - location: ./components/orchestration.openapi.yaml + modelNamespace: orchestration + - location: ./components/reconciliation.openapi.yaml + modelNamespace: reconciliation + - location: ./releases/base.yaml + overlays: + - location: ./releases/overlays/shared.overlay.yaml + output: ./releases/build/generate.json + registry: + location: registry.speakeasyapi.dev/formance/formance/stacks-source targets: {} diff --git a/Justfile b/Justfile index d932320f15..1198f9480d 100644 --- a/Justfile +++ b/Justfile @@ -1,5 +1,5 @@ # Component versions -LEDGER_VERSION := "v2.4.0" +LEDGER_VERSION := "v2.4.3" PAYMENTS_VERSION := "v3.2.0" WALLETS_VERSION := "v2.1.5" WEBHOOKS_VERSION := "v2.2.0"