Checkboxes on each row + Select All in the header. When users are
selected, a "Top Up Selected" button appears in the filter bar.
Opens a modal with preset amounts to top up all selected users at
once. Each individual top-up is logged to history.
New endpoint: POST /api/balances/batch/add
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Documents all new features: email approve/reject flow, credit requests,
history tracking, low balance view. Includes complete env var reference,
email security notes, and troubleshooting section.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Email security scanners (Microsoft Defender Safe Links, etc.) pre-click
all links in emails. Previously the GET request directly approved the
request. Now GET shows a confirmation page and only POST (clicking the
confirm button) actually processes the approval/rejection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a user submits a credit request, an email is sent to all
configured NOTIFY_TO recipients with approve buttons (5M, 10M, 20M),
a custom amount option, and a reject button. Each button is a
signed HMAC-SHA256 webhook URL that expires after WEBHOOK_TTL_HOURS.
Clicking approve from email processes the top-up identical to the
admin dashboard — balance update, history log, request status change.
Double-approval protection prevents the same link from being used
twice. Portal approval still works alongside email approval.
New dependencies: nodemailer
New files: services/email.js, routes/webhooks.js
Modified: server.js, routes/requests.js, .env.example
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- All balance changes (top-ups, sets, bulk ops, request approvals)
are now logged to data/history.json
- New "History" tab in admin sidebar
- Search by email to see all changes for a user with totals
- Partial name search shows matching users with summary stats
- Each entry shows action type, amount, source, OMG job #,
resulting balance, and timestamp
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds a Custom button alongside the preset 5M/10M/20M approve buttons.
Opens a modal with preset quick-picks and a free-form input for any amount.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Public page at /request for users to submit top-up requests
(email + OMG job number, no auth required)
- Admin "Requests" view with pending/processed/all filters
- Approve with preset amounts (5M/10M/20M) or reject
- Pending count badge in sidebar nav
- Request data stored in JSON file (data/requests.json)
- Data volume mounted for persistence across rebuilds
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Apostrophes in names (e.g. O'Hagan) broke inline onclick handlers.
Switched to data attributes with event delegation for safe handling
of all special characters.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Moved /balances/bulk/* routes before /balances/:userId/* so Express
doesn't treat "bulk" as a userId and try to parse it as an ObjectId.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shows users below 1M/2M/3M/4M/5M tokens with filter buttons.
Sorted lowest first so admins can quickly find and top up users
running low.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Paths were absolute (/css/, /js/, /api) which broke when served
behind NGINX at /balance-manager/. Now uses relative paths with
base href.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Admin dashboard for managing user token balances. View, search, top up, and bulk-manage credits.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>