Skip to main content

Documentation Index

Fetch the complete documentation index at: https://grantmaster.dev/llms.txt

Use this file to discover all available pages before exploring further.

Core Workflows

StatusUpdatedCovered File
🟢 Stable2026-04-14ServerGrantService.ts, ServerProjectService.ts, ServerComplianceService.ts, EventBus.ts

1. Grant Lifecycle (End-to-End)

This is the primary business flow of the system, taking a funding opportunity from discovery to close-out.

Steps & Technical Drivers

  • Trigger: User finds a GrantOpportunity and clicks “Add to Pipeline”.
  • Pipeline Stage Change: GrantService.updatePipelineStage updates the stage, history, and recalculates weighted probability.
  • Conversion: When a grant is “Won”, ServerActiveGrantServiceClass.convert() (in functions/src/api/services/ServerGrantService.ts) runs a composite transaction that:
    1. Creates an ActiveGrant document with award details.
    2. Moves the pipeline entry to the won stage.
    3. Looks up the pipeline entry to derive the grant title.
    4. Auto-creates a linked Project document via serverProjectService.create() with grantId, managerId, startDate/endDate, and budget derived from the award.
    5. Back-links the new projectId onto the ActiveGrant.
    6. Auto-provisions draft compliance policies from the opportunity’s complianceRequirements and grantorType via serverCompliancePolicyService.create() — scoped to the new project, with status: 'draft' and adoptionSource: 'grant_conversion'. Failures are non-fatal (Promise.allSettled).
    7. Emits GRANT_WON with { grantId, pipelineId, projectId } so downstream features (compliance, reports, notifications) receive the project link.
  • Client cache: useGrants.convertToActiveGrant invalidates utils.projects.list and utils.projects.stats in its onSuccess handler so the new project appears in the UI immediately.
  • Auditing: Every transition is logged via BaseService.logSuccess and emits an event to the EventBus.
See ADR #17 (Grant→Project Auto-Linking) and ADR #18 (Grant-Aware Compliance Policy Auto-Attach) in docs/overview/decision-log.md for the decision record.

2. Effort Tracking & Journals

Ensures personnel costs are accurately recorded and validated for grant compliance.
  • Trigger: User records time on a specific project.
  • Validation: Service layer checks if the hours are within reasonable bounds and if the project is active.
  • Integration: Journals are stored in the journals collection.
  • Reporting: Monthly rollups are generated for donor-specific reporting packs.

3. Notification Flow (Event → Novu → FCM)

Decoupled orchestration of user alerts.

Sequence:

  1. Event Emission: A service emits an event via EventBus.emit.
    • Example: EXPENSE_APPROVED.
  2. Listener: src/shared/notifications/portalEventService.ts (or similar) listens for the event.
  3. Novu Trigger: The listener calls the Novu API with the event payload and subscriber ID.
  4. Delivery: Novu sends a Push notification (via FCM), Email, or In-App alert based on the user’s preferences.

4. User Onboarding & RBAC

  • Invitation: Admin creates an invitation for a specific email and role.
  • Email: Novu sends the invitation link.
  • Acceptance: New user signs in via Firebase Auth; the system links their uid to the existing employee record.
  • Tenancy Binding: The user’s JWT is updated with organizationId claims (handled via Cloud Functions).

5. Report Generation (Grant-Contextual AI Narrative)

The reporting flow closes the MVP loop by generating donor-ready narratives backed by real operational data.

Sequence:

  1. Select type & project: User picks a report type and target project via ReportSelectionViewReportConfigureView.
  2. Compose financial context: The Reports container (src/features/reports/components/Reports.tsx) reads expenses and journalEntries from useExpenses() and useJournals(), then computes a ReportFinancialContext via useMemo:
    • totalExpenses, expensesByCategory, currency
    • budgetUtilization (derived from project budget)
    • totalJournalHours, journalHoursByProject
  3. Generate narrative: useReportGeneration({ projects, user, financialContext }) calls generateReportNarrative() in geminiForecast.ts. The financial context is formatted into the Gemini system prompt so the AI cites specific figures.
  4. Dev fallback: If no Gemini API key is present (import.meta.env.DEV && !hasUsableGeminiApiKey()), buildDevReportNarrative() produces a deterministic narrative that includes the financial overview when the context is populated.
  5. Persist & export: On confirmation, generateReport() stores the GeneratedReport in Firestore. Export uses useReportExport (PDF/Word/Excel).
  6. Events: GRANT_REPORT_SUBMITTED emits when the report is linked to an active grant.
See ADR #19 (Report Narrative Enrichment) in docs/overview/decision-log.md.

Maintenance

Update this document when:
  • Adding a new stage to the PipelineStage type.
  • Implementing a new background automation (e.g., AI-driven data extraction).
  • Changing the notification delivery provider.

Update Checklist

  1. Trace the flow from UI click to Firestore write.
  2. Identify all intermediate events emitted.
  3. Identify all downstream side effects (Audit logs, Notifications, Integrations).