[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6F84GNNDMS6DFHVAEXETR56":3,"skill-same:01M6F84GNNDMS6DFHVAEXETR56":74},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":42,"linkOnly":43,"markdownContent":44,"markdownBody":45,"frontMatter":46,"refName":51,"commitSha":52,"skillDirectory":53,"forksCount":54,"repositoryHtmlUrl":55,"repositoryHomepageUrl":6,"ownerHtmlUrl":56,"ownerBlogUrl":57,"ownerDescription":58,"updatedAt":59,"install":60,"resources":73},"01M6F84GNNDMS6DFHVAEXETR56","maintainx-reference-architecture",null,"Production-grade architecture patterns for MaintainX integrations.\nUse when designing system architecture, planning integrations,\nor building enterprise-scale MaintainX solutions.\nTrigger with phrases like \"maintainx architecture\", \"maintainx design\",\n\"maintainx system design\", \"maintainx enterprise\", \"maintainx patterns\".","Dicklesworthstone\u002Fpi_agent_rust","Dicklesworthstone","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F35050222?v=4","01M6CG26AR942CSVMN1M5E3DSE","Jeff Emanuel","01M6CG26EPP71PSHW1VDS71121",1981,"MIT","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Fplugins-community\u002Fplugins\u002Fsaas-packs\u002Fmaintainx-pack\u002Fskills\u002Fmaintainx-reference-architecture\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41],"architecture","maintainx reference architecture","reference","solutions","design","when","for","with","scale","trigger","io","patterns","system design","use","edit","write","read","integrations","system","architecture patterns","Production","Enterprise","planning","2026-11-10 10:12:30",false,"---\nname: maintainx-reference-architecture\ndescription: |\n  Production-grade architecture patterns for MaintainX integrations.\n  Use when designing system architecture, planning integrations,\n  or building enterprise-scale MaintainX solutions.\n  Trigger with phrases like \"maintainx architecture\", \"maintainx design\",\n  \"maintainx system design\", \"maintainx enterprise\", \"maintainx patterns\".\nallowed-tools: Read, Write, Edit\nversion: 1.0.0\nlicense: MIT\nauthor: Jeremy Longshore \u003Cjeremy@intentsolutions.io>\n---\n\n# MaintainX Reference Architecture\n\n## Overview\n\nProduction-grade architecture patterns for building scalable, maintainable MaintainX integrations.\n\n## Prerequisites\n\n- Understanding of distributed systems\n- Cloud platform experience\n- MaintainX API familiarity\n\n## Architecture Patterns\n\n### Pattern 1: Event-Driven Integration\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                     MaintainX Platform                          │\n│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐         │\n│  │ Work Orders  │  │   Assets     │  │  Locations   │         │\n│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘         │\n│         │                 │                 │                  │\n│         └─────────────────┼─────────────────┘                  │\n│                           │                                    │\n│                    ┌──────▼──────┐                             │\n│                    │  Webhooks   │                             │\n│                    └──────┬──────┘                             │\n└───────────────────────────┼─────────────────────────────────────┘\n                            │\n                            ▼\n┌───────────────────────────────────────────────────────────────────┐\n│                    Your Integration Layer                          │\n│                                                                    │\n│  ┌────────────────┐    ┌────────────────┐    ┌────────────────┐  │\n│  │ Webhook Handler│───▶│  Event Queue   │───▶│ Event Processor│  │\n│  │   (Express)    │    │   (Redis\u002FSQS)  │    │   (Workers)    │  │\n│  └────────────────┘    └────────────────┘    └───────┬────────┘  │\n│                                                      │           │\n│  ┌────────────────┐    ┌────────────────┐    ┌──────▼────────┐  │\n│  │  API Gateway   │───▶│ MaintainX Client│───▶│  Data Store   │  │\n│  │   (REST\u002FGraphQL)    │   (Cached)     │    │  (PostgreSQL) │  │\n│  └────────────────┘    └────────────────┘    └───────────────┘  │\n│                                                                    │\n└───────────────────────────────────────────────────────────────────┘\n                            │\n                            ▼\n┌───────────────────────────────────────────────────────────────────┐\n│                    External Systems                                │\n│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐         │\n│  │   ERP    │  │   SCADA  │  │  BI\u002FReports│ │  Slack  │         │\n│  └──────────┘  └──────────┘  └──────────┘  └──────────┘         │\n└───────────────────────────────────────────────────────────────────┘\n```\n\n### Pattern 2: Sync Gateway Architecture\n\n```typescript\n\u002F\u002F src\u002Farchitecture\u002Fsync-gateway.ts\n\ninterface SyncGatewayConfig {\n  pollInterval: number;\n  batchSize: number;\n  retryPolicy: RetryPolicy;\n}\n\nclass MaintainXSyncGateway {\n  private client: MaintainXClient;\n  private cache: CacheManager;\n  private eventEmitter: EventEmitter;\n  private syncState: Map\u003Cstring, Date>;\n\n  constructor(config: SyncGatewayConfig) {\n    this.client = new CachedMaintainXClient(new MaintainXClient());\n    this.cache = new CacheManager(process.env.REDIS_URL!);\n    this.eventEmitter = new EventEmitter();\n    this.syncState = new Map();\n  }\n\n  \u002F\u002F Bi-directional sync\n  async sync(): Promise\u003CSyncResult> {\n    const result: SyncResult = {\n      inbound: { created: 0, updated: 0, deleted: 0 },\n      outbound: { created: 0, updated: 0, deleted: 0 },\n    };\n\n    \u002F\u002F Inbound: MaintainX -> Local\n    await this.syncInbound(result.inbound);\n\n    \u002F\u002F Outbound: Local -> MaintainX\n    await this.syncOutbound(result.outbound);\n\n    return result;\n  }\n\n  private async syncInbound(stats: SyncStats): Promise\u003Cvoid> {\n    const lastSync = this.syncState.get('workorders') || new Date(0);\n\n    \u002F\u002F Fetch changes since last sync\n    const changes = await this.client.getWorkOrders({\n      updatedAfter: lastSync.toISOString(),\n      limit: 100,\n    });\n\n    for (const wo of changes.workOrders) {\n      const local = await this.localStore.getWorkOrder(wo.id);\n\n      if (!local) {\n        await this.localStore.createWorkOrder(wo);\n        stats.created++;\n        this.eventEmitter.emit('workorder:created', wo);\n      } else if (new Date(wo.updatedAt) > new Date(local.updatedAt)) {\n        await this.localStore.updateWorkOrder(wo);\n        stats.updated++;\n        this.eventEmitter.emit('workorder:updated', wo);\n      }\n    }\n\n    this.syncState.set('workorders', new Date());\n  }\n\n  private async syncOutbound(stats: SyncStats): Promise\u003Cvoid> {\n    \u002F\u002F Get pending local changes\n    const pendingChanges = await this.localStore.getPendingChanges();\n\n    for (const change of pendingChanges) {\n      try {\n        switch (change.action) {\n          case 'create':\n            await this.client.createWorkOrder(change.data);\n            stats.created++;\n            break;\n          case 'update':\n            \u002F\u002F await this.client.updateWorkOrder(change.id, change.data);\n            stats.updated++;\n            break;\n        }\n\n        await this.localStore.markSynced(change.id);\n      } catch (error) {\n        console.error(`Failed to sync change ${change.id}:`, error);\n      }\n    }\n  }\n\n  \u002F\u002F Subscribe to events\n  on(event: string, handler: (data: any) => void): void {\n    this.eventEmitter.on(event, handler);\n  }\n}\n```\n\n### Pattern 3: Multi-Tenant Architecture\n\n```typescript\n\u002F\u002F src\u002Farchitecture\u002Fmulti-tenant.ts\n\ninterface Tenant {\n  id: string;\n  name: string;\n  maintainxApiKey: string;\n  maintainxOrgId?: string;\n  config: TenantConfig;\n}\n\nclass MultiTenantMaintainXService {\n  private tenantClients: Map\u003Cstring, MaintainXClient> = new Map();\n  private tenantStore: TenantStore;\n\n  async getClientForTenant(tenantId: string): Promise\u003CMaintainXClient> {\n    \u002F\u002F Check cache\n    if (this.tenantClients.has(tenantId)) {\n      return this.tenantClients.get(tenantId)!;\n    }\n\n    \u002F\u002F Load tenant config\n    const tenant = await this.tenantStore.getTenant(tenantId);\n    if (!tenant) {\n      throw new Error(`Tenant ${tenantId} not found`);\n    }\n\n    \u002F\u002F Create client with tenant's API key\n    const client = new MaintainXClient({\n      apiKey: tenant.maintainxApiKey,\n      orgId: tenant.maintainxOrgId,\n    });\n\n    this.tenantClients.set(tenantId, client);\n    return client;\n  }\n\n  \u002F\u002F Tenant-scoped operations\n  async getWorkOrdersForTenant(\n    tenantId: string,\n    params?: WorkOrderQueryParams\n  ): Promise\u003CWorkOrder[]> {\n    const client = await this.getClientForTenant(tenantId);\n    const response = await client.getWorkOrders(params);\n    return response.workOrders;\n  }\n\n  \u002F\u002F Cross-tenant aggregation (for admin dashboards)\n  async getWorkOrderCountByTenant(): Promise\u003CMap\u003Cstring, number>> {\n    const counts = new Map\u003Cstring, number>();\n    const tenants = await this.tenantStore.getAllTenants();\n\n    await Promise.all(\n      tenants.map(async (tenant) => {\n        const client = await this.getClientForTenant(tenant.id);\n        const response = await client.getWorkOrders({ limit: 1 });\n        \u002F\u002F Use total from response metadata if available\n        counts.set(tenant.id, response.workOrders.length);\n      })\n    );\n\n    return counts;\n  }\n}\n```\n\n### Pattern 4: CQRS with Event Sourcing\n\n```typescript\n\u002F\u002F src\u002Farchitecture\u002Fcqrs.ts\n\n\u002F\u002F Commands - Write side\ninterface CreateWorkOrderCommand {\n  type: 'CreateWorkOrder';\n  payload: {\n    title: string;\n    description?: string;\n    priority: string;\n    assetId?: string;\n  };\n  metadata: {\n    userId: string;\n    timestamp: Date;\n  };\n}\n\nclass CommandHandler {\n  private client: MaintainXClient;\n  private eventStore: EventStore;\n\n  async handle(command: CreateWorkOrderCommand): Promise\u003Cvoid> {\n    \u002F\u002F Execute command\n    const workOrder = await this.client.createWorkOrder(command.payload);\n\n    \u002F\u002F Store event\n    await this.eventStore.append({\n      streamId: `workorder-${workOrder.id}`,\n      type: 'WorkOrderCreated',\n      data: workOrder,\n      metadata: command.metadata,\n    });\n\n    \u002F\u002F Publish event for projections\n    await this.eventBus.publish('WorkOrderCreated', workOrder);\n  }\n}\n\n\u002F\u002F Queries - Read side\ninterface WorkOrderReadModel {\n  id: string;\n  title: string;\n  status: string;\n  priority: string;\n  assetName?: string;\n  locationName?: string;\n  createdAt: Date;\n  \u002F\u002F Denormalized for fast reads\n}\n\nclass WorkOrderProjection {\n  private readStore: ReadStore;\n\n  \u002F\u002F Event handlers update read model\n  async onWorkOrderCreated(event: WorkOrderCreatedEvent): Promise\u003Cvoid> {\n    await this.readStore.upsert({\n      id: event.data.id,\n      title: event.data.title,\n      status: event.data.status,\n      priority: event.data.priority,\n      assetName: event.data.asset?.name,\n      locationName: event.data.location?.name,\n      createdAt: new Date(event.data.createdAt),\n    });\n  }\n\n  \u002F\u002F Fast read queries\n  async getOpenWorkOrders(): Promise\u003CWorkOrderReadModel[]> {\n    return this.readStore.find({ status: 'OPEN' });\n  }\n}\n```\n\n### Pattern 5: Microservices Integration\n\n```\n┌─────────────────────────────────────────────────────────────────────┐\n│                        API Gateway                                   │\n│                     (Kong \u002F AWS API GW)                              │\n└─────────────────────────────────┬───────────────────────────────────┘\n                                  │\n        ┌─────────────────────────┼─────────────────────────┐\n        │                         │                         │\n        ▼                         ▼                         ▼\n┌───────────────────┐  ┌───────────────────┐  ┌───────────────────┐\n│ Work Order Service │  │   Asset Service   │  │ Notification Svc  │\n│                    │  │                    │  │                   │\n│ ┌────────────────┐ │  │ ┌────────────────┐ │  │ ┌───────────────┐│\n│ │MaintainX Client│ │  │ │MaintainX Client│ │  │ │ Slack\u002FEmail   ││\n│ └────────────────┘ │  │ └────────────────┘ │  │ └───────────────┘│\n│ ┌────────────────┐ │  │ ┌────────────────┐ │  │ ┌───────────────┐│\n│ │   PostgreSQL   │ │  │ │   PostgreSQL   │ │  │ │    Redis      ││\n│ └────────────────┘ │  │ └────────────────┘ │  │ └───────────────┘│\n└─────────┬──────────┘  └─────────┬──────────┘  └─────────┬────────┘\n          │                       │                       │\n          └───────────────────────┼───────────────────────┘\n                                  │\n                          ┌───────▼───────┐\n                          │  Message Bus   │\n                          │ (Kafka\u002FRabbitMQ)│\n                          └───────────────┘\n```\n\n## Implementation Guidelines\n\n### Separation of Concerns\n\n```typescript\n\u002F\u002F src\u002Flayers\u002Fdomain.ts - Business logic\nclass WorkOrderDomain {\n  canTransitionTo(currentStatus: string, newStatus: string): boolean {\n    \u002F\u002F Business rules only - no MaintainX specifics\n  }\n}\n\n\u002F\u002F src\u002Flayers\u002Fapplication.ts - Use cases\nclass WorkOrderService {\n  async completeWorkOrder(id: string, completionData: any): Promise\u003Cvoid> {\n    \u002F\u002F Orchestrates domain + infrastructure\n  }\n}\n\n\u002F\u002F src\u002Flayers\u002Finfrastructure.ts - MaintainX integration\nclass MaintainXRepository {\n  async save(workOrder: WorkOrderEntity): Promise\u003Cvoid> {\n    \u002F\u002F MaintainX API calls\n  }\n}\n```\n\n### Error Boundaries\n\n```typescript\n\u002F\u002F src\u002Farchitecture\u002Ferror-boundaries.ts\n\nclass MaintainXIntegrationError extends Error {\n  constructor(\n    message: string,\n    public readonly code: string,\n    public readonly retryable: boolean = false\n  ) {\n    super(message);\n    this.name = 'MaintainXIntegrationError';\n  }\n}\n\n\u002F\u002F Wrap all MaintainX calls\nasync function withErrorBoundary\u003CT>(\n  operation: () => Promise\u003CT>,\n  context: string\n): Promise\u003CT> {\n  try {\n    return await operation();\n  } catch (error: any) {\n    const status = error.response?.status;\n\n    if (status === 429) {\n      throw new MaintainXIntegrationError(\n        'Rate limited',\n        'RATE_LIMITED',\n        true\n      );\n    }\n\n    if (status >= 500) {\n      throw new MaintainXIntegrationError(\n        'MaintainX service unavailable',\n        'SERVICE_UNAVAILABLE',\n        true\n      );\n    }\n\n    throw new MaintainXIntegrationError(\n      `${context}: ${error.message}`,\n      'INTEGRATION_ERROR',\n      false\n    );\n  }\n}\n```\n\n## Output\n\n- Event-driven architecture pattern\n- Sync gateway for bi-directional sync\n- Multi-tenant architecture\n- CQRS with event sourcing\n- Microservices integration\n\n## Architecture Decision Records\n\n| Decision | Choice | Rationale |\n|----------|--------|-----------|\n| API caching | Redis | Fast, supports TTL, cluster mode |\n| Message queue | Redis\u002FSQS | Simple, reliable, scales well |\n| Database | PostgreSQL | ACID, JSON support, mature |\n| Event store | PostgreSQL | Simplicity over dedicated event store |\n\n## Resources\n\n- [MaintainX API Documentation](https:\u002F\u002Fmaintainx.dev\u002F)\n- [Martin Fowler - Patterns](https:\u002F\u002Fmartinfowler.com\u002F)\n- [Microsoft - Cloud Design Patterns](https:\u002F\u002Fdocs.microsoft.com\u002Fen-us\u002Fazure\u002Farchitecture\u002Fpatterns\u002F)\n\n## Next Steps\n\nFor multi-environment setup, see `maintainx-multi-env-setup`.\n","# MaintainX Reference Architecture\n\n## Overview\n\nProduction-grade architecture patterns for building scalable, maintainable MaintainX integrations.\n\n## Prerequisites\n\n- Understanding of distributed systems\n- Cloud platform experience\n- MaintainX API familiarity\n\n## Architecture Patterns\n\n### Pattern 1: Event-Driven Integration\n\n```\n┌─────────────────────────────────────────────────────────────────┐\n│                     MaintainX Platform                          │\n│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐         │\n│  │ Work Orders  │  │   Assets     │  │  Locations   │         │\n│  └──────┬───────┘  └──────┬───────┘  └──────┬───────┘         │\n│         │                 │                 │                  │\n│         └─────────────────┼─────────────────┘                  │\n│                           │                                    │\n│                    ┌──────▼──────┐                             │\n│                    │  Webhooks   │                             │\n│                    └──────┬──────┘                             │\n└───────────────────────────┼─────────────────────────────────────┘\n                            │\n                            ▼\n┌───────────────────────────────────────────────────────────────────┐\n│                    Your Integration Layer                          │\n│                                                                    │\n│  ┌────────────────┐    ┌────────────────┐    ┌────────────────┐  │\n│  │ Webhook Handler│───▶│  Event Queue   │───▶│ Event Processor│  │\n│  │   (Express)    │    │   (Redis\u002FSQS)  │    │   (Workers)    │  │\n│  └────────────────┘    └────────────────┘    └───────┬────────┘  │\n│                                                      │           │\n│  ┌────────────────┐    ┌────────────────┐    ┌──────▼────────┐  │\n│  │  API Gateway   │───▶│ MaintainX Client│───▶│  Data Store   │  │\n│  │   (REST\u002FGraphQL)    │   (Cached)     │    │  (PostgreSQL) │  │\n│  └────────────────┘    └────────────────┘    └───────────────┘  │\n│                                                                    │\n└───────────────────────────────────────────────────────────────────┘\n                            │\n                            ▼\n┌───────────────────────────────────────────────────────────────────┐\n│                    External Systems                                │\n│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐         │\n│  │   ERP    │  │   SCADA  │  │  BI\u002FReports│ │  Slack  │         │\n│  └──────────┘  └──────────┘  └──────────┘  └──────────┘         │\n└───────────────────────────────────────────────────────────────────┘\n```\n\n### Pattern 2: Sync Gateway Architecture\n\n```typescript\n\u002F\u002F src\u002Farchitecture\u002Fsync-gateway.ts\n\ninterface SyncGatewayConfig {\n  pollInterval: number;\n  batchSize: number;\n  retryPolicy: RetryPolicy;\n}\n\nclass MaintainXSyncGateway {\n  private client: MaintainXClient;\n  private cache: CacheManager;\n  private eventEmitter: EventEmitter;\n  private syncState: Map\u003Cstring, Date>;\n\n  constructor(config: SyncGatewayConfig) {\n    this.client = new CachedMaintainXClient(new MaintainXClient());\n    this.cache = new CacheManager(process.env.REDIS_URL!);\n    this.eventEmitter = new EventEmitter();\n    this.syncState = new Map();\n  }\n\n  \u002F\u002F Bi-directional sync\n  async sync(): Promise\u003CSyncResult> {\n    const result: SyncResult = {\n      inbound: { created: 0, updated: 0, deleted: 0 },\n      outbound: { created: 0, updated: 0, deleted: 0 },\n    };\n\n    \u002F\u002F Inbound: MaintainX -> Local\n    await this.syncInbound(result.inbound);\n\n    \u002F\u002F Outbound: Local -> MaintainX\n    await this.syncOutbound(result.outbound);\n\n    return result;\n  }\n\n  private async syncInbound(stats: SyncStats): Promise\u003Cvoid> {\n    const lastSync = this.syncState.get('workorders') || new Date(0);\n\n    \u002F\u002F Fetch changes since last sync\n    const changes = await this.client.getWorkOrders({\n      updatedAfter: lastSync.toISOString(),\n      limit: 100,\n    });\n\n    for (const wo of changes.workOrders) {\n      const local = await this.localStore.getWorkOrder(wo.id);\n\n      if (!local) {\n        await this.localStore.createWorkOrder(wo);\n        stats.created++;\n        this.eventEmitter.emit('workorder:created', wo);\n      } else if (new Date(wo.updatedAt) > new Date(local.updatedAt)) {\n        await this.localStore.updateWorkOrder(wo);\n        stats.updated++;\n        this.eventEmitter.emit('workorder:updated', wo);\n      }\n    }\n\n    this.syncState.set('workorders', new Date());\n  }\n\n  private async syncOutbound(stats: SyncStats): Promise\u003Cvoid> {\n    \u002F\u002F Get pending local changes\n    const pendingChanges = await this.localStore.getPendingChanges();\n\n    for (const change of pendingChanges) {\n      try {\n        switch (change.action) {\n          case 'create':\n            await this.client.createWorkOrder(change.data);\n            stats.created++;\n            break;\n          case 'update':\n            \u002F\u002F await this.client.updateWorkOrder(change.id, change.data);\n            stats.updated++;\n            break;\n        }\n\n        await this.localStore.markSynced(change.id);\n      } catch (error) {\n        console.error(`Failed to sync change ${change.id}:`, error);\n      }\n    }\n  }\n\n  \u002F\u002F Subscribe to events\n  on(event: string, handler: (data: any) => void): void {\n    this.eventEmitter.on(event, handler);\n  }\n}\n```\n\n### Pattern 3: Multi-Tenant Architecture\n\n```typescript\n\u002F\u002F src\u002Farchitecture\u002Fmulti-tenant.ts\n\ninterface Tenant {\n  id: string;\n  name: string;\n  maintainxApiKey: string;\n  maintainxOrgId?: string;\n  config: TenantConfig;\n}\n\nclass MultiTenantMaintainXService {\n  private tenantClients: Map\u003Cstring, MaintainXClient> = new Map();\n  private tenantStore: TenantStore;\n\n  async getClientForTenant(tenantId: string): Promise\u003CMaintainXClient> {\n    \u002F\u002F Check cache\n    if (this.tenantClients.has(tenantId)) {\n      return this.tenantClients.get(tenantId)!;\n    }\n\n    \u002F\u002F Load tenant config\n    const tenant = await this.tenantStore.getTenant(tenantId);\n    if (!tenant) {\n      throw new Error(`Tenant ${tenantId} not found`);\n    }\n\n    \u002F\u002F Create client with tenant's API key\n    const client = new MaintainXClient({\n      apiKey: tenant.maintainxApiKey,\n      orgId: tenant.maintainxOrgId,\n    });\n\n    this.tenantClients.set(tenantId, client);\n    return client;\n  }\n\n  \u002F\u002F Tenant-scoped operations\n  async getWorkOrdersForTenant(\n    tenantId: string,\n    params?: WorkOrderQueryParams\n  ): Promise\u003CWorkOrder[]> {\n    const client = await this.getClientForTenant(tenantId);\n    const response = await client.getWorkOrders(params);\n    return response.workOrders;\n  }\n\n  \u002F\u002F Cross-tenant aggregation (for admin dashboards)\n  async getWorkOrderCountByTenant(): Promise\u003CMap\u003Cstring, number>> {\n    const counts = new Map\u003Cstring, number>();\n    const tenants = await this.tenantStore.getAllTenants();\n\n    await Promise.all(\n      tenants.map(async (tenant) => {\n        const client = await this.getClientForTenant(tenant.id);\n        const response = await client.getWorkOrders({ limit: 1 });\n        \u002F\u002F Use total from response metadata if available\n        counts.set(tenant.id, response.workOrders.length);\n      })\n    );\n\n    return counts;\n  }\n}\n```\n\n### Pattern 4: CQRS with Event Sourcing\n\n```typescript\n\u002F\u002F src\u002Farchitecture\u002Fcqrs.ts\n\n\u002F\u002F Commands - Write side\ninterface CreateWorkOrderCommand {\n  type: 'CreateWorkOrder';\n  payload: {\n    title: string;\n    description?: string;\n    priority: string;\n    assetId?: string;\n  };\n  metadata: {\n    userId: string;\n    timestamp: Date;\n  };\n}\n\nclass CommandHandler {\n  private client: MaintainXClient;\n  private eventStore: EventStore;\n\n  async handle(command: CreateWorkOrderCommand): Promise\u003Cvoid> {\n    \u002F\u002F Execute command\n    const workOrder = await this.client.createWorkOrder(command.payload);\n\n    \u002F\u002F Store event\n    await this.eventStore.append({\n      streamId: `workorder-${workOrder.id}`,\n      type: 'WorkOrderCreated',\n      data: workOrder,\n      metadata: command.metadata,\n    });\n\n    \u002F\u002F Publish event for projections\n    await this.eventBus.publish('WorkOrderCreated', workOrder);\n  }\n}\n\n\u002F\u002F Queries - Read side\ninterface WorkOrderReadModel {\n  id: string;\n  title: string;\n  status: string;\n  priority: string;\n  assetName?: string;\n  locationName?: string;\n  createdAt: Date;\n  \u002F\u002F Denormalized for fast reads\n}\n\nclass WorkOrderProjection {\n  private readStore: ReadStore;\n\n  \u002F\u002F Event handlers update read model\n  async onWorkOrderCreated(event: WorkOrderCreatedEvent): Promise\u003Cvoid> {\n    await this.readStore.upsert({\n      id: event.data.id,\n      title: event.data.title,\n      status: event.data.status,\n      priority: event.data.priority,\n      assetName: event.data.asset?.name,\n      locationName: event.data.location?.name,\n      createdAt: new Date(event.data.createdAt),\n    });\n  }\n\n  \u002F\u002F Fast read queries\n  async getOpenWorkOrders(): Promise\u003CWorkOrderReadModel[]> {\n    return this.readStore.find({ status: 'OPEN' });\n  }\n}\n```\n\n### Pattern 5: Microservices Integration\n\n```\n┌─────────────────────────────────────────────────────────────────────┐\n│                        API Gateway                                   │\n│                     (Kong \u002F AWS API GW)                              │\n└─────────────────────────────────┬───────────────────────────────────┘\n                                  │\n        ┌─────────────────────────┼─────────────────────────┐\n        │                         │                         │\n        ▼                         ▼                         ▼\n┌───────────────────┐  ┌───────────────────┐  ┌───────────────────┐\n│ Work Order Service │  │   Asset Service   │  │ Notification Svc  │\n│                    │  │                    │  │                   │\n│ ┌────────────────┐ │  │ ┌────────────────┐ │  │ ┌───────────────┐│\n│ │MaintainX Client│ │  │ │MaintainX Client│ │  │ │ Slack\u002FEmail   ││\n│ └────────────────┘ │  │ └────────────────┘ │  │ └───────────────┘│\n│ ┌────────────────┐ │  │ ┌────────────────┐ │  │ ┌───────────────┐│\n│ │   PostgreSQL   │ │  │ │   PostgreSQL   │ │  │ │    Redis      ││\n│ └────────────────┘ │  │ └────────────────┘ │  │ └───────────────┘│\n└─────────┬──────────┘  └─────────┬──────────┘  └─────────┬────────┘\n          │                       │                       │\n          └───────────────────────┼───────────────────────┘\n                                  │\n                          ┌───────▼───────┐\n                          │  Message Bus   │\n                          │ (Kafka\u002FRabbitMQ)│\n                          └───────────────┘\n```\n\n## Implementation Guidelines\n\n### Separation of Concerns\n\n```typescript\n\u002F\u002F src\u002Flayers\u002Fdomain.ts - Business logic\nclass WorkOrderDomain {\n  canTransitionTo(currentStatus: string, newStatus: string): boolean {\n    \u002F\u002F Business rules only - no MaintainX specifics\n  }\n}\n\n\u002F\u002F src\u002Flayers\u002Fapplication.ts - Use cases\nclass WorkOrderService {\n  async completeWorkOrder(id: string, completionData: any): Promise\u003Cvoid> {\n    \u002F\u002F Orchestrates domain + infrastructure\n  }\n}\n\n\u002F\u002F src\u002Flayers\u002Finfrastructure.ts - MaintainX integration\nclass MaintainXRepository {\n  async save(workOrder: WorkOrderEntity): Promise\u003Cvoid> {\n    \u002F\u002F MaintainX API calls\n  }\n}\n```\n\n### Error Boundaries\n\n```typescript\n\u002F\u002F src\u002Farchitecture\u002Ferror-boundaries.ts\n\nclass MaintainXIntegrationError extends Error {\n  constructor(\n    message: string,\n    public readonly code: string,\n    public readonly retryable: boolean = false\n  ) {\n    super(message);\n    this.name = 'MaintainXIntegrationError';\n  }\n}\n\n\u002F\u002F Wrap all MaintainX calls\nasync function withErrorBoundary\u003CT>(\n  operation: () => Promise\u003CT>,\n  context: string\n): Promise\u003CT> {\n  try {\n    return await operation();\n  } catch (error: any) {\n    const status = error.response?.status;\n\n    if (status === 429) {\n      throw new MaintainXIntegrationError(\n        'Rate limited',\n        'RATE_LIMITED',\n        true\n      );\n    }\n\n    if (status >= 500) {\n      throw new MaintainXIntegrationError(\n        'MaintainX service unavailable',\n        'SERVICE_UNAVAILABLE',\n        true\n      );\n    }\n\n    throw new MaintainXIntegrationError(\n      `${context}: ${error.message}`,\n      'INTEGRATION_ERROR',\n      false\n    );\n  }\n}\n```\n\n## Output\n\n- Event-driven architecture pattern\n- Sync gateway for bi-directional sync\n- Multi-tenant architecture\n- CQRS with event sourcing\n- Microservices integration\n\n## Architecture Decision Records\n\n| Decision | Choice | Rationale |\n|----------|--------|-----------|\n| API caching | Redis | Fast, supports TTL, cluster mode |\n| Message queue | Redis\u002FSQS | Simple, reliable, scales well |\n| Database | PostgreSQL | ACID, JSON support, mature |\n| Event store | PostgreSQL | Simplicity over dedicated event store |\n\n## Resources\n\n- [MaintainX API Documentation](https:\u002F\u002Fmaintainx.dev\u002F)\n- [Martin Fowler - Patterns](https:\u002F\u002Fmartinfowler.com\u002F)\n- [Microsoft - Cloud Design Patterns](https:\u002F\u002Fdocs.microsoft.com\u002Fen-us\u002Fazure\u002Farchitecture\u002Fpatterns\u002F)\n\n## Next Steps\n\nFor multi-environment setup, see `maintainx-multi-env-setup`.\n",{"name":5,"author":47,"license":15,"version":48,"description":49,"allowed-tools":50},"Jeremy Longshore \u003Cjeremy@intentsolutions.io>","1.0.0","Production-grade architecture patterns for MaintainX integrations.\nUse when designing system architecture, planning integrations,\nor building enterprise-scale MaintainX solutions.\nTrigger with phrases like \"maintainx architecture\", \"maintainx design\",\n\"maintainx system design\", \"maintainx enterprise\", \"maintainx patterns\".\n","Read, Write, Edit","main","90b50ed0778745a80fd5bfb13b1843d45b9e82f7","tests\u002Fext_conformance\u002Fartifacts\u002Fplugins-community\u002Fplugins\u002Fsaas-packs\u002Fmaintainx-pack\u002Fskills\u002Fmaintainx-reference-architecture",231,"https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust","https:\u002F\u002Fgithub.com\u002FDicklesworthstone","https:\u002F\u002Fwww.jeffreyemanuel.com\u002F","Building in NY","2026-11-12 03:15:57",{"source":8,"skillName":5,"commands":61,"prompt":71,"zipAvailable":72},[62,65,68],{"tool":63,"command":64},"npx","npx skills add Dicklesworthstone\u002Fpi_agent_rust --skill maintainx-reference-architecture",{"tool":66,"command":67},"bunx","bunx skills add Dicklesworthstone\u002Fpi_agent_rust --skill maintainx-reference-architecture",{"tool":69,"command":70},"pnpm","pnpm dlx skills add Dicklesworthstone\u002Fpi_agent_rust --skill maintainx-reference-architecture","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Fplugins-community\u002Fplugins\u002Fsaas-packs\u002Fmaintainx-pack\u002Fskills\u002Fmaintainx-reference-architecture\u002FSKILL.md",true,[],[75,114,138,164,190,212],{"skillNo":76,"name":77,"nameZh":6,"description":78,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":79,"licenseFileUrl":80,"sourceHtmlUrl":81,"categories":82,"keywords":88,"publishedAt":42},"01M6FEGPPK0ZTKCCM0R3E3KS33","web-artifacts-builder","Suite of tools for creating elaborate, multi-component claude.ai HTML artifacts using modern frontend web technologies (React, Tailwind CSS, shadcn\u002Fui). Use for complex artifacts requiring state management, routing, or shadcn\u002Fui components - not for simple single-file HTML\u002FJSX artifacts.","Apache-2.0","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Futilities\u002Fweb-artifacts-builder\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Futilities\u002Fweb-artifacts-builder\u002FSKILL.md",[83],{"categoryNo":84,"categoryName":85,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000009","前端开发","SCENARIO","使用场景",[89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,32,107,108,109,110,111,25,112,113],"web artifacts builder","web","artifacts","artifacts builder","builder","frontend","css","components","react","component","routing","state management","state","shadcn","file","ui","Tools","Tailwind","html","single-file","simple","ui components","multi","jsx","suite",{"skillNo":115,"name":116,"nameZh":6,"description":117,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":79,"licenseFileUrl":118,"sourceHtmlUrl":119,"categories":120,"keywords":125,"publishedAt":42},"01M6FEE9VTK1W4GY21AKREJXRG","webapp-testing","Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fsecurity\u002Fwebapp-testing\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fsecurity\u002Fwebapp-testing\u002FSKILL.md",[121,124],{"categoryNo":122,"categoryName":123,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":84,"categoryName":85,"taxonomyType":86,"taxonomyTypeDesc":87},[126,127,128,94,129,130,90,131,132,133,104,134,135,136,137,26,25],"testing","webapp testing","webapp","screenshots","playwright","debugging","toolkit","browser","logs","applications","behavior","local",{"skillNo":139,"name":140,"nameZh":6,"description":141,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":142,"sourceHtmlUrl":143,"categories":144,"keywords":145,"publishedAt":42},"01M6FE20F7ZTQBFWKF4MPJ2SBX","neuropixels-analysis","Neuropixels neural recording analysis. Load SpikeGLX\u002FOpenEphys data, preprocess, motion correction, Kilosort4 spike sorting, quality metrics, Allen\u002FIBL curation, AI-assisted visual analysis, for Neuropixels 1.0\u002F2.0 extracellular electrophysiology. Use when working with neural recordings, spike sorting, extracellular electrophysiology, or when the user mentions Neuropixels, SpikeGLX, Open Ephys, Kilosort, quality metrics, or unit curation.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fneuropixels-analysis\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fscientific\u002Fneuropixels-analysis\u002FSKILL.md",[],[146,147,148,149,150,151,152,153,32,154,155,156,157,158,159,160,26,161,162,163,25,24],"analysis","neuropixels analysis","spike","metrics","data","open","quality","user","recordings","Neural","motion","visual","quality metrics","unit","sorting","curation","recording","load",{"skillNo":165,"name":166,"nameZh":6,"description":167,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":79,"licenseFileUrl":168,"sourceHtmlUrl":169,"categories":170,"keywords":174,"publishedAt":42},"01M6FDP0PDK6F1GGX395C7625Z","skill-creator","Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Claude's capabilities with specialized knowledge, workflows, or tool integrations.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fskill-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fskill-creator\u002FSKILL.md",[171],{"categoryNo":172,"categoryName":173,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000023","Skill与智能体开发",[175,176,177,178,179,180,181,182,36,183,184,185,186,187,26,25,188,24,189],"skill creator","creator","workflows","create","update","capabilities","knowledge","tool","specialized","guide","new skill","existing skill","users","Existing","new",{"skillNo":191,"name":192,"nameZh":6,"description":193,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":194,"sourceHtmlUrl":195,"categories":196,"keywords":198,"publishedAt":42},"01M6FDM8Y7VK7NYG9SM7QPA3PW","notebooklm","Use this skill to query your Google NotebookLM notebooks directly from Claude Code for source-grounded, citation-backed answers from Gemini. Browser automation, library management, persistent auth. Drastically reduced hallucinations through document-only responses.","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fnotebooklm\u002FLICENSE","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fproductivity\u002Fnotebooklm\u002FSKILL.md",[197],{"categoryNo":172,"categoryName":173,"taxonomyType":86,"taxonomyTypeDesc":87},[192,199,200,201,202,203,204,133,205,206,32,207,208,209,210,25,211],"google","browser automation","gemini","automation","auth","code","library","management","only","document","query","Citation","source",{"skillNo":213,"name":214,"nameZh":6,"description":215,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":79,"licenseFileUrl":216,"sourceHtmlUrl":217,"categories":218,"keywords":225,"publishedAt":42},"01M6FDHPXE10J3XGTCH5HBHS1M","slack-gif-creator","Knowledge and utilities for creating animated GIFs optimized for Slack. Provides constraints, validation tools, and animation concepts. Use when users request animated GIFs for Slack like \"make me a GIF of X doing Y for Slack.\"","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fenterprise-communication\u002Fslack-gif-creator\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002FDicklesworthstone\u002Fpi_agent_rust\u002Fblob\u002Fmain\u002Ftests\u002Fext_conformance\u002Fartifacts\u002Ftemplates-davila7\u002Fcli-tool\u002Fcomponents\u002Fskills\u002Fenterprise-communication\u002Fslack-gif-creator\u002FSKILL.md",[219,222],{"categoryNo":220,"categoryName":221,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000005","邮件与沟通",{"categoryNo":223,"categoryName":224,"taxonomyType":86,"taxonomyTypeDesc":87},"01JBSEEDCAT000000000000016","图像与多媒体",[226,227,228,176,229,105,230,231,181,32,232,187,233,234,235,25,236,24],"slack gif creator","slack","gif","validation","constraints","Animation","me","make","Utilities","concepts","request"]