Documentation Index
Fetch the complete documentation index at: https://grantmaster.dev/llms.txt
Use this file to discover all available pages before exploring further.
@grantmaster/shared Package API Reference
Overview
@grantmaster/shared is a pure TypeScript package providing types, schemas, errors, events, configuration, and canonical contracts shared between the React frontend (src/) and Firebase Cloud Functions (functions/). It has zero Firebase dependencies — only zod and @trpc/server as runtime/peer dependencies.
Package location: packages/shared/
Version: 1.0.0
Dependencies:
zod ^3.25.76 (runtime + peer)
@trpc/server ^11.10.0
Subpath Exports Map
The package exposes six subpath exports plus the root barrel:
| Import path | Entry file | Description |
|---|
@grantmaster/shared | src/index.ts | Re-exports everything from all subpaths |
@grantmaster/shared/types | src/types/index.ts | Enums, utility types, entity interfaces, intelligence types, grant source types, tRPC router type |
@grantmaster/shared/schemas | src/schemas/index.ts | Zod validation schemas (common primitives) |
@grantmaster/shared/errors | src/errors/index.ts | Error class hierarchy and domain errors |
@grantmaster/shared/events | src/events/index.ts | SystemEventType enum, event payloads, type guards, persistence rules |
@grantmaster/shared/canonical | src/canonical/index.ts | Canonical event envelope, status projection, transition logic |
@grantmaster/shared/config | src/config/index.ts | Feature entitlements, tier limits, subscription configuration |
Types (@grantmaster/shared/types)
Enums
SystemRole
Authorization roles assigned to users.
| Value | String |
|---|
SUPER_ADMIN | 'Super Admin' |
ADMIN | 'Admin' |
MANAGER | 'Manager' |
MEMBER | 'Member' |
USER | 'User' |
AUDITOR | 'Auditor' |
OBSERVER | 'Observer' |
EmployeeStatus
ACTIVE | INACTIVE | INVITED | SUSPENDED
Permission
Comprehensive permission enum with ~200 values organized by domain:
- Platform:
MANAGE_PLATFORM
- Organization:
VIEW_ORG_PROFILE, EDIT_ORG_IDENTITY, MANAGE_BILLING, DELETE_ORGANIZATION, etc.
- Projects:
VIEW_PROJECTS, CREATE_PROJECT, EDIT_PROJECT_DETAILS, MANAGE_PROJECTS, DELETE_PROJECT, etc.
- Grants:
VIEW_GRANT_PIPELINE, CREATE_PIPELINE_ENTRY, VIEW_APPLICATIONS, CREATE_APPLICATION, SUBMIT_APPLICATION, etc.
- Journals:
VIEW_JOURNALS, SUBMIT_JOURNAL, APPROVE_JOURNALS, EDIT_LOCKED_ENTRIES, etc.
- Expenses:
VIEW_EXPENSES, SUBMIT_OWN_EXPENSES, MANAGE_EXPENSES, APPROVE_EXPENSES
- Team/HR:
VIEW_TEAM, INVITE_USER, MANAGE_TEAM, MANAGE_CONTRACTS, MANAGE_STAFF_ALLOCATIONS, etc.
- Documents:
VIEW_DOCUMENT_LIBRARY, UPLOAD_DOCUMENTS, APPROVE_DOCUMENTS, USE_AI_CLASSIFICATION, etc.
- Impact (M&E):
VIEW_ME, MANAGE_ME, APPROVE_ME_DATA, LINK_ME_TO_GRANTS, MANAGE_ME_WORKFLOWS, etc.
- Compliance/Audit:
VIEW_AUDIT_LOGS, EXPORT_AUDIT_LOGS, VIEW_POLICY_ENGINE, CREATE_COMPLIANCE_POLICY, etc.
- SuperAdmin:
IMPERSONATE_TENANT, PROVISION_TENANTS, MANAGE_TENANT_LIFECYCLE, MANAGE_BACKUP_POLICIES, etc.
- Leave:
REQUEST_TIME_OFF, APPROVE_TIME_OFF, VIEW_TIME_OFF_BALANCES, etc.
- Relations:
VIEW_RELATIONS, CREATE_CONTACT, MERGE_CONTACTS, MANAGE_CONTACT_INTEGRATIONS
- Reports:
VIEW_REPORTS, GENERATE_CUSTOM_REPORTS, EXPORT_REPORTS, MANAGE_SCHEDULED_REPORTS
SubscriptionTier
POTENTIAL | PROFESSIONAL | ULTIMATE
ProjectPhase
PLANNING | IMPLEMENTATION | MONITORING | REPORTING | CLOSING | ARCHIVED
GrantorType
PUBLIC_AUTHORITY | FOUNDATION | TRUST_BASED | BUSINESS | INDIVIDUAL | INTERNATIONAL_AGENCY | COMMUNITY_FOUNDATION | CROWDFUNDING | SOCIAL_INVESTOR
GrantSourceId
Identifies supported Dutch grant data sources for the aggregation pipeline:
RVO | EU_PORTAL | PROVINCE_ZH | PROVINCE_NH | PROVINCE_UT | NWO | FONDSEN_NL | DATA_OVERHEID | MANUAL | DUSI | ZONMW | OVERHEID_NL | RIJKSOVERHEID
Constants
ORG_SIZE_THRESHOLDS
Organization size buckets by FTE count. Privacy-preserving — never expose exact counts, only categories.
{ micro: { min: 0, max: 9 }, small: { min: 10, max: 49 }, medium: { min: 50, max: 199 }, large: { min: 200, max: Infinity } }
DATA_CATEGORIES
Intelligence data categories: 'grants' | 'finance' | 'compliance' | 'people' | 'projects'
Utility Types
| Type | Description |
|---|
LanguageCode | 'en' | 'nl' |
TimestampLike | string | { toDate: () => Date } — handles both ISO strings and Firebase Timestamps |
BaseDocument | { id, organizationId, createdAt, updatedAt } — base for all Firestore documents |
AuditedDocument | Extends BaseDocument with createdBy, updatedBy, and optional name fields |
OrgSizeCategory | 'micro' | 'small' | 'medium' | 'large' |
DataCategory | 'grants' | 'finance' | 'compliance' | 'people' | 'projects' |
GrantSourceType | 'api' | 'scrape' | 'manual' |
Entity Interfaces
Minimal entity interfaces shared between frontend and Cloud Functions. These contain only the fields both runtimes need.
| Interface | Key Fields |
|---|
ProjectBase | id, organizationId, name, code, fundingSource, phase, budgetHours, monetaryBudget, documents |
EmployeeBase | id, userId, organizationId, name, email, role, contractHours, fteRatio, workPattern |
OrganizationBase | id, name, settings (defaultLanguage, defaultCurrency) |
JournalEntry | date, projectId, projectName, hours, activityType, description |
JournalInput | month, selectedProjectIds, allocations, activities, patternConfirmation |
Intelligence Types
Cross-organization intelligence platform types for anonymized benchmarking:
| Interface | Purpose |
|---|
RawOrgData | In-memory raw data collected from Firestore (never stored/transmitted) |
IntelligenceConsent | Consent record for intelligence data sharing |
CohortDefinition | Segmentation: size, sectors, geography, tier |
GrantMetrics / FinanceMetrics / ComplianceMetrics / PeopleMetrics / ProjectMetrics | Anonymized metric interfaces per domain |
OrgMetricsSnapshot | Stored anonymized snapshot with SHA-256 anonymous ID |
BenchmarkStatistics | { mean, median, p25, p75, p90, sampleSize } |
Benchmark | Aggregated benchmark with overall + segmented statistics |
OrgBenchmarkPosition | Organization’s percentile position in benchmarks |
FunderProfile | Aggregated funder behavior (approval rate, avg award, decision time) |
SectorTrend | Sector-wide trend detection |
IntelligenceCache | Per-org cache for benchmarks and funder insights |
CollectionResult / AggregationResult / CacheRefreshResult | Processing pipeline results |
Grant Source Types
Types for the multi-source Dutch grant aggregation pipeline:
| Interface | Purpose |
|---|
GrantSourceConfig | Per-source configuration (schedule, webhook, sync status) |
GrantIngestPayload | Envelope sent by n8n workflows to ingest API |
GrantIngestItem | Single normalized grant item from an external source |
GrantIngestEligibility | Eligibility criteria (geography, sectors, org types) |
GrantIngestResult | Response from ingest API (created/updated/unchanged counts) |
GrantScrapingTarget | Firecrawl scraping target configuration |
GrantScrapingHash | SHA-256 content hash for change detection |
GrantSyncHistory | Audit log entry for sync runs |
GrantSyncStatusSummary | Aggregated status for admin dashboard |
GrantOpportunitiesSyncedPayload | Event payload for completed syncs |
tRPC Types
| Type | Purpose |
|---|
AppRouter | Compatibility adapter for createTRPCReact() with typed namespace routers (projects, expenses, journals, grants, contacts, documents, etc.) |
FunctionsAppRouter / GeneratedAppRouter | Generated router type from Cloud Functions — the canonical source of truth |
Schemas (@grantmaster/shared/schemas)
All schemas are Zod-based and dependency-free (no Firebase imports). They use duck-typing for Firestore Timestamp validation.
ID Schemas
| Schema | Description |
|---|
uuidSchema | Non-empty string (Firebase auto-generated IDs) |
organizationIdSchema | Non-empty string for tenant scoping |
userIdSchema | Non-empty string for user references |
projectIdSchema | Non-empty string for project references |
Date/Time Schemas
| Schema | Description | | |
|---|
isoDateSchema | ISO 8601 date string (YYYY-MM-DD) | | |
isoDatetimeSchema | ISO 8601 datetime with timezone | | |
timestampSchema | Positive integer (milliseconds since epoch) | | |
firestoreTimestampSchema | Union: Firestore Timestamp (duck-typed) | Date | ISO string — transforms to Date |
firestoreDateSchema | Like above but transforms to YYYY-MM-DD string | | |
Currency & Number Schemas
| Schema | Description |
|---|
currencyAmountSchema / currencySchema | Non-negative finite number |
positiveCurrencySchema | Positive finite number (no zero) |
currencyCodeSchema | z.enum(['EUR', 'USD', 'GBP', 'CAD']) |
percentageSchema | Number 0—100 |
confidenceScoreSchema | Number 0—100 |
Text & Contact Schemas
| Schema | Description |
|---|
emailSchema | Optional, validated, lowercased email |
requiredEmailSchema | Required validated email |
phoneSchema | Optional, international format regex |
urlSchema | Optional URL validation |
requiredStringSchema | Non-empty trimmed string |
optionalStringSchema | Optional string |
textAreaSchema(minLength) | String with minimum length (default 10) |
Common Object Schemas
| Schema | Inferred Type |
|---|
addressSchema | Address — optional object with street, city, state, postalCode, country |
attachmentSchema | Attachment — file reference with id, name, url, storagePath, contentType, size, uploadedAt, uploadedBy |
bankAccountSchema | BankAccount — optional object with accountHolder, iban, bic, bankName |
Audit Field Schemas
| Schema | Fields |
|---|
createdAuditSchema | createdAt, createdBy, createdByName? |
updatedAuditSchema | updatedAt, updatedBy, updatedByName? |
fullAuditSchema | Merge of created + updated |
baseEntitySchema | id, organizationId, createdAt, updatedAt |
Range Schemas
| Schema | Description |
|---|
dateRangeSchema | { startDate, endDate } with start < end refinement |
datetimeRangeSchema | { startTime, endTime } with start < end refinement |
Utility Functions
| Function | Description |
|---|
createEnumSchema(values, errorMessage?) | Creates a z.enum() from a readonly string array |
requiredIf(schema, condition, message?) | Makes a schema optional unless condition is true |
Errors (@grantmaster/shared/errors)
Error Severity & Category Enums
enum ErrorSeverity { INFO, WARNING, ERROR, CRITICAL }
enum ErrorCategory {
VALIDATION, AUTHENTICATION, AUTHORIZATION, NOT_FOUND,
NETWORK, FIRESTORE, STORAGE, RATE_LIMIT, BUSINESS_LOGIC,
EXTERNAL_API, AI_SERVICE, EMAIL_SERVICE, UNKNOWN
}
Error Class Hierarchy
All errors extend the abstract AppError base class which provides:
timestamp (ISO string)
severity (ErrorSeverity)
category (ErrorCategory)
context (optional debugging metadata)
userMessage (UI-safe message)
isOperational (recoverable vs. crash-worthy)
| Class | Extends | Category | Constructor |
|---|
AppError (abstract) | Error | — | (message, userMessage, severity, category, context?, isOperational?) |
UserError | AppError | varies | (message, userMessage, category, context?) — severity WARNING |
SystemError | AppError | varies | (message, category, context?) — generic user message |
ValidationError | UserError | VALIDATION | (message, context?) |
AuthenticationError | SystemError | AUTHENTICATION | (message, context?) |
AuthorizationError | UserError | AUTHORIZATION | (message, context?) — “You do not have permission…” |
NotFoundError | UserError | NOT_FOUND | (resource, id, context?) |
FirestoreError | SystemError | FIRESTORE | (operation, error, context?) |
StorageError | SystemError | STORAGE | (operation, error, context?) |
NetworkError | SystemError | NETWORK | (message, context?) |
RateLimitError | UserError | RATE_LIMIT | (retryAfter?, context?) |
BusinessLogicError | UserError | BUSINESS_LOGIC | (message, context?) |
ExternalAPIError | SystemError | EXTERNAL_API | (service, error, context?) |
AIServiceError | SystemError | AI_SERVICE | (operation, error, context?) |
EmailServiceError | SystemError | EMAIL_SERVICE | (operation, error, context?) |
Domain Errors
Standalone error classes (extend Error directly, not AppError) with toJSON() support:
| Class | Properties | Purpose |
|---|
RateLimitExceededError | retryAfter, limit, used, window | Rate limit with usage details |
TenantIsolationError | attemptedOrganizationId, userOrganizationId, operation, timestamp | Security: cross-tenant access attempt |
FeatureNotAvailableError | feature, currentTier, requiredTier, upgradeUrl | Feature gating by subscription tier |
Events (@grantmaster/shared/events)
SystemEventType Enum
All event type constants organized by domain:
Journal Events: JOURNAL_SUBMITTED, JOURNAL_APPROVED, JOURNAL_REJECTED
Expense Events: EXPENSE_CREATED, EXPENSE_SUBMITTED, EXPENSE_APPROVED, EXPENSE_REJECTED
Compliance Events: COMPLIANCE_ALERT_RAISED, COMPLIANCE_ALERT_RESOLVED, COMPLIANCE_RULE_VIOLATED
Budget Events: BUDGET_THRESHOLD_EXCEEDED, BUDGET_THRESHOLD_WARNING, BUDGET_DEPLETED
Project Events: PROJECT_DEADLINE_APPROACHING, PROJECT_STATUS_CHANGED, PROJECT_MILESTONE_COMPLETED
Project Lifecycle Events: PROJECT_CREATED, PROJECT_STARTED, PROJECT_PHASE_ADVANCED, PROJECT_ARCHIVED, PROJECT_UNARCHIVED, PROJECT_CHECKLIST_COMPLETED
Project Template Events: PROJECT_TEMPLATE_CREATED, PROJECT_TEMPLATE_USED
Employee Events: EMPLOYEE_ONBOARDED, EMPLOYEE_OFFBOARDED, USER_ONBOARDED (alias), USER_OFFBOARDED (alias)
Leave Events: LEAVE_REQUEST_SUBMITTED, LEAVE_REQUEST_APPROVED, LEAVE_REQUEST_REJECTED, TIME_OFF_REQUEST_SUBMITTED (alias), TIME_OFF_REQUEST_APPROVED (alias), TIME_OFF_REQUEST_REJECTED (alias)
Quota Events: QUOTA_EXCEEDED, QUOTA_WARNING
Audit Events: AUDIT_LOG_CREATED
Grant Pipeline Events: GRANT_CREATED, GRANT_UPDATED, GRANT_APPLICATION_CREATED, GRANT_ADDED_TO_PIPELINE, GRANT_PIPELINE_STAGE_CHANGED, GRANT_APPLICATION_SUBMITTED, GRANT_WON, GRANT_LOST, GRANT_REPORT_DUE, GRANT_REPORT_SUBMITTED, GRANT_DISBURSEMENT_RECEIVED, GRANT_APPLICATION_OUTCOME
Intelligence Events: INTELLIGENCE_CONSENT_CHANGED, INTELLIGENCE_SNAPSHOT_GENERATED
Document Brain Events: DOCUMENT_UPLOADED, DOCUMENT_APPROVED, DOCUMENT_REJECTED, DOCUMENT_REVIEW_REQUESTED, DOCUMENT_VERSION_CREATED, DOCUMENT_CLASSIFIED, DOCUMENT_DEADLINE_EXTRACTED
Portal Events: PORTAL_REPORT_ACKNOWLEDGED, PORTAL_REVISION_REQUESTED, PORTAL_COMMENT_POSTED, PORTAL_REPORT_SUBMITTED
Agent Events: AGENT_TASK_STARTED, AGENT_TASK_COMPLETED, AGENT_TASK_FAILED, AGENT_TASK_CANCELLED, AGENT_STEP_COMPLETED, AGENT_ESCALATION_REQUIRED, AGENT_ESCALATION_RESOLVED, AGENT_BUDGET_CONSUMED
Credit Events: CREDITS_CONSUMED, CREDITS_EXHAUSTED, CREDITS_PURCHASED
Impact (M&E) Events: ME_INDICATOR_CREATED, ME_INDICATOR_UPDATED, ME_INDICATOR_ARCHIVED, ME_TARGET_SET, ME_DATA_POINT_RECORDED, ME_INDICATOR_STATUS_CHANGED, ME_DATA_POINT_SUBMITTED, ME_DATA_POINT_APPROVED, ME_DATA_POINT_REJECTED, ME_KOBO_SYNC_COMPLETED, ME_KOBO_SYNC_FAILED, ME_GRANT_INDICATOR_LINKED, ME_GRANT_INDICATOR_UNLINKED, ME_DONOR_EXPORT_GENERATED, ME_PORTFOLIO_VIEWED, ME_AI_INDICATORS_SUGGESTED, ME_AI_SUGGESTION_ACCEPTED, ME_AI_SUGGESTION_DISMISSED, ME_AI_NARRATIVE_GENERATED, ME_AI_ANOMALY_DETECTED, ME_WORKFLOW_RULE_CREATED, ME_WORKFLOW_RULE_UPDATED, ME_WORKFLOW_RULE_DELETED, ME_WORKFLOW_RULE_TRIGGERED, ME_WORKFLOW_RULE_FAILED
Module Marketplace Events: MODULE_INSTALLED, MODULE_ACTIVATED, MODULE_DEACTIVATED, MODULE_UNINSTALLED, MODULE_TRIAL_STARTED, MODULE_TRIAL_EXPIRED, MODULE_PAYMENT_FAILED
Extension Events: EXTENSION_AUTO_DISABLED, EXTENSION_HEALTH_CHECK_FAILED, EXTENSION_TENANT_SWITCHED
Extension Domain Events: DONATION_RECEIVED, CARD_TRANSACTION, EMPLOYEE_DONATION_COMPLETED, MEETING_COMPLETED, RESOLUTION_PASSED, EVENT_REVENUE_MILESTONE
Tenant Events: TENANT_CLASSIFICATION_UPDATED
EventSeverity Enum
INFO | WARNING | ERROR | CRITICAL
Core Interfaces
SystemEvent<T>
interface SystemEvent<T = Record<string, unknown>> {
eventId?: string; // Stable ID for idempotency
occurredAt?: string; // ISO timestamp for persistence/replay
type: SystemEventType;
organizationId: string;
userId: string;
severity: EventSeverity;
timestamp: Date;
payload: T;
metadata?: {
source?: string;
version?: string;
correlationId?: string;
schemaVersion?: string;
criticality?: 'durable-critical' | 'ephemeral';
};
}
TypedSystemEvent<E>
Type-safe event helper: TypedSystemEvent<SystemEventType.GRANT_WON> resolves payload to GrantWonPayload.
EventPayloadMap
Complete mapping from every SystemEventType to its payload interface. Enables type-safe event handling:
type TypedSystemEvent<E extends keyof EventPayloadMap & SystemEventType> =
Omit<SystemEvent, 'type' | 'payload'> & { type: E; payload: EventPayloadMap[E] };
Type Guard Functions
Each returns boolean for a SystemEventType:
| Function | Matches |
|---|
isJournalEvent(type) | Journal events |
isExpenseEvent(type) | Expense events |
isComplianceEvent(type) | Compliance events |
isBudgetEvent(type) | Budget events |
isProjectLifecycleEvent(type) | Project lifecycle events |
isProjectTemplateEvent(type) | Project template events |
isLeaveRequestEvent(type) / isTimeOffRequestEvent(type) | Leave/time-off events |
isQuotaEvent(type) | Quota events |
isIntelligenceEvent(type) | Intelligence events |
isGrantEvent(type) | Grant pipeline events |
isPortalEvent(type) | Portal events |
isAgentEvent(type) | Agent lifecycle events |
isCreditEvent(type) | Credit events |
isMEEvent(type) | Impact (M&E) events |
isModuleEvent(type) | Module marketplace events |
Persistence & Delivery Rules
| Function | Description |
|---|
requiresPersistence(eventType) | Returns true if the event must be persisted to Firestore for audit/analytics. Covers: audit logs, compliance, approval/rejection workflows, budget critical events, employee lifecycle, project lifecycle/templates, quota, intelligence, portal, agent, credit, and M&E events. |
requiresDurableDelivery(eventType) | Returns true if the event requires guaranteed delivery (retry on failure). Covers: audit logs, approval decisions, credit events, module lifecycle, intelligence consent changes, project phase advancement, and GRANT_WON. |
Canonical (@grantmaster/shared/canonical)
The canonical event system provides a unified status model across all domains.
Types
type CanonicalStatus = 'pending' | 'progress' | 'blocked' | 'completed' | 'failed';
type CanonicalStatusDomain =
| 'grant_lifecycle' | 'expense_audit' | 'journal_workflow' | 'agent_run'
| 'billing' | 'compliance' | 'project' | 'project_lifecycle' | 'extension';
type CanonicalEntityType =
| 'grant' | 'expense' | 'journal' | 'agent_run'
| 'billing' | 'compliance' | 'project' | 'extension';
Interfaces
CanonicalEventEnvelope
Standard envelope wrapping any domain event into the canonical status model:
| Field | Type | Description |
|---|
eventId | string | Unique event identifier |
eventType | string | Canonical event type |
schemaVersion | string | Semver schema version |
organizationId | string | Tenant scope |
domain | CanonicalStatusDomain | Source domain |
entityType | CanonicalEntityType | Entity kind |
entityId | string | Entity identifier |
status | CanonicalStatus | Current status |
reason? | string | Optional status reason |
occurredAt | string | ISO datetime |
sourceEventType | string | Original SystemEventType |
source? / correlationId? | string | Tracing fields |
payload | Record<string, unknown> | Domain-specific data |
CanonicalStatusProjection
Materialized view of an entity’s current canonical status:
| Field | Type | Description |
|---|
key | string | Composite key |
organizationId / domain / entityType / entityId | — | Identity fields |
status | CanonicalStatus | Current status |
sourceEventType | string | Event that set this status |
lastEventAt / projectedAt | string | Timestamps |
staleAfter? | string | Expiry threshold |
CanonicalStatusSummary
Aggregate counts: { total, pending, progress, blocked, completed, failed }.
Functions
| Function | Description |
|---|
canTransitionCanonicalStatus(from, to) | Validates status transition. Terminal states (completed, failed) allow no outgoing transitions. |
getCanonicalSchemaVersion() | Returns current schema version ('1.0.0') |
getCanonicalMinSupportedSchemaVersion() | Returns minimum supported version ('1.0.0') |
isSupportedCanonicalSchemaVersion(version) | Checks if a version is within supported range (same major, >= min minor.patch) |
summarizeCanonicalStatuses(projections, filters?) | Aggregates projections into a CanonicalStatusSummary, optionally filtered by domains or entity IDs |
Zod Schema
canonicalEventEnvelopeSchema — validates a CanonicalEventEnvelope including schema version support check and ISO datetime validation.
Configuration (@grantmaster/shared/config)
Feature Enum
All gated features in the application (~40 values):
| Category | Features |
|---|
| Basic | BASIC_JOURNALS, BASIC_REPORTS, BASIC_PROJECTS, TEAM_COLLABORATION |
| AI | AI_GENERATION, AI_JOURNAL_SUBMISSION, AI_REPORT_GENERATION, AI_AUDIT_DEFENSE, AI_GRANT_ASSISTANT |
| Professional | API_ACCESS, ADVANCED_REPORTS, CUSTOM_EXPORTS, BUDGET_FORECASTING, EXPENSE_MANAGEMENT, GRANT_DISCOVERY |
| Enterprise | SSO, ADVANCED_SSO, SAML_SSO, AUDIT_LOGS, CUSTOM_INTEGRATIONS, CUSTOM_BRANDING, PRIORITY_SUPPORT, DEDICATED_ACCOUNT_MANAGER, MULTI_CURRENCY, ADVANCED_SECURITY, COMPLIANCE_MONITORING, WHITE_LABEL |
| Storage | DOCUMENT_UPLOADS, ADVANCED_STORAGE |
| RAG/AI | RAG_DOCUMENT_SEARCH, SEMANTIC_SEARCH |
| Analytics | ADVANCED_ANALYTICS, CUSTOM_DASHBOARDS |
| Agents | AGENT_BASIC, AGENT_MULTI_STEP, AGENT_AUTONOMOUS, AGENT_ORCHESTRATION |
| Modules | IMPACT_MODULE |
TierLimits Interface
Usage limits per subscription tier:
| Limit | Potential | Professional | Ultimate |
|---|
maxUsers | 3 | 15 | 25 |
maxProjects | 10 | 50 | unlimited |
maxStorage (MB) | 5,120 | 51,200 | unlimited |
maxApiCallsPerMonth | 0 | 10,000 | unlimited |
maxAiGenerationsPerMonth | 50 | 200 | unlimited |
maxAgentCreditsPerMonth | 100 | 1,000 | 10,000 |
maxConcurrentAgents | 1 | 3 | 10 |
maxAgentStepsPerRun | 5 | 20 | unlimited (-1) |
maxAgentRunsPerMonth | 10 | 200 | unlimited (-1) |
Feature Entitlements
FEATURE_ENTITLEMENTS: Record<SubscriptionTier, Feature[]> — maps each tier to its available features. Tiers are cumulative (Professional includes all Potential features, Ultimate includes all Professional features).
Helper Functions
| Function | Description |
|---|
getMinimumTierForFeature(feature) | Returns the lowest SubscriptionTier that includes the feature |
tierIncludesFeature(tier, feature) | Returns boolean |
getFeaturesForTier(tier) | Returns Feature[] for the given tier |
getLimitsForTier(tier) | Returns TierLimits for the given tier |
Display Maps
| Constant | Type | Description |
|---|
FEATURE_NAMES | Record<Feature, string> | Human-readable feature names |
FEATURE_DESCRIPTIONS | Record<Feature, string> | Feature descriptions for upgrade prompts |
FEATURE_MODULE_MAP | Partial<Record<Feature, string>> | Maps module-gated features to their module ID (e.g., IMPACT_MODULE -> 'impact') |
Usage Examples
Main App (React Frontend)
// Import from specific subpaths for tree-shaking
import { SystemRole, Permission, ProjectPhase } from '@grantmaster/shared/types';
import { requiredStringSchema, currencyCodeSchema } from '@grantmaster/shared/schemas';
import { NotFoundError, FeatureNotAvailableError } from '@grantmaster/shared/errors';
import { SystemEventType, type GrantWonPayload } from '@grantmaster/shared/events';
import { Feature, tierIncludesFeature, TIER_LIMITS } from '@grantmaster/shared/config';
// Check feature availability
if (!tierIncludesFeature(currentTier, Feature.GRANT_DISCOVERY)) {
throw new FeatureNotAvailableError(
'Grant Discovery',
currentTier,
getMinimumTierForFeature(Feature.GRANT_DISCOVERY)
);
}
// Validate form input with shared schema
const schema = z.object({
name: requiredStringSchema,
currency: currencyCodeSchema,
amount: currencyAmountSchema,
});
// Type-safe event handling
function handleEvent(event: TypedSystemEvent<SystemEventType.GRANT_WON>) {
const { grantTitle, awardedAmount } = event.payload; // fully typed
}
Cloud Functions
// Import from root barrel or specific subpaths
import {
SystemEventType,
EventSeverity,
type SystemEvent,
ProjectBase,
EmployeeBase,
} from '@grantmaster/shared';
import { AppError, FirestoreError } from '@grantmaster/shared/errors';
import { canonicalEventEnvelopeSchema } from '@grantmaster/shared/canonical';
// Validate incoming canonical event
function processCanonicalEvent(data: unknown) {
const result = canonicalEventEnvelopeSchema.safeParse(data);
if (!result.success) {
throw new ValidationError(result.error.message);
}
// result.data is typed as CanonicalEventEnvelope
}
// Use shared entity types for AI/search processing
function processProject(project: ProjectBase) {
// Only fields needed by functions are available
console.log(project.name, project.phase, project.fundingSource);
}
// Wrap Firestore errors
try {
await db.collection('projects').doc(id).get();
} catch (error) {
throw new FirestoreError('getProject', error, { projectId: id });
}
Event Persistence Check (Cloud Functions)
import {
requiresPersistence,
requiresDurableDelivery,
SystemEventType,
} from '@grantmaster/shared/events';
function routeEvent(event: SystemEvent) {
if (requiresPersistence(event.type)) {
await persistToFirestore(event);
}
if (requiresDurableDelivery(event.type)) {
await enqueueForGuaranteedDelivery(event);
}
}
Canonical Status Transitions
import {
canTransitionCanonicalStatus,
summarizeCanonicalStatuses,
type CanonicalStatusProjection,
} from '@grantmaster/shared/canonical';
// Validate a status change
if (!canTransitionCanonicalStatus('progress', 'completed')) {
throw new Error('Invalid status transition');
}
// Summarize projections for a dashboard widget
const summary = summarizeCanonicalStatuses(projections, {
domains: ['grant_lifecycle', 'expense_audit'],
});
// => { total: 42, pending: 5, progress: 20, blocked: 3, completed: 12, failed: 2 }