Add admin authorization to /api/admin/* and /api/users #27
Labels
No labels
bug
decision
docs
enhancement
integration
ops
security
tech-debt
testing
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
rbrooks/BatteryStorageCalculator#27
Loading…
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?
backend/src/app.js:83-104: the admin status/diagnostics routes and the user list/create routes sit behindauthMiddlewarebut have no role gate. The repository calls behind them (repository.pg.js:589-677) aggregate integrations, background jobs, and calculation diagnostics across all homes;GET /api/userslists all user emails;POST /api/usersaccepts arbitraryoidcSubjectvalues, which is the conflict key for the OIDC login upsert.Fix: add
is_admin boolean not null default falsetousers(new migration, numbered 007_), arequireAdminguard, and apply it to all four routes. Ignore client-suppliedoidcSubjecton user creation. WhenAUTH_MODE=disabled(single-user dev mode) keep current behavior, but deny by default wheneverauth.requiredis true.Acceptance criteria
Relations: relates to #17 (viewer-access decision is the same trust-boundary conversation)
(Audit finding F-06, 2026-07-16 — Severity: High, Confidence: High)
Scope addition from the #17 decision (2026-07-17): while adding the
requireAdminguard, also narrow raw usage-row access per the decided viewer policy — routes serving rawusageReadings(row-level hourly data) move to editor/owner; viewers keep calculation results, analytics summaries, and reports. Acceptance addition: a viewer-role request for raw usage rows returns 403, and the shared dashboard still renders for viewers.