Docs and verify-issue-365 for registry outage observability #375

Closed
opened 2026-06-13 02:49:46 +00:00 by PlasticDigits · 12 comments
PlasticDigits commented 2026-06-13 02:49:46 +00:00 (Migrated from gitlab.com)

Parent

Follow-up from GitLab #365 — approved verification follow-ups 3 and 4 (bundled):

  • 3: Integrator-facing documentation for fail-closed registry Err vs unregistered trader.
  • 4: make verify-issue-365 regression ladder for re-verification after implementation merges.

Parent gap: GitLab #361 register item M2.

Current codebase

  • Invariant P5 in docs/contracts-security-audit.md documents on-chain fail-closed behavior and references off-chain health + dApp warning.
  • Invariant I10 in docs/reference/fee-discount-tiers.md distinguishes unregistered vs registry unreachable for integrators.
  • docs/indexer-invariants.md documents GET /api/v1/health/fee-discount.
  • skills/AGENTS_FEE_DISCOUNT_TIERS.md § Registry outage observability summarizes the stack.
  • docs/integrators.md mentions effective fee after registry but lacks a dedicated registry outage subsection (recommended in parent issue § Docs).
  • No scripts/qa/verify-issue-365.sh or make verify-issue-365 target yet (peer pattern: scripts/qa/verify-issue-324.sh, verify-issue-369.sh).
  • Contract regression: swap_uses_full_fee_when_discount_registry_query_fails in smartcontracts/tests/src/lib.rs.

Why needed

Integrators and ops need a single place to learn that registry query failure ≠ “trader not registered”, and a one-command verification ladder to close #365 after child work lands (per parent verification comment: “rerun verification” once issues are implemented and closed).

Constraints / guardrails

  • Document observed behavior only; do not propose on-chain revert-on-registry-error without ADR.
  • Keep docs/reference/fee-discount-tiers.md as the canonical tier table — add cross-links, do not duplicate numeric tiers in integrators.md.
  • Verification script should follow existing scripts/qa/verify-issue-*.sh patterns: PASS/FAIL summary, bootstrap make setup-indexer-postgres when indexer/.env missing, no LocalTerra required for the default ladder.
  • Wire make verify-issue-365 in Makefile and mention in docs/testing.md if other verify targets are listed there.

Relevant files

  • docs/contracts-security-audit.md (P5)
  • docs/integrators.md (add registry-outage guidance)
  • docs/reference/fee-discount-tiers.md (I10)
  • docs/indexer-invariants.md
  • docs/testing.md
  • skills/AGENTS_FEE_DISCOUNT_TIERS.md
  • scripts/qa/verify-issue-365.sh (new)
  • Makefile
  • smartcontracts/tests/src/lib.rs (swap_uses_full_fee_when_discount_registry_query_fails)
  • indexer/tests/api_fee_discount_health.rs
  • frontend-dapp/src/utils/__tests__/feeDiscountRegistryWarning.test.ts

Documentation

  1. Add a short Fee-discount registry outage section to docs/integrators.md:
    • On-chain: GetDiscount Err → full pair fee_bps, swap succeeds.
    • Off-chain signals: indexer GET /api/v1/health/fee-discount, LCD get_registration / get_discount errors.
    • Decision table: unregistered (registered: false) vs registry unreachable (LCD errors or fee_discount_registry_ok: false).
    • Link to P5, I10, and skills/AGENTS_FEE_DISCOUNT_TIERS.md.
  2. Ensure P5 and I10 cross-link to the new integrator section (one-line pointers only).

Verification ladder

Create scripts/qa/verify-issue-365.sh exercising:

Step Command
Contract invariant cargo test swap_uses_full_fee_when_discount_registry_query_fails (from smartcontracts/tests or workspace alias)
Indexer health API cargo test --test api_fee_discount_health -- --test-threads=1
Frontend warning util make test-frontend filtered to feeDiscountRegistryWarning (or full frontend if filter unsupported)

