Documentation Index
Fetch the complete documentation index at: https://grantmaster.dev/llms.txt
Use this file to discover all available pages before exploring further.
Complete Data Model Reference
Single-read reference for the entire GrantMaster data model. Covers every Firestore collection, entity schema, enum, validation rule, relationship, and query pattern in one document.
See also:
Table of Contents
- Multi-Tenancy Model
- Collection Inventory (71 collections)
- Aggregate 1: Identity & Access
- Aggregate 2: Grant Lifecycle
- Aggregate 3: Project Engine
- Aggregate 4: Finance
- Aggregate 5: Time Tracking
- Aggregate 6: Compliance & Audit
- Aggregate 7: Relations / CRM
- Aggregate 8: Documents & Knowledge
- Aggregate 9: People & HR
- Aggregate 10: Platform & Extensions
- Aggregate 11: Partnerships & Credits
- Cross-Aggregate Relationships
- Subscription Tiers & Feature Entitlements
- Enum Catalog (120+ enums)
- Validation Rules Summary
- Denormalization Patterns
- Foreign Key Conventions
- Firestore Index Requirements
- Collection Name Gotchas
1. Multi-Tenancy Model
Every entity except global taxonomies belongs to exactly one Organization via the TenantScoped base interface:
interface TenantScoped {
organizationId: string; // Required on every write
createdAt: Timestamp;
updatedAt: Timestamp;
}
Rules:
- Strict Isolation — no entity can belong to more than one Organization
- Scoping — all Firestore queries must include
organizationId
- Exceptions —
foundations is a shared library readable by all orgs; write access is platform-admin only
- Cross-Tenant References — prohibited at both Service and Firestore Security Rules layers
- BaseService enforcement —
organizationId is validated via Zod schema before any write
2. Collection Inventory
Root Collections (Tenant-Scoped)
| # | Collection | Code Alias | TypeScript Type | Domain |
|---|
| 1 | employees | users | User | Identity |
| 2 | projects | projects | Project | Projects |
| 3 | journals | journals | JournalEntry | Time Tracking |
| 4 | expenses | expenses | Expense | Finance |
| 5 | journalSubmissions | journalSubmissions | JournalSubmission | Time Tracking |
| 6 | notifications | notifications | Notification | Platform |
| 7 | referrals | referrals | Referral | Partnerships |
| 8 | invitations | invitations | Invitation | Identity |
| 9 | grantApplications | grantApplications | GrantApplication | Grants |
| 10 | grantPipeline | grantPipeline | GrantPipelineEntry | Grants |
| 11 | activeGrants | activeGrants | ActiveGrant | Grants |
| 12 | expenseAllocations | expenseAllocations | ExpenseAllocation | Finance |
| 13 | auditLogs | auditLogs | AuditLogEntry | Compliance |
| 14 | securityEvents | securityEvents | SecurityEvent | Identity |
| 15 | systemEvents | systemEvents | Record<string, unknown> | Platform |
| 16 | deadlines | deadlines | Deadline | Projects |
| 17 | complianceSummaries | complianceSummaries | ComplianceSummary | Compliance |
| 18 | complianceAlerts | complianceAlerts | ComplianceAlert | Compliance |
Rule Engine Collections
| # | Collection | Code Alias | TypeScript Type | Scope |
|---|
| 19 | compliance_rules | complianceRules | CompliancePolicy | Tenant |
| 20 | rule_templates | ruleTemplates | RuleTemplate | Platform |
| 21 | grant_rules | grantRules | GrantRule | Tenant |
| 22 | rule_violations | ruleViolations | RuleViolation | Tenant |
| 23 | rule_analytics | ruleAnalytics | RulePerformanceMetrics | Tenant |
| 24 | platform_rules | platformRules | PlatformPolicy | Platform |
| 25 | tenant_donor_configs | tenantDonorConfigs | TenantDonorConfig | Tenant |
Relations & CRM Collections
| # | Collection | Code Alias | TypeScript Type |
|---|
| 26 | contacts | contacts | Contact |
| 27 | interactions | interactions | Interaction |
| 28 | contactViews | contactViews | ContactView |
| 29 | foundations | foundations | TaxonomyItem (Platform) |
| 30 | grantorInteractions | grantorInteractions | GrantorInteraction |
| 31 | reportingDeadlines | reportingDeadlines | ReportingDeadline |
| 32 | grantorRuleConflicts | grantorRuleConflicts | GrantorRuleConflict |
| 33 | hubspotConfigs | hubspotConfigs | HubSpotConfig |
| 34 | hubspotSyncLogs | hubspotSyncLogs | HubSpotSyncLog |
Stakeholder Portal Collections
| # | Collection | TypeScript Type |
|---|
| 35 | portalTokens | PortalToken |
| 36 | portalSessions | PortalSession |
| 37 | portalComments | PortalComment |
| 38 | portalReportAcknowledgments | PortalReportAcknowledgment |
Credits & Gamification Collections
| # | Collection | TypeScript Type | Scope |
|---|
| 39 | missionCredits | MissionCredit | Per-user wallet |
| 40 | creditTransactions | CreditTransaction | Tenant |
| 41 | creditRedemptions | CreditRedemption | Tenant |
| 42 | badges | Badge | Tenant |
| 43 | gamificationPreferences | GamificationPreferences | Per-user |
| 44 | campaigns | Campaign | Platform / Tenant |
Impact / M&E Collections
| # | Collection | TypeScript Type | Scope |
|---|
| 45 | meIndicators | MEIndicator | Tenant + Project |
| 46 | meIndicatorTargets | MEIndicatorTarget | Tenant + Project |
| 47 | meDataPoints | MEIndicatorDataPoint | Tenant + Project |
| 48 | meDashboardConfigs | MEDashboardConfig | Tenant + Project |
| 49 | meKoboConnections | MEKoboConnection | Tenant |
| 50 | meKoboFormLinks | MEKoboFormLink | Tenant + Project |
| 51 | meIndicatorSummaries | MEIndicatorSummary | Tenant (read-only) |
| 52 | meGrantIndicatorConfigs | MEGrantIndicatorConfig | Tenant |
| 53 | meAISuggestions | AIIndicatorSuggestion | Tenant + Project |
| 54 | meWorkflowRules | MEWorkflowRule | Tenant |
| 55 | meWorkflowExecutionLogs | MEWorkflowExecutionLog | Tenant |
| 56 | meSettings | MEOrgSettings | Tenant (1 doc/org) |
Taxonomy Collections
| # | Collection | TypeScript Type |
|---|
| 57 | budgetCategories | BudgetCategory |
| 58 | missionPillars | MissionPillar |
| 59 | donors | TaxonomyItem |
| # | Collection | TypeScript Type | Scope |
|---|
| 60 | imuserationSessions | ImuserationSession | Platform |
| 61 | auditorAccessGrants | AuditorAccessGrant | Tenant |
| 62 | configSnapshots | ConfigurationSnapshot | Tenant |
| 63 | auditExportJobs | AuditExportJob | Tenant |
| 64 | platformMetrics | PlatformMetrics | Platform |
| 65 | userGrowthMetrics | UserGrowthMetrics | Platform |
| 66 | retentionCohorts | RetentionCohort | Platform |
| 67 | organizationMetrics | OrganizationMetrics | Platform |
| 68 | auditorReports | AuditorReport | Tenant |
| # | Collection | TypeScript Type |
|---|
| 69 | grantOpportunities | GrantOpportunity |
| 70 | organizations | Organization |
| 71 | config | mixed |
Organization Subcollections
| Path | TypeScript Type | Purpose |
|---|
organizations/{orgId}/moduleInstallations/{moduleId} | ModuleInstallation | Extension install state |
organizations/{orgId}/config/appSettings | AppSettings | Org-specific settings |
organizations/{orgId}/apiKeys/ | ApiKey | Scoped API keys |
organizations/{orgId}/webhooks/ | Webhook | Integration webhooks |
organizations/{orgId}/integrations/ | Integration | Third-party configs |
organizations/{orgId}/onboarding/ | OnboardingState | Wizard progress |
Project Subcollections
| Path | TypeScript Type | Purpose |
|---|
projects/{id}/documentChunks/ | DocumentChunk | RAG chunks |
projects/{id}/complianceRules/ | ProjectComplianceRule | Project-specific rules |
projects/{id}/budgetForecasts/ | BudgetForecast | AI projections |
projects/{id}/budgetAlerts/ | BudgetAlert | Threshold alerts |
Pipeline Subcollections
| Path | TypeScript Type | Purpose |
|---|
grantPipeline/{id}/tasks/ | PipelineTask | Preparation tasks |
grantPipeline/{id}/documents/ | PipelineDocument | Application docs |
grantPipeline/{id}/activities/ | PipelineActivity | Activity log |
3. Identity & Access
Collections: organizations, employees, invitations, sessions, apiKeys, securityEvents
Organization
The root tenant. Users belong to exactly one organization.
| Field | Type | Notes |
|---|
id | string | Firestore document ID |
name | string | Display name |
slug | string | URL-safe identifier |
subscriptionTier | SubscriptionTier | free | starter | growth | enterprise |
settings | OrganizationSettings | Locale, branding, feature flags |
classification | TenantClassification | NGO type, sector, jurisdiction |
missionPillars | string[] | Tags for mission-alignment scoring |
TenantClassification
6-dimensional profiling system for NGO tenants. Defined in src/schemas/classification.schema.ts.
| Dimension | Enum Values |
|---|
organizationalRole | ngo, charity, social_enterprise, cooperative, foundation, government_agency, academic_institution, other |
primarySector | education, health, environment, human_rights, poverty, agriculture, technology, arts_culture, disaster_relief, water_sanitation, gender_equality, child_welfare, elderly_care, disability, housing, legal_aid, food_security, other |
geographicScope | local, regional, national, international, global |
budgetTier | micro (<50k), small (50k-500k), medium (500k-5M), large (5M-50M), enterprise (>50M) |
operationalModel | direct_service, grant_making, capacity_building, advocacy, research, hybrid |
jurisdiction | NL, UK, OTHER (discriminated union with jurisdiction-specific legal/fiscal schemas) |
Jurisdiction-specific legal/fiscal schemas (discriminated union):
- Netherlands:
STICHTING, VERENIGING, COOPERATIE, BV, OTHER legal forms; ANBI, SBBI, CBF recognition flags; KvK number, RSIN
- UK:
CIO, CLG, UNINCORPORATED, CIC, OTHER legal forms; charity number, HMRC, VAT flags
- Generic: Arbitrary jurisdiction and legal form description fields
User
Stored in the employees Firestore collection.
| Field | Type | Notes |
|---|
id | string | Firebase Auth UID |
email | string | |
firstName, lastName | string | |
role | SystemRole | SUPER_ADMIN | ADMIN | MANAGER | MEMBER | AUDITOR |
status | UserStatus | active | invited | suspended | deactivated |
staffType | StaffType | 12 types (see HR section) |
department | string | |
jobTitle | string | |
mfaEnabled | boolean | |
referralCode | string | null | Set when user joins via referral |
Invitation
| Field | Type |
|---|
email | string |
role | SystemRole |
token | string (signed JWT) |
status | pending | accepted | expired | revoked |
expiresAt | Timestamp (7 days) |
Session
| Field | Type |
|---|
userId | string |
deviceInfo | DeviceInfo (browser/OS fingerprint) |
lastActiveAt | Timestamp |
expiresAt | Timestamp |
SecurityEvent
| Field | Type |
|---|
userId | string |
type | SecurityEventType (login | logout | failed_login | mfa_enrolled | password_changed | ...) |
ipAddress | string |
success | boolean |
metadata | Record<string, unknown> |
ApiKey
| Field | Type |
|---|
userId | string (owner) |
name | string |
keyHash | string (SHA-256) |
prefix | string (first 8 chars, shown in UI) |
scopes | ApiKeyScope[] |
expiresAt | Timestamp | null |
revokedAt | Timestamp | null |
4. Grant Lifecycle
Collections: grantOpportunities, grantPipeline, grantApplications, activeGrants, grantReports
GrantOpportunity
| Field | Type | Notes |
|---|
title | string | |
grantor | string | Funder name |
fundingRange | { min, max } | |
deadline | Timestamp | |
eligibilityCriteria | string[] | |
source | 'platform' | 'manual' | |
matchScore | number | AI-computed 0–100 |
GrantPipelineEntry
| Field | Type | Notes |
|---|
opportunityId | string | FK → grantOpportunities |
stage | PipelineStage | prospect | preparing | submitted | under_review | won | lost |
probability | number | 0–100 |
requestedAmount | number | |
assignedTo | string[] | User IDs |
GrantApplication
| Field | Type | Notes |
|---|
pipelineId | string | FK → grantPipeline |
status | ApplicationStatus | draft | submitted | under_review | awarded | rejected + 4 more |
narrative | string | AI-assisted text |
attachments | string[] | Storage URLs |
ActiveGrant
| Field | Type | Notes |
|---|
applicationId | string | FK → grantApplications |
awardedAmount | number | |
currency | string | ISO 4217 |
disbursementSchedule | Disbursement[] | Embedded: tranche dates + amounts |
reportingRequirements | ReportingRequirement[] | Deadlines and report types |
projectIds | string[] | FK → projects (N:M) |
status | 'active' | 'completed' | 'suspended' | |
GrantReport
| Field | Type | Notes |
|---|
grantId | string | FK → activeGrants |
period | { from, to } | Reporting period |
status | 'draft' | 'submitted' | 'approved' | |
5. Project Engine
Collections: projects, budgetItems, milestones, tasks, deadlines
Project
| Field | Type | Notes |
|---|
name | string | |
status | ProjectStatus | planning | active | on_hold | completed | archived |
phase | ProjectPhase | initiation | planning | execution | monitoring | closure |
budget | number | Total budget |
currency | string | |
startDate / endDate | Timestamp | |
grantIds | string[] | FK → activeGrants (N:M) |
teamMemberIds | string[] | FK → employees |
managerId | string | FK → employees |
missionPillars | string[] | |
templateId | string | null | If created from template |
BudgetItem
| Field | Type | Notes |
|---|
projectId | string | FK → projects |
category | BudgetCategory | Personnel | Operations | Travel | Equipment | Consultancy | Overhead |
allocatedAmount | number | |
spentAmount | number | Denormalized |
grantId | string | null | Funding source |
Milestone
| Field | Type |
|---|
projectId | string |
title | string |
dueDate | Timestamp |
status | pending | in_progress | completed |
completionPercentage | number |
Task
| Field | Type |
|---|
milestoneId | string |
projectId | string (denormalized) |
assigneeId | string |
status | todo | in_progress | blocked | done |
priority | low | medium | high | urgent |
Deadline
| Field | Type |
|---|
projectId | string |
type | reporting | submission | payment | milestone |
dueDate | Timestamp |
completed | boolean |
6. Finance
Collections: expenses, invoices, receipts
Expense
| Field | Type | Notes |
|---|
amount | number | |
currency | string | |
category | ExpenseCategory | 7 categories |
projectId | string | FK → projects |
grantId | string | null | FK → activeGrants (primary grant) |
submittedBy | string | FK → employees |
status | ExpenseStatus | draft | pending | approved | rejected | paid |
allocations | ExpenseAllocation[] | Embedded: split across grants |
receiptUrl | string | null | Firebase Storage |
ExpenseAllocation (embedded)
| Field | Type | Constraint |
|---|
grantId | string | FK → activeGrants |
amount | number | |
percentage | number | Sum must = 100 (95-105% tolerance) |
Invoice
| Field | Type |
|---|
projectId | string |
vendorName | string |
amount | number |
dueDate | Timestamp |
status | unpaid | paid | overdue |
BudgetCategory Enum
Personnel · Operations · Travel · Equipment · Consultancy · Overhead
7. Time Tracking
Collections: journals (JournalEntry), journalSubmissions (JournalSubmission)
JournalEntry
Stored in the journals collection.
| Field | Type | Notes |
|---|
userId | string | FK → employees |
projectId | string | FK → projects |
date | string | ISO YYYY-MM-DD |
hours | number | 0–24 |
description | string | Activity description |
entryType | EntryType | work | vacation | sick_leave | parental_leave | study_leave |
submissionId | string | null | FK → journalSubmissions |
grantId | string | null | Direct grant attribution |
auditFlag | AuditFlag | high | medium | low |
locked | boolean | Locked entries cannot be edited |
leaveDetails | LeaveDetails | null | Required when entryType is a leave type |
isVolunteerTime | boolean | |
inKindValue | number | null | Monetary equivalent |
JournalSubmission
Monthly summary submitted for manager approval. Stored in journalSubmissions.
| Field | Type | Notes |
|---|
userId | string | Submitter |
month | string | YYYY-MM |
status | SubmissionStatus | Draft | Submitted | Approved | Rejected | Regeneration Needed |
totalHours | number | Denormalized sum |
approvedBy | string | null | |
entryIds | string[] | FKs → journals |
aiGenerationMetadata | AIGenerationMetadata | null | If AI-generated |
AI Journal Generation Pipeline
11-stage processing pipeline defined in journalGenerationJobSchema:
validate_input → load_platform_policy → load_history → load_project_context →
retrieve_documents → merge_activity_data → apply_compliance_rules →
draft_cover → draft_entries → self_review → finalize_artifact
TimeOffRequest
| Field | Type |
|---|
userId | string |
type | vacation | sick | personal | bereavement | parental | unpaid | other |
status | draft | pending | approved | rejected | cancelled | taken |
startDate / endDate | string |
totalDays | number |
approvedBy | string | null |
TimeOffBalance
| Field | Type |
|---|
userId | string |
year | number |
timeOffType | TimeOffType |
totalAllotted | number |
usedDays | number |
pendingDays | number |
carriedForwardDays | number |
availableDays | number (computed: totalAllotted - used - pending + carriedForward) |
8. Compliance & Audit
Collections: compliance_rules, complianceAlerts, auditLogs
ComplianceRule
| Field | Type |
|---|
name | string |
domain | financial | operational | legal | ... |
checkType | threshold | deadline | document | approval |
severity | low | medium | high | critical | info |
threshold | number | null |
enabled | boolean |
ComplianceAlert
| Field | Type |
|---|
ruleId | string |
entityType / entityId | string |
status | new | acknowledged | investigating | resolved | dismissed |
assignedTo | string | null |
AuditLog
Append-only. 80+ AuditAction constants.
| Field | Type |
|---|
action | AuditAction |
userId | string |
resourceType / resourceId | string |
organizationId | string |
result | success | failure | partial |
metadata | Record<string, unknown> (before/after diffs) |
ipAddress | string | null |
timestamp | Timestamp |
9. Relations / CRM
Collections: foundations, contacts, grantorInteractions, reportingDeadlines
Foundation
Shared library of grant-making organizations (platform-scoped, not tenant-scoped).
| Field | Type |
|---|
name | string |
type | foundation | government | corporate | bilateral |
focusAreas | string[] |
geographicFocus | string[] |
totalGrantsValue | number |
| Field | Type |
|---|
type | funder | partner | vendor | consultant | beneficiary | stakeholder | other |
firstName / lastName | string |
email | string |
foundationId | string | null |
relationshipStatus | active | inactive | prospect | archived |
segments | string[] |
hubspotContactId | string | null |
Interaction
| Field | Type |
|---|
contactId | string |
type | meeting | call | email | video_call | event | note |
date | Timestamp |
summary | string |
followUpDate | Timestamp | null |
GrantorRelationship
| Field | Type |
|---|
foundationId | string |
engagementScore | number (0–100) |
engagementLevel | low | medium | high | champion |
deadlines | GrantorDeadline[] (embedded) |
10. Documents & Knowledge
Collections: documents, documentFolders
DocumentFolder
| Field | Type | Notes |
|---|
name | string | |
parentId | string | null | Self-referencing tree |
path | string[] | Ancestor IDs (for breadcrumbs + subtree queries) |
Document
| Field | Type | Notes |
|---|
folderId | string | null | |
name | string | |
storageUrl | string | Firebase Storage |
mimeType | string | |
sizeBytes | number | |
status | processing | indexed | failed | RAG indexing state |
projectId / grantId | string | null | Optional scoping |
Document Brain Types
47 specialized document types in documents-brain.schema.ts:
- 8 compliance areas, 4 sensitivity levels, 6 approval statuses
- 10 template categories, system folder keys
RAG Pipeline
7-stage document processing:
upload → text_extraction → chunking → embedding → metadata_extraction → indexing → complete
Each document produces DocumentChunk entries with vector embeddings stored for semantic search.
11. People & HR
Collections: employees (extended User), timeOffRequests, securityEvents
StaffType Enum (12 types)
full_time · part_time · contractor · intern · volunteer · consultant · temporary · fellow · board_member · advisor · secondee · other
ContractType Enum
permanent · fixed_term · freelance · zero_hours · internship
Extended User Fields
| Field | Type |
|---|
staffType | StaffType |
contractType | ContractType |
hourlyRate | number | null |
emergencyContact | EmergencyContact | null |
fundingAllocations | FundingAllocation[] |
calendarIntegration | CalendarConfig | null |
Collections: organizations/{orgId}/moduleInstallations, widgetDefinitions, widgetAssignments
ModuleInstallation
| Field | Type |
|---|
moduleId | string (matches manifest ID) |
version | string (semver) |
status | trialing | active | inactive | suspended | expired |
installedBy | string |
config | Record<string, unknown> |
Notification
| Field | Type |
|---|
userId | string |
type | 18 notification types (journal, expense, project, compliance, system, etc.) |
channel | email | push | in_app | sms |
status | pending | sent | delivered | failed | read |
priority | 4 levels |
13. Partnerships & Credits
Collections: partnerOrganizations, referrals, missionCredits, creditTransactions, subscriptions
PartnerOrganization
| Field | Type |
|---|
name | string |
revenueShareRate | number (0.10–0.20) |
status | active | suspended | pending | inactive | terminated |
referralCode | string (PARTNER_{PREFIX}_{RANDOM}) |
MissionCredit
One document per org (document ID = organizationId).
| Field | Type |
|---|
balance | number |
lifetimeEarned / lifetimeSpent | number |
CreditTransaction
| Field | Type |
|---|
amount | number (positive = credit, negative = debit) |
type | referral_award | subscription_discount | manual_adjustment |
referenceId | string | null |
Subscription
| Field | Type |
|---|
stripeSubscriptionId | string |
tier | SubscriptionTier |
status | active | past_due | canceled | trialing | paused | suspended |
billingCycle | monthly | annual |
seats | number |
Agent Credit System
Reserve → Consume → Release pattern. See credit-system-architecture.md for the full flow.
| Field on Organization | Type |
|---|
subscription.features.agentCreditsPerMonth | number (monthly allocation) |
usageMetrics.agentCreditsUsedThisMonth | number (consumed) |
agentCreditsReserved | number (active reservations) |
agentCreditsPurchased | number (one-time top-ups) |
| Available = (monthly + purchased) - used - reserved | |
14. Cross-Aggregate Relationships
15. Subscription Tiers & Feature Entitlements
Source: src/config/entitlements.ts
Tier Limits
| Limit | Potential | Professional | Ultimate |
|---|
| Max Users | 3 | 15 | 25 |
| Max Projects | 10 | 50 | Unlimited |
| Max Storage | 5 GB | 50 GB | Unlimited |
| API Calls/Month | 0 | 10,000 | Unlimited |
| AI Generations/Month | 50 | 200 | Unlimited |
| Exports/Month | 50 | Unlimited | Unlimited |
| API Calls/Hour | 0 | 1,000 | 10,000 |
| AI Generations/Hour | 10 | 50 | Unlimited |
Agent-Specific Limits
| Limit | Potential | Professional | Ultimate |
|---|
| Agent Credits/Month | 100 | 1,000 | 10,000 |
| Concurrent Agents | 1 | 3 | 10 |
| Steps/Run | 5 | 20 | Unlimited |
| Tokens/Run | 50,000 | 200,000 | Unlimited |
| Runs/Month | 10 | 200 | Unlimited |
| Runs/Hour | 3 | 20 | 100 |
Feature Gates (29 features)
| Category | Features | Min Tier |
|---|
| Basic | Journals, Reports, Projects, Team Collaboration | Potential |
| AI | AI Generation, AI Journal, AI Report, AI Audit Defense, AI Grant Assistant | Professional |
| Professional | API Access, Advanced Reports, Custom Exports, Budget Forecasting, Expense Mgmt, Grant Discovery | Professional |
| Enterprise | SSO, SAML, Audit Logs, Custom Integrations, Branding, Multi-Currency, Compliance Monitoring | Ultimate |
| Storage/RAG | Document Uploads, Advanced Storage, RAG Search, Semantic Search | Varies |
| Agents | Basic, Multi-Step, Autonomous, Orchestration | Professional–Ultimate |
| Impact | Impact Module (M&E) | Professional |
16. Enum Catalog
Status Enums
| Enum | Values | Used By |
|---|
ExpenseStatus | draft, pending, approved, rejected, paid | Expense |
SubmissionStatus | Draft, Submitted, Approved, Rejected, Regeneration Needed | JournalSubmission |
ApplicationStatus | draft, submitted, under_review, awarded, rejected + 4 more | GrantApplication |
PipelineStage | prospect, preparing, submitted, under_review, won, lost | GrantPipelineEntry |
ProjectStatus | planning, active, on_hold, completed, archived | Project |
ProjectPhase | initiation, planning, execution, monitoring, closure | Project |
UserStatus | active, invited, suspended, deactivated | User |
InviteStatus | pending, accepted, expired, revoked | Invitation |
TimeOffStatus | draft, pending, approved, rejected, cancelled, taken | TimeOffRequest |
ModuleInstallStatus | trialing, active, inactive, suspended, expired | ModuleInstallation |
ComplianceAlertStatus | new, acknowledged, investigating, resolved, dismissed | ComplianceAlert |
AgentRunStatus | 7 statuses | AgentRun |
LeadStatus | new, contacted, qualified, proposal, negotiation, won, lost | Lead |
OpportunityStage | prospecting, qualification, proposal, negotiation, closed_won, closed_lost | Opportunity |
NotificationStatus | pending, sent, delivered, failed, read | Notification |
ReportStatus | draft, generating, completed, failed, archived | Report |
PartnerStatus | pending, active, inactive, suspended, terminated | PartnerOrganization |
Type/Category Enums
| Enum | Values | Used By |
|---|
ExpenseCategory | Personnel, Operations, Travel, Equipment, Consultancy, Overhead + 1 | Expense |
BudgetCategory | Same 6 categories | BudgetItem |
EntryType | work, vacation, sick_leave, parental_leave, study_leave | JournalEntry |
TimeOffType | vacation, sick, personal, bereavement, parental, unpaid, other | TimeOffRequest |
StaffType | 12 types (see HR section) | User |
ContractType | permanent, fixed_term, freelance, zero_hours, internship | User |
ContactType | funder, partner, vendor, consultant, beneficiary, stakeholder, other | Contact |
CommunicationType | meeting, call, email, video_call, event, note | Interaction |
DocumentType | 8 types | Document |
ReportType | project, expense, journal, budget, compliance, audit, grant, custom | Report |
DeadlineType | reporting, submission, payment, milestone | Deadline |
SystemRole | SUPER_ADMIN, ADMIN, MANAGER, MEMBER, AUDITOR | User |
SubscriptionTier | free, starter, growth, enterprise | Organization |
NotificationType | 18 types | Notification |
Severity & Priority Enums
| Enum | Values |
|---|
ComplianceSeverity | info, low, medium, high, critical |
EventSeverity | INFO, WARNING, ERROR, CRITICAL |
TaskPriority | low, medium, high, urgent |
AuditFlag | low, medium, high |
NotificationPriority | 4 levels |
Gamification Enums
| Enum | Values |
|---|
BadgeTier | bronze, silver, gold, platinum, diamond |
PointEventType | journal_submitted, journal_approved, project_created, expense_submitted, report_generated, milestone_completed, goal_achieved, streak_maintained, profile_completed, training_completed, badge_earned |
ChallengeType | individual, team, organization |
17. Validation Rules Summary
These Zod .refine() rules enforce business constraints at the schema level:
| Domain | Rule | Constraint |
|---|
| Expense | Allocation sum | sum(allocations[].percentage) must be 95–105% |
| Expense | Receipt requirement | Certain categories require receiptUrl |
| Journal | Hours range | 0–24 per entry |
| Journal | Locked immutability | Locked entries cannot be edited |
| Journal | Leave details | Leave-type entries must have leaveDetails |
| Journal | Future date | Entry date cannot be in the future |
| Submission | Submitted state | status=Submitted requires submittedAt |
| Submission | Approved state | status=Approved requires reviewedBy |
| Invoice | Date ordering | issueDate ≤ dueDate |
| Invoice | Paid state | status=paid requires paidAt |
| Invoice | Arithmetic | subtotal + tax = total |
| Subscription | Date ordering | startDate ≤ currentPeriodStart < currentPeriodEnd |
| Classification | Sector uniqueness | secondarySectors cannot include primarySector |
| Classification | Foundation year | 1800 – current year |
| Classification | SDG limit | Max 5 SDGs |
| TimeOff | Date ordering | startDate ≤ endDate |
| TimeOff | Approved state | Requires approvedBy |
| TimeOff | Rejected state | Requires rejectionReason |
| TimeOff | Balance formula | available = totalAllotted - used - pending + carriedForward |
| TimeOff | Overdraft guard | used + pending ≤ total + carriedForward |
| Accrual | Method validation | Accrual method accrued requires accrualRate |
| Project | Date ordering | startDate ≤ endDate |
| Organization | Suspension | Suspended orgs require suspensionReason |
| Generation Job | Completion | Completed jobs must have artifact |
| Timer | Future guard | startTime cannot be in future |
| Report | Completion | Completed reports require completedAt |
| Report | Failure | Failed reports require errorMessage |
| Gamification | Points formula | totalPoints = availablePoints + redeemedPoints |
| Gamification | Points calc | basePoints * multiplier + bonusPoints (±0.1% tolerance) |
| Feature Flags | Partial rollout | Not 0/100 percentage only for testing status flags |
18. Denormalization Patterns
| Denormalized Field | Lives On | Source Of Truth | Sync Mechanism |
|---|
project.grantIds[] | projects | activeGrant.projectIds[] | Co-write by grantService + projectService |
activeGrant.projectIds[] | activeGrants | project.grantIds[] | Co-write |
expense.grantId | expenses | allocations[0].grantId | Convenience field set on write |
journalSubmission.totalHours | journalSubmissions | Sum of journal entries | journalService.submitMonth() |
journalSubmission.entryIds[] | journalSubmissions | Entries where submissionId == id | journalService.submitMonth() |
documentFolder.path[] | documentFolders | Parent chain traversal | Computed on write |
contactSegment.memberCount | contactSegments | Contact count matching criteria | Scheduled evaluation |
grantorRelationship.engagementLevel | grantorRelationships | calculateEngagementScore() | Updated on score change |
task.projectId | tasks | milestone.projectId | Copied from milestone on create |
19. Foreign Key Conventions
Firestore has no native joins. GrantMaster uses four reference patterns:
| Pattern | When Used | Example |
|---|
| String ID reference | 1:1 or N:1 across collections | expense.projectId → projects/{id} |
| String array reference | N:M across collections | project.grantIds → activeGrants[] |
| Embedded sub-document | 1:N when child is always read with parent, array bounded | expense.allocations[] |
| Firestore subcollection | 1:N when child list is unbounded or queried independently | organizations/{id}/moduleInstallations/{moduleId} |
All string FK references use the target document’s Firestore document ID.
20. Firestore Index Requirements
| Collection | Fields | Direction | Used By |
|---|
expenses | organizationId, status, createdAt | ASC, ASC, DESC | Expense list views |
expenses | organizationId, grantId, status | ASC, ASC, ASC | Grant expense reports |
activeGrants | organizationId, status | ASC, ASC | Dashboard widgets |
journals | organizationId, userId, date | ASC, ASC, DESC | Journal views per user |
compliance_rules | organizationId, type, status, createdAt | ASC, ASC, ASC, DESC | Compliance dashboard |
auditLogs | organizationId, resourceType, resourceId, timestamp | ASC, ASC, ASC, DESC | Entity audit trails |
documents | organizationId, path, status | ASC, ASC, ASC | Folder subtree views |
grantPipeline | organizationId, stage, updatedAt | ASC, ASC, DESC | Pipeline board |
21. Collection Name Gotchas
| Collection Name | Stores | UI Calls It |
|---|
employees | User documents | Users / Team |
journals | JournalEntry documents | Journals / Time Tracking |
journalSubmissions | JournalSubmission documents | Monthly Submissions |
compliance_rules | CompliancePolicy documents | Compliance Rules |
missionCredits | MissionCredit wallet (1 per org) | Credits |
Maintenance
Update this document when:
- Adding or renaming a Firestore collection
- Introducing a new aggregate domain
- Changing entity schemas or adding new Zod schemas
- Modifying subscription tier limits or feature gates
- Adding new enum values or validation rules
For architectural patterns, see: