@pipeline-builder/api-core 3.4.83 → 3.4.84

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.
@@ -18,7 +18,3 @@ export declare const HttpStatus: {
18
18
  readonly SERVICE_UNAVAILABLE: 503;
19
19
  readonly GATEWAY_TIMEOUT: 504;
20
20
  };
21
- /**
22
- * Type for valid HTTP status codes.
23
- */
24
- export type HttpStatusCode = (typeof HttpStatus)[keyof typeof HttpStatus];
@@ -23,4 +23,4 @@ export const HttpStatus = {
23
23
  SERVICE_UNAVAILABLE: 503,
24
24
  GATEWAY_TIMEOUT: 504,
25
25
  };
26
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC1zdGF0dXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29uc3RhbnRzL2h0dHAtc3RhdHVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEM7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxVQUFVLEdBQUc7SUFDeEIsY0FBYztJQUNkLEVBQUUsRUFBRSxHQUFHO0lBQ1AsT0FBTyxFQUFFLEdBQUc7SUFDWixRQUFRLEVBQUUsR0FBRztJQUNiLFVBQVUsRUFBRSxHQUFHO0lBRWYsb0JBQW9CO0lBQ3BCLFdBQVcsRUFBRSxHQUFHO0lBQ2hCLFlBQVksRUFBRSxHQUFHO0lBQ2pCLFNBQVMsRUFBRSxHQUFHO0lBQ2QsU0FBUyxFQUFFLEdBQUc7SUFDZCxRQUFRLEVBQUUsR0FBRztJQUNiLG9CQUFvQixFQUFFLEdBQUc7SUFDekIsaUJBQWlCLEVBQUUsR0FBRztJQUV0QixvQkFBb0I7SUFDcEIscUJBQXFCLEVBQUUsR0FBRztJQUMxQixXQUFXLEVBQUUsR0FBRztJQUNoQixtQkFBbUIsRUFBRSxHQUFHO0lBQ3hCLGVBQWUsRUFBRSxHQUFHO0NBQ1osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIEhUVFAgc3RhdHVzIGNvZGVzIG9yZ2FuaXplZCBieSBjYXRlZ29yeS5cbiAqL1xuZXhwb3J0IGNvbnN0IEh0dHBTdGF0dXMgPSB7XG4gIC8vIFN1Y2Nlc3MgMnh4XG4gIE9LOiAyMDAsXG4gIENSRUFURUQ6IDIwMSxcbiAgQUNDRVBURUQ6IDIwMixcbiAgTk9fQ09OVEVOVDogMjA0LFxuXG4gIC8vIENsaWVudCBFcnJvcnMgNHh4XG4gIEJBRF9SRVFVRVNUOiA0MDAsXG4gIFVOQVVUSE9SSVpFRDogNDAxLFxuICBGT1JCSURERU46IDQwMyxcbiAgTk9UX0ZPVU5EOiA0MDQsXG4gIENPTkZMSUNUOiA0MDksXG4gIFVOUFJPQ0VTU0FCTEVfRU5USVRZOiA0MjIsXG4gIFRPT19NQU5ZX1JFUVVFU1RTOiA0MjksXG5cbiAgLy8gU2VydmVyIEVycm9ycyA1eHhcbiAgSU5URVJOQUxfU0VSVkVSX0VSUk9SOiA1MDAsXG4gIEJBRF9HQVRFV0FZOiA1MDIsXG4gIFNFUlZJQ0VfVU5BVkFJTEFCTEU6IDUwMyxcbiAgR0FURVdBWV9USU1FT1VUOiA1MDQsXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIFR5cGUgZm9yIHZhbGlkIEhUVFAgc3RhdHVzIGNvZGVzLlxuICovXG5leHBvcnQgdHlwZSBIdHRwU3RhdHVzQ29kZSA9ICh0eXBlb2YgSHR0cFN0YXR1cylba2V5b2YgdHlwZW9mIEh0dHBTdGF0dXNdO1xuIl19
26
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC1zdGF0dXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29uc3RhbnRzL2h0dHAtc3RhdHVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEM7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxVQUFVLEdBQUc7SUFDeEIsY0FBYztJQUNkLEVBQUUsRUFBRSxHQUFHO0lBQ1AsT0FBTyxFQUFFLEdBQUc7SUFDWixRQUFRLEVBQUUsR0FBRztJQUNiLFVBQVUsRUFBRSxHQUFHO0lBRWYsb0JBQW9CO0lBQ3BCLFdBQVcsRUFBRSxHQUFHO0lBQ2hCLFlBQVksRUFBRSxHQUFHO0lBQ2pCLFNBQVMsRUFBRSxHQUFHO0lBQ2QsU0FBUyxFQUFFLEdBQUc7SUFDZCxRQUFRLEVBQUUsR0FBRztJQUNiLG9CQUFvQixFQUFFLEdBQUc7SUFDekIsaUJBQWlCLEVBQUUsR0FBRztJQUV0QixvQkFBb0I7SUFDcEIscUJBQXFCLEVBQUUsR0FBRztJQUMxQixXQUFXLEVBQUUsR0FBRztJQUNoQixtQkFBbUIsRUFBRSxHQUFHO0lBQ3hCLGVBQWUsRUFBRSxHQUFHO0NBQ1osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIEhUVFAgc3RhdHVzIGNvZGVzIG9yZ2FuaXplZCBieSBjYXRlZ29yeS5cbiAqL1xuZXhwb3J0IGNvbnN0IEh0dHBTdGF0dXMgPSB7XG4gIC8vIFN1Y2Nlc3MgMnh4XG4gIE9LOiAyMDAsXG4gIENSRUFURUQ6IDIwMSxcbiAgQUNDRVBURUQ6IDIwMixcbiAgTk9fQ09OVEVOVDogMjA0LFxuXG4gIC8vIENsaWVudCBFcnJvcnMgNHh4XG4gIEJBRF9SRVFVRVNUOiA0MDAsXG4gIFVOQVVUSE9SSVpFRDogNDAxLFxuICBGT1JCSURERU46IDQwMyxcbiAgTk9UX0ZPVU5EOiA0MDQsXG4gIENPTkZMSUNUOiA0MDksXG4gIFVOUFJPQ0VTU0FCTEVfRU5USVRZOiA0MjIsXG4gIFRPT19NQU5ZX1JFUVVFU1RTOiA0MjksXG5cbiAgLy8gU2VydmVyIEVycm9ycyA1eHhcbiAgSU5URVJOQUxfU0VSVkVSX0VSUk9SOiA1MDAsXG4gIEJBRF9HQVRFV0FZOiA1MDIsXG4gIFNFUlZJQ0VfVU5BVkFJTEFCTEU6IDUwMyxcbiAgR0FURVdBWV9USU1FT1VUOiA1MDQsXG59IGFzIGNvbnN0O1xuIl19
@@ -2,3 +2,4 @@ export * from './crud-helpers.js';
2
2
  export * from './access-helpers.js';
3
3
  export * from './sse-helpers.js';
4
4
  export * from './org-hierarchy.js';
5
+ export * from './org-hierarchy-http.js';
@@ -4,4 +4,5 @@ export * from './crud-helpers.js';
4
4
  export * from './access-helpers.js';
5
5
  export * from './sse-helpers.js';
6
6
  export * from './org-hierarchy.js';
7
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaGVscGVycy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLGNBQWMsb0JBQW9CLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuZXhwb3J0ICogZnJvbSAnLi9jcnVkLWhlbHBlcnMuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9hY2Nlc3MtaGVscGVycy5qcyc7XG5leHBvcnQgKiBmcm9tICcuL3NzZS1oZWxwZXJzLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vb3JnLWhpZXJhcmNoeS5qcyc7XG4iXX0=
7
+ export * from './org-hierarchy-http.js';
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaGVscGVycy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLGNBQWMsbUJBQW1CLENBQUM7QUFDbEMsY0FBYyxxQkFBcUIsQ0FBQztBQUNwQyxjQUFjLGtCQUFrQixDQUFDO0FBQ2pDLGNBQWMsb0JBQW9CLENBQUM7QUFDbkMsY0FBYyx5QkFBeUIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5leHBvcnQgKiBmcm9tICcuL2NydWQtaGVscGVycy5qcyc7XG5leHBvcnQgKiBmcm9tICcuL2FjY2Vzcy1oZWxwZXJzLmpzJztcbmV4cG9ydCAqIGZyb20gJy4vc3NlLWhlbHBlcnMuanMnO1xuZXhwb3J0ICogZnJvbSAnLi9vcmctaGllcmFyY2h5LmpzJztcbmV4cG9ydCAqIGZyb20gJy4vb3JnLWhpZXJhcmNoeS1odHRwLmpzJztcbiJdfQ==
@@ -0,0 +1,34 @@
1
+ import type { ServiceConfig } from '../types/common.js';
2
+ /** Options shared by the platform org-hierarchy HTTP lookups. */
3
+ export interface OrgHierarchyHttpOptions {
4
+ /** Platform service host/port (+ optional default timeout) for the client. */
5
+ service: ServiceConfig;
6
+ /** Service name minted into the service-auth JWT `sub` (e.g. 'compliance'). */
7
+ serviceName: string;
8
+ /**
9
+ * Org id embedded in the signed service token's org context. Defaults to the
10
+ * queried `orgId`; pass a system org id for a system-scoped lookup.
11
+ */
12
+ authOrgId?: string;
13
+ /** Role carried by the service token (default 'member' — least privilege). */
14
+ role?: 'owner' | 'admin' | 'member';
15
+ /** Extra request headers merged after `Authorization` (e.g. `x-org-id`). */
16
+ headers?: Record<string, string>;
17
+ /** Per-request timeout override in ms (falls back to the client default). */
18
+ timeout?: number;
19
+ }
20
+ /**
21
+ * Resolve an org's direct parent id via platform's
22
+ * `GET /organization/:id/parent`. Returns `undefined` for a root org or a
23
+ * non-2xx response. Throws on a transport failure (connection/timeout) so the
24
+ * caller can apply its own fallback.
25
+ */
26
+ export declare function fetchParentOrgId(orgId: string, opts: OrgHierarchyHttpOptions): Promise<string | undefined>;
27
+ /**
28
+ * Resolve `[self, ...descendantOrgIds]` for an org via platform's
29
+ * `GET /organization/:id/descendants`. Returns the id list only when it is
30
+ * larger than the org itself (a real subtree), else `undefined`; also
31
+ * `undefined` on a non-2xx response. Throws on a transport failure so the
32
+ * caller can apply its own fallback.
33
+ */
34
+ export declare function fetchOrgDescendants(orgId: string, opts: OrgHierarchyHttpOptions): Promise<string[] | undefined>;
@@ -0,0 +1,64 @@
1
+ // Copyright 2026 Pipeline Builder Contributors
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ /**
4
+ * Org → team hierarchy lookups over HTTP against the platform service.
5
+ *
6
+ * The Mongoose-based traversal in {@link ./org-hierarchy} is for services that
7
+ * own the org table (platform, quota). Everyone else reads the hierarchy over
8
+ * the wire from platform's authoritative `/organization/:id/*` endpoints. This
9
+ * module centralizes the transport for those reads — URL construction, the
10
+ * signed service-token auth header, and timeout+retry via the shared
11
+ * {@link InternalHttpClient} — so compliance, reporting, and any future caller
12
+ * share ONE mechanism instead of each hand-rolling a `fetch`/client with its
13
+ * own auth and failure semantics.
14
+ *
15
+ * These functions deliberately do NOT swallow transport errors: a connection
16
+ * failure/timeout propagates so each caller keeps its own fallback policy (log
17
+ * level, degrade-to-self vs. return-undefined). A non-2xx response is treated
18
+ * as "no data" (returns undefined), matching what the callers previously did.
19
+ */
20
+ import { getServiceAuthHeader } from '../middleware/auth.js';
21
+ import { InternalHttpClient } from '../services/http-client.js';
22
+ function buildRequest(orgId, suffix, opts) {
23
+ const client = new InternalHttpClient(opts.service);
24
+ const path = `/organization/${encodeURIComponent(orgId)}/${suffix}`;
25
+ const headers = {
26
+ Authorization: getServiceAuthHeader({
27
+ serviceName: opts.serviceName,
28
+ orgId: opts.authOrgId ?? orgId,
29
+ role: opts.role ?? 'member',
30
+ }),
31
+ ...opts.headers,
32
+ };
33
+ return { client, path, headers };
34
+ }
35
+ /**
36
+ * Resolve an org's direct parent id via platform's
37
+ * `GET /organization/:id/parent`. Returns `undefined` for a root org or a
38
+ * non-2xx response. Throws on a transport failure (connection/timeout) so the
39
+ * caller can apply its own fallback.
40
+ */
41
+ export async function fetchParentOrgId(orgId, opts) {
42
+ const { client, path, headers } = buildRequest(orgId, 'parent', opts);
43
+ const res = await client.get(path, { headers, timeout: opts.timeout });
44
+ if (res.statusCode >= 400)
45
+ return undefined;
46
+ return res.body?.data?.parentOrgId ?? undefined;
47
+ }
48
+ /**
49
+ * Resolve `[self, ...descendantOrgIds]` for an org via platform's
50
+ * `GET /organization/:id/descendants`. Returns the id list only when it is
51
+ * larger than the org itself (a real subtree), else `undefined`; also
52
+ * `undefined` on a non-2xx response. Throws on a transport failure so the
53
+ * caller can apply its own fallback.
54
+ */
55
+ export async function fetchOrgDescendants(orgId, opts) {
56
+ const { client, path, headers } = buildRequest(orgId, 'descendants', opts);
57
+ const res = await client.get(path, { headers, timeout: opts.timeout });
58
+ if (res.statusCode >= 400)
59
+ return undefined;
60
+ const ids = res.body?.data?.orgIds;
61
+ // Only meaningful when the subtree is larger than the org itself.
62
+ return Array.isArray(ids) && ids.length > 1 ? ids : undefined;
63
+ }
64
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JnLWhpZXJhcmNoeS1odHRwLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2hlbHBlcnMvb3JnLWhpZXJhcmNoeS1odHRwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEM7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQkc7QUFFSCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQXNCaEUsU0FBUyxZQUFZLENBQ25CLEtBQWEsRUFDYixNQUFnQyxFQUNoQyxJQUE2QjtJQUU3QixNQUFNLE1BQU0sR0FBRyxJQUFJLGtCQUFrQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNwRCxNQUFNLElBQUksR0FBRyxpQkFBaUIsa0JBQWtCLENBQUMsS0FBSyxDQUFDLElBQUksTUFBTSxFQUFFLENBQUM7SUFDcEUsTUFBTSxPQUFPLEdBQTJCO1FBQ3RDLGFBQWEsRUFBRSxvQkFBb0IsQ0FBQztZQUNsQyxXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVc7WUFDN0IsS0FBSyxFQUFFLElBQUksQ0FBQyxTQUFTLElBQUksS0FBSztZQUM5QixJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksSUFBSSxRQUFRO1NBQzVCLENBQUM7UUFDRixHQUFHLElBQUksQ0FBQyxPQUFPO0tBQ2hCLENBQUM7SUFDRixPQUFPLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQztBQUNuQyxDQUFDO0FBRUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLGdCQUFnQixDQUFDLEtBQWEsRUFBRSxJQUE2QjtJQUNqRixNQUFNLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsR0FBRyxZQUFZLENBQUMsS0FBSyxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUN0RSxNQUFNLEdBQUcsR0FBRyxNQUFNLE1BQU0sQ0FBQyxHQUFHLENBQTZDLElBQUksRUFBRSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDbkgsSUFBSSxHQUFHLENBQUMsVUFBVSxJQUFJLEdBQUc7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUM1QyxPQUFPLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLFdBQVcsSUFBSSxTQUFTLENBQUM7QUFDbEQsQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsbUJBQW1CLENBQUMsS0FBYSxFQUFFLElBQTZCO0lBQ3BGLE1BQU0sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxHQUFHLFlBQVksQ0FBQyxLQUFLLEVBQUUsYUFBYSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQzNFLE1BQU0sR0FBRyxHQUFHLE1BQU0sTUFBTSxDQUFDLEdBQUcsQ0FBa0MsSUFBSSxFQUFFLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxJQUFJLENBQUMsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUN4RyxJQUFJLEdBQUcsQ0FBQyxVQUFVLElBQUksR0FBRztRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQzVDLE1BQU0sR0FBRyxHQUFHLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQztJQUNuQyxrRUFBa0U7SUFDbEUsT0FBTyxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBRSxHQUFnQixDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7QUFDOUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIE9yZyDihpIgdGVhbSBoaWVyYXJjaHkgbG9va3VwcyBvdmVyIEhUVFAgYWdhaW5zdCB0aGUgcGxhdGZvcm0gc2VydmljZS5cbiAqXG4gKiBUaGUgTW9uZ29vc2UtYmFzZWQgdHJhdmVyc2FsIGluIHtAbGluayAuL29yZy1oaWVyYXJjaHl9IGlzIGZvciBzZXJ2aWNlcyB0aGF0XG4gKiBvd24gdGhlIG9yZyB0YWJsZSAocGxhdGZvcm0sIHF1b3RhKS4gRXZlcnlvbmUgZWxzZSByZWFkcyB0aGUgaGllcmFyY2h5IG92ZXJcbiAqIHRoZSB3aXJlIGZyb20gcGxhdGZvcm0ncyBhdXRob3JpdGF0aXZlIGAvb3JnYW5pemF0aW9uLzppZC8qYCBlbmRwb2ludHMuIFRoaXNcbiAqIG1vZHVsZSBjZW50cmFsaXplcyB0aGUgdHJhbnNwb3J0IGZvciB0aG9zZSByZWFkcyDigJQgVVJMIGNvbnN0cnVjdGlvbiwgdGhlXG4gKiBzaWduZWQgc2VydmljZS10b2tlbiBhdXRoIGhlYWRlciwgYW5kIHRpbWVvdXQrcmV0cnkgdmlhIHRoZSBzaGFyZWRcbiAqIHtAbGluayBJbnRlcm5hbEh0dHBDbGllbnR9IOKAlCBzbyBjb21wbGlhbmNlLCByZXBvcnRpbmcsIGFuZCBhbnkgZnV0dXJlIGNhbGxlclxuICogc2hhcmUgT05FIG1lY2hhbmlzbSBpbnN0ZWFkIG9mIGVhY2ggaGFuZC1yb2xsaW5nIGEgYGZldGNoYC9jbGllbnQgd2l0aCBpdHNcbiAqIG93biBhdXRoIGFuZCBmYWlsdXJlIHNlbWFudGljcy5cbiAqXG4gKiBUaGVzZSBmdW5jdGlvbnMgZGVsaWJlcmF0ZWx5IGRvIE5PVCBzd2FsbG93IHRyYW5zcG9ydCBlcnJvcnM6IGEgY29ubmVjdGlvblxuICogZmFpbHVyZS90aW1lb3V0IHByb3BhZ2F0ZXMgc28gZWFjaCBjYWxsZXIga2VlcHMgaXRzIG93biBmYWxsYmFjayBwb2xpY3kgKGxvZ1xuICogbGV2ZWwsIGRlZ3JhZGUtdG8tc2VsZiB2cy4gcmV0dXJuLXVuZGVmaW5lZCkuIEEgbm9uLTJ4eCByZXNwb25zZSBpcyB0cmVhdGVkXG4gKiBhcyBcIm5vIGRhdGFcIiAocmV0dXJucyB1bmRlZmluZWQpLCBtYXRjaGluZyB3aGF0IHRoZSBjYWxsZXJzIHByZXZpb3VzbHkgZGlkLlxuICovXG5cbmltcG9ydCB7IGdldFNlcnZpY2VBdXRoSGVhZGVyIH0gZnJvbSAnLi4vbWlkZGxld2FyZS9hdXRoLmpzJztcbmltcG9ydCB7IEludGVybmFsSHR0cENsaWVudCB9IGZyb20gJy4uL3NlcnZpY2VzL2h0dHAtY2xpZW50LmpzJztcbmltcG9ydCB0eXBlIHsgU2VydmljZUNvbmZpZyB9IGZyb20gJy4uL3R5cGVzL2NvbW1vbi5qcyc7XG5cbi8qKiBPcHRpb25zIHNoYXJlZCBieSB0aGUgcGxhdGZvcm0gb3JnLWhpZXJhcmNoeSBIVFRQIGxvb2t1cHMuICovXG5leHBvcnQgaW50ZXJmYWNlIE9yZ0hpZXJhcmNoeUh0dHBPcHRpb25zIHtcbiAgLyoqIFBsYXRmb3JtIHNlcnZpY2UgaG9zdC9wb3J0ICgrIG9wdGlvbmFsIGRlZmF1bHQgdGltZW91dCkgZm9yIHRoZSBjbGllbnQuICovXG4gIHNlcnZpY2U6IFNlcnZpY2VDb25maWc7XG4gIC8qKiBTZXJ2aWNlIG5hbWUgbWludGVkIGludG8gdGhlIHNlcnZpY2UtYXV0aCBKV1QgYHN1YmAgKGUuZy4gJ2NvbXBsaWFuY2UnKS4gKi9cbiAgc2VydmljZU5hbWU6IHN0cmluZztcbiAgLyoqXG4gICAqIE9yZyBpZCBlbWJlZGRlZCBpbiB0aGUgc2lnbmVkIHNlcnZpY2UgdG9rZW4ncyBvcmcgY29udGV4dC4gRGVmYXVsdHMgdG8gdGhlXG4gICAqIHF1ZXJpZWQgYG9yZ0lkYDsgcGFzcyBhIHN5c3RlbSBvcmcgaWQgZm9yIGEgc3lzdGVtLXNjb3BlZCBsb29rdXAuXG4gICAqL1xuICBhdXRoT3JnSWQ/OiBzdHJpbmc7XG4gIC8qKiBSb2xlIGNhcnJpZWQgYnkgdGhlIHNlcnZpY2UgdG9rZW4gKGRlZmF1bHQgJ21lbWJlcicg4oCUIGxlYXN0IHByaXZpbGVnZSkuICovXG4gIHJvbGU/OiAnb3duZXInIHwgJ2FkbWluJyB8ICdtZW1iZXInO1xuICAvKiogRXh0cmEgcmVxdWVzdCBoZWFkZXJzIG1lcmdlZCBhZnRlciBgQXV0aG9yaXphdGlvbmAgKGUuZy4gYHgtb3JnLWlkYCkuICovXG4gIGhlYWRlcnM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+O1xuICAvKiogUGVyLXJlcXVlc3QgdGltZW91dCBvdmVycmlkZSBpbiBtcyAoZmFsbHMgYmFjayB0byB0aGUgY2xpZW50IGRlZmF1bHQpLiAqL1xuICB0aW1lb3V0PzogbnVtYmVyO1xufVxuXG5mdW5jdGlvbiBidWlsZFJlcXVlc3QoXG4gIG9yZ0lkOiBzdHJpbmcsXG4gIHN1ZmZpeDogJ3BhcmVudCcgfCAnZGVzY2VuZGFudHMnLFxuICBvcHRzOiBPcmdIaWVyYXJjaHlIdHRwT3B0aW9ucyxcbik6IHsgY2xpZW50OiBJbnRlcm5hbEh0dHBDbGllbnQ7IHBhdGg6IHN0cmluZzsgaGVhZGVyczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB9IHtcbiAgY29uc3QgY2xpZW50ID0gbmV3IEludGVybmFsSHR0cENsaWVudChvcHRzLnNlcnZpY2UpO1xuICBjb25zdCBwYXRoID0gYC9vcmdhbml6YXRpb24vJHtlbmNvZGVVUklDb21wb25lbnQob3JnSWQpfS8ke3N1ZmZpeH1gO1xuICBjb25zdCBoZWFkZXJzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgIEF1dGhvcml6YXRpb246IGdldFNlcnZpY2VBdXRoSGVhZGVyKHtcbiAgICAgIHNlcnZpY2VOYW1lOiBvcHRzLnNlcnZpY2VOYW1lLFxuICAgICAgb3JnSWQ6IG9wdHMuYXV0aE9yZ0lkID8/IG9yZ0lkLFxuICAgICAgcm9sZTogb3B0cy5yb2xlID8/ICdtZW1iZXInLFxuICAgIH0pLFxuICAgIC4uLm9wdHMuaGVhZGVycyxcbiAgfTtcbiAgcmV0dXJuIHsgY2xpZW50LCBwYXRoLCBoZWFkZXJzIH07XG59XG5cbi8qKlxuICogUmVzb2x2ZSBhbiBvcmcncyBkaXJlY3QgcGFyZW50IGlkIHZpYSBwbGF0Zm9ybSdzXG4gKiBgR0VUIC9vcmdhbml6YXRpb24vOmlkL3BhcmVudGAuIFJldHVybnMgYHVuZGVmaW5lZGAgZm9yIGEgcm9vdCBvcmcgb3IgYVxuICogbm9uLTJ4eCByZXNwb25zZS4gVGhyb3dzIG9uIGEgdHJhbnNwb3J0IGZhaWx1cmUgKGNvbm5lY3Rpb24vdGltZW91dCkgc28gdGhlXG4gKiBjYWxsZXIgY2FuIGFwcGx5IGl0cyBvd24gZmFsbGJhY2suXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmZXRjaFBhcmVudE9yZ0lkKG9yZ0lkOiBzdHJpbmcsIG9wdHM6IE9yZ0hpZXJhcmNoeUh0dHBPcHRpb25zKTogUHJvbWlzZTxzdHJpbmcgfCB1bmRlZmluZWQ+IHtcbiAgY29uc3QgeyBjbGllbnQsIHBhdGgsIGhlYWRlcnMgfSA9IGJ1aWxkUmVxdWVzdChvcmdJZCwgJ3BhcmVudCcsIG9wdHMpO1xuICBjb25zdCByZXMgPSBhd2FpdCBjbGllbnQuZ2V0PHsgZGF0YT86IHsgcGFyZW50T3JnSWQ/OiBzdHJpbmcgfCBudWxsIH0gfT4ocGF0aCwgeyBoZWFkZXJzLCB0aW1lb3V0OiBvcHRzLnRpbWVvdXQgfSk7XG4gIGlmIChyZXMuc3RhdHVzQ29kZSA+PSA0MDApIHJldHVybiB1bmRlZmluZWQ7XG4gIHJldHVybiByZXMuYm9keT8uZGF0YT8ucGFyZW50T3JnSWQgPz8gdW5kZWZpbmVkO1xufVxuXG4vKipcbiAqIFJlc29sdmUgYFtzZWxmLCAuLi5kZXNjZW5kYW50T3JnSWRzXWAgZm9yIGFuIG9yZyB2aWEgcGxhdGZvcm0nc1xuICogYEdFVCAvb3JnYW5pemF0aW9uLzppZC9kZXNjZW5kYW50c2AuIFJldHVybnMgdGhlIGlkIGxpc3Qgb25seSB3aGVuIGl0IGlzXG4gKiBsYXJnZXIgdGhhbiB0aGUgb3JnIGl0c2VsZiAoYSByZWFsIHN1YnRyZWUpLCBlbHNlIGB1bmRlZmluZWRgOyBhbHNvXG4gKiBgdW5kZWZpbmVkYCBvbiBhIG5vbi0yeHggcmVzcG9uc2UuIFRocm93cyBvbiBhIHRyYW5zcG9ydCBmYWlsdXJlIHNvIHRoZVxuICogY2FsbGVyIGNhbiBhcHBseSBpdHMgb3duIGZhbGxiYWNrLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZmV0Y2hPcmdEZXNjZW5kYW50cyhvcmdJZDogc3RyaW5nLCBvcHRzOiBPcmdIaWVyYXJjaHlIdHRwT3B0aW9ucyk6IFByb21pc2U8c3RyaW5nW10gfCB1bmRlZmluZWQ+IHtcbiAgY29uc3QgeyBjbGllbnQsIHBhdGgsIGhlYWRlcnMgfSA9IGJ1aWxkUmVxdWVzdChvcmdJZCwgJ2Rlc2NlbmRhbnRzJywgb3B0cyk7XG4gIGNvbnN0IHJlcyA9IGF3YWl0IGNsaWVudC5nZXQ8eyBkYXRhPzogeyBvcmdJZHM/OiB1bmtub3duIH0gfT4ocGF0aCwgeyBoZWFkZXJzLCB0aW1lb3V0OiBvcHRzLnRpbWVvdXQgfSk7XG4gIGlmIChyZXMuc3RhdHVzQ29kZSA+PSA0MDApIHJldHVybiB1bmRlZmluZWQ7XG4gIGNvbnN0IGlkcyA9IHJlcy5ib2R5Py5kYXRhPy5vcmdJZHM7XG4gIC8vIE9ubHkgbWVhbmluZ2Z1bCB3aGVuIHRoZSBzdWJ0cmVlIGlzIGxhcmdlciB0aGFuIHRoZSBvcmcgaXRzZWxmLlxuICByZXR1cm4gQXJyYXkuaXNBcnJheShpZHMpICYmIGlkcy5sZW5ndGggPiAxID8gKGlkcyBhcyBzdHJpbmdbXSkgOiB1bmRlZmluZWQ7XG59XG4iXX0=
@@ -1,4 +1,5 @@
1
1
  import type { Request, Response, NextFunction } from 'express';
2
+ import { type Permission } from '../types/permissions.js';
2
3
  export interface RequireAuthOptions {
3
4
  /**
4
5
  * Allow x-org-id/x-org-name headers to override the JWT's organization fields.
@@ -19,13 +20,34 @@ export declare function requireAuth(options?: RequireAuthOptions): (req: Request
19
20
  * Permits users whose per-org role is 'admin' or 'owner'.
20
21
  */
21
22
  export declare function requireAdmin(req: Request, res: Response, next: NextFunction): void;
22
- /** Organization ID/name that identifies the system (super-admin) tenant. */
23
+ /**
24
+ * Whether the request's user holds `permission`. Superadmins implicitly hold
25
+ * every permission. Reads the resolved `permissions` claim (set at token issue,
26
+ * or re-derived per request by the platform).
27
+ */
28
+ export declare function userHasPermission(req: Request, permission: Permission): boolean;
29
+ /**
30
+ * Requires that the user hold AT LEAST ONE of the given permissions (or be a
31
+ * superadmin). Use after requireAuth. Mirrors `requireRole`'s any-of semantics;
32
+ * pass a single permission for a specific action, or several when any one of
33
+ * them should grant access.
34
+ */
35
+ export declare function requirePermission(...permissions: Permission[]): (req: Request, res: Response, next: NextFunction) => void;
36
+ /**
37
+ * The system tenant's canonical org **id** — a fixed, well-known ObjectId (NOT
38
+ * the string 'system'). This is the single knob every service resolves the
39
+ * system tenant through; override via the `SYSTEM_ORG_ID` env for alternate
40
+ * installs. The system org's human identifier stays the slug/name 'system'
41
+ * (see {@link SYSTEM_ORG_SLUG}); only its `_id` is this ObjectId.
42
+ */
23
43
  export declare const SYSTEM_ORG_ID: string;
44
+ /** The system org's well-known slug/name (the human identifier; its `_id` is {@link SYSTEM_ORG_ID}). */
45
+ export declare const SYSTEM_ORG_SLUG = "system";
24
46
  /**
25
- * Check if an orgId or orgName matches the system org.
26
- * Use this instead of comparing directly against SYSTEM_ORG_ID,
27
- * because the JWT orgId is a database ID (e.g. MongoDB ObjectId)
28
- * while SYSTEM_ORG_ID is the well-known name "system".
47
+ * Check if an orgId or orgName/slug matches the system org. Use this instead of
48
+ * comparing directly: the id is now an ObjectId ({@link SYSTEM_ORG_ID}) while the
49
+ * name/slug is 'system' ({@link SYSTEM_ORG_SLUG}), so the two are compared against
50
+ * their respective canonical values.
29
51
  */
30
52
  export declare function isSystemOrgId(orgId?: string, orgName?: string): boolean;
31
53
  /**
@@ -88,3 +110,13 @@ export declare function signServiceToken(opts: ServiceTokenOptions): string;
88
110
  export declare function getServiceAuthHeader(opts: ServiceTokenOptions): string;
89
111
  /** True when `req.user.sub` was issued by `signServiceToken` (i.e. starts with `service:`). */
90
112
  export declare function isServicePrincipal(req: Request): boolean;
113
+ /**
114
+ * PRE-auth check: cryptographically verify the request carries a valid, signed
115
+ * SERVICE token (`sub` starts with `service:`). Unlike {@link isServicePrincipal}
116
+ * (which reads the already-populated `req.user`), this verifies the bearer token
117
+ * itself, so it is safe to call BEFORE `requireAuth` runs — e.g. the global rate
118
+ * limiter's `skip`, which must not trust the spoofable `x-internal-service`
119
+ * header. Mirrors `requireAuth`'s verification (algorithm pinning + optional
120
+ * issuer/audience) and returns `false` on any missing/invalid/non-service token.
121
+ */
122
+ export declare function verifyServicePrincipal(req: Request): boolean;
@@ -3,6 +3,7 @@
3
3
  import jwt from 'jsonwebtoken';
4
4
  import { HttpStatus } from '../constants/http-status.js';
5
5
  import { ErrorCode } from '../types/error-codes.js';
6
+ import { hasPermission } from '../types/permissions.js';
6
7
  import { getHeaderString } from '../utils/headers.js';
7
8
  import { createLogger } from '../utils/logger.js';
8
9
  import { sendError } from '../utils/response.js';
@@ -108,16 +109,51 @@ export function requireAdmin(req, res, next) {
108
109
  }
109
110
  next();
110
111
  }
111
- /** Organization ID/name that identifies the system (super-admin) tenant. */
112
- export const SYSTEM_ORG_ID = (process.env.SYSTEM_ORG_ID || 'system').toLowerCase();
113
112
  /**
114
- * Check if an orgId or orgName matches the system org.
115
- * Use this instead of comparing directly against SYSTEM_ORG_ID,
116
- * because the JWT orgId is a database ID (e.g. MongoDB ObjectId)
117
- * while SYSTEM_ORG_ID is the well-known name "system".
113
+ * Whether the request's user holds `permission`. Superadmins implicitly hold
114
+ * every permission. Reads the resolved `permissions` claim (set at token issue,
115
+ * or re-derived per request by the platform).
116
+ */
117
+ export function userHasPermission(req, permission) {
118
+ return hasPermission(req.user?.permissions, permission, req.user?.isSuperAdmin);
119
+ }
120
+ /**
121
+ * Requires that the user hold AT LEAST ONE of the given permissions (or be a
122
+ * superadmin). Use after requireAuth. Mirrors `requireRole`'s any-of semantics;
123
+ * pass a single permission for a specific action, or several when any one of
124
+ * them should grant access.
125
+ */
126
+ export function requirePermission(...permissions) {
127
+ return (req, res, next) => {
128
+ if (!req.user) {
129
+ return sendError(res, HttpStatus.UNAUTHORIZED, 'Authentication required', ErrorCode.UNAUTHORIZED);
130
+ }
131
+ // userHasPermission → hasPermission already grants superadmins every
132
+ // permission, so this single check covers both the superadmin bypass and
133
+ // the any-of membership test without re-inlining either.
134
+ if (permissions.some((p) => userHasPermission(req, p)))
135
+ return next();
136
+ return sendError(res, HttpStatus.FORBIDDEN, `Missing required permission: ${permissions.join(' or ')}`, ErrorCode.INSUFFICIENT_PERMISSIONS);
137
+ };
138
+ }
139
+ /**
140
+ * The system tenant's canonical org **id** — a fixed, well-known ObjectId (NOT
141
+ * the string 'system'). This is the single knob every service resolves the
142
+ * system tenant through; override via the `SYSTEM_ORG_ID` env for alternate
143
+ * installs. The system org's human identifier stays the slug/name 'system'
144
+ * (see {@link SYSTEM_ORG_SLUG}); only its `_id` is this ObjectId.
145
+ */
146
+ export const SYSTEM_ORG_ID = (process.env.SYSTEM_ORG_ID || '000000000000000000000001').toLowerCase();
147
+ /** The system org's well-known slug/name (the human identifier; its `_id` is {@link SYSTEM_ORG_ID}). */
148
+ export const SYSTEM_ORG_SLUG = 'system';
149
+ /**
150
+ * Check if an orgId or orgName/slug matches the system org. Use this instead of
151
+ * comparing directly: the id is now an ObjectId ({@link SYSTEM_ORG_ID}) while the
152
+ * name/slug is 'system' ({@link SYSTEM_ORG_SLUG}), so the two are compared against
153
+ * their respective canonical values.
118
154
  */
119
155
  export function isSystemOrgId(orgId, orgName) {
120
- return orgId?.toLowerCase() === SYSTEM_ORG_ID || orgName?.toLowerCase() === SYSTEM_ORG_ID;
156
+ return orgId?.toLowerCase() === SYSTEM_ORG_ID || orgName?.toLowerCase() === SYSTEM_ORG_SLUG;
121
157
  }
122
158
  /**
123
159
  * Check if the request is from a system admin.
@@ -237,4 +273,30 @@ export function getServiceAuthHeader(opts) {
237
273
  export function isServicePrincipal(req) {
238
274
  return req.user?.sub?.startsWith('service:') ?? false;
239
275
  }
240
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9taWRkbGV3YXJlL2F1dGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUd0QyxPQUFPLEdBQUcsTUFBTSxjQUFjLENBQUM7QUFDL0IsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRXpELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDdEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ2xELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUVqRCxNQUFNLE1BQU0sR0FBRyxZQUFZLENBQUMsaUJBQWlCLENBQUMsQ0FBQztBQUUvQyw0REFBNEQ7QUFDNUQsSUFBSSxVQUE4QixDQUFDO0FBQ25DLElBQUkscUJBQXFCLEdBQUcsQ0FBQyxDQUFDO0FBQzlCLE1BQU0sOEJBQThCLEdBQUcsT0FBTyxDQUFDLENBQUMsWUFBWTtBQUU1RCxTQUFTLFlBQVk7SUFDbkIsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ3ZCLElBQUksQ0FBQyxVQUFVLElBQUksR0FBRyxHQUFHLHFCQUFxQixHQUFHLDhCQUE4QixFQUFFLENBQUM7UUFDaEYsTUFBTSxNQUFNLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUM7UUFDdEMsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ1osTUFBTSxDQUFDLEtBQUssQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFDO1lBQzNELE1BQU0sSUFBSSxLQUFLLENBQUMsNkNBQTZDLENBQUMsQ0FBQztRQUNqRSxDQUFDO1FBQ0QsSUFBSSxVQUFVLElBQUksVUFBVSxLQUFLLE1BQU0sRUFBRSxDQUFDO1lBQ3hDLE1B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LG9FQUFvRTtJQUNwRSxNQUFNLFdBQVcsR0FBb0I7UUFDbkMsU0FBUyxFQUFFLElBQUksQ0FBQyxVQUFVLElBQUksaUNBQWlDO1FBQy9ELDJFQUEyRTtRQUMzRSx1REFBdUQ7UUFDdkQsU0FBUyxFQUFFLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxhQUFhLElBQUksT0FBTyxDQUFrQjtLQUNuRSxDQUFDO0lBQ0YsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVU7UUFBRSxXQUFXLENBQUMsTUFBTSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDO0lBQ3hFLElBQUksT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZO1FBQUUsV0FBVyxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLFlBQVksQ0FBQztJQUM5RSxPQUFPLEdBQUcsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLFlBQVksRUFBRSxFQUFFLFdBQVcsQ0FBQyxDQUFDO0FBQ3hELENBQUM7QUFFRCxrRkFBa0Y7QUFDbEYsTUFBTSxVQUFVLG9CQUFvQixDQUFDLElBQXlCO0lBQzVELE9BQU8sVUFBVSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO0FBQzVDLENBQUM7QUFFRCwrRkFBK0Y7QUFDL0YsTUFBTSxVQUFVLGtCQUFrQixDQUFDLEdBQVk7SUFDN0MsT0FBTyxHQUFHLENBQUMsSUFBSSxFQUFFLEdBQUcsRUFBRSxVQUFVLENBQUMsVUFBVSxDQUFDLElBQUksS0FBSyxDQUFDO0FBQ3hELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0LCBSZXNwb25zZSwgTmV4dEZ1bmN0aW9uIH0gZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQgand0IGZyb20gJ2pzb253ZWJ0b2tlbic7XG5pbXBvcnQgeyBIdHRwU3RhdHVzIH0gZnJvbSAnLi4vY29uc3RhbnRzL2h0dHAtc3RhdHVzLmpzJztcbmltcG9ydCB0eXBlIHsgSnd0UGF5bG9hZCB9IGZyb20gJy4uL3R5cGVzL2NvbW1vbi5qcyc7XG5pbXBvcnQgeyBFcnJvckNvZGUgfSBmcm9tICcuLi90eXBlcy9lcnJvci1jb2Rlcy5qcyc7XG5pbXBvcnQgeyBnZXRIZWFkZXJTdHJpbmcgfSBmcm9tICcuLi91dGlscy9oZWFkZXJzLmpzJztcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gJy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBzZW5kRXJyb3IgfSBmcm9tICcuLi91dGlscy9yZXNwb25zZS5qcyc7XG5cbmNvbnN0IGxvZ2dlciA9IGNyZWF0ZUxvZ2dlcignYXV0aC1taWRkbGV3YXJlJyk7XG5cbi8qKiBDYWNoZWQgSldUIHNlY3JldCB3aXRoIHBlcmlvZGljIHJlZnJlc2ggZnJvbSBlbnYgdmFyLiAqL1xubGV0IF9qd3RTZWNyZXQ6IHN0cmluZyB8IHVuZGVmaW5lZDtcbmxldCBfand0U2VjcmV0UmVmcmVzaGVkQXQgPSAwO1xuY29uc3QgSldUX1NFQ1JFVF9SRUZSRVNIX0lOVEVSVkFMX01TID0gMzAwXzAwMDsgLy8gNSBtaW51dGVzXG5cbmZ1bmN0aW9uIGdldEp3dFNlY3JldCgpOiBzdHJpbmcge1xuICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICBpZiAoIV9qd3RTZWNyZXQgfHwgbm93IC0gX2p3dFNlY3JldFJlZnJlc2hlZEF0ID4gSldUX1NFQ1JFVF9SRUZSRVNIX0lOVEVSVkFMX01TKSB7XG4gICAgY29uc3Qgc2VjcmV0ID0gcHJvY2Vzcy5lbnYuSldUX1NFQ1JFVDtcbiAgICBpZiAoIXNlY3JldCkge1xuICAgICAgbG9nZ2VyLmVycm9yKCdKV1RfU0VDUkVUIGVudmlyb25tZW50IHZhcmlhYmxlIGlzIG5vdCBzZXQnKTtcbiAgICAgIHRocm93IG5ldyBFcnJvcignSldUX1NFQ1JFVCBlbnZpcm9ubWVudCB2YXJpYWJsZSBpcyByZXF1aXJlZCcpO1xuICAgIH1cbiAgICBpZiAoX2p3dFNlY3JldCAmJiBfand0U2VjcmV0ICE9PSBzZWNyZXQpIHtcbiAgICAgIGxvZ2dlci5pbmZvKCdKV1Qgc2VjcmV0IHJvdGF0ZWQnKTtcbiAgICB9XG4gICAgX2p3dFNlY3JldCA9IHNlY3JldDtcbiAgICBfand0U2VjcmV0UmVmcmVzaGVkQXQgPSBub3c7XG4gIH1cbiAgcmV0dXJuIF9qd3RTZWNyZXQ7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVxdWlyZUF1dGhPcHRpb25zIHtcbiAgLyoqXG4gICAqIEFsbG93IHgtb3JnLWlkL3gtb3JnLW5hbWUgaGVhZGVycyB0byBvdmVycmlkZSB0aGUgSldUJ3Mgb3JnYW5pemF0aW9uIGZpZWxkcy5cbiAgICpcbiAgICogV2hlbiBlbmFibGVkLCB0aGUgYHgtb3JnLWlkYC9geC1vcmctbmFtZWAgaGVhZGVycyBvdmVycmlkZSB0aGUgY2FsbGVyJ3Mgb3JnXG4gICAqIOKAlCBidXQgT05MWSBmb3IgYSB2ZXJpZmllZCBTWVMtQURNSU4gKGBpc1N1cGVyQWRtaW5gIGNsYWltKS4gRm9yIGFueSBvcmRpbmFyeVxuICAgKiBhdXRoZW50aWNhdGVkIHVzZXIgdGhlIGhlYWRlcnMgYXJlIGlnbm9yZWQsIHNvIGVuYWJsaW5nIHRoaXMgY2FuIG5ldmVyIGxldCBhXG4gICAqIG5vcm1hbCB1c2VyIGltcGVyc29uYXRlIGFub3RoZXIgdGVuYW50J3Mgb3JnLiBVc2UgZm9yIGNyb3NzLW9yZyBhZG1pbiB0b29saW5nXG4gICAqIChlLmcuIGEgc3lzYWRtaW4gbWFuYWdpbmcgYSBnaXZlbiBvcmcncyBiaWxsaW5nKS4gSWYgdW5zdXJlLCBsZWF2ZSBpdCBkaXNhYmxlZC5cbiAgICovXG4gIGFsbG93T3JnSGVhZGVyT3ZlcnJpZGU/OiBib29sZWFuO1xufVxuXG4vKiogSldUIGF1dGggbWlkZGxld2FyZS4gVXNlIGRpcmVjdGx5IG9yIGNhbGwgd2l0aCBvcHRpb25zLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcXVpcmVBdXRoKFxuICByZXE6IFJlcXVlc3QsXG4gIHJlczogUmVzcG9uc2UsXG4gIG5leHQ6IE5leHRGdW5jdGlvbixcbik6IHZvaWQ7XG5leHBvcnQgZnVuY3Rpb24gcmVxdWlyZUF1dGgoXG4gIG9wdGlvbnM/OiBSZXF1aXJlQXV0aE9wdGlvbnMsXG4pOiAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pID0+IHZvaWQ7XG5leHBvcnQgZnVuY3Rpb24gcmVxdWlyZUF1dGgoXG4gIHJlcU9yT3B0aW9ucz86IFJlcXVlc3QgfCBSZXF1aXJlQXV0aE9wdGlvbnMsXG4gIHJlcz86IFJlc3BvbnNlLFxuICBuZXh0PzogTmV4dEZ1bmN0aW9uLFxuKTogdm9pZCB8ICgocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pID0+IHZvaWQpIHtcbiAgaWYgKHJlcU9yT3B0aW9ucyAmJiByZXMgJiYgbmV4dCAmJiAnaGVhZGVycycgaW4gcmVxT3JPcHRpb25zKSB7XG4gICAgcmV0dXJuIF9yZXF1aXJlQXV0aCh7fSwgcmVxT3JPcHRpb25zIGFzIFJlcXVlc3QsIHJlcywgbmV4dCk7XG4gIH1cblxuICBjb25zdCBvcHRpb25zID0gKHJlcU9yT3B0aW9ucyBhcyBSZXF1aXJlQXV0aE9wdGlvbnMpIHx8IHt9O1xuICByZXR1cm4gKHJlcTogUmVxdWVzdCwgcmVzSW5uZXI6IFJlc3BvbnNlLCBuZXh0SW5uZXI6IE5leHRGdW5jdGlvbikgPT4ge1xuICAgIF9yZXF1aXJlQXV0aChvcHRpb25zLCByZXEsIHJlc0lubmVyLCBuZXh0SW5uZXIpO1xuICB9O1xufVxuXG5mdW5jdGlvbiBfcmVxdWlyZUF1dGgoXG4gIG9wdGlvbnM6IFJlcXVpcmVBdXRoT3B0aW9ucyxcbiAgcmVxOiBSZXF1ZXN0LFxuICByZXM6IFJlc3BvbnNlLFxuICBuZXh0OiBOZXh0RnVuY3Rpb24sXG4pOiB2b2lkIHtcbiAgY29uc3QgYXV0aEhlYWRlciA9IHJlcS5oZWFkZXJzLmF1dGhvcml6YXRpb247XG5cbiAgaWYgKCFhdXRoSGVhZGVyKSB7XG4gICAgcmV0dXJuIHNlbmRFcnJvcihyZXMsIEh0dHBTdGF0dXMuVU5BVVRIT1JJWkVELCAnQXV0aG9yaXphdGlvbiBoZWFkZXIgcmVxdWlyZWQnLCBFcnJvckNvZGUuVE9LRU5fTUlTU0lORyk7XG4gIH1cblxuICBjb25zdCBwYXJ0cyA9IGF1dGhIZWFkZXIuc3BsaXQoJyAnKTtcbiAgaWYgKHBhcnRzLmxlbmd0aCAhPT0gMiB8fCBwYXJ0c1swXSAhPT0gJ0JlYXJlcicpIHtcbiAgICByZXR1cm4gc2VuZEVycm9yKHJlcywgSHR0cFN0YXR1cy5VTkFVVEhPUklaRUQsICdJbnZhbGlkIGF1dGhvcml6YXRpb24gZm9ybWF0LiBVc2U6IEJlYXJlciA8dG9rZW4+JywgRXJyb3JDb2RlLlRPS0VOX0lOVkFMSUQpO1xuICB9XG5cbiAgdHJ5IHtcbiAgICAvLyBQYXNzIHRocm91Z2ggb3B0aW9uYWwgaXNzdWVyL2F1ZGllbmNlIHZlcmlmaWNhdGlvbiB3aGVuIGVudi1jb25maWd1cmVkLlxuICAgIC8vIFdpdGhvdXQgdGhlc2UsIGEgSldUIHNpZ25lZCBieSBhbnkgc3lzdGVtIHRoYXQgaGFwcGVucyB0byBzaGFyZSB0aGVcbiAgICAvLyBzYW1lIEpXVF9TRUNSRVQgd291bGQgYmUgYWNjZXB0ZWQg4oCUIGRlZmVuY2UtaW4tZGVwdGggZm9yIHNoYXJlZC1zZWNyZXRcbiAgICAvLyBtaXNjb25maWd1cmF0aW9ucyBhY3Jvc3Mgc2VydmljZXMgLyBlbnZpcm9ubWVudHMuXG4gICAgLy8gUGluIHRoZSBhY2NlcHRlZCBhbGdvcml0aG0gdG8gdGhlIGNvbmZpZ3VyZWQgSE1BQyBhbGcgKGRlZmF1bHQgSFMyNTYpLlxuICAgIC8vIFdpdGhvdXQgYW4gYWxsb3ctbGlzdCwgYGp3dC52ZXJpZnlgIGFjY2VwdHMgYW55IGFsZ29yaXRobSB0aGUga2V5IGNhblxuICAgIC8vIHZlcmlmeSDigJQgdGhlIGNsYXNzaWMgYWxnLWNvbmZ1c2lvbiB2ZWN0b3IgKGFuZCBhIGhhcmQgZ3VhcmQgYWdhaW5zdFxuICAgIC8vIGBhbGc6bm9uZWApLiBFbnYtZHJpdmVuIHNvIGl0IHN0YXlzIGluIGxvY2tzdGVwIHdpdGggaG93IHRva2VucyBhcmVcbiAgICAvLyBzaWduZWQgKHNlZSBzaWduU2VydmljZVRva2VuICsgcGxhdGZvcm0ncyBjb25maWcuYXV0aC5qd3QuYWxnb3JpdGhtKS5cbiAgICBjb25zdCB2ZXJpZnlPcHRpb25zOiBqd3QuVmVyaWZ5T3B0aW9ucyA9IHsgYWxnb3JpdGhtczogWyhwcm9jZXNzLmVudi5KV1RfQUxHT1JJVEhNIHx8ICdIUzI1NicpIGFzIGp3dC5BbGdvcml0aG1dIH07XG4gICAgY29uc3QgZXhwZWN0ZWRJc3N1ZXIgPSBwcm9jZXNzLmVudi5KV1RfSVNTVUVSO1xuICAgIGNvbnN0IGV4cGVjdGVkQXVkaWVuY2UgPSBwcm9jZXNzLmVudi5KV1RfQVVESUVOQ0U7XG4gICAgaWYgKGV4cGVjdGVkSXNzdWVyKSB2ZXJpZnlPcHRpb25zLmlzc3VlciA9IGV4cGVjdGVkSXNzdWVyO1xuICAgIGlmIChleHBlY3RlZEF1ZGllbmNlKSB2ZXJpZnlPcHRpb25zLmF1ZGllbmNlID0gZXhwZWN0ZWRBdWRpZW5jZTtcbiAgICBjb25zdCBkZWNvZGVkID0gand0LnZlcmlmeShwYXJ0c1sxXSwgZ2V0Snd0U2VjcmV0KCksIHZlcmlmeU9wdGlvbnMpIGFzIEp3dFBheWxvYWQ7XG5cbiAgICBpZiAoZGVjb2RlZC50eXBlICE9PSAnYWNjZXNzJykge1xuICAgICAgcmV0dXJuIHNlbmRFcnJvcihyZXMsIEh0dHBTdGF0dXMuVU5BVVRIT1JJWkVELCAnT25seSBhY2Nlc3MgdG9rZW5zIGNhbiBiZSB1c2VkIGZvciBBUEkgcmVxdWVzdHMnLCBFcnJvckNvZGUuVE9LRU5fSU5WQUxJRCk7XG4gICAgfVxuXG4gICAgaWYgKCFkZWNvZGVkLnN1YiB8fCAhZGVjb2RlZC5yb2xlKSB7XG4gICAgICByZXR1cm4gc2VuZEVycm9yKHJlcywgSHR0cFN0YXR1cy5VTkFVVEhPUklaRUQsICdUb2tlbiBtaXNzaW5nIHJlcXVpcmVkIGZpZWxkcycsIEVycm9yQ29kZS5UT0tFTl9JTlZBTElEKTtcbiAgICB9XG5cbiAgICByZXEudXNlciA9IHsgLi4uZGVjb2RlZCB9O1xuXG4gICAgLy8gVGhlIHgtb3JnLWlkL3gtb3JnLW5hbWUgb3ZlcnJpZGUgbGV0cyBhIFNZUy1BRE1JTiBhY3Qgb24gYSBjaG9zZW4gb3JnXG4gICAgLy8gKGNyb3NzLW9yZyBhZG1pbiB0b29saW5nKS4gSXQgaXMgZ2F0ZWQgb24gdGhlIHZlcmlmaWVkIGBpc1N1cGVyQWRtaW5gIGNsYWltXG4gICAgLy8gaGVyZSBzbyB0aGF0IGV2ZW4gYSByb3V0ZSB3aGljaCBtaXN0YWtlbmx5IGVuYWJsZXMgYGFsbG93T3JnSGVhZGVyT3ZlcnJpZGVgXG4gICAgLy8gY2FuIE5FVkVSIGxldCBhbiBvcmRpbmFyeSBhdXRoZW50aWNhdGVkIHVzZXIgc3Bvb2YgYW5vdGhlciB0ZW5hbnQncyBvcmcgdmlhXG4gICAgLy8gdGhlIGhlYWRlciDigJQgZGVmZW5jZS1pbi1kZXB0aCBhZ2FpbnN0IHRoZSBjcm9zcy10ZW5hbnQgYnJlYWsgdGhpcyBjYXVzZWQuXG4gICAgaWYgKG9wdGlvbnMuYWxsb3dPcmdIZWFkZXJPdmVycmlkZSAmJiBkZWNvZGVkLmlzU3VwZXJBZG1pbiA9PT0gdHJ1ZSkge1xuICAgICAgY29uc3QgaGVhZGVyT3JnSWQgPSBnZXRIZWFkZXJTdHJpbmcocmVxLmhlYWRlcnNbJ3gtb3JnLWlkJ10pO1xuICAgICAgY29uc3QgaGVhZGVyT3JnTmFtZSA9IGdldEhlYWRlclN0cmluZyhyZXEuaGVhZGVyc1sneC1vcmctbmFtZSddKTtcbiAgICAgIGlmIChoZWFkZXJPcmdJZCkgcmVxLnVzZXIub3JnYW5pemF0aW9uSWQgPSBoZWFkZXJPcmdJZDtcbiAgICAgIGlmIChoZWFkZXJPcmdOYW1lKSByZXEudXNlci5vcmdhbml6YXRpb25OYW1lID0gaGVhZGVyT3JnTmFtZTtcbiAgICB9XG5cbiAgICBuZXh0KCk7XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgaWYgKGVycm9yIGluc3RhbmNlb2Ygand0LlRva2VuRXhwaXJlZEVycm9yKSB7XG4gICAgICByZXR1cm4gc2VuZEVycm9yKHJlcywgSHR0cFN0YXR1cy5VTkFVVEhPUklaRUQsICdUb2tlbiBoYXMgZXhwaXJlZCcsIEVycm9yQ29kZS5UT0tFTl9FWFBJUkVEKTtcbiAgICB9XG5cbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBqd3QuSnNvbldlYlRva2VuRXJyb3IpIHtcbiAgICAgIHJldHVybiBzZW5kRXJyb3IocmVzLCBIdHRwU3RhdHVzLlVOQVVUSE9SSVpFRCwgJ0ludmFsaWQgdG9rZW4nLCBFcnJvckNvZGUuVE9LRU5fSU5WQUxJRCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlbmRFcnJvcihyZXMsIEh0dHBTdGF0dXMuVU5BVVRIT1JJWkVELCAnQXV0aGVudGljYXRpb24gZmFpbGVkJywgRXJyb3JDb2RlLlVOQVVUSE9SSVpFRCk7XG4gIH1cbn1cblxuLyoqXG4gKiBSZXF1aXJlcyBhZG1pbiByb2xlLiBVc2UgYWZ0ZXIgcmVxdWlyZUF1dGguXG4gKiBQZXJtaXRzIHVzZXJzIHdob3NlIHBlci1vcmcgcm9sZSBpcyAnYWRtaW4nIG9yICdvd25lcicuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXF1aXJlQWRtaW4oXG4gIHJlcTogUmVxdWVzdCxcbiAgcmVzOiBSZXNwb25zZSxcbiAgbmV4dDogTmV4dEZ1bmN0aW9uLFxuKTogdm9pZCB7XG4gIGlmICghcmVxLnVzZXIpIHtcbiAgICByZXR1cm4gc2VuZEVycm9yKHJlcywgSHR0cFN0YXR1cy5VTkFVVEhPUklaRUQsICdBdXRoZW50aWNhdGlvbiByZXF1aXJlZCcsIEVycm9yQ29kZS5VTkFVVEhPUklaRUQpO1xuICB9XG5cbiAgaWYgKHJlcS51c2VyLnJvbGUgIT09ICdhZG1pbicgJiYgcmVxLnVzZXIucm9sZSAhPT0gJ293bmVyJykge1xuICAgIHJldHVybiBzZW5kRXJyb3IocmVzLCBIdHRwU3RhdHVzLkZPUkJJRERFTiwgJ0FkbWluIGFjY2VzcyByZXF1aXJlZCcsIEVycm9yQ29kZS5JTlNVRkZJQ0lFTlRfUEVSTUlTU0lPTlMpO1xuICB9XG5cbiAgbmV4dCgpO1xufVxuXG4vKiogT3JnYW5pemF0aW9uIElEL25hbWUgdGhhdCBpZGVudGlmaWVzIHRoZSBzeXN0ZW0gKHN1cGVyLWFkbWluKSB0ZW5hbnQuICovXG5leHBvcnQgY29uc3QgU1lTVEVNX09SR19JRCA9IChwcm9jZXNzLmVudi5TWVNURU1fT1JHX0lEIHx8ICdzeXN0ZW0nKS50b0xvd2VyQ2FzZSgpO1xuXG4vKipcbiAqIENoZWNrIGlmIGFuIG9yZ0lkIG9yIG9yZ05hbWUgbWF0Y2hlcyB0aGUgc3lzdGVtIG9yZy5cbiAqIFVzZSB0aGlzIGluc3RlYWQgb2YgY29tcGFyaW5nIGRpcmVjdGx5IGFnYWluc3QgU1lTVEVNX09SR19JRCxcbiAqIGJlY2F1c2UgdGhlIEpXVCBvcmdJZCBpcyBhIGRhdGFiYXNlIElEIChlLmcuIE1vbmdvREIgT2JqZWN0SWQpXG4gKiB3aGlsZSBTWVNURU1fT1JHX0lEIGlzIHRoZSB3ZWxsLWtub3duIG5hbWUgXCJzeXN0ZW1cIi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU3lzdGVtT3JnSWQob3JnSWQ/OiBzdHJpbmcsIG9yZ05hbWU/OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIG9yZ0lkPy50b0xvd2VyQ2FzZSgpID09PSBTWVNURU1fT1JHX0lEIHx8IG9yZ05hbWU/LnRvTG93ZXJDYXNlKCkgPT09IFNZU1RFTV9PUkdfSUQ7XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgdGhlIHJlcXVlc3QgaXMgZnJvbSBhIHN5c3RlbSBhZG1pbi5cbiAqXG4gKiBBdXRob3JpdHkgaXMgZ3JhbnRlZCBzb2xlbHkgYnkgdGhlIHVzZXItbGV2ZWwgYGlzU3VwZXJBZG1pbmAgZmxhZyBjYXJyaWVkXG4gKiBpbiB0aGUgSldULiBUaGUgXCJtZW1iZXJzaGlwIGluIHRoZSB3ZWxsLWtub3duICdzeXN0ZW0nIG9yZyB3aXRoIHJvbGVcbiAqIGFkbWluL293bmVyXCIgcGF0aCB3YXMgcmVtb3ZlZCDigJQgaXQgY29uZmxhdGVkIGEgUGlwZWxpbmUgQnVpbGRlciBvcGVyYXRvclxuICogd2l0aCBhIHJlYWwgY3VzdG9tZXIgdGVuYW50IGluIHRoZSBkYXRhIG1vZGVsLCBhbmQgbWVhbnQgYW55IHVuaW50ZW5kZWRcbiAqIHdyaXRlIHRoYXQgY3JlYXRlZCBhICdzeXN0ZW0nLW5hbWVkIG9yZyBjb3VsZCBxdWlldGx5IGdyYW50IGNyb3NzLW9yZ1xuICogYXV0aG9yaXR5LiBUaGUgYHN5c3RlbWAgb3JnIHN0aWxsIGV4aXN0cyBhcyBhICpjb250ZW50IGhvbGRlciogZm9yIHNoYXJlZFxuICogc2FtcGxlIGRhdGE7IGl0IGp1c3Qgbm8gbG9uZ2VyIGNvbmZlcnMgcHJpdmlsZWdlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNTeXN0ZW1BZG1pbihyZXE6IFJlcXVlc3QpOiBib29sZWFuIHtcbiAgcmV0dXJuIHJlcS51c2VyPy5pc1N1cGVyQWRtaW4gPT09IHRydWU7XG59XG5cbi8qKlxuICogV2hldGhlciB0aGUgcmVxdWVzdCdzIHRva2VuIGNhcnJpZXMgYSBzcGVjaWZpYyBjYXBhYmlsaXR5IGBzY29wZWAgKGUuZy5cbiAqIGAncmVwb3J0aW5nOmluZ2VzdCdgKS4gVXNlZCB0byBnYXRlIGVuZHBvaW50cyB0aGF0IGFjY2VwdCBhIG5hcnJvdyBtYWNoaW5lXG4gKiBpZGVudGl0eSDigJQgYSBub3JtYWwgaW50ZXJhY3RpdmUgdXNlciB0b2tlbiBoYXMgbm8gYHNjb3BlYCBhbmQgcmV0dXJucyBmYWxzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc1Njb3BlKHJlcTogUmVxdWVzdCwgc2NvcGU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gcmVxLnVzZXI/LnNjb3BlID09PSBzY29wZTtcbn1cblxuLyoqIFJlcXVpcmVzIHN5c3RlbSBhZG1pbiAoYWRtaW4gcm9sZSArIHN5c3RlbSBvcmdhbml6YXRpb24pLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcXVpcmVTeXN0ZW1BZG1pbihcbiAgcmVxOiBSZXF1ZXN0LFxuICByZXM6IFJlc3BvbnNlLFxuICBuZXh0OiBOZXh0RnVuY3Rpb24sXG4pOiB2b2lkIHtcbiAgaWYgKCFpc1N5c3RlbUFkbWluKHJlcSkpIHtcbiAgICByZXR1cm4gc2VuZEVycm9yKFxuICAgICAgcmVzLCBIdHRwU3RhdHVzLkZPUkJJRERFTixcbiAgICAgICdBY2Nlc3MgZGVuaWVkLiBPbmx5IHN5c3RlbSBhZG1pbmlzdHJhdG9ycyBjYW4gcGVyZm9ybSB0aGlzIGFjdGlvbi4nLFxuICAgICAgRXJyb3JDb2RlLklOU1VGRklDSUVOVF9QRVJNSVNTSU9OUyxcbiAgICApO1xuICB9XG4gIG5leHQoKTtcbn1cblxuLyoqXG4gKiBSZXF1aXJlIGEgc3BlY2lmaWMgZmVhdHVyZSBmbGFnLiBVc2UgYWZ0ZXIgcmVxdWlyZUF1dGguXG4gKiBDaGVja3MgdGhlIGBmZWF0dXJlc2AgYXJyYXkgaW4gdGhlIEpXVCBwYXlsb2FkIChzZXQgYXQgdG9rZW4gaXNzdWFuY2UpLlxuICogU3lzYWRtaW5zIChpc1N1cGVyQWRtaW4pIGJ5cGFzcyDigJQgdGhleSBhbHdheXMgaGF2ZSBldmVyeSBmZWF0dXJlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVxdWlyZUZlYXR1cmUoZmVhdHVyZTogc3RyaW5nKSB7XG4gIHJldHVybiAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pOiB2b2lkID0+IHtcbiAgICBpZiAoIXJlcS51c2VyKSB7XG4gICAgICByZXR1cm4gc2VuZEVycm9yKHJlcywgSHR0cFN0YXR1cy5VTkFVVEhPUklaRUQsICdBdXRoZW50aWNhdGlvbiByZXF1aXJlZCcsIEVycm9yQ29kZS5VTkFVVEhPUklaRUQpO1xuICAgIH1cblxuICAgIC8vIFN5c2FkbWlucyBnZXQgYWxsIGZlYXR1cmVzOyB0aGUgYGZlYXR1cmVzYCBhcnJheSBvbiB0aGVpciB0b2tlbiBpc1xuICAgIC8vIHBvcHVsYXRlZCB3aXRoIGV2ZXJ5IGZsYWcgYXQgaXNzdWFuY2UgdGltZSBidXQgdGhlIGJ5cGFzcyBoZXJlIGtlZXBzXG4gICAgLy8gdGhlIHJ1bGUgZXhwbGljaXQgYW5kIHN1cnZpdmVzIGEgdG9rZW4gaXNzdWVkIGJlZm9yZSBhIG5ldyBmZWF0dXJlXG4gICAgLy8gZmxhZyB3YXMgYWRkZWQuXG4gICAgaWYgKHJlcS51c2VyLmlzU3VwZXJBZG1pbiA9PT0gdHJ1ZSkgcmV0dXJuIG5leHQoKTtcblxuICAgIGlmICghcmVxLnVzZXIuZmVhdHVyZXM/LmluY2x1ZGVzKGZlYXR1cmUpKSB7XG4gICAgICByZXR1cm4gc2VuZEVycm9yKFxuICAgICAgICByZXMsIEh0dHBTdGF0dXMuRk9SQklEREVOLFxuICAgICAgICBgVGhpcyBmZWF0dXJlIHJlcXVpcmVzIGEgaGlnaGVyIHBsYW4gKCR7ZmVhdHVyZX0pYCxcbiAgICAgICAgRXJyb3JDb2RlLklOU1VGRklDSUVOVF9QRVJNSVNTSU9OUyxcbiAgICAgICk7XG4gICAgfVxuXG4gICAgbmV4dCgpO1xuICB9O1xufVxuXG4vKipcbiAqIFJlc29sdmUgdGhlIGVmZmVjdGl2ZSBhY2Nlc3MgbW9kaWZpZXIgZm9yIGFuIGVudGl0eSBiZWluZyBjcmVhdGVkL3VwZGF0ZWQuXG4gKiAncHVibGljJyBpcyBwZXJtaXR0ZWQgZm9yIGFueSBhZG1pbiBvciBvd25lciByb2xlIChzeXN0ZW0gYWRtaW5zIGNyZWF0ZVxuICogY2F0YWxvZy13aWRlIHB1YmxpYyBlbnRpdGllczsgb3JnIGFkbWlucyBjcmVhdGUgb3JnLXdpZGUgcHVibGljIGVudGl0aWVzKS5cbiAqIEV2ZXJ5b25lIGVsc2UgKG1lbWJlciByb2xlLCBubyByb2xlKSBnZXRzICdwcml2YXRlJy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVBY2Nlc3NNb2RpZmllcihyZXE6IFJlcXVlc3QsIHJlcXVlc3RlZDogc3RyaW5nIHwgdW5kZWZpbmVkKTogJ3B1YmxpYycgfCAncHJpdmF0ZScge1xuICBpZiAocmVxdWVzdGVkID09PSAncHVibGljJyAmJiAocmVxLnVzZXI/LnJvbGUgPT09ICdhZG1pbicgfHwgcmVxLnVzZXI/LnJvbGUgPT09ICdvd25lcicpKSB7XG4gICAgcmV0dXJuICdwdWJsaWMnO1xuICB9XG4gIHJldHVybiAncHJpdmF0ZSc7XG59XG5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuLy8gU2VydmljZS10by1zZXJ2aWNlIHRva2Vuc1xuLy9cbi8vIEludGVyLXNlcnZpY2UgSFRUUCBjYWxscyAoYmlsbGluZyDihpIgbWVzc2FnZSwgcGxhdGZvcm0g4oaSIGNvbXBsaWFuY2UsIGV0Yy4pXG4vLyBuZWVkIHRvIHNhdGlzZnkgdGhlIHNhbWUgYHJlcXVpcmVBdXRoYCBtaWRkbGV3YXJlIGFzIHVzZXIgcmVxdWVzdHMuXG4vLyBgc2lnblNlcnZpY2VUb2tlbmAgbWludHMgYSBzaG9ydC1saXZlZCBKV1Qgc2lnbmVkIHdpdGggdGhlIHNoYXJlZFxuLy8gSldUX1NFQ1JFVCwgaWRlbnRpZnlpbmcgdGhlIGNhbGxpbmcgc2VydmljZSB2aWEgYHN1YjogJ3NlcnZpY2U6PG5hbWU+J2AuXG4vLyBgcmVxdWlyZUF1dGhgIGFjY2VwdHMgdGhlc2UgdG9rZW5zIHRyYW5zcGFyZW50bHkg4oCUIHRoZXkgcGFzcyBgZGVjb2RlZC5zdWJgXG4vLyBhbmQgYGRlY29kZWQucm9sZWAgY2hlY2tzLCBhbmQgZG93bnN0cmVhbSBgcmVxdWlyZU9yZ2FuaXphdGlvbmAgL1xuLy8gYHJlcXVpcmVBZG1pbmAgcmVseSBvbiB0aGUgb3JnL3JvbGUgZW1iZWRkZWQgaW4gdGhlIHRva2VuLlxuLy9cbi8vIFRva2VucyBkZWZhdWx0IHRvIDUtbWludXRlIFRUTCDigJQgbG9uZyBlbm91Z2ggdG8gc3Vydml2ZSBhIGJhY2tlbmQgaG9wLFxuLy8gc2hvcnQgZW5vdWdoIHRoYXQgYSBsZWFrZWQgdG9rZW4gaXMgbG93LXZhbHVlLlxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmNvbnN0IERFRkFVTFRfU0VSVklDRV9UT0tFTl9UVExfU0VDT05EUyA9IDMwMDtcblxuZXhwb3J0IGludGVyZmFjZSBTZXJ2aWNlVG9rZW5PcHRpb25zIHtcbiAgLyoqIENhbGxpbmcgc2VydmljZSBpZGVudGlmaWVyIChlLmcuICdiaWxsaW5nJywgJ3BsYXRmb3JtJykuIEVtYmVkZGVkIGFzIGBzdWI6IHNlcnZpY2U6PG5hbWU+YC4gKi9cbiAgc2VydmljZU5hbWU6IHN0cmluZztcbiAgLyoqIEFjdGl2ZSBvcmcgY29udGV4dCBmb3IgdGhlIGNhbGwuIFVzZSB0aGUgdGFyZ2V0IHRlbmFudCdzIG9yZyBJRCwgb3IgJ3N5c3RlbScgZm9yIHN5c3RlbS13aWRlIG9wcy4gKi9cbiAgb3JnSWQ/OiBzdHJpbmc7XG4gIC8qKiBBY3RpdmUgb3JnIG5hbWUuIERlZmF1bHRzIHRvIG9yZ0lkLiAqL1xuICBvcmdOYW1lPzogc3RyaW5nO1xuICAvKiogVFRMIGluIHNlY29uZHMgKGRlZmF1bHQgMzAwKS4gKi9cbiAgdHRsU2Vjb25kcz86IG51bWJlcjtcbiAgLyoqXG4gICAqIFJvbGUgdGhlIHRva2VuIGNhcnJpZXMgKHJlcXVpcmVkIOKAlCBubyBpbXBsaWNpdCBkZWZhdWx0KS4gKipQYXNzIHRoZSBMT1dFU1RcbiAgICogcm9sZSB0aGUgY2FsbCBhY3R1YWxseSBuZWVkcyoqIChgJ21lbWJlcidgIGZvciByZWFkIC8gZGF0YS1wbGFuZSBjYWxscykgc28gYVxuICAgKiBsZWFrZWQgc2VydmljZSB0b2tlbiBjYW4ndCBwZXJmb3JtIGFkbWluIGFjdGlvbnMgaW4gdGhlIHRhcmdldCBvcmcuXG4gICAqIGBpc0FkbWluYCBpcyBkZXJpdmVkIGZyb20gdGhpcyAoYWRtaW58b3duZXIg4oaSIHRydWUpLlxuICAgKi9cbiAgcm9sZTogJ293bmVyJyB8ICdhZG1pbicgfCAnbWVtYmVyJztcbn1cblxuLyoqXG4gKiBNaW50IGEgSldUIGlkZW50aWZ5aW5nIHRoZSBjYWxsaW5nIHNlcnZpY2UuIFVzZWQgZm9yIGludGVyLXNlcnZpY2UgSFRUUCBjYWxscy5cbiAqIFRoZSB0b2tlbiBzYXRpc2ZpZXMgYHJlcXVpcmVBdXRoYCBhbmQgKHdoZW4gb3JnSWQgaXMgcHJlc2VudCkgYHJlcXVpcmVPcmdhbml6YXRpb25gLlxuICogU2NvcGUgaXQgd2l0aCBgb3B0cy5yb2xlYCDigJQgbGVhc3QgcHJpdmlsZWdlIGtlZXBzIGEgbGVha2VkIHRva2VuIGxvdy12YWx1ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNpZ25TZXJ2aWNlVG9rZW4ob3B0czogU2VydmljZVRva2VuT3B0aW9ucyk6IHN0cmluZyB7XG4gIGNvbnN0IHJvbGUgPSBvcHRzLnJvbGU7XG4gIGNvbnN0IHBheWxvYWQ6IEp3dFBheWxvYWQgPSB7XG4gICAgc3ViOiBgc2VydmljZToke29wdHMuc2VydmljZU5hbWV9YCxcbiAgICB1c2VybmFtZTogYCR7b3B0cy5zZXJ2aWNlTmFtZX0tc2VydmljZWAsXG4gICAgZW1haWw6IGAke29wdHMuc2VydmljZU5hbWV9QGludGVybmFsYCxcbiAgICByb2xlLFxuICAgIGlzQWRtaW46IHJvbGUgPT09ICdvd25lcicgfHwgcm9sZSA9PT0gJ2FkbWluJyxcbiAgICB0eXBlOiAnYWNjZXNzJyxcbiAgICBvcmdhbml6YXRpb25JZDogb3B0cy5vcmdJZCxcbiAgICBvcmdhbml6YXRpb25OYW1lOiBvcHRzLm9yZ05hbWUgPz8gb3B0cy5vcmdJZCxcbiAgfTtcbiAgLy8gTWF0Y2ggdGhlIG9wdGlvbmFsIGlzc3Vlci9hdWRpZW5jZSB0aGF0IHJlcXVpcmVBdXRoIHZlcmlmaWVzLCB3aGVuXG4gIC8vIGNvbmZpZ3VyZWQuIFdpdGhvdXQgdGhlc2UsIGEgc2VydmljZSB0b2tlbiBzaWduZWQgaGVyZSB3b3VsZCBmYWlsXG4gIC8vIHJlcXVpcmVBdXRoIGluIGEgZGVwbG95bWVudCB0aGF0IGhhcyBzZXQgSldUX0lTU1VFUi9KV1RfQVVESUVOQ0UuXG4gIGNvbnN0IHNpZ25PcHRpb25zOiBqd3QuU2lnbk9wdGlvbnMgPSB7XG4gICAgZXhwaXJlc0luOiBvcHRzLnR0bFNlY29uZHMgPz8gREVGQVVMVF9TRVJWSUNFX1RPS0VOX1RUTF9TRUNPTkRTLFxuICAgIC8vIFNpZ24gd2l0aCB0aGUgc2FtZSBjb25maWd1cmVkIGFsZyByZXF1aXJlQXV0aCBwaW5zIG9uIHZlcmlmeSwgc28gc2VydmljZVxuICAgIC8vIHRva2VucyBzdGF5IHZhbGlkIHVuZGVyIGEgbm9uLWRlZmF1bHQgSldUX0FMR09SSVRITS5cbiAgICBhbGdvcml0aG06IChwcm9jZXNzLmVudi5KV1RfQUxHT1JJVEhNIHx8ICdIUzI1NicpIGFzIGp3dC5BbGdvcml0aG0sXG4gIH07XG4gIGlmIChwcm9jZXNzLmVudi5KV1RfSVNTVUVSKSBzaWduT3B0aW9ucy5pc3N1ZXIgPSBwcm9jZXNzLmVudi5KV1RfSVNTVUVSO1xuICBpZiAocHJvY2Vzcy5lbnYuSldUX0FVRElFTkNFKSBzaWduT3B0aW9ucy5hdWRpZW5jZSA9IHByb2Nlc3MuZW52LkpXVF9BVURJRU5DRTtcbiAgcmV0dXJuIGp3dC5zaWduKHBheWxvYWQsIGdldEp3dFNlY3JldCgpLCBzaWduT3B0aW9ucyk7XG59XG5cbi8qKiBDb252ZW5pZW5jZTogcmV0dXJucyBhIGBCZWFyZXIgPHRva2VuPmAgaGVhZGVyIHZhbHVlIGZvciBmZXRjaC9heGlvcyBjYWxscy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRTZXJ2aWNlQXV0aEhlYWRlcihvcHRzOiBTZXJ2aWNlVG9rZW5PcHRpb25zKTogc3RyaW5nIHtcbiAgcmV0dXJuIGBCZWFyZXIgJHtzaWduU2VydmljZVRva2VuKG9wdHMpfWA7XG59XG5cbi8qKiBUcnVlIHdoZW4gYHJlcS51c2VyLnN1YmAgd2FzIGlzc3VlZCBieSBgc2lnblNlcnZpY2VUb2tlbmAgKGkuZS4gc3RhcnRzIHdpdGggYHNlcnZpY2U6YCkuICovXG5leHBvcnQgZnVuY3Rpb24gaXNTZXJ2aWNlUHJpbmNpcGFsKHJlcTogUmVxdWVzdCk6IGJvb2xlYW4ge1xuICByZXR1cm4gcmVxLnVzZXI/LnN1Yj8uc3RhcnRzV2l0aCgnc2VydmljZTonKSA/PyBmYWxzZTtcbn1cbiJdfQ==
276
+ /**
277
+ * PRE-auth check: cryptographically verify the request carries a valid, signed
278
+ * SERVICE token (`sub` starts with `service:`). Unlike {@link isServicePrincipal}
279
+ * (which reads the already-populated `req.user`), this verifies the bearer token
280
+ * itself, so it is safe to call BEFORE `requireAuth` runs — e.g. the global rate
281
+ * limiter's `skip`, which must not trust the spoofable `x-internal-service`
282
+ * header. Mirrors `requireAuth`'s verification (algorithm pinning + optional
283
+ * issuer/audience) and returns `false` on any missing/invalid/non-service token.
284
+ */
285
+ export function verifyServicePrincipal(req) {
286
+ const parts = req.headers.authorization?.split(' ');
287
+ if (!parts || parts.length !== 2 || parts[0] !== 'Bearer')
288
+ return false;
289
+ try {
290
+ const verifyOptions = { algorithms: [(process.env.JWT_ALGORITHM || 'HS256')] };
291
+ if (process.env.JWT_ISSUER)
292
+ verifyOptions.issuer = process.env.JWT_ISSUER;
293
+ if (process.env.JWT_AUDIENCE)
294
+ verifyOptions.audience = process.env.JWT_AUDIENCE;
295
+ const decoded = jwt.verify(parts[1], getJwtSecret(), verifyOptions);
296
+ return decoded.type === 'access' && typeof decoded.sub === 'string' && decoded.sub.startsWith('service:');
297
+ }
298
+ catch {
299
+ return false;
300
+ }
301
+ }
302
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXV0aC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9taWRkbGV3YXJlL2F1dGgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUd0QyxPQUFPLEdBQUcsTUFBTSxjQUFjLENBQUM7QUFDL0IsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBRXpELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNwRCxPQUFPLEVBQW1CLGFBQWEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ3pFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN0RCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDbEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRWpELE1BQU0sTUFBTSxHQUFHLFlBQVksQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO0FBRS9DLDREQUE0RDtBQUM1RCxJQUFJLFVBQThCLENBQUM7QUFDbkMsSUFBSSxxQkFBcUIsR0FBRyxDQUFDLENBQUM7QUFDOUIsTUFBTSw4QkFBOEIsR0FBRyxPQUFPLENBQUMsQ0FBQyxZQUFZO0FBRTVELFNBQVMsWUFBWTtJQUNuQixNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDdkIsSUFBSSxDQUFDLFVBQVUsSUFBSSxHQUFHLEdBQUcscUJBQXFCLEdBQUcsOEJBQThCLEVBQUUsQ0FBQztRQUNoRixNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQztRQUN0QyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDWixNQUFNLENBQUMsS0FBSyxDQUFDLDRDQUE0QyxDQUFDLENBQUM7WUFDM0QsTUFBTSxJQUFJLEtBQUssQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7UUFDRCxJQUFJ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QyxhQUFhLElBQUksT0FBTyxDQUFrQixDQUFDLEVBQUUsQ0FBQztRQUNuSCxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsVUFBVTtZQUFFLGFBQWEsQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUM7UUFDMUUsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFlBQVk7WUFBRSxhQUFhLENBQUMsUUFBUSxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsWUFBWSxDQUFDO1FBQ2hGLE1BQU0sT0FBTyxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLFlBQVksRUFBRSxFQUFFLGFBQWEsQ0FBZSxDQUFDO1FBQ2xGLE9BQU8sT0FBTyxDQUFDLElBQUksS0FBSyxRQUFRLElBQUksT0FBTyxPQUFPLENBQUMsR0FBRyxLQUFLLFFBQVEsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUM1RyxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgdHlwZSB7IFJlcXVlc3QsIFJlc3BvbnNlLCBOZXh0RnVuY3Rpb24gfSBmcm9tICdleHByZXNzJztcbmltcG9ydCBqd3QgZnJvbSAnanNvbndlYnRva2VuJztcbmltcG9ydCB7IEh0dHBTdGF0dXMgfSBmcm9tICcuLi9jb25zdGFudHMvaHR0cC1zdGF0dXMuanMnO1xuaW1wb3J0IHR5cGUgeyBKd3RQYXlsb2FkIH0gZnJvbSAnLi4vdHlwZXMvY29tbW9uLmpzJztcbmltcG9ydCB7IEVycm9yQ29kZSB9IGZyb20gJy4uL3R5cGVzL2Vycm9yLWNvZGVzLmpzJztcbmltcG9ydCB7IHR5cGUgUGVybWlzc2lvbiwgaGFzUGVybWlzc2lvbiB9IGZyb20gJy4uL3R5cGVzL3Blcm1pc3Npb25zLmpzJztcbmltcG9ydCB7IGdldEhlYWRlclN0cmluZyB9IGZyb20gJy4uL3V0aWxzL2hlYWRlcnMuanMnO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyLmpzJztcbmltcG9ydCB7IHNlbmRFcnJvciB9IGZyb20gJy4uL3V0aWxzL3Jlc3BvbnNlLmpzJztcblxuY29uc3QgbG9nZ2VyID0gY3JlYXRlTG9nZ2VyKCdhdXRoLW1pZGRsZXdhcmUnKTtcblxuLyoqIENhY2hlZCBKV1Qgc2VjcmV0IHdpdGggcGVyaW9kaWMgcmVmcmVzaCBmcm9tIGVudiB2YXIuICovXG5sZXQgX2p3dFNlY3JldDogc3RyaW5nIHwgdW5kZWZpbmVkO1xubGV0IF9qd3RTZWNyZXRSZWZyZXNoZWRBdCA9IDA7XG5jb25zdCBKV1RfU0VDUkVUX1JFRlJFU0hfSU5URVJWQUxfTVMgPSAzMDBfMDAwOyAvLyA1IG1pbnV0ZXNcblxuZnVuY3Rpb24gZ2V0Snd0U2VjcmV0KCk6IHN0cmluZyB7XG4gIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gIGlmICghX2p3dFNlY3JldCB8fCBub3cgLSBfand0U2VjcmV0UmVmcmVzaGVkQXQgPiBKV1RfU0VDUkVUX1JFRlJFU0hfSU5URVJWQUxfTVMpIHtcbiAgICBjb25zdCBzZWNyZXQgPSBwcm9jZXNzLmVudi5KV1RfU0VDUkVUO1xuICAgIGlmICghc2VjcmV0KSB7XG4gICAgICBsb2dnZXIuZXJyb3IoJ0pXVF9TRUNSRVQgZW52aXJvbm1lbnQgdmFyaWFibGUgaXMgbm90IHNldCcpO1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdKV1RfU0VDUkVUIGVudmlyb25tZW50IHZhcmlhYmxlIGlzIHJlcXVpcmVkJyk7XG4gICAgfVxuICAgIGlmIChfand0U2VjcmV0ICYmIF9qd3RTZWNyZXQgIT09IHNlY3JldCkge1xuICAgICAgbG9nZ2VyLmluZm8oJ0pXVCBzZWNyZXQgcm90YXRlZCcpO1xuICAgIH1cbiAgICBfand0U2VjcmV0ID0gc2VjcmV0O1xuICAgIF9qd3RTZWNyZXRSZWZyZXNoZWRBdCA9IG5vdztcbiAgfVxuICByZXR1cm4gX2p3dFNlY3JldDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXF1aXJlQXV0aE9wdGlvbnMge1xuICAvKipcbiAgICogQWxsb3cgeC1vcmctaWQveC1vcmctbmFtZSBoZWFkZXJzIHRvIG92ZXJyaWRlIHRoZSBKV1QncyBvcmdhbml6YXRpb24gZmllbGRzLlxuICAgKlxuICAgKiBXaGVuIGVuYWJsZWQsIHRoZSBgeC1vcmctaWRgL2B4LW9yZy1uYW1lYCBoZWFkZXJzIG92ZXJyaWRlIHRoZSBjYWxsZXIncyBvcmdcbiAgICog4oCUIGJ1dCBPTkxZIGZvciBhIHZlcmlmaWVkIFNZUy1BRE1JTiAoYGlzU3VwZXJBZG1pbmAgY2xhaW0pLiBGb3IgYW55IG9yZGluYXJ5XG4gICAqIGF1dGhlbnRpY2F0ZWQgdXNlciB0aGUgaGVhZGVycyBhcmUgaWdub3JlZCwgc28gZW5hYmxpbmcgdGhpcyBjYW4gbmV2ZXIgbGV0IGFcbiAgICogbm9ybWFsIHVzZXIgaW1wZXJzb25hdGUgYW5vdGhlciB0ZW5hbnQncyBvcmcuIFVzZSBmb3IgY3Jvc3Mtb3JnIGFkbWluIHRvb2xpbmdcbiAgICogKGUuZy4gYSBzeXNhZG1pbiBtYW5hZ2luZyBhIGdpdmVuIG9yZydzIGJpbGxpbmcpLiBJZiB1bnN1cmUsIGxlYXZlIGl0IGRpc2FibGVkLlxuICAgKi9cbiAgYWxsb3dPcmdIZWFkZXJPdmVycmlkZT86IGJvb2xlYW47XG59XG5cbi8qKiBKV1QgYXV0aCBtaWRkbGV3YXJlLiBVc2UgZGlyZWN0bHkgb3IgY2FsbCB3aXRoIG9wdGlvbnMuICovXG5leHBvcnQgZnVuY3Rpb24gcmVxdWlyZUF1dGgoXG4gIHJlcTogUmVxdWVzdCxcbiAgcmVzOiBSZXNwb25zZSxcbiAgbmV4dDogTmV4dEZ1bmN0aW9uLFxuKTogdm9pZDtcbmV4cG9ydCBmdW5jdGlvbiByZXF1aXJlQXV0aChcbiAgb3B0aW9ucz86IFJlcXVpcmVBdXRoT3B0aW9ucyxcbik6IChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbikgPT4gdm9pZDtcbmV4cG9ydCBmdW5jdGlvbiByZXF1aXJlQXV0aChcbiAgcmVxT3JPcHRpb25zPzogUmVxdWVzdCB8IFJlcXVpcmVBdXRoT3B0aW9ucyxcbiAgcmVzPzogUmVzcG9uc2UsXG4gIG5leHQ/OiBOZXh0RnVuY3Rpb24sXG4pOiB2b2lkIHwgKChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbikgPT4gdm9pZCkge1xuICBpZiAocmVxT3JPcHRpb25zICYmIHJlcyAmJiBuZXh0ICYmICdoZWFkZXJzJyBpbiByZXFPck9wdGlvbnMpIHtcbiAgICByZXR1cm4gX3JlcXVpcmVBdXRoKHt9LCByZXFPck9wdGlvbnMgYXMgUmVxdWVzdCwgcmVzLCBuZXh0KTtcbiAgfVxuXG4gIGNvbnN0IG9wdGlvbnMgPSAocmVxT3JPcHRpb25zIGFzIFJlcXVpcmVBdXRoT3B0aW9ucykgfHwge307XG4gIHJldHVybiAocmVxOiBSZXF1ZXN0LCByZXNJbm5lcjogUmVzcG9uc2UsIG5leHRJbm5lcjogTmV4dEZ1bmN0aW9uKSA9PiB7XG4gICAgX3JlcXVpcmVBdXRoKG9wdGlvbnMsIHJlcSwgcmVzSW5uZXIsIG5leHRJbm5lcik7XG4gIH07XG59XG5cbmZ1bmN0aW9uIF9yZXF1aXJlQXV0aChcbiAgb3B0aW9uczogUmVxdWlyZUF1dGhPcHRpb25zLFxuICByZXE6IFJlcXVlc3QsXG4gIHJlczogUmVzcG9uc2UsXG4gIG5leHQ6IE5leHRGdW5jdGlvbixcbik6IHZvaWQge1xuICBjb25zdCBhdXRoSGVhZGVyID0gcmVxLmhlYWRlcnMuYXV0aG9yaXphdGlvbjtcblxuICBpZiAoIWF1dGhIZWFkZXIpIHtcbiAgICByZXR1cm4gc2VuZEVycm9yKHJlcywgSHR0cFN0YXR1cy5VTkFVVEhPUklaRUQsICdBdXRob3JpemF0aW9uIGhlYWRlciByZXF1aXJlZCcsIEVycm9yQ29kZS5UT0tFTl9NSVNTSU5HKTtcbiAgfVxuXG4gIGNvbnN0IHBhcnRzID0gYXV0aEhlYWRlci5zcGxpdCgnICcpO1xuICBpZiAocGFydHMubGVuZ3RoICE9PSAyIHx8IHBhcnRzWzBdICE9PSAnQmVhcmVyJykge1xuICAgIHJldHVybiBzZW5kRXJyb3IocmVzLCBIdHRwU3RhdHVzLlVOQVVUSE9SSVpFRCwgJ0ludmFsaWQgYXV0aG9yaXphdGlvbiBmb3JtYXQuIFVzZTogQmVhcmVyIDx0b2tlbj4nLCBFcnJvckNvZGUuVE9LRU5fSU5WQUxJRCk7XG4gIH1cblxuICB0cnkge1xuICAgIC8vIFBhc3MgdGhyb3VnaCBvcHRpb25hbCBpc3N1ZXIvYXVkaWVuY2UgdmVyaWZpY2F0aW9uIHdoZW4gZW52LWNvbmZpZ3VyZWQuXG4gICAgLy8gV2l0aG91dCB0aGVzZSwgYSBKV1Qgc2lnbmVkIGJ5IGFueSBzeXN0ZW0gdGhhdCBoYXBwZW5zIHRvIHNoYXJlIHRoZVxuICAgIC8vIHNhbWUgSldUX1NFQ1JFVCB3b3VsZCBiZSBhY2NlcHRlZCDigJQgZGVmZW5jZS1pbi1kZXB0aCBmb3Igc2hhcmVkLXNlY3JldFxuICAgIC8vIG1pc2NvbmZpZ3VyYXRpb25zIGFjcm9zcyBzZXJ2aWNlcyAvIGVudmlyb25tZW50cy5cbiAgICAvLyBQaW4gdGhlIGFjY2VwdGVkIGFsZ29yaXRobSB0byB0aGUgY29uZmlndXJlZCBITUFDIGFsZyAoZGVmYXVsdCBIUzI1NikuXG4gICAgLy8gV2l0aG91dCBhbiBhbGxvdy1saXN0LCBgand0LnZlcmlmeWAgYWNjZXB0cyBhbnkgYWxnb3JpdGhtIHRoZSBrZXkgY2FuXG4gICAgLy8gdmVyaWZ5IOKAlCB0aGUgY2xhc3NpYyBhbGctY29uZnVzaW9uIHZlY3RvciAoYW5kIGEgaGFyZCBndWFyZCBhZ2FpbnN0XG4gICAgLy8gYGFsZzpub25lYCkuIEVudi1kcml2ZW4gc28gaXQgc3RheXMgaW4gbG9ja3N0ZXAgd2l0aCBob3cgdG9rZW5zIGFyZVxuICAgIC8vIHNpZ25lZCAoc2VlIHNpZ25TZXJ2aWNlVG9rZW4gKyBwbGF0Zm9ybSdzIGNvbmZpZy5hdXRoLmp3dC5hbGdvcml0aG0pLlxuICAgIGNvbnN0IHZlcmlmeU9wdGlvbnM6IGp3dC5WZXJpZnlPcHRpb25zID0geyBhbGdvcml0aG1zOiBbKHByb2Nlc3MuZW52LkpXVF9BTEdPUklUSE0gfHwgJ0hTMjU2JykgYXMgand0LkFsZ29yaXRobV0gfTtcbiAgICBjb25zdCBleHBlY3RlZElzc3VlciA9IHByb2Nlc3MuZW52LkpXVF9JU1NVRVI7XG4gICAgY29uc3QgZXhwZWN0ZWRBdWRpZW5jZSA9IHByb2Nlc3MuZW52LkpXVF9BVURJRU5DRTtcbiAgICBpZiAoZXhwZWN0ZWRJc3N1ZXIpIHZlcmlmeU9wdGlvbnMuaXNzdWVyID0gZXhwZWN0ZWRJc3N1ZXI7XG4gICAgaWYgKGV4cGVjdGVkQXVkaWVuY2UpIHZlcmlmeU9wdGlvbnMuYXVkaWVuY2UgPSBleHBlY3RlZEF1ZGllbmNlO1xuICAgIGNvbnN0IGRlY29kZWQgPSBqd3QudmVyaWZ5KHBhcnRzWzFdLCBnZXRKd3RTZWNyZXQoKSwgdmVyaWZ5T3B0aW9ucykgYXMgSnd0UGF5bG9hZDtcblxuICAgIGlmIChkZWNvZGVkLnR5cGUgIT09ICdhY2Nlc3MnKSB7XG4gICAgICByZXR1cm4gc2VuZEVycm9yKHJlcywgSHR0cFN0YXR1cy5VTkFVVEhPUklaRUQsICdPbmx5IGFjY2VzcyB0b2tlbnMgY2FuIGJlIHVzZWQgZm9yIEFQSSByZXF1ZXN0cycsIEVycm9yQ29kZS5UT0tFTl9JTlZBTElEKTtcbiAgICB9XG5cbiAgICBpZiAoIWRlY29kZWQuc3ViIHx8ICFkZWNvZGVkLnJvbGUpIHtcbiAgICAgIHJldHVybiBzZW5kRXJyb3IocmVzLCBIdHRwU3RhdHVzLlVOQVVUSE9SSVpFRCwgJ1Rva2VuIG1pc3NpbmcgcmVxdWlyZWQgZmllbGRzJywgRXJyb3JDb2RlLlRPS0VOX0lOVkFMSUQpO1xuICAgIH1cblxuICAgIHJlcS51c2VyID0geyAuLi5kZWNvZGVkIH07XG5cbiAgICAvLyBUaGUgeC1vcmctaWQveC1vcmctbmFtZSBvdmVycmlkZSBsZXRzIGEgU1lTLUFETUlOIGFjdCBvbiBhIGNob3NlbiBvcmdcbiAgICAvLyAoY3Jvc3Mtb3JnIGFkbWluIHRvb2xpbmcpLiBJdCBpcyBnYXRlZCBvbiB0aGUgdmVyaWZpZWQgYGlzU3VwZXJBZG1pbmAgY2xhaW1cbiAgICAvLyBoZXJlIHNvIHRoYXQgZXZlbiBhIHJvdXRlIHdoaWNoIG1pc3Rha2VubHkgZW5hYmxlcyBgYWxsb3dPcmdIZWFkZXJPdmVycmlkZWBcbiAgICAvLyBjYW4gTkVWRVIgbGV0IGFuIG9yZGluYXJ5IGF1dGhlbnRpY2F0ZWQgdXNlciBzcG9vZiBhbm90aGVyIHRlbmFudCdzIG9yZyB2aWFcbiAgICAvLyB0aGUgaGVhZGVyIOKAlCBkZWZlbmNlLWluLWRlcHRoIGFnYWluc3QgdGhlIGNyb3NzLXRlbmFudCBicmVhayB0aGlzIGNhdXNlZC5cbiAgICBpZiAob3B0aW9ucy5hbGxvd09yZ0hlYWRlck92ZXJyaWRlICYmIGRlY29kZWQuaXNTdXBlckFkbWluID09PSB0cnVlKSB7XG4gICAgICBjb25zdCBoZWFkZXJPcmdJZCA9IGdldEhlYWRlclN0cmluZyhyZXEuaGVhZGVyc1sneC1vcmctaWQnXSk7XG4gICAgICBjb25zdCBoZWFkZXJPcmdOYW1lID0gZ2V0SGVhZGVyU3RyaW5nKHJlcS5oZWFkZXJzWyd4LW9yZy1uYW1lJ10pO1xuICAgICAgaWYgKGhlYWRlck9yZ0lkKSByZXEudXNlci5vcmdhbml6YXRpb25JZCA9IGhlYWRlck9yZ0lkO1xuICAgICAgaWYgKGhlYWRlck9yZ05hbWUpIHJlcS51c2VyLm9yZ2FuaXphdGlvbk5hbWUgPSBoZWFkZXJPcmdOYW1lO1xuICAgIH1cblxuICAgIG5leHQoKTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAoZXJyb3IgaW5zdGFuY2VvZiBqd3QuVG9rZW5FeHBpcmVkRXJyb3IpIHtcbiAgICAgIHJldHVybiBzZW5kRXJyb3IocmVzLCBIdHRwU3RhdHVzLlVOQVVUSE9SSVpFRCwgJ1Rva2VuIGhhcyBleHBpcmVkJywgRXJyb3JDb2RlLlRPS0VOX0VYUElSRUQpO1xuICAgIH1cblxuICAgIGlmIChlcnJvciBpbnN0YW5jZW9mIGp3dC5Kc29uV2ViVG9rZW5FcnJvcikge1xuICAgICAgcmV0dXJuIHNlbmRFcnJvcihyZXMsIEh0dHBTdGF0dXMuVU5BVVRIT1JJWkVELCAnSW52YWxpZCB0b2tlbicsIEVycm9yQ29kZS5UT0tFTl9JTlZBTElEKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2VuZEVycm9yKHJlcywgSHR0cFN0YXR1cy5VTkFVVEhPUklaRUQsICdBdXRoZW50aWNhdGlvbiBmYWlsZWQnLCBFcnJvckNvZGUuVU5BVVRIT1JJWkVEKTtcbiAgfVxufVxuXG4vKipcbiAqIFJlcXVpcmVzIGFkbWluIHJvbGUuIFVzZSBhZnRlciByZXF1aXJlQXV0aC5cbiAqIFBlcm1pdHMgdXNlcnMgd2hvc2UgcGVyLW9yZyByb2xlIGlzICdhZG1pbicgb3IgJ293bmVyJy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcXVpcmVBZG1pbihcbiAgcmVxOiBSZXF1ZXN0LFxuICByZXM6IFJlc3BvbnNlLFxuICBuZXh0OiBOZXh0RnVuY3Rpb24sXG4pOiB2b2lkIHtcbiAgaWYgKCFyZXEudXNlcikge1xuICAgIHJldHVybiBzZW5kRXJyb3IocmVzLCBIdHRwU3RhdHVzLlVOQVVUSE9SSVpFRCwgJ0F1dGhlbnRpY2F0aW9uIHJlcXVpcmVkJywgRXJyb3JDb2RlLlVOQVVUSE9SSVpFRCk7XG4gIH1cblxuICBpZiAocmVxLnVzZXIucm9sZSAhPT0gJ2FkbWluJyAmJiByZXEudXNlci5yb2xlICE9PSAnb3duZXInKSB7XG4gICAgcmV0dXJuIHNlbmRFcnJvcihyZXMsIEh0dHBTdGF0dXMuRk9SQklEREVOLCAnQWRtaW4gYWNjZXNzIHJlcXVpcmVkJywgRXJyb3JDb2RlLklOU1VGRklDSUVOVF9QRVJNSVNTSU9OUyk7XG4gIH1cblxuICBuZXh0KCk7XG59XG5cbi8qKlxuICogV2hldGhlciB0aGUgcmVxdWVzdCdzIHVzZXIgaG9sZHMgYHBlcm1pc3Npb25gLiBTdXBlcmFkbWlucyBpbXBsaWNpdGx5IGhvbGRcbiAqIGV2ZXJ5IHBlcm1pc3Npb24uIFJlYWRzIHRoZSByZXNvbHZlZCBgcGVybWlzc2lvbnNgIGNsYWltIChzZXQgYXQgdG9rZW4gaXNzdWUsXG4gKiBvciByZS1kZXJpdmVkIHBlciByZXF1ZXN0IGJ5IHRoZSBwbGF0Zm9ybSkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1c2VySGFzUGVybWlzc2lvbihyZXE6IFJlcXVlc3QsIHBlcm1pc3Npb246IFBlcm1pc3Npb24pOiBib29sZWFuIHtcbiAgcmV0dXJuIGhhc1Blcm1pc3Npb24ocmVxLnVzZXI/LnBlcm1pc3Npb25zLCBwZXJtaXNzaW9uLCByZXEudXNlcj8uaXNTdXBlckFkbWluKTtcbn1cblxuLyoqXG4gKiBSZXF1aXJlcyB0aGF0IHRoZSB1c2VyIGhvbGQgQVQgTEVBU1QgT05FIG9mIHRoZSBnaXZlbiBwZXJtaXNzaW9ucyAob3IgYmUgYVxuICogc3VwZXJhZG1pbikuIFVzZSBhZnRlciByZXF1aXJlQXV0aC4gTWlycm9ycyBgcmVxdWlyZVJvbGVgJ3MgYW55LW9mIHNlbWFudGljcztcbiAqIHBhc3MgYSBzaW5nbGUgcGVybWlzc2lvbiBmb3IgYSBzcGVjaWZpYyBhY3Rpb24sIG9yIHNldmVyYWwgd2hlbiBhbnkgb25lIG9mXG4gKiB0aGVtIHNob3VsZCBncmFudCBhY2Nlc3MuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXF1aXJlUGVybWlzc2lvbiguLi5wZXJtaXNzaW9uczogUGVybWlzc2lvbltdKSB7XG4gIHJldHVybiAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pOiB2b2lkID0+IHtcbiAgICBpZiAoIXJlcS51c2VyKSB7XG4gICAgICByZXR1cm4gc2VuZEVycm9yKHJlcywgSHR0cFN0YXR1cy5VTkFVVEhPUklaRUQsICdBdXRoZW50aWNhdGlvbiByZXF1aXJlZCcsIEVycm9yQ29kZS5VTkFVVEhPUklaRUQpO1xuICAgIH1cbiAgICAvLyB1c2VySGFzUGVybWlzc2lvbiDihpIgaGFzUGVybWlzc2lvbiBhbHJlYWR5IGdyYW50cyBzdXBlcmFkbWlucyBldmVyeVxuICAgIC8vIHBlcm1pc3Npb24sIHNvIHRoaXMgc2luZ2xlIGNoZWNrIGNvdmVycyBib3RoIHRoZSBzdXBlcmFkbWluIGJ5cGFzcyBhbmRcbiAgICAvLyB0aGUgYW55LW9mIG1lbWJlcnNoaXAgdGVzdCB3aXRob3V0IHJlLWlubGluaW5nIGVpdGhlci5cbiAgICBpZiAocGVybWlzc2lvbnMuc29tZSgocCkgPT4gdXNlckhhc1Blcm1pc3Npb24ocmVxLCBwKSkpIHJldHVybiBuZXh0KCk7XG4gICAgcmV0dXJuIHNlbmRFcnJvcihcbiAgICAgIHJlcywgSHR0cFN0YXR1cy5GT1JCSURERU4sXG4gICAgICBgTWlzc2luZyByZXF1aXJlZCBwZXJtaXNzaW9uOiAke3Blcm1pc3Npb25zLmpvaW4oJyBvciAnKX1gLFxuICAgICAgRXJyb3JDb2RlLklOU1VGRklDSUVOVF9QRVJNSVNTSU9OUyxcbiAgICApO1xuICB9O1xufVxuXG4vKipcbiAqIFRoZSBzeXN0ZW0gdGVuYW50J3MgY2Fub25pY2FsIG9yZyAqKmlkKiog4oCUIGEgZml4ZWQsIHdlbGwta25vd24gT2JqZWN0SWQgKE5PVFxuICogdGhlIHN0cmluZyAnc3lzdGVtJykuIFRoaXMgaXMgdGhlIHNpbmdsZSBrbm9iIGV2ZXJ5IHNlcnZpY2UgcmVzb2x2ZXMgdGhlXG4gKiBzeXN0ZW0gdGVuYW50IHRocm91Z2g7IG92ZXJyaWRlIHZpYSB0aGUgYFNZU1RFTV9PUkdfSURgIGVudiBmb3IgYWx0ZXJuYXRlXG4gKiBpbnN0YWxscy4gVGhlIHN5c3RlbSBvcmcncyBodW1hbiBpZGVudGlmaWVyIHN0YXlzIHRoZSBzbHVnL25hbWUgJ3N5c3RlbSdcbiAqIChzZWUge0BsaW5rIFNZU1RFTV9PUkdfU0xVR30pOyBvbmx5IGl0cyBgX2lkYCBpcyB0aGlzIE9iamVjdElkLlxuICovXG5leHBvcnQgY29uc3QgU1lTVEVNX09SR19JRCA9IChwcm9jZXNzLmVudi5TWVNURU1fT1JHX0lEIHx8ICcwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDEnKS50b0xvd2VyQ2FzZSgpO1xuXG4vKiogVGhlIHN5c3RlbSBvcmcncyB3ZWxsLWtub3duIHNsdWcvbmFtZSAodGhlIGh1bWFuIGlkZW50aWZpZXI7IGl0cyBgX2lkYCBpcyB7QGxpbmsgU1lTVEVNX09SR19JRH0pLiAqL1xuZXhwb3J0IGNvbnN0IFNZU1RFTV9PUkdfU0xVRyA9ICdzeXN0ZW0nO1xuXG4vKipcbiAqIENoZWNrIGlmIGFuIG9yZ0lkIG9yIG9yZ05hbWUvc2x1ZyBtYXRjaGVzIHRoZSBzeXN0ZW0gb3JnLiBVc2UgdGhpcyBpbnN0ZWFkIG9mXG4gKiBjb21wYXJpbmcgZGlyZWN0bHk6IHRoZSBpZCBpcyBub3cgYW4gT2JqZWN0SWQgKHtAbGluayBTWVNURU1fT1JHX0lEfSkgd2hpbGUgdGhlXG4gKiBuYW1lL3NsdWcgaXMgJ3N5c3RlbScgKHtAbGluayBTWVNURU1fT1JHX1NMVUd9KSwgc28gdGhlIHR3byBhcmUgY29tcGFyZWQgYWdhaW5zdFxuICogdGhlaXIgcmVzcGVjdGl2ZSBjYW5vbmljYWwgdmFsdWVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNTeXN0ZW1PcmdJZChvcmdJZD86IHN0cmluZywgb3JnTmFtZT86IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gb3JnSWQ/LnRvTG93ZXJDYXNlKCkgPT09IFNZU1RFTV9PUkdfSUQgfHwgb3JnTmFtZT8udG9Mb3dlckNhc2UoKSA9PT0gU1lTVEVNX09SR19TTFVHO1xufVxuXG4vKipcbiAqIENoZWNrIGlmIHRoZSByZXF1ZXN0IGlzIGZyb20gYSBzeXN0ZW0gYWRtaW4uXG4gKlxuICogQXV0aG9yaXR5IGlzIGdyYW50ZWQgc29sZWx5IGJ5IHRoZSB1c2VyLWxldmVsIGBpc1N1cGVyQWRtaW5gIGZsYWcgY2FycmllZFxuICogaW4gdGhlIEpXVC4gVGhlIFwibWVtYmVyc2hpcCBpbiB0aGUgd2VsbC1rbm93biAnc3lzdGVtJyBvcmcgd2l0aCByb2xlXG4gKiBhZG1pbi9vd25lclwiIHBhdGggd2FzIHJlbW92ZWQg4oCUIGl0IGNvbmZsYXRlZCBhIFBpcGVsaW5lIEJ1aWxkZXIgb3BlcmF0b3JcbiAqIHdpdGggYSByZWFsIGN1c3RvbWVyIHRlbmFudCBpbiB0aGUgZGF0YSBtb2RlbCwgYW5kIG1lYW50IGFueSB1bmludGVuZGVkXG4gKiB3cml0ZSB0aGF0IGNyZWF0ZWQgYSAnc3lzdGVtJy1uYW1lZCBvcmcgY291bGQgcXVpZXRseSBncmFudCBjcm9zcy1vcmdcbiAqIGF1dGhvcml0eS4gVGhlIGBzeXN0ZW1gIG9yZyBzdGlsbCBleGlzdHMgYXMgYSAqY29udGVudCBob2xkZXIqIGZvciBzaGFyZWRcbiAqIHNhbXBsZSBkYXRhOyBpdCBqdXN0IG5vIGxvbmdlciBjb25mZXJzIHByaXZpbGVnZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU3lzdGVtQWRtaW4ocmVxOiBSZXF1ZXN0KTogYm9vbGVhbiB7XG4gIHJldHVybiByZXEudXNlcj8uaXNTdXBlckFkbWluID09PSB0cnVlO1xufVxuXG4vKipcbiAqIFdoZXRoZXIgdGhlIHJlcXVlc3QncyB0b2tlbiBjYXJyaWVzIGEgc3BlY2lmaWMgY2FwYWJpbGl0eSBgc2NvcGVgIChlLmcuXG4gKiBgJ3JlcG9ydGluZzppbmdlc3QnYCkuIFVzZWQgdG8gZ2F0ZSBlbmRwb2ludHMgdGhhdCBhY2NlcHQgYSBuYXJyb3cgbWFjaGluZVxuICogaWRlbnRpdHkg4oCUIGEgbm9ybWFsIGludGVyYWN0aXZlIHVzZXIgdG9rZW4gaGFzIG5vIGBzY29wZWAgYW5kIHJldHVybnMgZmFsc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNTY29wZShyZXE6IFJlcXVlc3QsIHNjb3BlOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIHJlcS51c2VyPy5zY29wZSA9PT0gc2NvcGU7XG59XG5cbi8qKiBSZXF1aXJlcyBzeXN0ZW0gYWRtaW4gKGFkbWluIHJvbGUgKyBzeXN0ZW0gb3JnYW5pemF0aW9uKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXF1aXJlU3lzdGVtQWRtaW4oXG4gIHJlcTogUmVxdWVzdCxcbiAgcmVzOiBSZXNwb25zZSxcbiAgbmV4dDogTmV4dEZ1bmN0aW9uLFxuKTogdm9pZCB7XG4gIGlmICghaXNTeXN0ZW1BZG1pbihyZXEpKSB7XG4gICAgcmV0dXJuIHNlbmRFcnJvcihcbiAgICAgIHJlcywgSHR0cFN0YXR1cy5GT1JCSURERU4sXG4gICAgICAnQWNjZXNzIGRlbmllZC4gT25seSBzeXN0ZW0gYWRtaW5pc3RyYXRvcnMgY2FuIHBlcmZvcm0gdGhpcyBhY3Rpb24uJyxcbiAgICAgIEVycm9yQ29kZS5JTlNVRkZJQ0lFTlRfUEVSTUlTU0lPTlMsXG4gICAgKTtcbiAgfVxuICBuZXh0KCk7XG59XG5cbi8qKlxuICogUmVxdWlyZSBhIHNwZWNpZmljIGZlYXR1cmUgZmxhZy4gVXNlIGFmdGVyIHJlcXVpcmVBdXRoLlxuICogQ2hlY2tzIHRoZSBgZmVhdHVyZXNgIGFycmF5IGluIHRoZSBKV1QgcGF5bG9hZCAoc2V0IGF0IHRva2VuIGlzc3VhbmNlKS5cbiAqIFN5c2FkbWlucyAoaXNTdXBlckFkbWluKSBieXBhc3Mg4oCUIHRoZXkgYWx3YXlzIGhhdmUgZXZlcnkgZmVhdHVyZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcXVpcmVGZWF0dXJlKGZlYXR1cmU6IHN0cmluZykge1xuICByZXR1cm4gKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSwgbmV4dDogTmV4dEZ1bmN0aW9uKTogdm9pZCA9PiB7XG4gICAgaWYgKCFyZXEudXNlcikge1xuICAgICAgcmV0dXJuIHNlbmRFcnJvcihyZXMsIEh0dHBTdGF0dXMuVU5BVVRIT1JJWkVELCAnQXV0aGVudGljYXRpb24gcmVxdWlyZWQnLCBFcnJvckNvZGUuVU5BVVRIT1JJWkVEKTtcbiAgICB9XG5cbiAgICAvLyBTeXNhZG1pbnMgZ2V0IGFsbCBmZWF0dXJlczsgdGhlIGBmZWF0dXJlc2AgYXJyYXkgb24gdGhlaXIgdG9rZW4gaXNcbiAgICAvLyBwb3B1bGF0ZWQgd2l0aCBldmVyeSBmbGFnIGF0IGlzc3VhbmNlIHRpbWUgYnV0IHRoZSBieXBhc3MgaGVyZSBrZWVwc1xuICAgIC8vIHRoZSBydWxlIGV4cGxpY2l0IGFuZCBzdXJ2aXZlcyBhIHRva2VuIGlzc3VlZCBiZWZvcmUgYSBuZXcgZmVhdHVyZVxuICAgIC8vIGZsYWcgd2FzIGFkZGVkLlxuICAgIGlmIChyZXEudXNlci5pc1N1cGVyQWRtaW4gPT09IHRydWUpIHJldHVybiBuZXh0KCk7XG5cbiAgICBpZiAoIXJlcS51c2VyLmZlYXR1cmVzPy5pbmNsdWRlcyhmZWF0dXJlKSkge1xuICAgICAgcmV0dXJuIHNlbmRFcnJvcihcbiAgICAgICAgcmVzLCBIdHRwU3RhdHVzLkZPUkJJRERFTixcbiAgICAgICAgYFRoaXMgZmVhdHVyZSByZXF1aXJlcyBhIGhpZ2hlciBwbGFuICgke2ZlYXR1cmV9KWAsXG4gICAgICAgIEVycm9yQ29kZS5JTlNVRkZJQ0lFTlRfUEVSTUlTU0lPTlMsXG4gICAgICApO1xuICAgIH1cblxuICAgIG5leHQoKTtcbiAgfTtcbn1cblxuLyoqXG4gKiBSZXNvbHZlIHRoZSBlZmZlY3RpdmUgYWNjZXNzIG1vZGlmaWVyIGZvciBhbiBlbnRpdHkgYmVpbmcgY3JlYXRlZC91cGRhdGVkLlxuICogJ3B1YmxpYycgaXMgcGVybWl0dGVkIGZvciBhbnkgYWRtaW4gb3Igb3duZXIgcm9sZSAoc3lzdGVtIGFkbWlucyBjcmVhdGVcbiAqIGNhdGFsb2ctd2lkZSBwdWJsaWMgZW50aXRpZXM7IG9yZyBhZG1pbnMgY3JlYXRlIG9yZy13aWRlIHB1YmxpYyBlbnRpdGllcykuXG4gKiBFdmVyeW9uZSBlbHNlIChtZW1iZXIgcm9sZSwgbm8gcm9sZSkgZ2V0cyAncHJpdmF0ZScuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlQWNjZXNzTW9kaWZpZXIocmVxOiBSZXF1ZXN0LCByZXF1ZXN0ZWQ6IHN0cmluZyB8IHVuZGVmaW5lZCk6ICdwdWJsaWMnIHwgJ3ByaXZhdGUnIHtcbiAgaWYgKHJlcXVlc3RlZCA9PT0gJ3B1YmxpYycgJiYgKHJlcS51c2VyPy5yb2xlID09PSAnYWRtaW4nIHx8IHJlcS51c2VyPy5yb2xlID09PSAnb3duZXInKSkge1xuICAgIHJldHVybiAncHVibGljJztcbiAgfVxuICByZXR1cm4gJ3ByaXZhdGUnO1xufVxuXG4vLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFNlcnZpY2UtdG8tc2VydmljZSB0b2tlbnNcbi8vXG4vLyBJbnRlci1zZXJ2aWNlIEhUVFAgY2FsbHMgKGJpbGxpbmcg4oaSIG1lc3NhZ2UsIHBsYXRmb3JtIOKGkiBjb21wbGlhbmNlLCBldGMuKVxuLy8gbmVlZCB0byBzYXRpc2Z5IHRoZSBzYW1lIGByZXF1aXJlQXV0aGAgbWlkZGxld2FyZSBhcyB1c2VyIHJlcXVlc3RzLlxuLy8gYHNpZ25TZXJ2aWNlVG9rZW5gIG1pbnRzIGEgc2hvcnQtbGl2ZWQgSldUIHNpZ25lZCB3aXRoIHRoZSBzaGFyZWRcbi8vIEpXVF9TRUNSRVQsIGlkZW50aWZ5aW5nIHRoZSBjYWxsaW5nIHNlcnZpY2UgdmlhIGBzdWI6ICdzZXJ2aWNlOjxuYW1lPidgLlxuLy8gYHJlcXVpcmVBdXRoYCBhY2NlcHRzIHRoZXNlIHRva2VucyB0cmFuc3BhcmVudGx5IOKAlCB0aGV5IHBhc3MgYGRlY29kZWQuc3ViYFxuLy8gYW5kIGBkZWNvZGVkLnJvbGVgIGNoZWNrcywgYW5kIGRvd25zdHJlYW0gYHJlcXVpcmVPcmdhbml6YXRpb25gIC9cbi8vIGByZXF1aXJlQWRtaW5gIHJlbHkgb24gdGhlIG9yZy9yb2xlIGVtYmVkZGVkIGluIHRoZSB0b2tlbi5cbi8vXG4vLyBUb2tlbnMgZGVmYXVsdCB0byA1LW1pbnV0ZSBUVEwg4oCUIGxvbmcgZW5vdWdoIHRvIHN1cnZpdmUgYSBiYWNrZW5kIGhvcCxcbi8vIHNob3J0IGVub3VnaCB0aGF0IGEgbGVha2VkIHRva2VuIGlzIGxvdy12YWx1ZS5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG5jb25zdCBERUZBVUxUX1NFUlZJQ0VfVE9LRU5fVFRMX1NFQ09ORFMgPSAzMDA7XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VydmljZVRva2VuT3B0aW9ucyB7XG4gIC8qKiBDYWxsaW5nIHNlcnZpY2UgaWRlbnRpZmllciAoZS5nLiAnYmlsbGluZycsICdwbGF0Zm9ybScpLiBFbWJlZGRlZCBhcyBgc3ViOiBzZXJ2aWNlOjxuYW1lPmAuICovXG4gIHNlcnZpY2VOYW1lOiBzdHJpbmc7XG4gIC8qKiBBY3RpdmUgb3JnIGNvbnRleHQgZm9yIHRoZSBjYWxsLiBVc2UgdGhlIHRhcmdldCB0ZW5hbnQncyBvcmcgSUQsIG9yICdzeXN0ZW0nIGZvciBzeXN0ZW0td2lkZSBvcHMuICovXG4gIG9yZ0lkPzogc3RyaW5nO1xuICAvKiogQWN0aXZlIG9yZyBuYW1lLiBEZWZhdWx0cyB0byBvcmdJZC4gKi9cbiAgb3JnTmFtZT86IHN0cmluZztcbiAgLyoqIFRUTCBpbiBzZWNvbmRzIChkZWZhdWx0IDMwMCkuICovXG4gIHR0bFNlY29uZHM/OiBudW1iZXI7XG4gIC8qKlxuICAgKiBSb2xlIHRoZSB0b2tlbiBjYXJyaWVzIChyZXF1aXJlZCDigJQgbm8gaW1wbGljaXQgZGVmYXVsdCkuICoqUGFzcyB0aGUgTE9XRVNUXG4gICAqIHJvbGUgdGhlIGNhbGwgYWN0dWFsbHkgbmVlZHMqKiAoYCdtZW1iZXInYCBmb3IgcmVhZCAvIGRhdGEtcGxhbmUgY2FsbHMpIHNvIGFcbiAgICogbGVha2VkIHNlcnZpY2UgdG9rZW4gY2FuJ3QgcGVyZm9ybSBhZG1pbiBhY3Rpb25zIGluIHRoZSB0YXJnZXQgb3JnLlxuICAgKiBgaXNBZG1pbmAgaXMgZGVyaXZlZCBmcm9tIHRoaXMgKGFkbWlufG93bmVyIOKGkiB0cnVlKS5cbiAgICovXG4gIHJvbGU6ICdvd25lcicgfCAnYWRtaW4nIHwgJ21lbWJlcic7XG59XG5cbi8qKlxuICogTWludCBhIEpXVCBpZGVudGlmeWluZyB0aGUgY2FsbGluZyBzZXJ2aWNlLiBVc2VkIGZvciBpbnRlci1zZXJ2aWNlIEhUVFAgY2FsbHMuXG4gKiBUaGUgdG9rZW4gc2F0aXNmaWVzIGByZXF1aXJlQXV0aGAgYW5kICh3aGVuIG9yZ0lkIGlzIHByZXNlbnQpIGByZXF1aXJlT3JnYW5pemF0aW9uYC5cbiAqIFNjb3BlIGl0IHdpdGggYG9wdHMucm9sZWAg4oCUIGxlYXN0IHByaXZpbGVnZSBrZWVwcyBhIGxlYWtlZCB0b2tlbiBsb3ctdmFsdWUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaWduU2VydmljZVRva2VuKG9wdHM6IFNlcnZpY2VUb2tlbk9wdGlvbnMpOiBzdHJpbmcge1xuICBjb25zdCByb2xlID0gb3B0cy5yb2xlO1xuICBjb25zdCBwYXlsb2FkOiBKd3RQYXlsb2FkID0ge1xuICAgIHN1YjogYHNlcnZpY2U6JHtvcHRzLnNlcnZpY2VOYW1lfWAsXG4gICAgdXNlcm5hbWU6IGAke29wdHMuc2VydmljZU5hbWV9LXNlcnZpY2VgLFxuICAgIGVtYWlsOiBgJHtvcHRzLnNlcnZpY2VOYW1lfUBpbnRlcm5hbGAsXG4gICAgcm9sZSxcbiAgICBpc0FkbWluOiByb2xlID09PSAnb3duZXInIHx8IHJvbGUgPT09ICdhZG1pbicsXG4gICAgdHlwZTogJ2FjY2VzcycsXG4gICAgb3JnYW5pemF0aW9uSWQ6IG9wdHMub3JnSWQsXG4gICAgb3JnYW5pemF0aW9uTmFtZTogb3B0cy5vcmdOYW1lID8/IG9wdHMub3JnSWQsXG4gIH07XG4gIC8vIE1hdGNoIHRoZSBvcHRpb25hbCBpc3N1ZXIvYXVkaWVuY2UgdGhhdCByZXF1aXJlQXV0aCB2ZXJpZmllcywgd2hlblxuICAvLyBjb25maWd1cmVkLiBXaXRob3V0IHRoZXNlLCBhIHNlcnZpY2UgdG9rZW4gc2lnbmVkIGhlcmUgd291bGQgZmFpbFxuICAvLyByZXF1aXJlQXV0aCBpbiBhIGRlcGxveW1lbnQgdGhhdCBoYXMgc2V0IEpXVF9JU1NVRVIvSldUX0FVRElFTkNFLlxuICBjb25zdCBzaWduT3B0aW9uczogand0LlNpZ25PcHRpb25zID0ge1xuICAgIGV4cGlyZXNJbjogb3B0cy50dGxTZWNvbmRzID8/IERFRkFVTFRfU0VSVklDRV9UT0tFTl9UVExfU0VDT05EUyxcbiAgICAvLyBTaWduIHdpdGggdGhlIHNhbWUgY29uZmlndXJlZCBhbGcgcmVxdWlyZUF1dGggcGlucyBvbiB2ZXJpZnksIHNvIHNlcnZpY2VcbiAgICAvLyB0b2tlbnMgc3RheSB2YWxpZCB1bmRlciBhIG5vbi1kZWZhdWx0IEpXVF9BTEdPUklUSE0uXG4gICAgYWxnb3JpdGhtOiAocHJvY2Vzcy5lbnYuSldUX0FMR09SSVRITSB8fCAnSFMyNTYnKSBhcyBqd3QuQWxnb3JpdGhtLFxuICB9O1xuICBpZiAocHJvY2Vzcy5lbnYuSldUX0lTU1VFUikgc2lnbk9wdGlvbnMuaXNzdWVyID0gcHJvY2Vzcy5lbnYuSldUX0lTU1VFUjtcbiAgaWYgKHByb2Nlc3MuZW52LkpXVF9BVURJRU5DRSkgc2lnbk9wdGlvbnMuYXVkaWVuY2UgPSBwcm9jZXNzLmVudi5KV1RfQVVESUVOQ0U7XG4gIHJldHVybiBqd3Quc2lnbihwYXlsb2FkLCBnZXRKd3RTZWNyZXQoKSwgc2lnbk9wdGlvbnMpO1xufVxuXG4vKiogQ29udmVuaWVuY2U6IHJldHVybnMgYSBgQmVhcmVyIDx0b2tlbj5gIGhlYWRlciB2YWx1ZSBmb3IgZmV0Y2gvYXhpb3MgY2FsbHMuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2VydmljZUF1dGhIZWFkZXIob3B0czogU2VydmljZVRva2VuT3B0aW9ucyk6IHN0cmluZyB7XG4gIHJldHVybiBgQmVhcmVyICR7c2lnblNlcnZpY2VUb2tlbihvcHRzKX1gO1xufVxuXG4vKiogVHJ1ZSB3aGVuIGByZXEudXNlci5zdWJgIHdhcyBpc3N1ZWQgYnkgYHNpZ25TZXJ2aWNlVG9rZW5gIChpLmUuIHN0YXJ0cyB3aXRoIGBzZXJ2aWNlOmApLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzU2VydmljZVByaW5jaXBhbChyZXE6IFJlcXVlc3QpOiBib29sZWFuIHtcbiAgcmV0dXJuIHJlcS51c2VyPy5zdWI/LnN0YXJ0c1dpdGgoJ3NlcnZpY2U6JykgPz8gZmFsc2U7XG59XG5cbi8qKlxuICogUFJFLWF1dGggY2hlY2s6IGNyeXB0b2dyYXBoaWNhbGx5IHZlcmlmeSB0aGUgcmVxdWVzdCBjYXJyaWVzIGEgdmFsaWQsIHNpZ25lZFxuICogU0VSVklDRSB0b2tlbiAoYHN1YmAgc3RhcnRzIHdpdGggYHNlcnZpY2U6YCkuIFVubGlrZSB7QGxpbmsgaXNTZXJ2aWNlUHJpbmNpcGFsfVxuICogKHdoaWNoIHJlYWRzIHRoZSBhbHJlYWR5LXBvcHVsYXRlZCBgcmVxLnVzZXJgKSwgdGhpcyB2ZXJpZmllcyB0aGUgYmVhcmVyIHRva2VuXG4gKiBpdHNlbGYsIHNvIGl0IGlzIHNhZmUgdG8gY2FsbCBCRUZPUkUgYHJlcXVpcmVBdXRoYCBydW5zIOKAlCBlLmcuIHRoZSBnbG9iYWwgcmF0ZVxuICogbGltaXRlcidzIGBza2lwYCwgd2hpY2ggbXVzdCBub3QgdHJ1c3QgdGhlIHNwb29mYWJsZSBgeC1pbnRlcm5hbC1zZXJ2aWNlYFxuICogaGVhZGVyLiBNaXJyb3JzIGByZXF1aXJlQXV0aGAncyB2ZXJpZmljYXRpb24gKGFsZ29yaXRobSBwaW5uaW5nICsgb3B0aW9uYWxcbiAqIGlzc3Vlci9hdWRpZW5jZSkgYW5kIHJldHVybnMgYGZhbHNlYCBvbiBhbnkgbWlzc2luZy9pbnZhbGlkL25vbi1zZXJ2aWNlIHRva2VuLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmVyaWZ5U2VydmljZVByaW5jaXBhbChyZXE6IFJlcXVlc3QpOiBib29sZWFuIHtcbiAgY29uc3QgcGFydHMgPSByZXEuaGVhZGVycy5hdXRob3JpemF0aW9uPy5zcGxpdCgnICcpO1xuICBpZiAoIXBhcnRzIHx8IHBhcnRzLmxlbmd0aCAhPT0gMiB8fCBwYXJ0c1swXSAhPT0gJ0JlYXJlcicpIHJldHVybiBmYWxzZTtcbiAgdHJ5IHtcbiAgICBjb25zdCB2ZXJpZnlPcHRpb25zOiBqd3QuVmVyaWZ5T3B0aW9ucyA9IHsgYWxnb3JpdGhtczogWyhwcm9jZXNzLmVudi5KV1RfQUxHT1JJVEhNIHx8ICdIUzI1NicpIGFzIGp3dC5BbGdvcml0aG1dIH07XG4gICAgaWYgKHByb2Nlc3MuZW52LkpXVF9JU1NVRVIpIHZlcmlmeU9wdGlvbnMuaXNzdWVyID0gcHJvY2Vzcy5lbnYuSldUX0lTU1VFUjtcbiAgICBpZiAocHJvY2Vzcy5lbnYuSldUX0FVRElFTkNFKSB2ZXJpZnlPcHRpb25zLmF1ZGllbmNlID0gcHJvY2Vzcy5lbnYuSldUX0FVRElFTkNFO1xuICAgIGNvbnN0IGRlY29kZWQgPSBqd3QudmVyaWZ5KHBhcnRzWzFdLCBnZXRKd3RTZWNyZXQoKSwgdmVyaWZ5T3B0aW9ucykgYXMgSnd0UGF5bG9hZDtcbiAgICByZXR1cm4gZGVjb2RlZC50eXBlID09PSAnYWNjZXNzJyAmJiB0eXBlb2YgZGVjb2RlZC5zdWIgPT09ICdzdHJpbmcnICYmIGRlY29kZWQuc3ViLnN0YXJ0c1dpdGgoJ3NlcnZpY2U6Jyk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxufVxuIl19
@@ -1,4 +1,15 @@
1
1
  import type { NextFunction, Request, Response } from 'express';
2
+ /** Maximum nesting depth accepted by {@link mongoSanitize}. */
3
+ export declare const MAX_SANITIZE_DEPTH = 10;
4
+ /**
5
+ * Thrown when a request payload nests deeper than {@link MAX_SANITIZE_DEPTH}.
6
+ * The middleware maps this to HTTP 400 instead of silently truncating the walk
7
+ * (which would let operator-shaped keys below the cap slip through unsanitized).
8
+ */
9
+ export declare class PayloadTooDeepError extends Error {
10
+ readonly statusCode: 400;
11
+ constructor(message?: string);
12
+ }
2
13
  /**
3
14
  * MongoDB operator-injection middleware.
4
15
  *
@@ -18,4 +29,4 @@ import type { NextFunction, Request, Response } from 'express';
18
29
  * sanitize a snapshot and pin it onto the request instance with
19
30
  * `Object.defineProperty`, shadowing the getter for all downstream reads.
20
31
  */
21
- export declare function mongoSanitize(): (req: Request, _res: Response, next: NextFunction) => void;
32
+ export declare function mongoSanitize(): (req: Request, res: Response, next: NextFunction) => void;
@@ -1,5 +1,22 @@
1
1
  // Copyright 2026 Pipeline Builder Contributors
2
2
  // SPDX-License-Identifier: Apache-2.0
