@pipeline-builder/api-core 4.1.2 → 4.1.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/README.md +3 -3
  2. package/lib/errors/app-errors.d.ts +0 -4
  3. package/lib/errors/app-errors.js +1 -8
  4. package/lib/helpers/restore-helpers.d.ts +3 -3
  5. package/lib/helpers/restore-helpers.js +4 -4
  6. package/lib/helpers/sse-helpers.d.ts +8 -1
  7. package/lib/helpers/sse-helpers.js +11 -3
  8. package/lib/middleware/auth.d.ts +174 -43
  9. package/lib/middleware/auth.js +384 -179
  10. package/lib/middleware/index.d.ts +1 -0
  11. package/lib/middleware/index.js +2 -1
  12. package/lib/middleware/route-table.d.ts +104 -0
  13. package/lib/middleware/route-table.js +230 -0
  14. package/lib/middleware/step-up.d.ts +48 -16
  15. package/lib/middleware/step-up.js +74 -36
  16. package/lib/services/api-key-exchange.d.ts +25 -0
  17. package/lib/services/api-key-exchange.js +219 -0
  18. package/lib/services/audit-spool.d.ts +2 -3
  19. package/lib/services/audit-spool.js +3 -4
  20. package/lib/services/cache-service.d.ts +65 -21
  21. package/lib/services/cache-service.js +173 -78
  22. package/lib/services/compliance-event-subscriber.d.ts +5 -4
  23. package/lib/services/compliance-event-subscriber.js +8 -6
  24. package/lib/services/durable-event-bus.d.ts +22 -39
  25. package/lib/services/durable-event-bus.js +109 -47
  26. package/lib/services/env-redis.d.ts +114 -35
  27. package/lib/services/env-redis.js +215 -73
  28. package/lib/services/http-client.d.ts +10 -15
  29. package/lib/services/http-client.js +32 -27
  30. package/lib/services/index.d.ts +3 -0
  31. package/lib/services/index.js +4 -1
  32. package/lib/services/jwks-cache.d.ts +102 -0
  33. package/lib/services/jwks-cache.js +222 -0
  34. package/lib/services/leader-lock.d.ts +6 -3
  35. package/lib/services/leader-lock.js +20 -5
  36. package/lib/services/quota.d.ts +44 -10
  37. package/lib/services/quota.js +95 -51
  38. package/lib/services/remote-audit-client.d.ts +1 -1
  39. package/lib/services/remote-audit-client.js +32 -1
  40. package/lib/services/scheduler.d.ts +2 -3
  41. package/lib/services/scheduler.js +2 -2
  42. package/lib/services/service-boot.d.ts +4 -2
  43. package/lib/services/service-boot.js +7 -3
  44. package/lib/services/service-keys.d.ts +83 -0
  45. package/lib/services/service-keys.js +354 -0
  46. package/lib/services/sse-ticket-store.d.ts +55 -22
  47. package/lib/services/sse-ticket-store.js +122 -79
  48. package/lib/services/token-revocation.d.ts +1 -1
  49. package/lib/services/token-revocation.js +31 -19
  50. package/lib/testing/route-coverage.d.ts +64 -0
  51. package/lib/testing/route-coverage.js +183 -0
  52. package/lib/testing/service-tokens.d.ts +66 -0
  53. package/lib/testing/service-tokens.js +137 -0
  54. package/lib/testing/tier-mock.d.ts +2 -2
  55. package/lib/testing/tier-mock.js +3 -3
  56. package/lib/testing/user-tokens.d.ts +75 -0
  57. package/lib/testing/user-tokens.js +115 -0
  58. package/lib/types/catalog-metadata.d.ts +0 -2
  59. package/lib/types/catalog-metadata.js +1 -3
  60. package/lib/types/common.d.ts +103 -4
  61. package/lib/types/common.js +11 -1
  62. package/lib/types/error-codes.d.ts +15 -0
  63. package/lib/types/error-codes.js +22 -1
  64. package/lib/types/permissions.d.ts +35 -1
  65. package/lib/types/permissions.js +70 -2
  66. package/lib/utils/api-key.d.ts +34 -0
  67. package/lib/utils/api-key.js +75 -0
  68. package/lib/utils/env.d.ts +0 -2
  69. package/lib/utils/env.js +1 -6
  70. package/lib/utils/index.d.ts +3 -0
  71. package/lib/utils/index.js +4 -1
  72. package/lib/utils/jwk.d.ts +98 -0
  73. package/lib/utils/jwk.js +139 -0
  74. package/lib/utils/logger.d.ts +4 -1
  75. package/lib/utils/logger.js +1 -22
  76. package/lib/utils/secret-encryption.d.ts +7 -2
  77. package/lib/utils/secret-encryption.js +47 -4
  78. package/lib/utils/secret-rotation.d.ts +17 -0
  79. package/lib/utils/secret-rotation.js +54 -0
  80. package/lib/validation/common-schemas.js +5 -4
  81. package/package.json +20 -1
@@ -1,130 +1,173 @@
1
1
  // Copyright 2026 Pipeline Builder Contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
  import crypto from 'crypto';
4
- import { createEnvRedisClient } from './env-redis.js';
4
+ import { createEnvRedisClient, createRedisReadyGate } from './env-redis.js';
5
5
  import { createLogger } from '../utils/logger.js';
6
6
  const logger = createLogger('sse-ticket-store');
7
- /** Redis key namespaces. Ticket → orgId; windowed issue counters bound abuse. */
8
- const TICKET_KEY_PREFIX = 'sse:tk:';
9
- const ORG_COUNT_PREFIX = 'sse:tkc:';
10
- const TOTAL_COUNT_KEY = 'sse:tkc:__all__';
11
7
  function newTicketId() {
12
8
  return crypto.randomBytes(24).toString('base64url');
13
9
  }
