@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.
Files changed (81) hide show
  1. package/lib/constants/ai-providers.d.ts +3 -22
  2. package/lib/constants/ai-providers.js +6 -56
  3. package/lib/errors/app-errors.d.ts +14 -0
  4. package/lib/errors/app-errors.js +21 -1
  5. package/lib/helpers/sse-helpers.d.ts +33 -3
  6. package/lib/helpers/sse-helpers.js +91 -19
  7. package/lib/middleware/auth.js +6 -3
  8. package/lib/middleware/deferred-quota-check.d.ts +5 -0
  9. package/lib/middleware/deferred-quota-check.js +33 -0
  10. package/lib/middleware/ecosystem-guard.d.ts +3 -3
  11. package/lib/middleware/ecosystem-guard.js +5 -5
  12. package/lib/middleware/index.d.ts +5 -2
  13. package/lib/middleware/index.js +6 -3
  14. package/lib/middleware/on-behalf.d.ts +37 -0
  15. package/lib/middleware/on-behalf.js +143 -0
  16. package/lib/middleware/permission-gates.d.ts +11 -0
  17. package/lib/middleware/permission-gates.js +7 -1
  18. package/lib/middleware/quota-exempt-routes.d.ts +36 -0
  19. package/lib/middleware/quota-exempt-routes.js +47 -0
  20. package/lib/middleware/route-table.d.ts +104 -0
  21. package/lib/middleware/route-table.js +72 -2
  22. package/lib/middleware/service-tokens.d.ts +8 -0
  23. package/lib/middleware/service-tokens.js +2 -1
  24. package/lib/middleware/step-up.js +11 -1
  25. package/lib/services/ai-call-weight.d.ts +24 -0
  26. package/lib/services/ai-call-weight.js +77 -0
  27. package/lib/services/audit-context.d.ts +105 -0
  28. package/lib/services/audit-context.js +134 -0
  29. package/lib/services/index.d.ts +7 -2
  30. package/lib/services/index.js +7 -2
  31. package/lib/services/org-ai-client.d.ts +61 -0
  32. package/lib/services/org-ai-client.js +112 -0
  33. package/lib/services/quota-increment-batcher.d.ts +81 -0
  34. package/lib/services/quota-increment-batcher.js +166 -0
  35. package/lib/services/quota.d.ts +158 -14
  36. package/lib/services/quota.js +252 -22
  37. package/lib/services/remote-audit-client.d.ts +44 -1
  38. package/lib/services/remote-audit-client.js +106 -20
  39. package/lib/services/version-vuln-policy.d.ts +174 -0
  40. package/lib/services/version-vuln-policy.js +242 -0
  41. package/lib/types/ai-catalog.d.ts +63 -0
  42. package/lib/types/ai-catalog.js +82 -0
  43. package/lib/types/ask-proposals.js +6 -6
  44. package/lib/types/build-catalog.d.ts +154 -0
  45. package/lib/types/build-catalog.js +158 -0
  46. package/lib/types/common.d.ts +37 -3
  47. package/lib/types/common.js +20 -2
  48. package/lib/types/ecosystem-notifications.d.ts +5 -5
  49. package/lib/types/ecosystem-notifications.js +9 -3
  50. package/lib/types/error-codes.d.ts +13 -6
  51. package/lib/types/error-codes.js +18 -8
  52. package/lib/types/feature-flags.d.ts +6 -4
  53. package/lib/types/feature-flags.js +11 -6
  54. package/lib/types/index.d.ts +6 -4
  55. package/lib/types/index.js +12 -5
  56. package/lib/types/metadata-keys.d.ts +6 -0
  57. package/lib/types/metadata-keys.js +4 -1
  58. package/lib/types/permissions.d.ts +344 -3
  59. package/lib/types/permissions.js +596 -21
  60. package/lib/types/pipeline.d.ts +39 -0
  61. package/lib/types/pipeline.js +57 -1
  62. package/lib/types/plugin-health.d.ts +0 -2
  63. package/lib/types/plugin-health.js +1 -11
  64. package/lib/types/plugin-scan.d.ts +192 -42
  65. package/lib/types/plugin-scan.js +159 -43
  66. package/lib/types/quota-catalog.d.ts +247 -0
  67. package/lib/types/quota-catalog.js +122 -0
  68. package/lib/types/quota-tiers.d.ts +118 -0
  69. package/lib/types/quota-tiers.js +153 -2
  70. package/lib/types/remote-audit-actions.d.ts +1 -1
  71. package/lib/types/remote-audit-actions.js +131 -1
  72. package/lib/types/wire-vocabulary.js +8 -1
  73. package/lib/utils/index.d.ts +1 -1
  74. package/lib/utils/index.js +2 -2
  75. package/lib/utils/response.d.ts +35 -2
  76. package/lib/utils/response.js +42 -3
  77. package/lib/validation/ai-schemas.d.ts +27 -0
  78. package/lib/validation/ai-schemas.js +31 -5
  79. package/lib/validation/plugin-schemas.d.ts +15 -0
  80. package/lib/validation/plugin-schemas.js +28 -1
  81. 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=
@@ -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 { createRemoteAuditClient, wireAuthzDenialAuditor, recordAudit, type RemoteAuditEvent, type RemoteAuditClient, } from './remote-audit-client.js';
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';