@pipeline-builder/api-core 5.2.3 → 5.2.4

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 (81) hide show
  1. package/lib/constants/ai-providers.d.ts +3 -22
  2. package/lib/constants/ai-providers.js +6 -56
  3. package/lib/errors/app-errors.d.ts +14 -0
  4. package/lib/errors/app-errors.js +21 -1
  5. package/lib/helpers/sse-helpers.d.ts +33 -3
  6. package/lib/helpers/sse-helpers.js +91 -19
  7. package/lib/middleware/auth.js +6 -3
  8. package/lib/middleware/deferred-quota-check.d.ts +5 -0
  9. package/lib/middleware/deferred-quota-check.js +33 -0
  10. package/lib/middleware/ecosystem-guard.d.ts +3 -3
  11. package/lib/middleware/ecosystem-guard.js +5 -5
  12. package/lib/middleware/index.d.ts +5 -2
  13. package/lib/middleware/index.js +6 -3
  14. package/lib/middleware/on-behalf.d.ts +37 -0
  15. package/lib/middleware/on-behalf.js +143 -0
  16. package/lib/middleware/permission-gates.d.ts +11 -0
  17. package/lib/middleware/permission-gates.js +7 -1
  18. package/lib/middleware/quota-exempt-routes.d.ts +36 -0
  19. package/lib/middleware/quota-exempt-routes.js +47 -0
  20. package/lib/middleware/route-table.d.ts +104 -0
  21. package/lib/middleware/route-table.js +72 -2
  22. package/lib/middleware/service-tokens.d.ts +8 -0
  23. package/lib/middleware/service-tokens.js +2 -1
  24. package/lib/middleware/step-up.js +11 -1
  25. package/lib/services/ai-call-weight.d.ts +24 -0
  26. package/lib/services/ai-call-weight.js +77 -0
  27. package/lib/services/audit-context.d.ts +105 -0
  28. package/lib/services/audit-context.js +134 -0
  29. package/lib/services/index.d.ts +7 -2
  30. package/lib/services/index.js +7 -2
  31. package/lib/services/org-ai-client.d.ts +61 -0
  32. package/lib/services/org-ai-client.js +112 -0
  33. package/lib/services/quota-increment-batcher.d.ts +81 -0
  34. package/lib/services/quota-increment-batcher.js +166 -0
  35. package/lib/services/quota.d.ts +158 -14
  36. package/lib/services/quota.js +252 -22
  37. package/lib/services/remote-audit-client.d.ts +44 -1
  38. package/lib/services/remote-audit-client.js +106 -20
  39. package/lib/services/version-vuln-policy.d.ts +174 -0
  40. package/lib/services/version-vuln-policy.js +242 -0
  41. package/lib/types/ai-catalog.d.ts +63 -0
  42. package/lib/types/ai-catalog.js +82 -0
  43. package/lib/types/ask-proposals.js +6 -6
  44. package/lib/types/build-catalog.d.ts +154 -0
  45. package/lib/types/build-catalog.js +158 -0
  46. package/lib/types/common.d.ts +37 -3
  47. package/lib/types/common.js +20 -2
  48. package/lib/types/ecosystem-notifications.d.ts +5 -5
  49. package/lib/types/ecosystem-notifications.js +9 -3
  50. package/lib/types/error-codes.d.ts +13 -6
  51. package/lib/types/error-codes.js +18 -8
  52. package/lib/types/feature-flags.d.ts +6 -4
  53. package/lib/types/feature-flags.js +11 -6
  54. package/lib/types/index.d.ts +6 -4
  55. package/lib/types/index.js +12 -5
  56. package/lib/types/metadata-keys.d.ts +6 -0
  57. package/lib/types/metadata-keys.js +4 -1
  58. package/lib/types/permissions.d.ts +344 -3
  59. package/lib/types/permissions.js +596 -21
  60. package/lib/types/pipeline.d.ts +39 -0
  61. package/lib/types/pipeline.js +57 -1
  62. package/lib/types/plugin-health.d.ts +0 -2
  63. package/lib/types/plugin-health.js +1 -11
  64. package/lib/types/plugin-scan.d.ts +192 -42
  65. package/lib/types/plugin-scan.js +159 -43
  66. package/lib/types/quota-catalog.d.ts +247 -0
  67. package/lib/types/quota-catalog.js +122 -0
  68. package/lib/types/quota-tiers.d.ts +118 -0
  69. package/lib/types/quota-tiers.js +153 -2
  70. package/lib/types/remote-audit-actions.d.ts +1 -1
  71. package/lib/types/remote-audit-actions.js +131 -1
  72. package/lib/types/wire-vocabulary.js +8 -1
  73. package/lib/utils/index.d.ts +1 -1
  74. package/lib/utils/index.js +2 -2
  75. package/lib/utils/response.d.ts +35 -2
  76. package/lib/utils/response.js +42 -3
  77. package/lib/validation/ai-schemas.d.ts +27 -0
  78. package/lib/validation/ai-schemas.js +31 -5
  79. package/lib/validation/plugin-schemas.d.ts +15 -0
  80. package/lib/validation/plugin-schemas.js +28 -1
  81. package/package.json +31 -2
@@ -0,0 +1,242 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * THE vulnerability assessment of one resolved plugin version, for one org (and,
5
+ * optionally, one pipeline's risk acceptance). One function, three callers:
6
+ * `/plugins/lookup` (what synth pins), `/plugins/runtime-check` (what a running
7
+ * pipeline is about to execute) and the pipeline service's save-time contract
8
+ * check. Three copies of these rules drifted once already.
9
+ *
10
+ * Vulnerability state NEVER refuses a pipeline — not its save, its synth, its
11
+ * deploy or its run. What it produces is SEVERITY-GRADED warnings (and, from the
12
+ * callers, notifications to the pipeline's owners). The grades:
13
+ *
14
+ * critical — a finding on the CISA Known Exploited Vulnerabilities list
15
+ * error — the version is FLAGGED (gated Criticals over the platform floor),
16
+ * it has fixable Critical findings, or an org compliance rule on the
17
+ * vulnerability attributes is in BLOCK mode and fails
18
+ * warning — fixable High findings over the org's `warnFixableHigh`, a version
19
+ * never scanned, a scan older than `PLUGIN_SCAN_STALE_HOURS`, or a
20
+ * compliance rule in WARN mode
21
+ * info — what a reader may want to know but need not act on
22
+ *
23
+ * A PIPELINE's active risk acceptance (`plugin_vuln_exposure`, triaged `accepted`
24
+ * with a reason and an expiry) downgrades the warnings about the findings it
25
+ * ACCEPTED to `info` ("accepted until …") — never one about a finding that
26
+ * appeared since, never a KEV one unless the acceptance said `kev: true`, and
27
+ * never the scan-freshness or compliance warnings (neither is about a finding).
28
+ */
29
+ import { createComplianceClient } from './compliance-client.js';
30
+ import { getServiceAuthHeader } from '../middleware/service-tokens.js';
31
+ import { isSystemOrgId } from '../middleware/system-org.js';
32
+ import { asScanFlag, describeFindings, failOnLabel, isGatedFinding, pluginVulnGateKev, scanFindingKey, } from '../types/plugin-scan.js';
33
+ import { envInt } from '../utils/env.js';
34
+ import { derivePluginImageCompliance, pluginRunsOwnImage } from '../utils/plugin-compliance.js';
35
+ import { errorMessage } from '../utils/response.js';
36
+ /** How loud a warning is, quietest first. */
37
+ export const VULN_SEVERITIES = ['info', 'warning', 'error', 'critical'];
38
+ /** The louder of two severities. */
39
+ export function maxSeverity(a, b) {
40
+ return VULN_SEVERITIES.indexOf(a) >= VULN_SEVERITIES.indexOf(b) ? a : b;
41
+ }
42
+ /** Whether `s` is at least `floor`. */
43
+ export function severityAtLeast(s, floor) {
44
+ return VULN_SEVERITIES.indexOf(s) >= VULN_SEVERITIES.indexOf(floor);
45
+ }
46
+ /** `PLUGIN_SCAN_STALE_HOURS` (default 72): a scan older than this is stale. */
47
+ export function scanStaleHours() {
48
+ return envInt('PLUGIN_SCAN_STALE_HOURS', 72, { min: 1 });
49
+ }
50
+ const toDate = (v) => {
51
+ if (!v)
52
+ return null;
53
+ const d = v instanceof Date ? v : new Date(String(v));
54
+ return Number.isNaN(d.getTime()) ? null : d;
55
+ };
56
+ const summaryOf = (record) => (record.scanSummary && typeof record.scanSummary === 'object' && !Array.isArray(record.scanSummary)
57
+ ? record.scanSummary : null);
58
+ /**
59
+ * When the version was last scanned: the later of the build-time `scannedAt` and
60
+ * the nightly rescan's `scan_summary.scannedAt`. Null = never.
61
+ */
62
+ export function lastScannedAt(record) {
63
+ const build = toDate(record.scannedAt);
64
+ const summary = toDate(summaryOf(record)?.scannedAt);
65
+ if (!build)
66
+ return summary;
67
+ if (!summary)
68
+ return build;
69
+ return summary > build ? summary : build;
70
+ }
71
+ /** Whether the record runs a BUILT image of its own — the only thing a scan applies to. */
72
+ function hasImage(record) {
73
+ return pluginRunsOwnImage(record) && typeof record.imageDigest === 'string' && record.imageDigest.length > 0;
74
+ }
75
+ /** Freshness of a version's scan: `none` (no image to scan), `unscanned`, `stale` or `fresh`. */
76
+ export function scanFreshness(record, now = new Date()) {
77
+ if (!hasImage(record))
78
+ return { state: 'none', scannedAt: null };
79
+ const at = lastScannedAt(record);
80
+ if (!at)
81
+ return { state: 'unscanned', scannedAt: null };
82
+ return { state: now.getTime() - at.getTime() > scanStaleHours() * 3_600_000 ? 'stale' : 'fresh', scannedAt: at };
83
+ }
84
+ /** `UNSCANNED` / `SCAN_STALE` for a resolved version (empty for a fresh scan or an image-less plugin). */
85
+ export function scanWarnings(record, now = new Date()) {
86
+ const ref = `${record.name}@${record.version}`;
87
+ const f = scanFreshness(record, now);
88
+ if (f.state === 'unscanned') {
89
+ return [{ code: 'UNSCANNED', severity: 'warning', message: `Plugin ${ref} has never been scanned for vulnerabilities; nothing is known about what its image contains.` }];
90
+ }
91
+ if (f.state === 'stale') {
92
+ const hours = scanStaleHours();
93
+ return [{
94
+ code: 'SCAN_STALE',
95
+ severity: 'warning',
96
+ message: `Plugin ${ref} was last scanned ${f.scannedAt.toISOString()}, more than ${hours}h ago; findings published since are not reflected.`,
97
+ scannedAt: f.scannedAt.toISOString(),
98
+ staleAfterHours: hours,
99
+ }];
100
+ }
101
+ return [];
102
+ }
103
+ /** The normalized scan facts of a resolved record. A summary describing another image is ignored. */
104
+ export function versionScanFacts(record) {
105
+ const flag = record.scanFlaggedAt ? asScanFlag(record.scanFlag) : null;
106
+ const raw = summaryOf(record);
107
+ const digest = typeof raw?.imageDigest === 'string' ? raw.imageDigest : null;
108
+ const summary = raw && (digest === null || !record.imageDigest || digest === record.imageDigest) ? raw : null;
109
+ const findings = summary && Array.isArray(summary.findings)
110
+ ? summary.findings.filter((f) => f && typeof f.id === 'string').map((f) => ({ ...f, fixedIn: Array.isArray(f.fixedIn) ? f.fixedIn : [] }))
111
+ : (flag?.findings ?? []);
112
+ const num = (v) => (typeof v === 'number' ? v : null);
113
+ const kevCount = Math.max(num(summary?.kev) ?? 0, flag?.kev ?? 0, findings.filter((f) => f.kev === true).length);
114
+ return {
115
+ flagged: flag !== null,
116
+ flag,
117
+ criticalFixable: num(summary?.criticalFixable),
118
+ highFixable: num(summary?.highFixable) ?? num(record.vulnHighFixable),
119
+ critical: num(summary?.critical),
120
+ high: num(summary?.high),
121
+ kev: kevCount,
122
+ findings,
123
+ truncated: summary?.truncated === true,
124
+ scannedAt: lastScannedAt(record),
125
+ };
126
+ }
127
+ /**
128
+ * Whether `acceptance` covers EVERY one of `findings` (by finding key), and its
129
+ * KEV ones only when it accepted KEV. An empty set is never "covered": with
130
+ * nothing itemized there is nothing an acceptance can be shown to describe.
131
+ */
132
+ function covers(acceptance, findings, truncated) {
133
+ if (!acceptance || truncated || findings.length === 0)
134
+ return false;
135
+ const keys = new Set(acceptance.findingKeys);
136
+ return findings.every((f) => keys.has(scanFindingKey(f)) && (f.kev !== true || acceptance.kev));
137
+ }
138
+ /** The loudest severity of `warnings`, or null for none. */
139
+ export function severityOf(warnings) {
140
+ return warnings.reduce((acc, w) => (w.severity ? (acc ? maxSeverity(acc, w.severity) : w.severity) : acc), null);
141
+ }
142
+ /**
143
+ * The assessment of one resolved version (see the module doc). Never throws and
144
+ * never refuses: a compliance outage adds an `info` `COMPLIANCE_UNAVAILABLE`.
145
+ */
146
+ export async function assessVersionVulns(input) {
147
+ const { orgId, record, policy, acceptance } = input;
148
+ const now = input.now ?? new Date();
149
+ const ref = `${record.name}@${record.version}`;
150
+ const facts = versionScanFacts(record);
151
+ const warnings = [...scanWarnings(record, now)];
152
+ const accepted = new Set();
153
+ const way = input.suggestedVersion ? ` Move to ${record.name}@${input.suggestedVersion}.` : '';
154
+ const suggested = input.suggestedVersion ? { suggestedVersion: input.suggestedVersion } : {};
155
+ const until = toDate(acceptance?.acceptedUntil)?.toISOString() ?? null;
156
+ /** Push a finding warning — or, when the pipeline accepted exactly those findings, its `info` downgrade. */
157
+ const finding = (code, severity, message, findings, extra = {}) => {
158
+ if (covers(acceptance, findings, facts.truncated)) {
159
+ for (const f of findings)
160
+ accepted.add(scanFindingKey(f));
161
+ warnings.push({
162
+ code: 'VULN_ACCEPTED',
163
+ severity: 'info',
164
+ message: `${message} Accepted for this pipeline${until ? ` until ${until}` : ''}.`,
165
+ findings: findings.map(scanFindingKey),
166
+ acceptedUntil: until,
167
+ kev: acceptance?.kev ?? false,
168
+ covers: code,
169
+ });
170
+ return;
171
+ }
172
+ warnings.push({ code, severity, message: `${message}${way}`, findings: findings.slice(0, 10), ...suggested, ...extra });
173
+ };
174
+ const kevFindings = facts.findings.filter((f) => f.kev === true);
175
+ if (facts.kev > 0) {
176
+ finding('VULN_KEV', 'critical', `${ref} has ${facts.kev} finding${facts.kev === 1 ? '' : 's'} on the CISA Known Exploited Vulnerabilities list${kevFindings.length ? `: ${describeFindings(kevFindings)}` : ''}.`, kevFindings);
177
+ }
178
+ const flag = facts.flag;
179
+ if (flag) {
180
+ const gated = facts.findings.filter((f) => isGatedFinding(f, pluginVulnGateKev(), flag.failOn ?? 'critical'));
181
+ finding('VULN_FLAGGED', 'error', `${ref} is flagged: a rescan found ${flag.gated} gated ${failOnLabel(flag.failOn ?? 'critical')} finding${flag.gated === 1 ? '' : 's'} over the platform limit${flag.findings.length ? ` (fix: ${describeFindings(flag.findings)})` : ''}.`, gated.length > 0 ? gated : flag.findings, { plugin: record.name, version: record.version, gated: flag.gated, high: flag.high });
182
+ }
183
+ else if ((facts.criticalFixable ?? 0) > 0) {
184
+ const crits = facts.findings.filter((f) => f.severity === 'critical' && f.fixedIn.length > 0);
185
+ finding('VULN_CRITICAL_FIXABLE', 'error', `${ref} has ${facts.criticalFixable} fixable Critical finding${facts.criticalFixable === 1 ? '' : 's'}${crits.length ? `: ${describeFindings(crits)}` : ''}.`, crits);
186
+ }
187
+ const highFixable = facts.highFixable ?? 0;
188
+ if (highFixable > 0) {
189
+ const highs = facts.findings.filter((f) => f.severity === 'high' && f.fixedIn.length > 0);
190
+ const over = policy.warnFixableHigh !== null && highFixable > policy.warnFixableHigh;
191
+ finding('VULN_HIGH_FIXABLE', over ? 'warning' : 'info', `${ref} has ${highFixable} fixable High finding${highFixable === 1 ? '' : 's'}${over ? `, over your organization's threshold of ${policy.warnFixableHigh}` : ''}.`, highs);
192
+ }
193
+ if (input.compliance !== false)
194
+ warnings.push(...await complianceVulnWarnings(orgId, record));
195
+ return { severity: severityOf(warnings), warnings, acceptedFindings: [...accepted], facts };
196
+ }
197
+ /** The compliance attributes a plugin's vulnerability rules read. */
198
+ const VULN_RULE_FIELDS = new Set(['scanned', 'vulnCritical', 'vulnHigh', 'vulnMedium', 'vulnLow', 'vulnCriticalFixable', 'vulnHighFixable']);
199
+ const fieldRoot = (field) => field.split(/[.[]/)[0] ?? field;
200
+ let complianceClient = null;
201
+ /** Test hook: replace the compliance client the assessment's compliance layer calls. */
202
+ export function setVulnPolicyComplianceClientForTests(client) {
203
+ complianceClient = client;
204
+ }
205
+ /**
206
+ * The org's plugin compliance rules on the vulnerability attributes, evaluated
207
+ * against the RESOLVED version — the org's own row, its parent's, a system
208
+ * plugin or an installed marketplace version alike. A BLOCK-mode rule that fails
209
+ * is an `error`, a WARN-mode one a `warning`; neither refuses anything here
210
+ * (vulnerability state never stops a pipeline).
211
+ *
212
+ * Only the vuln / scanned rules count here: the plugin's other rules (tags,
213
+ * secrets, commands …) describe how a plugin is AUTHORED, which is its owner's
214
+ * concern at upload, not the consumer's at resolution — and a system plugin would
215
+ * otherwise fail every tenant's authoring rules.
216
+ */
217
+ async function complianceVulnWarnings(orgId, record) {
218
+ if (isSystemOrgId(orgId) || !hasImage(record))
219
+ return [];
220
+ const facts = derivePluginImageCompliance(record, null).attributes;
221
+ const attributes = { name: record.name, version: record.version, ...facts };
222
+ try {
223
+ complianceClient ??= createComplianceClient();
224
+ const auth = getServiceAuthHeader({ serviceName: 'plugin', orgId, role: 'member' });
225
+ const result = await complianceClient.dryRunPlugin(orgId, attributes, auth);
226
+ const relevant = (v) => VULN_RULE_FIELDS.has(fieldRoot(v.field));
227
+ const as = (mode) => (v) => ({
228
+ code: 'COMPLIANCE_VULN_RULE',
229
+ severity: mode === 'block' ? 'error' : 'warning',
230
+ message: `${record.name}@${record.version}: ${v.message}`,
231
+ ruleId: v.ruleId,
232
+ ruleName: v.ruleName,
233
+ field: v.field,
234
+ mode,
235
+ });
236
+ return [...result.violations.filter(relevant).map(as('block')), ...result.warnings.filter(relevant).map(as('warn'))];
237
+ }
238
+ catch (err) {
239
+ return [{ code: 'COMPLIANCE_UNAVAILABLE', severity: 'info', message: `Your organization's plugin vulnerability rules could not be checked for ${record.name}@${record.version} (${errorMessage(err)}).` }];
240
+ }
241
+ }
242
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyc2lvbi12dWxuLXBvbGljeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy92ZXJzaW9uLXZ1bG4tcG9saWN5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F5Qkc7QUFFSCxPQUFPLEVBQUUsc0JBQXNCLEVBQTRCLE1BQU0sd0JBQXdCLENBQUM7QUFDMUYsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDdkUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzVELE9BQU8sRUFDTCxVQUFVLEVBQUUsZ0JBQWdCLEVBQUUsV0FBVyxFQUFFLGNBQWMsRUFBRSxpQkFBaUIsRUFBRSxjQUFjLEdBRTdGLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxrQkFBa0IsRUFBd0QsTUFBTSwrQkFBK0IsQ0FBQztBQUN0SixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFcEQsNkNBQTZDO0FBQzdDLE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxDQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLFVBQVUsQ0FBVSxDQUFDO0FBR2pGLG9DQUFvQztBQUNwQyxNQUFNLFVBQVUsV0FBVyxDQUFDLENBQWUsRUFBRSxDQUFlO0lBQzFELE9BQU8sZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMxRSxDQUFDO0FBRUQsdUNBQXVDO0FBQ3ZDLE1BQU0sVUFBVSxlQUFlLENBQUMsQ0FBZSxFQUFFLEtBQW1CO0lBQ2xFLE9BQU8sZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxlQUFlLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQ3RFLENBQUM7QUFFRCwrRUFBK0U7QUFDL0UsTUFBTSxVQUFVLGNBQWM7SUFDNUIsT0FBTyxNQUFNLENBQUMseUJBQXlCLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUM7QUFDM0QsQ0FBQztBQWFELE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBVSxFQUFlLEVBQUU7SUFDekMsSUFBSSxDQUFDLENBQUM7UUFBRSxPQUFPLElBQUksQ0FBQztJQUNwQixNQUFNLENBQUMsR0FBRyxDQUFDLFlBQVksSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3RELE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDOUMsQ0FBQyxDQUFDO0FBRUYsTUFBTSxTQUFTLEdBQUcsQ0FBQyxNQUEwQyxFQUFrQyxFQUFFLENBQy9GLENBQUMsTUFBTSxDQUFDLFdBQVcsSUFBSSxPQUFPLE1BQU0sQ0FBQyxXQUFXLEtBQUssUUFBUSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDO0lBQ2pHLENBQUMsQ0FBQyxNQUFNLENBQUMsV0FBc0MsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7QUFFNUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLGFBQWEsQ0FBQyxNQUF3RDtJQUNwRixNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQ3ZDLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDckQsSUFBSSxDQUFDLEtBQUs7UUFBRSxPQUFPLE9BQU8sQ0FBQztJQUMzQixJQUFJLENBQUMsT0FBTztRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQzNCLE9BQU8sT0FBTyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUM7QUFDM0MsQ0FBQztBQUVELDJGQUEyRjtBQUMzRixTQUFTLFFBQVEsQ0FBQyxNQUFxQjtJQUNyQyxPQUFPLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxJQUFJLE9BQU8sTUFBTSxDQUFDLFdBQVcsS0FBSyxRQUFRLElBQUksTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0FBQy9HLENBQUM7QUFFRCxpR0FBaUc7QUFDakcsTUFBTSxVQUFVLGFBQWEsQ0FBQyxNQUFxQixFQUFFLEdBQUcsR0FBRyxJQUFJLElBQUksRUFBRTtJQUNuRSxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQztRQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUNqRSxNQUFNLEVBQUUsR0FBRyxhQUFhLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDakMsSUFBSSxDQUFDLEVBQUU7UUFBRSxPQUFPLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLENBQUM7SUFDeEQsT0FBTyxFQUFFLEtBQUssRUFBRSxHQUFHLENBQUMsT0FBTyxFQUFFLEdBQUcsRUFBRSxDQUFDLE9BQU8sRUFBRSxHQUFHLGNBQWMsRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLEVBQUUsRUFBRSxDQUFDO0FBQ25ILENBQUM7QUF1QkQsMEdBQTBHO0FBQzFHLE1BQU0sVUFBVSxZQUFZLENBQUMsTUFBcUIsRUFBRSxHQUFHLEdBQUcsSUFBSSxJQUFJLEVBQUU7SUFDbEUsTUFBTSxHQUFHLEdBQUcsR0FBRyxNQUFNLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUMvQyxNQUFNLENBQUMsR0FBRyxhQUFhLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3JDLElBQUksQ0FBQyxDQUFDLEtBQUssS0FBSyxXQUFXLEVBQUUsQ0FBQztRQUM1QixPQUFPLENBQUMsRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLFVBQVUsR0FBRyw4RkFBOEYsRUFBRSxDQUFDLENBQUM7SUFDNUssQ0FBQztJQUNELElBQUksQ0FBQyxDQUFDLEtBQUssS0FBSyxPQUFPLEVBQUUsQ0FBQztRQUN4QixNQUFNLEtBQUssR0FBRyxjQUFjLEVBQUUsQ0FBQztRQUMvQixPQUFPLENBQUM7Z0JBQ04sSUFBSSxFQUFFLFlBQVk7Z0JBQ2xCLFFBQVEsRUFBRSxTQUFTO2dCQUNuQixPQUFPLEVBQUUsVUFBVSxHQUFHLHFCQUFxQixDQUFDLENBQUMsU0FBVSxDQUFDLFdBQVcsRUFBRSxlQUFlLEtBQUssb0RBQW9EO2dCQUM3SSxTQUFTLEVBQUUsQ0FBQyxDQUFDLFNBQVUsQ0FBQyxXQUFXLEVBQUU7Z0JBQ3JDLGVBQWUsRUFBRSxLQUFLO2FBQ3ZCLENBQUMsQ0FBQztJQUNMLENBQUM7SUFDRCxPQUFPLEVBQUUsQ0FBQztBQUNaLENBQUM7QUFzQ0QscUdBQXFHO0FBQ3JHLE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxNQUFxQjtJQUNwRCxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDdkUsTUFBTSxHQUFHLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzlCLE1BQU0sTUFBTSxHQUFHLE9BQU8sR0FBRyxFQUFFLFdBQVcsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUM3RSxNQUFNLE9BQU8sR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLEtBQUssSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsSUFBSSxNQUFNLEtBQUssTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUM5RyxNQUFNLFFBQVEsR0FBRyxPQUFPLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDO1FBQ3pELENBQUMsQ0FBRSxPQUFPLENBQUMsUUFBZ0MsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxPQUFPLENBQUMsQ0FBQyxFQUFFLEtBQUssUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLEVBQUUsT0FBTyxFQUFFLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBQ25LLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxRQUFRLElBQUksRUFBRSxDQUFDLENBQUM7SUFDM0IsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFVLEVBQWlCLEVBQUUsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxLQUFLLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM5RSxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQyxFQUFFLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDakgsT0FBTztRQUNMLE9BQU8sRUFBRSxJQUFJLEtBQUssSUFBSTtRQUN0QixJQUFJO1FBQ0osZUFBZSxFQUFFLEdBQUcsQ0FBQyxPQUFPLEVBQUUsZUFBZSxDQUFDO1FBQzlDLFdBQVcsRUFBRSxHQUFHLENBQUMsT0FBTyxFQUFFLFdBQVcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDO1FBQ3JFLFFBQVEsRUFBRSxHQUFHLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQztRQUNoQyxJQUFJLEVBQUUsR0FBRyxDQUFDLE9BQU8sRUFBRSxJQUFJLENBQUM7UUFDeEIsR0FBRyxFQUFFLFFBQVE7UUFDYixRQUFRO1FBQ1IsU0FBUyxFQUFFLE9BQU8sRUFBRSxTQUFTLEtBQUssSUFBSTtRQUN0QyxTQUFTLEVBQUUsYUFBYSxDQUFDLE1BQU0sQ0FBQztLQUNqQyxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxTQUFTLE1BQU0sQ0FBQyxVQUE2QyxFQUFFLFFBQXNDLEVBQUUsU0FBa0I7SUFDdkgsSUFBSSxDQUFDLFVBQVUsSUFBSSxTQUFTLElBQUksUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDcEUsTUFBTSxJQUFJLEdBQUcsSUFBSSxHQUFHLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0lBQzdDLE9BQU8sUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssSUFBSSxJQUFJLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBQ2xHLENBQUM7QUEwQkQsNERBQTREO0FBQzVELE1BQU0sVUFBVSxVQUFVLENBQUMsUUFBb0Q7SUFDN0UsT0FBTyxRQUFRLENBQUMsTUFBTSxDQUFzQixDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0FBQ3hJLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGtCQUFrQixDQUFDLEtBQXVCO0lBQzlELE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsR0FBRyxLQUFLLENBQUM7SUFDcEQsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLEdBQUcsSUFBSSxJQUFJLElBQUksRUFBRSxDQUFDO0lBQ3BDLE1BQU0sR0FBRyxHQUFHLEdBQUcsTUFBTSxDQUFDLElBQUksSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDL0MsTUFBTSxLQUFLLEdBQUcsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDdkMsTUFBTSxRQUFRLEdBQWtCLENBQUMsR0FBRyxZQUFZLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDL0QsTUFBTSxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztJQUNuQyxNQUFNLEdBQUcsR0FBRyxLQUFLLENBQUMsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLFlBQVksTUFBTSxDQUFDLElBQUksSUFBSSxLQUFLLENBQUMsZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQy9GLE1BQU0sU0FBUyxHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsRUFBRSxnQkFBZ0IsRUFBRSxLQUFLLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO0lBQzdGLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxVQUFVLEVBQUUsYUFBYSxDQUFDLEVBQUUsV0FBVyxFQUFFLElBQUksSUFBSSxDQUFDO0lBRXZFLDRHQUE0RztJQUM1RyxNQUFNLE9BQU8sR0FBRyxDQUFDLElBQWlGLEVBQUUsUUFBc0IsRUFBRSxPQUFlLEVBQUUsUUFBNkIsRUFDeEssS0FBSyxHQUF5RSxFQUFFLEVBQUUsRUFBRTtRQUNwRixJQUFJLE1BQU0sQ0FBQyxVQUFVLEVBQUUsUUFBUSxFQUFFLEtBQUssQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQ2xELEtBQUssTUFBTSxDQUFDLElBQUksUUFBUTtnQkFBRSxRQUFRLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzFELFFBQVEsQ0FBQyxJQUFJLENBQUM7Z0JBQ1osSUFBSSxFQUFFLGVBQWU7Z0JBQ3JCLFFBQVEsRUFBRSxNQUFNO2dCQUNoQixPQUFPLEVBQUUsR0FBRyxPQUFPLDhCQUE4QixLQUFLLENBQUMsQ0FBQyxDQUFDLFVBQVUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRztnQkFDbEYsUUFBUSxFQUFFLFFBQVEsQ0FBQyxHQUFHLENBQUMsY0FBYyxDQUFDO2dCQUN0QyxhQUFhLEVBQUUsS0FBSztnQkFDcEIsR0FBRyxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksS0FBSztnQkFDN0IsTUFBTSxFQUFFLElBQUk7YUFDYixDQUFDLENBQUM7WUFDSCxPQUFPO1FBQ1QsQ0FBQztRQUNELFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxHQUFHLE9BQU8sR0FBRyxHQUFHLEVBQUUsRUFBRSxRQUFRLEVBQUUsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLEVBQUUsR0FBRyxTQUFTLEVBQUUsR0FBRyxLQUFLLEVBQUUsQ0FBQyxDQUFDO0lBQzFILENBQUMsQ0FBQztJQUVGLE1BQU0sV0FBVyxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLElBQUksQ0FBQyxDQUFDO0lBQ2pFLElBQUksS0FBSyxDQUFDLEdBQUcsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNsQixPQUFPLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxHQUFHLEdBQUcsUUFBUSxLQUFLLENBQUMsR0FBRyxXQUFXLEtBQUssQ0FBQyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsb0RBQW9ELFdBQVcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssZ0JBQWdCLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDbE8sQ0FBQztJQUNELE1BQU0sSUFBSSxHQUFHLEtBQUssQ0FBQyxJQUFJLENBQUM7SUFDeEIsSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUNULE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxjQUFjLENBQUMsQ0FBQyxFQUFFLGlCQUFpQixFQUFFLEVBQUUsSUFBSSxDQUFDLE1BQU0sSUFBSSxVQUFVLENBQUMsQ0FBQyxDQUFDO1FBQzlHLE9BQU8sQ0FBQyxjQUFjLEVBQUUsT0FBTyxFQUFFLEdBQUcsR0FBRywrQkFBK0IsSUFBSSxDQUFDLEtBQUssVUFBVSxXQUFXLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxVQUFVLENBQUMsV0FBVyxJQUFJLENBQUMsS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLDJCQUEyQixJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsVUFBVSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEVBQzFRLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFDcEksQ0FBQztTQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsZUFBZSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzVDLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxLQUFLLFVBQVUsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztRQUM5RixPQUFPLENBQUMsdUJBQXVCLEVBQUUsT0FBTyxFQUFFLEdBQUcsR0FBRyxRQUFRLEtBQUssQ0FBQyxlQUFlLDRCQUE0QixLQUFLLENBQUMsZUFBZSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNsTixDQUFDO0lBQ0QsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLFdBQVcsSUFBSSxDQUFDLENBQUM7SUFDM0MsSUFBSSxXQUFXLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDcEIsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLEtBQUssTUFBTSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzFGLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxlQUFlLEtBQUssSUFBSSxJQUFJLFdBQVcsR0FBRyxNQUFNLENBQUMsZUFBZSxDQUFDO1FBQ3JGLE9BQU8sQ0FBQyxtQkFBbUIsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUNwRCxHQUFHLEdBQUcsUUFBUSxXQUFXLHdCQUF3QixXQUFXLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLDJDQUEyQyxNQUFNLENBQUMsZUFBZSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQy9LLENBQUM7SUFFRCxJQUFJLEtBQUssQ0FBQyxVQUFVLEtBQUssS0FBSztRQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxNQUFNLHNCQUFzQixDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQzlGLE9BQU8sRUFBRSxRQUFRLEVBQUUsVUFBVSxDQUFDLFFBQVEsQ0FBQyxFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDLEdBQUcsUUFBUSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUM7QUFDOUYsQ0FBQztBQUVELHFFQUFxRTtBQUNyRSxNQUFNLGdCQUFnQixHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLGNBQWMsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxxQkFBcUIsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7QUFFN0ksTUFBTSxTQUFTLEdBQUcsQ0FBQyxLQUFhLEVBQVUsRUFBRSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDO0FBSTdFLElBQUksZ0JBQWdCLEdBQTRCLElBQUksQ0FBQztBQUVyRCx3RkFBd0Y7QUFDeEYsTUFBTSxVQUFVLHFDQUFxQyxDQUFDLE1BQStCO0lBQ25GLGdCQUFnQixHQUFHLE1BQU0sQ0FBQztBQUM1QixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxLQUFLLFVBQVUsc0JBQXNCLENBQUMsS0FBYSxFQUFFLE1BQXFCO0lBQ3hFLElBQUksYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQztRQUFFLE9BQU8sRUFBRSxDQUFDO0lBQ3pELE1BQU0sS0FBSyxHQUFHLDJCQUEyQixDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxVQUFVLENBQUM7SUFDbkUsTUFBTSxVQUFVLEdBQStCLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLEVBQUUsR0FBRyxLQUFLLEVBQUUsQ0FBQztJQUN4RyxJQUFJLENBQUM7UUFDSCxnQkFBZ0IsS0FBSyxzQkFBc0IsRUFBRSxDQUFDO1FBQzlDLE1BQU0sSUFBSSxHQUFHLG9CQUFvQixDQUFDLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDcEYsTUFBTSxNQUFNLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLFVBQXFDLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDdkcsTUFBTSxRQUFRLEdBQUcsQ0FBQyxDQUFzQixFQUFFLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ3RGLE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBc0IsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFzQixFQUFlLEVBQUUsQ0FBQyxDQUFDO1lBQy9FLElBQUksRUFBRSxzQkFBc0I7WUFDNUIsUUFBUSxFQUFFLElBQUksS0FBSyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsU0FBUztZQUNoRCxPQUFPLEVBQUUsR0FBRyxNQUFNLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxPQUFPLEtBQUssQ0FBQyxDQUFDLE9BQU8sRUFBRTtZQUN6RCxNQUFNLEVBQUUsQ0FBQyxDQUFDLE1BQU07WUFDaEIsUUFBUSxFQUFFLENBQUMsQ0FBQyxRQUFRO1lBQ3BCLEtBQUssRUFBRSxDQUFDLENBQUMsS0FBSztZQUNkLElBQUk7U0FDTCxDQUFDLENBQUM7UUFDSCxPQUFPLENBQUMsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2SCxDQUFDO0lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNiLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSx3QkFBd0IsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSwyRUFBMkUsTUFBTSxDQUFDLElBQUksSUFBSSxNQUFNLENBQUMsT0FBTyxLQUFLLFlBQVksQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUM3TSxDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIFRIRSB2dWxuZXJhYmlsaXR5IGFzc2Vzc21lbnQgb2Ygb25lIHJlc29sdmVkIHBsdWdpbiB2ZXJzaW9uLCBmb3Igb25lIG9yZyAoYW5kLFxuICogb3B0aW9uYWxseSwgb25lIHBpcGVsaW5lJ3MgcmlzayBhY2NlcHRhbmNlKS4gT25lIGZ1bmN0aW9uLCB0aHJlZSBjYWxsZXJzOlxuICogYC9wbHVnaW5zL2xvb2t1cGAgKHdoYXQgc3ludGggcGlucyksIGAvcGx1Z2lucy9ydW50aW1lLWNoZWNrYCAod2hhdCBhIHJ1bm5pbmdcbiAqIHBpcGVsaW5lIGlzIGFib3V0IHRvIGV4ZWN1dGUpIGFuZCB0aGUgcGlwZWxpbmUgc2VydmljZSdzIHNhdmUtdGltZSBjb250cmFjdFxuICogY2hlY2suIFRocmVlIGNvcGllcyBvZiB0aGVzZSBydWxlcyBkcmlmdGVkIG9uY2UgYWxyZWFkeS5cbiAqXG4gKiBWdWxuZXJhYmlsaXR5IHN0YXRlIE5FVkVSIHJlZnVzZXMgYSBwaXBlbGluZSDigJQgbm90IGl0cyBzYXZlLCBpdHMgc3ludGgsIGl0c1xuICogZGVwbG95IG9yIGl0cyBydW4uIFdoYXQgaXQgcHJvZHVjZXMgaXMgU0VWRVJJVFktR1JBREVEIHdhcm5pbmdzIChhbmQsIGZyb20gdGhlXG4gKiBjYWxsZXJzLCBub3RpZmljYXRpb25zIHRvIHRoZSBwaXBlbGluZSdzIG93bmVycykuIFRoZSBncmFkZXM6XG4gKlxuICogICBjcml0aWNhbCDigJQgYSBmaW5kaW5nIG9uIHRoZSBDSVNBIEtub3duIEV4cGxvaXRlZCBWdWxuZXJhYmlsaXRpZXMgbGlzdFxuICogICBlcnJvciAgICDigJQgdGhlIHZlcnNpb24gaXMgRkxBR0dFRCAoZ2F0ZWQgQ3JpdGljYWxzIG92ZXIgdGhlIHBsYXRmb3JtIGZsb29yKSxcbiAqICAgICAgICAgICAgICBpdCBoYXMgZml4YWJsZSBDcml0aWNhbCBmaW5kaW5ncywgb3IgYW4gb3JnIGNvbXBsaWFuY2UgcnVsZSBvbiB0aGVcbiAqICAgICAgICAgICAgICB2dWxuZXJhYmlsaXR5IGF0dHJpYnV0ZXMgaXMgaW4gQkxPQ0sgbW9kZSBhbmQgZmFpbHNcbiAqICAgd2FybmluZyAg4oCUIGZpeGFibGUgSGlnaCBmaW5kaW5ncyBvdmVyIHRoZSBvcmcncyBgd2FybkZpeGFibGVIaWdoYCwgYSB2ZXJzaW9uXG4gKiAgICAgICAgICAgICAgbmV2ZXIgc2Nhbm5lZCwgYSBzY2FuIG9sZGVyIHRoYW4gYFBMVUdJTl9TQ0FOX1NUQUxFX0hPVVJTYCwgb3IgYVxuICogICAgICAgICAgICAgIGNvbXBsaWFuY2UgcnVsZSBpbiBXQVJOIG1vZGVcbiAqICAgaW5mbyAgICAg4oCUIHdoYXQgYSByZWFkZXIgbWF5IHdhbnQgdG8ga25vdyBidXQgbmVlZCBub3QgYWN0IG9uXG4gKlxuICogQSBQSVBFTElORSdzIGFjdGl2ZSByaXNrIGFjY2VwdGFuY2UgKGBwbHVnaW5fdnVsbl9leHBvc3VyZWAsIHRyaWFnZWQgYGFjY2VwdGVkYFxuICogd2l0aCBhIHJlYXNvbiBhbmQgYW4gZXhwaXJ5KSBkb3duZ3JhZGVzIHRoZSB3YXJuaW5ncyBhYm91dCB0aGUgZmluZGluZ3MgaXRcbiAqIEFDQ0VQVEVEIHRvIGBpbmZvYCAoXCJhY2NlcHRlZCB1bnRpbCDigKZcIikg4oCUIG5ldmVyIG9uZSBhYm91dCBhIGZpbmRpbmcgdGhhdFxuICogYXBwZWFyZWQgc2luY2UsIG5ldmVyIGEgS0VWIG9uZSB1bmxlc3MgdGhlIGFjY2VwdGFuY2Ugc2FpZCBga2V2OiB0cnVlYCwgYW5kXG4gKiBuZXZlciB0aGUgc2Nhbi1mcmVzaG5lc3Mgb3IgY29tcGxpYW5jZSB3YXJuaW5ncyAobmVpdGhlciBpcyBhYm91dCBhIGZpbmRpbmcpLlxuICovXG5cbmltcG9ydCB7IGNyZWF0ZUNvbXBsaWFuY2VDbGllbnQsIHR5cGUgQ29tcGxpYW5jZVZpb2xhdGlvbiB9IGZyb20gJy4vY29tcGxpYW5jZS1jbGllbnQuanMnO1xuaW1wb3J0IHsgZ2V0U2VydmljZUF1dGhIZWFkZXIgfSBmcm9tICcuLi9taWRkbGV3YXJlL3NlcnZpY2UtdG9rZW5zLmpzJztcbmltcG9ydCB7IGlzU3lzdGVtT3JnSWQgfSBmcm9tICcuLi9taWRkbGV3YXJlL3N5c3RlbS1vcmcuanMnO1xuaW1wb3J0IHtcbiAgYXNTY2FuRmxhZywgZGVzY3JpYmVGaW5kaW5ncywgZmFpbE9uTGFiZWwsIGlzR2F0ZWRGaW5kaW5nLCBwbHVnaW5WdWxuR2F0ZUtldiwgc2NhbkZpbmRpbmdLZXksXG4gIHR5cGUgUGx1Z2luU2NhbkZpbmRpbmcsIHR5cGUgUGx1Z2luU2NhbkZsYWcsXG59IGZyb20gJy4uL3R5cGVzL3BsdWdpbi1zY2FuLmpzJztcbmltcG9ydCB7IGVudkludCB9IGZyb20gJy4uL3V0aWxzL2Vudi5qcyc7XG5pbXBvcnQgeyBkZXJpdmVQbHVnaW5JbWFnZUNvbXBsaWFuY2UsIHBsdWdpblJ1bnNPd25JbWFnZSwgdHlwZSBQbHVnaW5Db21wbGlhbmNlQXR0cmlidXRlcywgdHlwZSBQbHVnaW5JbWFnZVJvdyB9IGZyb20gJy4uL3V0aWxzL3BsdWdpbi1jb21wbGlhbmNlLmpzJztcbmltcG9ydCB7IGVycm9yTWVzc2FnZSB9IGZyb20gJy4uL3V0aWxzL3Jlc3BvbnNlLmpzJztcblxuLyoqIEhvdyBsb3VkIGEgd2FybmluZyBpcywgcXVpZXRlc3QgZmlyc3QuICovXG5leHBvcnQgY29uc3QgVlVMTl9TRVZFUklUSUVTID0gWydpbmZvJywgJ3dhcm5pbmcnLCAnZXJyb3InLCAnY3JpdGljYWwnXSBhcyBjb25zdDtcbmV4cG9ydCB0eXBlIFZ1bG5TZXZlcml0eSA9IHR5cGVvZiBWVUxOX1NFVkVSSVRJRVNbbnVtYmVyXTtcblxuLyoqIFRoZSBsb3VkZXIgb2YgdHdvIHNldmVyaXRpZXMuICovXG5leHBvcnQgZnVuY3Rpb24gbWF4U2V2ZXJpdHkoYTogVnVsblNldmVyaXR5LCBiOiBWdWxuU2V2ZXJpdHkpOiBWdWxuU2V2ZXJpdHkge1xuICByZXR1cm4gVlVMTl9TRVZFUklUSUVTLmluZGV4T2YoYSkgPj0gVlVMTl9TRVZFUklUSUVTLmluZGV4T2YoYikgPyBhIDogYjtcbn1cblxuLyoqIFdoZXRoZXIgYHNgIGlzIGF0IGxlYXN0IGBmbG9vcmAuICovXG5leHBvcnQgZnVuY3Rpb24gc2V2ZXJpdHlBdExlYXN0KHM6IFZ1bG5TZXZlcml0eSwgZmxvb3I6IFZ1bG5TZXZlcml0eSk6IGJvb2xlYW4ge1xuICByZXR1cm4gVlVMTl9TRVZFUklUSUVTLmluZGV4T2YocykgPj0gVlVMTl9TRVZFUklUSUVTLmluZGV4T2YoZmxvb3IpO1xufVxuXG4vKiogYFBMVUdJTl9TQ0FOX1NUQUxFX0hPVVJTYCAoZGVmYXVsdCA3Mik6IGEgc2NhbiBvbGRlciB0aGFuIHRoaXMgaXMgc3RhbGUuICovXG5leHBvcnQgZnVuY3Rpb24gc2NhblN0YWxlSG91cnMoKTogbnVtYmVyIHtcbiAgcmV0dXJuIGVudkludCgnUExVR0lOX1NDQU5fU1RBTEVfSE9VUlMnLCA3MiwgeyBtaW46IDEgfSk7XG59XG5cbi8qKiBUaGUgc2Nhbi1yZWxhdGVkIGZpZWxkcyBvZiBhIHJlc29sdmVkIHJlY29yZCAoYW4gb3JnIHJvdyBvciBhIGxpc3RlZCByZWNvcmQpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBTY2FubmVkUmVjb3JkIGV4dGVuZHMgUGx1Z2luSW1hZ2VSb3cge1xuICBuYW1lOiBzdHJpbmc7XG4gIHZlcnNpb246IHN0cmluZztcbiAgc2Nhbm5lZEF0PzogRGF0ZSB8IHN0cmluZyB8IG51bGw7XG4gIHNjYW5TdW1tYXJ5PzogdW5rbm93bjtcbiAgc2NhbkZsYWdnZWRBdD86IERhdGUgfCBzdHJpbmcgfCBudWxsO1xuICBzY2FuRmxhZz86IHVua25vd247XG4gIHZ1bG5IaWdoRml4YWJsZT86IHVua25vd247XG59XG5cbmNvbnN0IHRvRGF0ZSA9ICh2OiB1bmtub3duKTogRGF0ZSB8IG51bGwgPT4ge1xuICBpZiAoIXYpIHJldHVybiBudWxsO1xuICBjb25zdCBkID0gdiBpbnN0YW5jZW9mIERhdGUgPyB2IDogbmV3IERhdGUoU3RyaW5nKHYpKTtcbiAgcmV0dXJuIE51bWJlci5pc05hTihkLmdldFRpbWUoKSkgPyBudWxsIDogZDtcbn07XG5cbmNvbnN0IHN1bW1hcnlPZiA9IChyZWNvcmQ6IFBpY2s8U2Nhbm5lZFJlY29yZCwgJ3NjYW5TdW1tYXJ5Jz4pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IG51bGwgPT5cbiAgKHJlY29yZC5zY2FuU3VtbWFyeSAmJiB0eXBlb2YgcmVjb3JkLnNjYW5TdW1tYXJ5ID09PSAnb2JqZWN0JyAmJiAhQXJyYXkuaXNBcnJheShyZWNvcmQuc2NhblN1bW1hcnkpXG4gICAgPyByZWNvcmQuc2NhblN1bW1hcnkgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gOiBudWxsKTtcblxuLyoqXG4gKiBXaGVuIHRoZSB2ZXJzaW9uIHdhcyBsYXN0IHNjYW5uZWQ6IHRoZSBsYXRlciBvZiB0aGUgYnVpbGQtdGltZSBgc2Nhbm5lZEF0YCBhbmRcbiAqIHRoZSBuaWdodGx5IHJlc2NhbidzIGBzY2FuX3N1bW1hcnkuc2Nhbm5lZEF0YC4gTnVsbCA9IG5ldmVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbGFzdFNjYW5uZWRBdChyZWNvcmQ6IFBpY2s8U2Nhbm5lZFJlY29yZCwgJ3NjYW5uZWRBdCcgfCAnc2NhblN1bW1hcnknPik6IERhdGUgfCBudWxsIHtcbiAgY29uc3QgYnVpbGQgPSB0b0RhdGUocmVjb3JkLnNjYW5uZWRBdCk7XG4gIGNvbnN0IHN1bW1hcnkgPSB0b0RhdGUoc3VtbWFyeU9mKHJlY29yZCk/LnNjYW5uZWRBdCk7XG4gIGlmICghYnVpbGQpIHJldHVybiBzdW1tYXJ5O1xuICBpZiAoIXN1bW1hcnkpIHJldHVybiBidWlsZDtcbiAgcmV0dXJuIHN1bW1hcnkgPiBidWlsZCA/IHN1bW1hcnkgOiBidWlsZDtcbn1cblxuLyoqIFdoZXRoZXIgdGhlIHJlY29yZCBydW5zIGEgQlVJTFQgaW1hZ2Ugb2YgaXRzIG93biDigJQgdGhlIG9ubHkgdGhpbmcgYSBzY2FuIGFwcGxpZXMgdG8uICovXG5mdW5jdGlvbiBoYXNJbWFnZShyZWNvcmQ6IFNjYW5uZWRSZWNvcmQpOiBib29sZWFuIHtcbiAgcmV0dXJuIHBsdWdpblJ1bnNPd25JbWFnZShyZWNvcmQpICYmIHR5cGVvZiByZWNvcmQuaW1hZ2VEaWdlc3QgPT09ICdzdHJpbmcnICYmIHJlY29yZC5pbWFnZURpZ2VzdC5sZW5ndGggPiAwO1xufVxuXG4vKiogRnJlc2huZXNzIG9mIGEgdmVyc2lvbidzIHNjYW46IGBub25lYCAobm8gaW1hZ2UgdG8gc2NhbiksIGB1bnNjYW5uZWRgLCBgc3RhbGVgIG9yIGBmcmVzaGAuICovXG5leHBvcnQgZnVuY3Rpb24gc2NhbkZyZXNobmVzcyhyZWNvcmQ6IFNjYW5uZWRSZWNvcmQsIG5vdyA9IG5ldyBEYXRlKCkpOiB7IHN0YXRlOiAnbm9uZScgfCAndW5zY2FubmVkJyB8ICdzdGFsZScgfCAnZnJlc2gnOyBzY2FubmVkQXQ6IERhdGUgfCBudWxsIH0ge1xuICBpZiAoIWhhc0ltYWdlKHJlY29yZCkpIHJldHVybiB7IHN0YXRlOiAnbm9uZScsIHNjYW5uZWRBdDogbnVsbCB9O1xuICBjb25zdCBhdCA9IGxhc3RTY2FubmVkQXQocmVjb3JkKTtcbiAgaWYgKCFhdCkgcmV0dXJuIHsgc3RhdGU6ICd1bnNjYW5uZWQnLCBzY2FubmVkQXQ6IG51bGwgfTtcbiAgcmV0dXJuIHsgc3RhdGU6IG5vdy5nZXRUaW1lKCkgLSBhdC5nZXRUaW1lKCkgPiBzY2FuU3RhbGVIb3VycygpICogM182MDBfMDAwID8gJ3N0YWxlJyA6ICdmcmVzaCcsIHNjYW5uZWRBdDogYXQgfTtcbn1cblxuLyoqIE9uZSBzZXZlcml0eS1ncmFkZWQgdnVsbmVyYWJpbGl0eSB3YXJuaW5nLiAqL1xuZXhwb3J0IHR5cGUgVnVsbldhcm5pbmcgPVxuICB8IHtcbiAgICBjb2RlOiAnVlVMTl9LRVYnIHwgJ1ZVTE5fRkxBR0dFRCcgfCAnVlVMTl9DUklUSUNBTF9GSVhBQkxFJyB8ICdWVUxOX0hJR0hfRklYQUJMRSc7XG4gICAgc2V2ZXJpdHk6IFZ1bG5TZXZlcml0eTtcbiAgICBtZXNzYWdlOiBzdHJpbmc7XG4gICAgZmluZGluZ3M6IFBsdWdpblNjYW5GaW5kaW5nW107XG4gICAgc3VnZ2VzdGVkVmVyc2lvbj86IHN0cmluZztcbiAgICAvKiogYFZVTE5fRkxBR0dFRGAgY2FycmllcyB0aGUgZmxhZydzIGNvdW50cyAodGhlIHNoYXBlIHRoZSByZXNjYW4tZmxhZyB3YXJuaW5nIGFsd2F5cyBoYWQpLiAqL1xuICAgIHBsdWdpbj86IHN0cmluZztcbiAgICB2ZXJzaW9uPzogc3RyaW5nO1xuICAgIC8qKiBUaGUgZmxhZydzIGdhdGVkIGNvdW50IChmaW5kaW5ncyBhdCBvciBhYm92ZSBpdHMgYGZhaWxPbmApLiAqL1xuICAgIGdhdGVkPzogbnVtYmVyO1xuICAgIGhpZ2g/OiBudW1iZXI7XG4gIH1cbiAgfCB7IGNvZGU6ICdWVUxOX0FDQ0VQVEVEJzsgc2V2ZXJpdHk6ICdpbmZvJzsgbWVzc2FnZTogc3RyaW5nOyBmaW5kaW5nczogc3RyaW5nW107IGFjY2VwdGVkVW50aWw6IHN0cmluZyB8IG51bGw7IGtldjogYm9vbGVhbjsgY292ZXJzOiBzdHJpbmcgfVxuICB8IHsgY29kZTogJ1VOU0NBTk5FRCc7IHNldmVyaXR5OiBWdWxuU2V2ZXJpdHk7IG1lc3NhZ2U6IHN0cmluZyB9XG4gIHwgeyBjb2RlOiAnU0NBTl9TVEFMRSc7IHNldmVyaXR5OiBWdWxuU2V2ZXJpdHk7IG1lc3NhZ2U6IHN0cmluZzsgc2Nhbm5lZEF0OiBzdHJpbmc7IHN0YWxlQWZ0ZXJIb3VyczogbnVtYmVyIH1cbiAgfCB7IGNvZGU6ICdDT01QTElBTkNFX1ZVTE5fUlVMRSc7IHNldmVyaXR5OiBWdWxuU2V2ZXJpdHk7IG1lc3NhZ2U6IHN0cmluZzsgcnVsZUlkOiBzdHJpbmc7IHJ1bGVOYW1lOiBzdHJpbmc7IGZpZWxkOiBzdHJpbmc7IG1vZGU6ICdibG9jaycgfCAnd2FybicgfVxuICB8IHsgY29kZTogJ0NPTVBMSUFOQ0VfVU5BVkFJTEFCTEUnOyBzZXZlcml0eTogVnVsblNldmVyaXR5OyBtZXNzYWdlOiBzdHJpbmcgfTtcblxuLyoqIGBVTlNDQU5ORURgIC8gYFNDQU5fU1RBTEVgIGZvciBhIHJlc29sdmVkIHZlcnNpb24gKGVtcHR5IGZvciBhIGZyZXNoIHNjYW4gb3IgYW4gaW1hZ2UtbGVzcyBwbHVnaW4pLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjYW5XYXJuaW5ncyhyZWNvcmQ6IFNjYW5uZWRSZWNvcmQsIG5vdyA9IG5ldyBEYXRlKCkpOiBWdWxuV2FybmluZ1tdIHtcbiAgY29uc3QgcmVmID0gYCR7cmVjb3JkLm5hbWV9QCR7cmVjb3JkLnZlcnNpb259YDtcbiAgY29uc3QgZiA9IHNjYW5GcmVzaG5lc3MocmVjb3JkLCBub3cpO1xuICBpZiAoZi5zdGF0ZSA9PT0gJ3Vuc2Nhbm5lZCcpIHtcbiAgICByZXR1cm4gW3sgY29kZTogJ1VOU0NBTk5FRCcsIHNldmVyaXR5OiAnd2FybmluZycsIG1lc3NhZ2U6IGBQbHVnaW4gJHtyZWZ9IGhhcyBuZXZlciBiZWVuIHNjYW5uZWQgZm9yIHZ1bG5lcmFiaWxpdGllczsgbm90aGluZyBpcyBrbm93biBhYm91dCB3aGF0IGl0cyBpbWFnZSBjb250YWlucy5gIH1dO1xuICB9XG4gIGlmIChmLnN0YXRlID09PSAnc3RhbGUnKSB7XG4gICAgY29uc3QgaG91cnMgPSBzY2FuU3RhbGVIb3VycygpO1xuICAgIHJldHVybiBbe1xuICAgICAgY29kZTogJ1NDQU5fU1RBTEUnLFxuICAgICAgc2V2ZXJpdHk6ICd3YXJuaW5nJyxcbiAgICAgIG1lc3NhZ2U6IGBQbHVnaW4gJHtyZWZ9IHdhcyBsYXN0IHNjYW5uZWQgJHtmLnNjYW5uZWRBdCEudG9JU09TdHJpbmcoKX0sIG1vcmUgdGhhbiAke2hvdXJzfWggYWdvOyBmaW5kaW5ncyBwdWJsaXNoZWQgc2luY2UgYXJlIG5vdCByZWZsZWN0ZWQuYCxcbiAgICAgIHNjYW5uZWRBdDogZi5zY2FubmVkQXQhLnRvSVNPU3RyaW5nKCksXG4gICAgICBzdGFsZUFmdGVySG91cnM6IGhvdXJzLFxuICAgIH1dO1xuICB9XG4gIHJldHVybiBbXTtcbn1cblxuLyoqIFRoZSB2dWxuZXJhYmlsaXR5IGZpZWxkcyBvZiBhbiBvcmcncyBjb25zdW1wdGlvbiBwb2xpY3kgKHBpcGVsaW5lLWRhdGEncyBgQ29uc3VtcHRpb25Qb2xpY3lgIHNhdGlzZmllcyBpdCkuICovXG5leHBvcnQgaW50ZXJmYWNlIFZ1bG5Db25zdW1wdGlvblBvbGljeSB7XG4gIC8qKiBGaXhhYmxlIEhpZ2ggZmluZGluZ3MgYWJvdmUgdGhpcyBtYW55IHJhaXNlIGEgYHdhcm5pbmdgOyBudWxsID0gbmV2ZXIgKHRoZXkgc3RheSBgaW5mb2ApLiAqL1xuICB3YXJuRml4YWJsZUhpZ2g6IG51bWJlciB8IG51bGw7XG59XG5cbi8qKlxuICogQSBwaXBlbGluZSdzIEFDVElWRSByaXNrIGFjY2VwdGFuY2Ugb2Ygb25lIHZlcnNpb24gLyBpbWFnZTogdGhlIGZpbmRpbmcga2V5c1xuICogKHtAbGluayBzY2FuRmluZGluZ0tleX0pIGl0IGFjY2VwdGVkLCB3aGV0aGVyIGl0IGFjY2VwdGVkIEtFViBmaW5kaW5ncywgYW5kXG4gKiB1bnRpbCB3aGVuLiBCdWlsdCBieSBwaXBlbGluZS1kYXRhIGZyb20gYHBsdWdpbl92dWxuX2V4cG9zdXJlYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBWdWxuQWNjZXB0YW5jZSB7XG4gIGZpbmRpbmdLZXlzOiByZWFkb25seSBzdHJpbmdbXTtcbiAga2V2OiBib29sZWFuO1xuICBhY2NlcHRlZFVudGlsOiBEYXRlIHwgc3RyaW5nIHwgbnVsbDtcbn1cblxuLyoqIFdoYXQgYSB2ZXJzaW9uJ3Mgc3RvcmVkIHNjYW4gc2F5cywgbm9ybWFsaXplZCBmcm9tIGBzY2FuX3N1bW1hcnlgIChmb3IgaXRzIGltYWdlKSBhbmQgYHNjYW5fZmxhZ2AuICovXG5leHBvcnQgaW50ZXJmYWNlIFZlcnNpb25TY2FuRmFjdHMge1xuICBmbGFnZ2VkOiBib29sZWFuO1xuICBmbGFnOiBQbHVnaW5TY2FuRmxhZyB8IG51bGw7XG4gIC8qKiBGaXhhYmxlIENyaXRpY2FsIC8gSGlnaCBmaW5kaW5ncyAobnVsbCA9IG5vdCBrbm93bikuICovXG4gIGNyaXRpY2FsRml4YWJsZTogbnVtYmVyIHwgbnVsbDtcbiAgaGlnaEZpeGFibGU6IG51bWJlciB8IG51bGw7XG4gIC8qKiBUb3RhbHMgaW5jbHVkaW5nIHVuZml4YWJsZSBmaW5kaW5ncyAobnVsbCA9IG5vdCBrbm93bikuICovXG4gIGNyaXRpY2FsOiBudW1iZXIgfCBudWxsO1xuICBoaWdoOiBudW1iZXIgfCBudWxsO1xuICAvKiogS0VWLWxpc3RlZCBDcml0aWNhbCArIEhpZ2ggZmluZGluZ3MuICovXG4gIGtldjogbnVtYmVyO1xuICAvKiogRXZlcnkgQ3JpdGljYWwvSGlnaCBmaW5kaW5nIHRoZSBzY2FuIGl0ZW1pemVkICh0aGUgc3VtbWFyeSdzIGxpc3QsIGVsc2UgdGhlIGZsYWcncykuICovXG4gIGZpbmRpbmdzOiBQbHVnaW5TY2FuRmluZGluZ1tdO1xuICAvKiogVGhlIHN1bW1hcnkgY3V0IGl0cyBmaW5kaW5ncyBsaXN0IOKAlCBhIHN1YnNldCBjaGVjayBvdmVyIGl0IGNhbm5vdCBiZSB0cnVzdGVkLiAqL1xuICB0cnVuY2F0ZWQ6IGJvb2xlYW47XG4gIHNjYW5uZWRBdDogRGF0ZSB8IG51bGw7XG59XG5cbi8qKiBUaGUgbm9ybWFsaXplZCBzY2FuIGZhY3RzIG9mIGEgcmVzb2x2ZWQgcmVjb3JkLiBBIHN1bW1hcnkgZGVzY3JpYmluZyBhbm90aGVyIGltYWdlIGlzIGlnbm9yZWQuICovXG5leHBvcnQgZnVuY3Rpb24gdmVyc2lvblNjYW5GYWN0cyhyZWNvcmQ6IFNjYW5uZWRSZWNvcmQpOiBWZXJzaW9uU2NhbkZhY3RzIHtcbiAgY29uc3QgZmxhZyA9IHJlY29yZC5zY2FuRmxhZ2dlZEF0ID8gYXNTY2FuRmxhZyhyZWNvcmQuc2NhbkZsYWcpIDogbnVsbDtcbiAgY29uc3QgcmF3ID0gc3VtbWFyeU9mKHJlY29yZCk7XG4gIGNvbnN0IGRpZ2VzdCA9IHR5cGVvZiByYXc/LmltYWdlRGlnZXN0ID09PSAnc3RyaW5nJyA/IHJhdy5pbWFnZURpZ2VzdCA6IG51bGw7XG4gIGNvbnN0IHN1bW1hcnkgPSByYXcgJiYgKGRpZ2VzdCA9PT0gbnVsbCB8fCAhcmVjb3JkLmltYWdlRGlnZXN0IHx8IGRpZ2VzdCA9PT0gcmVjb3JkLmltYWdlRGlnZXN0KSA/IHJhdyA6IG51bGw7XG4gIGNvbnN0IGZpbmRpbmdzID0gc3VtbWFyeSAmJiBBcnJheS5pc0FycmF5KHN1bW1hcnkuZmluZGluZ3MpXG4gICAgPyAoc3VtbWFyeS5maW5kaW5ncyBhcyBQbHVnaW5TY2FuRmluZGluZ1tdKS5maWx0ZXIoKGYpID0+IGYgJiYgdHlwZW9mIGYuaWQgPT09ICdzdHJpbmcnKS5tYXAoKGYpID0+ICh7IC4uLmYsIGZpeGVkSW46IEFycmF5LmlzQXJyYXkoZi5maXhlZEluKSA/IGYuZml4ZWRJbiA6IFtdIH0pKVxuICAgIDogKGZsYWc/LmZpbmRpbmdzID8/IFtdKTtcbiAgY29uc3QgbnVtID0gKHY6IHVua25vd24pOiBudW1iZXIgfCBudWxsID0+ICh0eXBlb2YgdiA9PT0gJ251bWJlcicgPyB2IDogbnVsbCk7XG4gIGNvbnN0IGtldkNvdW50ID0gTWF0aC5tYXgobnVtKHN1bW1hcnk/LmtldikgPz8gMCwgZmxhZz8ua2V2ID8/IDAsIGZpbmRpbmdzLmZpbHRlcigoZikgPT4gZi5rZXYgPT09IHRydWUpLmxlbmd0aCk7XG4gIHJldHVybiB7XG4gICAgZmxhZ2dlZDogZmxhZyAhPT0gbnVsbCxcbiAgICBmbGFnLFxuICAgIGNyaXRpY2FsRml4YWJsZTogbnVtKHN1bW1hcnk/LmNyaXRpY2FsRml4YWJsZSksXG4gICAgaGlnaEZpeGFibGU6IG51bShzdW1tYXJ5Py5oaWdoRml4YWJsZSkgPz8gbnVtKHJlY29yZC52dWxuSGlnaEZpeGFibGUpLFxuICAgIGNyaXRpY2FsOiBudW0oc3VtbWFyeT8uY3JpdGljYWwpLFxuICAgIGhpZ2g6IG51bShzdW1tYXJ5Py5oaWdoKSxcbiAgICBrZXY6IGtldkNvdW50LFxuICAgIGZpbmRpbmdzLFxuICAgIHRydW5jYXRlZDogc3VtbWFyeT8udHJ1bmNhdGVkID09PSB0cnVlLFxuICAgIHNjYW5uZWRBdDogbGFzdFNjYW5uZWRBdChyZWNvcmQpLFxuICB9O1xufVxuXG4vKipcbiAqIFdoZXRoZXIgYGFjY2VwdGFuY2VgIGNvdmVycyBFVkVSWSBvbmUgb2YgYGZpbmRpbmdzYCAoYnkgZmluZGluZyBrZXkpLCBhbmQgaXRzXG4gKiBLRVYgb25lcyBvbmx5IHdoZW4gaXQgYWNjZXB0ZWQgS0VWLiBBbiBlbXB0eSBzZXQgaXMgbmV2ZXIgXCJjb3ZlcmVkXCI6IHdpdGhcbiAqIG5vdGhpbmcgaXRlbWl6ZWQgdGhlcmUgaXMgbm90aGluZyBhbiBhY2NlcHRhbmNlIGNhbiBiZSBzaG93biB0byBkZXNjcmliZS5cbiAqL1xuZnVuY3Rpb24gY292ZXJzKGFjY2VwdGFuY2U6IFZ1bG5BY2NlcHRhbmNlIHwgbnVsbCB8IHVuZGVmaW5lZCwgZmluZGluZ3M6IHJlYWRvbmx5IFBsdWdpblNjYW5GaW5kaW5nW10sIHRydW5jYXRlZDogYm9vbGVhbik6IGJvb2xlYW4ge1xuICBpZiAoIWFjY2VwdGFuY2UgfHwgdHJ1bmNhdGVkIHx8IGZpbmRpbmdzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIGZhbHNlO1xuICBjb25zdCBrZXlzID0gbmV3IFNldChhY2NlcHRhbmNlLmZpbmRpbmdLZXlzKTtcbiAgcmV0dXJuIGZpbmRpbmdzLmV2ZXJ5KChmKSA9PiBrZXlzLmhhcyhzY2FuRmluZGluZ0tleShmKSkgJiYgKGYua2V2ICE9PSB0cnVlIHx8IGFjY2VwdGFuY2Uua2V2KSk7XG59XG5cbi8qKiBJbnB1dCB0byB7QGxpbmsgYXNzZXNzVmVyc2lvblZ1bG5zfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVmVyc2lvblZ1bG5JbnB1dCB7XG4gIG9yZ0lkOiBzdHJpbmc7XG4gIHJlY29yZDogU2Nhbm5lZFJlY29yZDtcbiAgcG9saWN5OiBWdWxuQ29uc3VtcHRpb25Qb2xpY3k7XG4gIC8qKiBUaGUgcGlwZWxpbmUncyBhY3RpdmUgYWNjZXB0YW5jZSBvZiB0aGlzIHZlcnNpb24gLyBpbWFnZSwgd2hlbiB0aGUgY2FsbGVyIGhhcyBhIHBpcGVsaW5lLiAqL1xuICBhY2NlcHRhbmNlPzogVnVsbkFjY2VwdGFuY2UgfCBudWxsO1xuICAvKiogVGhlIG5ld2VzdCB1bmZsYWdnZWQgdmVyc2lvbiB0aGUgb3duZXIgY2FuIG1vdmUgdG8sIG5hbWVkIG9uIHRoZSBmaW5kaW5nIHdhcm5pbmdzLiAqL1xuICBzdWdnZXN0ZWRWZXJzaW9uPzogc3RyaW5nIHwgbnVsbDtcbiAgLyoqIFJ1biB0aGUgb3JnJ3MgY29tcGxpYW5jZSBydWxlcyAoYSBuZXR3b3JrIGNhbGwpLiBEZWZhdWx0IHRydWUuICovXG4gIGNvbXBsaWFuY2U/OiBib29sZWFuO1xuICBub3c/OiBEYXRlO1xufVxuXG4vKiogVGhlIGFzc2Vzc21lbnQ6IGV2ZXJ5IHdhcm5pbmcsIHRoZSBsb3VkZXN0IHNldmVyaXR5LCBhbmQgd2hpY2ggYWNjZXB0ZWQgZmluZGluZ3MgaXQgZG93bmdyYWRlZC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVmVyc2lvblZ1bG5Bc3Nlc3NtZW50IHtcbiAgLyoqIGBudWxsYCB3aGVuIHRoZXJlIGlzIG5vdGhpbmcgdG8gc2F5LiAqL1xuICBzZXZlcml0eTogVnVsblNldmVyaXR5IHwgbnVsbDtcbiAgd2FybmluZ3M6IFZ1bG5XYXJuaW5nW107XG4gIC8qKiBGaW5kaW5nIGtleXMgYW4gYWNjZXB0YW5jZSBkb3duZ3JhZGVkIChlbXB0eSA9IG5vIGFjY2VwdGFuY2UgYXBwbGllZCkuICovXG4gIGFjY2VwdGVkRmluZGluZ3M6IHN0cmluZ1tdO1xuICBmYWN0czogVmVyc2lvblNjYW5GYWN0cztcbn1cblxuLyoqIFRoZSBsb3VkZXN0IHNldmVyaXR5IG9mIGB3YXJuaW5nc2AsIG9yIG51bGwgZm9yIG5vbmUuICovXG5leHBvcnQgZnVuY3Rpb24gc2V2ZXJpdHlPZih3YXJuaW5nczogUmVhZG9ubHlBcnJheTx7IHNldmVyaXR5PzogVnVsblNldmVyaXR5IH0+KTogVnVsblNldmVyaXR5IHwgbnVsbCB7XG4gIHJldHVybiB3YXJuaW5ncy5yZWR1Y2U8VnVsblNldmVyaXR5IHwgbnVsbD4oKGFjYywgdykgPT4gKHcuc2V2ZXJpdHkgPyAoYWNjID8gbWF4U2V2ZXJpdHkoYWNjLCB3LnNldmVyaXR5KSA6IHcuc2V2ZXJpdHkpIDogYWNjKSwgbnVsbCk7XG59XG5cbi8qKlxuICogVGhlIGFzc2Vzc21lbnQgb2Ygb25lIHJlc29sdmVkIHZlcnNpb24gKHNlZSB0aGUgbW9kdWxlIGRvYykuIE5ldmVyIHRocm93cyBhbmRcbiAqIG5ldmVyIHJlZnVzZXM6IGEgY29tcGxpYW5jZSBvdXRhZ2UgYWRkcyBhbiBgaW5mb2AgYENPTVBMSUFOQ0VfVU5BVkFJTEFCTEVgLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXNzZXNzVmVyc2lvblZ1bG5zKGlucHV0OiBWZXJzaW9uVnVsbklucHV0KTogUHJvbWlzZTxWZXJzaW9uVnVsbkFzc2Vzc21lbnQ+IHtcbiAgY29uc3QgeyBvcmdJZCwgcmVjb3JkLCBwb2xpY3ksIGFjY2VwdGFuY2UgfSA9IGlucHV0O1xuICBjb25zdCBub3cgPSBpbnB1dC5ub3cgPz8gbmV3IERhdGUoKTtcbiAgY29uc3QgcmVmID0gYCR7cmVjb3JkLm5hbWV9QCR7cmVjb3JkLnZlcnNpb259YDtcbiAgY29uc3QgZmFjdHMgPSB2ZXJzaW9uU2NhbkZhY3RzKHJlY29yZCk7XG4gIGNvbnN0IHdhcm5pbmdzOiBWdWxuV2FybmluZ1tdID0gWy4uLnNjYW5XYXJuaW5ncyhyZWNvcmQsIG5vdyldO1xuICBjb25zdCBhY2NlcHRlZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBjb25zdCB3YXkgPSBpbnB1dC5zdWdnZXN0ZWRWZXJzaW9uID8gYCBNb3ZlIHRvICR7cmVjb3JkLm5hbWV9QCR7aW5wdXQuc3VnZ2VzdGVkVmVyc2lvbn0uYCA6ICcnO1xuICBjb25zdCBzdWdnZXN0ZWQgPSBpbnB1dC5zdWdnZXN0ZWRWZXJzaW9uID8geyBzdWdnZXN0ZWRWZXJzaW9uOiBpbnB1dC5zdWdnZXN0ZWRWZXJzaW9uIH0gOiB7fTtcbiAgY29uc3QgdW50aWwgPSB0b0RhdGUoYWNjZXB0YW5jZT8uYWNjZXB0ZWRVbnRpbCk/LnRvSVNPU3RyaW5nKCkgPz8gbnVsbDtcblxuICAvKiogUHVzaCBhIGZpbmRpbmcgd2FybmluZyDigJQgb3IsIHdoZW4gdGhlIHBpcGVsaW5lIGFjY2VwdGVkIGV4YWN0bHkgdGhvc2UgZmluZGluZ3MsIGl0cyBgaW5mb2AgZG93bmdyYWRlLiAqL1xuICBjb25zdCBmaW5kaW5nID0gKGNvZGU6ICdWVUxOX0tFVicgfCAnVlVMTl9GTEFHR0VEJyB8ICdWVUxOX0NSSVRJQ0FMX0ZJWEFCTEUnIHwgJ1ZVTE5fSElHSF9GSVhBQkxFJywgc2V2ZXJpdHk6IFZ1bG5TZXZlcml0eSwgbWVzc2FnZTogc3RyaW5nLCBmaW5kaW5nczogUGx1Z2luU2NhbkZpbmRpbmdbXSxcbiAgICBleHRyYTogeyBwbHVnaW4/OiBzdHJpbmc7IHZlcnNpb24/OiBzdHJpbmc7IGdhdGVkPzogbnVtYmVyOyBoaWdoPzogbnVtYmVyIH0gPSB7fSkgPT4ge1xuICAgIGlmIChjb3ZlcnMoYWNjZXB0YW5jZSwgZmluZGluZ3MsIGZhY3RzLnRydW5jYXRlZCkpIHtcbiAgICAgIGZvciAoY29uc3QgZiBvZiBmaW5kaW5ncykgYWNjZXB0ZWQuYWRkKHNjYW5GaW5kaW5nS2V5KGYpKTtcbiAgICAgIHdhcm5pbmdzLnB1c2goe1xuICAgICAgICBjb2RlOiAnVlVMTl9BQ0NFUFRFRCcsXG4gICAgICAgIHNldmVyaXR5OiAnaW5mbycsXG4gICAgICAgIG1lc3NhZ2U6IGAke21lc3NhZ2V9IEFjY2VwdGVkIGZvciB0aGlzIHBpcGVsaW5lJHt1bnRpbCA/IGAgdW50aWwgJHt1bnRpbH1gIDogJyd9LmAsXG4gICAgICAgIGZpbmRpbmdzOiBmaW5kaW5ncy5tYXAoc2NhbkZpbmRpbmdLZXkpLFxuICAgICAgICBhY2NlcHRlZFVudGlsOiB1bnRpbCxcbiAgICAgICAga2V2OiBhY2NlcHRhbmNlPy5rZXYgPz8gZmFsc2UsXG4gICAgICAgIGNvdmVyczogY29kZSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB3YXJuaW5ncy5wdXNoKHsgY29kZSwgc2V2ZXJpdHksIG1lc3NhZ2U6IGAke21lc3NhZ2V9JHt3YXl9YCwgZmluZGluZ3M6IGZpbmRpbmdzLnNsaWNlKDAsIDEwKSwgLi4uc3VnZ2VzdGVkLCAuLi5leHRyYSB9KTtcbiAgfTtcblxuICBjb25zdCBrZXZGaW5kaW5ncyA9IGZhY3RzLmZpbmRpbmdzLmZpbHRlcigoZikgPT4gZi5rZXYgPT09IHRydWUpO1xuICBpZiAoZmFjdHMua2V2ID4gMCkge1xuICAgIGZpbmRpbmcoJ1ZVTE5fS0VWJywgJ2NyaXRpY2FsJywgYCR7cmVmfSBoYXMgJHtmYWN0cy5rZXZ9IGZpbmRpbmcke2ZhY3RzLmtldiA9PT0gMSA/ICcnIDogJ3MnfSBvbiB0aGUgQ0lTQSBLbm93biBFeHBsb2l0ZWQgVnVsbmVyYWJpbGl0aWVzIGxpc3Qke2tldkZpbmRpbmdzLmxlbmd0aCA/IGA6ICR7ZGVzY3JpYmVGaW5kaW5ncyhrZXZGaW5kaW5ncyl9YCA6ICcnfS5gLCBrZXZGaW5kaW5ncyk7XG4gIH1cbiAgY29uc3QgZmxhZyA9IGZhY3RzLmZsYWc7XG4gIGlmIChmbGFnKSB7XG4gICAgY29uc3QgZ2F0ZWQgPSBmYWN0cy5maW5kaW5ncy5maWx0ZXIoKGYpID0+IGlzR2F0ZWRGaW5kaW5nKGYsIHBsdWdpblZ1bG5HYXRlS2V2KCksIGZsYWcuZmFpbE9uID8/ICdjcml0aWNhbCcpKTtcbiAgICBmaW5kaW5nKCdWVUxOX0ZMQUdHRUQnLCAnZXJyb3InLCBgJHtyZWZ9IGlzIGZsYWdnZWQ6IGEgcmVzY2FuIGZvdW5kICR7ZmxhZy5nYXRlZH0gZ2F0ZWQgJHtmYWlsT25MYWJlbChmbGFnLmZhaWxPbiA/PyAnY3JpdGljYWwnKX0gZmluZGluZyR7ZmxhZy5nYXRlZCA9PT0gMSA/ICcnIDogJ3MnfSBvdmVyIHRoZSBwbGF0Zm9ybSBsaW1pdCR7ZmxhZy5maW5kaW5ncy5sZW5ndGggPyBgIChmaXg6ICR7ZGVzY3JpYmVGaW5kaW5ncyhmbGFnLmZpbmRpbmdzKX0pYCA6ICcnfS5gLFxuICAgICAgZ2F0ZWQubGVuZ3RoID4gMCA/IGdhdGVkIDogZmxhZy5maW5kaW5ncywgeyBwbHVnaW46IHJlY29yZC5uYW1lLCB2ZXJzaW9uOiByZWNvcmQudmVyc2lvbiwgZ2F0ZWQ6IGZsYWcuZ2F0ZWQsIGhpZ2g6IGZsYWcuaGlnaCB9KTtcbiAgfSBlbHNlIGlmICgoZmFjdHMuY3JpdGljYWxGaXhhYmxlID8/IDApID4gMCkge1xuICAgIGNvbnN0IGNyaXRzID0gZmFjdHMuZmluZGluZ3MuZmlsdGVyKChmKSA9PiBmLnNldmVyaXR5ID09PSAnY3JpdGljYWwnICYmIGYuZml4ZWRJbi5sZW5ndGggPiAwKTtcbiAgICBmaW5kaW5nKCdWVUxOX0NSSVRJQ0FMX0ZJWEFCTEUnLCAnZXJyb3InLCBgJHtyZWZ9IGhhcyAke2ZhY3RzLmNyaXRpY2FsRml4YWJsZX0gZml4YWJsZSBDcml0aWNhbCBmaW5kaW5nJHtmYWN0cy5jcml0aWNhbEZpeGFibGUgPT09IDEgPyAnJyA6ICdzJ30ke2NyaXRzLmxlbmd0aCA/IGA6ICR7ZGVzY3JpYmVGaW5kaW5ncyhjcml0cyl9YCA6ICcnfS5gLCBjcml0cyk7XG4gIH1cbiAgY29uc3QgaGlnaEZpeGFibGUgPSBmYWN0cy5oaWdoRml4YWJsZSA/PyAwO1xuICBpZiAoaGlnaEZpeGFibGUgPiAwKSB7XG4gICAgY29uc3QgaGlnaHMgPSBmYWN0cy5maW5kaW5ncy5maWx0ZXIoKGYpID0+IGYuc2V2ZXJpdHkgPT09ICdoaWdoJyAmJiBmLmZpeGVkSW4ubGVuZ3RoID4gMCk7XG4gICAgY29uc3Qgb3ZlciA9IHBvbGljeS53YXJuRml4YWJsZUhpZ2ggIT09IG51bGwgJiYgaGlnaEZpeGFibGUgPiBwb2xpY3kud2FybkZpeGFibGVIaWdoO1xuICAgIGZpbmRpbmcoJ1ZVTE5fSElHSF9GSVhBQkxFJywgb3ZlciA/ICd3YXJuaW5nJyA6ICdpbmZvJyxcbiAgICAgIGAke3JlZn0gaGFzICR7aGlnaEZpeGFibGV9IGZpeGFibGUgSGlnaCBmaW5kaW5nJHtoaWdoRml4YWJsZSA9PT0gMSA/ICcnIDogJ3MnfSR7b3ZlciA/IGAsIG92ZXIgeW91ciBvcmdhbml6YXRpb24ncyB0aHJlc2hvbGQgb2YgJHtwb2xpY3kud2FybkZpeGFibGVIaWdofWAgOiAnJ30uYCwgaGlnaHMpO1xuICB9XG5cbiAgaWYgKGlucHV0LmNvbXBsaWFuY2UgIT09IGZhbHNlKSB3YXJuaW5ncy5wdXNoKC4uLmF3YWl0IGNvbXBsaWFuY2VWdWxuV2FybmluZ3Mob3JnSWQsIHJlY29yZCkpO1xuICByZXR1cm4geyBzZXZlcml0eTogc2V2ZXJpdHlPZih3YXJuaW5ncyksIHdhcm5pbmdzLCBhY2NlcHRlZEZpbmRpbmdzOiBbLi4uYWNjZXB0ZWRdLCBmYWN0cyB9O1xufVxuXG4vKiogVGhlIGNvbXBsaWFuY2UgYXR0cmlidXRlcyBhIHBsdWdpbidzIHZ1bG5lcmFiaWxpdHkgcnVsZXMgcmVhZC4gKi9cbmNvbnN0IFZVTE5fUlVMRV9GSUVMRFMgPSBuZXcgU2V0KFsnc2Nhbm5lZCcsICd2dWxuQ3JpdGljYWwnLCAndnVsbkhpZ2gnLCAndnVsbk1lZGl1bScsICd2dWxuTG93JywgJ3Z1bG5Dcml0aWNhbEZpeGFibGUnLCAndnVsbkhpZ2hGaXhhYmxlJ10pO1xuXG5jb25zdCBmaWVsZFJvb3QgPSAoZmllbGQ6IHN0cmluZyk6IHN0cmluZyA9PiBmaWVsZC5zcGxpdCgvWy5bXS8pWzBdID8/IGZpZWxkO1xuXG50eXBlIENvbXBsaWFuY2VDbGllbnQgPSBQaWNrPFJldHVyblR5cGU8dHlwZW9mIGNyZWF0ZUNvbXBsaWFuY2VDbGllbnQ+LCAnZHJ5UnVuUGx1Z2luJz47XG5cbmxldCBjb21wbGlhbmNlQ2xpZW50OiBDb21wbGlhbmNlQ2xpZW50IHwgbnVsbCA9IG51bGw7XG5cbi8qKiBUZXN0IGhvb2s6IHJlcGxhY2UgdGhlIGNvbXBsaWFuY2UgY2xpZW50IHRoZSBhc3Nlc3NtZW50J3MgY29tcGxpYW5jZSBsYXllciBjYWxscy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRWdWxuUG9saWN5Q29tcGxpYW5jZUNsaWVudEZvclRlc3RzKGNsaWVudDogQ29tcGxpYW5jZUNsaWVudCB8IG51bGwpOiB2b2lkIHtcbiAgY29tcGxpYW5jZUNsaWVudCA9IGNsaWVudDtcbn1cblxuLyoqXG4gKiBUaGUgb3JnJ3MgcGx1Z2luIGNvbXBsaWFuY2UgcnVsZXMgb24gdGhlIHZ1bG5lcmFiaWxpdHkgYXR0cmlidXRlcywgZXZhbHVhdGVkXG4gKiBhZ2FpbnN0IHRoZSBSRVNPTFZFRCB2ZXJzaW9uIOKAlCB0aGUgb3JnJ3Mgb3duIHJvdywgaXRzIHBhcmVudCdzLCBhIHN5c3RlbVxuICogcGx1Z2luIG9yIGFuIGluc3RhbGxlZCBtYXJrZXRwbGFjZSB2ZXJzaW9uIGFsaWtlLiBBIEJMT0NLLW1vZGUgcnVsZSB0aGF0IGZhaWxzXG4gKiBpcyBhbiBgZXJyb3JgLCBhIFdBUk4tbW9kZSBvbmUgYSBgd2FybmluZ2A7IG5laXRoZXIgcmVmdXNlcyBhbnl0aGluZyBoZXJlXG4gKiAodnVsbmVyYWJpbGl0eSBzdGF0ZSBuZXZlciBzdG9wcyBhIHBpcGVsaW5lKS5cbiAqXG4gKiBPbmx5IHRoZSB2dWxuIC8gc2Nhbm5lZCBydWxlcyBjb3VudCBoZXJlOiB0aGUgcGx1Z2luJ3Mgb3RoZXIgcnVsZXMgKHRhZ3MsXG4gKiBzZWNyZXRzLCBjb21tYW5kcyDigKYpIGRlc2NyaWJlIGhvdyBhIHBsdWdpbiBpcyBBVVRIT1JFRCwgd2hpY2ggaXMgaXRzIG93bmVyJ3NcbiAqIGNvbmNlcm4gYXQgdXBsb2FkLCBub3QgdGhlIGNvbnN1bWVyJ3MgYXQgcmVzb2x1dGlvbiDigJQgYW5kIGEgc3lzdGVtIHBsdWdpbiB3b3VsZFxuICogb3RoZXJ3aXNlIGZhaWwgZXZlcnkgdGVuYW50J3MgYXV0aG9yaW5nIHJ1bGVzLlxuICovXG5hc3luYyBmdW5jdGlvbiBjb21wbGlhbmNlVnVsbldhcm5pbmdzKG9yZ0lkOiBzdHJpbmcsIHJlY29yZDogU2Nhbm5lZFJlY29yZCk6IFByb21pc2U8VnVsbldhcm5pbmdbXT4ge1xuICBpZiAoaXNTeXN0ZW1PcmdJZChvcmdJZCkgfHwgIWhhc0ltYWdlKHJlY29yZCkpIHJldHVybiBbXTtcbiAgY29uc3QgZmFjdHMgPSBkZXJpdmVQbHVnaW5JbWFnZUNvbXBsaWFuY2UocmVjb3JkLCBudWxsKS5hdHRyaWJ1dGVzO1xuICBjb25zdCBhdHRyaWJ1dGVzOiBQbHVnaW5Db21wbGlhbmNlQXR0cmlidXRlcyA9IHsgbmFtZTogcmVjb3JkLm5hbWUsIHZlcnNpb246IHJlY29yZC52ZXJzaW9uLCAuLi5mYWN0cyB9O1xuICB0cnkge1xuICAgIGNvbXBsaWFuY2VDbGllbnQgPz89IGNyZWF0ZUNvbXBsaWFuY2VDbGllbnQoKTtcbiAgICBjb25zdCBhdXRoID0gZ2V0U2VydmljZUF1dGhIZWFkZXIoeyBzZXJ2aWNlTmFtZTogJ3BsdWdpbicsIG9yZ0lkLCByb2xlOiAnbWVtYmVyJyB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb21wbGlhbmNlQ2xpZW50LmRyeVJ1blBsdWdpbihvcmdJZCwgYXR0cmlidXRlcyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgYXV0aCk7XG4gICAgY29uc3QgcmVsZXZhbnQgPSAodjogQ29tcGxpYW5jZVZpb2xhdGlvbikgPT4gVlVMTl9SVUxFX0ZJRUxEUy5oYXMoZmllbGRSb290KHYuZmllbGQpKTtcbiAgICBjb25zdCBhcyA9IChtb2RlOiAnYmxvY2snIHwgJ3dhcm4nKSA9PiAodjogQ29tcGxpYW5jZVZpb2xhdGlvbik6IFZ1bG5XYXJuaW5nID0+ICh7XG4gICAgICBjb2RlOiAnQ09NUExJQU5DRV9WVUxOX1JVTEUnLFxuICAgICAgc2V2ZXJpdHk6IG1vZGUgPT09ICdibG9jaycgPyAnZXJyb3InIDogJ3dhcm5pbmcnLFxuICAgICAgbWVzc2FnZTogYCR7cmVjb3JkLm5hbWV9QCR7cmVjb3JkLnZlcnNpb259OiAke3YubWVzc2FnZX1gLFxuICAgICAgcnVsZUlkOiB2LnJ1bGVJZCxcbiAgICAgIHJ1bGVOYW1lOiB2LnJ1bGVOYW1lLFxuICAgICAgZmllbGQ6IHYuZmllbGQsXG4gICAgICBtb2RlLFxuICAgIH0pO1xuICAgIHJldHVybiBbLi4ucmVzdWx0LnZpb2xhdGlvbnMuZmlsdGVyKHJlbGV2YW50KS5tYXAoYXMoJ2Jsb2NrJykpLCAuLi5yZXN1bHQud2FybmluZ3MuZmlsdGVyKHJlbGV2YW50KS5tYXAoYXMoJ3dhcm4nKSldO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICByZXR1cm4gW3sgY29kZTogJ0NPTVBMSUFOQ0VfVU5BVkFJTEFCTEUnLCBzZXZlcml0eTogJ2luZm8nLCBtZXNzYWdlOiBgWW91ciBvcmdhbml6YXRpb24ncyBwbHVnaW4gdnVsbmVyYWJpbGl0eSBydWxlcyBjb3VsZCBub3QgYmUgY2hlY2tlZCBmb3IgJHtyZWNvcmQubmFtZX1AJHtyZWNvcmQudmVyc2lvbn0gKCR7ZXJyb3JNZXNzYWdlKGVycil9KS5gIH1dO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,63 @@
1
+ /**
2
+ * The AI provider + model catalog, as DATA ONLY.
3
+ *
4
+ * Dependency-free and env-free so the browser imports it directly
5
+ * (`@pipeline-builder/api-core/ai-catalog`) — the frontend's model picker and the
6
+ * backend's provider registry read the one list, instead of the frontend keeping a
7
+ * hand-maintained mirror that drifted every time a model shipped. Anything that
8
+ * reads the environment (the OpenAI-compatible endpoint, provider key env vars)
9
+ * stays in `constants/ai-providers.ts`, which re-exports this.
10
+ */
11
+ /** Metadata for a single AI model. */
12
+ export interface AIModelInfo {
13
+ /** Model identifier used in API calls (e.g. "claude-sonnet-5-5"). */
14
+ id: string;
15
+ /** Human-readable display name (e.g. "Claude Sonnet 5.5"). */
16
+ name: string;
17
+ }
18
+ /** Metadata for an AI provider with its available models. */
19
+ export interface AIProviderInfo {
20
+ /** Provider identifier (e.g. "anthropic", "openai", "google"). */
21
+ id: string;
22
+ /** Human-readable display name (e.g. "Anthropic"). */
23
+ name: string;
24
+ /** Models available for this provider. */
25
+ models: AIModelInfo[];
26
+ /**
27
+ * The provider authenticates with the DEPLOYMENT's own credentials (an IAM
28
+ * role), not an API key — so there is no key for an organization to bring.
29
+ * Absent = key-based.
30
+ *
31
+ * This is the ONE place that fact is recorded. Everything that asks "can an
32
+ * org hold its own key for this provider?" reads {@link AI_KEY_PROVIDER_IDS}
33
+ * or {@link isKeylessProviderId}: the settings picker that offers the slot,
34
+ * the platform that stores and re-encrypts it, the internal route that serves
35
+ * it, and the model selection that spends it. They disagreed once — the
36
+ * picker offered Amazon Bedrock, the platform encrypted the key and reported
37
+ * it `configured`, and no AI call could ever use it.
38
+ */
39
+ keyless?: true;
40
+ }
41
+ /**
42
+ * Standard AI provider catalog — single source of truth for all supported
43
+ * providers and their models. The FIRST model of a provider is its default
44
+ * (what a provider-only request resolves to), so order matters.
45
+ */
46
+ export declare const AI_PROVIDER_CATALOG: Record<string, AIProviderInfo>;
47
+ /**
48
+ * Provider ids an organization CAN hold its own API key for — the catalog minus
49
+ * the keyless providers ({@link AIProviderInfo.keyless}).
50
+ *
51
+ * The single list behind every org-key surface: the settings picker offers these
52
+ * slots, the platform stores and re-encrypts these fields, `GET
53
+ * /internal/ai/keys/:orgId/:provider` serves only these, and org-aware model
54
+ * selection spends only these. A provider absent here has no org key by
55
+ * construction, so no caller needs its own exclusion.
56
+ */
57
+ export declare const AI_KEY_PROVIDER_IDS: readonly string[];
58
+ /** True when the provider authenticates with the deployment's own credentials rather than a key. */
59
+ export declare function isKeylessProviderId(providerId: string): boolean;
60
+ /** Display names by provider id — the catalog's names, for UI surfaces that list providers. */
61
+ export declare const AI_PROVIDER_NAMES: Record<string, string>;
62
+ /** Model lists by provider id — the catalog's models, for UI surfaces that need only those. */
63
+ export declare const AI_PROVIDER_MODELS: Record<string, AIModelInfo[]>;
@@ -0,0 +1,82 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * Standard AI provider catalog — single source of truth for all supported
5
+ * providers and their models. The FIRST model of a provider is its default
6
+ * (what a provider-only request resolves to), so order matters.
7
+ */
8
+ export const AI_PROVIDER_CATALOG = {
9
+ 'anthropic': {
10
+ id: 'anthropic',
11
+ name: 'Anthropic',
12
+ models: [
13
+ { id: 'claude-sonnet-5-5', name: 'Claude Sonnet 5.5' },
14
+ { id: 'claude-opus-5-5', name: 'Claude Opus 5.5' },
15
+ { id: 'claude-fable-5-1', name: 'Claude Fable 5.1' },
16
+ { id: 'claude-haiku-4-5-20251001', name: 'Claude Haiku 4.5' },
17
+ ],
18
+ },
19
+ 'openai': {
20
+ id: 'openai',
21
+ name: 'OpenAI',
22
+ models: [
23
+ { id: 'gpt-5.6-sol', name: 'GPT-5.6 Sol' },
24
+ { id: 'gpt-5.6-terra', name: 'GPT-5.6 Terra' },
25
+ { id: 'gpt-5.6-luna', name: 'GPT-5.6 Luna' },
26
+ ],
27
+ },
28
+ 'google': {
29
+ id: 'google',
30
+ name: 'Google',
31
+ models: [
32
+ { id: 'gemini-3.7-flash', name: 'Gemini 3.7 Flash' },
33
+ { id: 'gemini-3.1-pro-preview', name: 'Gemini 3.1 Pro' },
34
+ ],
35
+ },
36
+ 'xai': {
37
+ id: 'xai',
38
+ name: 'xAI (Grok)',
39
+ models: [
40
+ { id: 'grok-4.6', name: 'Grok 4.6' },
41
+ { id: 'grok-4.5', name: 'Grok 4.5' },
42
+ { id: 'grok-4.3', name: 'Grok 4.3' },
43
+ ],
44
+ },
45
+ 'amazon-bedrock': {
46
+ id: 'amazon-bedrock',
47
+ name: 'Amazon Bedrock',
48
+ // Authenticated by the deployment's IAM role, never an org-supplied key.
49
+ keyless: true,
50
+ // Bedrock ids are region-scoped cross-region inference profiles; the `us.`
51
+ // prefix targets US regions — swap the prefix (eu./apac./…) to match your
52
+ // deploy region, and confirm availability in the Bedrock console.
53
+ models: [
54
+ { id: 'us.anthropic.claude-sonnet-5-5', name: 'Claude Sonnet 5.5' },
55
+ { id: 'us.anthropic.claude-opus-5-5', name: 'Claude Opus 5.5' },
56
+ { id: 'us.anthropic.claude-haiku-4-5-20251001-v1:0', name: 'Claude Haiku 4.5' },
57
+ { id: 'us.amazon.nova-pro-v1:0', name: 'Amazon Nova Pro' },
58
+ ],
59
+ },
60
+ };
61
+ /**
62
+ * Provider ids an organization CAN hold its own API key for — the catalog minus
63
+ * the keyless providers ({@link AIProviderInfo.keyless}).
64
+ *
65
+ * The single list behind every org-key surface: the settings picker offers these
66
+ * slots, the platform stores and re-encrypts these fields, `GET
67
+ * /internal/ai/keys/:orgId/:provider` serves only these, and org-aware model
68
+ * selection spends only these. A provider absent here has no org key by
69
+ * construction, so no caller needs its own exclusion.
70
+ */
71
+ export const AI_KEY_PROVIDER_IDS = Object.values(AI_PROVIDER_CATALOG)
72
+ .filter((p) => !p.keyless)
73
+ .map((p) => p.id);
74
+ /** True when the provider authenticates with the deployment's own credentials rather than a key. */
75
+ export function isKeylessProviderId(providerId) {
76
+ return AI_PROVIDER_CATALOG[providerId]?.keyless === true;
77
+ }
78
+ /** Display names by provider id — the catalog's names, for UI surfaces that list providers. */
79
+ export const AI_PROVIDER_NAMES = Object.fromEntries(Object.values(AI_PROVIDER_CATALOG).map((p) => [p.id, p.name]));
80
+ /** Model lists by provider id — the catalog's models, for UI surfaces that need only those. */
81
+ export const AI_PROVIDER_MODELS = Object.fromEntries(Object.values(AI_PROVIDER_CATALOG).map((p) => [p.id, p.models]));
82
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWktY2F0YWxvZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eXBlcy9haS1jYXRhbG9nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUE2Q3RDOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBbUM7SUFDakUsV0FBVyxFQUFFO1FBQ1gsRUFBRSxFQUFFLFdBQVc7UUFDZixJQUFJLEVBQUUsV0FBVztRQUNqQixNQUFNLEVBQUU7WUFDTixFQUFFLEVBQUUsRUFBRSxtQkFBbUIsRUFBRSxJQUFJLEVBQUUsbUJBQW1CLEVBQUU7WUFDdEQsRUFBRSxFQUFFLEVBQUUsaUJBQWlCLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFO1lBQ2xELEVBQUUsRUFBRSxFQUFFLGtCQUFrQixFQUFFLElBQUksRUFBRSxrQkFBa0IsRUFBRTtZQUNwRCxFQUFFLEVBQUUsRUFBRSwyQkFBMkIsRUFBRSxJQUFJLEVBQUUsa0JBQWtCLEVBQUU7U0FDOUQ7S0FDRjtJQUNELFFBQVEsRUFBRTtRQUNSLEVBQUUsRUFBRSxRQUFRO1FBQ1osSUFBSSxFQUFFLFFBQVE7UUFDZCxNQUFNLEVBQUU7WUFDTixFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRTtZQUMxQyxFQUFFLEVBQUUsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLGVBQWUsRUFBRTtZQUM5QyxFQUFFLEVBQUUsRUFBRSxjQUFjLEVBQUUsSUFBSSxFQUFFLGNBQWMsRUFBRTtTQUM3QztLQUNGO0lBQ0QsUUFBUSxFQUFFO1FBQ1IsRUFBRSxFQUFFLFFBQVE7UUFDWixJQUFJLEVBQUUsUUFBUTtRQUNkLE1BQU0sRUFBRTtZQUNOLEVBQUUsRUFBRSxFQUFFLGtCQUFrQixFQUFFLElBQUksRUFBRSxrQkFBa0IsRUFBRTtZQUNwRCxFQUFFLEVBQUUsRUFBRSx3QkFBd0IsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUU7U0FDekQ7S0FDRjtJQUNELEtBQUssRUFBRTtRQUNMLEVBQUUsRUFBRSxLQUFLO1FBQ1QsSUFBSSxFQUFFLFlBQVk7UUFDbEIsTUFBTSxFQUFFO1lBQ04sRUFBRSxFQUFFLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDcEMsRUFBRSxFQUFFLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDcEMsRUFBRSxFQUFFLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7U0FDckM7S0FDRjtJQUNELGdCQUFnQixFQUFFO1FBQ2hCLEVBQUUsRUFBRSxnQkFBZ0I7UUFDcEIsSUFBSSxFQUFFLGdCQUFnQjtRQUN0Qix5RUFBeUU7UUFDekUsT0FBTyxFQUFFLElBQUk7UUFDYiwyRUFBMkU7UUFDM0UsMEVBQTBFO1FBQzFFLGtFQUFrRTtRQUNsRSxNQUFNLEVBQUU7WUFDTixFQUFFLEVBQUUsRUFBRSxnQ0FBZ0MsRUFBRSxJQUFJLEVBQUUsbUJBQW1CLEVBQUU7WUFDbkUsRUFBRSxFQUFFLEVBQUUsOEJBQThCLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFO1lBQy9ELEVBQUUsRUFBRSxFQUFFLDZDQUE2QyxFQUFFLElBQUksRUFBRSxrQkFBa0IsRUFBRTtZQUMvRSxFQUFFLEVBQUUsRUFBRSx5QkFBeUIsRUFBRSxJQUFJLEVBQUUsaUJBQWlCLEVBQUU7U0FDM0Q7S0FDRjtDQUNGLENBQUM7QUFFRjs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBc0IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQztLQUNyRixNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztLQUN6QixHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUVwQixvR0FBb0c7QUFDcEcsTUFBTSxVQUFVLG1CQUFtQixDQUFDLFVBQWtCO0lBQ3BELE9BQU8sbUJBQW1CLENBQUMsVUFBVSxDQUFDLEVBQUUsT0FBTyxLQUFLLElBQUksQ0FBQztBQUMzRCxDQUFDO0FBRUQsK0ZBQStGO0FBQy9GLE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUEyQixNQUFNLENBQUMsV0FBVyxDQUN6RSxNQUFNLENBQUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQzlELENBQUM7QUFFRiwrRkFBK0Y7QUFDL0YsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQWtDLE1BQU0sQ0FBQyxXQUFXLENBQ2pGLE1BQU0sQ0FBQyxNQUFNLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FDaEUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIFRoZSBBSSBwcm92aWRlciArIG1vZGVsIGNhdGFsb2csIGFzIERBVEEgT05MWS5cbiAqXG4gKiBEZXBlbmRlbmN5LWZyZWUgYW5kIGVudi1mcmVlIHNvIHRoZSBicm93c2VyIGltcG9ydHMgaXQgZGlyZWN0bHlcbiAqIChgQHBpcGVsaW5lLWJ1aWxkZXIvYXBpLWNvcmUvYWktY2F0YWxvZ2ApIOKAlCB0aGUgZnJvbnRlbmQncyBtb2RlbCBwaWNrZXIgYW5kIHRoZVxuICogYmFja2VuZCdzIHByb3ZpZGVyIHJlZ2lzdHJ5IHJlYWQgdGhlIG9uZSBsaXN0LCBpbnN0ZWFkIG9mIHRoZSBmcm9udGVuZCBrZWVwaW5nIGFcbiAqIGhhbmQtbWFpbnRhaW5lZCBtaXJyb3IgdGhhdCBkcmlmdGVkIGV2ZXJ5IHRpbWUgYSBtb2RlbCBzaGlwcGVkLiBBbnl0aGluZyB0aGF0XG4gKiByZWFkcyB0aGUgZW52aXJvbm1lbnQgKHRoZSBPcGVuQUktY29tcGF0aWJsZSBlbmRwb2ludCwgcHJvdmlkZXIga2V5IGVudiB2YXJzKVxuICogc3RheXMgaW4gYGNvbnN0YW50cy9haS1wcm92aWRlcnMudHNgLCB3aGljaCByZS1leHBvcnRzIHRoaXMuXG4gKi9cblxuLyoqIE1ldGFkYXRhIGZvciBhIHNpbmdsZSBBSSBtb2RlbC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQUlNb2RlbEluZm8ge1xuICAvKiogTW9kZWwgaWRlbnRpZmllciB1c2VkIGluIEFQSSBjYWxscyAoZS5nLiBcImNsYXVkZS1zb25uZXQtNS01XCIpLiAqL1xuICBpZDogc3RyaW5nO1xuICAvKiogSHVtYW4tcmVhZGFibGUgZGlzcGxheSBuYW1lIChlLmcuIFwiQ2xhdWRlIFNvbm5ldCA1LjVcIikuICovXG4gIG5hbWU6IHN0cmluZztcbn1cblxuLyoqIE1ldGFkYXRhIGZvciBhbiBBSSBwcm92aWRlciB3aXRoIGl0cyBhdmFpbGFibGUgbW9kZWxzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBBSVByb3ZpZGVySW5mbyB7XG4gIC8qKiBQcm92aWRlciBpZGVudGlmaWVyIChlLmcuIFwiYW50aHJvcGljXCIsIFwib3BlbmFpXCIsIFwiZ29vZ2xlXCIpLiAqL1xuICBpZDogc3RyaW5nO1xuICAvKiogSHVtYW4tcmVhZGFibGUgZGlzcGxheSBuYW1lIChlLmcuIFwiQW50aHJvcGljXCIpLiAqL1xuICBuYW1lOiBzdHJpbmc7XG4gIC8qKiBNb2RlbHMgYXZhaWxhYmxlIGZvciB0aGlzIHByb3ZpZGVyLiAqL1xuICBtb2RlbHM6IEFJTW9kZWxJbmZvW107XG4gIC8qKlxuICAgKiBUaGUgcHJvdmlkZXIgYXV0aGVudGljYXRlcyB3aXRoIHRoZSBERVBMT1lNRU5UJ3Mgb3duIGNyZWRlbnRpYWxzIChhbiBJQU1cbiAgICogcm9sZSksIG5vdCBhbiBBUEkga2V5IOKAlCBzbyB0aGVyZSBpcyBubyBrZXkgZm9yIGFuIG9yZ2FuaXphdGlvbiB0byBicmluZy5cbiAgICogQWJzZW50ID0ga2V5LWJhc2VkLlxuICAgKlxuICAgKiBUaGlzIGlzIHRoZSBPTkUgcGxhY2UgdGhhdCBmYWN0IGlzIHJlY29yZGVkLiBFdmVyeXRoaW5nIHRoYXQgYXNrcyBcImNhbiBhblxuICAgKiBvcmcgaG9sZCBpdHMgb3duIGtleSBmb3IgdGhpcyBwcm92aWRlcj9cIiByZWFkcyB7QGxpbmsgQUlfS0VZX1BST1ZJREVSX0lEU31cbiAgICogb3Ige0BsaW5rIGlzS2V5bGVzc1Byb3ZpZGVySWR9OiB0aGUgc2V0dGluZ3MgcGlja2VyIHRoYXQgb2ZmZXJzIHRoZSBzbG90LFxuICAgKiB0aGUgcGxhdGZvcm0gdGhhdCBzdG9yZXMgYW5kIHJlLWVuY3J5cHRzIGl0LCB0aGUgaW50ZXJuYWwgcm91dGUgdGhhdCBzZXJ2ZXNcbiAgICogaXQsIGFuZCB0aGUgbW9kZWwgc2VsZWN0aW9uIHRoYXQgc3BlbmRzIGl0LiBUaGV5IGRpc2FncmVlZCBvbmNlIOKAlCB0aGVcbiAgICogcGlja2VyIG9mZmVyZWQgQW1hem9uIEJlZHJvY2ssIHRoZSBwbGF0Zm9ybSBlbmNyeXB0ZWQgdGhlIGtleSBhbmQgcmVwb3J0ZWRcbiAgICogaXQgYGNvbmZpZ3VyZWRgLCBhbmQgbm8gQUkgY2FsbCBjb3VsZCBldmVyIHVzZSBpdC5cbiAgICovXG4gIGtleWxlc3M/OiB0cnVlO1xufVxuXG4vKipcbiAqIFN0YW5kYXJkIEFJIHByb3ZpZGVyIGNhdGFsb2cg4oCUIHNpbmdsZSBzb3VyY2Ugb2YgdHJ1dGggZm9yIGFsbCBzdXBwb3J0ZWRcbiAqIHByb3ZpZGVycyBhbmQgdGhlaXIgbW9kZWxzLiBUaGUgRklSU1QgbW9kZWwgb2YgYSBwcm92aWRlciBpcyBpdHMgZGVmYXVsdFxuICogKHdoYXQgYSBwcm92aWRlci1vbmx5IHJlcXVlc3QgcmVzb2x2ZXMgdG8pLCBzbyBvcmRlciBtYXR0ZXJzLlxuICovXG5leHBvcnQgY29uc3QgQUlfUFJPVklERVJfQ0FUQUxPRzogUmVjb3JkPHN0cmluZywgQUlQcm92aWRlckluZm8+ID0ge1xuICAnYW50aHJvcGljJzoge1xuICAgIGlkOiAnYW50aHJvcGljJyxcbiAgICBuYW1lOiAnQW50aHJvcGljJyxcbiAgICBtb2RlbHM6IFtcbiAgICAgIHsgaWQ6ICdjbGF1ZGUtc29ubmV0LTUtNScsIG5hbWU6ICdDbGF1ZGUgU29ubmV0IDUuNScgfSxcbiAgICAgIHsgaWQ6ICdjbGF1ZGUtb3B1cy01LTUnLCBuYW1lOiAnQ2xhdWRlIE9wdXMgNS41JyB9LFxuICAgICAgeyBpZDogJ2NsYXVkZS1mYWJsZS01LTEnLCBuYW1lOiAnQ2xhdWRlIEZhYmxlIDUuMScgfSxcbiAgICAgIHsgaWQ6ICdjbGF1ZGUtaGFpa3UtNC01LTIwMjUxMDAxJywgbmFtZTogJ0NsYXVkZSBIYWlrdSA0LjUnIH0sXG4gICAgXSxcbiAgfSxcbiAgJ29wZW5haSc6IHtcbiAgICBpZDogJ29wZW5haScsXG4gICAgbmFtZTogJ09wZW5BSScsXG4gICAgbW9kZWxzOiBbXG4gICAgICB7IGlkOiAnZ3B0LTUuNi1zb2wnLCBuYW1lOiAnR1BULTUuNiBTb2wnIH0sXG4gICAgICB7IGlkOiAnZ3B0LTUuNi10ZXJyYScsIG5hbWU6ICdHUFQtNS42IFRlcnJhJyB9LFxuICAgICAgeyBpZDogJ2dwdC01LjYtbHVuYScsIG5hbWU6ICdHUFQtNS42IEx1bmEnIH0sXG4gICAgXSxcbiAgfSxcbiAgJ2dvb2dsZSc6IHtcbiAgICBpZDogJ2dvb2dsZScsXG4gICAgbmFtZTogJ0dvb2dsZScsXG4gICAgbW9kZWxzOiBbXG4gICAgICB7IGlkOiAnZ2VtaW5pLTMuNy1mbGFzaCcsIG5hbWU6ICdHZW1pbmkgMy43IEZsYXNoJyB9LFxuICAgICAgeyBpZDogJ2dlbWluaS0zLjEtcHJvLXByZXZpZXcnLCBuYW1lOiAnR2VtaW5pIDMuMSBQcm8nIH0sXG4gICAgXSxcbiAgfSxcbiAgJ3hhaSc6IHtcbiAgICBpZDogJ3hhaScsXG4gICAgbmFtZTogJ3hBSSAoR3JvayknLFxuICAgIG1vZGVsczogW1xuICAgICAgeyBpZDogJ2dyb2stNC42JywgbmFtZTogJ0dyb2sgNC42JyB9LFxuICAgICAgeyBpZDogJ2dyb2stNC41JywgbmFtZTogJ0dyb2sgNC41JyB9LFxuICAgICAgeyBpZDogJ2dyb2stNC4zJywgbmFtZTogJ0dyb2sgNC4zJyB9LFxuICAgIF0sXG4gIH0sXG4gICdhbWF6b24tYmVkcm9jayc6IHtcbiAgICBpZDogJ2FtYXpvbi1iZWRyb2NrJyxcbiAgICBuYW1lOiAnQW1hem9uIEJlZHJvY2snLFxuICAgIC8vIEF1dGhlbnRpY2F0ZWQgYnkgdGhlIGRlcGxveW1lbnQncyBJQU0gcm9sZSwgbmV2ZXIgYW4gb3JnLXN1cHBsaWVkIGtleS5cbiAgICBrZXlsZXNzOiB0cnVlLFxuICAgIC8vIEJlZHJvY2sgaWRzIGFyZSByZWdpb24tc2NvcGVkIGNyb3NzLXJlZ2lvbiBpbmZlcmVuY2UgcHJvZmlsZXM7IHRoZSBgdXMuYFxuICAgIC8vIHByZWZpeCB0YXJnZXRzIFVTIHJlZ2lvbnMg4oCUIHN3YXAgdGhlIHByZWZpeCAoZXUuL2FwYWMuL+KApikgdG8gbWF0Y2ggeW91clxuICAgIC8vIGRlcGxveSByZWdpb24sIGFuZCBjb25maXJtIGF2YWlsYWJpbGl0eSBpbiB0aGUgQmVkcm9jayBjb25zb2xlLlxuICAgIG1vZGVsczogW1xuICAgICAgeyBpZDogJ3VzLmFudGhyb3BpYy5jbGF1ZGUtc29ubmV0LTUtNScsIG5hbWU6ICdDbGF1ZGUgU29ubmV0IDUuNScgfSxcbiAgICAgIHsgaWQ6ICd1cy5hbnRocm9waWMuY2xhdWRlLW9wdXMtNS01JywgbmFtZTogJ0NsYXVkZSBPcHVzIDUuNScgfSxcbiAgICAgIHsgaWQ6ICd1cy5hbnRocm9waWMuY2xhdWRlLWhhaWt1LTQtNS0yMDI1MTAwMS12MTowJywgbmFtZTogJ0NsYXVkZSBIYWlrdSA0LjUnIH0sXG4gICAgICB7IGlkOiAndXMuYW1hem9uLm5vdmEtcHJvLXYxOjAnLCBuYW1lOiAnQW1hem9uIE5vdmEgUHJvJyB9LFxuICAgIF0sXG4gIH0sXG59O1xuXG4vKipcbiAqIFByb3ZpZGVyIGlkcyBhbiBvcmdhbml6YXRpb24gQ0FOIGhvbGQgaXRzIG93biBBUEkga2V5IGZvciDigJQgdGhlIGNhdGFsb2cgbWludXNcbiAqIHRoZSBrZXlsZXNzIHByb3ZpZGVycyAoe0BsaW5rIEFJUHJvdmlkZXJJbmZvLmtleWxlc3N9KS5cbiAqXG4gKiBUaGUgc2luZ2xlIGxpc3QgYmVoaW5kIGV2ZXJ5IG9yZy1rZXkgc3VyZmFjZTogdGhlIHNldHRpbmdzIHBpY2tlciBvZmZlcnMgdGhlc2VcbiAqIHNsb3RzLCB0aGUgcGxhdGZvcm0gc3RvcmVzIGFuZCByZS1lbmNyeXB0cyB0aGVzZSBmaWVsZHMsIGBHRVRcbiAqIC9pbnRlcm5hbC9haS9rZXlzLzpvcmdJZC86cHJvdmlkZXJgIHNlcnZlcyBvbmx5IHRoZXNlLCBhbmQgb3JnLWF3YXJlIG1vZGVsXG4gKiBzZWxlY3Rpb24gc3BlbmRzIG9ubHkgdGhlc2UuIEEgcHJvdmlkZXIgYWJzZW50IGhlcmUgaGFzIG5vIG9yZyBrZXkgYnlcbiAqIGNvbnN0cnVjdGlvbiwgc28gbm8gY2FsbGVyIG5lZWRzIGl0cyBvd24gZXhjbHVzaW9uLlxuICovXG5leHBvcnQgY29uc3QgQUlfS0VZX1BST1ZJREVSX0lEUzogcmVhZG9ubHkgc3RyaW5nW10gPSBPYmplY3QudmFsdWVzKEFJX1BST1ZJREVSX0NBVEFMT0cpXG4gIC5maWx0ZXIoKHApID0+ICFwLmtleWxlc3MpXG4gIC5tYXAoKHApID0+IHAuaWQpO1xuXG4vKiogVHJ1ZSB3aGVuIHRoZSBwcm92aWRlciBhdXRoZW50aWNhdGVzIHdpdGggdGhlIGRlcGxveW1lbnQncyBvd24gY3JlZGVudGlhbHMgcmF0aGVyIHRoYW4gYSBrZXkuICovXG5leHBvcnQgZnVuY3Rpb24gaXNLZXlsZXNzUHJvdmlkZXJJZChwcm92aWRlcklkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIEFJX1BST1ZJREVSX0NBVEFMT0dbcHJvdmlkZXJJZF0/LmtleWxlc3MgPT09IHRydWU7XG59XG5cbi8qKiBEaXNwbGF5IG5hbWVzIGJ5IHByb3ZpZGVyIGlkIOKAlCB0aGUgY2F0YWxvZydzIG5hbWVzLCBmb3IgVUkgc3VyZmFjZXMgdGhhdCBsaXN0IHByb3ZpZGVycy4gKi9cbmV4cG9ydCBjb25zdCBBSV9QUk9WSURFUl9OQU1FUzogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IE9iamVjdC5mcm9tRW50cmllcyhcbiAgT2JqZWN0LnZhbHVlcyhBSV9QUk9WSURFUl9DQVRBTE9HKS5tYXAoKHApID0+IFtwLmlkLCBwLm5hbWVdKSxcbik7XG5cbi8qKiBNb2RlbCBsaXN0cyBieSBwcm92aWRlciBpZCDigJQgdGhlIGNhdGFsb2cncyBtb2RlbHMsIGZvciBVSSBzdXJmYWNlcyB0aGF0IG5lZWQgb25seSB0aG9zZS4gKi9cbmV4cG9ydCBjb25zdCBBSV9QUk9WSURFUl9NT0RFTFM6IFJlY29yZDxzdHJpbmcsIEFJTW9kZWxJbmZvW10+ID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICBPYmplY3QudmFsdWVzKEFJX1BST1ZJREVSX0NBVEFMT0cpLm1hcCgocCkgPT4gW3AuaWQsIHAubW9kZWxzXSksXG4pO1xuIl19