Add make verify-issue-365 target mirroring verify-issue-324 / verify-issue-369 (chmod + invoke script).

Acceptance criteria

  • docs/integrators.md includes integrator guidance distinguishing unregistered vs registry LCD outage (with links to health endpoint and on-chain semantics).
  • make verify-issue-365 exists and passes on main when #365 scope is complete.
  • docs/testing.md or skills/AGENTS_FEE_DISCOUNT_TIERS.md references make verify-issue-365 for agents/QA.
  • P5 / I10 remain accurate and cross-linked.
  • Verification script prints PASS/FAIL summary and exits non-zero on failure.

Test plan

Path Command / action
Docs drift make check-fee-discount-tier-docs (if tier doc touched)
Verify ladder make verify-issue-365
Manual Read docs/integrators.md registry-outage section — actionable without reading Rust sources

Attack / abuse test plan

  • Integrator docs must not instruct exposing per-trader registry errors via public APIs.
  • Verify script must not print secrets from indexer/.env.

Verification criteria

  • make verify-issue-365 green on a checkout with indexer health + frontend warning + docs landed.
  • Parent #365 can be re-verified and closed after all three child issues close.
  • Contract test swap_uses_full_fee_when_discount_registry_query_fails included in ladder and passing.
## Parent Follow-up from [GitLab #365](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/365) — approved verification follow-ups **3** and **4** (bundled): - **3:** Integrator-facing documentation for fail-closed registry `Err` vs unregistered trader. - **4:** `make verify-issue-365` regression ladder for re-verification after implementation merges. Parent gap: [GitLab #361](https://gitlab.com/PlasticDigits/cl8y-dex-terraclassic/-/work_items/361) register item **M2**. ## Current codebase - Invariant **P5** in `docs/contracts-security-audit.md` documents on-chain fail-closed behavior and references off-chain health + dApp warning. - Invariant **I10** in `docs/reference/fee-discount-tiers.md` distinguishes unregistered vs registry unreachable for integrators. - `docs/indexer-invariants.md` documents `GET /api/v1/health/fee-discount`. - `skills/AGENTS_FEE_DISCOUNT_TIERS.md` § Registry outage observability summarizes the stack. - `docs/integrators.md` mentions effective fee after registry but lacks a dedicated **registry outage** subsection (recommended in parent issue § Docs). - **No** `scripts/qa/verify-issue-365.sh` or `make verify-issue-365` target yet (peer pattern: `scripts/qa/verify-issue-324.sh`, `verify-issue-369.sh`). - Contract regression: `swap_uses_full_fee_when_discount_registry_query_fails` in `smartcontracts/tests/src/lib.rs`. ## Why needed Integrators and ops need a single place to learn that registry query failure ≠ “trader not registered”, and a one-command verification ladder to close #365 after child work lands (per parent verification comment: “rerun verification” once issues are implemented and closed). ## Constraints / guardrails - Document **observed behavior** only; do not propose on-chain revert-on-registry-error without ADR. - Keep `docs/reference/fee-discount-tiers.md` as the canonical tier table — add cross-links, do not duplicate numeric tiers in `integrators.md`. - Verification script should follow existing `scripts/qa/verify-issue-*.sh` patterns: PASS/FAIL summary, bootstrap `make setup-indexer-postgres` when `indexer/.env` missing, no LocalTerra required for the default ladder. - Wire `make verify-issue-365` in `Makefile` and mention in `docs/testing.md` if other verify targets are listed there. ## Relevant files - `docs/contracts-security-audit.md` (P5) - `docs/integrators.md` (add registry-outage guidance) - `docs/reference/fee-discount-tiers.md` (I10) - `docs/indexer-invariants.md` - `docs/testing.md` - `skills/AGENTS_FEE_DISCOUNT_TIERS.md` - `scripts/qa/verify-issue-365.sh` (new) - `Makefile` - `smartcontracts/tests/src/lib.rs` (`swap_uses_full_fee_when_discount_registry_query_fails`) - `indexer/tests/api_fee_discount_health.rs` - `frontend-dapp/src/utils/__tests__/feeDiscountRegistryWarning.test.ts` ## Recommended direction ### Documentation 1. Add a short **Fee-discount registry outage** section to `docs/integrators.md`: - On-chain: `GetDiscount` `Err` → full pair `fee_bps`, swap succeeds. - Off-chain signals: indexer `GET /api/v1/health/fee-discount`, LCD `get_registration` / `get_discount` errors. - Decision table: unregistered (`registered: false`) vs registry unreachable (LCD errors or `fee_discount_registry_ok: false`). - Link to P5, I10, and `skills/AGENTS_FEE_DISCOUNT_TIERS.md`. 2. Ensure P5 and I10 cross-link to the new integrator section (one-line pointers only). ### Verification ladder Create `scripts/qa/verify-issue-365.sh` exercising: | Step | Command | |------|---------| | Contract invariant | `cargo test swap_uses_full_fee_when_discount_registry_query_fails` (from `smartcontracts/tests` or workspace alias) | | Indexer health API | `cargo test --test api_fee_discount_health -- --test-threads=1` | | Frontend warning util | `make test-frontend` filtered to `feeDiscountRegistryWarning` (or full frontend if filter unsupported) | Add `make verify-issue-365` target mirroring `verify-issue-324` / `verify-issue-369` (chmod + invoke script). ## Acceptance criteria - [ ] `docs/integrators.md` includes integrator guidance distinguishing unregistered vs registry LCD outage (with links to health endpoint and on-chain semantics). - [ ] `make verify-issue-365` exists and passes on `main` when #365 scope is complete. - [ ] `docs/testing.md` or `skills/AGENTS_FEE_DISCOUNT_TIERS.md` references `make verify-issue-365` for agents/QA. - [ ] P5 / I10 remain accurate and cross-linked. - [ ] Verification script prints PASS/FAIL summary and exits non-zero on failure. ## Test plan | Path | Command / action | |------|------------------| | Docs drift | `make check-fee-discount-tier-docs` (if tier doc touched) | | Verify ladder | `make verify-issue-365` | | Manual | Read `docs/integrators.md` registry-outage section — actionable without reading Rust sources | ## Attack / abuse test plan - Integrator docs must not instruct exposing per-trader registry errors via public APIs. - Verify script must not print secrets from `indexer/.env`. ## Verification criteria - `make verify-issue-365` green on a checkout with indexer health + frontend warning + docs landed. - Parent #365 can be re-verified and closed after all three child issues close. - Contract test `swap_uses_full_fee_when_discount_registry_query_fails` included in ladder and passing.
PlasticDigits commented 2026-06-13 02:49:57 +00:00 (Migrated from gitlab.com)

