Step-by-step guide covering act_runner installation, registration,
host execution mode configuration, systemd service setup, and
troubleshooting for the HOALedgerIQ production deployment workflow.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The health check used curl which is not installed on the prod server.
Replace with a dual approach:
1. Primary: check Docker's own container health status (already running
via docker-compose.prod.yml healthcheck with wget inside container)
2. Secondary: wget from host as fallback signal
Also add diagnostic logging (container status + recent backend logs)
before triggering rollback on health check failure.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The APPLIED_MIGRATIONS associative array triggered "unbound variable"
under set -u when empty (first run / seed-existing). Fix by initializing
with =() and using a safe helper function with ${:-} default syntax.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace bc-based floating point division with pure bash integer
arithmetic so the script works on minimal Ubuntu servers without
bc installed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add automated production deployment pipeline:
- scripts/deploy-prod.sh: Full deployment script with pre/post DB backups,
migration tracking via shared.schema_migrations table, health checks,
and automatic rollback on failure (restores DB, reverts code, rebuilds)
- .gitea/workflows/deploy.yml: Manual-trigger Gitea Actions workflow for
intentional production deployments with optional --seed-existing flag
- scripts/db-backup.sh: Add --yes/-y flag to skip interactive confirmation
prompts, enabling automated restore during rollback
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>
Users entering the full endpoint URL (e.g. https://openrouter.ai/api/v1/chat/completions)
caused a 404 because the code appended /chat/completions again. Now strips any trailing
/chat/completions before re-appending, and adds a hint in the UI.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a new admin-only feature that allows the platform owner to benchmark
the production AI model against up to 2 alternate models (any OpenAI-compatible
API) using real tenant data, without impacting users.
Backend:
- Shared AI caller utility (ai-caller.ts) for OpenAI-compatible endpoints
- Shadow AI module with service, controller, and 3 entities
- 6 admin API endpoints for model config CRUD, run trigger, and history
- Auto-creates shadow_ai_models, shadow_runs, shadow_run_results tables
- Exposes health-scores and investment-planning prompt builders for reuse
Frontend:
- New admin page at /admin/shadow-ai with 3 tabs:
- Model Configuration (production + 2 alternate slots)
- Run Comparison (tenant select, feature select, side-by-side results)
- History (filterable run log with detail drill-down)
- Full side-by-side output display with diff highlighting
- Sidebar navigation link for AI Benchmarking
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds a dedicated super admin page for managing idea submissions across
all tenants. Includes status summary cards, filterable/searchable table,
detail modal with status updates, and private admin notes for internal
tracking (sprint refs, thoughts, follow-ups). Notes are not visible to
tenant users.
- Database: admin_note column on shared.ideas (019 migration)
- Backend: PUT /admin/ideas/:id/note endpoint
- Frontend: AdminIdeasPage with table, filters, detail modal
- Sidebar: "Idea Submissions" nav link in admin sections
- Routing: /admin/ideas route under SuperAdminRoute guard
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds idea submission capability gated by a per-tenant feature flag.
Super admins can enable/disable ideation for specific tenants via the
admin tenant detail drawer. Users see a lightbulb icon in the header
when enabled, opening a modal to submit ideas (title + description).
Ideas are stored in shared schema for cross-tenant backlog querying.
- Database: shared.ideas table (018-ideas.sql migration)
- Backend: Ideas NestJS module (entity, service, controller)
- Admin API: GET /admin/ideas, PUT /admin/ideas/:id/status,
PUT /admin/organizations/:id/settings
- Frontend: IdeaModal component, lightbulb ActionIcon in header
- Admin UI: Feature Toggles card with ideation Switch in drawer
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remaining life years is documentation-only reference info. The board's
planned project date is the authoritative timeline for urgency assessment.
Updates data gathering, prompt construction, and system instructions to
base all urgency on target_year/target_month instead of remaining_life_years.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move useMemo hook above early returns to satisfy React Rules of Hooks,
fixing blank screen when navigating to scenario detail. Also re-fetch
scenario after projection updates so auto-renew renewal records appear
automatically without requiring manual navigation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Lock InvestmentTimeline and ProjectionChart to shared X axis range
- Auto-create renewal scenario_investments records when auto_renew is true
- Add fund transfer mechanism between asset accounts with journal entries
- Add Capital Planning Report (5-year forecast grouped by category)
- Add Upcoming Investment Activities dashboard card (maturities + planned purchases)
- Bump version to 2026.3.24
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Onboarding wizard: add Reserve Account step between Operating and Assessments,
redirect to Budget Planning on completion
- Dashboard: health score pending state shows clickable links to set up missing items
- Projects/Vendors: rich empty-state wizard screens with real-world examples and CTAs
- Investment Planning: auto-refresh AI recommendations when empty or stale (>30 days)
- Hide Invoices and Payments menus (see PARKING-LOT.md for re-enablement)
- Send welcome email via Resend when new members are added to a tenant
- Enforce 5-member limit for Starter/Standard/Professional plans (Enterprise unlimited)
- Cash flow forecast: only mark months as "Actual" when journal entries exist,
fixing the issue where months without data showed as actuals
- Bump version to 2026.3.19
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix "Manage Billing" button error for trial orgs without Stripe customer;
add fallback to retrieve customer from subscription, show helpful message
for trial users, and surface real error messages in the UI
- Add "Balance As-Of Date" field to onboarding wizard so opening balance
journal entries use the correct statement date instead of today
- Add "Total Unit Count" field to onboarding wizard assessment group step
so cash flow projections work immediately
- Remove broken budget upload step from onboarding wizard (was using legacy
budgets endpoint); replace with guidance to use Budget Planning page
- Replace bare "No budget plan lines" text with rich onboarding-style card
featuring download template and upload CSV action buttons
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Interactive CLI for managing test organizations, users, and tenant schemas.
Supports list, delete-org, delete-user, purge-all, and reseed commands
with dry-run mode and safety guards for platform owner protection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add monthly/annual billing toggle with 25% annual discount on pricing page
- Implement 14-day no-card free trial (server-side Stripe subscription creation)
- Enable upgrade/downgrade via Stripe Customer Portal
- Add admin-initiated ACH/invoice billing for enterprise customers
- Add billing card to Settings page with plan info and Manage Billing button
- Handle past_due status with read-only grace period access
- Add trial ending and trial expired email templates
- Add DB migration for billing_interval and collection_method columns
- Update ONBOARDING-AND-AUTH.md documentation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the 4 summary cards from the Cash Flow page as they don't
properly represent the story over time. Increase gradient opacity
on stacked area charts (cash flow and investment scenarios) from
0.3-0.4/0-0.05 to 0.6/0.15 for better visual shading.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the stubbed email service with Resend API integration.
Emails are sent with branded HTML templates including activation,
welcome, payment failed, member invite, and password reset flows.
- Install resend@6.9.4 in backend
- Rewrite EmailService with Resend SDK + graceful fallback to
stub mode when API key is not configured
- Add branded HTML email template with CTA buttons, preheader
text, and fallback URL for all email types
- Add reply-to support (sales@hoaledgeriq.com in production)
- Track send status (sent/failed) in shared.email_log metadata
- Add RESEND_API_KEY, RESEND_FROM_ADDRESS, RESEND_REPLY_TO env
vars to both docker-compose.yml and docker-compose.prod.yml
- Add sendPasswordResetEmail() method for future use
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
APP_URL was never passed to the backend container, causing Stripe
checkout success_url to redirect to http://localhost instead of the
production domain. The prod overlay also completely replaced the base
environment block, dropping all Stripe, SSO, WebAuthn, and invite
token variables.
- Add APP_URL to base docker-compose.yml (default: http://localhost)
- Add all missing vars to docker-compose.prod.yml with production
defaults (app.hoaledgeriq.com)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enterprise plan no longer displays a fixed price. Instead it shows
"Request Quote" and the CTA opens the interest form on hoaledgeriq.com
in a new tab to capture leads for custom quotes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- L2: Add server_tokens off to nginx configs to hide version
- M1: Add X-Frame-Options, X-Content-Type-Options, Referrer-Policy,
Permissions-Policy headers to all nginx routes
- L3: Add global NoCacheInterceptor (Cache-Control: no-store) on all
API responses to prevent caching of sensitive financial data
- C1: Disable open registration by default (ALLOW_OPEN_REGISTRATION env)
- H3: Add logout endpoint with correct HTTP 200 status code
- M2: Implement full password reset flow (forgot-password, reset-password,
change-password) with hashed tokens, 15-min expiry, single-use
- Reduce JWT access token expiry from 24h to 1h
- Add EmailService stub (logs to shared.email_log)
- Add DB migration 016 for password_reset_tokens table
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove redundant Settings link from sidebar (accessible via user menu)
- Move Transactions section below Board Reference for better grouping
- Promote Investment Scenarios to its own top-level sidebar item
- Add Compact View preference with tighter spacing theme
- Wire compact theme into MantineProvider with dynamic switching
- Enable Compact View toggle in both Preferences and Settings pages
- Install missing @simplewebauthn/browser package (lock file update)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Covers Stripe billing flow, provisioning pipeline, activation magic links,
onboarding checklist, refresh tokens, MFA, SSO, passkeys, env var reference,
manual intervention checklist, and full API endpoint reference.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>