@skyhook-io/k8s-ui 1.10.0 → 1.10.2

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.
@@ -0,0 +1,702 @@
1
+ import type { Issue } from "../components/issues/types";
2
+
3
+ export const CAPACITY_SCHEMA_VERSION = "v1alpha1" as const;
4
+
5
+ export interface CapacitySubjectRef {
6
+ group?: string;
7
+ kind: string;
8
+ namespace?: string;
9
+ name: string;
10
+ }
11
+
12
+ export interface CapacityResourceIdentity {
13
+ ref: CapacitySubjectRef;
14
+ apiVersion?: string;
15
+ uid?: string;
16
+ }
17
+
18
+ export type CapacityCertainty =
19
+ "exact" | "lower_bound" | "upper_bound" | "unknown";
20
+ export type CapacityGranularity =
21
+ "aggregate" | "aggregate_not_binpacked" | "per_node";
22
+ export type CapacityResourceVector = Record<string, string>;
23
+
24
+ export interface CapacityQuantityObservation {
25
+ resources: CapacityResourceVector;
26
+ certainty: CapacityCertainty;
27
+ sources: string[];
28
+ asOf: string;
29
+ granularity: CapacityGranularity;
30
+ }
31
+
32
+ export interface CapacityResourceUtilization {
33
+ resource: string;
34
+ usage: string;
35
+ allocatable: string;
36
+ percent: number;
37
+ }
38
+
39
+ export interface CapacityUsageObservation {
40
+ quantity: CapacityQuantityObservation;
41
+ coveredNodes: number;
42
+ totalNodes: number;
43
+ coveredAllocatable: CapacityQuantityObservation;
44
+ utilization: CapacityResourceUtilization[];
45
+ }
46
+
47
+ export type CapacityConfidence = "high" | "medium" | "low";
48
+ export type CapacityConditionStatus = "True" | "False" | "Unknown";
49
+
50
+ export interface CapacityCondition {
51
+ type: string;
52
+ status: CapacityConditionStatus;
53
+ reason?: string;
54
+ message?: string;
55
+ observedGeneration?: number;
56
+ lastTransitionTime?: string;
57
+ }
58
+
59
+ export interface CapacityBoundedResultMeta {
60
+ total: number;
61
+ returned: number;
62
+ truncated: boolean;
63
+ }
64
+
65
+ export interface CapacityPageInfo {
66
+ hasMore: boolean;
67
+ nextCursor?: string;
68
+ }
69
+
70
+ export type CapacityIntegrationState =
71
+ "available" | "not_detected" | "denied" | "syncing";
72
+
73
+ export interface CapacityClusterContext {
74
+ contextName: string;
75
+ clusterName?: string;
76
+ }
77
+
78
+ export type CapacityProviderType = "karpenter";
79
+ export type CapacityControllerMode = "self_managed" | "eks_auto" | "unknown";
80
+
81
+ export interface CapacityProviderFeatures {
82
+ staticCapacity?: boolean;
83
+ metrics?: boolean;
84
+ }
85
+
86
+ export interface CapacityAPIKind {
87
+ group: string;
88
+ kind: string;
89
+ resource: string;
90
+ versions: string[];
91
+ }
92
+
93
+ export interface CapacityProvider {
94
+ type: CapacityProviderType;
95
+ controllerMode: CapacityControllerMode;
96
+ apiVersionsByKind: Record<string, string[]>;
97
+ nodeClassKinds: CapacityAPIKind[];
98
+ features: CapacityProviderFeatures;
99
+ }
100
+
101
+ export type CapacityCoverageSource =
102
+ | "nodePools"
103
+ | "nodeClaims"
104
+ | "nodeClasses"
105
+ | "nodes"
106
+ | "pods"
107
+ | "workloads"
108
+ | "karpenterObjectEvents"
109
+ | "nodeMetrics"
110
+ | "timeline"
111
+ | "autoscalerStatus";
112
+
113
+ export type CapacityCoverageStatus =
114
+ "available" | "partial" | "denied" | "syncing" | "unavailable" | "error";
115
+ export type CapacityCoverageScope =
116
+ "cluster" | "all_authorized_namespaces" | "explicit_namespaces";
117
+
118
+ export interface CapacitySourceCoverage {
119
+ status: CapacityCoverageStatus;
120
+ reasonCode?: string;
121
+ reason?: string;
122
+ scope: CapacityCoverageScope;
123
+ namespaces?: string[];
124
+ observedAt?: string;
125
+ observationStart?: string;
126
+ itemCount?: number;
127
+ impactFields: string[];
128
+ }
129
+
130
+ export type CapacityCoverageBySource = Partial<
131
+ Record<CapacityCoverageSource, CapacitySourceCoverage>
132
+ >;
133
+
134
+ export interface CapacityResponseMeta {
135
+ schemaVersion: typeof CAPACITY_SCHEMA_VERSION;
136
+ generatedAt: string;
137
+ clusterContext: CapacityClusterContext;
138
+ provider: CapacityProvider;
139
+ coverage: CapacityCoverageBySource;
140
+ }
141
+
142
+ export type CapacityPoolMode = "dynamic" | "static" | "unknown";
143
+
144
+ export interface CapacityNodeClassReference {
145
+ group: string;
146
+ kind: string;
147
+ name: string;
148
+ apiVersion?: string;
149
+ }
150
+
151
+ export interface CapacityNodeClassObservation {
152
+ reference: CapacityNodeClassReference;
153
+ resource?: CapacityResourceIdentity;
154
+ ready?: boolean;
155
+ conditions: CapacityCondition[];
156
+ }
157
+
158
+ export interface CapacityRequirement {
159
+ key: string;
160
+ operator: string;
161
+ values: string[];
162
+ minValues?: number;
163
+ }
164
+
165
+ export interface CapacityTaint {
166
+ key: string;
167
+ value?: string;
168
+ effect: string;
169
+ }
170
+
171
+ export interface CapacityToleration {
172
+ key?: string;
173
+ operator?: string;
174
+ value?: string;
175
+ effect?: string;
176
+ tolerationSeconds?: number;
177
+ }
178
+
179
+ export interface CapacityPoolConfiguration {
180
+ weight?: number;
181
+ replicas?: number;
182
+ labels: Record<string, string>;
183
+ requirements: CapacityRequirement[];
184
+ taints: CapacityTaint[];
185
+ startupTaints: CapacityTaint[];
186
+ expireAfter?: string;
187
+ terminationGracePeriod?: string;
188
+ }
189
+
190
+ export interface CapacityLimitPressure {
191
+ resource: string;
192
+ provisioned: string;
193
+ limit: string;
194
+ percent?: number;
195
+ overLimit: boolean;
196
+ }
197
+
198
+ export interface CapacityLedger {
199
+ configuredLimit?: CapacityQuantityObservation;
200
+ provisioned?: CapacityQuantityObservation;
201
+ allocatable?: CapacityQuantityObservation;
202
+ scheduledRequests?: CapacityQuantityObservation;
203
+ inFlightCapacity?: CapacityQuantityObservation;
204
+ actualUsage?: CapacityUsageObservation;
205
+ aggregateUnallocatedRequests?: CapacityQuantityObservation;
206
+ limitHeadroom?: CapacityQuantityObservation;
207
+ limitPressure: CapacityLimitPressure[];
208
+ }
209
+
210
+ export interface CapacityDisruptionBudget {
211
+ nodes: string;
212
+ reasons: string[];
213
+ schedule?: string;
214
+ duration?: string;
215
+ }
216
+
217
+ export interface CapacityDisruptionPolicy {
218
+ consolidationPolicy?: string;
219
+ consolidateAfter?: string;
220
+ budgets: CapacityDisruptionBudget[];
221
+ }
222
+
223
+ export interface CapacityClaimLifecycleSummary {
224
+ total: number;
225
+ pending: number;
226
+ launched: number;
227
+ registered: number;
228
+ initialized: number;
229
+ ready: number;
230
+ failed: number;
231
+ terminating: number;
232
+ }
233
+
234
+ export interface CapacityNodeLifecycleSummary {
235
+ total: number;
236
+ ready: number;
237
+ notReady: number;
238
+ cordoned: number;
239
+ terminating: number;
240
+ }
241
+
242
+ export interface CapacityCompositionBucket {
243
+ value: string;
244
+ count: number;
245
+ resources?: CapacityQuantityObservation;
246
+ }
247
+
248
+ export interface CapacityPoolComposition {
249
+ capacityTypes: CapacityCompositionBucket[];
250
+ capacityTypesMeta: CapacityBoundedResultMeta;
251
+ instanceTypes: CapacityCompositionBucket[];
252
+ instanceTypesMeta: CapacityBoundedResultMeta;
253
+ zones: CapacityCompositionBucket[];
254
+ zonesMeta: CapacityBoundedResultMeta;
255
+ architectures: CapacityCompositionBucket[];
256
+ architecturesMeta: CapacityBoundedResultMeta;
257
+ images: CapacityCompositionBucket[];
258
+ imagesMeta: CapacityBoundedResultMeta;
259
+ }
260
+
261
+ export interface CapacityWorkloadAttribution {
262
+ owner: CapacitySubjectRef;
263
+ podCount: number;
264
+ requests?: CapacityQuantityObservation;
265
+ }
266
+
267
+ export interface CapacityWorkloadSummary {
268
+ scheduledPodCount: number;
269
+ workloadCount: number;
270
+ topScheduled: CapacityWorkloadAttribution[];
271
+ topScheduledMeta: CapacityBoundedResultMeta;
272
+ pendingEligibleGroupCount: number;
273
+ }
274
+
275
+ export interface CapacityPostureFact {
276
+ code: string;
277
+ summary: string;
278
+ detail?: string;
279
+ sourcePaths: string[];
280
+ }
281
+
282
+ export interface CapacityPoolObservation {
283
+ resource: CapacityResourceIdentity;
284
+ generation: number;
285
+ observedGeneration?: number;
286
+ createdAt?: string;
287
+ updatedAt?: string;
288
+ mode: CapacityPoolMode;
289
+ ready?: boolean;
290
+ conditions: CapacityCondition[];
291
+ nodeClass?: CapacityNodeClassObservation;
292
+ configuration: CapacityPoolConfiguration;
293
+ ledger: CapacityLedger;
294
+ disruption: CapacityDisruptionPolicy;
295
+ claims?: CapacityClaimLifecycleSummary;
296
+ nodes?: CapacityNodeLifecycleSummary;
297
+ composition?: CapacityPoolComposition;
298
+ workloads?: CapacityWorkloadSummary;
299
+ issues: Issue[];
300
+ facts: CapacityPostureFact[];
301
+ coverage: CapacityCoverageBySource;
302
+ }
303
+
304
+ export interface CapacityPoolSummary {
305
+ resource: CapacityResourceIdentity;
306
+ mode: CapacityPoolMode;
307
+ ready?: boolean;
308
+ nodeClass?: CapacityNodeClassReference;
309
+ ledger: CapacityLedger;
310
+ claims?: CapacityClaimLifecycleSummary;
311
+ nodes?: CapacityNodeLifecycleSummary;
312
+ issueCount: number;
313
+ factCount: number;
314
+ }
315
+
316
+ export type CapacityMemberType = "node" | "claim" | "workload";
317
+ export type CapacityClaimStage =
318
+ | "pending"
319
+ | "launched"
320
+ | "registered"
321
+ | "initialized"
322
+ | "ready"
323
+ | "failed"
324
+ | "terminating"
325
+ | "unknown";
326
+
327
+ export interface CapacityNodeMember {
328
+ ready?: boolean;
329
+ cordoned: boolean;
330
+ conditions: CapacityCondition[];
331
+ instanceType?: string;
332
+ capacityType?: string;
333
+ zone?: string;
334
+ architecture?: string;
335
+ image?: string;
336
+ allocatable?: CapacityQuantityObservation;
337
+ scheduledRequests?: CapacityQuantityObservation;
338
+ actualUsage?: CapacityUsageObservation;
339
+ podCount?: number;
340
+ }
341
+
342
+ export interface CapacityClaimMember {
343
+ stage: CapacityClaimStage;
344
+ conditions: CapacityCondition[];
345
+ nodeName?: string;
346
+ node?: CapacityResourceIdentity;
347
+ capacity?: CapacityQuantityObservation;
348
+ }
349
+
350
+ export interface CapacityWorkloadMember {
351
+ owner: CapacitySubjectRef;
352
+ podCount: number;
353
+ requests?: CapacityQuantityObservation;
354
+ nodes: CapacityResourceIdentity[];
355
+ nodesMeta: CapacityBoundedResultMeta;
356
+ }
357
+
358
+ export interface CapacityPoolMember {
359
+ type: CapacityMemberType;
360
+ resource: CapacityResourceIdentity;
361
+ node?: CapacityNodeMember;
362
+ claim?: CapacityClaimMember;
363
+ workload?: CapacityWorkloadMember;
364
+ }
365
+
366
+ export interface CapacityActionSummary {
367
+ code: string;
368
+ count: number;
369
+ highestSeverity?: string;
370
+ pools: CapacityResourceIdentity[];
371
+ truncated: boolean;
372
+ }
373
+
374
+ export interface CapacityOverviewSummary {
375
+ actions: CapacityActionSummary[];
376
+ aggregateDemand?: CapacityQuantityObservation;
377
+ scheduling?: CapacitySchedulingCapacity;
378
+ claimStages?: CapacityClaimLifecycleSummary;
379
+ /** Absent when NodePools were not observed — never render that as zero. */
380
+ poolCount?: number;
381
+ claimCount?: number;
382
+ nodeCount?: number;
383
+ pendingPodCount?: number;
384
+ orphanedClaimCount?: number;
385
+ unpooledNodeCount?: number;
386
+ /** All observed nodes, every manager included; `scheduling` above stays Karpenter-scoped forever. */
387
+ clusterScheduling?: CapacitySchedulingCapacity;
388
+ /** Detected capacity managers; interpretation is coverage-gated. */
389
+ managers: CapacityManagerSummary[];
390
+ /** Nodes with no group-identity evidence — a presentation bucket, never "static". */
391
+ unattributedNodeCount?: number;
392
+ }
393
+
394
+ export type CapacityManager =
395
+ "karpenter" | "cluster_autoscaler" | "gke_autoscaler" | "aks_autoscaler";
396
+
397
+ export type CapacityManagerRollupStatus = "healthy" | "degraded" | "unknown";
398
+
399
+ export interface CapacityManagerSummary {
400
+ manager: CapacityManager;
401
+ groupCount: number;
402
+ status: CapacityManagerRollupStatus;
403
+ detail?: string;
404
+ }
405
+
406
+ export interface CapacityScalingFact {
407
+ code: string;
408
+ summary: string;
409
+ }
410
+
411
+ export interface CapacityAutoscalerBackoff {
412
+ errorClass?: string;
413
+ errorCode?: string;
414
+ errorMessage?: string;
415
+ }
416
+
417
+ /**
418
+ * One node group as the autoscaler itself reports it (zonal MIG / VMSS).
419
+ * ID is the published name's basename and never changes when the child gains
420
+ * or loses a parent group. `asOf` nil means the payload published null —
421
+ * "not probed", never zero and never now.
422
+ */
423
+ export interface CapacityAutoscalerChildObservation {
424
+ id: string;
425
+ name: string;
426
+ minSize?: number;
427
+ maxSize?: number;
428
+ target?: number;
429
+ health?: string;
430
+ readyNodes?: number;
431
+ totalNodes?: number;
432
+ backoff?: CapacityAutoscalerBackoff;
433
+ asOf?: string;
434
+ }
435
+
436
+ /**
437
+ * A logical node group a user recognizes (Karpenter NodePool, GKE node pool,
438
+ * EKS managed node group, AKS agent pool). Identity comes from node labels or
439
+ * CRD evidence, never from parsing provider group names.
440
+ */
441
+ export type CapacityGroupPlatform =
442
+ | "karpenter" | "gke" | "eks" | "aks"
443
+ | "kops" | "doks" | "ack" | "lke" | "scaleway";
444
+
445
+ export interface CapacityGroupSummary {
446
+ id: string;
447
+ name: string;
448
+ /** The identity domain the row exists BY (node label / CRD family) — always
449
+ * present and distinct from manager: a static EKS managed node group has a
450
+ * platform and no manager. Render unknown future values via a humanized
451
+ * fallback, never crash. */
452
+ platform: CapacityGroupPlatform | (string & {});
453
+ manager?: CapacityManager;
454
+ managerValidated: boolean;
455
+ nodeCount: number;
456
+ readyNodeCount: number;
457
+ allocatable?: CapacityQuantityObservation;
458
+ scheduledRequests?: CapacityQuantityObservation;
459
+ scaling: CapacityScalingFact[];
460
+ children: CapacityAutoscalerChildObservation[];
461
+ childrenMeta: CapacityBoundedResultMeta;
462
+ }
463
+
464
+ /**
465
+ * Cluster-level scheduling ledger across Karpenter-pooled nodes only. Each
466
+ * value carries its own certainty; an absent value means the source was not
467
+ * observed (unavailable ≠ zero).
468
+ */
469
+ export interface CapacitySchedulingCapacity {
470
+ scheduledRequests?: CapacityQuantityObservation;
471
+ allocatable?: CapacityQuantityObservation;
472
+ inFlightCapacity?: CapacityQuantityObservation;
473
+ /** SUBSET of scheduledRequests from pods with spec.priority < 0 (potential preemption victims). Never additive with scheduledRequests. */
474
+ negativePriorityRequests?: CapacityQuantityObservation;
475
+ }
476
+
477
+ export interface CapacityOverviewResponse extends CapacityResponseMeta {
478
+ state: CapacityIntegrationState;
479
+ summary: CapacityOverviewSummary;
480
+ pools: CapacityPoolSummary[];
481
+ poolsTruncated: boolean;
482
+ /** Logical-group inventory across every manager; empty is a true zero only under observed node coverage. */
483
+ groups: CapacityGroupSummary[];
484
+ /** Autoscaler-known groups with no joinable nodes (scale-to-zero included) — never counted as logical groups. */
485
+ orphanAutoscalerGroups: CapacityAutoscalerChildObservation[];
486
+ orphanAutoscalerGroupsMeta: CapacityBoundedResultMeta;
487
+ }
488
+
489
+ export interface CapacityPoolDetailResponse extends CapacityResponseMeta {
490
+ state: CapacityIntegrationState;
491
+ pool?: CapacityPoolObservation;
492
+ }
493
+
494
+ export interface CapacityPoolListResponse extends CapacityResponseMeta {
495
+ state: CapacityIntegrationState;
496
+ items: CapacityPoolSummary[];
497
+ page: CapacityPageInfo;
498
+ }
499
+
500
+ export interface CapacityMemberListResponse extends CapacityResponseMeta {
501
+ state: CapacityIntegrationState;
502
+ pool: CapacityResourceIdentity;
503
+ type: CapacityMemberType;
504
+ items: CapacityPoolMember[];
505
+ page: CapacityPageInfo;
506
+ }
507
+
508
+ export type CapacityDemandState =
509
+ | "waiting_for_scheduler"
510
+ | "held"
511
+ | "awaiting_capacity"
512
+ | "blocked"
513
+ | "unknown";
514
+
515
+ export interface CapacityDemandCounts {
516
+ podCount: number;
517
+ groupCount: number;
518
+ }
519
+
520
+ export interface CapacityDemandSummary {
521
+ total: CapacityDemandCounts;
522
+ byState: Record<CapacityDemandState, CapacityDemandCounts>;
523
+ }
524
+
525
+ export interface CapacitySchedulingConstraint {
526
+ predicate: string;
527
+ key?: string;
528
+ operator?: string;
529
+ values: string[];
530
+ sourcePath: string;
531
+ }
532
+
533
+ export interface CapacitySchedulingSignature {
534
+ fingerprint: string;
535
+ constraints: CapacitySchedulingConstraint[];
536
+ constraintsMeta: CapacityBoundedResultMeta;
537
+ tolerations: CapacityToleration[];
538
+ tolerationsMeta: CapacityBoundedResultMeta;
539
+ }
540
+
541
+ export interface CapacitySchedulerReason {
542
+ code: string;
543
+ source: string;
544
+ message?: string;
545
+ count: number;
546
+ firstSeen: string;
547
+ lastSeen: string;
548
+ }
549
+
550
+ export type CapacityPoolEvaluationResult =
551
+ "declared_compatible" | "incompatible" | "unknown";
552
+
553
+ export interface CapacityEvaluationEvidence {
554
+ predicate: string;
555
+ sourcePath: string;
556
+ observedValues: string[];
557
+ expectedValues: string[];
558
+ confidence: CapacityConfidence;
559
+ explanation: string;
560
+ }
561
+
562
+ export interface CapacityPoolEvaluation {
563
+ pool: CapacitySubjectRef;
564
+ result: CapacityPoolEvaluationResult;
565
+ evidence: CapacityEvaluationEvidence[];
566
+ evidenceMeta: CapacityBoundedResultMeta;
567
+ unknownPredicates: string[];
568
+ unknownPredicatesMeta: CapacityBoundedResultMeta;
569
+ }
570
+
571
+ export interface CapacityPoolEvaluationCounts {
572
+ declaredCompatible: number;
573
+ incompatible: number;
574
+ unknown: number;
575
+ }
576
+
577
+ export interface CapacityDemandGroup {
578
+ id: string;
579
+ fingerprint: string;
580
+ owner?: CapacitySubjectRef;
581
+ pods: CapacityResourceIdentity[];
582
+ podsMeta: CapacityBoundedResultMeta;
583
+ namespace: string;
584
+ firstSeen: string;
585
+ lastSeen: string;
586
+ podCount: number;
587
+ /** Pods holding a scheduler node nomination (preemption in progress; best-effort — never changes state or eligibility). */
588
+ nominatedPodCount?: number;
589
+ perPodRequests: CapacityQuantityObservation;
590
+ aggregateRequests: CapacityQuantityObservation;
591
+ schedulingSignature: CapacitySchedulingSignature;
592
+ state: CapacityDemandState;
593
+ schedulerReasons: CapacitySchedulerReason[];
594
+ schedulerReasonsMeta: CapacityBoundedResultMeta;
595
+ poolEvaluations: CapacityPoolEvaluation[];
596
+ poolEvaluationsMeta: CapacityBoundedResultMeta;
597
+ poolEvaluationCounts: CapacityPoolEvaluationCounts;
598
+ issues: Issue[];
599
+ }
600
+
601
+ export interface CapacityDemandResponse extends CapacityResponseMeta {
602
+ state: CapacityIntegrationState;
603
+ summary?: CapacityDemandSummary;
604
+ items: CapacityDemandGroup[];
605
+ page: CapacityPageInfo;
606
+ }
607
+
608
+ export type CapacityActivityType =
609
+ | "provision"
610
+ | "launch_failure"
611
+ | "registration_failure"
612
+ | "initialization_failure"
613
+ | "disruption"
614
+ | "interruption"
615
+ | "termination"
616
+ | "config_change";
617
+ /** `ended` terminalizes an episode without asserting a cause — the subject went
618
+ * away before reaching its goal and no failure evidence was recorded. It is
619
+ * deliberately neither `completed` nor `failed`. */
620
+ export type CapacityActivityState =
621
+ | "open"
622
+ | "completed"
623
+ | "ended"
624
+ | "failed"
625
+ | "observed"
626
+ | "blocked"
627
+ | "unknown";
628
+ export type CapacityEvidenceSource =
629
+ "condition" | "k8s_event" | "resource_change";
630
+ export type CapacityEvidenceRelationship =
631
+ "direct" | "structural" | "correlated";
632
+
633
+ export interface CapacityActivityEvidence {
634
+ at: string;
635
+ source: CapacityEvidenceSource;
636
+ reasonCode: string;
637
+ rawReason?: string;
638
+ rawMessage?: string;
639
+ relationship: CapacityEvidenceRelationship;
640
+ confidence: CapacityConfidence;
641
+ refs: CapacityResourceIdentity[];
642
+ }
643
+
644
+ export interface CapacityActivityEpisode {
645
+ id: string;
646
+ type: CapacityActivityType;
647
+ state: CapacityActivityState;
648
+ summary: string;
649
+ primaryReasonCode?: string;
650
+ startedAt: string;
651
+ endedAt?: string;
652
+ durationSeconds?: number;
653
+ pool?: CapacityResourceIdentity;
654
+ claim?: CapacityResourceIdentity;
655
+ node?: CapacityResourceIdentity;
656
+ evidence: CapacityActivityEvidence[];
657
+ evidenceMeta: CapacityBoundedResultMeta;
658
+ }
659
+
660
+ export type CapacityCursorStatus = "valid" | "epoch_changed" | "evicted";
661
+
662
+ export interface CapacityObservationGap {
663
+ detectedAt: string;
664
+ reason: string;
665
+ previousCursor?: string;
666
+ newEpoch?: string;
667
+ }
668
+
669
+ export interface CapacityRetention {
670
+ mode: string;
671
+ maxEvents?: number;
672
+ maxAgeSeconds?: number;
673
+ }
674
+
675
+ export interface CapacityObservationWindow {
676
+ startedAt: string;
677
+ endedAt: string;
678
+ sources: CapacityEvidenceSource[];
679
+ retention: CapacityRetention;
680
+ gaps: CapacityObservationGap[];
681
+ }
682
+
683
+ export interface CapacityActivityTypeCounts {
684
+ total: number;
685
+ byState: Partial<Record<CapacityActivityState, number>>;
686
+ }
687
+
688
+ export interface CapacityActivityAggregate {
689
+ total: number;
690
+ byType: Partial<Record<CapacityActivityType, CapacityActivityTypeCounts>>;
691
+ }
692
+
693
+ export interface CapacityActivityResponse extends CapacityResponseMeta {
694
+ state: CapacityIntegrationState;
695
+ items: CapacityActivityEpisode[];
696
+ page: CapacityPageInfo;
697
+ cursorStatus: CapacityCursorStatus;
698
+ cursorGap?: CapacityObservationGap;
699
+ observation: CapacityObservationWindow;
700
+ /** Whole-window rollup; present only on first-page responses and never narrowed by the type filter. */
701
+ aggregate?: CapacityActivityAggregate;
702
+ }