pepr 0.42.0 → 0.42.2

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 (149) hide show
  1. package/dist/cli/build.d.ts +1 -0
  2. package/dist/cli/build.d.ts.map +1 -1
  3. package/dist/cli/build.helpers.d.ts +66 -0
  4. package/dist/cli/build.helpers.d.ts.map +1 -1
  5. package/dist/cli/deploy.d.ts +15 -0
  6. package/dist/cli/deploy.d.ts.map +1 -1
  7. package/dist/cli/dev.d.ts.map +1 -1
  8. package/dist/cli/format.d.ts.map +1 -1
  9. package/dist/cli/format.helpers.d.ts +3 -0
  10. package/dist/cli/format.helpers.d.ts.map +1 -0
  11. package/dist/cli/init/enums.d.ts +10 -0
  12. package/dist/cli/init/enums.d.ts.map +1 -0
  13. package/dist/cli/init/index.d.ts.map +1 -1
  14. package/dist/cli/init/templates.d.ts +15 -11
  15. package/dist/cli/init/templates.d.ts.map +1 -1
  16. package/dist/cli/init/utils.d.ts.map +1 -1
  17. package/dist/cli/init/walkthrough.d.ts +3 -2
  18. package/dist/cli/init/walkthrough.d.ts.map +1 -1
  19. package/dist/cli/kfc.d.ts.map +1 -1
  20. package/dist/cli/monitor.d.ts +23 -0
  21. package/dist/cli/monitor.d.ts.map +1 -1
  22. package/dist/cli/root.d.ts.map +1 -1
  23. package/dist/cli/update.d.ts.map +1 -1
  24. package/dist/cli/uuid.d.ts.map +1 -1
  25. package/dist/cli.js +483 -586
  26. package/dist/controller.js +1 -195
  27. package/dist/fixtures/loader.d.ts.map +1 -1
  28. package/dist/lib/assets/deploy.d.ts.map +1 -1
  29. package/dist/lib/assets/destroy.d.ts.map +1 -1
  30. package/dist/lib/assets/helm.d.ts +1 -1
  31. package/dist/lib/assets/helm.d.ts.map +1 -1
  32. package/dist/lib/assets/index.d.ts +1 -1
  33. package/dist/lib/assets/index.d.ts.map +1 -1
  34. package/dist/lib/assets/pods.d.ts +6 -22
  35. package/dist/lib/assets/pods.d.ts.map +1 -1
  36. package/dist/lib/assets/rbac.d.ts.map +1 -1
  37. package/dist/lib/assets/webhooks.d.ts.map +1 -1
  38. package/dist/lib/assets/yaml.d.ts.map +1 -1
  39. package/dist/lib/controller/index.d.ts +2 -2
  40. package/dist/lib/controller/index.d.ts.map +1 -1
  41. package/dist/lib/controller/store.d.ts +1 -2
  42. package/dist/lib/controller/store.d.ts.map +1 -1
  43. package/dist/lib/controller/storeCache.d.ts +2 -1
  44. package/dist/lib/controller/storeCache.d.ts.map +1 -1
  45. package/dist/lib/{capability.d.ts → core/capability.d.ts} +1 -1
  46. package/dist/lib/core/capability.d.ts.map +1 -0
  47. package/dist/lib/{module.d.ts → core/module.d.ts} +2 -2
  48. package/dist/lib/core/module.d.ts.map +1 -0
  49. package/dist/lib/core/queue.d.ts.map +1 -0
  50. package/dist/lib/{schedule.d.ts → core/schedule.d.ts} +0 -1
  51. package/dist/lib/core/schedule.d.ts.map +1 -0
  52. package/dist/lib/{storage.d.ts → core/storage.d.ts} +4 -4
  53. package/dist/lib/core/storage.d.ts.map +1 -0
  54. package/dist/lib/deploymentChecks.d.ts.map +1 -1
  55. package/dist/lib/errors.d.ts +0 -5
  56. package/dist/lib/errors.d.ts.map +1 -1
  57. package/dist/lib/filesystemService.d.ts.map +1 -1
  58. package/dist/lib/filter/adjudicators/adjudicators.d.ts +5 -4
  59. package/dist/lib/filter/adjudicators/adjudicators.d.ts.map +1 -1
  60. package/dist/lib/filter/filter.d.ts +33 -1
  61. package/dist/lib/filter/filter.d.ts.map +1 -1
  62. package/dist/lib/finalizer.d.ts.map +1 -1
  63. package/dist/lib/helpers.d.ts +4 -9
  64. package/dist/lib/helpers.d.ts.map +1 -1
  65. package/dist/lib/included-files.d.ts.map +1 -1
  66. package/dist/lib/mutate-request.d.ts +2 -2
  67. package/dist/lib/mutate-request.d.ts.map +1 -1
  68. package/dist/lib/processors/mutate-processor.d.ts +28 -0
  69. package/dist/lib/processors/mutate-processor.d.ts.map +1 -0
  70. package/dist/lib/processors/validate-processor.d.ts +9 -0
  71. package/dist/lib/processors/validate-processor.d.ts.map +1 -0
  72. package/dist/lib/{watch-processor.d.ts → processors/watch-processor.d.ts} +2 -2
  73. package/dist/lib/processors/watch-processor.d.ts.map +1 -0
  74. package/dist/lib/telemetry/logger.d.ts.map +1 -1
  75. package/dist/lib/telemetry/metrics.d.ts.map +1 -1
  76. package/dist/lib/utils.d.ts.map +1 -1
  77. package/dist/lib/validate-request.d.ts +2 -2
  78. package/dist/lib/validate-request.d.ts.map +1 -1
  79. package/dist/lib.d.ts +2 -2
  80. package/dist/lib.d.ts.map +1 -1
  81. package/dist/lib.js +508 -341
  82. package/dist/lib.js.map +4 -4
  83. package/dist/sdk/heredoc.d.ts.map +1 -1
  84. package/package.json +9 -9
  85. package/src/cli/build.helpers.ts +180 -0
  86. package/src/cli/build.ts +85 -133
  87. package/src/cli/deploy.ts +113 -74
  88. package/src/cli/dev.ts +2 -2
  89. package/src/cli/format.helpers.ts +27 -0
  90. package/src/cli/format.ts +4 -18
  91. package/src/cli/init/enums.ts +9 -0
  92. package/src/cli/init/index.ts +4 -3
  93. package/src/cli/init/templates.ts +30 -2
  94. package/src/cli/init/utils.ts +3 -3
  95. package/src/cli/init/walkthrough.ts +7 -8
  96. package/src/cli/kfc.ts +1 -1
  97. package/src/cli/monitor.ts +108 -65
  98. package/src/cli/root.ts +1 -1
  99. package/src/cli/update.ts +1 -1
  100. package/src/cli/uuid.ts +1 -1
  101. package/src/fixtures/loader.ts +2 -2
  102. package/src/lib/assets/deploy.ts +11 -11
  103. package/src/lib/assets/destroy.ts +1 -1
  104. package/src/lib/assets/helm.ts +6 -6
  105. package/src/lib/assets/index.ts +23 -23
  106. package/src/lib/assets/pods.ts +11 -6
  107. package/src/lib/assets/webhooks.ts +31 -46
  108. package/src/lib/assets/yaml.ts +12 -9
  109. package/src/lib/controller/index.ts +13 -11
  110. package/src/lib/controller/store.ts +25 -12
  111. package/src/lib/controller/storeCache.ts +16 -3
  112. package/src/lib/{capability.ts → core/capability.ts} +25 -14
  113. package/src/lib/{module.ts → core/module.ts} +10 -10
  114. package/src/lib/{queue.ts → core/queue.ts} +13 -5
  115. package/src/lib/{storage.ts → core/storage.ts} +33 -24
  116. package/src/lib/deploymentChecks.ts +2 -2
  117. package/src/lib/errors.ts +3 -8
  118. package/src/lib/filesystemService.ts +1 -1
  119. package/src/lib/filter/adjudicators/adjudicators.ts +40 -9
  120. package/src/lib/filter/filter.ts +204 -111
  121. package/src/lib/finalizer.ts +2 -2
  122. package/src/lib/helpers.ts +20 -133
  123. package/src/lib/included-files.ts +1 -1
  124. package/src/lib/mutate-request.ts +11 -11
  125. package/src/lib/processors/mutate-processor.ts +225 -0
  126. package/src/lib/processors/validate-processor.ts +93 -0
  127. package/src/lib/{watch-processor.ts → processors/watch-processor.ts} +19 -15
  128. package/src/lib/telemetry/logger.ts +3 -1
  129. package/src/lib/tls.ts +5 -1
  130. package/src/lib/utils.ts +5 -5
  131. package/src/lib/validate-request.ts +4 -4
  132. package/src/lib.ts +2 -2
  133. package/src/runtime/controller.ts +2 -2
  134. package/src/sdk/cosign.ts +4 -4
  135. package/src/sdk/heredoc.ts +1 -1
  136. package/dist/lib/capability.d.ts.map +0 -1
  137. package/dist/lib/module.d.ts.map +0 -1
  138. package/dist/lib/mutate-processor.d.ts +0 -6
  139. package/dist/lib/mutate-processor.d.ts.map +0 -1
  140. package/dist/lib/queue.d.ts.map +0 -1
  141. package/dist/lib/schedule.d.ts.map +0 -1
  142. package/dist/lib/storage.d.ts.map +0 -1
  143. package/dist/lib/validate-processor.d.ts +0 -6
  144. package/dist/lib/validate-processor.d.ts.map +0 -1
  145. package/dist/lib/watch-processor.d.ts.map +0 -1
  146. package/src/lib/mutate-processor.ts +0 -165
  147. package/src/lib/validate-processor.ts +0 -85
  148. /package/dist/lib/{queue.d.ts → core/queue.d.ts} +0 -0
  149. /package/src/lib/{schedule.ts → core/schedule.ts} +0 -0
package/dist/lib.js CHANGED
@@ -6,8 +6,8 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
8
  var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
9
+ for (var name2 in all)
10
+ __defProp(target, name2, { get: all[name2], enumerable: true });
11
11
  };