14
- /**
15
- * In-memory backend — the original single-process behaviour. Counts LIVE
16
- * (unexpired) tickets per org and evicts expired entries on a timer. Correct
17
- * only within one process, so it is the fallback used when Redis isn't configured.
18
- */
19
- function createInMemorySseTicketStore(config) {
20
- const store = new Map();
21
- const cleanup = setInterval(() => {
10
+ function errMsg(err) {
11
+ return err instanceof Error ? err.message : String(err);
12
+ }
13
+ /** In-memory backend — single-process fallback when Redis isn't configured. */
14
+ export function createMemorySseTicketStore(config) {
15
+ const tickets = new Map();
16
+ const owners = new Map();
17
+ const sweep = () => {
22
18
  const now = Date.now();
23
- for (const [id, t] of store)
24
- if (now > t.expiresAt)
25
- store.delete(id);
26
- }, config.ttlMs);
27
- cleanup.unref();
28
- function countLiveForOrg(orgId, now) {
29
- let count = 0;
30
- for (const t of store.values())
31
- if (t.orgId === orgId && t.expiresAt > now)
32
- count++;
33
- return count;
34
- }
19
+ for (const [id, t] of tickets)
20
+ if (now >= t.expiresAt)
21
+ tickets.delete(id);
22
+ for (const [id, o] of owners)
23
+ if (now >= o.expiresAt)
24
+ owners.delete(id);
25
+ };
26
+ const timer = setInterval(sweep, Math.max(1_000, config.ttlMs));
27
+ timer.unref();
35
28
  return {
36
- async issue(orgId) {
37
- const now = Date.now();
38
- if (store.size >= config.maxTotal)
29
+ async issue(orgId, subject) {
30
+ sweep();
31
+ if (tickets.size >= config.maxTotal)
39
32
  return { ok: false, reason: 'total' };
40
- if (countLiveForOrg(orgId, now) >= config.maxPerOrg)
33
+ let forOrg = 0;
34
+ for (const t of tickets.values())
35
+ if (t.orgId === orgId)
36
+ forOrg++;
37
+ if (forOrg >= config.maxPerOrg)
41
38
  return { ok: false, reason: 'org' };
42
39
  const ticket = newTicketId();
43
- store.set(ticket, { orgId, expiresAt: now + config.ttlMs });
40
+ tickets.set(ticket, { orgId, ...(subject !== undefined && { subject }), expiresAt: Date.now() + config.ttlMs });
44
41
  return { ok: true, ticket };
45
42
  },
46
43
  async consume(ticketId) {
47
- const t = store.get(ticketId);
48
- store.delete(ticketId); // single-use — consume immediately
49
- if (!t || Date.now() > t.expiresAt)
44
+ const t = tickets.get(ticketId);
45
+ tickets.delete(ticketId); // single-use — gone whether or not it was valid
46
+ if (!t || Date.now() >= t.expiresAt)
50
47
  return null;
51
- return { orgId: t.orgId };
48
+ return { orgId: t.orgId, ...(t.subject !== undefined && { subject: t.subject }) };
49
+ },
50
+ async bindOwner(subject, orgId, ttlMs) {
51
+ owners.set(subject, { orgId, expiresAt: Date.now() + ttlMs });
52
+ },
53
+ async getOwner(subject) {
54
+ const o = owners.get(subject);
55
+ if (!o)
56
+ return null;
57
+ if (Date.now() >= o.expiresAt) {
58
+ owners.delete(subject);
59
+ return null;
60
+ }
61
+ return o.orgId;
52
62
  },
53
- stop() { clearInterval(cleanup); },
63
+ stop() { clearInterval(timer); },
54
64
  };
55
65
  }
56
66
  /**
57
- * Redis backend — multi-replica safe. Tickets live under a TTL'd key so any pod
58
- * can redeem one; {@link SseTicketStore.consume} uses GETDEL so redemption is
59
- * atomic (two pods can't both spend the same ticket). The per-org / global caps
60
- * become windowed rate limits (max mints per TTL window) via INCR + first-hit
61
- * EXPIRE — equivalent abuse bounding to the in-memory live-count, and it also
62
- * caps churn.
67
+ * Atomic live-count issue. Prunes expired members from both cap sets, checks the
68
+ * total then the per-org cap, and only then stores the ticket and records it in
69
+ * both sets — so concurrent mints can't overshoot a cap and a cap can never
70
+ * stick (every member carries its own expiry score and every key a TTL).
63
71
  *
64
- * Fail-CLOSED by design (unlike the fail-open token-revocation reader): if Redis
65
- * errors, `issue` returns a cap rejection and `consume` returns null, so a Redis
66
- * outage degrades to "no live notifications" rather than handing out or
67
- * accepting unvalidated tickets. SSE notifications are non-critical, so failing
68
- * closed here costs only real-time delivery, never correctness.
72
+ * KEYS: total zset, org zset, ticket key.
73
+ * ARGV: ttlMs, maxTotal, maxPerOrg, ticketId, record JSON.
74
+ * Uses the server clock so every pod agrees on "expired".
69
75
  */
70
- function createRedisSseTicketStore(redis, config) {
71
- const ttlSec = Math.max(1, Math.ceil(config.ttlMs / 1000));
72
- // Per-channel namespace so two services' ticket stores don't share keys.
76
+ const ISSUE_SCRIPT = `
77
+ local t = redis.call('TIME')
78
+ local now = tonumber(t[1]) * 1000 + math.floor(tonumber(t[2]) / 1000)
79
+ local ttl = tonumber(ARGV[1])
80
+ redis.call('ZREMRANGEBYSCORE', KEYS[1], '-inf', now)
81
+ redis.call('ZREMRANGEBYSCORE', KEYS[2], '-inf', now)
82
+ if redis.call('ZCARD', KEYS[1]) >= tonumber(ARGV[2]) then return 'total' end
83
+ if redis.call('ZCARD', KEYS[2]) >= tonumber(ARGV[3]) then return 'org' end
84
+ redis.call('SET', KEYS[3], ARGV[5], 'PX', ttl)
85
+ redis.call('ZADD', KEYS[1], now + ttl, ARGV[4])
86
+ redis.call('ZADD', KEYS[2], now + ttl, ARGV[4])
87
+ redis.call('PEXPIRE', KEYS[1], ttl)
88
+ redis.call('PEXPIRE', KEYS[2], ttl)
89
+ return 'ok'`;
90
+ /**
91
+ * Redis backend — multi-replica safe.
92
+ *
93
+ * Fail-CLOSED: a Redis error makes `issue` reject (`total`), `consume` return
94
+ * null and `getOwner` throw, so an outage degrades to "no live stream" rather
95
+ * than handing out or accepting unvalidated tickets. `bindOwner` is best-effort.
96
+ */
97
+ export function createRedisSseTicketStore(redis, config) {
73
98
  const ns = config.keyPrefix ? `${config.keyPrefix}:` : '';
74
- const ticketKey = (t) => `${ns}${TICKET_KEY_PREFIX}${t}`;
75
- const orgCountKey = (o) => `${ns}${ORG_COUNT_PREFIX}${o}`;
76
- const totalCountKey = `${ns}${TOTAL_COUNT_KEY}`;
77
- // Windowed counter: INCR, and on the first hit of a window set the TTL so it
78
- // auto-resets. Returns true while still within `limit` for this window.
79
- async function withinWindow(key, limit) {
80
- const n = await redis.incr(key);
81
- if (n === 1)
82
- await redis.expire(key, ttlSec);
83
- return n <= limit;
84
- }
99
+ const ticketKey = (t) => `${ns}sse:tk:${t}`;
100
+ const orgSetKey = (o) => `${ns}sse:tkz:org:${o}`;
101
+ const totalSetKey = `${ns}sse:tkz:all`;
102
+ const ownerKey = (s) => `${ns}sse:owner:${s}`;
103
+ const ttlMs = Math.max(1, Math.ceil(config.ttlMs));
104
+ // The env client has no offline queue: wait (bounded) for the first connection
105
+ // so the first mint/redeem after boot isn't rejected outright.
106
+ const ready = createRedisReadyGate(redis);
85
107
  return {
86
- async issue(orgId) {
108
+ async issue(orgId, subject) {
87
109
  try {
88
- if (!(await withinWindow(totalCountKey, config.maxTotal)))
89
- return { ok: false, reason: 'total' };
90
- if (!(await withinWindow(orgCountKey(orgId), config.maxPerOrg)))
91
- return { ok: false, reason: 'org' };
110
+ await ready();
92
111
  const ticket = newTicketId();
93
- await redis.set(ticketKey(ticket), orgId, 'EX', ttlSec);
94
- return { ok: true, ticket };
112
+ const record = { orgId, ...(subject !== undefined && { subject }) };
113
+ const outcome = await redis.eval(ISSUE_SCRIPT, 3, totalSetKey, orgSetKey(orgId), ticketKey(ticket), ttlMs, config.maxTotal, config.maxPerOrg, ticket, JSON.stringify(record));
114
+ if (outcome === 'ok')
115
+ return { ok: true, ticket };
116
+ return { ok: false, reason: outcome === 'org' ? 'org' : 'total' };
95
117
  }
96
118
  catch (err) {
97
- logger.warn('SSE ticket issue failed (fail-closed)', { error: err instanceof Error ? err.message : String(err) });
119
+ logger.warn('SSE ticket issue failed (fail-closed)', { error: errMsg(err) });
98
120
  return { ok: false, reason: 'total' };
99
121
  }
100
122
  },
101
123
  async consume(ticketId) {
102
124
  try {
103
- const orgId = await redis.getdel(ticketKey(ticketId));
104
- return orgId ? { orgId } : null;
125
+ await ready();
126
+ const raw = await redis.getdel(ticketKey(ticketId));
127
+ if (!raw)
128
+ return null;
129
+ const rec = JSON.parse(raw);
130
+ if (typeof rec?.orgId !== 'string')
131
+ return null;
132
+ // Free the live-count slots now rather than at expiry. Best-effort: a
133
+ // failure here only delays the slot until the member's expiry score.
134
+ await Promise.all([redis.zrem(orgSetKey(rec.orgId), ticketId), redis.zrem(totalSetKey, ticketId)])
135
+ .catch((err) => logger.debug('SSE ticket slot release failed', { error: errMsg(err) }));
136
+ return rec;
105
137
  }
106
138
  catch (err) {
107
- logger.warn('SSE ticket consume failed (fail-closed)', { error: err instanceof Error ? err.message : String(err) });
139
+ logger.warn('SSE ticket consume failed (fail-closed)', { error: errMsg(err) });
108
140
  return null;
109
141
  }
110
142
  },
143
+ async bindOwner(subject, orgId, ownerTtlMs) {
144
+ try {
145
+ await ready();
146
+ await redis.set(ownerKey(subject), orgId, 'PX', Math.max(1, Math.ceil(ownerTtlMs)));
147
+ }
148
+ catch (err) {
149
+ logger.warn('SSE stream-owner bind failed', { error: errMsg(err) });
150
+ }
151
+ },
152
+ async getOwner(subject) {
153
+ await ready();
154
+ return redis.get(ownerKey(subject));
155
+ },
111
156
  stop() { },
112
157
  };
113
158
  }
114
159
  /**
115
160
  * Build an {@link SseTicketStore} from the standard Redis env (`REDIS_URL` or
116
- * `REDIS_HOST`/`REDIS_PORT`). Uses the Redis backend when configured
117
- * (multi-replica safe), otherwise falls back to the in-memory single-process
118
- * backend. A service opts in with one boot line:
119
- * `const tickets = createEnvSseTicketStore({ ttlMs, maxTotal, maxPerOrg });`
161
+ * `REDIS_SENTINELS`): the Redis backend when configured (multi-replica safe),
162
+ * otherwise the in-memory single-process backend.
120
163
  */
121
164
  export function createEnvSseTicketStore(config) {
122
165
  const redis = createEnvRedisClient('sse-ticket');
123
166
  if (redis) {
124
- logger.info('SSE ticket store: Redis backend (multi-replica)');
167
+ logger.info('SSE ticket store: Redis backend (multi-replica)', { keyPrefix: config.keyPrefix });
125
168
  return createRedisSseTicketStore(redis, config);
126
169
  }
127
- logger.info('SSE ticket store: in-memory backend (single-process fallback)');
128
- return createInMemorySseTicketStore(config);
170
+ logger.info('SSE ticket store: in-memory backend (single-process fallback)', { keyPrefix: config.keyPrefix });
171
+ return createMemorySseTicketStore(config);
129
172
  }
130
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3NlLXRpY2tldC1zdG9yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy9zc2UtdGlja2V0LXN0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBRTVCLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUVsRCxNQUFNLE1BQU0sR0FBRyxZQUFZLENBQUMsa0JBQWtCLENBQUMsQ0FBQztBQUVoRCxpRkFBaUY7QUFDakYsTUFBTSxpQkFBaUIsR0FBRyxTQUFTLENBQUM7QUFDcEMsTUFBTSxnQkFBZ0IsR0FBRyxVQUFVLENBQUM7QUFDcEMsTUFBTSxlQUFlLEdBQUcsaUJBQWlCLENBQUM7QUFrRDFDLFNBQVMsV0FBVztJQUNsQixPQUFPLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQ3RELENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsU0FBUyw0QkFBNEIsQ0FBQyxNQUE0QjtJQUVoRSxNQUFNLEtBQUssR0FBRyxJQUFJLEdBQUcsRUFBaUIsQ0FBQztJQUV2QyxNQUFNLE9BQU8sR0FBRyxXQUFXLENBQUMsR0FBRyxFQUFFO1FBQy9CLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUN2QixLQUFLLE1BQU0sQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksS0FBSztZQUFFLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQyxTQUFTO2dCQUFFLEtBQUssQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDdkUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUNqQixPQUFPLENBQUMsS0FBSyxFQUFFLENBQUM7SUFFaEIsU0FBUyxlQUFlLENBQUMsS0FBYSxFQUFFLEdBQVc7UUFDakQsSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ2QsS0FBSyxNQUFNLENBQUMsSUFBSSxLQUFLLENBQUMsTUFBTSxFQUFFO1lBQUUsSUFBSSxDQUFDLENBQUMsS0FBSyxLQUFLLEtBQUssSUFBSSxDQUFDLENBQUMsU0FBUyxHQUFHLEdBQUc7Z0JBQUUsS0FBSyxFQUFFLENBQUM7UUFDcEYsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRUQsT0FBTztRQUNMLEtBQUssQ0FBQyxLQUFLLENBQUMsS0FBYTtZQUN2QixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDdkIsSUFBSSxLQUFLLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxRQUFRO2dCQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsQ0FBQztZQUN6RSxJQUFJLGVBQWUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLElBQUksTUFBTSxDQUFDLFNBQVM7Z0JBQUUsT0FBTyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxDQUFDO1lBQ3pGLE1BQU0sTUFBTSxHQUFHLFdBQVcsRUFBRSxDQUFDO1lBQzdCLEtBQUssQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLEVBQUUsS0FBSyxFQUFFLFNBQVMsRUFBRSxHQUFHLEdBQUcsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDNUQsT0FBTyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUM7UUFDOUIsQ0FBQztRQUNELEtBQUssQ0FBQyxPQUFPLENBQUMsUUFBZ0I7WUFDNUIsTUFBTSxDQUFDLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUM5QixLQUFLLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsbUNBQW1DO1lBQzNELElBQUksQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQyxTQUFTO2dCQUFFLE9BQU8sSUFBSSxDQUFDO1lBQ2hELE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDO1FBQzVCLENBQUM7UUFDRCxJQUFJLEtBQVcsYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztLQUN6QyxDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxTQUFTLHlCQUF5QixDQUFDLEtBQWUsRUFBRSxNQUE0QjtJQUM5RSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUMzRCx5RUFBeUU7SUFDekUsTUFBTSxFQUFFLEdBQUcsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUMxRCxNQUFNLFNBQVMsR0FBRyxDQUFDLENBQVMsRUFBRSxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsaUJBQWlCLEdBQUcsQ0FBQyxFQUFFLENBQUM7SUFDakUsTUFBTSxXQUFXLEdBQUcsQ0FBQyxDQUFTLEVBQUUsRUFBRSxDQUFDLEdBQUcsRUFBRSxHQUFHLGdCQUFnQixHQUFHLENBQUMsRUFBRSxDQUFDO0lBQ2xFLE1BQU0sYUFBYSxHQUFHLEdBQUcsRUFBRSxHQUFHLGVBQWUsRUFBRSxDQUFDO0lBRWhELDZFQUE2RTtJQUM3RSx3RUFBd0U7SUFDeEUsS0FBSyxVQUFVLFlBQVksQ0FBQyxHQUFXLEVBQUUsS0FBYTtRQUNwRCxNQUFNLENBQUMsR0FBRyxNQUFNLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDaEMsSUFBSSxDQUFDLEtBQUssQ0FBQztZQUFFLE1BQU0sS0FBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDN0MsT0FBTyxDQUFDLElBQUksS0FBSyxDQUFDO0lBQ3BCLENBQUM7SUFFRCxPQUFPO1FBQ0wsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFhO1lBQ3ZCLElBQUksQ0FBQztnQkFDSCxJQUFJLENBQUMsQ0FBQyxNQUFNLFlBQVksQ0FBQyxhQUFhLEVBQUUsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO29CQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsQ0FBQztnQkFDakcsSUFBSSxDQUFDLENBQUMsTUFBTSxZQUFZLENBQUMsV0FBVyxDQUFDLEtBQUssQ0FBQyxFQUFFLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztvQkFBRSxPQUFPLEVBQUUsRUFBRSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUM7Z0JBQ3JHLE1BQU0sTUFBTSxHQUFHLFdBQVcsRUFBRSxDQUFDO2dCQUM3QixNQUFNLEtBQUssQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUM7Z0JBQ3hELE9BQU8sRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBRSxDQUFDO1lBQzlCLENBQUM7WUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUNiLE1BQU0sQ0FBQyxJQUFJLENBQUMsdUNBQXVDLEVBQUUsRUFBRSxLQUFLLEVBQUUsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDbEgsT0FBTyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxDQUFDO1lBQ3hDLENBQUM7UUFDSCxDQUFDO1FBQ0QsS0FBSyxDQUFDLE9BQU8sQ0FBQyxRQUFnQjtZQUM1QixJQUFJLENBQUM7Z0JBQ0gsTUFBTSxLQUFLLEdBQUcsTUFBTSxLQUFLLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDO2dCQUN0RCxPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ2xDLENBQUM7WUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUNiLE1BQU0sQ0FBQyxJQUFJLENBQUMseUNBQXlDLEVBQUUsRUFBRSxLQUFLLEVBQUUsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztnQkFDcEgsT0FBTyxJQUFJLENBQUM7WUFDZCxDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksS0FBMEUsQ0FBQztLQUNoRixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSx1QkFBdUIsQ0FBQyxNQUE0QjtJQUNsRSxNQUFNLEtBQUssR0FBRyxvQkFBb0IsQ0FBVyxZQUFZLENBQUMsQ0FBQztJQUMzRCxJQUFJLEtBQUssRUFBRSxDQUFDO1FBQ1YsTUFBTSxDQUFDLElBQUksQ0FBQyxpREFBaUQsQ0FBQyxDQUFDO1FBQy9ELE9BQU8seUJBQXlCLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQ2xELENBQUM7SUFDRCxNQUFNLENBQUMsSUFBSSxDQUFDLCtEQUErRCxDQUFDLENBQUM7SUFDN0UsT0FBTyw0QkFBNEIsQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUM5QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCBjcnlwdG8gZnJvbSAnY3J5cHRvJztcblxuaW1wb3J0IHsgY3JlYXRlRW52UmVkaXNDbGllbnQgfSBmcm9tICcuL2Vudi1yZWRpcy5qcyc7XG5pbXBvcnQgeyBjcmVhdGVMb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ3NzZS10aWNrZXQtc3RvcmUnKTtcblxuLyoqIFJlZGlzIGtleSBuYW1lc3BhY2VzLiBUaWNrZXQg4oaSIG9yZ0lkOyB3aW5kb3dlZCBpc3N1ZSBjb3VudGVycyBib3VuZCBhYnVzZS4gKi9cbmNvbnN0IFRJQ0tFVF9LRVlfUFJFRklYID0gJ3NzZTp0azonO1xuY29uc3QgT1JHX0NPVU5UX1BSRUZJWCA9ICdzc2U6dGtjOic7XG5jb25zdCBUT1RBTF9DT1VOVF9LRVkgPSAnc3NlOnRrYzpfX2FsbF9fJztcblxuLyoqIFJlc3VsdCBvZiB7QGxpbmsgU3NlVGlja2V0U3RvcmUuaXNzdWV9LiAqL1xuZXhwb3J0IHR5cGUgU3NlVGlja2V0SXNzdWVSZXN1bHQgPVxuICB8IHsgb2s6IHRydWU7IHRpY2tldDogc3RyaW5nIH1cbiAgfCB7IG9rOiBmYWxzZTsgcmVhc29uOiAndG90YWwnIHwgJ29yZycgfTtcblxuLyoqXG4gKiBTdG9yZSBmb3Igc2hvcnQtbGl2ZWQsIHNpbmdsZS11c2UgU1NFIGF1dGggdGlja2V0cy4gQSBjbGllbnQgZXhjaGFuZ2VzIGl0cyBKV1RcbiAqIGZvciBhIHRpY2tldCAoc28gdGhlIHRva2VuIG5ldmVyIGxhbmRzIGluIGFuIEV2ZW50U291cmNlIHF1ZXJ5IHN0cmluZyAvIGFjY2Vzc1xuICogbG9nKSwgdGhlbiByZWRlZW1zIGl0IG9uIHRoZSBTU0UgYEdFVGAuXG4gKlxuICogVGhlIHN0b3JlIGlzIHRoZSBtdWx0aS1yZXBsaWNhIGNvcnJlY3RuZXNzIGJvdW5kYXJ5OiBhIHRpY2tldCBtaW50ZWQgb24gcG9kIEFcbiAqIE1VU1QgYmUgcmVkZWVtYWJsZSBvbiBwb2QgQi4gVGhlIFJlZGlzIGJhY2tlbmQgbWFrZXMgdGhhdCB0cnVlOyB0aGUgaW4tbWVtb3J5XG4gKiBiYWNrZW5kIGlzIGEgc2luZ2xlLXByb2Nlc3MgZmFsbGJhY2sgZm9yIGRldiAvIHNpbmdsZS1yZXBsaWNhIGluc3RhbGxzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNzZVRpY2tldFN0b3JlIHtcbiAgLyoqIE1pbnQgYSB0aWNrZXQgZm9yIGBvcmdJZGAsIG9yIHJlamVjdCB3aGVuIGEgcmF0ZSB3aW5kb3cgaXMgc2F0dXJhdGVkLiAqL1xuICBpc3N1ZShvcmdJZDogc3RyaW5nKTogUHJvbWlzZTxTc2VUaWNrZXRJc3N1ZVJlc3VsdD47XG4gIC8qKiBBdG9taWNhbGx5IHJlZGVlbSBhIHRpY2tldCBleGFjdGx5IG9uY2U7IHJldHVybnMgaXRzIG9yZyBvciBudWxsIGlmIGludmFsaWQvZXhwaXJlZC9zcGVudC4gKi9cbiAgY29uc3VtZSh0aWNrZXRJZDogc3RyaW5nKTogUHJvbWlzZTx7IG9yZ0lkOiBzdHJpbmcgfSB8IG51bGw+O1xuICAvKiogUmVsZWFzZSB0aW1lcnMvcmVzb3VyY2VzLiBJbi1tZW1vcnkgY2xlYXJzIGl0cyBzd2VlcCBpbnRlcnZhbDsgUmVkaXMgaXMgYSBuby1vcC4gKi9cbiAgc3RvcCgpOiB2b2lkO1xufVxuXG4vKiogQ2FwcyArIFRUTCBmb3IgdGhlIHRpY2tldCBzdG9yZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3NlVGlja2V0U3RvcmVDb25maWcge1xuICAvKiogVGlja2V0IGxpZmV0aW1lIOKAlCBsb25nIGVub3VnaCBmb3IgdGhlIGNsaWVudCB0byBvcGVuIHRoZSBFdmVudFNvdXJjZS4gKi9cbiAgdHRsTXM6IG51bWJlcjtcbiAgLyoqIEhhcmQgY2FwIG9uIHRpY2tldHMgbWludGVkIHBlciBUVEwgd2luZG93IGFjcm9zcyBhbGwgb3JncyAoYWJ1c2UgYm91bmQpLiAqL1xuICBtYXhUb3RhbDogbnVtYmVyO1xuICAvKiogUGVyLW9yZyBjYXAgb24gdGlja2V0cyBtaW50ZWQgcGVyIFRUTCB3aW5kb3cgKHNpbmdsZS10ZW5hbnQgYWJ1c2UgYm91bmQpLiAqL1xuICBtYXhQZXJPcmc6IG51bWJlcjtcbiAgLyoqXG4gICAqIE9wdGlvbmFsIFJlZGlzIGtleSBuYW1lc3BhY2Ugc28gaW5kZXBlbmRlbnQgY2hhbm5lbHMgKGUuZy4gbWVzc2FnZVxuICAgKiBub3RpZmljYXRpb25zIHZzLiByZXBvcnRpbmcgZXhlY3V0aW9uLXN0YXR1cykgZG9uJ3Qgc2hhcmUgb25lIHRpY2tldFxuICAgKiBrZXlzcGFjZSDigJQgYSB0aWNrZXQgbWludGVkIGZvciBvbmUgY2hhbm5lbCBtdXN0IG5vdCBiZSByZWRlZW1hYmxlIG9uXG4gICAqIGFub3RoZXIuIE9taXQgZm9yIHRoZSBkZWZhdWx0IChzaGFyZWQpIG5hbWVzcGFjZS5cbiAgICovXG4gIGtleVByZWZpeD86IHN0cmluZztcbn1cblxuLyoqIE1pbmltYWwgaW9yZWRpcyBzdXJmYWNlIHRoaXMgc3RvcmUgbmVlZHMgKEdFVERFTCByZXF1aXJlcyBSZWRpcyDiiaUgNi4yKS4gKi9cbmludGVyZmFjZSBTc2VSZWRpcyB7XG4gIGluY3Ioa2V5OiBzdHJpbmcpOiBQcm9taXNlPG51bWJlcj47XG4gIGV4cGlyZShrZXk6IHN0cmluZywgc2Vjb25kczogbnVtYmVyKTogUHJvbWlzZTx1bmtub3duPjtcbiAgc2V0KGtleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nLCAuLi5hcmdzOiB1bmtub3duW10pOiBQcm9taXNlPHVua25vd24+O1xuICBnZXRkZWwoa2V5OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+O1xufVxuXG5mdW5jdGlvbiBuZXdUaWNrZXRJZCgpOiBzdHJpbmcge1xuICByZXR1cm4gY3J5cHRvLnJhbmRvbUJ5dGVzKDI0KS50b1N0cmluZygnYmFzZTY0dXJsJyk7XG59XG5cbi8qKlxuICogSW4tbWVtb3J5IGJhY2tlbmQg4oCUIHRoZSBvcmlnaW5hbCBzaW5nbGUtcHJvY2VzcyBiZWhhdmlvdXIuIENvdW50cyBMSVZFXG4gKiAodW5leHBpcmVkKSB0aWNrZXRzIHBlciBvcmcgYW5kIGV2aWN0cyBleHBpcmVkIGVudHJpZXMgb24gYSB0aW1lci4gQ29ycmVjdFxuICogb25seSB3aXRoaW4gb25lIHByb2Nlc3MsIHNvIGl0IGlzIHRoZSBmYWxsYmFjayB1c2VkIHdoZW4gUmVkaXMgaXNuJ3QgY29uZmlndXJlZC5cbiAqL1xuZnVuY3Rpb24gY3JlYXRlSW5NZW1vcnlTc2VUaWNrZXRTdG9yZShjb25maWc6IFNzZVRpY2tldFN0b3JlQ29uZmlnKTogU3NlVGlja2V0U3RvcmUge1xuICBpbnRlcmZhY2UgRW50cnkgeyBvcmdJZDogc3RyaW5nOyBleHBpcmVzQXQ6IG51bWJlciB9XG4gIGNvbnN0IHN0b3JlID0gbmV3IE1hcDxzdHJpbmcsIEVudHJ5PigpO1xuXG4gIGNvbnN0IGNsZWFudXAgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gICAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgICBmb3IgKGNvbnN0IFtpZCwgdF0gb2Ygc3RvcmUpIGlmIChub3cgPiB0LmV4cGlyZXNBdCkgc3RvcmUuZGVsZXRlKGlkKTtcbiAgfSwgY29uZmlnLnR0bE1zKTtcbiAgY2xlYW51cC51bnJlZigpO1xuXG4gIGZ1bmN0aW9uIGNvdW50TGl2ZUZvck9yZyhvcmdJZDogc3RyaW5nLCBub3c6IG51bWJlcik6IG51bWJlciB7XG4gICAgbGV0IGNvdW50ID0gMDtcbiAgICBmb3IgKGNvbnN0IHQgb2Ygc3RvcmUudmFsdWVzKCkpIGlmICh0Lm9yZ0lkID09PSBvcmdJZCAmJiB0LmV4cGlyZXNBdCA+IG5vdykgY291bnQrKztcbiAgICByZXR1cm4gY291bnQ7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGFzeW5jIGlzc3VlKG9yZ0lkOiBzdHJpbmcpOiBQcm9taXNlPFNzZVRpY2tldElzc3VlUmVzdWx0PiB7XG4gICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgaWYgKHN0b3JlLnNpemUgPj0gY29uZmlnLm1heFRvdGFsKSByZXR1cm4geyBvazogZmFsc2UsIHJlYXNvbjogJ3RvdGFsJyB9O1xuICAgICAgaWYgKGNvdW50TGl2ZUZvck9yZyhvcmdJZCwgbm93KSA+PSBjb25maWcubWF4UGVyT3JnKSByZXR1cm4geyBvazogZmFsc2UsIHJlYXNvbjogJ29yZycgfTtcbiAgICAgIGNvbnN0IHRpY2tldCA9IG5ld1RpY2tldElkKCk7XG4gICAgICBzdG9yZS5zZXQodGlja2V0LCB7IG9yZ0lkLCBleHBpcmVzQXQ6IG5vdyArIGNvbmZpZy50dGxNcyB9KTtcbiAgICAgIHJldHVybiB7IG9rOiB0cnVlLCB0aWNrZXQgfTtcbiAgICB9LFxuICAgIGFzeW5jIGNvbnN1bWUodGlja2V0SWQ6IHN0cmluZyk6IFByb21pc2U8eyBvcmdJZDogc3RyaW5nIH0gfCBudWxsPiB7XG4gICAgICBjb25zdCB0ID0gc3RvcmUuZ2V0KHRpY2tldElkKTtcbiAgICAgIHN0b3JlLmRlbGV0ZSh0aWNrZXRJZCk7IC8vIHNpbmdsZS11c2Ug4oCUIGNvbnN1bWUgaW1tZWRpYXRlbHlcbiAgICAgIGlmICghdCB8fCBEYXRlLm5vdygpID4gdC5leHBpcmVzQXQpIHJldHVybiBudWxsO1xuICAgICAgcmV0dXJuIHsgb3JnSWQ6IHQub3JnSWQgfTtcbiAgICB9LFxuICAgIHN0b3AoKTogdm9pZCB7IGNsZWFySW50ZXJ2YWwoY2xlYW51cCk7IH0sXG4gIH07XG59XG5cbi8qKlxuICogUmVkaXMgYmFja2VuZCDigJQgbXVsdGktcmVwbGljYSBzYWZlLiBUaWNrZXRzIGxpdmUgdW5kZXIgYSBUVEwnZCBrZXkgc28gYW55IHBvZFxuICogY2FuIHJlZGVlbSBvbmU7IHtAbGluayBTc2VUaWNrZXRTdG9yZS5jb25zdW1lfSB1c2VzIEdFVERFTCBzbyByZWRlbXB0aW9uIGlzXG4gKiBhdG9taWMgKHR3byBwb2RzIGNhbid0IGJvdGggc3BlbmQgdGhlIHNhbWUgdGlja2V0KS4gVGhlIHBlci1vcmcgLyBnbG9iYWwgY2Fwc1xuICogYmVjb21lIHdpbmRvd2VkIHJhdGUgbGltaXRzIChtYXggbWludHMgcGVyIFRUTCB3aW5kb3cpIHZpYSBJTkNSICsgZmlyc3QtaGl0XG4gKiBFWFBJUkUg4oCUIGVxdWl2YWxlbnQgYWJ1c2UgYm91bmRpbmcgdG8gdGhlIGluLW1lbW9yeSBsaXZlLWNvdW50LCBhbmQgaXQgYWxzb1xuICogY2FwcyBjaHVybi5cbiAqXG4gKiBGYWlsLUNMT1NFRCBieSBkZXNpZ24gKHVubGlrZSB0aGUgZmFpbC1vcGVuIHRva2VuLXJldm9jYXRpb24gcmVhZGVyKTogaWYgUmVkaXNcbiAqIGVycm9ycywgYGlzc3VlYCByZXR1cm5zIGEgY2FwIHJlamVjdGlvbiBhbmQgYGNvbnN1bWVgIHJldHVybnMgbnVsbCwgc28gYSBSZWRpc1xuICogb3V0YWdlIGRlZ3JhZGVzIHRvIFwibm8gbGl2ZSBub3RpZmljYXRpb25zXCIgcmF0aGVyIHRoYW4gaGFuZGluZyBvdXQgb3JcbiAqIGFjY2VwdGluZyB1bnZhbGlkYXRlZCB0aWNrZXRzLiBTU0Ugbm90aWZpY2F0aW9ucyBhcmUgbm9uLWNyaXRpY2FsLCBzbyBmYWlsaW5nXG4gKiBjbG9zZWQgaGVyZSBjb3N0cyBvbmx5IHJlYWwtdGltZSBkZWxpdmVyeSwgbmV2ZXIgY29ycmVjdG5lc3MuXG4gKi9cbmZ1bmN0aW9uIGNyZWF0ZVJlZGlzU3NlVGlja2V0U3RvcmUocmVkaXM6IFNzZVJlZGlzLCBjb25maWc6IFNzZVRpY2tldFN0b3JlQ29uZmlnKTogU3NlVGlja2V0U3RvcmUge1xuICBjb25zdCB0dGxTZWMgPSBNYXRoLm1heCgxLCBNYXRoLmNlaWwoY29uZmlnLnR0bE1zIC8gMTAwMCkpO1xuICAvLyBQZXItY2hhbm5lbCBuYW1lc3BhY2Ugc28gdHdvIHNlcnZpY2VzJyB0aWNrZXQgc3RvcmVzIGRvbid0IHNoYXJlIGtleXMuXG4gIGNvbnN0IG5zID0gY29uZmlnLmtleVByZWZpeCA/IGAke2NvbmZpZy5rZXlQcmVmaXh9OmAgOiAnJztcbiAgY29uc3QgdGlja2V0S2V5ID0gKHQ6IHN0cmluZykgPT4gYCR7bnN9JHtUSUNLRVRfS0VZX1BSRUZJWH0ke3R9YDtcbiAgY29uc3Qgb3JnQ291bnRLZXkgPSAobzogc3RyaW5nKSA9PiBgJHtuc30ke09SR19DT1VOVF9QUkVGSVh9JHtvfWA7XG4gIGNvbnN0IHRvdGFsQ291bnRLZXkgPSBgJHtuc30ke1RPVEFMX0NPVU5UX0tFWX1gO1xuXG4gIC8vIFdpbmRvd2VkIGNvdW50ZXI6IElOQ1IsIGFuZCBvbiB0aGUgZmlyc3QgaGl0IG9mIGEgd2luZG93IHNldCB0aGUgVFRMIHNvIGl0XG4gIC8vIGF1dG8tcmVzZXRzLiBSZXR1cm5zIHRydWUgd2hpbGUgc3RpbGwgd2l0aGluIGBsaW1pdGAgZm9yIHRoaXMgd2luZG93LlxuICBhc3luYyBmdW5jdGlvbiB3aXRoaW5XaW5kb3coa2V5OiBzdHJpbmcsIGxpbWl0OiBudW1iZXIpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBjb25zdCBuID0gYXdhaXQgcmVkaXMuaW5jcihrZXkpO1xuICAgIGlmIChuID09PSAxKSBhd2FpdCByZWRpcy5leHBpcmUoa2V5LCB0dGxTZWMpO1xuICAgIHJldHVybiBuIDw9IGxpbWl0O1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBhc3luYyBpc3N1ZShvcmdJZDogc3RyaW5nKTogUHJvbWlzZTxTc2VUaWNrZXRJc3N1ZVJlc3VsdD4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgaWYgKCEoYXdhaXQgd2l0aGluV2luZG93KHRvdGFsQ291bnRLZXksIGNvbmZpZy5tYXhUb3RhbCkpKSByZXR1cm4geyBvazogZmFsc2UsIHJlYXNvbjogJ3RvdGFsJyB9O1xuICAgICAgICBpZiAoIShhd2FpdCB3aXRoaW5XaW5kb3cob3JnQ291bnRLZXkob3JnSWQpLCBjb25maWcubWF4UGVyT3JnKSkpIHJldHVybiB7IG9rOiBmYWxzZSwgcmVhc29uOiAnb3JnJyB9O1xuICAgICAgICBjb25zdCB0aWNrZXQgPSBuZXdUaWNrZXRJZCgpO1xuICAgICAgICBhd2FpdCByZWRpcy5zZXQodGlja2V0S2V5KHRpY2tldCksIG9yZ0lkLCAnRVgnLCB0dGxTZWMpO1xuICAgICAgICByZXR1cm4geyBvazogdHJ1ZSwgdGlja2V0IH07XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1NTRSB0aWNrZXQgaXNzdWUgZmFpbGVkIChmYWlsLWNsb3NlZCknLCB7IGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycikgfSk7XG4gICAgICAgIHJldHVybiB7IG9rOiBmYWxzZSwgcmVhc29uOiAndG90YWwnIH07XG4gICAgICB9XG4gICAgfSxcbiAgICBhc3luYyBjb25zdW1lKHRpY2tldElkOiBzdHJpbmcpOiBQcm9taXNlPHsgb3JnSWQ6IHN0cmluZyB9IHwgbnVsbD4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3Qgb3JnSWQgPSBhd2FpdCByZWRpcy5nZXRkZWwodGlja2V0S2V5KHRpY2tldElkKSk7XG4gICAgICAgIHJldHVybiBvcmdJZCA/IHsgb3JnSWQgfSA6IG51bGw7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1NTRSB0aWNrZXQgY29uc3VtZSBmYWlsZWQgKGZhaWwtY2xvc2VkKScsIHsgZXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKSB9KTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSxcbiAgICBzdG9wKCk6IHZvaWQgeyAvKiBSZWRpcyBrZXlzIGV4cGlyZSBvbiB0aGVpciBvd24gVFRMIOKAlCBub3RoaW5nIHRvIHJlbGVhc2UuICovIH0sXG4gIH07XG59XG5cbi8qKlxuICogQnVpbGQgYW4ge0BsaW5rIFNzZVRpY2tldFN0b3JlfSBmcm9tIHRoZSBzdGFuZGFyZCBSZWRpcyBlbnYgKGBSRURJU19VUkxgIG9yXG4gKiBgUkVESVNfSE9TVGAvYFJFRElTX1BPUlRgKS4gVXNlcyB0aGUgUmVkaXMgYmFja2VuZCB3aGVuIGNvbmZpZ3VyZWRcbiAqIChtdWx0aS1yZXBsaWNhIHNhZmUpLCBvdGhlcndpc2UgZmFsbHMgYmFjayB0byB0aGUgaW4tbWVtb3J5IHNpbmdsZS1wcm9jZXNzXG4gKiBiYWNrZW5kLiBBIHNlcnZpY2Ugb3B0cyBpbiB3aXRoIG9uZSBib290IGxpbmU6XG4gKiAgIGBjb25zdCB0aWNrZXRzID0gY3JlYXRlRW52U3NlVGlja2V0U3RvcmUoeyB0dGxNcywgbWF4VG90YWwsIG1heFBlck9yZyB9KTtgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVFbnZTc2VUaWNrZXRTdG9yZShjb25maWc6IFNzZVRpY2tldFN0b3JlQ29uZmlnKTogU3NlVGlja2V0U3RvcmUge1xuICBjb25zdCByZWRpcyA9IGNyZWF0ZUVudlJlZGlzQ2xpZW50PFNzZVJlZGlzPignc3NlLXRpY2tldCcpO1xuICBpZiAocmVkaXMpIHtcbiAgICBsb2dnZXIuaW5mbygnU1NFIHRpY2tldCBzdG9yZTogUmVkaXMgYmFja2VuZCAobXVsdGktcmVwbGljYSknKTtcbiAgICByZXR1cm4gY3JlYXRlUmVkaXNTc2VUaWNrZXRTdG9yZShyZWRpcywgY29uZmlnKTtcbiAgfVxuICBsb2dnZXIuaW5mbygnU1NFIHRpY2tldCBzdG9yZTogaW4tbWVtb3J5IGJhY2tlbmQgKHNpbmdsZS1wcm9jZXNzIGZhbGxiYWNrKScpO1xuICByZXR1cm4gY3JlYXRlSW5NZW1vcnlTc2VUaWNrZXRTdG9yZShjb25maWcpO1xufVxuIl19
173
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3NlLXRpY2tldC1zdG9yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy9zc2UtdGlja2V0LXN0b3JlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBRTVCLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxvQkFBb0IsRUFBd0IsTUFBTSxnQkFBZ0IsQ0FBQztBQUNsRyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFbEQsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLGtCQUFrQixDQUFDLENBQUM7QUE2RGhELFNBQVMsV0FBVztJQUNsQixPQUFPLE1BQU0sQ0FBQyxXQUFXLENBQUMsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQ3RELENBQUM7QUFFRCxTQUFTLE1BQU0sQ0FBQyxHQUFZO0lBQzFCLE9BQU8sR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQzFELENBQUM7QUFFRCwrRUFBK0U7QUFDL0UsTUFBTSxVQUFVLDBCQUEwQixDQUFDLE1BQTRCO0lBRXJFLE1BQU0sT0FBTyxHQUFHLElBQUksR0FBRyxFQUFpQixDQUFDO0lBQ3pDLE1BQU0sTUFBTSxHQUFHLElBQUksR0FBRyxFQUFnRCxDQUFDO0lBRXZFLE1BQU0sS0FBSyxHQUFHLEdBQVMsRUFBRTtRQUN2QixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDdkIsS0FBSyxNQUFNLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLE9BQU87WUFBRSxJQUFJLEdBQUcsSUFBSSxDQUFDLENBQUMsU0FBUztnQkFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxD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QUMsOEJBQThCLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN0RSxDQUFDO1FBQ0gsQ0FBQztRQUNELEtBQUssQ0FBQyxRQUFRLENBQUMsT0FBTztZQUNwQixNQUFNLEtBQUssRUFBRSxDQUFDO1lBQ2QsT0FBTyxLQUFLLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO1FBQ3RDLENBQUM7UUFDRCxJQUFJLEtBQXdDLENBQUM7S0FDOUMsQ0FBQztBQUNKLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLHVCQUF1QixDQUFDLE1BQTRCO0lBQ2xFLE1BQU0sS0FBSyxHQUFHLG9CQUFvQixDQUFpQixZQUFZLENBQUMsQ0FBQztJQUNqRSxJQUFJLEtBQUssRUFBRSxDQUFDO1FBQ1YsTUFBTSxDQUFDLElBQUksQ0FBQyxpREFBaUQsRUFBRSxFQUFFLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQztRQUNoRyxPQUFPLHlCQUF5QixDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQztJQUNsRCxDQUFDO0lBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQywrREFBK0QsRUFBRSxFQUFFLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQztJQUM5RyxPQUFPLDBCQUEwQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0FBQzVDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IGNyeXB0byBmcm9tICdjcnlwdG8nO1xuXG5pbXBvcnQgeyBjcmVhdGVFbnZSZWRpc0NsaWVudCwgY3JlYXRlUmVkaXNSZWFkeUdhdGUsIHR5cGUgUmVhZHlBd2FyZVJlZGlzIH0gZnJvbSAnLi9lbnYtcmVkaXMuanMnO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyLmpzJztcblxuY29uc3QgbG9nZ2VyID0gY3JlYXRlTG9nZ2VyKCdzc2UtdGlja2V0LXN0b3JlJyk7XG5cbi8qKiBXaGF0IGEgdGlja2V0IGF1dGhvcml6ZXM6IHRoZSBvd25pbmcgb3JnIGFuZCwgZm9yIHN1YmplY3QtYm91bmQgY2hhbm5lbHMsIHRoZSBzdHJlYW0gc3ViamVjdC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3NlVGlja2V0UmVjb3JkIHtcbiAgb3JnSWQ6IHN0cmluZztcbiAgLyoqIFN0cmVhbSBzdWJqZWN0IHRoZSB0aWNrZXQgaXMgYm91bmQgdG8gKGUuZy4gYSBidWlsZC1sb2cgcmVxdWVzdElkKS4gQWJzZW50IGZvciBvcmcta2V5ZWQgY2hhbm5lbHMuICovXG4gIHN1YmplY3Q/OiBzdHJpbmc7XG59XG5cbi8qKiBSZXN1bHQgb2Yge0BsaW5rIFNzZVRpY2tldFN0b3JlLmlzc3VlfS4gKi9cbmV4cG9ydCB0eXBlIFNzZVRpY2tldElzc3VlUmVzdWx0ID1cbiAgfCB7IG9rOiB0cnVlOyB0aWNrZXQ6IHN0cmluZyB9XG4gIHwgeyBvazogZmFsc2U7IHJlYXNvbjogJ3RvdGFsJyB8ICdvcmcnIH07XG5cbi8qKlxuICogVGhlIE9ORSBzdG9yZSBmb3Igc2hvcnQtbGl2ZWQsIHNpbmdsZS11c2UgU1NFIGF1dGggdGlja2V0cywgcGx1cyB0aGVcbiAqIHN0cmVhbS1vd25lcnNoaXAgYmluZGluZ3Mgc3ViamVjdC1ib3VuZCBjaGFubmVscyBuZWVkLlxuICpcbiAqIEEgY2xpZW50IGV4Y2hhbmdlcyBpdHMgSldUIGZvciBhIHRpY2tldCAoc28gdGhlIHRva2VuIG5ldmVyIGxhbmRzIGluIGFuXG4gKiBFdmVudFNvdXJjZSBxdWVyeSBzdHJpbmcgLyBhY2Nlc3MgbG9nKSwgdGhlbiByZWRlZW1zIGl0IG9uIHRoZSBTU0UgYEdFVGAuXG4gKlxuICogLSAqKlRpY2tldHMqKiBhcmUgc2luZ2xlLXVzZSBhY3Jvc3MgcG9kczogdGhlIFJlZGlzIGJhY2tlbmQgcmVkZWVtcyB3aXRoXG4gKiAgIGBHRVRERUxgLCBzbyB0d28gcG9kcyBjYW4gbmV2ZXIgYm90aCBzcGVuZCBvbmUgdGlja2V0LlxuICogLSAqKkNhcHMgY291bnQgTElWRSB0aWNrZXRzKiogKGlzc3VlZCwgbm90IHlldCByZWRlZW1lZCwgbm90IGV4cGlyZWQpIOKAlCBwZXIgb3JnXG4gKiAgIGFuZCBpbiB0b3RhbC4gQSByZWRlZW1lZCBvciBleHBpcmVkIHRpY2tldCBmcmVlcyBpdHMgc2xvdCBpbW1lZGlhdGVseS5cbiAqIC0gKipPd25lcnNoaXAqKiByZWNvcmRzIHdoaWNoIG9yZyBvd25zIGEgc3RyZWFtIHN1YmplY3QsIHNvIGEgc3ViamVjdC1ib3VuZFxuICogICBjaGFubmVsIGNhbiByZWZ1c2UgdG8gbWludCBhIHRpY2tldCBmb3IgYW5vdGhlciBvcmcncyBzdHJlYW0uXG4gKlxuICogQm90aCBiYWNrZW5kcyBzaGFyZSB0aGVzZSBzZW1hbnRpY3M7IHRoZSBpbi1tZW1vcnkgb25lIGlzIGNvcnJlY3QgZm9yIGFcbiAqIHNpbmdsZSBwcm9jZXNzIG9ubHkuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3NlVGlja2V0U3RvcmUge1xuICAvKiogTWludCBhIHRpY2tldCBmb3IgYG9yZ0lkYCAob3B0aW9uYWxseSBib3VuZCB0byBgc3ViamVjdGApLCBvciByZWplY3Qgd2hlbiBhIGxpdmUtdGlja2V0IGNhcCBpcyByZWFjaGVkLiAqL1xuICBpc3N1ZShvcmdJZDogc3RyaW5nLCBzdWJqZWN0Pzogc3RyaW5nKTogUHJvbWlzZTxTc2VUaWNrZXRJc3N1ZVJlc3VsdD47XG4gIC8qKiBSZWRlZW0gYSB0aWNrZXQgZXhhY3RseSBvbmNlOyBudWxsIHdoZW4gdW5rbm93biwgZXhwaXJlZCBvciBhbHJlYWR5IHNwZW50LiAqL1xuICBjb25zdW1lKHRpY2tldElkOiBzdHJpbmcpOiBQcm9taXNlPFNzZVRpY2tldFJlY29yZCB8IG51bGw+O1xuICAvKiogUmVjb3JkIHRoZSBvcmcgdGhhdCBvd25zIGBzdWJqZWN0YCBmb3IgYHR0bE1zYC4gKi9cbiAgYmluZE93bmVyKHN1YmplY3Q6IHN0cmluZywgb3JnSWQ6IHN0cmluZywgdHRsTXM6IG51bWJlcik6IFByb21pc2U8dm9pZD47XG4gIC8qKiBUaGUgb3JnIHRoYXQgb3ducyBgc3ViamVjdGAsIG9yIG51bGwgd2hlbiBub25lIGlzIGJvdW5kLiBUaHJvd3Mgd2hlbiB0aGUgYmFja2VuZCBjYW4ndCBhbnN3ZXIuICovXG4gIGdldE93bmVyKHN1YmplY3Q6IHN0cmluZyk6IFByb21pc2U8c3RyaW5nIHwgbnVsbD47XG4gIC8qKiBSZWxlYXNlIHRpbWVycy9yZXNvdXJjZXMuIEluLW1lbW9yeSBjbGVhcnMgaXRzIHN3ZWVwIGludGVydmFsOyBSZWRpcyBpcyBhIG5vLW9wLiAqL1xuICBzdG9wKCk6IHZvaWQ7XG59XG5cbi8qKiBDYXBzICsgVFRMIGZvciB0aGUgdGlja2V0IHN0b3JlLiAqL1xuZXhwb3J0IGludGVyZmFjZSBTc2VUaWNrZXRTdG9yZUNvbmZpZyB7XG4gIC8qKiBUaWNrZXQgbGlmZXRpbWUg4oCUIGxvbmcgZW5vdWdoIGZvciB0aGUgY2xpZW50IHRvIG9wZW4gdGhlIEV2ZW50U291cmNlLiAqL1xuICB0dGxNczogbnVtYmVyO1xuICAvKiogQ2FwIG9uIExJVkUgdGlja2V0cyBhY3Jvc3MgYWxsIG9yZ3MgKGFidXNlIC8gbWVtb3J5IGJvdW5kKS4gKi9cbiAgbWF4VG90YWw6IG51bWJlcjtcbiAgLyoqIENhcCBvbiBMSVZFIHRpY2tldHMgcGVyIG9yZyAoc2luZ2xlLXRlbmFudCBmYWlybmVzcyBib3VuZCkuICovXG4gIG1heFBlck9yZzogbnVtYmVyO1xuICAvKipcbiAgICogS2V5IG5hbWVzcGFjZSBzbyBpbmRlcGVuZGVudCBjaGFubmVscyAobWVzc2FnZSBub3RpZmljYXRpb25zLCByZXBvcnRpbmdcbiAgICogZXhlY3V0aW9uLXN0YXR1cywgYSBzZXJ2aWNlJ3MgYnVpbGQtbG9nIHN0cmVhbSkgbmV2ZXIgc2hhcmUgdGlja2V0cywgY2Fwc1xuICAgKiBvciBvd25lcnNoaXAgYmluZGluZ3Mg4oCUIGEgdGlja2V0IG1pbnRlZCBmb3Igb25lIGNoYW5uZWwgbXVzdCBub3QgYmVcbiAgICogcmVkZWVtYWJsZSBvbiBhbm90aGVyLiBPbWl0IGZvciB0aGUgZGVmYXVsdCBuYW1lc3BhY2UuXG4gICAqL1xuICBrZXlQcmVmaXg/OiBzdHJpbmc7XG59XG5cbmZ1bmN0aW9uIG5ld1RpY2tldElkKCk6IHN0cmluZyB7XG4gIHJldHVybiBjcnlwdG8ucmFuZG9tQnl0ZXMoMjQpLnRvU3RyaW5nKCdiYXNlNjR1cmwnKTtcbn1cblxuZnVuY3Rpb24gZXJyTXNnKGVycjogdW5rbm93bik6IHN0cmluZyB7XG4gIHJldHVybiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycik7XG59XG5cbi8qKiBJbi1tZW1vcnkgYmFja2VuZCDigJQgc2luZ2xlLXByb2Nlc3MgZmFsbGJhY2sgd2hlbiBSZWRpcyBpc24ndCBjb25maWd1cmVkLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZU1lbW9yeVNzZVRpY2tldFN0b3JlKGNvbmZpZzogU3NlVGlja2V0U3RvcmVDb25maWcpOiBTc2VUaWNrZXRTdG9yZSB7XG4gIGludGVyZmFjZSBFbnRyeSBleHRlbmRzIFNzZVRpY2tldFJlY29yZCB7IGV4cGlyZXNBdDogbnVtYmVyIH1cbiAgY29uc3QgdGlja2V0cyA9IG5ldyBNYXA8c3RyaW5nLCBFbnRyeT4oKTtcbiAgY29uc3Qgb3duZXJzID0gbmV3IE1hcDxzdHJpbmcsIHsgb3JnSWQ6IHN0cmluZzsgZXhwaXJlc0F0OiBudW1iZXIgfT4oKTtcblxuICBjb25zdCBzd2VlcCA9ICgpOiB2b2lkID0+IHtcbiAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgIGZvciAoY29uc3QgW2lkLCB0XSBvZiB0aWNrZXRzKSBpZiAobm93ID49IHQuZXhwaXJlc0F0KSB0aWNrZXRzLmRlbGV0ZShpZCk7XG4gICAgZm9yIChjb25zdCBbaWQsIG9dIG9mIG93bmVycykgaWYgKG5vdyA+PSBvLmV4cGlyZXNBdCkgb3duZXJzLmRlbGV0ZShpZCk7XG4gIH07XG4gIGNvbnN0IHRpbWVyID0gc2V0SW50ZXJ2YWwoc3dlZXAsIE1hdGgubWF4KDFfMDAwLCBjb25maWcudHRsTXMpKTtcbiAgdGltZXIudW5yZWYoKTtcblxuICByZXR1cm4ge1xuICAgIGFzeW5jIGlzc3VlKG9yZ0lkLCBzdWJqZWN0KSB7XG4gICAgICBzd2VlcCgpO1xuICAgICAgaWYgKHRpY2tldHMuc2l6ZSA+PSBjb25maWcubWF4VG90YWwpIHJldHVybiB7IG9rOiBmYWxzZSwgcmVhc29uOiAndG90YWwnIH07XG4gICAgICBsZXQgZm9yT3JnID0gMDtcbiAgICAgIGZvciAoY29uc3QgdCBvZiB0aWNrZXRzLnZhbHVlcygpKSBpZiAodC5vcmdJZCA9PT0gb3JnSWQpIGZvck9yZysrO1xuICAgICAgaWYgKGZvck9yZyA+PSBjb25maWcubWF4UGVyT3JnKSByZXR1cm4geyBvazogZmFsc2UsIHJlYXNvbjogJ29yZycgfTtcbiAgICAgIGNvbnN0IHRpY2tldCA9IG5ld1RpY2tldElkKCk7XG4gICAgICB0aWNrZXRzLnNldCh0aWNrZXQsIHsgb3JnSWQsIC4uLihzdWJqZWN0ICE9PSB1bmRlZmluZWQgJiYgeyBzdWJqZWN0IH0pLCBleHBpcmVzQXQ6IERhdGUubm93KCkgKyBjb25maWcudHRsTXMgfSk7XG4gICAgICByZXR1cm4geyBvazogdHJ1ZSwgdGlja2V0IH07XG4gICAgfSxcbiAgICBhc3luYyBjb25zdW1lKHRpY2tldElkKSB7XG4gICAgICBjb25zdCB0ID0gdGlja2V0cy5nZXQodGlja2V0SWQpO1xuICAgICAgdGlja2V0cy5kZWxldGUodGlja2V0SWQpOyAvLyBzaW5nbGUtdXNlIOKAlCBnb25lIHdoZXRoZXIgb3Igbm90IGl0IHdhcyB2YWxpZFxuICAgICAgaWYgKCF0IHx8IERhdGUubm93KCkgPj0gdC5leHBpcmVzQXQpIHJldHVybiBudWxsO1xuICAgICAgcmV0dXJuIHsgb3JnSWQ6IHQub3JnSWQsIC4uLih0LnN1YmplY3QgIT09IHVuZGVmaW5lZCAmJiB7IHN1YmplY3Q6IHQuc3ViamVjdCB9KSB9O1xuICAgIH0sXG4gICAgYXN5bmMgYmluZE93bmVyKHN1YmplY3QsIG9yZ0lkLCB0dGxNcykge1xuICAgICAgb3duZXJzLnNldChzdWJqZWN0LCB7IG9yZ0lkLCBleHBpcmVzQXQ6IERhdGUubm93KCkgKyB0dGxNcyB9KTtcbiAgICB9LFxuICAgIGFzeW5jIGdldE93bmVyKHN1YmplY3QpIHtcbiAgICAgIGNvbnN0IG8gPSBvd25lcnMuZ2V0KHN1YmplY3QpO1xuICAgICAgaWYgKCFvKSByZXR1cm4gbnVsbDtcbiAgICAgIGlmIChEYXRlLm5vdygpID49IG8uZXhwaXJlc0F0KSB7IG93bmVycy5kZWxldGUoc3ViamVjdCk7IHJldHVybiBudWxsOyB9XG4gICAgICByZXR1cm4gby5vcmdJZDtcbiAgICB9LFxuICAgIHN0b3AoKSB7IGNsZWFySW50ZXJ2YWwodGltZXIpOyB9LFxuICB9O1xufVxuXG4vKiogTWluaW1hbCBpb3JlZGlzIHN1cmZhY2UgdGhlIFJlZGlzIGJhY2tlbmQgbmVlZHMgKEdFVERFTCByZXF1aXJlcyBSZWRpcyDiiaUgNi4yKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3NlVGlja2V0UmVkaXMgZXh0ZW5kcyBSZWFkeUF3YXJlUmVkaXMge1xuICBldmFsKHNjcmlwdDogc3RyaW5nLCBudW1LZXlzOiBudW1iZXIsIC4uLmFyZ3M6IChzdHJpbmcgfCBudW1iZXIpW10pOiBQcm9taXNlPHVua25vd24+O1xuICBnZXRkZWwoa2V5OiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZyB8IG51bGw+O1xuICB6cmVtKGtleTogc3RyaW5nLCAuLi5tZW1iZXJzOiBzdHJpbmdbXSk6IFByb21pc2U8bnVtYmVyPjtcbiAgc2V0KGtleTogc3RyaW5nLCB2YWx1ZTogc3RyaW5nLCAuLi5hcmdzOiAoc3RyaW5nIHwgbnVtYmVyKVtdKTogUHJvbWlzZTx1bmtub3duPjtcbiAgZ2V0KGtleTogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmcgfCBudWxsPjtcbn1cblxuLyoqXG4gKiBBdG9taWMgbGl2ZS1jb3VudCBpc3N1ZS4gUHJ1bmVzIGV4cGlyZWQgbWVtYmVycyBmcm9tIGJvdGggY2FwIHNldHMsIGNoZWNrcyB0aGVcbiAqIHRvdGFsIHRoZW4gdGhlIHBlci1vcmcgY2FwLCBhbmQgb25seSB0aGVuIHN0b3JlcyB0aGUgdGlja2V0IGFuZCByZWNvcmRzIGl0IGluXG4gKiBib3RoIHNldHMg4oCUIHNvIGNvbmN1cnJlbnQgbWludHMgY2FuJ3Qgb3ZlcnNob290IGEgY2FwIGFuZCBhIGNhcCBjYW4gbmV2ZXJcbiAqIHN0aWNrIChldmVyeSBtZW1iZXIgY2FycmllcyBpdHMgb3duIGV4cGlyeSBzY29yZSBhbmQgZXZlcnkga2V5IGEgVFRMKS5cbiAqXG4gKiBLRVlTOiB0b3RhbCB6c2V0LCBvcmcgenNldCwgdGlja2V0IGtleS5cbiAqIEFSR1Y6IHR0bE1zLCBtYXhUb3RhbCwgbWF4UGVyT3JnLCB0aWNrZXRJZCwgcmVjb3JkIEpTT04uXG4gKiBVc2VzIHRoZSBzZXJ2ZXIgY2xvY2sgc28gZXZlcnkgcG9kIGFncmVlcyBvbiBcImV4cGlyZWRcIi5cbiAqL1xuY29uc3QgSVNTVUVfU0NSSVBUID0gYFxubG9jYWwgdCA9IHJlZGlzLmNhbGwoJ1RJTUUnKVxubG9jYWwgbm93ID0gdG9udW1iZXIodFsxXSkgKiAxMDAwICsgbWF0aC5mbG9vcih0b251bWJlcih0WzJdKSAvIDEwMDApXG5sb2NhbCB0dGwgPSB0b251bWJlcihBUkdWWzFdKVxucmVkaXMuY2FsbCgnWlJFTVJBTkdFQllTQ09SRScsIEtFWVNbMV0sICctaW5mJywgbm93KVxucmVkaXMuY2FsbCgnWlJFTVJBTkdFQllTQ09SRScsIEtFWVNbMl0sICctaW5mJywgbm93KVxuaWYgcmVkaXMuY2FsbCgnWkNBUkQnLCBLRVlTWzFdKSA+PSB0b251bWJlcihBUkdWWzJdKSB0aGVuIHJldHVybiAndG90YWwnIGVuZFxuaWYgcmVkaXMuY2FsbCgnWkNBUkQnLCBLRVlTWzJdKSA+PSB0b251bWJlcihBUkdWWzNdKSB0aGVuIHJldHVybiAnb3JnJyBlbmRcbnJlZGlzLmNhbGwoJ1NFVCcsIEtFWVNbM10sIEFSR1ZbNV0sICdQWCcsIHR0bClcbnJlZGlzLmNhbGwoJ1pBREQnLCBLRVlTWzFdLCBub3cgKyB0dGwsIEFSR1ZbNF0pXG5yZWRpcy5jYWxsKCdaQUREJywgS0VZU1syXSwgbm93ICsgdHRsLCBBUkdWWzRdKVxucmVkaXMuY2FsbCgnUEVYUElSRScsIEtFWVNbMV0sIHR0bClcbnJlZGlzLmNhbGwoJ1BFWFBJUkUnLCBLRVlTWzJdLCB0dGwpXG5yZXR1cm4gJ29rJ2A7XG5cbi8qKlxuICogUmVkaXMgYmFja2VuZCDigJQgbXVsdGktcmVwbGljYSBzYWZlLlxuICpcbiAqIEZhaWwtQ0xPU0VEOiBhIFJlZGlzIGVycm9yIG1ha2VzIGBpc3N1ZWAgcmVqZWN0IChgdG90YWxgKSwgYGNvbnN1bWVgIHJldHVyblxuICogbnVsbCBhbmQgYGdldE93bmVyYCB0aHJvdywgc28gYW4gb3V0YWdlIGRlZ3JhZGVzIHRvIFwibm8gbGl2ZSBzdHJlYW1cIiByYXRoZXJcbiAqIHRoYW4gaGFuZGluZyBvdXQgb3IgYWNjZXB0aW5nIHVudmFsaWRhdGVkIHRpY2tldHMuIGBiaW5kT3duZXJgIGlzIGJlc3QtZWZmb3J0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUmVkaXNTc2VUaWNrZXRTdG9yZShyZWRpczogU3NlVGlja2V0UmVkaXMsIGNvbmZpZzogU3NlVGlja2V0U3RvcmVDb25maWcpOiBTc2VUaWNrZXRTdG9yZSB7XG4gIGNvbnN0IG5zID0gY29uZmlnLmtleVByZWZpeCA/IGAke2NvbmZpZy5rZXlQcmVmaXh9OmAgOiAnJztcbiAgY29uc3QgdGlja2V0S2V5ID0gKHQ6IHN0cmluZykgPT4gYCR7bnN9c3NlOnRrOiR7dH1gO1xuICBjb25zdCBvcmdTZXRLZXkgPSAobzogc3RyaW5nKSA9PiBgJHtuc31zc2U6dGt6Om9yZzoke299YDtcbiAgY29uc3QgdG90YWxTZXRLZXkgPSBgJHtuc31zc2U6dGt6OmFsbGA7XG4gIGNvbnN0IG93bmVyS2V5ID0gKHM6IHN0cmluZykgPT4gYCR7bnN9c3NlOm93bmVyOiR7c31gO1xuICBjb25zdCB0dGxNcyA9IE1hdGgubWF4KDEsIE1hdGguY2VpbChjb25maWcudHRsTXMpKTtcbiAgLy8gVGhlIGVudiBjbGllbnQgaGFzIG5vIG9mZmxpbmUgcXVldWU6IHdhaXQgKGJvdW5kZWQpIGZvciB0aGUgZmlyc3QgY29ubmVjdGlvblxuICAvLyBzbyB0aGUgZmlyc3QgbWludC9yZWRlZW0gYWZ0ZXIgYm9vdCBpc24ndCByZWplY3RlZCBvdXRyaWdodC5cbiAgY29uc3QgcmVhZHkgPSBjcmVhdGVSZWRpc1JlYWR5R2F0ZShyZWRpcyk7XG5cbiAgcmV0dXJuIHtcbiAgICBhc3luYyBpc3N1ZShvcmdJZCwgc3ViamVjdCkge1xuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgcmVhZHkoKTtcbiAgICAgICAgY29uc3QgdGlja2V0ID0gbmV3VGlja2V0SWQoKTtcbiAgICAgICAgY29uc3QgcmVjb3JkOiBTc2VUaWNrZXRSZWNvcmQgPSB7IG9yZ0lkLCAuLi4oc3ViamVjdCAhPT0gdW5kZWZpbmVkICYmIHsgc3ViamVjdCB9KSB9O1xuICAgICAgICBjb25zdCBvdXRjb21lID0gYXdhaXQgcmVkaXMuZXZhbChcbiAgICAgICAgICBJU1NVRV9TQ1JJUFQsIDMsIHRvdGFsU2V0S2V5LCBvcmdTZXRLZXkob3JnSWQpLCB0aWNrZXRLZXkodGlja2V0KSxcbiAgICAgICAgICB0dGxNcywgY29uZmlnLm1heFRvdGFsLCBjb25maWcubWF4UGVyT3JnLCB0aWNrZXQsIEpTT04uc3RyaW5naWZ5KHJlY29yZCksXG4gICAgICAgICk7XG4gICAgICAgIGlmIChvdXRjb21lID09PSAnb2snKSByZXR1cm4geyBvazogdHJ1ZSwgdGlja2V0IH07XG4gICAgICAgIHJldHVybiB7IG9rOiBmYWxzZSwgcmVhc29uOiBvdXRjb21lID09PSAnb3JnJyA/ICdvcmcnIDogJ3RvdGFsJyB9O1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKCdTU0UgdGlja2V0IGlzc3VlIGZhaWxlZCAoZmFpbC1jbG9zZWQpJywgeyBlcnJvcjogZXJyTXNnKGVycikgfSk7XG4gICAgICAgIHJldHVybiB7IG9rOiBmYWxzZSwgcmVhc29uOiAndG90YWwnIH07XG4gICAgICB9XG4gICAgfSxcbiAgICBhc3luYyBjb25zdW1lKHRpY2tldElkKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCByZWFkeSgpO1xuICAgICAgICBjb25zdCByYXcgPSBhd2FpdCByZWRpcy5nZXRkZWwodGlja2V0S2V5KHRpY2tldElkKSk7XG4gICAgICAgIGlmICghcmF3KSByZXR1cm4gbnVsbDtcbiAgICAgICAgY29uc3QgcmVjID0gSlNPTi5wYXJzZShyYXcpIGFzIFNzZVRpY2tldFJlY29yZDtcbiAgICAgICAgaWYgKHR5cGVvZiByZWM/Lm9yZ0lkICE9PSAnc3RyaW5nJykgcmV0dXJuIG51bGw7XG4gICAgICAgIC8vIEZyZWUgdGhlIGxpdmUtY291bnQgc2xvdHMgbm93IHJhdGhlciB0aGFuIGF0IGV4cGlyeS4gQmVzdC1lZmZvcnQ6IGFcbiAgICAgICAgLy8gZmFpbHVyZSBoZXJlIG9ubHkgZGVsYXlzIHRoZSBzbG90IHVudGlsIHRoZSBtZW1iZXIncyBleHBpcnkgc2NvcmUuXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFtyZWRpcy56cmVtKG9yZ1NldEtleShyZWMub3JnSWQpLCB0aWNrZXRJZCksIHJlZGlzLnpyZW0odG90YWxTZXRLZXksIHRpY2tldElkKV0pXG4gICAgICAgICAgLmNhdGNoKChlcnI6IHVua25vd24pID0+IGxvZ2dlci5kZWJ1ZygnU1NFIHRpY2tldCBzbG90IHJlbGVhc2UgZmFpbGVkJywgeyBlcnJvcjogZXJyTXNnKGVycikgfSkpO1xuICAgICAgICByZXR1cm4gcmVjO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKCdTU0UgdGlja2V0IGNvbnN1bWUgZmFpbGVkIChmYWlsLWNsb3NlZCknLCB7IGVycm9yOiBlcnJNc2coZXJyKSB9KTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSxcbiAgICBhc3luYyBiaW5kT3duZXIoc3ViamVjdCwgb3JnSWQsIG93bmVyVHRsTXMpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGF3YWl0IHJlYWR5KCk7XG4gICAgICAgIGF3YWl0IHJlZGlzLnNldChvd25lcktleShzdWJqZWN0KSwgb3JnSWQsICdQWCcsIE1hdGgubWF4KDEsIE1hdGguY2VpbChvd25lclR0bE1zKSkpO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGxvZ2dlci53YXJuKCdTU0Ugc3RyZWFtLW93bmVyIGJpbmQgZmFpbGVkJywgeyBlcnJvcjogZXJyTXNnKGVycikgfSk7XG4gICAgICB9XG4gICAgfSxcbiAgICBhc3luYyBnZXRPd25lcihzdWJqZWN0KSB7XG4gICAgICBhd2FpdCByZWFkeSgpO1xuICAgICAgcmV0dXJuIHJlZGlzLmdldChvd25lcktleShzdWJqZWN0KSk7XG4gICAgfSxcbiAgICBzdG9wKCkgeyAvKiBrZXlzIGV4cGlyZSBvbiB0aGVpciBvd24gVFRMICovIH0sXG4gIH07XG59XG5cbi8qKlxuICogQnVpbGQgYW4ge0BsaW5rIFNzZVRpY2tldFN0b3JlfSBmcm9tIHRoZSBzdGFuZGFyZCBSZWRpcyBlbnYgKGBSRURJU19VUkxgIG9yXG4gKiBgUkVESVNfU0VOVElORUxTYCk6IHRoZSBSZWRpcyBiYWNrZW5kIHdoZW4gY29uZmlndXJlZCAobXVsdGktcmVwbGljYSBzYWZlKSxcbiAqIG90aGVyd2lzZSB0aGUgaW4tbWVtb3J5IHNpbmdsZS1wcm9jZXNzIGJhY2tlbmQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVFbnZTc2VUaWNrZXRTdG9yZShjb25maWc6IFNzZVRpY2tldFN0b3JlQ29uZmlnKTogU3NlVGlja2V0U3RvcmUge1xuICBjb25zdCByZWRpcyA9IGNyZWF0ZUVudlJlZGlzQ2xpZW50PFNzZVRpY2tldFJlZGlzPignc3NlLXRpY2tldCcpO1xuICBpZiAocmVkaXMpIHtcbiAgICBsb2dnZXIuaW5mbygnU1NFIHRpY2tldCBzdG9yZTogUmVkaXMgYmFja2VuZCAobXVsdGktcmVwbGljYSknLCB7IGtleVByZWZpeDogY29uZmlnLmtleVByZWZpeCB9KTtcbiAgICByZXR1cm4gY3JlYXRlUmVkaXNTc2VUaWNrZXRTdG9yZShyZWRpcywgY29uZmlnKTtcbiAgfVxuICBsb2dnZXIuaW5mbygnU1NFIHRpY2tldCBzdG9yZTogaW4tbWVtb3J5IGJhY2tlbmQgKHNpbmdsZS1wcm9jZXNzIGZhbGxiYWNrKScsIHsga2V5UHJlZml4OiBjb25maWcua2V5UHJlZml4IH0pO1xuICByZXR1cm4gY3JlYXRlTWVtb3J5U3NlVGlja2V0U3RvcmUoY29uZmlnKTtcbn1cbiJdfQ==
@@ -30,7 +30,7 @@ export declare function sessionRevocationKey(jti: string): string;
30
30
  export declare function createRedisTokenRevocationStore(redis: RedisCacheClient): TokenRevocationStore;
31
31
  /**
32
32
  * Build a {@link TokenRevocationStore} backed by a Redis client that is lazily
33
- * constructed from the standard `REDIS_URL` or `REDIS_HOST`/`REDIS_PORT` env —
33
+ * constructed from the standard `REDIS_URL` or `REDIS_SENTINELS` env —
34
34
  * for a stateless service that keeps NO Redis client of its own. The client is
35
35
  * built on first `getCurrentVersion` call and memoized; `ioredis` is loaded via
36
36
  * a guarded dynamic require so merely importing this never breaks a build/test
@@ -1,6 +1,6 @@
1
1
  // Copyright 2026 Pipeline Builder Contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
- import { createEnvRedisClient } from './env-redis.js';
3
+ import { createEnvRedisClient, createRedisReadyGate } from './env-redis.js';
4
4
  import { createLogger } from '../utils/logger.js';
5
5
  import { emitCounter } from '../utils/metric-emitter.js';
6
6
  const logger = createLogger('token-revocation');
@@ -84,7 +84,7 @@ export function createRedisTokenRevocationStore(redis) {
84
84
  }
85
85
  /**
86
86
  * Build a {@link TokenRevocationStore} backed by a Redis client that is lazily
87
- * constructed from the standard `REDIS_URL` or `REDIS_HOST`/`REDIS_PORT` env —
87
+ * constructed from the standard `REDIS_URL` or `REDIS_SENTINELS` env —
88
88
  * for a stateless service that keeps NO Redis client of its own. The client is
89
89
  * built on first `getCurrentVersion` call and memoized; `ioredis` is loaded via
90
90
  * a guarded dynamic require so merely importing this never breaks a build/test
@@ -99,34 +99,46 @@ export function createRedisTokenRevocationStore(redis) {
99
99
  export function createEnvRedisTokenRevocationStore() {
100
100
  // undefined = not yet attempted; null = attempted and unavailable (stay off).
101
101
  let cached;
102
- function build() {
103
- // Shared env-configured ioredis construction (fail-open, error-listener
104
- // attached, null when Redis isn't configured/available); the reader stays
105
- // fail-open — a null client just falls back to natural token expiry.
106
- const inst = createEnvRedisClient('revocation-reader');
107
- if (inst)
108
- logger.info('Redis token-revocation reader initialized');
109
- return inst;
102
+ let ready;
103
+ /**
104
+ * The reader client, built on first use. The env client has no offline queue,
105
+ * so a GET before the first connection completes is rejected — which made the
106
+ * FIRST impersonation check on every pod read 'unavailable' (401). Wait
107
+ * (bounded, never rejecting) for readiness; a genuinely down Redis then keeps
108
+ * the existing fail-open / 'unavailable' semantics.
109
+ */
110
+ async function client() {
111
+ if (cached === undefined) {
112
+ // Shared env-configured ioredis construction (error listener attached, null
113
+ // when Redis isn't configured); the reader stays fail-open — a null client
114
+ // just falls back to natural token expiry.
115
+ cached = createEnvRedisClient('revocation-reader');
116
+ if (cached) {
117
+ logger.info('Redis token-revocation reader initialized');
118
+ ready = createRedisReadyGate(cached);
119
+ }
120
+ }
121
+ if (ready)
122
+ await ready();
123
+ return cached;
110
124
  }
111
125
  return {
112
126
  async getCurrentVersion(userId) {
113
- if (cached === undefined)
114
- cached = build();
115
- if (!cached)
127
+ const redis = await client();
128
+ if (!redis)
116
129
  return null;
117
- return createRedisTokenRevocationStore(cached).getCurrentVersion(userId);
130
+ return createRedisTokenRevocationStore(redis).getCurrentVersion(userId);
118
131
  },
119
132
  async getSessionRevocation(jti) {
120
- if (cached === undefined)
121
- cached = build();
133
+ const redis = await client();
122
134
  // No Redis configured ⇒ there is no way to learn a session was ended, so
123
135
  // an impersonation token can't be trusted. Every real deployment runs Redis
124
136
  // (the build queue needs it), so this only bites a misconfigured service.
125
- if (!cached) {
137
+ if (!redis) {
126
138
  emitCounter('session_revocation_unavailable_total', { reason: 'not-configured' });
127
139
  return 'unavailable';
128
140
  }
129
- return createRedisTokenRevocationStore(cached).getSessionRevocation(jti);
141
+ return createRedisTokenRevocationStore(redis).getSessionRevocation(jti);
130
142
  },
131
143
  };
132
144
  }
@@ -181,4 +193,4 @@ export async function publishSessionRevocation(redis, jti, ttlMs) {
181
193
  return false;
182
194
  }
183
195
  }
184
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4tcmV2b2NhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy90b2tlbi1yZXZvY2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFHdEMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFdEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUV6RCxNQUFNLE1BQU0sR0FBRyxZQUFZLENBQUMsa0JBQWtCLENBQUMsQ0FBQztBQUVoRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLENBQUMsTUFBTSwyQkFBMkIsR0FBRyxhQUFhLENBQUM7QUFFekQsd0NBQXdDO0FBQ3hDLE1BQU0sVUFBVSxrQkFBa0IsQ0FBQyxNQUFjO0lBQy9DLE9BQU8sR0FBRywyQkFBMkIsR0FBRyxNQUFNLEVBQUUsQ0FBQztBQUNuRCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLDZCQUE2QixHQUFHLGNBQWMsQ0FBQztBQUU1RCxxREFBcUQ7QUFDckQsTUFBTSxVQUFVLG9CQUFvQixDQUFDLEdBQVc7SUFDOUMsT0FBTyxHQUFHLDZCQUE2QixHQUFHLEdBQUcsRUFBRSxDQUFDO0FBQ2xELENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sVUFBVSwrQkFBK0IsQ0FBQyxLQUF1QjtJQUNyRSxPQUFPO1FBQ0wsS0FBSyxDQUFDLGlCQUFpQixDQUFDLE1BQWM7WUFDcEMsSUFBSSxDQUFDO2dCQUNILE1BQU0sR0FBRyxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO2dCQUN4RCxJQUFJLEdBQUcsS0FBSyxJQUFJLElBQUksR0FBRyxLQUFLLFNBQVMsSUFBSSxHQUFHLENBQUMs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QUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4RixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2IsTUFBTSxDQUFDLElBQUksQ0FBQywyRkFBMkYsRUFBRTtZQUN2RyxLQUFLLEVBQUUsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztTQUN4RCxDQUFDLENBQUM7UUFDSCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB0eXBlIHsgUmVkaXNDYWNoZUNsaWVudCB9IGZyb20gJy4vY2FjaGUtc2VydmljZS5qcyc7XG5pbXBvcnQgeyBjcmVhdGVFbnZSZWRpc0NsaWVudCB9IGZyb20gJy4vZW52LXJlZGlzLmpzJztcbmltcG9ydCB0eXBlIHsgU2Vzc2lvblJldm9jYXRpb25TdGF0ZSwgVG9rZW5SZXZvY2F0aW9uU3RvcmUgfSBmcm9tICcuLi9taWRkbGV3YXJlL2F1dGguanMnO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyLmpzJztcbmltcG9ydCB7IGVtaXRDb3VudGVyIH0gZnJvbSAnLi4vdXRpbHMvbWV0cmljLWVtaXR0ZXIuanMnO1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ3Rva2VuLXJldm9jYXRpb24nKTtcblxuLyoqXG4gKiBSZWRpcyBrZXkgbmFtZXNwYWNlIGZvciB0aGUgcGVyLXVzZXIgY3VycmVudCBgdG9rZW5WZXJzaW9uYC4gVGhlIHBsYXRmb3JtXG4gKiBQVUJMSVNIRVMgdG8gdGhpcyBrZXkgb24gZXZlcnkgcHJpdmlsZWdlIGNoYW5nZTsgdGhlIHN0YXRlbGVzcyBzZXJ2aWNlcyBSRUFEXG4gKiBpdCBpbiBgcmVxdWlyZUF1dGhgICh2aWEge0BsaW5rIGNyZWF0ZVJlZGlzVG9rZW5SZXZvY2F0aW9uU3RvcmV9KSB0byByZWplY3RcbiAqIHRva2VucyBtaW50ZWQgYmVmb3JlIHRoYXQgY2hhbmdlLiBQdWJsaXNoZXIgYW5kIHJlYWRlcnMgTVVTVCBzaGFyZSB0aGlzIGV4YWN0XG4gKiBwcmVmaXgg4oCUIGhlbmNlIGJvdGggaGVscGVycyBsaXZlIGhlcmUsIGluIG9uZSBwbGFjZS5cbiAqL1xuZXhwb3J0IGNvbnN0IFRPS0VOX1JFVk9DQVRJT05fS0VZX1BSRUZJWCA9ICdhdXRocmV2OnR2Oic7XG5cbi8qKiBUaGUgcmV2b2NhdGlvbiBrZXkgZm9yIGEgdXNlciBpZC4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b2tlblJldm9jYXRpb25LZXkodXNlcklkOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYCR7VE9LRU5fUkVWT0NBVElPTl9LRVlfUFJFRklYfSR7dXNlcklkfWA7XG59XG5cbi8qKlxuICogUmVkaXMga2V5IG5hbWVzcGFjZSBmb3IgZW5kZWQgSU1QRVJTT05BVElPTiBzZXNzaW9ucywgYnkgdG9rZW4gYGp0aWAuIFNhbWVcbiAqIHB1Ymxpc2gvcmVhZCBzcGxpdCBhcyB0aGUgdG9rZW5WZXJzaW9uIGtleXMgYWJvdmUsIGFuZCBrZXB0IGJlc2lkZSB0aGVtIGZvciB0aGVcbiAqIHNhbWUgcmVhc29uOiBwdWJsaXNoZXIgYW5kIHJlYWRlcnMgbXVzdCBhZ3JlZSBvbiB0aGlzIGV4YWN0IHByZWZpeC5cbiAqL1xuZXhwb3J0IGNvbnN0IFNFU1NJT05fUkVWT0NBVElPTl9LRVlfUFJFRklYID0gJ2F1dGhyZXY6anRpOic7XG5cbi8qKiBUaGUgcmV2b2NhdGlvbiBrZXkgZm9yIG9uZSBzZXNzaW9uJ3MgdG9rZW4gaWQuICovXG5leHBvcnQgZnVuY3Rpb24gc2Vzc2lvblJldm9jYXRpb25LZXkoanRpOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYCR7U0VTU0lPTl9SRVZPQ0FUSU9OX0tFWV9QUkVGSVh9JHtqdGl9YDtcbn1cblxuLyoqXG4gKiBCdWlsZCBhIHtAbGluayBUb2tlblJldm9jYXRpb25TdG9yZX0gYmFja2VkIGJ5IGEgUmVkaXMgY2xpZW50LCBmb3IgYSBzdGF0ZWxlc3NcbiAqIHNlcnZpY2UgdG8gcmVnaXN0ZXIgdmlhIGBzZXRUb2tlblJldm9jYXRpb25TdG9yZWAuIFJlYWRzIHRoZSBjdXJyZW50XG4gKiBgdG9rZW5WZXJzaW9uYCB0aGUgcGxhdGZvcm0gcHVibGlzaGVkIGZvciB0aGUgdXNlci5cbiAqXG4gKiBGYWlsLW9wZW4gYnkgY29udHJhY3Q6IGEgbWlzcywgYSBwYXJzZSBmYWlsdXJlLCBvciBhIFJlZGlzIGVycm9yIGFsbCB5aWVsZFxuICogYG51bGxgICjigJQgYHJlcXVpcmVBdXRoYCB0cmVhdHMgdGhhdCBhcyBcIm5vIGtub3duIHJldm9jYXRpb25cIiksIHNvIGEgUmVkaXNcbiAqIG91dGFnZSBkZWdyYWRlcyB0byB0aGUgcHJlLWV4aXN0aW5nIGJlaGF2aW91ciByYXRoZXIgdGhhbiBsb2NraW5nIHVzZXJzIG91dC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVJlZGlzVG9rZW5SZXZvY2F0aW9uU3RvcmUocmVkaXM6IFJlZGlzQ2FjaGVDbGllbnQpOiBUb2tlblJldm9jYXRpb25TdG9yZSB7XG4gIHJldHVybiB7XG4gICAgYXN5bmMgZ2V0Q3VycmVudFZlcnNpb24odXNlcklkOiBzdHJpbmcpOiBQcm9taXNlPG51bWJlciB8IG51bGw+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJhdyA9IGF3YWl0IHJlZGlzLmdldCh0b2tlblJldm9jYXRpb25LZXkodXNlcklkKSk7XG4gICAgICAgIGlmIChyYXcgPT09IG51bGwgfHwgcmF3ID09PSB1bmRlZmluZWQgfHwgcmF3LnRyaW0oKSA9PT0gJycpIHJldHVybiBudWxsO1xuICAgICAgICAvLyBTdHJpY3QgaW50ZWdlciBwYXJzZTogYE51bWJlcmAgKHVubGlrZSBgcGFyc2VJbnRgKSByZWplY3RzIHRyYWlsaW5nXG4gICAgICAgIC8vIGdhcmJhZ2UgKFwiNWFiY1wiIOKGkiBOYU4pLCBzbyBhIGNvcnJ1cHRlZCBlbnRyeSBmYWlscyBvcGVuIChudWxsIOKGkiBcIm5vdFxuICAgICAgICAvLyByZXZva2VkXCIpIHJhdGhlciB0aGFuIGJlaW5nIHJlYWQgYXMgYSBib2d1cyB2ZXJzaW9uLiBUaGUgZW1wdHktc3RyaW5nXG4gICAgICAgIC8vIGd1YXJkIGFib3ZlIG1hdHRlcnMgYmVjYXVzZSBgTnVtYmVyKCcnKWAgaXMgMCwgbm90IE5hTi5cbiAgICAgICAgY29uc3QgbiA9IE51bWJlcihyYXcpO1xuICAgICAgICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcihuKSA/IG4gOiBudWxsO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIC8vIFJlZGlzIHdhcyByZWFjaGFibGUgZW5vdWdoIHRvIHRyeSBidXQgdGhlIHJlYWQgZXJyb3JlZCDigJQgdGhpcyBpcyBhXG4gICAgICAgIC8vIERFR1JBREFUSU9OOiB3aGlsZSBpdCBwZXJzaXN0cywgZm9yY2VkIGxvZ291dHMgLyBwcml2aWxlZ2UgcmV2b2NhdGlvbnNcbiAgICAgICAgLy8gc2lsZW50bHkgc3RvcCB0YWtpbmcgZWZmZWN0IHVudGlsIG5hdHVyYWwgdG9rZW4gZXhwaXJ5LiBFbWl0IGEgY291bnRlclxuICAgICAgICAvLyBzbyBgVG9rZW5SZXZvY2F0aW9uRmFpbGluZ09wZW5gIGNhbiBhbGVydCBvbiBhIFNVU1RBSU5FRCByYXRlIChtaXJyb3JzXG4gICAgICAgIC8vIHRoZSBxdW90YV9mYWlsX29wZW5fdG90YWwgcGF0dGVybikuIE5vdCBlbWl0dGVkIGZvciB0aGUgXCJSZWRpcyBub3RcbiAgICAgICAgLy8gY29uZmlndXJlZFwiIHBhdGggKGNyZWF0ZUVudlJlZGlzVG9rZW5SZXZvY2F0aW9uU3RvcmUg4oaSIG51bGwgY2xpZW50KSxcbiAgICAgICAgLy8gd2hpY2ggaXMgYSBkZWxpYmVyYXRlIG9wdC1vdXQsIG5vdCBhIGRlZ3JhZGF0aW9uLlxuICAgICAgICBlbWl0Q291bnRlcigndG9rZW5fcmV2b2NhdGlvbl9mYWlsX29wZW5fdG90YWwnLCB7IHJlYXNvbjogJ3JlYWQtZXJyb3InIH0pO1xuICAgICAgICBsb2dnZXIuZGVidWcoJ1Rva2VuLXJldm9jYXRpb24gcmVhZCBmYWlsZWQgKGZhaWwtb3BlbiknLCB7XG4gICAgICAgICAgdXNlcklkLCBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSxcbiAgICBhc3luYyBnZXRTZXNzaW9uUmV2b2NhdGlvbihqdGk6IHN0cmluZyk6IFByb21pc2U8U2Vzc2lvblJldm9jYXRpb25TdGF0ZT4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmF3ID0gYXdhaXQgcmVkaXMuZ2V0KHNlc3Npb25SZXZvY2F0aW9uS2V5KGp0aSkpO1xuICAgICAgICByZXR1cm4gcmF3ID09PSBudWxsIHx8IHJhdyA9PT0gdW5kZWZpbmVkID8gJ2xpdmUnIDogJ3Jldm9rZWQnO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIC8vIE5PVCBmYWlsLW9wZW4sIHVubGlrZSBnZXRDdXJyZW50VmVyc2lvbiBhYm92ZTogYHVuYXZhaWxhYmxlYCByZWplY3RzXG4gICAgICAgIC8vIHRoZSBpbXBlcnNvbmF0aW9uIHRva2VuLiBDb3VudGVkIHNvIGEgc3VzdGFpbmVkIG91dGFnZSDigJQgd2hpY2ggc3RvcHNcbiAgICAgICAgLy8gc3VwcG9ydCBpbXBlcnNvbmF0aW9uIGV2ZXJ5d2hlcmUg4oCUIGlzIHZpc2libGUgYW5kIGFsZXJ0YWJsZS5cbiAgICAgICAgZW1pdENvdW50ZXIoJ3Nlc3Npb25fcmV2b2NhdGlvbl91bmF2YWlsYWJsZV90b3RhbCcsIHsgcmVhc29uOiAncmVhZC1lcnJvcicgfSk7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnU2Vzc2lvbi1yZXZvY2F0aW9uIHJlYWQgZmFpbGVkIChyZWplY3RpbmcgaW1wZXJzb25hdGlvbiB0b2tlbiknLCB7XG4gICAgICAgICAgZXJyb3I6IGVyciBpbnN0YW5jZW9mIEVycm9yID8gZXJyLm1lc3NhZ2UgOiBTdHJpbmcoZXJyKSxcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiAndW5hdmFpbGFibGUnO1xuICAgICAgfVxuICAgIH0sXG4gIH07XG59XG5cbi8qKlxuICogQnVpbGQgYSB7QGxpbmsgVG9rZW5SZXZvY2F0aW9uU3RvcmV9IGJhY2tlZCBieSBhIFJlZGlzIGNsaWVudCB0aGF0IGlzIGxhemlseVxuICogY29uc3RydWN0ZWQgZnJvbSB0aGUgc3RhbmRhcmQgYFJFRElTX1VSTGAgb3IgYFJFRElTX0hPU1RgL2BSRURJU19QT1JUYCBlbnYg4oCUXG4gKiBmb3IgYSBzdGF0ZWxlc3Mgc2VydmljZSB0aGF0IGtlZXBzIE5PIFJlZGlzIGNsaWVudCBvZiBpdHMgb3duLiBUaGUgY2xpZW50IGlzXG4gKiBidWlsdCBvbiBmaXJzdCBgZ2V0Q3VycmVudFZlcnNpb25gIGNhbGwgYW5kIG1lbW9pemVkOyBgaW9yZWRpc2AgaXMgbG9hZGVkIHZpYVxuICogYSBndWFyZGVkIGR5bmFtaWMgcmVxdWlyZSBzbyBtZXJlbHkgaW1wb3J0aW5nIHRoaXMgbmV2ZXIgYnJlYWtzIGEgYnVpbGQvdGVzdFxuICogd2hlcmUgUmVkaXMgaXNuJ3QgcHJlc2VudC5cbiAqXG4gKiBGVUxMWSBGQUlMLU9QRU46IG5vIGVudiBjb25maWd1cmVkLCBhbiBpb3JlZGlzIGxvYWQgZmFpbHVyZSwgYSBjb25uZWN0IGVycm9yLFxuICogb3IgYW55IHJlYWQgZmFpbHVyZSBhbGwgcmVzb2x2ZSB0byBgbnVsbGAgKFwibm8ga25vd24gcmV2b2NhdGlvblwiKSwgc28gYVxuICogc2VydmljZSBkZWdyYWRlcyB0byBuYXR1cmFsIHRva2VuIGV4cGlyeSByYXRoZXIgdGhhbiBsb2NraW5nIHVzZXJzIG91dC4gQVxuICogc2VydmljZSBvcHRzIGluIHdpdGggYSBzaW5nbGUgYm9vdCBsaW5lOlxuICogICBgc2V0VG9rZW5SZXZvY2F0aW9uU3RvcmUoY3JlYXRlRW52UmVkaXNUb2tlblJldm9jYXRpb25TdG9yZSgpKTtgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVFbnZSZWRpc1Rva2VuUmV2b2NhdGlvblN0b3JlKCk6IFRva2VuUmV2b2NhdGlvblN0b3JlIHtcbiAgLy8gdW5kZWZpbmVkID0gbm90IHlldCBhdHRlbXB0ZWQ7IG51bGwgPSBhdHRlbXB0ZWQgYW5kIHVuYXZhaWxhYmxlIChzdGF5IG9mZikuXG4gIGxldCBjYWNoZWQ6IFJlZGlzQ2FjaGVDbGllbnQgfCBudWxsIHwgdW5kZWZpbmVkO1xuXG4gIGZ1bmN0aW9uIGJ1aWxkKCk6IFJlZGlzQ2FjaGVDbGllbnQgfCBudWxsIHtcbiAgICAvLyBTaGFyZWQgZW52LWNvbmZpZ3VyZWQgaW9yZWRpcyBjb25zdHJ1Y3Rpb24gKGZhaWwtb3BlbiwgZXJyb3ItbGlzdGVuZXJcbiAgICAvLyBhdHRhY2hlZCwgbnVsbCB3aGVuIFJlZGlzIGlzbid0IGNvbmZpZ3VyZWQvYXZhaWxhYmxlKTsgdGhlIHJlYWRlciBzdGF5c1xuICAgIC8vIGZhaWwtb3BlbiDigJQgYSBudWxsIGNsaWVudCBqdXN0IGZhbGxzIGJhY2sgdG8gbmF0dXJhbCB0b2tlbiBleHBpcnkuXG4gICAgY29uc3QgaW5zdCA9IGNyZWF0ZUVudlJlZGlzQ2xpZW50PFJlZGlzQ2FjaGVDbGllbnQ+KCdyZXZvY2F0aW9uLXJlYWRlcicpO1xuICAgIGlmIChpbnN0KSBsb2dnZXIuaW5mbygnUmVkaXMgdG9rZW4tcmV2b2NhdGlvbiByZWFkZXIgaW5pdGlhbGl6ZWQnKTtcbiAgICByZXR1cm4gaW5zdDtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgYXN5bmMgZ2V0Q3VycmVudFZlcnNpb24odXNlcklkOiBzdHJpbmcpOiBQcm9taXNlPG51bWJlciB8IG51bGw+IHtcbiAgICAgIGlmIChjYWNoZWQgPT09IHVuZGVmaW5lZCkgY2FjaGVkID0gYnVpbGQoKTtcbiAgICAgIGlmICghY2FjaGVkKSByZXR1cm4gbnVsbDtcbiAgICAgIHJldHVybiBjcmVhdGVSZWRpc1Rva2VuUmV2b2NhdGlvblN0b3JlKGNhY2hlZCkuZ2V0Q3VycmVudFZlcnNpb24odXNlcklkKTtcbiAgICB9LFxuICAgIGFzeW5jIGdldFNlc3Npb25SZXZvY2F0aW9uKGp0aTogc3RyaW5nKTogUHJvbWlzZTxTZXNzaW9uUmV2b2NhdGlvblN0YXRlPiB7XG4gICAgICBpZiAoY2FjaGVkID09PSB1bmRlZmluZWQpIGNhY2hlZCA9IGJ1aWxkKCk7XG4gICAgICAvLyBObyBSZWRpcyBjb25maWd1cmVkIOKHkiB0aGVyZSBpcyBubyB3YXkgdG8gbGVhcm4gYSBzZXNzaW9uIHdhcyBlbmRlZCwgc29cbiAgICAgIC8vIGFuIGltcGVyc29uYXRpb24gdG9rZW4gY2FuJ3QgYmUgdHJ1c3RlZC4gRXZlcnkgcmVhbCBkZXBsb3ltZW50IHJ1bnMgUmVkaXNcbiAgICAgIC8vICh0aGUgYnVpbGQgcXVldWUgbmVlZHMgaXQpLCBzbyB0aGlzIG9ubHkgYml0ZXMgYSBtaXNjb25maWd1cmVkIHNlcnZpY2UuXG4gICAgICBpZiAoIWNhY2hlZCkge1xuICAgICAgICBlbWl0Q291bnRlcignc2Vzc2lvbl9yZXZvY2F0aW9uX3VuYXZhaWxhYmxlX3RvdGFsJywgeyByZWFzb246ICdub3QtY29uZmlndXJlZCcgfSk7XG4gICAgICAgIHJldHVybiAndW5hdmFpbGFibGUnO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGNyZWF0ZVJlZGlzVG9rZW5SZXZvY2F0aW9uU3RvcmUoY2FjaGVkKS5nZXRTZXNzaW9uUmV2b2NhdGlvbiEoanRpKTtcbiAgICB9LFxuICB9O1xufVxuXG4vKipcbiAqIFB1Ymxpc2ggYSB1c2VyJ3MgY3VycmVudCBgdG9rZW5WZXJzaW9uYCBzbyB0aGUgc3RhdGVsZXNzIHNlcnZpY2VzIHNlZSB0aGVcbiAqIHJldm9jYXRpb24gaW1tZWRpYXRlbHkgKHBsYXRmb3JtIHNpZGUpLiBCZXN0LWVmZm9ydCDigJQgbmV2ZXIgdGhyb3dzOyBhIGZhaWx1cmVcbiAqIGp1c3QgbWVhbnMgdGhlIHNlcnZpY2VzIGZhbGwgYmFjayB0byBuYXR1cmFsIHRva2VuIGV4cGlyeSBmb3IgdGhpcyBjaGFuZ2UuXG4gKlxuICogVGhlIGtleSBpcyB3cml0dGVuIHdpdGggYSBUVEwgZXF1YWwgdG8gdGhlIGFjY2Vzcy10b2tlbiBsaWZldGltZTogYW55IHRva2VuXG4gKiB0aGF0IGNvdWxkIHN0aWxsIGNhcnJ5IGFuIG9sZGVyIHZlcnNpb24gaGFzIGV4cGlyZWQgYnkgdGhlIHRpbWUgdGhlIGVudHJ5XG4gKiBsYXBzZXMsIHNvIGFuIGV4cGlyZWQgZW50cnkgY2FuIG5ldmVyIGNhdXNlIGEgZmFsc2UgXCJyZXZva2VkXCIgbm9yIGEgbWlzc2VkIG9uZS5cbiAqXG4gKiBAcGFyYW0gcmVkaXMgLSB0aGUgcGxhdGZvcm0ncyBSZWRpcyBjbGllbnRcbiAqIEBwYXJhbSB1c2VySWQgLSB0aGUgdXNlciB3aG9zZSBzZXNzaW9ucyBjaGFuZ2VkXG4gKiBAcGFyYW0gdG9rZW5WZXJzaW9uIC0gdGhlIHVzZXIncyBORVcgKHBvc3QtaW5jcmVtZW50KSB0b2tlblZlcnNpb25cbiAqIEBwYXJhbSB0dGxTZWNvbmRzIC0gYWNjZXNzLXRva2VuIGxpZmV0aW1lIGluIHNlY29uZHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHB1Ymxpc2hUb2tlblJldm9jYXRpb24oXG4gIHJlZGlzOiBSZWRpc0NhY2hlQ2xpZW50LFxuICB1c2VySWQ6IHN0cmluZyxcbiAgdG9rZW5WZXJzaW9uOiBudW1iZXIsXG4gIHR0bFNlY29uZHM6IG51bWJlcixcbik6IFByb21pc2U8dm9pZD4ge1xuICB0cnkge1xuICAgIC8vIGlvcmVkaXMtc3R5bGUgdmFyaWFkaWMgU0VUIHdpdGggZXhwaXJ5OiBTRVQga2V5IHZhbCBFWCB0dGwuXG4gICAgYXdhaXQgcmVkaXMuc2V0KHRva2VuUmV2b2NhdGlvbktleSh1c2VySWQpLCBTdHJpbmcodG9rZW5WZXJzaW9uKSwgJ0VYJywgTWF0aC5tYXgoMSwgTWF0aC5mbG9vcih0dGxTZWNvbmRzKSkpO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBsb2dnZXIud2FybignVG9rZW4tcmV2b2NhdGlvbiBwdWJsaXNoIGZhaWxlZCAoc2VydmljZXMgZmFsbCBiYWNrIHRvIHRva2VuIGV4cGlyeSknLCB7XG4gICAgICB1c2VySWQsIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBQdWJsaXNoIHRoYXQgb25lIElNUEVSU09OQVRJT04gc2Vzc2lvbiBoYXMgZW5kZWQsIHNvIGV2ZXJ5IHN0YXRlbGVzcyBzZXJ2aWNlXG4gKiByZWplY3RzIGl0cyB0b2tlbiBvbiB0aGUgbmV4dCByZXF1ZXN0IChwbGF0Zm9ybSBzaWRlKS5cbiAqXG4gKiBSZXR1cm5zIHdoZXRoZXIgdGhlIHB1Ymxpc2ggbGFuZGVkIOKAlCB1bmxpa2UgYHB1Ymxpc2hUb2tlblJldm9jYXRpb25gLCB3aGljaCBpc1xuICogZmlyZS1hbmQtZm9yZ2V0LiBUaGUgY2FsbGVyIG11c3QgYmUgYWJsZSB0byB0ZWxsIHRoZSBwZXJzb24gd2hvIGVuZGVkIHRoZVxuICogc2Vzc2lvbiB0aGF0IGl0IGRpZCBOT1QgZW5kIGV2ZXJ5d2hlcmUsIHJhdGhlciB0aGFuIHJlcG9ydGluZyBzdWNjZXNzIHdoaWxlXG4gKiB0aGUgdG9rZW4gc3RpbGwgd29ya3MgYWdhaW5zdCBvdGhlciBzZXJ2aWNlcy5cbiAqXG4gKiBUaGUgZW50cnkgZXhwaXJlcyB3aXRoIHRoZSBzZXNzaW9uOiBvbmNlIHRoZSB0b2tlbiBpdHNlbGYgY2FuIG5vIGxvbmdlciBiZVxuICogdXNlZCwgdGhlcmUgaXMgbm90aGluZyBsZWZ0IHRvIHJldm9rZSwgc28gdGhlIGtleSBjbGVhbnMgaXRzZWxmIHVwLlxuICpcbiAqIEBwYXJhbSB0dGxNcyAtIHRpbWUgcmVtYWluaW5nIG9uIHRoZSBzZXNzaW9uJ3MgdG9rZW5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHB1Ymxpc2hTZXNzaW9uUmV2b2NhdGlvbihcbiAgcmVkaXM6IFJlZGlzQ2FjaGVDbGllbnQsXG4gIGp0aTogc3RyaW5nLFxuICB0dGxNczogbnVtYmVyLFxuKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIHRyeSB7XG4gICAgYXdhaXQgcmVkaXMuc2V0KHNlc3Npb25SZXZvY2F0aW9uS2V5KGp0aSksICcxJywgJ1BYJywgTWF0aC5tYXgoMTAwMCwgTWF0aC5jZWlsKHR0bE1zKSkpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBsb2dnZXIud2FybignU2Vzc2lvbi1yZXZvY2F0aW9uIHB1Ymxpc2ggZmFpbGVkIChvdGhlciBzZXJ2aWNlcyB3aWxsIGhvbm91ciB0aGUgdG9rZW4gdW50aWwgaXQgZXhwaXJlcyknLCB7XG4gICAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgIH0pO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuIl19
196
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4tcmV2b2NhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy90b2tlbi1yZXZvY2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFHdEMsT0FBTyxFQUFFLG9CQUFvQixFQUFFLG9CQUFvQixFQUF3QixNQUFNLGdCQUFnQixDQUFDO0FBRWxHLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFFekQsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLGtCQUFrQixDQUFDLENBQUM7QUFFaEQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxDQUFDLE1BQU0sMkJBQTJCLEdBQUcsYUFBYSxDQUFDO0FBRXpELHdDQUF3QztBQUN4QyxNQUFNLFVBQVUsa0JBQWtCLENBQUMsTUFBYztJQUMvQyxPQUFPLEdBQUcsMkJBQTJCLEdBQUcsTUFBTSxFQUFFLENBQUM7QUFDbkQsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSw2QkFBNkIsR0FBRyxjQUFjLENBQUM7QUFFNUQscURBQXFEO0FBQ3JELE1BQU0sVUFBVSxvQkFBb0IsQ0FBQyxHQUFXO0lBQzlDLE9BQU8sR0FBRyw2QkFBNkIsR0FBRyxHQUFHLEVBQUUsQ0FBQztBQUNsRCxDQUFDO0FBRUQ7Ozs7Ozs7O0dBUUc7QUFDSCxNQUFNLFVBQVUsK0JBQStCLENBQUMsS0FBdUI7SUFDckUsT0FBTztRQUNMLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxNQUFjO1lBQ3BDLElBQUksQ0FBQztnQkFDSCxNQUFNLEdBQUcsR0FBRyxNQUFNLEtBQUssQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztnQkFDeEQsSUFBSSxHQUFHLEtBQUssSUFBSSxJQUFJLEdBQUcsS0FBSyxTQUFTLElBQUksR0FBRyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUU7b0JBQUUsT0FBTyxJQUFJLENBQUM7Z0JBQ3hFLHNFQUFzRTtnQkFDdEUsdUVBQXVFO2dCQUN2RSx3RUFBd0U7Z0JBQ3hFLDBEQUEwRDtnQkFDMUQsTUFBTSxDQUFDLEdBQUcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUN0QixPQUFPLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQ3hDLENBQUM7WUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUNiLHFFQUFxRTtnQkFDckUseUVBQXlFO2dCQUN6RSx5RUFBeUU7Z0JBQ3pFLHlFQUF5RTtnQkFDekUscUVBQXFFO2dCQUNyRSx1RUFBdUU7Z0JBQ3ZFLG9EQUFvRDtnQkFDcEQsV0FBVyxDQUFDLGtDQUFrQyxFQUFFLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7Z0JBQzFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsMENBQTBDLEVBQUU7b0JBQ3ZELE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztpQkFDaEUsQ0FBQyxDQUFDO2dCQUNILE9BQU8sSUFBSSxDQUFDO1lBQ2QsQ0FBQztRQUNILENBQUM7UUFDRCxLQUFLLENBQUMsb0JBQW9CLENBQUMsR0FBVztZQUNwQyxJQUFJLENBQUM7Z0JBQ0gsTUFBTSxHQUFHLEdBQUcsTUFBTSxLQUFLLENBQUMsR0FBRyxDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7Z0JBQ3ZELE9BQU8sR0FBRyxLQUFLLElBQUksSUFBSSxHQUFHLEtBQUssU0FBUyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztZQUNoRSxDQUFDO1lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztnQkFDYix1RUFBdUU7Z0JBQ3ZFLHVFQUF1RTtnQkFDdkUsK0RBQStEO2dCQUMvRCxXQUFXLENBQUMsc0NBQXNDLEVBQUUsRUFBRSxNQUFNLEVBQUUsWUFBWSxFQUFFLENBQUMsQ0FBQztnQkFDOUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxnRUFBZ0UsRUFBRTtvQkFDN0UsS0FBSyxFQUFFLEdBQUcsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUM7aUJBQ3hELENBQUMsQ0FBQztnQkFDSCxPQUFPLGFBQWEsQ0FBQztZQUN2QixDQUFDO1FBQ0gsQ0FBQztLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sVUFBVSxrQ0FBa0M7SUFFaEQsOEVBQThFO0lBQzlFLElBQUksTUFBc0MsQ0FBQztJQUMzQyxJQUFJLEtBQXdDLENBQUM7SUFFN0M7Ozs7OztPQU1HO0lBQ0gsS0FBSyxVQUFVLE1BQU07UUFDbkIsSUFBSSxNQUFNLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDekIsNEVBQTRFO1lBQzVFLDJFQUEyRTtZQUMzRSwyQ0FBMkM7WUFDM0MsTUFBTSxHQUFHLG9CQUFvQixDQUFjLG1CQUFtQixDQUFDLENBQUM7WUFDaEUsSUFBSSxNQUFNLEVBQUUsQ0FBQztnQkFDWCxNQUFNLENBQUMsSUFBSSxDQUFDLDJDQUEyQyxDQUFDLENBQUM7Z0JBQ3pELEtBQUssR0FBRyxvQkFBb0IsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN2QyxDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksS0FBSztZQUFFLE1BQU0sS0FBSyxFQUFFLENBQUM7UUFDekIsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVELE9BQU87UUFDTCxLQUFLLENBQUMsaUJBQWlCLENBQUMsTUFBYztZQUNwQyxNQUFNLEtBQUssR0FBRyxNQUFNLE1BQU0sRUFBRSxDQUFDO1lBQzdCLElBQUksQ0FBQyxLQUFLO2dCQUFFLE9BQU8sSUFBSSxDQUFDO1lBQ3hCLE9BQU8sK0JBQStCLENBQUMsS0FBSyxDQUFDLENBQUMsaUJBQWlCLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDMUUsQ0FBQztRQUNELEtBQUssQ0FBQyxvQkFBb0IsQ0FBQyxHQUFXO1lBQ3BDLE1BQU0sS0FBSyxHQUFHLE1BQU0sTUFBTSxFQUFFLENBQUM7WUFDN0IseUVBQXlFO1lBQ3pFLDRFQUE0RTtZQUM1RSwwRUFBMEU7WUFDMUUsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNYLFdBQVcsQ0FBQyxzQ0FBc0MsRUFBRSxFQUFFLE1BQU0sRUFBRSxnQkFBZ0IsRUFBRSxDQUFDLENBQUM7Z0JBQ2xGLE9BQU8sYUFBYSxDQUFDO1lBQ3ZCLENBQUM7WUFDRCxPQUFPLCtCQUErQixDQUFDLEtBQUssQ0FBQyxDQUFDLG9CQUFxQixDQUFDLEdBQUcsQ0FBQyxDQUFDO1FBQzNFLENBQUM7S0FDRixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLHNCQUFzQixDQUMxQyxLQUF1QixFQUN2QixNQUFjLEVBQ2QsWUFBb0IsRUFDcEIsVUFBa0I7SUFFbEIsSUFBSSxDQUFDO1FBQ0gsOERBQThEO1FBQzlELE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsRUFBRSxNQUFNLENBQUMsWUFBWSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQy9HLENBQUM7SUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2IsTUFBTSxDQUFDLElBQUksQ0FBQyxzRUFBc0UsRUFBRTtZQUNsRixNQUFNLEVBQUUsS0FBSyxFQUFFLEdBQUcsWUFBWSxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUM7U0FDaEUsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztBQUNILENBQUM7QUFFRDs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSx3QkFBd0IsQ0FDNUMsS0FBdUIsRUFDdkIsR0FBVyxFQUNYLEtBQWE7SUFFYixJQUFJLENBQUM7UUFDSCxNQUFNLEtBQUssQ0FBQyxHQUFHLENBQUMsb0JBQW9CLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN4RixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2IsTUFBTSxDQUFDLElBQUksQ0FBQywyRkFBMkYsRUFBRTtZQUN2RyxLQUFLLEVBQUUsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztTQUN4RCxDQUFDLENBQUM7UUFDSCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB0eXBlIHsgUmVkaXNDYWNoZUNsaWVudCB9IGZyb20gJy4vY2FjaGUtc2VydmljZS5qcyc7XG5pbXBvcnQgeyBjcmVhdGVFbnZSZWRpc0NsaWVudCwgY3JlYXRlUmVkaXNSZWFkeUdhdGUsIHR5cGUgUmVhZHlBd2FyZVJlZGlzIH0gZnJvbSAnLi9lbnYtcmVkaXMuanMnO1xuaW1wb3J0IHR5cGUgeyBTZXNzaW9uUmV2b2NhdGlvblN0YXRlLCBUb2tlblJldm9jYXRpb25TdG9yZSB9IGZyb20gJy4uL21pZGRsZXdhcmUvYXV0aC5qcyc7XG5pbXBvcnQgeyBjcmVhdGVMb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuaW1wb3J0IHsgZW1pdENvdW50ZXIgfSBmcm9tICcuLi91dGlscy9tZXRyaWMtZW1pdHRlci5qcyc7XG5cbmNvbnN0IGxvZ2dlciA9IGNyZWF0ZUxvZ2dlcigndG9rZW4tcmV2b2NhdGlvbicpO1xuXG4vKipcbiAqIFJlZGlzIGtleSBuYW1lc3BhY2UgZm9yIHRoZSBwZXItdXNlciBjdXJyZW50IGB0b2tlblZlcnNpb25gLiBUaGUgcGxhdGZvcm1cbiAqIFBVQkxJU0hFUyB0byB0aGlzIGtleSBvbiBldmVyeSBwcml2aWxlZ2UgY2hhbmdlOyB0aGUgc3RhdGVsZXNzIHNlcnZpY2VzIFJFQURcbiAqIGl0IGluIGByZXF1aXJlQXV0aGAgKHZpYSB7QGxpbmsgY3JlYXRlUmVkaXNUb2tlblJldm9jYXRpb25TdG9yZX0pIHRvIHJlamVjdFxuICogdG9rZW5zIG1pbnRlZCBiZWZvcmUgdGhhdCBjaGFuZ2UuIFB1Ymxpc2hlciBhbmQgcmVhZGVycyBNVVNUIHNoYXJlIHRoaXMgZXhhY3RcbiAqIHByZWZpeCDigJQgaGVuY2UgYm90aCBoZWxwZXJzIGxpdmUgaGVyZSwgaW4gb25lIHBsYWNlLlxuICovXG5leHBvcnQgY29uc3QgVE9LRU5fUkVWT0NBVElPTl9LRVlfUFJFRklYID0gJ2F1dGhyZXY6dHY6JztcblxuLyoqIFRoZSByZXZvY2F0aW9uIGtleSBmb3IgYSB1c2VyIGlkLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRva2VuUmV2b2NhdGlvbktleSh1c2VySWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtUT0tFTl9SRVZPQ0FUSU9OX0tFWV9QUkVGSVh9JHt1c2VySWR9YDtcbn1cblxuLyoqXG4gKiBSZWRpcyBrZXkgbmFtZXNwYWNlIGZvciBlbmRlZCBJTVBFUlNPTkFUSU9OIHNlc3Npb25zLCBieSB0b2tlbiBganRpYC4gU2FtZVxuICogcHVibGlzaC9yZWFkIHNwbGl0IGFzIHRoZSB0b2tlblZlcnNpb24ga2V5cyBhYm92ZSwgYW5kIGtlcHQgYmVzaWRlIHRoZW0gZm9yIHRoZVxuICogc2FtZSByZWFzb246IHB1Ymxpc2hlciBhbmQgcmVhZGVycyBtdXN0IGFncmVlIG9uIHRoaXMgZXhhY3QgcHJlZml4LlxuICovXG5leHBvcnQgY29uc3QgU0VTU0lPTl9SRVZPQ0FUSU9OX0tFWV9QUkVGSVggPSAnYXV0aHJldjpqdGk6JztcblxuLyoqIFRoZSByZXZvY2F0aW9uIGtleSBmb3Igb25lIHNlc3Npb24ncyB0b2tlbiBpZC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXNzaW9uUmV2b2NhdGlvbktleShqdGk6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtTRVNTSU9OX1JFVk9DQVRJT05fS0VZX1BSRUZJWH0ke2p0aX1gO1xufVxuXG4vKipcbiAqIEJ1aWxkIGEge0BsaW5rIFRva2VuUmV2b2NhdGlvblN0b3JlfSBiYWNrZWQgYnkgYSBSZWRpcyBjbGllbnQsIGZvciBhIHN0YXRlbGVzc1xuICogc2VydmljZSB0byByZWdpc3RlciB2aWEgYHNldFRva2VuUmV2b2NhdGlvblN0b3JlYC4gUmVhZHMgdGhlIGN1cnJlbnRcbiAqIGB0b2tlblZlcnNpb25gIHRoZSBwbGF0Zm9ybSBwdWJsaXNoZWQgZm9yIHRoZSB1c2VyLlxuICpcbiAqIEZhaWwtb3BlbiBieSBjb250cmFjdDogYSBtaXNzLCBhIHBhcnNlIGZhaWx1cmUsIG9yIGEgUmVkaXMgZXJyb3IgYWxsIHlpZWxkXG4gKiBgbnVsbGAgKOKAlCBgcmVxdWlyZUF1dGhgIHRyZWF0cyB0aGF0IGFzIFwibm8ga25vd24gcmV2b2NhdGlvblwiKSwgc28gYSBSZWRpc1xuICogb3V0YWdlIGRlZ3JhZGVzIHRvIHRoZSBwcmUtZXhpc3RpbmcgYmVoYXZpb3VyIHJhdGhlciB0aGFuIGxvY2tpbmcgdXNlcnMgb3V0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUmVkaXNUb2tlblJldm9jYXRpb25TdG9yZShyZWRpczogUmVkaXNDYWNoZUNsaWVudCk6IFRva2VuUmV2b2NhdGlvblN0b3JlIHtcbiAgcmV0dXJuIHtcbiAgICBhc3luYyBnZXRDdXJyZW50VmVyc2lvbih1c2VySWQ6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyIHwgbnVsbD4ge1xuICAgICAgdHJ5IHtcbiAgICAgICAgY29uc3QgcmF3ID0gYXdhaXQgcmVkaXMuZ2V0KHRva2VuUmV2b2NhdGlvbktleSh1c2VySWQpKTtcbiAgICAgICAgaWYgKHJhdyA9PT0gbnVsbCB8fCByYXcgPT09IHVuZGVmaW5lZCB8fCByYXcudHJpbSgpID09PSAnJykgcmV0dXJuIG51bGw7XG4gICAgICAgIC8vIFN0cmljdCBpbnRlZ2VyIHBhcnNlOiBgTnVtYmVyYCAodW5saWtlIGBwYXJzZUludGApIHJlamVjdHMgdHJhaWxpbmdcbiAgICAgICAgLy8gZ2FyYmFnZSAoXCI1YWJjXCIg4oaSIE5hTiksIHNvIGEgY29ycnVwdGVkIGVudHJ5IGZhaWxzIG9wZW4gKG51bGwg4oaSIFwibm90XG4gICAgICAgIC8vIHJldm9rZWRcIikgcmF0aGVyIHRoYW4gYmVpbmcgcmVhZCBhcyBhIGJvZ3VzIHZlcnNpb24uIFRoZSBlbXB0eS1zdHJpbmdcbiAgICAgICAgLy8gZ3VhcmQgYWJvdmUgbWF0dGVycyBiZWNhdXNlIGBOdW1iZXIoJycpYCBpcyAwLCBub3QgTmFOLlxuICAgICAgICBjb25zdCBuID0gTnVtYmVyKHJhdyk7XG4gICAgICAgIHJldHVybiBOdW1iZXIuaXNJbnRlZ2VyKG4pID8gbiA6IG51bGw7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgLy8gUmVkaXMgd2FzIHJlYWNoYWJsZSBlbm91Z2ggdG8gdHJ5IGJ1dCB0aGUgcmVhZCBlcnJvcmVkIOKAlCB0aGlzIGlzIGFcbiAgICAgICAgLy8gREVHUkFEQVRJT046IHdoaWxlIGl0IHBlcnNpc3RzLCBmb3JjZWQgbG9nb3V0cyAvIHByaXZpbGVnZSByZXZvY2F0aW9uc1xuICAgICAgICAvLyBzaWxlbnRseSBzdG9wIHRha2luZyBlZmZlY3QgdW50aWwgbmF0dXJhbCB0b2tlbiBleHBpcnkuIEVtaXQgYSBjb3VudGVyXG4gICAgICAgIC8vIHNvIGBUb2tlblJldm9jYXRpb25GYWlsaW5nT3BlbmAgY2FuIGFsZXJ0IG9uIGEgU1VTVEFJTkVEIHJhdGUgKG1pcnJvcnNcbiAgICAgICAgLy8gdGhlIHF1b3RhX2ZhaWxfb3Blbl90b3RhbCBwYXR0ZXJuKS4gTm90IGVtaXR0ZWQgZm9yIHRoZSBcIlJlZGlzIG5vdFxuICAgICAgICAvLyBjb25maWd1cmVkXCIgcGF0aCAoY3JlYXRlRW52UmVkaXNUb2tlblJldm9jYXRpb25TdG9yZSDihpIgbnVsbCBjbGllbnQpLFxuICAgICAgICAvLyB3aGljaCBpcyBhIGRlbGliZXJhdGUgb3B0LW91dCwgbm90IGEgZGVncmFkYXRpb24uXG4gICAgICAgIGVtaXRDb3VudGVyKCd0b2tlbl9yZXZvY2F0aW9uX2ZhaWxfb3Blbl90b3RhbCcsIHsgcmVhc29uOiAncmVhZC1lcnJvcicgfSk7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnVG9rZW4tcmV2b2NhdGlvbiByZWFkIGZhaWxlZCAoZmFpbC1vcGVuKScsIHtcbiAgICAgICAgICB1c2VySWQsIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9LFxuICAgIGFzeW5jIGdldFNlc3Npb25SZXZvY2F0aW9uKGp0aTogc3RyaW5nKTogUHJvbWlzZTxTZXNzaW9uUmV2b2NhdGlvblN0YXRlPiB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByYXcgPSBhd2FpdCByZWRpcy5nZXQoc2Vzc2lvblJldm9jYXRpb25LZXkoanRpKSk7XG4gICAgICAgIHJldHVybiByYXcgPT09IG51bGwgfHwgcmF3ID09PSB1bmRlZmluZWQgPyAnbGl2ZScgOiAncmV2b2tlZCc7XG4gICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgLy8gTk9UIGZhaWwtb3BlbiwgdW5saWtlIGdldEN1cnJlbnRWZXJzaW9uIGFib3ZlOiBgdW5hdmFpbGFibGVgIHJlamVjdHNcbiAgICAgICAgLy8gdGhlIGltcGVyc29uYXRpb24gdG9rZW4uIENvdW50ZWQgc28gYSBzdXN0YWluZWQgb3V0YWdlIOKAlCB3aGljaCBzdG9wc1xuICAgICAgICAvLyBzdXBwb3J0IGltcGVyc29uYXRpb24gZXZlcnl3aGVyZSDigJQgaXMgdmlzaWJsZSBhbmQgYWxlcnRhYmxlLlxuICAgICAgICBlbWl0Q291bnRlcignc2Vzc2lvbl9yZXZvY2F0aW9uX3VuYXZhaWxhYmxlX3RvdGFsJywgeyByZWFzb246ICdyZWFkLWVycm9yJyB9KTtcbiAgICAgICAgbG9nZ2VyLmRlYnVnKCdTZXNzaW9uLXJldm9jYXRpb24gcmVhZCBmYWlsZWQgKHJlamVjdGluZyBpbXBlcnNvbmF0aW9uIHRva2VuKScsIHtcbiAgICAgICAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuICd1bmF2YWlsYWJsZSc7XG4gICAgICB9XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBCdWlsZCBhIHtAbGluayBUb2tlblJldm9jYXRpb25TdG9yZX0gYmFja2VkIGJ5IGEgUmVkaXMgY2xpZW50IHRoYXQgaXMgbGF6aWx5XG4gKiBjb25zdHJ1Y3RlZCBmcm9tIHRoZSBzdGFuZGFyZCBgUkVESVNfVVJMYCBvciBgUkVESVNfU0VOVElORUxTYCBlbnYg4oCUXG4gKiBmb3IgYSBzdGF0ZWxlc3Mgc2VydmljZSB0aGF0IGtlZXBzIE5PIFJlZGlzIGNsaWVudCBvZiBpdHMgb3duLiBUaGUgY2xpZW50IGlzXG4gKiBidWlsdCBvbiBmaXJzdCBgZ2V0Q3VycmVudFZlcnNpb25gIGNhbGwgYW5kIG1lbW9pemVkOyBgaW9yZWRpc2AgaXMgbG9hZGVkIHZpYVxuICogYSBndWFyZGVkIGR5bmFtaWMgcmVxdWlyZSBzbyBtZXJlbHkgaW1wb3J0aW5nIHRoaXMgbmV2ZXIgYnJlYWtzIGEgYnVpbGQvdGVzdFxuICogd2hlcmUgUmVkaXMgaXNuJ3QgcHJlc2VudC5cbiAqXG4gKiBGVUxMWSBGQUlMLU9QRU46IG5vIGVudiBjb25maWd1cmVkLCBhbiBpb3JlZGlzIGxvYWQgZmFpbHVyZSwgYSBjb25uZWN0IGVycm9yLFxuICogb3IgYW55IHJlYWQgZmFpbHVyZSBhbGwgcmVzb2x2ZSB0byBgbnVsbGAgKFwibm8ga25vd24gcmV2b2NhdGlvblwiKSwgc28gYVxuICogc2VydmljZSBkZWdyYWRlcyB0byBuYXR1cmFsIHRva2VuIGV4cGlyeSByYXRoZXIgdGhhbiBsb2NraW5nIHVzZXJzIG91dC4gQVxuICogc2VydmljZSBvcHRzIGluIHdpdGggYSBzaW5nbGUgYm9vdCBsaW5lOlxuICogICBgc2V0VG9rZW5SZXZvY2F0aW9uU3RvcmUoY3JlYXRlRW52UmVkaXNUb2tlblJldm9jYXRpb25TdG9yZSgpKTtgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVFbnZSZWRpc1Rva2VuUmV2b2NhdGlvblN0b3JlKCk6IFRva2VuUmV2b2NhdGlvblN0b3JlIHtcbiAgdHlwZSBSZWFkZXJSZWRpcyA9IFJlZGlzQ2FjaGVDbGllbnQgJiBSZWFkeUF3YXJlUmVkaXM7XG4gIC8vIHVuZGVmaW5lZCA9IG5vdCB5ZXQgYXR0ZW1wdGVkOyBudWxsID0gYXR0ZW1wdGVkIGFuZCB1bmF2YWlsYWJsZSAoc3RheSBvZmYpLlxuICBsZXQgY2FjaGVkOiBSZWFkZXJSZWRpcyB8IG51bGwgfCB1bmRlZmluZWQ7XG4gIGxldCByZWFkeTogKCgpID0+IFByb21pc2U8dm9pZD4pIHwgdW5kZWZpbmVkO1xuXG4gIC8qKlxuICAgKiBUaGUgcmVhZGVyIGNsaWVudCwgYnVpbHQgb24gZmlyc3QgdXNlLiBUaGUgZW52IGNsaWVudCBoYXMgbm8gb2ZmbGluZSBxdWV1ZSxcbiAgICogc28gYSBHRVQgYmVmb3JlIHRoZSBmaXJzdCBjb25uZWN0aW9uIGNvbXBsZXRlcyBpcyByZWplY3RlZCDigJQgd2hpY2ggbWFkZSB0aGVcbiAgICogRklSU1QgaW1wZXJzb25hdGlvbiBjaGVjayBvbiBldmVyeSBwb2QgcmVhZCAndW5hdmFpbGFibGUnICg0MDEpLiBXYWl0XG4gICAqIChib3VuZGVkLCBuZXZlciByZWplY3RpbmcpIGZvciByZWFkaW5lc3M7IGEgZ2VudWluZWx5IGRvd24gUmVkaXMgdGhlbiBrZWVwc1xuICAgKiB0aGUgZXhpc3RpbmcgZmFpbC1vcGVuIC8gJ3VuYXZhaWxhYmxlJyBzZW1hbnRpY3MuXG4gICAqL1xuICBhc3luYyBmdW5jdGlvbiBjbGllbnQoKTogUHJvbWlzZTxSZWFkZXJSZWRpcyB8IG51bGw+IHtcbiAgICBpZiAoY2FjaGVkID09PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIFNoYXJlZCBlbnYtY29uZmlndXJlZCBpb3JlZGlzIGNvbnN0cnVjdGlvbiAoZXJyb3IgbGlzdGVuZXIgYXR0YWNoZWQsIG51bGxcbiAgICAgIC8vIHdoZW4gUmVkaXMgaXNuJ3QgY29uZmlndXJlZCk7IHRoZSByZWFkZXIgc3RheXMgZmFpbC1vcGVuIOKAlCBhIG51bGwgY2xpZW50XG4gICAgICAvLyBqdXN0IGZhbGxzIGJhY2sgdG8gbmF0dXJhbCB0b2tlbiBleHBpcnkuXG4gICAgICBjYWNoZWQgPSBjcmVhdGVFbnZSZWRpc0NsaWVudDxSZWFkZXJSZWRpcz4oJ3Jldm9jYXRpb24tcmVhZGVyJyk7XG4gICAgICBpZiAoY2FjaGVkKSB7XG4gICAgICAgIGxvZ2dlci5pbmZvKCdSZWRpcyB0b2tlbi1yZXZvY2F0aW9uIHJlYWRlciBpbml0aWFsaXplZCcpO1xuICAgICAgICByZWFkeSA9IGNyZWF0ZVJlZGlzUmVhZHlHYXRlKGNhY2hlZCk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChyZWFkeSkgYXdhaXQgcmVhZHkoKTtcbiAgICByZXR1cm4gY2FjaGVkO1xuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBhc3luYyBnZXRDdXJyZW50VmVyc2lvbih1c2VySWQ6IHN0cmluZyk6IFByb21pc2U8bnVtYmVyIHwgbnVsbD4ge1xuICAgICAgY29uc3QgcmVkaXMgPSBhd2FpdCBjbGllbnQoKTtcbiAgICAgIGlmICghcmVkaXMpIHJldHVybiBudWxsO1xuICAgICAgcmV0dXJuIGNyZWF0ZVJlZGlzVG9rZW5SZXZvY2F0aW9uU3RvcmUocmVkaXMpLmdldEN1cnJlbnRWZXJzaW9uKHVzZXJJZCk7XG4gICAgfSxcbiAgICBhc3luYyBnZXRTZXNzaW9uUmV2b2NhdGlvbihqdGk6IHN0cmluZyk6IFByb21pc2U8U2Vzc2lvblJldm9jYXRpb25TdGF0ZT4ge1xuICAgICAgY29uc3QgcmVkaXMgPSBhd2FpdCBjbGllbnQoKTtcbiAgICAgIC8vIE5vIFJlZGlzIGNvbmZpZ3VyZWQg4oeSIHRoZXJlIGlzIG5vIHdheSB0byBsZWFybiBhIHNlc3Npb24gd2FzIGVuZGVkLCBzb1xuICAgICAgLy8gYW4gaW1wZXJzb25hdGlvbiB0b2tlbiBjYW4ndCBiZSB0cnVzdGVkLiBFdmVyeSByZWFsIGRlcGxveW1lbnQgcnVucyBSZWRpc1xuICAgICAgLy8gKHRoZSBidWlsZCBxdWV1ZSBuZWVkcyBpdCksIHNvIHRoaXMgb25seSBiaXRlcyBhIG1pc2NvbmZpZ3VyZWQgc2VydmljZS5cbiAgICAgIGlmICghcmVkaXMpIHtcbiAgICAgICAgZW1pdENvdW50ZXIoJ3Nlc3Npb25fcmV2b2NhdGlvbl91bmF2YWlsYWJsZV90b3RhbCcsIHsgcmVhc29uOiAnbm90LWNvbmZpZ3VyZWQnIH0pO1xuICAgICAgICByZXR1cm4gJ3VuYXZhaWxhYmxlJztcbiAgICAgIH1cbiAgICAgIHJldHVybiBjcmVhdGVSZWRpc1Rva2VuUmV2b2NhdGlvblN0b3JlKHJlZGlzKS5nZXRTZXNzaW9uUmV2b2NhdGlvbiEoanRpKTtcbiAgICB9LFxuICB9O1xufVxuXG4vKipcbiAqIFB1Ymxpc2ggYSB1c2VyJ3MgY3VycmVudCBgdG9rZW5WZXJzaW9uYCBzbyB0aGUgc3RhdGVsZXNzIHNlcnZpY2VzIHNlZSB0aGVcbiAqIHJldm9jYXRpb24gaW1tZWRpYXRlbHkgKHBsYXRmb3JtIHNpZGUpLiBCZXN0LWVmZm9ydCDigJQgbmV2ZXIgdGhyb3dzOyBhIGZhaWx1cmVcbiAqIGp1c3QgbWVhbnMgdGhlIHNlcnZpY2VzIGZhbGwgYmFjayB0byBuYXR1cmFsIHRva2VuIGV4cGlyeSBmb3IgdGhpcyBjaGFuZ2UuXG4gKlxuICogVGhlIGtleSBpcyB3cml0dGVuIHdpdGggYSBUVEwgZXF1YWwgdG8gdGhlIGFjY2Vzcy10b2tlbiBsaWZldGltZTogYW55IHRva2VuXG4gKiB0aGF0IGNvdWxkIHN0aWxsIGNhcnJ5IGFuIG9sZGVyIHZlcnNpb24gaGFzIGV4cGlyZWQgYnkgdGhlIHRpbWUgdGhlIGVudHJ5XG4gKiBsYXBzZXMsIHNvIGFuIGV4cGlyZWQgZW50cnkgY2FuIG5ldmVyIGNhdXNlIGEgZmFsc2UgXCJyZXZva2VkXCIgbm9yIGEgbWlzc2VkIG9uZS5cbiAqXG4gKiBAcGFyYW0gcmVkaXMgLSB0aGUgcGxhdGZvcm0ncyBSZWRpcyBjbGllbnRcbiAqIEBwYXJhbSB1c2VySWQgLSB0aGUgdXNlciB3aG9zZSBzZXNzaW9ucyBjaGFuZ2VkXG4gKiBAcGFyYW0gdG9rZW5WZXJzaW9uIC0gdGhlIHVzZXIncyBORVcgKHBvc3QtaW5jcmVtZW50KSB0b2tlblZlcnNpb25cbiAqIEBwYXJhbSB0dGxTZWNvbmRzIC0gYWNjZXNzLXRva2VuIGxpZmV0aW1lIGluIHNlY29uZHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHB1Ymxpc2hUb2tlblJldm9jYXRpb24oXG4gIHJlZGlzOiBSZWRpc0NhY2hlQ2xpZW50LFxuICB1c2VySWQ6IHN0cmluZyxcbiAgdG9rZW5WZXJzaW9uOiBudW1iZXIsXG4gIHR0bFNlY29uZHM6IG51bWJlcixcbik6IFByb21pc2U8dm9pZD4ge1xuICB0cnkge1xuICAgIC8vIGlvcmVkaXMtc3R5bGUgdmFyaWFkaWMgU0VUIHdpdGggZXhwaXJ5OiBTRVQga2V5IHZhbCBFWCB0dGwuXG4gICAgYXdhaXQgcmVkaXMuc2V0KHRva2VuUmV2b2NhdGlvbktleSh1c2VySWQpLCBTdHJpbmcodG9rZW5WZXJzaW9uKSwgJ0VYJywgTWF0aC5tYXgoMSwgTWF0aC5mbG9vcih0dGxTZWNvbmRzKSkpO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBsb2dnZXIud2FybignVG9rZW4tcmV2b2NhdGlvbiBwdWJsaXNoIGZhaWxlZCAoc2VydmljZXMgZmFsbCBiYWNrIHRvIHRva2VuIGV4cGlyeSknLCB7XG4gICAgICB1c2VySWQsIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqXG4gKiBQdWJsaXNoIHRoYXQgb25lIElNUEVSU09OQVRJT04gc2Vzc2lvbiBoYXMgZW5kZWQsIHNvIGV2ZXJ5IHN0YXRlbGVzcyBzZXJ2aWNlXG4gKiByZWplY3RzIGl0cyB0b2tlbiBvbiB0aGUgbmV4dCByZXF1ZXN0IChwbGF0Zm9ybSBzaWRlKS5cbiAqXG4gKiBSZXR1cm5zIHdoZXRoZXIgdGhlIHB1Ymxpc2ggbGFuZGVkIOKAlCB1bmxpa2UgYHB1Ymxpc2hUb2tlblJldm9jYXRpb25gLCB3aGljaCBpc1xuICogZmlyZS1hbmQtZm9yZ2V0LiBUaGUgY2FsbGVyIG11c3QgYmUgYWJsZSB0byB0ZWxsIHRoZSBwZXJzb24gd2hvIGVuZGVkIHRoZVxuICogc2Vzc2lvbiB0aGF0IGl0IGRpZCBOT1QgZW5kIGV2ZXJ5d2hlcmUsIHJhdGhlciB0aGFuIHJlcG9ydGluZyBzdWNjZXNzIHdoaWxlXG4gKiB0aGUgdG9rZW4gc3RpbGwgd29ya3MgYWdhaW5zdCBvdGhlciBzZXJ2aWNlcy5cbiAqXG4gKiBUaGUgZW50cnkgZXhwaXJlcyB3aXRoIHRoZSBzZXNzaW9uOiBvbmNlIHRoZSB0b2tlbiBpdHNlbGYgY2FuIG5vIGxvbmdlciBiZVxuICogdXNlZCwgdGhlcmUgaXMgbm90aGluZyBsZWZ0IHRvIHJldm9rZSwgc28gdGhlIGtleSBjbGVhbnMgaXRzZWxmIHVwLlxuICpcbiAqIEBwYXJhbSB0dGxNcyAtIHRpbWUgcmVtYWluaW5nIG9uIHRoZSBzZXNzaW9uJ3MgdG9rZW5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHB1Ymxpc2hTZXNzaW9uUmV2b2NhdGlvbihcbiAgcmVkaXM6IFJlZGlzQ2FjaGVDbGllbnQsXG4gIGp0aTogc3RyaW5nLFxuICB0dGxNczogbnVtYmVyLFxuKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIHRyeSB7XG4gICAgYXdhaXQgcmVkaXMuc2V0KHNlc3Npb25SZXZvY2F0aW9uS2V5KGp0aSksICcxJywgJ1BYJywgTWF0aC5tYXgoMTAwMCwgTWF0aC5jZWlsKHR0bE1zKSkpO1xuICAgIHJldHVybiB0cnVlO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICBsb2dnZXIud2FybignU2Vzc2lvbi1yZXZvY2F0aW9uIHB1Ymxpc2ggZmFpbGVkIChvdGhlciBzZXJ2aWNlcyB3aWxsIGhvbm91ciB0aGUgdG9rZW4gdW50aWwgaXQgZXhwaXJlcyknLCB7XG4gICAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgIH0pO1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuIl19
@@ -0,0 +1,64 @@
1
+ import { type RouteTableEntry } from '../middleware/route-table.js';
2
+ /** A rule a route is allowed not to satisfy, with the reason it is exempt. */
3
+ export interface RouteCoverageException {
4
+ /** HTTP method, or '*' for any. */
5
+ method?: string;
6
+ /** Exact route path, or a pattern matched against `METHOD /path`. */
7
+ path: string | RegExp;
8
+ /** Which rule is waived: the permission gate, the audit declaration, or both. */
9
+ waive: 'permission' | 'audit' | 'all';
10
+ /** Why this route can't carry the gate/audit. Required — no silent allowlisting. */
11
+ reason: string;
12
+ /**
13
+ * Skip the staleness check for this entry. Only for the shared
14
+ * {@link INFRA_ROUTE_EXCEPTIONS}, whose routes depend on per-service
15
+ * `createApp` options (OpenAPI docs, log stream) — a service that doesn't
16
+ * enable them would otherwise fail on an "unused" shared exception.
17
+ */
18
+ optional?: boolean;
19
+ }
20
+ /**
21
+ * Exceptions every service inherits from `createApp`'s infrastructure routes:
22
+ * unauthenticated probes, the service-principal-gated warm-up, the metrics
23
+ * scrape endpoint, the OpenAPI docs, and the ticket-gated SSE log stream.
24
+ */
25
+ export declare const INFRA_ROUTE_EXCEPTIONS: readonly RouteCoverageException[];
26
+ /** The outcome of a coverage check: what fails, and which exceptions went unused. */
27
+ export interface RouteCoverageResult {
28
+ /** One human-readable line per uncovered route (empty ⇒ full coverage). */
29
+ violations: string[];
30
+ /** Exceptions that waived nothing — stale entries to delete. */
31
+ unusedExceptions: string[];
32
+ }
33
+ /** Check a service's route table against the coverage rules. */
34
+ export declare function findRouteCoverageViolations(table: readonly RouteTableEntry[], exceptions?: readonly RouteCoverageException[]): RouteCoverageResult;
35
+ /** One internal route a service declares, and the services allowed to call it. */
36
+ export interface InternalRouteDeclaration {
37
+ method: string;
38
+ path: string;
39
+ /** The `callers` passed to `requireInternalService` — also what the mesh policy names. */
40
+ callers: string[];
41
+ }
42
+ /**
43
+ * Check a service's INTERNAL routes (#14) against what it declares.
44
+ *
45
+ * The declaration is the single list a service maintains, and it is checked in
46
+ * BOTH directions, so neither side can drift:
47
+ *
48
+ * - every declared route must exist and be gated by `requireInternalService`
49
+ * with exactly the declared callers (and `requireAuth` before it);
50
+ * - every route the table says is internal must be declared — so adding one
51
+ * forces a visible change here, and the Istio `AuthorizationPolicy` that
52
+ * names the same callers (`deploy/*​/k8s/istio-internal-routes.yaml`) has
53
+ * one authoritative list to be reviewed against.
54
+ */
55
+ export declare function findInternalRouteViolations(table: readonly RouteTableEntry[], declared: readonly InternalRouteDeclaration[]): string[];
56
+ /** Every audit action declared anywhere in a route table. */
57
+ export declare function declaredAuditActions(table: readonly RouteTableEntry[]): string[];
58
+ /**
59
+ * Compare a service's route table to its checked-in copy under
60
+ * `frontend/src/generated/route-table/` — the file the frontend's `can(...)`
61
+ * tests read. Returns a diff message, or `null` when they match. Set
62
+ * `UPDATE_ROUTE_TABLES=1` to rewrite the file after an intended route change.
63
+ */
64
+ export declare function compareRouteTableSnapshot(table: readonly RouteTableEntry[], file: string): string | null;