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.

@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 pathEntry fileDescription
@grantmaster/sharedsrc/index.tsRe-exports everything from all subpaths
@grantmaster/shared/typessrc/types/index.tsEnums, utility types, entity interfaces, intelligence types, grant source types, tRPC router type
@grantmaster/shared/schemassrc/schemas/index.tsZod validation schemas (common primitives)
@grantmaster/shared/errorssrc/errors/index.tsError class hierarchy and domain errors
@grantmaster/shared/eventssrc/events/index.tsSystemEventType enum, event payloads, type guards, persistence rules
@grantmaster/shared/canonicalsrc/canonical/index.tsCanonical event envelope, status projection, transition logic
@grantmaster/shared/configsrc/config/index.tsFeature entitlements, tier limits, subscription configuration

Types (@grantmaster/shared/types)

Enums

SystemRole

Authorization roles assigned to users.
ValueString
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

TypeDescription
LanguageCode'en' | 'nl'
TimestampLikestring | { toDate: () => Date } — handles both ISO strings and Firebase Timestamps
BaseDocument{ id, organizationId, createdAt, updatedAt } — base for all Firestore documents
AuditedDocumentExtends 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.
InterfaceKey Fields
ProjectBaseid, organizationId, name, code, fundingSource, phase, budgetHours, monetaryBudget, documents
EmployeeBaseid, userId, organizationId, name, email, role, contractHours, fteRatio, workPattern
OrganizationBaseid, name, settings (defaultLanguage, defaultCurrency)
JournalEntrydate, projectId, projectName, hours, activityType, description
JournalInputmonth, selectedProjectIds, allocations, activities, patternConfirmation

Intelligence Types

Cross-organization intelligence platform types for anonymized benchmarking:
InterfacePurpose
RawOrgDataIn-memory raw data collected from Firestore (never stored/transmitted)
IntelligenceConsentConsent record for intelligence data sharing
CohortDefinitionSegmentation: size, sectors, geography, tier
GrantMetrics / FinanceMetrics / ComplianceMetrics / PeopleMetrics / ProjectMetricsAnonymized metric interfaces per domain
OrgMetricsSnapshotStored anonymized snapshot with SHA-256 anonymous ID
BenchmarkStatistics{ mean, median, p25, p75, p90, sampleSize }
BenchmarkAggregated benchmark with overall + segmented statistics
OrgBenchmarkPositionOrganization’s percentile position in benchmarks
FunderProfileAggregated funder behavior (approval rate, avg award, decision time)
SectorTrendSector-wide trend detection
IntelligenceCachePer-org cache for benchmarks and funder insights
CollectionResult / AggregationResult / CacheRefreshResultProcessing pipeline results

Grant Source Types

Types for the multi-source Dutch grant aggregation pipeline:
InterfacePurpose
GrantSourceConfigPer-source configuration (schedule, webhook, sync status)
GrantIngestPayloadEnvelope sent by n8n workflows to ingest API
GrantIngestItemSingle normalized grant item from an external source
GrantIngestEligibilityEligibility criteria (geography, sectors, org types)
GrantIngestResultResponse from ingest API (created/updated/unchanged counts)
GrantScrapingTargetFirecrawl scraping target configuration
GrantScrapingHashSHA-256 content hash for change detection
GrantSyncHistoryAudit log entry for sync runs
GrantSyncStatusSummaryAggregated status for admin dashboard
GrantOpportunitiesSyncedPayloadEvent payload for completed syncs

tRPC Types

TypePurpose
AppRouterCompatibility adapter for createTRPCReact() with typed namespace routers (projects, expenses, journals, grants, contacts, documents, etc.)
FunctionsAppRouter / GeneratedAppRouterGenerated 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

SchemaDescription
uuidSchemaNon-empty string (Firebase auto-generated IDs)
organizationIdSchemaNon-empty string for tenant scoping
userIdSchemaNon-empty string for user references
projectIdSchemaNon-empty string for project references

Date/Time Schemas

SchemaDescription
isoDateSchemaISO 8601 date string (YYYY-MM-DD)
isoDatetimeSchemaISO 8601 datetime with timezone
timestampSchemaPositive integer (milliseconds since epoch)
firestoreTimestampSchemaUnion: Firestore Timestamp (duck-typed)DateISO string — transforms to Date
firestoreDateSchemaLike above but transforms to YYYY-MM-DD string

Currency & Number Schemas

SchemaDescription
currencyAmountSchema / currencySchemaNon-negative finite number
positiveCurrencySchemaPositive finite number (no zero)
currencyCodeSchemaz.enum(['EUR', 'USD', 'GBP', 'CAD'])
percentageSchemaNumber 0—100
confidenceScoreSchemaNumber 0—100

Text & Contact Schemas

SchemaDescription
emailSchemaOptional, validated, lowercased email
requiredEmailSchemaRequired validated email
phoneSchemaOptional, international format regex
urlSchemaOptional URL validation
requiredStringSchemaNon-empty trimmed string
optionalStringSchemaOptional string
textAreaSchema(minLength)String with minimum length (default 10)

Common Object Schemas

SchemaInferred Type
addressSchemaAddress — optional object with street, city, state, postalCode, country
attachmentSchemaAttachment — file reference with id, name, url, storagePath, contentType, size, uploadedAt, uploadedBy
bankAccountSchemaBankAccount — optional object with accountHolder, iban, bic, bankName

Audit Field Schemas