12
12
  var __copyProps = (to, from, except, desc) => {
13
13
  if (from && typeof from === "object" || typeof from === "function") {
@@ -49,9 +49,9 @@ module.exports = __toCommonJS(lib_exports);
49
49
  var import_kubernetes_fluent_client8 = require("kubernetes-fluent-client");
50
50
  var R = __toESM(require("ramda"));
51
51
 
52
- // src/lib/capability.ts
53
- var import_kubernetes_fluent_client7 = require("kubernetes-fluent-client");
54
- var import_ramda7 = require("ramda");
52
+ // src/lib/core/capability.ts
53
+ var import_kubernetes_fluent_client6 = require("kubernetes-fluent-client");
54
+ var import_ramda8 = require("ramda");
55
55
 
56
56
  // src/lib/telemetry/logger.ts
57
57
  var import_pino = require("pino");
@@ -101,8 +101,8 @@ function redactedPatch(patch = {}) {
101
101
  }
102
102
  var logger_default = Log;
103
103
 
104
- // src/lib/module.ts
105
- var import_ramda5 = require("ramda");
104
+ // src/lib/core/module.ts
105
+ var import_ramda6 = require("ramda");
106
106
 
107
107
  // src/lib/controller/index.ts
108
108
  var import_express = __toESM(require("express"));
@@ -142,34 +142,34 @@ var MetricsCollector = class {
142
142
  this.addGauge(this.#metricNames.cacheMiss, "Number of cache misses per window", ["window"]);
143
143
  this.addGauge(this.#metricNames.resyncFailureCount, "Number of failures per resync operation", ["count"]);
144
144
  }
145
- #getMetricName = (name) => `${this.#prefix}_${name}`;
146
- #addMetric = (collection, MetricType, name, help, labelNames) => {
147
- if (collection.has(this.#getMetricName(name))) {
148
- logger_default.debug(`Metric for ${name} already exists`, loggingPrefix);
145
+ #getMetricName = (name2) => `${this.#prefix}_${name2}`;
146
+ #addMetric = (collection, MetricType, name2, help, labelNames) => {
147
+ if (collection.has(this.#getMetricName(name2))) {
148
+ logger_default.debug(`Metric for ${name2} already exists`, loggingPrefix);
149
149
  return;
150
150
  }
151
151
  const metric = new MetricType({
152
- name: this.#getMetricName(name),
152
+ name: this.#getMetricName(name2),
153
153
  help,
154
154
  registers: [this.#registry],
155
155
  labelNames
156
156
  });
157
- collection.set(this.#getMetricName(name), metric);
157
+ collection.set(this.#getMetricName(name2), metric);
158
158
  };
159
- addCounter = (name, help) => {
160
- this.#addMetric(this.#counters, import_prom_client.default.Counter, name, help, []);
159
+ addCounter = (name2, help) => {
160
+ this.#addMetric(this.#counters, import_prom_client.default.Counter, name2, help, []);
161
161
  };
162
- addSummary = (name, help) => {
163
- this.#addMetric(this.#summaries, import_prom_client.default.Summary, name, help, []);
162
+ addSummary = (name2, help) => {
163
+ this.#addMetric(this.#summaries, import_prom_client.default.Summary, name2, help, []);
164
164
  };
165
- addGauge = (name, help, labelNames) => {
166
- this.#addMetric(this.#gauges, import_prom_client.default.Gauge, name, help, labelNames);
165
+ addGauge = (name2, help, labelNames) => {
166
+ this.#addMetric(this.#gauges, import_prom_client.default.Gauge, name2, help, labelNames);
167
167
  };
168
- incCounter = (name) => {
169
- this.#counters.get(this.#getMetricName(name))?.inc();
168
+ incCounter = (name2) => {
169
+ this.#counters.get(this.#getMetricName(name2))?.inc();
170
170
  };
171
- incGauge = (name, labels, value = 1) => {
172
- this.#gauges.get(this.#getMetricName(name))?.inc(labels || {}, value);
171
+ incGauge = (name2, labels, value = 1) => {
172
+ this.#gauges.get(this.#getMetricName(name2))?.inc(labels || {}, value);
173
173
  };
174
174
  /**
175
175
  * Increments the error counter.
@@ -184,8 +184,8 @@ var MetricsCollector = class {
184
184
  * @param startTime - The start time.
185
185
  * @param name - The metrics summary to increment.
186
186
  */
187
- observeEnd = (startTime, name = this.#metricNames.mutate) => {
188
- this.#summaries.get(this.#getMetricName(name))?.observe(import_perf_hooks.performance.now() - startTime);
187
+ observeEnd = (startTime, name2 = this.#metricNames.mutate) => {
188
+ this.#summaries.get(this.#getMetricName(name2))?.observe(import_perf_hooks.performance.now() - startTime);
189
189
  };
190
190
  /**
191
191
  * Fetches the current metrics from the registry.
@@ -238,21 +238,9 @@ var MetricsCollector = class {
238
238
  };
239
239
  var metricsCollector = new MetricsCollector("pepr");
240
240
 
241
- // src/lib/mutate-processor.ts
241
+ // src/lib/processors/mutate-processor.ts
242
242
  var import_fast_json_patch = __toESM(require("fast-json-patch"));
243
-
244
- // src/lib/errors.ts
245
- var Errors = {
246
- audit: "audit",
247
- ignore: "ignore",
248
- reject: "reject"
249
- };
250
- var ErrorList = Object.values(Errors);
251
- function ValidateError(error = "") {
252
- if (!ErrorList.includes(error)) {
253
- throw new Error(`Invalid error: ${error}. Must be one of: ${ErrorList.join(", ")}`);
254
- }
255
- }
243
+ var import_ramda3 = require("ramda");
256
244
 
257
245
  // src/lib/filter/adjudicators/adjudicators.ts
258
246
  var import_ramda = require("ramda");
@@ -401,8 +389,15 @@ var mismatchedLabels = (0, import_ramda.allPass)([
401
389
  ]);
402
390
  var uncarryableNamespace = (0, import_ramda.allPass)([
403
391
  (0, import_ramda.pipe)((0, import_ramda.nthArg)(0), import_ramda.length, (0, import_ramda.gt)(import_ramda.__, 0)),
404
- (0, import_ramda.pipe)((0, import_ramda.nthArg)(1), carriesNamespace),
405
- (0, import_ramda.pipe)((namespaceSelector, kubernetesObject) => namespaceSelector.includes(carriedNamespace(kubernetesObject)), import_ramda.not)
392
+ (0, import_ramda.pipe)((namespaceSelector, kubernetesObject) => {
393
+ if (kubernetesObject?.kind === "Namespace") {
394
+ return namespaceSelector.includes(kubernetesObject?.metadata?.name);
395
+ }
396
+ if (carriesNamespace(kubernetesObject)) {
397
+ return namespaceSelector.includes(carriedNamespace(kubernetesObject));
398
+ }
399
+ return true;
400
+ }, import_ramda.not)
406
401
  ]);
407
402
  var missingCarriableNamespace = (0, import_ramda.allPass)([
408
403
  (0, import_ramda.pipe)((0, import_ramda.nthArg)(0), import_ramda.length, (0, import_ramda.gt)(import_ramda.__, 0)),
@@ -412,8 +407,15 @@ var missingCarriableNamespace = (0, import_ramda.allPass)([
412
407
  ]);
413
408
  var carriesIgnoredNamespace = (0, import_ramda.allPass)([
414
409
  (0, import_ramda.pipe)((0, import_ramda.nthArg)(0), import_ramda.length, (0, import_ramda.gt)(import_ramda.__, 0)),
415
- (0, import_ramda.pipe)((0, import_ramda.nthArg)(1), carriesNamespace),
416
- (0, import_ramda.pipe)((namespaceSelector, kubernetesObject) => namespaceSelector.includes(carriedNamespace(kubernetesObject)))
410
+ (0, import_ramda.pipe)((namespaceSelector, kubernetesObject) => {
411
+ if (kubernetesObject?.kind === "Namespace") {
412
+ return namespaceSelector.includes(kubernetesObject?.metadata?.name);
413
+ }
414
+ if (carriesNamespace(kubernetesObject)) {
415
+ return namespaceSelector.includes(carriedNamespace(kubernetesObject));
416
+ }
417
+ return false;
418
+ })
417
419
  ]);
418
420
  var unbindableNamespaces = (0, import_ramda.allPass)([
419
421
  (0, import_ramda.pipe)((0, import_ramda.nthArg)(0), import_ramda.length, (0, import_ramda.gt)(import_ramda.__, 0)),
@@ -450,9 +452,108 @@ var mismatchedKind = (0, import_ramda.allPass)([
450
452
 
451
453
  // src/lib/filter/filter.ts
452
454
  function shouldSkipRequest(binding, req, capabilityNamespaces, ignoredNamespaces) {
453
- const prefix = "Ignoring Admission Callback:";
454
455
  const obj = req.operation === "DELETE" /* DELETE */ ? req.oldObject : req.object;
455
- return misboundDeleteWithDeletionTimestamp(binding) ? `${prefix} Cannot use deletionTimestamp filter on a DELETE operation.` : mismatchedDeletionTimestamp(binding, obj) ? `${prefix} Binding defines deletionTimestamp but Object does not carry it.` : mismatchedEvent(binding, req) ? `${prefix} Binding defines event '${definedEvent(binding)}' but Request declares '${declaredOperation(req)}'.` : mismatchedName(binding, obj) ? `${prefix} Binding defines name '${definedName(binding)}' but Object carries '${carriedName(obj)}'.` : mismatchedGroup(binding, req) ? `${prefix} Binding defines group '${definedGroup(binding)}' but Request declares '${declaredGroup(req)}'.` : mismatchedVersion(binding, req) ? `${prefix} Binding defines version '${definedVersion(binding)}' but Request declares '${declaredVersion(req)}'.` : mismatchedKind(binding, req) ? `${prefix} Binding defines kind '${definedKind(binding)}' but Request declares '${declaredKind(req)}'.` : unbindableNamespaces(capabilityNamespaces, binding) ? `${prefix} Binding defines namespaces ${JSON.stringify(definedNamespaces(binding))} but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespaces)}'.` : uncarryableNamespace(capabilityNamespaces, obj) ? `${prefix} Object carries namespace '${carriedNamespace(obj)}' but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespaces)}'.` : mismatchedNamespace(binding, obj) ? `${prefix} Binding defines namespaces '${JSON.stringify(definedNamespaces(binding))}' but Object carries '${carriedNamespace(obj)}'.` : mismatchedLabels(binding, obj) ? `${prefix} Binding defines labels '${JSON.stringify(definedLabels(binding))}' but Object carries '${JSON.stringify(carriedLabels(obj))}'.` : mismatchedAnnotations(binding, obj) ? `${prefix} Binding defines annotations '${JSON.stringify(definedAnnotations(binding))}' but Object carries '${JSON.stringify(carriedAnnotations(obj))}'.` : mismatchedNamespaceRegex(binding, obj) ? `${prefix} Binding defines namespace regexes '${JSON.stringify(definedNamespaceRegexes(binding))}' but Object carries '${carriedNamespace(obj)}'.` : mismatchedNameRegex(binding, obj) ? `${prefix} Binding defines name regex '${definedNameRegex(binding)}' but Object carries '${carriedName(obj)}'.` : carriesIgnoredNamespace(ignoredNamespaces, obj) ? `${prefix} Object carries namespace '${carriedNamespace(obj)}' but ignored namespaces include '${JSON.stringify(ignoredNamespaces)}'.` : missingCarriableNamespace(capabilityNamespaces, obj) ? `${prefix} Object does not carry a namespace but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespaces)}'.` : "";
456
+ const prefix = "Ignoring Admission Callback:";
457
+ const adjudicators = [
458
+ () => adjudicateMisboundDeleteWithDeletionTimestamp(binding),
459
+ () => adjudicateMismatchedDeletionTimestamp(binding, obj),
460
+ () => adjudicateMismatchedEvent(binding, req),
461
+ () => adjudicateMismatchedName(binding, obj),
462
+ () => adjudicateMismatchedGroup(binding, req),
463
+ () => adjudicateMismatchedVersion(binding, req),
464
+ () => adjudicateMismatchedKind(binding, req),
465
+ () => adjudicateUnbindableNamespaces(capabilityNamespaces, binding),
466
+ () => adjudicateUncarryableNamespace(capabilityNamespaces, obj),
467
+ () => adjudicateMismatchedNamespace(binding, obj),
468
+ () => adjudicateMismatchedLabels(binding, obj),
469
+ () => adjudicateMismatchedAnnotations(binding, obj),
470
+ () => adjudicateMismatchedNamespaceRegex(binding, obj),
471
+ () => adjudicateMismatchedNameRegex(binding, obj),
472
+ () => adjudicateCarriesIgnoredNamespace(ignoredNamespaces, obj),
473
+ () => adjudicateMissingCarriableNamespace(capabilityNamespaces, obj)
474
+ ];
475
+ for (const adjudicator of adjudicators) {
476
+ const result = adjudicator();
477
+ if (result) {
478
+ return `${prefix} ${result}`;
479
+ }
480
+ }
481
+ return "";
482
+ }
483
+ function filterNoMatchReason(binding, obj, capabilityNamespaces, ignoredNamespaces) {
484
+ const prefix = "Ignoring Watch Callback:";
485
+ const adjudicators = [
486
+ () => adjudicateMismatchedDeletionTimestamp(binding, obj),
487
+ () => adjudicateMismatchedName(binding, obj),
488
+ () => adjudicateMisboundNamespace(binding),
489
+ () => adjudicateMismatchedLabels(binding, obj),
490
+ () => adjudicateMismatchedAnnotations(binding, obj),
491
+ () => adjudicateUncarryableNamespace(capabilityNamespaces, obj),
492
+ () => adjudicateUnbindableNamespaces(capabilityNamespaces, binding),
493
+ () => adjudicateMismatchedNamespace(binding, obj),
494
+ () => adjudicateMismatchedNamespaceRegex(binding, obj),
495
+ () => adjudicateMismatchedNameRegex(binding, obj),
496
+ () => adjudicateCarriesIgnoredNamespace(ignoredNamespaces, obj),
497
+ () => adjudicateMissingCarriableNamespace(capabilityNamespaces, obj)
498
+ ];
499
+ for (const adjudicator of adjudicators) {
500
+ const result = adjudicator();
501
+ if (result) {
502
+ return `${prefix} ${result}`;
503
+ }
504
+ }
505
+ return "";
506
+ }
507
+ function adjudicateMisboundNamespace(binding) {
508
+ return misboundNamespace(binding) ? "Cannot use namespace filter on a namespace object." : null;
509
+ }
510
+ function adjudicateMisboundDeleteWithDeletionTimestamp(binding) {
511
+ return misboundDeleteWithDeletionTimestamp(binding) ? "Cannot use deletionTimestamp filter on a DELETE operation." : null;
512
+ }
513
+ function adjudicateMismatchedDeletionTimestamp(binding, obj) {
514
+ return mismatchedDeletionTimestamp(binding, obj) ? "Binding defines deletionTimestamp but Object does not carry it." : null;
515
+ }
516
+ function adjudicateMismatchedEvent(binding, req) {
517
+ return mismatchedEvent(binding, req) ? `Binding defines event '${definedEvent(binding)}' but Request declares '${declaredOperation(req)}'.` : null;
518
+ }
519
+ function adjudicateMismatchedName(binding, obj) {
520
+ return mismatchedName(binding, obj) ? `Binding defines name '${definedName(binding)}' but Object carries '${carriedName(obj)}'.` : null;
521
+ }
522
+ function adjudicateMismatchedGroup(binding, req) {
523
+ return mismatchedGroup(binding, req) ? `Binding defines group '${definedGroup(binding)}' but Request declares '${declaredGroup(req)}'.` : null;
524
+ }
525
+ function adjudicateMismatchedVersion(binding, req) {
526
+ return mismatchedVersion(binding, req) ? `Binding defines version '${definedVersion(binding)}' but Request declares '${declaredVersion(req)}'.` : null;
527
+ }
528
+ function adjudicateMismatchedKind(binding, req) {
529
+ return mismatchedKind(binding, req) ? `Binding defines kind '${definedKind(binding)}' but Request declares '${declaredKind(req)}'.` : null;
530
+ }
531
+ function adjudicateUnbindableNamespaces(capabilityNamespaces, binding) {
532
+ return unbindableNamespaces(capabilityNamespaces, binding) ? `Binding defines namespaces ${JSON.stringify(definedNamespaces(binding))} but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespaces)}'.` : null;
533
+ }
534
+ function adjudicateUncarryableNamespace(capabilityNamespaces, obj) {
535
+ return uncarryableNamespace(capabilityNamespaces, obj) ? `Object carries namespace '${obj.kind && obj.kind === "Namespace" ? obj.metadata?.name : carriedNamespace(obj)}' but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespaces)}'.` : null;
536
+ }
537
+ function adjudicateMismatchedNamespace(binding, obj) {
538
+ return mismatchedNamespace(binding, obj) ? `Binding defines namespaces '${JSON.stringify(definedNamespaces(binding))}' but Object carries '${carriedNamespace(obj)}'.` : null;
539
+ }
540
+ function adjudicateMismatchedLabels(binding, obj) {
541
+ return mismatchedLabels(binding, obj) ? `Binding defines labels '${JSON.stringify(definedLabels(binding))}' but Object carries '${JSON.stringify(carriedLabels(obj))}'.` : null;
542
+ }
543
+ function adjudicateMismatchedAnnotations(binding, obj) {
544
+ return mismatchedAnnotations(binding, obj) ? `Binding defines annotations '${JSON.stringify(definedAnnotations(binding))}' but Object carries '${JSON.stringify(carriedAnnotations(obj))}'.` : null;
545
+ }
546
+ function adjudicateMismatchedNamespaceRegex(binding, obj) {
547
+ return mismatchedNamespaceRegex(binding, obj) ? `Binding defines namespace regexes '${JSON.stringify(definedNamespaceRegexes(binding))}' but Object carries '${carriedNamespace(obj)}'.` : null;
548
+ }
549
+ function adjudicateMismatchedNameRegex(binding, obj) {
550
+ return mismatchedNameRegex(binding, obj) ? `Binding defines name regex '${definedNameRegex(binding)}' but Object carries '${carriedName(obj)}'.` : null;
551
+ }
552
+ function adjudicateCarriesIgnoredNamespace(ignoredNamespaces, obj) {
553
+ return carriesIgnoredNamespace(ignoredNamespaces, obj) ? `Object carries namespace '${obj.kind && obj.kind === "Namespace" ? obj.metadata?.name : carriedNamespace(obj)}' but ignored namespaces include '${JSON.stringify(ignoredNamespaces)}'.` : null;
554
+ }
555
+ function adjudicateMissingCarriableNamespace(capabilityNamespaces, obj) {
556
+ return missingCarriableNamespace(capabilityNamespaces, obj) ? `Object does not carry a namespace but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespaces)}'.` : null;
456
557
  }
457
558
 
458
559
  // src/lib/mutate-request.ts
@@ -562,80 +663,126 @@ function base64Encode(data) {
562
663
  return Buffer.from(data).toString("base64");
563
664
  }
564
665
 
565
- // src/lib/mutate-processor.ts
666
+ // src/cli/init/enums.ts
667
+ var OnError = /* @__PURE__ */ ((OnError2) => {
668
+ OnError2["AUDIT"] = "audit";
669
+ OnError2["IGNORE"] = "ignore";
670
+ OnError2["REJECT"] = "reject";
671
+ return OnError2;
672
+ })(OnError || {});
673
+
674
+ // src/lib/processors/mutate-processor.ts
675
+ function updateStatus(config, name2, wrapped, status) {
676
+ if (wrapped.Request.operation === "DELETE") {
677
+ return wrapped;
678
+ }
679
+ wrapped.SetAnnotation(`${config.uuid}.pepr.dev/${name2}`, status);
680
+ return wrapped;
681
+ }
682
+ function logMutateErrorMessage(e) {
683
+ try {
684
+ if (e.message && e.message !== "[object Object]") {
685
+ return e.message;
686
+ } else {
687
+ throw new Error("An error occurred in the mutate action.");
688
+ }
689
+ } catch (e2) {
690
+ return "An error occurred with the mutate action.";
691
+ }
692
+ }
693
+ function decodeData(wrapped) {
694
+ let skipped = [];
695
+ const isSecret = wrapped.Request.kind.version === "v1" && wrapped.Request.kind.kind === "Secret";
696
+ if (isSecret) {
697
+ skipped = convertFromBase64Map(wrapped.Raw);
698
+ }
699
+ return { skipped, wrapped };
700
+ }
701
+ function reencodeData(wrapped, skipped) {
702
+ const transformed = (0, import_ramda3.clone)(wrapped.Raw);
703
+ const isSecret = wrapped.Request.kind.version === "v1" && wrapped.Request.kind.kind === "Secret";
704
+ if (isSecret) {
705
+ convertToBase64Map(transformed, skipped);
706
+ }
707
+ return transformed;
708
+ }
709
+ async function processRequest(bindable, wrapped, response) {
710
+ const { binding, actMeta, name: name2, config } = bindable;
711
+ const label = binding.mutateCallback.name;
712
+ logger_default.info(actMeta, `Processing mutation action (${label})`);
713
+ wrapped = updateStatus(config, name2, wrapped, "started");
714
+ try {
715
+ await binding.mutateCallback(wrapped);
716
+ logger_default.info(actMeta, `Mutation action succeeded (${label})`);
717
+ wrapped = updateStatus(config, name2, wrapped, "succeeded");
718
+ } catch (e) {
719
+ wrapped = updateStatus(config, name2, wrapped, "warning");
720
+ response.warnings = response.warnings || [];
721
+ const errorMessage = logMutateErrorMessage(e);
722
+ logger_default.error(actMeta, `Action failed: ${errorMessage}`);
723
+ response.warnings.push(`Action failed: ${errorMessage}`);
724
+ switch (config.onError) {
725
+ case "reject" /* REJECT */:
726
+ response.result = "Pepr module configured to reject on error";
727
+ break;
728
+ case "audit" /* AUDIT */:
729
+ response.auditAnnotations = response.auditAnnotations || {};
730
+ response.auditAnnotations[Date.now()] = `Action failed: ${errorMessage}`;
731
+ break;
732
+ }
733
+ }
734
+ return { wrapped, response };
735
+ }
566
736
  async function mutateProcessor(config, capabilities, req, reqMetadata) {
567
- const wrapped = new PeprMutateRequest(req);
568
- const response = {
737
+ let response = {
569
738
  uid: req.uid,
570
739
  warnings: [],
571
740
  allowed: false
572
741
  };
573
- let matchedAction = false;
574
- let skipDecode = [];
575
- const isSecret = req.kind.version === "v1" && req.kind.kind === "Secret";
576
- if (isSecret) {
577
- skipDecode = convertFromBase64Map(wrapped.Raw);
578
- }
742
+ const decoded = decodeData(new PeprMutateRequest(req));
743
+ let wrapped = decoded.wrapped;
579
744
  logger_default.info(reqMetadata, `Processing request`);
580
- for (const { name, bindings, namespaces } of capabilities) {
581
- const actionMetadata = { ...reqMetadata, name };
582
- for (const action of bindings) {
583
- if (!action.mutateCallback) {
584
- continue;
585
- }
586
- const shouldSkip = shouldSkipRequest(action, req, namespaces, config?.alwaysIgnore?.namespaces);
587
- if (shouldSkip !== "") {
588
- logger_default.debug(shouldSkip);
589
- continue;
590
- }
591
- const label = action.mutateCallback.name;
592
- logger_default.info(actionMetadata, `Processing mutation action (${label})`);
593
- matchedAction = true;
594
- const updateStatus = (status) => {
595
- if (req.operation === "DELETE") {
596
- return;
597
- }
598
- const identifier = `${config.uuid}.pepr.dev/${name}`;
599
- wrapped.Raw.metadata = wrapped.Raw.metadata || {};
600
- wrapped.Raw.metadata.annotations = wrapped.Raw.metadata.annotations || {};
601
- wrapped.Raw.metadata.annotations[identifier] = status;
602
- };
603
- updateStatus("started");
604
- try {
605
- await action.mutateCallback(wrapped);
606
- logger_default.info(actionMetadata, `Mutation action succeeded (${label})`);
607
- updateStatus("succeeded");
608
- } catch (e) {
609
- updateStatus("warning");
610
- response.warnings = response.warnings || [];
611
- const errorMessage = logMutateErrorMessage(e);
612
- logger_default.error(actionMetadata, `Action failed: ${errorMessage}`);
613
- response.warnings.push(`Action failed: ${errorMessage}`);
614
- switch (config.onError) {
615
- case Errors.reject:
616
- logger_default.error(actionMetadata, `Action failed: ${errorMessage}`);
617
- response.result = "Pepr module configured to reject on error";
618
- return response;
619
- case Errors.audit:
620
- response.auditAnnotations = response.auditAnnotations || {};
621
- response.auditAnnotations[Date.now()] = `Action failed: ${errorMessage}`;
622
- break;
623
- }
624
- }
745
+ let bindables = capabilities.flatMap(
746
+ (capa) => capa.bindings.map((bind) => ({
747
+ req,
748
+ config,
749
+ name: capa.name,
750
+ namespaces: capa.namespaces,
751
+ binding: bind,
752
+ actMeta: { ...reqMetadata, name: capa.name }
753
+ }))
754
+ );
755
+ bindables = bindables.filter((bind) => {
756
+ if (!bind.binding.mutateCallback) {
757
+ return false;
758
+ }
759
+ const shouldSkip = shouldSkipRequest(
760
+ bind.binding,
761
+ bind.req,
762
+ bind.namespaces,
763
+ bind.config?.alwaysIgnore?.namespaces
764
+ );
765
+ if (shouldSkip !== "") {
766
+ logger_default.debug(shouldSkip);
767
+ return false;
768
+ }
769
+ return true;
770
+ });
771
+ for (const bindable of bindables) {
772
+ ({ wrapped, response } = await processRequest(bindable, wrapped, response));
773
+ if (config.onError === "reject" /* REJECT */ && response?.warnings.length > 0) {
774
+ return response;
625
775
  }
626
776
  }
627
777
  response.allowed = true;
628
- if (!matchedAction) {
778
+ if (bindables.length === 0) {
629
779
  logger_default.info(reqMetadata, `No matching actions found`);
630
780
  return response;
631
781
  }
632
782
  if (req.operation === "DELETE") {
633
783
  return response;
634
784
  }
635
- const transformed = wrapped.Raw;
636
- if (isSecret) {
637
- convertToBase64Map(transformed, skipDecode);
638
- }
785
+ const transformed = reencodeData(wrapped, decoded.skipped);
639
786
  const patches = import_fast_json_patch.default.compare(req.object, transformed);
640
787
  if (patches.length > 0) {
641
788
  response.patchType = "JSONPatch";
@@ -647,20 +794,9 @@ async function mutateProcessor(config, capabilities, req, reqMetadata) {
647
794
  logger_default.debug({ ...reqMetadata, patches }, `Patches generated`);
648
795
  return response;
649
796
  }
650
- var logMutateErrorMessage = (e) => {
651
- try {
652
- if (e.message && e.message !== "[object Object]") {
653
- return e.message;
654
- } else {
655
- throw new Error("An error occurred in the mutate action.");
656
- }
657
- } catch (e2) {
658
- return "An error occurred with the mutate action.";
659
- }
660
- };
661
797
 
662
798
  // src/lib/validate-request.ts
663
- var import_ramda3 = require("ramda");
799
+ var import_ramda4 = require("ramda");
664
800
  var PeprValidateRequest = class {
665
801
  Raw;
666
802
  #input;
@@ -685,9 +821,9 @@ var PeprValidateRequest = class {
685
821
  constructor(input) {
686
822
  this.#input = input;
687
823
  if (input.operation.toUpperCase() === "DELETE" /* DELETE */) {
688
- this.Raw = (0, import_ramda3.clone)(input.oldObject);
824
+ this.Raw = (0, import_ramda4.clone)(input.oldObject);
689
825
  } else {
690
- this.Raw = (0, import_ramda3.clone)(input.object);
826
+ this.Raw = (0, import_ramda4.clone)(input.object);
691
827
  }
692
828
  if (!this.Raw) {
693
829
  throw new Error("unable to load the request object into PeprRequest.Raw");
@@ -737,7 +873,36 @@ var PeprValidateRequest = class {
737
873
  };
738
874
  };
739
875
 
740
- // src/lib/validate-processor.ts
876
+ // src/lib/processors/validate-processor.ts
877
+ async function processRequest2(binding, actionMetadata, peprValidateRequest) {
878
+ const label = binding.validateCallback.name;
879
+ logger_default.info(actionMetadata, `Processing validation action (${label})`);
880
+ const valResp = {
881
+ uid: peprValidateRequest.Request.uid,
882
+ allowed: true
883
+ // Assume it's allowed until a validation check fails
884
+ };
885
+ try {
886
+ const callbackResp = await binding.validateCallback(peprValidateRequest);
887
+ valResp.allowed = callbackResp.allowed;
888
+ if (callbackResp.statusCode || callbackResp.statusMessage) {
889
+ valResp.status = {
890
+ code: callbackResp.statusCode || 400,
891
+ message: callbackResp.statusMessage || `Validation failed for ${name}`
892
+ };
893
+ }
894
+ logger_default.info(actionMetadata, `Validation action complete (${label}): ${callbackResp.allowed ? "allowed" : "denied"}`);
895
+ return valResp;
896
+ } catch (e) {
897
+ logger_default.error(actionMetadata, `Action failed: ${JSON.stringify(e)}`);
898
+ valResp.allowed = false;
899
+ valResp.status = {
900
+ code: 500,
901
+ message: `Action failed with error: ${JSON.stringify(e)}`
902
+ };
903
+ return valResp;
904
+ }
905
+ }
741
906
  async function validateProcessor(config, capabilities, req, reqMetadata) {
742
907
  const wrapped = new PeprValidateRequest(req);
743
908
  const response = [];
@@ -746,44 +911,19 @@ async function validateProcessor(config, capabilities, req, reqMetadata) {
746
911
  convertFromBase64Map(wrapped.Raw);
747
912
  }
748
913
  logger_default.info(reqMetadata, `Processing validation request`);
749
- for (const { name, bindings, namespaces } of capabilities) {
750
- const actionMetadata = { ...reqMetadata, name };
751
- for (const action of bindings) {
752
- if (!action.validateCallback) {
914
+ for (const { name: name2, bindings, namespaces } of capabilities) {
915
+ const actionMetadata = { ...reqMetadata, name: name2 };
916
+ for (const binding of bindings) {
917
+ if (!binding.validateCallback) {
753
918
  continue;
754
919
  }
755
- const localResponse = {
756
- uid: req.uid,
757
- allowed: true
758
- // Assume it's allowed until a validation check fails
759
- };
760
- const shouldSkip = shouldSkipRequest(action, req, namespaces, config?.alwaysIgnore?.namespaces);
920
+ const shouldSkip = shouldSkipRequest(binding, req, namespaces, config?.alwaysIgnore?.namespaces);
761
921
  if (shouldSkip !== "") {
762
922
  logger_default.debug(shouldSkip);
763
923
  continue;
764
924
  }
765
- const label = action.validateCallback.name;
766
- logger_default.info(actionMetadata, `Processing validation action (${label})`);
767
- try {
768
- const resp = await action.validateCallback(wrapped);
769
- localResponse.allowed = resp.allowed;
770
- if (resp.statusCode || resp.statusMessage) {
771
- localResponse.status = {
772
- code: resp.statusCode || 400,
773
- message: resp.statusMessage || `Validation failed for ${name}`
774
- };
775
- }
776
- logger_default.info(actionMetadata, `Validation action complete (${label}): ${resp.allowed ? "allowed" : "denied"}`);
777
- } catch (e) {
778
- logger_default.error(actionMetadata, `Action failed: ${JSON.stringify(e)}`);
779
- localResponse.allowed = false;
780
- localResponse.status = {
781
- code: 500,
782
- message: `Action failed with error: ${JSON.stringify(e)}`
783
- };
784
- return [localResponse];
785
- }
786
- response.push(localResponse);
925
+ const resp = await processRequest2(binding, actionMetadata, wrapped);
926
+ response.push(resp);
787
927
  }
788
928
  }
789
929
  return response;
@@ -791,7 +931,7 @@ async function validateProcessor(config, capabilities, req, reqMetadata) {
791
931
 
792
932
  // src/lib/controller/store.ts
793
933
  var import_kubernetes_fluent_client3 = require("kubernetes-fluent-client");
794
- var import_ramda4 = require("ramda");
934
+ var import_ramda5 = require("ramda");
795
935
 
796
936
  // src/lib/k8s.ts
797
937
  var import_kubernetes_fluent_client = require("kubernetes-fluent-client");
@@ -807,12 +947,12 @@ var peprStoreGVK = {
807
947
  // src/lib/controller/storeCache.ts
808
948
  var import_kubernetes_fluent_client2 = require("kubernetes-fluent-client");
809
949
  var import_http_status_codes = require("http-status-codes");
810
- var sendUpdatesAndFlushCache = async (cache, namespace2, name) => {
950
+ var sendUpdatesAndFlushCache = async (cache, namespace2, name2) => {
811
951
  const indexes = Object.keys(cache);
812
952
  const payload = Object.values(cache);
813
953
  try {
814
954
  if (payload.length > 0) {
815
- await (0, import_kubernetes_fluent_client2.K8s)(Store, { namespace: namespace2, name }).Patch(payload);
955
+ await (0, import_kubernetes_fluent_client2.K8s)(Store, { namespace: namespace2, name: name2 }).Patch(updateCacheID(payload));
816
956
  Object.keys(cache).forEach((key) => delete cache[key]);
817
957
  }
818
958
  } catch (err) {
@@ -844,32 +984,41 @@ var fillStoreCache = (cache, capabilityName, op, cacheItem) => {
844
984
  }
845
985
  return cache;
846
986
  };
987
+ function updateCacheID(payload) {
988
+ payload.push({
989
+ op: "replace",
990
+ path: "/metadata/labels/pepr.dev-cacheID",
991
+ value: `${Date.now()}`
992
+ });
993
+ return payload;
994
+ }
847
995
 
848
996
  // src/lib/controller/store.ts
849
997
  var namespace = "pepr-system";
850
- var debounceBackoff = 1e3;
998
+ var debounceBackoffReceive = 1e3;
999
+ var debounceBackoffSend = 4e3;
851
1000
  var StoreController = class {
852
1001
  #name;
853
1002
  #stores = {};
854
1003
  #sendDebounce;
855
1004
  #onReady;
856
- constructor(capabilities, name, onReady) {
1005
+ constructor(capabilities, name2, onReady) {
857
1006
  this.#onReady = onReady;
858
- this.#name = name;
859
- const setStorageInstance = (registrationFunction, name2) => {
1007
+ this.#name = name2;
1008
+ const setStorageInstance = (registrationFunction, name3) => {
860
1009
  const scheduleStore = registrationFunction();
861
- scheduleStore.registerSender(this.#send(name2));
862
- this.#stores[name2] = scheduleStore;
1010
+ scheduleStore.registerSender(this.#send(name3));
1011
+ this.#stores[name3] = scheduleStore;
863
1012
  };
864
- if (name.includes("schedule")) {
865
- for (const { name: name2, registerScheduleStore, hasSchedule } of capabilities) {
1013
+ if (name2.includes("schedule")) {
1014
+ for (const { name: name3, registerScheduleStore, hasSchedule } of capabilities) {
866
1015
  if (hasSchedule === true) {
867
- setStorageInstance(registerScheduleStore, name2);
1016
+ setStorageInstance(registerScheduleStore, name3);
868
1017
  }
869
1018
  }
870
1019
  } else {
871
- for (const { name: name2, registerStore } of capabilities) {
872
- setStorageInstance(registerStore, name2);
1020
+ for (const { name: name3, registerStore } of capabilities) {
1021
+ setStorageInstance(registerStore, name3);
873
1022
  }
874
1023
  }
875
1024
  setTimeout(
@@ -884,17 +1033,24 @@ var StoreController = class {
884
1033
  };
885
1034
  #migrateAndSetupWatch = async (store) => {
886
1035
  logger_default.debug(redactedStore(store), "Pepr Store migration");
1036
+ await (0, import_kubernetes_fluent_client3.K8s)(Store, { namespace, name: this.#name }).Patch([
1037
+ {
1038
+ op: "add",
1039
+ path: "/metadata/labels/pepr.dev-cacheID",
1040
+ value: `${Date.now()}`
1041
+ }
1042
+ ]);
887
1043
  const data = store.data || {};
888
1044
  let storeCache = {};
889
- for (const name of Object.keys(this.#stores)) {
890
- const offset = `${name}-`.length;
1045
+ for (const name2 of Object.keys(this.#stores)) {
1046
+ const offset = `${name2}-`.length;
891
1047
  for (const key of Object.keys(data)) {
892
- if ((0, import_ramda4.startsWith)(name, key) && !(0, import_ramda4.startsWith)(`${name}-v2`, key)) {
893
- storeCache = fillStoreCache(storeCache, name, "remove", {
1048
+ if ((0, import_ramda5.startsWith)(name2, key) && !(0, import_ramda5.startsWith)(`${name2}-v2`, key)) {
1049
+ storeCache = fillStoreCache(storeCache, name2, "remove", {
894
1050
  key: [key.slice(offset)],
895
1051
  value: data[key]
896
1052
  });
897
- storeCache = fillStoreCache(storeCache, name, "add", {
1053
+ storeCache = fillStoreCache(storeCache, name2, "add", {
898
1054
  key: [key.slice(offset)],
899
1055
  value: data[key],
900
1056
  version: "v2"
@@ -909,15 +1065,15 @@ var StoreController = class {
909
1065
  logger_default.debug(redactedStore(store), "Pepr Store update");
910
1066
  const debounced = () => {
911
1067
  const data = store.data || {};
912
- for (const name of Object.keys(this.#stores)) {
913
- const offset = `${name}-`.length;
1068
+ for (const name2 of Object.keys(this.#stores)) {
1069
+ const offset = `${name2}-`.length;
914
1070
  const filtered = {};
915
1071
  for (const key of Object.keys(data)) {
916
- if ((0, import_ramda4.startsWith)(name, key)) {
1072
+ if ((0, import_ramda5.startsWith)(name2, key)) {
917
1073
  filtered[key.slice(offset)] = data[key];
918
1074
  }
919
1075
  }
920
- this.#stores[name].receive(filtered);
1076
+ this.#stores[name2].receive(filtered);
921
1077
  }
922
1078
  if (this.#onReady) {
923
1079
  this.#onReady();
@@ -925,7 +1081,7 @@ var StoreController = class {
925
1081
  }
926
1082
  };
927
1083
  clearTimeout(this.#sendDebounce);
928
- this.#sendDebounce = setTimeout(debounced, this.#onReady ? 0 : debounceBackoff);
1084
+ this.#sendDebounce = setTimeout(debounced, this.#onReady ? 0 : debounceBackoffReceive);
929
1085
  };
930
1086
  #send = (capabilityName) => {
931
1087
  let storeCache = {};
@@ -937,7 +1093,7 @@ var StoreController = class {
937
1093
  logger_default.debug(redactedPatch(storeCache), "Sending updates to Pepr store");
938
1094
  void sendUpdatesAndFlushCache(storeCache, namespace, this.#name);
939
1095
  }
940
- }, debounceBackoff);
1096
+ }, debounceBackoffSend);
941
1097
  return sender;
942
1098
  };
943
1099
  #createStoreResource = async (e) => {
@@ -947,7 +1103,10 @@ var StoreController = class {
947
1103
  await (0, import_kubernetes_fluent_client3.K8s)(Store).Apply({
948
1104
  metadata: {
949
1105
  name: this.#name,
950
- namespace
1106
+ namespace,
1107
+ labels: {
1108
+ "pepr.dev-cacheID": `${Date.now()}`
1109
+ }
951
1110
  },
952
1111
  data: {
953
1112
  // JSON Patch will die if the data is empty, so we need to add a placeholder
@@ -1125,12 +1284,12 @@ var Controller = class _Controller {
1125
1284
  const startTime = MetricsCollector.observeStart();
1126
1285
  try {
1127
1286
  const request = req.body?.request || {};
1128
- const { name, namespace: namespace2, gvk } = {
1287
+ const { name: name2, namespace: namespace2, gvk } = {
1129
1288
  name: request?.name ? `/${request.name}` : "",
1130
1289
  namespace: request?.namespace || "",
1131
1290
  gvk: request?.kind || { group: "", version: "", kind: "" }
1132
1291
  };
1133
- const reqMetadata = { uid: request.uid, namespace: namespace2, name };
1292
+ const reqMetadata = { uid: request.uid, namespace: namespace2, name: name2 };
1134
1293
  logger_default.info({ ...reqMetadata, gvk, operation: request.operation, admissionKind }, "Incoming request");
1135
1294
  logger_default.debug({ ...reqMetadata, request }, "Incoming request body");
1136
1295
  this.#beforeHook && this.#beforeHook(request || {});
@@ -1192,131 +1351,26 @@ var Controller = class _Controller {
1192
1351
  }
1193
1352
  };
1194
1353
 
1195
- // src/lib/watch-processor.ts
1196
- var import_kubernetes_fluent_client6 = require("kubernetes-fluent-client");
1197
- var import_types = require("kubernetes-fluent-client/dist/fluent/types");
1198
-
1199
- // src/sdk/sdk.ts
1200
- var sdk_exports = {};
1201
- __export(sdk_exports, {
1202
- containers: () => containers,
1203
- getOwnerRefFrom: () => getOwnerRefFrom,
1204
- sanitizeResourceName: () => sanitizeResourceName,
1205
- writeEvent: () => writeEvent
1206
- });
1207
- var import_kubernetes_fluent_client4 = require("kubernetes-fluent-client");
1208
- function containers(request, containerType) {
1209
- const containers2 = request.Raw.spec?.containers || [];
1210
- const initContainers = request.Raw.spec?.initContainers || [];
1211
- const ephemeralContainers = request.Raw.spec?.ephemeralContainers || [];
1212
- if (containerType === "containers") {
1213
- return containers2;
1214
- }
1215
- if (containerType === "initContainers") {
1216
- return initContainers;
1217
- }
1218
- if (containerType === "ephemeralContainers") {
1219
- return ephemeralContainers;
1354
+ // src/lib/errors.ts
1355
+ var ErrorList = Object.values(OnError);
1356
+ function ValidateError(error = "") {
1357
+ if (!ErrorList.includes(error)) {
1358
+ throw new Error(`Invalid error: ${error}. Must be one of: ${ErrorList.join(", ")}`);
1220
1359
  }
1221
- return [...containers2, ...initContainers, ...ephemeralContainers];
1222
- }
1223
- async function writeEvent(cr, event, eventType, eventReason, reportingComponent, reportingInstance) {
1224
- await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.CoreEvent).Create({
1225
- type: eventType,
1226
- reason: eventReason,
1227
- ...event,
1228
- // Fixed values
1229
- metadata: {
1230
- namespace: cr.metadata.namespace,
1231
- generateName: cr.metadata.name
1232
- },
1233
- involvedObject: {
1234
- apiVersion: cr.apiVersion,
1235
- kind: cr.kind,
1236
- name: cr.metadata.name,
1237
- namespace: cr.metadata.namespace,
1238
- uid: cr.metadata.uid
1239
- },
1240
- firstTimestamp: /* @__PURE__ */ new Date(),
1241
- reportingComponent,
1242
- reportingInstance
1243
- });
1244
- }
1245
- function getOwnerRefFrom(customResource, blockOwnerDeletion, controller) {
1246
- const { apiVersion, kind: kind3, metadata } = customResource;
1247
- const { name, uid } = metadata;
1248
- return [
1249
- {
1250
- apiVersion,
1251
- kind: kind3,
1252
- uid,
1253
- name,
1254
- ...blockOwnerDeletion !== void 0 && { blockOwnerDeletion },
1255
- ...controller !== void 0 && { controller }
1256
- }
1257
- ];
1258
- }
1259
- function sanitizeResourceName(name) {
1260
- return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 250).replace(/^[^a-z]+|[^a-z]+$/g, "");
1261
1360
  }
1262
1361
 
1263
- // src/lib/helpers.ts
1264
- function filterNoMatchReason(binding, kubernetesObject, capabilityNamespaces, ignoredNamespaces) {
1265
- const prefix = "Ignoring Watch Callback:";
1266
- return mismatchedDeletionTimestamp(binding, kubernetesObject) ? `${prefix} Binding defines deletionTimestamp but Object does not carry it.` : mismatchedName(binding, kubernetesObject) ? `${prefix} Binding defines name '${definedName(binding)}' but Object carries '${carriedName(kubernetesObject)}'.` : misboundNamespace(binding) ? `${prefix} Cannot use namespace filter on a namespace object.` : mismatchedLabels(binding, kubernetesObject) ? `${prefix} Binding defines labels '${JSON.stringify(definedLabels(binding))}' but Object carries '${JSON.stringify(carriedLabels(kubernetesObject))}'.` : mismatchedAnnotations(binding, kubernetesObject) ? `${prefix} Binding defines annotations '${JSON.stringify(definedAnnotations(binding))}' but Object carries '${JSON.stringify(carriedAnnotations(kubernetesObject))}'.` : uncarryableNamespace(capabilityNamespaces, kubernetesObject) ? `${prefix} Object carries namespace '${carriedNamespace(kubernetesObject)}' but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespaces)}'.` : unbindableNamespaces(capabilityNamespaces, binding) ? `${prefix} Binding defines namespaces ${JSON.stringify(definedNamespaces(binding))} but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespaces)}'.` : mismatchedNamespace(binding, kubernetesObject) ? `${prefix} Binding defines namespaces '${JSON.stringify(definedNamespaces(binding))}' but Object carries '${carriedNamespace(kubernetesObject)}'.` : mismatchedNamespaceRegex(binding, kubernetesObject) ? `${prefix} Binding defines namespace regexes '${JSON.stringify(definedNamespaceRegexes(binding))}' but Object carries '${carriedNamespace(kubernetesObject)}'.` : mismatchedNameRegex(binding, kubernetesObject) ? `${prefix} Binding defines name regex '${definedNameRegex(binding)}' but Object carries '${carriedName(kubernetesObject)}'.` : carriesIgnoredNamespace(ignoredNamespaces, kubernetesObject) ? `${prefix} Object carries namespace '${carriedNamespace(kubernetesObject)}' but ignored namespaces include '${JSON.stringify(ignoredNamespaces)}'.` : missingCarriableNamespace(capabilityNamespaces, kubernetesObject) ? `${prefix} Object does not carry a namespace but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespaces)}'.` : "";
1267
- }
1268
-
1269
- // src/lib/finalizer.ts
1362
+ // src/lib/processors/watch-processor.ts
1270
1363
  var import_kubernetes_fluent_client5 = require("kubernetes-fluent-client");
1271
- function addFinalizer(request) {
1272
- if (request.Request.operation === "DELETE" /* DELETE */) {
1273
- return;
1274
- }
1275
- if (request.Request.operation === "UPDATE" /* UPDATE */ && request.Raw.metadata?.deletionTimestamp) {
1276
- return;
1277
- }
1278
- const peprFinal = "pepr.dev/finalizer";
1279
- const finalizers = request.Raw.metadata?.finalizers || [];
1280
- if (!finalizers.includes(peprFinal)) {
1281
- finalizers.push(peprFinal);
1282
- }
1283
- request.Merge({ metadata: { finalizers } });
1284
- }
1285
- async function removeFinalizer(binding, obj) {
1286
- const peprFinal = "pepr.dev/finalizer";
1287
- const meta = obj.metadata;
1288
- const resource = `${meta.namespace || "ClusterScoped"}/${meta.name}`;
1289
- logger_default.debug({ obj }, `Removing finalizer '${peprFinal}' from '${resource}'`);
1290
- const { model, kind: kind3 } = binding;
1291
- try {
1292
- (0, import_kubernetes_fluent_client5.RegisterKind)(model, kind3);
1293
- } catch (e) {
1294
- const expected = e.message === `GVK ${model.name} already registered`;
1295
- if (!expected) {
1296
- logger_default.error({ model, kind: kind3, error: e }, `Error registering "${kind3}" during finalization.`);
1297
- return;
1298
- }
1299
- }
1300
- const finalizers = meta.finalizers?.filter((f) => f !== peprFinal) || [];
1301
- obj = await (0, import_kubernetes_fluent_client5.K8s)(model, meta).Patch([
1302
- {
1303
- op: "replace",
1304
- path: `/metadata/finalizers`,
1305
- value: finalizers
1306
- }
1307
- ]);
1308
- logger_default.debug({ obj }, `Removed finalizer '${peprFinal}' from '${resource}'`);
1309
- }
1310
1364
 
1311
- // src/lib/queue.ts
1365
+ // src/lib/core/queue.ts
1312
1366
  var import_node_crypto = require("node:crypto");
1313
1367
  var Queue = class {
1314
1368
  #name;
1315
1369
  #uid;
1316
1370
  #queue = [];
1317
1371
  #pendingPromise = false;
1318
- constructor(name) {
1319
- this.#name = name;
1372
+ constructor(name2) {
1373
+ this.#name = name2;
1320
1374
  this.#uid = `${Date.now()}-${(0, import_node_crypto.randomBytes)(2).toString("hex")}`;
1321
1375
  }
1322
1376
  label() {
@@ -1396,7 +1450,52 @@ var Queue = class {
1396
1450
  }
1397
1451
  };
1398
1452
 
1399
- // src/lib/watch-processor.ts
1453
+ // src/lib/processors/watch-processor.ts
1454
+ var import_types = require("kubernetes-fluent-client/dist/fluent/types");
1455
+
1456
+ // src/lib/finalizer.ts
1457
+ var import_kubernetes_fluent_client4 = require("kubernetes-fluent-client");
1458
+ function addFinalizer(request) {
1459
+ if (request.Request.operation === "DELETE" /* DELETE */) {
1460
+ return;
1461
+ }
1462
+ if (request.Request.operation === "UPDATE" /* UPDATE */ && request.Raw.metadata?.deletionTimestamp) {
1463
+ return;
1464
+ }
1465
+ const peprFinal = "pepr.dev/finalizer";
1466
+ const finalizers = request.Raw.metadata?.finalizers || [];
1467
+ if (!finalizers.includes(peprFinal)) {
1468
+ finalizers.push(peprFinal);
1469
+ }
1470
+ request.Merge({ metadata: { finalizers } });
1471
+ }
1472
+ async function removeFinalizer(binding, obj) {
1473
+ const peprFinal = "pepr.dev/finalizer";
1474
+ const meta = obj.metadata;
1475
+ const resource = `${meta.namespace || "ClusterScoped"}/${meta.name}`;
1476
+ logger_default.debug({ obj }, `Removing finalizer '${peprFinal}' from '${resource}'`);
1477
+ const { model, kind: kind3 } = binding;
1478
+ try {
1479
+ (0, import_kubernetes_fluent_client4.RegisterKind)(model, kind3);
1480
+ } catch (e) {
1481
+ const expected = e.message === `GVK ${model.name} already registered`;
1482
+ if (!expected) {
1483
+ logger_default.error({ model, kind: kind3, error: e }, `Error registering "${kind3}" during finalization.`);
1484
+ return;
1485
+ }
1486
+ }
1487
+ const finalizers = meta.finalizers?.filter((f) => f !== peprFinal) || [];
1488
+ obj = await (0, import_kubernetes_fluent_client4.K8s)(model, meta).Patch([
1489
+ {
1490
+ op: "replace",
1491
+ path: `/metadata/finalizers`,
1492
+ value: finalizers
1493
+ }
1494
+ ]);
1495
+ logger_default.debug({ obj }, `Removed finalizer '${peprFinal}' from '${resource}'`);
1496
+ }
1497
+
1498
+ // src/lib/processors/watch-processor.ts
1400
1499
  var queues = {};
1401
1500
  function queueKey(obj) {
1402
1501
  const options = ["kind", "kindNs", "kindNsName", "global"];
@@ -1405,11 +1504,11 @@ function queueKey(obj) {
1405
1504
  strat = options.includes(strat) ? strat : d3fault;
1406
1505
  const ns = obj.metadata?.namespace ?? "cluster-scoped";
1407
1506
  const kind3 = obj.kind ?? "UnknownKind";
1408
- const name = obj.metadata?.name ?? "Unnamed";
1507
+ const name2 = obj.metadata?.name ?? "Unnamed";
1409
1508
  const lookup = {
1410
1509
  kind: `${kind3}`,
1411
1510
  kindNs: `${kind3}/${ns}`,
1412
- kindNsName: `${kind3}/${ns}/${name}`,
1511
+ kindNsName: `${kind3}/${ns}/${name2}`,
1413
1512
  global: "global"
1414
1513
  };
1415
1514
  return lookup[strat];
@@ -1474,7 +1573,7 @@ async function runBinding(binding, capabilityNamespaces, ignoredNamespaces) {
1474
1573
  shouldRemoveFinalizer === false ? logger_default.debug({ obj: kubernetesObject }, `Skipping removal of finalizer '${peprFinal}' from '${resource}'`) : await removeFinalizer(binding, kubernetesObject);
1475
1574
  }
1476
1575
  };
1477
- const watcher = (0, import_kubernetes_fluent_client6.K8s)(binding.model, binding.filters).Watch(async (obj, phase) => {
1576
+ const watcher = (0, import_kubernetes_fluent_client5.K8s)(binding.model, binding.filters).Watch(async (obj, phase) => {
1478
1577
  logger_default.debug(obj, `Watch event ${phase} received`);
1479
1578
  if (binding.isQueue) {
1480
1579
  const queue = getOrCreateQueue(obj);
@@ -1483,30 +1582,30 @@ async function runBinding(binding, capabilityNamespaces, ignoredNamespaces) {
1483
1582
  await watchCallback(obj, phase);
1484
1583
  }
1485
1584
  }, watchCfg);
1486
- watcher.events.on(import_kubernetes_fluent_client6.WatchEvent.GIVE_UP, (err) => {
1585
+ watcher.events.on(import_kubernetes_fluent_client5.WatchEvent.GIVE_UP, (err) => {
1487
1586
  logger_default.error(err, "Watch failed after 5 attempts, giving up");
1488
1587
  process.exit(1);
1489
1588
  });
1490
- watcher.events.on(import_kubernetes_fluent_client6.WatchEvent.CONNECT, (url) => logEvent(import_kubernetes_fluent_client6.WatchEvent.CONNECT, url));
1491
- watcher.events.on(import_kubernetes_fluent_client6.WatchEvent.DATA_ERROR, (err) => logEvent(import_kubernetes_fluent_client6.WatchEvent.DATA_ERROR, err.message));
1589
+ watcher.events.on(import_kubernetes_fluent_client5.WatchEvent.CONNECT, (url) => logEvent(import_kubernetes_fluent_client5.WatchEvent.CONNECT, url));
1590
+ watcher.events.on(import_kubernetes_fluent_client5.WatchEvent.DATA_ERROR, (err) => logEvent(import_kubernetes_fluent_client5.WatchEvent.DATA_ERROR, err.message));
1492
1591
  watcher.events.on(
1493
- import_kubernetes_fluent_client6.WatchEvent.RECONNECT,
1494
- (retryCount) => logEvent(import_kubernetes_fluent_client6.WatchEvent.RECONNECT, `Reconnecting after ${retryCount} attempt${retryCount === 1 ? "" : "s"}`)
1592
+ import_kubernetes_fluent_client5.WatchEvent.RECONNECT,
1593
+ (retryCount) => logEvent(import_kubernetes_fluent_client5.WatchEvent.RECONNECT, `Reconnecting after ${retryCount} attempt${retryCount === 1 ? "" : "s"}`)
1495
1594
  );
1496
- watcher.events.on(import_kubernetes_fluent_client6.WatchEvent.RECONNECT_PENDING, () => logEvent(import_kubernetes_fluent_client6.WatchEvent.RECONNECT_PENDING));
1497
- watcher.events.on(import_kubernetes_fluent_client6.WatchEvent.GIVE_UP, (err) => logEvent(import_kubernetes_fluent_client6.WatchEvent.GIVE_UP, err.message));
1498
- watcher.events.on(import_kubernetes_fluent_client6.WatchEvent.ABORT, (err) => logEvent(import_kubernetes_fluent_client6.WatchEvent.ABORT, err.message));
1499
- watcher.events.on(import_kubernetes_fluent_client6.WatchEvent.OLD_RESOURCE_VERSION, (err) => logEvent(import_kubernetes_fluent_client6.WatchEvent.OLD_RESOURCE_VERSION, err));
1500
- watcher.events.on(import_kubernetes_fluent_client6.WatchEvent.NETWORK_ERROR, (err) => logEvent(import_kubernetes_fluent_client6.WatchEvent.NETWORK_ERROR, err.message));
1501
- watcher.events.on(import_kubernetes_fluent_client6.WatchEvent.LIST_ERROR, (err) => logEvent(import_kubernetes_fluent_client6.WatchEvent.LIST_ERROR, err.message));
1502
- watcher.events.on(import_kubernetes_fluent_client6.WatchEvent.LIST, (list) => logEvent(import_kubernetes_fluent_client6.WatchEvent.LIST, JSON.stringify(list, void 0, 2)));
1503
- watcher.events.on(import_kubernetes_fluent_client6.WatchEvent.CACHE_MISS, (windowName) => {
1595
+ watcher.events.on(import_kubernetes_fluent_client5.WatchEvent.RECONNECT_PENDING, () => logEvent(import_kubernetes_fluent_client5.WatchEvent.RECONNECT_PENDING));
1596
+ watcher.events.on(import_kubernetes_fluent_client5.WatchEvent.GIVE_UP, (err) => logEvent(import_kubernetes_fluent_client5.WatchEvent.GIVE_UP, err.message));
1597
+ watcher.events.on(import_kubernetes_fluent_client5.WatchEvent.ABORT, (err) => logEvent(import_kubernetes_fluent_client5.WatchEvent.ABORT, err.message));
1598
+ watcher.events.on(import_kubernetes_fluent_client5.WatchEvent.OLD_RESOURCE_VERSION, (err) => logEvent(import_kubernetes_fluent_client5.WatchEvent.OLD_RESOURCE_VERSION, err));
1599
+ watcher.events.on(import_kubernetes_fluent_client5.WatchEvent.NETWORK_ERROR, (err) => logEvent(import_kubernetes_fluent_client5.WatchEvent.NETWORK_ERROR, err.message));
1600
+ watcher.events.on(import_kubernetes_fluent_client5.WatchEvent.LIST_ERROR, (err) => logEvent(import_kubernetes_fluent_client5.WatchEvent.LIST_ERROR, err.message));
1601
+ watcher.events.on(import_kubernetes_fluent_client5.WatchEvent.LIST, (list) => logEvent(import_kubernetes_fluent_client5.WatchEvent.LIST, JSON.stringify(list, void 0, 2)));
1602
+ watcher.events.on(import_kubernetes_fluent_client5.WatchEvent.CACHE_MISS, (windowName) => {
1504
1603
  metricsCollector.incCacheMiss(windowName);
1505
1604
  });
1506
- watcher.events.on(import_kubernetes_fluent_client6.WatchEvent.INIT_CACHE_MISS, (windowName) => {
1605
+ watcher.events.on(import_kubernetes_fluent_client5.WatchEvent.INIT_CACHE_MISS, (windowName) => {
1507
1606
  metricsCollector.initCacheMissWindow(windowName);
1508
1607
  });
1509
- watcher.events.on(import_kubernetes_fluent_client6.WatchEvent.INC_RESYNC_FAILURE_COUNT, (retryCount) => {
1608
+ watcher.events.on(import_kubernetes_fluent_client5.WatchEvent.INC_RESYNC_FAILURE_COUNT, (retryCount) => {
1510
1609
  metricsCollector.incRetryCount(retryCount);
1511
1610
  });
1512
1611
  try {
@@ -1525,7 +1624,7 @@ function logEvent(event, message = "", obj) {
1525
1624
  }
1526
1625
  }
1527
1626
 
1528
- // src/lib/module.ts
1627
+ // src/lib/core/module.ts
1529
1628
  var isWatchMode = () => process.env.PEPR_WATCH_MODE === "true";
1530
1629
  var isBuildMode = () => process.env.PEPR_MODE === "build";
1531
1630
  var isDevMode = () => process.env.PEPR_MODE === "dev";
@@ -1539,7 +1638,7 @@ var PeprModule = class {
1539
1638
  * @param opts Options for the Pepr runtime
1540
1639
  */
1541
1640
  constructor({ description, pepr }, capabilities = [], opts = {}) {
1542
- const config = (0, import_ramda5.clone)(pepr);
1641
+ const config = (0, import_ramda6.clone)(pepr);
1543
1642
  config.description = description;
1544
1643
  ValidateError(config.onError);
1545
1644
  if (isBuildMode()) {
@@ -1585,8 +1684,8 @@ var PeprModule = class {
1585
1684
  };
1586
1685
  };
1587
1686
 
1588
- // src/lib/storage.ts
1589
- var import_ramda6 = require("ramda");
1687
+ // src/lib/core/storage.ts
1688
+ var import_ramda7 = require("ramda");
1590
1689
  var import_json_pointer = __toESM(require("json-pointer"));
1591
1690
  var MAX_WAIT_TIME = 15e3;
1592
1691
  var STORE_VERSION_PREFIX = "v2";
@@ -1609,7 +1708,7 @@ var Storage = class {
1609
1708
  this.#store = data || {};
1610
1709
  this.#onReady();
1611
1710
  for (const idx in this.#subscribers) {
1612
- this.#subscribers[idx]((0, import_ramda6.clone)(this.#store));
1711
+ this.#subscribers[idx]((0, import_ramda7.clone)(this.#store));
1613
1712
  }
1614
1713
  };
1615
1714
  getItem = (key) => {
@@ -1641,17 +1740,19 @@ var Storage = class {
1641
1740
  */
1642
1741
  setItemAndWait = (key, value) => {
1643
1742
  this.#dispatchUpdate("add", [v2StoreKey(key)], value);
1743
+ const record = {};
1644
1744
  return new Promise((resolve, reject) => {
1645
- const unsubscribe = this.subscribe((data) => {
1745
+ record.timeout = setTimeout(() => {
1746
+ record.unsubscribe();
1747
+ return reject(`MAX_WAIT_TIME elapsed: Key ${key} not seen in ${MAX_WAIT_TIME / 1e3}s`);
1748
+ }, MAX_WAIT_TIME);
1749
+ record.unsubscribe = this.subscribe((data) => {
1646
1750
  if (data[`${v2UnescapedStoreKey(key)}`] === value) {
1647
- unsubscribe();
1648
- resolve();
1751
+ record.unsubscribe();
1752
+ clearTimeout(record.timeout);
1753
+ resolve("ok");
1649
1754
  }
1650
1755
  });
1651
- setTimeout(() => {
1652
- unsubscribe();
1653
- return reject();
1654
- }, MAX_WAIT_TIME);
1655
1756
  });
1656
1757
  };
1657
1758
  /**
@@ -1663,17 +1764,19 @@ var Storage = class {
1663
1764
  */
1664
1765
  removeItemAndWait = (key) => {
1665
1766
  this.#dispatchUpdate("remove", [v2StoreKey(key)]);
1767
+ const record = {};
1666
1768
  return new Promise((resolve, reject) => {
1667
- const unsubscribe = this.subscribe((data) => {
1769
+ record.timeout = setTimeout(() => {
1770
+ record.unsubscribe();
1771
+ return reject(`MAX_WAIT_TIME elapsed: Key ${key} still seen after ${MAX_WAIT_TIME / 1e3}s`);
1772
+ }, MAX_WAIT_TIME);
1773
+ record.unsubscribe = this.subscribe((data) => {
1668
1774
  if (!Object.hasOwn(data, `${v2UnescapedStoreKey(key)}`)) {
1669
- unsubscribe();
1670
- resolve();
1775
+ record.unsubscribe();
1776
+ clearTimeout(record.timeout);
1777
+ resolve("ok");
1671
1778
  }
1672
1779
  });
1673
- setTimeout(() => {
1674
- unsubscribe();
1675
- return reject();
1676
- }, MAX_WAIT_TIME);
1677
1780
  });
1678
1781
  };
1679
1782
  subscribe = (subscriber) => {
@@ -1693,7 +1796,7 @@ var Storage = class {
1693
1796
  };
1694
1797
  #onReady = () => {
1695
1798
  for (const handler of this.#readyHandlers) {
1696
- handler((0, import_ramda6.clone)(this.#store));
1799
+ handler((0, import_ramda7.clone)(this.#store));
1697
1800
  }
1698
1801
  this.#onReady = () => {
1699
1802
  };
@@ -1709,7 +1812,7 @@ var Storage = class {
1709
1812
  };
1710
1813
  };
1711
1814
 
1712
- // src/lib/schedule.ts
1815
+ // src/lib/core/schedule.ts
1713
1816
  var OnSchedule = class {
1714
1817
  intervalId = null;
1715
1818
  store;
@@ -1837,7 +1940,7 @@ var OnSchedule = class {
1837
1940
  }
1838
1941
  };
1839
1942
 
1840
- // src/lib/capability.ts
1943
+ // src/lib/core/capability.ts
1841
1944
  var registerAdmission = isBuildMode() || !isWatchMode();
1842
1945
  var registerWatch = isBuildMode() || isWatchMode() || isDevMode();
1843
1946
  var Capability = class {
@@ -1857,11 +1960,11 @@ var Capability = class {
1857
1960
  * @returns
1858
1961
  */
1859
1962
  OnSchedule = (schedule) => {
1860
- const { name, every, unit, run, startTime, completions } = schedule;
1963
+ const { name: name2, every, unit, run, startTime, completions } = schedule;
1861
1964
  this.hasSchedule = true;
1862
1965
  if (process.env.PEPR_WATCH_MODE === "true" || process.env.PEPR_MODE === "dev") {
1863
1966
  const newSchedule = {
1864
- name,
1967
+ name: name2,
1865
1968
  every,
1866
1969
  unit,
1867
1970
  run,
@@ -1964,7 +2067,7 @@ var Capability = class {
1964
2067
  * @returns
1965
2068
  */
1966
2069
  When = (model, kind3) => {
1967
- const matchedKind = (0, import_kubernetes_fluent_client7.modelToGroupVersionKind)(model.name);
2070
+ const matchedKind = (0, import_kubernetes_fluent_client6.modelToGroupVersionKind)(model.name);
1968
2071
  if (!matchedKind && !kind3) {
1969
2072
  throw new Error(`Kind not specified for ${model.name}`);
1970
2073
  }
@@ -1988,7 +2091,7 @@ var Capability = class {
1988
2091
  const commonChain = { WithLabel, WithAnnotation, WithDeletionTimestamp, Mutate, Validate, Watch, Reconcile, Alias };
1989
2092
  const isNotEmpty = (value) => Object.keys(value).length > 0;
1990
2093
  const log = (message, cbString) => {
1991
- const filteredObj = (0, import_ramda7.pickBy)(isNotEmpty, binding.filters);
2094
+ const filteredObj = (0, import_ramda8.pickBy)(isNotEmpty, binding.filters);
1992
2095
  logger_default.info(`${message} configured for ${binding.event}`, prefix);
1993
2096
  logger_default.info(filteredObj, prefix);
1994
2097
  logger_default.debug(cbString, prefix);
@@ -2101,9 +2204,9 @@ var Capability = class {
2101
2204
  binding.filters.regexName = regexName.source;
2102
2205
  return commonChain;
2103
2206
  }
2104
- function WithName(name) {
2105
- logger_default.debug(`Add name filter ${name}`, prefix);
2106
- binding.filters.name = name;
2207
+ function WithName(name2) {
2208
+ logger_default.debug(`Add name filter ${name2}`, prefix);
2209
+ binding.filters.name = name2;
2107
2210
  return commonChain;
2108
2211
  }
2109
2212
  function WithLabel(key, value = "") {
@@ -2141,6 +2244,70 @@ var Capability = class {
2141
2244
  };
2142
2245
  };
2143
2246
  };
2247
+
2248
+ // src/sdk/sdk.ts
2249
+ var sdk_exports = {};
2250
+ __export(sdk_exports, {
2251
+ containers: () => containers,
2252
+ getOwnerRefFrom: () => getOwnerRefFrom,
2253
+ sanitizeResourceName: () => sanitizeResourceName,
2254
+ writeEvent: () => writeEvent
2255
+ });
2256
+ var import_kubernetes_fluent_client7 = require("kubernetes-fluent-client");
2257
+ function containers(request, containerType) {
2258
+ const containers2 = request.Raw.spec?.containers || [];
2259
+ const initContainers = request.Raw.spec?.initContainers || [];
2260
+ const ephemeralContainers = request.Raw.spec?.ephemeralContainers || [];
2261
+ if (containerType === "containers") {
2262
+ return containers2;
2263
+ }
2264
+ if (containerType === "initContainers") {
2265
+ return initContainers;
2266
+ }
2267
+ if (containerType === "ephemeralContainers") {
2268
+ return ephemeralContainers;
2269
+ }
2270
+ return [...containers2, ...initContainers, ...ephemeralContainers];
2271
+ }
2272
+ async function writeEvent(cr, event, eventType, eventReason, reportingComponent, reportingInstance) {
2273
+ await (0, import_kubernetes_fluent_client7.K8s)(import_kubernetes_fluent_client7.kind.CoreEvent).Create({
2274
+ type: eventType,
2275
+ reason: eventReason,
2276
+ ...event,
2277
+ // Fixed values
2278
+ metadata: {
2279
+ namespace: cr.metadata.namespace,
2280
+ generateName: cr.metadata.name
2281
+ },
2282
+ involvedObject: {
2283
+ apiVersion: cr.apiVersion,
2284
+ kind: cr.kind,
2285
+ name: cr.metadata.name,
2286
+ namespace: cr.metadata.namespace,
2287
+ uid: cr.metadata.uid
2288
+ },
2289
+ firstTimestamp: /* @__PURE__ */ new Date(),
2290
+ reportingComponent,
2291
+ reportingInstance
2292
+ });
2293
+ }
2294
+ function getOwnerRefFrom(customResource, blockOwnerDeletion, controller) {
2295
+ const { apiVersion, kind: kind3, metadata } = customResource;
2296
+ const { name: name2, uid } = metadata;
2297
+ return [
2298
+ {
2299
+ apiVersion,
2300
+ kind: kind3,
2301
+ uid,
2302
+ name: name2,
2303
+ ...blockOwnerDeletion !== void 0 && { blockOwnerDeletion },
2304
+ ...controller !== void 0 && { controller }
2305
+ }
2306
+ ];
2307
+ }
2308
+ function sanitizeResourceName(name2) {
2309
+ return name2.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 250).replace(/^[^a-z]+|[^a-z]+$/g, "");
2310
+ }
2144
2311
  // Annotate the CommonJS export names for ESM import in node:
2145
2312
  0 && (module.exports = {
2146
2313
  Capability,