@pipeline-builder/api-core 3.4.89 → 3.4.91
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.d.ts +1 -1
- package/lib/index.js +2 -2
- package/lib/middleware/auth.d.ts +30 -5
- package/lib/middleware/auth.js +70 -17
- package/lib/services/audit-spool.d.ts +62 -0
- package/lib/services/audit-spool.js +111 -0
- package/lib/services/compliance-client.js +4 -2
- package/lib/services/compliance-event-subscriber.js +17 -15
- package/lib/services/compliance-queue.js +10 -1
- package/lib/services/index.d.ts +1 -0
- package/lib/services/index.js +2 -1
- package/lib/services/remote-audit-client.d.ts +79 -6
- package/lib/services/remote-audit-client.js +238 -31
- package/lib/services/token-revocation.d.ts +15 -0
- package/lib/services/token-revocation.js +60 -1
- package/lib/types/common.d.ts +12 -3
- package/lib/types/common.js +1 -1
- package/lib/types/permissions.d.ts +6 -4
- package/lib/types/permissions.js +13 -10
- package/lib/types/quota-tiers.js +15 -16
- package/lib/utils/aws-scrub.d.ts +11 -0
- package/lib/utils/aws-scrub.js +57 -0
- package/lib/utils/index.d.ts +2 -0
- package/lib/utils/index.js +3 -1
- package/lib/utils/ssrf.d.ts +30 -0
- package/lib/utils/ssrf.js +89 -0
- package/lib/validation/message-schemas.d.ts +9 -0
- package/lib/validation/message-schemas.js +13 -4
- package/package.json +2 -1
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
// Copyright 2026 Pipeline Builder Contributors
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { randomUUID } from 'crypto';
|
|
4
|
+
import { createEnvRedisAuditSpool } from './audit-spool.js';
|
|
4
5
|
import { createSafeClient } from './http-client.js';
|
|
5
|
-
import { getServiceAuthHeader } from '../middleware/auth.js';
|
|
6
|
+
import { getServiceAuthHeader, setAuthzDenialAuditor } from '../middleware/auth.js';
|
|
6
7
|
import { createLogger } from '../utils/logger.js';
|
|
8
|
+
import { emitCounter } from '../utils/metric-emitter.js';
|
|
7
9
|
const logger = createLogger('remote-audit');
|
|
8
10
|
/**
|
|
9
11
|
* Audit ingest is best-effort and MUST NOT block the caller, but a transient
|
|
@@ -18,6 +20,99 @@ const AUDIT_REQUEST_OPTIONS = {
|
|
|
18
20
|
maxRateLimitRetries: 2,
|
|
19
21
|
maxRetries: 2,
|
|
20
22
|
};
|
|
23
|
+
/**
|
|
24
|
+
* The exact set of audit actions a NON-PLATFORM (remote) service is permitted to
|
|
25
|
+
* emit through `POST /audit/events`. This is the SINGLE SOURCE — `RemoteAuditAction`
|
|
26
|
+
* is derived from it, so the type and the runtime allow-list can never drift.
|
|
27
|
+
*
|
|
28
|
+
* SECURITY: platform's ingest validates `action` against this subset (via
|
|
29
|
+
* {@link isRemoteAuditAction}), NOT the full platform `AuditAction` union — a
|
|
30
|
+
* `service:*` token must not be able to forge platform-authority events
|
|
31
|
+
* (`admin.superadmin.grant`, `org.ownership.transfer`, `user.login`, …). Keep
|
|
32
|
+
* this list free of any platform-only action.
|
|
33
|
+
*/
|
|
34
|
+
export const REMOTE_AUDIT_ACTIONS = [
|
|
35
|
+
'plugin.build.completed',
|
|
36
|
+
'plugin.build.failed',
|
|
37
|
+
'plugin.build.timeout',
|
|
38
|
+
// Plugin lifecycle mutations (api/plugin route handlers) — the destructive /
|
|
39
|
+
// publishing surface that builds already audit's counterpart: registry delete,
|
|
40
|
+
// source upload, and deploy-to-cluster. `targetId` is the plugin id.
|
|
41
|
+
'plugin.delete',
|
|
42
|
+
'plugin.upload',
|
|
43
|
+
'plugin.deploy',
|
|
44
|
+
// Plugin bulk mutations (api/plugin bulk-plugin route) + DLQ purge (drops all
|
|
45
|
+
// dead-lettered build jobs, cross-org, sysadmin). `details` carries counts.
|
|
46
|
+
'plugin.bulk.update',
|
|
47
|
+
'plugin.bulk.delete',
|
|
48
|
+
'plugin.dlq.purge',
|
|
49
|
+
// Pipeline mutations — emitted by api/pipeline's route handlers
|
|
50
|
+
// (create/update/delete + CodePipeline execution trigger/cancel) and
|
|
51
|
+
// posted to platform's `POST /audit/events` ingest.
|
|
52
|
+
'pipeline.create',
|
|
53
|
+
'pipeline.update',
|
|
54
|
+
'pipeline.delete',
|
|
55
|
+
'pipeline.execution.start',
|
|
56
|
+
'pipeline.execution.cancel',
|
|
57
|
+
// CodePipeline ARN-registry config (api/pipeline registry route) — registering /
|
|
58
|
+
// deregistering the external CodePipeline that backs a pipeline (deploy-affecting).
|
|
59
|
+
'pipeline.registry.register',
|
|
60
|
+
'pipeline.registry.deregister',
|
|
61
|
+
// Quota administration (api/quota) — a superadmin resetting an org's usage
|
|
62
|
+
// counter or editing its tier limits. `affectedOrgId` is the org changed;
|
|
63
|
+
// `details` carries the quotaType + old/new value.
|
|
64
|
+
'quota.reset',
|
|
65
|
+
'quota.limit.update',
|
|
66
|
+
// A superadmin deleting an org's entire quota document.
|
|
67
|
+
'quota.delete',
|
|
68
|
+
// Compliance administration (api/compliance) — the enforcement-posture surface.
|
|
69
|
+
// Approving/revoking an exemption, toggling/authoring/deleting a rule,
|
|
70
|
+
// authoring/deleting a policy, managing scan schedules, applying a template,
|
|
71
|
+
// or cancelling a running scan. `targetId` is the rule/policy/exemption/scan id.
|
|
72
|
+
'compliance.exemption.approve',
|
|
73
|
+
'compliance.exemption.revoke',
|
|
74
|
+
'compliance.rule.toggle',
|
|
75
|
+
'compliance.rule.create',
|
|
76
|
+
'compliance.rule.update',
|
|
77
|
+
'compliance.rule.delete',
|
|
78
|
+
'compliance.policy.create',
|
|
79
|
+
'compliance.policy.update',
|
|
80
|
+
'compliance.policy.delete',
|
|
81
|
+
'compliance.scan-schedule.create',
|
|
82
|
+
'compliance.scan-schedule.update',
|
|
83
|
+
'compliance.scan-schedule.delete',
|
|
84
|
+
'compliance.template.apply',
|
|
85
|
+
'compliance.scan.cancel',
|
|
86
|
+
// Image-registry destructive ops (api/image-registry) — garbage-collection
|
|
87
|
+
// sweeps and explicit image/tag deletes (previously only a log line).
|
|
88
|
+
'registry.gc',
|
|
89
|
+
'registry.image.delete',
|
|
90
|
+
// Messaging (api/message) — admin BROADCAST announcements + destructive
|
|
91
|
+
// deletes. 1:1 user messages are intentionally NOT audited (noise + they would
|
|
92
|
+
// pull private content into the trail). `details` carry metadata only
|
|
93
|
+
// (subject/type/scope), NEVER message body content.
|
|
94
|
+
'message.announcement.create',
|
|
95
|
+
'message.delete',
|
|
96
|
+
// Billing (api/billing) — subscription + entitlement mutations, mirrored to the
|
|
97
|
+
// central audit trail (these also write to the service-local billing_events
|
|
98
|
+
// collection). `details` carry plan/tier/addon ids only — never card/payment
|
|
99
|
+
// secrets or an AWS account id.
|
|
100
|
+
'billing.subscription.cancel',
|
|
101
|
+
'billing.subscription.delete',
|
|
102
|
+
'billing.tier.override',
|
|
103
|
+
'billing.addon.add',
|
|
104
|
+
'billing.addon.remove',
|
|
105
|
+
// Denied authorization attempt — emitted best-effort by the shared
|
|
106
|
+
// `requirePermission` / `requireSystemAdmin` gate when a state-changing
|
|
107
|
+
// (non-GET) request is rejected, so probing/escalation attempts are visible
|
|
108
|
+
// rather than invisible. `details` carries the required permission + path;
|
|
109
|
+
// `outcome` is 'failure'.
|
|
110
|
+
'authz.denied',
|
|
111
|
+
];
|
|
112
|
+
/** Whether `value` is an action a remote service may emit (the ingest allow-list). */
|
|
113
|
+
export function isRemoteAuditAction(value) {
|
|
114
|
+
return REMOTE_AUDIT_ACTIONS.includes(value);
|
|
115
|
+
}
|
|
21
116
|
/**
|
|
22
117
|
* Construct a remote-audit client targeted at the platform service.
|
|
23
118
|
*
|
|
@@ -45,41 +140,153 @@ export function createRemoteAuditClient(config = {}) {
|
|
|
45
140
|
timeout: config.timeout ?? 3000,
|
|
46
141
|
};
|
|
47
142
|
const client = createSafeClient(serviceConfig);
|
|
143
|
+
const spool = config.spool;
|
|
144
|
+
const drainBatchSize = config.drainBatchSize ?? 100;
|
|
145
|
+
/**
|
|
146
|
+
* Attempt ONE live delivery. Resolves `true` on a 2xx accept, `false` on any
|
|
147
|
+
* non-2xx / thrown error (the http-client has already applied the retry
|
|
148
|
+
* budget). A stable per-emission `Idempotency-Key` makes this non-idempotent
|
|
149
|
+
* POST retry-safe and lets the platform ingest dedup a re-delivered event
|
|
150
|
+
* instead of writing a duplicate audit row (and duplicate chain link).
|
|
151
|
+
* `Idempotency-Key` is derived from the event so a SPOOLED re-delivery reuses
|
|
152
|
+
* the same key as its original live attempt — the two collapse to one row.
|
|
153
|
+
*/
|
|
154
|
+
async function deliver(event, serviceName) {
|
|
155
|
+
const authHeader = getServiceAuthHeader({ serviceName, orgId: event.orgId, role: 'member' });
|
|
156
|
+
const headers = {
|
|
157
|
+
'Authorization': authHeader,
|
|
158
|
+
'Idempotency-Key': event.idempotencyKey ?? randomUUID(),
|
|
159
|
+
};
|
|
160
|
+
try {
|
|
161
|
+
const response = await client.post('/audit/events', event, { headers, ...AUDIT_REQUEST_OPTIONS });
|
|
162
|
+
const ok = !!response && response.statusCode >= 200 && response.statusCode < 300;
|
|
163
|
+
if (!ok) {
|
|
164
|
+
logger.warn('Remote audit ingest non-ok', { action: event.action, statusCode: response?.statusCode });
|
|
165
|
+
}
|
|
166
|
+
return ok;
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
logger.warn('Remote audit ingest threw', { action: event.action, error: err instanceof Error ? err.message : String(err) });
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Serialize spool drains so a periodic tick and an on-success drain can't both
|
|
174
|
+
// pull the same batch. Stops early the moment a re-delivery fails (platform
|
|
175
|
+
// still down) so we don't hammer it or churn the buffer.
|
|
176
|
+
let draining = false;
|
|
177
|
+
async function drain() {
|
|
178
|
+
if (!spool || draining)
|
|
179
|
+
return;
|
|
180
|
+
draining = true;
|
|
181
|
+
try {
|
|
182
|
+
for (;;) {
|
|
183
|
+
const batch = await spool.take(drainBatchSize);
|
|
184
|
+
if (batch.length === 0)
|
|
185
|
+
return;
|
|
186
|
+
const failed = [];
|
|
187
|
+
let platformDown = false;
|
|
188
|
+
for (const entry of batch) {
|
|
189
|
+
if (platformDown) {
|
|
190
|
+
failed.push(entry);
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
const ok = await deliver(entry.event, entry.serviceName);
|
|
194
|
+
if (ok) {
|
|
195
|
+
emitCounter('audit_spool_redelivered_total', { service: entry.serviceName });
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
platformDown = true;
|
|
199
|
+
failed.push(entry);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (failed.length > 0) {
|
|
203
|
+
await spool.requeue(failed);
|
|
204
|
+
return; // still down — try again on the next tick
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
logger.warn('Audit spool drain failed', { error: err instanceof Error ? err.message : String(err) });
|
|
210
|
+
}
|
|
211
|
+
finally {
|
|
212
|
+
draining = false;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
let drainTimer;
|
|
216
|
+
if (spool) {
|
|
217
|
+
drainTimer = setInterval(() => { void drain(); }, config.drainIntervalMs ?? 30_000);
|
|
218
|
+
// Don't let the drain timer keep the process alive on shutdown.
|
|
219
|
+
drainTimer.unref?.();
|
|
220
|
+
}
|
|
48
221
|
return {
|
|
49
222
|
record(event, serviceName) {
|
|
50
|
-
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
// rather than dropped) and lets the platform ingest dedup a re-delivered
|
|
57
|
-
// event instead of writing a duplicate audit row. Generated once here so
|
|
58
|
-
// every retry of THIS emission reuses the same key.
|
|
59
|
-
const headers = {
|
|
60
|
-
'Authorization': authHeader,
|
|
61
|
-
'Idempotency-Key': randomUUID(),
|
|
223
|
+
// Stamp when the action actually occurred (survives spool delay) and pin a
|
|
224
|
+
// stable idempotency key so a live attempt and its spooled retry dedup.
|
|
225
|
+
const stamped = {
|
|
226
|
+
...event,
|
|
227
|
+
occurredAt: event.occurredAt ?? new Date().toISOString(),
|
|
228
|
+
idempotencyKey: event.idempotencyKey ?? randomUUID(),
|
|
62
229
|
};
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
});
|
|
230
|
+
void deliver(stamped, serviceName).then((ok) => {
|
|
231
|
+
if (ok) {
|
|
232
|
+
emitCounter('audit_emitted_total', { service: serviceName, outcome: stamped.outcome ?? 'success' });
|
|
233
|
+
if (spool)
|
|
234
|
+
void drain(); // platform is reachable — flush any backlog
|
|
235
|
+
}
|
|
236
|
+
else if (spool) {
|
|
237
|
+
void spool.enqueue({ event: stamped, serviceName });
|
|
238
|
+
}
|
|
239
|
+
else {
|
|
240
|
+
emitCounter('audit_dropped_total', { service: serviceName });
|
|
74
241
|
}
|
|
75
|
-
})
|
|
76
|
-
.catch((err) => {
|
|
77
|
-
logger.warn('Remote audit ingest threw', {
|
|
78
|
-
action: event.action,
|
|
79
|
-
error: err instanceof Error ? err.message : String(err),
|
|
80
|
-
});
|
|
81
242
|
});
|
|
82
243
|
},
|
|
244
|
+
close() {
|
|
245
|
+
if (drainTimer) {
|
|
246
|
+
clearInterval(drainTimer);
|
|
247
|
+
drainTimer = undefined;
|
|
248
|
+
}
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Register the standard `authz.denied` sink used by every remote-audit service
|
|
254
|
+
* (pipeline, plugin, compliance, quota, message, billing, reporting, …).
|
|
255
|
+
*
|
|
256
|
+
* The shared `requireAuth` gate forwards each DENIED state-changing request to
|
|
257
|
+
* the auditor set via {@link setAuthzDenialAuditor}; this wires that hook to the
|
|
258
|
+
* service's {@link RemoteAuditClient}, forwarding a `failure`-outcome
|
|
259
|
+
* `authz.denied` event so probing / privilege-escalation attempts leave a trail.
|
|
260
|
+
* Emission is fire-and-forget (the client never throws). `getClient` is a getter
|
|
261
|
+
* so the client stays lazily constructed (services memoize it on first use).
|
|
262
|
+
*
|
|
263
|
+
* Platform is intentionally NOT a caller — it is the audit authority and writes
|
|
264
|
+
* `authz.denied` straight to its local store (with `affectedOrgId`), not through
|
|
265
|
+
* a RemoteAuditClient.
|
|
266
|
+
*/
|
|
267
|
+
export function wireAuthzDenialAuditor(serviceName, getClient) {
|
|
268
|
+
setAuthzDenialAuditor((info) => getClient().record({
|
|
269
|
+
action: 'authz.denied',
|
|
270
|
+
actorId: info.actorId ?? 'anonymous',
|
|
271
|
+
actorEmail: info.actorEmail,
|
|
272
|
+
orgId: info.orgId,
|
|
273
|
+
outcome: 'failure',
|
|
274
|
+
details: { method: info.method, path: info.path, required: info.required },
|
|
275
|
+
}, serviceName));
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Build a service's audit client: a RemoteAuditClient wired to the durable Redis
|
|
279
|
+
* spool (from ambient env; null → no spool) with `serviceName` bound. Construct
|
|
280
|
+
* ONCE per process — memoize behind a lazy `getAuditClient()` in the service's
|
|
281
|
+
* `services/audit.ts`. Pass `config.spool` to override the env-derived spool
|
|
282
|
+
* (e.g. reuse a service's existing ioredis connection).
|
|
283
|
+
*/
|
|
284
|
+
export function createServiceAuditClient(serviceName, config = {}) {
|
|
285
|
+
const spool = config.spool ?? createEnvRedisAuditSpool() ?? undefined;
|
|
286
|
+
const client = createRemoteAuditClient({ ...config, spool });
|
|
287
|
+
return {
|
|
288
|
+
emit: (event) => client.record(event, serviceName),
|
|
289
|
+
client,
|
|
83
290
|
};
|
|
84
291
|
}
|
|
85
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVtb3RlLWF1ZGl0LWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy9yZW1vdGUtYXVkaXQtY2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUNwQyxPQUFPLEVBQUUsZ0JBQWdCLEVBQXVCLE1BQU0sa0JBQWtCLENBQUM7QUFDekUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFN0QsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRWxELE1BQU0sTUFBTSxHQUFHLFlBQVksQ0FBQyxjQUFjLENBQUMsQ0FBQztBQUU1Qzs7Ozs7Ozs7R0FRRztBQUNILE1BQU0scUJBQXFCLEdBQStEO0lBQ3hGLG1CQUFtQixFQUFFLENBQUM7SUFDdEIsVUFBVSxFQUFFLENBQUM7Q0FDZCxDQUFDO0FBNEZGOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBQ0gsTUFBTSxVQUFVLHVCQUF1QixDQUFDLFNBQWtDLEVBQUU7SUFDMUUsTUFBTSxhQUFhLEdBQWtCO1FBQ25DLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMscUJBQXFCLElBQUksVUFBVTtRQUNwRSxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUksSUFBSSxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxxQkFBcUIsSUFBSSxNQUFNLEVBQUUsRUFBRSxDQUFDO1FBQzlFLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTyxJQUFJLElBQUk7S0FDaEMsQ0FBQztJQUNGLE1BQU0sTUFBTSxHQUFHLGdCQUFnQixDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBRS9DLE9BQU87UUFDTCxNQUFNLENBQUMsS0FBSyxFQUFFLFdBQVc7WUFDdkIsTUFBTSxVQUFVLEdBQUcsb0JBQW9CLENBQUMsRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7WUFDN0Ysa0VBQWtFO1lBQ2xFLHlFQUF5RTtZQUN6RSwyRUFBMkU7WUFDM0UsdUVBQXVFO1lBQ3ZFLDBFQUEwRTtZQUMxRSx5RUFBeUU7WUFDekUseUVBQXlFO1lBQ3pFLG9EQUFvRDtZQUNwRCxNQUFNLE9BQU8sR0FBMkI7Z0JBQ3RDLGVBQWUsRUFBRSxVQUFVO2dCQUMzQixpQkFBaUIsRUFBRSxVQUFVLEVBQUU7YUFDaEMsQ0FBQztZQUNGLG9FQUFvRTtZQUNwRSx3RUFBd0U7WUFDeEUsTUFBTSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsS0FBSyxFQUFFLEVBQUUsT0FBTyxFQUFFLEdBQUcscUJBQXFCLEVBQUUsQ0FBQztpQkFDdkUsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUU7Z0JBQ2pCLHNFQUFzRTtnQkFDdEUsa0VBQWtFO2dCQUNsRSxNQUFNLEVBQUUsR0FBRyxRQUFRLElBQUksUUFBUSxDQUFDLFVBQVUsSUFBSSxHQUFHLElBQUksUUFBUSxDQUFDLFVBQVUsR0FBRyxHQUFHLENBQUM7Z0JBQy9FLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQztvQkFDUixNQUFNLENBQUMsSUFBSSxDQUFDLDRCQUE0QixFQUFFO3dCQUN4QyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUUsUUFBUSxFQUFFLFVBQVU7cUJBQ3ZELENBQUMsQ0FBQztnQkFDTCxDQUFDO1lBQ0gsQ0FBQyxDQUFDO2lCQUNELEtBQUssQ0FBQyxDQUFDLEdBQVksRUFBRSxFQUFFO2dCQUN0QixNQUFNLENBQUMsSUFBSSxDQUFDLDJCQUEyQixFQUFFO29CQUN2QyxNQUFNLEVBQUUsS0FBSyxDQUFDLE1BQU07b0JBQ3BCLEtBQUssRUFBRSxHQUFHLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFBLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDO2lCQUN2RCxDQUFDLENBQUM7WUFDTCxDQUFDLENBQUMsQ0FBQztRQUNQLENBQUM7S0FDRixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyByYW5kb21VVUlEIH0gZnJvbSAnY3J5cHRvJztcbmltcG9ydCB7IGNyZWF0ZVNhZmVDbGllbnQsIHR5cGUgUmVxdWVzdE9wdGlvbnMgfSBmcm9tICcuL2h0dHAtY2xpZW50LmpzJztcbmltcG9ydCB7IGdldFNlcnZpY2VBdXRoSGVhZGVyIH0gZnJvbSAnLi4vbWlkZGxld2FyZS9hdXRoLmpzJztcbmltcG9ydCB0eXBlIHsgU2VydmljZUNvbmZpZyB9IGZyb20gJy4uL3R5cGVzL2NvbW1vbi5qcyc7XG5pbXBvcnQgeyBjcmVhdGVMb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ3JlbW90ZS1hdWRpdCcpO1xuXG4vKipcbiAqIEF1ZGl0IGluZ2VzdCBpcyBiZXN0LWVmZm9ydCBhbmQgTVVTVCBOT1QgYmxvY2sgdGhlIGNhbGxlciwgYnV0IGEgdHJhbnNpZW50XG4gKiBmYWlsdXJlICg0MjkgLyA1eHggLyBjb25uZWN0aW9uIHJlc2V0IC8gdGltZW91dCkgc2hvdWxkIG5vdCBzaWxlbnRseSBkcm9wIHRoZVxuICogcm93IG9uIHRoZSBmaXJzdCBhdHRlbXB0LiBFYWNoIGVtaXNzaW9uIGNhcnJpZXMgYSBzdGFibGUgcGVyLWV2ZW50XG4gKiBgSWRlbXBvdGVuY3ktS2V5YCAoc2VlIGByZWNvcmRgKSwgc28gdGhlIGh0dHAtY2xpZW50IHRyZWF0cyB0aGUgUE9TVCBhc1xuICogcmV0cnktc2FmZSBhbmQgdGhlIHBsYXRmb3JtIGNhbiBkZWR1cCBhIHJldHJpZWQgZGVsaXZlcnkgaW5zdGVhZCBvZiB3cml0aW5nIGFcbiAqIGR1cGxpY2F0ZSByb3cuIEJ1ZGdldCBpcyBrZXB0IHNtYWxsIHNvIGEgaGFyZC1kb3duIHBsYXRmb3JtIGNhbid0IGJhY2sgdGhlXG4gKiB3b3JrZXIgdXAgZm9yIGxvbmc6IGJhc2UgZGVsYXkgw5coMiByZXRyaWVzKSArIGEgY291cGxlIG9mIDQyOSBiYWNrb2Zmcy5cbiAqL1xuY29uc3QgQVVESVRfUkVRVUVTVF9PUFRJT05TOiBQaWNrPFJlcXVlc3RPcHRpb25zLCAnbWF4UmF0ZUxpbWl0UmV0cmllcycgfCAnbWF4UmV0cmllcyc+ID0ge1xuICBtYXhSYXRlTGltaXRSZXRyaWVzOiAyLFxuICBtYXhSZXRyaWVzOiAyLFxufTtcblxuLyoqXG4gKiBTdWJzZXQgb2YgcGxhdGZvcm0ncyBBdWRpdEFjdGlvbiBlbnVtIHRoYXQgbm9uLXBsYXRmb3JtIHNlcnZpY2VzIGVtaXQuXG4gKiBLZXB0IGluIHN5bmMgbWFudWFsbHkgd2l0aCBwbGF0Zm9ybS9zcmMvbW9kZWxzL2F1ZGl0LWV2ZW50LnRzOyBtaXNtYXRjaGVkXG4gKiBhY3Rpb25zIGFyZSByZWplY3RlZCBieSB0aGUgcGxhdGZvcm0gaW5nZXN0IGVuZHBvaW50ICg0MDApIHNvIGEgZHJpZnQgaXNcbiAqIHZpc2libGUgaW4gbG9ncyByYXRoZXIgdGhhbiBzaWxlbnRseSBkcm9wcGVkLlxuICovXG5leHBvcnQgdHlwZSBSZW1vdGVBdWRpdEFjdGlvbiA9XG4gIHwgJ3BsdWdpbi5idWlsZC5jb21wbGV0ZWQnXG4gIHwgJ3BsdWdpbi5idWlsZC5mYWlsZWQnXG4gIHwgJ3BsdWdpbi5idWlsZC50aW1lb3V0J1xuICAvLyBQbHVnaW4gbGlmZWN5Y2xlIG11dGF0aW9ucyAoYXBpL3BsdWdpbiByb3V0ZSBoYW5kbGVycykg4oCUIHRoZSBkZXN0cnVjdGl2ZSAvXG4gIC8vIHB1Ymxpc2hpbmcgc3VyZmFjZSB0aGF0IGJ1aWxkcyBhbHJlYWR5IGF1ZGl0J3MgY291bnRlcnBhcnQ6IHJlZ2lzdHJ5IGRlbGV0ZSxcbiAgLy8gc291cmNlIHVwbG9hZCwgYW5kIGRlcGxveS10by1jbHVzdGVyLiBgdGFyZ2V0SWRgIGlzIHRoZSBwbHVnaW4gaWQuXG4gIHwgJ3BsdWdpbi5kZWxldGUnXG4gIHwgJ3BsdWdpbi51cGxvYWQnXG4gIHwgJ3BsdWdpbi5kZXBsb3knXG4gIC8vIFBpcGVsaW5lIG11dGF0aW9ucyDigJQgZW1pdHRlZCBieSBhcGkvcGlwZWxpbmUncyByb3V0ZSBoYW5kbGVyc1xuICAvLyAoY3JlYXRlL3VwZGF0ZS9kZWxldGUgKyBDb2RlUGlwZWxpbmUgZXhlY3V0aW9uIHRyaWdnZXIvY2FuY2VsKSBhbmRcbiAgLy8gcG9zdGVkIHRvIHBsYXRmb3JtJ3MgYFBPU1QgL2F1ZGl0L2V2ZW50c2AgaW5nZXN0LlxuICB8ICdwaXBlbGluZS5jcmVhdGUnXG4gIHwgJ3BpcGVsaW5lLnVwZGF0ZSdcbiAgfCAncGlwZWxpbmUuZGVsZXRlJ1xuICB8ICdwaXBlbGluZS5leGVjdXRpb24uc3RhcnQnXG4gIHwgJ3BpcGVsaW5lLmV4ZWN1dGlvbi5jYW5jZWwnXG4gIC8vIFF1b3RhIGFkbWluaXN0cmF0aW9uIChhcGkvcXVvdGEpIOKAlCBhIHN1cGVyYWRtaW4gcmVzZXR0aW5nIGFuIG9yZydzIHVzYWdlXG4gIC8vIGNvdW50ZXIgb3IgZWRpdGluZyBpdHMgdGllciBsaW1pdHMuIGBhZmZlY3RlZE9yZ0lkYCBpcyB0aGUgb3JnIGNoYW5nZWQ7XG4gIC8vIGBkZXRhaWxzYCBjYXJyaWVzIHRoZSBxdW90YVR5cGUgKyBvbGQvbmV3IHZhbHVlLlxuICB8ICdxdW90YS5yZXNldCdcbiAgfCAncXVvdGEubGltaXQudXBkYXRlJ1xuICAvLyBDb21wbGlhbmNlIHJ1bGUgYWRtaW5pc3RyYXRpb24gKGFwaS9jb21wbGlhbmNlKSDigJQgYXBwcm92aW5nIGFuIGV4ZW1wdGlvblxuICAvLyByZXF1ZXN0LCB0b2dnbGluZyBhIHJ1bGUgYWN0aXZlL2luYWN0aXZlLCBvciBjYW5jZWxsaW5nIGEgcnVubmluZyBzY2FuLlxuICAvLyBgdGFyZ2V0SWRgIGlzIHRoZSBydWxlL2V4ZW1wdGlvbi9zY2FuIGlkLlxuICB8ICdjb21wbGlhbmNlLmV4ZW1wdGlvbi5hcHByb3ZlJ1xuICB8ICdjb21wbGlhbmNlLnJ1bGUudG9nZ2xlJ1xuICB8ICdjb21wbGlhbmNlLnNjYW4uY2FuY2VsJ1xuICAvLyBJbWFnZS1yZWdpc3RyeSBkZXN0cnVjdGl2ZSBvcHMgKGFwaS9pbWFnZS1yZWdpc3RyeSkg4oCUIGdhcmJhZ2UtY29sbGVjdGlvblxuICAvLyBzd2VlcHMgYW5kIGV4cGxpY2l0IGltYWdlL3RhZyBkZWxldGVzIChwcmV2aW91c2x5IG9ubHkgYSBsb2cgbGluZSkuXG4gIHwgJ3JlZ2lzdHJ5LmdjJ1xuICB8ICdyZWdpc3RyeS5pbWFnZS5kZWxldGUnXG4gIC8vIERlbmllZCBhdXRob3JpemF0aW9uIGF0dGVtcHQg4oCUIGVtaXR0ZWQgYmVzdC1lZmZvcnQgYnkgdGhlIHNoYXJlZFxuICAvLyBgcmVxdWlyZVBlcm1pc3Npb25gIC8gYHJlcXVpcmVTeXN0ZW1BZG1pbmAgZ2F0ZSB3aGVuIGEgc3RhdGUtY2hhbmdpbmdcbiAgLy8gKG5vbi1HRVQpIHJlcXVlc3QgaXMgcmVqZWN0ZWQsIHNvIHByb2JpbmcvZXNjYWxhdGlvbiBhdHRlbXB0cyBhcmUgdmlzaWJsZVxuICAvLyByYXRoZXIgdGhhbiBpbnZpc2libGUuIGBkZXRhaWxzYCBjYXJyaWVzIHRoZSByZXF1aXJlZCBwZXJtaXNzaW9uICsgcGF0aDtcbiAgLy8gYG91dGNvbWVgIGlzICdmYWlsdXJlJy5cbiAgfCAnYXV0aHouZGVuaWVkJztcblxuZXhwb3J0IGludGVyZmFjZSBSZW1vdGVBdWRpdEV2ZW50IHtcbiAgYWN0aW9uOiBSZW1vdGVBdWRpdEFjdGlvbjtcbiAgYWN0b3JJZDogc3RyaW5nO1xuICBhY3RvckVtYWlsPzogc3RyaW5nO1xuICBvcmdJZD86IHN0cmluZztcbiAgYWZmZWN0ZWRPcmdJZD86IHN0cmluZztcbiAgdGFyZ2V0VHlwZT86IHN0cmluZztcbiAgdGFyZ2V0SWQ/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBEaWQgdGhlIGF1ZGl0ZWQgYWN0aW9uIHN1Y2NlZWQgb3IgZmFpbD8gRGVmYXVsdHMgdG8gJ3N1Y2Nlc3MnIHdoZW4gb21pdHRlZFxuICAgKiAodGhlIHBsYXRmb3JtIGluZ2VzdCBhcHBsaWVzIHRoZSBzYW1lIGRlZmF1bHQpLiBEZW5pZWQtYXV0aHogZXZlbnRzIHNldFxuICAgKiAnZmFpbHVyZScgc28gYSByZXZpZXdlciBjYW4gZmlsdGVyIGF0dGVtcHRzIGZyb20gY29tcGxldGVkIGFjdGlvbnMuXG4gICAqL1xuICBvdXRjb21lPzogJ3N1Y2Nlc3MnIHwgJ2ZhaWx1cmUnO1xuICBkZXRhaWxzPzogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59XG5cbi8qKlxuICogQ2xpZW50IGZvciBQT1NUaW5nIGF1ZGl0IGV2ZW50cyB0byB0aGUgcGxhdGZvcm0ncyBgL2F1ZGl0LWV2ZW50c2AgaW5nZXN0XG4gKiBlbmRwb2ludC4gTWludHMgYSBmcmVzaCBzZXJ2aWNlIHRva2VuIHBlciBjYWxsICg1IG1pbiBUVEwpICB0aGVyZSdzIG5vXG4gKiBtZWFuaW5nZnVsIGNhY2hpbmcgYmVuZWZpdCB3aGVuIGVtaXNzaW9ucyBhcmUgc3BhcnNlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlbW90ZUF1ZGl0Q2xpZW50IHtcbiAgLyoqXG4gICAqIEZpcmUtYW5kLWZvcmdldCBhdWRpdCBlbWlzc2lvbi4gRmFpbHVyZXMgYXJlIGxvZ2dlZCBhdCB3YXJuIGxldmVsIGJ1dFxuICAgKiBuZXZlciB0aHJvd24gIHRoZSBvcmlnaW5hdGluZyBhY3Rpb24gKGUuZy4gYSBwbHVnaW4gYnVpbGQpIGhhcyBpdHNcbiAgICogb3duIHN1Y2Nlc3MvZmFpbHVyZSBwYXRoIHRoYXQgc2hvdWxkbid0IGdldCBwb2xsdXRlZCBieSBhIGZsYWt5IGF1ZGl0XG4gICAqIGRvd25zdHJlYW0uXG4gICAqL1xuICByZWNvcmQoZXZlbnQ6IFJlbW90ZUF1ZGl0RXZlbnQsIHNlcnZpY2VOYW1lOiBzdHJpbmcpOiB2b2lkO1xufVxuXG4vKipcbiAqIENvbmZpZ3VyYXRpb24gZm9yIHRoZSByZW1vdGUgYXVkaXQgY2xpZW50LlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlbW90ZUF1ZGl0Q2xpZW50Q29uZmlnIHtcbiAgLyoqIFBsYXRmb3JtIHNlcnZpY2UgaG9zdCAoZGVmYXVsdDogZW52IFBMQVRGT1JNX1NFUlZJQ0VfSE9TVCBvciAncGxhdGZvcm0nKSAqL1xuICBob3N0Pzogc3RyaW5nO1xuICAvKiogUGxhdGZvcm0gc2VydmljZSBwb3J0IChkZWZhdWx0OiBlbnYgUExBVEZPUk1fU0VSVklDRV9QT1JUIG9yIDMwMDApICovXG4gIHBvcnQ/OiBudW1iZXI7XG4gIC8qKiBSZXF1ZXN0IHRpbWVvdXQgbXMgKGRlZmF1bHQgMzAwMCAgYXVkaXQgc2hvdWxkbid0IGJsb2NrIHRoZSB3b3JrZXIpLiAqL1xuICB0aW1lb3V0PzogbnVtYmVyO1xufVxuXG4vKipcbiAqIENvbnN0cnVjdCBhIHJlbW90ZS1hdWRpdCBjbGllbnQgdGFyZ2V0ZWQgYXQgdGhlIHBsYXRmb3JtIHNlcnZpY2UuXG4gKlxuICogVXNlZCBieSBhcGkvcGx1Z2luJ3MgYnVpbGQgd29ya2VyIHRvIHB1c2ggYHBsdWdpbi5idWlsZC4qYCBldmVudHMgaW50b1xuICogdGhlIHBsYXRmb3JtJ3MgTW9uZ29EQiBgYXVkaXRfZXZlbnRzYCBjb2xsZWN0aW9uLiBPdGhlciBzZXJ2aWNlc1xuICogd2l0aCB3b3JrZXItc3R5bGUgZW1pdHRlcnMgY2FuIHVzZSB0aGUgc2FtZSBjbGllbnQuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGF1ZGl0Q2xpZW50ID0gY3JlYXRlUmVtb3RlQXVkaXRDbGllbnQoKTtcbiAqIGF1ZGl0Q2xpZW50LnJlY29yZCh7XG4gKiBhY3Rpb246ICdwbHVnaW4uYnVpbGQuY29tcGxldGVkJyxcbiAqIGFjdG9ySWQ6ICd1c2VyLTEyMycsXG4gKiBvcmdJZDogJ29yZy1hY21lJyxcbiAqIHRhcmdldFR5cGU6ICdwbHVnaW4nLFxuICogdGFyZ2V0SWQ6ICdwbHVnaW4tYWJjJyxcbiAqIGRldGFpbHM6IHsgbmFtZTogJ215LXBsdWdpbicsIHZlcnNpb246ICcxLjAuMCcgfSxcbiAqIH0sICdwbHVnaW4nKTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlUmVtb3RlQXVkaXRDbGllbnQoY29uZmlnOiBSZW1vdGVBdWRpdENsaWVudENvbmZpZyA9IHt9KTogUmVtb3RlQXVkaXRDbGllbnQge1xuICBjb25zdCBzZXJ2aWNlQ29uZmlnOiBTZXJ2aWNlQ29uZmlnID0ge1xuICAgIGhvc3Q6IGNvbmZpZy5ob3N0ID8/IHByb2Nlc3MuZW52LlBMQVRGT1JNX1NFUlZJQ0VfSE9TVCA/PyAncGxhdGZvcm0nLFxuICAgIHBvcnQ6IGNvbmZpZy5wb3J0ID8/IHBhcnNlSW50KHByb2Nlc3MuZW52LlBMQVRGT1JNX1NFUlZJQ0VfUE9SVCA/PyAnMzAwMCcsIDEwKSxcbiAgICB0aW1lb3V0OiBjb25maWcudGltZW91dCA/PyAzMDAwLFxuICB9O1xuICBjb25zdCBjbGllbnQgPSBjcmVhdGVTYWZlQ2xpZW50KHNlcnZpY2VDb25maWcpO1xuXG4gIHJldHVybiB7XG4gICAgcmVjb3JkKGV2ZW50LCBzZXJ2aWNlTmFtZSkge1xuICAgICAgY29uc3QgYXV0aEhlYWRlciA9IGdldFNlcnZpY2VBdXRoSGVhZGVyKHsgc2VydmljZU5hbWUsIG9yZ0lkOiBldmVudC5vcmdJZCwgcm9sZTogJ21lbWJlcicgfSk7XG4gICAgICAvLyBnZXRTZXJ2aWNlQXV0aEhlYWRlciByZXR1cm5zIGEgZnVsbCBgQmVhcmVyIDx0b2tlbj5gIHZhbHVlOyB0aGVcbiAgICAgIC8vIGh0dHAtY2xpZW50IGZvcndhcmRzIHJlcXVlc3QgaGVhZGVycyBhcy1pcyAoaXQgZG9lcyBOT1QgaW5qZWN0IGl0cyBvd25cbiAgICAgIC8vIEF1dGhvcml6YXRpb24pLCBzbyBwYXNzIGl0IHN0cmFpZ2h0IHRocm91Z2ggYXMgdGhlIEF1dGhvcml6YXRpb24gaGVhZGVyLlxuICAgICAgLy8gQSBzdGFibGUgcGVyLWVtaXNzaW9uIElkZW1wb3RlbmN5LUtleSBtYWtlcyB0aGlzIG5vbi1pZGVtcG90ZW50IFBPU1RcbiAgICAgIC8vIHJldHJ5LXNhZmUgaW4gdGhlIGh0dHAtY2xpZW50IChzbyB0cmFuc2llbnQgNXh4L3RpbWVvdXQvNDI5IGFyZSByZXRyaWVkXG4gICAgICAvLyByYXRoZXIgdGhhbiBkcm9wcGVkKSBhbmQgbGV0cyB0aGUgcGxhdGZvcm0gaW5nZXN0IGRlZHVwIGEgcmUtZGVsaXZlcmVkXG4gICAgICAvLyBldmVudCBpbnN0ZWFkIG9mIHdyaXRpbmcgYSBkdXBsaWNhdGUgYXVkaXQgcm93LiBHZW5lcmF0ZWQgb25jZSBoZXJlIHNvXG4gICAgICAvLyBldmVyeSByZXRyeSBvZiBUSElTIGVtaXNzaW9uIHJldXNlcyB0aGUgc2FtZSBrZXkuXG4gICAgICBjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgICAgICAnQXV0aG9yaXphdGlvbic6IGF1dGhIZWFkZXIsXG4gICAgICAgICdJZGVtcG90ZW5jeS1LZXknOiByYW5kb21VVUlEKCksXG4gICAgICB9O1xuICAgICAgLy8gUGF0aCBpcyAvYXVkaXQvZXZlbnRzICB0aGUgcGxhdGZvcm0gbW91bnRzIHRoZSBhdWRpdCByb3V0ZXIgdW5kZXJcbiAgICAgIC8vIC9hdWRpdCwgYW5kIHRoZSBpbnRlcm5hbCBpbmdlc3QgZW5kcG9pbnQgbGl2ZXMgYXQgL2V2ZW50cyB1bmRlciB0aGF0LlxuICAgICAgY2xpZW50LnBvc3QoJy9hdWRpdC9ldmVudHMnLCBldmVudCwgeyBoZWFkZXJzLCAuLi5BVURJVF9SRVFVRVNUX09QVElPTlMgfSlcbiAgICAgICAgLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgLy8gQW55IDJ4eCBpcyBhbiBhY2NlcHQgKHRoZSBpbmdlc3QgcmV0dXJucyAyMDAgdG9kYXksIGJ1dCAyMDEvMjAyLzIwNFxuICAgICAgICAgIC8vIGFyZSBlcXVhbGx5IFwic3RvcmVkXCIpOyBvbmx5IGEgbm9uLTJ4eCAvIG1pc3NpbmcgcmVzcG9uc2Ugd2FybnMuXG4gICAgICAgICAgY29uc3Qgb2sgPSByZXNwb25zZSAmJiByZXNwb25zZS5zdGF0dXNDb2RlID49IDIwMCAmJiByZXNwb25zZS5zdGF0dXNDb2RlIDwgMzAwO1xuICAgICAgICAgIGlmICghb2spIHtcbiAgICAgICAgICAgIGxvZ2dlci53YXJuKCdSZW1vdGUgYXVkaXQgaW5nZXN0IG5vbi1vaycsIHtcbiAgICAgICAgICAgICAgYWN0aW9uOiBldmVudC5hY3Rpb24sIHN0YXR1c0NvZGU6IHJlc3BvbnNlPy5zdGF0dXNDb2RlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycjogdW5rbm93bikgPT4ge1xuICAgICAgICAgIGxvZ2dlci53YXJuKCdSZW1vdGUgYXVkaXQgaW5nZXN0IHRocmV3Jywge1xuICAgICAgICAgICAgYWN0aW9uOiBldmVudC5hY3Rpb24sXG4gICAgICAgICAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZTogU3RyaW5nKGVyciksXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH0sXG4gIH07XG59XG4iXX0=
|
|
292
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVtb3RlLWF1ZGl0LWNsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy9yZW1vdGUtYXVkaXQtY2xpZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUNwQyxPQUFPLEVBQUUsd0JBQXdCLEVBQXlDLE1BQU0sa0JBQWtCLENBQUM7QUFDbkcsT0FBTyxFQUFFLGdCQUFnQixFQUF1QixNQUFNLGtCQUFrQixDQUFDO0FBQ3pFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxxQkFBcUIsRUFBd0IsTUFBTSx1QkFBdUIsQ0FBQztBQUUxRyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDbEQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRXpELE1BQU0sTUFBTSxHQUFHLFlBQVksQ0FBQyxjQUFjLENBQUMsQ0FBQztBQUU1Qzs7Ozs7Ozs7R0FRRztBQUNILE1BQU0scUJBQXFCLEdBQStEO0lBQ3hGLG1CQUFtQixFQUFFLENBQUM7SUFDdEIsVUFBVSxFQUFFLENBQUM7Q0FDZCxDQUFDO0FBRUY7Ozs7Ozs7Ozs7R0FVRztBQUNILE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFHO0lBQ2xDLHdCQUF3QjtJQUN4QixxQkFBcUI7SUFDckIsc0JBQXNCO0lBQ3RCLDZFQUE2RTtJQUM3RSwrRUFBK0U7SUFDL0UscUVBQXFFO0lBQ3JFLGVBQWU7SUFDZixlQUFlO0lBQ2YsZUFBZTtJQUNmLDhFQUE4RTtJQUM5RSw0RUFBNEU7SUFDNUUsb0JBQW9CO0lBQ3BCLG9CQUFvQjtJQUNwQixrQkFBa0I7SUFDbEIsZ0VBQWdFO0lBQ2hFLHFFQUFxRTtJQUNyRSxvREFBb0Q7SUFDcEQsaUJBQWlCO0lBQ2pCLGlCQUFpQjtJQUNqQixpQkFBaUI7SUFDakIsMEJBQTBCO0lB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LFdBQW1CLEVBQUUsU0FBa0M7SUFDNUYscUJBQXFCLENBQUMsQ0FBQyxJQUFxQixFQUFFLEVBQUUsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxNQUFNLENBQUM7UUFDbEUsTUFBTSxFQUFFLGNBQWM7UUFDdEIsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPLElBQUksV0FBVztRQUNwQyxVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVU7UUFDM0IsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLO1FBQ2pCLE9BQU8sRUFBRSxTQUFTO1FBQ2xCLE9BQU8sRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSSxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFO0tBQzNFLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQztBQUNuQixDQUFDO0FBZUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLHdCQUF3QixDQUFDLFdBQW1CLEVBQUUsU0FBa0MsRUFBRTtJQUNoRyxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsS0FBSyxJQUFJLHdCQUF3QixFQUFFLElBQUksU0FBUyxDQUFDO0lBQ3RFLE1BQU0sTUFBTSxHQUFHLHVCQUF1QixDQUFDLEVBQUUsR0FBRyxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztJQUM3RCxPQUFPO1FBQ0wsSUFBSSxFQUFFLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxXQUFXLENBQUM7UUFDbEQsTUFBTTtLQUNQLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB7IHJhbmRvbVVVSUQgfSBmcm9tICdjcnlwdG8nO1xuaW1wb3J0IHsgY3JlYXRlRW52UmVkaXNBdWRpdFNwb29sLCB0eXBlIEF1ZGl0U3Bvb2wsIHR5cGUgQXVkaXRTcG9vbEVudHJ5IH0gZnJvbSAnLi9hdWRpdC1zcG9vbC5qcyc7XG5pbXBvcnQgeyBjcmVhdGVTYWZlQ2xpZW50LCB0eXBlIFJlcXVlc3RPcHRpb25zIH0gZnJvbSAnLi9odHRwLWNsaWVudC5qcyc7XG5pbXBvcnQgeyBnZXRTZXJ2aWNlQXV0aEhlYWRlciwgc2V0QXV0aHpEZW5pYWxBdWRpdG9yLCB0eXBlIEF1dGh6RGVuaWFsSW5mbyB9IGZyb20gJy4uL21pZGRsZXdhcmUvYXV0aC5qcyc7XG5pbXBvcnQgdHlwZSB7IFNlcnZpY2VDb25maWcgfSBmcm9tICcuLi90eXBlcy9jb21tb24uanMnO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyLmpzJztcbmltcG9ydCB7IGVtaXRDb3VudGVyIH0gZnJvbSAnLi4vdXRpbHMvbWV0cmljLWVtaXR0ZXIuanMnO1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ3JlbW90ZS1hdWRpdCcpO1xuXG4vKipcbiAqIEF1ZGl0IGluZ2VzdCBpcyBiZXN0LWVmZm9ydCBhbmQgTVVTVCBOT1QgYmxvY2sgdGhlIGNhbGxlciwgYnV0IGEgdHJhbnNpZW50XG4gKiBmYWlsdXJlICg0MjkgLyA1eHggLyBjb25uZWN0aW9uIHJlc2V0IC8gdGltZW91dCkgc2hvdWxkIG5vdCBzaWxlbnRseSBkcm9wIHRoZVxuICogcm93IG9uIHRoZSBmaXJzdCBhdHRlbXB0LiBFYWNoIGVtaXNzaW9uIGNhcnJpZXMgYSBzdGFibGUgcGVyLWV2ZW50XG4gKiBgSWRlbXBvdGVuY3ktS2V5YCAoc2VlIGByZWNvcmRgKSwgc28gdGhlIGh0dHAtY2xpZW50IHRyZWF0cyB0aGUgUE9TVCBhc1xuICogcmV0cnktc2FmZSBhbmQgdGhlIHBsYXRmb3JtIGNhbiBkZWR1cCBhIHJldHJpZWQgZGVsaXZlcnkgaW5zdGVhZCBvZiB3cml0aW5nIGFcbiAqIGR1cGxpY2F0ZSByb3cuIEJ1ZGdldCBpcyBrZXB0IHNtYWxsIHNvIGEgaGFyZC1kb3duIHBsYXRmb3JtIGNhbid0IGJhY2sgdGhlXG4gKiB3b3JrZXIgdXAgZm9yIGxvbmc6IGJhc2UgZGVsYXkgw5coMiByZXRyaWVzKSArIGEgY291cGxlIG9mIDQyOSBiYWNrb2Zmcy5cbiAqL1xuY29uc3QgQVVESVRfUkVRVUVTVF9PUFRJT05TOiBQaWNrPFJlcXVlc3RPcHRpb25zLCAnbWF4UmF0ZUxpbWl0UmV0cmllcycgfCAnbWF4UmV0cmllcyc+ID0ge1xuICBtYXhSYXRlTGltaXRSZXRyaWVzOiAyLFxuICBtYXhSZXRyaWVzOiAyLFxufTtcblxuLyoqXG4gKiBUaGUgZXhhY3Qgc2V0IG9mIGF1ZGl0IGFjdGlvbnMgYSBOT04tUExBVEZPUk0gKHJlbW90ZSkgc2VydmljZSBpcyBwZXJtaXR0ZWQgdG9cbiAqIGVtaXQgdGhyb3VnaCBgUE9TVCAvYXVkaXQvZXZlbnRzYC4gVGhpcyBpcyB0aGUgU0lOR0xFIFNPVVJDRSDigJQgYFJlbW90ZUF1ZGl0QWN0aW9uYFxuICogaXMgZGVyaXZlZCBmcm9tIGl0LCBzbyB0aGUgdHlwZSBhbmQgdGhlIHJ1bnRpbWUgYWxsb3ctbGlzdCBjYW4gbmV2ZXIgZHJpZnQuXG4gKlxuICogU0VDVVJJVFk6IHBsYXRmb3JtJ3MgaW5nZXN0IHZhbGlkYXRlcyBgYWN0aW9uYCBhZ2FpbnN0IHRoaXMgc3Vic2V0ICh2aWFcbiAqIHtAbGluayBpc1JlbW90ZUF1ZGl0QWN0aW9ufSksIE5PVCB0aGUgZnVsbCBwbGF0Zm9ybSBgQXVkaXRBY3Rpb25gIHVuaW9uIOKAlCBhXG4gKiBgc2VydmljZToqYCB0b2tlbiBtdXN0IG5vdCBiZSBhYmxlIHRvIGZvcmdlIHBsYXRmb3JtLWF1dGhvcml0eSBldmVudHNcbiAqIChgYWRtaW4uc3VwZXJhZG1pbi5ncmFudGAsIGBvcmcub3duZXJzaGlwLnRyYW5zZmVyYCwgYHVzZXIubG9naW5gLCDigKYpLiBLZWVwXG4gKiB0aGlzIGxpc3QgZnJlZSBvZiBhbnkgcGxhdGZvcm0tb25seSBhY3Rpb24uXG4gKi9cbmV4cG9ydCBjb25zdCBSRU1PVEVfQVVESVRfQUNUSU9OUyA9IFtcbiAgJ3BsdWdpbi5idWlsZC5jb21wbGV0ZWQnLFxuICAncGx1Z2luLmJ1aWxkLmZhaWxlZCcsXG4gICdwbHVnaW4uYnVpbGQudGltZW91dCcsXG4gIC8vIFBsdWdpbiBsaWZlY3ljbGUgbXV0YXRpb25zIChhcGkvcGx1Z2luIHJvdXRlIGhhbmRsZXJzKSDigJQgdGhlIGRlc3RydWN0aXZlIC9cbiAgLy8gcHVibGlzaGluZyBzdXJmYWNlIHRoYXQgYnVpbGRzIGFscmVhZHkgYXVkaXQncyBjb3VudGVycGFydDogcmVnaXN0cnkgZGVsZXRlLFxuICAvLyBzb3VyY2UgdXBsb2FkLCBhbmQgZGVwbG95LXRvLWNsdXN0ZXIuIGB0YXJnZXRJZGAgaXMgdGhlIHBsdWdpbiBpZC5cbiAgJ3BsdWdpbi5kZWxldGUnLFxuICAncGx1Z2luLnVwbG9hZCcsXG4gICdwbHVnaW4uZGVwbG95JyxcbiAgLy8gUGx1Z2luIGJ1bGsgbXV0YXRpb25zIChhcGkvcGx1Z2luIGJ1bGstcGx1Z2luIHJvdXRlKSArIERMUSBwdXJnZSAoZHJvcHMgYWxsXG4gIC8vIGRlYWQtbGV0dGVyZWQgYnVpbGQgam9icywgY3Jvc3Mtb3JnLCBzeXNhZG1pbikuIGBkZXRhaWxzYCBjYXJyaWVzIGNvdW50cy5cbiAgJ3BsdWdpbi5idWxrLnVwZGF0ZScsXG4gICdwbHVnaW4uYnVsay5kZWxldGUnLFxuICAncGx1Z2luLmRscS5wdXJnZScsXG4gIC8vIFBpcGVsaW5lIG11dGF0aW9ucyDigJQgZW1pdHRlZCBieSBhcGkvcGlwZWxpbmUncyByb3V0ZSBoYW5kbGVyc1xuICAvLyAoY3JlYXRlL3VwZGF0ZS9kZWxldGUgKyBDb2RlUGlwZWxpbmUgZXhlY3V0aW9uIHRyaWdnZXIvY2FuY2VsKSBhbmRcbiAgLy8gcG9zdGVkIHRvIHBsYXRmb3JtJ3MgYFBPU1QgL2F1ZGl0L2V2ZW50c2AgaW5nZXN0LlxuICAncGlwZWxpbmUuY3JlYXRlJyxcbiAgJ3BpcGVsaW5lLnVwZGF0ZScsXG4gICdwaXBlbGluZS5kZWxldGUnLFxuICAncGlwZWxpbmUuZXhlY3V0aW9uLnN0YXJ0JyxcbiAgJ3BpcGVsaW5lLmV4ZWN1dGlvbi5jYW5jZWwnLFxuICAvLyBDb2RlUGlwZWxpbmUgQVJOLXJlZ2lzdHJ5IGNvbmZpZyAoYXBpL3BpcGVsaW5lIHJlZ2lzdHJ5IHJvdXRlKSDigJQgcmVnaXN0ZXJpbmcgL1xuICAvLyBkZXJlZ2lzdGVyaW5nIHRoZSBleHRlcm5hbCBDb2RlUGlwZWxpbmUgdGhhdCBiYWNrcyBhIHBpcGVsaW5lIChkZXBsb3ktYWZmZWN0aW5nKS5cbiAgJ3BpcGVsaW5lLnJlZ2lzdHJ5LnJlZ2lzdGVyJyxcbiAgJ3BpcGVsaW5lLnJlZ2lzdHJ5LmRlcmVnaXN0ZXInLFxuICAvLyBRdW90YSBhZG1pbmlzdHJhdGlvbiAoYXBpL3F1b3RhKSDigJQgYSBzdXBlcmFkbWluIHJlc2V0dGluZyBhbiBvcmcncyB1c2FnZVxuICAvLyBjb3VudGVyIG9yIGVkaXRpbmcgaXRzIHRpZXIgbGltaXRzLiBgYWZmZWN0ZWRPcmdJZGAgaXMgdGhlIG9yZyBjaGFuZ2VkO1xuICAvLyBgZGV0YWlsc2AgY2FycmllcyB0aGUgcXVvdGFUeXBlICsgb2xkL25ldyB2YWx1ZS5cbiAgJ3F1b3RhLnJlc2V0JyxcbiAgJ3F1b3RhLmxpbWl0LnVwZGF0ZScsXG4gIC8vIEEgc3VwZXJhZG1pbiBkZWxldGluZyBhbiBvcmcncyBlbnRpcmUgcXVvdGEgZG9jdW1lbnQuXG4gICdxdW90YS5kZWxldGUnLFxuICAvLyBDb21wbGlhbmNlIGFkbWluaXN0cmF0aW9uIChhcGkvY29tcGxpYW5jZSkg4oCUIHRoZSBlbmZvcmNlbWVudC1wb3N0dXJlIHN1cmZhY2UuXG4gIC8vIEFwcHJvdmluZy9yZXZva2luZyBhbiBleGVtcHRpb24sIHRvZ2dsaW5nL2F1dGhvcmluZy9kZWxldGluZyBhIHJ1bGUsXG4gIC8vIGF1dGhvcmluZy9kZWxldGluZyBhIHBvbGljeSwgbWFuYWdpbmcgc2NhbiBzY2hlZHVsZXMsIGFwcGx5aW5nIGEgdGVtcGxhdGUsXG4gIC8vIG9yIGNhbmNlbGxpbmcgYSBydW5uaW5nIHNjYW4uIGB0YXJnZXRJZGAgaXMgdGhlIHJ1bGUvcG9saWN5L2V4ZW1wdGlvbi9zY2FuIGlkLlxuICAnY29tcGxpYW5jZS5leGVtcHRpb24uYXBwcm92ZScsXG4gICdjb21wbGlhbmNlLmV4ZW1wdGlvbi5yZXZva2UnLFxuICAnY29tcGxpYW5jZS5ydWxlLnRvZ2dsZScsXG4gICdjb21wbGlhbmNlLnJ1bGUuY3JlYXRlJyxcbiAgJ2NvbXBsaWFuY2UucnVsZS51cGRhdGUnLFxuICAnY29tcGxpYW5jZS5ydWxlLmRlbGV0ZScsXG4gICdjb21wbGlhbmNlLnBvbGljeS5jcmVhdGUnLFxuICAnY29tcGxpYW5jZS5wb2xpY3kudXBkYXRlJyxcbiAgJ2NvbXBsaWFuY2UucG9saWN5LmRlbGV0ZScsXG4gICdjb21wbGlhbmNlLnNjYW4tc2NoZWR1bGUuY3JlYXRlJyxcbiAgJ2NvbXBsaWFuY2Uuc2Nhbi1zY2hlZHVsZS51cGRhdGUnLFxuICAnY29tcGxpYW5jZS5zY2FuLXNjaGVkdWxlLmRlbGV0ZScsXG4gICdjb21wbGlhbmNlLnRlbXBsYXRlLmFwcGx5JyxcbiAgJ2NvbXBsaWFuY2Uuc2Nhbi5jYW5jZWwnLFxuICAvLyBJbWFnZS1yZWdpc3RyeSBkZXN0cnVjdGl2ZSBvcHMgKGFwaS9pbWFnZS1yZWdpc3RyeSkg4oCUIGdhcmJhZ2UtY29sbGVjdGlvblxuICAvLyBzd2VlcHMgYW5kIGV4cGxpY2l0IGltYWdlL3RhZyBkZWxldGVzIChwcmV2aW91c2x5IG9ubHkgYSBsb2cgbGluZSkuXG4gICdyZWdpc3RyeS5nYycsXG4gICdyZWdpc3RyeS5pbWFnZS5kZWxldGUnLFxuICAvLyBNZXNzYWdpbmcgKGFwaS9tZXNzYWdlKSDigJQgYWRtaW4gQlJPQURDQVNUIGFubm91bmNlbWVudHMgKyBkZXN0cnVjdGl2ZVxuICAvLyBkZWxldGVzLiAxOjEgdXNlciBtZXNzYWdlcyBhcmUgaW50ZW50aW9uYWxseSBOT1QgYXVkaXRlZCAobm9pc2UgKyB0aGV5IHdvdWxkXG4gIC8vIHB1bGwgcHJpdmF0ZSBjb250ZW50IGludG8gdGhlIHRyYWlsKS4gYGRldGFpbHNgIGNhcnJ5IG1ldGFkYXRhIG9ubHlcbiAgLy8gKHN1YmplY3QvdHlwZS9zY29wZSksIE5FVkVSIG1lc3NhZ2UgYm9keSBjb250ZW50LlxuICAnbWVzc2FnZS5hbm5vdW5jZW1lbnQuY3JlYXRlJyxcbiAgJ21lc3NhZ2UuZGVsZXRlJyxcbiAgLy8gQmlsbGluZyAoYXBpL2JpbGxpbmcpIOKAlCBzdWJzY3JpcHRpb24gKyBlbnRpdGxlbWVudCBtdXRhdGlvbnMsIG1pcnJvcmVkIHRvIHRoZVxuICAvLyBjZW50cmFsIGF1ZGl0IHRyYWlsICh0aGVzZSBhbHNvIHdyaXRlIHRvIHRoZSBzZXJ2aWNlLWxvY2FsIGJpbGxpbmdfZXZlbnRzXG4gIC8vIGNvbGxlY3Rpb24pLiBgZGV0YWlsc2AgY2FycnkgcGxhbi90aWVyL2FkZG9uIGlkcyBvbmx5IOKAlCBuZXZlciBjYXJkL3BheW1lbnRcbiAgLy8gc2VjcmV0cyBvciBhbiBBV1MgYWNjb3VudCBpZC5cbiAgJ2JpbGxpbmcuc3Vic2NyaXB0aW9uLmNhbmNlbCcsXG4gICdiaWxsaW5nLnN1YnNjcmlwdGlvbi5kZWxldGUnLFxuICAnYmlsbGluZy50aWVyLm92ZXJyaWRlJyxcbiAgJ2JpbGxpbmcuYWRkb24uYWRkJyxcbiAgJ2JpbGxpbmcuYWRkb24ucmVtb3ZlJyxcbiAgLy8gRGVuaWVkIGF1dGhvcml6YXRpb24gYXR0ZW1wdCDigJQgZW1pdHRlZCBiZXN0LWVmZm9ydCBieSB0aGUgc2hhcmVkXG4gIC8vIGByZXF1aXJlUGVybWlzc2lvbmAgLyBgcmVxdWlyZVN5c3RlbUFkbWluYCBnYXRlIHdoZW4gYSBzdGF0ZS1jaGFuZ2luZ1xuICAvLyAobm9uLUdFVCkgcmVxdWVzdCBpcyByZWplY3RlZCwgc28gcHJvYmluZy9lc2NhbGF0aW9uIGF0dGVtcHRzIGFyZSB2aXNpYmxlXG4gIC8vIHJhdGhlciB0aGFuIGludmlzaWJsZS4gYGRldGFpbHNgIGNhcnJpZXMgdGhlIHJlcXVpcmVkIHBlcm1pc3Npb24gKyBwYXRoO1xuICAvLyBgb3V0Y29tZWAgaXMgJ2ZhaWx1cmUnLlxuICAnYXV0aHouZGVuaWVkJyxcbl0gYXMgY29uc3Q7XG5cbmV4cG9ydCB0eXBlIFJlbW90ZUF1ZGl0QWN0aW9uID0gdHlwZW9mIFJFTU9URV9BVURJVF9BQ1RJT05TW251bWJlcl07XG5cbi8qKiBXaGV0aGVyIGB2YWx1ZWAgaXMgYW4gYWN0aW9uIGEgcmVtb3RlIHNlcnZpY2UgbWF5IGVtaXQgKHRoZSBpbmdlc3QgYWxsb3ctbGlzdCkuICovXG5leHBvcnQgZnVuY3Rpb24gaXNSZW1vdGVBdWRpdEFjdGlvbih2YWx1ZTogc3RyaW5nKTogdmFsdWUgaXMgUmVtb3RlQXVkaXRBY3Rpb24ge1xuICByZXR1cm4gKFJFTU9URV9BVURJVF9BQ1RJT05TIGFzIHJlYWRvbmx5IHN0cmluZ1tdKS5pbmNsdWRlcyh2YWx1ZSk7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVtb3RlQXVkaXRFdmVudCB7XG4gIGFjdGlvbjogUmVtb3RlQXVkaXRBY3Rpb247XG4gIGFjdG9ySWQ6IHN0cmluZztcbiAgYWN0b3JFbWFpbD86IHN0cmluZztcbiAgb3JnSWQ/OiBzdHJpbmc7XG4gIGFmZmVjdGVkT3JnSWQ/OiBzdHJpbmc7XG4gIHRhcmdldFR5cGU/OiBzdHJpbmc7XG4gIHRhcmdldElkPzogc3RyaW5nO1xuICAvKipcbiAgICogRGlkIHRoZSBhdWRpdGVkIGFjdGlvbiBzdWNjZWVkIG9yIGZhaWw/IERlZmF1bHRzIHRvICdzdWNjZXNzJyB3aGVuIG9taXR0ZWRcbiAgICogKHRoZSBwbGF0Zm9ybSBpbmdlc3QgYXBwbGllcyB0aGUgc2FtZSBkZWZhdWx0KS4gRGVuaWVkLWF1dGh6IGV2ZW50cyBzZXRcbiAgICogJ2ZhaWx1cmUnIHNvIGEgcmV2aWV3ZXIgY2FuIGZpbHRlciBhdHRlbXB0cyBmcm9tIGNvbXBsZXRlZCBhY3Rpb25zLlxuICAgKi9cbiAgb3V0Y29tZT86ICdzdWNjZXNzJyB8ICdmYWlsdXJlJztcbiAgLyoqXG4gICAqIFdoZW4gdGhlIGF1ZGl0ZWQgYWN0aW9uIGFjdHVhbGx5IE9DQ1VSUkVEIChJU08tODYwMSksIHN0YW1wZWQgYXQgZW1pc3Npb24uXG4gICAqIFRoZSBwbGF0Zm9ybSBzdG9yZXMgdGhpcyBmb3IgcmV2aWV3ZXJzOyBpdCBpcyBOT1QgdGhlIGNoYWluLW9yZGVyaW5nIGZpZWxkXG4gICAqICh0aGUgdGFtcGVyLWV2aWRlbnQgY2hhaW4gb3JkZXJzIGJ5IGluZ2VzdC9gY3JlYXRlZEF0YCkuIEl0IG1hdHRlcnMgZm9yXG4gICAqIFNQT09MRUQgZXZlbnRzOiBvbmUgYnVmZmVyZWQgZHVyaW5nIGEgcGxhdGZvcm0gb3V0YWdlIGlzIHJlLWRlbGl2ZXJlZCDigJQgYW5kXG4gICAqIHNvIGNoYWluZWQg4oCUIGxhdGVyLCBidXQgYG9jY3VycmVkQXRgIHByZXNlcnZlcyB3aGVuIGl0IHJlYWxseSBoYXBwZW5lZC5cbiAgICovXG4gIG9jY3VycmVkQXQ/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBTdGFibGUgcGVyLWVtaXNzaW9uIGRlZHVwIGtleSAoYWxzbyBzZW50IGFzIHRoZSBgSWRlbXBvdGVuY3ktS2V5YCBoZWFkZXIgdGhlXG4gICAqIHBsYXRmb3JtIGluZ2VzdCBkZWR1cHMgb24pLiBTdGFtcGVkIGJ5IGByZWNvcmQoKWAgYW5kIGNhcnJpZWQgb24gdGhlIHNwb29sZWRcbiAgICogY29weSBzbyBhIGxpdmUgYXR0ZW1wdCBhbmQgaXRzIGxhdGVyIHJlLWRlbGl2ZXJ5IGNvbGxhcHNlIHRvIE9ORSBzdG9yZWQgcm93LlxuICAgKi9cbiAgaWRlbXBvdGVuY3lLZXk/OiBzdHJpbmc7XG4gIGRldGFpbHM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbn1cblxuLyoqXG4gKiBDbGllbnQgZm9yIFBPU1RpbmcgYXVkaXQgZXZlbnRzIHRvIHRoZSBwbGF0Zm9ybSdzIGAvYXVkaXQtZXZlbnRzYCBpbmdlc3RcbiAqIGVuZHBvaW50LiBNaW50cyBhIGZyZXNoIHNlcnZpY2UgdG9rZW4gcGVyIGNhbGwgKDUgbWluIFRUTCkgIHRoZXJlJ3Mgbm9cbiAqIG1lYW5pbmdmdWwgY2FjaGluZyBiZW5lZml0IHdoZW4gZW1pc3Npb25zIGFyZSBzcGFyc2UuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVtb3RlQXVkaXRDbGllbnQge1xuICAvKipcbiAgICogRmlyZS1hbmQtZm9yZ2V0IGF1ZGl0IGVtaXNzaW9uLiBGYWlsdXJlcyBhcmUgbG9nZ2VkIGF0IHdhcm4gbGV2ZWwgYnV0XG4gICAqIG5ldmVyIHRocm93biAgdGhlIG9yaWdpbmF0aW5nIGFjdGlvbiAoZS5nLiBhIHBsdWdpbiBidWlsZCkgaGFzIGl0c1xuICAgKiBvd24gc3VjY2Vzcy9mYWlsdXJlIHBhdGggdGhhdCBzaG91bGRuJ3QgZ2V0IHBvbGx1dGVkIGJ5IGEgZmxha3kgYXVkaXRcbiAgICogZG93bnN0cmVhbS4gV2hlbiBhIHtAbGluayBBdWRpdFNwb29sfSBpcyBjb25maWd1cmVkLCBhbiBlbWlzc2lvbiB0aGF0XG4gICAqIGV4aGF1c3RzIGl0cyBsaXZlIHJldHJpZXMgaXMgYnVmZmVyZWQgYW5kIHJlLWRlbGl2ZXJlZCBsYXRlciBpbnN0ZWFkIG9mXG4gICAqIGJlaW5nIGRyb3BwZWQuXG4gICAqL1xuICByZWNvcmQoZXZlbnQ6IFJlbW90ZUF1ZGl0RXZlbnQsIHNlcnZpY2VOYW1lOiBzdHJpbmcpOiB2b2lkO1xuICAvKiogU3RvcCB0aGUgYmFja2dyb3VuZCBzcG9vbC1kcmFpbiB0aW1lciAoaWYgYW55KS4gU2FmZSB0byBjYWxsIHJlcGVhdGVkbHkuICovXG4gIGNsb3NlKCk6IHZvaWQ7XG59XG5cbi8qKlxuICogQ29uZmlndXJhdGlvbiBmb3IgdGhlIHJlbW90ZSBhdWRpdCBjbGllbnQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVtb3RlQXVkaXRDbGllbnRDb25maWcge1xuICAvKiogUGxhdGZvcm0gc2VydmljZSBob3N0IChkZWZhdWx0OiBlbnYgUExBVEZPUk1fU0VSVklDRV9IT1NUIG9yICdwbGF0Zm9ybScpICovXG4gIGhvc3Q/OiBzdHJpbmc7XG4gIC8qKiBQbGF0Zm9ybSBzZXJ2aWNlIHBvcnQgKGRlZmF1bHQ6IGVudiBQTEFURk9STV9TRVJWSUNFX1BPUlQgb3IgMzAwMCkgKi9cbiAgcG9ydD86IG51bWJlcjtcbiAgLyoqIFJlcXVlc3QgdGltZW91dCBtcyAoZGVmYXVsdCAzMDAwICBhdWRpdCBzaG91bGRuJ3QgYmxvY2sgdGhlIHdvcmtlcikuICovXG4gIHRpbWVvdXQ/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBPcHRpb25hbCBkdXJhYmxlIGJ1ZmZlci4gV2hlbiBzZXQsIGFuIGVtaXNzaW9uIHRoYXQgZXhoYXVzdHMgaXRzIGxpdmUgcmV0cnlcbiAgICogYnVkZ2V0IChzdXN0YWluZWQgcGxhdGZvcm0gb3V0YWdlKSBpcyBzcG9vbGVkIGFuZCByZS1kZWxpdmVyZWQg4oCUIG9uIHRoZSBuZXh0XG4gICAqIHN1Y2Nlc3NmdWwgZW1pc3Npb24gYW5kIG9uIGEgcGVyaW9kaWMgdGltZXIg4oCUIGluc3RlYWQgb2YgYmVpbmcgbG9zdC5cbiAgICovXG4gIHNwb29sPzogQXVkaXRTcG9vbDtcbiAgLyoqIFNwb29sLWRyYWluIGludGVydmFsIG1zIChkZWZhdWx0IDMwXzAwMCkuIE9ubHkgdXNlZCB3aGVuIGBzcG9vbGAgaXMgc2V0LiAqL1xuICBkcmFpbkludGVydmFsTXM/OiBudW1iZXI7XG4gIC8qKiBNYXggZW50cmllcyBkcmFpbmVkIHBlciBzd2VlcCAoZGVmYXVsdCAxMDApLiAqL1xuICBkcmFpbkJhdGNoU2l6ZT86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBDb25zdHJ1Y3QgYSByZW1vdGUtYXVkaXQgY2xpZW50IHRhcmdldGVkIGF0IHRoZSBwbGF0Zm9ybSBzZXJ2aWNlLlxuICpcbiAqIFVzZWQgYnkgYXBpL3BsdWdpbidzIGJ1aWxkIHdvcmtlciB0byBwdXNoIGBwbHVnaW4uYnVpbGQuKmAgZXZlbnRzIGludG9cbiAqIHRoZSBwbGF0Zm9ybSdzIE1vbmdvREIgYGF1ZGl0X2V2ZW50c2AgY29sbGVjdGlvbi4gT3RoZXIgc2VydmljZXNcbiAqIHdpdGggd29ya2VyLXN0eWxlIGVtaXR0ZXJzIGNhbiB1c2UgdGhlIHNhbWUgY2xpZW50LlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBhdWRpdENsaWVudCA9IGNyZWF0ZVJlbW90ZUF1ZGl0Q2xpZW50KCk7XG4gKiBhdWRpdENsaWVudC5yZWNvcmQoe1xuICogYWN0aW9uOiAncGx1Z2luLmJ1aWxkLmNvbXBsZXRlZCcsXG4gKiBhY3RvcklkOiAndXNlci0xMjMnLFxuICogb3JnSWQ6ICdvcmctYWNtZScsXG4gKiB0YXJnZXRUeXBlOiAncGx1Z2luJyxcbiAqIHRhcmdldElkOiAncGx1Z2luLWFiYycsXG4gKiBkZXRhaWxzOiB7IG5hbWU6ICdteS1wbHVnaW4nLCB2ZXJzaW9uOiAnMS4wLjAnIH0sXG4gKiB9LCAncGx1Z2luJyk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVJlbW90ZUF1ZGl0Q2xpZW50KGNvbmZpZzogUmVtb3RlQXVkaXRDbGllbnRDb25maWcgPSB7fSk6IFJlbW90ZUF1ZGl0Q2xpZW50IHtcbiAgY29uc3Qgc2VydmljZUNvbmZpZzogU2VydmljZUNvbmZpZyA9IHtcbiAgICBob3N0OiBjb25maWcuaG9zdCA/PyBwcm9jZXNzLmVudi5QTEFURk9STV9TRVJWSUNFX0hPU1QgPz8gJ3BsYXRmb3JtJyxcbiAgICBwb3J0OiBjb25maWcucG9ydCA/PyBwYXJzZUludChwcm9jZXNzLmVudi5QTEFURk9STV9TRVJWSUNFX1BPUlQgPz8gJzMwMDAnLCAxMCksXG4gICAgdGltZW91dDogY29uZmlnLnRpbWVvdXQgPz8gMzAwMCxcbiAgfTtcbiAgY29uc3QgY2xpZW50ID0gY3JlYXRlU2FmZUNsaWVudChzZXJ2aWNlQ29uZmlnKTtcbiAgY29uc3Qgc3Bvb2wgPSBjb25maWcuc3Bvb2w7XG4gIGNvbnN0IGRyYWluQmF0Y2hTaXplID0gY29uZmlnLmRyYWluQmF0Y2hTaXplID8/IDEwMDtcblxuICAvKipcbiAgICogQXR0ZW1wdCBPTkUgbGl2ZSBkZWxpdmVyeS4gUmVzb2x2ZXMgYHRydWVgIG9uIGEgMnh4IGFjY2VwdCwgYGZhbHNlYCBvbiBhbnlcbiAgICogbm9uLTJ4eCAvIHRocm93biBlcnJvciAodGhlIGh0dHAtY2xpZW50IGhhcyBhbHJlYWR5IGFwcGxpZWQgdGhlIHJldHJ5XG4gICAqIGJ1ZGdldCkuIEEgc3RhYmxlIHBlci1lbWlzc2lvbiBgSWRlbXBvdGVuY3ktS2V5YCBtYWtlcyB0aGlzIG5vbi1pZGVtcG90ZW50XG4gICAqIFBPU1QgcmV0cnktc2FmZSBhbmQgbGV0cyB0aGUgcGxhdGZvcm0gaW5nZXN0IGRlZHVwIGEgcmUtZGVsaXZlcmVkIGV2ZW50XG4gICAqIGluc3RlYWQgb2Ygd3JpdGluZyBhIGR1cGxpY2F0ZSBhdWRpdCByb3cgKGFuZCBkdXBsaWNhdGUgY2hhaW4gbGluaykuXG4gICAqIGBJZGVtcG90ZW5jeS1LZXlgIGlzIGRlcml2ZWQgZnJvbSB0aGUgZXZlbnQgc28gYSBTUE9PTEVEIHJlLWRlbGl2ZXJ5IHJldXNlc1xuICAgKiB0aGUgc2FtZSBrZXkgYXMgaXRzIG9yaWdpbmFsIGxpdmUgYXR0ZW1wdCDigJQgdGhlIHR3byBjb2xsYXBzZSB0byBvbmUgcm93LlxuICAgKi9cbiAgYXN5bmMgZnVuY3Rpb24gZGVsaXZlcihldmVudDogUmVtb3RlQXVkaXRFdmVudCwgc2VydmljZU5hbWU6IHN0cmluZyk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGNvbnN0IGF1dGhIZWFkZXIgPSBnZXRTZXJ2aWNlQXV0aEhlYWRlcih7IHNlcnZpY2VOYW1lLCBvcmdJZDogZXZlbnQub3JnSWQsIHJvbGU6ICdtZW1iZXInIH0pO1xuICAgIGNvbnN0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICAnQXV0aG9yaXphdGlvbic6IGF1dGhIZWFkZXIsXG4gICAgICAnSWRlbXBvdGVuY3ktS2V5JzogZXZlbnQuaWRlbXBvdGVuY3lLZXkgPz8gcmFuZG9tVVVJRCgpLFxuICAgIH07XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50LnBvc3QoJy9hdWRpdC9ldmVudHMnLCBldmVudCwgeyBoZWFkZXJzLCAuLi5BVURJVF9SRVFVRVNUX09QVElPTlMgfSk7XG4gICAgICBjb25zdCBvayA9ICEhcmVzcG9uc2UgJiYgcmVzcG9uc2Uuc3RhdHVzQ29kZSA+PSAyMDAgJiYgcmVzcG9uc2Uuc3RhdHVzQ29kZSA8IDMwMDtcbiAgICAgIGlmICghb2spIHtcbiAgICAgICAgbG9nZ2VyLndhcm4oJ1JlbW90ZSBhdWRpdCBpbmdlc3Qgbm9uLW9rJywgeyBhY3Rpb246IGV2ZW50LmFjdGlvbiwgc3RhdHVzQ29kZTogcmVzcG9uc2U/LnN0YXR1c0NvZGUgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gb2s7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2dnZXIud2FybignUmVtb3RlIGF1ZGl0IGluZ2VzdCB0aHJldycsIHsgYWN0aW9uOiBldmVudC5hY3Rpb24sIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVycikgfSk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLy8gU2VyaWFsaXplIHNwb29sIGRyYWlucyBzbyBhIHBlcmlvZGljIHRpY2sgYW5kIGFuIG9uLXN1Y2Nlc3MgZHJhaW4gY2FuJ3QgYm90aFxuICAvLyBwdWxsIHRoZSBzYW1lIGJhdGNoLiBTdG9wcyBlYXJseSB0aGUgbW9tZW50IGEgcmUtZGVsaXZlcnkgZmFpbHMgKHBsYXRmb3JtXG4gIC8vIHN0aWxsIGRvd24pIHNvIHdlIGRvbid0IGhhbW1lciBpdCBvciBjaHVybiB0aGUgYnVmZmVyLlxuICBsZXQgZHJhaW5pbmcgPSBmYWxzZTtcbiAgYXN5bmMgZnVuY3Rpb24gZHJhaW4oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCFzcG9vbCB8fCBkcmFpbmluZykgcmV0dXJuO1xuICAgIGRyYWluaW5nID0gdHJ1ZTtcbiAgICB0cnkge1xuICAgICAgZm9yICg7Oykge1xuICAgICAgICBjb25zdCBiYXRjaCA9IGF3YWl0IHNwb29sLnRha2UoZHJhaW5CYXRjaFNpemUpO1xuICAgICAgICBpZiAoYmF0Y2gubGVuZ3RoID09PSAwKSByZXR1cm47XG4gICAgICAgIGNvbnN0IGZhaWxlZDogQXVkaXRTcG9vbEVudHJ5W10gPSBbXTtcbiAgICAgICAgbGV0IHBsYXRmb3JtRG93biA9IGZhbHNlO1xuICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGJhdGNoKSB7XG4gICAgICAgICAgaWYgKHBsYXRmb3JtRG93bikgeyBmYWlsZWQucHVzaChlbnRyeSk7IGNvbnRpbnVlOyB9XG4gICAgICAgICAgY29uc3Qgb2sgPSBhd2FpdCBkZWxpdmVyKGVudHJ5LmV2ZW50LCBlbnRyeS5zZXJ2aWNlTmFtZSk7XG4gICAgICAgICAgaWYgKG9rKSB7XG4gICAgICAgICAgICBlbWl0Q291bnRlcignYXVkaXRfc3Bvb2xfcmVkZWxpdmVyZWRfdG90YWwnLCB7IHNlcnZpY2U6IGVudHJ5LnNlcnZpY2VOYW1lIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBwbGF0Zm9ybURvd24gPSB0cnVlO1xuICAgICAgICAgICAgZmFpbGVkLnB1c2goZW50cnkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoZmFpbGVkLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBhd2FpdCBzcG9vbC5yZXF1ZXVlKGZhaWxlZCk7XG4gICAgICAgICAgcmV0dXJuOyAvLyBzdGlsbCBkb3duIOKAlCB0cnkgYWdhaW4gb24gdGhlIG5leHQgdGlja1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2dnZXIud2FybignQXVkaXQgc3Bvb2wgZHJhaW4gZmFpbGVkJywgeyBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpIH0pO1xuICAgIH0gZmluYWxseSB7XG4gICAgICBkcmFpbmluZyA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIGxldCBkcmFpblRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRJbnRlcnZhbD4gfCB1bmRlZmluZWQ7XG4gIGlmIChzcG9vbCkge1xuICAgIGRyYWluVGltZXIgPSBzZXRJbnRlcnZhbCgoKSA9PiB7IHZvaWQgZHJhaW4oKTsgfSwgY29uZmlnLmRyYWluSW50ZXJ2YWxNcyA/PyAzMF8wMDApO1xuICAgIC8vIERvbid0IGxldCB0aGUgZHJhaW4gdGltZXIga2VlcCB0aGUgcHJvY2VzcyBhbGl2ZSBvbiBzaHV0ZG93bi5cbiAgICAoZHJhaW5UaW1lciBhcyB1bmtub3duIGFzIHsgdW5yZWY/OiAoKSA9PiB2b2lkIH0pLnVucmVmPy4oKTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgcmVjb3JkKGV2ZW50LCBzZXJ2aWNlTmFtZSkge1xuICAgICAgLy8gU3RhbXAgd2hlbiB0aGUgYWN0aW9uIGFjdHVhbGx5IG9jY3VycmVkIChzdXJ2aXZlcyBzcG9vbCBkZWxheSkgYW5kIHBpbiBhXG4gICAgICAvLyBzdGFibGUgaWRlbXBvdGVuY3kga2V5IHNvIGEgbGl2ZSBhdHRlbXB0IGFuZCBpdHMgc3Bvb2xlZCByZXRyeSBkZWR1cC5cbiAgICAgIGNvbnN0IHN0YW1wZWQ6IFJlbW90ZUF1ZGl0RXZlbnQgPSB7XG4gICAgICAgIC4uLmV2ZW50LFxuICAgICAgICBvY2N1cnJlZEF0OiBldmVudC5vY2N1cnJlZEF0ID8/IG5ldyBEYXRlKCkudG9JU09TdHJpbmcoKSxcbiAgICAgICAgaWRlbXBvdGVuY3lLZXk6IGV2ZW50LmlkZW1wb3RlbmN5S2V5ID8/IHJhbmRvbVVVSUQoKSxcbiAgICAgIH07XG4gICAgICB2b2lkIGRlbGl2ZXIoc3RhbXBlZCwgc2VydmljZU5hbWUpLnRoZW4oKG9rKSA9PiB7XG4gICAgICAgIGlmIChvaykge1xuICAgICAgICAgIGVtaXRDb3VudGVyKCdhdWRpdF9lbWl0dGVkX3RvdGFsJywgeyBzZXJ2aWNlOiBzZXJ2aWNlTmFtZSwgb3V0Y29tZTogc3RhbXBlZC5vdXRjb21lID8/ICdzdWNjZXNzJyB9KTtcbiAgICAgICAgICBpZiAoc3Bvb2wpIHZvaWQgZHJhaW4oKTsgLy8gcGxhdGZvcm0gaXMgcmVhY2hhYmxlIOKAlCBmbHVzaCBhbnkgYmFja2xvZ1xuICAgICAgICB9IGVsc2UgaWYgKHNwb29sKSB7XG4gICAgICAgICAgdm9pZCBzcG9vbC5lbnF1ZXVlKHsgZXZlbnQ6IHN0YW1wZWQsIHNlcnZpY2VOYW1lIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGVtaXRDb3VudGVyKCdhdWRpdF9kcm9wcGVkX3RvdGFsJywgeyBzZXJ2aWNlOiBzZXJ2aWNlTmFtZSB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgICBjbG9zZSgpIHtcbiAgICAgIGlmIChkcmFpblRpbWVyKSB7IGNsZWFySW50ZXJ2YWwoZHJhaW5UaW1lcik7IGRyYWluVGltZXIgPSB1bmRlZmluZWQ7IH1cbiAgICB9LFxuICB9O1xufVxuXG4vKipcbiAqIFJlZ2lzdGVyIHRoZSBzdGFuZGFyZCBgYXV0aHouZGVuaWVkYCBzaW5rIHVzZWQgYnkgZXZlcnkgcmVtb3RlLWF1ZGl0IHNlcnZpY2VcbiAqIChwaXBlbGluZSwgcGx1Z2luLCBjb21wbGlhbmNlLCBxdW90YSwgbWVzc2FnZSwgYmlsbGluZywgcmVwb3J0aW5nLCDigKYpLlxuICpcbiAqIFRoZSBzaGFyZWQgYHJlcXVpcmVBdXRoYCBnYXRlIGZvcndhcmRzIGVhY2ggREVOSUVEIHN0YXRlLWNoYW5naW5nIHJlcXVlc3QgdG9cbiAqIHRoZSBhdWRpdG9yIHNldCB2aWEge0BsaW5rIHNldEF1dGh6RGVuaWFsQXVkaXRvcn07IHRoaXMgd2lyZXMgdGhhdCBob29rIHRvIHRoZVxuICogc2VydmljZSdzIHtAbGluayBSZW1vdGVBdWRpdENsaWVudH0sIGZvcndhcmRpbmcgYSBgZmFpbHVyZWAtb3V0Y29tZVxuICogYGF1dGh6LmRlbmllZGAgZXZlbnQgc28gcHJvYmluZyAvIHByaXZpbGVnZS1lc2NhbGF0aW9uIGF0dGVtcHRzIGxlYXZlIGEgdHJhaWwuXG4gKiBFbWlzc2lvbiBpcyBmaXJlLWFuZC1mb3JnZXQgKHRoZSBjbGllbnQgbmV2ZXIgdGhyb3dzKS4gYGdldENsaWVudGAgaXMgYSBnZXR0ZXJcbiAqIHNvIHRoZSBjbGllbnQgc3RheXMgbGF6aWx5IGNvbnN0cnVjdGVkIChzZXJ2aWNlcyBtZW1vaXplIGl0IG9uIGZpcnN0IHVzZSkuXG4gKlxuICogUGxhdGZvcm0gaXMgaW50ZW50aW9uYWxseSBOT1QgYSBjYWxsZXIg4oCUIGl0IGlzIHRoZSBhdWRpdCBhdXRob3JpdHkgYW5kIHdyaXRlc1xuICogYGF1dGh6LmRlbmllZGAgc3RyYWlnaHQgdG8gaXRzIGxvY2FsIHN0b3JlICh3aXRoIGBhZmZlY3RlZE9yZ0lkYCksIG5vdCB0aHJvdWdoXG4gKiBhIFJlbW90ZUF1ZGl0Q2xpZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gd2lyZUF1dGh6RGVuaWFsQXVkaXRvcihzZXJ2aWNlTmFtZTogc3RyaW5nLCBnZXRDbGllbnQ6ICgpID0+IFJlbW90ZUF1ZGl0Q2xpZW50KTogdm9pZCB7XG4gIHNldEF1dGh6RGVuaWFsQXVkaXRvcigoaW5mbzogQXV0aHpEZW5pYWxJbmZvKSA9PiBnZXRDbGllbnQoKS5yZWNvcmQoe1xuICAgIGFjdGlvbjogJ2F1dGh6LmRlbmllZCcsXG4gICAgYWN0b3JJZDogaW5mby5hY3RvcklkID8/ICdhbm9ueW1vdXMnLFxuICAgIGFjdG9yRW1haWw6IGluZm8uYWN0b3JFbWFpbCxcbiAgICBvcmdJZDogaW5mby5vcmdJZCxcbiAgICBvdXRjb21lOiAnZmFpbHVyZScsXG4gICAgZGV0YWlsczogeyBtZXRob2Q6IGluZm8ubWV0aG9kLCBwYXRoOiBpbmZvLnBhdGgsIHJlcXVpcmVkOiBpbmZvLnJlcXVpcmVkIH0sXG4gIH0sIHNlcnZpY2VOYW1lKSk7XG59XG5cbi8qKlxuICogQSBzZXJ2aWNlLXNjb3BlZCBhdWRpdCBjbGllbnQ6IGEgZHVyYWJsZS1zcG9vbC1iYWNrZWQge0BsaW5rIFJlbW90ZUF1ZGl0Q2xpZW50fVxuICogd2l0aCB0aGUgc2VydmljZSBuYW1lIHByZS1ib3VuZCBmb3IgZW1pc3Npb24uIFJlcGxhY2VzIHRoZSBwZXItc2VydmljZVxuICogYm9pbGVycGxhdGUgb2YgYGNyZWF0ZVJlbW90ZUF1ZGl0Q2xpZW50KHsgc3Bvb2w6IGNyZWF0ZUVudlJlZGlzQXVkaXRTcG9vbCgpID8/IHVuZGVmaW5lZCB9KWBcbiAqIHBsdXMgYSBoYW5kLXJvbGxlZCBgZW1pdDxTZXJ2aWNlPkF1ZGl0YCB3cmFwcGVyIHRoYXQgcmVwZWF0cyB0aGUgc2VydmljZSBuYW1lLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZpY2VBdWRpdENsaWVudCB7XG4gIC8qKiBFbWl0IGFuIGF1ZGl0IGV2ZW50IHdpdGggdGhlIHNlcnZpY2UgbmFtZSBib3VuZC4gRmlyZS1hbmQtZm9yZ2V0LiAqL1xuICBlbWl0KGV2ZW50OiBSZW1vdGVBdWRpdEV2ZW50KTogdm9pZDtcbiAgLyoqIFRoZSB1bmRlcmx5aW5nIHJlbW90ZSBjbGllbnQg4oCUIGZvciBgd2lyZUF1dGh6RGVuaWFsQXVkaXRvcmAgKyBgY2xvc2UoKWAuICovXG4gIHJlYWRvbmx5IGNsaWVudDogUmVtb3RlQXVkaXRDbGllbnQ7XG59XG5cbi8qKlxuICogQnVpbGQgYSBzZXJ2aWNlJ3MgYXVkaXQgY2xpZW50OiBhIFJlbW90ZUF1ZGl0Q2xpZW50IHdpcmVkIHRvIHRoZSBkdXJhYmxlIFJlZGlzXG4gKiBzcG9vbCAoZnJvbSBhbWJpZW50IGVudjsgbnVsbCDihpIgbm8gc3Bvb2wpIHdpdGggYHNlcnZpY2VOYW1lYCBib3VuZC4gQ29uc3RydWN0XG4gKiBPTkNFIHBlciBwcm9jZXNzIOKAlCBtZW1vaXplIGJlaGluZCBhIGxhenkgYGdldEF1ZGl0Q2xpZW50KClgIGluIHRoZSBzZXJ2aWNlJ3NcbiAqIGBzZXJ2aWNlcy9hdWRpdC50c2AuIFBhc3MgYGNvbmZpZy5zcG9vbGAgdG8gb3ZlcnJpZGUgdGhlIGVudi1kZXJpdmVkIHNwb29sXG4gKiAoZS5nLiByZXVzZSBhIHNlcnZpY2UncyBleGlzdGluZyBpb3JlZGlzIGNvbm5lY3Rpb24pLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlU2VydmljZUF1ZGl0Q2xpZW50KHNlcnZpY2VOYW1lOiBzdHJpbmcsIGNvbmZpZzogUmVtb3RlQXVkaXRDbGllbnRDb25maWcgPSB7fSk6IFNlcnZpY2VBdWRpdENsaWVudCB7XG4gIGNvbnN0IHNwb29sID0gY29uZmlnLnNwb29sID8/IGNyZWF0ZUVudlJlZGlzQXVkaXRTcG9vbCgpID8/IHVuZGVmaW5lZDtcbiAgY29uc3QgY2xpZW50ID0gY3JlYXRlUmVtb3RlQXVkaXRDbGllbnQoeyAuLi5jb25maWcsIHNwb29sIH0pO1xuICByZXR1cm4ge1xuICAgIGVtaXQ6IChldmVudCkgPT4gY2xpZW50LnJlY29yZChldmVudCwgc2VydmljZU5hbWUpLFxuICAgIGNsaWVudCxcbiAgfTtcbn1cbiJdfQ==
|
|
@@ -20,6 +20,21 @@ export declare function tokenRevocationKey(userId: string): string;
|
|
|
20
20
|
* outage degrades to the pre-existing behaviour rather than locking users out.
|
|
21
21
|
*/
|
|
22
22
|
export declare function createRedisTokenRevocationStore(redis: RedisCacheClient): TokenRevocationStore;
|
|
23
|
+
/**
|
|
24
|
+
* Build a {@link TokenRevocationStore} backed by a Redis client that is lazily
|
|
25
|
+
* constructed from the standard `REDIS_URL` or `REDIS_HOST`/`REDIS_PORT` env —
|
|
26
|
+
* for a stateless service that keeps NO Redis client of its own. The client is
|
|
27
|
+
* built on first `getCurrentVersion` call and memoized; `ioredis` is loaded via
|
|
28
|
+
* a guarded dynamic require so merely importing this never breaks a build/test
|
|
29
|
+
* where Redis isn't present.
|
|
30
|
+
*
|
|
31
|
+
* FULLY FAIL-OPEN: no env configured, an ioredis load failure, a connect error,
|
|
32
|
+
* or any read failure all resolve to `null` ("no known revocation"), so a
|
|
33
|
+
* service degrades to natural token expiry rather than locking users out. A
|
|
34
|
+
* service opts in with a single boot line:
|
|
35
|
+
* `setTokenRevocationStore(createEnvRedisTokenRevocationStore());`
|
|
36
|
+
*/
|
|
37
|
+
export declare function createEnvRedisTokenRevocationStore(): TokenRevocationStore;
|
|
23
38
|
/**
|
|
24
39
|
* Publish a user's current `tokenVersion` so the stateless services see the
|
|
25
40
|
* revocation immediately (platform side). Best-effort — never throws; a failure
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Copyright 2026 Pipeline Builder Contributors
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { createRequire } from 'module';
|
|
3
4
|
import { createLogger } from '../utils/logger.js';
|
|
4
5
|
const logger = createLogger('token-revocation');
|
|
5
6
|
/**
|
|
@@ -46,6 +47,64 @@ export function createRedisTokenRevocationStore(redis) {
|
|
|
46
47
|
},
|
|
47
48
|
};
|
|
48
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Build a {@link TokenRevocationStore} backed by a Redis client that is lazily
|
|
52
|
+
* constructed from the standard `REDIS_URL` or `REDIS_HOST`/`REDIS_PORT` env —
|
|
53
|
+
* for a stateless service that keeps NO Redis client of its own. The client is
|
|
54
|
+
* built on first `getCurrentVersion` call and memoized; `ioredis` is loaded via
|
|
55
|
+
* a guarded dynamic require so merely importing this never breaks a build/test
|
|
56
|
+
* where Redis isn't present.
|
|
57
|
+
*
|
|
58
|
+
* FULLY FAIL-OPEN: no env configured, an ioredis load failure, a connect error,
|
|
59
|
+
* or any read failure all resolve to `null` ("no known revocation"), so a
|
|
60
|
+
* service degrades to natural token expiry rather than locking users out. A
|
|
61
|
+
* service opts in with a single boot line:
|
|
62
|
+
* `setTokenRevocationStore(createEnvRedisTokenRevocationStore());`
|
|
63
|
+
*/
|
|
64
|
+
export function createEnvRedisTokenRevocationStore() {
|
|
65
|
+
// undefined = not yet attempted; null = attempted and unavailable (stay off).
|
|
66
|
+
let cached;
|
|
67
|
+
function build() {
|
|
68
|
+
try {
|
|
69
|
+
const url = process.env.REDIS_URL;
|
|
70
|
+
const host = process.env.REDIS_HOST;
|
|
71
|
+
if (!url && !host)
|
|
72
|
+
return null; // Redis not configured — no-op reader.
|
|
73
|
+
// Dynamic require: ioredis is a runtime-only optional dep, never a static
|
|
74
|
+
// import, so this module loads cleanly wherever Redis isn't present.
|
|
75
|
+
const req = createRequire(import.meta.url);
|
|
76
|
+
const mod = req('ioredis');
|
|
77
|
+
const RedisCtor = (mod.Redis ?? mod.default ?? mod);
|
|
78
|
+
const opts = { maxRetriesPerRequest: 1, enableOfflineQueue: false };
|
|
79
|
+
const inst = url
|
|
80
|
+
? new RedisCtor(url, opts)
|
|
81
|
+
: new RedisCtor({ host, port: parseInt(process.env.REDIS_PORT ?? '6379', 10), ...opts });
|
|
82
|
+
// Swallow connection errors (ioredis auto-reconnects) so an unhandled
|
|
83
|
+
// 'error' can't crash the process; the reader stays fail-open meanwhile.
|
|
84
|
+
inst
|
|
85
|
+
.on('error', (e) => logger.warn('Redis revocation-reader client error', {
|
|
86
|
+
error: e instanceof Error ? e.message : String(e),
|
|
87
|
+
}));
|
|
88
|
+
logger.info('Redis token-revocation reader initialized');
|
|
89
|
+
return inst;
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
logger.warn('Redis unavailable for revocation reader; falling back to token expiry', {
|
|
93
|
+
error: err instanceof Error ? err.message : String(err),
|
|
94
|
+
});
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return {
|
|
99
|
+
async getCurrentVersion(userId) {
|
|
100
|
+
if (cached === undefined)
|
|
101
|
+
cached = build();
|
|
102
|
+
if (!cached)
|
|
103
|
+
return null;
|
|
104
|
+
return createRedisTokenRevocationStore(cached).getCurrentVersion(userId);
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
}
|
|
49
108
|
/**
|
|
50
109
|
* Publish a user's current `tokenVersion` so the stateless services see the
|
|
51
110
|
* revocation immediately (platform side). Best-effort — never throws; a failure
|
|
@@ -71,4 +130,4 @@ export async function publishTokenRevocation(redis, userId, tokenVersion, ttlSec
|
|
|
71
130
|
});
|
|
72
131
|
}
|
|
73
132
|
}
|
|
74
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4tcmV2b2NhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy90b2tlbi1yZXZvY2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFJdEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRWxELE1BQU0sTUFBTSxHQUFHLFlBQVksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0FBRWhEOzs7Ozs7R0FNRztBQUNILE1BQU0sQ0FBQyxNQUFNLDJCQUEyQixHQUFHLGFBQWEsQ0FBQztBQUV6RCx3Q0FBd0M7QUFDeEMsTUFBTSxVQUFVLGtCQUFrQixDQUFDLE1BQWM7SUFDL0MsT0FBTyxHQUFHLDJCQUEyQixHQUFHLE1BQU0sRUFBRSxDQUFDO0FBQ25ELENBQUM7QUFFRDs7Ozs7Ozs7R0FRRztBQUNILE1BQU0sVUFBVSwrQkFBK0IsQ0FBQyxLQUF1QjtJQUNyRSxPQUFPO1FBQ0wsS0FBSyxDQUFDLGlCQUFpQixDQUFDLE1BQWM7WUFDcEMsSUFBSSxDQUFDO2dCQUNILE1BQU0sR0FBRyxHQUFHLE1BQU0sS0FBSyxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO2dCQUN4RCxJQUFJLEdBQUcsS0FBSyxJQUFJLElBQUksR0FBRyxLQUFLLFNBQVMsSUFBSSxHQUFHLENBQUMsSUFBSSxFQUFFLEtBQUssRUFBRTtvQkFBRSxPQUFPLElBQUksQ0FBQztnQkFDeEUsc0VBQXNFO2dCQUN0RSx1RUFBdUU7Z0JBQ3ZFLHdFQUF3RTtnQkFDeEUsMERBQTBEO2dCQUMxRCxNQUFNLENBQUMsR0FBRyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7Z0JBQ3RCLE9BQU8sTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7WUFDeEMsQ0FBQztZQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7Z0JBQ2IsTUFBTSxDQUFDLEtBQUssQ0FBQywwQ0FBMEMsRUFBRTtvQkFDdkQsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLFlBQVksS0FBSyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDO2lCQUNoRSxDQUFDLENBQUM7Z0JBQ0gsT0FBTyxJQUFJLENBQUM7WUFDZCxDQUFDO1FBQ0gsQ0FBQztLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsc0JBQXNCLENBQzFDLEtBQXVCLEVBQ3ZCLE1BQWMsRUFDZCxZQUFvQixFQUNwQixVQUFrQjtJQUVsQixJQUFJLENBQUM7UUFDSCw4REFBOEQ7UUFDOUQsTUFBTSxLQUFLLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sQ0FBQyxZQUFZLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDL0csQ0FBQztJQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDYixNQUFNLENBQUMsSUFBSSxDQUFDLHNFQUFzRSxFQUFFO1lBQ2xGLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztTQUNoRSxDQUFDLENBQUM7SUFDTCxDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgdHlwZSB7IFJlZGlzQ2FjaGVDbGllbnQgfSBmcm9tICcuL2NhY2hlLXNlcnZpY2UuanMnO1xuaW1wb3J0IHR5cGUgeyBUb2tlblJldm9jYXRpb25TdG9yZSB9IGZyb20gJy4uL21pZGRsZXdhcmUvYXV0aC5qcyc7XG5pbXBvcnQgeyBjcmVhdGVMb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ3Rva2VuLXJldm9jYXRpb24nKTtcblxuLyoqXG4gKiBSZWRpcyBrZXkgbmFtZXNwYWNlIGZvciB0aGUgcGVyLXVzZXIgY3VycmVudCBgdG9rZW5WZXJzaW9uYC4gVGhlIHBsYXRmb3JtXG4gKiBQVUJMSVNIRVMgdG8gdGhpcyBrZXkgb24gZXZlcnkgcHJpdmlsZWdlIGNoYW5nZTsgdGhlIHN0YXRlbGVzcyBzZXJ2aWNlcyBSRUFEXG4gKiBpdCBpbiBgcmVxdWlyZUF1dGhgICh2aWEge0BsaW5rIGNyZWF0ZVJlZGlzVG9rZW5SZXZvY2F0aW9uU3RvcmV9KSB0byByZWplY3RcbiAqIHRva2VucyBtaW50ZWQgYmVmb3JlIHRoYXQgY2hhbmdlLiBQdWJsaXNoZXIgYW5kIHJlYWRlcnMgTVVTVCBzaGFyZSB0aGlzIGV4YWN0XG4gKiBwcmVmaXgg4oCUIGhlbmNlIGJvdGggaGVscGVycyBsaXZlIGhlcmUsIGluIG9uZSBwbGFjZS5cbiAqL1xuZXhwb3J0IGNvbnN0IFRPS0VOX1JFVk9DQVRJT05fS0VZX1BSRUZJWCA9ICdhdXRocmV2OnR2Oic7XG5cbi8qKiBUaGUgcmV2b2NhdGlvbiBrZXkgZm9yIGEgdXNlciBpZC4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0b2tlblJldm9jYXRpb25LZXkodXNlcklkOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYCR7VE9LRU5fUkVWT0NBVElPTl9LRVlfUFJFRklYfSR7dXNlcklkfWA7XG59XG5cbi8qKlxuICogQnVpbGQgYSB7QGxpbmsgVG9rZW5SZXZvY2F0aW9uU3RvcmV9IGJhY2tlZCBieSBhIFJlZGlzIGNsaWVudCwgZm9yIGEgc3RhdGVsZXNzXG4gKiBzZXJ2aWNlIHRvIHJlZ2lzdGVyIHZpYSBgc2V0VG9rZW5SZXZvY2F0aW9uU3RvcmVgLiBSZWFkcyB0aGUgY3VycmVudFxuICogYHRva2VuVmVyc2lvbmAgdGhlIHBsYXRmb3JtIHB1Ymxpc2hlZCBmb3IgdGhlIHVzZXIuXG4gKlxuICogRmFpbC1vcGVuIGJ5IGNvbnRyYWN0OiBhIG1pc3MsIGEgcGFyc2UgZmFpbHVyZSwgb3IgYSBSZWRpcyBlcnJvciBhbGwgeWllbGRcbiAqIGBudWxsYCAo4oCUIGByZXF1aXJlQXV0aGAgdHJlYXRzIHRoYXQgYXMgXCJubyBrbm93biByZXZvY2F0aW9uXCIpLCBzbyBhIFJlZGlzXG4gKiBvdXRhZ2UgZGVncmFkZXMgdG8gdGhlIHByZS1leGlzdGluZyBiZWhhdmlvdXIgcmF0aGVyIHRoYW4gbG9ja2luZyB1c2VycyBvdXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVSZWRpc1Rva2VuUmV2b2NhdGlvblN0b3JlKHJlZGlzOiBSZWRpc0NhY2hlQ2xpZW50KTogVG9rZW5SZXZvY2F0aW9uU3RvcmUge1xuICByZXR1cm4ge1xuICAgIGFzeW5jIGdldEN1cnJlbnRWZXJzaW9uKHVzZXJJZDogc3RyaW5nKTogUHJvbWlzZTxudW1iZXIgfCBudWxsPiB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByYXcgPSBhd2FpdCByZWRpcy5nZXQodG9rZW5SZXZvY2F0aW9uS2V5KHVzZXJJZCkpO1xuICAgICAgICBpZiAocmF3ID09PSBudWxsIHx8IHJhdyA9PT0gdW5kZWZpbmVkIHx8IHJhdy50cmltKCkgPT09ICcnKSByZXR1cm4gbnVsbDtcbiAgICAgICAgLy8gU3RyaWN0IGludGVnZXIgcGFyc2U6IGBOdW1iZXJgICh1bmxpa2UgYHBhcnNlSW50YCkgcmVqZWN0cyB0cmFpbGluZ1xuICAgICAgICAvLyBnYXJiYWdlIChcIjVhYmNcIiDihpIgTmFOKSwgc28gYSBjb3JydXB0ZWQgZW50cnkgZmFpbHMgb3BlbiAobnVsbCDihpIgXCJub3RcbiAgICAgICAgLy8gcmV2b2tlZFwiKSByYXRoZXIgdGhhbiBiZWluZyByZWFkIGFzIGEgYm9ndXMgdmVyc2lvbi4gVGhlIGVtcHR5LXN0cmluZ1xuICAgICAgICAvLyBndWFyZCBhYm92ZSBtYXR0ZXJzIGJlY2F1c2UgYE51bWJlcignJylgIGlzIDAsIG5vdCBOYU4uXG4gICAgICAgIGNvbnN0IG4gPSBOdW1iZXIocmF3KTtcbiAgICAgICAgcmV0dXJuIE51bWJlci5pc0ludGVnZXIobikgPyBuIDogbnVsbDtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBsb2dnZXIuZGVidWcoJ1Rva2VuLXJldm9jYXRpb24gcmVhZCBmYWlsZWQgKGZhaWwtb3BlbiknLCB7XG4gICAgICAgICAgdXNlcklkLCBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBQdWJsaXNoIGEgdXNlcidzIGN1cnJlbnQgYHRva2VuVmVyc2lvbmAgc28gdGhlIHN0YXRlbGVzcyBzZXJ2aWNlcyBzZWUgdGhlXG4gKiByZXZvY2F0aW9uIGltbWVkaWF0ZWx5IChwbGF0Zm9ybSBzaWRlKS4gQmVzdC1lZmZvcnQg4oCUIG5ldmVyIHRocm93czsgYSBmYWlsdXJlXG4gKiBqdXN0IG1lYW5zIHRoZSBzZXJ2aWNlcyBmYWxsIGJhY2sgdG8gbmF0dXJhbCB0b2tlbiBleHBpcnkgZm9yIHRoaXMgY2hhbmdlLlxuICpcbiAqIFRoZSBrZXkgaXMgd3JpdHRlbiB3aXRoIGEgVFRMIGVxdWFsIHRvIHRoZSBhY2Nlc3MtdG9rZW4gbGlmZXRpbWU6IGFueSB0b2tlblxuICogdGhhdCBjb3VsZCBzdGlsbCBjYXJyeSBhbiBvbGRlciB2ZXJzaW9uIGhhcyBleHBpcmVkIGJ5IHRoZSB0aW1lIHRoZSBlbnRyeVxuICogbGFwc2VzLCBzbyBhbiBleHBpcmVkIGVudHJ5IGNhbiBuZXZlciBjYXVzZSBhIGZhbHNlIFwicmV2b2tlZFwiIG5vciBhIG1pc3NlZCBvbmUuXG4gKlxuICogQHBhcmFtIHJlZGlzIC0gdGhlIHBsYXRmb3JtJ3MgUmVkaXMgY2xpZW50XG4gKiBAcGFyYW0gdXNlcklkIC0gdGhlIHVzZXIgd2hvc2Ugc2Vzc2lvbnMgY2hhbmdlZFxuICogQHBhcmFtIHRva2VuVmVyc2lvbiAtIHRoZSB1c2VyJ3MgTkVXIChwb3N0LWluY3JlbWVudCkgdG9rZW5WZXJzaW9uXG4gKiBAcGFyYW0gdHRsU2Vjb25kcyAtIGFjY2Vzcy10b2tlbiBsaWZldGltZSBpbiBzZWNvbmRzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwdWJsaXNoVG9rZW5SZXZvY2F0aW9uKFxuICByZWRpczogUmVkaXNDYWNoZUNsaWVudCxcbiAgdXNlcklkOiBzdHJpbmcsXG4gIHRva2VuVmVyc2lvbjogbnVtYmVyLFxuICB0dGxTZWNvbmRzOiBudW1iZXIsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgdHJ5IHtcbiAgICAvLyBpb3JlZGlzLXN0eWxlIHZhcmlhZGljIFNFVCB3aXRoIGV4cGlyeTogU0VUIGtleSB2YWwgRVggdHRsLlxuICAgIGF3YWl0IHJlZGlzLnNldCh0b2tlblJldm9jYXRpb25LZXkodXNlcklkKSwgU3RyaW5nKHRva2VuVmVyc2lvbiksICdFWCcsIE1hdGgubWF4KDEsIE1hdGguZmxvb3IodHRsU2Vjb25kcykpKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgbG9nZ2VyLndhcm4oJ1Rva2VuLXJldm9jYXRpb24gcHVibGlzaCBmYWlsZWQgKHNlcnZpY2VzIGZhbGwgYmFjayB0byB0b2tlbiBleHBpcnkpJywge1xuICAgICAgdXNlcklkLCBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgIH0pO1xuICB9XG59XG4iXX0=
|
|
133
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidG9rZW4tcmV2b2NhdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy90b2tlbi1yZXZvY2F0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUd2QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFbEQsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLGtCQUFrQixDQUFDLENBQUM7QUFFaEQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxDQUFDLE1BQU0sMkJBQTJCLEdBQUcsYUFBYSxDQUFDO0FBRXpELHdDQUF3QztBQUN4QyxNQUFNLFVBQVUsa0JBQWtCLENBQUMsTUFBYztJQUMvQyxPQUFPLEdBQUcsMkJBQTJCLEdBQUcsTUFBTSxFQUFFLENBQUM7QUFDbkQsQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxVQUFVLCtCQUErQixDQUFDLEtBQXVCO0lBQ3JFLE9BQU87UUFDTCxLQUFLLENBQUMsaUJBQWlCLENBQUMsTUFBYztZQUNwQyxJQUFJLENBQUM7Z0JBQ0gsTUFBTSxHQUFHLEdBQUcsTUFBTSxLQUFLLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7Z0JBQ3hELElBQUksR0FBRyxLQUFLLElBQUksSUFBSSxHQUFHLEtBQUssU0FBUyxJQUFJLEdBQUcsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFO29CQUFFLE9BQU8sSUFBSSxDQUFDO2dCQUN4RSxzRUFBc0U7Z0JBQ3RFLHVFQUF1RTtnQkFDdkUsd0VBQXdFO2dCQUN4RSwwREFBMEQ7Z0JBQzFELE1BQU0sQ0FBQyxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDdEIsT0FBTyxNQUFNLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxD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LENBQUMsTUFBTSxDQUFDLENBQUM7UUFDM0UsQ0FBQztLQUNGLENBQUM7QUFDSixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsc0JBQXNCLENBQzFDLEtBQXVCLEVBQ3ZCLE1BQWMsRUFDZCxZQUFvQixFQUNwQixVQUFrQjtJQUVsQixJQUFJLENBQUM7UUFDSCw4REFBOEQ7UUFDOUQsTUFBTSxLQUFLLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sQ0FBQyxZQUFZLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDL0csQ0FBQztJQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDYixNQUFNLENBQUMsSUFBSSxDQUFDLHNFQUFzRSxFQUFFO1lBQ2xGLE1BQU0sRUFBRSxLQUFLLEVBQUUsR0FBRyxZQUFZLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQztTQUNoRSxDQUFDLENBQUM7SUFDTCxDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBjcmVhdGVSZXF1aXJlIH0gZnJvbSAnbW9kdWxlJztcbmltcG9ydCB0eXBlIHsgUmVkaXNDYWNoZUNsaWVudCB9IGZyb20gJy4vY2FjaGUtc2VydmljZS5qcyc7XG5pbXBvcnQgdHlwZSB7IFRva2VuUmV2b2NhdGlvblN0b3JlIH0gZnJvbSAnLi4vbWlkZGxld2FyZS9hdXRoLmpzJztcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gJy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5cbmNvbnN0IGxvZ2dlciA9IGNyZWF0ZUxvZ2dlcigndG9rZW4tcmV2b2NhdGlvbicpO1xuXG4vKipcbiAqIFJlZGlzIGtleSBuYW1lc3BhY2UgZm9yIHRoZSBwZXItdXNlciBjdXJyZW50IGB0b2tlblZlcnNpb25gLiBUaGUgcGxhdGZvcm1cbiAqIFBVQkxJU0hFUyB0byB0aGlzIGtleSBvbiBldmVyeSBwcml2aWxlZ2UgY2hhbmdlOyB0aGUgc3RhdGVsZXNzIHNlcnZpY2VzIFJFQURcbiAqIGl0IGluIGByZXF1aXJlQXV0aGAgKHZpYSB7QGxpbmsgY3JlYXRlUmVkaXNUb2tlblJldm9jYXRpb25TdG9yZX0pIHRvIHJlamVjdFxuICogdG9rZW5zIG1pbnRlZCBiZWZvcmUgdGhhdCBjaGFuZ2UuIFB1Ymxpc2hlciBhbmQgcmVhZGVycyBNVVNUIHNoYXJlIHRoaXMgZXhhY3RcbiAqIHByZWZpeCDigJQgaGVuY2UgYm90aCBoZWxwZXJzIGxpdmUgaGVyZSwgaW4gb25lIHBsYWNlLlxuICovXG5leHBvcnQgY29uc3QgVE9LRU5fUkVWT0NBVElPTl9LRVlfUFJFRklYID0gJ2F1dGhyZXY6dHY6JztcblxuLyoqIFRoZSByZXZvY2F0aW9uIGtleSBmb3IgYSB1c2VyIGlkLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRva2VuUmV2b2NhdGlvbktleSh1c2VySWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtUT0tFTl9SRVZPQ0FUSU9OX0tFWV9QUkVGSVh9JHt1c2VySWR9YDtcbn1cblxuLyoqXG4gKiBCdWlsZCBhIHtAbGluayBUb2tlblJldm9jYXRpb25TdG9yZX0gYmFja2VkIGJ5IGEgUmVkaXMgY2xpZW50LCBmb3IgYSBzdGF0ZWxlc3NcbiAqIHNlcnZpY2UgdG8gcmVnaXN0ZXIgdmlhIGBzZXRUb2tlblJldm9jYXRpb25TdG9yZWAuIFJlYWRzIHRoZSBjdXJyZW50XG4gKiBgdG9rZW5WZXJzaW9uYCB0aGUgcGxhdGZvcm0gcHVibGlzaGVkIGZvciB0aGUgdXNlci5cbiAqXG4gKiBGYWlsLW9wZW4gYnkgY29udHJhY3Q6IGEgbWlzcywgYSBwYXJzZSBmYWlsdXJlLCBvciBhIFJlZGlzIGVycm9yIGFsbCB5aWVsZFxuICogYG51bGxgICjigJQgYHJlcXVpcmVBdXRoYCB0cmVhdHMgdGhhdCBhcyBcIm5vIGtub3duIHJldm9jYXRpb25cIiksIHNvIGEgUmVkaXNcbiAqIG91dGFnZSBkZWdyYWRlcyB0byB0aGUgcHJlLWV4aXN0aW5nIGJlaGF2aW91ciByYXRoZXIgdGhhbiBsb2NraW5nIHVzZXJzIG91dC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZVJlZGlzVG9rZW5SZXZvY2F0aW9uU3RvcmUocmVkaXM6IFJlZGlzQ2FjaGVDbGllbnQpOiBUb2tlblJldm9jYXRpb25TdG9yZSB7XG4gIHJldHVybiB7XG4gICAgYXN5bmMgZ2V0Q3VycmVudFZlcnNpb24odXNlcklkOiBzdHJpbmcpOiBQcm9taXNlPG51bWJlciB8IG51bGw+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJhdyA9IGF3YWl0IHJlZGlzLmdldCh0b2tlblJldm9jYXRpb25LZXkodXNlcklkKSk7XG4gICAgICAgIGlmIChyYXcgPT09IG51bGwgfHwgcmF3ID09PSB1bmRlZmluZWQgfHwgcmF3LnRyaW0oKSA9PT0gJycpIHJldHVybiBudWxsO1xuICAgICAgICAvLyBTdHJpY3QgaW50ZWdlciBwYXJzZTogYE51bWJlcmAgKHVubGlrZSBgcGFyc2VJbnRgKSByZWplY3RzIHRyYWlsaW5nXG4gICAgICAgIC8vIGdhcmJhZ2UgKFwiNWFiY1wiIOKGkiBOYU4pLCBzbyBhIGNvcnJ1cHRlZCBlbnRyeSBmYWlscyBvcGVuIChudWxsIOKGkiBcIm5vdFxuICAgICAgICAvLyByZXZva2VkXCIpIHJhdGhlciB0aGFuIGJlaW5nIHJlYWQgYXMgYSBib2d1cyB2ZXJzaW9uLiBUaGUgZW1wdHktc3RyaW5nXG4gICAgICAgIC8vIGd1YXJkIGFib3ZlIG1hdHRlcnMgYmVjYXVzZSBgTnVtYmVyKCcnKWAgaXMgMCwgbm90IE5hTi5cbiAgICAgICAgY29uc3QgbiA9IE51bWJlcihyYXcpO1xuICAgICAgICByZXR1cm4gTnVtYmVyLmlzSW50ZWdlcihuKSA/IG4gOiBudWxsO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGxvZ2dlci5kZWJ1ZygnVG9rZW4tcmV2b2NhdGlvbiByZWFkIGZhaWxlZCAoZmFpbC1vcGVuKScsIHtcbiAgICAgICAgICB1c2VySWQsIGVycm9yOiBlcnIgaW5zdGFuY2VvZiBFcnJvciA/IGVyci5tZXNzYWdlIDogU3RyaW5nKGVyciksXG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgIH1cbiAgICB9LFxuICB9O1xufVxuXG4vKipcbiAqIEJ1aWxkIGEge0BsaW5rIFRva2VuUmV2b2NhdGlvblN0b3JlfSBiYWNrZWQgYnkgYSBSZWRpcyBjbGllbnQgdGhhdCBpcyBsYXppbHlcbiAqIGNvbnN0cnVjdGVkIGZyb20gdGhlIHN0YW5kYXJkIGBSRURJU19VUkxgIG9yIGBSRURJU19IT1NUYC9gUkVESVNfUE9SVGAgZW52IOKAlFxuICogZm9yIGEgc3RhdGVsZXNzIHNlcnZpY2UgdGhhdCBrZWVwcyBOTyBSZWRpcyBjbGllbnQgb2YgaXRzIG93bi4gVGhlIGNsaWVudCBpc1xuICogYnVpbHQgb24gZmlyc3QgYGdldEN1cnJlbnRWZXJzaW9uYCBjYWxsIGFuZCBtZW1vaXplZDsgYGlvcmVkaXNgIGlzIGxvYWRlZCB2aWFcbiAqIGEgZ3VhcmRlZCBkeW5hbWljIHJlcXVpcmUgc28gbWVyZWx5IGltcG9ydGluZyB0aGlzIG5ldmVyIGJyZWFrcyBhIGJ1aWxkL3Rlc3RcbiAqIHdoZXJlIFJlZGlzIGlzbid0IHByZXNlbnQuXG4gKlxuICogRlVMTFkgRkFJTC1PUEVOOiBubyBlbnYgY29uZmlndXJlZCwgYW4gaW9yZWRpcyBsb2FkIGZhaWx1cmUsIGEgY29ubmVjdCBlcnJvcixcbiAqIG9yIGFueSByZWFkIGZhaWx1cmUgYWxsIHJlc29sdmUgdG8gYG51bGxgIChcIm5vIGtub3duIHJldm9jYXRpb25cIiksIHNvIGFcbiAqIHNlcnZpY2UgZGVncmFkZXMgdG8gbmF0dXJhbCB0b2tlbiBleHBpcnkgcmF0aGVyIHRoYW4gbG9ja2luZyB1c2VycyBvdXQuIEFcbiAqIHNlcnZpY2Ugb3B0cyBpbiB3aXRoIGEgc2luZ2xlIGJvb3QgbGluZTpcbiAqICAgYHNldFRva2VuUmV2b2NhdGlvblN0b3JlKGNyZWF0ZUVudlJlZGlzVG9rZW5SZXZvY2F0aW9uU3RvcmUoKSk7YFxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlRW52UmVkaXNUb2tlblJldm9jYXRpb25TdG9yZSgpOiBUb2tlblJldm9jYXRpb25TdG9yZSB7XG4gIC8vIHVuZGVmaW5lZCA9IG5vdCB5ZXQgYXR0ZW1wdGVkOyBudWxsID0gYXR0ZW1wdGVkIGFuZCB1bmF2YWlsYWJsZSAoc3RheSBvZmYpLlxuICBsZXQgY2FjaGVkOiBSZWRpc0NhY2hlQ2xpZW50IHwgbnVsbCB8IHVuZGVmaW5lZDtcblxuICBmdW5jdGlvbiBidWlsZCgpOiBSZWRpc0NhY2hlQ2xpZW50IHwgbnVsbCB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHVybCA9IHByb2Nlc3MuZW52LlJFRElTX1VSTDtcbiAgICAgIGNvbnN0IGhvc3QgPSBwcm9jZXNzLmVudi5SRURJU19IT1NUO1xuICAgICAgaWYgKCF1cmwgJiYgIWhvc3QpIHJldHVybiBudWxsOyAvLyBSZWRpcyBub3QgY29uZmlndXJlZCDigJQgbm8tb3AgcmVhZGVyLlxuICAgICAgLy8gRHluYW1pYyByZXF1aXJlOiBpb3JlZGlzIGlzIGEgcnVudGltZS1vbmx5IG9wdGlvbmFsIGRlcCwgbmV2ZXIgYSBzdGF0aWNcbiAgICAgIC8vIGltcG9ydCwgc28gdGhpcyBtb2R1bGUgbG9hZHMgY2xlYW5seSB3aGVyZXZlciBSZWRpcyBpc24ndCBwcmVzZW50LlxuICAgICAgY29uc3QgcmVxID0gY3JlYXRlUmVxdWlyZShpbXBvcnQubWV0YS51cmwpO1xuICAgICAgY29uc3QgbW9kID0gcmVxKCdpb3JlZGlzJykgYXMge1xuICAgICAgICBSZWRpcz86IG5ldyAoLi4uYXJnczogdW5rbm93bltdKSA9PiB1bmtub3duO1xuICAgICAgICBkZWZhdWx0PzogbmV3ICguLi5hcmdzOiB1bmtub3duW10pID0+IHVua25vd247XG4gICAgICB9O1xuICAgICAgY29uc3QgUmVkaXNDdG9yID0gKG1vZC5SZWRpcyA/PyBtb2QuZGVmYXVsdCA/PyBtb2QpIGFzIG5ldyAoLi4uYXJnczogdW5rbm93bltdKSA9PiBSZWRpc0NhY2hlQ2xpZW50O1xuICAgICAgY29uc3Qgb3B0cyA9IHsgbWF4UmV0cmllc1BlclJlcXVlc3Q6IDEsIGVuYWJsZU9mZmxpbmVRdWV1ZTogZmFsc2UgfTtcbiAgICAgIGNvbnN0IGluc3QgPSB1cmxcbiAgICAgICAgPyBuZXcgUmVkaXNDdG9yKHVybCwgb3B0cylcbiAgICAgICAgOiBuZXcgUmVkaXNDdG9yKHsgaG9zdCwgcG9ydDogcGFyc2VJbnQocHJvY2Vzcy5lbnYuUkVESVNfUE9SVCA/PyAnNjM3OScsIDEwKSwgLi4ub3B0cyB9KTtcbiAgICAgIC8vIFN3YWxsb3cgY29ubmVjdGlvbiBlcnJvcnMgKGlvcmVkaXMgYXV0by1yZWNvbm5lY3RzKSBzbyBhbiB1bmhhbmRsZWRcbiAgICAgIC8vICdlcnJvcicgY2FuJ3QgY3Jhc2ggdGhlIHByb2Nlc3M7IHRoZSByZWFkZXIgc3RheXMgZmFpbC1vcGVuIG1lYW53aGlsZS5cbiAgICAgIChpbnN0IGFzIHVua25vd24gYXMgeyBvbjogKGV2dDogc3RyaW5nLCBjYjogKGU6IHVua25vd24pID0+IHZvaWQpID0+IHZvaWQgfSlcbiAgICAgICAgLm9uKCdlcnJvcicsIChlKSA9PiBsb2dnZXIud2FybignUmVkaXMgcmV2b2NhdGlvbi1yZWFkZXIgY2xpZW50IGVycm9yJywge1xuICAgICAgICAgIGVycm9yOiBlIGluc3RhbmNlb2YgRXJyb3IgPyBlLm1lc3NhZ2UgOiBTdHJpbmcoZSksXG4gICAgICAgIH0pKTtcbiAgICAgIGxvZ2dlci5pbmZvKCdSZWRpcyB0b2tlbi1yZXZvY2F0aW9uIHJlYWRlciBpbml0aWFsaXplZCcpO1xuICAgICAgcmV0dXJuIGluc3Q7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2dnZXIud2FybignUmVkaXMgdW5hdmFpbGFibGUgZm9yIHJldm9jYXRpb24gcmVhZGVyOyBmYWxsaW5nIGJhY2sgdG8gdG9rZW4gZXhwaXJ5Jywge1xuICAgICAgICBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgICAgfSk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGFzeW5jIGdldEN1cnJlbnRWZXJzaW9uKHVzZXJJZDogc3RyaW5nKTogUHJvbWlzZTxudW1iZXIgfCBudWxsPiB7XG4gICAgICBpZiAoY2FjaGVkID09PSB1bmRlZmluZWQpIGNhY2hlZCA9IGJ1aWxkKCk7XG4gICAgICBpZiAoIWNhY2hlZCkgcmV0dXJuIG51bGw7XG4gICAgICByZXR1cm4gY3JlYXRlUmVkaXNUb2tlblJldm9jYXRpb25TdG9yZShjYWNoZWQpLmdldEN1cnJlbnRWZXJzaW9uKHVzZXJJZCk7XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqXG4gKiBQdWJsaXNoIGEgdXNlcidzIGN1cnJlbnQgYHRva2VuVmVyc2lvbmAgc28gdGhlIHN0YXRlbGVzcyBzZXJ2aWNlcyBzZWUgdGhlXG4gKiByZXZvY2F0aW9uIGltbWVkaWF0ZWx5IChwbGF0Zm9ybSBzaWRlKS4gQmVzdC1lZmZvcnQg4oCUIG5ldmVyIHRocm93czsgYSBmYWlsdXJlXG4gKiBqdXN0IG1lYW5zIHRoZSBzZXJ2aWNlcyBmYWxsIGJhY2sgdG8gbmF0dXJhbCB0b2tlbiBleHBpcnkgZm9yIHRoaXMgY2hhbmdlLlxuICpcbiAqIFRoZSBrZXkgaXMgd3JpdHRlbiB3aXRoIGEgVFRMIGVxdWFsIHRvIHRoZSBhY2Nlc3MtdG9rZW4gbGlmZXRpbWU6IGFueSB0b2tlblxuICogdGhhdCBjb3VsZCBzdGlsbCBjYXJyeSBhbiBvbGRlciB2ZXJzaW9uIGhhcyBleHBpcmVkIGJ5IHRoZSB0aW1lIHRoZSBlbnRyeVxuICogbGFwc2VzLCBzbyBhbiBleHBpcmVkIGVudHJ5IGNhbiBuZXZlciBjYXVzZSBhIGZhbHNlIFwicmV2b2tlZFwiIG5vciBhIG1pc3NlZCBvbmUuXG4gKlxuICogQHBhcmFtIHJlZGlzIC0gdGhlIHBsYXRmb3JtJ3MgUmVkaXMgY2xpZW50XG4gKiBAcGFyYW0gdXNlcklkIC0gdGhlIHVzZXIgd2hvc2Ugc2Vzc2lvbnMgY2hhbmdlZFxuICogQHBhcmFtIHRva2VuVmVyc2lvbiAtIHRoZSB1c2VyJ3MgTkVXIChwb3N0LWluY3JlbWVudCkgdG9rZW5WZXJzaW9uXG4gKiBAcGFyYW0gdHRsU2Vjb25kcyAtIGFjY2Vzcy10b2tlbiBsaWZldGltZSBpbiBzZWNvbmRzXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwdWJsaXNoVG9rZW5SZXZvY2F0aW9uKFxuICByZWRpczogUmVkaXNDYWNoZUNsaWVudCxcbiAgdXNlcklkOiBzdHJpbmcsXG4gIHRva2VuVmVyc2lvbjogbnVtYmVyLFxuICB0dGxTZWNvbmRzOiBudW1iZXIsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgdHJ5IHtcbiAgICAvLyBpb3JlZGlzLXN0eWxlIHZhcmlhZGljIFNFVCB3aXRoIGV4cGlyeTogU0VUIGtleSB2YWwgRVggdHRsLlxuICAgIGF3YWl0IHJlZGlzLnNldCh0b2tlblJldm9jYXRpb25LZXkodXNlcklkKSwgU3RyaW5nKHRva2VuVmVyc2lvbiksICdFWCcsIE1hdGgubWF4KDEsIE1hdGguZmxvb3IodHRsU2Vjb25kcykpKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgbG9nZ2VyLndhcm4oJ1Rva2VuLXJldm9jYXRpb24gcHVibGlzaCBmYWlsZWQgKHNlcnZpY2VzIGZhbGwgYmFjayB0byB0b2tlbiBleHBpcnkpJywge1xuICAgICAgdXNlcklkLCBlcnJvcjogZXJyIGluc3RhbmNlb2YgRXJyb3IgPyBlcnIubWVzc2FnZSA6IFN0cmluZyhlcnIpLFxuICAgIH0pO1xuICB9XG59XG4iXX0=
|
package/lib/types/common.d.ts
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
import type { Permission } from './permissions.js';
|
|
2
|
+
import type { QuotaTier } from './quota-tiers.js';
|
|
3
|
+
/**
|
|
4
|
+
* Capability scope catalog for machine/automation tokens. A scoped token carries
|
|
5
|
+
* exactly one of these instead of role-based permissions; endpoints that accept a
|
|
6
|
+
* scoped identity check it via `hasScope`. Kept a closed union (mirroring
|
|
7
|
+
* {@link Permission}) so a typo on either the mint or the check side is a compile
|
|
8
|
+
* error. Add a value here when introducing a new scoped-token surface.
|
|
9
|
+
*/
|
|
10
|
+
export type TokenScope = 'reporting:ingest';
|
|
2
11
|
/**
|
|
3
12
|
* Quota type identifiers.
|
|
4
13
|
*
|
|
@@ -165,8 +174,8 @@ export interface JwtPayload {
|
|
|
165
174
|
* during the rollout; new users should be granted via `isSuperAdmin`.
|
|
166
175
|
*/
|
|
167
176
|
isSuperAdmin?: boolean;
|
|
168
|
-
/** Organization's quota tier
|
|
169
|
-
tier?:
|
|
177
|
+
/** Organization's quota tier. */
|
|
178
|
+
tier?: QuotaTier;
|
|
170
179
|
/** Resolved feature flags for this user/org */
|
|
171
180
|
features?: string[];
|
|
172
181
|
/**
|
|
@@ -175,7 +184,7 @@ export interface JwtPayload {
|
|
|
175
184
|
* that accept a scoped identity check this (see `hasScope`) instead of role;
|
|
176
185
|
* a scoped token is minted with minimal role for least-privilege.
|
|
177
186
|
*/
|
|
178
|
-
scope?:
|
|
187
|
+
scope?: TokenScope;
|
|
179
188
|
/** Active organization ID (from UserOrganization membership) */
|
|
180
189
|
organizationId?: string;
|
|
181
190
|
/** Active organization name */
|