Indexer: narrow fee-discount registry health API #373
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic#373
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Parent
Follow-up from GitLab #365 — approved verification follow-up 1: narrow
GET /api/v1/health/fee-discountwith LCDconfigprobe and sanitized errors.Parent gap: GitLab #361 register item M2 (fee-discount registry
Err→ silent full fee on-chain; off-chain ops need a health signal).Current codebase
GetDiscountqueryErr(_)to full pairfee_bpswith no discount metadata (smartcontracts/contracts/pair/src/discount_cache.rs:145,173). Integration test:swap_uses_full_fee_when_discount_registry_query_fails(smartcontracts/tests/src/lib.rs).GET /healthstill returns only{"status":"ok"}(indexer/src/api/mod.rs) — no DB/LCD probe on the generic health surface (deep/healthwas rejected for #361).main:indexer/src/indexer/fee_discount_registry_health.rs(60s background LCDconfigprobe, consecutive failure counter,tracing::errorat ≥2 failures),indexer/src/api/fee_discount_health.rs(GET /api/v1/health/fee-discount), route wired inindexer/src/api/mod.rs, spawned fromindexer/src/main.rswhenFEE_DISCOUNT_ADDRESSis set. Integration tests:indexer/tests/api_fee_discount_health.rs(sanitized JSON, no LCD stack traces).trader_tracker.rsstill logs per-trader tier-sync LCD failures atwarnbut does not expose them via API (by design — no per-trader enumeration).Why needed
When the fee-discount registry is paused, migrating, or LCD-unreachable, pairs fail-closed to full fee on-chain with no swap revert. Ops and integrators currently have no narrow, opt-in signal that the registry LCD surface is unhealthy — only scattered per-trader sync warnings in logs.
Constraints / guardrails
GET /healthwith LCD/DB probes (rejected for #361). Keep this endpoint narrow and dedicated.indexer/tests/security.rspatterns — no raw LCD URLs, stack traces, or upstream body text in JSON responses./metricsdependency (#200).Relevant files
indexer/src/indexer/fee_discount_registry_health.rsindexer/src/api/fee_discount_health.rsindexer/src/api/mod.rs(route registration,AppState.fee_discount_registry_health)indexer/src/main.rs(probe loop spawn)indexer/src/config.rs(FEE_DISCOUNT_ADDRESS)indexer/tests/api_fee_discount_health.rsindexer/tests/security.rsdocs/indexer-invariants.md(observability exception row)Recommended direction
GET /api/v1/health/fee-discountreturnsFeeDiscountRegistryHealthSnapshot:configured: bool—FEE_DISCOUNT_ADDRESSsetfee_discount_registry_ok: bool | null—nullwhen unconfigured; otherwise latest probe resultconsecutive_lcd_failures: u32configsmart query every 60s via existingLcdClient; record success/failure in shared in-memory state.error(≥2 consecutive) with guidance that pairs fail-closed to full fee; recovery atinfo.docs/indexer-invariants.mdas the narrow observability exception to the tracing-only rule.Acceptance criteria
GET /api/v1/health/fee-discountreturns structured JSON withconfigured,fee_discount_registry_ok,consecutive_lcd_failures.FEE_DISCOUNT_ADDRESSis unset,fee_discount_registry_okisnullandconfiguredisfalse.consecutive_lcd_failuresand setsfee_discount_registry_ok: falsewithout leaking upstream error text in the HTTP body.tracing::error(not only per-trader tier-sync warns).GET /healthremains unchanged ({"status":"ok"}).Test plan
cd indexer && cargo test fee_discount_registry_health --libcd indexer && cargo test --test api_fee_discount_health -- --test-threads=1cd indexer && cargo test --test security(sanitization spot-check)curl /api/v1/health/fee-discountshowsfee_discount_registry_ok: false; body contains no LCD hostnamesAttack / abuse test plan
api_fee_discount_health.rsasserts)./api/v1/*if applicable; no unbounded LCD fan-out from public callers (probe is server-side only).Verification criteria
fee_discount_registry_ok: false,consecutive_lcd_failures ≥ 2, response text excludescosmwasm,http://,All LCD endpoints failed./api/v1/health/fee-discountduring registry outage without parsing per-trader logs.swap_uses_full_fee_when_discount_registry_query_failsstill passes unchanged.mentioned in issue #365
mentioned in commit
a165749c4cmentioned in merge request !891
mentioned in merge request !892
mentioned in commit
85b2af8e5fVerified on my side on main
edbe288.The narrow endpoint is in and the ACs hold:
Tests green:
Live endpoint is serving configured:true / fee_discount_registry_ok:true on the current deploy, and /health is unchanged alongside it.
Good to close from my side. @PlasticDigits
mentioned in commit
cccd4cf23ementioned in commit
44d73ee47cmentioned in merge request !893
Re-verified on main
d013b61after the health-API rework landed (the fee_discount_registry_health rework + main.rs from_config wiring), since my earlier note was against the pre-rework tree. Rebuilt + restarted the indexer offd013b61first.Still holds, with one behavior change worth noting:
Tests green on
d013b61: lib fee_discount_registry_health 4/4 (incl. configured-starts-null + successful-probe-sets-true), integration api_fee_discount_health 5/5 (incl. unconfigured returns null ok), security 25/25.Still good to close from my side. @PlasticDigits