Skip to content

Main#8

Open
jlaguilarm wants to merge 1955 commits into
jlaguilarm:mainfrom
stellar:main
Open

Main#8
jlaguilarm wants to merge 1955 commits into
jlaguilarm:mainfrom
stellar:main

Conversation

@jlaguilarm

Copy link
Copy Markdown
Owner
PR Checklist

PR Structure

  • This PR has reasonably narrow scope (if not, break it down into smaller PRs).
  • This PR avoids mixing refactoring changes with feature changes (split into two PRs
    otherwise).
  • This PR's title starts with name of package that is most changed in the PR, ex.
    paymentservice.stellar, or all or doc if the changes are broad or impact many
    packages.

Thoroughness

  • This PR adds tests for the most critical parts of the new functionality or fixes.

What

[TODO: Short statement about what is changing.]

Why

[TODO: Why this change is being made. Include any context required to understand the why.]

Known limitations

[TODO or N/A]

@lijamie98 lijamie98 deleted the branch jlaguilarm:main March 2, 2023 20:31
@lijamie98 lijamie98 deleted the main branch March 2, 2023 20:31
@lijamie98 lijamie98 deleted the branch jlaguilarm:main March 10, 2023 00:08
@lijamie98 lijamie98 restored the main branch March 10, 2023 00:08
@lijamie98 lijamie98 deleted the branch jlaguilarm:main March 10, 2023 00:09
@lijamie98 lijamie98 deleted the main branch March 10, 2023 00:09
@JiahuiWho JiahuiWho deleted the branch jlaguilarm:main December 17, 2024 18:19
@JiahuiWho JiahuiWho restored the main branch December 17, 2024 18:37
@lijamie98 lijamie98 deleted the branch jlaguilarm:main January 10, 2025 04:37
@lijamie98 lijamie98 deleted the main branch January 10, 2025 04:37
…ed to the secret (#1792)

### Description

- Check and add secret validation to configurations related to the
secret

### Context

- Improve developer experience
### Description

- SEP-24 fiat asset casted to stellar asset
```
ClassCastException
class org.stellar.anchor.api.asset.FiatAssetInfo cannot be cast to class org.stellar.anchor.api.asset.StellarAssetInfo (org.stellar.anchor.api.asset.FiatAssetInfo and org.stellar.anchor.api.asset.StellarAssetInfo are in unnamed module of loader org.springframework.boot.loader.launch.LaunchedClassLoader @50040f0c)
```

### Context

- Bug fixes
### Description

- Release 3.1.3 back merge to `main`

### Context

- Missing from 3.1.3 post release.
…_to_develop (#1798)

### Description

- Add concurrency configurations to on_pull_request and
on_push_to_develop

### Context

- This is trying to avoid cancelling the waiting jobs of extended and
essential tests.
### Description

- [ANCHOR-1059] SEP-24 fiat asset casted to stellar asset 

### Context

- Hotfix the fiat asset cast exception and make 3.1.4 bug fix release.


[ANCHOR-1059]:
https://stellarorg.atlassian.net/browse/ANCHOR-1059?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
…to DB (#1794)

### Description

- In SEP-6 handling, there is an unnecessary database call. We should
optimize it by constructing the response without the database query.

### Context

- Optimization
### Description

- Merge `main` with `develop` for release `3.1.4`

### Context

- Post release maintenance.
…int (#1917)

### Description

- Add 50KB size limit on `transaction` field in SEP-10 POST `/auth`
before XDR parsing
- Reduce existing SEP-45 `authorization_entries` size limit from 100KB
to 50KB

### Context

Valid SEP-10/SEP-45 auth payloads are small (a few KB). Limiting input
size before XDR deserialization prevents unnecessary memory allocation
from oversized payloads.

### Testing

- `./gradlew test`

### Documentation

N/A

### Known limitations

N/A
### Description

This bumps the version to 4.2.1

### Context

Patch release

### Testing

- `./gradlew test`

### Documentation

N/A

### Known limitations

N/A
… range (#1918)

### Description

- Fix MEMO_ID validation to support the full Stellar uint64 range (0 to
18,446,744,073,709,551,615)
- Replace Long.parseLong and Long.longValue() with BigInteger for
MEMO_ID parsing and conversion
- Consolidate memo ID creation into a shared MemoHelper.makeMemoId()
method

### Context

Partner reported that SEP-24 requests with refund_memo
11872666534918305457 were rejected with "Invalid Memo" due to this
refund_memo value above Java's `Long.MAX_VALUE
`(9,223,372,036,854,775,807)

Stellar protocol defines `MEMO_ID` as uint64, but the platform was using
Java's signed long for parsing, which only supports half the range.

The same issue existed in SEP-10 memo validation, `xdrMemoToString`
(used by the payment observer for memo matching), and muxed account memo
handling in `DefaultPaymentListener`

### Testing

  - ./gradlew test
  - Added new unit tests to cover all cases

### Documentation

N/A

### Known limitations

N/A
### Description

Merge `release/4.2.1` to `main`

### Context

Git flow

### Testing

- `./gradlew test`

### Documentation

N/A

### Known limitations

N/A
Comment on lines +8 to +10
uses: ./.github/workflows/sub_gradle_build.yml

rust_build:
Comment on lines +11 to +13
uses: ./.github/workflows/sub_rust_build.yml

essential_tests:
Comment on lines +14 to +20
needs: [ gradle_build ]
uses: ./.github/workflows/sub_essential_tests.yml
concurrency:
group: ap-test-job
cancel-in-progress: false

extended_tests:
Comment on lines +21 to +27
needs: [ gradle_build, essential_tests ]
uses: ./.github/workflows/sub_extended_tests.yml
concurrency:
group: ap-test-job
cancel-in-progress: false

complete:
Comment on lines +28 to +33
if: always()
needs: [ gradle_build, essential_tests, extended_tests, rust_build ]
runs-on: ubuntu-24.04
steps:
- if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
run: exit 1
Comment on lines +28 to +67
name: Push to DockerHub (tag=stellar/anchor-platform:${{ github.event.release.tag_name }}) - AMD64
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4

- name: Get EXPECTED_RELEASE_TAG
shell: bash
run: echo "EXPECTED_RELEASE_TAG=$(./gradlew -q printVersionName)" >> "$GITHUB_ENV"

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
install: true
driver: docker-container
driver-opts: |
image=moby/buildkit:latest

- name: Docker Login
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build and push Docker images - AMD64
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
platforms: linux/amd64
build-args: |
TARGETARCH=amd64
tags: |
stellar/anchor-platform:${{ env.EXPECTED_RELEASE_TAG }}
stellar/anchor-platform:latest
# add build cache for faster rebuilds
cache-from: type=gha
cache-to: type=gha,mode=max

build_and_push_docker_image_arm64:
Comment on lines +68 to +109
name: Push to DockerHub (tag=stellar/anchor-platform:${{ github.event.release.tag_name }}) - ARM64
# Having a separate job for ARM64 helps to reduce overall build time.
# The multi-arch build takes longer if running the arm build on an amd64 runner via emulation.
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v4

- name: Get EXPECTED_RELEASE_TAG
shell: bash
run: echo "EXPECTED_RELEASE_TAG=$(./gradlew -q printVersionName)" >> "$GITHUB_ENV"

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
install: true
driver: docker-container
driver-opts: |
image=moby/buildkit:latest

- name: Docker Login
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build and push Docker images - ARM64
uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
push: true
platforms: linux/arm64
build-args: |
TARGETARCH=arm64
tags: |
stellar/anchor-platform:${{ env.EXPECTED_RELEASE_TAG }}
stellar/anchor-platform:latest
# Optional: add build cache for faster rebuilds
cache-from: type=gha
cache-to: type=gha,mode=max

complete:
Comment on lines +110 to +115
if: always()
needs: [ build_and_push_docker_image_amd64, build_and_push_docker_image_arm64, check_release_tag ]
runs-on: ubuntu-latest
steps:
- if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
run: exit 1
Comment on lines +13 to +115
name: Run Essential Tests (Integration Tests, Faster End-2-End Tests, Unit Tests, and Stellar Validation Tools)
runs-on: ubuntu-latest
env:
# Anchor Platform secrets
SECRET_SEP10_SIGNING_SEED: ${{ vars.SECRET_SEP10_SIGNING_SEED }}
APP__PAYMENT_SIGNING_SEED: ${{ vars.APP__PAYMENT_SIGNING_SEED }}
SECRET__KEY: ${{ vars.SECRET__KEY }}

# Test secrets
TEST_CLIENT_WALLET_SECRET: ${{ vars.TEST_CLIENT_WALLET_SECRET }}
TEST_CLIENT_SMART_WALLET_ACCOUNT: ${{ vars.TEST_CLIENT_SMART_WALLET_ACCOUNT }}
TEST_CLIENT_WALLET_EXTRA_SIGNER_1_SECRET: ${{ vars.TEST_CLIENT_WALLET_EXTRA_SIGNER_1_SECRET }}
TEST_CLIENT_WALLET_EXTRA_SIGNER_2_SECRET: ${{ vars.TEST_CLIENT_WALLET_EXTRA_SIGNER_2_SECRET }}
TEST_WITHDRAW_FUND_CLIENT_SECRET_1: ${{ vars.TEST_WITHDRAW_FUND_CLIENT_SECRET_1 }}
TEST_WITHDRAW_FUND_CLIENT_SECRET_2: ${{ vars.TEST_WITHDRAW_FUND_CLIENT_SECRET_2 }}
TEST_DEPOSIT_FUND_CLIENT_SECRET_1: ${{ vars.TEST_DEPOSIT_FUND_CLIENT_SECRET_1 }}
TEST_DEPOSIT_FUND_CLIENT_SECRET_2: ${{ vars.TEST_DEPOSIT_FUND_CLIENT_SECRET_2 }}
steps:
#############################################
# Setup JDK 17
# Download, and Extract anchor-platform.tar
# Setup hostnames (/etc/hosts)
#############################################
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'

- name: Download anchor-platform.tar
uses: actions/download-artifact@v4
with:
name: anchor-platform-tar
path: /home/runner/

- name: Extract anchor-platform.tar
run: |
cd /home/runner
tar -xf /home/runner/anchor-platform.tar
cd /home/runner/anchor-platform

- name: Set up hostnames (/etc/hosts)
run: |
sudo echo "127.0.0.1 db" | sudo tee -a /etc/hosts
sudo echo "127.0.0.1 kafka" | sudo tee -a /etc/hosts
sudo echo "127.0.0.1 sep24-reference-ui" | sudo tee -a /etc/hosts
sudo echo "127.0.0.1 reference-server" | sudo tee -a /etc/hosts
sudo echo "127.0.0.1 reference-db" | sudo tee -a /etc/hosts
sudo echo "127.0.0.1 wallet-server" | sudo tee -a /etc/hosts
sudo echo "127.0.0.1 platform" | sudo tee -a /etc/hosts
sudo echo "127.0.0.1 host.docker.internal" | sudo tee -a /etc/hosts

#############################################


- name: Pull Stellar Validation Tests Docker Image
run: docker pull stellar/anchor-tests:latest &

- name: Run Kafka, Postgres, and Sep24 UI with docker compose
run: docker compose -f /home/runner/anchor-platform/service-runner/src/main/resources/docker-compose-test.yaml up -d --build

- name: Start `default` configuration
env:
TEST_PROFILE_NAME: default
SEP1_TOML_VALUE: /home/runner/anchor-platform/service-runner/src/main/resources/config/stellar.host.docker.internal.toml
SEP10_WEB_AUTH_DOMAIN: host.docker.internal:8080
SEP10_HOME_DOMAINS: host.docker.internal:8080,*.stellar.org
SEP45_WEB_AUTH_DOMAIN: host.docker.internal:8080
SEP45_HOME_DOMAINS: host.docker.internal:8080,*.stellar.org
TOML_PATH: /home/runner/anchor-platform/wallet-reference-server/src/main/resources/toml
KT_REFERENCE_SERVER_CONFIG: /home/runner/anchor-platform/service-runner/src/main/resources/config/reference-config.yaml
run: |
cd /home/runner/anchor-platform
./gradlew startServersWithTestProfile &
echo "PID=$!" >> $GITHUB_ENV

- name: Wait for the sep server to start and get ready
uses: mydea/action-wait-for-api@v1
with:
url: "http://host.docker.internal:8080/.well-known/stellar.toml"
interval: "1"
timeout: "600"
- name: Run Essential Tests
env:
TEST_PROFILE_NAME: default
RUN_DOCKER: false
ANCHOR_DOMAIN: http://host.docker.internal:8080
run: |
cd /home/runner/anchor-platform
./gradlew clean runEssentialTests
# do not call "kill -9 $PID" to continue running the servers for Stellar Validation Tool

- name: Run Stellar validation tool
run: |
docker run --network host -v /home/runner/anchor-platform/platform/src/test/resources://config stellar/anchor-tests:latest --home-domain http://host.docker.internal:8080 --seps 1 6 10 12 24 31 38 --sep-config //config/stellar-anchor-tests-sep-config.json --asset-code USDC --verbose

- name: Upload Essential Tests report
if: always()
uses: actions/upload-artifact@v4
with:
name: essential-tests-report
path: |
/home/runner/anchor-platform/essential-tests/build/reports/
Comment on lines +13 to +154
name: Run Extended Tests
runs-on: ubuntu-latest
env:
# Anchor Platform secrets
SECRET_SEP10_SIGNING_SEED: ${{ vars.SECRET_SEP10_SIGNING_SEED }}
APP__PAYMENT_SIGNING_SEED: ${{ vars.APP__PAYMENT_SIGNING_SEED }}
SECRET__KEY: ${{ vars.SECRET__KEY }}

# Test secrets
TEST_CLIENT_WALLET_SECRET: ${{ vars.TEST_CLIENT_WALLET_SECRET }}
TEST_CLIENT_SMART_WALLET_ACCOUNT: ${{ vars.TEST_CLIENT_SMART_WALLET_ACCOUNT }}
TEST_CLIENT_WALLET_EXTRA_SIGNER_1_SECRET: ${{ vars.TEST_CLIENT_WALLET_EXTRA_SIGNER_1_SECRET }}
TEST_CLIENT_WALLET_EXTRA_SIGNER_2_SECRET: ${{ vars.TEST_CLIENT_WALLET_EXTRA_SIGNER_2_SECRET }}
TEST_WITHDRAW_FUND_CLIENT_SECRET_1: ${{ vars.TEST_WITHDRAW_FUND_CLIENT_SECRET_1 }}
TEST_WITHDRAW_FUND_CLIENT_SECRET_2: ${{ vars.TEST_WITHDRAW_FUND_CLIENT_SECRET_2 }}
TEST_DEPOSIT_FUND_CLIENT_SECRET_1: ${{ vars.TEST_DEPOSIT_FUND_CLIENT_SECRET_1 }}
TEST_DEPOSIT_FUND_CLIENT_SECRET_2: ${{ vars.TEST_DEPOSIT_FUND_CLIENT_SECRET_2 }}
steps:
#############################################
# Setup JDK 17
# Download, and Extract anchor-platform.tar
# Setup hostnames (/etc/hosts)
#############################################
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'

- name: Download anchor-platform.tar
uses: actions/download-artifact@v4
with:
name: anchor-platform-tar
path: /home/runner/

- name: Extract anchor-platform.tar
run: |
cd /home/runner
tar -xf /home/runner/anchor-platform.tar
cd /home/runner/anchor-platform

- name: Set up hostnames (/etc/hosts)
run: |
sudo echo "127.0.0.1 db" | sudo tee -a /etc/hosts
sudo echo "127.0.0.1 kafka" | sudo tee -a /etc/hosts
sudo echo "127.0.0.1 sep24-reference-ui" | sudo tee -a /etc/hosts
sudo echo "127.0.0.1 reference-server" | sudo tee -a /etc/hosts
sudo echo "127.0.0.1 reference-db" | sudo tee -a /etc/hosts
sudo echo "127.0.0.1 wallet-server" | sudo tee -a /etc/hosts
sudo echo "127.0.0.1 platform" | sudo tee -a /etc/hosts
sudo echo "127.0.0.1 host.docker.internal" | sudo tee -a /etc/hosts

#############################################

- name: Run Kafka, Postgres, and Sep24 UI with docker compose
run: docker compose -f /home/runner/anchor-platform/service-runner/src/main/resources/docker-compose-test.yaml up -d --build

# `auth-apikey-platform` Tests
- name: Start `auth-apikey-platform` configuration
env:
TEST_PROFILE_NAME: auth-apikey-platform
KT_REFERENCE_SERVER_CONFIG: /home/runner/anchor-platform/service-runner/src/main/resources/config/reference-config.yaml
run: |
cd /home/runner/anchor-platform
./gradlew startServersWithTestProfile &
echo "PID=$!" >> $GITHUB_ENV

- name: Wait for the platform server to start and get ready
uses: mydea/action-wait-for-api@v1
with:
url: "http://localhost:8085/health"
expected-status: "200"
interval: "1"
timeout: "600"

- name: Run `auth-apikey-platform` configuration tests
env:
TEST_PROFILE_NAME: auth-apikey-platform
run: |
cd /home/runner/anchor-platform
./gradlew :extended-tests:test --tests org.stellar.anchor.platform.suite.AuthApikeyPlatformTestSuite
kill -9 $PID

# `auth-jwt-platform` Tests
- name: Start `auth-jwt-platform` configuration
env:
TEST_PROFILE_NAME: auth-jwt-platform
KT_REFERENCE_SERVER_CONFIG: /home/runner/anchor-platform/service-runner/src/main/resources/config/reference-config.yaml
run: |
cd /home/runner/anchor-platform
./gradlew startServersWithTestProfile &
echo "PID=$!" >> $GITHUB_ENV

- name: Wait for the platform server to start and get ready
uses: mydea/action-wait-for-api@v1
with:
url: "http://localhost:8085/health"
expected-status: "200"
interval: "1"
timeout: "600"

- name: Run `auth-jwt-platform` configuration tests
env:
TEST_PROFILE_NAME: auth-jwt-platform
run: |
cd /home/runner/anchor-platform
./gradlew :extended-tests:test --tests org.stellar.anchor.platform.suite.AuthJwtPlatformTestSuite
kill -9 $PID

# `default-horizon` end-2-end Tests
- name: Start `default-horizon` configuration
env:
TEST_PROFILE_NAME: default-horizon
KT_REFERENCE_SERVER_CONFIG: /home/runner/anchor-platform/service-runner/src/main/resources/config/reference-config.yaml
run: |
cd /home/runner/anchor-platform
./gradlew startServersWithTestProfile &
echo "PID=$!" >> $GITHUB_ENV

- name: Wait for the sep server to start and get ready
uses: mydea/action-wait-for-api@v1
with:
url: "http://localhost:8080/.well-known/stellar.toml"
interval: "1"
timeout: "600"

- name: Run limited `end-2-end` tests
env:
TEST_PROFILE_NAME: default-horizon
run: |
cd /home/runner/anchor-platform
./gradlew :service-runner:clean :extended-tests:clean :extended-tests:test --tests org.stellar.anchor.platform.suite.End2EndTestSuite
kill -9 $PID

- name: Upload Extended Tests Report
if: always()
uses: actions/upload-artifact@v4
with:
name: extended-tests-report
path: |
/home/runner/anchor-platform/extended-tests/build/reports/

JiahuiWho and others added 25 commits April 8, 2026 19:36
### Description

Merge `main` to `develop`

### Context

Git flow

### Testing

- `./gradlew test`

### Documentation

N/A

### Known limitations

N/A
### Description

Each release job now pushes to a temporary arch-specific tag (-amd64,
-arm64), and a new `create_multi_arch_manifest` job combines them into a
single multi-arch manifest.

Same for `on_push_to_develop`

### Context

Since 4.1.1, the release workflow has been publishing only one
architecture per release due to a race condition, the amd64 and arm64
jobs both push to the same Docker tag, so whichever finishes last
overwrites the other.

### Testing

- `./gradlew test`

### Documentation

N/A

### Known limitations

N/A
### Description

  - Switch to Docker's recommended pattern: 
- Build jobs push by digest only (no intermediate -amd64 -arm64 tags)
- Then a `create_multi_arch_manifest` job uses `docker buildx imagetools
create` to merge both digests into a single multi-arch manifest.
  - Apply the same fix to `on_push_to_develop`

### Context

#1922 failed because
`docker manifest create` (used to merge the amd64 and arm64 builds)
expects each source image to be a plain image manifest. However,
`build-push-action` v6 with buildx wraps each single-platform image into
a manifest list (containing the image + provenance attestation), so the
command rejects them with the error "is a manifest list"

### Testing

- `./gradlew test`

### Documentation

N/A

### Known limitations

N/A
)

### Description

Include HTTP status code and response body in the error message string
instead of passing the exception object, matching the existing pattern
in `RpcService`. Remove the dangerous `(String, Throwable)` constructors
to prevent this class of bug.

### Context

When Horizon fails (e.g., rate limiting, network issues), the platform
tries to return an error but crashes on serializing the exception,
resulting in an unhelpful HTTP 500 (`HttpMessageNotWritableException`).

Root cause: `InternalErrorException(message, Throwable)` looks like it
sets the Java exception cause, but actually passes the `Throwable` into
`RpcException`'s `additionalData` field (an `Object`). Spring then tries
to JSON-serialize that `Throwable` and fails because
`Throwable#detailMessage` is a private field.

### Testing

- `./gradlew test`
- Updated assertions in `NotifyOnchainFundsReceivedHandlerTest`,
`NotifyOnchainFundsSentHandlerTest`

### Documentation

N/A

### Known limitations

N/A
…oding (#1925)

### Description

Fix muxed (M-address) payment destinations were discarded after
resolved, causing deposit matching to silently fail

### Context

stellar/internal-agents#93
Finding 11 — Muxed Account Address Discarded → NPE

### Testing

- `./gradlew test`
- Added unit tests asserting `convert()` returns a non-null M-address
for muxed destinations across `PAYMENT`, `PATH_PAYMENT_STRICT_RECEIVE`,
and `PATH_PAYMENT_STRICT_SEND`

### Documentation

N/A

### Known limitations

N/A

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
### Description

This bumps the version to 4.2.2

### Context

Patch release

### Testing

- `./gradlew test`

### Documentation

N/A

### Known limitations

N/A
### Description

Merge `release/4.2.2` to `main`

### Context

Git flow

### Testing

- `./gradlew test`

### Documentation

N/A

### Known limitations

N/A
### Description

Merge `main` to `develop`

### Context

Git flow

### Testing

- `./gradlew test`

### Documentation

N/A

### Known limitations

N/A
…generator (#1929)

### Description

Use `SecureRandom.nextLong(1, Long.MAX_VALUE)` to replace non-atomic
memo ID generation

- Thread-safe within a JVM
- Collision-resistant across HA instances
- Excludes 0 to avoid downstream sentinel-value confusion
- 2^63 space → birthday-paradox collision expected at ~3 billion memos,
far beyond any realistic anchor lifetime

### Context
`DepositInfoSelfGeneratorBase.generateMemoId()` previously used a
non-atomic post-increment on a shared static `long`, so concurrent calls
(especially across HA instances initializing from
`System.currentTimeMillis()`) can emit the same memo ID. Two
transactions then collide on `(withdraw_anchor_account, memo, status)`
and the matcher (`findOneBy...`, no `ORDER BY`) can credit an inbound
payment to the wrong customer's transaction.

### Testing

- `./gradlew test`
- New `DepositInfoSelfGeneratorBaseTest` adds a 64-thread × 2,000-call
concurrency regression test asserting zero collisions

### Documentation

N/A

### Known limitations

Does not repair pre-fix transactions that already collided if any.
…nsaction (#1930)

### Description

- For muxed accounts, storage at all six creation sites (`Sep24Service`
deposit/withdraw, `Sep6Service`
deposit/depositExchange/withdraw/withdrawExchange) now writes the
**muxed M-address** as `webAuthAccount` instead of the underlying
G-address, using `Objects.requireNonNullElse(token.getMuxedAccount(),
token.getAccount())`.

- Validation on `GET/transactions` in both SEPs. The database is queried
for rows where `webAuthAccount` matches the JWT's muxed M-address if it
has one, and the G-account otherwise. A muxed customer only sees rows
whose `webAuthAccount` equals their M-address now.

- G-accounts stay unaffected.

### Context

`Sep24Service` and `Sep6Service` previously stored `webAuthAccount =
token.getAccount()`, which collapses muxed JWTs' sub-id to the
underlying G-address. Two muxed customers on a shared custodial G could
read each other's transactions.

### Testing

- `./gradlew test`
- New tests verify storage behavior, post-fix isolation,
findTransactions, findTransaction by id

### Documentation

N/A

### Known limitations

**Breaking changes for muxed accounts**
                                   
- `GET /transactions` endpoint will no longer return muxed
customers'pre-fix legacy rows; those must be fetched by direct ID.
- On `GET /transaction?id=..` endpoint, if customer A learns customer B'
transaction ID for a row created before this change, customer A can
still fetch that row's details. Both customers' rows were stored with
`webAuthAccount = G_shared` and `accountMemo = null`, and the muxed
sub-ID was never recorded, so we can't tell their pre-change rows apart.
### Description

This bumps the version to 4.3.0

### Context

minor release

### Testing

- `./gradlew test`

### Documentation

N/A

### Known limitations

N/A
### Description

Merge `release/4.3.0` to `main`

### Context

Git flow

### Testing

- `./gradlew test`

### Documentation

N/A

### Known limitations

N/A
### Description

Merge `main` to `develop`

### Context

Git flow

### Testing

- `./gradlew test`

### Documentation

N/A

### Known limitations

N/A
* update soroban-sdk to version 26.0.0
### Description
update soroban-sdk to version 26.0.0

### Testing
`cd soroban && cargo test`

### Documentation
N/A

### Known limitations
N/A
### Description

Adds Gateway API (`Gateway` + `HTTPRoute`) support to all three Anchor
Platform helm charts.
 
### Context

Gateway Migration

### Testing

- `./gradlew test`
- `helm lint` passes for all three charts.
- `helm template` with default. Ingress still emitted, no
Gateway/HTTPRoute.
- `helm template` with Gateway API enabled. renders match the shape in
`stellar/kube`.
- Server-side dry-run not available locally

### Documentation

N/A

### Known limitations

N/A
#1940)

### Description

- adds an `httpRoute.responseHeaders` values block that emits a Gateway
API filter to set security response headers
- Explicit `namespace` + `sectionName` on `parentRefs` when using the
chart-managed Gateway

### Context

The first migration PR dropped the existing `ingress.responseHeaders`
block.
Adding `namespace` + `sectionName` on `parentRefs` is purely a
consistency fix to match the established Gateway API pattern.

### Testing

- `helm lint` passes for all three charts. 
- `helm template` with Gateway API enabled.

### Documentation

N/A

### Known limitations

N/A
…d allows cross-customer KYC disclosure and payout destination overwrite (#1946)

### Description

Before this change, \`Sep12Service.validateGetOrPutRequest\` enforced
authorization on \`request.account\` and \`request.memo\` only. When a
caller supplied \`request.id\` without \`account\`, the account check
short-circuited entirely, allowing any valid SEP-10 session to \`GET\`
or \`PUT\` any customer record by its \`id\` — regardless of who created
it. The \`id\` was forwarded unmodified to the business-server callback,
so any conforming business server would act on it.

The fix introduces a \`sep12_customer_ownership\` table. Every
successful \`PUT /sep12/customer\` writes the caller's identity
(\`stellar_account\`, \`memo\`) as the owner of the returned
\`customer_id\`. Subsequent \`GET\` or \`PUT\` requests that supply
\`id\` are checked against this table: if the stored owner does not
match the token, the request is rejected with 403 before the business
server is called. No business server contract changes are required.

**Changes**
- [x] \`Sep12CustomerOwnership\` / \`Sep12CustomerOwnershipStore\`: new
core interfaces defining the ownership record model and its storage
contract.
- [x] \`JdbcSep12CustomerOwnership\` /
\`JdbcSep12CustomerOwnershipRepo\` /
\`JdbcSep12CustomerOwnershipStore\`: platform JDBC implementation backed
by the new \`sep12_customer_ownership\` table.
- [x] \`V29__add_sep12_customer_ownership.sql\`: Flyway migration
creating the table (\`customer_id PK\`, \`stellar_account NOT NULL\`,
\`memo\`).
- [x] \`Sep12Service.putCustomer\`: after every successful callback
response, saves \`(customer_id, token_account, token_memo)\` to the
ownership store, overwriting any prior record on update.
- [x] \`Sep12Service.validateGetOrPutRequest\`: when \`id\` is present
and \`transactionId\` is absent, looks up the ownership record. If a
record exists and the token's identity does not match, returns 403
before reaching the business server. If no record exists (customer
predates the fix or SEP-31 first-time access), the request is allowed
through with the caller's account injected, preserving backward
compatibility.
- [x] \`SepBeans\` / \`DataBeans\`: wire \`Sep12CustomerOwnershipStore\`
into the Spring context.
- [x] \`Sep12ServiceTest\`: mocked \`Sep12CustomerOwnershipStore\`;
updated existing id-path tests; added IDOR unit tests covering
mismatched account rejection, mismatched memo rejection, no-record
allow-through, ownership save on PUT (plain and muxed), transactionId
path bypass, and forward-account-to-callback behaviour.
- [x] \`Sep12Tests\`: added \`test cross-account id access is rejected\`
integration test — registers a victim customer (ownership row written),
attempts raw HTTP \`GET\` and \`PUT\` against that \`id\` from a
different SEP-10 session, asserts 403 on both, and verifies the victim's
record is unchanged.

**Acceptance Criteria**
- [x] \`GET /sep12/customer?id=<id>\` with a SEP-10 token that does not
own that customer returns 403.
- [x] \`PUT /sep12/customer\` with \`{"id":"<id>", ...}\` from a
different SEP-10 session returns 403.
- [x] The same \`GET\` and \`PUT\` succeed when issued by the token that
owns the customer record.
- [x] No ownership record (first access or pre-existing customer) allows
the request through with the caller's account injected.
- [x] The \`transactionId\` path is unaffected.
- [x] All existing \`Sep12ServiceTest\` tests pass.

### Context

[HackerOne #3735379](https://hackerone.com/reports/3735379)

### Testing

- Unit: \`./gradlew :core:test --tests
"org.stellar.anchor.sep12.Sep12ServiceTest"\`
- Integration: \`./gradlew runEssentialTests\` — covers \`test
cross-account id access is rejected\` in \`Sep12Tests\`

### Documentation
N/A

### Known limitations

Customers created before this migration has run have no ownership
record. On their next \`PUT /customer\`, the record is written and all
subsequent id-based requests are fully enforced. Until then, id-based
access for those customers falls back to the caller's account being
injected, relying on the business server's own id+account consistency
check.
* update project version in `build.gradle.kts`

* update docker badge in `readme.md`

* update `version-info.properties`
### Description

This bumps the version to 4.4.0

### Context

Release

### Testing

- `./gradlew test`

### Documentation

N/A

### Known limitations

N/A
### Description

Merges `release/4.4.0` into `main` for the 4.4.0 release.

### Context

- **[ANCHOR-1215]** Fix SEP-12 IDOR via unvalidated customer `id` —
prevents cross-customer KYC disclosure and payout destination overwrite
(#1946)
- **[ANCHOR-1943]** Fix RPC observer DoS via malformed Soroban transfer
event (#1944)
- **[ANCHOR-1939]** Add per-client event isolation and ambiguous payment
routing safety (#1941, #1942)
- **[ANCHOR-1934]** Enforce single-use on SEP-38 quotes (#1935)
- **[ANCHOR-1206]** Add Gateway API support to Helm charts and carry
forward security headers (#1936, #1940)
- **[Chore]** Bump Soroban SDK from v22 to v26 (#1937)
- **[Chore]** Bump version to 4.4.0


[ANCHOR-1215]:
https://stellarorg.atlassian.net/browse/ANCHOR-1215?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
[ANCHOR-1206]:
https://stellarorg.atlassian.net/browse/ANCHOR-1206?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants