Skip to content

Feat/issues 721 723 724 726 dashboard shortcuts and e2e - #831

Merged
Markadrian6399 merged 3 commits into
StellarGateLabs:mainfrom
samuelb4u2000-sys:feat/issues-721-723-724-726-dashboard-shortcuts-and-e2e
Sep 27, 2026
Merged

Markadrian6399 merged 3 commits into
StellarGateLabs:mainfrom
samuelb4u2000-sys:feat/issues-721-723-724-726-dashboard-shortcuts-and-e2e

Conversation

@samuelb4u2000-sys

Copy link
Copy Markdown
Contributor

What and why

Closes #

How it was verified

  • cargo test passes
  • cargo fmt --check and cargo clippy --all-targets -- -D warnings pass
  • New behaviour is covered by a test that fails without this change

Risk

  • Adds or changes a database migration (forward-only — see DEPLOYMENT.md)
  • Changes a public API response shape or error code
  • Touches payment verification, settlement, or amount handling
  • Touches authentication, the SSRF guard, or webhook signing
  • Adds or updates a dependency (cargo deny check all passes)
  • Requires a config/env change to deploy (documented in README + .env.example)

Notes for the reviewer

closes #721
closes #723
closes #724
closes #726

…ode --test

Closes StellarGateLabs#723.

The dashboard's logic was locked inside one IIFE in dashboard.js, so none of
it could be tested without a browser. Split the reusable parts into four
DOM-free ES modules and cover them with Node's built-in test runner — no npm
dependencies, no package.json, no lockfile to rot:

  format.js   pure formatting, query building, CSV serialisation, row filtering
  session.js  API-key storage rules, with storage and clock injected
  state.js    the single view-state store, plus URL-hash (de)serialisation
  keys.js     which keystroke means which action, and row-movement clamping

Each module is named after the route it is served on and imports its siblings
with relative specifiers. That is what lets the same file load in the browser
and under `node --test`: an absolute `/dashboard/...` specifier works in the
page and then fails to resolve in the test runner, which is exactly the browser
coupling the split exists to remove.

`node --test` runs 120 assertions covering the cases that are awkward to reach
through a UI: storage blocked or full (Safari private mode), a corrupted save
timestamp, `/` typed into a date field, Cmd+R left to the browser, a highlight
that a filter change left pointing past the end of the list, a filter value
escaping its own URL parameter, and a memo that would otherwise re-enter Excel
as a formula on CSV export.

Also restored a batch of pre-existing breakage on main that left the dashboard
non-functional and CI red:

- dashboard.js called formatAmount, countdown, relativeTime, explorerTx,
  readHashState and writeHashState, none of which existed. Sign-in threw a
  ReferenceError before it could authenticate anyone. All six now live in
  format.js/state.js, and the search box and auto-refresh toggle the lost
  code referenced are back in the markup.
- src/api/payments.rs carried a duplicated axum import block, so the crate did
  not compile at all.
- Cargo.lock listed foldhash and hashbrown twice and a phantom rand entry
  carrying a mangled registry URL, so `cargo build --locked` and
  `cargo test --locked` failed before running anything.
- tests/db_tests.rs called list_payments with its pre-date-filter signature.
- tests/rate_limit_tests.rs sent the literal string "******" as the API key
  instead of the one provision_merchant had just minted, so every request 401'd
  and the rate-limit assertions never ran.
- tests/schema_snapshot_test.rs replayed the snapshot in file order, but the
  file is ordered as SQLite reports sqlite_master — every CREATE INDEX ahead of
  every CREATE TABLE — so the first index failed against a table that did not
  exist yet. Statements are now replayed in dependency order.
- tests/multi_op_transaction_tests.rs asserted that a half-payment returns
  false from reconcile_payment. It returns true: an underpayment is itself a
  settlement event that fires payment.underpaid. The tests now assert the
  status transitions they were written to protect — the intent reaches
  completed, one webhook per transition, and a rescan is still a no-op.
- An unauthenticated PUT to a known path answered 401 rather than 405, because
  `route_layer` wraps the MethodRouter and so ran the credential check before
  axum had rejected the verb. Auth is now layered per method, so the 405 wins
  and the request never reaches the credential check (StellarGateLabs#635).

Finally, every relative import in a dashboard module is asserted to resolve to
a route the router actually serves, and the API key is pinned to the
Authorization header in both source and served bytes.
The e2e job boots the real binary and drives the router, auth middleware, the
payments API and the migrations, so a change under src/ can break it exactly as
easily as a change under static/. The path filter only listed static/, so the
suite was quietly narrower than it appeared.

Also drop the '|| npm install' fallback: it would paper over a lockfile that
needs regenerating by silently resolving fresh versions, which is the opposite
of what a reproducible suite wants.
@drips-wave

drips-wave Bot commented Sep 26, 2026

Copy link
Copy Markdown

@samuelb4u2000-sys 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

@Markadrian6399
Markadrian6399 merged commit a9c4aa6 into StellarGateLabs:main Sep 27, 2026
4 of 13 checks passed
@grantfox-oss grantfox-oss Bot mentioned this pull request Sep 27, 2026
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants