services-as-software 0.1.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/.turbo/turbo-build.log +5 -0
  2. package/CHANGELOG.md +10 -0
  3. package/README.md +235 -225
  4. package/dist/client.d.ts +25 -0
  5. package/dist/client.d.ts.map +1 -0
  6. package/dist/client.js +103 -0
  7. package/dist/client.js.map +1 -0
  8. package/dist/endpoint.d.ts +102 -0
  9. package/dist/endpoint.d.ts.map +1 -0
  10. package/dist/endpoint.js +96 -0
  11. package/dist/endpoint.js.map +1 -0
  12. package/dist/entities/billing.d.ts +60 -0
  13. package/dist/entities/billing.d.ts.map +1 -0
  14. package/dist/entities/billing.js +954 -0
  15. package/dist/entities/billing.js.map +1 -0
  16. package/dist/entities/customers.d.ts +45 -0
  17. package/dist/entities/customers.d.ts.map +1 -0
  18. package/dist/entities/customers.js +679 -0
  19. package/dist/entities/customers.js.map +1 -0
  20. package/dist/entities/delivery.d.ts +59 -0
  21. package/dist/entities/delivery.d.ts.map +1 -0
  22. package/dist/entities/delivery.js +890 -0
  23. package/dist/entities/delivery.js.map +1 -0
  24. package/dist/entities/index.d.ts +114 -0
  25. package/dist/entities/index.d.ts.map +1 -0
  26. package/dist/entities/index.js +89 -0
  27. package/dist/entities/index.js.map +1 -0
  28. package/dist/entities/operations.d.ts +59 -0
  29. package/dist/entities/operations.d.ts.map +1 -0
  30. package/dist/entities/operations.js +1010 -0
  31. package/dist/entities/operations.js.map +1 -0
  32. package/dist/entities/orchestration.d.ts +52 -0
  33. package/dist/entities/orchestration.d.ts.map +1 -0
  34. package/dist/entities/orchestration.js +883 -0
  35. package/dist/entities/orchestration.js.map +1 -0
  36. package/dist/entities/services.d.ts +50 -0
  37. package/dist/entities/services.d.ts.map +1 -0
  38. package/dist/entities/services.js +805 -0
  39. package/dist/entities/services.js.map +1 -0
  40. package/dist/helpers.d.ts +362 -0
  41. package/dist/helpers.d.ts.map +1 -0
  42. package/dist/helpers.js +400 -0
  43. package/dist/helpers.js.map +1 -0
  44. package/dist/index.d.ts +17 -215
  45. package/dist/index.d.ts.map +1 -0
  46. package/dist/index.js +18 -172
  47. package/dist/index.js.map +1 -0
  48. package/dist/provider.d.ts +85 -0
  49. package/dist/provider.d.ts.map +1 -0
  50. package/dist/provider.js +158 -0
  51. package/dist/provider.js.map +1 -0
  52. package/dist/service.d.ts +43 -0
  53. package/dist/service.d.ts.map +1 -0
  54. package/dist/service.js +206 -0
  55. package/dist/service.js.map +1 -0
  56. package/dist/types.d.ts +469 -0
  57. package/dist/types.d.ts.map +1 -0
  58. package/dist/types.js +5 -0
  59. package/dist/types.js.map +1 -0
  60. package/examples/client-usage.ts +82 -0
  61. package/examples/translation-service.ts +227 -0
  62. package/package.json +24 -38
  63. package/src/client.ts +132 -0
  64. package/src/endpoint.ts +144 -0
  65. package/src/entities/billing.ts +1037 -0
  66. package/src/entities/customers.ts +740 -0
  67. package/src/entities/delivery.ts +974 -0
  68. package/src/entities/index.ts +157 -0
  69. package/src/entities/operations.ts +1099 -0
  70. package/src/entities/orchestration.ts +956 -0
  71. package/src/entities/services.ts +872 -0
  72. package/src/helpers.ts +474 -0
  73. package/src/index.ts +97 -0
  74. package/src/provider.ts +183 -0
  75. package/src/service.test.ts +195 -0
  76. package/src/service.ts +266 -0
  77. package/src/types.ts +543 -0
  78. package/tsconfig.json +9 -0
