@pipeline-builder/pipeline-data 4.3.10 → 4.3.12

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,445 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * THE resolver for the managed toolchain (docs/plans/bootstrap-image-versioning.md
5
+ * §2). `pipeline-bootstrap@V` and `cdk-synth@V` are two SYSTEM-ORG plugin rows
6
+ * that share one release version `V`; every path that can resolve a managed
7
+ * name answers from here and nothing else may:
8
+ *
9
+ * release pin given → that release, if it EXISTS (yanked / deprecated /
10
+ * never-promoted still resolve, with a warning; deleted ⇒ 404)
11
+ * else org default → the NEAREST `org_toolchain_default` walking caller → … → root
12
+ * else canary → the NEAREST `toolchain_rollout` membership, served only
13
+ * while it passes the scan + metadata guards
14
+ * else platform → `toolchain_platform_default`
15
+ * else → 409 TOOLCHAIN_NO_DEFAULT (never "highest version", D11)
16
+ *
17
+ * - Reads are ELEVATED (`runWithTenantContext({ isSuperAdmin: true })`, as
18
+ * `versionReferences` does) and touch SYSTEM-ORG plugin rows only: the owner
19
+ * rank of `pluginResolutionOrderBy` is never consulted, so a same-named row in
20
+ * any other org is never a candidate.
21
+ * - Eligibility (D15) is a SET-time rule ({@link isEligibleRelease}); at resolve
22
+ * time a pin / org default only has to exist.
23
+ * - Both halves always come from ONE release (`TOOLCHAIN_PAIR_MISMATCH` otherwise).
24
+ * - The answer carries `resolvedVia` and nothing about any other org: no
25
+ * rollout membership, no ancestor's settings.
26
+ */
27
+ import { AppError, compareSemver, createLogger, envInt, ErrorCode, fetchParentOrgId, getStatusForErrorCode, isSystemOrgId, MANAGED_TOOLCHAIN_PLUGINS, MAX_ORG_DEPTH, SYSTEM_ORG_ID, TOOLCHAIN_RELEASE_VERSION_PATTERN, toolchainFromMetadata, toOrgIdString, } from '@pipeline-builder/api-core';
28
+ import { and, eq, inArray, isNull, sql } from 'drizzle-orm';
29
+ import { schema } from '../database/drizzle-schema.js';
30
+ import { runWithTenantContext, withTenantTx } from '../database/tenancy.js';
31
+ const logger = createLogger('managed-toolchain');
32
+ /** A resolver refusal: `code` is TOOLCHAIN_NO_DEFAULT, NOT_FOUND, TOOLCHAIN_PAIR_MISMATCH or VALIDATION_ERROR. */
33
+ export class ManagedToolchainError extends AppError {
34
+ constructor(code, message, details) {
35
+ super(getStatusForErrorCode(code), code, message, details);
36
+ this.name = 'ManagedToolchainError';
37
+ }
38
+ }
39
+ /** Whether `version` is a release version (`MAJOR.MINOR.PATCH`). */
40
+ export function isToolchainReleaseVersion(version) {
41
+ return typeof version === 'string' && TOOLCHAIN_RELEASE_VERSION_PATTERN.test(version);
42
+ }
43
+ const BOOTSTRAP = 'pipeline-bootstrap';
44
+ const SYNTH = 'cdk-synth';
45
+ /** The release row and both SYSTEM-ORG halves of `releaseVersion` (deleted rows excluded). */
46
+ export async function loadReleaseHalves(db, releaseVersion) {
47
+ const [releases, rows] = await Promise.all([
48
+ db.select().from(schema.toolchainRelease).where(eq(schema.toolchainRelease.releaseVersion, releaseVersion)),
49
+ db.select().from(schema.plugin).where(and(sql `lower(${schema.plugin.orgId}) = ${SYSTEM_ORG_ID}`, inArray(schema.plugin.name, [...MANAGED_TOOLCHAIN_PLUGINS]), eq(schema.plugin.version, releaseVersion), isNull(schema.plugin.deletedAt))),
50
+ ]);
51
+ const plugins = rows;
52
+ return {
53
+ releaseVersion,
54
+ release: releases[0] ?? null,
55
+ bootstrap: plugins.find((p) => p.name === BOOTSTRAP) ?? null,
56
+ synth: plugins.find((p) => p.name === SYNTH) ?? null,
57
+ };
58
+ }
59
+ /** The NEAREST row of `table` (keyed by `org_id`) on `chain` (own org first). */
60
+ async function nearestOnChain(db, table, chain) {
61
+ if (chain.length === 0)
62
+ return null;
63
+ const rows = await db.select({ orgId: table.orgId, releaseVersion: table.releaseVersion })
64
+ .from(table)
65
+ .where(inArray(sql `lower(${table.orgId})`, [...chain]));
66
+ let best = null;
67
+ for (const r of rows) {
68
+ const depth = chain.indexOf(r.orgId.toLowerCase());
69
+ if (depth >= 0 && (!best || depth < best.depth))
70
+ best = { depth, releaseVersion: r.releaseVersion };
71
+ }
72
+ return best;
73
+ }
74
+ async function currentPlatformDefault(db) {
75
+ const rows = await db.select({ releaseVersion: schema.toolchainPlatformDefault.releaseVersion })
76
+ .from(schema.toolchainPlatformDefault).limit(1);
77
+ return rows[0]?.releaseVersion ?? null;
78
+ }
79
+ /** Whether `releaseVersion` has ever been (or is) the platform default. */
80
+ async function wasPlatformDefault(db, releaseVersion) {
81
+ const [history, current] = await Promise.all([
82
+ db.select({ id: schema.toolchainDefaultHistory.id }).from(schema.toolchainDefaultHistory)
83
+ .where(eq(schema.toolchainDefaultHistory.releaseVersion, releaseVersion)).limit(1),
84
+ currentPlatformDefault(db),
85
+ ]);
86
+ return history.length > 0 || current === releaseVersion;
87
+ }
88
+ /** Whether ANY org has an org default or a canary membership (else no walk is needed). */
89
+ async function anyOrgSettings(db) {
90
+ const [defaults, rollout] = await Promise.all([
91
+ db.select({ orgId: schema.orgToolchainDefault.orgId }).from(schema.orgToolchainDefault).limit(1),
92
+ db.select({ orgId: schema.toolchainRollout.orgId }).from(schema.toolchainRollout).limit(1),
93
+ ]);
94
+ return defaults.length > 0 || rollout.length > 0;
95
+ }
96
+ // -----------------------------------------------------------------------------
97
+ // The org chain (caller → … → root)
98
+ // -----------------------------------------------------------------------------
99
+ /**
100
+ * The caller's chain, own org first, lowercased: `[self, parent, …, root]`.
101
+ * The same parent walk as `org-reachability.ts` (platform's
102
+ * `GET /organization/:id/parent`), cycle-safe and capped at `MAX_ORG_DEPTH` like
103
+ * `reporting-retention.ts` — but FAIL-CLOSED: a lookup failure, a cycle or an
104
+ * over-deep chain throws rather than resolving the wrong org's toolchain.
105
+ */
106
+ export async function toolchainOrgChain(orgId, getParent) {
107
+ const self = orgId.toLowerCase();
108
+ const chain = [self];
109
+ if (isSystemOrgId(self))
110
+ return chain;
111
+ let current = self;
112
+ for (let depth = 0; depth < MAX_ORG_DEPTH; depth++) {
113
+ const parent = toOrgIdString(await getParent(current))?.toLowerCase();
114
+ if (!parent || parent === current)
115
+ return chain;
116
+ if (chain.includes(parent)) {
117
+ throw new ManagedToolchainError(ErrorCode.INTERNAL_ERROR, 'The organization hierarchy has a cycle; the toolchain release cannot be resolved.', { orgId: self });
118
+ }
119
+ chain.push(parent);
120
+ current = parent;
121
+ }
122
+ throw new ManagedToolchainError(ErrorCode.INTERNAL_ERROR, `The organization hierarchy is deeper than ${MAX_ORG_DEPTH}; the toolchain release cannot be resolved.`, { orgId: self });
123
+ }
124
+ /** Parent lookups are cached briefly: one synth makes several lookups for the same org. */
125
+ const PARENT_CACHE_TTL_MS = 30_000;
126
+ const PARENT_CACHE_MAX = 5_000;
127
+ const parentCache = new Map();
128
+ async function platformParent(orgId) {
129
+ const hit = parentCache.get(orgId);
130
+ if (hit && Date.now() - hit.at < PARENT_CACHE_TTL_MS)
131
+ return hit.parent;
132
+ // A system-scoped service token; a non-2xx THROWS (fail-closed, see toolchainOrgChain).
133
+ const parent = await fetchParentOrgId(orgId, { authOrgId: SYSTEM_ORG_ID, throwOnHttpError: true, timeout: 5_000 });
134
+ if (parentCache.size >= PARENT_CACHE_MAX)
135
+ parentCache.clear();
136
+ parentCache.set(orgId, { parent, at: Date.now() });
137
+ return parent;
138
+ }
139
+ /** Test hook: drop cached parent lookups. */
140
+ export function clearToolchainParentCacheForTests() {
141
+ parentCache.clear();
142
+ }
143
+ const productionDeps = {
144
+ read: (fn) => runWithTenantContext({ isSuperAdmin: true }, () => withTenantTx((tx) => fn(tx))),
145
+ getParent: platformParent,
146
+ };
147
+ let defaultDeps = productionDeps;
148
+ /** Test hook: replace the resolver's reads and hierarchy (null restores production). */
149
+ export function setManagedToolchainDepsForTests(deps) {
150
+ defaultDeps = deps ?? productionDeps;
151
+ }
152
+ const isYanked = (p) => p.yankedAt !== null || p.lifecycle === 'yanked';
153
+ const isDeprecated = (p) => p.deprecatedAt !== null || p.lifecycle === 'deprecated';
154
+ /** Whether both halves are present (the release EXISTS). */
155
+ export function releaseExists(h) {
156
+ return h.release !== null && h.bootstrap !== null && h.synth !== null;
157
+ }
158
+ export function releaseLifecycleProblems(h) {
159
+ if (!releaseExists(h))
160
+ return ['missing'];
161
+ const halves = [h.bootstrap, h.synth];
162
+ const out = [];
163
+ if (halves.some((p) => !p.isActive))
164
+ out.push('inactive');
165
+ if (halves.some(isYanked))
166
+ out.push('yanked');
167
+ if (halves.some(isDeprecated))
168
+ out.push('deprecated');
169
+ return out;
170
+ }
171
+ /**
172
+ * The bootstrap half's toolchain metadata (`pipelineManager`, `awsCdk`, …), or
173
+ * null when it carries no complete, valid one. Upload persists it on the row's
174
+ * `metadata` as flat `toolchain.<field>` keys (api-core `toolchainMetadata`).
175
+ */
176
+ export function bootstrapToolchainOf(row) {
177
+ return row ? toolchainFromMetadata(row.metadata) : null;
178
+ }
179
+ /** `PLUGIN_VULN_MAX_FINDINGS` (default 0): the fixable-Critical floor a release must be within. */
180
+ function vulnFloor() {
181
+ return envInt('PLUGIN_VULN_MAX_FINDINGS', 0, { min: 0 });
182
+ }
183
+ /**
184
+ * The §8 candidate guards (pair, scan, metadata) a release fails, as their
185
+ * error codes — empty when it passes. The canary gate and concurrency are the
186
+ * platform-default service's; a canary is served only while this is empty.
187
+ */
188
+ export function toolchainCandidateProblems(h) {
189
+ if (!releaseExists(h) || releaseLifecycleProblems(h).length > 0)
190
+ return [ErrorCode.TOOLCHAIN_GUARD_PAIR_INCOMPLETE];
191
+ const out = [];
192
+ const halves = [h.bootstrap, h.synth];
193
+ if (halves.some((p) => !p.scannedAt))
194
+ out.push(ErrorCode.TOOLCHAIN_GUARD_UNSCANNED);
195
+ else if (halves.some((p) => (p.vulnCriticalFixable ?? 0) > vulnFloor()))
196
+ out.push(ErrorCode.TOOLCHAIN_GUARD_VULN_FLOOR);
197
+ if (!bootstrapToolchainOf(h.bootstrap))
198
+ out.push(ErrorCode.TOOLCHAIN_GUARD_METADATA);
199
+ return out;
200
+ }
201
+ /** Warnings for a release that EXISTS but is no longer (or never was) eligible. */
202
+ function standingWarnings(h, promoted, via) {
203
+ const ref = `Toolchain release ${h.releaseVersion}`;
204
+ const out = [];
205
+ const yanked = [h.bootstrap, h.synth].find(isYanked);
206
+ if (yanked) {
207
+ out.push({
208
+ code: 'TOOLCHAIN_RELEASE_YANKED',
209
+ severity: 'warning',
210
+ message: `${ref} is yanked${yanked.yankReason ? `: ${yanked.yankReason}` : ''}. It resolves only because it is selected exactly; move to a supported release.`,
211
+ });
212
+ }
213
+ const deprecated = [h.bootstrap, h.synth].find(isDeprecated);
214
+ if (deprecated) {
215
+ out.push({
216
+ code: 'TOOLCHAIN_RELEASE_DEPRECATED',
217
+ severity: 'warning',
218
+ message: `${ref} is deprecated${deprecated.deprecationMessage ? `: ${deprecated.deprecationMessage}` : ''}.`,
219
+ });
220
+ }
221
+ if ([h.bootstrap, h.synth].some((p) => !p.isActive)) {
222
+ out.push({ code: 'TOOLCHAIN_RELEASE_INACTIVE', severity: 'warning', message: `${ref} is inactive; move to a supported release.` });
223
+ }
224
+ if (!promoted && (via === 'pin' || via === 'org-default')) {
225
+ out.push({
226
+ code: 'TOOLCHAIN_RELEASE_NOT_PROMOTED',
227
+ severity: 'warning',
228
+ message: `${ref} was never the platform default and is not in a canary for your organization; it resolves only because it is selected exactly.`,
229
+ });
230
+ }
231
+ return out;
232
+ }
233
+ // -----------------------------------------------------------------------------
234
+ // Resolution
235
+ // -----------------------------------------------------------------------------
236
+ function pairOf(h, via) {
237
+ if (!releaseExists(h)) {
238
+ // A default (platform or org) whose halves are gone is a broken invariant
239
+ // (in-use protection counts defaults): refused, never served.
240
+ throw new ManagedToolchainError(ErrorCode.TOOLCHAIN_PAIR_MISMATCH, `Toolchain release ${h.releaseVersion} (${via}) is incomplete; it is never served.`, {
241
+ releaseVersion: h.releaseVersion,
242
+ missing: [...(h.bootstrap ? [] : [BOOTSTRAP]), ...(h.synth ? [] : [SYNTH]), ...(h.release ? [] : ['toolchain_release'])],
243
+ });
244
+ }
245
+ if (h.bootstrap.version !== h.releaseVersion || h.synth.version !== h.releaseVersion) {
246
+ throw new ManagedToolchainError(ErrorCode.TOOLCHAIN_PAIR_MISMATCH, `Toolchain halves disagree (${BOOTSTRAP}@${h.bootstrap.version}, ${SYNTH}@${h.synth.version}); never served.`, {
247
+ releaseVersion: h.releaseVersion,
248
+ });
249
+ }
250
+ return { bootstrap: h.bootstrap, synth: h.synth };
251
+ }
252
+ /** The resolution inside one elevated read, over a known chain. */
253
+ async function resolveOnChain(db, chain, releasePin) {
254
+ const canary = await nearestOnChain(db, schema.toolchainRollout, chain);
255
+ const answer = async (h, via) => {
256
+ const pair = pairOf(h, via);
257
+ const promoted = via === 'pin' || via === 'org-default'
258
+ ? (await wasPlatformDefault(db, h.releaseVersion)) || canary?.releaseVersion === h.releaseVersion
259
+ : true;
260
+ return { releaseVersion: h.releaseVersion, resolvedVia: via, ...pair, warnings: standingWarnings({ ...h, ...pair }, promoted, via) };
261
+ };
262
+ if (releasePin !== undefined) {
263
+ if (!isToolchainReleaseVersion(releasePin)) {
264
+ throw new ManagedToolchainError(ErrorCode.VALIDATION_ERROR, 'releasePin must be a release version (MAJOR.MINOR.PATCH, e.g. 1.4.2).', { releasePin });
265
+ }
266
+ const h = await loadReleaseHalves(db, releasePin);
267
+ if (!releaseExists(h)) {
268
+ throw new ManagedToolchainError(ErrorCode.NOT_FOUND, `Toolchain release ${releasePin} does not exist (or was deleted). Pin an eligible release, or remove toolchain.release to follow your organization's default.`, {
269
+ reason: 'toolchain_release_not_found', releaseVersion: releasePin,
270
+ });
271
+ }
272
+ return answer(h, 'pin');
273
+ }
274
+ const orgDefault = await nearestOnChain(db, schema.orgToolchainDefault, chain);
275
+ if (orgDefault)
276
+ return answer(await loadReleaseHalves(db, orgDefault.releaseVersion), 'org-default');
277
+ if (canary) {
278
+ const h = await loadReleaseHalves(db, canary.releaseVersion);
279
+ const problems = toolchainCandidateProblems(h);
280
+ if (problems.length === 0)
281
+ return answer(h, 'canary');
282
+ // Members fall through to the platform default. Logged, never returned:
283
+ // the answer must not reveal canary membership.
284
+ logger.warn('Canary toolchain release fails its guards; serving the platform default', { releaseVersion: canary.releaseVersion, problems });
285
+ }
286
+ const platform = await currentPlatformDefault(db);
287
+ if (!platform) {
288
+ throw new ManagedToolchainError(ErrorCode.TOOLCHAIN_NO_DEFAULT, 'No platform default toolchain release is set. An operator must set one (init-platform does this on a fresh install).');
289
+ }
290
+ return answer(await loadReleaseHalves(db, platform), 'default');
291
+ }
292
+ /** {@link resolveManagedToolchain} with injected reads and hierarchy (tests). */
293
+ export async function resolveManagedToolchainWith(deps, caller, opts = {}) {
294
+ const self = caller.orgId.toLowerCase();
295
+ // Walk the hierarchy only when some org has a setting (and outside the transaction).
296
+ const walk = await deps.read((db) => anyOrgSettings(db));
297
+ const chain = walk ? await toolchainOrgChain(self, deps.getParent) : [self];
298
+ return deps.read((db) => resolveOnChain(db, chain, opts.releasePin));
299
+ }
300
+ /**
301
+ * Resolve the managed toolchain release for `caller` (see the module doc).
302
+ * Throws {@link ManagedToolchainError}: TOOLCHAIN_NO_DEFAULT (409, no platform
303
+ * default), NOT_FOUND (404, a missing / deleted pin), TOOLCHAIN_PAIR_MISMATCH
304
+ * (500), VALIDATION_ERROR (400, a malformed pin).
305
+ */
306
+ export function resolveManagedToolchain(caller, opts = {}) {
307
+ return resolveManagedToolchainWith(defaultDeps, caller, opts);
308
+ }
309
+ /** {@link isEligibleRelease} with injected reads and hierarchy (tests). */
310
+ export async function isEligibleReleaseWith(deps, orgId, releaseVersion) {
311
+ if (!isToolchainReleaseVersion(releaseVersion))
312
+ return false;
313
+ const self = orgId.toLowerCase();
314
+ const halves = await deps.read((db) => loadReleaseHalves(db, releaseVersion));
315
+ if (releaseLifecycleProblems(halves).length > 0)
316
+ return false;
317
+ if (await deps.read((db) => wasPlatformDefault(db, releaseVersion)))
318
+ return true;
319
+ const walk = await deps.read((db) => anyOrgSettings(db));
320
+ if (!walk)
321
+ return false;
322
+ const chain = await toolchainOrgChain(self, deps.getParent);
323
+ const canary = await deps.read((db) => nearestOnChain(db, schema.toolchainRollout, chain));
324
+ return canary?.releaseVersion === releaseVersion;
325
+ }
326
+ /**
327
+ * D15: whether `orgId` may SET `releaseVersion` as a pipeline pin or its org
328
+ * default — both halves live (active, unyanked, not deprecated) AND either it
329
+ * has been the platform default or it is the caller's canary (nearest
330
+ * membership on its chain).
331
+ */
332
+ export function isEligibleRelease(orgId, releaseVersion) {
333
+ return isEligibleReleaseWith(defaultDeps, orgId, releaseVersion);
334
+ }
335
+ /** {@link readOrgToolchainOverview} with injected reads and hierarchy (tests). */
336
+ export async function readOrgToolchainOverviewWith(deps, orgId) {
337
+ const self = orgId.toLowerCase();
338
+ const walk = await deps.read((db) => anyOrgSettings(db));
339
+ const chain = walk ? await toolchainOrgChain(self, deps.getParent) : [self];
340
+ return deps.read(async (db) => {
341
+ const rows = await db.select().from(schema.orgToolchainDefault)
342
+ .where(inArray(sql `lower(${schema.orgToolchainDefault.orgId})`, chain));
343
+ const depthOf = (r) => chain.indexOf(r.orgId.toLowerCase());
344
+ const ownDefault = rows.find((r) => depthOf(r) === 0) ?? null;
345
+ const nearest = rows.filter((r) => depthOf(r) >= 0).sort((a, b) => depthOf(a) - depthOf(b))[0] ?? null;
346
+ const [canary, platformDefault, resolution] = await Promise.all([
347
+ nearestOnChain(db, schema.toolchainRollout, chain),
348
+ currentPlatformDefault(db),
349
+ resolveOnChain(db, chain),
350
+ ]);
351
+ return {
352
+ chain,
353
+ effective: { releaseVersion: resolution.releaseVersion, resolvedVia: resolution.resolvedVia, warnings: resolution.warnings },
354
+ ownDefault,
355
+ inheritedFrom: !ownDefault && nearest ? { orgId: nearest.orgId, releaseVersion: nearest.releaseVersion } : null,
356
+ canaryRelease: canary?.releaseVersion ?? null,
357
+ platformDefault,
358
+ };
359
+ });
360
+ }
361
+ /**
362
+ * The caller org's toolchain overview (elevated reads, the same chain walk and
363
+ * precedence as {@link resolveManagedToolchain}). Throws what the resolver
364
+ * throws — TOOLCHAIN_NO_DEFAULT (409) when nothing resolves at all.
365
+ */
366
+ export function readOrgToolchainOverview(orgId) {
367
+ return readOrgToolchainOverviewWith(defaultDeps, orgId);
368
+ }
369
+ /** {@link listEligibleReleases} with injected reads and hierarchy (tests). */
370
+ export async function listEligibleReleasesWith(deps, orgId) {
371
+ const self = orgId.toLowerCase();
372
+ const walk = await deps.read((db) => anyOrgSettings(db));
373
+ const chain = walk ? await toolchainOrgChain(self, deps.getParent) : [self];
374
+ return deps.read(async (db) => {
375
+ const [releases, rows, history, platformDefault, canary] = await Promise.all([
376
+ db.select().from(schema.toolchainRelease),
377
+ db.select().from(schema.plugin).where(and(sql `lower(${schema.plugin.orgId}) = ${SYSTEM_ORG_ID}`, inArray(schema.plugin.name, [...MANAGED_TOOLCHAIN_PLUGINS]), isNull(schema.plugin.deletedAt))),
378
+ db.select({ releaseVersion: schema.toolchainDefaultHistory.releaseVersion }).from(schema.toolchainDefaultHistory),
379
+ currentPlatformDefault(db),
380
+ nearestOnChain(db, schema.toolchainRollout, chain),
381
+ ]);
382
+ const promoted = new Set(history.map((h) => h.releaseVersion));
383
+ if (platformDefault)
384
+ promoted.add(platformDefault);
385
+ const out = [];
386
+ for (const release of releases) {
387
+ const v = release.releaseVersion;
388
+ const halves = {
389
+ releaseVersion: v,
390
+ release,
391
+ bootstrap: rows.find((p) => p.name === BOOTSTRAP && p.version === v) ?? null,
392
+ synth: rows.find((p) => p.name === SYNTH && p.version === v) ?? null,
393
+ };
394
+ if (!releaseExists(halves) || releaseLifecycleProblems(halves).length > 0)
395
+ continue;
396
+ const isCanary = canary?.releaseVersion === v;
397
+ if (!promoted.has(v) && !isCanary)
398
+ continue;
399
+ out.push({ releaseVersion: v, release, bootstrap: halves.bootstrap, synth: halves.synth, isPlatformDefault: platformDefault === v, isCanary });
400
+ }
401
+ out.sort((a, b) => compareSemver(b.releaseVersion, a.releaseVersion));
402
+ return { platformDefault, releases: out };
403
+ });
404
+ }
405
+ /**
406
+ * Every release `orgId` may SET as a pipeline pin or its org default (D15, the
407
+ * same rule as {@link isEligibleRelease}), newest first. Never another org's
408
+ * data: a canary appears only when it is the caller's own (nearest) membership.
409
+ */
410
+ export function listEligibleReleases(orgId) {
411
+ return listEligibleReleasesWith(defaultDeps, orgId);
412
+ }
413
+ // -----------------------------------------------------------------------------
414
+ // Caller helpers
415
+ // -----------------------------------------------------------------------------
416
+ /** The resolver's error as the refusal shape step resolution reports (contract check, declared side, facts). */
417
+ export function managedToolchainRefusal(err) {
418
+ switch (err.code) {
419
+ case ErrorCode.NOT_FOUND:
420
+ return { code: 'NOT_FOUND', reason: 'toolchain_release_not_found', message: err.message, ...(err.details ? { details: err.details } : {}) };
421
+ case ErrorCode.VALIDATION_ERROR:
422
+ return { code: 'NOT_FOUND', reason: 'toolchain_release_invalid', message: err.message, ...(err.details ? { details: err.details } : {}) };
423
+ case ErrorCode.TOOLCHAIN_NO_DEFAULT:
424
+ return { code: 'PLUGIN_UNAVAILABLE', reason: 'toolchain_no_default', message: err.message };
425
+ default:
426
+ return { code: 'PLUGIN_UNAVAILABLE', reason: 'toolchain_unresolved', message: err.message, ...(err.details ? { details: err.details } : {}) };
427
+ }
428
+ }
429
+ /**
430
+ * Resolve ONE managed half for a step: the plugin row plus the resolution, or
431
+ * the refusal. Any non-resolver error (a database or hierarchy failure)
432
+ * propagates.
433
+ */
434
+ export async function resolveManagedToolchainHalf(caller, name, opts = {}) {
435
+ try {
436
+ const resolution = await resolveManagedToolchain(caller, opts);
437
+ return { plugin: name === BOOTSTRAP ? resolution.bootstrap : resolution.synth, resolution };
438
+ }
439
+ catch (err) {
440
+ if (err instanceof ManagedToolchainError)
441
+ return { refusal: managedToolchainRefusal(err), error: err };
442
+ throw err;
443
+ }
444
+ }
445
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFuYWdlZC10b29sY2hhaW4uanMiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvbWFuYWdlZC10b29sY2hhaW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F1Qkc7QUFFSCxPQUFPLEVBQ0wsUUFBUSxFQUFFLGFBQWEsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxnQkFBZ0IsRUFBRSxxQkFBcUIsRUFBRSxhQUFhLEVBQ2hILHlCQUF5QixFQUFFLGFBQWEsRUFBRSxhQUFhLEVBQUUsaUNBQWlDLEVBQUUscUJBQXFCLEVBQUUsYUFBYSxHQUVqSSxNQUFNLDRCQUE0QixDQUFDO0FBQ3BDLE9BQU8sRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRzVELE9BQU8sRUFBRSxNQUFNLEVBQWdFLE1BQU0sK0JBQStCLENBQUM7QUFDckgsT0FBTyxFQUFFLG9CQUFvQixFQUFFLFlBQVksRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRTVFLE1BQU0sTUFBTSxHQUFHLFlBQVksQ0FBQyxtQkFBbUIsQ0FBQyxDQUFDO0FBeUJqRCxrSEFBa0g7QUFDbEgsTUFBTSxPQUFPLHFCQUFzQixTQUFRLFFBQVE7SUFDakQsWUFBWSxJQUFlLEVBQUUsT0FBZSxFQUFFLE9BQWlDO1FBQzdFLEtBQUssQ0FBQyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDO1FBQzNELElBQUksQ0FBQyxJQUFJLEdBQUcsdUJBQXVCLENBQUM7SUFDdEMsQ0FBQztDQUNGO0FBT0Qsb0VBQW9FO0FBQ3BFLE1BQU0sVUFBVSx5QkFBeUIsQ0FBQyxPQUFnQjtJQUN4RCxPQUFPLE9BQU8sT0FBTyxLQUFLLFFBQVEsSUFBSSxpQ0FBaUMsQ0FBQyxJQUFJ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R0FBRyxDQUFDO0lBQ1osQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLyoqXG4gKiBUSEUgcmVzb2x2ZXIgZm9yIHRoZSBtYW5hZ2VkIHRvb2xjaGFpbiAoZG9jcy9wbGFucy9ib290c3RyYXAtaW1hZ2UtdmVyc2lvbmluZy5tZFxuICogwqcyKS4gYHBpcGVsaW5lLWJvb3RzdHJhcEBWYCBhbmQgYGNkay1zeW50aEBWYCBhcmUgdHdvIFNZU1RFTS1PUkcgcGx1Z2luIHJvd3NcbiAqIHRoYXQgc2hhcmUgb25lIHJlbGVhc2UgdmVyc2lvbiBgVmA7IGV2ZXJ5IHBhdGggdGhhdCBjYW4gcmVzb2x2ZSBhIG1hbmFnZWRcbiAqIG5hbWUgYW5zd2VycyBmcm9tIGhlcmUgYW5kIG5vdGhpbmcgZWxzZSBtYXk6XG4gKlxuICogICByZWxlYXNlIHBpbiBnaXZlbiDihpIgdGhhdCByZWxlYXNlLCBpZiBpdCBFWElTVFMgKHlhbmtlZCAvIGRlcHJlY2F0ZWQgL1xuICogICAgICAgICAgICAgICAgICAgICAgIG5ldmVyLXByb21vdGVkIHN0aWxsIHJlc29sdmUsIHdpdGggYSB3YXJuaW5nOyBkZWxldGVkIOKHkiA0MDQpXG4gKiAgIGVsc2Ugb3JnIGRlZmF1bHQgIOKGkiB0aGUgTkVBUkVTVCBgb3JnX3Rvb2xjaGFpbl9kZWZhdWx0YCB3YWxraW5nIGNhbGxlciDihpIg4oCmIOKGkiByb290XG4gKiAgIGVsc2UgY2FuYXJ5ICAgICAgIOKGkiB0aGUgTkVBUkVTVCBgdG9vbGNoYWluX3JvbGxvdXRgIG1lbWJlcnNoaXAsIHNlcnZlZCBvbmx5XG4gKiAgICAgICAgICAgICAgICAgICAgICAgd2hpbGUgaXQgcGFzc2VzIHRoZSBzY2FuICsgbWV0YWRhdGEgZ3VhcmRzXG4gKiAgIGVsc2UgcGxhdGZvcm0gICAgIOKGkiBgdG9vbGNoYWluX3BsYXRmb3JtX2RlZmF1bHRgXG4gKiAgIGVsc2UgICAgICAgICAgICAgIOKGkiA0MDkgVE9PTENIQUlOX05PX0RFRkFVTFQgKG5ldmVyIFwiaGlnaGVzdCB2ZXJzaW9uXCIsIEQxMSlcbiAqXG4gKiAtIFJlYWRzIGFyZSBFTEVWQVRFRCAoYHJ1bldpdGhUZW5hbnRDb250ZXh0KHsgaXNTdXBlckFkbWluOiB0cnVlIH0pYCwgYXNcbiAqICAgYHZlcnNpb25SZWZlcmVuY2VzYCBkb2VzKSBhbmQgdG91Y2ggU1lTVEVNLU9SRyBwbHVnaW4gcm93cyBvbmx5OiB0aGUgb3duZXJcbiAqICAgcmFuayBvZiBgcGx1Z2luUmVzb2x1dGlvbk9yZGVyQnlgIGlzIG5ldmVyIGNvbnN1bHRlZCwgc28gYSBzYW1lLW5hbWVkIHJvdyBpblxuICogICBhbnkgb3RoZXIgb3JnIGlzIG5ldmVyIGEgY2FuZGlkYXRlLlxuICogLSBFbGlnaWJpbGl0eSAoRDE1KSBpcyBhIFNFVC10aW1lIHJ1bGUgKHtAbGluayBpc0VsaWdpYmxlUmVsZWFzZX0pOyBhdCByZXNvbHZlXG4gKiAgIHRpbWUgYSBwaW4gLyBvcmcgZGVmYXVsdCBvbmx5IGhhcyB0byBleGlzdC5cbiAqIC0gQm90aCBoYWx2ZXMgYWx3YXlzIGNvbWUgZnJvbSBPTkUgcmVsZWFzZSAoYFRPT0xDSEFJTl9QQUlSX01JU01BVENIYCBvdGhlcndpc2UpLlxuICogLSBUaGUgYW5zd2VyIGNhcnJpZXMgYHJlc29sdmVkVmlhYCBhbmQgbm90aGluZyBhYm91dCBhbnkgb3RoZXIgb3JnOiBub1xuICogICByb2xsb3V0IG1lbWJlcnNoaXAsIG5vIGFuY2VzdG9yJ3Mgc2V0dGluZ3MuXG4gKi9cblxuaW1wb3J0IHtcbiAgQXBwRXJyb3IsIGNvbXBhcmVTZW12ZXIsIGNyZWF0ZUxvZ2dlciwgZW52SW50LCBFcnJvckNvZGUsIGZldGNoUGFyZW50T3JnSWQsIGdldFN0YXR1c0ZvckVycm9yQ29kZSwgaXNTeXN0ZW1PcmdJZCxcbiAgTUFOQUdFRF9UT09MQ0hBSU5fUExVR0lOUywgTUFYX09SR19ERVBUSCwgU1lTVEVNX09SR19JRCwgVE9PTENIQUlOX1JFTEVBU0VfVkVSU0lPTl9QQVRURVJOLCB0b29sY2hhaW5Gcm9tTWV0YWRhdGEsIHRvT3JnSWRTdHJpbmcsXG4gIHR5cGUgR2V0UGFyZW50T3JnSWQsIHR5cGUgTWFuYWdlZFRvb2xjaGFpblBsdWdpbiwgdHlwZSBQbHVnaW5Ub29sY2hhaW4sXG59IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbmltcG9ydCB7IGFuZCwgZXEsIGluQXJyYXksIGlzTnVsbCwgc3FsIH0gZnJvbSAnZHJpenpsZS1vcm0nO1xuaW1wb3J0IHR5cGUgeyBDcnVkVHggfSBmcm9tICcuL2NydWQtc2VydmljZS5qcyc7XG5pbXBvcnQgdHlwZSB7IFJlc29sdXRpb25SZWZ1c2FsIH0gZnJvbSAnLi9wbHVnaW4tcmVzb2x1dGlvbi5qcyc7XG5pbXBvcnQgeyBzY2hlbWEsIHR5cGUgT3JnVG9vbGNoYWluRGVmYXVsdCwgdHlwZSBQbHVnaW4sIHR5cGUgVG9vbGNoYWluUmVsZWFzZSB9IGZyb20gJy4uL2RhdGFiYXNlL2RyaXp6bGUtc2NoZW1hLmpzJztcbmltcG9ydCB7IHJ1bldpdGhUZW5hbnRDb250ZXh0LCB3aXRoVGVuYW50VHggfSBmcm9tICcuLi9kYXRhYmFzZS90ZW5hbmN5LmpzJztcblxuY29uc3QgbG9nZ2VyID0gY3JlYXRlTG9nZ2VyKCdtYW5hZ2VkLXRvb2xjaGFpbicpO1xuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gUHVibGljIHNoYXBlc1xuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqIEhvdyBhIHJlc29sdXRpb24gY2hvc2UgaXRzIHJlbGVhc2UuIE5ldmVyIG5hbWVzIHRoZSBvcmcgaXQgY2FtZSBmcm9tLiAqL1xuZXhwb3J0IHR5cGUgVG9vbGNoYWluUmVzb2x2ZWRWaWEgPSAncGluJyB8ICdvcmctZGVmYXVsdCcgfCAnY2FuYXJ5JyB8ICdkZWZhdWx0JztcblxuLyoqIEEgbm9uLWZhdGFsIG5vdGUgb24gYSByZXNvbHZlZCByZWxlYXNlIChzeW50aCBwcmludHMgaXQpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBNYW5hZ2VkVG9vbGNoYWluV2FybmluZyB7XG4gIGNvZGU6IHN0cmluZztcbiAgbWVzc2FnZTogc3RyaW5nO1xuICBzZXZlcml0eTogJ2luZm8nIHwgJ3dhcm5pbmcnIHwgJ2Vycm9yJztcbn1cblxuLyoqIE9uZSByZWxlYXNlLCBib3RoIGhhbHZlcy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWFuYWdlZFRvb2xjaGFpblJlc29sdXRpb24ge1xuICByZWxlYXNlVmVyc2lvbjogc3RyaW5nO1xuICByZXNvbHZlZFZpYTogVG9vbGNoYWluUmVzb2x2ZWRWaWE7XG4gIGJvb3RzdHJhcDogUGx1Z2luO1xuICBzeW50aDogUGx1Z2luO1xuICB3YXJuaW5nczogTWFuYWdlZFRvb2xjaGFpbldhcm5pbmdbXTtcbn1cblxuLyoqIEEgcmVzb2x2ZXIgcmVmdXNhbDogYGNvZGVgIGlzIFRPT0xDSEFJTl9OT19ERUZBVUxULCBOT1RfRk9VTkQsIFRPT0xDSEFJTl9QQUlSX01JU01BVENIIG9yIFZBTElEQVRJT05fRVJST1IuICovXG5leHBvcnQgY2xhc3MgTWFuYWdlZFRvb2xjaGFpbkVycm9yIGV4dGVuZHMgQXBwRXJyb3Ige1xuICBjb25zdHJ1Y3Rvcihjb2RlOiBFcnJvckNvZGUsIG1lc3NhZ2U6IHN0cmluZywgZGV0YWlscz86IFJlY29yZDxzdHJpbmcsIHVua25vd24+KSB7XG4gICAgc3VwZXIoZ2V0U3RhdHVzRm9yRXJyb3JDb2RlKGNvZGUpLCBjb2RlLCBtZXNzYWdlLCBkZXRhaWxzKTtcbiAgICB0aGlzLm5hbWUgPSAnTWFuYWdlZFRvb2xjaGFpbkVycm9yJztcbiAgfVxufVxuXG4vKiogVGhlIGNhbGxlciBhIHJlc29sdXRpb24gcnVucyBmb3IuICovXG5leHBvcnQgaW50ZXJmYWNlIE1hbmFnZWRUb29sY2hhaW5DYWxsZXIge1xuICBvcmdJZDogc3RyaW5nO1xufVxuXG4vKiogV2hldGhlciBgdmVyc2lvbmAgaXMgYSByZWxlYXNlIHZlcnNpb24gKGBNQUpPUi5NSU5PUi5QQVRDSGApLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVG9vbGNoYWluUmVsZWFzZVZlcnNpb24odmVyc2lvbjogdW5rbm93bik6IHZlcnNpb24gaXMgc3RyaW5nIHtcbiAgcmV0dXJuIHR5cGVvZiB2ZXJzaW9uID09PSAnc3RyaW5nJyAmJiBUT09MQ0hBSU5fUkVMRUFTRV9WRVJTSU9OX1BBVFRFUk4udGVzdCh2ZXJzaW9uKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIERhdGEgYWNjZXNzIChzeXN0ZW0tb3JnIHJvd3MsIGVsZXZhdGVkKVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqIFdoYXQgdGhlIHJlc29sdmVyIHJlYWRzIHdpdGg6IGEgZHJpenpsZSB0cmFuc2FjdGlvbiAob3IgYW55IGRyaXp6bGUgZGF0YWJhc2UgaW4gdGVzdHMpLiAqL1xuZXhwb3J0IHR5cGUgVG9vbGNoYWluRGIgPSBQaWNrPENydWRUeCwgJ3NlbGVjdCc+O1xuXG4vKiogSG93IHRoZSByZXNvbHZlciByZWFkcyBhbmQgd2Fsa3MgdGhlIG9yZyB0cmVlIChpbmplY3RhYmxlIGZvciB0ZXN0cykuICovXG5leHBvcnQgaW50ZXJmYWNlIE1hbmFnZWRUb29sY2hhaW5EZXBzIHtcbiAgLyoqIFJ1biBgZm5gIHdpdGggRUxFVkFURUQgcmVhZHMuICovXG4gIHJlYWQ8VD4oZm46IChkYjogVG9vbGNoYWluRGIpID0+IFByb21pc2U8VD4pOiBQcm9taXNlPFQ+O1xuICAvKiogQW4gb3JnJ3MgZGlyZWN0IHBhcmVudCwgb3IgdW5kZWZpbmVkIGZvciBhIHJvb3QuIFRocm93cyB3aGVuIGl0IGNhbid0IHRlbGwuICovXG4gIGdldFBhcmVudDogR2V0UGFyZW50T3JnSWQ7XG59XG5cbi8qKiBCb3RoIGhhbHZlcyBvZiBvbmUgcmVsZWFzZSBhcyBzdG9yZWQsIHdpdGggdGhlIHJlbGVhc2Ugcm93LiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWxlYXNlSGFsdmVzIHtcbiAgcmVsZWFzZVZlcnNpb246IHN0cmluZztcbiAgcmVsZWFzZTogVG9vbGNoYWluUmVsZWFzZSB8IG51bGw7XG4gIGJvb3RzdHJhcDogUGx1Z2luIHwgbnVsbDtcbiAgc3ludGg6IFBsdWdpbiB8IG51bGw7XG59XG5cbmNvbnN0IEJPT1RTVFJBUDogTWFuYWdlZFRvb2xjaGFpblBsdWdpbiA9ICdwaXBlbGluZS1ib290c3RyYXAnO1xuY29uc3QgU1lOVEg6IE1hbmFnZWRUb29sY2hhaW5QbHVnaW4gPSAnY2RrLXN5bnRoJztcblxuLyoqIFRoZSByZWxlYXNlIHJvdyBhbmQgYm90aCBTWVNURU0tT1JHIGhhbHZlcyBvZiBgcmVsZWFzZVZlcnNpb25gIChkZWxldGVkIHJvd3MgZXhjbHVkZWQpLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxvYWRSZWxlYXNlSGFsdmVzKGRiOiBUb29sY2hhaW5EYiwgcmVsZWFzZVZlcnNpb246IHN0cmluZyk6IFByb21pc2U8UmVsZWFzZUhhbHZlcz4ge1xuICBjb25zdCBbcmVsZWFzZXMsIHJvd3NdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgIGRiLnNlbGVjdCgpLmZyb20oc2NoZW1hLnRvb2xjaGFpblJlbGVhc2UpLndoZXJlKGVxKHNjaGVtYS50b29sY2hhaW5SZWxlYXNlLnJlbGVhc2VWZXJzaW9uLCByZWxlYXNlVmVyc2lvbikpLFxuICAgIGRiLnNlbGVjdCgpLmZyb20oc2NoZW1hLnBsdWdpbikud2hlcmUoYW5kKFxuICAgICAgc3FsYGxvd2VyKCR7c2NoZW1hLnBsdWdpbi5vcmdJZH0pID0gJHtTWVNURU1fT1JHX0lEfWAsXG4gICAgICBpbkFycmF5KHNjaGVtYS5wbHVnaW4ubmFtZSwgWy4uLk1BTkFHRURfVE9PTENIQUlOX1BMVUdJTlNdKSxcbiAgICAgIGVxKHNjaGVtYS5wbHVnaW4udmVyc2lvbiwgcmVsZWFzZVZlcnNpb24pLFxuICAgICAgaXNOdWxsKHNjaGVtYS5wbHVnaW4uZGVsZXRlZEF0KSxcbiAgICApKSxcbiAgXSk7XG4gIGNvbnN0IHBsdWdpbnMgPSByb3dzIGFzIFBsdWdpbltdO1xuICByZXR1cm4ge1xuICAgIHJlbGVhc2VWZXJzaW9uLFxuICAgIHJlbGVhc2U6IChyZWxlYXNlcyBhcyBUb29sY2hhaW5SZWxlYXNlW10pWzBdID8/IG51bGwsXG4gICAgYm9vdHN0cmFwOiBwbHVnaW5zLmZpbmQoKHApID0+IHAubmFtZSA9PT0gQk9PVFNUUkFQKSA/PyBudWxsLFxuICAgIHN5bnRoOiBwbHVnaW5zLmZpbmQoKHApID0+IHAubmFtZSA9PT0gU1lOVEgpID8/IG51bGwsXG4gIH07XG59XG5cbi8qKiBBIHNldHRpbmcgZm91bmQgb24gdGhlIGNhbGxlcidzIGNoYWluOiB3aGljaCBjaGFpbiBpbmRleCwgYW5kIGl0cyByZWxlYXNlLiAqL1xuaW50ZXJmYWNlIENoYWluU2V0dGluZyB7IGRlcHRoOiBudW1iZXI7IHJlbGVhc2VWZXJzaW9uOiBzdHJpbmcgfVxuXG4vKiogVGhlIE5FQVJFU1Qgcm93IG9mIGB0YWJsZWAgKGtleWVkIGJ5IGBvcmdfaWRgKSBvbiBgY2hhaW5gIChvd24gb3JnIGZpcnN0KS4gKi9cbmFzeW5jIGZ1bmN0aW9uIG5lYXJlc3RPbkNoYWluKFxuICBkYjogVG9vbGNoYWluRGIsXG4gIHRhYmxlOiB0eXBlb2Ygc2NoZW1hLm9yZ1Rvb2xjaGFpbkRlZmF1bHQgfCB0eXBlb2Ygc2NoZW1hLnRvb2xjaGFpblJvbGxvdXQsXG4gIGNoYWluOiByZWFkb25seSBzdHJpbmdbXSxcbik6IFByb21pc2U8Q2hhaW5TZXR0aW5nIHwgbnVsbD4ge1xuICBpZiAoY2hhaW4ubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcbiAgY29uc3Qgcm93cyA9IGF3YWl0IGRiLnNlbGVjdCh7IG9yZ0lkOiB0YWJsZS5vcmdJZCwgcmVsZWFzZVZlcnNpb246IHRhYmxlLnJlbGVhc2VWZXJzaW9uIH0pXG4gICAgLmZyb20odGFibGUpXG4gICAgLndoZXJlKGluQXJyYXkoc3FsPHN0cmluZz5gbG93ZXIoJHt0YWJsZS5vcmdJZH0pYCwgWy4uLmNoYWluXSkpIGFzIEFycmF5PHsgb3JnSWQ6IHN0cmluZzsgcmVsZWFzZVZlcnNpb246IHN0cmluZyB9PjtcbiAgbGV0IGJlc3Q6IENoYWluU2V0dGluZyB8IG51bGwgPSBudWxsO1xuICBmb3IgKGNvbnN0IHIgb2Ygcm93cykge1xuICAgIGNvbnN0IGRlcHRoID0gY2hhaW4uaW5kZXhPZihyLm9yZ0lkLnRvTG93ZXJDYXNlKCkpO1xuICAgIGlmIChkZXB0aCA+PSAwICYmICghYmVzdCB8fCBkZXB0aCA8IGJlc3QuZGVwdGgpKSBiZXN0ID0geyBkZXB0aCwgcmVsZWFzZVZlcnNpb246IHIucmVsZWFzZVZlcnNpb24gfTtcbiAgfVxuICByZXR1cm4gYmVzdDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY3VycmVudFBsYXRmb3JtRGVmYXVsdChkYjogVG9vbGNoYWluRGIpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+IHtcbiAgY29uc3Qgcm93cyA9IGF3YWl0IGRiLnNlbGVjdCh7IHJlbGVhc2VWZXJzaW9uOiBzY2hlbWEudG9vbGNoYWluUGxhdGZvcm1EZWZhdWx0LnJlbGVhc2VWZXJzaW9uIH0pXG4gICAgLmZyb20oc2NoZW1hLnRvb2xjaGFpblBsYXRmb3JtRGVmYXVsdCkubGltaXQoMSkgYXMgQXJyYXk8eyByZWxlYXNlVmVyc2lvbjogc3RyaW5nIH0+O1xuICByZXR1cm4gcm93c1swXT8ucmVsZWFzZVZlcnNpb24gPz8gbnVsbDtcbn1cblxuLyoqIFdoZXRoZXIgYHJlbGVhc2VWZXJzaW9uYCBoYXMgZXZlciBiZWVuIChvciBpcykgdGhlIHBsYXRmb3JtIGRlZmF1bHQuICovXG5hc3luYyBmdW5jdGlvbiB3YXNQbGF0Zm9ybURlZmF1bHQoZGI6IFRvb2xjaGFpbkRiLCByZWxlYXNlVmVyc2lvbjogc3RyaW5nKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIGNvbnN0IFtoaXN0b3J5LCBjdXJyZW50XSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICBkYi5zZWxlY3QoeyBpZDogc2NoZW1hLnRvb2xjaGFpbkRlZmF1bHRIaXN0b3J5LmlkIH0pLmZyb20oc2NoZW1hLnRvb2xjaGFpbkRlZmF1bHRIaXN0b3J5KVxuICAgICAgLndoZXJlKGVxKHNjaGVtYS50b29sY2hhaW5EZWZhdWx0SGlzdG9yeS5yZWxlYXNlVmVyc2lvbiwgcmVsZWFzZVZlcnNpb24pKS5saW1pdCgxKSxcbiAgICBjdXJyZW50UGxhdGZvcm1EZWZhdWx0KGRiKSxcbiAgXSk7XG4gIHJldHVybiAoaGlzdG9yeSBhcyB1bmtub3duW10pLmxlbmd0aCA+IDAgfHwgY3VycmVudCA9PT0gcmVsZWFzZVZlcnNpb247XG59XG5cbi8qKiBXaGV0aGVyIEFOWSBvcmcgaGFzIGFuIG9yZyBkZWZhdWx0IG9yIGEgY2FuYXJ5IG1lbWJlcnNoaXAgKGVsc2Ugbm8gd2FsayBpcyBuZWVkZWQpLiAqL1xuYXN5bmMgZnVuY3Rpb24gYW55T3JnU2V0dGluZ3MoZGI6IFRvb2xjaGFpbkRiKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIGNvbnN0IFtkZWZhdWx0cywgcm9sbG91dF0gPSBhd2FpdCBQcm9taXNlLmFsbChbXG4gICAgZGIuc2VsZWN0KHsgb3JnSWQ6IHNjaGVtYS5vcmdUb29sY2hhaW5EZWZhdWx0Lm9yZ0lkIH0pLmZyb20oc2NoZW1hLm9yZ1Rvb2xjaGFpbkRlZmF1bHQpLmxpbWl0KDEpLFxuICAgIGRiLnNlbGVjdCh7IG9yZ0lkOiBzY2hlbWEudG9vbGNoYWluUm9sbG91dC5vcmdJZCB9KS5mcm9tKHNjaGVtYS50b29sY2hhaW5Sb2xsb3V0KS5saW1pdCgxKSxcbiAgXSk7XG4gIHJldHVybiAoZGVmYXVsdHMgYXMgdW5rbm93bltdKS5sZW5ndGggPiAwIHx8IChyb2xsb3V0IGFzIHVua25vd25bXSkubGVuZ3RoID4gMDtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFRoZSBvcmcgY2hhaW4gKGNhbGxlciDihpIg4oCmIOKGkiByb290KVxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLyoqXG4gKiBUaGUgY2FsbGVyJ3MgY2hhaW4sIG93biBvcmcgZmlyc3QsIGxvd2VyY2FzZWQ6IGBbc2VsZiwgcGFyZW50LCDigKYsIHJvb3RdYC5cbiAqIFRoZSBzYW1lIHBhcmVudCB3YWxrIGFzIGBvcmctcmVhY2hhYmlsaXR5LnRzYCAocGxhdGZvcm0nc1xuICogYEdFVCAvb3JnYW5pemF0aW9uLzppZC9wYXJlbnRgKSwgY3ljbGUtc2FmZSBhbmQgY2FwcGVkIGF0IGBNQVhfT1JHX0RFUFRIYCBsaWtlXG4gKiBgcmVwb3J0aW5nLXJldGVudGlvbi50c2Ag4oCUIGJ1dCBGQUlMLUNMT1NFRDogYSBsb29rdXAgZmFpbHVyZSwgYSBjeWNsZSBvciBhblxuICogb3Zlci1kZWVwIGNoYWluIHRocm93cyByYXRoZXIgdGhhbiByZXNvbHZpbmcgdGhlIHdyb25nIG9yZydzIHRvb2xjaGFpbi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHRvb2xjaGFpbk9yZ0NoYWluKG9yZ0lkOiBzdHJpbmcsIGdldFBhcmVudDogR2V0UGFyZW50T3JnSWQpOiBQcm9taXNlPHN0cmluZ1tdPiB7XG4gIGNvbnN0IHNlbGYgPSBvcmdJZC50b0xvd2VyQ2FzZSgpO1xuICBjb25zdCBjaGFpbiA9IFtzZWxmXTtcbiAgaWYgKGlzU3lzdGVtT3JnSWQoc2VsZikpIHJldHVybiBjaGFpbjtcbiAgbGV0IGN1cnJlbnQgPSBzZWxmO1xuICBmb3IgKGxldCBkZXB0aCA9IDA7IGRlcHRoIDwgTUFYX09SR19ERVBUSDsgZGVwdGgrKykge1xuICAgIGNvbnN0IHBhcmVudCA9IHRvT3JnSWRTdHJpbmcoYXdhaXQgZ2V0UGFyZW50KGN1cnJlbnQpKT8udG9Mb3dlckNhc2UoKTtcbiAgICBpZiAoIXBhcmVudCB8fCBwYXJlbnQgPT09IGN1cnJlbnQpIHJldHVybiBjaGFpbjtcbiAgICBpZiAoY2hhaW4uaW5jbHVkZXMocGFyZW50KSkge1xuICAgICAgdGhyb3cgbmV3IE1hbmFnZWRUb29sY2hhaW5FcnJvcihFcnJvckNvZGUuSU5URVJOQUxfRVJST1IsICdUaGUgb3JnYW5pemF0aW9uIGhpZXJhcmNoeSBoYXMgYSBjeWNsZTsgdGhlIHRvb2xjaGFpbiByZWxlYXNlIGNhbm5vdCBiZSByZXNvbHZlZC4nLCB7IG9yZ0lkOiBzZWxmIH0pO1xuICAgIH1cbiAgICBjaGFpbi5wdXNoKHBhcmVudCk7XG4gICAgY3VycmVudCA9IHBhcmVudDtcbiAgfVxuICB0aHJvdyBuZXcgTWFuYWdlZFRvb2xjaGFpbkVycm9yKEVycm9yQ29kZS5JTlRFUk5BTF9FUlJPUiwgYFRoZSBvcmdhbml6YXRpb24gaGllcmFyY2h5IGlzIGRlZXBlciB0aGFuICR7TUFYX09SR19ERVBUSH07IHRoZSB0b29sY2hhaW4gcmVsZWFzZSBjYW5ub3QgYmUgcmVzb2x2ZWQuYCwgeyBvcmdJZDogc2VsZiB9KTtcbn1cblxuLyoqIFBhcmVudCBsb29rdXBzIGFyZSBjYWNoZWQgYnJpZWZseTogb25lIHN5bnRoIG1ha2VzIHNldmVyYWwgbG9va3VwcyBmb3IgdGhlIHNhbWUgb3JnLiAqL1xuY29uc3QgUEFSRU5UX0NBQ0hFX1RUTF9NUyA9IDMwXzAwMDtcbmNvbnN0IFBBUkVOVF9DQUNIRV9NQVggPSA1XzAwMDtcbmNvbnN0IHBhcmVudENhY2hlID0gbmV3IE1hcDxzdHJpbmcsIHsgcGFyZW50OiBzdHJpbmcgfCB1bmRlZmluZWQ7IGF0OiBudW1iZXIgfT4oKTtcblxuYXN5bmMgZnVuY3Rpb24gcGxhdGZvcm1QYXJlbnQob3JnSWQ6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gIGNvbnN0IGhpdCA9IHBhcmVudENhY2hlLmdldChvcmdJZCk7XG4gIGlmIChoaXQgJiYgRGF0ZS5ub3coKSAtIGhpdC5hdCA8IFBBUkVOVF9DQUNIRV9UVExfTVMpIHJldHVybiBoaXQucGFyZW50O1xuICAvLyBBIHN5c3RlbS1zY29wZWQgc2VydmljZSB0b2tlbjsgYSBub24tMnh4IFRIUk9XUyAoZmFpbC1jbG9zZWQsIHNlZSB0b29sY2hhaW5PcmdDaGFpbikuXG4gIGNvbnN0IHBhcmVudCA9IGF3YWl0IGZldGNoUGFyZW50T3JnSWQob3JnSWQsIHsgYXV0aE9yZ0lkOiBTWVNURU1fT1JHX0lELCB0aHJvd09uSHR0cEVycm9yOiB0cnVlLCB0aW1lb3V0OiA1XzAwMCB9KTtcbiAgaWYgKHBhcmVudENhY2hlLnNpemUgPj0gUEFSRU5UX0NBQ0hFX01BWCkgcGFyZW50Q2FjaGUuY2xlYXIoKTtcbiAgcGFyZW50Q2FjaGUuc2V0KG9yZ0lkLCB7IHBhcmVudCwgYXQ6IERhdGUubm93KCkgfSk7XG4gIHJldHVybiBwYXJlbnQ7XG59XG5cbi8qKiBUZXN0IGhvb2s6IGRyb3AgY2FjaGVkIHBhcmVudCBsb29rdXBzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsZWFyVG9vbGNoYWluUGFyZW50Q2FjaGVGb3JUZXN0cygpOiB2b2lkIHtcbiAgcGFyZW50Q2FjaGUuY2xlYXIoKTtcbn1cblxuY29uc3QgcHJvZHVjdGlvbkRlcHM6IE1hbmFnZWRUb29sY2hhaW5EZXBzID0ge1xuICByZWFkOiAoZm4pID0+IHJ1bldpdGhUZW5hbnRDb250ZXh0KHsgaXNTdXBlckFkbWluOiB0cnVlIH0sICgpID0+IHdpdGhUZW5hbnRUeCgodHgpID0+IGZuKHR4KSkpLFxuICBnZXRQYXJlbnQ6IHBsYXRmb3JtUGFyZW50LFxufTtcbmxldCBkZWZhdWx0RGVwczogTWFuYWdlZFRvb2xjaGFpbkRlcHMgPSBwcm9kdWN0aW9uRGVwcztcblxuLyoqIFRlc3QgaG9vazogcmVwbGFjZSB0aGUgcmVzb2x2ZXIncyByZWFkcyBhbmQgaGllcmFyY2h5IChudWxsIHJlc3RvcmVzIHByb2R1Y3Rpb24pLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldE1hbmFnZWRUb29sY2hhaW5EZXBzRm9yVGVzdHMoZGVwczogTWFuYWdlZFRvb2xjaGFpbkRlcHMgfCBudWxsKTogdm9pZCB7XG4gIGRlZmF1bHREZXBzID0gZGVwcyA/PyBwcm9kdWN0aW9uRGVwcztcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIExpZmVjeWNsZSwgZWxpZ2liaWxpdHkgYW5kIHRoZSBjYW5hcnkgZ3VhcmRzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKiogV2h5IGEgc3RvcmVkIHJlbGVhc2UgaXMgbm90IExJVkUgKGVtcHR5ID0gbGl2ZTogYm90aCBoYWx2ZXMgcHJlc2VudCwgYWN0aXZlLCB1bnlhbmtlZCwgbm90IGRlcHJlY2F0ZWQpLiAqL1xuZXhwb3J0IHR5cGUgUmVsZWFzZUxpZmVjeWNsZVByb2JsZW0gPSAnbWlzc2luZycgfCAnaW5hY3RpdmUnIHwgJ3lhbmtlZCcgfCAnZGVwcmVjYXRlZCc7XG5cbmNvbnN0IGlzWWFua2VkID0gKHA6IFBsdWdpbikgPT4gcC55YW5rZWRBdCAhPT0gbnVsbCB8fCBwLmxpZmVjeWNsZSA9PT0gJ3lhbmtlZCc7XG5jb25zdCBpc0RlcHJlY2F0ZWQgPSAocDogUGx1Z2luKSA9PiBwLmRlcHJlY2F0ZWRBdCAhPT0gbnVsbCB8fCBwLmxpZmVjeWNsZSA9PT0gJ2RlcHJlY2F0ZWQnO1xuXG4vKiogV2hldGhlciBib3RoIGhhbHZlcyBhcmUgcHJlc2VudCAodGhlIHJlbGVhc2UgRVhJU1RTKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWxlYXNlRXhpc3RzKGg6IFJlbGVhc2VIYWx2ZXMpOiBoIGlzIFJlbGVhc2VIYWx2ZXMgJiB7IGJvb3RzdHJhcDogUGx1Z2luOyBzeW50aDogUGx1Z2luIH0ge1xuICByZXR1cm4gaC5yZWxlYXNlICE9PSBudWxsICYmIGguYm9vdHN0cmFwICE9PSBudWxsICYmIGguc3ludGggIT09IG51bGw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWxlYXNlTGlmZWN5Y2xlUHJvYmxlbXMoaDogUmVsZWFzZUhhbHZlcyk6IFJlbGVhc2VMaWZlY3ljbGVQcm9ibGVtW10ge1xuICBpZiAoIXJlbGVhc2VFeGlzdHMoaCkpIHJldHVybiBbJ21pc3NpbmcnXTtcbiAgY29uc3QgaGFsdmVzID0gW2guYm9vdHN0cmFwLCBoLnN5bnRoXTtcbiAgY29uc3Qgb3V0OiBSZWxlYXNlTGlmZWN5Y2xlUHJvYmxlbVtdID0gW107XG4gIGlmIChoYWx2ZXMuc29tZSgocCkgPT4gIXAuaXNBY3RpdmUpKSBvdXQucHVzaCgnaW5hY3RpdmUnKTtcbiAgaWYgKGhhbHZlcy5zb21lKGlzWWFua2VkKSkgb3V0LnB1c2goJ3lhbmtlZCcpO1xuICBpZiAoaGFsdmVzLnNvbWUoaXNEZXByZWNhdGVkKSkgb3V0LnB1c2goJ2RlcHJlY2F0ZWQnKTtcbiAgcmV0dXJuIG91dDtcbn1cblxuLyoqXG4gKiBUaGUgYm9vdHN0cmFwIGhhbGYncyB0b29sY2hhaW4gbWV0YWRhdGEgKGBwaXBlbGluZU1hbmFnZXJgLCBgYXdzQ2RrYCwg4oCmKSwgb3JcbiAqIG51bGwgd2hlbiBpdCBjYXJyaWVzIG5vIGNvbXBsZXRlLCB2YWxpZCBvbmUuIFVwbG9hZCBwZXJzaXN0cyBpdCBvbiB0aGUgcm93J3NcbiAqIGBtZXRhZGF0YWAgYXMgZmxhdCBgdG9vbGNoYWluLjxmaWVsZD5gIGtleXMgKGFwaS1jb3JlIGB0b29sY2hhaW5NZXRhZGF0YWApLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYm9vdHN0cmFwVG9vbGNoYWluT2Yocm93OiBQbHVnaW4gfCBudWxsIHwgdW5kZWZpbmVkKTogUGx1Z2luVG9vbGNoYWluIHwgbnVsbCB7XG4gIHJldHVybiByb3cgPyB0b29sY2hhaW5Gcm9tTWV0YWRhdGEocm93Lm1ldGFkYXRhKSA6IG51bGw7XG59XG5cbi8qKiBgUExVR0lOX1ZVTE5fTUFYX0ZJTkRJTkdTYCAoZGVmYXVsdCAwKTogdGhlIGZpeGFibGUtQ3JpdGljYWwgZmxvb3IgYSByZWxlYXNlIG11c3QgYmUgd2l0aGluLiAqL1xuZnVuY3Rpb24gdnVsbkZsb29yKCk6IG51bWJlciB7XG4gIHJldHVybiBlbnZJbnQoJ1BMVUdJTl9WVUxOX01BWF9GSU5ESU5HUycsIDAsIHsgbWluOiAwIH0pO1xufVxuXG4vKipcbiAqIFRoZSDCpzggY2FuZGlkYXRlIGd1YXJkcyAocGFpciwgc2NhbiwgbWV0YWRhdGEpIGEgcmVsZWFzZSBmYWlscywgYXMgdGhlaXJcbiAqIGVycm9yIGNvZGVzIOKAlCBlbXB0eSB3aGVuIGl0IHBhc3Nlcy4gVGhlIGNhbmFyeSBnYXRlIGFuZCBjb25jdXJyZW5jeSBhcmUgdGhlXG4gKiBwbGF0Zm9ybS1kZWZhdWx0IHNlcnZpY2UnczsgYSBjYW5hcnkgaXMgc2VydmVkIG9ubHkgd2hpbGUgdGhpcyBpcyBlbXB0eS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvb2xjaGFpbkNhbmRpZGF0ZVByb2JsZW1zKGg6IFJlbGVhc2VIYWx2ZXMpOiBFcnJvckNvZGVbXSB7XG4gIGlmICghcmVsZWFzZUV4aXN0cyhoKSB8fCByZWxlYXNlTGlmZWN5Y2xlUHJvYmxlbXMoaCkubGVuZ3RoID4gMCkgcmV0dXJuIFtFcnJvckNvZGUuVE9PTENIQUlOX0dVQVJEX1BBSVJfSU5DT01QTEVURV07XG4gIGNvbnN0IG91dDogRXJyb3JDb2RlW10gPSBbXTtcbiAgY29uc3QgaGFsdmVzID0gW2guYm9vdHN0cmFwLCBoLnN5bnRoXTtcbiAgaWYgKGhhbHZlcy5zb21lKChwKSA9PiAhcC5zY2FubmVkQXQpKSBvdXQucHVzaChFcnJvckNvZGUuVE9PTENIQUlOX0dVQVJEX1VOU0NBTk5FRCk7XG4gIGVsc2UgaWYgKGhhbHZlcy5zb21lKChwKSA9PiAocC52dWxuQ3JpdGljYWxGaXhhYmxlID8/IDApID4gdnVsbkZsb29yKCkpKSBvdXQucHVzaChFcnJvckNvZGUuVE9PTENIQUlOX0dVQVJEX1ZVTE5fRkxPT1IpO1xuICBpZiAoIWJvb3RzdHJhcFRvb2xjaGFpbk9mKGguYm9vdHN0cmFwKSkgb3V0LnB1c2goRXJyb3JDb2RlLlRPT0xDSEFJTl9HVUFSRF9NRVRBREFUQSk7XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKiBXYXJuaW5ncyBmb3IgYSByZWxlYXNlIHRoYXQgRVhJU1RTIGJ1dCBpcyBubyBsb25nZXIgKG9yIG5ldmVyIHdhcykgZWxpZ2libGUuICovXG5mdW5jdGlvbiBzdGFuZGluZ1dhcm5pbmdzKGg6IFJlbGVhc2VIYWx2ZXMgJiB7IGJvb3RzdHJhcDogUGx1Z2luOyBzeW50aDogUGx1Z2luIH0sIHByb21vdGVkOiBib29sZWFuLCB2aWE6IFRvb2xjaGFpblJlc29sdmVkVmlhKTogTWFuYWdlZFRvb2xjaGFpbldhcm5pbmdbXSB7XG4gIGNvbnN0IHJlZiA9IGBUb29sY2hhaW4gcmVsZWFzZSAke2gucmVsZWFzZVZlcnNpb259YDtcbiAgY29uc3Qgb3V0OiBNYW5hZ2VkVG9vbGNoYWluV2FybmluZ1tdID0gW107XG4gIGNvbnN0IHlhbmtlZCA9IFtoLmJvb3RzdHJhcCwgaC5zeW50aF0uZmluZChpc1lhbmtlZCk7XG4gIGlmICh5YW5rZWQpIHtcbiAgICBvdXQucHVzaCh7XG4gICAgICBjb2RlOiAnVE9PTENIQUlOX1JFTEVBU0VfWUFOS0VEJyxcbiAgICAgIHNldmVyaXR5OiAnd2FybmluZycsXG4gICAgICBtZXNzYWdlOiBgJHtyZWZ9IGlzIHlhbmtlZCR7eWFua2VkLnlhbmtSZWFzb24gPyBgOiAke3lhbmtlZC55YW5rUmVhc29ufWAgOiAnJ30uIEl0IHJlc29sdmVzIG9ubHkgYmVjYXVzZSBpdCBpcyBzZWxlY3RlZCBleGFjdGx5OyBtb3ZlIHRvIGEgc3VwcG9ydGVkIHJlbGVhc2UuYCxcbiAgICB9KTtcbiAgfVxuICBjb25zdCBkZXByZWNhdGVkID0gW2guYm9vdHN0cmFwLCBoLnN5bnRoXS5maW5kKGlzRGVwcmVjYXRlZCk7XG4gIGlmIChkZXByZWNhdGVkKSB7XG4gICAgb3V0LnB1c2goe1xuICAgICAgY29kZTogJ1RPT0xDSEFJTl9SRUxFQVNFX0RFUFJFQ0FURUQnLFxuICAgICAgc2V2ZXJpdHk6ICd3YXJuaW5nJyxcbiAgICAgIG1lc3NhZ2U6IGAke3JlZn0gaXMgZGVwcmVjYXRlZCR7ZGVwcmVjYXRlZC5kZXByZWNhdGlvbk1lc3NhZ2UgPyBgOiAke2RlcHJlY2F0ZWQuZGVwcmVjYXRpb25NZXNzYWdlfWAgOiAnJ30uYCxcbiAgICB9KTtcbiAgfVxuICBpZiAoW2guYm9vdHN0cmFwLCBoLnN5bnRoXS5zb21lKChwKSA9PiAhcC5pc0FjdGl2ZSkpIHtcbiAgICBvdXQucHVzaCh7IGNvZGU6ICdUT09MQ0hBSU5fUkVMRUFTRV9JTkFDVElWRScsIHNldmVyaXR5OiAnd2FybmluZycsIG1lc3NhZ2U6IGAke3JlZn0gaXMgaW5hY3RpdmU7IG1vdmUgdG8gYSBzdXBwb3J0ZWQgcmVsZWFzZS5gIH0pO1xuICB9XG4gIGlmICghcHJvbW90ZWQgJiYgKHZpYSA9PT0gJ3BpbicgfHwgdmlhID09PSAnb3JnLWRlZmF1bHQnKSkge1xuICAgIG91dC5wdXNoKHtcbiAgICAgIGNvZGU6ICdUT09MQ0hBSU5fUkVMRUFTRV9OT1RfUFJPTU9URUQnLFxuICAgICAgc2V2ZXJpdHk6ICd3YXJuaW5nJyxcbiAgICAgIG1lc3NhZ2U6IGAke3JlZn0gd2FzIG5ldmVyIHRoZSBwbGF0Zm9ybSBkZWZhdWx0IGFuZCBpcyBub3QgaW4gYSBjYW5hcnkgZm9yIHlvdXIgb3JnYW5pemF0aW9uOyBpdCByZXNvbHZlcyBvbmx5IGJlY2F1c2UgaXQgaXMgc2VsZWN0ZWQgZXhhY3RseS5gLFxuICAgIH0pO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBSZXNvbHV0aW9uXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5mdW5jdGlvbiBwYWlyT2YoaDogUmVsZWFzZUhhbHZlcywgdmlhOiBUb29sY2hhaW5SZXNvbHZlZFZpYSk6IHsgYm9vdHN0cmFwOiBQbHVnaW47IHN5bnRoOiBQbHVnaW4gfSB7XG4gIGlmICghcmVsZWFzZUV4aXN0cyhoKSkge1xuICAgIC8vIEEgZGVmYXVsdCAocGxhdGZvcm0gb3Igb3JnKSB3aG9zZSBoYWx2ZXMgYXJlIGdvbmUgaXMgYSBicm9rZW4gaW52YXJpYW50XG4gICAgLy8gKGluLXVzZSBwcm90ZWN0aW9uIGNvdW50cyBkZWZhdWx0cyk6IHJlZnVzZWQsIG5ldmVyIHNlcnZlZC5cbiAgICB0aHJvdyBuZXcgTWFuYWdlZFRvb2xjaGFpbkVycm9yKEVycm9yQ29kZS5UT09MQ0hBSU5fUEFJUl9NSVNNQVRDSCwgYFRvb2xjaGFpbiByZWxlYXNlICR7aC5yZWxlYXNlVmVyc2lvbn0gKCR7dmlhfSkgaXMgaW5jb21wbGV0ZTsgaXQgaXMgbmV2ZXIgc2VydmVkLmAsIHtcbiAgICAgIHJlbGVhc2VWZXJzaW9uOiBoLnJlbGVhc2VWZXJzaW9uLFxuICAgICAgbWlzc2luZzogWy4uLihoLmJvb3RzdHJhcCA/IFtdIDogW0JPT1RTVFJBUF0pLCAuLi4oaC5zeW50aCA/IFtdIDogW1NZTlRIXSksIC4uLihoLnJlbGVhc2UgPyBbXSA6IFsndG9vbGNoYWluX3JlbGVhc2UnXSldLFxuICAgIH0pO1xuICB9XG4gIGlmIChoLmJvb3RzdHJhcC52ZXJzaW9uICE9PSBoLnJlbGVhc2VWZXJzaW9uIHx8IGguc3ludGgudmVyc2lvbiAhPT0gaC5yZWxlYXNlVmVyc2lvbikge1xuICAgIHRocm93IG5ldyBNYW5hZ2VkVG9vbGNoYWluRXJyb3IoRXJyb3JDb2RlLlRPT0xDSEFJTl9QQUlSX01JU01BVENILCBgVG9vbGNoYWluIGhhbHZlcyBkaXNhZ3JlZSAoJHtCT09UU1RSQVB9QCR7aC5ib290c3RyYXAudmVyc2lvbn0sICR7U1lOVEh9QCR7aC5zeW50aC52ZXJzaW9ufSk7IG5ldmVyIHNlcnZlZC5gLCB7XG4gICAgICByZWxlYXNlVmVyc2lvbjogaC5yZWxlYXNlVmVyc2lvbixcbiAgICB9KTtcbiAgfVxuICByZXR1cm4geyBib290c3RyYXA6IGguYm9vdHN0cmFwLCBzeW50aDogaC5zeW50aCB9O1xufVxuXG4vKiogVGhlIHJlc29sdXRpb24gaW5zaWRlIG9uZSBlbGV2YXRlZCByZWFkLCBvdmVyIGEga25vd24gY2hhaW4uICovXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlT25DaGFpbihkYjogVG9vbGNoYWluRGIsIGNoYWluOiByZWFkb25seSBzdHJpbmdbXSwgcmVsZWFzZVBpbj86IHN0cmluZyk6IFByb21pc2U8TWFuYWdlZFRvb2xjaGFpblJlc29sdXRpb24+IHtcbiAgY29uc3QgY2FuYXJ5ID0gYXdhaXQgbmVhcmVzdE9uQ2hhaW4oZGIsIHNjaGVtYS50b29sY2hhaW5Sb2xsb3V0LCBjaGFpbik7XG4gIGNvbnN0IGFuc3dlciA9IGFzeW5jIChoOiBSZWxlYXNlSGFsdmVzLCB2aWE6IFRvb2xjaGFpblJlc29sdmVkVmlhKTogUHJvbWlzZTxNYW5hZ2VkVG9vbGNoYWluUmVzb2x1dGlvbj4gPT4ge1xuICAgIGNvbnN0IHBhaXIgPSBwYWlyT2YoaCwgdmlhKTtcbiAgICBjb25zdCBwcm9tb3RlZCA9IHZpYSA9PT0gJ3BpbicgfHwgdmlhID09PSAnb3JnLWRlZmF1bHQnXG4gICAgICA/IChhd2FpdCB3YXNQbGF0Zm9ybURlZmF1bHQoZGIsIGgucmVsZWFzZVZlcnNpb24pKSB8fCBjYW5hcnk/LnJlbGVhc2VWZXJzaW9uID09PSBoLnJlbGVhc2VWZXJzaW9uXG4gICAgICA6IHRydWU7XG4gICAgcmV0dXJuIHsgcmVsZWFzZVZlcnNpb246IGgucmVsZWFzZVZlcnNpb24sIHJlc29sdmVkVmlhOiB2aWEsIC4uLnBhaXIsIHdhcm5pbmdzOiBzdGFuZGluZ1dhcm5pbmdzKHsgLi4uaCwgLi4ucGFpciB9LCBwcm9tb3RlZCwgdmlhKSB9O1xuICB9O1xuXG4gIGlmIChyZWxlYXNlUGluICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoIWlzVG9vbGNoYWluUmVsZWFzZVZlcnNpb24ocmVsZWFzZVBpbikpIHtcbiAgICAgIHRocm93IG5ldyBNYW5hZ2VkVG9vbGNoYWluRXJyb3IoRXJyb3JDb2RlLlZBTElEQVRJT05fRVJST1IsICdyZWxlYXNlUGluIG11c3QgYmUgYSByZWxlYXNlIHZlcnNpb24gKE1BSk9SLk1JTk9SLlBBVENILCBlLmcuIDEuNC4yKS4nLCB7IHJlbGVhc2VQaW4gfSk7XG4gICAgfVxuICAgIGNvbnN0IGggPSBhd2FpdCBsb2FkUmVsZWFzZUhhbHZlcyhkYiwgcmVsZWFzZVBpbik7XG4gICAgaWYgKCFyZWxlYXNlRXhpc3RzKGgpKSB7XG4gICAgICB0aHJvdyBuZXcgTWFuYWdlZFRvb2xjaGFpbkVycm9yKEVycm9yQ29kZS5OT1RfRk9VTkQsIGBUb29sY2hhaW4gcmVsZWFzZSAke3JlbGVhc2VQaW59IGRvZXMgbm90IGV4aXN0IChvciB3YXMgZGVsZXRlZCkuIFBpbiBhbiBlbGlnaWJsZSByZWxlYXNlLCBvciByZW1vdmUgdG9vbGNoYWluLnJlbGVhc2UgdG8gZm9sbG93IHlvdXIgb3JnYW5pemF0aW9uJ3MgZGVmYXVsdC5gLCB7XG4gICAgICAgIHJlYXNvbjogJ3Rvb2xjaGFpbl9yZWxlYXNlX25vdF9mb3VuZCcsIHJlbGVhc2VWZXJzaW9uOiByZWxlYXNlUGluLFxuICAgICAgfSk7XG4gICAgfVxuICAgIHJldHVybiBhbnN3ZXIoaCwgJ3BpbicpO1xuICB9XG5cbiAgY29uc3Qgb3JnRGVmYXVsdCA9IGF3YWl0IG5lYXJlc3RPbkNoYWluKGRiLCBzY2hlbWEub3JnVG9vbGNoYWluRGVmYXVsdCwgY2hhaW4pO1xuICBpZiAob3JnRGVmYXVsdCkgcmV0dXJuIGFuc3dlcihhd2FpdCBsb2FkUmVsZWFzZUhhbHZlcyhkYiwgb3JnRGVmYXVsdC5yZWxlYXNlVmVyc2lvbiksICdvcmctZGVmYXVsdCcpO1xuXG4gIGlmIChjYW5hcnkpIHtcbiAgICBjb25zdCBoID0gYXdhaXQgbG9hZFJlbGVhc2VIYWx2ZXMoZGIsIGNhbmFyeS5yZWxlYXNlVmVyc2lvbik7XG4gICAgY29uc3QgcHJvYmxlbXMgPSB0b29sY2hhaW5DYW5kaWRhdGVQcm9ibGVtcyhoKTtcbiAgICBpZiAocHJvYmxlbXMubGVuZ3RoID09PSAwKSByZXR1cm4gYW5zd2VyKGgsICdjYW5hcnknKTtcbiAgICAvLyBNZW1iZXJzIGZhbGwgdGhyb3VnaCB0byB0aGUgcGxhdGZvcm0gZGVmYXVsdC4gTG9nZ2VkLCBuZXZlciByZXR1cm5lZDpcbiAgICAvLyB0aGUgYW5zd2VyIG11c3Qgbm90IHJldmVhbCBjYW5hcnkgbWVtYmVyc2hpcC5cbiAgICBsb2dnZXIud2FybignQ2FuYXJ5IHRvb2xjaGFpbiByZWxlYXNlIGZhaWxzIGl0cyBndWFyZHM7IHNlcnZpbmcgdGhlIHBsYXRmb3JtIGRlZmF1bHQnLCB7IHJlbGVhc2VWZXJzaW9uOiBjYW5hcnkucmVsZWFzZVZlcnNpb24sIHByb2JsZW1zIH0pO1xuICB9XG5cbiAgY29uc3QgcGxhdGZvcm0gPSBhd2FpdCBjdXJyZW50UGxhdGZvcm1EZWZhdWx0KGRiKTtcbiAgaWYgKCFwbGF0Zm9ybSkge1xuICAgIHRocm93IG5ldyBNYW5hZ2VkVG9vbGNoYWluRXJyb3IoRXJyb3JDb2RlLlRPT0xDSEFJTl9OT19ERUZBVUxULCAnTm8gcGxhdGZvcm0gZGVmYXVsdCB0b29sY2hhaW4gcmVsZWFzZSBpcyBzZXQuIEFuIG9wZXJhdG9yIG11c3Qgc2V0IG9uZSAoaW5pdC1wbGF0Zm9ybSBkb2VzIHRoaXMgb24gYSBmcmVzaCBpbnN0YWxsKS4nKTtcbiAgfVxuICByZXR1cm4gYW5zd2VyKGF3YWl0IGxvYWRSZWxlYXNlSGFsdmVzKGRiLCBwbGF0Zm9ybSksICdkZWZhdWx0Jyk7XG59XG5cbi8qKiB7QGxpbmsgcmVzb2x2ZU1hbmFnZWRUb29sY2hhaW59IHdpdGggaW5qZWN0ZWQgcmVhZHMgYW5kIGhpZXJhcmNoeSAodGVzdHMpLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlc29sdmVNYW5hZ2VkVG9vbGNoYWluV2l0aChcbiAgZGVwczogTWFuYWdlZFRvb2xjaGFpbkRlcHMsXG4gIGNhbGxlcjogTWFuYWdlZFRvb2xjaGFpbkNhbGxlcixcbiAgb3B0czogeyByZWxlYXNlUGluPzogc3RyaW5nIH0gPSB7fSxcbik6IFByb21pc2U8TWFuYWdlZFRvb2xjaGFpblJlc29sdXRpb24+IHtcbiAgY29uc3Qgc2VsZiA9IGNhbGxlci5vcmdJZC50b0xvd2VyQ2FzZSgpO1xuICAvLyBXYWxrIHRoZSBoaWVyYXJjaHkgb25seSB3aGVuIHNvbWUgb3JnIGhhcyBhIHNldHRpbmcgKGFuZCBvdXRzaWRlIHRoZSB0cmFuc2FjdGlvbikuXG4gIGNvbnN0IHdhbGsgPSBhd2FpdCBkZXBzLnJlYWQoKGRiKSA9PiBhbnlPcmdTZXR0aW5ncyhkYikpO1xuICBjb25zdCBjaGFpbiA9IHdhbGsgPyBhd2FpdCB0b29sY2hhaW5PcmdDaGFpbihzZWxmLCBkZXBzLmdldFBhcmVudCkgOiBbc2VsZl07XG4gIHJldHVybiBkZXBzLnJlYWQoKGRiKSA9PiByZXNvbHZlT25DaGFpbihkYiwgY2hhaW4sIG9wdHMucmVsZWFzZVBpbikpO1xufVxuXG4vKipcbiAqIFJlc29sdmUgdGhlIG1hbmFnZWQgdG9vbGNoYWluIHJlbGVhc2UgZm9yIGBjYWxsZXJgIChzZWUgdGhlIG1vZHVsZSBkb2MpLlxuICogVGhyb3dzIHtAbGluayBNYW5hZ2VkVG9vbGNoYWluRXJyb3J9OiBUT09MQ0hBSU5fTk9fREVGQVVMVCAoNDA5LCBubyBwbGF0Zm9ybVxuICogZGVmYXVsdCksIE5PVF9GT1VORCAoNDA0LCBhIG1pc3NpbmcgLyBkZWxldGVkIHBpbiksIFRPT0xDSEFJTl9QQUlSX01JU01BVENIXG4gKiAoNTAwKSwgVkFMSURBVElPTl9FUlJPUiAoNDAwLCBhIG1hbGZvcm1lZCBwaW4pLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZU1hbmFnZWRUb29sY2hhaW4oY2FsbGVyOiBNYW5hZ2VkVG9vbGNoYWluQ2FsbGVyLCBvcHRzOiB7IHJlbGVhc2VQaW4/OiBzdHJpbmcgfSA9IHt9KTogUHJvbWlzZTxNYW5hZ2VkVG9vbGNoYWluUmVzb2x1dGlvbj4ge1xuICByZXR1cm4gcmVzb2x2ZU1hbmFnZWRUb29sY2hhaW5XaXRoKGRlZmF1bHREZXBzLCBjYWxsZXIsIG9wdHMpO1xufVxuXG4vKioge0BsaW5rIGlzRWxpZ2libGVSZWxlYXNlfSB3aXRoIGluamVjdGVkIHJlYWRzIGFuZCBoaWVyYXJjaHkgKHRlc3RzKS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpc0VsaWdpYmxlUmVsZWFzZVdpdGgoZGVwczogTWFuYWdlZFRvb2xjaGFpbkRlcHMsIG9yZ0lkOiBzdHJpbmcsIHJlbGVhc2VWZXJzaW9uOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgaWYgKCFpc1Rvb2xjaGFpblJlbGVhc2VWZXJzaW9uKHJlbGVhc2VWZXJzaW9uKSkgcmV0dXJuIGZhbHNlO1xuICBjb25zdCBzZWxmID0gb3JnSWQudG9Mb3dlckNhc2UoKTtcbiAgY29uc3QgaGFsdmVzID0gYXdhaXQgZGVwcy5yZWFkKChkYikgPT4gbG9hZFJlbGVhc2VIYWx2ZXMoZGIsIHJlbGVhc2VWZXJzaW9uKSk7XG4gIGlmIChyZWxlYXNlTGlmZWN5Y2xlUHJvYmxlbXMoaGFsdmVzKS5sZW5ndGggPiAwKSByZXR1cm4gZmFsc2U7XG4gIGlmIChhd2FpdCBkZXBzLnJlYWQoKGRiKSA9PiB3YXNQbGF0Zm9ybURlZmF1bHQoZGIsIHJlbGVhc2VWZXJzaW9uKSkpIHJldHVybiB0cnVlO1xuICBjb25zdCB3YWxrID0gYXdhaXQgZGVwcy5yZWFkKChkYikgPT4gYW55T3JnU2V0dGluZ3MoZGIpKTtcbiAgaWYgKCF3YWxrKSByZXR1cm4gZmFsc2U7XG4gIGNvbnN0IGNoYWluID0gYXdhaXQgdG9vbGNoYWluT3JnQ2hhaW4oc2VsZiwgZGVwcy5nZXRQYXJlbnQpO1xuICBjb25zdCBjYW5hcnkgPSBhd2FpdCBkZXBzLnJlYWQoKGRiKSA9PiBuZWFyZXN0T25DaGFpbihkYiwgc2NoZW1hLnRvb2xjaGFpblJvbGxvdXQsIGNoYWluKSk7XG4gIHJldHVybiBjYW5hcnk/LnJlbGVhc2VWZXJzaW9uID09PSByZWxlYXNlVmVyc2lvbjtcbn1cblxuLyoqXG4gKiBEMTU6IHdoZXRoZXIgYG9yZ0lkYCBtYXkgU0VUIGByZWxlYXNlVmVyc2lvbmAgYXMgYSBwaXBlbGluZSBwaW4gb3IgaXRzIG9yZ1xuICogZGVmYXVsdCDigJQgYm90aCBoYWx2ZXMgbGl2ZSAoYWN0aXZlLCB1bnlhbmtlZCwgbm90IGRlcHJlY2F0ZWQpIEFORCBlaXRoZXIgaXRcbiAqIGhhcyBiZWVuIHRoZSBwbGF0Zm9ybSBkZWZhdWx0IG9yIGl0IGlzIHRoZSBjYWxsZXIncyBjYW5hcnkgKG5lYXJlc3RcbiAqIG1lbWJlcnNoaXAgb24gaXRzIGNoYWluKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzRWxpZ2libGVSZWxlYXNlKG9yZ0lkOiBzdHJpbmcsIHJlbGVhc2VWZXJzaW9uOiBzdHJpbmcpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgcmV0dXJuIGlzRWxpZ2libGVSZWxlYXNlV2l0aChkZWZhdWx0RGVwcywgb3JnSWQsIHJlbGVhc2VWZXJzaW9uKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFRoZSBvcmcncyBvd24gcGljdHVyZTogdGhlIG9yZy1kZWZhdWx0IHBhbmVsIGFuZCB0aGUgZWxpZ2libGUtcmVsZWFzZSBsaXN0XG4vLyAoZG9jcy9wbGFucy9ib290c3RyYXAtaW1hZ2UtdmVyc2lvbmluZy5tZCDCpzUsIFBoYXNlIDQsIEQxNSlcbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbi8qKlxuICogV2hhdCB0aGUgb3JnLWRlZmF1bHQgcGFuZWwgc2hvd3MgYSBjYWxsZXIgYWJvdXQgSVRTIE9XTiBvcmc6IG5ldmVyIGFub3RoZXJcbiAqIG9yZydzIGNob2ljZSwgYW5kIG9mIHRoZSBhbmNlc3RvcnMgb25seSB3aGljaCBvbmUncyBkZWZhdWx0IGFwcGxpZXMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgT3JnVG9vbGNoYWluT3ZlcnZpZXcge1xuICAvKiogVGhlIGNhbGxlcidzIGNoYWluLCBvd24gb3JnIGZpcnN0IChsb3dlcmNhc2VkKS4gKi9cbiAgY2hhaW46IHN0cmluZ1tdO1xuICAvKiogV2hhdCB0aGUgb3JnJ3MgVU5QSU5ORUQgcGlwZWxpbmVzIHJlc29sdmUgdG8gbm93LiAqL1xuICBlZmZlY3RpdmU6IHsgcmVsZWFzZVZlcnNpb246IHN0cmluZzsgcmVzb2x2ZWRWaWE6IFRvb2xjaGFpblJlc29sdmVkVmlhOyB3YXJuaW5nczogTWFuYWdlZFRvb2xjaGFpbldhcm5pbmdbXSB9O1xuICAvKiogVGhlIGNhbGxlciBvcmcncyBvd24gYG9yZ190b29sY2hhaW5fZGVmYXVsdGAgcm93LCBpZiBpdCBzZXQgb25lLiAqL1xuICBvd25EZWZhdWx0OiBPcmdUb29sY2hhaW5EZWZhdWx0IHwgbnVsbDtcbiAgLyoqIFRoZSBhbmNlc3RvciB3aG9zZSBvcmcgZGVmYXVsdCBhcHBsaWVzLCB3aGVuIHRoZSBvcmcgc2V0IG5vbmUgb2YgaXRzIG93bi4gKi9cbiAgaW5oZXJpdGVkRnJvbTogeyBvcmdJZDogc3RyaW5nOyByZWxlYXNlVmVyc2lvbjogc3RyaW5nIH0gfCBudWxsO1xuICAvKiogVGhlIGNhbGxlcidzIGNhbmFyeSByZWxlYXNlIChpdHMgTkVBUkVTVCBtZW1iZXJzaGlwIG9uIHRoZSBjaGFpbiksIG9yIG51bGwuICovXG4gIGNhbmFyeVJlbGVhc2U6IHN0cmluZyB8IG51bGw7XG4gIHBsYXRmb3JtRGVmYXVsdDogc3RyaW5nIHwgbnVsbDtcbn1cblxuLyoqIHtAbGluayByZWFkT3JnVG9vbGNoYWluT3ZlcnZpZXd9IHdpdGggaW5qZWN0ZWQgcmVhZHMgYW5kIGhpZXJhcmNoeSAodGVzdHMpLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRPcmdUb29sY2hhaW5PdmVydmlld1dpdGgoZGVwczogTWFuYWdlZFRvb2xjaGFpbkRlcHMsIG9yZ0lkOiBzdHJpbmcpOiBQcm9taXNlPE9yZ1Rvb2xjaGFpbk92ZXJ2aWV3PiB7XG4gIGNvbnN0IHNlbGYgPSBvcmdJZC50b0xvd2VyQ2FzZSgpO1xuICBjb25zdCB3YWxrID0gYXdhaXQgZGVwcy5yZWFkKChkYikgPT4gYW55T3JnU2V0dGluZ3MoZGIpKTtcbiAgY29uc3QgY2hhaW4gPSB3YWxrID8gYXdhaXQgdG9vbGNoYWluT3JnQ2hhaW4oc2VsZiwgZGVwcy5nZXRQYXJlbnQpIDogW3NlbGZdO1xuICByZXR1cm4gZGVwcy5yZWFkKGFzeW5jIChkYikgPT4ge1xuICAgIGNvbnN0IHJvd3MgPSBhd2FpdCBkYi5zZWxlY3QoKS5mcm9tKHNjaGVtYS5vcmdUb29sY2hhaW5EZWZhdWx0KVxuICAgICAgLndoZXJlKGluQXJyYXkoc3FsPHN0cmluZz5gbG93ZXIoJHtzY2hlbWEub3JnVG9vbGNoYWluRGVmYXVsdC5vcmdJZH0pYCwgY2hhaW4pKSBhcyBPcmdUb29sY2hhaW5EZWZhdWx0W107XG4gICAgY29uc3QgZGVwdGhPZiA9IChyOiBPcmdUb29sY2hhaW5EZWZhdWx0KSA9PiBjaGFpbi5pbmRleE9mKHIub3JnSWQudG9Mb3dlckNhc2UoKSk7XG4gICAgY29uc3Qgb3duRGVmYXVsdCA9IHJvd3MuZmluZCgocikgPT4gZGVwdGhPZihyKSA9PT0gMCkgPz8gbnVsbDtcbiAgICBjb25zdCBuZWFyZXN0ID0gcm93cy5maWx0ZXIoKHIpID0+IGRlcHRoT2YocikgPj0gMCkuc29ydCgoYSwgYikgPT4gZGVwdGhPZihhKSAtIGRlcHRoT2YoYikpWzBdID8/IG51bGw7XG4gICAgY29uc3QgW2NhbmFyeSwgcGxhdGZvcm1EZWZhdWx0LCByZXNvbHV0aW9uXSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIG5lYXJlc3RPbkNoYWluKGRiLCBzY2hlbWEudG9vbGNoYWluUm9sbG91dCwgY2hhaW4pLFxuICAgICAgY3VycmVudFBsYXRmb3JtRGVmYXVsdChkYiksXG4gICAgICByZXNvbHZlT25DaGFpbihkYiwgY2hhaW4pLFxuICAgIF0pO1xuICAgIHJldHVybiB7XG4gICAgICBjaGFpbixcbiAgICAgIGVmZmVjdGl2ZTogeyByZWxlYXNlVmVyc2lvbjogcmVzb2x1dGlvbi5yZWxlYXNlVmVyc2lvbiwgcmVzb2x2ZWRWaWE6IHJlc29sdXRpb24ucmVzb2x2ZWRWaWEsIHdhcm5pbmdzOiByZXNvbHV0aW9uLndhcm5pbmdzIH0sXG4gICAgICBvd25EZWZhdWx0LFxuICAgICAgaW5oZXJpdGVkRnJvbTogIW93bkRlZmF1bHQgJiYgbmVhcmVzdCA/IHsgb3JnSWQ6IG5lYXJlc3Qub3JnSWQsIHJlbGVhc2VWZXJzaW9uOiBuZWFyZXN0LnJlbGVhc2VWZXJzaW9uIH0gOiBudWxsLFxuICAgICAgY2FuYXJ5UmVsZWFzZTogY2FuYXJ5Py5yZWxlYXNlVmVyc2lvbiA/PyBudWxsLFxuICAgICAgcGxhdGZvcm1EZWZhdWx0LFxuICAgIH07XG4gIH0pO1xufVxuXG4vKipcbiAqIFRoZSBjYWxsZXIgb3JnJ3MgdG9vbGNoYWluIG92ZXJ2aWV3IChlbGV2YXRlZCByZWFkcywgdGhlIHNhbWUgY2hhaW4gd2FsayBhbmRcbiAqIHByZWNlZGVuY2UgYXMge0BsaW5rIHJlc29sdmVNYW5hZ2VkVG9vbGNoYWlufSkuIFRocm93cyB3aGF0IHRoZSByZXNvbHZlclxuICogdGhyb3dzIOKAlCBUT09MQ0hBSU5fTk9fREVGQVVMVCAoNDA5KSB3aGVuIG5vdGhpbmcgcmVzb2x2ZXMgYXQgYWxsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVhZE9yZ1Rvb2xjaGFpbk92ZXJ2aWV3KG9yZ0lkOiBzdHJpbmcpOiBQcm9taXNlPE9yZ1Rvb2xjaGFpbk92ZXJ2aWV3PiB7XG4gIHJldHVybiByZWFkT3JnVG9vbGNoYWluT3ZlcnZpZXdXaXRoKGRlZmF1bHREZXBzLCBvcmdJZCk7XG59XG5cbi8qKiBPbmUgcmVsZWFzZSB0aGUgY2FsbGVyIG1heSBwaW4gb3Igc2V0IChEMTUpLCB3aXRoIHdoYXQgdGhlIHNlbGVjdG9ycyBzaG93LiAqL1xuZXhwb3J0IGludGVyZmFjZSBFbGlnaWJsZVRvb2xjaGFpblJlbGVhc2Uge1xuICByZWxlYXNlVmVyc2lvbjogc3RyaW5nO1xuICByZWxlYXNlOiBUb29sY2hhaW5SZWxlYXNlO1xuICBib290c3RyYXA6IFBsdWdpbjtcbiAgc3ludGg6IFBsdWdpbjtcbiAgLyoqIFRIRSBwbGF0Zm9ybSBkZWZhdWx0IG5vdy4gKi9cbiAgaXNQbGF0Zm9ybURlZmF1bHQ6IGJvb2xlYW47XG4gIC8qKiBUaGUgY2FsbGVyJ3MgY2FuYXJ5IHJlbGVhc2UgKG5lYXJlc3QgbWVtYmVyc2hpcCkuICovXG4gIGlzQ2FuYXJ5OiBib29sZWFuO1xufVxuXG4vKioge0BsaW5rIGxpc3RFbGlnaWJsZVJlbGVhc2VzfSB3aXRoIGluamVjdGVkIHJlYWRzIGFuZCBoaWVyYXJjaHkgKHRlc3RzKS4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBsaXN0RWxpZ2libGVSZWxlYXNlc1dpdGgoZGVwczogTWFuYWdlZFRvb2xjaGFpbkRlcHMsIG9yZ0lkOiBzdHJpbmcpOiBQcm9taXNlPHsgcGxhdGZvcm1EZWZhdWx0OiBzdHJpbmcgfCBudWxsOyByZWxlYXNlczogRWxpZ2libGVUb29sY2hhaW5SZWxlYXNlW10gfT4ge1xuICBjb25zdCBzZWxmID0gb3JnSWQudG9Mb3dlckNhc2UoKTtcbiAgY29uc3Qgd2FsayA9IGF3YWl0IGRlcHMucmVhZCgoZGIpID0+IGFueU9yZ1NldHRpbmdzKGRiKSk7XG4gIGNvbnN0IGNoYWluID0gd2FsayA/IGF3YWl0IHRvb2xjaGFpbk9yZ0NoYWluKHNlbGYsIGRlcHMuZ2V0UGFyZW50KSA6IFtzZWxmXTtcbiAgcmV0dXJuIGRlcHMucmVhZChhc3luYyAoZGIpID0+IHtcbiAgICBjb25zdCBbcmVsZWFzZXMsIHJvd3MsIGhpc3RvcnksIHBsYXRmb3JtRGVmYXVsdCwgY2FuYXJ5XSA9IGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIGRiLnNlbGVjdCgpLmZyb20oc2NoZW1hLnRvb2xjaGFpblJlbGVhc2UpIGFzIFByb21pc2U8VG9vbGNoYWluUmVsZWFzZVtdPixcbiAgICAgIGRiLnNlbGVjdCgpLmZyb20oc2NoZW1hLnBsdWdpbikud2hlcmUoYW5kKFxuICAgICAgICBzcWxgbG93ZXIoJHtzY2hlbWEucGx1Z2luLm9yZ0lkfSkgPSAke1NZU1RFTV9PUkdfSUR9YCxcbiAgICAgICAgaW5BcnJheShzY2hlbWEucGx1Z2luLm5hbWUsIFsuLi5NQU5BR0VEX1RPT0xDSEFJTl9QTFVHSU5TXSksXG4gICAgICAgIGlzTnVsbChzY2hlbWEucGx1Z2luLmRlbGV0ZWRBdCksXG4gICAgICApKSBhcyBQcm9taXNlPFBsdWdpbltdPixcbiAgICAgIGRiLnNlbGVjdCh7IHJlbGVhc2VWZXJzaW9uOiBzY2hlbWEudG9vbGNoYWluRGVmYXVsdEhpc3RvcnkucmVsZWFzZVZlcnNpb24gfSkuZnJvbShzY2hlbWEudG9vbGNoYWluRGVmYXVsdEhpc3RvcnkpIGFzIFByb21pc2U8QXJyYXk8eyByZWxlYXNlVmVyc2lvbjogc3RyaW5nIH0+PixcbiAgICAgIGN1cnJlbnRQbGF0Zm9ybURlZmF1bHQoZGIpLFxuICAgICAgbmVhcmVzdE9uQ2hhaW4oZGIsIHNjaGVtYS50b29sY2hhaW5Sb2xsb3V0LCBjaGFpbiksXG4gICAgXSk7XG4gICAgY29uc3QgcHJvbW90ZWQgPSBuZXcgU2V0KGhpc3RvcnkubWFwKChoKSA9PiBoLnJlbGVhc2VWZXJzaW9uKSk7XG4gICAgaWYgKHBsYXRmb3JtRGVmYXVsdCkgcHJvbW90ZWQuYWRkKHBsYXRmb3JtRGVmYXVsdCk7XG4gICAgY29uc3Qgb3V0OiBFbGlnaWJsZVRvb2xjaGFpblJlbGVhc2VbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgcmVsZWFzZSBvZiByZWxlYXNlcykge1xuICAgICAgY29uc3QgdiA9IHJlbGVhc2UucmVsZWFzZVZlcnNpb247XG4gICAgICBjb25zdCBoYWx2ZXM6IFJlbGVhc2VIYWx2ZXMgPSB7XG4gICAgICAgIHJlbGVhc2VWZXJzaW9uOiB2LFxuICAgICAgICByZWxlYXNlLFxuICAgICAgICBib290c3RyYXA6IHJvd3MuZmluZCgocCkgPT4gcC5uYW1lID09PSBCT09UU1RSQVAgJiYgcC52ZXJzaW9uID09PSB2KSA/PyBudWxsLFxuICAgICAgICBzeW50aDogcm93cy5maW5kKChwKSA9PiBwLm5hbWUgPT09IFNZTlRIICYmIHAudmVyc2lvbiA9PT0gdikgPz8gbnVsbCxcbiAgICAgIH07XG4gICAgICBpZiAoIXJlbGVhc2VFeGlzdHMoaGFsdmVzKSB8fCByZWxlYXNlTGlmZWN5Y2xlUHJvYmxlbXMoaGFsdmVzKS5sZW5ndGggPiAwKSBjb250aW51ZTtcbiAgICAgIGNvbnN0IGlzQ2FuYXJ5ID0gY2FuYXJ5Py5yZWxlYXNlVmVyc2lvbiA9PT0gdjtcbiAgICAgIGlmICghcHJvbW90ZWQuaGFzKHYpICYmICFpc0NhbmFyeSkgY29udGludWU7XG4gICAgICBvdXQucHVzaCh7IHJlbGVhc2VWZXJzaW9uOiB2LCByZWxlYXNlLCBib290c3RyYXA6IGhhbHZlcy5ib290c3RyYXAsIHN5bnRoOiBoYWx2ZXMuc3ludGgsIGlzUGxhdGZvcm1EZWZhdWx0OiBwbGF0Zm9ybURlZmF1bHQgPT09IHYsIGlzQ2FuYXJ5IH0pO1xuICAgIH1cbiAgICBvdXQuc29ydCgoYSwgYikgPT4gY29tcGFyZVNlbXZlcihiLnJlbGVhc2VWZXJzaW9uLCBhLnJlbGVhc2VWZXJzaW9uKSk7XG4gICAgcmV0dXJuIHsgcGxhdGZvcm1EZWZhdWx0LCByZWxlYXNlczogb3V0IH07XG4gIH0pO1xufVxuXG4vKipcbiAqIEV2ZXJ5IHJlbGVhc2UgYG9yZ0lkYCBtYXkgU0VUIGFzIGEgcGlwZWxpbmUgcGluIG9yIGl0cyBvcmcgZGVmYXVsdCAoRDE1LCB0aGVcbiAqIHNhbWUgcnVsZSBhcyB7QGxpbmsgaXNFbGlnaWJsZVJlbGVhc2V9KSwgbmV3ZXN0IGZpcnN0LiBOZXZlciBhbm90aGVyIG9yZydzXG4gKiBkYXRhOiBhIGNhbmFyeSBhcHBlYXJzIG9ubHkgd2hlbiBpdCBpcyB0aGUgY2FsbGVyJ3Mgb3duIChuZWFyZXN0KSBtZW1iZXJzaGlwLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbGlzdEVsaWdpYmxlUmVsZWFzZXMob3JnSWQ6IHN0cmluZyk6IFByb21pc2U8eyBwbGF0Zm9ybURlZmF1bHQ6IHN0cmluZyB8IG51bGw7IHJlbGVhc2VzOiBFbGlnaWJsZVRvb2xjaGFpblJlbGVhc2VbXSB9PiB7XG4gIHJldHVybiBsaXN0RWxpZ2libGVSZWxlYXNlc1dpdGgoZGVmYXVsdERlcHMsIG9yZ0lkKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIENhbGxlciBoZWxwZXJzXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKiogVGhlIHJlc29sdmVyJ3MgZXJyb3IgYXMgdGhlIHJlZnVzYWwgc2hhcGUgc3RlcCByZXNvbHV0aW9uIHJlcG9ydHMgKGNvbnRyYWN0IGNoZWNrLCBkZWNsYXJlZCBzaWRlLCBmYWN0cykuICovXG5leHBvcnQgZnVuY3Rpb24gbWFuYWdlZFRvb2xjaGFpblJlZnVzYWwoZXJyOiBNYW5hZ2VkVG9vbGNoYWluRXJyb3IpOiBSZXNvbHV0aW9uUmVmdXNhbCB7XG4gIHN3aXRjaCAoZXJyLmNvZGUpIHtcbiAgICBjYXNlIEVycm9yQ29kZS5OT1RfRk9VTkQ6XG4gICAgICByZXR1cm4geyBjb2RlOiAnTk9UX0ZPVU5EJywgcmVhc29uOiAndG9vbGNoYWluX3JlbGVhc2Vfbm90X2ZvdW5kJywgbWVzc2FnZTogZXJyLm1lc3NhZ2UsIC4uLihlcnIuZGV0YWlscyA/IHsgZGV0YWlsczogZXJyLmRldGFpbHMgfSA6IHt9KSB9O1xuICAgIGNhc2UgRXJyb3JDb2RlLlZBTElEQVRJT05fRVJST1I6XG4gICAgICByZXR1cm4geyBjb2RlOiAnTk9UX0ZPVU5EJywgcmVhc29uOiAndG9vbGNoYWluX3JlbGVhc2VfaW52YWxpZCcsIG1lc3NhZ2U6IGVyci5tZXNzYWdlLCAuLi4oZXJyLmRldGFpbHMgPyB7IGRldGFpbHM6IGVyci5kZXRhaWxzIH0gOiB7fSkgfTtcbiAgICBjYXNlIEVycm9yQ29kZS5UT09MQ0hBSU5fTk9fREVGQVVMVDpcbiAgICAgIHJldHVybiB7IGNvZGU6ICdQTFVHSU5fVU5BVkFJTEFCTEUnLCByZWFzb246ICd0b29sY2hhaW5fbm9fZGVmYXVsdCcsIG1lc3NhZ2U6IGVyci5tZXNzYWdlIH07XG4gICAgZGVmYXVsdDpcbiAgICAgIHJldHVybiB7IGNvZGU6ICdQTFVHSU5fVU5BVkFJTEFCTEUnLCByZWFzb246ICd0b29sY2hhaW5fdW5yZXNvbHZlZCcsIG1lc3NhZ2U6IGVyci5tZXNzYWdlLCAuLi4oZXJyLmRldGFpbHMgPyB7IGRldGFpbHM6IGVyci5kZXRhaWxzIH0gOiB7fSkgfTtcbiAgfVxufVxuXG4vKipcbiAqIFJlc29sdmUgT05FIG1hbmFnZWQgaGFsZiBmb3IgYSBzdGVwOiB0aGUgcGx1Z2luIHJvdyBwbHVzIHRoZSByZXNvbHV0aW9uLCBvclxuICogdGhlIHJlZnVzYWwuIEFueSBub24tcmVzb2x2ZXIgZXJyb3IgKGEgZGF0YWJhc2Ugb3IgaGllcmFyY2h5IGZhaWx1cmUpXG4gKiBwcm9wYWdhdGVzLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZU1hbmFnZWRUb29sY2hhaW5IYWxmKFxuICBjYWxsZXI6IE1hbmFnZWRUb29sY2hhaW5DYWxsZXIsXG4gIG5hbWU6IE1hbmFnZWRUb29sY2hhaW5QbHVnaW4sXG4gIG9wdHM6IHsgcmVsZWFzZVBpbj86IHN0cmluZyB9ID0ge30sXG4pOiBQcm9taXNlPHsgcGx1Z2luOiBQbHVnaW47IHJlc29sdXRpb246IE1hbmFnZWRUb29sY2hhaW5SZXNvbHV0aW9uIH0gfCB7IHJlZnVzYWw6IFJlc29sdXRpb25SZWZ1c2FsOyBlcnJvcjogTWFuYWdlZFRvb2xjaGFpbkVycm9yIH0+IHtcbiAgdHJ5IHtcbiAgICBjb25zdCByZXNvbHV0aW9uID0gYXdhaXQgcmVzb2x2ZU1hbmFnZWRUb29sY2hhaW4oY2FsbGVyLCBvcHRzKTtcbiAgICByZXR1cm4geyBwbHVnaW46IG5hbWUgPT09IEJPT1RTVFJBUCA/IHJlc29sdXRpb24uYm9vdHN0cmFwIDogcmVzb2x1dGlvbi5zeW50aCwgcmVzb2x1dGlvbiB9O1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBpZiAoZXJyIGluc3RhbmNlb2YgTWFuYWdlZFRvb2xjaGFpbkVycm9yKSByZXR1cm4geyByZWZ1c2FsOiBtYW5hZ2VkVG9vbGNoYWluUmVmdXNhbChlcnIpLCBlcnJvcjogZXJyIH07XG4gICAgdGhyb3cgZXJyO1xuICB9XG59XG4iXX0=