mentioned in issue #365

mentioned in issue #365
PlasticDigits commented 2026-06-13 03:01:45 +00:00 (Migrated from gitlab.com)

mentioned in commit b92a12ced3

mentioned in commit b92a12ced36a5b803b78fa13637005d9f017968c
PlasticDigits commented 2026-06-13 03:02:02 +00:00 (Migrated from gitlab.com)

mentioned in merge request !892

mentioned in merge request !892
PlasticDigits commented 2026-06-13 03:11:31 +00:00 (Migrated from gitlab.com)

mentioned in commit edbe288781

mentioned in commit edbe288781a51b224e9eed9971de563c09ef1260
Brouie commented 2026-06-13 03:19:42 +00:00 (Migrated from gitlab.com)

Checked on my side on main edbe288.

Docs side is all there:

  • docs/integrators.md has a Fee-discount registry outage section with the decision table distinguishing unregistered (registered:false) from registry unreachable (LCD errors or indexer fee_discount_registry_ok:false), the fail-closed-to-full-fee semantics, and the health endpoint — no per-trader fields, no raw LCD text.
  • I10 in docs/reference/fee-discount-tiers.md makes the same unregistered-vs-unreachable distinction and links to the integrators section.
  • docs/testing.md and skills/AGENTS_FEE_DISCOUNT_TIERS.md both point at make verify-issue-365, and P5 / I10 cross-link.