@@ -0,0 +1,1099 @@
1
+ /**
2
+ * Operations Entity Types (Nouns)
3
+ *
4
+ * Service operations: SLA, SLO, ServiceIncident, SupportTicket, ServiceFeedback, ServiceMetric
5
+ *
6
+ * @packageDocumentation
7
+ */
8
+
9
+ import type { Noun } from 'ai-database'
10
+
11
+ // =============================================================================
12
+ // SLA
13
+ // =============================================================================
14
+
15
+ /**
16
+ * SLA entity
17
+ *
18
+ * Service Level Agreement.
19
+ */
20
+ export const SLA: Noun = {
21
+ singular: 'sla',
22
+ plural: 'slas',
23
+ description: 'A Service Level Agreement defining commitments',
24
+
25
+ properties: {
26
+ // Identity
27
+ name: {
28
+ type: 'string',
29
+ description: 'SLA name',
30
+ },
31
+ description: {
32
+ type: 'string',
33
+ optional: true,
34
+ description: 'SLA description',
35
+ },
36
+ version: {
37
+ type: 'string',
38
+ optional: true,
39
+ description: 'SLA version',
40
+ },
41
+
42
+ // Tier
43
+ tier: {
44
+ type: 'string',
45
+ optional: true,
46
+ description: 'SLA tier',
47
+ examples: ['basic', 'standard', 'premium', 'enterprise'],
48
+ },
49
+
50
+ // Availability
51
+ uptimeTarget: {
52
+ type: 'number',
53
+ optional: true,
54
+ description: 'Uptime target percentage (e.g., 99.9)',
55
+ },
56
+ uptimeCalculation: {
57
+ type: 'string',
58
+ optional: true,
59
+ description: 'How uptime is calculated',
60
+ examples: ['monthly', 'quarterly', 'yearly'],
61
+ },
62
+
63
+ // Response Times
64
+ responseTimeTarget: {
65
+ type: 'number',
66
+ optional: true,
67
+ description: 'Target response time (ms)',
68
+ },
69
+ responseTimeP50: {
70
+ type: 'number',
71
+ optional: true,
72
+ description: 'P50 response time target (ms)',
73
+ },
74
+ responseTimeP99: {
75
+ type: 'number',
76
+ optional: true,
77
+ description: 'P99 response time target (ms)',
78
+ },
79
+
80
+ // Support
81
+ supportResponseTime: {
82
+ type: 'string',
83
+ optional: true,
84
+ description: 'Support response time target',
85
+ },
86
+ supportHours: {
87
+ type: 'string',
88
+ optional: true,
89
+ description: 'Support hours',
90
+ examples: ['24/7', 'business-hours', '9-5'],
91
+ },
92
+ supportChannels: {
93
+ type: 'string',
94
+ array: true,
95
+ optional: true,
96
+ description: 'Support channels',
97
+ examples: ['email', 'chat', 'phone', 'slack'],
98
+ },
99
+
100
+ // Credits
101
+ creditPolicy: {
102
+ type: 'json',
103
+ optional: true,
104
+ description: 'Credit policy for SLA breaches',
105
+ },
106
+ maxCredit: {
107
+ type: 'number',
108
+ optional: true,
109
+ description: 'Maximum credit percentage',
110
+ },
111
+
112
+ // Exclusions
113
+ exclusions: {
114
+ type: 'string',
115
+ array: true,
116
+ optional: true,
117
+ description: 'SLA exclusions',
118
+ },
119
+ maintenanceWindows: {
120
+ type: 'json',
121
+ optional: true,
122
+ description: 'Scheduled maintenance windows',
123
+ },
124
+
125
+ // Dates
126
+ effectiveFrom: {
127
+ type: 'date',
128
+ optional: true,
129
+ description: 'Effective from date',
130
+ },
131
+ effectiveUntil: {
132
+ type: 'date',
133
+ optional: true,
134
+ description: 'Effective until date',
135
+ },
136
+
137
+ // Status
138
+ status: {
139
+ type: 'string',
140
+ description: 'SLA status',
141
+ examples: ['draft', 'active', 'superseded', 'expired'],
142
+ },
143
+ },
144
+
145
+ relationships: {
146
+ service: {
147
+ type: 'ProductizedService',
148
+ description: 'Service this SLA covers',
149
+ },
150
+ objectives: {
151
+ type: 'SLO[]',
152
+ description: 'Service level objectives',
153
+ },
154
+ incidents: {
155
+ type: 'ServiceIncident[]',
156
+ description: 'Related incidents',
157
+ },
158
+ },
159
+
160
+ actions: [
161
+ 'create',
162
+ 'update',
163
+ 'activate',
164
+ 'supersede',
165
+ 'expire',
166
+ ],
167
+
168
+ events: [
169
+ 'created',
170
+ 'updated',
171
+ 'activated',
172
+ 'superseded',
173
+ 'expired',
174
+ 'breached',
175
+ ],
176
+ }
177
+
178
+ // =============================================================================
179
+ // SLO
180
+ // =============================================================================
181
+
182
+ /**
183
+ * SLO entity
184
+ *
185
+ * Service Level Objective.
186
+ */
187
+ export const SLO: Noun = {
188
+ singular: 'slo',
189
+ plural: 'slos',
190
+ description: 'A Service Level Objective defining a specific target',
191
+
192
+ properties: {
193
+ // Identity
194
+ name: {
195
+ type: 'string',
196
+ description: 'SLO name',
197
+ },
198
+ description: {
199
+ type: 'string',
200
+ optional: true,
201
+ description: 'SLO description',
202
+ },
203
+
204
+ // Metric
205
+ metric: {
206
+ type: 'string',
207
+ description: 'Metric being measured',
208
+ examples: ['availability', 'latency', 'throughput', 'error-rate', 'success-rate'],
209
+ },
210
+ metricQuery: {
211
+ type: 'string',
212
+ optional: true,
213
+ description: 'Query to calculate metric',
214
+ },
215
+
216
+ // Target
217
+ target: {
218
+ type: 'number',
219
+ description: 'Target value',
220
+ },
221
+ comparison: {
222
+ type: 'string',
223
+ description: 'Comparison operator',
224
+ examples: ['>=', '<=', '>', '<', '='],
225
+ },
226
+ unit: {
227
+ type: 'string',
228
+ optional: true,
229
+ description: 'Unit of measure',
230
+ },
231
+
232
+ // Window
233
+ windowType: {
234
+ type: 'string',
235
+ description: 'Window type',
236
+ examples: ['rolling', 'calendar'],
237
+ },
238
+ windowDuration: {
239
+ type: 'string',
240
+ optional: true,
241
+ description: 'Window duration',
242
+ examples: ['30d', '7d', '1h', '1m'],
243
+ },
244
+
245
+ // Error Budget
246
+ errorBudget: {
247
+ type: 'number',
248
+ optional: true,
249
+ description: 'Error budget (as percentage)',
250
+ },
251
+ errorBudgetRemaining: {
252
+ type: 'number',
253
+ optional: true,
254
+ description: 'Remaining error budget',
255
+ },
256
+ burnRate: {
257
+ type: 'number',
258
+ optional: true,
259
+ description: 'Current burn rate',
260
+ },
261
+
262
+ // Current State
263
+ currentValue: {
264
+ type: 'number',
265
+ optional: true,
266
+ description: 'Current metric value',
267
+ },
268
+ lastCalculatedAt: {
269
+ type: 'date',
270
+ optional: true,
271
+ description: 'Last calculation time',
272
+ },
273
+
274
+ // Alerting
275
+ alertThreshold: {
276
+ type: 'number',
277
+ optional: true,
278
+ description: 'Alert threshold',
279
+ },
280
+ alertOnBreach: {
281
+ type: 'boolean',
282
+ optional: true,
283
+ description: 'Alert on breach',
284
+ },
285
+
286
+ // Status
287
+ status: {
288
+ type: 'string',
289
+ description: 'SLO status',
290
+ examples: ['healthy', 'at-risk', 'breached', 'disabled'],
291
+ },
292
+ isMet: {
293
+ type: 'boolean',
294
+ optional: true,
295
+ description: 'Currently meeting target',
296
+ },
297
+ },
298
+
299
+ relationships: {
300
+ sla: {
301
+ type: 'SLA',
302
+ required: false,
303
+ description: 'Parent SLA',
304
+ },
305
+ service: {
306
+ type: 'ProductizedService',
307
+ description: 'Service measured',
308
+ },
309
+ alerts: {
310
+ type: 'Alert[]',
311
+ description: 'Related alerts',
312
+ },
313
+ },
314
+
315
+ actions: [
316
+ 'create',
317
+ 'update',
318
+ 'enable',
319
+ 'disable',
320
+ 'recalculate',
321
+ 'alert',
322
+ ],
323
+
324
+ events: [
325
+ 'created',
326
+ 'updated',
327
+ 'enabled',
328
+ 'disabled',
329
+ 'breached',
330
+ 'recovered',
331
+ 'alertTriggered',
332
+ ],
333
+ }
334
+
335
+ // =============================================================================
336
+ // ServiceIncident
337
+ // =============================================================================
338
+
339
+ /**
340
+ * ServiceIncident entity
341
+ *
342
+ * Service incident or outage.
343
+ */
344
+ export const ServiceIncident: Noun = {
345
+ singular: 'service-incident',
346
+ plural: 'service-incidents',
347
+ description: 'A service incident or outage',
348
+
349
+ properties: {
350
+ // Identity
351
+ id: {
352
+ type: 'string',
353
+ description: 'Incident ID',
354
+ },
355
+ title: {
356
+ type: 'string',
357
+ description: 'Incident title',
358
+ },
359
+ description: {
360
+ type: 'string',
361
+ optional: true,
362
+ description: 'Incident description',
363
+ },
364
+
365
+ // Classification
366
+ severity: {
367
+ type: 'string',
368
+ description: 'Incident severity',
369
+ examples: ['critical', 'major', 'minor', 'warning'],
370
+ },
371
+ type: {
372
+ type: 'string',
373
+ optional: true,
374
+ description: 'Incident type',
375
+ examples: ['outage', 'degradation', 'maintenance', 'security', 'data'],
376
+ },
377
+ category: {
378
+ type: 'string',
379
+ optional: true,
380
+ description: 'Incident category',
381
+ },
382
+
383
+ // Impact
384
+ impactLevel: {
385
+ type: 'string',
386
+ optional: true,
387
+ description: 'Impact level',
388
+ examples: ['none', 'partial', 'major', 'complete'],
389
+ },
390
+ affectedServices: {
391
+ type: 'string',
392
+ array: true,
393
+ optional: true,
394
+ description: 'Affected services',
395
+ },
396
+ affectedCustomers: {
397
+ type: 'number',
398
+ optional: true,
399
+ description: 'Number of affected customers',
400
+ },
401
+ affectedRegions: {
402
+ type: 'string',
403
+ array: true,
404
+ optional: true,
405
+ description: 'Affected regions',
406
+ },
407
+
408
+ // Root Cause
409
+ rootCause: {
410
+ type: 'string',
411
+ optional: true,
412
+ description: 'Root cause',
413
+ },
414
+ rootCauseCategory: {
415
+ type: 'string',
416
+ optional: true,
417
+ description: 'Root cause category',
418
+ examples: ['infrastructure', 'code', 'config', 'dependency', 'external', 'unknown'],
419
+ },
420
+
421
+ // Resolution
422
+ resolution: {
423
+ type: 'string',
424
+ optional: true,
425
+ description: 'Resolution description',
426
+ },
427
+ resolutionSteps: {
428
+ type: 'string',
429
+ array: true,
430
+ optional: true,
431
+ description: 'Resolution steps taken',
432
+ },
433
+ preventionPlan: {
434
+ type: 'string',
435
+ optional: true,
436
+ description: 'Prevention plan',
437
+ },
438
+
439
+ // Timeline
440
+ detectedAt: {
441
+ type: 'date',
442
+ optional: true,
443
+ description: 'Detection time',
444
+ },
445
+ startedAt: {
446
+ type: 'date',
447
+ optional: true,
448
+ description: 'Incident start time',
449
+ },
450
+ acknowledgedAt: {
451
+ type: 'date',
452
+ optional: true,
453
+ description: 'Acknowledgement time',
454
+ },
455
+ mitigatedAt: {
456
+ type: 'date',
457
+ optional: true,
458
+ description: 'Mitigation time',
459
+ },
460
+ resolvedAt: {
461
+ type: 'date',
462
+ optional: true,
463
+ description: 'Resolution time',
464
+ },
465
+ closedAt: {
466
+ type: 'date',
467
+ optional: true,
468
+ description: 'Closure time',
469
+ },
470
+
471
+ // Duration
472
+ durationMinutes: {
473
+ type: 'number',
474
+ optional: true,
475
+ description: 'Total duration in minutes',
476
+ },
477
+ timeToDetect: {
478
+ type: 'number',
479
+ optional: true,
480
+ description: 'Time to detect (minutes)',
481
+ },
482
+ timeToMitigate: {
483
+ type: 'number',
484
+ optional: true,
485
+ description: 'Time to mitigate (minutes)',
486
+ },
487
+ timeToResolve: {
488
+ type: 'number',
489
+ optional: true,
490
+ description: 'Time to resolve (minutes)',
491
+ },
492
+
493
+ // Status
494
+ status: {
495
+ type: 'string',
496
+ description: 'Incident status',
497
+ examples: ['detected', 'investigating', 'identified', 'mitigating', 'monitoring', 'resolved', 'closed'],
498
+ },
499
+ isPublic: {
500
+ type: 'boolean',
501
+ optional: true,
502
+ description: 'Visible on status page',
503
+ },
504
+ },
505
+
506
+ relationships: {
507
+ service: {
508
+ type: 'ProductizedService',
509
+ description: 'Affected service',
510
+ },
511
+ sla: {
512
+ type: 'SLA',
513
+ required: false,
514
+ description: 'Related SLA',
515
+ },
516
+ assignee: {
517
+ type: 'Worker',
518
+ required: false,
519
+ description: 'Assigned responder',
520
+ },
521
+ tickets: {
522
+ type: 'SupportTicket[]',
523
+ description: 'Related tickets',
524
+ },
525
+ },
526
+
527
+ actions: [
528
+ 'create',
529
+ 'acknowledge',
530
+ 'investigate',
531
+ 'mitigate',
532
+ 'resolve',
533
+ 'close',
534
+ 'reopen',
535
+ 'escalate',
536
+ ],
537
+
538
+ events: [
539
+ 'created',
540
+ 'acknowledged',
541
+ 'investigating',
542
+ 'identified',
543
+ 'mitigating',
544
+ 'resolved',
545
+ 'closed',
546
+ 'reopened',
547
+ 'escalated',
548
+ ],
549
+ }
550
+
551
+ // =============================================================================
552
+ // SupportTicket
553
+ // =============================================================================
554
+
555
+ /**
556
+ * SupportTicket entity
557
+ *
558
+ * Customer support ticket.
559
+ */
560
+ export const SupportTicket: Noun = {
561
+ singular: 'support-ticket',
562
+ plural: 'support-tickets',
563
+ description: 'A customer support ticket',
564
+
565
+ properties: {
566
+ // Identity
567
+ id: {
568
+ type: 'string',
569
+ description: 'Ticket ID',
570
+ },
571
+ number: {
572
+ type: 'string',
573
+ optional: true,
574
+ description: 'Ticket number',
575
+ },
576
+
577
+ // Content
578
+ subject: {
579
+ type: 'string',
580
+ description: 'Ticket subject',
581
+ },
582
+ description: {
583
+ type: 'string',
584
+ optional: true,
585
+ description: 'Ticket description',
586
+ },
587
+ tags: {
588
+ type: 'string',
589
+ array: true,
590
+ optional: true,
591
+ description: 'Ticket tags',
592
+ },
593
+
594
+ // Classification
595
+ type: {
596
+ type: 'string',
597
+ description: 'Ticket type',
598
+ examples: ['question', 'problem', 'feature-request', 'bug', 'task'],
599
+ },
600
+ category: {
601
+ type: 'string',
602
+ optional: true,
603
+ description: 'Ticket category',
604
+ },
605
+
606
+ // Priority
607
+ priority: {
608
+ type: 'string',
609
+ description: 'Ticket priority',
610
+ examples: ['low', 'normal', 'high', 'urgent'],
611
+ },
612
+ severity: {
613
+ type: 'string',
614
+ optional: true,
615
+ description: 'Issue severity',
616
+ examples: ['cosmetic', 'minor', 'major', 'critical'],
617
+ },
618
+
619
+ // Channel
620
+ channel: {
621
+ type: 'string',
622
+ optional: true,
623
+ description: 'Ticket channel',
624
+ examples: ['email', 'chat', 'phone', 'web', 'api', 'social'],
625
+ },
626
+
627
+ // Assignment
628
+ assignedTo: {
629
+ type: 'string',
630
+ optional: true,
631
+ description: 'Assigned agent',
632
+ },
633
+ assignedTeam: {
634
+ type: 'string',
635
+ optional: true,
636
+ description: 'Assigned team',
637
+ },
638
+
639
+ // SLA
640
+ slaTarget: {
641
+ type: 'date',
642
+ optional: true,
643
+ description: 'SLA target time',
644
+ },
645
+ slaBreached: {
646
+ type: 'boolean',
647
+ optional: true,
648
+ description: 'SLA was breached',
649
+ },
650
+ firstResponseAt: {
651
+ type: 'date',
652
+ optional: true,
653
+ description: 'First response time',
654
+ },
655
+
656
+ // Resolution
657
+ resolution: {
658
+ type: 'string',
659
+ optional: true,
660
+ description: 'Resolution description',
661
+ },
662
+ resolutionCode: {
663
+ type: 'string',
664
+ optional: true,
665
+ description: 'Resolution code',
666
+ examples: ['solved', 'not-a-bug', 'duplicate', 'wont-fix', 'by-design'],
667
+ },
668
+
669
+ // Timeline
670
+ createdAt: {
671
+ type: 'date',
672
+ optional: true,
673
+ description: 'Creation time',
674
+ },
675
+ updatedAt: {
676
+ type: 'date',
677
+ optional: true,
678
+ description: 'Last update time',
679
+ },
680
+ resolvedAt: {
681
+ type: 'date',
682
+ optional: true,
683
+ description: 'Resolution time',
684
+ },
685
+ closedAt: {
686
+ type: 'date',
687
+ optional: true,
688
+ description: 'Closure time',
689
+ },
690
+
691
+ // AI
692
+ aiHandled: {
693
+ type: 'boolean',
694
+ optional: true,
695
+ description: 'Handled by AI',
696
+ },
697
+ aiSuggestedResolution: {
698
+ type: 'string',
699
+ optional: true,
700
+ description: 'AI suggested resolution',
701
+ },
702
+ aiConfidence: {
703
+ type: 'number',
704
+ optional: true,
705
+ description: 'AI confidence score',
706
+ },
707
+
708
+ // Satisfaction
709
+ satisfactionScore: {
710
+ type: 'number',
711
+ optional: true,
712
+ description: 'Customer satisfaction score',
713
+ },
714
+ satisfactionComment: {
715
+ type: 'string',
716
+ optional: true,
717
+ description: 'Satisfaction comment',
718
+ },
719
+
720
+ // Status
721
+ status: {
722
+ type: 'string',
723
+ description: 'Ticket status',
724
+ examples: ['new', 'open', 'pending', 'on-hold', 'escalated', 'solved', 'closed'],
725
+ },
726
+ },
727
+
728
+ relationships: {
729
+ customer: {
730
+ type: 'ServiceCustomer',
731
+ description: 'Customer',
732
+ },
733
+ service: {
734
+ type: 'ProductizedService',
735
+ required: false,
736
+ description: 'Related service',
737
+ },
738
+ incident: {
739
+ type: 'ServiceIncident',
740
+ required: false,
741
+ description: 'Related incident',
742
+ },
743
+ messages: {
744
+ type: 'TicketMessage[]',
745
+ description: 'Ticket messages',
746
+ },
747
+ },
748
+
749
+ actions: [
750
+ 'create',
751
+ 'assign',
752
+ 'respond',
753
+ 'escalate',
754
+ 'solve',
755
+ 'close',
756
+ 'reopen',
757
+ ],
758
+
759
+ events: [
760
+ 'created',
761
+ 'assigned',
762
+ 'responded',
763
+ 'escalated',
764
+ 'solved',
765
+ 'closed',
766
+ 'reopened',
767
+ 'ratedByCustomer',
768
+ ],
769
+ }
770
+
771
+ // =============================================================================
772
+ // ServiceFeedback
773
+ // =============================================================================
774
+
775
+ /**
776
+ * ServiceFeedback entity
777
+ *
778
+ * Customer feedback on service.
779
+ */
780
+ export const ServiceFeedback: Noun = {
781
+ singular: 'service-feedback',
782
+ plural: 'service-feedbacks',
783
+ description: 'Customer feedback on a service',
784
+
785
+ properties: {
786
+ // Identity
787
+ id: {
788
+ type: 'string',
789
+ description: 'Feedback ID',
790
+ },
791
+
792
+ // Rating
793
+ rating: {
794
+ type: 'number',
795
+ optional: true,
796
+ description: 'Rating score (1-5)',
797
+ },
798
+ npsScore: {
799
+ type: 'number',
800
+ optional: true,
801
+ description: 'NPS score (0-10)',
802
+ },
803
+ satisfactionScore: {
804
+ type: 'number',
805
+ optional: true,
806
+ description: 'Satisfaction score (1-5)',
807
+ },
808
+
809
+ // Content
810
+ comment: {
811
+ type: 'string',
812
+ optional: true,
813
+ description: 'Feedback comment',
814
+ },
815
+ highlights: {
816
+ type: 'string',
817
+ array: true,
818
+ optional: true,
819
+ description: 'Positive highlights',
820
+ },
821
+ improvements: {
822
+ type: 'string',
823
+ array: true,
824
+ optional: true,
825
+ description: 'Suggested improvements',
826
+ },
827
+
828
+ // Type
829
+ type: {
830
+ type: 'string',
831
+ description: 'Feedback type',
832
+ examples: ['post-execution', 'periodic', 'exit', 'support', 'spontaneous'],
833
+ },
834
+ trigger: {
835
+ type: 'string',
836
+ optional: true,
837
+ description: 'What triggered feedback request',
838
+ },
839
+
840
+ // Context
841
+ context: {
842
+ type: 'json',
843
+ optional: true,
844
+ description: 'Feedback context',
845
+ },
846
+
847
+ // Sentiment
848
+ sentiment: {
849
+ type: 'string',
850
+ optional: true,
851
+ description: 'Detected sentiment',
852
+ examples: ['positive', 'neutral', 'negative', 'mixed'],
853
+ },
854
+ sentimentScore: {
855
+ type: 'number',
856
+ optional: true,
857
+ description: 'Sentiment score (-1 to 1)',
858
+ },
859
+
860
+ // Follow-up
861
+ requiresFollowUp: {
862
+ type: 'boolean',
863
+ optional: true,
864
+ description: 'Requires follow-up',
865
+ },
866
+ followedUpAt: {
867
+ type: 'date',
868
+ optional: true,
869
+ description: 'Follow-up date',
870
+ },
871
+
872
+ // Dates
873
+ submittedAt: {
874
+ type: 'date',
875
+ optional: true,
876
+ description: 'Submission time',
877
+ },
878
+
879
+ // Status
880
+ status: {
881
+ type: 'string',
882
+ description: 'Feedback status',
883
+ examples: ['submitted', 'reviewed', 'actioned', 'archived'],
884
+ },
885
+ },
886
+
887
+ relationships: {
888
+ customer: {
889
+ type: 'ServiceCustomer',
890
+ description: 'Customer',
891
+ },
892
+ service: {
893
+ type: 'ProductizedService',
894
+ description: 'Service',
895
+ },
896
+ execution: {
897
+ type: 'ServiceExecution',
898
+ required: false,
899
+ description: 'Related execution',
900
+ },
901
+ ticket: {
902
+ type: 'SupportTicket',
903
+ required: false,
904
+ description: 'Related ticket',
905
+ },
906
+ },
907
+
908
+ actions: [
909
+ 'submit',
910
+ 'review',
911
+ 'action',
912
+ 'followUp',
913
+ 'archive',
914
+ ],
915
+
916
+ events: [
917
+ 'submitted',
918
+ 'reviewed',
919
+ 'actioned',
920
+ 'followedUp',
921
+ 'archived',
922
+ ],
923
+ }
924
+
925
+ // =============================================================================
926
+ // ServiceMetric
927
+ // =============================================================================
928
+
929
+ /**
930
+ * ServiceMetric entity
931
+ *
932
+ * Service performance metric.
933
+ */
934
+ export const ServiceMetric: Noun = {
935
+ singular: 'service-metric',
936
+ plural: 'service-metrics',
937
+ description: 'A service performance metric',
938
+
939
+ properties: {
940
+ // Identity
941
+ name: {
942
+ type: 'string',
943
+ description: 'Metric name',
944
+ },
945
+ description: {
946
+ type: 'string',
947
+ optional: true,
948
+ description: 'Metric description',
949
+ },
950
+
951
+ // Classification
952
+ type: {
953
+ type: 'string',
954
+ description: 'Metric type',
955
+ examples: ['counter', 'gauge', 'histogram', 'summary'],
956
+ },
957
+ category: {
958
+ type: 'string',
959
+ optional: true,
960
+ description: 'Metric category',
961
+ examples: ['performance', 'reliability', 'usage', 'cost', 'quality'],
962
+ },
963
+
964
+ // Value
965
+ value: {
966
+ type: 'number',
967
+ optional: true,
968
+ description: 'Current value',
969
+ },
970
+ unit: {
971
+ type: 'string',
972
+ optional: true,
973
+ description: 'Unit of measure',
974
+ },
975
+
976
+ // Aggregation
977
+ aggregation: {
978
+ type: 'string',
979
+ optional: true,
980
+ description: 'Aggregation method',
981
+ examples: ['sum', 'avg', 'min', 'max', 'p50', 'p95', 'p99', 'count'],
982
+ },
983
+ windowDuration: {
984
+ type: 'string',
985
+ optional: true,
986
+ description: 'Aggregation window',
987
+ },
988
+
989
+ // Dimensions
990
+ dimensions: {
991
+ type: 'json',
992
+ optional: true,
993
+ description: 'Metric dimensions/labels',
994
+ },
995
+
996
+ // Targets
997
+ targetValue: {
998
+ type: 'number',
999
+ optional: true,
1000
+ description: 'Target value',
1001
+ },
1002
+ warningThreshold: {
1003
+ type: 'number',
1004
+ optional: true,
1005
+ description: 'Warning threshold',
1006
+ },
1007
+ criticalThreshold: {
1008
+ type: 'number',
1009
+ optional: true,
1010
+ description: 'Critical threshold',
1011
+ },
1012
+
1013
+ // Trends
1014
+ trend: {
1015
+ type: 'string',
1016
+ optional: true,
1017
+ description: 'Value trend',
1018
+ examples: ['improving', 'stable', 'degrading'],
1019
+ },
1020
+ changePercent: {
1021
+ type: 'number',
1022
+ optional: true,
1023
+ description: 'Change percentage from previous period',
1024
+ },
1025
+
1026
+ // Timestamps
1027
+ lastUpdatedAt: {
1028
+ type: 'date',
1029
+ optional: true,
1030
+ description: 'Last update time',
1031
+ },
1032
+ periodStart: {
1033
+ type: 'date',
1034
+ optional: true,
1035
+ description: 'Period start',
1036
+ },
1037
+ periodEnd: {
1038
+ type: 'date',
1039
+ optional: true,
1040
+ description: 'Period end',
1041
+ },
1042
+
1043
+ // Status
1044
+ status: {
1045
+ type: 'string',
1046
+ description: 'Metric status',
1047
+ examples: ['healthy', 'warning', 'critical', 'unknown'],
1048
+ },
1049
+ },
1050
+
1051
+ relationships: {
1052
+ service: {
1053
+ type: 'ProductizedService',
1054
+ description: 'Service measured',
1055
+ },
1056
+ slo: {
1057
+ type: 'SLO',
1058
+ required: false,
1059
+ description: 'Related SLO',
1060
+ },
1061
+ },
1062
+
1063
+ actions: [
1064
+ 'create',
1065
+ 'update',
1066
+ 'record',
1067
+ 'aggregate',
1068
+ 'alert',
1069
+ ],
1070
+
1071
+ events: [
1072
+ 'created',
1073
+ 'updated',
1074
+ 'recorded',
1075
+ 'aggregated',
1076
+ 'thresholdExceeded',
1077
+ 'recovered',
1078
+ ],
1079
+ }
1080
+
1081
+ // =============================================================================
1082
+ // Exports
1083
+ // =============================================================================
1084
+
1085
+ export const OperationsEntities = {
1086
+ SLA,
1087
+ SLO,
1088
+ ServiceIncident,
1089
+ SupportTicket,
1090
+ ServiceFeedback,
1091
+ ServiceMetric,
1092
+ }
1093
+
1094
+ export const OperationsCategories = {
1095
+ agreements: ['SLA', 'SLO'],
1096
+ incidents: ['ServiceIncident'],
1097
+ support: ['SupportTicket', 'ServiceFeedback'],
1098
+ metrics: ['ServiceMetric'],
1099
+ } as const