Commit Graph

4 Commits

Author SHA1 Message Date
Chris Chen 62592c29ae Add audit logs.
ci-cd-vm / ci-cd (push) Successful in 4m2s
2026-06-23 12:13:47 -07:00
Chris Chen 95fa37ebdf fix(expense): open category read to all authed users; statement lookups via FirstOrDefaultAsync
Final-review findings:
- ExpenseCategoriesController was finance-only at the class level, but the member
  self-service reimbursement form reads the category list to populate its dropdown,
  so members got 403 and could not submit. Open GET to any authenticated user;
  keep group/subcategory writes finance-only (mirrors MinistriesController).
  Verified live with a member-role account: reads 200, writes 403, self-submit 200.
- MonthlyStatementService Update/Finalize now use FirstOrDefaultAsync for
  convention consistency with the rest of the service layer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 19:14:18 -07:00
Chris Chen e1f99158aa fix(expense): resolve current user id from 'sub' JWT claim
Live verification revealed the JWT carries the user id in the 'sub' claim
(NameClaimType=sub, MapInboundClaims=false), so ClaimTypes.NameIdentifier is
null at runtime. This caused ExpensesController.GetMine/GetById to throw
NullReferenceException (500) on the '!.Value', and made the services fall back
to 'system' — silently defeating the self-ownership guard. Resolve via
NameIdentifier (unit tests) then 'sub' (real tokens). Adds a regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-29 19:08:21 -07:00
Chris Chen 86d9879a6d feat(expense): add MonthlyStatementService with server-side recompute + tests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-29 18:34:39 -07:00