Skip to content

fix(cli): show the real credit balance on the CLI connect pages - #83

Merged
ralyodio merged 1 commit into
moshcoder:mainfrom
clawedassistant26:fix/cli-pages-hardcoded-balance
Jul 30, 2026
Merged

fix(cli): show the real credit balance on the CLI connect pages#83
ralyodio merged 1 commit into
moshcoder:mainfrom
clawedassistant26:fix/cli-pages-hardcoded-balance

Conversation

@clawedassistant26

Copy link
Copy Markdown
Contributor

The bug

appBar(user, balance, csrf) renders a ◆ <n> cr chip for every signed-in visitor. Every other signed-in page passes the account's real balance into it, so the chip reads as a live credit readout:

  • routes/pages.mjs:56,133appBar(req.user, bal, ...)
  • routes/approvals.mjs:119appBar(req.user, await balance(req.user.id), ...)

The two CLI-connect pages pass a literal 0:

  • apps/pwa/src/routes/cli.mjs:41GET /cli/authorize
  • apps/pwa/src/routes/cli.mjs:132GET /device

Both sit behind requireAuth, so the visitor is always a real signed-in account. A user with 4,321 credits is told ◆ 0 cr on the exact page where they are deciding whether to authorize the CLI or connect a device — the pages that unlock the notify() / ask() calls those credits pay for.

Repro

On unmodified main (df9d1e0), real cliRouter + pagesRouter against a throwaway libsql database, one user seeded with 4,321 credits in credit_ledger:

page chip shows ledger balance
GET /cli/authorize 0 4321
GET /device 0 4321
GET /dashboard (control) 4321 4321

No fault injection, no stubs — the dashboard reads the same seeded ledger through the same helper and gets it right.

The fix

Pass await balance(req.user.id), which cli.mjs already imports for GET /api/me, and make the two handlers async. The file's other handlers in this router are already async, so this does not introduce a new failure mode for the router. 7 insertions, 4 deletions — 3 of the insertions are the comment.

Tests

New apps/pwa/test/cli-pages-balance.test.mjs, 4 tests, built on the existing logout-csrf.test.mjs harness (skip-guard when PWA deps are missing, throwaway libsql file db).

Fail-before verified by restoring the pristine cli.mjs and re-running:

  • unpatched: 2 fail / 2 pass — both CLI pages report 0
  • patched: 4 pass

The two controls (/dashboard reads the ledger; /cli/authorize still renders the approve form with its CSRF field) pass both ways by design. That is what makes the two failures meaningful rather than a broken parser: the same regex reads 4321 off the dashboard in the unpatched run.

Suites: apps/pwa 30 → 34, root npm test 204 → 208, 0 failures before and after.

The app bar renders a "◆ <n> cr" chip for every signed-in visitor, and
every other signed-in page passes the account's real balance into it.
The two CLI-connect pages passed a literal 0, so a funded account is
told it has no credits on the exact page where it is deciding whether
to authorize the CLI or connect a device.

Pass await balance(req.user.id) instead, the same way the dashboard and
the approvals page already do. balance() was already imported here for
GET /api/me.

Adds apps/pwa/test/cli-pages-balance.test.mjs: 2 tests that fail on main
and pass with the fix, plus 2 controls that pass both ways.
@ralyodio
ralyodio merged commit f0702d9 into moshcoder:main Jul 30, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants