@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.
- package/dist/controllers/alert.controller.d.ts.map +1 -1
- package/dist/controllers/alert.controller.js +5 -0
- package/dist/controllers/alert.controller.js.map +1 -1
- package/dist/controllers/incident.controller.d.ts.map +1 -1
- package/dist/controllers/incident.controller.js +18 -2
- package/dist/controllers/incident.controller.js.map +1 -1
- package/dist/database/schema.d.ts +163 -20
- package/dist/database/schema.d.ts.map +1 -1
- package/dist/database/schema.js +18 -2
- package/dist/database/schema.js.map +1 -1
- package/dist/features/connector-environment/environment.query.d.ts +12 -0
- package/dist/features/connector-environment/environment.query.d.ts.map +1 -0
- package/dist/features/connector-environment/environment.query.js +12 -0
- package/dist/features/connector-environment/environment.query.js.map +1 -0
- package/dist/features/connector-environment/environment.scope.d.ts +13 -0
- package/dist/features/connector-environment/environment.scope.d.ts.map +1 -0
- package/dist/features/connector-environment/environment.scope.js +16 -0
- package/dist/features/connector-environment/environment.scope.js.map +1 -0
- package/dist/features/connector-environment/environment.types.d.ts +11 -0
- package/dist/features/connector-environment/environment.types.d.ts.map +1 -0
- package/dist/features/connector-environment/environment.types.js +5 -0
- package/dist/features/connector-environment/environment.types.js.map +1 -0
- package/dist/features/connector-environment/index.d.ts +4 -0
- package/dist/features/connector-environment/index.d.ts.map +1 -0
- package/dist/features/connector-environment/index.js +4 -0
- package/dist/features/connector-environment/index.js.map +1 -0
- package/dist/features/incident-priority/index.d.ts +3 -0
- package/dist/features/incident-priority/index.d.ts.map +1 -0
- package/dist/features/incident-priority/index.js +3 -0
- package/dist/features/incident-priority/index.js.map +1 -0
- package/dist/features/incident-priority/priority.rules.d.ts +15 -0
- package/dist/features/incident-priority/priority.rules.d.ts.map +1 -0
- package/dist/features/incident-priority/priority.rules.js +38 -0
- package/dist/features/incident-priority/priority.rules.js.map +1 -0
- package/dist/features/incident-priority/priority.types.d.ts +13 -0
- package/dist/features/incident-priority/priority.types.d.ts.map +1 -0
- package/dist/features/incident-priority/priority.types.js +7 -0
- package/dist/features/incident-priority/priority.types.js.map +1 -0
- package/dist/features/sla/domain/sla.defaults.d.ts +8 -0
- package/dist/features/sla/domain/sla.defaults.d.ts.map +1 -0
- package/dist/features/sla/domain/sla.defaults.js +15 -0
- package/dist/features/sla/domain/sla.defaults.js.map +1 -0
- package/dist/features/sla/domain/sla.evaluator.d.ts +1 -1
- package/dist/features/sla/domain/sla.evaluator.d.ts.map +1 -1
- package/dist/features/sla/domain/sla.evaluator.js +4 -2
- package/dist/features/sla/domain/sla.evaluator.js.map +1 -1
- package/dist/features/sla/domain/sla.resolver.d.ts +11 -11
- package/dist/features/sla/domain/sla.resolver.d.ts.map +1 -1
- package/dist/features/sla/domain/sla.resolver.js +41 -15
- package/dist/features/sla/domain/sla.resolver.js.map +1 -1
- package/dist/features/sla/domain/sla.types.d.ts +28 -3
- package/dist/features/sla/domain/sla.types.d.ts.map +1 -1
- package/dist/features/sla/domain/sla.types.js.map +1 -1
- package/dist/features/sla/index.d.ts +2 -1
- package/dist/features/sla/index.d.ts.map +1 -1
- package/dist/features/sla/index.js +1 -0
- package/dist/features/sla/index.js.map +1 -1
- package/dist/features/sla/sla-policy.model.d.ts +23 -10
- package/dist/features/sla/sla-policy.model.d.ts.map +1 -1
- package/dist/features/sla/sla-policy.model.js +50 -28
- package/dist/features/sla/sla-policy.model.js.map +1 -1
- package/dist/features/sla/sla-policy.service.d.ts +7 -13
- package/dist/features/sla/sla-policy.service.d.ts.map +1 -1
- package/dist/features/sla/sla-policy.service.js +25 -20
- package/dist/features/sla/sla-policy.service.js.map +1 -1
- package/dist/features/sla/sla.schema.d.ts +19 -2
- package/dist/features/sla/sla.schema.d.ts.map +1 -1
- package/dist/features/sla/sla.schema.js +7 -6
- package/dist/features/sla/sla.schema.js.map +1 -1
- package/dist/migrations/run.d.ts.map +1 -1
- package/dist/migrations/run.js +91 -5
- package/dist/migrations/run.js.map +1 -1
- package/dist/models/alert.model.d.ts +2 -0
- package/dist/models/alert.model.d.ts.map +1 -1
- package/dist/models/alert.model.js +4 -0
- package/dist/models/alert.model.js.map +1 -1
- package/dist/models/incident.model.d.ts +5 -0
- package/dist/models/incident.model.d.ts.map +1 -1
- package/dist/models/incident.model.js +10 -0
- package/dist/models/incident.model.js.map +1 -1
- package/dist/service.d.ts +2 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +1 -1
- package/dist/service.js.map +1 -1
- package/dist/services/alert.service.d.ts +2 -0
- package/dist/services/alert.service.d.ts.map +1 -1
- package/dist/services/alert.service.js +3 -0
- package/dist/services/alert.service.js.map +1 -1
- package/dist/services/connector.service.d.ts +3 -0
- package/dist/services/connector.service.d.ts.map +1 -1
- package/dist/services/incident.service.d.ts +10 -0
- package/dist/services/incident.service.d.ts.map +1 -1
- package/dist/services/incident.service.js +20 -5
- package/dist/services/incident.service.js.map +1 -1
- package/dist/services/workflow.service.d.ts.map +1 -1
- package/dist/services/workflow.service.js +2 -0
- package/dist/services/workflow.service.js.map +1 -1
- 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
|
|
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;
|
|
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":"
|
|
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
|
|
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,
|
|
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 +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,
|
|
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
|
-
/**
|
|
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
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
|
|
14
|
-
resolveMinutes: number;
|
|
24
|
+
targets: SlaTargets;
|
|
15
25
|
updatedBy: string | null;
|
|
16
|
-
}): Promise<
|
|
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":"
|
|
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
|
-
|
|
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
|
-
|
|
6
|
-
|
|
9
|
+
policies;
|
|
10
|
+
targets;
|
|
11
|
+
constructor(db, policies, targets) {
|
|
7
12
|
this.db = db;
|
|
8
|
-
this.
|
|
13
|
+
this.policies = policies;
|
|
14
|
+
this.targets = targets;
|
|
9
15
|
}
|
|
10
16
|
async listByTenant(tenantId) {
|
|
11
|
-
|
|
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 [
|
|
22
|
+
const [policy] = await this.db
|
|
15
23
|
.select()
|
|
16
|
-
.from(this.
|
|
17
|
-
.where(and(eq(this.
|
|
24
|
+
.from(this.policies)
|
|
25
|
+
.where(and(eq(this.policies.tenantId, tenantId), eq(this.policies.accountId, accountId)))
|
|
18
26
|
.limit(1);
|
|
19
|
-
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
41
|
-
|
|
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;
|
|
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 {
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
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,
|
|
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 {
|
|
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
|
|
32
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
45
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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":"AAEA,OAAO,EAAE,oBAAoB,
|
|
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
|
-
|
|
5
|
-
|
|
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;
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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"}
|
package/dist/migrations/run.js
CHANGED
|
@@ -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
|