@meyicloud/meyi-insight-server 1.0.6 → 1.0.8

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 (98) hide show
  1. package/dist/controllers/alert.controller.d.ts.map +1 -1
  2. package/dist/controllers/alert.controller.js +5 -0
  3. package/dist/controllers/alert.controller.js.map +1 -1
  4. package/dist/controllers/incident.controller.d.ts.map +1 -1
  5. package/dist/controllers/incident.controller.js +18 -2
  6. package/dist/controllers/incident.controller.js.map +1 -1
  7. package/dist/database/schema.d.ts +163 -20
  8. package/dist/database/schema.d.ts.map +1 -1
  9. package/dist/database/schema.js +18 -2
  10. package/dist/database/schema.js.map +1 -1
  11. package/dist/features/connector-environment/environment.query.d.ts +12 -0
  12. package/dist/features/connector-environment/environment.query.d.ts.map +1 -0
  13. package/dist/features/connector-environment/environment.query.js +12 -0
  14. package/dist/features/connector-environment/environment.query.js.map +1 -0
  15. package/dist/features/connector-environment/environment.scope.d.ts +13 -0
  16. package/dist/features/connector-environment/environment.scope.d.ts.map +1 -0
  17. package/dist/features/connector-environment/environment.scope.js +16 -0
  18. package/dist/features/connector-environment/environment.scope.js.map +1 -0
  19. package/dist/features/connector-environment/environment.types.d.ts +11 -0
  20. package/dist/features/connector-environment/environment.types.d.ts.map +1 -0
  21. package/dist/features/connector-environment/environment.types.js +5 -0
  22. package/dist/features/connector-environment/environment.types.js.map +1 -0
  23. package/dist/features/connector-environment/index.d.ts +4 -0
  24. package/dist/features/connector-environment/index.d.ts.map +1 -0
  25. package/dist/features/connector-environment/index.js +4 -0
  26. package/dist/features/connector-environment/index.js.map +1 -0
  27. package/dist/features/incident-priority/index.d.ts +3 -0
  28. package/dist/features/incident-priority/index.d.ts.map +1 -0
  29. package/dist/features/incident-priority/index.js +3 -0
  30. package/dist/features/incident-priority/index.js.map +1 -0
  31. package/dist/features/incident-priority/priority.rules.d.ts +15 -0
  32. package/dist/features/incident-priority/priority.rules.d.ts.map +1 -0
  33. package/dist/features/incident-priority/priority.rules.js +38 -0
  34. package/dist/features/incident-priority/priority.rules.js.map +1 -0
  35. package/dist/features/incident-priority/priority.types.d.ts +13 -0
  36. package/dist/features/incident-priority/priority.types.d.ts.map +1 -0
  37. package/dist/features/incident-priority/priority.types.js +7 -0
  38. package/dist/features/incident-priority/priority.types.js.map +1 -0
  39. package/dist/features/sla/domain/sla.defaults.d.ts +8 -0
  40. package/dist/features/sla/domain/sla.defaults.d.ts.map +1 -0
  41. package/dist/features/sla/domain/sla.defaults.js +15 -0
  42. package/dist/features/sla/domain/sla.defaults.js.map +1 -0
  43. package/dist/features/sla/domain/sla.evaluator.d.ts +1 -1
  44. package/dist/features/sla/domain/sla.evaluator.d.ts.map +1 -1
  45. package/dist/features/sla/domain/sla.evaluator.js +4 -2
  46. package/dist/features/sla/domain/sla.evaluator.js.map +1 -1
  47. package/dist/features/sla/domain/sla.resolver.d.ts +11 -11
  48. package/dist/features/sla/domain/sla.resolver.d.ts.map +1 -1
  49. package/dist/features/sla/domain/sla.resolver.js +41 -15
  50. package/dist/features/sla/domain/sla.resolver.js.map +1 -1
  51. package/dist/features/sla/domain/sla.types.d.ts +28 -3
  52. package/dist/features/sla/domain/sla.types.d.ts.map +1 -1
  53. package/dist/features/sla/domain/sla.types.js.map +1 -1
  54. package/dist/features/sla/index.d.ts +2 -1
  55. package/dist/features/sla/index.d.ts.map +1 -1
  56. package/dist/features/sla/index.js +1 -0
  57. package/dist/features/sla/index.js.map +1 -1
  58. package/dist/features/sla/sla-policy.model.d.ts +23 -10
  59. package/dist/features/sla/sla-policy.model.d.ts.map +1 -1
  60. package/dist/features/sla/sla-policy.model.js +50 -28
  61. package/dist/features/sla/sla-policy.model.js.map +1 -1
  62. package/dist/features/sla/sla-policy.service.d.ts +7 -13
  63. package/dist/features/sla/sla-policy.service.d.ts.map +1 -1
  64. package/dist/features/sla/sla-policy.service.js +25 -20
  65. package/dist/features/sla/sla-policy.service.js.map +1 -1
  66. package/dist/features/sla/sla.schema.d.ts +19 -2
  67. package/dist/features/sla/sla.schema.d.ts.map +1 -1
  68. package/dist/features/sla/sla.schema.js +7 -6
  69. package/dist/features/sla/sla.schema.js.map +1 -1
  70. package/dist/migrations/run.d.ts.map +1 -1
  71. package/dist/migrations/run.js +91 -5
  72. package/dist/migrations/run.js.map +1 -1
  73. package/dist/models/alert.model.d.ts +2 -0
  74. package/dist/models/alert.model.d.ts.map +1 -1
  75. package/dist/models/alert.model.js +4 -0
  76. package/dist/models/alert.model.js.map +1 -1
  77. package/dist/models/incident.model.d.ts +5 -0
  78. package/dist/models/incident.model.d.ts.map +1 -1
  79. package/dist/models/incident.model.js +10 -0
  80. package/dist/models/incident.model.js.map +1 -1
  81. package/dist/service.d.ts +2 -1
  82. package/dist/service.d.ts.map +1 -1
  83. package/dist/service.js +1 -1
  84. package/dist/service.js.map +1 -1
  85. package/dist/services/alert.service.d.ts +2 -0
  86. package/dist/services/alert.service.d.ts.map +1 -1
  87. package/dist/services/alert.service.js +3 -0
  88. package/dist/services/alert.service.js.map +1 -1
  89. package/dist/services/connector.service.d.ts +3 -0
  90. package/dist/services/connector.service.d.ts.map +1 -1
  91. package/dist/services/incident.service.d.ts +10 -0
  92. package/dist/services/incident.service.d.ts.map +1 -1
  93. package/dist/services/incident.service.js +20 -5
  94. package/dist/services/incident.service.js.map +1 -1
  95. package/dist/services/workflow.service.d.ts.map +1 -1
  96. package/dist/services/workflow.service.js +2 -0
  97. package/dist/services/workflow.service.js.map +1 -1
  98. package/package.json +1 -1
@@ -1,18 +1,43 @@
1
+ import type { IncidentPriority } from "../../incident-priority/priority.types.js";
1
2
  /** Where an effective SLA policy came from. */
2
3
  export type SlaPolicySource = "account" | "default";
4
+ /** Acknowledge and resolve limits for one priority. */
5
+ export interface SlaTarget {
6
+ ackMinutes: number;
7
+ resolveMinutes: number;
8
+ }
9
+ /** Limits for every priority; an enabled account always has all four. */
10
+ export type SlaTargets = Record<IncidentPriority, SlaTarget>;
11
+ /** The policy that applies to one incident: its account's settings resolved for the incident's priority. */
3
12
  export interface SlaPolicy {
4
13
  enabled: boolean;
14
+ priority: IncidentPriority;
5
15
  ackMinutes: number;
6
16
  resolveMinutes: number;
7
17
  source: SlaPolicySource;
8
18
  }
9
- /** Persisted per-account override (one row per tenant + AWS account). */
19
+ /** Persisted account-level switch (one row per tenant + AWS account). */
10
20
  export interface SlaPolicyRecord {
11
21
  tenantId: string;
12
22
  accountId: string;
13
23
  enabled: boolean;
24
+ updatedBy: string | null;
25
+ updatedAt: Date | string | null;
26
+ }
27
+ /** Persisted limits for one priority of one account. */
28
+ export interface SlaTargetRecord {
29
+ tenantId: string;
30
+ accountId: string;
31
+ priority: IncidentPriority;
14
32
  ackMinutes: number;
15
33
  resolveMinutes: number;
34
+ }
35
+ /** An account's whole SLA configuration, as the API presents it. */
36
+ export interface AccountSlaConfig {
37
+ accountId: string;
38
+ enabled: boolean;
39
+ source: SlaPolicySource;
40
+ targets: SlaTargets;
16
41
  updatedBy: string | null;
17
42
  updatedAt: Date | string | null;
18
43
  }
@@ -40,8 +65,8 @@ export interface SlaIncidentInput {
40
65
  ackedAt?: Date | string | null;
41
66
  resolvedAt?: Date | string | null;
42
67
  }
43
- /** Resolves the effective policy for an incident's account. Built once per request. */
44
- export type SlaPolicyResolver = (accountId: string | null | undefined) => SlaPolicy;
68
+ /** Resolves the effective policy for an incident's account and priority. Built once per request. */
69
+ export type SlaPolicyResolver = (accountId: string | null | undefined, priority: IncidentPriority) => SlaPolicy;
45
70
  /**
46
71
  * Port used by incident code so it doesn't depend on persistence details.
47
72
  * `tenantId` undefined yields a resolver that only returns defaults.
@@ -1 +1 @@
1
- {"version":3,"file":"sla.types.d.ts","sourceRoot":"","sources":["../../../../src/features/sla/domain/sla.types.ts"],"names":[],"mappings":"AAAA,+CAA+C;AAC/C,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpD,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,eAAe,CAAC;CACzB;AAED,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AAEpF,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,aAAa,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,gFAAgF;IAChF,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,SAAS,CAAC;IAClB,GAAG,EAAE,QAAQ,CAAC;IACd,OAAO,EAAE,QAAQ,CAAC;IAClB,+DAA+D;IAC/D,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,kDAAkD;AAClD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC5C,oDAAoD;IACpD,OAAO,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IAC/B,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,uFAAuF;AACvF,MAAM,MAAM,iBAAiB,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,KAAK,SAAS,CAAC;AAEpF;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC7D;AAED,eAAO,MAAM,UAAU;;IAErB,eAAe;;CAEP,CAAC"}
1
+ {"version":3,"file":"sla.types.d.ts","sourceRoot":"","sources":["../../../../src/features/sla/domain/sla.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2CAA2C,CAAC;AAElF,+CAA+C;AAC/C,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,SAAS,CAAC;AAEpD,uDAAuD;AACvD,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,yEAAyE;AACzE,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC,gBAAgB,EAAE,SAAS,CAAC,CAAC;AAE7D,4GAA4G;AAC5G,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,eAAe,CAAC;CACzB;AAED,yEAAyE;AACzE,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,wDAAwD;AACxD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,oEAAoE;AACpE,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,eAAe,CAAC;IACxB,OAAO,EAAE,UAAU,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;AAEpF,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,aAAa,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,gFAAgF;IAChF,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,SAAS,CAAC;IAClB,GAAG,EAAE,QAAQ,CAAC;IACd,OAAO,EAAE,QAAQ,CAAC;IAClB,+DAA+D;IAC/D,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,kDAAkD;AAClD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAC5C,oDAAoD;IACpD,OAAO,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IAC/B,UAAU,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;CACnC;AAED,oGAAoG;AACpG,MAAM,MAAM,iBAAiB,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,QAAQ,EAAE,gBAAgB,KAAK,SAAS,CAAC;AAEhH;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;CAC7D;AAED,eAAO,MAAM,UAAU;;IAErB,eAAe;;CAEP,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"sla.types.js","sourceRoot":"","sources":["../../../../src/features/sla/domain/sla.types.ts"],"names":[],"mappings":"AA4DA,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,UAAU,EAAE,CAAC;IACb,eAAe;IACf,UAAU,EAAE,MAAM;CACV,CAAC"}
1
+ {"version":3,"file":"sla.types.js","sourceRoot":"","sources":["../../../../src/features/sla/domain/sla.types.ts"],"names":[],"mappings":"AA0FA,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,UAAU,EAAE,CAAC;IACb,eAAe;IACf,UAAU,EAAE,MAAM;CACV,CAAC"}
@@ -1,7 +1,8 @@
1
1
  export * from "./domain/sla.types.js";
2
+ export * from "./domain/sla.defaults.js";
2
3
  export * from "./domain/sla.resolver.js";
3
4
  export * from "./domain/sla.evaluator.js";
4
5
  export { SlaPolicyModel } from "./sla-policy.model.js";
5
- export { SlaPolicyService, SlaError, type AccountSlaPolicy } from "./sla-policy.service.js";
6
+ export { SlaPolicyService, SlaError } from "./sla-policy.service.js";
6
7
  export { createSlaRouter } from "./sla.routes.js";
7
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/sla/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,KAAK,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC5F,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/features/sla/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export * from "./domain/sla.types.js";
2
+ export * from "./domain/sla.defaults.js";
2
3
  export * from "./domain/sla.resolver.js";
3
4
  export * from "./domain/sla.evaluator.js";
4
5
  export { SlaPolicyModel } from "./sla-policy.model.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/features/sla/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAyB,MAAM,yBAAyB,CAAC;AAC5F,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/features/sla/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC"}
@@ -1,19 +1,32 @@
1
- import type { SlaPolicyRecord } from "./domain/sla.types.js";
2
- /** Persistence only: every query is scoped by tenant_id. No business rules here. */
1
+ import type { SlaPolicyRecord, SlaTargetRecord, SlaTargets } from "./domain/sla.types.js";
2
+ /**
3
+ * Persistence for an account's SLA policy: the account-level switch plus its per-priority limits.
4
+ * Every query is scoped by tenant_id; there are no business rules here.
5
+ */
3
6
  export declare class SlaPolicyModel {
4
7
  private db;
5
- private tbl;
6
- constructor(db: any, tbl: any);
7
- listByTenant(tenantId: string): Promise<SlaPolicyRecord[]>;
8
- findByAccount(tenantId: string, accountId: string): Promise<SlaPolicyRecord | null>;
9
- upsert(input: {
8
+ private policies;
9
+ private targets;
10
+ constructor(db: any, policies: any, targets: any);
11
+ listByTenant(tenantId: string): Promise<{
12
+ policies: SlaPolicyRecord[];
13
+ targets: SlaTargetRecord[];
14
+ }>;
15
+ findByAccount(tenantId: string, accountId: string): Promise<{
16
+ policy: SlaPolicyRecord | null;
17
+ targets: SlaTargetRecord[];
18
+ }>;
19
+ /** Saves the switch and replaces all four priority limits atomically, so an account is never half-saved. */
20
+ save(input: {
10
21
  tenantId: string;
11
22
  accountId: string;
12
23
  enabled: boolean;
13
- ackMinutes: number;
14
- resolveMinutes: number;
24
+ targets: SlaTargets;
15
25
  updatedBy: string | null;
16
- }): Promise<SlaPolicyRecord>;
26
+ }): Promise<{
27
+ policy: SlaPolicyRecord;
28
+ targets: SlaTargetRecord[];
29
+ }>;
17
30
  delete(tenantId: string, accountId: string): Promise<void>;
18
31
  }
19
32
  //# sourceMappingURL=sla-policy.model.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sla-policy.model.d.ts","sourceRoot":"","sources":["../../../src/features/sla/sla-policy.model.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D,oFAAoF;AACpF,qBAAa,cAAc;IAEvB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,GAAG;gBADH,EAAE,EAAE,GAAG,EACP,GAAG,EAAE,GAAG;IAGZ,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAI1D,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IASnF,MAAM,CAAC,KAAK,EAAE;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,cAAc,EAAE,MAAM,CAAC;QACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,GAAG,OAAO,CAAC,eAAe,CAAC;IAkBtB,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAKjE"}
1
+ {"version":3,"file":"sla-policy.model.d.ts","sourceRoot":"","sources":["../../../src/features/sla/sla-policy.model.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAE1F;;;GAGG;AACH,qBAAa,cAAc;IAEvB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,OAAO;gBAFP,EAAE,EAAE,GAAG,EACP,QAAQ,EAAE,GAAG,EACb,OAAO,EAAE,GAAG;IAGhB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;QAAC,OAAO,EAAE,eAAe,EAAE,CAAA;KAAE,CAAC;IAMpG,aAAa,CACjB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,MAAM,EAAE,eAAe,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,eAAe,EAAE,CAAA;KAAE,CAAC;IAa1E,4GAA4G;IACtG,IAAI,CAAC,KAAK,EAAE;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,EAAE,UAAU,CAAC;QACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;KAC1B,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,eAAe,CAAC;QAAC,OAAO,EAAE,eAAe,EAAE,CAAA;KAAE,CAAC;IAsB9D,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAUjE"}
@@ -1,44 +1,66 @@
1
1
  import { and, eq } from "drizzle-orm";
2
- /** Persistence only: every query is scoped by tenant_id. No business rules here. */
2
+ import { INCIDENT_PRIORITIES } from "../incident-priority/priority.types.js";
3
+ /**
4
+ * Persistence for an account's SLA policy: the account-level switch plus its per-priority limits.
5
+ * Every query is scoped by tenant_id; there are no business rules here.
6
+ */
3
7
  export class SlaPolicyModel {
4
8
  db;
5
- tbl;
6
- constructor(db, tbl) {
9
+ policies;
10
+ targets;
11
+ constructor(db, policies, targets) {
7
12
  this.db = db;
8
- this.tbl = tbl;
13
+ this.policies = policies;
14
+ this.targets = targets;
9
15
  }
10
16
  async listByTenant(tenantId) {
11
- return this.db.select().from(this.tbl).where(eq(this.tbl.tenantId, tenantId));
17
+ const policies = await this.db.select().from(this.policies).where(eq(this.policies.tenantId, tenantId));
18
+ const targets = await this.db.select().from(this.targets).where(eq(this.targets.tenantId, tenantId));
19
+ return { policies, targets };
12
20
  }
13
21
  async findByAccount(tenantId, accountId) {
14
- const [row] = await this.db
22
+ const [policy] = await this.db
15
23
  .select()
16
- .from(this.tbl)
17
- .where(and(eq(this.tbl.tenantId, tenantId), eq(this.tbl.accountId, accountId)))
24
+ .from(this.policies)
25
+ .where(and(eq(this.policies.tenantId, tenantId), eq(this.policies.accountId, accountId)))
18
26
  .limit(1);
19
- return row ?? null;
27
+ const targets = await this.db
28
+ .select()
29
+ .from(this.targets)
30
+ .where(and(eq(this.targets.tenantId, tenantId), eq(this.targets.accountId, accountId)));
31
+ return { policy: policy ?? null, targets };
20
32
  }
21
- async upsert(input) {
22
- const [row] = await this.db
23
- .insert(this.tbl)
24
- .values(input)
25
- .onConflictDoUpdate({
26
- target: [this.tbl.tenantId, this.tbl.accountId],
27
- set: {
28
- enabled: input.enabled,
29
- ackMinutes: input.ackMinutes,
30
- resolveMinutes: input.resolveMinutes,
31
- updatedBy: input.updatedBy,
32
- updatedAt: new Date(),
33
- },
34
- })
35
- .returning();
36
- return row;
33
+ /** Saves the switch and replaces all four priority limits atomically, so an account is never half-saved. */
34
+ async save(input) {
35
+ const { tenantId, accountId, enabled, targets, updatedBy } = input;
36
+ return this.db.transaction(async (tx) => {
37
+ const [policy] = await tx
38
+ .insert(this.policies)
39
+ .values({ tenantId, accountId, enabled, updatedBy })
40
+ .onConflictDoUpdate({
41
+ target: [this.policies.tenantId, this.policies.accountId],
42
+ set: { enabled, updatedBy, updatedAt: new Date() },
43
+ })
44
+ .returning();
45
+ await tx
46
+ .delete(this.targets)
47
+ .where(and(eq(this.targets.tenantId, tenantId), eq(this.targets.accountId, accountId)));
48
+ const rows = await tx
49
+ .insert(this.targets)
50
+ .values(INCIDENT_PRIORITIES.map((priority) => ({ tenantId, accountId, priority, ...targets[priority] })))
51
+ .returning();
52
+ return { policy, targets: rows };
53
+ });
37
54
  }
38
55
  async delete(tenantId, accountId) {
39
- await this.db
40
- .delete(this.tbl)
41
- .where(and(eq(this.tbl.tenantId, tenantId), eq(this.tbl.accountId, accountId)));
56
+ await this.db.transaction(async (tx) => {
57
+ await tx
58
+ .delete(this.targets)
59
+ .where(and(eq(this.targets.tenantId, tenantId), eq(this.targets.accountId, accountId)));
60
+ await tx
61
+ .delete(this.policies)
62
+ .where(and(eq(this.policies.tenantId, tenantId), eq(this.policies.accountId, accountId)));
63
+ });
42
64
  }
43
65
  }
44
66
  //# sourceMappingURL=sla-policy.model.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sla-policy.model.js","sourceRoot":"","sources":["../../../src/features/sla/sla-policy.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AAGtC,oFAAoF;AACpF,MAAM,OAAO,cAAc;IAEf;IACA;IAFV,YACU,EAAO,EACP,GAAQ;QADR,OAAE,GAAF,EAAE,CAAK;QACP,QAAG,GAAH,GAAG,CAAK;IACf,CAAC;IAEJ,KAAK,CAAC,YAAY,CAAC,QAAgB;QACjC,OAAO,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IAChF,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,QAAgB,EAAE,SAAiB;QACrD,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,IAAI,CAAC,EAAE;aACxB,MAAM,EAAE;aACR,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;aACd,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;aAC9E,KAAK,CAAC,CAAC,CAAC,CAAC;QACZ,OAAO,GAAG,IAAI,IAAI,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAOZ;QACC,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,IAAI,CAAC,EAAE;aACxB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;aAChB,MAAM,CAAC,KAAK,CAAC;aACb,kBAAkB,CAAC;YAClB,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC;YAC/C,GAAG,EAAE;gBACH,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,UAAU,EAAE,KAAK,CAAC,UAAU;gBAC5B,cAAc,EAAE,KAAK,CAAC,cAAc;gBACpC,SAAS,EAAE,KAAK,CAAC,SAAS;gBAC1B,SAAS,EAAE,IAAI,IAAI,EAAE;aACtB;SACF,CAAC;aACD,SAAS,EAAE,CAAC;QACf,OAAO,GAAG,CAAC;IACb,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAAgB,EAAE,SAAiB;QAC9C,MAAM,IAAI,CAAC,EAAE;aACV,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;aAChB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC;IACpF,CAAC;CACF"}
1
+ {"version":3,"file":"sla-policy.model.js","sourceRoot":"","sources":["../../../src/features/sla/sla-policy.model.ts"],"names":[],"mappings":"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"}
@@ -1,29 +1,23 @@
1
1
  import type { ConnectorService } from "../../services/connector.service.js";
2
2
  import type { SlaPolicyModel } from "./sla-policy.model.js";
3
- import type { SlaPolicy, SlaPolicyProvider, SlaPolicyResolver } from "./domain/sla.types.js";
3
+ import type { AccountSlaConfig, SlaPolicyProvider, SlaPolicyResolver } from "./domain/sla.types.js";
4
4
  export declare class SlaError extends Error {
5
5
  readonly status: 400 | 404;
6
6
  readonly details?: unknown;
7
7
  constructor(status: 400 | 404, message: string, details?: unknown);
8
8
  }
9
- export interface AccountSlaPolicy extends SlaPolicy {
10
- accountId: string;
11
- updatedBy: string | null;
12
- updatedAt: Date | string | null;
13
- }
14
9
  export declare class SlaPolicyService implements SlaPolicyProvider {
15
10
  private model;
16
11
  private connectors;
17
12
  constructor(model: SlaPolicyModel, connectors: ConnectorService);
18
13
  /** The account must be one of this tenant's connectors; prevents writing policies for foreign accounts. */
19
14
  private assertConnector;
20
- private toAccountPolicy;
21
- list(tenantId: string): Promise<AccountSlaPolicy[]>;
22
- get(tenantId: string, accountId: string): Promise<AccountSlaPolicy>;
23
- upsert(tenantId: string, accountId: string, input: unknown, actor: string | null): Promise<AccountSlaPolicy>;
24
- /** Removes the override so the account falls back to defaults. */
25
- reset(tenantId: string, accountId: string): Promise<AccountSlaPolicy>;
26
- /** One query per request; used by incident dashboards, analytics and detail. */
15
+ list(tenantId: string): Promise<AccountSlaConfig[]>;
16
+ get(tenantId: string, accountId: string): Promise<AccountSlaConfig>;
17
+ upsert(tenantId: string, accountId: string, input: unknown, actor: string | null): Promise<AccountSlaConfig>;
18
+ /** Removes the policy and its limits so the account falls back to SLA off. */
19
+ reset(tenantId: string, accountId: string): Promise<AccountSlaConfig>;
20
+ /** One query pair per request; used by incident dashboards, analytics, list and detail. */
27
21
  loadResolver(tenantId?: string): Promise<SlaPolicyResolver>;
28
22
  }
29
23
  //# sourceMappingURL=sla-policy.service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sla-policy.service.d.ts","sourceRoot":"","sources":["../../../src/features/sla/sla-policy.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,OAAO,KAAK,EAAE,SAAS,EAAE,iBAAiB,EAAmB,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAE9G,qBAAa,QAAS,SAAQ,KAAK;IAE/B,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG;IAE1B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO;gBAFjB,MAAM,EAAE,GAAG,GAAG,GAAG,EAC1B,OAAO,EAAE,MAAM,EACN,OAAO,CAAC,EAAE,OAAO;CAI7B;AAED,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,qBAAa,gBAAiB,YAAW,iBAAiB;IAEtD,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,UAAU;gBADV,KAAK,EAAE,cAAc,EACrB,UAAU,EAAE,gBAAgB;IAGtC,2GAA2G;YAC7F,eAAe;IAK7B,OAAO,CAAC,eAAe;IAKjB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAKnD,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAKnE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAWlH,kEAAkE;IAC5D,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAM3E,gFAAgF;IAC1E,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;CASlE"}
1
+ {"version":3,"file":"sla-policy.service.d.ts","sourceRoot":"","sources":["../../../src/features/sla/sla-policy.service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG5D,OAAO,KAAK,EACV,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EAElB,MAAM,uBAAuB,CAAC;AAE/B,qBAAa,QAAS,SAAQ,KAAK;IAE/B,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG;IAE1B,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO;gBAFjB,MAAM,EAAE,GAAG,GAAG,GAAG,EAC1B,OAAO,EAAE,MAAM,EACN,OAAO,CAAC,EAAE,OAAO;CAI7B;AAQD,qBAAa,gBAAiB,YAAW,iBAAiB;IAEtD,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,UAAU;gBADV,KAAK,EAAE,cAAc,EACrB,UAAU,EAAE,gBAAgB;IAGtC,2GAA2G;YAC7F,eAAe;IAKvB,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAOnD,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAMnE,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAWlH,8EAA8E;IACxE,KAAK,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAM3E,2FAA2F;IACrF,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;CAUlE"}
@@ -1,5 +1,5 @@
1
1
  import { SlaPolicyInputSchema } from "./sla.schema.js";
2
- import { createSlaResolver, defaultSlaPolicy, policyFromRecord } from "./domain/sla.resolver.js";
2
+ import { accountConfigFromRecords, createSlaResolver } from "./domain/sla.resolver.js";
3
3
  export class SlaError extends Error {
4
4
  status;
5
5
  details;
@@ -9,6 +9,11 @@ export class SlaError extends Error {
9
9
  this.details = details;
10
10
  }
11
11
  }
12
+ /** "P2: Resolve limit must be..." so the user can tell which priority row is wrong. */
13
+ function describeIssue(issue) {
14
+ const priority = issue.path[0] === "targets" ? String(issue.path[1] ?? "") : "";
15
+ return priority ? `${priority}: ${issue.message}` : issue.message;
16
+ }
12
17
  export class SlaPolicyService {
13
18
  model;
14
19
  connectors;
@@ -22,45 +27,45 @@ export class SlaPolicyService {
22
27
  if (!connector)
23
28
  throw new SlaError(404, "Connector not found");
24
29
  }
25
- toAccountPolicy(accountId, record) {
26
- if (!record)
27
- return { ...defaultSlaPolicy(), accountId, updatedBy: null, updatedAt: null };
28
- return { ...policyFromRecord(record), accountId, updatedBy: record.updatedBy, updatedAt: record.updatedAt };
29
- }
30
30
  async list(tenantId) {
31
- const records = await this.model.listByTenant(tenantId);
32
- return records.map((r) => this.toAccountPolicy(r.accountId, r));
31
+ const { policies, targets } = await this.model.listByTenant(tenantId);
32
+ const byAccount = new Map();
33
+ for (const t of targets)
34
+ byAccount.set(t.accountId, [...(byAccount.get(t.accountId) ?? []), t]);
35
+ return policies.map((p) => accountConfigFromRecords(p.accountId, p, byAccount.get(p.accountId) ?? []));
33
36
  }
34
37
  async get(tenantId, accountId) {
35
38
  await this.assertConnector(tenantId, accountId);
36
- return this.toAccountPolicy(accountId, await this.model.findByAccount(tenantId, accountId));
39
+ const { policy, targets } = await this.model.findByAccount(tenantId, accountId);
40
+ return accountConfigFromRecords(accountId, policy, targets);
37
41
  }
38
42
  async upsert(tenantId, accountId, input, actor) {
39
43
  const parsed = SlaPolicyInputSchema.safeParse(input);
40
44
  if (!parsed.success) {
41
- throw new SlaError(400, parsed.error.issues[0]?.message ?? "Invalid SLA policy", parsed.error.issues);
45
+ const first = parsed.error.issues[0];
46
+ throw new SlaError(400, first ? describeIssue(first) : "Invalid SLA policy", parsed.error.issues);
42
47
  }
43
48
  await this.assertConnector(tenantId, accountId);
44
- const data = parsed.data;
45
- const record = await this.model.upsert({ tenantId, accountId, ...data, updatedBy: actor });
46
- return this.toAccountPolicy(accountId, record);
49
+ const saved = await this.model.save({ tenantId, accountId, ...parsed.data, updatedBy: actor });
50
+ return accountConfigFromRecords(accountId, saved.policy, saved.targets);
47
51
  }
48
- /** Removes the override so the account falls back to defaults. */
52
+ /** Removes the policy and its limits so the account falls back to SLA off. */
49
53
  async reset(tenantId, accountId) {
50
54
  await this.assertConnector(tenantId, accountId);
51
55
  await this.model.delete(tenantId, accountId);
52
- return this.toAccountPolicy(accountId, null);
56
+ return accountConfigFromRecords(accountId, null, []);
53
57
  }
54
- /** One query per request; used by incident dashboards, analytics and detail. */
58
+ /** One query pair per request; used by incident dashboards, analytics, list and detail. */
55
59
  async loadResolver(tenantId) {
56
60
  if (!tenantId)
57
- return createSlaResolver([]);
61
+ return createSlaResolver([], []);
58
62
  try {
59
- return createSlaResolver(await this.model.listByTenant(tenantId));
63
+ const { policies, targets } = await this.model.listByTenant(tenantId);
64
+ return createSlaResolver(policies, targets);
60
65
  }
61
66
  catch {
62
- // Never break incident views because the policy table is unavailable; fall back to defaults.
63
- return createSlaResolver([]);
67
+ // Never break incident views because the policy tables are unavailable; fall back to defaults.
68
+ return createSlaResolver([], []);
64
69
  }
65
70
  }
66
71
  }
@@ -1 +1 @@
1
- {"version":3,"file":"sla-policy.service.js","sourceRoot":"","sources":["../../../src/features/sla/sla-policy.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sla-policy.service.js","sourceRoot":"","sources":["../../../src/features/sla/sla-policy.service.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,25 @@
1
1
  import { z } from "zod";
2
+ /** Every priority is required, so an enabled account always has complete limits. */
2
3
  export declare const SlaPolicyInputSchema: z.ZodObject<{
3
4
  enabled: z.ZodBoolean;
4
- ackMinutes: z.ZodNumber;
5
- resolveMinutes: z.ZodNumber;
5
+ targets: z.ZodObject<{
6
+ P1: z.ZodObject<{
7
+ ackMinutes: z.ZodNumber;
8
+ resolveMinutes: z.ZodNumber;
9
+ }, z.core.$strip>;
10
+ P2: z.ZodObject<{
11
+ ackMinutes: z.ZodNumber;
12
+ resolveMinutes: z.ZodNumber;
13
+ }, z.core.$strip>;
14
+ P3: z.ZodObject<{
15
+ ackMinutes: z.ZodNumber;
16
+ resolveMinutes: z.ZodNumber;
17
+ }, z.core.$strip>;
18
+ P4: z.ZodObject<{
19
+ ackMinutes: z.ZodNumber;
20
+ resolveMinutes: z.ZodNumber;
21
+ }, z.core.$strip>;
22
+ }, z.core.$strip>;
6
23
  }, z.core.$strip>;
7
24
  export type SlaPolicyInput = z.infer<typeof SlaPolicyInputSchema>;
8
25
  //# sourceMappingURL=sla.schema.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sla.schema.d.ts","sourceRoot":"","sources":["../../../src/features/sla/sla.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AASxB,eAAO,MAAM,oBAAoB;;;;iBAS7B,CAAC;AAEL,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
1
+ {"version":3,"file":"sla.schema.d.ts","sourceRoot":"","sources":["../../../src/features/sla/sla.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAgBxB,oFAAoF;AACpF,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;iBAG/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
@@ -5,14 +5,15 @@ const minutes = z
5
5
  .int("Must be a whole number of minutes")
6
6
  .min(SLA_LIMITS.minMinutes, `Must be at least ${SLA_LIMITS.minMinutes} minute`)
7
7
  .max(SLA_LIMITS.maxMinutes, `Must be at most ${SLA_LIMITS.maxMinutes} minutes (30 days)`);
8
- export const SlaPolicyInputSchema = z
9
- .object({
10
- enabled: z.boolean(),
11
- ackMinutes: minutes,
12
- resolveMinutes: minutes,
13
- })
8
+ const target = z
9
+ .object({ ackMinutes: minutes, resolveMinutes: minutes })
14
10
  .refine((v) => v.resolveMinutes >= v.ackMinutes, {
15
11
  message: "Resolve limit must be greater than or equal to the acknowledge limit",
16
12
  path: ["resolveMinutes"],
17
13
  });
14
+ /** Every priority is required, so an enabled account always has complete limits. */
15
+ export const SlaPolicyInputSchema = z.object({
16
+ enabled: z.boolean(),
17
+ targets: z.object({ P1: target, P2: target, P3: target, P4: target }),
18
+ });
18
19
  //# sourceMappingURL=sla.schema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"sla.schema.js","sourceRoot":"","sources":["../../../src/features/sla/sla.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,MAAM,OAAO,GAAG,CAAC;KACd,MAAM,EAAE;KACR,GAAG,CAAC,mCAAmC,CAAC;KACxC,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,oBAAoB,UAAU,CAAC,UAAU,SAAS,CAAC;KAC9E,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,mBAAmB,UAAU,CAAC,UAAU,oBAAoB,CAAC,CAAC;AAE5F,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC;KAClC,MAAM,CAAC;IACN,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,UAAU,EAAE,OAAO;IACnB,cAAc,EAAE,OAAO;CACxB,CAAC;KACD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,UAAU,EAAE;IAC/C,OAAO,EAAE,sEAAsE;IAC/E,IAAI,EAAE,CAAC,gBAAgB,CAAC;CACzB,CAAC,CAAC"}
1
+ {"version":3,"file":"sla.schema.js","sourceRoot":"","sources":["../../../src/features/sla/sla.schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAEnD,MAAM,OAAO,GAAG,CAAC;KACd,MAAM,EAAE;KACR,GAAG,CAAC,mCAAmC,CAAC;KACxC,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,oBAAoB,UAAU,CAAC,UAAU,SAAS,CAAC;KAC9E,GAAG,CAAC,UAAU,CAAC,UAAU,EAAE,mBAAmB,UAAU,CAAC,UAAU,oBAAoB,CAAC,CAAC;AAE5F,MAAM,MAAM,GAAG,CAAC;KACb,MAAM,CAAC,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,CAAC;KACxD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,UAAU,EAAE;IAC/C,OAAO,EAAE,sEAAsE;IAC/E,IAAI,EAAE,CAAC,gBAAgB,CAAC;CACzB,CAAC,CAAC;AAEL,oFAAoF;AACpF,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE;IACpB,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;CACtE,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/migrations/run.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAizC1D"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/migrations/run.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAsB,aAAa,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAy4C1D"}
@@ -1188,6 +1188,15 @@ export async function runMigrations(db) {
1188
1188
  await db.execute(sql.raw(`
1189
1189
  CREATE INDEX IF NOT EXISTS insight_connectors_connection_idx
1190
1190
  ON "meyiconnect"."insight_connectors" ("connection_id")
1191
+ `));
1192
+ // connectors.environment: the live table is "connectors" (created by onboarding); guard in case it
1193
+ // doesn't exist yet. Onboarding's migrate.ts also adds this column, so either service may run first.
1194
+ await db.execute(sql.raw(`
1195
+ DO $$ BEGIN
1196
+ IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_schema = 'meyiconnect' AND table_name = 'connectors') THEN
1197
+ ALTER TABLE "meyiconnect"."connectors" ADD COLUMN IF NOT EXISTS "environment" TEXT;
1198
+ END IF;
1199
+ END $$
1191
1200
  `));
1192
1201
  await db.execute(sql.raw(`
1193
1202
  CREATE INDEX IF NOT EXISTS insight_connectors_access_status_idx
@@ -1201,13 +1210,9 @@ export async function runMigrations(db) {
1201
1210
  "tenant_id" TEXT NOT NULL,
1202
1211
  "account_id" TEXT NOT NULL,
1203
1212
  "enabled" BOOLEAN NOT NULL DEFAULT true,
1204
- "ack_minutes" INTEGER NOT NULL,
1205
- "resolve_minutes" INTEGER NOT NULL,
1206
1213
  "updated_by" TEXT,
1207
1214
  "created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1208
- "updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1209
- CONSTRAINT insight_connector_sla_policies_limits_chk
1210
- CHECK (ack_minutes > 0 AND resolve_minutes >= ack_minutes AND resolve_minutes <= 43200)
1215
+ "updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW()
1211
1216
  )
1212
1217
  `));
1213
1218
  await db.execute(sql.raw(`
@@ -1217,6 +1222,52 @@ export async function runMigrations(db) {
1217
1222
  await db.execute(sql.raw(`
1218
1223
  CREATE INDEX IF NOT EXISTS insight_connector_sla_policies_tenant_idx
1219
1224
  ON "meyiconnect"."insight_connector_sla_policies" ("tenant_id")
1225
+ `));
1226
+ // ─── insight_connector_sla_targets ────────────────────────────────────────
1227
+ // Per-priority acknowledge/resolve limits for an account's SLA policy.
1228
+ await db.execute(sql.raw(`
1229
+ CREATE TABLE IF NOT EXISTS "meyiconnect"."insight_connector_sla_targets" (
1230
+ "id" UUID PRIMARY KEY DEFAULT gen_random_uuid(),
1231
+ "tenant_id" TEXT NOT NULL,
1232
+ "account_id" TEXT NOT NULL,
1233
+ "priority" TEXT NOT NULL,
1234
+ "ack_minutes" INTEGER NOT NULL,
1235
+ "resolve_minutes" INTEGER NOT NULL,
1236
+ "created_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1237
+ "updated_at" TIMESTAMPTZ NOT NULL DEFAULT NOW(),
1238
+ CONSTRAINT insight_connector_sla_targets_priority_chk CHECK (priority IN ('P1','P2','P3','P4')),
1239
+ CONSTRAINT insight_connector_sla_targets_limits_chk
1240
+ CHECK (ack_minutes > 0 AND resolve_minutes >= ack_minutes AND resolve_minutes <= 43200)
1241
+ )
1242
+ `));
1243
+ await db.execute(sql.raw(`
1244
+ CREATE UNIQUE INDEX IF NOT EXISTS insight_connector_sla_targets_tenant_account_priority_unique
1245
+ ON "meyiconnect"."insight_connector_sla_targets" ("tenant_id", "account_id", "priority")
1246
+ `));
1247
+ await db.execute(sql.raw(`
1248
+ CREATE INDEX IF NOT EXISTS insight_connector_sla_targets_tenant_idx
1249
+ ON "meyiconnect"."insight_connector_sla_targets" ("tenant_id")
1250
+ `));
1251
+ // Upgrade from the single-limit policy: copy each account's limits to all four priorities (so behaviour is
1252
+ // unchanged), then relax the old columns. They stay in place, unread, until a later release drops them.
1253
+ await db.execute(sql.raw(`
1254
+ DO $$ BEGIN
1255
+ IF EXISTS (
1256
+ SELECT 1 FROM information_schema.columns
1257
+ WHERE table_schema = 'meyiconnect' AND table_name = 'insight_connector_sla_policies' AND column_name = 'ack_minutes'
1258
+ ) THEN
1259
+ INSERT INTO "meyiconnect"."insight_connector_sla_targets" ("tenant_id", "account_id", "priority", "ack_minutes", "resolve_minutes")
1260
+ SELECT p."tenant_id", p."account_id", v."priority", p."ack_minutes", p."resolve_minutes"
1261
+ FROM "meyiconnect"."insight_connector_sla_policies" p
1262
+ CROSS JOIN (VALUES ('P1'), ('P2'), ('P3'), ('P4')) AS v("priority")
1263
+ WHERE p."ack_minutes" IS NOT NULL AND p."resolve_minutes" IS NOT NULL
1264
+ ON CONFLICT ("tenant_id", "account_id", "priority") DO NOTHING;
1265
+
1266
+ ALTER TABLE "meyiconnect"."insight_connector_sla_policies" ALTER COLUMN "ack_minutes" DROP NOT NULL;
1267
+ ALTER TABLE "meyiconnect"."insight_connector_sla_policies" ALTER COLUMN "resolve_minutes" DROP NOT NULL;
1268
+ ALTER TABLE "meyiconnect"."insight_connector_sla_policies" DROP CONSTRAINT IF EXISTS insight_connector_sla_policies_limits_chk;
1269
+ END IF;
1270
+ END $$
1220
1271
  `));
1221
1272
  // ─── insight_job_queue ────────────────────────────────────────────────────
1222
1273
  await db.execute(sql.raw(`
@@ -1284,5 +1335,40 @@ export async function runMigrations(db) {
1284
1335
  CREATE INDEX IF NOT EXISTS insight_incidents_tags_idx
1285
1336
  ON "meyiconnect"."insight_incidents" USING GIN ("tags");
1286
1337
  `));
1338
+ // ─── insight_incidents.priority ───────────────────────────────────────────
1339
+ // P1..P4. The default is set before the backfill so rows inserted meanwhile (e.g. by a server that
1340
+ // has not been upgraded yet) are never NULL when NOT NULL is applied.
1341
+ await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ADD COLUMN IF NOT EXISTS "priority" TEXT`));
1342
+ await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ALTER COLUMN "priority" SET DEFAULT 'P2'`));
1343
+ // Backfill: priority tag, else severity tag, else the linked alert's severity, else P2.
1344
+ await db.execute(sql.raw(`
1345
+ UPDATE "meyiconnect"."insight_incidents" i
1346
+ SET "priority" = COALESCE(
1347
+ CASE UPPER(BTRIM(i."tags"->>'priority'))
1348
+ WHEN 'P1' THEN 'P1' WHEN 'P2' THEN 'P2' WHEN 'P3' THEN 'P3' WHEN 'P4' THEN 'P4'
1349
+ END,
1350
+ CASE LOWER(BTRIM(i."tags"->>'severity'))
1351
+ WHEN 'critical' THEN 'P1' WHEN 'high' THEN 'P2' WHEN 'medium' THEN 'P3' WHEN 'low' THEN 'P4' WHEN 'info' THEN 'P4'
1352
+ END,
1353
+ CASE LOWER(BTRIM((SELECT a."severity" FROM "meyiconnect"."insight_alerts" a WHERE a."id" = i."source_alert_id")))
1354
+ WHEN 'critical' THEN 'P1' WHEN 'high' THEN 'P2' WHEN 'medium' THEN 'P3' WHEN 'low' THEN 'P4' WHEN 'info' THEN 'P4'
1355
+ END,
1356
+ 'P2'
1357
+ )
1358
+ WHERE i."priority" IS NULL
1359
+ `));
1360
+ await db.execute(sql.raw(`ALTER TABLE "meyiconnect"."insight_incidents" ALTER COLUMN "priority" SET NOT NULL`));
1361
+ await db.execute(sql.raw(`
1362
+ DO $$ BEGIN
1363
+ IF NOT EXISTS (SELECT 1 FROM pg_constraint WHERE conname = 'insight_incidents_priority_chk') THEN
1364
+ ALTER TABLE "meyiconnect"."insight_incidents" ADD CONSTRAINT insight_incidents_priority_chk
1365
+ CHECK ("priority" IN ('P1','P2','P3','P4'));
1366
+ END IF;
1367
+ END $$
1368
+ `));
1369
+ await db.execute(sql.raw(`
1370
+ CREATE INDEX IF NOT EXISTS insight_incidents_tenant_priority_idx
1371
+ ON "meyiconnect"."insight_incidents" ("tenant_id", "priority")
1372
+ `));
1287
1373
  }
1288
1374
  //# sourceMappingURL=run.js.map