Stellar Index v0.5.0-rc.111
Pre-release
Pre-release
[v0.5.0-rc.111] — 2026-06-18
Changed
- Explorer nav restructured toward an entity-centric IA. The left rail is
now Explorer entities (Home, Ledgers, Accounts, Issuers, Assets, AMM Pools) →
Protocols (DEX/AMM, Lending, Aggregators, Bridges, Oracles, Soroswap Router) →
External Markets → Analytics (Anomalies, Divergence, MEV) → Developers (API
docs, SDK, Status). Secondary/marketing pages (Pricing, Methodology,
Diagnostics, the CEX board) moved to footer + search. First slice of the
deep-explorer build; Transactions, Contracts, and a dedicated SDEX order-book
view land with their pages next.
Added
- Contracts as a first-class entity — directory + interaction map. New
GET /v1/contractsranks the most active Soroban contracts over a recent
window, each tagged with its owningprotocolfrom the factory-anchored
registry (the attribution hinge). New
GET /v1/contracts/{id}/interactionsreturns the contract's cross-contract
interaction map — other contracts that co-occur in its transactions (a proxy
for cross-contract calls, since Soroban sub-invocations nest within one tx),
ranked by shared-tx count and protocol-tagged. Both back the explorer's new
/contractsdirectory page (top-level nav) and an interaction-map panel on
the contract detail page (alongside the existing events + decoded-code
panels). Lake-backed (stellar.contract_events), window-scoped to stay on
the primary-key range. - Transactions page + SDEX Markets nav split —
/transactions(recent
network activity, ledger-paged) and a distinct "SDEX Markets" nav entry
(native order book) separate from "AMM Pools". /bridgespage — cross-chain settlement directory (Circle CCTP v2 + Rozo),
a category landing over/v1/protocols(reuses the protocol-directory grid).
Fixed
- Deploys silently skipped every migration — the F-1220 auto-apply was a
no-op.deploy.ymlpasses-e "migrations_skip=false", which Ansible
receives as the STRING"false"(truthy in Jinja), so the playbook's
when: ... or not migrations_skipalways evaluated false and SKIPPED the
"Sync migrations" + "Apply outstanding migrations" tasks — printing
"migrations_skip=true — skipping" even when the operator passed false. Every
binary deploy since left schema changes unapplied, the exact "healthz 200 but
partial outage" shape F-1220 was meant to prevent (and why the canonical
/usr/local/share/stellarindex/migrationswas empty on r1). Fixed by coercing
with| boolin the playbook conditions. Also corrected the
fx-history-missingrunbook, which pointed operators at the stale,
unmanaged/var/lib/stellarindex/migrationsinstead of the deploy-managed
/usr/local/share/stellarindex/migrations. - Doc/config drift: the dashboard SPA at
app.stellarindex.iowas retired
(2026-06-17) into the in-sitestellarindex.io/account, but config doc-strings,
handler comments, the OpenAPI/auth/logindescription,package.json, and
three architecture docs still pointed at the dead host (one with a dead
web/dashboard/README.mdlink). Updated to reality and regenerated the
spec-derived artifacts. - Hardened against the
nil-Now-class latent panic found in dashboard auth.
A codebase sweep for the same pattern (a dependency dereferenced on a path
that didn't guard/default it) surfaced three latent cases, all now closed:
lookupUSDPricederefed the optionalPricesreader unguarded on the
populateChange24hpath (the siblingpopulatePriceUSDguarded it) — and
since asset-detail fields populate on child goroutines that
middleware.Recoverercan't cover, an unguarded panic there would crash the
whole API process; therun()helper now recovers per-goroutine. The
statsflushandsupplyrefresher constructors now default a nil logger like
their siblings (both deref it on a background tick).
Fixed
- Dashboard sign-in was completely broken — every authenticated request
500'd.main.gobuilt the dashboard authConfigwithout aNowclock
and passed it raw to the session-resolver middleware;NewHandlersdefaulted
Nowonly on its own copy, soresolveSessionnil-deref-panicked on every
request carrying a session cookie. The magic link set the cookie correctly,
then/v1/account/me500'd and the dashboard never loaded — so login looked
dead.Nowis now set explicitly and the middleware defaultsNow/Logger
defensively. - The emailed "6-digit code" was really 5 digits + a NUL byte. It was
derived from 3 hash bytes → 5 base32 chars, leaving the 6th position unset.
Now derived from 4 bytes so it is a clean 6 ASCII digits — required, since
the code is now a typed credential.
Added
- Sign in with a 6-digit code, not just the magic link. New
POST /v1/auth/verify-code {email, code}consumes the emailed code and mints
the same session cookie the magic-link callback does (returns JSON, no
redirect — the SPA calls it via credentialedfetch). The sign-in page is now
a two-step flow (email → code) and the email leads with the code; the
one-click link still works. Brute-force is bounded by a per-token attempt cap
(migration 0065 addsmagic_link_tokens.attempts); all code-failure modes
return one generic 400.
Changed
- Cross-origin session auth (F-03) — the in-site
/accountsection now
authenticates on the apex. The session cookie is issuedSameSite=None
whenSecure(prod), so the explorer at stellarindex.io can send it on
credentialed requests to the API at api.stellarindex.io;useMe+ the
account API client sendcredentials: include. Requiresallow_credentials = true+cookie_domain = ".stellarindex.io"in the API config (set on r1).
Replaces the prior "explorer always renders signed-out" limitation.