Skip to content

Fix/api hardening followups - #128

Open
lonerthefirst3-sudo wants to merge 5 commits into
RWA-ToolKit:mainfrom
lonerthefirst3-sudo:fix/api-hardening-followups
Open

Fix/api hardening followups#128
lonerthefirst3-sudo wants to merge 5 commits into
RWA-ToolKit:mainfrom
lonerthefirst3-sudo:fix/api-hardening-followups

Conversation

Merging feat/api-hardening into main (59c9fdd/e9cc3ba) silently dropped
the metrics, metrics-exporter-prometheus, and rand dependencies from
Cargo.toml, and dropped AppState::last_indexed_ledger() even though
indexer/mod.rs and routes/mod.rs still reference all of them. The crate
did not compile on main.

Restores the three dependencies (plus the metrics_exporter_prometheus
imports main.rs/indexer/mod.rs never picked up either), and re-adds
last_indexed_ledger() as a plain sync read off the now-synchronous
ArcSwap-backed snapshot (the async version from before the ArcSwap
migration no longer applies).
Every asset and every allowlisted address was processed with sequential
awaits, so one slow read serialized behind everything else in the
refresh cycle.

- refresh() now indexes assets concurrently via buffer_unordered,
  capped at ASSET_CONCURRENCY (8).
- Within an asset, metadata and dividends don't depend on each other
  and now run via tokio::join! instead of one after the other; the
  holder/compliance read still runs after metadata since it needs the
  compliance contract id from it.
- index_compliance_and_holders now reads each address's compliance
  record and balance concurrently (tokio::join!) and processes
  addresses concurrently via buffer_unordered, capped at
  ADDRESS_CONCURRENCY (16), instead of one address at a time.

Error-handling semantics are unchanged: a failed metadata or balance
read still fails that asset/address and propagates; a failed dividends
or compliance-record read is still tolerated and treated as
empty/absent.
GET / hardcoded "docs": "https://github.com/your-org/stellar-rwa-api-docs",
an un-substituted placeholder pointing nowhere useful.

Adds RWA_DOCS_URL (default: the real repo, https://github.com/RWA-ToolKit/stellar-rwa-api-docs)
to Config, and serves it from there instead of the literal placeholder.
ratio_percent clamped to [0,100] unconditionally, so a holder balance
exceeding total supply (possible via the asset-token self-transfer
inflation bug) was silently reported as exactly 100% — indistinguishable
from a legitimate whole-supply holder.

Still clamps to 100% for display (share_percent/claimed_percent stay
sane, bounded API values), but now logs a tracing::warn! with the
offending part/whole and increments a new
rwa_indexer_ratio_overflow_total{kind} counter (kind only, not the
address/distribution id, to keep label cardinality bounded) whenever
part > whole, so the inconsistency is visible instead of swallowed.
CorsLayer hardcoded allow_origin(Any)/allow_methods(Any)/allow_headers(Any).
Defensible for a read-only public API, but not configurable, and a
future write endpoint would inherit the same wide-open policy by
surprise.

Adds RWA_CORS_ALLOWED_ORIGINS (comma-separated). Unset/empty keeps the
current Any behavior as the default; setting it locks the deployment
down to exactly those origins. Entries that don't parse as a valid
header value are logged and dropped rather than failing startup.
@drips-wave

drips-wave Bot commented Jul 25, 2026

Copy link
Copy Markdown

@lonerthefirst3-sudo Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment