@pipeline-builder/pipeline-data 3.4.86 → 3.4.87

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,120 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ import { sql } from 'drizzle-orm';
4
+ import { boolean, varchar, pgTable, text, timestamp, uuid, index, uniqueIndex } from 'drizzle-orm/pg-core';
5
+ /**
6
+ * Per-org alert notification destination. Multi-tenant alerting routes
7
+ * Alertmanager webhooks to the platform; the platform looks the firing
8
+ * alert's `org_id` label up here and forwards to each enabled destination.
9
+ *
10
+ * Channels * - `slack` `target` is the incoming-webhook URL
11
+ * - `webhook` `target` is any HTTPS URL; the relay posts the
12
+ * Alertmanager v2 webhook payload verbatim
13
+ * - `in-app` `target` ignored; surfaces as an in-app message via
14
+ * the existing `messages` table
15
+ *
16
+ * Secrets * - For `slack`/`webhook` channels, the URL itself is the secret. We don't
17
+ * log it on `dashboard.update` or surface the full URL on GET endpoints
18
+ * after write; just a masked preview (last 12 chars). Stored in clear
19
+ * text same posture as `compliance_notification_preferences.webhook_url`
20
+ * and consistent with the rest of the app's secret handling for org-level
21
+ * integrations. If we add a KMS-encryption tier for any secret column,
22
+ * this is one of the first to migrate.
23
+ *
24
+ * @table org_alert_destinations
25
+ */
26
+ export const orgAlertDestination = pgTable('org_alert_destinations', {
27
+ id: uuid('id').primaryKey().defaultRandom(),
28
+ orgId: varchar('org_id', { length: 255 }).notNull(),
29
+ createdBy: text('created_by').notNull(),
30
+ createdAt: timestamp('created_at', { withTimezone: true })
31
+ .defaultNow()
32
+ .notNull(),
33
+ updatedBy: text('updated_by').notNull(),
34
+ updatedAt: timestamp('updated_at', { withTimezone: true })
35
+ .defaultNow()
36
+ .notNull(),
37
+ /** 'slack' | 'webhook' | 'in-app' | 'email' kept stringly so future channels
38
+ * (PagerDuty, …) can be added without a schema migration. */
39
+ channel: varchar('channel', { length: 20 })
40
+ .$type()
41
+ .notNull(),
42
+ /** Channel-specific target. Slack/webhook: URL. Email: address. In-app: ignored. */
43
+ target: text('target').default('').notNull(),
44
+ /** Friendly label shown in the settings UI. */
45
+ label: varchar('label', { length: 100 }).notNull(),
46
+ /** Lowest severity that triggers this destination ('warning' = warning+critical,
47
+ * 'critical' = critical only). Mirrors Alertmanager severity ordering. */
48
+ minSeverity: varchar('min_severity', { length: 10 })
49
+ .$type()
50
+ .default('warning')
51
+ .notNull(),
52
+ enabled: boolean('enabled').default(true).notNull(),
53
+ /** Soft delete so we keep audit history of who-deleted-what. */
54
+ deletedAt: timestamp('deleted_at', { withTimezone: true }),
55
+ deletedBy: text('deleted_by'),
56
+ }, (table) => ({
57
+ // Per-org listing the only access path.
58
+ orgIdx: index('org_alert_destination_org_idx')
59
+ .on(table.orgId, table.enabled),
60
+ }));
61
+ /**
62
+ * Per-org alert rules authored by operators.
63
+ *
64
+ * Each row materializes into a `groups[].rules[]` entry in a Prometheus
65
+ * `rule_files` YAML. The materializer endpoint
66
+ * `GET /api/observability/alert-rules/materialized.yml` renders all enabled
67
+ * rules across all orgs (deleted=null) into one document; Prometheus polls
68
+ * or a sidecar copies it into the rules dir.
69
+ *
70
+ * Tenancy + safety * - `expr` is user-authored PromQL. The CRUD route enforces that the
71
+ * expression substring-contains `org_id="<orgId>"` so an operator can't
72
+ * write rules that fire on other orgs' metrics. This is a coarse gate
73
+ * (a malformed expression can still be syntactically wrong) but it
74
+ * closes the cross-tenant data leak. Real PromQL parsing + automatic
75
+ * org_id injection is a follow-on.
76
+ * - The materialized rule carries `labels.org_id = <orgId>` so the
77
+ * alertmanager-relay routes firing alerts to the right org's
78
+ * destinations (matches the alert-relay model).
79
+ *
80
+ * @table org_alert_rules
81
+ */
82
+ export const orgAlertRule = pgTable('org_alert_rules', {
83
+ id: uuid('id').primaryKey().defaultRandom(),
84
+ orgId: varchar('org_id', { length: 255 }).notNull(),
85
+ createdBy: text('created_by').notNull(),
86
+ createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
87
+ updatedBy: text('updated_by').notNull(),
88
+ updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
89
+ /** Operator-supplied rule name. Sanitized into a valid Prom alert name at
90
+ * materialization time (becomes `OrgRule_<orgId>_<slug>` to avoid name
91
+ * collisions across orgs). */
92
+ name: varchar('name', { length: 100 }).notNull(),
93
+ /** PromQL expression. MUST substring-contain `org_id="<orgId>"`. */
94
+ expr: text('expr').notNull(),
95
+ /** `for: 5m` style duration. Validated against Prom's duration regex. */
96
+ forDuration: varchar('for_duration', { length: 20 }).default('5m').notNull(),
97
+ /** 'warning' | 'critical' matches the platform-wide severity ladder. */
98
+ severity: varchar('severity', { length: 20 })
99
+ .$type()
100
+ .default('warning')
101
+ .notNull(),
102
+ /** Alertmanager `summary` annotation. Supports `{{ $value }}`. */
103
+ summary: text('summary').notNull(),
104
+ /** Alertmanager `description` annotation. Optional; '' is fine. */
105
+ description: text('description').default('').notNull(),
106
+ /** Disabled rules don't materialize. Lets operators stage rules without firing. */
107
+ enabled: boolean('enabled').default(true).notNull(),
108
+ /** Soft delete so we keep audit of who-deleted-what. */
109
+ deletedAt: timestamp('deleted_at', { withTimezone: true }),
110
+ deletedBy: text('deleted_by'),
111
+ }, (table) => ({
112
+ // Per-org listing + materializer's enabled-only scan.
113
+ orgEnabledIdx: index('org_alert_rule_org_enabled_idx')
114
+ .on(table.orgId, table.enabled),
115
+ // Unique within an org so operators can't accidentally clone a rule.
116
+ orgNameUq: uniqueIndex('org_alert_rule_org_name_uq')
117
+ .on(table.orgId, table.name)
118
+ .where(sql `deleted_at IS NULL`),
119
+ }));
120
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWxlcnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvZGF0YWJhc2Uvc2NoZW1hL2FsZXJ0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLEdBQUcsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNsQyxPQUFPLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRTNHOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQW9CRztBQUNILE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLE9BQU8sQ0FBQyx3QkFBd0IsRUFBRTtJQUNuRSxFQUFFLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDLGFBQWEsRUFBRTtJQUMzQyxLQUFLLEVBQUUsT0FBTyxDQUFDLFFBQVEsRUFBRSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFDLE9BQU8sRUFBRTtJQUVuRCxTQUFTLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLE9BQU8sRUFBRTtJQUN2QyxTQUFTLEVBQUUsU0FBUyxDQUFDLFlBQVksRUFBRSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsQ0FBQztTQUN2RCxVQUFVLEVBQUU7U0FDWixPQUFPLEVBQUU7SUFDWixTQUFTLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxDQUFDLE9BQU8sRUFBRTtJQUN2QyxTQUFTLEVBQUUsU0FBUyxDQUFDLFlBQVksRUFBRSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsQ0FBQztTQUN2RCxVQUFVLEVBQUU7U0FDWixPQUFPLEVBQUU7SUFFWjtpRUFDNkQ7SUFDN0QsT0FBTyxFQUFFLE9BQU8sQ0FBQyxTQUFTLEVBQUUsRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFF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QU8sRUFBRTtJQUV0RCxtRkFBbUY7SUFDbkYsT0FBTyxFQUFFLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxFQUFFO0lBRW5ELHdEQUF3RDtJQUN4RCxTQUFTLEVBQUUsU0FBUyxDQUFDLFlBQVksRUFBRSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUMxRCxTQUFTLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQztDQUM5QixFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2Isc0RBQXNEO0lBQ3RELGFBQWEsRUFBRSxLQUFLLENBQUMsZ0NBQWdDLENBQUM7U0FDbkQsRUFBRSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLE9BQU8sQ0FBQztJQUNqQyxxRUFBcUU7SUFDckUsU0FBUyxFQUFFLFdBQVcsQ0FBQyw0QkFBNEIsQ0FBQztTQUNqRCxFQUFFLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDO1NBQzNCLEtBQUssQ0FBQyxHQUFHLENBQUEsb0JBQW9CLENBQUM7Q0FDbEMsQ0FBQyxDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgc3FsIH0gZnJvbSAnZHJpenpsZS1vcm0nO1xuaW1wb3J0IHsgYm9vbGVhbiwgdmFyY2hhciwgcGdUYWJsZSwgdGV4dCwgdGltZXN0YW1wLCB1dWlkLCBpbmRleCwgdW5pcXVlSW5kZXggfSBmcm9tICdkcml6emxlLW9ybS9wZy1jb3JlJztcblxuLyoqXG4gKiBQZXItb3JnIGFsZXJ0IG5vdGlmaWNhdGlvbiBkZXN0aW5hdGlvbi4gTXVsdGktdGVuYW50IGFsZXJ0aW5nIHJvdXRlc1xuICogQWxlcnRtYW5hZ2VyIHdlYmhvb2tzIHRvIHRoZSBwbGF0Zm9ybTsgdGhlIHBsYXRmb3JtIGxvb2tzIHRoZSBmaXJpbmdcbiAqIGFsZXJ0J3MgYG9yZ19pZGAgbGFiZWwgdXAgaGVyZSBhbmQgZm9yd2FyZHMgdG8gZWFjaCBlbmFibGVkIGRlc3RpbmF0aW9uLlxuICpcbiAqIENoYW5uZWxzICogLSBgc2xhY2tgICBgdGFyZ2V0YCBpcyB0aGUgaW5jb21pbmctd2ViaG9vayBVUkxcbiAqIC0gYHdlYmhvb2tgICBgdGFyZ2V0YCBpcyBhbnkgSFRUUFMgVVJMOyB0aGUgcmVsYXkgcG9zdHMgdGhlXG4gKiBBbGVydG1hbmFnZXIgdjIgd2ViaG9vayBwYXlsb2FkIHZlcmJhdGltXG4gKiAtIGBpbi1hcHBgICBgdGFyZ2V0YCBpZ25vcmVkOyBzdXJmYWNlcyBhcyBhbiBpbi1hcHAgbWVzc2FnZSB2aWFcbiAqIHRoZSBleGlzdGluZyBgbWVzc2FnZXNgIHRhYmxlXG4gKlxuICogU2VjcmV0cyAqIC0gRm9yIGBzbGFja2AvYHdlYmhvb2tgIGNoYW5uZWxzLCB0aGUgVVJMIGl0c2VsZiBpcyB0aGUgc2VjcmV0LiBXZSBkb24ndFxuICogbG9nIGl0IG9uIGBkYXNoYm9hcmQudXBkYXRlYCBvciBzdXJmYWNlIHRoZSBmdWxsIFVSTCBvbiBHRVQgZW5kcG9pbnRzXG4gKiBhZnRlciB3cml0ZTsganVzdCBhIG1hc2tlZCBwcmV2aWV3IChsYXN0IDEyIGNoYXJzKS4gU3RvcmVkIGluIGNsZWFyXG4gKiB0ZXh0ICBzYW1lIHBvc3R1cmUgYXMgYGNvbXBsaWFuY2Vfbm90aWZpY2F0aW9uX3ByZWZlcmVuY2VzLndlYmhvb2tfdXJsYFxuICogYW5kIGNvbnNpc3RlbnQgd2l0aCB0aGUgcmVzdCBvZiB0aGUgYXBwJ3Mgc2VjcmV0IGhhbmRsaW5nIGZvciBvcmctbGV2ZWxcbiAqIGludGVncmF0aW9ucy4gSWYgd2UgYWRkIGEgS01TLWVuY3J5cHRpb24gdGllciBmb3IgYW55IHNlY3JldCBjb2x1bW4sXG4gKiB0aGlzIGlzIG9uZSBvZiB0aGUgZmlyc3QgdG8gbWlncmF0ZS5cbiAqXG4gKiBAdGFibGUgb3JnX2FsZXJ0X2Rlc3RpbmF0aW9uc1xuICovXG5leHBvcnQgY29uc3Qgb3JnQWxlcnREZXN0aW5hdGlvbiA9IHBnVGFibGUoJ29yZ19hbGVydF9kZXN0aW5hdGlvbnMnLCB7XG4gIGlkOiB1dWlkKCdpZCcpLnByaW1hcnlLZXkoKS5kZWZhdWx0UmFuZG9tKCksXG4gIG9yZ0lkOiB2YXJjaGFyKCdvcmdfaWQnLCB7IGxlbmd0aDogMjU1IH0pLm5vdE51bGwoKSxcblxuICBjcmVhdGVkQnk6IHRleHQoJ2NyZWF0ZWRfYnknKS5ub3ROdWxsKCksXG4gIGNyZWF0ZWRBdDogdGltZXN0YW1wKCdjcmVhdGVkX2F0JywgeyB3aXRoVGltZXpvbmU6IHRydWUgfSlcbiAgICAuZGVmYXVsdE5vdygpXG4gICAgLm5vdE51bGwoKSxcbiAgdXBkYXRlZEJ5OiB0ZXh0KCd1cGRhdGVkX2J5Jykubm90TnVsbCgpLFxuICB1cGRhdGVkQXQ6IHRpbWVzdGFtcCgndXBkYXRlZF9hdCcsIHsgd2l0aFRpbWV6b25lOiB0cnVlIH0pXG4gICAgLmRlZmF1bHROb3coKVxuICAgIC5ub3ROdWxsKCksXG5cbiAgLyoqICdzbGFjaycgfCAnd2ViaG9vaycgfCAnaW4tYXBwJyB8ICdlbWFpbCcgIGtlcHQgc3RyaW5nbHkgc28gZnV0dXJlIGNoYW5uZWxzXG4gICAqIChQYWdlckR1dHksIOKApikgY2FuIGJlIGFkZGVkIHdpdGhvdXQgYSBzY2hlbWEgbWlncmF0aW9uLiAqL1xuICBjaGFubmVsOiB2YXJjaGFyKCdjaGFubmVsJywgeyBsZW5ndGg6IDIwIH0pXG4gICAgLiR0eXBlPCdzbGFjaycgfCAnd2ViaG9vaycgfCAnaW4tYXBwJyB8ICdlbWFpbCc+KClcbiAgICAubm90TnVsbCgpLFxuICAvKiogQ2hhbm5lbC1zcGVjaWZpYyB0YXJnZXQuIFNsYWNrL3dlYmhvb2s6IFVSTC4gRW1haWw6IGFkZHJlc3MuIEluLWFwcDogaWdub3JlZC4gKi9cbiAgdGFyZ2V0OiB0ZXh0KCd0YXJnZXQnKS5kZWZhdWx0KCcnKS5ub3ROdWxsKCksXG4gIC8qKiBGcmllbmRseSBsYWJlbCBzaG93biBpbiB0aGUgc2V0dGluZ3MgVUkuICovXG4gIGxhYmVsOiB2YXJjaGFyKCdsYWJlbCcsIHsgbGVuZ3RoOiAxMDAgfSkubm90TnVsbCgpLFxuXG4gIC8qKiBMb3dlc3Qgc2V2ZXJpdHkgdGhhdCB0cmlnZ2VycyB0aGlzIGRlc3RpbmF0aW9uICgnd2FybmluZycgPSB3YXJuaW5nK2NyaXRpY2FsLFxuICAgKiAnY3JpdGljYWwnID0gY3JpdGljYWwgb25seSkuIE1pcnJvcnMgQWxlcnRtYW5hZ2VyIHNldmVyaXR5IG9yZGVyaW5nLiAqL1xuICBtaW5TZXZlcml0eTogdmFyY2hhcignbWluX3NldmVyaXR5JywgeyBsZW5ndGg6IDEwIH0pXG4gICAgLiR0eXBlPCd3YXJuaW5nJyB8ICdjcml0aWNhbCc+KClcbiAgICAuZGVmYXVsdCgnd2FybmluZycpXG4gICAgLm5vdE51bGwoKSxcbiAgZW5hYmxlZDogYm9vbGVhbignZW5hYmxlZCcpLmRlZmF1bHQodHJ1ZSkubm90TnVsbCgpLFxuXG4gIC8qKiBTb2Z0IGRlbGV0ZSBzbyB3ZSBrZWVwIGF1ZGl0IGhpc3Rvcnkgb2Ygd2hvLWRlbGV0ZWQtd2hhdC4gKi9cbiAgZGVsZXRlZEF0OiB0aW1lc3RhbXAoJ2RlbGV0ZWRfYXQnLCB7IHdpdGhUaW1lem9uZTogdHJ1ZSB9KSxcbiAgZGVsZXRlZEJ5OiB0ZXh0KCdkZWxldGVkX2J5JyksXG59LCAodGFibGUpID0+ICh7XG4gIC8vIFBlci1vcmcgbGlzdGluZyAgdGhlIG9ubHkgYWNjZXNzIHBhdGguXG4gIG9yZ0lkeDogaW5kZXgoJ29yZ19hbGVydF9kZXN0aW5hdGlvbl9vcmdfaWR4JylcbiAgICAub24odGFibGUub3JnSWQsIHRhYmxlLmVuYWJsZWQpLFxufSkpO1xuXG4vKipcbiAqICBQZXItb3JnIGFsZXJ0IHJ1bGVzIGF1dGhvcmVkIGJ5IG9wZXJhdG9ycy5cbiAqXG4gKiBFYWNoIHJvdyBtYXRlcmlhbGl6ZXMgaW50byBhIGBncm91cHNbXS5ydWxlc1tdYCBlbnRyeSBpbiBhIFByb21ldGhldXNcbiAqIGBydWxlX2ZpbGVzYCBZQU1MLiBUaGUgbWF0ZXJpYWxpemVyIGVuZHBvaW50XG4gKiBgR0VUIC9hcGkvb2JzZXJ2YWJpbGl0eS9hbGVydC1ydWxlcy9tYXRlcmlhbGl6ZWQueW1sYCByZW5kZXJzIGFsbCBlbmFibGVkXG4gKiBydWxlcyBhY3Jvc3MgYWxsIG9yZ3MgKGRlbGV0ZWQ9bnVsbCkgaW50byBvbmUgZG9jdW1lbnQ7IFByb21ldGhldXMgcG9sbHNcbiAqIG9yIGEgc2lkZWNhciBjb3BpZXMgaXQgaW50byB0aGUgcnVsZXMgZGlyLlxuICpcbiAqIFRlbmFuY3kgKyBzYWZldHkgKiAtIGBleHByYCBpcyB1c2VyLWF1dGhvcmVkIFByb21RTC4gVGhlIENSVUQgcm91dGUgZW5mb3JjZXMgdGhhdCB0aGVcbiAqIGV4cHJlc3Npb24gc3Vic3RyaW5nLWNvbnRhaW5zIGBvcmdfaWQ9XCI8b3JnSWQ+XCJgIHNvIGFuIG9wZXJhdG9yIGNhbid0XG4gKiB3cml0ZSBydWxlcyB0aGF0IGZpcmUgb24gb3RoZXIgb3JncycgbWV0cmljcy4gVGhpcyBpcyBhIGNvYXJzZSBnYXRlXG4gKiAoYSBtYWxmb3JtZWQgZXhwcmVzc2lvbiBjYW4gc3RpbGwgYmUgc3ludGFjdGljYWxseSB3cm9uZykgYnV0IGl0XG4gKiBjbG9zZXMgdGhlIGNyb3NzLXRlbmFudCBkYXRhIGxlYWsuIFJlYWwgUHJvbVFMIHBhcnNpbmcgKyBhdXRvbWF0aWNcbiAqIG9yZ19pZCBpbmplY3Rpb24gaXMgYSBmb2xsb3ctb24uXG4gKiAtIFRoZSBtYXRlcmlhbGl6ZWQgcnVsZSBjYXJyaWVzIGBsYWJlbHMub3JnX2lkID0gPG9yZ0lkPmAgc28gdGhlXG4gKiBhbGVydG1hbmFnZXItcmVsYXkgcm91dGVzIGZpcmluZyBhbGVydHMgdG8gdGhlIHJpZ2h0IG9yZydzXG4gKiBkZXN0aW5hdGlvbnMgKG1hdGNoZXMgdGhlIGFsZXJ0LXJlbGF5IG1vZGVsKS5cbiAqXG4gKiBAdGFibGUgb3JnX2FsZXJ0X3J1bGVzXG4gKi9cbmV4cG9ydCBjb25zdCBvcmdBbGVydFJ1bGUgPSBwZ1RhYmxlKCdvcmdfYWxlcnRfcnVsZXMnLCB7XG4gIGlkOiB1dWlkKCdpZCcpLnByaW1hcnlLZXkoKS5kZWZhdWx0UmFuZG9tKCksXG4gIG9yZ0lkOiB2YXJjaGFyKCdvcmdfaWQnLCB7IGxlbmd0aDogMjU1IH0pLm5vdE51bGwoKSxcblxuICBjcmVhdGVkQnk6IHRleHQoJ2NyZWF0ZWRfYnknKS5ub3ROdWxsKCksXG4gIGNyZWF0ZWRBdDogdGltZXN0YW1wKCdjcmVhdGVkX2F0JywgeyB3aXRoVGltZXpvbmU6IHRydWUgfSkuZGVmYXVsdE5vdygpLm5vdE51bGwoKSxcbiAgdXBkYXRlZEJ5OiB0ZXh0KCd1cGRhdGVkX2J5Jykubm90TnVsbCgpLFxuICB1cGRhdGVkQXQ6IHRpbWVzdGFtcCgndXBkYXRlZF9hdCcsIHsgd2l0aFRpbWV6b25lOiB0cnVlIH0pLmRlZmF1bHROb3coKS5ub3ROdWxsKCksXG5cbiAgLyoqIE9wZXJhdG9yLXN1cHBsaWVkIHJ1bGUgbmFtZS4gU2FuaXRpemVkIGludG8gYSB2YWxpZCBQcm9tIGFsZXJ0IG5hbWUgYXRcbiAgICogbWF0ZXJpYWxpemF0aW9uIHRpbWUgKGJlY29tZXMgYE9yZ1J1bGVfPG9yZ0lkPl88c2x1Zz5gIHRvIGF2b2lkIG5hbWVcbiAgICogY29sbGlzaW9ucyBhY3Jvc3Mgb3JncykuICovXG4gIG5hbWU6IHZhcmNoYXIoJ25hbWUnLCB7IGxlbmd0aDogMTAwIH0pLm5vdE51bGwoKSxcbiAgLyoqIFByb21RTCBleHByZXNzaW9uLiBNVVNUIHN1YnN0cmluZy1jb250YWluIGBvcmdfaWQ9XCI8b3JnSWQ+XCJgLiAqL1xuICBleHByOiB0ZXh0KCdleHByJykubm90TnVsbCgpLFxuICAvKiogYGZvcjogNW1gIHN0eWxlIGR1cmF0aW9uLiBWYWxpZGF0ZWQgYWdhaW5zdCBQcm9tJ3MgZHVyYXRpb24gcmVnZXguICovXG4gIGZvckR1cmF0aW9uOiB2YXJjaGFyKCdmb3JfZHVyYXRpb24nLCB7IGxlbmd0aDogMjAgfSkuZGVmYXVsdCgnNW0nKS5ub3ROdWxsKCksXG4gIC8qKiAnd2FybmluZycgfCAnY3JpdGljYWwnICBtYXRjaGVzIHRoZSBwbGF0Zm9ybS13aWRlIHNldmVyaXR5IGxhZGRlci4gKi9cbiAgc2V2ZXJpdHk6IHZhcmNoYXIoJ3NldmVyaXR5JywgeyBsZW5ndGg6IDIwIH0pXG4gICAgLiR0eXBlPCd3YXJuaW5nJyB8ICdjcml0aWNhbCc+KClcbiAgICAuZGVmYXVsdCgnd2FybmluZycpXG4gICAgLm5vdE51bGwoKSxcbiAgLyoqIEFsZXJ0bWFuYWdlciBgc3VtbWFyeWAgYW5ub3RhdGlvbi4gU3VwcG9ydHMgYHt7ICR2YWx1ZSB9fWAuICovXG4gIHN1bW1hcnk6IHRleHQoJ3N1bW1hcnknKS5ub3ROdWxsKCksXG4gIC8qKiBBbGVydG1hbmFnZXIgYGRlc2NyaXB0aW9uYCBhbm5vdGF0aW9uLiBPcHRpb25hbDsgJycgaXMgZmluZS4gKi9cbiAgZGVzY3JpcHRpb246IHRleHQoJ2Rlc2NyaXB0aW9uJykuZGVmYXVsdCgnJykubm90TnVsbCgpLFxuXG4gIC8qKiBEaXNhYmxlZCBydWxlcyBkb24ndCBtYXRlcmlhbGl6ZS4gTGV0cyBvcGVyYXRvcnMgc3RhZ2UgcnVsZXMgd2l0aG91dCBmaXJpbmcuICovXG4gIGVuYWJsZWQ6IGJvb2xlYW4oJ2VuYWJsZWQnKS5kZWZhdWx0KHRydWUpLm5vdE51bGwoKSxcblxuICAvKiogU29mdCBkZWxldGUgc28gd2Uga2VlcCBhdWRpdCBvZiB3aG8tZGVsZXRlZC13aGF0LiAqL1xuICBkZWxldGVkQXQ6IHRpbWVzdGFtcCgnZGVsZXRlZF9hdCcsIHsgd2l0aFRpbWV6b25lOiB0cnVlIH0pLFxuICBkZWxldGVkQnk6IHRleHQoJ2RlbGV0ZWRfYnknKSxcbn0sICh0YWJsZSkgPT4gKHtcbiAgLy8gUGVyLW9yZyBsaXN0aW5nICsgbWF0ZXJpYWxpemVyJ3MgZW5hYmxlZC1vbmx5IHNjYW4uXG4gIG9yZ0VuYWJsZWRJZHg6IGluZGV4KCdvcmdfYWxlcnRfcnVsZV9vcmdfZW5hYmxlZF9pZHgnKVxuICAgIC5vbih0YWJsZS5vcmdJZCwgdGFibGUuZW5hYmxlZCksXG4gIC8vIFVuaXF1ZSB3aXRoaW4gYW4gb3JnIHNvIG9wZXJhdG9ycyBjYW4ndCBhY2NpZGVudGFsbHkgY2xvbmUgYSBydWxlLlxuICBvcmdOYW1lVXE6IHVuaXF1ZUluZGV4KCdvcmdfYWxlcnRfcnVsZV9vcmdfbmFtZV91cScpXG4gICAgLm9uKHRhYmxlLm9yZ0lkLCB0YWJsZS5uYW1lKVxuICAgIC53aGVyZShzcWxgZGVsZXRlZF9hdCBJUyBOVUxMYCksXG59KSk7XG5cbmV4cG9ydCB0eXBlIE9yZ0FsZXJ0RGVzdGluYXRpb24gPSB0eXBlb2Ygb3JnQWxlcnREZXN0aW5hdGlvbi4kaW5mZXJTZWxlY3Q7XG5leHBvcnQgdHlwZSBPcmdBbGVydERlc3RpbmF0aW9uSW5zZXJ0ID0gdHlwZW9mIG9yZ0FsZXJ0RGVzdGluYXRpb24uJGluZmVySW5zZXJ0O1xuZXhwb3J0IHR5cGUgT3JnQWxlcnREZXN0aW5hdGlvblVwZGF0ZSA9IFBhcnRpYWw8T21pdDxPcmdBbGVydERlc3RpbmF0aW9uSW5zZXJ0LCAnaWQnIHwgJ2NyZWF0ZWRBdCcgfCAnY3JlYXRlZEJ5JyB8ICdvcmdJZCc+PjtcbiJdfQ==