@pipeline-builder/api-core 3.4.35 → 3.4.37

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.
@@ -53,19 +53,19 @@ exports.FEATURE_METADATA = {
53
53
  /**
54
54
  * Resolve a user's effective feature set.
55
55
  *
56
- * 1. System org users always get ALL features.
56
+ * 1. Sysadmins (isSuperAdmin) always get ALL features.
57
57
  * 2. Start with the tier's default features.
58
58
  * 3. Apply per-user overrides: `true` adds a feature, `false` removes it.
59
59
  * 4. Invalid override keys are silently ignored.
60
60
  *
61
61
  * @param tier - The organization's quota tier
62
62
  * @param featureOverrides - Per-user overrides (key = feature flag, value = enabled)
63
- * @param isSystemOrg - Whether the user belongs to the system organization
63
+ * @param isSuperAdmin - Whether the user has the global super-admin flag
64
64
  * @returns Sorted array of enabled feature flags
65
65
  */
66
- function resolveUserFeatures(tier, featureOverrides, isSystemOrg) {
67
- // System org always gets everything
68
- if (isSystemOrg)
66
+ function resolveUserFeatures(tier, featureOverrides, isSuperAdmin) {
67
+ // Sysadmins get everything regardless of tier.
68
+ if (isSuperAdmin)
69
69
  return [...exports.ALL_FEATURE_FLAGS];
70
70
  // Start with tier defaults
71
71
  const features = new Set(exports.TIER_FEATURES[tier] ?? []);
@@ -91,11 +91,11 @@ function resolveUserFeatures(tier, featureOverrides, isSystemOrg) {
91
91
  * @param tier - The organization's quota tier
92
92
  * @param feature - The feature flag to check
93
93
  * @param featureOverrides - Per-user overrides
94
- * @param isSystemOrg - Whether the user belongs to the system organization
94
+ * @param isSuperAdmin - Whether the user has the global super-admin flag
95
95
  * @returns true if the feature is enabled
96
96
  */
97
- function hasFeature(tier, feature, featureOverrides, isSystemOrg) {
98
- if (isSystemOrg)
97
+ function hasFeature(tier, feature, featureOverrides, isSuperAdmin) {
98
+ if (isSuperAdmin)
99
99
  return true;
100
100
  // Check override first
101
101
  if (featureOverrides && feature in featureOverrides) {
@@ -104,4 +104,4 @@ function hasFeature(tier, feature, featureOverrides, isSystemOrg) {
104
104
  // Fall back to tier default
105
105
  return (exports.TIER_FEATURES[tier] ?? []).includes(feature);
106
106
  }
107
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmVhdHVyZS1mbGFncy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eXBlcy9mZWF0dXJlLWZsYWdzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDOzs7QUF3QnRDLGdEQUVDO0FBb0RELGtEQXlCQztBQVdELGdDQWVDO0FBbkhELGdFQUFnRTtBQUNuRCxRQUFBLGlCQUFpQixHQUEyQjtJQUN2RCxrQkFBa0I7SUFDbEIsZUFBZTtJQUNmLGlCQUFpQjtJQUNqQixxQkFBcUI7SUFDckIsV0FBVztDQUNaLENBQUM7QUFFRixxREFBcUQ7QUFDckQsU0FBZ0Isa0JBQWtCLENBQUMsS0FBYTtJQUM5QyxPQUFRLHlCQUF1QyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNsRSxDQUFDO0FBRUQsMEJBQTBCO0FBRTFCLGlEQUFpRDtBQUNwQyxRQUFBLGFBQWEsR0FBOEM7SUFDdEUsU0FBUyxFQUFFLEVBQUU7SUFDYixHQUFHLEVBQUUsQ0FBQyxrQkFBa0IsRUFBRSxlQUFlLEVBQUUsaUJBQWlCLENBQUM7SUFDN0QsU0FBUyxFQUFFLENBQUMsR0FBRyx5QkFBaUIsQ0FBQztDQUNsQyxDQUFDO0FBRUYsaUNBQWlDO0FBRWpDLHFEQUFxRDtBQUN4QyxRQUFBLGdCQUFnQixHQUFnRTtJQUMzRixnQkFBZ0IsRUFBRTtRQUNoQixLQUFLLEVBQUUsa0JBQWtCO1FBQ3pCLFdBQVcsRUFBRSxzREFBc0Q7S0FDcEU7SUFDRCxhQUFhLEVBQUU7UUFDYixLQUFLLEVBQUUsZUFBZTtRQUN0QixXQUFXLEVBQUUsMkNBQTJDO0tBQ3pEO0lBQ0QsZUFBZSxFQUFFO1FBQ2YsS0FBSyxFQUFFLGlCQUFpQjtRQUN4QixXQUFXLEVBQUUsNERBQTREO0tBQzFFO0lBQ0QsbUJBQW1CLEVBQUU7UUFDbkIsS0FBSyxFQUFFLHFCQUFxQjtRQUM1QixXQUFXLEVBQUUsMkRBQTJEO0tBQ3pFO0lBQ0QsU0FBUyxFQUFFO1FBQ1QsS0FBSyxFQUFFLFdBQVc7UUFDbEIsV0FBVyxFQUFFLHFEQUFxRDtLQUNuRTtDQUNGLENBQUM7QUFFRixtQkFBbUI7QUFFbkI7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsU0FBZ0IsbUJBQW1CLENBQ2pDLElBQWUsRUFDZixnQkFBaUQsRUFDakQsV0FBcUI7SUFFckIsb0NBQW9DO0lBQ3BDLElBQUksV0FBVztRQUFFLE9BQU8sQ0FBQyxHQUFHLHlCQUFpQixDQUFDLENBQUM7SUFFL0MsMkJBQTJCO0lBQzNCLE1BQU0sUUFBUSxHQUFHLElBQUksR0FBRyxDQUFjLHFCQUFhLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFFakUsMkJBQTJCO0lBQzNCLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztRQUNyQixLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUM7WUFDOUQsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQztnQkFBRSxTQUFTO1lBQ3ZDLElBQUksT0FBTyxFQUFFLENBQUM7Z0JBQ1osUUFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNwQixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sUUFBUSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN2QixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRCw0QkFBNEI7SUFDNUIsT0FBTyx5QkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDeEQsQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsU0FBZ0IsVUFBVSxDQUN4QixJQUFlLEVBQ2YsT0FBb0IsRUFDcEIsZ0JBQWlELEVBQ2pELFdBQXFCO0lBRXJCLElBQUksV0FBVztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBRTdCLHVCQUF1QjtJQUN2QixJQUFJLGdCQUFnQixJQUFJLE9BQU8sSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3BELE9BQU8sZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVELDRCQUE0QjtJQUM1QixPQUFPLENBQUMscUJBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDdkQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgdHlwZSB7IFF1b3RhVGllciB9IGZyb20gJy4vcXVvdGEtdGllcnMnO1xuXG4vLyBGZWF0dXJlIGZsYWcgaWRlbnRpZmllcnNcblxuLyoqIENhbm9uaWNhbCBmZWF0dXJlIGZsYWcgaWRlbnRpZmllcnMuICovXG5leHBvcnQgdHlwZSBGZWF0dXJlRmxhZyA9XG4gIHwgJ3ByaW9yaXR5X3N1cHBvcnQnXG4gIHwgJ2N1c3RvbV9pbnRlZ3JhdGlvbnMnXG4gIHwgJ2FpX2dlbmVyYXRpb24nXG4gIHwgJ2J1bGtfb3BlcmF0aW9ucydcbiAgfCAnYXVkaXRfbG9nJztcblxuLyoqIEFsbCB2YWxpZCBmZWF0dXJlIGZsYWdzIChvcmRlciBkZXRlcm1pbmVzIGRpc3BsYXkgb3JkZXIpLiAqL1xuZXhwb3J0IGNvbnN0IEFMTF9GRUFUVVJFX0ZMQUdTOiByZWFkb25seSBGZWF0dXJlRmxhZ1tdID0gW1xuICAncHJpb3JpdHlfc3VwcG9ydCcsXG4gICdhaV9nZW5lcmF0aW9uJyxcbiAgJ2J1bGtfb3BlcmF0aW9ucycsXG4gICdjdXN0b21faW50ZWdyYXRpb25zJyxcbiAgJ2F1ZGl0X2xvZycsXG5dO1xuXG4vKiogQ2hlY2sgd2hldGhlciBhIHN0cmluZyBpcyBhIHZhbGlkIEZlYXR1cmVGbGFnLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRGZWF0dXJlRmxhZyh2YWx1ZTogc3RyaW5nKTogdmFsdWUgaXMgRmVhdHVyZUZsYWcge1xuICByZXR1cm4gKEFMTF9GRUFUVVJFX0ZMQUdTIGFzIHJlYWRvbmx5IHN0cmluZ1tdKS5pbmNsdWRlcyh2YWx1ZSk7XG59XG5cbi8vIFRpZXItdG8tZmVhdHVyZSBtYXBwaW5nXG5cbi8qKiBGZWF0dXJlcyBlbmFibGVkIGJ5IGRlZmF1bHQgZm9yIGVhY2ggdGllci4gKi9cbmV4cG9ydCBjb25zdCBUSUVSX0ZFQVRVUkVTOiBSZWNvcmQ8UXVvdGFUaWVyLCByZWFkb25seSBGZWF0dXJlRmxhZ1tdPiA9IHtcbiAgZGV2ZWxvcGVyOiBbXSxcbiAgcHJvOiBbJ3ByaW9yaXR5X3N1cHBvcnQnLCAnYWlfZ2VuZXJhdGlvbicsICdidWxrX29wZXJhdGlvbnMnXSxcbiAgdW5saW1pdGVkOiBbLi4uQUxMX0ZFQVRVUkVfRkxBR1NdLFxufTtcblxuLy8gRmVhdHVyZSBtZXRhZGF0YSAoZm9yIGRpc3BsYXkpXG5cbi8qKiBIdW1hbi1yZWFkYWJsZSBtZXRhZGF0YSBmb3IgZWFjaCBmZWF0dXJlIGZsYWcuICovXG5leHBvcnQgY29uc3QgRkVBVFVSRV9NRVRBREFUQTogUmVjb3JkPEZlYXR1cmVGbGFnLCB7IGxhYmVsOiBzdHJpbmc7IGRlc2NyaXB0aW9uOiBzdHJpbmcgfT4gPSB7XG4gIHByaW9yaXR5X3N1cHBvcnQ6IHtcbiAgICBsYWJlbDogJ1ByaW9yaXR5IFN1cHBvcnQnLFxuICAgIGRlc2NyaXB0aW9uOiAnRmFzdGVyIHJlc3BvbnNlIHRpbWVzIGFuZCBkZWRpY2F0ZWQgc3VwcG9ydCBjaGFubmVscycsXG4gIH0sXG4gIGFpX2dlbmVyYXRpb246IHtcbiAgICBsYWJlbDogJ0FJIEdlbmVyYXRpb24nLFxuICAgIGRlc2NyaXB0aW9uOiAnQUktcG93ZXJlZCBwaXBlbGluZSBhbmQgcGx1Z2luIGdlbmVyYXRpb24nLFxuICB9LFxuICBidWxrX29wZXJhdGlvbnM6IHtcbiAgICBsYWJlbDogJ0J1bGsgT3BlcmF0aW9ucycsXG4gICAgZGVzY3JpcHRpb246ICdCYXRjaCBjcmVhdGUsIHVwZGF0ZSwgYW5kIGRlbGV0ZSBmb3IgcGlwZWxpbmVzIGFuZCBwbHVnaW5zJyxcbiAgfSxcbiAgY3VzdG9tX2ludGVncmF0aW9uczoge1xuICAgIGxhYmVsOiAnQ3VzdG9tIEludGVncmF0aW9ucycsXG4gICAgZGVzY3JpcHRpb246ICdDb25uZWN0IHRvIGV4dGVybmFsIHNlcnZpY2VzIGFuZCBjdXN0b20gd2ViaG9vayBlbmRwb2ludHMnLFxuICB9LFxuICBhdWRpdF9sb2c6IHtcbiAgICBsYWJlbDogJ0F1ZGl0IExvZycsXG4gICAgZGVzY3JpcHRpb246ICdEZXRhaWxlZCBhdWRpdCB0cmFpbCBvZiBhbGwgdXNlciBhbmQgc3lzdGVtIGFjdGlvbnMnLFxuICB9LFxufTtcblxuLy8gUmVzb2x1dGlvbiBsb2dpY1xuXG4vKipcbiAqIFJlc29sdmUgYSB1c2VyJ3MgZWZmZWN0aXZlIGZlYXR1cmUgc2V0LlxuICpcbiAqIDEuIFN5c3RlbSBvcmcgdXNlcnMgYWx3YXlzIGdldCBBTEwgZmVhdHVyZXMuXG4gKiAyLiBTdGFydCB3aXRoIHRoZSB0aWVyJ3MgZGVmYXVsdCBmZWF0dXJlcy5cbiAqIDMuIEFwcGx5IHBlci11c2VyIG92ZXJyaWRlczogYHRydWVgIGFkZHMgYSBmZWF0dXJlLCBgZmFsc2VgIHJlbW92ZXMgaXQuXG4gKiA0LiBJbnZhbGlkIG92ZXJyaWRlIGtleXMgYXJlIHNpbGVudGx5IGlnbm9yZWQuXG4gKlxuICogQHBhcmFtIHRpZXIgLSBUaGUgb3JnYW5pemF0aW9uJ3MgcXVvdGEgdGllclxuICogQHBhcmFtIGZlYXR1cmVPdmVycmlkZXMgLSBQZXItdXNlciBvdmVycmlkZXMgKGtleSA9IGZlYXR1cmUgZmxhZywgdmFsdWUgPSBlbmFibGVkKVxuICogQHBhcmFtIGlzU3lzdGVtT3JnIC0gV2hldGhlciB0aGUgdXNlciBiZWxvbmdzIHRvIHRoZSBzeXN0ZW0gb3JnYW5pemF0aW9uXG4gKiBAcmV0dXJucyBTb3J0ZWQgYXJyYXkgb2YgZW5hYmxlZCBmZWF0dXJlIGZsYWdzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlVXNlckZlYXR1cmVzKFxuICB0aWVyOiBRdW90YVRpZXIsXG4gIGZlYXR1cmVPdmVycmlkZXM/OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuPiB8IG51bGwsXG4gIGlzU3lzdGVtT3JnPzogYm9vbGVhbixcbik6IEZlYXR1cmVGbGFnW10ge1xuICAvLyBTeXN0ZW0gb3JnIGFsd2F5cyBnZXRzIGV2ZXJ5dGhpbmdcbiAgaWYgKGlzU3lzdGVtT3JnKSByZXR1cm4gWy4uLkFMTF9GRUFUVVJFX0ZMQUdTXTtcblxuICAvLyBTdGFydCB3aXRoIHRpZXIgZGVmYXVsdHNcbiAgY29uc3QgZmVhdHVyZXMgPSBuZXcgU2V0PEZlYXR1cmVGbGFnPihUSUVSX0ZFQVRVUkVTW3RpZXJdID8/IFtdKTtcblxuICAvLyBBcHBseSBwZXItdXNlciBvdmVycmlkZXNcbiAgaWYgKGZlYXR1cmVPdmVycmlkZXMpIHtcbiAgICBmb3IgKGNvbnN0IFtrZXksIGVuYWJsZWRdIG9mIE9iamVjdC5lbnRyaWVzKGZlYXR1cmVPdmVycmlkZXMpKSB7XG4gICAgICBpZiAoIWlzVmFsaWRGZWF0dXJlRmxhZyhrZXkpKSBjb250aW51ZTtcbiAgICAgIGlmIChlbmFibGVkKSB7XG4gICAgICAgIGZlYXR1cmVzLmFkZChrZXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZmVhdHVyZXMuZGVsZXRlKGtleSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy8gUmV0dXJuIGluIGNhbm9uaWNhbCBvcmRlclxuICByZXR1cm4gQUxMX0ZFQVRVUkVfRkxBR1MuZmlsdGVyKGYgPT4gZmVhdHVyZXMuaGFzKGYpKTtcbn1cblxuLyoqXG4gKiBDaGVjayBpZiBhIHNwZWNpZmljIGZlYXR1cmUgaXMgZW5hYmxlZCBmb3IgYSB1c2VyLlxuICpcbiAqIEBwYXJhbSB0aWVyIC0gVGhlIG9yZ2FuaXphdGlvbidzIHF1b3RhIHRpZXJcbiAqIEBwYXJhbSBmZWF0dXJlIC0gVGhlIGZlYXR1cmUgZmxhZyB0byBjaGVja1xuICogQHBhcmFtIGZlYXR1cmVPdmVycmlkZXMgLSBQZXItdXNlciBvdmVycmlkZXNcbiAqIEBwYXJhbSBpc1N5c3RlbU9yZyAtIFdoZXRoZXIgdGhlIHVzZXIgYmVsb25ncyB0byB0aGUgc3lzdGVtIG9yZ2FuaXphdGlvblxuICogQHJldHVybnMgdHJ1ZSBpZiB0aGUgZmVhdHVyZSBpcyBlbmFibGVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNGZWF0dXJlKFxuICB0aWVyOiBRdW90YVRpZXIsXG4gIGZlYXR1cmU6IEZlYXR1cmVGbGFnLFxuICBmZWF0dXJlT3ZlcnJpZGVzPzogUmVjb3JkPHN0cmluZywgYm9vbGVhbj4gfCBudWxsLFxuICBpc1N5c3RlbU9yZz86IGJvb2xlYW4sXG4pOiBib29sZWFuIHtcbiAgaWYgKGlzU3lzdGVtT3JnKSByZXR1cm4gdHJ1ZTtcblxuICAvLyBDaGVjayBvdmVycmlkZSBmaXJzdFxuICBpZiAoZmVhdHVyZU92ZXJyaWRlcyAmJiBmZWF0dXJlIGluIGZlYXR1cmVPdmVycmlkZXMpIHtcbiAgICByZXR1cm4gZmVhdHVyZU92ZXJyaWRlc1tmZWF0dXJlXTtcbiAgfVxuXG4gIC8vIEZhbGwgYmFjayB0byB0aWVyIGRlZmF1bHRcbiAgcmV0dXJuIChUSUVSX0ZFQVRVUkVTW3RpZXJdID8/IFtdKS5pbmNsdWRlcyhmZWF0dXJlKTtcbn1cbiJdfQ==
107
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmVhdHVyZS1mbGFncy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eXBlcy9mZWF0dXJlLWZsYWdzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDOzs7QUF3QnRDLGdEQUVDO0FBb0RELGtEQXlCQztBQVdELGdDQWVDO0FBbkhELGdFQUFnRTtBQUNuRCxRQUFBLGlCQUFpQixHQUEyQjtJQUN2RCxrQkFBa0I7SUFDbEIsZUFBZTtJQUNmLGlCQUFpQjtJQUNqQixxQkFBcUI7SUFDckIsV0FBVztDQUNaLENBQUM7QUFFRixxREFBcUQ7QUFDckQsU0FBZ0Isa0JBQWtCLENBQUMsS0FBYTtJQUM5QyxPQUFRLHlCQUF1QyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUNsRSxDQUFDO0FBRUQsMEJBQTBCO0FBRTFCLGlEQUFpRDtBQUNwQyxRQUFBLGFBQWEsR0FBOEM7SUFDdEUsU0FBUyxFQUFFLEVBQUU7SUFDYixHQUFHLEVBQUUsQ0FBQyxrQkFBa0IsRUFBRSxlQUFlLEVBQUUsaUJBQWlCLENBQUM7SUFDN0QsU0FBUyxFQUFFLENBQUMsR0FBRyx5QkFBaUIsQ0FBQztDQUNsQyxDQUFDO0FBRUYsaUNBQWlDO0FBRWpDLHFEQUFxRDtBQUN4QyxRQUFBLGdCQUFnQixHQUFnRTtJQUMzRixnQkFBZ0IsRUFBRTtRQUNoQixLQUFLLEVBQUUsa0JBQWtCO1FBQ3pCLFdBQVcsRUFBRSxzREFBc0Q7S0FDcEU7SUFDRCxhQUFhLEVBQUU7UUFDYixLQUFLLEVBQUUsZUFBZTtRQUN0QixXQUFXLEVBQUUsMkNBQTJDO0tBQ3pEO0lBQ0QsZUFBZSxFQUFFO1FBQ2YsS0FBSyxFQUFFLGlCQUFpQjtRQUN4QixXQUFXLEVBQUUsNERBQTREO0tBQzFFO0lBQ0QsbUJBQW1CLEVBQUU7UUFDbkIsS0FBSyxFQUFFLHFCQUFxQjtRQUM1QixXQUFXLEVBQUUsMkRBQTJEO0tBQ3pFO0lBQ0QsU0FBUyxFQUFFO1FBQ1QsS0FBSyxFQUFFLFdBQVc7UUFDbEIsV0FBVyxFQUFFLHFEQUFxRDtLQUNuRTtDQUNGLENBQUM7QUFFRixtQkFBbUI7QUFFbkI7Ozs7Ozs7Ozs7OztHQVlHO0FBQ0gsU0FBZ0IsbUJBQW1CLENBQ2pDLElBQWUsRUFDZixnQkFBaUQsRUFDakQsWUFBc0I7SUFFdEIsK0NBQStDO0lBQy9DLElBQUksWUFBWTtRQUFFLE9BQU8sQ0FBQyxHQUFHLHlCQUFpQixDQUFDLENBQUM7SUFFaEQsMkJBQTJCO0lBQzNCLE1BQU0sUUFBUSxHQUFHLElBQUksR0FBRyxDQUFjLHFCQUFhLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFFakUsMkJBQTJCO0lBQzNCLElBQUksZ0JBQWdCLEVBQUUsQ0FBQztRQUNyQixLQUFLLE1BQU0sQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxnQkFBZ0IsQ0FBQyxFQUFFLENBQUM7WUFDOUQsSUFBSSxDQUFDLGtCQUFrQixDQUFDLEdBQUcsQ0FBQztnQkFBRSxTQUFTO1lBQ3ZDLElBQUksT0FBTyxFQUFFLENBQUM7Z0JBQ1osUUFBUSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNwQixDQUFDO2lCQUFNLENBQUM7Z0JBQ04sUUFBUSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUN2QixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFFRCw0QkFBNEI7SUFDNUIsT0FBTyx5QkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDeEQsQ0FBQztBQUVEOzs7Ozs7OztHQVFHO0FBQ0gsU0FBZ0IsVUFBVSxDQUN4QixJQUFlLEVBQ2YsT0FBb0IsRUFDcEIsZ0JBQWlELEVBQ2pELFlBQXNCO0lBRXRCLElBQUksWUFBWTtRQUFFLE9BQU8sSUFBSSxDQUFDO0lBRTlCLHVCQUF1QjtJQUN2QixJQUFJLGdCQUFnQixJQUFJLE9BQU8sSUFBSSxnQkFBZ0IsRUFBRSxDQUFDO1FBQ3BELE9BQU8sZ0JBQWdCLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbkMsQ0FBQztJQUVELDRCQUE0QjtJQUM1QixPQUFPLENBQUMscUJBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDdkQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgdHlwZSB7IFF1b3RhVGllciB9IGZyb20gJy4vcXVvdGEtdGllcnMnO1xuXG4vLyBGZWF0dXJlIGZsYWcgaWRlbnRpZmllcnNcblxuLyoqIENhbm9uaWNhbCBmZWF0dXJlIGZsYWcgaWRlbnRpZmllcnMuICovXG5leHBvcnQgdHlwZSBGZWF0dXJlRmxhZyA9XG4gIHwgJ3ByaW9yaXR5X3N1cHBvcnQnXG4gIHwgJ2N1c3RvbV9pbnRlZ3JhdGlvbnMnXG4gIHwgJ2FpX2dlbmVyYXRpb24nXG4gIHwgJ2J1bGtfb3BlcmF0aW9ucydcbiAgfCAnYXVkaXRfbG9nJztcblxuLyoqIEFsbCB2YWxpZCBmZWF0dXJlIGZsYWdzIChvcmRlciBkZXRlcm1pbmVzIGRpc3BsYXkgb3JkZXIpLiAqL1xuZXhwb3J0IGNvbnN0IEFMTF9GRUFUVVJFX0ZMQUdTOiByZWFkb25seSBGZWF0dXJlRmxhZ1tdID0gW1xuICAncHJpb3JpdHlfc3VwcG9ydCcsXG4gICdhaV9nZW5lcmF0aW9uJyxcbiAgJ2J1bGtfb3BlcmF0aW9ucycsXG4gICdjdXN0b21faW50ZWdyYXRpb25zJyxcbiAgJ2F1ZGl0X2xvZycsXG5dO1xuXG4vKiogQ2hlY2sgd2hldGhlciBhIHN0cmluZyBpcyBhIHZhbGlkIEZlYXR1cmVGbGFnLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRGZWF0dXJlRmxhZyh2YWx1ZTogc3RyaW5nKTogdmFsdWUgaXMgRmVhdHVyZUZsYWcge1xuICByZXR1cm4gKEFMTF9GRUFUVVJFX0ZMQUdTIGFzIHJlYWRvbmx5IHN0cmluZ1tdKS5pbmNsdWRlcyh2YWx1ZSk7XG59XG5cbi8vIFRpZXItdG8tZmVhdHVyZSBtYXBwaW5nXG5cbi8qKiBGZWF0dXJlcyBlbmFibGVkIGJ5IGRlZmF1bHQgZm9yIGVhY2ggdGllci4gKi9cbmV4cG9ydCBjb25zdCBUSUVSX0ZFQVRVUkVTOiBSZWNvcmQ8UXVvdGFUaWVyLCByZWFkb25seSBGZWF0dXJlRmxhZ1tdPiA9IHtcbiAgZGV2ZWxvcGVyOiBbXSxcbiAgcHJvOiBbJ3ByaW9yaXR5X3N1cHBvcnQnLCAnYWlfZ2VuZXJhdGlvbicsICdidWxrX29wZXJhdGlvbnMnXSxcbiAgdW5saW1pdGVkOiBbLi4uQUxMX0ZFQVRVUkVfRkxBR1NdLFxufTtcblxuLy8gRmVhdHVyZSBtZXRhZGF0YSAoZm9yIGRpc3BsYXkpXG5cbi8qKiBIdW1hbi1yZWFkYWJsZSBtZXRhZGF0YSBmb3IgZWFjaCBmZWF0dXJlIGZsYWcuICovXG5leHBvcnQgY29uc3QgRkVBVFVSRV9NRVRBREFUQTogUmVjb3JkPEZlYXR1cmVGbGFnLCB7IGxhYmVsOiBzdHJpbmc7IGRlc2NyaXB0aW9uOiBzdHJpbmcgfT4gPSB7XG4gIHByaW9yaXR5X3N1cHBvcnQ6IHtcbiAgICBsYWJlbDogJ1ByaW9yaXR5IFN1cHBvcnQnLFxuICAgIGRlc2NyaXB0aW9uOiAnRmFzdGVyIHJlc3BvbnNlIHRpbWVzIGFuZCBkZWRpY2F0ZWQgc3VwcG9ydCBjaGFubmVscycsXG4gIH0sXG4gIGFpX2dlbmVyYXRpb246IHtcbiAgICBsYWJlbDogJ0FJIEdlbmVyYXRpb24nLFxuICAgIGRlc2NyaXB0aW9uOiAnQUktcG93ZXJlZCBwaXBlbGluZSBhbmQgcGx1Z2luIGdlbmVyYXRpb24nLFxuICB9LFxuICBidWxrX29wZXJhdGlvbnM6IHtcbiAgICBsYWJlbDogJ0J1bGsgT3BlcmF0aW9ucycsXG4gICAgZGVzY3JpcHRpb246ICdCYXRjaCBjcmVhdGUsIHVwZGF0ZSwgYW5kIGRlbGV0ZSBmb3IgcGlwZWxpbmVzIGFuZCBwbHVnaW5zJyxcbiAgfSxcbiAgY3VzdG9tX2ludGVncmF0aW9uczoge1xuICAgIGxhYmVsOiAnQ3VzdG9tIEludGVncmF0aW9ucycsXG4gICAgZGVzY3JpcHRpb246ICdDb25uZWN0IHRvIGV4dGVybmFsIHNlcnZpY2VzIGFuZCBjdXN0b20gd2ViaG9vayBlbmRwb2ludHMnLFxuICB9LFxuICBhdWRpdF9sb2c6IHtcbiAgICBsYWJlbDogJ0F1ZGl0IExvZycsXG4gICAgZGVzY3JpcHRpb246ICdEZXRhaWxlZCBhdWRpdCB0cmFpbCBvZiBhbGwgdXNlciBhbmQgc3lzdGVtIGFjdGlvbnMnLFxuICB9LFxufTtcblxuLy8gUmVzb2x1dGlvbiBsb2dpY1xuXG4vKipcbiAqIFJlc29sdmUgYSB1c2VyJ3MgZWZmZWN0aXZlIGZlYXR1cmUgc2V0LlxuICpcbiAqIDEuIFN5c2FkbWlucyAoaXNTdXBlckFkbWluKSBhbHdheXMgZ2V0IEFMTCBmZWF0dXJlcy5cbiAqIDIuIFN0YXJ0IHdpdGggdGhlIHRpZXIncyBkZWZhdWx0IGZlYXR1cmVzLlxuICogMy4gQXBwbHkgcGVyLXVzZXIgb3ZlcnJpZGVzOiBgdHJ1ZWAgYWRkcyBhIGZlYXR1cmUsIGBmYWxzZWAgcmVtb3ZlcyBpdC5cbiAqIDQuIEludmFsaWQgb3ZlcnJpZGUga2V5cyBhcmUgc2lsZW50bHkgaWdub3JlZC5cbiAqXG4gKiBAcGFyYW0gdGllciAtIFRoZSBvcmdhbml6YXRpb24ncyBxdW90YSB0aWVyXG4gKiBAcGFyYW0gZmVhdHVyZU92ZXJyaWRlcyAtIFBlci11c2VyIG92ZXJyaWRlcyAoa2V5ID0gZmVhdHVyZSBmbGFnLCB2YWx1ZSA9IGVuYWJsZWQpXG4gKiBAcGFyYW0gaXNTdXBlckFkbWluIC0gV2hldGhlciB0aGUgdXNlciBoYXMgdGhlIGdsb2JhbCBzdXBlci1hZG1pbiBmbGFnXG4gKiBAcmV0dXJucyBTb3J0ZWQgYXJyYXkgb2YgZW5hYmxlZCBmZWF0dXJlIGZsYWdzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlVXNlckZlYXR1cmVzKFxuICB0aWVyOiBRdW90YVRpZXIsXG4gIGZlYXR1cmVPdmVycmlkZXM/OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuPiB8IG51bGwsXG4gIGlzU3VwZXJBZG1pbj86IGJvb2xlYW4sXG4pOiBGZWF0dXJlRmxhZ1tdIHtcbiAgLy8gU3lzYWRtaW5zIGdldCBldmVyeXRoaW5nIHJlZ2FyZGxlc3Mgb2YgdGllci5cbiAgaWYgKGlzU3VwZXJBZG1pbikgcmV0dXJuIFsuLi5BTExfRkVBVFVSRV9GTEFHU107XG5cbiAgLy8gU3RhcnQgd2l0aCB0aWVyIGRlZmF1bHRzXG4gIGNvbnN0IGZlYXR1cmVzID0gbmV3IFNldDxGZWF0dXJlRmxhZz4oVElFUl9GRUFUVVJFU1t0aWVyXSA/PyBbXSk7XG5cbiAgLy8gQXBwbHkgcGVyLXVzZXIgb3ZlcnJpZGVzXG4gIGlmIChmZWF0dXJlT3ZlcnJpZGVzKSB7XG4gICAgZm9yIChjb25zdCBba2V5LCBlbmFibGVkXSBvZiBPYmplY3QuZW50cmllcyhmZWF0dXJlT3ZlcnJpZGVzKSkge1xuICAgICAgaWYgKCFpc1ZhbGlkRmVhdHVyZUZsYWcoa2V5KSkgY29udGludWU7XG4gICAgICBpZiAoZW5hYmxlZCkge1xuICAgICAgICBmZWF0dXJlcy5hZGQoa2V5KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZlYXR1cmVzLmRlbGV0ZShrZXkpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIFJldHVybiBpbiBjYW5vbmljYWwgb3JkZXJcbiAgcmV0dXJuIEFMTF9GRUFUVVJFX0ZMQUdTLmZpbHRlcihmID0+IGZlYXR1cmVzLmhhcyhmKSk7XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgYSBzcGVjaWZpYyBmZWF0dXJlIGlzIGVuYWJsZWQgZm9yIGEgdXNlci5cbiAqXG4gKiBAcGFyYW0gdGllciAtIFRoZSBvcmdhbml6YXRpb24ncyBxdW90YSB0aWVyXG4gKiBAcGFyYW0gZmVhdHVyZSAtIFRoZSBmZWF0dXJlIGZsYWcgdG8gY2hlY2tcbiAqIEBwYXJhbSBmZWF0dXJlT3ZlcnJpZGVzIC0gUGVyLXVzZXIgb3ZlcnJpZGVzXG4gKiBAcGFyYW0gaXNTdXBlckFkbWluIC0gV2hldGhlciB0aGUgdXNlciBoYXMgdGhlIGdsb2JhbCBzdXBlci1hZG1pbiBmbGFnXG4gKiBAcmV0dXJucyB0cnVlIGlmIHRoZSBmZWF0dXJlIGlzIGVuYWJsZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc0ZlYXR1cmUoXG4gIHRpZXI6IFF1b3RhVGllcixcbiAgZmVhdHVyZTogRmVhdHVyZUZsYWcsXG4gIGZlYXR1cmVPdmVycmlkZXM/OiBSZWNvcmQ8c3RyaW5nLCBib29sZWFuPiB8IG51bGwsXG4gIGlzU3VwZXJBZG1pbj86IGJvb2xlYW4sXG4pOiBib29sZWFuIHtcbiAgaWYgKGlzU3VwZXJBZG1pbikgcmV0dXJuIHRydWU7XG5cbiAgLy8gQ2hlY2sgb3ZlcnJpZGUgZmlyc3RcbiAgaWYgKGZlYXR1cmVPdmVycmlkZXMgJiYgZmVhdHVyZSBpbiBmZWF0dXJlT3ZlcnJpZGVzKSB7XG4gICAgcmV0dXJuIGZlYXR1cmVPdmVycmlkZXNbZmVhdHVyZV07XG4gIH1cblxuICAvLyBGYWxsIGJhY2sgdG8gdGllciBkZWZhdWx0XG4gIHJldHVybiAoVElFUl9GRUFUVVJFU1t0aWVyXSA/PyBbXSkuaW5jbHVkZXMoZmVhdHVyZSk7XG59XG4iXX0=
@@ -15,23 +15,13 @@ export interface HttpRequest {
15
15
  params: Record<string, string | string[] | undefined>;
16
16
  /** Query parameters */
17
17
  query: Record<string, unknown>;
18
- /** Authenticated user (if present) */
18
+ /** Authenticated user (if present). `sub` is the OIDC-standard subject
19
+ * (= user id); higher-level layers may attach additional fields, hence
20
+ * the index signature. */
19
21
  user?: {
22
+ sub?: string;
20
23
  organizationId?: string;
21
- userId?: string;
22
24
  role?: string;
23
25
  [key: string]: unknown;
24
26
  };
25
27
  }
26
- /**
27
- * Generic HTTP response interface.
28
- * Represents the minimal response shape needed by api-core utilities.
29
- */
30
- export interface HttpResponse {
31
- /** Set HTTP status code */
32
- status(code: number): HttpResponse;
33
- /** Send JSON response */
34
- json(body: unknown): void;
35
- /** Set response header */
36
- setHeader(name: string, value: string | number): void;
37
- }
package/lib/types/http.js CHANGED
@@ -2,4 +2,4 @@
2
2
  // Copyright 2026 Pipeline Builder Contributors
3
3
  // SPDX-License-Identifier: Apache-2.0
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eXBlcy9odHRwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogR2VuZXJpYyBIVFRQIGhlYWRlcnMgcmVwcmVzZW50YXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSHR0cEhlYWRlcnMge1xuICBba2V5OiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXSB8IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBHZW5lcmljIEhUVFAgcmVxdWVzdCBpbnRlcmZhY2UuXG4gKiBSZXByZXNlbnRzIHRoZSBtaW5pbWFsIHJlcXVlc3Qgc2hhcGUgbmVlZGVkIGJ5IGFwaS1jb3JlIHV0aWxpdGllcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBIdHRwUmVxdWVzdCB7XG4gIC8qKiBSZXF1ZXN0IGhlYWRlcnMgKi9cbiAgaGVhZGVyczogSHR0cEhlYWRlcnM7XG4gIC8qKiBSb3V0ZSBwYXJhbWV0ZXJzICovXG4gIHBhcmFtczogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgc3RyaW5nW10gfCB1bmRlZmluZWQ+O1xuICAvKiogUXVlcnkgcGFyYW1ldGVycyAqL1xuICBxdWVyeTogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIC8qKiBBdXRoZW50aWNhdGVkIHVzZXIgKGlmIHByZXNlbnQpICovXG4gIHVzZXI/OiB7XG4gICAgb3JnYW5pemF0aW9uSWQ/OiBzdHJpbmc7XG4gICAgdXNlcklkPzogc3RyaW5nO1xuICAgIHJvbGU/OiBzdHJpbmc7XG4gICAgW2tleTogc3RyaW5nXTogdW5rbm93bjtcbiAgfTtcbn1cblxuLyoqXG4gKiBHZW5lcmljIEhUVFAgcmVzcG9uc2UgaW50ZXJmYWNlLlxuICogUmVwcmVzZW50cyB0aGUgbWluaW1hbCByZXNwb25zZSBzaGFwZSBuZWVkZWQgYnkgYXBpLWNvcmUgdXRpbGl0aWVzLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEh0dHBSZXNwb25zZSB7XG4gIC8qKiBTZXQgSFRUUCBzdGF0dXMgY29kZSAqL1xuICBzdGF0dXMoY29kZTogbnVtYmVyKTogSHR0cFJlc3BvbnNlO1xuICAvKiogU2VuZCBKU09OIHJlc3BvbnNlICovXG4gIGpzb24oYm9keTogdW5rbm93bik6IHZvaWQ7XG4gIC8qKiBTZXQgcmVzcG9uc2UgaGVhZGVyICovXG4gIHNldEhlYWRlcihuYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcgfCBudW1iZXIpOiB2b2lkO1xufVxuIl19
5
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eXBlcy9odHRwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gQ29weXJpZ2h0IDIwMjYgUGlwZWxpbmUgQnVpbGRlciBDb250cmlidXRvcnNcbi8vIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBBcGFjaGUtMi4wXG5cbi8qKlxuICogR2VuZXJpYyBIVFRQIGhlYWRlcnMgcmVwcmVzZW50YXRpb24uXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgSHR0cEhlYWRlcnMge1xuICBba2V5OiBzdHJpbmddOiBzdHJpbmcgfCBzdHJpbmdbXSB8IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBHZW5lcmljIEhUVFAgcmVxdWVzdCBpbnRlcmZhY2UuXG4gKiBSZXByZXNlbnRzIHRoZSBtaW5pbWFsIHJlcXVlc3Qgc2hhcGUgbmVlZGVkIGJ5IGFwaS1jb3JlIHV0aWxpdGllcy5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBIdHRwUmVxdWVzdCB7XG4gIC8qKiBSZXF1ZXN0IGhlYWRlcnMgKi9cbiAgaGVhZGVyczogSHR0cEhlYWRlcnM7XG4gIC8qKiBSb3V0ZSBwYXJhbWV0ZXJzICovXG4gIHBhcmFtczogUmVjb3JkPHN0cmluZywgc3RyaW5nIHwgc3RyaW5nW10gfCB1bmRlZmluZWQ+O1xuICAvKiogUXVlcnkgcGFyYW1ldGVycyAqL1xuICBxdWVyeTogUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG4gIC8qKiBBdXRoZW50aWNhdGVkIHVzZXIgKGlmIHByZXNlbnQpLiBgc3ViYCBpcyB0aGUgT0lEQy1zdGFuZGFyZCBzdWJqZWN0XG4gICAqICAoPSB1c2VyIGlkKTsgaGlnaGVyLWxldmVsIGxheWVycyBtYXkgYXR0YWNoIGFkZGl0aW9uYWwgZmllbGRzLCBoZW5jZVxuICAgKiAgdGhlIGluZGV4IHNpZ25hdHVyZS4gKi9cbiAgdXNlcj86IHtcbiAgICBzdWI/OiBzdHJpbmc7XG4gICAgb3JnYW5pemF0aW9uSWQ/OiBzdHJpbmc7XG4gICAgcm9sZT86IHN0cmluZztcbiAgICBba2V5OiBzdHJpbmddOiB1bmtub3duO1xuICB9O1xufVxuXG4iXX0=
@@ -6,19 +6,25 @@ export interface QuotaTierLimits {
6
6
  pipelines: number;
7
7
  apiCalls: number;
8
8
  aiCalls: number;
9
+ /**
10
+ * Aggregate registry storage cap in BYTES. Counted across every repo
11
+ * under the org's `org-{orgId}/` namespace. -1 means unlimited.
12
+ * push-gate reads this; the image-registry rejects token issuance for
13
+ * `push` scope when the org's measured usage exceeds the limit.
14
+ */
15
+ storageBytes: number;
16
+ /** Count-quotas on the user-editable feature tables added to close per-org
17
+ * DoS via spam. -1 means unlimited. */
18
+ dashboards: number;
19
+ alertRules: number;
20
+ alertDestinations: number;
21
+ idpConfigs: number;
9
22
  }
10
23
  /** Full preset for a single tier (label + limits). */
11
24
  export interface QuotaTierPreset {
12
25
  label: string;
13
26
  limits: QuotaTierLimits;
14
27
  }
15
- /**
16
- * Preset limits for each tier. -1 means unlimited.
17
- *
18
- * AI calls are sized much smaller than `apiCalls` because each call has
19
- * external provider cost (~$0.01–$0.10/call). Developer tier allows light
20
- * exploration (100/period); Pro lifts to 5000; Unlimited is uncapped.
21
- */
22
28
  export declare const QUOTA_TIERS: Record<QuotaTier, QuotaTierPreset>;
23
29
  /** All valid tier names. */
24
30
  export declare const VALID_TIERS: readonly QuotaTier[];
@@ -9,13 +9,62 @@ exports.getTierLimits = getTierLimits;
9
9
  * Preset limits for each tier. -1 means unlimited.
10
10
  *
11
11
  * AI calls are sized much smaller than `apiCalls` because each call has
12
- * external provider cost (~$0.01–$0.10/call). Developer tier allows light
12
+ * external provider cost (~$0.01$0.10/call). Developer tier allows light
13
13
  * exploration (100/period); Pro lifts to 5000; Unlimited is uncapped.
14
+ *
15
+ * `storageBytes` is the aggregate registry cap per org. Sized
16
+ * around plugin-image realities: a typical plugin image is 200500 MB;
17
+ * Developer's 5 GB holds ~10 versions × ~500 MB, Pro's 100 GB covers a
18
+ * mature catalog. Operators can override per-org via the quota CRUD API.
14
19
  */
20
+ const GB = 1024 * 1024 * 1024;
15
21
  exports.QUOTA_TIERS = {
16
- developer: { label: 'Developer', limits: { plugins: 100, pipelines: 10, apiCalls: -1, aiCalls: 100 } },
17
- pro: { label: 'Pro', limits: { plugins: 1000, pipelines: 100, apiCalls: -1, aiCalls: 5000 } },
18
- unlimited: { label: 'Unlimited', limits: { plugins: -1, pipelines: -1, apiCalls: -1, aiCalls: -1 } },
22
+ developer: {
23
+ label: 'Developer',
24
+ limits: {
25
+ plugins: 100,
26
+ pipelines: 10,
27
+ apiCalls: -1,
28
+ aiCalls: 100,
29
+ storageBytes: 5 * GB,
30
+ // Counts sized to "comfortably enough for one team, not a script spam":
31
+ // 20 dashboards covers ops + per-service drill-downs, 50 alert rules
32
+ // covers per-service alerts, 10 destinations covers Slack channels
33
+ // per team + a webhook fallback, 1 IdP config (you only have one).
34
+ dashboards: 20,
35
+ alertRules: 50,
36
+ alertDestinations: 10,
37
+ idpConfigs: 1,
38
+ },
39
+ },
40
+ pro: {
41
+ label: 'Pro',
42
+ limits: {
43
+ plugins: 1000,
44
+ pipelines: 100,
45
+ apiCalls: -1,
46
+ aiCalls: 5000,
47
+ storageBytes: 100 * GB,
48
+ dashboards: 200,
49
+ alertRules: 500,
50
+ alertDestinations: 50,
51
+ idpConfigs: 5,
52
+ },
53
+ },
54
+ unlimited: {
55
+ label: 'Unlimited',
56
+ limits: {
57
+ plugins: -1,
58
+ pipelines: -1,
59
+ apiCalls: -1,
60
+ aiCalls: -1,
61
+ storageBytes: -1,
62
+ dashboards: -1,
63
+ alertRules: -1,
64
+ alertDestinations: -1,
65
+ idpConfigs: -1,
66
+ },
67
+ },
19
68
  };
20
69
  /** All valid tier names. */
21
70
  exports.VALID_TIERS = Object.keys(exports.QUOTA_TIERS);
@@ -29,4 +78,4 @@ function isValidTier(value) {
29
78
  function getTierLimits(tier) {
30
79
  return isValidTier(tier) ? exports.QUOTA_TIERS[tier].limits : exports.QUOTA_TIERS.developer.limits;
31
80
  }
32
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVvdGEtdGllcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHlwZXMvcXVvdGEtdGllcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7OztBQXVDdEMsa0NBRUM7QUFHRCxzQ0FFQztBQTNCRDs7Ozs7O0dBTUc7QUFDVSxRQUFBLFdBQVcsR0FBdUM7SUFDN0QsU0FBUyxFQUFFLEVBQUUsS0FBSyxFQUFFLFdBQVcsRUFBRSxNQUFNLEVBQUUsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLFNBQVMsRUFBRSxFQUFFLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxHQUFHLEVBQUUsRUFBRTtJQUN0RyxHQUFHLEVBQUUsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxFQUFFLE9BQU8sRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLElBQUksRUFBRSxFQUFFO0lBQzdGLFNBQVMsRUFBRSxFQUFFLEtBQUssRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUU7Q0FDckcsQ0FBQztBQUVGLDRCQUE0QjtBQUNmLFFBQUEsV0FBVyxHQUF5QixNQUFNLENBQUMsSUFBSSxDQUFDLG1CQUFXLENBQWdCLENBQUM7QUFFekYsa0RBQWtEO0FBQ3JDLFFBQUEsWUFBWSxHQUFjLFdBQVcsQ0FBQztBQUVuRCxtREFBbUQ7QUFDbkQsU0FBZ0IsV0FBVyxDQUFDLEtBQWE7SUFDdkMsT0FBTyxLQUFLLElBQUksbUJBQVcsQ0FBQztBQUM5QixDQUFDO0FBRUQseUVBQXlFO0FBQ3pFLFNBQWdCLGFBQWEsQ0FBQyxJQUFZO0lBQ3hDLE9BQU8sV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxtQkFBVyxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsbUJBQVcsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDO0FBQ3JGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLyoqIEF2YWlsYWJsZSBxdW90YSB0aWVyIGlkZW50aWZpZXJzLiAqL1xuZXhwb3J0IHR5cGUgUXVvdGFUaWVyID0gJ2RldmVsb3BlcicgfCAncHJvJyB8ICd1bmxpbWl0ZWQnO1xuXG4vKiogTGltaXQgdmFsdWVzIGZvciBlYWNoIHF1b3RhIHR5cGUgd2l0aGluIGEgdGllci4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUXVvdGFUaWVyTGltaXRzIHtcbiAgcGx1Z2luczogbnVtYmVyO1xuICBwaXBlbGluZXM6IG51bWJlcjtcbiAgYXBpQ2FsbHM6IG51bWJlcjtcbiAgYWlDYWxsczogbnVtYmVyO1xufVxuXG4vKiogRnVsbCBwcmVzZXQgZm9yIGEgc2luZ2xlIHRpZXIgKGxhYmVsICsgbGltaXRzKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUXVvdGFUaWVyUHJlc2V0IHtcbiAgbGFiZWw6IHN0cmluZztcbiAgbGltaXRzOiBRdW90YVRpZXJMaW1pdHM7XG59XG5cbi8qKlxuICogUHJlc2V0IGxpbWl0cyBmb3IgZWFjaCB0aWVyLiAtMSBtZWFucyB1bmxpbWl0ZWQuXG4gKlxuICogQUkgY2FsbHMgYXJlIHNpemVkIG11Y2ggc21hbGxlciB0aGFuIGBhcGlDYWxsc2AgYmVjYXVzZSBlYWNoIGNhbGwgaGFzXG4gKiBleHRlcm5hbCBwcm92aWRlciBjb3N0ICh+JDAuMDHigJMkMC4xMC9jYWxsKS4gRGV2ZWxvcGVyIHRpZXIgYWxsb3dzIGxpZ2h0XG4gKiBleHBsb3JhdGlvbiAoMTAwL3BlcmlvZCk7IFBybyBsaWZ0cyB0byA1MDAwOyBVbmxpbWl0ZWQgaXMgdW5jYXBwZWQuXG4gKi9cbmV4cG9ydCBjb25zdCBRVU9UQV9USUVSUzogUmVjb3JkPFF1b3RhVGllciwgUXVvdGFUaWVyUHJlc2V0PiA9IHtcbiAgZGV2ZWxvcGVyOiB7IGxhYmVsOiAnRGV2ZWxvcGVyJywgbGltaXRzOiB7IHBsdWdpbnM6IDEwMCwgcGlwZWxpbmVzOiAxMCwgYXBpQ2FsbHM6IC0xLCBhaUNhbGxzOiAxMDAgfSB9LFxuICBwcm86IHsgbGFiZWw6ICdQcm8nLCBsaW1pdHM6IHsgcGx1Z2luczogMTAwMCwgcGlwZWxpbmVzOiAxMDAsIGFwaUNhbGxzOiAtMSwgYWlDYWxsczogNTAwMCB9IH0sXG4gIHVubGltaXRlZDogeyBsYWJlbDogJ1VubGltaXRlZCcsIGxpbWl0czogeyBwbHVnaW5zOiAtMSwgcGlwZWxpbmVzOiAtMSwgYXBpQ2FsbHM6IC0xLCBhaUNhbGxzOiAtMSB9IH0sXG59O1xuXG4vKiogQWxsIHZhbGlkIHRpZXIgbmFtZXMuICovXG5leHBvcnQgY29uc3QgVkFMSURfVElFUlM6IHJlYWRvbmx5IFF1b3RhVGllcltdID0gT2JqZWN0LmtleXMoUVVPVEFfVElFUlMpIGFzIFF1b3RhVGllcltdO1xuXG4vKiogRGVmYXVsdCB0aWVyIGFzc2lnbmVkIHRvIG5ldyBvcmdhbml6YXRpb25zLiAqL1xuZXhwb3J0IGNvbnN0IERFRkFVTFRfVElFUjogUXVvdGFUaWVyID0gJ2RldmVsb3Blcic7XG5cbi8qKiBDaGVjayB3aGV0aGVyIGEgc3RyaW5nIGlzIGEgdmFsaWQgUXVvdGFUaWVyLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzVmFsaWRUaWVyKHZhbHVlOiBzdHJpbmcpOiB2YWx1ZSBpcyBRdW90YVRpZXIge1xuICByZXR1cm4gdmFsdWUgaW4gUVVPVEFfVElFUlM7XG59XG5cbi8qKiBHZXQgdGhlIGRlZmF1bHQgbGltaXRzIGZvciBhIGdpdmVuIHRpZXIgKGZhbGxzIGJhY2sgdG8gZGV2ZWxvcGVyKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRUaWVyTGltaXRzKHRpZXI6IHN0cmluZyk6IFF1b3RhVGllckxpbWl0cyB7XG4gIHJldHVybiBpc1ZhbGlkVGllcih0aWVyKSA/IFFVT1RBX1RJRVJTW3RpZXJdLmxpbWl0cyA6IFFVT1RBX1RJRVJTLmRldmVsb3Blci5saW1pdHM7XG59XG4iXX0=
81
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVvdGEtdGllcnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdHlwZXMvcXVvdGEtdGllcnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7OztBQXFHdEMsa0NBRUM7QUFHRCxzQ0FFQztBQTVFRDs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQU0sRUFBRSxHQUFHLElBQUksR0FBRyxJQUFJLEdBQUcsSUFBSSxDQUFDO0FBQ2pCLFFBQUEsV0FBVyxHQUF1QztJQUM3RCxTQUFTLEVBQUU7UUFDVCxLQUFLLEVBQUUsV0FBVztRQUNsQixNQUFNLEVBQUU7WUFDTixPQUFPLEVBQUUsR0FBRztZQUNaLFNBQVMsRUFBRSxFQUFFO1lBQ2IsUUFBUSxFQUFFLENBQUMsQ0FBQztZQUNaLE9BQU8sRUFBRSxHQUFHO1lBQ1osWUFBWSxFQUFFLENBQUMsR0FBRyxFQUFFO1lBQ3BCLHdFQUF3RTtZQUN4RSxxRUFBcUU7WUFDckUsbUVBQW1FO1lBQ25FLG1FQUFtRTtZQUNuRSxVQUFVLEVBQUUsRUFBRTtZQUNkLFVBQVUsRUFBRSxFQUFFO1lBQ2QsaUJBQWlCLEVBQUUsRUFBRTtZQUNyQixVQUFVLEVBQUUsQ0FBQztTQUNkO0tBQ0Y7SUFDRCxHQUFHLEVBQUU7UUFDSCxLQUFLLEVBQUUsS0FBSztRQUNaLE1BQU0sRUFBRTtZQUNOLE9BQU8sRUFBRSxJQUFJO1lBQ2IsU0FBUyxFQUFFLEdBQUc7WUFDZCxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBQ1osT0FBTyxFQUFFLElBQUk7WUFDYixZQUFZLEVBQUUsR0FBRyxHQUFHLEVBQUU7WUFDdEIsVUFBVSxFQUFFLEdBQUc7WUFDZixVQUFVLEVBQUUsR0FBRztZQUNmLGlCQUFpQixFQUFFLEVBQUU7WUFDckIsVUFBVSxFQUFFLENBQUM7U0FDZDtLQUNGO0lBQ0QsU0FBUyxFQUFFO1FBQ1QsS0FBSyxFQUFFLFdBQVc7UUFDbEIsTUFBTSxFQUFFO1lBQ04sT0FBTyxFQUFFLENBQUMsQ0FBQztZQUNYLFNBQVMsRUFBRSxDQUFDLENBQUM7WUFDYixRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBQ1osT0FBTyxFQUFFLENBQUMsQ0FBQztZQUNYLFlBQVksRUFBRSxDQUFDLENBQUM7WUFDaEIsVUFBVSxFQUFFLENBQUMsQ0FBQztZQUNkLFVBQVUsRUFBRSxDQUFDLENBQUM7WUFDZCxpQkFBaUIsRUFBRSxDQUFDLENBQUM7WUFDckIsVUFBVSxFQUFFLENBQUMsQ0FBQztTQUNmO0tBQ0Y7Q0FDRixDQUFDO0FBRUYsNEJBQTRCO0FBQ2YsUUFBQSxXQUFXLEdBQXlCLE1BQU0sQ0FBQyxJQUFJLENBQUMsbUJBQVcsQ0FBZ0IsQ0FBQztBQUV6RixrREFBa0Q7QUFDckMsUUFBQSxZQUFZLEdBQWMsV0FBVyxDQUFDO0FBRW5ELG1EQUFtRDtBQUNuRCxTQUFnQixXQUFXLENBQUMsS0FBYTtJQUN2QyxPQUFPLEtBQUssSUFBSSxtQkFBVyxDQUFDO0FBQzlCLENBQUM7QUFFRCx5RUFBeUU7QUFDekUsU0FBZ0IsYUFBYSxDQUFDLElBQVk7SUFDeEMsT0FBTyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLG1CQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFBLENBQUMsQ0FBQyxtQkFBVyxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUM7QUFDcEYsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKiogQXZhaWxhYmxlIHF1b3RhIHRpZXIgaWRlbnRpZmllcnMuICovXG5leHBvcnQgdHlwZSBRdW90YVRpZXIgPSAnZGV2ZWxvcGVyJyB8ICdwcm8nIHwgJ3VubGltaXRlZCc7XG5cbi8qKiBMaW1pdCB2YWx1ZXMgZm9yIGVhY2ggcXVvdGEgdHlwZSB3aXRoaW4gYSB0aWVyLiAqL1xuZXhwb3J0IGludGVyZmFjZSBRdW90YVRpZXJMaW1pdHMge1xuICBwbHVnaW5zOiBudW1iZXI7XG4gIHBpcGVsaW5lczogbnVtYmVyO1xuICBhcGlDYWxsczogbnVtYmVyO1xuICBhaUNhbGxzOiBudW1iZXI7XG4gIC8qKlxuICAgKiBBZ2dyZWdhdGUgcmVnaXN0cnkgc3RvcmFnZSBjYXAgaW4gQllURVMuIENvdW50ZWQgYWNyb3NzIGV2ZXJ5IHJlcG9cbiAgICogdW5kZXIgdGhlIG9yZydzIGBvcmcte29yZ0lkfS9gIG5hbWVzcGFjZS4gLTEgbWVhbnMgdW5saW1pdGVkLlxuICAgKiBwdXNoLWdhdGUgcmVhZHMgdGhpczsgdGhlIGltYWdlLXJlZ2lzdHJ5IHJlamVjdHMgdG9rZW4gaXNzdWFuY2UgZm9yXG4gICAqIGBwdXNoYCBzY29wZSB3aGVuIHRoZSBvcmcncyBtZWFzdXJlZCB1c2FnZSBleGNlZWRzIHRoZSBsaW1pdC5cbiAgICovXG4gIHN0b3JhZ2VCeXRlczogbnVtYmVyO1xuICAvKiogQ291bnQtcXVvdGFzIG9uIHRoZSB1c2VyLWVkaXRhYmxlIGZlYXR1cmUgdGFibGVzIGFkZGVkIHRvIGNsb3NlIHBlci1vcmdcbiAgICogIERvUyB2aWEgc3BhbS4gLTEgbWVhbnMgdW5saW1pdGVkLiAqL1xuICBkYXNoYm9hcmRzOiBudW1iZXI7XG4gIGFsZXJ0UnVsZXM6IG51bWJlcjtcbiAgYWxlcnREZXN0aW5hdGlvbnM6IG51bWJlcjtcbiAgaWRwQ29uZmlnczogbnVtYmVyO1xufVxuXG4vKiogRnVsbCBwcmVzZXQgZm9yIGEgc2luZ2xlIHRpZXIgKGxhYmVsICsgbGltaXRzKS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUXVvdGFUaWVyUHJlc2V0IHtcbiAgbGFiZWw6IHN0cmluZztcbiAgbGltaXRzOiBRdW90YVRpZXJMaW1pdHM7XG59XG5cbi8qKlxuICogUHJlc2V0IGxpbWl0cyBmb3IgZWFjaCB0aWVyLiAtMSBtZWFucyB1bmxpbWl0ZWQuXG4gKlxuICogQUkgY2FsbHMgYXJlIHNpemVkIG11Y2ggc21hbGxlciB0aGFuIGBhcGlDYWxsc2AgYmVjYXVzZSBlYWNoIGNhbGwgaGFzXG4gKiBleHRlcm5hbCBwcm92aWRlciBjb3N0ICh+JDAuMDEkMC4xMC9jYWxsKS4gRGV2ZWxvcGVyIHRpZXIgYWxsb3dzIGxpZ2h0XG4gKiBleHBsb3JhdGlvbiAoMTAwL3BlcmlvZCk7IFBybyBsaWZ0cyB0byA1MDAwOyBVbmxpbWl0ZWQgaXMgdW5jYXBwZWQuXG4gKlxuICogYHN0b3JhZ2VCeXRlc2AgaXMgdGhlIGFnZ3JlZ2F0ZSByZWdpc3RyeSBjYXAgcGVyIG9yZy4gU2l6ZWRcbiAqIGFyb3VuZCBwbHVnaW4taW1hZ2UgcmVhbGl0aWVzOiBhIHR5cGljYWwgcGx1Z2luIGltYWdlIGlzIDIwMDUwMCBNQjtcbiAqIERldmVsb3BlcidzIDUgR0IgaG9sZHMgfjEwIHZlcnNpb25zIMOXIH41MDAgTUIsIFBybydzIDEwMCBHQiBjb3ZlcnMgYVxuICogbWF0dXJlIGNhdGFsb2cuIE9wZXJhdG9ycyBjYW4gb3ZlcnJpZGUgcGVyLW9yZyB2aWEgdGhlIHF1b3RhIENSVUQgQVBJLlxuICovXG5jb25zdCBHQiA9IDEwMjQgKiAxMDI0ICogMTAyNDtcbmV4cG9ydCBjb25zdCBRVU9UQV9USUVSUzogUmVjb3JkPFF1b3RhVGllciwgUXVvdGFUaWVyUHJlc2V0PiA9IHtcbiAgZGV2ZWxvcGVyOiB7XG4gICAgbGFiZWw6ICdEZXZlbG9wZXInLFxuICAgIGxpbWl0czoge1xuICAgICAgcGx1Z2luczogMTAwLFxuICAgICAgcGlwZWxpbmVzOiAxMCxcbiAgICAgIGFwaUNhbGxzOiAtMSxcbiAgICAgIGFpQ2FsbHM6IDEwMCxcbiAgICAgIHN0b3JhZ2VCeXRlczogNSAqIEdCLFxuICAgICAgLy8gQ291bnRzIHNpemVkIHRvIFwiY29tZm9ydGFibHkgZW5vdWdoIGZvciBvbmUgdGVhbSwgbm90IGEgc2NyaXB0IHNwYW1cIjpcbiAgICAgIC8vIDIwIGRhc2hib2FyZHMgY292ZXJzIG9wcyArIHBlci1zZXJ2aWNlIGRyaWxsLWRvd25zLCA1MCBhbGVydCBydWxlc1xuICAgICAgLy8gY292ZXJzIHBlci1zZXJ2aWNlIGFsZXJ0cywgMTAgZGVzdGluYXRpb25zIGNvdmVycyBTbGFjayBjaGFubmVsc1xuICAgICAgLy8gcGVyIHRlYW0gKyBhIHdlYmhvb2sgZmFsbGJhY2ssIDEgSWRQIGNvbmZpZyAoeW91IG9ubHkgaGF2ZSBvbmUpLlxuICAgICAgZGFzaGJvYXJkczogMjAsXG4gICAgICBhbGVydFJ1bGVzOiA1MCxcbiAgICAgIGFsZXJ0RGVzdGluYXRpb25zOiAxMCxcbiAgICAgIGlkcENvbmZpZ3M6IDEsXG4gICAgfSxcbiAgfSxcbiAgcHJvOiB7XG4gICAgbGFiZWw6ICdQcm8nLFxuICAgIGxpbWl0czoge1xuICAgICAgcGx1Z2luczogMTAwMCxcbiAgICAgIHBpcGVsaW5lczogMTAwLFxuICAgICAgYXBpQ2FsbHM6IC0xLFxuICAgICAgYWlDYWxsczogNTAwMCxcbiAgICAgIHN0b3JhZ2VCeXRlczogMTAwICogR0IsXG4gICAgICBkYXNoYm9hcmRzOiAyMDAsXG4gICAgICBhbGVydFJ1bGVzOiA1MDAsXG4gICAgICBhbGVydERlc3RpbmF0aW9uczogNTAsXG4gICAgICBpZHBDb25maWdzOiA1LFxuICAgIH0sXG4gIH0sXG4gIHVubGltaXRlZDoge1xuICAgIGxhYmVsOiAnVW5saW1pdGVkJyxcbiAgICBsaW1pdHM6IHtcbiAgICAgIHBsdWdpbnM6IC0xLFxuICAgICAgcGlwZWxpbmVzOiAtMSxcbiAgICAgIGFwaUNhbGxzOiAtMSxcbiAgICAgIGFpQ2FsbHM6IC0xLFxuICAgICAgc3RvcmFnZUJ5dGVzOiAtMSxcbiAgICAgIGRhc2hib2FyZHM6IC0xLFxuICAgICAgYWxlcnRSdWxlczogLTEsXG4gICAgICBhbGVydERlc3RpbmF0aW9uczogLTEsXG4gICAgICBpZHBDb25maWdzOiAtMSxcbiAgICB9LFxuICB9LFxufTtcblxuLyoqIEFsbCB2YWxpZCB0aWVyIG5hbWVzLiAqL1xuZXhwb3J0IGNvbnN0IFZBTElEX1RJRVJTOiByZWFkb25seSBRdW90YVRpZXJbXSA9IE9iamVjdC5rZXlzKFFVT1RBX1RJRVJTKSBhcyBRdW90YVRpZXJbXTtcblxuLyoqIERlZmF1bHQgdGllciBhc3NpZ25lZCB0byBuZXcgb3JnYW5pemF0aW9ucy4gKi9cbmV4cG9ydCBjb25zdCBERUZBVUxUX1RJRVI6IFF1b3RhVGllciA9ICdkZXZlbG9wZXInO1xuXG4vKiogQ2hlY2sgd2hldGhlciBhIHN0cmluZyBpcyBhIHZhbGlkIFF1b3RhVGllci4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc1ZhbGlkVGllcih2YWx1ZTogc3RyaW5nKTogdmFsdWUgaXMgUXVvdGFUaWVyIHtcbiAgcmV0dXJuIHZhbHVlIGluIFFVT1RBX1RJRVJTO1xufVxuXG4vKiogR2V0IHRoZSBkZWZhdWx0IGxpbWl0cyBmb3IgYSBnaXZlbiB0aWVyIChmYWxscyBiYWNrIHRvIGRldmVsb3BlcikuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VGllckxpbWl0cyh0aWVyOiBzdHJpbmcpOiBRdW90YVRpZXJMaW1pdHMge1xuICByZXR1cm4gaXNWYWxpZFRpZXIodGllcikgPyBRVU9UQV9USUVSU1t0aWVyXS5saW1pdHM6IFFVT1RBX1RJRVJTLmRldmVsb3Blci5saW1pdHM7XG59XG4iXX0=
@@ -31,14 +31,14 @@ const headers_1 = require("./headers");
31
31
  * ```
32
32
  */
33
33
  function getIdentity(req) {
34
- // Prefer JWT-verified claims (req.user) over raw headers to prevent spoofing.
35
- // Headers are only used as fallback or for fields not in the JWT (e.g. requestId).
34
+ // Prefer JWT-verified claims (req.user) over raw headers to prevent
35
+ // spoofing. Headers are only used as fallback or for fields not in the
36
+ // JWT (e.g. requestId). The JWT payload uses `sub` for the user id per
37
+ // OIDC convention; that's our authoritative source.
36
38
  const user = req.user;
37
39
  return {
38
40
  orgId: user?.organizationId || (0, headers_1.getHeaderString)(req.headers['x-org-id']),
39
- userId: user?.sub
40
- || user?.userId
41
- || (0, headers_1.getHeaderString)(req.headers['x-user-id']),
41
+ userId: user?.sub || (0, headers_1.getHeaderString)(req.headers['x-user-id']),
42
42
  requestId: (0, headers_1.getHeaderString)(req.headers['x-request-id']),
43
43
  role: user?.role || (0, headers_1.getHeaderString)(req.headers['x-user-role']),
44
44
  };
@@ -72,4 +72,4 @@ function validateIdentity(identity, required) {
72
72
  missing,
73
73
  };
74
74
  }
75
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWRlbnRpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvaWRlbnRpdHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7O0FBNEN0QyxrQ0FZQztBQW1CRCw0Q0FnQkM7QUF6RkQsdUNBQTRDO0FBaUI1Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHO0FBQ0gsU0FBZ0IsV0FBVyxDQUFDLEdBQWdCO0lBQzFDLDhFQUE4RTtJQUM5RSxtRkFBbUY7SUFDbkYsTUFBTSxJQUFJLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQztJQUN0QixPQUFPO1FBQ0wsS0FBSyxFQUFFLElBQUksRUFBRSxjQUFjLElBQUksSUFBQSx5QkFBZSxFQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDdkUsTUFBTSxFQUFHLElBQTRDLEVBQUUsR0FBeUI7ZUFDM0UsSUFBSSxFQUFFLE1BQU07ZUFDWixJQUFBLHlCQUFlLEVBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM5QyxTQUFTLEVBQUUsSUFBQSx5QkFBZSxFQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDdkQsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLElBQUksSUFBQSx5QkFBZSxFQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUM7S0FDaEUsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7OztHQWdCRztBQUNILFNBQWdCLGdCQUFnQixDQUM5QixRQUF5QixFQUN6QixRQUFtQztJQUVuQyxNQUFNLE9BQU8sR0FBYSxFQUFFLENBQUM7SUFFN0IsS0FBSyxNQUFNLEtBQUssSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUM3QixJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDckIsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLEtBQUssQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN0RSxDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU87UUFDTCxPQUFPLEVBQUUsT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQzdCLE9BQU87S0FDUixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBnZXRIZWFkZXJTdHJpbmcgfSBmcm9tICcuL2hlYWRlcnMnO1xuaW1wb3J0IHsgSHR0cFJlcXVlc3QgfSBmcm9tICcuLi90eXBlcy9odHRwJztcblxuLyoqXG4gKiBJZGVudGl0eSBpbmZvcm1hdGlvbiBleHRyYWN0ZWQgZnJvbSByZXF1ZXN0IGhlYWRlcnMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVxdWVzdElkZW50aXR5IHtcbiAgLyoqIE9yZ2FuaXphdGlvbiBJRCBmcm9tIHgtb3JnLWlkIGhlYWRlciAqL1xuICByZWFkb25seSBvcmdJZD86IHN0cmluZztcbiAgLyoqIFVzZXIgSUQgZnJvbSB4LXVzZXItaWQgaGVhZGVyICovXG4gIHJlYWRvbmx5IHVzZXJJZD86IHN0cmluZztcbiAgLyoqIFJlcXVlc3QgSUQgZnJvbSB4LXJlcXVlc3QtaWQgaGVhZGVyICovXG4gIHJlYWRvbmx5IHJlcXVlc3RJZD86IHN0cmluZztcbiAgLyoqIFVzZXIgcm9sZSBmcm9tIHgtdXNlci1yb2xlIGhlYWRlciAoZGVjb2RlZCBmcm9tIEpXVCkgKi9cbiAgcmVhZG9ubHkgcm9sZT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBFeHRyYWN0IGlkZW50aXR5IGluZm9ybWF0aW9uIGZyb20gcmVxdWVzdCBoZWFkZXJzLlxuICpcbiAqIEV4dHJhY3RzIGNvbW1vbiBpZGVudGl0eSBoZWFkZXJzIHVzZWQgZm9yIG11bHRpLXRlbmFudCBhdXRoZW50aWNhdGlvbjpcbiAqIC0geC1vcmctaWQ6IE9yZ2FuaXphdGlvbiBpZGVudGlmaWVyXG4gKiAtIHgtdXNlci1pZDogVXNlciBpZGVudGlmaWVyXG4gKiAtIHgtcmVxdWVzdC1pZDogUmVxdWVzdCB0cmFjZSBpZGVudGlmaWVyXG4gKiAtIHgtdXNlci1yb2xlOiBVc2VyIHJvbGVcbiAqXG4gKiBAcGFyYW0gcmVxIC0gSFRUUCByZXF1ZXN0IG9iamVjdFxuICogQHJldHVybnMgSWRlbnRpdHkgb2JqZWN0IHdpdGggb3JnSWQsIHVzZXJJZCwgcmVxdWVzdElkLCBhbmQgcm9sZVxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBhcHAucG9zdCgnL2FwaS9yZXNvdXJjZScsIHJlcXVpcmVBdXRoLCBhc3luYyAocmVxLCByZXMpID0+IHtcbiAqICAgY29uc3QgaWRlbnRpdHkgPSBnZXRJZGVudGl0eShyZXEpO1xuICpcbiAqICAgaWYgKCFpZGVudGl0eS5vcmdJZCkge1xuICogICAgIHJldHVybiBzZW5kRXJyb3IocmVzLCA0MDAsICd4LW9yZy1pZCBoZWFkZXIgcmVxdWlyZWQnKTtcbiAqICAgfVxuICpcbiAqICAgLy8gVXNlIGlkZW50aXR5Lm9yZ0lkLCBpZGVudGl0eS51c2VySWQsIGV0Yy5cbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRJZGVudGl0eShyZXE6IEh0dHBSZXF1ZXN0KTogUmVxdWVzdElkZW50aXR5IHtcbiAgLy8gUHJlZmVyIEpXVC12ZXJpZmllZCBjbGFpbXMgKHJlcS51c2VyKSBvdmVyIHJhdyBoZWFkZXJzIHRvIHByZXZlbnQgc3Bvb2ZpbmcuXG4gIC8vIEhlYWRlcnMgYXJlIG9ubHkgdXNlZCBhcyBmYWxsYmFjayBvciBmb3IgZmllbGRzIG5vdCBpbiB0aGUgSldUIChlLmcuIHJlcXVlc3RJZCkuXG4gIGNvbnN0IHVzZXIgPSByZXEudXNlcjtcbiAgcmV0dXJuIHtcbiAgICBvcmdJZDogdXNlcj8ub3JnYW5pemF0aW9uSWQgfHwgZ2V0SGVhZGVyU3RyaW5nKHJlcS5oZWFkZXJzWyd4LW9yZy1pZCddKSxcbiAgICB1c2VySWQ6ICh1c2VyIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgdW5kZWZpbmVkKT8uc3ViIGFzIHN0cmluZyB8IHVuZGVmaW5lZFxuICAgICAgfHwgdXNlcj8udXNlcklkXG4gICAgICB8fCBnZXRIZWFkZXJTdHJpbmcocmVxLmhlYWRlcnNbJ3gtdXNlci1pZCddKSxcbiAgICByZXF1ZXN0SWQ6IGdldEhlYWRlclN0cmluZyhyZXEuaGVhZGVyc1sneC1yZXF1ZXN0LWlkJ10pLFxuICAgIHJvbGU6IHVzZXI/LnJvbGUgfHwgZ2V0SGVhZGVyU3RyaW5nKHJlcS5oZWFkZXJzWyd4LXVzZXItcm9sZSddKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBWYWxpZGF0ZSB0aGF0IHJlcXVpcmVkIGlkZW50aXR5IGZpZWxkcyBhcmUgcHJlc2VudC5cbiAqXG4gKiBAcGFyYW0gaWRlbnRpdHkgLSBJZGVudGl0eSBvYmplY3QgdG8gdmFsaWRhdGVcbiAqIEBwYXJhbSByZXF1aXJlZCAtIEFycmF5IG9mIHJlcXVpcmVkIGZpZWxkIG5hbWVzXG4gKiBAcmV0dXJucyBPYmplY3Qgd2l0aCBpc1ZhbGlkIGJvb2xlYW4gYW5kIG1pc3NpbmcgZmllbGRzIGFycmF5XG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGNvbnN0IGlkZW50aXR5ID0gZ2V0SWRlbnRpdHkocmVxKTtcbiAqIGNvbnN0IHZhbGlkYXRpb24gPSB2YWxpZGF0ZUlkZW50aXR5KGlkZW50aXR5LCBbJ29yZ0lkJywgJ3VzZXJJZCddKTtcbiAqXG4gKiBpZiAoIXZhbGlkYXRpb24uaXNWYWxpZCkge1xuICogICByZXR1cm4gc2VuZEVycm9yKHJlcywgNDAwLCBgTWlzc2luZyByZXF1aXJlZCBoZWFkZXJzOiAke3ZhbGlkYXRpb24ubWlzc2luZy5qb2luKCcsICcpfWApO1xuICogfVxuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUlkZW50aXR5KFxuICBpZGVudGl0eTogUmVxdWVzdElkZW50aXR5LFxuICByZXF1aXJlZDogKGtleW9mIFJlcXVlc3RJZGVudGl0eSlbXSxcbik6IHsgaXNWYWxpZDogYm9vbGVhbjsgbWlzc2luZzogc3RyaW5nW10gfSB7XG4gIGNvbnN0IG1pc3Npbmc6IHN0cmluZ1tdID0gW107XG5cbiAgZm9yIChjb25zdCBmaWVsZCBvZiByZXF1aXJlZCkge1xuICAgIGlmICghaWRlbnRpdHlbZmllbGRdKSB7XG4gICAgICBtaXNzaW5nLnB1c2goYHgtJHtmaWVsZC5yZXBsYWNlKC8oW0EtWl0pL2csICctJDEnKS50b0xvd2VyQ2FzZSgpfWApO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgaXNWYWxpZDogbWlzc2luZy5sZW5ndGggPT09IDAsXG4gICAgbWlzc2luZyxcbiAgfTtcbn1cbiJdfQ==
75
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWRlbnRpdHkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvaWRlbnRpdHkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7O0FBNEN0QyxrQ0FZQztBQW1CRCw0Q0FnQkM7QUF6RkQsdUNBQTRDO0FBaUI1Qzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBd0JHO0FBQ0gsU0FBZ0IsV0FBVyxDQUFDLEdBQWdCO0lBQzFDLG9FQUFvRTtJQUNwRSx1RUFBdUU7SUFDdkUsdUVBQXVFO0lBQ3ZFLG9EQUFvRDtJQUNwRCxNQUFNLElBQUksR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDO0lBQ3RCLE9BQU87UUFDTCxLQUFLLEVBQUUsSUFBSSxFQUFFLGNBQWMsSUFBSSxJQUFBLHlCQUFlLEVBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUN2RSxNQUFNLEVBQUUsSUFBSSxFQUFFLEdBQUcsSUFBSSxJQUFBLHlCQUFlLEVBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQztRQUM5RCxTQUFTLEVBQUUsSUFBQSx5QkFBZSxFQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsY0FBYyxDQUFDLENBQUM7UUFDdkQsSUFBSSxFQUFFLElBQUksRUFBRSxJQUFJLElBQUksSUFBQSx5QkFBZSxFQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLENBQUM7S0FDaEUsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7OztHQWdCRztBQUNILFNBQWdCLGdCQUFnQixDQUM5QixRQUF5QixFQUN6QixRQUFtQztJQUVuQyxNQUFNLE9BQU8sR0FBYSxFQUFFLENBQUM7SUFFN0IsS0FBSyxNQUFNLEtBQUssSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUM3QixJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDckIsT0FBTyxDQUFDLElBQUksQ0FBQyxLQUFLLEtBQUssQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLEtBQUssQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN0RSxDQUFDO0lBQ0gsQ0FBQztJQUVELE9BQU87UUFDTCxPQUFPLEVBQUUsT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQzdCLE9BQU87S0FDUixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyBnZXRIZWFkZXJTdHJpbmcgfSBmcm9tICcuL2hlYWRlcnMnO1xuaW1wb3J0IHsgSHR0cFJlcXVlc3QgfSBmcm9tICcuLi90eXBlcy9odHRwJztcblxuLyoqXG4gKiBJZGVudGl0eSBpbmZvcm1hdGlvbiBleHRyYWN0ZWQgZnJvbSByZXF1ZXN0IGhlYWRlcnMuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVxdWVzdElkZW50aXR5IHtcbiAgLyoqIE9yZ2FuaXphdGlvbiBJRCBmcm9tIHgtb3JnLWlkIGhlYWRlciAqL1xuICByZWFkb25seSBvcmdJZD86IHN0cmluZztcbiAgLyoqIFVzZXIgSUQgZnJvbSB4LXVzZXItaWQgaGVhZGVyICovXG4gIHJlYWRvbmx5IHVzZXJJZD86IHN0cmluZztcbiAgLyoqIFJlcXVlc3QgSUQgZnJvbSB4LXJlcXVlc3QtaWQgaGVhZGVyICovXG4gIHJlYWRvbmx5IHJlcXVlc3RJZD86IHN0cmluZztcbiAgLyoqIFVzZXIgcm9sZSBmcm9tIHgtdXNlci1yb2xlIGhlYWRlciAoZGVjb2RlZCBmcm9tIEpXVCkgKi9cbiAgcmVhZG9ubHkgcm9sZT86IHN0cmluZztcbn1cblxuLyoqXG4gKiBFeHRyYWN0IGlkZW50aXR5IGluZm9ybWF0aW9uIGZyb20gcmVxdWVzdCBoZWFkZXJzLlxuICpcbiAqIEV4dHJhY3RzIGNvbW1vbiBpZGVudGl0eSBoZWFkZXJzIHVzZWQgZm9yIG11bHRpLXRlbmFudCBhdXRoZW50aWNhdGlvbjpcbiAqIC0geC1vcmctaWQ6IE9yZ2FuaXphdGlvbiBpZGVudGlmaWVyXG4gKiAtIHgtdXNlci1pZDogVXNlciBpZGVudGlmaWVyXG4gKiAtIHgtcmVxdWVzdC1pZDogUmVxdWVzdCB0cmFjZSBpZGVudGlmaWVyXG4gKiAtIHgtdXNlci1yb2xlOiBVc2VyIHJvbGVcbiAqXG4gKiBAcGFyYW0gcmVxIC0gSFRUUCByZXF1ZXN0IG9iamVjdFxuICogQHJldHVybnMgSWRlbnRpdHkgb2JqZWN0IHdpdGggb3JnSWQsIHVzZXJJZCwgcmVxdWVzdElkLCBhbmQgcm9sZVxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBhcHAucG9zdCgnL2FwaS9yZXNvdXJjZScsIHJlcXVpcmVBdXRoLCBhc3luYyAocmVxLCByZXMpID0+IHtcbiAqICAgY29uc3QgaWRlbnRpdHkgPSBnZXRJZGVudGl0eShyZXEpO1xuICpcbiAqICAgaWYgKCFpZGVudGl0eS5vcmdJZCkge1xuICogICAgIHJldHVybiBzZW5kRXJyb3IocmVzLCA0MDAsICd4LW9yZy1pZCBoZWFkZXIgcmVxdWlyZWQnKTtcbiAqICAgfVxuICpcbiAqICAgLy8gVXNlIGlkZW50aXR5Lm9yZ0lkLCBpZGVudGl0eS51c2VySWQsIGV0Yy5cbiAqIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRJZGVudGl0eShyZXE6IEh0dHBSZXF1ZXN0KTogUmVxdWVzdElkZW50aXR5IHtcbiAgLy8gUHJlZmVyIEpXVC12ZXJpZmllZCBjbGFpbXMgKHJlcS51c2VyKSBvdmVyIHJhdyBoZWFkZXJzIHRvIHByZXZlbnRcbiAgLy8gc3Bvb2ZpbmcuIEhlYWRlcnMgYXJlIG9ubHkgdXNlZCBhcyBmYWxsYmFjayBvciBmb3IgZmllbGRzIG5vdCBpbiB0aGVcbiAgLy8gSldUIChlLmcuIHJlcXVlc3RJZCkuIFRoZSBKV1QgcGF5bG9hZCB1c2VzIGBzdWJgIGZvciB0aGUgdXNlciBpZCBwZXJcbiAgLy8gT0lEQyBjb252ZW50aW9uOyB0aGF0J3Mgb3VyIGF1dGhvcml0YXRpdmUgc291cmNlLlxuICBjb25zdCB1c2VyID0gcmVxLnVzZXI7XG4gIHJldHVybiB7XG4gICAgb3JnSWQ6IHVzZXI/Lm9yZ2FuaXphdGlvbklkIHx8IGdldEhlYWRlclN0cmluZyhyZXEuaGVhZGVyc1sneC1vcmctaWQnXSksXG4gICAgdXNlcklkOiB1c2VyPy5zdWIgfHwgZ2V0SGVhZGVyU3RyaW5nKHJlcS5oZWFkZXJzWyd4LXVzZXItaWQnXSksXG4gICAgcmVxdWVzdElkOiBnZXRIZWFkZXJTdHJpbmcocmVxLmhlYWRlcnNbJ3gtcmVxdWVzdC1pZCddKSxcbiAgICByb2xlOiB1c2VyPy5yb2xlIHx8IGdldEhlYWRlclN0cmluZyhyZXEuaGVhZGVyc1sneC11c2VyLXJvbGUnXSksXG4gIH07XG59XG5cbi8qKlxuICogVmFsaWRhdGUgdGhhdCByZXF1aXJlZCBpZGVudGl0eSBmaWVsZHMgYXJlIHByZXNlbnQuXG4gKlxuICogQHBhcmFtIGlkZW50aXR5IC0gSWRlbnRpdHkgb2JqZWN0IHRvIHZhbGlkYXRlXG4gKiBAcGFyYW0gcmVxdWlyZWQgLSBBcnJheSBvZiByZXF1aXJlZCBmaWVsZCBuYW1lc1xuICogQHJldHVybnMgT2JqZWN0IHdpdGggaXNWYWxpZCBib29sZWFuIGFuZCBtaXNzaW5nIGZpZWxkcyBhcnJheVxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBjb25zdCBpZGVudGl0eSA9IGdldElkZW50aXR5KHJlcSk7XG4gKiBjb25zdCB2YWxpZGF0aW9uID0gdmFsaWRhdGVJZGVudGl0eShpZGVudGl0eSwgWydvcmdJZCcsICd1c2VySWQnXSk7XG4gKlxuICogaWYgKCF2YWxpZGF0aW9uLmlzVmFsaWQpIHtcbiAqICAgcmV0dXJuIHNlbmRFcnJvcihyZXMsIDQwMCwgYE1pc3NpbmcgcmVxdWlyZWQgaGVhZGVyczogJHt2YWxpZGF0aW9uLm1pc3Npbmcuam9pbignLCAnKX1gKTtcbiAqIH1cbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVJZGVudGl0eShcbiAgaWRlbnRpdHk6IFJlcXVlc3RJZGVudGl0eSxcbiAgcmVxdWlyZWQ6IChrZXlvZiBSZXF1ZXN0SWRlbnRpdHkpW10sXG4pOiB7IGlzVmFsaWQ6IGJvb2xlYW47IG1pc3Npbmc6IHN0cmluZ1tdIH0ge1xuICBjb25zdCBtaXNzaW5nOiBzdHJpbmdbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgZmllbGQgb2YgcmVxdWlyZWQpIHtcbiAgICBpZiAoIWlkZW50aXR5W2ZpZWxkXSkge1xuICAgICAgbWlzc2luZy5wdXNoKGB4LSR7ZmllbGQucmVwbGFjZSgvKFtBLVpdKS9nLCAnLSQxJykudG9Mb3dlckNhc2UoKX1gKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIGlzVmFsaWQ6IG1pc3NpbmcubGVuZ3RoID09PSAwLFxuICAgIG1pc3NpbmcsXG4gIH07XG59XG4iXX0=
@@ -7,3 +7,6 @@ export * from './object';
7
7
  export * from './alias-resolver';
8
8
  export * from './concurrency';
9
9
  export * from './audit';
10
+ export * from './secret-encryption';
11
+ export * from './org-aws-credentials';
12
+ export * from './metric-emitter';
@@ -25,4 +25,7 @@ __exportStar(require("./object"), exports);
25
25
  __exportStar(require("./alias-resolver"), exports);
26
26
  __exportStar(require("./concurrency"), exports);
27
27
  __exportStar(require("./audit"), exports);
28
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFdEMsMkNBQXlCO0FBQ3pCLDZDQUEyQjtBQUMzQiwyQ0FBeUI7QUFDekIsNENBQTBCO0FBQzFCLDZDQUEyQjtBQUMzQiwyQ0FBeUI7QUFDekIsbURBQWlDO0FBQ2pDLGdEQUE4QjtBQUM5QiwwQ0FBd0IiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuZXhwb3J0ICogZnJvbSAnLi9sb2dnZXInO1xuZXhwb3J0ICogZnJvbSAnLi9yZXNwb25zZSc7XG5leHBvcnQgKiBmcm9tICcuL3BhcmFtcyc7XG5leHBvcnQgKiBmcm9tICcuL2hlYWRlcnMnO1xuZXhwb3J0ICogZnJvbSAnLi9pZGVudGl0eSc7XG5leHBvcnQgKiBmcm9tICcuL29iamVjdCc7XG5leHBvcnQgKiBmcm9tICcuL2FsaWFzLXJlc29sdmVyJztcbmV4cG9ydCAqIGZyb20gJy4vY29uY3VycmVuY3knO1xuZXhwb3J0ICogZnJvbSAnLi9hdWRpdCc7XG4iXX0=
28
+ __exportStar(require("./secret-encryption"), exports);
29
+ __exportStar(require("./org-aws-credentials"), exports);
30
+ __exportStar(require("./metric-emitter"), exports);
31
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7Ozs7Ozs7Ozs7Ozs7Ozs7QUFFdEMsMkNBQXlCO0FBQ3pCLDZDQUEyQjtBQUMzQiwyQ0FBeUI7QUFDekIsNENBQTBCO0FBQzFCLDZDQUEyQjtBQUMzQiwyQ0FBeUI7QUFDekIsbURBQWlDO0FBQ2pDLGdEQUE4QjtBQUM5QiwwQ0FBd0I7QUFDeEIsc0RBQW9DO0FBQ3BDLHdEQUFzQztBQUN0QyxtREFBaUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuZXhwb3J0ICogZnJvbSAnLi9sb2dnZXInO1xuZXhwb3J0ICogZnJvbSAnLi9yZXNwb25zZSc7XG5leHBvcnQgKiBmcm9tICcuL3BhcmFtcyc7XG5leHBvcnQgKiBmcm9tICcuL2hlYWRlcnMnO1xuZXhwb3J0ICogZnJvbSAnLi9pZGVudGl0eSc7XG5leHBvcnQgKiBmcm9tICcuL29iamVjdCc7XG5leHBvcnQgKiBmcm9tICcuL2FsaWFzLXJlc29sdmVyJztcbmV4cG9ydCAqIGZyb20gJy4vY29uY3VycmVuY3knO1xuZXhwb3J0ICogZnJvbSAnLi9hdWRpdCc7XG5leHBvcnQgKiBmcm9tICcuL3NlY3JldC1lbmNyeXB0aW9uJztcbmV4cG9ydCAqIGZyb20gJy4vb3JnLWF3cy1jcmVkZW50aWFscyc7XG5leHBvcnQgKiBmcm9tICcuL21ldHJpYy1lbWl0dGVyJztcbiJdfQ==
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Pluggable counter-emit shim.
3
+ *
4
+ * Background: several api-core primitives (quota client fail-open, future
5
+ * security-event hooks) want to record Prometheus counters when something
6
+ * notable happens. The actual `prom-client` Counter registration lives in
7
+ * api-server, and api-core must not depend on api-server (api-core is
8
+ * upstream — Express infrastructure imports it, not the other way around).
9
+ *
10
+ * This module is the seam. api-core code calls `emitCounter(name, labels)`;
11
+ * by default it's a no-op (tests, CLIs, environments without Prometheus).
12
+ * api-server's app-factory calls `setCounterEmitter(incCounter)` at startup
13
+ * so production processes start incrementing the real counter on the
14
+ * shared registry.
15
+ *
16
+ * Why a callback instead of an interface registered via DI? The call sites
17
+ * (quota fail-open, etc.) sit in deep helpers that never touch the Express
18
+ * context, so requiring a `metrics` parameter on every call would mean
19
+ * threading it through dozens of unrelated functions. A process-singleton
20
+ * callback is the simplest non-invasive option; the trade-off is one
21
+ * shared global, which is acceptable for a sink that's strictly write-only.
22
+ */
23
+ /** Callable signature mirroring api-server's `incCounter`. */
24
+ export type CounterEmitter = (name: string, labels?: Record<string, string>, value?: number) => void;
25
+ /**
26
+ * Register the real counter implementation. Idempotent — the last call wins;
27
+ * typically called once at service startup from api-server.
28
+ */
29
+ export declare function setCounterEmitter(fn: CounterEmitter): void;
30
+ /** Reset to the no-op emitter. For tests that want to clear any wiring. */
31
+ export declare function resetCounterEmitter(): void;
32
+ /**
33
+ * Record a counter event. Safe to call from any api-core module — if no
34
+ * emitter is wired, this is a no-op.
35
+ */
36
+ export declare function emitCounter(name: string, labels?: Record<string, string>, value?: number): void;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ // Copyright 2026 Pipeline Builder Contributors
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.setCounterEmitter = setCounterEmitter;
6
+ exports.resetCounterEmitter = resetCounterEmitter;
7
+ exports.emitCounter = emitCounter;
8
+ let emitter = () => {
9
+ // Default no-op. api-server wires this to a real Prometheus counter at
10
+ // startup; until then, calls from api-core helpers are silently dropped
11
+ // (which is what we want in tests and CLIs that don't run a Prom server).
12
+ };
13
+ /**
14
+ * Register the real counter implementation. Idempotent — the last call wins;
15
+ * typically called once at service startup from api-server.
16
+ */
17
+ function setCounterEmitter(fn) {
18
+ emitter = fn;
19
+ }
20
+ /** Reset to the no-op emitter. For tests that want to clear any wiring. */
21
+ function resetCounterEmitter() {
22
+ emitter = () => undefined;
23
+ }
24
+ /**
25
+ * Record a counter event. Safe to call from any api-core module — if no
26
+ * emitter is wired, this is a no-op.
27
+ */
28
+ function emitCounter(name, labels = {}, value = 1) {
29
+ try {
30
+ emitter(name, labels, value);
31
+ }
32
+ catch {
33
+ // Never let metric emission break the calling path. A misbehaving
34
+ // emitter shouldn't be able to take down quota checks (or anything else).
35
+ }
36
+ }
37
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljLWVtaXR0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdXRpbHMvbWV0cmljLWVtaXR0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7O0FBc0N0Qyw4Q0FFQztBQUdELGtEQUVDO0FBTUQsa0NBT0M7QUE5QkQsSUFBSSxPQUFPLEdBQW1CLEdBQUcsRUFBRTtJQUNqQyx1RUFBdUU7SUFDdkUsd0VBQXdFO0lBQ3hFLDBFQUEwRTtBQUM1RSxDQUFDLENBQUM7QUFFRjs7O0dBR0c7QUFDSCxTQUFnQixpQkFBaUIsQ0FBQyxFQUFrQjtJQUNsRCxPQUFPLEdBQUcsRUFBRSxDQUFDO0FBQ2YsQ0FBQztBQUVELDJFQUEyRTtBQUMzRSxTQUFnQixtQkFBbUI7SUFDakMsT0FBTyxHQUFHLEdBQUcsRUFBRSxDQUFDLFNBQVMsQ0FBQztBQUM1QixDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsU0FBZ0IsV0FBVyxDQUFDLElBQVksRUFBRSxTQUFpQyxFQUFFLEVBQUUsS0FBSyxHQUFHLENBQUM7SUFDdEYsSUFBSSxDQUFDO1FBQ0gsT0FBTyxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7SUFDL0IsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLGtFQUFrRTtRQUNsRSwwRUFBMEU7SUFDNUUsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLyoqXG4gKiBQbHVnZ2FibGUgY291bnRlci1lbWl0IHNoaW0uXG4gKlxuICogQmFja2dyb3VuZDogc2V2ZXJhbCBhcGktY29yZSBwcmltaXRpdmVzIChxdW90YSBjbGllbnQgZmFpbC1vcGVuLCBmdXR1cmVcbiAqIHNlY3VyaXR5LWV2ZW50IGhvb2tzKSB3YW50IHRvIHJlY29yZCBQcm9tZXRoZXVzIGNvdW50ZXJzIHdoZW4gc29tZXRoaW5nXG4gKiBub3RhYmxlIGhhcHBlbnMuIFRoZSBhY3R1YWwgYHByb20tY2xpZW50YCBDb3VudGVyIHJlZ2lzdHJhdGlvbiBsaXZlcyBpblxuICogYXBpLXNlcnZlciwgYW5kIGFwaS1jb3JlIG11c3Qgbm90IGRlcGVuZCBvbiBhcGktc2VydmVyIChhcGktY29yZSBpc1xuICogdXBzdHJlYW0g4oCUIEV4cHJlc3MgaW5mcmFzdHJ1Y3R1cmUgaW1wb3J0cyBpdCwgbm90IHRoZSBvdGhlciB3YXkgYXJvdW5kKS5cbiAqXG4gKiBUaGlzIG1vZHVsZSBpcyB0aGUgc2VhbS4gYXBpLWNvcmUgY29kZSBjYWxscyBgZW1pdENvdW50ZXIobmFtZSwgbGFiZWxzKWA7XG4gKiBieSBkZWZhdWx0IGl0J3MgYSBuby1vcCAodGVzdHMsIENMSXMsIGVudmlyb25tZW50cyB3aXRob3V0IFByb21ldGhldXMpLlxuICogYXBpLXNlcnZlcidzIGFwcC1mYWN0b3J5IGNhbGxzIGBzZXRDb3VudGVyRW1pdHRlcihpbmNDb3VudGVyKWAgYXQgc3RhcnR1cFxuICogc28gcHJvZHVjdGlvbiBwcm9jZXNzZXMgc3RhcnQgaW5jcmVtZW50aW5nIHRoZSByZWFsIGNvdW50ZXIgb24gdGhlXG4gKiBzaGFyZWQgcmVnaXN0cnkuXG4gKlxuICogV2h5IGEgY2FsbGJhY2sgaW5zdGVhZCBvZiBhbiBpbnRlcmZhY2UgcmVnaXN0ZXJlZCB2aWEgREk/IFRoZSBjYWxsIHNpdGVzXG4gKiAocXVvdGEgZmFpbC1vcGVuLCBldGMuKSBzaXQgaW4gZGVlcCBoZWxwZXJzIHRoYXQgbmV2ZXIgdG91Y2ggdGhlIEV4cHJlc3NcbiAqIGNvbnRleHQsIHNvIHJlcXVpcmluZyBhIGBtZXRyaWNzYCBwYXJhbWV0ZXIgb24gZXZlcnkgY2FsbCB3b3VsZCBtZWFuXG4gKiB0aHJlYWRpbmcgaXQgdGhyb3VnaCBkb3plbnMgb2YgdW5yZWxhdGVkIGZ1bmN0aW9ucy4gQSBwcm9jZXNzLXNpbmdsZXRvblxuICogY2FsbGJhY2sgaXMgdGhlIHNpbXBsZXN0IG5vbi1pbnZhc2l2ZSBvcHRpb247IHRoZSB0cmFkZS1vZmYgaXMgb25lXG4gKiBzaGFyZWQgZ2xvYmFsLCB3aGljaCBpcyBhY2NlcHRhYmxlIGZvciBhIHNpbmsgdGhhdCdzIHN0cmljdGx5IHdyaXRlLW9ubHkuXG4gKi9cblxuLyoqIENhbGxhYmxlIHNpZ25hdHVyZSBtaXJyb3JpbmcgYXBpLXNlcnZlcidzIGBpbmNDb3VudGVyYC4gKi9cbmV4cG9ydCB0eXBlIENvdW50ZXJFbWl0dGVyID0gKG5hbWU6IHN0cmluZywgbGFiZWxzPzogUmVjb3JkPHN0cmluZywgc3RyaW5nPiwgdmFsdWU/OiBudW1iZXIpID0+IHZvaWQ7XG5cbmxldCBlbWl0dGVyOiBDb3VudGVyRW1pdHRlciA9ICgpID0+IHtcbiAgLy8gRGVmYXVsdCBuby1vcC4gYXBpLXNlcnZlciB3aXJlcyB0aGlzIHRvIGEgcmVhbCBQcm9tZXRoZXVzIGNvdW50ZXIgYXRcbiAgLy8gc3RhcnR1cDsgdW50aWwgdGhlbiwgY2FsbHMgZnJvbSBhcGktY29yZSBoZWxwZXJzIGFyZSBzaWxlbnRseSBkcm9wcGVkXG4gIC8vICh3aGljaCBpcyB3aGF0IHdlIHdhbnQgaW4gdGVzdHMgYW5kIENMSXMgdGhhdCBkb24ndCBydW4gYSBQcm9tIHNlcnZlcikuXG59O1xuXG4vKipcbiAqIFJlZ2lzdGVyIHRoZSByZWFsIGNvdW50ZXIgaW1wbGVtZW50YXRpb24uIElkZW1wb3RlbnQg4oCUIHRoZSBsYXN0IGNhbGwgd2lucztcbiAqIHR5cGljYWxseSBjYWxsZWQgb25jZSBhdCBzZXJ2aWNlIHN0YXJ0dXAgZnJvbSBhcGktc2VydmVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2V0Q291bnRlckVtaXR0ZXIoZm46IENvdW50ZXJFbWl0dGVyKTogdm9pZCB7XG4gIGVtaXR0ZXIgPSBmbjtcbn1cblxuLyoqIFJlc2V0IHRvIHRoZSBuby1vcCBlbWl0dGVyLiBGb3IgdGVzdHMgdGhhdCB3YW50IHRvIGNsZWFyIGFueSB3aXJpbmcuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzZXRDb3VudGVyRW1pdHRlcigpOiB2b2lkIHtcbiAgZW1pdHRlciA9ICgpID0+IHVuZGVmaW5lZDtcbn1cblxuLyoqXG4gKiBSZWNvcmQgYSBjb3VudGVyIGV2ZW50LiBTYWZlIHRvIGNhbGwgZnJvbSBhbnkgYXBpLWNvcmUgbW9kdWxlIOKAlCBpZiBub1xuICogZW1pdHRlciBpcyB3aXJlZCwgdGhpcyBpcyBhIG5vLW9wLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZW1pdENvdW50ZXIobmFtZTogc3RyaW5nLCBsYWJlbHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fSwgdmFsdWUgPSAxKTogdm9pZCB7XG4gIHRyeSB7XG4gICAgZW1pdHRlcihuYW1lLCBsYWJlbHMsIHZhbHVlKTtcbiAgfSBjYXRjaCB7XG4gICAgLy8gTmV2ZXIgbGV0IG1ldHJpYyBlbWlzc2lvbiBicmVhayB0aGUgY2FsbGluZyBwYXRoLiBBIG1pc2JlaGF2aW5nXG4gICAgLy8gZW1pdHRlciBzaG91bGRuJ3QgYmUgYWJsZSB0byB0YWtlIGRvd24gcXVvdGEgY2hlY2tzIChvciBhbnl0aGluZyBlbHNlKS5cbiAgfVxufVxuIl19
@@ -0,0 +1,154 @@
1
+ /**
2
+ * Per-org IAM role assumption for build / runtime AWS API calls.
3
+ *
4
+ * The shared posture for AWS calls today is "the service's IAM role, full
5
+ * blast radius across every org." The operator-side mitigation operators
6
+ * actually want is: each customer org gets its own IAM role in its own
7
+ * account; build/runtime AWS calls for that org `sts:AssumeRole` into the
8
+ * customer's role; a compromise of one org's role can't enumerate another
9
+ * org's S3 buckets / ECR repos.
10
+ *
11
+ * This module is the credential-provider primitive. It's pluggable on the
12
+ * org-config resolver so the same code path works whether config is read
13
+ * from Mongo, Postgres, or env vars. Callers receive a standard SDK v3
14
+ * `AwsCredentialIdentityProvider` and pass it to any SDK client
15
+ * (`new CodeBuildClient({ credentials })`, etc.).
16
+ *
17
+ * No global state — callers construct one `OrgAwsCredentialsManager` per
18
+ * process and `await manager.getCredentials(orgId)` before each AWS call.
19
+ * The returned provider handles credential refresh internally (the
20
+ * underlying `fromTemporaryCredentials` re-calls AssumeRole ~5 min before
21
+ * the temporary credentials expire), so call sites don't manage TTL.
22
+ *
23
+ * Safety properties:
24
+ * - `externalId` is plumbed through to AssumeRole. Operators bake this
25
+ * into the IAM trust policy as the "confused deputy" mitigation; this
26
+ * module never silently omits it.
27
+ * - Orgs without a configured role fall through to the supplied
28
+ * `fallback` provider (typically the SDK default chain). Mixed-mode
29
+ * deployments where some orgs have per-org roles and others use the
30
+ * shared role are explicitly supported.
31
+ * - `evict(orgId)` drops the cached provider so the next call re-resolves
32
+ * from the resolver — use after the operator changes an org's role.
33
+ *
34
+ * Integration pattern for AWS SDK clients:
35
+ *
36
+ * ```ts
37
+ * import { S3Client } from '@aws-sdk/client-s3';
38
+ * import { withOrgAwsCredentials } from '@pipeline-builder/api-core';
39
+ *
40
+ * const manager = new OrgAwsCredentialsManager({ resolver });
41
+ *
42
+ * async function s3ForOrg(orgId: string) {
43
+ * return withOrgAwsCredentials(manager, orgId, (creds) =>
44
+ * new S3Client({ credentials: creds, region: 'us-west-2' }));
45
+ * }
46
+ * ```
47
+ *
48
+ * Today's codebase: no platform-side service makes AWS API calls scoped to
49
+ * a customer org (build runners use buildkitd; AWS Lambda handlers run in
50
+ * customer territory with their own IAM). This primitive is in place for
51
+ * when the architecture grows to add such call sites — per-org S3 buckets,
52
+ * per-org ECR repos, per-org CodeBuild projects — without forcing an
53
+ * insecure default.
54
+ */
55
+ /** Structural shape of an AWS credential. Matches `@smithy/types#AwsCredentialIdentity`
56
+ * exactly — defined locally so api-core doesn't need to declare @smithy/types
57
+ * as a direct dep (it's a transitive of every AWS SDK client we use). */
58
+ export interface AwsCredentialIdentity {
59
+ accessKeyId: string;
60
+ secretAccessKey: string;
61
+ sessionToken?: string;
62
+ expiration?: Date;
63
+ credentialScope?: string;
64
+ accountId?: string;
65
+ }
66
+ /** Standard credential-provider callable. Matches `@smithy/types#AwsCredentialIdentityProvider`. */
67
+ export type AwsCredentialIdentityProvider = () => Promise<AwsCredentialIdentity>;
68
+ /** Operator-supplied per-org IAM role + region pinning. */
69
+ export interface OrgAwsConfig {
70
+ /** ARN of the role this org's build/runtime code should assume. */
71
+ assumeRoleArn: string;
72
+ /** External id baked into the role's trust policy (recommended). */
73
+ externalId?: string;
74
+ /** Region to use when the calling code doesn't pin one. */
75
+ region?: string;
76
+ /** AssumeRole session duration (seconds). AWS allows 900-43200; the
77
+ * effective ceiling is the role's `MaxSessionDuration`. Default 3600. */
78
+ sessionDurationSeconds?: number;
79
+ /** Session name embedded in CloudTrail. Useful for incident-response
80
+ * attribution. Default `pipeline-builder-<orgId>`. */
81
+ roleSessionName?: string;
82
+ }
83
+ /** Async resolver: orgId → config | null. Returning null means "this org
84
+ * has no per-org role; use the fallback provider." */
85
+ export type OrgAwsConfigResolver = (orgId: string) => Promise<OrgAwsConfig | null>;
86
+ /** Constructor options. */
87
+ export interface OrgAwsCredentialsManagerOptions {
88
+ resolver: OrgAwsConfigResolver;
89
+ /** Provider used for orgs whose resolver returns null. Default: the SDK
90
+ * default chain via `@aws-sdk/credential-providers#fromNodeProviderChain`. */
91
+ fallback?: AwsCredentialIdentityProvider;
92
+ /** Region passed to the inner STS client when the org config doesn't
93
+ * pin one. Default: `AWS_REGION` / `AWS_DEFAULT_REGION` env. */
94
+ region?: string;
95
+ /** STS endpoint override (LocalStack, VPC endpoint). Default: SDK default. */
96
+ endpoint?: string;
97
+ }
98
+ /**
99
+ * Per-process manager that resolves and caches per-org credential providers.
100
+ * One instance per service; share it across handlers.
101
+ */
102
+ export declare class OrgAwsCredentialsManager {
103
+ private readonly resolver;
104
+ private readonly fallbackOverride?;
105
+ private readonly region?;
106
+ private readonly endpoint?;
107
+ private readonly cache;
108
+ private readonly inFlight;
109
+ /** Lazy default chain. Built once per manager so we don't import the
110
+ * credential-providers SDK in test environments that never touch the
111
+ * fallback path. */
112
+ private fallbackCache?;
113
+ constructor(opts: OrgAwsCredentialsManagerOptions);
114
+ /**
115
+ * Return an AwsCredentialIdentityProvider scoped to `orgId`. Pass the
116
+ * returned value into any SDK v3 client's `credentials` option.
117
+ *
118
+ * Concurrent first-touch callers share one resolver invocation; later
119
+ * calls hit the cache. The provider itself caches and refreshes
120
+ * AssumeRole-derived credentials internally.
121
+ */
122
+ getCredentials(orgId: string): Promise<AwsCredentialIdentityProvider>;
123
+ /** Drop the cached provider for an org. Call after the operator rotates
124
+ * the role ARN or external id so the next request rebuilds. */
125
+ evict(orgId: string): void;
126
+ /** Drop every cached provider. Useful in tests; rarely in production. */
127
+ evictAll(): void;
128
+ private resolveAndBuild;
129
+ private getFallback;
130
+ private buildAssumeRoleProvider;
131
+ }
132
+ /** Convenience: directly resolve credentials for a single call. The manager
133
+ * doesn't cache when called this way — useful in CLIs / one-shot scripts. */
134
+ export declare function resolveOrgCredentialsOnce(orgId: string, resolver: OrgAwsConfigResolver): Promise<AwsCredentialIdentity>;
135
+ /**
136
+ * Adapter: resolve per-org credentials and construct an AWS SDK client
137
+ * pre-bound to them. The factory is async because credential resolution may
138
+ * need to make a network call (fetching org config + AssumeRole). Once
139
+ * resolved, the returned client is ready for normal SDK calls; the provider
140
+ * inside refreshes credentials automatically before they expire.
141
+ *
142
+ * Typical usage:
143
+ * ```ts
144
+ * const s3 = await withOrgAwsCredentials(manager, orgId, (creds) =>
145
+ * new S3Client({ credentials: creds, region: 'us-west-2' }));
146
+ * await s3.send(new ListObjectsV2Command({ Bucket: bucketFor(orgId) }));
147
+ * ```
148
+ *
149
+ * The factory is invoked exactly once per call — callers that need a
150
+ * long-lived client should cache the result themselves rather than rebuilding
151
+ * on every operation. (Re-resolving on every op is fine for cold paths and
152
+ * a wasted couple of object allocations on hot paths.)
153
+ */
154
+ export declare function withOrgAwsCredentials<TClient>(manager: OrgAwsCredentialsManager, orgId: string, factory: (credentials: AwsCredentialIdentityProvider) => TClient): Promise<TClient>;