3
+ import { HttpStatus } from '../constants/http-status.js';
4
+ import { ErrorCode } from '../types/error-codes.js';
5
+ import { sendError } from '../utils/response.js';
6
+ /** Maximum nesting depth accepted by {@link mongoSanitize}. */
7
+ export const MAX_SANITIZE_DEPTH = 10;
8
+ /**
9
+ * Thrown when a request payload nests deeper than {@link MAX_SANITIZE_DEPTH}.
10
+ * The middleware maps this to HTTP 400 instead of silently truncating the walk
11
+ * (which would let operator-shaped keys below the cap slip through unsanitized).
12
+ */
13
+ export class PayloadTooDeepError extends Error {
14
+ statusCode = HttpStatus.BAD_REQUEST;
15
+ constructor(message = `Request payload nesting exceeds the maximum depth of ${MAX_SANITIZE_DEPTH}`) {
16
+ super(message);
17
+ this.name = 'PayloadTooDeepError';
18
+ }
19
+ }
3
20
  /**
4
21
  * MongoDB operator-injection middleware.
5
22
  *
@@ -20,22 +37,32 @@
20
37
  * `Object.defineProperty`, shadowing the getter for all downstream reads.
21
38
  */
22
39
  export function mongoSanitize() {
23
- return (req, _res, next) => {
24
- if (req.body && typeof req.body === 'object')
25
- sanitizeObject(req.body);
26
- if (req.params && typeof req.params === 'object')
27
- sanitizeObject(req.params);
28
- if (req.query && typeof req.query === 'object') {
29
- const q = req.query;
30
- sanitizeObject(q);
31
- // Pin the sanitized snapshot so the Express 5 getter can't re-parse a
32
- // fresh (unsanitized) object on the next access.
33
- try {
34
- Object.defineProperty(req, 'query', { value: q, writable: true, configurable: true, enumerable: true });
40
+ return (req, res, next) => {
41
+ try {
42
+ if (req.body && typeof req.body === 'object')
43
+ sanitizeObject(req.body);
44
+ if (req.params && typeof req.params === 'object')
45
+ sanitizeObject(req.params);
46
+ if (req.query && typeof req.query === 'object') {
47
+ const q = req.query;
48
+ sanitizeObject(q);
49
+ // Pin the sanitized snapshot so the Express 5 getter can't re-parse a
50
+ // fresh (unsanitized) object on the next access.
51
+ try {
52
+ Object.defineProperty(req, 'query', { value: q, writable: true, configurable: true, enumerable: true });
53
+ }
54
+ catch {
55
+ // Express 4 (writable data prop) — the in-place sanitize above sufficed.
56
+ }
35
57
  }
36
- catch {
37
- // Express 4 (writable data prop) — the in-place sanitize above sufficed.
58
+ }
59
+ catch (err) {
60
+ // Reject over-deep payloads with a 400 rather than silently truncating
61
+ // the sanitize walk (which risked leaving deep operator keys in place).
62
+ if (err instanceof PayloadTooDeepError) {
63
+ return sendError(res, err.statusCode, err.message, ErrorCode.VALIDATION_ERROR);
38
64
  }
65
+ throw err;
39
66
  }
40
67
  next();
41
68
  };
@@ -45,9 +72,12 @@ export function mongoSanitize() {
45
72
  // `constructor.prototype` to inject Mongo operators or pollute Object.prototype.
46
73
  const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
47
74
  function sanitizeObject(obj, depth = 0) {
48
- // Cap depth defense against pathological nested input.
49
- if (depth > 10)
50
- return;
75
+ // Reject pathologically nested input rather than silently returning — a
76
+ // silent cap would leave any operator/dot/prototype keys deeper than the
77
+ // cap un-sanitized. The middleware maps this to a 400.
78
+ if (depth > MAX_SANITIZE_DEPTH) {
79
+ throw new PayloadTooDeepError();
80
+ }
51
81
  for (const key of Object.keys(obj)) {
52
82
  if (key.startsWith('$') || key.includes('.') || FORBIDDEN_KEYS.has(key)) {
53
83
  delete obj[key];
@@ -67,4 +97,4 @@ function sanitizeObject(obj, depth = 0) {
67
97
  }
68
98
  }
69
99
  }
70
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9uZ28tc2FuaXRpemUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWlkZGxld2FyZS9tb25nby1zYW5pdGl6ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBSXRDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrQkc7QUFDSCxNQUFNLFVBQVUsYUFBYTtJQUMzQixPQUFPLENBQUMsR0FBWSxFQUFFLElBQWMsRUFBRSxJQUFrQixFQUFFLEVBQUU7UUFDMUQsSUFBSSxHQUFHLENBQUMsSUFBSSxJQUFJLE9BQU8sR0FBRyxDQUFDLElBQUksS0FBSyxRQUFRO1lBQUUsY0FBYyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN2RSxJQUFJLEdBQUcsQ0FBQyxNQUFNLElBQUksT0FBTyxHQUFHLENBQUMsTUFBTSxLQUFLLFFBQVE7WUFBRSxjQUFjLENBQUMsR0FBRyxDQUFDLE1BQWlDLENBQUMsQ0FBQztRQUN4RyxJQUFJLEdBQUcsQ0FBQyxLQUFLLElBQUksT0FBTyxHQUFHLENBQUMsS0FBSyxLQUFLLFFBQVEsRUFBRSxDQUFDO1lBQy9DLE1BQU0sQ0FBQyxHQUFHLEdBQUcsQ0FBQyxLQUFnQyxDQUFDO1lBQy9DLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNsQixzRUFBc0U7WUFDdEUsaURBQWlEO1lBQ2pELElBQUksQ0FBQztnQkFDSCxNQUFNLENBQUMsY0FBYyxDQUFDLEdBQUcsRUFBRSxPQUFPLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztZQUMxRyxDQUFDO1lBQUMsTUFBTSxDQUFDO2dCQUNQLHlFQUF5RTtZQUMzRSxDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksRUFBRSxDQUFDO0lBQ1QsQ0FBQyxDQUFDO0FBQ0osQ0FBQztBQUVELDhFQUE4RTtBQUM5RSw4RUFBOEU7QUFDOUUsaUZBQWlGO0FBQ2pGLE1BQU0sY0FBYyxHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsV0FBVyxFQUFFLGFBQWEsRUFBRSxXQUFXLENBQUMsQ0FBQyxDQUFDO0FBRTFFLFNBQVMsY0FBYyxDQUFDLEdBQTRCLEVBQUUsS0FBSyxHQUFHLENBQUM7SUFDN0QseURBQXlEO0lBQ3pELElBQUksS0FBSyxHQUFHLEVBQUU7UUFBRSxPQUFPO0lBQ3ZCLEtBQUssTUFBTSxHQUFHLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ25DLElBQUksR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsSUFBSSxHQUFHLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLGNBQWMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN4RSxPQUFPLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNoQixTQUFTO1FBQ1gsQ0FBQztRQUNELE1BQU0sQ0FBQyxHQUFHLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNuQixJQUFJLENBQUMsSUFBSSxPQUFPLENBQUMsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUMvQixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDckIsS0FBSyxNQUFNLElBQUksSUFBSSxDQUFDLEVBQUUsQ0FBQztvQkFDckIsSUFBSSxJQUFJLElBQUksT0FBTyxJQUFJLEtBQUssUUFBUTt3QkFBRSxjQUFjLENBQUMsSUFBK0IsRUFBRSxLQUFLLEdBQUcsQ0FBQyxDQUFDLENBQUM7Z0JBQ25HLENBQUM7WUFDSCxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sY0FBYyxDQUFDLENBQTRCLEVBQUUsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQzFELENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHR5cGUgeyBOZXh0RnVuY3Rpb24sIFJlcXVlc3QsIFJlc3BvbnNlIH0gZnJvbSAnZXhwcmVzcyc7XG5cbi8qKlxuICogTW9uZ29EQiBvcGVyYXRvci1pbmplY3Rpb24gbWlkZGxld2FyZS5cbiAqXG4gKiBSZWN1cnNpdmVseSBzdHJpcHMgb2JqZWN0IGtleXMgc3RhcnRpbmcgd2l0aCBgJGAgKE1vbmdvIG9wZXJhdG9ycyBsaWtlXG4gKiBgJG5lYCwgYCRndGAsIGAkd2hlcmVgKSBhbmQga2V5cyBjb250YWluaW5nIGAuYCAoZG90LXdhbGtzKSBmcm9tXG4gKiBgcmVxLmJvZHlgLCBgcmVxLnF1ZXJ5YCwgYW5kIGByZXEucGFyYW1zYC4gV2l0aG91dCB0aGlzLCBhIEpTT04gcmVxdWVzdFxuICogbGlrZSBge1wiZW1haWxcIjoge1wiJG5lXCI6IG51bGx9fWAgYWdhaW5zdCBhIE1vbmdvLWJhY2tlZCBzZXJ2aWNlIGNhbiBtYXRjaFxuICogYW55IGRvY3VtZW50IOKAlCBab2QgY2F0Y2hlcyB0aGUgd3JvbmcgKnR5cGUqIGJ1dCB3b24ndCByZWFjaCBpbnRvIG5lc3RlZFxuICogb2JqZWN0cyB0byBzdHJpcCBvcGVyYXRvci1zaGFwZWQga2V5cy5cbiAqXG4gKiBBcHBseSBCRUZPUkUgYW55IE1vbmdvIHF1ZXJ5IGhhbmRsZXIgKHR5cGljYWxseSByaWdodCBhZnRlclxuICogYGV4cHJlc3MuanNvbigpYCkuIFBvc3RncmVzLWJhY2tlZCBzZXJ2aWNlcyBkb24ndCBuZWVkIGl0LlxuICpcbiAqIGByZXEuYm9keWAgYW5kIGByZXEucGFyYW1zYCBhcmUgcGxhaW4gd3JpdGFibGUgb2JqZWN0cywgc28gdGhleSdyZSBzYW5pdGl6ZWRcbiAqIGluIHBsYWNlLiBPbiBFeHByZXNzIDUgYHJlcS5xdWVyeWAgaXMgYSBHRVRURVIgdGhhdCByZS1wYXJzZXMgdGhlIFVSTCBhbmRcbiAqIHJldHVybnMgYSBmcmVzaCBvYmplY3Qgb24gZXZlcnkgYWNjZXNzIOKAlCBtdXRhdGluZyBpdCBpcyBhIG5vLW9wIOKAlCBzbyB3ZVxuICogc2FuaXRpemUgYSBzbmFwc2hvdCBhbmQgcGluIGl0IG9udG8gdGhlIHJlcXVlc3QgaW5zdGFuY2Ugd2l0aFxuICogYE9iamVjdC5kZWZpbmVQcm9wZXJ0eWAsIHNoYWRvd2luZyB0aGUgZ2V0dGVyIGZvciBhbGwgZG93bnN0cmVhbSByZWFkcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1vbmdvU2FuaXRpemUoKSB7XG4gIHJldHVybiAocmVxOiBSZXF1ZXN0LCBfcmVzOiBSZXNwb25zZSwgbmV4dDogTmV4dEZ1bmN0aW9uKSA9PiB7XG4gICAgaWYgKHJlcS5ib2R5ICYmIHR5cGVvZiByZXEuYm9keSA9PT0gJ29iamVjdCcpIHNhbml0aXplT2JqZWN0KHJlcS5ib2R5KTtcbiAgICBpZiAocmVxLnBhcmFtcyAmJiB0eXBlb2YgcmVxLnBhcmFtcyA9PT0gJ29iamVjdCcpIHNhbml0aXplT2JqZWN0KHJlcS5wYXJhbXMgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pO1xuICAgIGlmIChyZXEucXVlcnkgJiYgdHlwZW9mIHJlcS5xdWVyeSA9PT0gJ29iamVjdCcpIHtcbiAgICAgIGNvbnN0IHEgPSByZXEucXVlcnkgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gICAgICBzYW5pdGl6ZU9iamVjdChxKTtcbiAgICAgIC8vIFBpbiB0aGUgc2FuaXRpemVkIHNuYXBzaG90IHNvIHRoZSBFeHByZXNzIDUgZ2V0dGVyIGNhbid0IHJlLXBhcnNlIGFcbiAgICAgIC8vIGZyZXNoICh1bnNhbml0aXplZCkgb2JqZWN0IG9uIHRoZSBuZXh0IGFjY2Vzcy5cbiAgICAgIHRyeSB7XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShyZXEsICdxdWVyeScsIHsgdmFsdWU6IHEsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUsIGVudW1lcmFibGU6IHRydWUgfSk7XG4gICAgICB9IGNhdGNoIHtcbiAgICAgICAgLy8gRXhwcmVzcyA0ICh3cml0YWJsZSBkYXRhIHByb3ApIOKAlCB0aGUgaW4tcGxhY2Ugc2FuaXRpemUgYWJvdmUgc3VmZmljZWQuXG4gICAgICB9XG4gICAgfVxuICAgIG5leHQoKTtcbiAgfTtcbn1cblxuLy8gUHJvdG90eXBlLXBvbGx1dGlvbiBrZXlzIOKAlCB0aGVzZSBuZXZlciBiZWxvbmcgaW4gSlNPTiByZXF1ZXN0IGJvZGllcywgYW5kIGFcbi8vIGRvd25zdHJlYW0gcmVjdXJzaXZlIG1lcmdlL2Fzc2lnbiBvbiB0aGUgcGFyc2VkIG9iamVjdCBjb3VsZCBvdGhlcndpc2Ugd2Fsa1xuLy8gYGNvbnN0cnVjdG9yLnByb3RvdHlwZWAgdG8gaW5qZWN0IE1vbmdvIG9wZXJhdG9ycyBvciBwb2xsdXRlIE9iamVjdC5wcm90b3R5cGUuXG5jb25zdCBGT1JCSURERU5fS0VZUyA9IG5ldyBTZXQoWydfX3Byb3RvX18nLCAnY29uc3RydWN0b3InLCAncHJvdG90eXBlJ10pO1xuXG5mdW5jdGlvbiBzYW5pdGl6ZU9iamVjdChvYmo6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBkZXB0aCA9IDApOiB2b2lkIHtcbiAgLy8gQ2FwIGRlcHRoIOKAlCBkZWZlbnNlIGFnYWluc3QgcGF0aG9sb2dpY2FsIG5lc3RlZCBpbnB1dC5cbiAgaWYgKGRlcHRoID4gMTApIHJldHVybjtcbiAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMob2JqKSkge1xuICAgIGlmIChrZXkuc3RhcnRzV2l0aCgnJCcpIHx8IGtleS5pbmNsdWRlcygnLicpIHx8IEZPUkJJRERFTl9LRVlTLmhhcyhrZXkpKSB7XG4gICAgICBkZWxldGUgb2JqW2tleV07XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgY29uc3QgdiA9IG9ialtrZXldO1xuICAgIGlmICh2ICYmIHR5cGVvZiB2ID09PSAnb2JqZWN0Jykge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkodikpIHtcbiAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHYpIHtcbiAgICAgICAgICBpZiAoaXRlbSAmJiB0eXBlb2YgaXRlbSA9PT0gJ29iamVjdCcpIHNhbml0aXplT2JqZWN0KGl0ZW0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4sIGRlcHRoICsgMSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNhbml0aXplT2JqZWN0KHYgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4sIGRlcHRoICsgMSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0=
100
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibW9uZ28tc2FuaXRpemUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbWlkZGxld2FyZS9tb25nby1zYW5pdGl6ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBR3RDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDcEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRWpELCtEQUErRDtBQUMvRCxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxFQUFFLENBQUM7QUFFckM7Ozs7R0FJRztBQUNILE1BQU0sT0FBTyxtQkFBb0IsU0FBUSxLQUFLO0lBQ25DLFVBQVUsR0FBRyxVQUFVLENBQUMsV0FBVyxDQUFDO0lBQzdDLFlBQVksT0FBTyxHQUFHLHdEQUF3RCxrQkFBa0IsRUFBRTtRQUNoRyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDZixJQUFJLENBQUMsSUFBSSxHQUFHLHFCQUFxQixDQUFDO0lBQ3BDLENBQUM7Q0FDRjtBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FrQkc7QUFDSCxNQUFNLFVBQVUsYUFBYTtJQUMzQixPQUFPLENBQUMsR0FBWSxFQUFFLEdBQWEsRUFBRSxJQUFrQixFQUFFLEVBQUU7UUFDekQsSUFBSSxDQUFDO1lBQ0gsSUFBSSxHQUFHLENBQUMsSUFBSSxJQUFJLE9BQU8sR0FBRyxDQUFDLElBQUksS0FBSyxRQUFRO2dCQUFFLGNBQWMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDdkUsSUFBSSxHQUFHLENBQUMsTUFBTSxJQUFJLE9BQU8sR0FBRyxDQUFDLE1BQU0sS0FBSyxRQUFRO2dCQUFFLGNBQWMsQ0FBQyxHQUFHLENBQUMsTUFBaUMsQ0FBQyxDQUFDO1lBQ3hHLElBQUksR0FBRyxDQUFDLEtBQUssSUFBSSxPQUFPLEdBQUcsQ0FBQyxLQUFLLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQy9DLE1BQU0sQ0FBQyxHQUFHLEdBQUcsQ0FBQyxLQUFnQyxDQUFDO2dCQUMvQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2xCLHNFQUFzRTtnQkFDdEUsaURBQWlEO2dCQUNqRCxJQUFJLENBQUM7b0JBQ0gsTUFBTSxDQUFDLGNBQWMsQ0FBQyxHQUFHLEVBQUUsT0FBTyxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7Z0JBQzFHLENBQUM7Z0JBQUMsTUFBTSxDQUFDO29CQUNQLHlFQUF5RTtnQkFDM0UsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztZQUNiLHVFQUF1RTtZQUN2RSx3RUFBd0U7WUFDeEUsSUFBSSxHQUFHLFlBQVksbUJBQW1CLEVBQUUsQ0FBQztnQkFDdkMsT0FBTyxTQUFTLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxVQUFVLEVBQUUsR0FBRyxDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztZQUNqRixDQUFDO1lBQ0QsTUFBTSxHQUFHLENBQUM7UUFDWixDQUFDO1FBQ0QsSUFBSSxFQUFFLENBQUM7SUFDVCxDQUFDLENBQUM7QUFDSixDQUFDO0FBRUQsOEVBQThFO0FBQzlFLDhFQUE4RTtBQUM5RSxpRkFBaUY7QUFDakYsTUFBTSxjQUFjLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxXQUFXLEVBQUUsYUFBYSxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUM7QUFFMUUsU0FBUyxjQUFjLENBQUMsR0FBNEIsRUFBRSxLQUFLLEdBQUcsQ0FBQztJQUM3RCx3RUFBd0U7SUFDeEUseUVBQXlFO0lBQ3pFLHVEQUF1RDtJQUN2RCxJQUFJLEtBQUssR0FBRyxrQkFBa0IsRUFBRSxDQUFDO1FBQy9CLE1BQU0sSUFBSSxtQkFBbUIsRUFBRSxDQUFDO0lBQ2xDLENBQUM7SUFDRCxLQUFLLE1BQU0sR0FBRyxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztRQUNuQyxJQUFJLEdBQUcsQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLElBQUksR0FBRyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxjQUFjLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7WUFDeEUsT0FBTyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDaEIsU0FBUztRQUNYLENBQUM7UUFDRCxNQUFNLENBQUMsR0FBRyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbkIsSUFBSSxDQUFDLElBQUksT0FBTyxDQUFDLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDL0IsSUFBSSxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7Z0JBQ3JCLEtBQUssTUFBTSxJQUFJLElBQUksQ0FBQyxFQUFFLENBQUM7b0JBQ3JCLElBQUksSUFBSSxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVE7d0JBQUUsY0FBYyxDQUFDLElBQStCLEVBQUUsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUNuRyxDQUFDO1lBQ0gsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLGNBQWMsQ0FBQyxDQUE0QixFQUFFLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQztZQUMxRCxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbmltcG9ydCB0eXBlIHsgTmV4dEZ1bmN0aW9uLCBSZXF1ZXN0LCBSZXNwb25zZSB9IGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHsgSHR0cFN0YXR1cyB9IGZyb20gJy4uL2NvbnN0YW50cy9odHRwLXN0YXR1cy5qcyc7XG5pbXBvcnQgeyBFcnJvckNvZGUgfSBmcm9tICcuLi90eXBlcy9lcnJvci1jb2Rlcy5qcyc7XG5pbXBvcnQgeyBzZW5kRXJyb3IgfSBmcm9tICcuLi91dGlscy9yZXNwb25zZS5qcyc7XG5cbi8qKiBNYXhpbXVtIG5lc3RpbmcgZGVwdGggYWNjZXB0ZWQgYnkge0BsaW5rIG1vbmdvU2FuaXRpemV9LiAqL1xuZXhwb3J0IGNvbnN0IE1BWF9TQU5JVElaRV9ERVBUSCA9IDEwO1xuXG4vKipcbiAqIFRocm93biB3aGVuIGEgcmVxdWVzdCBwYXlsb2FkIG5lc3RzIGRlZXBlciB0aGFuIHtAbGluayBNQVhfU0FOSVRJWkVfREVQVEh9LlxuICogVGhlIG1pZGRsZXdhcmUgbWFwcyB0aGlzIHRvIEhUVFAgNDAwIGluc3RlYWQgb2Ygc2lsZW50bHkgdHJ1bmNhdGluZyB0aGUgd2Fsa1xuICogKHdoaWNoIHdvdWxkIGxldCBvcGVyYXRvci1zaGFwZWQga2V5cyBiZWxvdyB0aGUgY2FwIHNsaXAgdGhyb3VnaCB1bnNhbml0aXplZCkuXG4gKi9cbmV4cG9ydCBjbGFzcyBQYXlsb2FkVG9vRGVlcEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICByZWFkb25seSBzdGF0dXNDb2RlID0gSHR0cFN0YXR1cy5CQURfUkVRVUVTVDtcbiAgY29uc3RydWN0b3IobWVzc2FnZSA9IGBSZXF1ZXN0IHBheWxvYWQgbmVzdGluZyBleGNlZWRzIHRoZSBtYXhpbXVtIGRlcHRoIG9mICR7TUFYX1NBTklUSVpFX0RFUFRIfWApIHtcbiAgICBzdXBlcihtZXNzYWdlKTtcbiAgICB0aGlzLm5hbWUgPSAnUGF5bG9hZFRvb0RlZXBFcnJvcic7XG4gIH1cbn1cblxuLyoqXG4gKiBNb25nb0RCIG9wZXJhdG9yLWluamVjdGlvbiBtaWRkbGV3YXJlLlxuICpcbiAqIFJlY3Vyc2l2ZWx5IHN0cmlwcyBvYmplY3Qga2V5cyBzdGFydGluZyB3aXRoIGAkYCAoTW9uZ28gb3BlcmF0b3JzIGxpa2VcbiAqIGAkbmVgLCBgJGd0YCwgYCR3aGVyZWApIGFuZCBrZXlzIGNvbnRhaW5pbmcgYC5gIChkb3Qtd2Fsa3MpIGZyb21cbiAqIGByZXEuYm9keWAsIGByZXEucXVlcnlgLCBhbmQgYHJlcS5wYXJhbXNgLiBXaXRob3V0IHRoaXMsIGEgSlNPTiByZXF1ZXN0XG4gKiBsaWtlIGB7XCJlbWFpbFwiOiB7XCIkbmVcIjogbnVsbH19YCBhZ2FpbnN0IGEgTW9uZ28tYmFja2VkIHNlcnZpY2UgY2FuIG1hdGNoXG4gKiBhbnkgZG9jdW1lbnQg4oCUIFpvZCBjYXRjaGVzIHRoZSB3cm9uZyAqdHlwZSogYnV0IHdvbid0IHJlYWNoIGludG8gbmVzdGVkXG4gKiBvYmplY3RzIHRvIHN0cmlwIG9wZXJhdG9yLXNoYXBlZCBrZXlzLlxuICpcbiAqIEFwcGx5IEJFRk9SRSBhbnkgTW9uZ28gcXVlcnkgaGFuZGxlciAodHlwaWNhbGx5IHJpZ2h0IGFmdGVyXG4gKiBgZXhwcmVzcy5qc29uKClgKS4gUG9zdGdyZXMtYmFja2VkIHNlcnZpY2VzIGRvbid0IG5lZWQgaXQuXG4gKlxuICogYHJlcS5ib2R5YCBhbmQgYHJlcS5wYXJhbXNgIGFyZSBwbGFpbiB3cml0YWJsZSBvYmplY3RzLCBzbyB0aGV5J3JlIHNhbml0aXplZFxuICogaW4gcGxhY2UuIE9uIEV4cHJlc3MgNSBgcmVxLnF1ZXJ5YCBpcyBhIEdFVFRFUiB0aGF0IHJlLXBhcnNlcyB0aGUgVVJMIGFuZFxuICogcmV0dXJucyBhIGZyZXNoIG9iamVjdCBvbiBldmVyeSBhY2Nlc3Mg4oCUIG11dGF0aW5nIGl0IGlzIGEgbm8tb3Ag4oCUIHNvIHdlXG4gKiBzYW5pdGl6ZSBhIHNuYXBzaG90IGFuZCBwaW4gaXQgb250byB0aGUgcmVxdWVzdCBpbnN0YW5jZSB3aXRoXG4gKiBgT2JqZWN0LmRlZmluZVByb3BlcnR5YCwgc2hhZG93aW5nIHRoZSBnZXR0ZXIgZm9yIGFsbCBkb3duc3RyZWFtIHJlYWRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbW9uZ29TYW5pdGl6ZSgpIHtcbiAgcmV0dXJuIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbikgPT4ge1xuICAgIHRyeSB7XG4gICAgICBpZiAocmVxLmJvZHkgJiYgdHlwZW9mIHJlcS5ib2R5ID09PSAnb2JqZWN0Jykgc2FuaXRpemVPYmplY3QocmVxLmJvZHkpO1xuICAgICAgaWYgKHJlcS5wYXJhbXMgJiYgdHlwZW9mIHJlcS5wYXJhbXMgPT09ICdvYmplY3QnKSBzYW5pdGl6ZU9iamVjdChyZXEucGFyYW1zIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KTtcbiAgICAgIGlmIChyZXEucXVlcnkgJiYgdHlwZW9mIHJlcS5xdWVyeSA9PT0gJ29iamVjdCcpIHtcbiAgICAgICAgY29uc3QgcSA9IHJlcS5xdWVyeSBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgICAgICAgc2FuaXRpemVPYmplY3QocSk7XG4gICAgICAgIC8vIFBpbiB0aGUgc2FuaXRpemVkIHNuYXBzaG90IHNvIHRoZSBFeHByZXNzIDUgZ2V0dGVyIGNhbid0IHJlLXBhcnNlIGFcbiAgICAgICAgLy8gZnJlc2ggKHVuc2FuaXRpemVkKSBvYmplY3Qgb24gdGhlIG5leHQgYWNjZXNzLlxuICAgICAgICB0cnkge1xuICAgICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShyZXEsICdxdWVyeScsIHsgdmFsdWU6IHEsIHdyaXRhYmxlOiB0cnVlLCBjb25maWd1cmFibGU6IHRydWUsIGVudW1lcmFibGU6IHRydWUgfSk7XG4gICAgICAgIH0gY2F0Y2gge1xuICAgICAgICAgIC8vIEV4cHJlc3MgNCAod3JpdGFibGUgZGF0YSBwcm9wKSDigJQgdGhlIGluLXBsYWNlIHNhbml0aXplIGFib3ZlIHN1ZmZpY2VkLlxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAvLyBSZWplY3Qgb3Zlci1kZWVwIHBheWxvYWRzIHdpdGggYSA0MDAgcmF0aGVyIHRoYW4gc2lsZW50bHkgdHJ1bmNhdGluZ1xuICAgICAgLy8gdGhlIHNhbml0aXplIHdhbGsgKHdoaWNoIHJpc2tlZCBsZWF2aW5nIGRlZXAgb3BlcmF0b3Iga2V5cyBpbiBwbGFjZSkuXG4gICAgICBpZiAoZXJyIGluc3RhbmNlb2YgUGF5bG9hZFRvb0RlZXBFcnJvcikge1xuICAgICAgICByZXR1cm4gc2VuZEVycm9yKHJlcywgZXJyLnN0YXR1c0NvZGUsIGVyci5tZXNzYWdlLCBFcnJvckNvZGUuVkFMSURBVElPTl9FUlJPUik7XG4gICAgICB9XG4gICAgICB0aHJvdyBlcnI7XG4gICAgfVxuICAgIG5leHQoKTtcbiAgfTtcbn1cblxuLy8gUHJvdG90eXBlLXBvbGx1dGlvbiBrZXlzIOKAlCB0aGVzZSBuZXZlciBiZWxvbmcgaW4gSlNPTiByZXF1ZXN0IGJvZGllcywgYW5kIGFcbi8vIGRvd25zdHJlYW0gcmVjdXJzaXZlIG1lcmdlL2Fzc2lnbiBvbiB0aGUgcGFyc2VkIG9iamVjdCBjb3VsZCBvdGhlcndpc2Ugd2Fsa1xuLy8gYGNvbnN0cnVjdG9yLnByb3RvdHlwZWAgdG8gaW5qZWN0IE1vbmdvIG9wZXJhdG9ycyBvciBwb2xsdXRlIE9iamVjdC5wcm90b3R5cGUuXG5jb25zdCBGT1JCSURERU5fS0VZUyA9IG5ldyBTZXQoWydfX3Byb3RvX18nLCAnY29uc3RydWN0b3InLCAncHJvdG90eXBlJ10pO1xuXG5mdW5jdGlvbiBzYW5pdGl6ZU9iamVjdChvYmo6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBkZXB0aCA9IDApOiB2b2lkIHtcbiAgLy8gUmVqZWN0IHBhdGhvbG9naWNhbGx5IG5lc3RlZCBpbnB1dCByYXRoZXIgdGhhbiBzaWxlbnRseSByZXR1cm5pbmcg4oCUIGFcbiAgLy8gc2lsZW50IGNhcCB3b3VsZCBsZWF2ZSBhbnkgb3BlcmF0b3IvZG90L3Byb3RvdHlwZSBrZXlzIGRlZXBlciB0aGFuIHRoZVxuICAvLyBjYXAgdW4tc2FuaXRpemVkLiBUaGUgbWlkZGxld2FyZSBtYXBzIHRoaXMgdG8gYSA0MDAuXG4gIGlmIChkZXB0aCA+IE1BWF9TQU5JVElaRV9ERVBUSCkge1xuICAgIHRocm93IG5ldyBQYXlsb2FkVG9vRGVlcEVycm9yKCk7XG4gIH1cbiAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMob2JqKSkge1xuICAgIGlmIChrZXkuc3RhcnRzV2l0aCgnJCcpIHx8IGtleS5pbmNsdWRlcygnLicpIHx8IEZPUkJJRERFTl9LRVlTLmhhcyhrZXkpKSB7XG4gICAgICBkZWxldGUgb2JqW2tleV07XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgY29uc3QgdiA9IG9ialtrZXldO1xuICAgIGlmICh2ICYmIHR5cGVvZiB2ID09PSAnb2JqZWN0Jykge1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkodikpIHtcbiAgICAgICAgZm9yIChjb25zdCBpdGVtIG9mIHYpIHtcbiAgICAgICAgICBpZiAoaXRlbSAmJiB0eXBlb2YgaXRlbSA9PT0gJ29iamVjdCcpIHNhbml0aXplT2JqZWN0KGl0ZW0gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4sIGRlcHRoICsgMSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHNhbml0aXplT2JqZWN0KHYgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4sIGRlcHRoICsgMSk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0=