SchemaFields
createdAuditSchemacreatedAt, createdBy, createdByName?
updatedAuditSchemaupdatedAt, updatedBy, updatedByName?
fullAuditSchemaMerge of created + updated
baseEntitySchemaid, organizationId, createdAt, updatedAt

Range Schemas

SchemaDescription
dateRangeSchema{ startDate, endDate } with start < end refinement
datetimeRangeSchema{ startTime, endTime } with start < end refinement

Utility Functions

FunctionDescription
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)
ClassExtendsCategoryConstructor
AppError (abstract)Error(message, userMessage, severity, category, context?, isOperational?)
UserErrorAppErrorvaries(message, userMessage, category, context?) — severity WARNING
SystemErrorAppErrorvaries(message, category, context?) — generic user message
ValidationErrorUserErrorVALIDATION(message, context?)
AuthenticationErrorSystemErrorAUTHENTICATION(message, context?)
AuthorizationErrorUserErrorAUTHORIZATION(message, context?) — “You do not have permission…”
NotFoundErrorUserErrorNOT_FOUND(resource, id, context?)
FirestoreErrorSystemErrorFIRESTORE(operation, error, context?)
StorageErrorSystemErrorSTORAGE(operation, error, context?)
NetworkErrorSystemErrorNETWORK(message, context?)
RateLimitErrorUserErrorRATE_LIMIT(retryAfter?, context?)
BusinessLogicErrorUserErrorBUSINESS_LOGIC(message, context?)
ExternalAPIErrorSystemErrorEXTERNAL_API(service, error, context?)
AIServiceErrorSystemErrorAI_SERVICE(operation, error, context?)
EmailServiceErrorSystemErrorEMAIL_SERVICE(operation, error, context?)

Domain Errors

Standalone error classes (extend Error directly, not AppError) with toJSON() support:
ClassPropertiesPurpose
RateLimitExceededErrorretryAfter, limit, used, windowRate limit with usage details
TenantIsolationErrorattemptedOrganizationId, userOrganizationId, operation, timestampSecurity: cross-tenant access attempt
FeatureNotAvailableErrorfeature, currentTier, requiredTier, upgradeUrlFeature 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:
FunctionMatches
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

FunctionDescription
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:
FieldTypeDescription
eventIdstringUnique event identifier
eventTypestringCanonical event type
schemaVersionstringSemver schema version
organizationIdstringTenant scope
domainCanonicalStatusDomainSource domain
entityTypeCanonicalEntityTypeEntity kind
entityIdstringEntity identifier
statusCanonicalStatusCurrent status
reason?stringOptional status reason
occurredAtstringISO datetime
sourceEventTypestringOriginal SystemEventType
source? / correlationId?stringTracing fields
payloadRecord<string, unknown>Domain-specific data

CanonicalStatusProjection

Materialized view of an entity’s current canonical status:
FieldTypeDescription
keystringComposite key
organizationId / domain / entityType / entityIdIdentity fields
statusCanonicalStatusCurrent status
sourceEventTypestringEvent that set this status
lastEventAt / projectedAtstringTimestamps
staleAfter?stringExpiry threshold

CanonicalStatusSummary

Aggregate counts: { total, pending, progress, blocked, completed, failed }.

Functions

FunctionDescription
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):
CategoryFeatures
BasicBASIC_JOURNALS, BASIC_REPORTS, BASIC_PROJECTS, TEAM_COLLABORATION
AIAI_GENERATION, AI_JOURNAL_SUBMISSION, AI_REPORT_GENERATION, AI_AUDIT_DEFENSE, AI_GRANT_ASSISTANT
ProfessionalAPI_ACCESS, ADVANCED_REPORTS, CUSTOM_EXPORTS, BUDGET_FORECASTING, EXPENSE_MANAGEMENT, GRANT_DISCOVERY
EnterpriseSSO, ADVANCED_SSO, SAML_SSO, AUDIT_LOGS, CUSTOM_INTEGRATIONS, CUSTOM_BRANDING, PRIORITY_SUPPORT, DEDICATED_ACCOUNT_MANAGER, MULTI_CURRENCY, ADVANCED_SECURITY, COMPLIANCE_MONITORING, WHITE_LABEL
StorageDOCUMENT_UPLOADS, ADVANCED_STORAGE
RAG/AIRAG_DOCUMENT_SEARCH, SEMANTIC_SEARCH
AnalyticsADVANCED_ANALYTICS, CUSTOM_DASHBOARDS
AgentsAGENT_BASIC, AGENT_MULTI_STEP, AGENT_AUTONOMOUS, AGENT_ORCHESTRATION
ModulesIMPACT_MODULE

TierLimits Interface

Usage limits per subscription tier:
LimitPotentialProfessionalUltimate
maxUsers31525
maxProjects1050unlimited
maxStorage (MB)5,12051,200unlimited
maxApiCallsPerMonth010,000unlimited
maxAiGenerationsPerMonth50200unlimited
maxAgentCreditsPerMonth1001,00010,000
maxConcurrentAgents1310
maxAgentStepsPerRun520unlimited (-1)
maxAgentRunsPerMonth10200unlimited (-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

FunctionDescription
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

ConstantTypeDescription
FEATURE_NAMESRecord<Feature, string>Human-readable feature names
FEATURE_DESCRIPTIONSRecord<Feature, string>Feature descriptions for upgrade prompts
FEATURE_MODULE_MAPPartial<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 }