The ladder content passes — scripts/qa/verify-issue-365.sh is 3/3:

  • contract P5 swap_uses_full_fee_when_discount_registry_query_fails
  • indexer api_fee_discount_health
  • frontend feeDiscountRegistryWarning
    PASS/FAIL summary prints and it exits non-zero on failure as specified.

One nit on the make target: make verify-issue-365 bails before the script runs. The recipe does chmod +x scripts/qa/verify-issue-365.sh scripts/setup-cloud-agent-indexer-postgres.sh scripts/with-node.sh, and if setup-cloud-agent-indexer-postgres.sh isn't owned by the invoking user the chmod fails and the whole target errors out. The default ladder doesn't need that script anyway (it only shells setup-indexer-postgres when indexer/.env is missing). Running scripts/qa/verify-issue-365.sh directly is 3/3 green. Suggest dropping setup-cloud-agent-indexer-postgres.sh from that chmod line (or guarding it) so make verify-issue-365 is portable.

Docs + ladder content are good from my side; the chmod line is the one thing to tidy so the make wrapper strictly passes. @PlasticDigits

Checked on my side on main edbe288. Docs side is all there: - docs/integrators.md has a Fee-discount registry outage section with the decision table distinguishing unregistered (registered:false) from registry unreachable (LCD errors or indexer fee_discount_registry_ok:false), the fail-closed-to-full-fee semantics, and the health endpoint — no per-trader fields, no raw LCD text. - I10 in docs/reference/fee-discount-tiers.md makes the same unregistered-vs-unreachable distinction and links to the integrators section. - docs/testing.md and skills/AGENTS_FEE_DISCOUNT_TIERS.md both point at make verify-issue-365, and P5 / I10 cross-link. The ladder content passes — scripts/qa/verify-issue-365.sh is 3/3: - contract P5 swap_uses_full_fee_when_discount_registry_query_fails - indexer api_fee_discount_health - frontend feeDiscountRegistryWarning PASS/FAIL summary prints and it exits non-zero on failure as specified. One nit on the make target: `make verify-issue-365` bails before the script runs. The recipe does `chmod +x scripts/qa/verify-issue-365.sh scripts/setup-cloud-agent-indexer-postgres.sh scripts/with-node.sh`, and if setup-cloud-agent-indexer-postgres.sh isn't owned by the invoking user the chmod fails and the whole target errors out. The default ladder doesn't need that script anyway (it only shells setup-indexer-postgres when indexer/.env is missing). Running scripts/qa/verify-issue-365.sh directly is 3/3 green. Suggest dropping setup-cloud-agent-indexer-postgres.sh from that chmod line (or guarding it) so `make verify-issue-365` is portable. Docs + ladder content are good from my side; the chmod line is the one thing to tidy so the make wrapper strictly passes. @PlasticDigits
PlasticDigits commented 2026-06-13 03:52:34 +00:00 (Migrated from gitlab.com)

Approved fix for make verify-issue-365

Approved fix for make verify-issue-365
PlasticDigits commented 2026-06-13 03:56:19 +00:00 (Migrated from gitlab.com)

mentioned in merge request !898

mentioned in merge request !898
PlasticDigits commented 2026-06-13 04:23:00 +00:00 (Migrated from gitlab.com)

mentioned in commit b23c1c51cf

mentioned in commit b23c1c51cf4bdf5efa7551fff5e45388c2f9581e
Brouie commented 2026-06-13 04:23:40 +00:00 (Migrated from gitlab.com)

mentioned in commit 10893b6b79

mentioned in commit 10893b6b79dd253ffbd67c1840bea326cfab84c5
Brouie commented 2026-06-13 04:23:43 +00:00 (Migrated from gitlab.com)

