Introduces a capability layer on top of existing roles that controls
feature visibility and access. Capabilities follow an area.feature.action
taxonomy (~35 capabilities) with sensible defaults per role. Tenant admins
can customize via grant/revoke overrides stored in org settings JSONB.
Key changes:
- Add vice_president role to DB schema
- Backend: capability constants, resolution logic, CapabilityGuard (global),
@RequireCapability decorator on all 16 tenant controllers
- Frontend: permission hooks (useCanEdit, useHasCapability), CapabilityGate
component, sidebar filtering by capability, all 17 pages migrated from
useIsReadOnly to capability-based checks
- New admin UI: /settings/permissions matrix page for per-tenant role
customization with grant/revoke delta model
- GET /organizations/my-capabilities endpoint for capability refresh
- Validation of permissionOverrides in settings updates
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Dashboard Quick Stats:
- Create Capital Projects section with "Planned Capital Spend 2026"
- Fix Interest Earned YTD to pull from actual journal entries on
interest income accounts instead of unrealized investment gains
- Add Interest Earned YoY showing projected current year vs last year
actuals with percentage change badge
Monthly Actuals:
- Default to read-only view when actuals are already reconciled
- Show "Edit Actuals" button instead of "Save Actuals" for reconciled months
- Add confirmation modal warning that editing will void existing journal
entry before allowing edits
- New months without actuals open directly in edit mode
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add global WriteAccessGuard that blocks POST/PUT/PATCH/DELETE for viewer role
- Add @AllowViewer() decorator for endpoints viewers need (switch-org, intro-seen, AI recommendations)
- Add useIsReadOnly hook to auth store for frontend role checks
- Hide write UI (add/edit/delete/import buttons, inline editors) in all 13 data pages for viewers
- Disable inline NumberInputs on Budgets and Monthly Actuals pages for viewers
- Skip onboarding wizard for viewer role users
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove min={0} from NumberInput to allow negative actuals (refunds/corrections)
- Fix post() in journal-entries service: use id param directly instead of
RETURNING result which returns [rows, count] in TypeORM QueryRunner
- Handle negative amounts in saveActuals(): negative expense credits the
expense account, negative income debits the income account
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add spreadsheet-style Monthly Actuals page for entering monthly actuals
against budget with auto-generated journal entries and reconciliation flag.
Add file attachment support (PDF, images, spreadsheets) on journal entries
for receipts and invoices. Enhance Budget vs Actual report with month
filter dropdown. Add reconciled badge to Transactions page. Replace bcrypt
with bcryptjs to fix Docker cross-platform native binding issues.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>