@pipeline-builder/api-core 5.2.3 → 5.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/constants/ai-providers.d.ts +3 -22
- package/lib/constants/ai-providers.js +6 -56
- package/lib/errors/app-errors.d.ts +14 -0
- package/lib/errors/app-errors.js +21 -1
- package/lib/helpers/sse-helpers.d.ts +33 -3
- package/lib/helpers/sse-helpers.js +91 -19
- package/lib/middleware/auth.js +6 -3
- package/lib/middleware/deferred-quota-check.d.ts +5 -0
- package/lib/middleware/deferred-quota-check.js +33 -0
- package/lib/middleware/ecosystem-guard.d.ts +3 -3
- package/lib/middleware/ecosystem-guard.js +5 -5
- package/lib/middleware/index.d.ts +5 -2
- package/lib/middleware/index.js +6 -3
- package/lib/middleware/on-behalf.d.ts +37 -0
- package/lib/middleware/on-behalf.js +143 -0
- package/lib/middleware/permission-gates.d.ts +11 -0
- package/lib/middleware/permission-gates.js +7 -1
- package/lib/middleware/quota-exempt-routes.d.ts +36 -0
- package/lib/middleware/quota-exempt-routes.js +47 -0
- package/lib/middleware/route-table.d.ts +104 -0
- package/lib/middleware/route-table.js +72 -2
- package/lib/middleware/service-tokens.d.ts +8 -0
- package/lib/middleware/service-tokens.js +2 -1
- package/lib/middleware/step-up.js +11 -1
- package/lib/services/ai-call-weight.d.ts +24 -0
- package/lib/services/ai-call-weight.js +77 -0
- package/lib/services/audit-context.d.ts +105 -0
- package/lib/services/audit-context.js +134 -0
- package/lib/services/index.d.ts +7 -2
- package/lib/services/index.js +7 -2
- package/lib/services/org-ai-client.d.ts +61 -0
- package/lib/services/org-ai-client.js +112 -0
- package/lib/services/quota-increment-batcher.d.ts +81 -0
- package/lib/services/quota-increment-batcher.js +166 -0
- package/lib/services/quota.d.ts +158 -14
- package/lib/services/quota.js +252 -22
- package/lib/services/remote-audit-client.d.ts +44 -1
- package/lib/services/remote-audit-client.js +106 -20
- package/lib/services/version-vuln-policy.d.ts +174 -0
- package/lib/services/version-vuln-policy.js +242 -0
- package/lib/types/ai-catalog.d.ts +63 -0
- package/lib/types/ai-catalog.js +82 -0
- package/lib/types/ask-proposals.js +6 -6
- package/lib/types/build-catalog.d.ts +154 -0
- package/lib/types/build-catalog.js +158 -0
- package/lib/types/common.d.ts +37 -3
- package/lib/types/common.js +20 -2
- package/lib/types/ecosystem-notifications.d.ts +5 -5
- package/lib/types/ecosystem-notifications.js +9 -3
- package/lib/types/error-codes.d.ts +13 -6
- package/lib/types/error-codes.js +18 -8
- package/lib/types/feature-flags.d.ts +6 -4
- package/lib/types/feature-flags.js +11 -6
- package/lib/types/index.d.ts +6 -4
- package/lib/types/index.js +12 -5
- package/lib/types/metadata-keys.d.ts +6 -0
- package/lib/types/metadata-keys.js +4 -1
- package/lib/types/permissions.d.ts +344 -3
- package/lib/types/permissions.js +596 -21
- package/lib/types/pipeline.d.ts +39 -0
- package/lib/types/pipeline.js +57 -1
- package/lib/types/plugin-health.d.ts +0 -2
- package/lib/types/plugin-health.js +1 -11
- package/lib/types/plugin-scan.d.ts +192 -42
- package/lib/types/plugin-scan.js +159 -43
- package/lib/types/quota-catalog.d.ts +247 -0
- package/lib/types/quota-catalog.js +122 -0
- package/lib/types/quota-tiers.d.ts +118 -0
- package/lib/types/quota-tiers.js +153 -2
- package/lib/types/remote-audit-actions.d.ts +1 -1
- package/lib/types/remote-audit-actions.js +131 -1
- package/lib/types/wire-vocabulary.js +8 -1
- package/lib/utils/index.d.ts +1 -1
- package/lib/utils/index.js +2 -2
- package/lib/utils/response.d.ts +35 -2
- package/lib/utils/response.js +42 -3
- package/lib/validation/ai-schemas.d.ts +27 -0
- package/lib/validation/ai-schemas.js +31 -5
- package/lib/validation/plugin-schemas.d.ts +15 -0
- package/lib/validation/plugin-schemas.js +28 -1
- package/package.json +31 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// Copyright 2026 Pipeline Builder Contributors
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { verifyUserJwt } from './jwt-verify.js';
|
|
4
|
+
import { recordAuthzDenial } from './permission-gates.js';
|
|
4
5
|
import { tagRouteGate } from './route-table.js';
|
|
5
6
|
import { isServiceAccountPrincipal, isServicePrincipal } from './service-tokens.js';
|
|
6
7
|
import { createEnvRedisClient, createRedisReadyGate } from '../services/env-redis.js';
|
|
@@ -142,6 +143,7 @@ async function _requireStepUp(options, req, res, next) {
|
|
|
142
143
|
// so "a machine credential never satisfies an assurance requirement" is a
|
|
143
144
|
// property of this gate, not a side effect of how step-up tokens are minted.
|
|
144
145
|
if (isServiceAccountPrincipal(req)) {
|
|
146
|
+
recordAuthzDenial(req, 'step-up (STEP_UP_NOT_AVAILABLE: service account)');
|
|
145
147
|
sendError(res, 403, 'A service account cannot perform this action — it requires a person to re-verify', 'STEP_UP_NOT_AVAILABLE');
|
|
146
148
|
return;
|
|
147
149
|
}
|
|
@@ -160,10 +162,16 @@ async function _requireStepUp(options, req, res, next) {
|
|
|
160
162
|
payload = await verifyStepUpToken(token);
|
|
161
163
|
}
|
|
162
164
|
catch {
|
|
165
|
+
// A presented-but-unverifiable token (forged, expired, wrong key) is on the
|
|
166
|
+
// trail; a MISSING one (STEP_UP_REQUIRED above) is the UI's normal first
|
|
167
|
+
// attempt and is not.
|
|
168
|
+
recordAuthzDenial(req, 'step-up (STEP_UP_INVALID)');
|
|
163
169
|
sendError(res, 401, 'Step-up token invalid or expired', 'STEP_UP_INVALID');
|
|
164
170
|
return;
|
|
165
171
|
}
|
|
166
172
|
if (payload.sub !== callerSub) {
|
|
173
|
+
// Someone else's step-up token replayed on this session — never a UI bug.
|
|
174
|
+
recordAuthzDenial(req, 'step-up (STEP_UP_MISMATCH)');
|
|
167
175
|
sendError(res, 401, 'Step-up token does not match session', 'STEP_UP_MISMATCH');
|
|
168
176
|
return;
|
|
169
177
|
}
|
|
@@ -171,11 +179,13 @@ async function _requireStepUp(options, req, res, next) {
|
|
|
171
179
|
// earned by the wrong factor can still be spent on a route that accepts it —
|
|
172
180
|
// burning it here would make the refusal destructive as well as confusing.
|
|
173
181
|
if (options.methods && !(payload.method && options.methods.includes(payload.method))) {
|
|
182
|
+
recordAuthzDenial(req, `step-up (STEP_UP_METHOD_REQUIRED: ${options.methods.join(' or ')}, got ${payload.method ?? 'none'})`);
|
|
174
183
|
sendError(res, 401, 'This action must be confirmed with a passkey or an authenticator code', 'STEP_UP_METHOD_REQUIRED', { methods: [...options.methods] });
|
|
175
184
|
return;
|
|
176
185
|
}
|
|
177
186
|
try {
|
|
178
187
|
if (!(await consumeStepUpJti(payload.jti, payload.exp))) {
|
|
188
|
+
recordAuthzDenial(req, 'step-up (STEP_UP_REPLAY)');
|
|
179
189
|
sendError(res, 401, 'Step-up token already used or expired', 'STEP_UP_REPLAY');
|
|
180
190
|
return;
|
|
181
191
|
}
|
|
@@ -187,4 +197,4 @@ async function _requireStepUp(options, req, res, next) {
|
|
|
187
197
|
}
|
|
188
198
|
next();
|
|
189
199
|
}
|
|
190
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC11cC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9taWRkbGV3YXJlL3N0ZXAtdXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQXFCdEMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUseUJBQXlCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNwRixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsb0JBQW9CLEVBQXdCLE1BQU0sMEJBQTBCLENBQUM7QUFDNUcsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFakQsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQ3ZDLE1BQU0sTUFBTSxHQUFHLGlCQUFpQixDQUFDO0FBU2pDOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQTRCLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBcUJwRjs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxpQkFBaUIsQ0FBQyxLQUFhO0lBQ25ELE1BQU0sT0FBTyxHQUFHLE1BQU0sYUFBYSxDQUFxQixLQUFLLENBQUMsQ0FBQztJQUUvRCxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssU0FBUyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUMvRCxNQUFNLElBQUksS0FBSyxDQUFDLHVCQUF1QixDQUFDLENBQUM7SUFDM0MsQ0FB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QUFDO1FBQ2hGLE9BQU87SUFDVCxDQUFDO0lBRUQscUVBQXFFO0lBQ3JFLDZFQUE2RTtJQUM3RSwyRUFBMkU7SUFDM0UsSUFBSSxPQUFPLENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxJQUFJLE9BQU8sQ0FBQyxPQUFPLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxFQUFFLENBQUM7UUFDckYsU0FBUyxDQUNQLEdBQUcsRUFBRSxHQUFHLEVBQ1IsdUVBQXVFLEVBQ3ZFLHlCQUF5QixFQUN6QixFQUFFLE9BQU8sRUFBRSxDQUFDLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQ2xDLENBQUM7UUFDRixPQUFPO0lBQ1QsQ0FBQztJQUVELElBQUksQ0FBQztRQUNILElBQUksQ0FBQyxDQUFDLE1BQU0sZ0JBQWdCLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQ3hELFNBQVMsQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLHVDQUF1QyxFQUFFLGdCQUFnQixDQUFDLENBQUM7WUFDL0UsT0FBTztRQUNULENBQUM7SUFDSCxDQUFDO0lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNiLE1BQU0sQ0FBQyxLQUFLLENBQUMsNkJBQTZCLEVBQUUsRUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUNwRSxTQUFTLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSw2QkFBNkIsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1FBQ3RFLE9BQU87SUFDVCxDQUFDO0lBRUQsSUFBSSxFQUFFLENBQUM7QUFDVCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogYHJlcXVpcmVTdGVwVXBgIOKAlCBhIHNoYXJlZCBzdGVwLXVwIChyZWNlbnQtcGFzc3dvcmQtcmV2ZXJpZnkpIGdhdGUgZm9yIHRoZVxuICogc3RhdGVsZXNzIGFwaSBzZXJ2aWNlcywgbWlycm9yaW5nIHRoZSBwbGF0Zm9ybSBtaWRkbGV3YXJlIG9mIHRoZSBzYW1lIG5hbWUuXG4gKlxuICogRmxvdzogdGhlIFVJIGhpdHMgYFBPU1QgL2FwaS9hdXRoL3N0ZXAtdXBgIChwbGF0Zm9ybSkgdG8gcmUtdmVyaWZ5IHRoZSB1c2VyO1xuICogcGxhdGZvcm0gbWludHMgYSBzaG9ydC1saXZlZCAoNjBzKSBgc3RlcC11cGAgSldUIHdpdGggdGhlIFNBTUUgRVMyNTYgc2lnbmluZ1xuICoga2V5IGl0IG1pbnRzIGFjY2VzcyB0b2tlbnMgd2l0aCwgc28gdGhlc2Ugc2VydmljZXMgdmVyaWZ5IGl0IHRocm91Z2ggdGhlIHNhbWVcbiAqIEpXS1MuIFRoZSBVSVxuICogcmVwbGF5cyBpdCBhcyB0aGUgYFgtU3RlcC1VcC1Ub2tlbmAgaGVhZGVyIG9uIHRoZSBkZXN0cnVjdGl2ZS9zZW5zaXRpdmUgY2FsbDtcbiAqIHRoaXMgbWlkZGxld2FyZSB2ZXJpZmllcyBpdCwgYmluZHMgaXQgdG8gdGhlIGNhbGxlciAoYHN1YmAgbWF0Y2gpLCBhbmRcbiAqIGNvbnN1bWVzIGl0cyBganRpYCBvbmNlIChSZWRpcy1iYWNrZWQgY3Jvc3MtaW5zdGFuY2Ugd2hlbiBjb25maWd1cmVkLCBlbHNlIGFcbiAqIGJvdW5kZWQgcHJvY2Vzcy1sb2NhbCBzZXQpIHNvIGEgcmVwbGF5IGluc2lkZSB0aGUgVFRMIGlzIHJlamVjdGVkLlxuICpcbiAqIFdIWSBoZXJlOiByZXN0b3JlIGVuZHBvaW50cyBvbiB0aGUgYXBpIHNlcnZpY2VzIChwaXBlbGluZS9wbHVnaW4vLi4uKSBhcmVcbiAqIHN0ZXAtdXAtZ2F0ZWQsIHNvIHRoZSB2ZXJpZnkgKyBzaW5nbGUtdXNlIGp0aSBsaXZlIGluIGFwaS1jb3JlIHdoZXJlIGFueVxuICogc2VydmljZSBjYW4gcmVxdWlyZSB0aGVtLlxuICovXG5cbmltcG9ydCB0eXBlIHsgUmVxdWVzdCwgUmVzcG9uc2UsIE5leHRGdW5jdGlvbiB9IGZyb20gJ2V4cHJlc3MnO1xuaW1wb3J0IHsgdmVyaWZ5VXNlckp3dCB9IGZyb20gJy4vand0LXZlcmlmeS5qcyc7XG5pbXBvcnQgeyB0YWdSb3V0ZUdhdGUgfSBmcm9tICcuL3JvdXRlLXRhYmxlLmpzJztcbmltcG9ydCB7IGlzU2VydmljZUFjY291bnRQcmluY2lwYWwsIGlzU2VydmljZVByaW5jaXBhbCB9IGZyb20gJy4vc2VydmljZS10b2tlbnMuanMnO1xuaW1wb3J0IHsgY3JlYXRlRW52UmVkaXNDbGllbnQsIGNyZWF0ZVJlZGlzUmVhZHlHYXRlLCB0eXBlIFJlYWR5QXdhcmVSZWRpcyB9IGZyb20gJy4uL3NlcnZpY2VzL2Vudi1yZWRpcy5qcyc7XG5pbXBvcnQgeyBnZXRIZWFkZXJTdHJpbmcgfSBmcm9tICcuLi91dGlscy9oZWFkZXJzLmpzJztcbmltcG9ydCB7IGNyZWF0ZUxvZ2dlciB9IGZyb20gJy4uL3V0aWxzL2xvZ2dlci5qcyc7XG5pbXBvcnQgeyBzZW5kRXJyb3IgfSBmcm9tICcuLi91dGlscy9yZXNwb25zZS5qcyc7XG5cbmNvbnN0IGxvZ2dlciA9IGNyZWF0ZUxvZ2dlcignc3RlcC11cCcpO1xuY29uc3QgSEVBREVSID0gJ3gtc3RlcC11cC10b2tlbic7XG5cbi8qKlxuICogSG93IGEgc3RlcC11cCB0b2tlbiB3YXMgZWFybmVkLiBNaXJyb3JzIHBsYXRmb3JtJ3MgYFN0ZXBVcE1ldGhvZGA7IGtlcHQgaGVyZVxuICogYXMgaXRzIG93biB1bmlvbiBzbyBhIHZlcmlmaWVyIGNhbiBuYW1lIHRoZSBmYWN0b3JzIGl0IGFjY2VwdHMgd2l0aG91dFxuICogaW1wb3J0aW5nIHBsYXRmb3JtLlxuICovXG5leHBvcnQgdHlwZSBTdGVwVXBNZXRob2QgPSAncGFzc3dvcmQnIHwgJ3dlYmF1dGhuJyB8ICd0b3RwJyB8ICdyZWF1dGgnO1xuXG4vKipcbiAqIFRoZSBmYWN0b3JzIHRoYXQgY291bnQgYXMgYSBTRUNPTkQgRkFDVE9SLCBmb3Igcm91dGVzIHRoYXQgbWF5IG9ubHkgYmVcbiAqIHVubG9ja2VkIGJ5IG9uZSAoIzg6IGltcGVyc29uYXRpb24sIEtNUywgSWRQIHNldHRpbmdzLCBwbGF0Zm9ybSBhZG1pbikuXG4gKlxuICogQSBwYXNzd29yZCBvciBhIHByb3ZpZGVyIHJlLWF1dGggcHJvdmVzIHRoZSBzYW1lIHNpbmdsZSBmYWN0b3IgdGhlIHNlc3Npb24gd2FzXG4gKiBhbHJlYWR5IG9wZW5lZCB3aXRoLCBzbyBvbiB0aG9zZSByb3V0ZXMgdGhleSBhcmUgbm90IGVub3VnaDogdGhlIHBvaW50IGlzIHRoYXRcbiAqIHNvbWVvbmUgaG9sZGluZyBvbmx5IGEgc3RvbGVuIHNlc3Npb24g4oCUIG9yIG9ubHkgYSBzdG9sZW4gcGFzc3dvcmQg4oCUIGNhbm5vdFxuICogcHJvY2VlZC5cbiAqL1xuZXhwb3J0IGNvbnN0IFNUUk9OR19TVEVQX1VQX01FVEhPRFM6IHJlYWRvbmx5IFN0ZXBVcE1ldGhvZFtdID0gWyd3ZWJhdXRobicsICd0b3RwJ107XG5cbi8qKiBQYXlsb2FkIG9mIGEgcGxhdGZvcm0taXNzdWVkIHN0ZXAtdXAgdG9rZW4gKHNlZSBwbGF0Zm9ybSBpc3N1ZVN0ZXBVcFRva2VuKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RlcFVwVG9rZW5QYXlsb2FkIHtcbiAgdHlwZTogJ3N0ZXAtdXAnO1xuICBzdWI6IHN0cmluZztcbiAganRpOiBzdHJpbmc7XG4gIC8qKiBXaGljaCBmYWN0b3IgZWFybmVkIGl0LiBBYnNlbnQgb25seSBvbiBhIHRva2VuIG1pbnRlZCBiZWZvcmUgdGhlIGNsYWltXG4gICAqICBleGlzdGVkLCB3aGljaCBhIG1ldGhvZC1yZXN0cmljdGVkIGdhdGUgdHJlYXRzIGFzIFwibm90IHByb3ZlblwiLiAqL1xuICBtZXRob2Q/OiBTdGVwVXBNZXRob2Q7XG4gIGlhdDogbnVtYmVyO1xuICBleHA6IG51bWJlcjtcbn1cblxuLyoqIE9wdGlvbnMgZm9yIHtAbGluayByZXF1aXJlU3RlcFVwfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVxdWlyZVN0ZXBVcE9wdGlvbnMge1xuICAvKiogUmVzdHJpY3Qgd2hpY2ggZmFjdG9ycyBtYXkgZWFybiB0aGUgc3RlcC11cCAoZS5nLiB7QGxpbmsgU1RST05HX1NURVBfVVBfTUVUSE9EU30pLlxuICAgKiAgT21pdHRlZCBtZWFucyBhbnkgZmFjdG9yIHRoZSBwbGF0Zm9ybSB3aWxsIGlzc3VlIGEgdG9rZW4gZm9yLiAqL1xuICBtZXRob2RzPzogcmVhZG9ubHkgU3RlcFVwTWV0aG9kW107XG59XG5cbi8qKlxuICogVmVyaWZ5IGEgc3RlcC11cCB0b2tlbjogYSB2YWxpZCBFUzI1NiBzaWduYXR1cmUgZnJvbSBvbmUgb2YgcGxhdGZvcm0nc1xuICogcHVibGlzaGVkIHNpZ25pbmcga2V5cywgaXNzdWVyIGFuZCBhdWRpZW5jZSB3aGVuIGNvbmZpZ3VyZWQsIEFORCB0aGVcbiAqIGB0eXBlOiAnc3RlcC11cCdgICsgYGp0aWAgY2xhaW1zIOKAlCBhIHBsYWluIGFjY2VzcyB0b2tlbiBpcyBzaWduZWQgYnkgdGhlIHNhbWVcbiAqIGtleSBhbmQgY2FycmllcyB0aGUgc2FtZSBgc3ViYCwgc28gd2l0aG91dCBhc3NlcnRpbmcgdGhlIHN0ZXAtdXAgc2hhcGUgaXRcbiAqIHdvdWxkIGJ5cGFzcyB0aGUgZ2F0ZS4gVGhyb3dzIG9uIGFueSBmYWlsdXJlIChhbiB1bmZldGNoYWJsZSBrZXkgc2V0IGluY2x1ZGVkOlxuICogYW4gdW52ZXJpZmlhYmxlIHRva2VuIGlzIG5vdCBhIHN0ZXAtdXApLiBEb2VzIE5PVCBiaW5kIHRvIGEgY2FsbGVyIOKAlFxuICogYHJlcXVpcmVTdGVwVXBgIGRvZXMgdGhlIGBzdWJgIG1hdGNoIGFuZCBzaW5nbGUtdXNlIGNvbnN1bWUuXG4gKlxuICogRGVsZWdhdGVzIHRvIGByZXF1aXJlQXV0aGAncyBvd24gcHJpbWl0aXZlIChgdmVyaWZ5VXNlckp3dGApIHJhdGhlciB0aGFuXG4gKiByZS1pbXBsZW1lbnRpbmcgaXQuIFRoZSBoYW5kLXJvbGxlZCBjb3B5IHRoaXMgcmVwbGFjZWQgZHJvcHBlZCBUV08gb2YgaXRzXG4gKiBndWFyZHM6IGl0IG5ldmVyIHBpbm5lZCBpc3N1ZXIvYXVkaWVuY2UsIGFuZCBpdHMgcHJldmlvdXMtc2VjcmV0IHJldHJ5IGhhZCBub1xuICogZXhwaXJ5L25vdC1iZWZvcmUgY2FydmUtb3V0LCBzbyBhbiBFWFBJUkVEIHRva2VuIHN1cmZhY2VkIGFzIGEgc2lnbmF0dXJlIGVycm9yLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdmVyaWZ5U3RlcFVwVG9rZW4odG9rZW46IHN0cmluZyk6IFByb21pc2U8U3RlcFVwVG9rZW5QYXlsb2FkPiB7XG4gIGNvbnN0IHBheWxvYWQgPSBhd2FpdCB2ZXJpZnlVc2VySnd0PFN0ZXBVcFRva2VuUGF5bG9hZD4odG9rZW4pO1xuXG4gIGlmIChwYXlsb2FkLnR5cGUgIT09ICdzdGVwLXVwJyB8fCAhcGF5bG9hZC5qdGkgfHwgIXBheWxvYWQuc3ViKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdJTlZBTElEX1NURVBfVVBfVE9LRU4nKTtcbiAgfVxuICByZXR1cm4gcGF5bG9hZDtcbn1cblxuLy8gLS0gU2luZ2xlLXVzZSBqdGkgc3RvcmUgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbi8vIFJlZGlzIFNFVCBOWCBFWCB3aGVuIFJlZGlzIGlzIGNvbmZpZ3VyZWQgKGNyb3NzLWluc3RhbmNlIHNpbmdsZS11c2UpOyBlbHNlIGFcbi8vIGJvdW5kZWQgcHJvY2Vzcy1sb2NhbCBtYXAgd2l0aCBUVEwgc3dlZXAgKHBlci1wcm9jZXNzKS4gQSBzdGVwLXVwIHRva2VuIGlzXG4vLyA2MHMtbGl2ZWQuIFdoZW4gUmVkaXMgSVMgY29uZmlndXJlZCBpdCdzIHRoZSBhdXRob3JpdGF0aXZlIHN0b3JlOiBhIFJlZGlzXG4vLyBlcnJvciBGQUlMUyBDTE9TRUQgKHRocm93cyDihpIgU1RFUF9VUF9JTlZBTElELCB1c2VyIHJlLXZlcmlmaWVzKSByYXRoZXIgdGhhblxuLy8gZGVncmFkaW5nIHRvIHRoZSBwZXItaW5zdGFuY2UgbWVtIGd1YXJkLCB3aGljaCB3b3VsZCBhY2NlcHQgYSBjcm9zcy1pbnN0YW5jZVxuLy8gcmVwbGF5IGR1cmluZyB0aGUgb3V0YWdlLiBUaGUgbWVtIGd1YXJkIGlzIHVzZWQgT05MWSB3aGVuIFJlZGlzIGlzIGFic2VudC5cblxudHlwZSBKdGlSZWRpcyA9IFJlYWR5QXdhcmVSZWRpcyAmIHsgc2V0OiAoLi4uYXJnczogdW5rbm93bltdKSA9PiBQcm9taXNlPHVua25vd24+IH07XG5sZXQgX3JlZGlzOiBKdGlSZWRpcyB8IG51bGwgfCB1bmRlZmluZWQ7XG5sZXQgX3JlZGlzUmVhZHk6ICgoKSA9PiBQcm9taXNlPHZvaWQ+KSB8IHVuZGVmaW5lZDtcbi8qKlxuICogVGhlIGp0aSBjbGllbnQsIGJ1aWx0IGxhemlseS4gVGhlIGVudiBjbGllbnQgaGFzIG5vIG9mZmxpbmUgcXVldWUsIHNvIGEgU0VUIG9uXG4gKiBhIGNvbm5lY3Rpb24gdGhhdCBpc24ndCB1cCB5ZXQgaXMgcmVqZWN0ZWQg4oCUIHRoZSBGSVJTVCBzdGVwLXVwIG9uIGV2ZXJ5IHBvZFxuICogd291bGQgZmFpbC4gV2FpdCAoYm91bmRlZCwgbmV2ZXIgcmVqZWN0aW5nKSBmb3IgcmVhZGluZXNzIGJlZm9yZVxuICogaGFuZGluZyBpdCBvdXQ7IGEgZ2VudWluZWx5IGRvd24gUmVkaXMgc3RpbGwgZmFpbHMgY2xvc2VkIG9uIHRoZSBTRVQgYmVsb3cuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHJlZGlzKCk6IFByb21pc2U8SnRpUmVkaXMgfCBudWxsPiB7XG4gIGlmIChfcmVkaXMgPT09IHVuZGVmaW5lZCkge1xuICAgIF9yZWRpcyA9IGNyZWF0ZUVudlJlZGlzQ2xpZW50PEp0aVJlZGlzPignc3RlcC11cC1qdGknKTtcbiAgICBfcmVkaXNSZWFkeSA9IF9yZWRpcyA/IGNyZWF0ZVJlZGlzUmVhZHlHYXRlKF9yZWRpcykgOiB1bmRlZmluZWQ7XG4gIH1cbiAgaWYgKF9yZWRpc1JlYWR5KSBhd2FpdCBfcmVkaXNSZWFkeSgpO1xuICByZXR1cm4gX3JlZGlzO1xufVxuXG5jb25zdCBtZW1KdGkgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpOyAvLyBqdGkgLT4gZXhwaXJ5IGVwb2NoIG1zXG5jb25zdCBtZW1Td2VlcCA9IHNldEludGVydmFsKCgpID0+IHtcbiAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgZm9yIChjb25zdCBbanRpLCBleHBdIG9mIG1lbUp0aSkgaWYgKGV4cCA8PSBub3cpIG1lbUp0aS5kZWxldGUoanRpKTtcbn0sIDMwXzAwMCk7XG5tZW1Td2VlcC51bnJlZj8uKCk7XG5cbi8qKlxuICogSGFyZCBjZWlsaW5nIG9uIHRoZSBwcm9jZXNzLWxvY2FsIGp0aSBzZXQuXG4gKlxuICogVGhlIDMwcyBzd2VlcCBhbG9uZSBkb2VzIE5PVCBib3VuZCBpdDogZW50cmllcyBvbmx5IGxlYXZlIG9uY2UgdGhlaXIgdG9rZW4nc1xuICogVFRMIGhhcyBwYXNzZWQsIHNvIGEgYnVyc3Qgb2Ygc3RlcC11cCB0cmFmZmljIChvciBhIGZsb29kIG9mIGRpc3RpbmN0IGZvcmdlZFxuICoganRpcyBvbiBhIFJlZGlzLWxlc3MgZGVwbG95bWVudCkgZ3Jvd3MgdGhlIG1hcCBmYXN0ZXIgdGhhbiB0aGUgc3dlZXAgZHJhaW5zXG4gKiBpdC4gVGhpcyBpcyBhIHJlcGxheSBndWFyZCwgc28gc2hlZGRpbmcgdGhlIE9MREVTVCBlbnRyaWVzIGlzIHRoZSBzYWZlXG4gKiBkaXJlY3Rpb246IHRoZSB3b3JzdCBjYXNlIGlzIHRoYXQgYSBsb25nLWV4cGlyZWQganRpIGNvdWxkIGJlIHJlcGxheWVkLCBhbmRcbiAqIGV4cGlyeSBpcyBlbmZvcmNlZCBpbmRlcGVuZGVudGx5IGJ5IHRoZSB0b2tlbidzIG93biBgZXhwYC5cbiAqL1xuY29uc3QgTUVNX0pUSV9NQVggPSAxMF8wMDA7XG5cbi8qKiBEcm9wIHRoZSBzb29uZXN0LXRvLWV4cGlyZSBlbnRyaWVzIHVudGlsIHRoZSBtYXAgaXMgdW5kZXIgdGhlIGNlaWxpbmcuICovXG5mdW5jdGlvbiBldmljdE9sZGVzdEp0aSgpOiB2b2lkIHtcbiAgaWYgKG1lbUp0aS5zaXplIDwgTUVNX0pUSV9NQVgpIHJldHVybjtcbiAgY29uc3QgYnlFeHBpcnkgPSBbLi4ubWVtSnRpLmVudHJpZXMoKV0uc29ydCgoYSwgYikgPT4gYVsxXSAtIGJbMV0pO1xuICBjb25zdCBleGNlc3MgPSBtZW1KdGkuc2l6ZSAtIE1FTV9KVElfTUFYICsgMTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBleGNlc3M7IGkgKz0gMSkgbWVtSnRpLmRlbGV0ZShieUV4cGlyeVtpXVswXSk7XG59XG5cbi8qKlxuICogQ29uc3VtZSBhIHN0ZXAtdXAgYGp0aWAgZXhhY3RseSBvbmNlLiBSZXR1cm5zIHRydWUgaWYgdGhpcyBjYWxsIGNsYWltZWQgaXRcbiAqIChmaXJzdCB1c2UpLCBmYWxzZSBpZiBpdCB3YXMgYWxyZWFkeSBjb25zdW1lZCAocmVwbGF5KS4gYGV4cEVwb2NoU2Vjb25kc2AgaXNcbiAqIHRoZSB0b2tlbidzIGBleHBgLCBzbyB0aGUgbWFya2VyIGF1dG8tZXhwaXJlcyB3aXRoIHRoZSB0b2tlbi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNvbnN1bWVTdGVwVXBKdGkoanRpOiBzdHJpbmcsIGV4cEVwb2NoU2Vjb25kczogbnVtYmVyKTogUHJvbWlzZTxib29sZWFuPiB7XG4gIGNvbnN0IHR0bFNlY29uZHMgPSBNYXRoLm1heCgxLCBleHBFcG9jaFNlY29uZHMgLSBNYXRoLmZsb29yKERhdGUubm93KCkgLyAxMDAwKSk7XG4gIGNvbnN0IGNsaWVudCA9IGF3YWl0IHJlZGlzKCk7XG4gIGlmIChjbGllbnQpIHtcbiAgICAvLyBSZWRpcyBjb25maWd1cmVkIOKHkiBhdXRob3JpdGF0aXZlIGNyb3NzLWluc3RhbmNlIHN0b3JlLiBTRVQgTlggRVgg4oaSICdPSydcbiAgICAvLyB3aGVuIG5ld2x5IHNldCwgbnVsbCB3aGVuIGFscmVhZHkgY29uc3VtZWQuIEEgdGhyb3duIFJlZGlzIGVycm9yIGlzIE5PVFxuICAgIC8vIGNhdWdodCBoZXJlOiBpdCBwcm9wYWdhdGVzIHNvIGByZXF1aXJlU3RlcFVwYCBmYWlscyBjbG9zZWQgKFNURVBfVVBfSU5WQUxJRClcbiAgICAvLyBpbnN0ZWFkIG9mIHNpbGVudGx5IGRlZ3JhZGluZyB0byB0aGUgcGVyLWluc3RhbmNlIG1lbSBndWFyZC5cbiAgICBjb25zdCByZXMgPSBhd2FpdCBjbGllbnQuc2V0KGBzdGVwdXA6anRpOiR7anRpfWAsICcxJywgJ0VYJywgdHRsU2Vjb25kcywgJ05YJyk7XG4gICAgcmV0dXJuIHJlcyA9PT0gJ09LJztcbiAgfVxuICAvLyBObyBSZWRpcyDih5Igc2luZ2xlLWluc3RhbmNlIGRlcGxveW1lbnQ7IHRoZSBwcm9jZXNzLWxvY2FsIG1hcCBJUyB0aGUgc3RvcmUuXG4gIGlmIChtZW1KdGkuaGFzKGp0aSkpIHJldHVybiBmYWxzZTtcbiAgZXZpY3RPbGRlc3RKdGkoKTtcbiAgbWVtSnRpLnNldChqdGksIERhdGUubm93KCkgKyB0dGxTZWNvbmRzICogMTAwMCk7XG4gIHJldHVybiB0cnVlO1xufVxuXG4vKipcbiAqIEV4cHJlc3MgbWlkZGxld2FyZTogcmVxdWlyZSBhIHZhbGlkLCBjYWxsZXItYm91bmQsIHNpbmdsZS11c2Ugc3RlcC11cCB0b2tlbiBpblxuICogdGhlIGBYLVN0ZXAtVXAtVG9rZW5gIGhlYWRlci4gTXVzdCBydW4gQUZURVIgYHJlcXVpcmVBdXRoYCAobmVlZHMgYHJlcS51c2VyYCkuXG4gKlxuICogVXNlIGRpcmVjdGx5IChgcm91dGVyLnBvc3QoJy94JywgcmVxdWlyZUF1dGgsIHJlcXVpcmVTdGVwVXAsIGgpYCkgZm9yIHRoZVxuICogb3JkaW5hcnkgYW55LWZhY3RvciBnYXRlLCBvciBjYWxsIGl0IHdpdGggYHsgbWV0aG9kcyB9YCB0byBkZW1hbmQgdGhhdCB0aGVcbiAqIGNvbmZpcm1hdGlvbiB3YXMgZWFybmVkIGJ5IGEgc3BlY2lmaWMgZmFjdG9yIOKAlCBgcmVxdWlyZVN0ZXBVcCh7IG1ldGhvZHM6XG4gKiBTVFJPTkdfU1RFUF9VUF9NRVRIT0RTIH0pYCBvbiB0aGUgcm91dGVzIHdoZXJlIGEgcGFzc3dvcmQgcmUtcHJvbXB0IGlzIG5vdCBhXG4gKiBtZWFuaW5nZnVsIHNlY29uZCBwcm9vZi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcXVpcmVTdGVwVXAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pOiBQcm9taXNlPHZvaWQ+O1xuZXhwb3J0IGZ1bmN0aW9uIHJlcXVpcmVTdGVwVXAob3B0aW9uczogUmVxdWlyZVN0ZXBVcE9wdGlvbnMpOiAocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pID0+IHZvaWQ7XG5leHBvcnQgZnVuY3Rpb24gcmVxdWlyZVN0ZXBVcChcbiAgcmVxT3JPcHRpb25zOiBSZXF1ZXN0IHwgUmVxdWlyZVN0ZXBVcE9wdGlvbnMsXG4gIHJlcz86IFJlc3BvbnNlLFxuICBuZXh0PzogTmV4dEZ1bmN0aW9uLFxuKTogUHJvbWlzZTx2b2lkPiB8ICgocmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pID0+IHZvaWQpIHtcbiAgLy8gVGhlIGRpcmVjdCBmb3JtIFJFVFVSTlMgdGhlIHByb21pc2UgKEV4cHJlc3MgaWdub3JlcyBpdDsgYSB0ZXN0IGF3YWl0cyBpdCksXG4gIC8vIHNvIGNvbXBvc2luZyB0aGUgZ2F0ZSBhcyBgcm91dGVyLnBvc3QoJy94JywgcmVxdWlyZVN0ZXBVcCwgaClgIGJlaGF2ZXNcbiAgLy8gZXhhY3RseSBhcyBpdCBkaWQgYmVmb3JlIHRoZSBvcHRpb25zIGZvcm0gZXhpc3RlZC5cbiAgaWYgKHJlcyAmJiBuZXh0ICYmICdoZWFkZXJzJyBpbiByZXFPck9wdGlvbnMpIHtcbiAgICByZXR1cm4gX3JlcXVpcmVTdGVwVXAoe30sIHJlcU9yT3B0aW9ucyBhcyBSZXF1ZXN0LCByZXMsIG5leHQpO1xuICB9XG4gIGNvbnN0IG9wdGlvbnMgPSByZXFPck9wdGlvbnMgYXMgUmVxdWlyZVN0ZXBVcE9wdGlvbnM7XG4gIHJldHVybiB0YWdSb3V0ZUdhdGUoXG4gICAgKHJlcUlubmVyOiBSZXF1ZXN0LCByZXNJbm5lcjogUmVzcG9uc2UsIG5leHRJbm5lcjogTmV4dEZ1bmN0aW9uKSA9PiB7XG4gICAgICB2b2lkIF9yZXF1aXJlU3RlcFVwKG9wdGlvbnMsIHJlcUlubmVyLCByZXNJbm5lciwgbmV4dElubmVyKTtcbiAgICB9LFxuICAgIHsga2luZDogJ3N0ZXBVcCcsIC4uLihvcHRpb25zLm1ldGhvZHMgPyB7IG1ldGhvZHM6IFsuLi5vcHRpb25zLm1ldGhvZHNdIH0gOiB7fSkgfSxcbiAgKTtcbn1cbnRhZ1JvdXRlR2F0ZShyZXF1aXJlU3RlcFVwLCB7IGtpbmQ6ICdzdGVwVXAnIH0pO1xuXG5hc3luYyBmdW5jdGlvbiBfcmVxdWlyZVN0ZXBVcChvcHRpb25zOiBSZXF1aXJlU3RlcFVwT3B0aW9ucywgcmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlLCBuZXh0OiBOZXh0RnVuY3Rpb24pOiBQcm9taXNlPHZvaWQ+IHtcbiAgLy8gVmVyaWZpZWQgaW50ZXJuYWwgc2VydmljZSBwcmluY2lwYWxzIGFyZSBFWEVNUFQ6IHN0ZXAtdXAgaXMgYSByZS12ZXJpZnktdGhlLVxuICAvLyBIVU1BTiBnYXRlICh0aGV5IHJlcGxheSBhIHBhc3N3b3JkLXJldmVyaWZ5IHRva2VuKSwgd2hpY2ggYSBzZXJ2aWNlIHRva2VuXG4gIC8vIHN0cnVjdHVyYWxseSBjYW5ub3QgcHJvZHVjZS4gU2VydmljZXMgYWxyZWFkeSBieXBhc3MgYHJlcXVpcmVQZXJtaXNzaW9uYCBvblxuICAvLyB0aGUgc2FtZSB0cnVzdCBiYXNpcyAoYSBzaWduZWQgc2VydmljZSBKV1QpLCBhbmQgaW50ZXJuYWwgY2FsbGVycyBvZiBhXG4gIC8vIHN0ZXAtdXAtZ2F0ZWQgcm91dGUg4oCUIGUuZy4gdGhlIHBsYXRmb3JtIG9yZy1jYXNjYWRlJ3MgYERFTEVURSAvcXVvdGFzLzpvcmdJZGBcbiAgLy8gb3IgdGhlIGJpbGxpbmfihpJxdW90YSBlbnRpdGxlbWVudCBzeW5jIOKAlCB3b3VsZCBvdGhlcndpc2UgYmUgaGFyZC1ibG9ja2VkLlxuICAvLyBTYWZlOiBhIHNlcnZpY2UgdG9rZW4gY2FuIG9ubHkgYmUgbWludGVkIHdpdGggYSBTRVJWSUNFJ3Mgb3duIEVTMjU2IGtleSxcbiAgLy8gd2hpY2ggbm8gZXh0ZXJuYWwgY2xpZW50IGhvbGRzLCBzbyB0aGlzIGNhbid0IGJlIHNwb29mZWQgdG8gc2tpcFxuICAvLyBzdGVwLXVwLlxuICBpZiAoaXNTZXJ2aWNlUHJpbmNpcGFsKHJlcSkpIHtcbiAgICBuZXh0KCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gQW4gT1JHIFNFUlZJQ0UgQUNDT1VOVCBpcyB0aGUgb3Bwb3NpdGUgY2FzZTogaXQgaXMgc3ViamVjdCB0byBldmVyeSBnYXRlIGFcbiAgLy8gbWVtYmVyIGlzLCBhbmQgdGhlcmUgaXMgbm8gcGVyc29uIGJlaGluZCBpdCB0byByZS12ZXJpZnkg4oCUIHNvIGl0IGNhbiBORVZFUlxuICAvLyBwYXNzIHN0ZXAtdXAuIFJlZnVzZSBleHBsaWNpdGx5IChyYXRoZXIgdGhhbiBsZXR0aW5nIGl0IGZhbGwgdGhyb3VnaCB0byB0aGVcbiAgLy8gYHN1YmAtYm91bmQgdG9rZW4gY2hlY2ssIHdoaWNoIHdvdWxkIGZhaWwgd2l0aCBhIGNvbmZ1c2luZyBTVEVQX1VQX01JU01BVENIKVxuICAvLyBzbyBcImEgbWFjaGluZSBjcmVkZW50aWFsIG5ldmVyIHNhdGlzZmllcyBhbiBhc3N1cmFuY2UgcmVxdWlyZW1lbnRcIiBpcyBhXG4gIC8vIHByb3BlcnR5IG9mIHRoaXMgZ2F0ZSwgbm90IGEgc2lkZSBlZmZlY3Qgb2YgaG93IHN0ZXAtdXAgdG9rZW5zIGFyZSBtaW50ZWQuXG4gIGlmIChpc1NlcnZpY2VBY2NvdW50UHJpbmNpcGFsKHJlcSkpIHtcbiAgICBzZW5kRXJyb3IocmVzLCA0MDMsICdBIHNlcnZpY2UgYWNjb3VudCBjYW5ub3QgcGVyZm9ybSB0aGlzIGFjdGlvbiDigJQgaXQgcmVxdWlyZXMgYSBwZXJzb24gdG8gcmUtdmVyaWZ5JywgJ1NURVBfVVBfTk9UX0FWQUlMQUJMRScpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IGNhbGxlclN1YiA9IChyZXEgYXMgUmVxdWVzdCAmIHsgdXNlcj86IHsgc3ViPzogc3RyaW5nIH0gfSkudXNlcj8uc3ViO1xuICBpZiAoIWNhbGxlclN1Yikge1xuICAgIHNlbmRFcnJvcihyZXMsIDQwMSwgJ0F1dGhlbnRpY2F0aW9uIHJlcXVpcmVkJywgJ1VOQVVUSE9SSVpFRCcpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHRva2VuID0gZ2V0SGVhZGVyU3RyaW5nKHJlcS5oZWFkZXJzW0hFQURFUl0pO1xuICBpZiAoIXRva2VuKSB7XG4gICAgc2VuZEVycm9yKHJlcywgNDAxLCAnU3RlcC11cCB2ZXJpZmljYXRpb24gcmVxdWlyZWQnLCAnU1RFUF9VUF9SRVFVSVJFRCcpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGxldCBwYXlsb2FkOiBTdGVwVXBUb2tlblBheWxvYWQ7XG4gIHRyeSB7XG4gICAgcGF5bG9hZCA9IGF3YWl0IHZlcmlmeVN0ZXBVcFRva2VuKHRva2VuKTtcbiAgfSBjYXRjaCB7XG4gICAgc2VuZEVycm9yKHJlcywgNDAxLCAnU3RlcC11cCB0b2tlbiBpbnZhbGlkIG9yIGV4cGlyZWQnLCAnU1RFUF9VUF9JTlZBTElEJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKHBheWxvYWQuc3ViICE9PSBjYWxsZXJTdWIpIHtcbiAgICBzZW5kRXJyb3IocmVzLCA0MDEsICdTdGVwLXVwIHRva2VuIGRvZXMgbm90IG1hdGNoIHNlc3Npb24nLCAnU1RFUF9VUF9NSVNNQVRDSCcpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIEZhY3RvciByZXN0cmljdGlvbi4gQ2hlY2tlZCBCRUZPUkUgdGhlIGp0aSBpcyBjb25zdW1lZCwgc28gYSB0b2tlblxuICAvLyBlYXJuZWQgYnkgdGhlIHdyb25nIGZhY3RvciBjYW4gc3RpbGwgYmUgc3BlbnQgb24gYSByb3V0ZSB0aGF0IGFjY2VwdHMgaXQg4oCUXG4gIC8vIGJ1cm5pbmcgaXQgaGVyZSB3b3VsZCBtYWtlIHRoZSByZWZ1c2FsIGRlc3RydWN0aXZlIGFzIHdlbGwgYXMgY29uZnVzaW5nLlxuICBpZiAob3B0aW9ucy5tZXRob2RzICYmICEocGF5bG9hZC5tZXRob2QgJiYgb3B0aW9ucy5tZXRob2RzLmluY2x1ZGVzKHBheWxvYWQubWV0aG9kKSkpIHtcbiAgICBzZW5kRXJyb3IoXG4gICAgICByZXMsIDQwMSxcbiAgICAgICdUaGlzIGFjdGlvbiBtdXN0IGJlIGNvbmZpcm1lZCB3aXRoIGEgcGFzc2tleSBvciBhbiBhdXRoZW50aWNhdG9yIGNvZGUnLFxuICAgICAgJ1NURVBfVVBfTUVUSE9EX1JFUVVJUkVEJyxcbiAgICAgIHsgbWV0aG9kczogWy4uLm9wdGlvbnMubWV0aG9kc10gfSxcbiAgICApO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIHRyeSB7XG4gICAgaWYgKCEoYXdhaXQgY29uc3VtZVN0ZXBVcEp0aShwYXlsb2FkLmp0aSwgcGF5bG9hZC5leHApKSkge1xuICAgICAgc2VuZEVycm9yKHJlcywgNDAxLCAnU3RlcC11cCB0b2tlbiBhbHJlYWR5IHVzZWQgb3IgZXhwaXJlZCcsICdTVEVQX1VQX1JFUExBWScpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgbG9nZ2VyLmVycm9yKCdTdGVwLXVwIGp0aSBjb25zdW1lIGVycm9yZWQnLCB7IGVycm9yOiBTdHJpbmcoZXJyKSB9KTtcbiAgICBzZW5kRXJyb3IocmVzLCA0MDEsICdTdGVwLXVwIHZlcmlmaWNhdGlvbiBmYWlsZWQnLCAnU1RFUF9VUF9JTlZBTElEJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgbmV4dCgpO1xufVxuIl19
|
|
200
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RlcC11cC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9taWRkbGV3YXJlL3N0ZXAtdXAudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQXFCdEMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzFELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUNoRCxPQUFPLEVBQUUseUJBQXlCLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUNwRixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsb0JBQW9CLEVBQXdCLE1BQU0sMEJBQTBCLENBQUM7QUFDNUcsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3RELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFakQsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLFNBQVMsQ0FBQyxDQUFDO0FBQ3ZDLE1BQU0sTUFBTSxHQUFHLGlCQUFpQixDQUFDO0FBU2pDOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQTRCLENBQUMsVUFBVSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0FBcUJwRjs7Ozs7Ozs7Ozs7OztHQWFHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxpQkFBaUIsQ0FBQyxLQUFhO0lBQ25ELE1BQU0sT0FBTyxHQUFHLE1BQU0sYUFBYSxDQUFxQixLQUFLLENBQUMsQ0FBQztJQUUvRCxJQUFJLE9BQU8sQ0FBQyxJQUFJLEtBQUssU0FBUyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUMvRCxN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O1lBQy9FLE9BQU87UUFDVCxDQUFDO0lBQ0gsQ0FBQztJQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDYixNQUFNLENBQUMsS0FBSyxDQUFDLDZCQUE2QixFQUFFLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDcEUsU0FBUyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsNkJBQTZCLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztRQUN0RSxPQUFPO0lBQ1QsQ0FBQztJQUVELElBQUksRUFBRSxDQUFDO0FBQ1QsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIGByZXF1aXJlU3RlcFVwYCDigJQgYSBzaGFyZWQgc3RlcC11cCAocmVjZW50LXBhc3N3b3JkLXJldmVyaWZ5KSBnYXRlIGZvciB0aGVcbiAqIHN0YXRlbGVzcyBhcGkgc2VydmljZXMsIG1pcnJvcmluZyB0aGUgcGxhdGZvcm0gbWlkZGxld2FyZSBvZiB0aGUgc2FtZSBuYW1lLlxuICpcbiAqIEZsb3c6IHRoZSBVSSBoaXRzIGBQT1NUIC9hcGkvYXV0aC9zdGVwLXVwYCAocGxhdGZvcm0pIHRvIHJlLXZlcmlmeSB0aGUgdXNlcjtcbiAqIHBsYXRmb3JtIG1pbnRzIGEgc2hvcnQtbGl2ZWQgKDYwcykgYHN0ZXAtdXBgIEpXVCB3aXRoIHRoZSBTQU1FIEVTMjU2IHNpZ25pbmdcbiAqIGtleSBpdCBtaW50cyBhY2Nlc3MgdG9rZW5zIHdpdGgsIHNvIHRoZXNlIHNlcnZpY2VzIHZlcmlmeSBpdCB0aHJvdWdoIHRoZSBzYW1lXG4gKiBKV0tTLiBUaGUgVUlcbiAqIHJlcGxheXMgaXQgYXMgdGhlIGBYLVN0ZXAtVXAtVG9rZW5gIGhlYWRlciBvbiB0aGUgZGVzdHJ1Y3RpdmUvc2Vuc2l0aXZlIGNhbGw7XG4gKiB0aGlzIG1pZGRsZXdhcmUgdmVyaWZpZXMgaXQsIGJpbmRzIGl0IHRvIHRoZSBjYWxsZXIgKGBzdWJgIG1hdGNoKSwgYW5kXG4gKiBjb25zdW1lcyBpdHMgYGp0aWAgb25jZSAoUmVkaXMtYmFja2VkIGNyb3NzLWluc3RhbmNlIHdoZW4gY29uZmlndXJlZCwgZWxzZSBhXG4gKiBib3VuZGVkIHByb2Nlc3MtbG9jYWwgc2V0KSBzbyBhIHJlcGxheSBpbnNpZGUgdGhlIFRUTCBpcyByZWplY3RlZC5cbiAqXG4gKiBXSFkgaGVyZTogcmVzdG9yZSBlbmRwb2ludHMgb24gdGhlIGFwaSBzZXJ2aWNlcyAocGlwZWxpbmUvcGx1Z2luLy4uLikgYXJlXG4gKiBzdGVwLXVwLWdhdGVkLCBzbyB0aGUgdmVyaWZ5ICsgc2luZ2xlLXVzZSBqdGkgbGl2ZSBpbiBhcGktY29yZSB3aGVyZSBhbnlcbiAqIHNlcnZpY2UgY2FuIHJlcXVpcmUgdGhlbS5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7IFJlcXVlc3QsIFJlc3BvbnNlLCBOZXh0RnVuY3Rpb24gfSBmcm9tICdleHByZXNzJztcbmltcG9ydCB7IHZlcmlmeVVzZXJKd3QgfSBmcm9tICcuL2p3dC12ZXJpZnkuanMnO1xuaW1wb3J0IHsgcmVjb3JkQXV0aHpEZW5pYWwgfSBmcm9tICcuL3Blcm1pc3Npb24tZ2F0ZXMuanMnO1xuaW1wb3J0IHsgdGFnUm91dGVHYXRlIH0gZnJvbSAnLi9yb3V0ZS10YWJsZS5qcyc7XG5pbXBvcnQgeyBpc1NlcnZpY2VBY2NvdW50UHJpbmNpcGFsLCBpc1NlcnZpY2VQcmluY2lwYWwgfSBmcm9tICcuL3NlcnZpY2UtdG9rZW5zLmpzJztcbmltcG9ydCB7IGNyZWF0ZUVudlJlZGlzQ2xpZW50LCBjcmVhdGVSZWRpc1JlYWR5R2F0ZSwgdHlwZSBSZWFkeUF3YXJlUmVkaXMgfSBmcm9tICcuLi9zZXJ2aWNlcy9lbnYtcmVkaXMuanMnO1xuaW1wb3J0IHsgZ2V0SGVhZGVyU3RyaW5nIH0gZnJvbSAnLi4vdXRpbHMvaGVhZGVycy5qcyc7XG5pbXBvcnQgeyBjcmVhdGVMb2dnZXIgfSBmcm9tICcuLi91dGlscy9sb2dnZXIuanMnO1xuaW1wb3J0IHsgc2VuZEVycm9yIH0gZnJvbSAnLi4vdXRpbHMvcmVzcG9uc2UuanMnO1xuXG5jb25zdCBsb2dnZXIgPSBjcmVhdGVMb2dnZXIoJ3N0ZXAtdXAnKTtcbmNvbnN0IEhFQURFUiA9ICd4LXN0ZXAtdXAtdG9rZW4nO1xuXG4vKipcbiAqIEhvdyBhIHN0ZXAtdXAgdG9rZW4gd2FzIGVhcm5lZC4gTWlycm9ycyBwbGF0Zm9ybSdzIGBTdGVwVXBNZXRob2RgOyBrZXB0IGhlcmVcbiAqIGFzIGl0cyBvd24gdW5pb24gc28gYSB2ZXJpZmllciBjYW4gbmFtZSB0aGUgZmFjdG9ycyBpdCBhY2NlcHRzIHdpdGhvdXRcbiAqIGltcG9ydGluZyBwbGF0Zm9ybS5cbiAqL1xuZXhwb3J0IHR5cGUgU3RlcFVwTWV0aG9kID0gJ3Bhc3N3b3JkJyB8ICd3ZWJhdXRobicgfCAndG90cCcgfCAncmVhdXRoJztcblxuLyoqXG4gKiBUaGUgZmFjdG9ycyB0aGF0IGNvdW50IGFzIGEgU0VDT05EIEZBQ1RPUiwgZm9yIHJvdXRlcyB0aGF0IG1heSBvbmx5IGJlXG4gKiB1bmxvY2tlZCBieSBvbmUgKCM4OiBpbXBlcnNvbmF0aW9uLCBLTVMsIElkUCBzZXR0aW5ncywgcGxhdGZvcm0gYWRtaW4pLlxuICpcbiAqIEEgcGFzc3dvcmQgb3IgYSBwcm92aWRlciByZS1hdXRoIHByb3ZlcyB0aGUgc2FtZSBzaW5nbGUgZmFjdG9yIHRoZSBzZXNzaW9uIHdhc1xuICogYWxyZWFkeSBvcGVuZWQgd2l0aCwgc28gb24gdGhvc2Ugcm91dGVzIHRoZXkgYXJlIG5vdCBlbm91Z2g6IHRoZSBwb2ludCBpcyB0aGF0XG4gKiBzb21lb25lIGhvbGRpbmcgb25seSBhIHN0b2xlbiBzZXNzaW9uIOKAlCBvciBvbmx5IGEgc3RvbGVuIHBhc3N3b3JkIOKAlCBjYW5ub3RcbiAqIHByb2NlZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBTVFJPTkdfU1RFUF9VUF9NRVRIT0RTOiByZWFkb25seSBTdGVwVXBNZXRob2RbXSA9IFsnd2ViYXV0aG4nLCAndG90cCddO1xuXG4vKiogUGF5bG9hZCBvZiBhIHBsYXRmb3JtLWlzc3VlZCBzdGVwLXVwIHRva2VuIChzZWUgcGxhdGZvcm0gaXNzdWVTdGVwVXBUb2tlbikuICovXG5leHBvcnQgaW50ZXJmYWNlIFN0ZXBVcFRva2VuUGF5bG9hZCB7XG4gIHR5cGU6ICdzdGVwLXVwJztcbiAgc3ViOiBzdHJpbmc7XG4gIGp0aTogc3RyaW5nO1xuICAvKiogV2hpY2ggZmFjdG9yIGVhcm5lZCBpdC4gQWJzZW50IG9ubHkgb24gYSB0b2tlbiBtaW50ZWQgYmVmb3JlIHRoZSBjbGFpbVxuICAgKiAgZXhpc3RlZCwgd2hpY2ggYSBtZXRob2QtcmVzdHJpY3RlZCBnYXRlIHRyZWF0cyBhcyBcIm5vdCBwcm92ZW5cIi4gKi9cbiAgbWV0aG9kPzogU3RlcFVwTWV0aG9kO1xuICBpYXQ6IG51bWJlcjtcbiAgZXhwOiBudW1iZXI7XG59XG5cbi8qKiBPcHRpb25zIGZvciB7QGxpbmsgcmVxdWlyZVN0ZXBVcH0uICovXG5leHBvcnQgaW50ZXJmYWNlIFJlcXVpcmVTdGVwVXBPcHRpb25zIHtcbiAgLyoqIFJlc3RyaWN0IHdoaWNoIGZhY3RvcnMgbWF5IGVhcm4gdGhlIHN0ZXAtdXAgKGUuZy4ge0BsaW5rIFNUUk9OR19TVEVQX1VQX01FVEhPRFN9KS5cbiAgICogIE9taXR0ZWQgbWVhbnMgYW55IGZhY3RvciB0aGUgcGxhdGZvcm0gd2lsbCBpc3N1ZSBhIHRva2VuIGZvci4gKi9cbiAgbWV0aG9kcz86IHJlYWRvbmx5IFN0ZXBVcE1ldGhvZFtdO1xufVxuXG4vKipcbiAqIFZlcmlmeSBhIHN0ZXAtdXAgdG9rZW46IGEgdmFsaWQgRVMyNTYgc2lnbmF0dXJlIGZyb20gb25lIG9mIHBsYXRmb3JtJ3NcbiAqIHB1Ymxpc2hlZCBzaWduaW5nIGtleXMsIGlzc3VlciBhbmQgYXVkaWVuY2Ugd2hlbiBjb25maWd1cmVkLCBBTkQgdGhlXG4gKiBgdHlwZTogJ3N0ZXAtdXAnYCArIGBqdGlgIGNsYWltcyDigJQgYSBwbGFpbiBhY2Nlc3MgdG9rZW4gaXMgc2lnbmVkIGJ5IHRoZSBzYW1lXG4gKiBrZXkgYW5kIGNhcnJpZXMgdGhlIHNhbWUgYHN1YmAsIHNvIHdpdGhvdXQgYXNzZXJ0aW5nIHRoZSBzdGVwLXVwIHNoYXBlIGl0XG4gKiB3b3VsZCBieXBhc3MgdGhlIGdhdGUuIFRocm93cyBvbiBhbnkgZmFpbHVyZSAoYW4gdW5mZXRjaGFibGUga2V5IHNldCBpbmNsdWRlZDpcbiAqIGFuIHVudmVyaWZpYWJsZSB0b2tlbiBpcyBub3QgYSBzdGVwLXVwKS4gRG9lcyBOT1QgYmluZCB0byBhIGNhbGxlciDigJRcbiAqIGByZXF1aXJlU3RlcFVwYCBkb2VzIHRoZSBgc3ViYCBtYXRjaCBhbmQgc2luZ2xlLXVzZSBjb25zdW1lLlxuICpcbiAqIERlbGVnYXRlcyB0byBgcmVxdWlyZUF1dGhgJ3Mgb3duIHByaW1pdGl2ZSAoYHZlcmlmeVVzZXJKd3RgKSByYXRoZXIgdGhhblxuICogcmUtaW1wbGVtZW50aW5nIGl0LiBUaGUgaGFuZC1yb2xsZWQgY29weSB0aGlzIHJlcGxhY2VkIGRyb3BwZWQgVFdPIG9mIGl0c1xuICogZ3VhcmRzOiBpdCBuZXZlciBwaW5uZWQgaXNzdWVyL2F1ZGllbmNlLCBhbmQgaXRzIHByZXZpb3VzLXNlY3JldCByZXRyeSBoYWQgbm9cbiAqIGV4cGlyeS9ub3QtYmVmb3JlIGNhcnZlLW91dCwgc28gYW4gRVhQSVJFRCB0b2tlbiBzdXJmYWNlZCBhcyBhIHNpZ25hdHVyZSBlcnJvci5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHZlcmlmeVN0ZXBVcFRva2VuKHRva2VuOiBzdHJpbmcpOiBQcm9taXNlPFN0ZXBVcFRva2VuUGF5bG9hZD4ge1xuICBjb25zdCBwYXlsb2FkID0gYXdhaXQgdmVyaWZ5VXNlckp3dDxTdGVwVXBUb2tlblBheWxvYWQ+KHRva2VuKTtcblxuICBpZiAocGF5bG9hZC50eXBlICE9PSAnc3RlcC11cCcgfHwgIXBheWxvYWQuanRpIHx8ICFwYXlsb2FkLnN1Yikge1xuICAgIHRocm93IG5ldyBFcnJvcignSU5WQUxJRF9TVEVQX1VQX1RPS0VOJyk7XG4gIH1cbiAgcmV0dXJuIHBheWxvYWQ7XG59XG5cbi8vIC0tIFNpbmdsZS11c2UganRpIHN0b3JlIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBSZWRpcyBTRVQgTlggRVggd2hlbiBSZWRpcyBpcyBjb25maWd1cmVkIChjcm9zcy1pbnN0YW5jZSBzaW5nbGUtdXNlKTsgZWxzZSBhXG4vLyBib3VuZGVkIHByb2Nlc3MtbG9jYWwgbWFwIHdpdGggVFRMIHN3ZWVwIChwZXItcHJvY2VzcykuIEEgc3RlcC11cCB0b2tlbiBpc1xuLy8gNjBzLWxpdmVkLiBXaGVuIFJlZGlzIElTIGNvbmZpZ3VyZWQgaXQncyB0aGUgYXV0aG9yaXRhdGl2ZSBzdG9yZTogYSBSZWRpc1xuLy8gZXJyb3IgRkFJTFMgQ0xPU0VEICh0aHJvd3Mg4oaSIFNURVBfVVBfSU5WQUxJRCwgdXNlciByZS12ZXJpZmllcykgcmF0aGVyIHRoYW5cbi8vIGRlZ3JhZGluZyB0byB0aGUgcGVyLWluc3RhbmNlIG1lbSBndWFyZCwgd2hpY2ggd291bGQgYWNjZXB0IGEgY3Jvc3MtaW5zdGFuY2Vcbi8vIHJlcGxheSBkdXJpbmcgdGhlIG91dGFnZS4gVGhlIG1lbSBndWFyZCBpcyB1c2VkIE9OTFkgd2hlbiBSZWRpcyBpcyBhYnNlbnQuXG5cbnR5cGUgSnRpUmVkaXMgPSBSZWFkeUF3YXJlUmVkaXMgJiB7IHNldDogKC4uLmFyZ3M6IHVua25vd25bXSkgPT4gUHJvbWlzZTx1bmtub3duPiB9O1xubGV0IF9yZWRpczogSnRpUmVkaXMgfCBudWxsIHwgdW5kZWZpbmVkO1xubGV0IF9yZWRpc1JlYWR5OiAoKCkgPT4gUHJvbWlzZTx2b2lkPikgfCB1bmRlZmluZWQ7XG4vKipcbiAqIFRoZSBqdGkgY2xpZW50LCBidWlsdCBsYXppbHkuIFRoZSBlbnYgY2xpZW50IGhhcyBubyBvZmZsaW5lIHF1ZXVlLCBzbyBhIFNFVCBvblxuICogYSBjb25uZWN0aW9uIHRoYXQgaXNuJ3QgdXAgeWV0IGlzIHJlamVjdGVkIOKAlCB0aGUgRklSU1Qgc3RlcC11cCBvbiBldmVyeSBwb2RcbiAqIHdvdWxkIGZhaWwuIFdhaXQgKGJvdW5kZWQsIG5ldmVyIHJlamVjdGluZykgZm9yIHJlYWRpbmVzcyBiZWZvcmVcbiAqIGhhbmRpbmcgaXQgb3V0OyBhIGdlbnVpbmVseSBkb3duIFJlZGlzIHN0aWxsIGZhaWxzIGNsb3NlZCBvbiB0aGUgU0VUIGJlbG93LlxuICovXG5hc3luYyBmdW5jdGlvbiByZWRpcygpOiBQcm9taXNlPEp0aVJlZGlzIHwgbnVsbD4ge1xuICBpZiAoX3JlZGlzID09PSB1bmRlZmluZWQpIHtcbiAgICBfcmVkaXMgPSBjcmVhdGVFbnZSZWRpc0NsaWVudDxKdGlSZWRpcz4oJ3N0ZXAtdXAtanRpJyk7XG4gICAgX3JlZGlzUmVhZHkgPSBfcmVkaXMgPyBjcmVhdGVSZWRpc1JlYWR5R2F0ZShfcmVkaXMpIDogdW5kZWZpbmVkO1xuICB9XG4gIGlmIChfcmVkaXNSZWFkeSkgYXdhaXQgX3JlZGlzUmVhZHkoKTtcbiAgcmV0dXJuIF9yZWRpcztcbn1cblxuY29uc3QgbWVtSnRpID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTsgLy8ganRpIC0+IGV4cGlyeSBlcG9jaCBtc1xuY29uc3QgbWVtU3dlZXAgPSBzZXRJbnRlcnZhbCgoKSA9PiB7XG4gIGNvbnN0IG5vdyA9IERhdGUubm93KCk7XG4gIGZvciAoY29uc3QgW2p0aSwgZXhwXSBvZiBtZW1KdGkpIGlmIChleHAgPD0gbm93KSBtZW1KdGkuZGVsZXRlKGp0aSk7XG59LCAzMF8wMDApO1xubWVtU3dlZXAudW5yZWY/LigpO1xuXG4vKipcbiAqIEhhcmQgY2VpbGluZyBvbiB0aGUgcHJvY2Vzcy1sb2NhbCBqdGkgc2V0LlxuICpcbiAqIFRoZSAzMHMgc3dlZXAgYWxvbmUgZG9lcyBOT1QgYm91bmQgaXQ6IGVudHJpZXMgb25seSBsZWF2ZSBvbmNlIHRoZWlyIHRva2VuJ3NcbiAqIFRUTCBoYXMgcGFzc2VkLCBzbyBhIGJ1cnN0IG9mIHN0ZXAtdXAgdHJhZmZpYyAob3IgYSBmbG9vZCBvZiBkaXN0aW5jdCBmb3JnZWRcbiAqIGp0aXMgb24gYSBSZWRpcy1sZXNzIGRlcGxveW1lbnQpIGdyb3dzIHRoZSBtYXAgZmFzdGVyIHRoYW4gdGhlIHN3ZWVwIGRyYWluc1xuICogaXQuIFRoaXMgaXMgYSByZXBsYXkgZ3VhcmQsIHNvIHNoZWRkaW5nIHRoZSBPTERFU1QgZW50cmllcyBpcyB0aGUgc2FmZVxuICogZGlyZWN0aW9uOiB0aGUgd29yc3QgY2FzZSBpcyB0aGF0IGEgbG9uZy1leHBpcmVkIGp0aSBjb3VsZCBiZSByZXBsYXllZCwgYW5kXG4gKiBleHBpcnkgaXMgZW5mb3JjZWQgaW5kZXBlbmRlbnRseSBieSB0aGUgdG9rZW4ncyBvd24gYGV4cGAuXG4gKi9cbmNvbnN0IE1FTV9KVElfTUFYID0gMTBfMDAwO1xuXG4vKiogRHJvcCB0aGUgc29vbmVzdC10by1leHBpcmUgZW50cmllcyB1bnRpbCB0aGUgbWFwIGlzIHVuZGVyIHRoZSBjZWlsaW5nLiAqL1xuZnVuY3Rpb24gZXZpY3RPbGRlc3RKdGkoKTogdm9pZCB7XG4gIGlmIChtZW1KdGkuc2l6ZSA8IE1FTV9KVElfTUFYKSByZXR1cm47XG4gIGNvbnN0IGJ5RXhwaXJ5ID0gWy4uLm1lbUp0aS5lbnRyaWVzKCldLnNvcnQoKGEsIGIpID0+IGFbMV0gLSBiWzFdKTtcbiAgY29uc3QgZXhjZXNzID0gbWVtSnRpLnNpemUgLSBNRU1fSlRJX01BWCArIDE7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgZXhjZXNzOyBpICs9IDEpIG1lbUp0aS5kZWxldGUoYnlFeHBpcnlbaV1bMF0pO1xufVxuXG4vKipcbiAqIENvbnN1bWUgYSBzdGVwLXVwIGBqdGlgIGV4YWN0bHkgb25jZS4gUmV0dXJucyB0cnVlIGlmIHRoaXMgY2FsbCBjbGFpbWVkIGl0XG4gKiAoZmlyc3QgdXNlKSwgZmFsc2UgaWYgaXQgd2FzIGFscmVhZHkgY29uc3VtZWQgKHJlcGxheSkuIGBleHBFcG9jaFNlY29uZHNgIGlzXG4gKiB0aGUgdG9rZW4ncyBgZXhwYCwgc28gdGhlIG1hcmtlciBhdXRvLWV4cGlyZXMgd2l0aCB0aGUgdG9rZW4uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjb25zdW1lU3RlcFVwSnRpKGp0aTogc3RyaW5nLCBleHBFcG9jaFNlY29uZHM6IG51bWJlcik6IFByb21pc2U8Ym9vbGVhbj4ge1xuICBjb25zdCB0dGxTZWNvbmRzID0gTWF0aC5tYXgoMSwgZXhwRXBvY2hTZWNvbmRzIC0gTWF0aC5mbG9vcihEYXRlLm5vdygpIC8gMTAwMCkpO1xuICBjb25zdCBjbGllbnQgPSBhd2FpdCByZWRpcygpO1xuICBpZiAoY2xpZW50KSB7XG4gICAgLy8gUmVkaXMgY29uZmlndXJlZCDih5IgYXV0aG9yaXRhdGl2ZSBjcm9zcy1pbnN0YW5jZSBzdG9yZS4gU0VUIE5YIEVYIOKGkiAnT0snXG4gICAgLy8gd2hlbiBuZXdseSBzZXQsIG51bGwgd2hlbiBhbHJlYWR5IGNvbnN1bWVkLiBBIHRocm93biBSZWRpcyBlcnJvciBpcyBOT1RcbiAgICAvLyBjYXVnaHQgaGVyZTogaXQgcHJvcGFnYXRlcyBzbyBgcmVxdWlyZVN0ZXBVcGAgZmFpbHMgY2xvc2VkIChTVEVQX1VQX0lOVkFMSUQpXG4gICAgLy8gaW5zdGVhZCBvZiBzaWxlbnRseSBkZWdyYWRpbmcgdG8gdGhlIHBlci1pbnN0YW5jZSBtZW0gZ3VhcmQuXG4gICAgY29uc3QgcmVzID0gYXdhaXQgY2xpZW50LnNldChgc3RlcHVwOmp0aToke2p0aX1gLCAnMScsICdFWCcsIHR0bFNlY29uZHMsICdOWCcpO1xuICAgIHJldHVybiByZXMgPT09ICdPSyc7XG4gIH1cbiAgLy8gTm8gUmVkaXMg4oeSIHNpbmdsZS1pbnN0YW5jZSBkZXBsb3ltZW50OyB0aGUgcHJvY2Vzcy1sb2NhbCBtYXAgSVMgdGhlIHN0b3JlLlxuICBpZiAobWVtSnRpLmhhcyhqdGkpKSByZXR1cm4gZmFsc2U7XG4gIGV2aWN0T2xkZXN0SnRpKCk7XG4gIG1lbUp0aS5zZXQoanRpLCBEYXRlLm5vdygpICsgdHRsU2Vjb25kcyAqIDEwMDApO1xuICByZXR1cm4gdHJ1ZTtcbn1cblxuLyoqXG4gKiBFeHByZXNzIG1pZGRsZXdhcmU6IHJlcXVpcmUgYSB2YWxpZCwgY2FsbGVyLWJvdW5kLCBzaW5nbGUtdXNlIHN0ZXAtdXAgdG9rZW4gaW5cbiAqIHRoZSBgWC1TdGVwLVVwLVRva2VuYCBoZWFkZXIuIE11c3QgcnVuIEFGVEVSIGByZXF1aXJlQXV0aGAgKG5lZWRzIGByZXEudXNlcmApLlxuICpcbiAqIFVzZSBkaXJlY3RseSAoYHJvdXRlci5wb3N0KCcveCcsIHJlcXVpcmVBdXRoLCByZXF1aXJlU3RlcFVwLCBoKWApIGZvciB0aGVcbiAqIG9yZGluYXJ5IGFueS1mYWN0b3IgZ2F0ZSwgb3IgY2FsbCBpdCB3aXRoIGB7IG1ldGhvZHMgfWAgdG8gZGVtYW5kIHRoYXQgdGhlXG4gKiBjb25maXJtYXRpb24gd2FzIGVhcm5lZCBieSBhIHNwZWNpZmljIGZhY3RvciDigJQgYHJlcXVpcmVTdGVwVXAoeyBtZXRob2RzOlxuICogU1RST05HX1NURVBfVVBfTUVUSE9EUyB9KWAgb24gdGhlIHJvdXRlcyB3aGVyZSBhIHBhc3N3b3JkIHJlLXByb21wdCBpcyBub3QgYVxuICogbWVhbmluZ2Z1bCBzZWNvbmQgcHJvb2YuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXF1aXJlU3RlcFVwKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSwgbmV4dDogTmV4dEZ1bmN0aW9uKTogUHJvbWlzZTx2b2lkPjtcbmV4cG9ydCBmdW5jdGlvbiByZXF1aXJlU3RlcFVwKG9wdGlvbnM6IFJlcXVpcmVTdGVwVXBPcHRpb25zKTogKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSwgbmV4dDogTmV4dEZ1bmN0aW9uKSA9PiB2b2lkO1xuZXhwb3J0IGZ1bmN0aW9uIHJlcXVpcmVTdGVwVXAoXG4gIHJlcU9yT3B0aW9uczogUmVxdWVzdCB8IFJlcXVpcmVTdGVwVXBPcHRpb25zLFxuICByZXM/OiBSZXNwb25zZSxcbiAgbmV4dD86IE5leHRGdW5jdGlvbixcbik6IFByb21pc2U8dm9pZD4gfCAoKHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSwgbmV4dDogTmV4dEZ1bmN0aW9uKSA9PiB2b2lkKSB7XG4gIC8vIFRoZSBkaXJlY3QgZm9ybSBSRVRVUk5TIHRoZSBwcm9taXNlIChFeHByZXNzIGlnbm9yZXMgaXQ7IGEgdGVzdCBhd2FpdHMgaXQpLFxuICAvLyBzbyBjb21wb3NpbmcgdGhlIGdhdGUgYXMgYHJvdXRlci5wb3N0KCcveCcsIHJlcXVpcmVTdGVwVXAsIGgpYCBiZWhhdmVzXG4gIC8vIGV4YWN0bHkgYXMgaXQgZGlkIGJlZm9yZSB0aGUgb3B0aW9ucyBmb3JtIGV4aXN0ZWQuXG4gIGlmIChyZXMgJiYgbmV4dCAmJiAnaGVhZGVycycgaW4gcmVxT3JPcHRpb25zKSB7XG4gICAgcmV0dXJuIF9yZXF1aXJlU3RlcFVwKHt9LCByZXFPck9wdGlvbnMgYXMgUmVxdWVzdCwgcmVzLCBuZXh0KTtcbiAgfVxuICBjb25zdCBvcHRpb25zID0gcmVxT3JPcHRpb25zIGFzIFJlcXVpcmVTdGVwVXBPcHRpb25zO1xuICByZXR1cm4gdGFnUm91dGVHYXRlKFxuICAgIChyZXFJbm5lcjogUmVxdWVzdCwgcmVzSW5uZXI6IFJlc3BvbnNlLCBuZXh0SW5uZXI6IE5leHRGdW5jdGlvbikgPT4ge1xuICAgICAgdm9pZCBfcmVxdWlyZVN0ZXBVcChvcHRpb25zLCByZXFJbm5lciwgcmVzSW5uZXIsIG5leHRJbm5lcik7XG4gICAgfSxcbiAgICB7IGtpbmQ6ICdzdGVwVXAnLCAuLi4ob3B0aW9ucy5tZXRob2RzID8geyBtZXRob2RzOiBbLi4ub3B0aW9ucy5tZXRob2RzXSB9IDoge30pIH0sXG4gICk7XG59XG50YWdSb3V0ZUdhdGUocmVxdWlyZVN0ZXBVcCwgeyBraW5kOiAnc3RlcFVwJyB9KTtcblxuYXN5bmMgZnVuY3Rpb24gX3JlcXVpcmVTdGVwVXAob3B0aW9uczogUmVxdWlyZVN0ZXBVcE9wdGlvbnMsIHJlcTogUmVxdWVzdCwgcmVzOiBSZXNwb25zZSwgbmV4dDogTmV4dEZ1bmN0aW9uKTogUHJvbWlzZTx2b2lkPiB7XG4gIC8vIFZlcmlmaWVkIGludGVybmFsIHNlcnZpY2UgcHJpbmNpcGFscyBhcmUgRVhFTVBUOiBzdGVwLXVwIGlzIGEgcmUtdmVyaWZ5LXRoZS1cbiAgLy8gSFVNQU4gZ2F0ZSAodGhleSByZXBsYXkgYSBwYXNzd29yZC1yZXZlcmlmeSB0b2tlbiksIHdoaWNoIGEgc2VydmljZSB0b2tlblxuICAvLyBzdHJ1Y3R1cmFsbHkgY2Fubm90IHByb2R1Y2UuIFNlcnZpY2VzIGFscmVhZHkgYnlwYXNzIGByZXF1aXJlUGVybWlzc2lvbmAgb25cbiAgLy8gdGhlIHNhbWUgdHJ1c3QgYmFzaXMgKGEgc2lnbmVkIHNlcnZpY2UgSldUKSwgYW5kIGludGVybmFsIGNhbGxlcnMgb2YgYVxuICAvLyBzdGVwLXVwLWdhdGVkIHJvdXRlIOKAlCBlLmcuIHRoZSBwbGF0Zm9ybSBvcmctY2FzY2FkZSdzIGBERUxFVEUgL3F1b3Rhcy86b3JnSWRgXG4gIC8vIG9yIHRoZSBiaWxsaW5n4oaScXVvdGEgZW50aXRsZW1lbnQgc3luYyDigJQgd291bGQgb3RoZXJ3aXNlIGJlIGhhcmQtYmxvY2tlZC5cbiAgLy8gU2FmZTogYSBzZXJ2aWNlIHRva2VuIGNhbiBvbmx5IGJlIG1pbnRlZCB3aXRoIGEgU0VSVklDRSdzIG93biBFUzI1NiBrZXksXG4gIC8vIHdoaWNoIG5vIGV4dGVybmFsIGNsaWVudCBob2xkcywgc28gdGhpcyBjYW4ndCBiZSBzcG9vZmVkIHRvIHNraXBcbiAgLy8gc3RlcC11cC5cbiAgaWYgKGlzU2VydmljZVByaW5jaXBhbChyZXEpKSB7XG4gICAgbmV4dCgpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIC8vIEFuIE9SRyBTRVJWSUNFIEFDQ09VTlQgaXMgdGhlIG9wcG9zaXRlIGNhc2U6IGl0IGlzIHN1YmplY3QgdG8gZXZlcnkgZ2F0ZSBhXG4gIC8vIG1lbWJlciBpcywgYW5kIHRoZXJlIGlzIG5vIHBlcnNvbiBiZWhpbmQgaXQgdG8gcmUtdmVyaWZ5IOKAlCBzbyBpdCBjYW4gTkVWRVJcbiAgLy8gcGFzcyBzdGVwLXVwLiBSZWZ1c2UgZXhwbGljaXRseSAocmF0aGVyIHRoYW4gbGV0dGluZyBpdCBmYWxsIHRocm91Z2ggdG8gdGhlXG4gIC8vIGBzdWJgLWJvdW5kIHRva2VuIGNoZWNrLCB3aGljaCB3b3VsZCBmYWlsIHdpdGggYSBjb25mdXNpbmcgU1RFUF9VUF9NSVNNQVRDSClcbiAgLy8gc28gXCJhIG1hY2hpbmUgY3JlZGVudGlhbCBuZXZlciBzYXRpc2ZpZXMgYW4gYXNzdXJhbmNlIHJlcXVpcmVtZW50XCIgaXMgYVxuICAvLyBwcm9wZXJ0eSBvZiB0aGlzIGdhdGUsIG5vdCBhIHNpZGUgZWZmZWN0IG9mIGhvdyBzdGVwLXVwIHRva2VucyBhcmUgbWludGVkLlxuICBpZiAoaXNTZXJ2aWNlQWNjb3VudFByaW5jaXBhbChyZXEpKSB7XG4gICAgcmVjb3JkQXV0aHpEZW5pYWwocmVxLCAnc3RlcC11cCAoU1RFUF9VUF9OT1RfQVZBSUxBQkxFOiBzZXJ2aWNlIGFjY291bnQpJyk7XG4gICAgc2VuZEVycm9yKHJlcywgNDAzLCAnQSBzZXJ2aWNlIGFjY291bnQgY2Fubm90IHBlcmZvcm0gdGhpcyBhY3Rpb24g4oCUIGl0IHJlcXVpcmVzIGEgcGVyc29uIHRvIHJlLXZlcmlmeScsICdTVEVQX1VQX05PVF9BVkFJTEFCTEUnKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCBjYWxsZXJTdWIgPSAocmVxIGFzIFJlcXVlc3QgJiB7IHVzZXI/OiB7IHN1Yj86IHN0cmluZyB9IH0pLnVzZXI/LnN1YjtcbiAgaWYgKCFjYWxsZXJTdWIpIHtcbiAgICBzZW5kRXJyb3IocmVzLCA0MDEsICdBdXRoZW50aWNhdGlvbiByZXF1aXJlZCcsICdVTkFVVEhPUklaRUQnKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBjb25zdCB0b2tlbiA9IGdldEhlYWRlclN0cmluZyhyZXEuaGVhZGVyc1tIRUFERVJdKTtcbiAgaWYgKCF0b2tlbikge1xuICAgIHNlbmRFcnJvcihyZXMsIDQwMSwgJ1N0ZXAtdXAgdmVyaWZpY2F0aW9uIHJlcXVpcmVkJywgJ1NURVBfVVBfUkVRVUlSRUQnKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBsZXQgcGF5bG9hZDogU3RlcFVwVG9rZW5QYXlsb2FkO1xuICB0cnkge1xuICAgIHBheWxvYWQgPSBhd2FpdCB2ZXJpZnlTdGVwVXBUb2tlbih0b2tlbik7XG4gIH0gY2F0Y2gge1xuICAgIC8vIEEgcHJlc2VudGVkLWJ1dC11bnZlcmlmaWFibGUgdG9rZW4gKGZvcmdlZCwgZXhwaXJlZCwgd3Jvbmcga2V5KSBpcyBvbiB0aGVcbiAgICAvLyB0cmFpbDsgYSBNSVNTSU5HIG9uZSAoU1RFUF9VUF9SRVFVSVJFRCBhYm92ZSkgaXMgdGhlIFVJJ3Mgbm9ybWFsIGZpcnN0XG4gICAgLy8gYXR0ZW1wdCBhbmQgaXMgbm90LlxuICAgIHJlY29yZEF1dGh6RGVuaWFsKHJlcSwgJ3N0ZXAtdXAgKFNURVBfVVBfSU5WQUxJRCknKTtcbiAgICBzZW5kRXJyb3IocmVzLCA0MDEsICdTdGVwLXVwIHRva2VuIGludmFsaWQgb3IgZXhwaXJlZCcsICdTVEVQX1VQX0lOVkFMSUQnKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAocGF5bG9hZC5zdWIgIT09IGNhbGxlclN1Yikge1xuICAgIC8vIFNvbWVvbmUgZWxzZSdzIHN0ZXAtdXAgdG9rZW4gcmVwbGF5ZWQgb24gdGhpcyBzZXNzaW9uIOKAlCBuZXZlciBhIFVJIGJ1Zy5cbiAgICByZWNvcmRBdXRoekRlbmlhbChyZXEsICdzdGVwLXVwIChTVEVQX1VQX01JU01BVENIKScpO1xuICAgIHNlbmRFcnJvcihyZXMsIDQwMSwgJ1N0ZXAtdXAgdG9rZW4gZG9lcyBub3QgbWF0Y2ggc2Vzc2lvbicsICdTVEVQX1VQX01JU01BVENIJyk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gRmFjdG9yIHJlc3RyaWN0aW9uLiBDaGVja2VkIEJFRk9SRSB0aGUganRpIGlzIGNvbnN1bWVkLCBzbyBhIHRva2VuXG4gIC8vIGVhcm5lZCBieSB0aGUgd3JvbmcgZmFjdG9yIGNhbiBzdGlsbCBiZSBzcGVudCBvbiBhIHJvdXRlIHRoYXQgYWNjZXB0cyBpdCDigJRcbiAgLy8gYnVybmluZyBpdCBoZXJlIHdvdWxkIG1ha2UgdGhlIHJlZnVzYWwgZGVzdHJ1Y3RpdmUgYXMgd2VsbCBhcyBjb25mdXNpbmcuXG4gIGlmIChvcHRpb25zLm1ldGhvZHMgJiYgIShwYXlsb2FkLm1ldGhvZCAmJiBvcHRpb25zLm1ldGhvZHMuaW5jbHVkZXMocGF5bG9hZC5tZXRob2QpKSkge1xuICAgIHJlY29yZEF1dGh6RGVuaWFsKHJlcSwgYHN0ZXAtdXAgKFNURVBfVVBfTUVUSE9EX1JFUVVJUkVEOiAke29wdGlvbnMubWV0aG9kcy5qb2luKCcgb3IgJyl9LCBnb3QgJHtwYXlsb2FkLm1ldGhvZCA/PyAnbm9uZSd9KWApO1xuICAgIHNlbmRFcnJvcihcbiAgICAgIHJlcywgNDAxLFxuICAgICAgJ1RoaXMgYWN0aW9uIG11c3QgYmUgY29uZmlybWVkIHdpdGggYSBwYXNza2V5IG9yIGFuIGF1dGhlbnRpY2F0b3IgY29kZScsXG4gICAgICAnU1RFUF9VUF9NRVRIT0RfUkVRVUlSRUQnLFxuICAgICAgeyBtZXRob2RzOiBbLi4ub3B0aW9ucy5tZXRob2RzXSB9LFxuICAgICk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgdHJ5IHtcbiAgICBpZiAoIShhd2FpdCBjb25zdW1lU3RlcFVwSnRpKHBheWxvYWQuanRpLCBwYXlsb2FkLmV4cCkpKSB7XG4gICAgICByZWNvcmRBdXRoekRlbmlhbChyZXEsICdzdGVwLXVwIChTVEVQX1VQX1JFUExBWSknKTtcbiAgICAgIHNlbmRFcnJvcihyZXMsIDQwMSwgJ1N0ZXAtdXAgdG9rZW4gYWxyZWFkeSB1c2VkIG9yIGV4cGlyZWQnLCAnU1RFUF9VUF9SRVBMQVknKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGxvZ2dlci5lcnJvcignU3RlcC11cCBqdGkgY29uc3VtZSBlcnJvcmVkJywgeyBlcnJvcjogU3RyaW5nKGVycikgfSk7XG4gICAgc2VuZEVycm9yKHJlcywgNDAxLCAnU3RlcC11cCB2ZXJpZmljYXRpb24gZmFpbGVkJywgJ1NURVBfVVBfSU5WQUxJRCcpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIG5leHQoKTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Largest weight one model may carry — one call can never reserve more than this many units. */
|
|
2
|
+
export declare const MAX_AI_CALL_WEIGHT = 100;
|
|
3
|
+
/**
|
|
4
|
+
* Parse `AI_MODEL_WEIGHTS` — a JSON object of `key → integer weight` — into
|
|
5
|
+
* lower-cased entries. A malformed value is IGNORED (logged), never fatal: the
|
|
6
|
+
* weights are an optional pricing lever and every call still meters at 1.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseAiModelWeights(raw: string | undefined): Record<string, number>;
|
|
9
|
+
/**
|
|
10
|
+
* How many `aiCalls` units one call on `{ provider, modelId }` reserves.
|
|
11
|
+
*
|
|
12
|
+
* MODEL-CLASS WEIGHTING is OFF by default: with `AI_MODEL_WEIGHTS` unset every
|
|
13
|
+
* model weighs 1 — except the self-hosted provider, which weighs 0 (see
|
|
14
|
+
* {@link BUILT_IN_WEIGHTS}). Matching, first hit wins:
|
|
15
|
+
* 1. a key equal to the PROVIDER id (`"openai-compatible": 0`, `"bedrock": 2`);
|
|
16
|
+
* 2. the LONGEST key contained in the model id (`"opus": 3` matches
|
|
17
|
+
* `claude-opus-4-1`; `"sonnet": 1`, `"haiku": 1`).
|
|
18
|
+
* No match → 1. A weight of 0 means the call reserves nothing (it is still
|
|
19
|
+
* recorded in the usage ledger with its tokens).
|
|
20
|
+
*/
|
|
21
|
+
export declare function aiCallWeight(selection: {
|
|
22
|
+
provider: string;
|
|
23
|
+
modelId: string;
|
|
24
|
+
}): number;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
import { OPENAI_COMPATIBLE_PROVIDER_ID } from '../constants/ai-providers.js';
|
|
4
|
+
import { createLogger } from '../utils/logger.js';
|
|
5
|
+
const logger = createLogger('ai-call-weight');
|
|
6
|
+
/** Largest weight one model may carry — one call can never reserve more than this many units. */
|
|
7
|
+
export const MAX_AI_CALL_WEIGHT = 100;
|
|
8
|
+
/**
|
|
9
|
+
* Built-in weights, under whatever `AI_MODEL_WEIGHTS` sets. The self-hosted
|
|
10
|
+
* OpenAI-compatible provider (the in-cluster `ask-model`) runs on hardware the
|
|
11
|
+
* operator already pays for, so a call on it spends NO `aiCalls` unit by default;
|
|
12
|
+
* set `{"openai-compatible": 1}` to meter it like any other model.
|
|
13
|
+
*/
|
|
14
|
+
const BUILT_IN_WEIGHTS = { [OPENAI_COMPATIBLE_PROVIDER_ID]: 0 };
|
|
15
|
+
/**
|
|
16
|
+
* Parse `AI_MODEL_WEIGHTS` — a JSON object of `key → integer weight` — into
|
|
17
|
+
* lower-cased entries. A malformed value is IGNORED (logged), never fatal: the
|
|
18
|
+
* weights are an optional pricing lever and every call still meters at 1.
|
|
19
|
+
*/
|
|
20
|
+
export function parseAiModelWeights(raw) {
|
|
21
|
+
const out = { ...BUILT_IN_WEIGHTS };
|
|
22
|
+
if (!raw || raw.trim() === '')
|
|
23
|
+
return out;
|
|
24
|
+
let parsed;
|
|
25
|
+
try {
|
|
26
|
+
parsed = JSON.parse(raw);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
logger.warn('AI_MODEL_WEIGHTS is not valid JSON; every model weighs 1');
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
33
|
+
logger.warn('AI_MODEL_WEIGHTS must be a JSON object; every model weighs 1');
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
37
|
+
if (typeof value !== 'number' || !Number.isInteger(value) || value < 0 || value > MAX_AI_CALL_WEIGHT) {
|
|
38
|
+
logger.warn('AI_MODEL_WEIGHTS entry ignored (weight must be an integer 0..100)', { key });
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
out[key.trim().toLowerCase()] = value;
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
let cached;
|
|
46
|
+
function currentWeights() {
|
|
47
|
+
const raw = process.env.AI_MODEL_WEIGHTS;
|
|
48
|
+
if (!cached || cached.raw !== raw)
|
|
49
|
+
cached = { raw, weights: parseAiModelWeights(raw) };
|
|
50
|
+
return cached.weights;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* How many `aiCalls` units one call on `{ provider, modelId }` reserves.
|
|
54
|
+
*
|
|
55
|
+
* MODEL-CLASS WEIGHTING is OFF by default: with `AI_MODEL_WEIGHTS` unset every
|
|
56
|
+
* model weighs 1 — except the self-hosted provider, which weighs 0 (see
|
|
57
|
+
* {@link BUILT_IN_WEIGHTS}). Matching, first hit wins:
|
|
58
|
+
* 1. a key equal to the PROVIDER id (`"openai-compatible": 0`, `"bedrock": 2`);
|
|
59
|
+
* 2. the LONGEST key contained in the model id (`"opus": 3` matches
|
|
60
|
+
* `claude-opus-4-1`; `"sonnet": 1`, `"haiku": 1`).
|
|
61
|
+
* No match → 1. A weight of 0 means the call reserves nothing (it is still
|
|
62
|
+
* recorded in the usage ledger with its tokens).
|
|
63
|
+
*/
|
|
64
|
+
export function aiCallWeight(selection) {
|
|
65
|
+
const weights = currentWeights();
|
|
66
|
+
const provider = selection.provider.toLowerCase();
|
|
67
|
+
if (provider in weights)
|
|
68
|
+
return weights[provider];
|
|
69
|
+
const model = selection.modelId.toLowerCase();
|
|
70
|
+
let best;
|
|
71
|
+
for (const [key, weight] of Object.entries(weights)) {
|
|
72
|
+
if (key.length > 0 && model.includes(key) && (!best || key.length > best.key.length))
|
|
73
|
+
best = { key, weight };
|
|
74
|
+
}
|
|
75
|
+
return best ? best.weight : 1;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWktY2FsbC13ZWlnaHQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2VydmljZXMvYWktY2FsbC13ZWlnaHQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0QyxPQUFPLEVBQUUsNkJBQTZCLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM3RSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFFbEQsTUFBTSxNQUFNLEdBQUcsWUFBWSxDQUFDLGdCQUFnQixDQUFDLENBQUM7QUFFOUMsaUdBQWlHO0FBQ2pHLE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLEdBQUcsQ0FBQztBQUV0Qzs7Ozs7R0FLRztBQUNILE1BQU0sZ0JBQWdCLEdBQXFDLEVBQUUsQ0FBQyw2QkFBNkIsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO0FBRWxHOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUsbUJBQW1CLENBQUMsR0FBdUI7SUFDekQsTUFBTSxHQUFHLEdBQTJCLEVBQUUsR0FBRyxnQkFBZ0IsRUFBRSxDQUFDO0lBQzVELElBQUksQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUU7UUFBRSxPQUFPLEdBQUcsQ0FBQztJQUMxQyxJQUFJLE1BQWUsQ0FBQztJQUNwQixJQUFJLENBQUM7UUFDSCxNQUFNLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUMzQixDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsTUFBTSxDQUFDLElBQUksQ0FBQywwREFBMEQsQ0FBQyxDQUFDO1FBQ3hFLE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUNELElBQUksTUFBTSxLQUFLLElBQUksSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDO1FBQzNFLE1BQU0sQ0FBQyxJQUFJLENBQUMsOERBQThELENBQUMsQ0FBQztRQUM1RSxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFDRCxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFpQyxDQUFDLEVBQUUsQ0FBQztRQUM3RSxJQUFJLE9BQU8sS0FBSyxLQUFLLFFBQVEsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLElBQUksS0FBSyxHQUFHLENBQUMsSUFBSSxLQUFLLEdBQUcsa0JBQWtCLEVBQUUsQ0FBQztZQUNyRyxNQUFNLENBQUMsSUFBSSxDQUFDLG1FQUFtRSxFQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztZQUMxRixTQUFTO1FBQ1gsQ0FBQztRQUNELEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUM7SUFDeEMsQ0FBQztJQUNELE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQUVELElBQUksTUFBZ0YsQ0FBQztBQUVyRixTQUFTLGNBQWM7SUFDckIsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQztJQUN6QyxJQUFJLENBQUMsTUFBTSxJQUFJLE1BQU0sQ0FBQyxHQUFHLEtBQUssR0FBRztRQUFFLE1BQU0sR0FBRyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsbUJBQW1CLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztJQUN2RixPQUFPLE1BQU0sQ0FBQyxPQUFPLENBQUM7QUFDeEIsQ0FBQztBQUVEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsTUFBTSxVQUFVLFlBQVksQ0FBQyxTQUFnRDtJQUMzRSxNQUFNLE9BQU8sR0FBRyxjQUFjLEVBQUUsQ0FBQztJQUNqQyxNQUFNLFFBQVEsR0FBRyxTQUFTLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQ2xELElBQUksUUFBUSxJQUFJLE9BQU87UUFBRSxPQUFPLE9BQU8sQ0FBQyxRQUFRLENBQUUsQ0FBQztJQUNuRCxNQUFNLEtBQUssR0FBRyxTQUFTLENBQUMsT0FBTyxDQUFDLFdBQVcsRUFBRSxDQUFDO0lBQzlDLElBQUksSUFBaUQsQ0FBQztJQUN0RCxLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsTUFBTSxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1FBQ3BELElBQUksR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxJQUFJLEdBQUcsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUM7WUFBRSxJQUFJLEdBQUcsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLENBQUM7SUFDL0csQ0FBQztJQUNELE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDaEMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBPUEVOQUlfQ09NUEFUSUJMRV9QUk9WSURFUl9JRCB9IGZyb20gJy4uL2NvbnN0YW50cy9haS1wcm92aWRlcnMuanMnO1xuaW1wb3J0IHsgY3JlYXRlTG9nZ2VyIH0gZnJvbSAnLi4vdXRpbHMvbG9nZ2VyLmpzJztcblxuY29uc3QgbG9nZ2VyID0gY3JlYXRlTG9nZ2VyKCdhaS1jYWxsLXdlaWdodCcpO1xuXG4vKiogTGFyZ2VzdCB3ZWlnaHQgb25lIG1vZGVsIG1heSBjYXJyeSDigJQgb25lIGNhbGwgY2FuIG5ldmVyIHJlc2VydmUgbW9yZSB0aGFuIHRoaXMgbWFueSB1bml0cy4gKi9cbmV4cG9ydCBjb25zdCBNQVhfQUlfQ0FMTF9XRUlHSFQgPSAxMDA7XG5cbi8qKlxuICogQnVpbHQtaW4gd2VpZ2h0cywgdW5kZXIgd2hhdGV2ZXIgYEFJX01PREVMX1dFSUdIVFNgIHNldHMuIFRoZSBzZWxmLWhvc3RlZFxuICogT3BlbkFJLWNvbXBhdGlibGUgcHJvdmlkZXIgKHRoZSBpbi1jbHVzdGVyIGBhc2stbW9kZWxgKSBydW5zIG9uIGhhcmR3YXJlIHRoZVxuICogb3BlcmF0b3IgYWxyZWFkeSBwYXlzIGZvciwgc28gYSBjYWxsIG9uIGl0IHNwZW5kcyBOTyBgYWlDYWxsc2AgdW5pdCBieSBkZWZhdWx0O1xuICogc2V0IGB7XCJvcGVuYWktY29tcGF0aWJsZVwiOiAxfWAgdG8gbWV0ZXIgaXQgbGlrZSBhbnkgb3RoZXIgbW9kZWwuXG4gKi9cbmNvbnN0IEJVSUxUX0lOX1dFSUdIVFM6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIG51bWJlcj4+ID0geyBbT1BFTkFJX0NPTVBBVElCTEVfUFJPVklERVJfSURdOiAwIH07XG5cbi8qKlxuICogUGFyc2UgYEFJX01PREVMX1dFSUdIVFNgIOKAlCBhIEpTT04gb2JqZWN0IG9mIGBrZXkg4oaSIGludGVnZXIgd2VpZ2h0YCDigJQgaW50b1xuICogbG93ZXItY2FzZWQgZW50cmllcy4gQSBtYWxmb3JtZWQgdmFsdWUgaXMgSUdOT1JFRCAobG9nZ2VkKSwgbmV2ZXIgZmF0YWw6IHRoZVxuICogd2VpZ2h0cyBhcmUgYW4gb3B0aW9uYWwgcHJpY2luZyBsZXZlciBhbmQgZXZlcnkgY2FsbCBzdGlsbCBtZXRlcnMgYXQgMS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHBhcnNlQWlNb2RlbFdlaWdodHMocmF3OiBzdHJpbmcgfCB1bmRlZmluZWQpOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+IHtcbiAgY29uc3Qgb3V0OiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+ID0geyAuLi5CVUlMVF9JTl9XRUlHSFRTIH07XG4gIGlmICghcmF3IHx8IHJhdy50cmltKCkgPT09ICcnKSByZXR1cm4gb3V0O1xuICBsZXQgcGFyc2VkOiB1bmtub3duO1xuICB0cnkge1xuICAgIHBhcnNlZCA9IEpTT04ucGFyc2UocmF3KTtcbiAgfSBjYXRjaCB7XG4gICAgbG9nZ2VyLndhcm4oJ0FJX01PREVMX1dFSUdIVFMgaXMgbm90IHZhbGlkIEpTT047IGV2ZXJ5IG1vZGVsIHdlaWdocyAxJyk7XG4gICAgcmV0dXJuIG91dDtcbiAgfVxuICBpZiAocGFyc2VkID09PSBudWxsIHx8IHR5cGVvZiBwYXJzZWQgIT09ICdvYmplY3QnIHx8IEFycmF5LmlzQXJyYXkocGFyc2VkKSkge1xuICAgIGxvZ2dlci53YXJuKCdBSV9NT0RFTF9XRUlHSFRTIG11c3QgYmUgYSBKU09OIG9iamVjdDsgZXZlcnkgbW9kZWwgd2VpZ2hzIDEnKTtcbiAgICByZXR1cm4gb3V0O1xuICB9XG4gIGZvciAoY29uc3QgW2tleSwgdmFsdWVdIG9mIE9iamVjdC5lbnRyaWVzKHBhcnNlZCBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPikpIHtcbiAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnbnVtYmVyJyB8fCAhTnVtYmVyLmlzSW50ZWdlcih2YWx1ZSkgfHwgdmFsdWUgPCAwIHx8IHZhbHVlID4gTUFYX0FJX0NBTExfV0VJR0hUKSB7XG4gICAgICBsb2dnZXIud2FybignQUlfTU9ERUxfV0VJR0hUUyBlbnRyeSBpZ25vcmVkICh3ZWlnaHQgbXVzdCBiZSBhbiBpbnRlZ2VyIDAuLjEwMCknLCB7IGtleSB9KTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBvdXRba2V5LnRyaW0oKS50b0xvd2VyQ2FzZSgpXSA9IHZhbHVlO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbmxldCBjYWNoZWQ6IHsgcmF3OiBzdHJpbmcgfCB1bmRlZmluZWQ7IHdlaWdodHM6IFJlY29yZDxzdHJpbmcsIG51bWJlcj4gfSB8IHVuZGVmaW5lZDtcblxuZnVuY3Rpb24gY3VycmVudFdlaWdodHMoKTogUmVjb3JkPHN0cmluZywgbnVtYmVyPiB7XG4gIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52LkFJX01PREVMX1dFSUdIVFM7XG4gIGlmICghY2FjaGVkIHx8IGNhY2hlZC5yYXcgIT09IHJhdykgY2FjaGVkID0geyByYXcsIHdlaWdodHM6IHBhcnNlQWlNb2RlbFdlaWdodHMocmF3KSB9O1xuICByZXR1cm4gY2FjaGVkLndlaWdodHM7XG59XG5cbi8qKlxuICogSG93IG1hbnkgYGFpQ2FsbHNgIHVuaXRzIG9uZSBjYWxsIG9uIGB7IHByb3ZpZGVyLCBtb2RlbElkIH1gIHJlc2VydmVzLlxuICpcbiAqIE1PREVMLUNMQVNTIFdFSUdIVElORyBpcyBPRkYgYnkgZGVmYXVsdDogd2l0aCBgQUlfTU9ERUxfV0VJR0hUU2AgdW5zZXQgZXZlcnlcbiAqIG1vZGVsIHdlaWdocyAxIOKAlCBleGNlcHQgdGhlIHNlbGYtaG9zdGVkIHByb3ZpZGVyLCB3aGljaCB3ZWlnaHMgMCAoc2VlXG4gKiB7QGxpbmsgQlVJTFRfSU5fV0VJR0hUU30pLiBNYXRjaGluZywgZmlyc3QgaGl0IHdpbnM6XG4gKiAgMS4gYSBrZXkgZXF1YWwgdG8gdGhlIFBST1ZJREVSIGlkIChgXCJvcGVuYWktY29tcGF0aWJsZVwiOiAwYCwgYFwiYmVkcm9ja1wiOiAyYCk7XG4gKiAgMi4gdGhlIExPTkdFU1Qga2V5IGNvbnRhaW5lZCBpbiB0aGUgbW9kZWwgaWQgKGBcIm9wdXNcIjogM2AgbWF0Y2hlc1xuICogICAgIGBjbGF1ZGUtb3B1cy00LTFgOyBgXCJzb25uZXRcIjogMWAsIGBcImhhaWt1XCI6IDFgKS5cbiAqIE5vIG1hdGNoIOKGkiAxLiBBIHdlaWdodCBvZiAwIG1lYW5zIHRoZSBjYWxsIHJlc2VydmVzIG5vdGhpbmcgKGl0IGlzIHN0aWxsXG4gKiByZWNvcmRlZCBpbiB0aGUgdXNhZ2UgbGVkZ2VyIHdpdGggaXRzIHRva2VucykuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhaUNhbGxXZWlnaHQoc2VsZWN0aW9uOiB7IHByb3ZpZGVyOiBzdHJpbmc7IG1vZGVsSWQ6IHN0cmluZyB9KTogbnVtYmVyIHtcbiAgY29uc3Qgd2VpZ2h0cyA9IGN1cnJlbnRXZWlnaHRzKCk7XG4gIGNvbnN0IHByb3ZpZGVyID0gc2VsZWN0aW9uLnByb3ZpZGVyLnRvTG93ZXJDYXNlKCk7XG4gIGlmIChwcm92aWRlciBpbiB3ZWlnaHRzKSByZXR1cm4gd2VpZ2h0c1twcm92aWRlcl0hO1xuICBjb25zdCBtb2RlbCA9IHNlbGVjdGlvbi5tb2RlbElkLnRvTG93ZXJDYXNlKCk7XG4gIGxldCBiZXN0OiB7IGtleTogc3RyaW5nOyB3ZWlnaHQ6IG51bWJlciB9IHwgdW5kZWZpbmVkO1xuICBmb3IgKGNvbnN0IFtrZXksIHdlaWdodF0gb2YgT2JqZWN0LmVudHJpZXMod2VpZ2h0cykpIHtcbiAgICBpZiAoa2V5Lmxlbmd0aCA+IDAgJiYgbW9kZWwuaW5jbHVkZXMoa2V5KSAmJiAoIWJlc3QgfHwga2V5Lmxlbmd0aCA+IGJlc3Qua2V5Lmxlbmd0aCkpIGJlc3QgPSB7IGtleSwgd2VpZ2h0IH07XG4gIH1cbiAgcmV0dXJuIGJlc3QgPyBiZXN0LndlaWdodCA6IDE7XG59XG4iXX0=
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import type { Request } from 'express';
|
|
2
|
+
import type { JwtPayload } from '../types/common.js';
|
|
3
|
+
/** Inbound correlation ids a caller (CLI, Lambda, CodeBuild) may forward. */
|
|
4
|
+
export interface AuditCorrelation {
|
|
5
|
+
/** `X-Pipeline-Execution-Id` — the CodePipeline execution that made the call. */
|
|
6
|
+
pipelineExecutionId?: string;
|
|
7
|
+
/** `X-CodeBuild-Build-Id` — the CodeBuild build that made the call. */
|
|
8
|
+
codebuildBuildId?: string;
|
|
9
|
+
/** `X-Source-Event-Id` — the upstream event (EventBridge / webhook) being handled. */
|
|
10
|
+
sourceEventId?: string;
|
|
11
|
+
}
|
|
12
|
+
/** Background-work identity for events recorded outside any request. */
|
|
13
|
+
export interface AuditJobContext {
|
|
14
|
+
/** Stable job name (e.g. `registry-gc`, `vuln-rescan`). */
|
|
15
|
+
jobId?: string;
|
|
16
|
+
/** This run's id (a BullMQ job id, a sweep's uuid). */
|
|
17
|
+
runId?: string;
|
|
18
|
+
/** What started it: `schedule`, `queue`, `startup`, `manual`, … */
|
|
19
|
+
trigger?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface AuditContext {
|
|
22
|
+
requestId?: string;
|
|
23
|
+
traceId?: string;
|
|
24
|
+
ip?: string;
|
|
25
|
+
userAgent?: string;
|
|
26
|
+
correlation?: AuditCorrelation;
|
|
27
|
+
job?: AuditJobContext;
|
|
28
|
+
/**
|
|
29
|
+
* The VERIFIED principal of the inbound request. A getter, not a value: the
|
|
30
|
+
* scope opens before `requireAuth` runs, so `req.user` is read at the moment
|
|
31
|
+
* an event is recorded.
|
|
32
|
+
*/
|
|
33
|
+
principal?: () => JwtPayload | undefined;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* The credential behind an audited action — reserved `details._auth`, so it is
|
|
37
|
+
* covered by the audit hash chain (which hashes `details`). Built only from a
|
|
38
|
+
* verified token, never from caller input; the remote-audit client overwrites
|
|
39
|
+
* any `_auth` a call site put in `details`.
|
|
40
|
+
*/
|
|
41
|
+
export interface AuditAuthBlock {
|
|
42
|
+
principalType?: string;
|
|
43
|
+
/** The internal service, when the principal is a service token. */
|
|
44
|
+
service?: string;
|
|
45
|
+
/**
|
|
46
|
+
* The revocable credential: the access key (PAT / service-account key) the
|
|
47
|
+
* token derives from (`parentKeyId`), else the token's own `jti` (an exchanged
|
|
48
|
+
* key token's key id, an impersonation session id, a service mint id).
|
|
49
|
+
*/
|
|
50
|
+
keyId?: string;
|
|
51
|
+
/** Refresh-session slot the token was minted on. */
|
|
52
|
+
sid?: string;
|
|
53
|
+
scope?: string;
|
|
54
|
+
tokenUse?: string;
|
|
55
|
+
/** The token's permissions were narrowed to a subset at credential creation. */
|
|
56
|
+
permissionsRestricted?: true;
|
|
57
|
+
/** The principal is a platform superadmin. */
|
|
58
|
+
superAdmin?: true;
|
|
59
|
+
/**
|
|
60
|
+
* The principal's active org is the system org (vendor staff acting through a
|
|
61
|
+
* system-org job Role). With `superAdmin`, this is what lets the remote-audit
|
|
62
|
+
* client claim a cross-org `affectedOrgId` (see `auditCrossOrg`).
|
|
63
|
+
*/
|
|
64
|
+
systemOrg?: true;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Run `fn` inside an audit-context scope. Nested scopes MERGE onto the outer
|
|
68
|
+
* one (a job started inside a request keeps the request's id), with the inner
|
|
69
|
+
* fields winning.
|
|
70
|
+
*/
|
|
71
|
+
export declare function runWithAuditContext<T>(ctx: AuditContext, fn: () => T): T;
|
|
72
|
+
/** The active audit context, or undefined outside any scope. */
|
|
73
|
+
export declare function currentAuditContext(): AuditContext | undefined;
|
|
74
|
+
/** Inbound correlation headers recorded into the audit context. */
|
|
75
|
+
export declare const AUDIT_CORRELATION_HEADERS: {
|
|
76
|
+
readonly pipelineExecutionId: 'x-pipeline-execution-id';
|
|
77
|
+
readonly codebuildBuildId: 'x-codebuild-build-id';
|
|
78
|
+
readonly sourceEventId: 'x-source-event-id';
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Validate an inbound correlation id (`X-Request-Id`, `X-CodeBuild-Build-Id`, …):
|
|
82
|
+
* a bounded opaque token, else `undefined` — an invalid value is dropped, never
|
|
83
|
+
* truncated into something that looks like a different id.
|
|
84
|
+
*
|
|
85
|
+
* No AWS account id is ever stored: an ARN (a CodeBuild build ARN, say) has its
|
|
86
|
+
* account segment emptied, and a bare 12-digit value is refused. The generic
|
|
87
|
+
* 12-digit-run scrub is NOT used here — it would redact the all-digit final
|
|
88
|
+
* group of roughly one uuid in three hundred, corrupting the id it exists to
|
|
89
|
+
* correlate.
|
|
90
|
+
*/
|
|
91
|
+
export declare function sanitizeCorrelationId(raw: unknown): string | undefined;
|
|
92
|
+
/** Strip control characters from a User-Agent and cap its length; undefined when empty. */
|
|
93
|
+
export declare function sanitizeUserAgent(raw: unknown): string | undefined;
|
|
94
|
+
/**
|
|
95
|
+
* The audit context for an inbound request. `requestId` is the id the
|
|
96
|
+
* request-id middleware resolved (validated inbound `X-Request-Id`, else a fresh
|
|
97
|
+
* uuid); the principal is read lazily from `req.user` (auth runs later in the
|
|
98
|
+
* chain).
|
|
99
|
+
*/
|
|
100
|
+
export declare function auditContextFromRequest(req: Request, ids?: {
|
|
101
|
+
requestId?: string;
|
|
102
|
+
traceId?: string;
|
|
103
|
+
}): AuditContext;
|
|
104
|
+
/** The `_auth` block for a verified principal (undefined when there is none). */
|
|
105
|
+
export declare function auditAuthBlock(user: JwtPayload | undefined): AuditAuthBlock | undefined;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Ambient audit context: the request/job facts every audit event should carry
|
|
5
|
+
* (request id, trace id, client ip / user agent, the verified principal's
|
|
6
|
+
* credential, inbound correlation ids) without each of the ~150 `recordAudit`
|
|
7
|
+
* call sites threading them through by hand.
|
|
8
|
+
*
|
|
9
|
+
* api-server's request pipeline opens a scope per inbound request
|
|
10
|
+
* (`auditContextFromRequest` + `runWithAuditContext`); background work opens its
|
|
11
|
+
* own with `runWithAuditContext({ job: { jobId, runId, trigger } }, fn)`. The
|
|
12
|
+
* remote-audit client reads the scope when an event is RECORDED and stamps the
|
|
13
|
+
* result onto the event itself, so a spooled re-delivery minutes later still
|
|
14
|
+
* carries the context of the moment it happened.
|
|
15
|
+
*/
|
|
16
|
+
import { AsyncLocalStorage } from 'async_hooks';
|
|
17
|
+
import { serviceNameOf } from '../middleware/service-tokens.js';
|
|
18
|
+
import { isSystemOrgId } from '../middleware/system-org.js';
|
|
19
|
+
const storage = new AsyncLocalStorage();
|
|
20
|
+
/**
|
|
21
|
+
* Run `fn` inside an audit-context scope. Nested scopes MERGE onto the outer
|
|
22
|
+
* one (a job started inside a request keeps the request's id), with the inner
|
|
23
|
+
* fields winning.
|
|
24
|
+
*/
|
|
25
|
+
export function runWithAuditContext(ctx, fn) {
|
|
26
|
+
const outer = storage.getStore();
|
|
27
|
+
const merged = outer
|
|
28
|
+
? { ...outer, ...ctx, correlation: ctx.correlation ?? outer.correlation, job: ctx.job ? { ...outer.job, ...ctx.job } : outer.job }
|
|
29
|
+
: ctx;
|
|
30
|
+
return storage.run(merged, fn);
|
|
31
|
+
}
|
|
32
|
+
/** The active audit context, or undefined outside any scope. */
|
|
33
|
+
export function currentAuditContext() {
|
|
34
|
+
return storage.getStore();
|
|
35
|
+
}
|
|
36
|
+
/** Inbound correlation headers recorded into the audit context. */
|
|
37
|
+
export const AUDIT_CORRELATION_HEADERS = {
|
|
38
|
+
pipelineExecutionId: 'x-pipeline-execution-id',
|
|
39
|
+
codebuildBuildId: 'x-codebuild-build-id',
|
|
40
|
+
sourceEventId: 'x-source-event-id',
|
|
41
|
+
};
|
|
42
|
+
/** Max length of a stored correlation id / request id. */
|
|
43
|
+
const MAX_CORRELATION_LEN = 128;
|
|
44
|
+
/** Ids are opaque tokens: uuids, `project:uuid` build ids, ULIDs. Nothing else is stored. */
|
|
45
|
+
const CORRELATION_ID = /^[A-Za-z0-9._:/@+=-]+$/;
|
|
46
|
+
/** A bare AWS account id. */
|
|
47
|
+
const BARE_ACCOUNT_ID = /^\d{12}$/;
|
|
48
|
+
/** Max stored User-Agent length — a hostile header must not bloat audit rows. */
|
|
49
|
+
const MAX_USER_AGENT_LEN = 512;
|
|
50
|
+
/** C0 + DEL + C1 control characters, replaced so a UA can't inject into the UI/CSV export. */
|
|
51
|
+
const CONTROL_CHARS = new RegExp('[\\u0000-\\u001f\\u007f-\\u009f]', 'g');
|
|
52
|
+
function firstHeader(raw) {
|
|
53
|
+
return Array.isArray(raw) ? raw[0] : raw;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Validate an inbound correlation id (`X-Request-Id`, `X-CodeBuild-Build-Id`, …):
|
|
57
|
+
* a bounded opaque token, else `undefined` — an invalid value is dropped, never
|
|
58
|
+
* truncated into something that looks like a different id.
|
|
59
|
+
*
|
|
60
|
+
* No AWS account id is ever stored: an ARN (a CodeBuild build ARN, say) has its
|
|
61
|
+
* account segment emptied, and a bare 12-digit value is refused. The generic
|
|
62
|
+
* 12-digit-run scrub is NOT used here — it would redact the all-digit final
|
|
63
|
+
* group of roughly one uuid in three hundred, corrupting the id it exists to
|
|
64
|
+
* correlate.
|
|
65
|
+
*/
|
|
66
|
+
export function sanitizeCorrelationId(raw) {
|
|
67
|
+
if (typeof raw !== 'string')
|
|
68
|
+
return undefined;
|
|
69
|
+
const value = raw.trim();
|
|
70
|
+
if (value.length === 0 || value.length > MAX_CORRELATION_LEN || !CORRELATION_ID.test(value))
|
|
71
|
+
return undefined;
|
|
72
|
+
if (BARE_ACCOUNT_ID.test(value))
|
|
73
|
+
return undefined;
|
|
74
|
+
if (/^arn:/i.test(value)) {
|
|
75
|
+
const parts = value.split(':');
|
|
76
|
+
if (parts.length > 4)
|
|
77
|
+
parts[4] = '';
|
|
78
|
+
return parts.join(':');
|
|
79
|
+
}
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
/** Strip control characters from a User-Agent and cap its length; undefined when empty. */
|
|
83
|
+
export function sanitizeUserAgent(raw) {
|
|
84
|
+
if (typeof raw !== 'string' || raw.length === 0)
|
|
85
|
+
return undefined;
|
|
86
|
+
const cleaned = raw.replace(CONTROL_CHARS, ' ').trim();
|
|
87
|
+
return cleaned.length === 0 ? undefined : cleaned.slice(0, MAX_USER_AGENT_LEN);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The audit context for an inbound request. `requestId` is the id the
|
|
91
|
+
* request-id middleware resolved (validated inbound `X-Request-Id`, else a fresh
|
|
92
|
+
* uuid); the principal is read lazily from `req.user` (auth runs later in the
|
|
93
|
+
* chain).
|
|
94
|
+
*/
|
|
95
|
+
export function auditContextFromRequest(req, ids = {}) {
|
|
96
|
+
const correlation = {};
|
|
97
|
+
for (const [field, header] of Object.entries(AUDIT_CORRELATION_HEADERS)) {
|
|
98
|
+
const value = sanitizeCorrelationId(firstHeader(req.headers[header]));
|
|
99
|
+
if (value)
|
|
100
|
+
correlation[field] = value;
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
requestId: ids.requestId,
|
|
104
|
+
traceId: ids.traceId,
|
|
105
|
+
ip: req.ip,
|
|
106
|
+
userAgent: sanitizeUserAgent(firstHeader(req.headers['user-agent'])),
|
|
107
|
+
correlation: Object.keys(correlation).length > 0 ? correlation : undefined,
|
|
108
|
+
principal: () => req.user,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/** The `_auth` block for a verified principal (undefined when there is none). */
|
|
112
|
+
export function auditAuthBlock(user) {
|
|
113
|
+
if (!user)
|
|
114
|
+
return undefined;
|
|
115
|
+
const block = {
|
|
116
|
+
principalType: user.principalType,
|
|
117
|
+
service: serviceNameOf(user),
|
|
118
|
+
keyId: user.parentKeyId ?? user.jti,
|
|
119
|
+
sid: user.sid,
|
|
120
|
+
scope: user.scope,
|
|
121
|
+
tokenUse: user.token_use,
|
|
122
|
+
...(user.permissionsRestricted === true ? { permissionsRestricted: true } : {}),
|
|
123
|
+
...(user.isSuperAdmin === true ? { superAdmin: true } : {}),
|
|
124
|
+
// A SERVICE token in the system org is the platform's own plumbing, not staff
|
|
125
|
+
// acting on a tenant; only human / service-account principals count.
|
|
126
|
+
...(user.principalType !== 'service' && isSystemOrgId(user.organizationId) ? { systemOrg: true } : {}),
|
|
127
|
+
};
|
|
128
|
+
for (const key of Object.keys(block)) {
|
|
129
|
+
if (block[key] === undefined)
|
|
130
|
+
delete block[key];
|
|
131
|
+
}
|
|
132
|
+
return Object.keys(block).length > 0 ? block : undefined;
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXVkaXQtY29udGV4dC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy9hdWRpdC1jb250ZXh0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEM7Ozs7Ozs7Ozs7OztHQVlHO0FBRUgsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRWhELE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNoRSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFzRTVELE1BQU0sT0FBTyxHQUFHLElBQUksaUJBQWlCLEVBQWdCLENBQUM7QUFFdEQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxtQkFBbUIsQ0FBSSxHQUFpQixFQUFFLEVBQVc7SUFDbkUsTUFBTSxLQUFLLEdBQUcsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO0lBQ2pDLE1BQU0sTUFBTSxHQUFpQixLQUFLO1FBQ2hDLENBQUMsQ0FBQyxFQUFFLEdBQUcsS0FBSyxFQUFFLEdBQUcsR0FBRyxFQUFFLFdBQVcsRUFBRSxHQUFHLENBQUMsV0FBVyxJQUFJLEtBQUssQ0FBQyxXQUFXLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxLQUFLLENBQUMsR0FBRyxFQUFFLEdBQUcsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxFQUFFO1FBQ2xJLENBQUMsQ0FBQyxHQUFHLENBQUM7SUFDUixPQUFPLE9BQU8sQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0FBQ2pDLENBQUM7QUFFRCxnRUFBZ0U7QUFDaEUsTUFBTSxVQUFVLG1CQUFtQjtJQUNqQyxPQUFPLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQztBQUM1QixDQUFDO0FBRUQsbUVBQW1FO0FBQ25F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QUFxRTtRQUNyRSxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsS0FBSyxTQUFTLElBQUksYUFBYSxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxTQUFTLEVBQUUsSUFBYSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztLQUNoSCxDQUFDO0lBQ0YsS0FBSyxNQUFNLEdBQUcsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBZ0MsRUFBRSxDQUFDO1FBQ3BFLElBQUksS0FBSyxDQUFDLEdBQUcsQ0FBQyxLQUFLLFNBQVM7WUFBRSxPQUFPLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNsRCxDQUFDO0lBQ0QsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQzNELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLyoqXG4gKiBBbWJpZW50IGF1ZGl0IGNvbnRleHQ6IHRoZSByZXF1ZXN0L2pvYiBmYWN0cyBldmVyeSBhdWRpdCBldmVudCBzaG91bGQgY2FycnlcbiAqIChyZXF1ZXN0IGlkLCB0cmFjZSBpZCwgY2xpZW50IGlwIC8gdXNlciBhZ2VudCwgdGhlIHZlcmlmaWVkIHByaW5jaXBhbCdzXG4gKiBjcmVkZW50aWFsLCBpbmJvdW5kIGNvcnJlbGF0aW9uIGlkcykgd2l0aG91dCBlYWNoIG9mIHRoZSB+MTUwIGByZWNvcmRBdWRpdGBcbiAqIGNhbGwgc2l0ZXMgdGhyZWFkaW5nIHRoZW0gdGhyb3VnaCBieSBoYW5kLlxuICpcbiAqIGFwaS1zZXJ2ZXIncyByZXF1ZXN0IHBpcGVsaW5lIG9wZW5zIGEgc2NvcGUgcGVyIGluYm91bmQgcmVxdWVzdFxuICogKGBhdWRpdENvbnRleHRGcm9tUmVxdWVzdGAgKyBgcnVuV2l0aEF1ZGl0Q29udGV4dGApOyBiYWNrZ3JvdW5kIHdvcmsgb3BlbnMgaXRzXG4gKiBvd24gd2l0aCBgcnVuV2l0aEF1ZGl0Q29udGV4dCh7IGpvYjogeyBqb2JJZCwgcnVuSWQsIHRyaWdnZXIgfSB9LCBmbilgLiBUaGVcbiAqIHJlbW90ZS1hdWRpdCBjbGllbnQgcmVhZHMgdGhlIHNjb3BlIHdoZW4gYW4gZXZlbnQgaXMgUkVDT1JERUQgYW5kIHN0YW1wcyB0aGVcbiAqIHJlc3VsdCBvbnRvIHRoZSBldmVudCBpdHNlbGYsIHNvIGEgc3Bvb2xlZCByZS1kZWxpdmVyeSBtaW51dGVzIGxhdGVyIHN0aWxsXG4gKiBjYXJyaWVzIHRoZSBjb250ZXh0IG9mIHRoZSBtb21lbnQgaXQgaGFwcGVuZWQuXG4gKi9cblxuaW1wb3J0IHsgQXN5bmNMb2NhbFN0b3JhZ2UgfSBmcm9tICdhc3luY19ob29rcyc7XG5pbXBvcnQgdHlwZSB7IFJlcXVlc3QgfSBmcm9tICdleHByZXNzJztcbmltcG9ydCB7IHNlcnZpY2VOYW1lT2YgfSBmcm9tICcuLi9taWRkbGV3YXJlL3NlcnZpY2UtdG9rZW5zLmpzJztcbmltcG9ydCB7IGlzU3lzdGVtT3JnSWQgfSBmcm9tICcuLi9taWRkbGV3YXJlL3N5c3RlbS1vcmcuanMnO1xuaW1wb3J0IHR5cGUgeyBKd3RQYXlsb2FkIH0gZnJvbSAnLi4vdHlwZXMvY29tbW9uLmpzJztcblxuLyoqIEluYm91bmQgY29ycmVsYXRpb24gaWRzIGEgY2FsbGVyIChDTEksIExhbWJkYSwgQ29kZUJ1aWxkKSBtYXkgZm9yd2FyZC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXVkaXRDb3JyZWxhdGlvbiB7XG4gIC8qKiBgWC1QaXBlbGluZS1FeGVjdXRpb24tSWRgIOKAlCB0aGUgQ29kZVBpcGVsaW5lIGV4ZWN1dGlvbiB0aGF0IG1hZGUgdGhlIGNhbGwuICovXG4gIHBpcGVsaW5lRXhlY3V0aW9uSWQ/OiBzdHJpbmc7XG4gIC8qKiBgWC1Db2RlQnVpbGQtQnVpbGQtSWRgIOKAlCB0aGUgQ29kZUJ1aWxkIGJ1aWxkIHRoYXQgbWFkZSB0aGUgY2FsbC4gKi9cbiAgY29kZWJ1aWxkQnVpbGRJZD86IHN0cmluZztcbiAgLyoqIGBYLVNvdXJjZS1FdmVudC1JZGAg4oCUIHRoZSB1cHN0cmVhbSBldmVudCAoRXZlbnRCcmlkZ2UgLyB3ZWJob29rKSBiZWluZyBoYW5kbGVkLiAqL1xuICBzb3VyY2VFdmVudElkPzogc3RyaW5nO1xufVxuXG4vKiogQmFja2dyb3VuZC13b3JrIGlkZW50aXR5IGZvciBldmVudHMgcmVjb3JkZWQgb3V0c2lkZSBhbnkgcmVxdWVzdC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQXVkaXRKb2JDb250ZXh0IHtcbiAgLyoqIFN0YWJsZSBqb2IgbmFtZSAoZS5nLiBgcmVnaXN0cnktZ2NgLCBgdnVsbi1yZXNjYW5gKS4gKi9cbiAgam9iSWQ/OiBzdHJpbmc7XG4gIC8qKiBUaGlzIHJ1bidzIGlkIChhIEJ1bGxNUSBqb2IgaWQsIGEgc3dlZXAncyB1dWlkKS4gKi9cbiAgcnVuSWQ/OiBzdHJpbmc7XG4gIC8qKiBXaGF0IHN0YXJ0ZWQgaXQ6IGBzY2hlZHVsZWAsIGBxdWV1ZWAsIGBzdGFydHVwYCwgYG1hbnVhbGAsIOKApiAqL1xuICB0cmlnZ2VyPzogc3RyaW5nO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEF1ZGl0Q29udGV4dCB7XG4gIHJlcXVlc3RJZD86IHN0cmluZztcbiAgdHJhY2VJZD86IHN0cmluZztcbiAgaXA/OiBzdHJpbmc7XG4gIHVzZXJBZ2VudD86IHN0cmluZztcbiAgY29ycmVsYXRpb24/OiBBdWRpdENvcnJlbGF0aW9uO1xuICBqb2I/OiBBdWRpdEpvYkNvbnRleHQ7XG4gIC8qKlxuICAgKiBUaGUgVkVSSUZJRUQgcHJpbmNpcGFsIG9mIHRoZSBpbmJvdW5kIHJlcXVlc3QuIEEgZ2V0dGVyLCBub3QgYSB2YWx1ZTogdGhlXG4gICAqIHNjb3BlIG9wZW5zIGJlZm9yZSBgcmVxdWlyZUF1dGhgIHJ1bnMsIHNvIGByZXEudXNlcmAgaXMgcmVhZCBhdCB0aGUgbW9tZW50XG4gICAqIGFuIGV2ZW50IGlzIHJlY29yZGVkLlxuICAgKi9cbiAgcHJpbmNpcGFsPzogKCkgPT4gSnd0UGF5bG9hZCB8IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBUaGUgY3JlZGVudGlhbCBiZWhpbmQgYW4gYXVkaXRlZCBhY3Rpb24g4oCUIHJlc2VydmVkIGBkZXRhaWxzLl9hdXRoYCwgc28gaXQgaXNcbiAqIGNvdmVyZWQgYnkgdGhlIGF1ZGl0IGhhc2ggY2hhaW4gKHdoaWNoIGhhc2hlcyBgZGV0YWlsc2ApLiBCdWlsdCBvbmx5IGZyb20gYVxuICogdmVyaWZpZWQgdG9rZW4sIG5ldmVyIGZyb20gY2FsbGVyIGlucHV0OyB0aGUgcmVtb3RlLWF1ZGl0IGNsaWVudCBvdmVyd3JpdGVzXG4gKiBhbnkgYF9hdXRoYCBhIGNhbGwgc2l0ZSBwdXQgaW4gYGRldGFpbHNgLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEF1ZGl0QXV0aEJsb2NrIHtcbiAgcHJpbmNpcGFsVHlwZT86IHN0cmluZztcbiAgLyoqIFRoZSBpbnRlcm5hbCBzZXJ2aWNlLCB3aGVuIHRoZSBwcmluY2lwYWwgaXMgYSBzZXJ2aWNlIHRva2VuLiAqL1xuICBzZXJ2aWNlPzogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIHJldm9jYWJsZSBjcmVkZW50aWFsOiB0aGUgYWNjZXNzIGtleSAoUEFUIC8gc2VydmljZS1hY2NvdW50IGtleSkgdGhlXG4gICAqIHRva2VuIGRlcml2ZXMgZnJvbSAoYHBhcmVudEtleUlkYCksIGVsc2UgdGhlIHRva2VuJ3Mgb3duIGBqdGlgIChhbiBleGNoYW5nZWRcbiAgICoga2V5IHRva2VuJ3Mga2V5IGlkLCBhbiBpbXBlcnNvbmF0aW9uIHNlc3Npb24gaWQsIGEgc2VydmljZSBtaW50IGlkKS5cbiAgICovXG4gIGtleUlkPzogc3RyaW5nO1xuICAvKiogUmVmcmVzaC1zZXNzaW9uIHNsb3QgdGhlIHRva2VuIHdhcyBtaW50ZWQgb24uICovXG4gIHNpZD86IHN0cmluZztcbiAgc2NvcGU/OiBzdHJpbmc7XG4gIHRva2VuVXNlPzogc3RyaW5nO1xuICAvKiogVGhlIHRva2VuJ3MgcGVybWlzc2lvbnMgd2VyZSBuYXJyb3dlZCB0byBhIHN1YnNldCBhdCBjcmVkZW50aWFsIGNyZWF0aW9uLiAqL1xuICBwZXJtaXNzaW9uc1Jlc3RyaWN0ZWQ/OiB0cnVlO1xuICAvKiogVGhlIHByaW5jaXBhbCBpcyBhIHBsYXRmb3JtIHN1cGVyYWRtaW4uICovXG4gIHN1cGVyQWRtaW4/OiB0cnVlO1xuICAvKipcbiAgICogVGhlIHByaW5jaXBhbCdzIGFjdGl2ZSBvcmcgaXMgdGhlIHN5c3RlbSBvcmcgKHZlbmRvciBzdGFmZiBhY3RpbmcgdGhyb3VnaCBhXG4gICAqIHN5c3RlbS1vcmcgam9iIFJvbGUpLiBXaXRoIGBzdXBlckFkbWluYCwgdGhpcyBpcyB3aGF0IGxldHMgdGhlIHJlbW90ZS1hdWRpdFxuICAgKiBjbGllbnQgY2xhaW0gYSBjcm9zcy1vcmcgYGFmZmVjdGVkT3JnSWRgIChzZWUgYGF1ZGl0Q3Jvc3NPcmdgKS5cbiAgICovXG4gIHN5c3RlbU9yZz86IHRydWU7XG59XG5cbmNvbnN0IHN0b3JhZ2UgPSBuZXcgQXN5bmNMb2NhbFN0b3JhZ2U8QXVkaXRDb250ZXh0PigpO1xuXG4vKipcbiAqIFJ1biBgZm5gIGluc2lkZSBhbiBhdWRpdC1jb250ZXh0IHNjb3BlLiBOZXN0ZWQgc2NvcGVzIE1FUkdFIG9udG8gdGhlIG91dGVyXG4gKiBvbmUgKGEgam9iIHN0YXJ0ZWQgaW5zaWRlIGEgcmVxdWVzdCBrZWVwcyB0aGUgcmVxdWVzdCdzIGlkKSwgd2l0aCB0aGUgaW5uZXJcbiAqIGZpZWxkcyB3aW5uaW5nLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcnVuV2l0aEF1ZGl0Q29udGV4dDxUPihjdHg6IEF1ZGl0Q29udGV4dCwgZm46ICgpID0+IFQpOiBUIHtcbiAgY29uc3Qgb3V0ZXIgPSBzdG9yYWdlLmdldFN0b3JlKCk7XG4gIGNvbnN0IG1lcmdlZDogQXVkaXRDb250ZXh0ID0gb3V0ZXJcbiAgICA/IHsgLi4ub3V0ZXIsIC4uLmN0eCwgY29ycmVsYXRpb246IGN0eC5jb3JyZWxhdGlvbiA/PyBvdXRlci5jb3JyZWxhdGlvbiwgam9iOiBjdHguam9iID8geyAuLi5vdXRlci5qb2IsIC4uLmN0eC5qb2IgfSA6IG91dGVyLmpvYiB9XG4gICAgOiBjdHg7XG4gIHJldHVybiBzdG9yYWdlLnJ1bihtZXJnZWQsIGZuKTtcbn1cblxuLyoqIFRoZSBhY3RpdmUgYXVkaXQgY29udGV4dCwgb3IgdW5kZWZpbmVkIG91dHNpZGUgYW55IHNjb3BlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGN1cnJlbnRBdWRpdENvbnRleHQoKTogQXVkaXRDb250ZXh0IHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHN0b3JhZ2UuZ2V0U3RvcmUoKTtcbn1cblxuLyoqIEluYm91bmQgY29ycmVsYXRpb24gaGVhZGVycyByZWNvcmRlZCBpbnRvIHRoZSBhdWRpdCBjb250ZXh0LiAqL1xuZXhwb3J0IGNvbnN0IEFVRElUX0NPUlJFTEFUSU9OX0hFQURFUlMgPSB7XG4gIHBpcGVsaW5lRXhlY3V0aW9uSWQ6ICd4LXBpcGVsaW5lLWV4ZWN1dGlvbi1pZCcsXG4gIGNvZGVidWlsZEJ1aWxkSWQ6ICd4LWNvZGVidWlsZC1idWlsZC1pZCcsXG4gIHNvdXJjZUV2ZW50SWQ6ICd4LXNvdXJjZS1ldmVudC1pZCcsXG59IGFzIGNvbnN0O1xuXG4vKiogTWF4IGxlbmd0aCBvZiBhIHN0b3JlZCBjb3JyZWxhdGlvbiBpZCAvIHJlcXVlc3QgaWQuICovXG5jb25zdCBNQVhfQ09SUkVMQVRJT05fTEVOID0gMTI4O1xuLyoqIElkcyBhcmUgb3BhcXVlIHRva2VuczogdXVpZHMsIGBwcm9qZWN0OnV1aWRgIGJ1aWxkIGlkcywgVUxJRHMuIE5vdGhpbmcgZWxzZSBpcyBzdG9yZWQuICovXG5jb25zdCBDT1JSRUxBVElPTl9JRCA9IC9eW0EtWmEtejAtOS5fOi9AKz0tXSskLztcbi8qKiBBIGJhcmUgQVdTIGFjY291bnQgaWQuICovXG5jb25zdCBCQVJFX0FDQ09VTlRfSUQgPSAvXlxcZHsxMn0kLztcblxuLyoqIE1heCBzdG9yZWQgVXNlci1BZ2VudCBsZW5ndGgg4oCUIGEgaG9zdGlsZSBoZWFkZXIgbXVzdCBub3QgYmxvYXQgYXVkaXQgcm93cy4gKi9cbmNvbnN0IE1BWF9VU0VSX0FHRU5UX0xFTiA9IDUxMjtcbi8qKiBDMCArIERFTCArIEMxIGNvbnRyb2wgY2hhcmFjdGVycywgcmVwbGFjZWQgc28gYSBVQSBjYW4ndCBpbmplY3QgaW50byB0aGUgVUkvQ1NWIGV4cG9ydC4gKi9cbmNvbnN0IENPTlRST0xfQ0hBUlMgPSBuZXcgUmVnRXhwKCdbXFxcXHUwMDAwLVxcXFx1MDAxZlxcXFx1MDA3Zi1cXFxcdTAwOWZdJywgJ2cnKTtcblxuZnVuY3Rpb24gZmlyc3RIZWFkZXIocmF3OiBzdHJpbmcgfCBzdHJpbmdbXSB8IHVuZGVmaW5lZCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBBcnJheS5pc0FycmF5KHJhdykgPyByYXdbMF0gOiByYXc7XG59XG5cbi8qKlxuICogVmFsaWRhdGUgYW4gaW5ib3VuZCBjb3JyZWxhdGlvbiBpZCAoYFgtUmVxdWVzdC1JZGAsIGBYLUNvZGVCdWlsZC1CdWlsZC1JZGAsIOKApik6XG4gKiBhIGJvdW5kZWQgb3BhcXVlIHRva2VuLCBlbHNlIGB1bmRlZmluZWRgIOKAlCBhbiBpbnZhbGlkIHZhbHVlIGlzIGRyb3BwZWQsIG5ldmVyXG4gKiB0cnVuY2F0ZWQgaW50byBzb21ldGhpbmcgdGhhdCBsb29rcyBsaWtlIGEgZGlmZmVyZW50IGlkLlxuICpcbiAqIE5vIEFXUyBhY2NvdW50IGlkIGlzIGV2ZXIgc3RvcmVkOiBhbiBBUk4gKGEgQ29kZUJ1aWxkIGJ1aWxkIEFSTiwgc2F5KSBoYXMgaXRzXG4gKiBhY2NvdW50IHNlZ21lbnQgZW1wdGllZCwgYW5kIGEgYmFyZSAxMi1kaWdpdCB2YWx1ZSBpcyByZWZ1c2VkLiBUaGUgZ2VuZXJpY1xuICogMTItZGlnaXQtcnVuIHNjcnViIGlzIE5PVCB1c2VkIGhlcmUg4oCUIGl0IHdvdWxkIHJlZGFjdCB0aGUgYWxsLWRpZ2l0IGZpbmFsXG4gKiBncm91cCBvZiByb3VnaGx5IG9uZSB1dWlkIGluIHRocmVlIGh1bmRyZWQsIGNvcnJ1cHRpbmcgdGhlIGlkIGl0IGV4aXN0cyB0b1xuICogY29ycmVsYXRlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2FuaXRpemVDb3JyZWxhdGlvbklkKHJhdzogdW5rbm93bik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGlmICh0eXBlb2YgcmF3ICE9PSAnc3RyaW5nJykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3QgdmFsdWUgPSByYXcudHJpbSgpO1xuICBpZiAodmFsdWUubGVuZ3RoID09PSAwIHx8IHZhbHVlLmxlbmd0aCA+IE1BWF9DT1JSRUxBVElPTl9MRU4gfHwgIUNPUlJFTEFUSU9OX0lELnRlc3QodmFsdWUpKSByZXR1cm4gdW5kZWZpbmVkO1xuICBpZiAoQkFSRV9BQ0NPVU5UX0lELnRlc3QodmFsdWUpKSByZXR1cm4gdW5kZWZpbmVkO1xuICBpZiAoL15hcm46L2kudGVzdCh2YWx1ZSkpIHtcbiAgICBjb25zdCBwYXJ0cyA9IHZhbHVlLnNwbGl0KCc6Jyk7XG4gICAgaWYgKHBhcnRzLmxlbmd0aCA+IDQpIHBhcnRzWzRdID0gJyc7XG4gICAgcmV0dXJuIHBhcnRzLmpvaW4oJzonKTtcbiAgfVxuICByZXR1cm4gdmFsdWU7XG59XG5cbi8qKiBTdHJpcCBjb250cm9sIGNoYXJhY3RlcnMgZnJvbSBhIFVzZXItQWdlbnQgYW5kIGNhcCBpdHMgbGVuZ3RoOyB1bmRlZmluZWQgd2hlbiBlbXB0eS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzYW5pdGl6ZVVzZXJBZ2VudChyYXc6IHVua25vd24pOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBpZiAodHlwZW9mIHJhdyAhPT0gJ3N0cmluZycgfHwgcmF3Lmxlbmd0aCA9PT0gMCkgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3QgY2xlYW5lZCA9IHJhdy5yZXBsYWNlKENPTlRST0xfQ0hBUlMsICcgJykudHJpbSgpO1xuICByZXR1cm4gY2xlYW5lZC5sZW5ndGggPT09IDAgPyB1bmRlZmluZWQgOiBjbGVhbmVkLnNsaWNlKDAsIE1BWF9VU0VSX0FHRU5UX0xFTik7XG59XG5cbi8qKlxuICogVGhlIGF1ZGl0IGNvbnRleHQgZm9yIGFuIGluYm91bmQgcmVxdWVzdC4gYHJlcXVlc3RJZGAgaXMgdGhlIGlkIHRoZVxuICogcmVxdWVzdC1pZCBtaWRkbGV3YXJlIHJlc29sdmVkICh2YWxpZGF0ZWQgaW5ib3VuZCBgWC1SZXF1ZXN0LUlkYCwgZWxzZSBhIGZyZXNoXG4gKiB1dWlkKTsgdGhlIHByaW5jaXBhbCBpcyByZWFkIGxhemlseSBmcm9tIGByZXEudXNlcmAgKGF1dGggcnVucyBsYXRlciBpbiB0aGVcbiAqIGNoYWluKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGF1ZGl0Q29udGV4dEZyb21SZXF1ZXN0KHJlcTogUmVxdWVzdCwgaWRzOiB7IHJlcXVlc3RJZD86IHN0cmluZzsgdHJhY2VJZD86IHN0cmluZyB9ID0ge30pOiBBdWRpdENvbnRleHQge1xuICBjb25zdCBjb3JyZWxhdGlvbjogQXVkaXRDb3JyZWxhdGlvbiA9IHt9O1xuICBmb3IgKGNvbnN0IFtmaWVsZCwgaGVhZGVyXSBvZiBPYmplY3QuZW50cmllcyhBVURJVF9DT1JSRUxBVElPTl9IRUFERVJTKSBhcyBBcnJheTxba2V5b2YgQXVkaXRDb3JyZWxhdGlvbiwgc3RyaW5nXT4pIHtcbiAgICBjb25zdCB2YWx1ZSA9IHNhbml0aXplQ29ycmVsYXRpb25JZChmaXJzdEhlYWRlcihyZXEuaGVhZGVyc1toZWFkZXJdKSk7XG4gICAgaWYgKHZhbHVlKSBjb3JyZWxhdGlvbltmaWVsZF0gPSB2YWx1ZTtcbiAgfVxuICByZXR1cm4ge1xuICAgIHJlcXVlc3RJZDogaWRzLnJlcXVlc3RJZCxcbiAgICB0cmFjZUlkOiBpZHMudHJhY2VJZCxcbiAgICBpcDogcmVxLmlwLFxuICAgIHVzZXJBZ2VudDogc2FuaXRpemVVc2VyQWdlbnQoZmlyc3RIZWFkZXIocmVxLmhlYWRlcnNbJ3VzZXItYWdlbnQnXSkpLFxuICAgIGNvcnJlbGF0aW9uOiBPYmplY3Qua2V5cyhjb3JyZWxhdGlvbikubGVuZ3RoID4gMCA/IGNvcnJlbGF0aW9uIDogdW5kZWZpbmVkLFxuICAgIHByaW5jaXBhbDogKCkgPT4gcmVxLnVzZXIsXG4gIH07XG59XG5cbi8qKiBUaGUgYF9hdXRoYCBibG9jayBmb3IgYSB2ZXJpZmllZCBwcmluY2lwYWwgKHVuZGVmaW5lZCB3aGVuIHRoZXJlIGlzIG5vbmUpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGF1ZGl0QXV0aEJsb2NrKHVzZXI6IEp3dFBheWxvYWQgfCB1bmRlZmluZWQpOiBBdWRpdEF1dGhCbG9jayB8IHVuZGVmaW5lZCB7XG4gIGlmICghdXNlcikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3QgYmxvY2s6IEF1ZGl0QXV0aEJsb2NrID0ge1xuICAgIHByaW5jaXBhbFR5cGU6IHVzZXIucHJpbmNpcGFsVHlwZSxcbiAgICBzZXJ2aWNlOiBzZXJ2aWNlTmFtZU9mKHVzZXIpLFxuICAgIGtleUlkOiB1c2VyLnBhcmVudEtleUlkID8/IHVzZXIuanRpLFxuICAgIHNpZDogdXNlci5zaWQsXG4gICAgc2NvcGU6IHVzZXIuc2NvcGUsXG4gICAgdG9rZW5Vc2U6IHVzZXIudG9rZW5fdXNlLFxuICAgIC4uLih1c2VyLnBlcm1pc3Npb25zUmVzdHJpY3RlZCA9PT0gdHJ1ZSA/IHsgcGVybWlzc2lvbnNSZXN0cmljdGVkOiB0cnVlIGFzIGNvbnN0IH0gOiB7fSksXG4gICAgLi4uKHVzZXIuaXNTdXBlckFkbWluID09PSB0cnVlID8geyBzdXBlckFkbWluOiB0cnVlIGFzIGNvbnN0IH0gOiB7fSksXG4gICAgLy8gQSBTRVJWSUNFIHRva2VuIGluIHRoZSBzeXN0ZW0gb3JnIGlzIHRoZSBwbGF0Zm9ybSdzIG93biBwbHVtYmluZywgbm90IHN0YWZmXG4gICAgLy8gYWN0aW5nIG9uIGEgdGVuYW50OyBvbmx5IGh1bWFuIC8gc2VydmljZS1hY2NvdW50IHByaW5jaXBhbHMgY291bnQuXG4gICAgLi4uKHVzZXIucHJpbmNpcGFsVHlwZSAhPT0gJ3NlcnZpY2UnICYmIGlzU3lzdGVtT3JnSWQodXNlci5vcmdhbml6YXRpb25JZCkgPyB7IHN5c3RlbU9yZzogdHJ1ZSBhcyBjb25zdCB9IDoge30pLFxuICB9O1xuICBmb3IgKGNvbnN0IGtleSBvZiBPYmplY3Qua2V5cyhibG9jaykgYXMgQXJyYXk8a2V5b2YgQXVkaXRBdXRoQmxvY2s+KSB7XG4gICAgaWYgKGJsb2NrW2tleV0gPT09IHVuZGVmaW5lZCkgZGVsZXRlIGJsb2NrW2tleV07XG4gIH1cbiAgcmV0dXJuIE9iamVjdC5rZXlzKGJsb2NrKS5sZW5ndGggPiAwID8gYmxvY2sgOiB1bmRlZmluZWQ7XG59XG4iXX0=
|
package/lib/services/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { createCacheService, type RedisCacheClient, type CacheInvalidationMessag
|
|
|
3
3
|
export { withLeaderLock, createEnvRedisLock, leaderLockKey, DEFAULT_LEADER_LOCK_TTL_MS, type LockRedis, type LeaderLockRun, type LeaderLockOptions, type LeaderLockAbortReason, } from './leader-lock.js';
|
|
4
4
|
export { sendSystemNotification, SYSTEM_NOTIFY_PATH, type SystemNotification, } from './system-notification.js';
|
|
5
5
|
export { createScheduler, type SchedulerOptions, type Scheduler, } from './scheduler.js';
|
|
6
|
+
export { assessVersionVulns, versionScanFacts, scanFreshness, scanWarnings, lastScannedAt, scanStaleHours, severityOf, maxSeverity, severityAtLeast, VULN_SEVERITIES, setVulnPolicyComplianceClientForTests, type VulnSeverity, type VulnWarning, type ScannedRecord, type VulnConsumptionPolicy, type VulnAcceptance, type VersionScanFacts, type VersionVulnInput, type VersionVulnAssessment, } from './version-vuln-policy.js';
|
|
6
7
|
export { createComplianceClient, type ComplianceCheckResult, type ComplianceViolation, } from './compliance-client.js';
|
|
7
8
|
export { pluginRunsOwnImage, pluginComplianceTags, derivePluginImageCompliance, type PluginComplianceAttributes, PLUGIN_IMAGE_COMPLIANCE_FIELDS, type PluginImageRow, } from '../utils/plugin-compliance.js';
|
|
8
9
|
export * from './compliance-event-subscriber.js';
|
|
@@ -15,8 +16,11 @@ export { createEnvRedisDurableEventBus, type EventSubscription, type DurableEven
|
|
|
15
16
|
export { getErrorRetryDecision, } from './retry-strategy.js';
|
|
16
17
|
export type { RetryConfig, } from './retry-strategy.js';
|
|
17
18
|
export { nextBackoffMs, retryForever, } from './retry-forever.js';
|
|
18
|
-
export { getQuotaServiceAuthHeader, createQuotaService, incrementQuota, reserveQuota, sendQuotaReserveDenied, decrementQuota, type QuotaReserveResult, type QuotaService, } from './quota.js';
|
|
19
|
-
export {
|
|
19
|
+
export { getQuotaServiceAuthHeader, createQuotaService, incrementQuota, reserveQuota, sendQuotaReserveDenied, decrementQuota, meteredQuotaTypeFor, callQuotaExemption, QUOTA_CHECK_TIMEOUT_MS, quotaAttributionFromRequest, type AiKeySource, type AiLimitCode, type CallQuotaExemption, type QuotaReserveResult, type QuotaTokenUsage, type QuotaService, type QuotaUsageAttribution, } from './quota.js';
|
|
20
|
+
export { aiCallWeight, parseAiModelWeights, MAX_AI_CALL_WEIGHT, } from './ai-call-weight.js';
|
|
21
|
+
export { QuotaIncrementBatcher, flushQuotaIncrements, QUOTA_INCREMENT_FLUSH_MS, QUOTA_INCREMENT_BUFFER_MAX, MAX_GROUPS_PER_INCREMENT, type MeteredIncrementGroup, } from './quota-increment-batcher.js';
|
|
22
|
+
export { createRemoteAuditClient, wireAuthzDenialAuditor, recordAudit, type RemoteAuditEvent, type RemoteAuditWireEvent, type RemoteAuditClient, } from './remote-audit-client.js';
|
|
23
|
+
export { runWithAuditContext, currentAuditContext, auditContextFromRequest, auditAuthBlock, sanitizeCorrelationId, sanitizeUserAgent, AUDIT_CORRELATION_HEADERS, type AuditContext, type AuditCorrelation, type AuditJobContext, type AuditAuthBlock, } from './audit-context.js';
|
|
20
24
|
export { auditSpoolKey, createEnvRedisAuditSpool, type AuditSpool, } from './audit-spool.js';
|
|
21
25
|
export { resolveRedisConnection, describeRedisConnection, createRedisClient, createEnvRedisClient, createRedisReadyGate, incrWindow, RedisConfigError, type RedisEvalClient, } from './env-redis.js';
|
|
22
26
|
export { createRedisTokenRevocationStore, createEnvRedisTokenRevocationStore, publishTokenRevocation, publishSessionRevocation, publishCredentialRevocation, } from './token-revocation.js';
|
|
@@ -27,3 +31,4 @@ export { alertDeliveryConfig, canDeliverAnywhere, deadmanConfig, reportAlertDeli
|
|
|
27
31
|
export { verifyPagerDutySignature, onCallInboundConfig, fetchRotaCoverage, parseOnCallWebhook, ackLatencySeconds, PAGERDUTY_API_URL, type OnCallInboundConfig, type OnCallWebhookEvent, type OnCallWebhookEventType, type RotaCoverage, } from './pagerduty-inbound.js';
|
|
28
32
|
export { sendPagerDutyEvent, pagerDutyConfig, resolveEventsEndpoint, PAGERDUTY_EVENTS_URL, type OnCallProvider, type PagerDutyAction, type PagerDutyConfig, type PagerDutyEvent, type PagerDutyResult, type PagerDutySeverity, } from './pagerduty.js';
|
|
29
33
|
export { createEcosystemNotifyClient, ECOSYSTEM_NOTIFY_PATH, type EcosystemNotifyClient, } from './ecosystem-notify-client.js';
|
|
34
|
+
export { fetchOrgAIAccess, fetchOrgAIKey, assertOrgAIEnabled, requireOrgAIEnabled, resetOrgAICache, ORG_AI_ACCESS_PATH, ORG_AI_KEYS_PATH, type OrgAIAccess, } from './org-ai-client.js';
|