mentioned in merge request !900

mentioned in merge request !900
Brouie commented 2026-06-13 04:23:50 +00:00 (Migrated from gitlab.com)

Fixed the make verify-issue-365 chmod nit I flagged. Branch qa/375-verify-365-make-chmod (commit 10893b6), MR !900.

The recipe was chmod-ing two scripts the ladder doesn't directly exec — with-node.sh (run as bash scripts/with-node.sh, no exec bit needed) and setup-cloud-agent-indexer-postgres.sh (not invoked at all; bootstrap shells make setup-indexer-postgres). When one of those isn't owned by the invoking user the chmod fails and the target dies before the ladder runs. Now it chmods only scripts/qa/verify-issue-365.sh, with a - prefix so a no-op chmod can't abort.

Confirmed make verify-issue-365 now runs end-to-end, 3/3 PASS (contract P5 + indexer health + frontend warning). One-line recipe change.

With this in, the make-target AC is satisfied — good to close from my side once !900 lands. @PlasticDigits

Fixed the make verify-issue-365 chmod nit I flagged. Branch qa/375-verify-365-make-chmod (commit 10893b6), MR !900. The recipe was chmod-ing two scripts the ladder doesn't directly exec — with-node.sh (run as `bash scripts/with-node.sh`, no exec bit needed) and setup-cloud-agent-indexer-postgres.sh (not invoked at all; bootstrap shells `make setup-indexer-postgres`). When one of those isn't owned by the invoking user the chmod fails and the target dies before the ladder runs. Now it chmods only scripts/qa/verify-issue-365.sh, with a `-` prefix so a no-op chmod can't abort. Confirmed `make verify-issue-365` now runs end-to-end, 3/3 PASS (contract P5 + indexer health + frontend warning). One-line recipe change. With this in, the make-target AC is satisfied — good to close from my side once !900 lands. @PlasticDigits
Brouie commented 2026-06-13 04:27:56 +00:00 (Migrated from gitlab.com)

Closed my !900 — it raced with 2b5d263 ("make verify-issue-365 portable without setup script chmod"), which already landed on main and drops the setup-cloud-agent-indexer-postgres.sh chmod that was the actual blocker. Re-checked on current main: make verify-issue-365 runs clean here, 3/3. So !900 was redundant; closed it and deleted the branch rather than resolve the conflict into a duplicate.

One small residual, take it or leave it: the target on main still does @chmod +x scripts/qa/verify-issue-365.sh scripts/with-node.sh with no - guard. with-node.sh is run via bash so it doesn't need the exec bit, and on a normal checkout it's user-owned — but on a host where that script ends up non-user-owned (same way setup-cloud-agent-indexer-postgres.sh did), that chmod would fail and abort the target again. A - prefix (or dropping with-node.sh from the chmod) makes it bulletproof. Not blocking — the make-target AC is satisfied as-is.

Good to close from my side. @PlasticDigits

Closed my !900 — it raced with 2b5d263 ("make verify-issue-365 portable without setup script chmod"), which already landed on main and drops the setup-cloud-agent-indexer-postgres.sh chmod that was the actual blocker. Re-checked on current main: `make verify-issue-365` runs clean here, 3/3. So !900 was redundant; closed it and deleted the branch rather than resolve the conflict into a duplicate. One small residual, take it or leave it: the target on main still does `@chmod +x scripts/qa/verify-issue-365.sh scripts/with-node.sh` with no `-` guard. with-node.sh is run via `bash` so it doesn't need the exec bit, and on a normal checkout it's user-owned — but on a host where that script ends up non-user-owned (same way setup-cloud-agent-indexer-postgres.sh did), that chmod would fail and abort the target again. A `-` prefix (or dropping with-node.sh from the chmod) makes it bulletproof. Not blocking — the make-target AC is satisfied as-is. Good to close from my side. @PlasticDigits
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-06-13 07:31:16 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
code/cl8y-dex-terraclassic#375
No description provided.