pepr 0.38.3 → 0.39.0

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 (95) hide show
  1. package/dist/cli/build.d.ts +1 -1
  2. package/dist/cli/build.d.ts.map +1 -1
  3. package/dist/cli/build.helpers.d.ts +19 -0
  4. package/dist/cli/build.helpers.d.ts.map +1 -0
  5. package/dist/cli/deploy.d.ts.map +1 -1
  6. package/dist/cli/format.d.ts.map +1 -1
  7. package/dist/cli/init/index.d.ts.map +1 -1
  8. package/dist/cli/init/templates.d.ts +6 -2
  9. package/dist/cli/init/templates.d.ts.map +1 -1
  10. package/dist/cli/monitor.d.ts.map +1 -1
  11. package/dist/cli.js +278 -225
  12. package/dist/controller.js +37 -27
  13. package/dist/lib/assets/deploy.d.ts.map +1 -1
  14. package/dist/lib/assets/helm.d.ts +1 -0
  15. package/dist/lib/assets/helm.d.ts.map +1 -1
  16. package/dist/lib/assets/index.d.ts +1 -1
  17. package/dist/lib/assets/index.d.ts.map +1 -1
  18. package/dist/lib/assets/rbac.d.ts +31 -4
  19. package/dist/lib/assets/rbac.d.ts.map +1 -1
  20. package/dist/lib/assets/yaml.d.ts +2 -2
  21. package/dist/lib/assets/yaml.d.ts.map +1 -1
  22. package/dist/lib/capability.d.ts +2 -8
  23. package/dist/lib/capability.d.ts.map +1 -1
  24. package/dist/lib/controller/store.d.ts +1 -5
  25. package/dist/lib/controller/store.d.ts.map +1 -1
  26. package/dist/lib/controller/storeCache.d.ts +11 -0
  27. package/dist/lib/controller/storeCache.d.ts.map +1 -0
  28. package/dist/lib/enums.d.ts +17 -0
  29. package/dist/lib/enums.d.ts.map +1 -0
  30. package/dist/lib/{adjudicators.d.ts → filter/adjudicators.d.ts} +15 -13
  31. package/dist/lib/filter/adjudicators.d.ts.map +1 -0
  32. package/dist/lib/{filter.d.ts → filter/filter.d.ts} +1 -1
  33. package/dist/lib/filter/filter.d.ts.map +1 -0
  34. package/dist/lib/helpers.d.ts +1 -2
  35. package/dist/lib/helpers.d.ts.map +1 -1
  36. package/dist/lib/k8s.d.ts +1 -1
  37. package/dist/lib/k8s.d.ts.map +1 -1
  38. package/dist/lib/logger.d.ts +4 -0
  39. package/dist/lib/logger.d.ts.map +1 -1
  40. package/dist/lib/metrics.d.ts.map +1 -1
  41. package/dist/lib/module.d.ts +5 -0
  42. package/dist/lib/module.d.ts.map +1 -1
  43. package/dist/lib/mutate-processor.d.ts.map +1 -1
  44. package/dist/lib/mutate-request.d.ts +1 -60
  45. package/dist/lib/mutate-request.d.ts.map +1 -1
  46. package/dist/lib/types.d.ts +8 -24
  47. package/dist/lib/types.d.ts.map +1 -1
  48. package/dist/lib/validate-request.d.ts.map +1 -1
  49. package/dist/lib/watch-processor.d.ts.map +1 -1
  50. package/dist/lib.js +220 -295
  51. package/dist/lib.js.map +4 -4
  52. package/dist/sdk/cosign.d.ts +18 -0
  53. package/dist/sdk/cosign.d.ts.map +1 -0
  54. package/dist/sdk/heredoc.d.ts +2 -0
  55. package/dist/sdk/heredoc.d.ts.map +1 -0
  56. package/dist/sdk/sdk.d.ts +1 -2
  57. package/dist/sdk/sdk.d.ts.map +1 -1
  58. package/package.json +11 -7
  59. package/src/cli/build.helpers.ts +28 -0
  60. package/src/cli/build.ts +124 -121
  61. package/src/cli/deploy.ts +27 -24
  62. package/src/cli/dev.ts +3 -3
  63. package/src/cli/format.ts +3 -6
  64. package/src/cli/init/index.ts +23 -19
  65. package/src/cli/monitor.ts +34 -36
  66. package/src/lib/assets/deploy.ts +12 -3
  67. package/src/lib/assets/helm.ts +14 -0
  68. package/src/lib/assets/index.ts +12 -8
  69. package/src/lib/assets/rbac.ts +69 -17
  70. package/src/lib/assets/webhooks.ts +1 -1
  71. package/src/lib/assets/yaml.ts +8 -4
  72. package/src/lib/capability.ts +7 -12
  73. package/src/lib/controller/index.ts +3 -3
  74. package/src/lib/controller/store.ts +42 -202
  75. package/src/lib/controller/storeCache.ts +63 -0
  76. package/src/lib/enums.ts +21 -0
  77. package/src/lib/{adjudicators.ts → filter/adjudicators.ts} +39 -28
  78. package/src/lib/{filter.ts → filter/filter.ts} +3 -2
  79. package/src/lib/finalizer.ts +1 -1
  80. package/src/lib/helpers.ts +19 -15
  81. package/src/lib/k8s.ts +2 -2
  82. package/src/lib/logger.ts +41 -0
  83. package/src/lib/metrics.ts +3 -1
  84. package/src/lib/module.ts +5 -0
  85. package/src/lib/mutate-processor.ts +14 -12
  86. package/src/lib/mutate-request.ts +4 -69
  87. package/src/lib/types.ts +9 -28
  88. package/src/lib/validate-processor.ts +1 -1
  89. package/src/lib/validate-request.ts +2 -1
  90. package/src/lib/watch-processor.ts +34 -20
  91. package/src/sdk/cosign.ts +327 -0
  92. package/src/sdk/heredoc.ts +36 -0
  93. package/src/sdk/sdk.ts +1 -2
  94. package/dist/lib/adjudicators.d.ts.map +0 -1
  95. package/dist/lib/filter.d.ts.map +0 -1
@@ -49,43 +49,41 @@ export default function (program: RootCmd) {
49
49
 
50
50
  for (const line of lines) {
51
51
  // Check for `"msg":"Hello Pepr"`
52
- if (line.includes(respMsg)) {
53
- try {
54
- const payload = JSON.parse(line.trim());
55
- const isMutate = payload.res.patchType || payload.res.warnings;
56
-
57
- const name = `${payload.namespace}${payload.name}`;
58
- const uid = payload.res.uid;
59
-
60
- if (isMutate) {
61
- const plainPatch =
62
- payload.res?.patch !== undefined && payload.res?.patch !== null
63
- ? atob(payload.res.patch)
64
- : "";
65
-
66
- const patch = plainPatch !== "" && JSON.stringify(JSON.parse(plainPatch), null, 2);
67
- const patchType = payload.res.patchType || payload.res.warnings || "";
68
- const allowOrDeny = payload.res.allowed ? "🔀" : "🚫";
69
- console.log(`\n${allowOrDeny} MUTATE ${name} (${uid})`);
70
- if (patchType.length > 0) {
71
- console.log(`\n\u001b[1;34m${patch}\u001b[0m`);
72
- }
73
- } else {
74
- const failures = Array.isArray(payload.res) ? payload.res : [payload.res];
75
-
76
- const filteredFailures = failures
77
- .filter((r: ResponseItem) => !r.allowed)
78
- .map((r: ResponseItem) => r.status.message);
79
- if (filteredFailures.length > 0) {
80
- console.log(`\n❌ VALIDATE ${name} (${uid})`);
81
- console.log(`\u001b[1;31m${filteredFailures}\u001b[0m`);
82
- } else {
83
- console.log(`\n✅ VALIDATE ${name} (${uid})`);
84
- }
85
- }
86
- } catch {
87
- // Do nothing
52
+ if (!line.includes(respMsg)) continue;
53
+ try {
54
+ const payload = JSON.parse(line.trim());
55
+ const isMutate = payload.res.patchType || payload.res.warnings;
56
+
57
+ const name = `${payload.namespace}${payload.name}`;
58
+ const uid = payload.res.uid;
59
+
60
+ if (isMutate) {
61
+ const plainPatch =
62
+ payload.res?.patch !== undefined && payload.res?.patch !== null
63
+ ? atob(payload.res.patch)
64
+ : "";
65
+
66
+ const patch = plainPatch !== "" && JSON.stringify(JSON.parse(plainPatch), null, 2);
67
+ const patchType = payload.res.patchType || payload.res.warnings || "";
68
+ const allowOrDeny = payload.res.allowed ? "🔀" : "🚫";
69
+ console.log(`\n${allowOrDeny} MUTATE ${name} (${uid})`);
70
+ patchType.length > 0 && console.log(`\n\u001b[1;34m${patch}\u001b[0m`);
71
+ } else {
72
+ const failures = Array.isArray(payload.res) ? payload.res : [payload.res];
73
+
74
+ const filteredFailures = failures
75
+ .filter((r: ResponseItem) => !r.allowed)
76
+ .map((r: ResponseItem) => r.status.message);
77
+
78
+ console.log(
79
+ `\n${filteredFailures.length > 0 ? "❌" : "✅"} VALIDATE ${name} (${uid})`,
80
+ );
81
+ console.log(
82
+ filteredFailures.length > 0 ? `\u001b[1;31m${filteredFailures}\u001b[0m` : "",
83
+ );
88
84
  }
85
+ } catch {
86
+ // Do nothing
89
87
  }
90
88
  }
91
89
  });
@@ -4,6 +4,7 @@
4
4
  import crypto from "crypto";
5
5
  import { promises as fs } from "fs";
6
6
  import { K8s, kind } from "kubernetes-fluent-client";
7
+ import { V1PolicyRule as PolicyRule } from "@kubernetes/client-node";
7
8
 
8
9
  import { Assets } from ".";
9
10
  import Log from "../logger";
@@ -84,18 +85,25 @@ export async function deploy(assets: Assets, force: boolean, webhookTimeout?: nu
84
85
  throw new Error("No code provided");
85
86
  }
86
87
 
87
- await setupRBAC(name, assets.capabilities, force);
88
+ await setupRBAC(name, assets.capabilities, force, assets.config);
88
89
  await setupController(assets, code, hash, force);
89
90
  await setupWatcher(assets, hash, force);
90
91
  }
91
92
 
92
- async function setupRBAC(name: string, capabilities: CapabilityExport[], force: boolean) {
93
+ async function setupRBAC(
94
+ name: string,
95
+ capabilities: CapabilityExport[],
96
+ force: boolean,
97
+ config: { rbacMode?: string; rbac?: PolicyRule[] },
98
+ ) {
99
+ const { rbacMode, rbac } = config;
100
+
93
101
  Log.info("Applying cluster role binding");
94
102
  const crb = clusterRoleBinding(name);
95
103
  await K8s(kind.ClusterRoleBinding).Apply(crb, { force });
96
104
 
97
105
  Log.info("Applying cluster role");
98
- const cr = clusterRole(name, capabilities);
106
+ const cr = clusterRole(name, capabilities, rbacMode, rbac);
99
107
  await K8s(kind.ClusterRole).Apply(cr, { force });
100
108
 
101
109
  Log.info("Applying service account");
@@ -135,6 +143,7 @@ async function setupController(assets: Assets, code: Buffer, hash: string, force
135
143
  await K8s(kind.Deployment).Apply(dep, { force });
136
144
  }
137
145
 
146
+ // Setup the watcher deployment and service
138
147
  async function setupWatcher(assets: Assets, hash: string, force: boolean) {
139
148
  // If the module has a watcher, deploy it
140
149
  const watchDeployment = watcher(assets, hash, assets.buildTimestamp);
@@ -1,6 +1,20 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
3
 
4
+ export function clusterRoleTemplate() {
5
+ return `
6
+ apiVersion: rbac.authorization.k8s.io/v1
7
+ kind: ClusterRole
8
+ metadata:
9
+ name: {{ .Values.uuid }}
10
+ namespace: pepr-system
11
+ rules:
12
+ {{- if .Values.rbac }}
13
+ {{- toYaml .Values.rbac | nindent 2 }}
14
+ {{- end }}
15
+ `;
16
+ }
17
+
4
18
  export function nsTemplate() {
5
19
  return `
6
20
  apiVersion: v1
@@ -13,13 +13,20 @@ import { allYaml, zarfYaml, overridesFile, zarfYamlChart } from "./yaml";
13
13
  import { namespaceComplianceValidator, replaceString } from "../helpers";
14
14
  import { createDirectoryIfNotExists, dedent } from "../helpers";
15
15
  import { resolve } from "path";
16
- import { chartYaml, nsTemplate, admissionDeployTemplate, watcherDeployTemplate, serviceMonitorTemplate } from "./helm";
16
+ import {
17
+ chartYaml,
18
+ nsTemplate,
19
+ admissionDeployTemplate,
20
+ watcherDeployTemplate,
21
+ clusterRoleTemplate,
22
+ serviceMonitorTemplate,
23
+ } from "./helm";
17
24
  import { promises as fs } from "fs";
18
25
  import { webhookConfig } from "./webhooks";
19
26
  import { apiTokenSecret, service, tlsSecret, watcherService } from "./networking";
20
27
  import { watcher, moduleSecret } from "./pods";
21
28
 
22
- import { clusterRole, clusterRoleBinding, serviceAccount, storeRole, storeRoleBinding } from "./rbac";
29
+ import { clusterRoleBinding, serviceAccount, storeRole, storeRoleBinding } from "./rbac";
23
30
  export class Assets {
24
31
  readonly name: string;
25
32
  readonly tls: TLSOut;
@@ -61,14 +68,14 @@ export class Assets {
61
68
 
62
69
  zarfYamlChart = (path: string) => zarfYamlChart(this, path);
63
70
 
64
- allYaml = async (rbacMode: string, imagePullSecret?: string) => {
71
+ allYaml = async (imagePullSecret?: string) => {
65
72
  this.capabilities = await loadCapabilities(this.path);
66
73
  // give error if namespaces are not respected
67
74
  for (const capability of this.capabilities) {
68
75
  namespaceComplianceValidator(capability, this.alwaysIgnore?.namespaces);
69
76
  }
70
77
 
71
- return allYaml(this, rbacMode, imagePullSecret);
78
+ return allYaml(this, imagePullSecret);
72
79
  };
73
80
 
74
81
  generateHelmChart = async (basePath: string) => {
@@ -123,10 +130,7 @@ export class Assets {
123
130
  await fs.writeFile(moduleSecretPath, dumpYaml(moduleSecret(this.name, code, this.hash), { noRefs: true }));
124
131
  await fs.writeFile(storeRolePath, dumpYaml(storeRole(this.name), { noRefs: true }));
125
132
  await fs.writeFile(storeRoleBindingPath, dumpYaml(storeRoleBinding(this.name), { noRefs: true }));
126
- await fs.writeFile(
127
- clusterRolePath,
128
- dumpYaml(clusterRole(this.name, this.capabilities, "rbac"), { noRefs: true }),
129
- );
133
+ await fs.writeFile(clusterRolePath, dedent(clusterRoleTemplate()));
130
134
  await fs.writeFile(clusterRoleBindingPath, dumpYaml(clusterRoleBinding(this.name), { noRefs: true }));
131
135
  await fs.writeFile(serviceAccountPath, dumpYaml(serviceAccount(this.name), { noRefs: true }));
132
136
 
@@ -2,35 +2,63 @@
2
2
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
3
 
4
4
  import { kind } from "kubernetes-fluent-client";
5
+ import { V1PolicyRule as PolicyRule } from "@kubernetes/client-node";
5
6
  import { CapabilityExport } from "../types";
6
7
  import { createRBACMap } from "../helpers";
8
+
7
9
  /**
8
- * Grants the controller access to cluster resources beyond the mutating webhook.
10
+ * Creates a Kubernetes ClusterRole based on capabilities and optional custom RBAC rules.
9
11
  *
10
- * @todo: should dynamically generate this based on resources used by the module. will also need to explore how this should work for multiple modules.
11
- * @returns
12
+ * @param {string} name - The name of the ClusterRole.
13
+ * @param {CapabilityExport[]} capabilities - Array of capabilities defining RBAC rules.
14
+ * @param {string} [rbacMode=""] - The RBAC mode; if "scoped", generates scoped rules, otherwise uses wildcard rules.
15
+ * @returns {kind.ClusterRole} - A Kubernetes ClusterRole object.
12
16
  */
13
- export function clusterRole(name: string, capabilities: CapabilityExport[], rbacMode: string = ""): kind.ClusterRole {
17
+ export function clusterRole(
18
+ name: string,
19
+ capabilities: CapabilityExport[],
20
+ rbacMode: string = "admin",
21
+ customRbac: PolicyRule[] | undefined,
22
+ ): kind.ClusterRole {
23
+ // Create the RBAC map from capabilities
14
24
  const rbacMap = createRBACMap(capabilities);
25
+
26
+ // Generate scoped rules from rbacMap
27
+ const scopedRules = Object.keys(rbacMap).map(key => {
28
+ let group: string;
29
+ key.split("/").length < 3 ? (group = "") : (group = key.split("/")[0]);
30
+
31
+ return {
32
+ apiGroups: [group],
33
+ resources: [rbacMap[key].plural],
34
+ verbs: rbacMap[key].verbs,
35
+ };
36
+ });
37
+
38
+ // Merge and deduplicate custom RBAC and scoped rules
39
+ const mergedRBAC = [...(Array.isArray(customRbac) ? customRbac : []), ...scopedRules];
40
+ const deduper: Record<string, PolicyRule & { verbs: string[] }> = {};
41
+
42
+ mergedRBAC.forEach(rule => {
43
+ const key = `${rule.apiGroups}/${rule.resources}`;
44
+ if (deduper[key]) {
45
+ // Deduplicate verbs
46
+ deduper[key].verbs = Array.from(new Set([...deduper[key].verbs, ...rule.verbs]));
47
+ } else {
48
+ deduper[key] = { ...rule, verbs: rule.verbs || [] };
49
+ }
50
+ });
51
+
52
+ // Convert deduplicated RBAC rules back to an array
53
+ const deduplicatedRules = Object.values(deduper);
54
+
15
55
  return {
16
56
  apiVersion: "rbac.authorization.k8s.io/v1",
17
57
  kind: "ClusterRole",
18
58
  metadata: { name },
19
59
  rules:
20
60
  rbacMode === "scoped"
21
- ? [
22
- ...Object.keys(rbacMap).map(key => {
23
- // let group:string, version:string, kind:string;
24
- let group: string;
25
- key.split("/").length < 3 ? (group = "") : (group = key.split("/")[0]);
26
-
27
- return {
28
- apiGroups: [group],
29
- resources: [rbacMap[key].plural],
30
- verbs: rbacMap[key].verbs,
31
- };
32
- }),
33
- ]
61
+ ? deduplicatedRules
34
62
  : [
35
63
  {
36
64
  apiGroups: ["*"],
@@ -41,6 +69,12 @@ export function clusterRole(name: string, capabilities: CapabilityExport[], rbac
41
69
  };
42
70
  }
43
71
 
72
+ /**
73
+ * Creates a Kubernetes ClusterRoleBinding for a specified ClusterRole.
74
+ *
75
+ * @param {string} name - The name of the ClusterRole to bind.
76
+ * @returns {kind.ClusterRoleBinding} - A Kubernetes ClusterRoleBinding object.
77
+ */
44
78
  export function clusterRoleBinding(name: string): kind.ClusterRoleBinding {
45
79
  return {
46
80
  apiVersion: "rbac.authorization.k8s.io/v1",
@@ -61,6 +95,12 @@ export function clusterRoleBinding(name: string): kind.ClusterRoleBinding {
61
95
  };
62
96
  }
63
97
 
98
+ /**
99
+ * Creates a Kubernetes ServiceAccount with the specified name.
100
+ *
101
+ * @param {string} name - The name of the ServiceAccount.
102
+ * @returns {kind.ServiceAccount} - A Kubernetes ServiceAccount object.
103
+ */
64
104
  export function serviceAccount(name: string): kind.ServiceAccount {
65
105
  return {
66
106
  apiVersion: "v1",
@@ -72,6 +112,12 @@ export function serviceAccount(name: string): kind.ServiceAccount {
72
112
  };
73
113
  }
74
114
 
115
+ /**
116
+ * Creates a Kubernetes Role for managing peprstores in a specified namespace.
117
+ *
118
+ * @param {string} name - The base name of the Role.
119
+ * @returns {kind.Role} - A Kubernetes Role object for peprstores.
120
+ */
75
121
  export function storeRole(name: string): kind.Role {
76
122
  name = `${name}-store`;
77
123
  return {
@@ -89,6 +135,12 @@ export function storeRole(name: string): kind.Role {
89
135
  };
90
136
  }
91
137
 
138
+ /**
139
+ * Creates a Kubernetes RoleBinding for a specified Role in the pepr-system namespace.
140
+ *
141
+ * @param {string} name - The base name of the Role to bind.
142
+ * @returns {kind.RoleBinding} - A Kubernetes RoleBinding object.
143
+ */
92
144
  export function storeRoleBinding(name: string): kind.RoleBinding {
93
145
  name = `${name}-store`;
94
146
  return {
@@ -10,7 +10,7 @@ import { kind } from "kubernetes-fluent-client";
10
10
  import { concat, equals, uniqWith } from "ramda";
11
11
 
12
12
  import { Assets } from ".";
13
- import { Event } from "../types";
13
+ import { Event } from "../enums";
14
14
 
15
15
  const peprIgnoreLabel: V1LabelSelectorRequirement = {
16
16
  key: "pepr.dev",
@@ -10,9 +10,13 @@ import { deployment, moduleSecret, namespace, watcher } from "./pods";
10
10
  import { clusterRole, clusterRoleBinding, serviceAccount, storeRole, storeRoleBinding } from "./rbac";
11
11
  import { webhookConfig } from "./webhooks";
12
12
  import { genEnv } from "./pods";
13
+
13
14
  // Helm Chart overrides file (values.yaml) generated from assets
14
- export async function overridesFile({ hash, name, image, config, apiToken }: Assets, path: string) {
15
+ export async function overridesFile({ hash, name, image, config, apiToken, capabilities }: Assets, path: string) {
16
+ const rbacOverrides = clusterRole(name, capabilities, config.rbacMode, config.rbac).rules;
17
+
15
18
  const overrides = {
19
+ rbac: rbacOverrides,
16
20
  secrets: {
17
21
  apiToken: Buffer.from(apiToken).toString("base64"),
18
22
  },
@@ -219,8 +223,8 @@ export function zarfYamlChart({ name, image, config }: Assets, path: string) {
219
223
  return dumpYaml(zarfCfg, { noRefs: true });
220
224
  }
221
225
 
222
- export async function allYaml(assets: Assets, rbacMode: string, imagePullSecret?: string) {
223
- const { name, tls, apiToken, path } = assets;
226
+ export async function allYaml(assets: Assets, imagePullSecret?: string) {
227
+ const { name, tls, apiToken, path, config } = assets;
224
228
  const code = await fs.readFile(path);
225
229
 
226
230
  // Generate a hash of the code
@@ -232,7 +236,7 @@ export async function allYaml(assets: Assets, rbacMode: string, imagePullSecret?
232
236
 
233
237
  const resources = [
234
238
  namespace(assets.config.customLabels?.namespace),
235
- clusterRole(name, assets.capabilities, rbacMode),
239
+ clusterRole(name, assets.capabilities, config.rbacMode, config.rbac),
236
240
  clusterRoleBinding(name),
237
241
  serviceAccount(name),
238
242
  apiTokenSecret(name, apiToken),
@@ -1,3 +1,4 @@
1
+ /* eslint-disable max-statements */
1
2
  // SPDX-License-Identifier: Apache-2.0
2
3
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
4
 
@@ -7,13 +8,13 @@ import Log from "./logger";
7
8
  import { isBuildMode, isDevMode, isWatchMode } from "./module";
8
9
  import { PeprStore, Storage } from "./storage";
9
10
  import { OnSchedule, Schedule } from "./schedule";
11
+ import { Event } from "./enums";
10
12
  import {
11
13
  Binding,
12
14
  BindingFilter,
13
15
  BindingWithName,
14
16
  CapabilityCfg,
15
17
  CapabilityExport,
16
- Event,
17
18
  MutateAction,
18
19
  MutateActionChain,
19
20
  ValidateAction,
@@ -139,10 +140,8 @@ export class Capability implements CapabilityExport {
139
140
 
140
141
  /**
141
142
  * Register the store with the capability. This is called automatically by the Pepr controller.
142
- *
143
- * @param store
144
143
  */
145
- registerScheduleStore = () => {
144
+ registerScheduleStore = (): Storage => {
146
145
  Log.info(`Registering schedule store for ${this.#name}`);
147
146
 
148
147
  if (this.#scheduleRegistered) {
@@ -152,9 +151,7 @@ export class Capability implements CapabilityExport {
152
151
  this.#scheduleRegistered = true;
153
152
 
154
153
  // Pass back any ready callback to the controller
155
- return {
156
- scheduleStore: this.#scheduleStore,
157
- };
154
+ return this.#scheduleStore;
158
155
  };
159
156
 
160
157
  /**
@@ -162,7 +159,7 @@ export class Capability implements CapabilityExport {
162
159
  *
163
160
  * @param store
164
161
  */
165
- registerStore = () => {
162
+ registerStore = (): Storage => {
166
163
  Log.info(`Registering store for ${this.#name}`);
167
164
 
168
165
  if (this.#registered) {
@@ -172,9 +169,7 @@ export class Capability implements CapabilityExport {
172
169
  this.#registered = true;
173
170
 
174
171
  // Pass back any ready callback to the controller
175
- return {
176
- store: this.#store,
177
- };
172
+ return this.#store;
178
173
  };
179
174
 
180
175
  /**
@@ -337,7 +332,7 @@ export class Capability implements CapabilityExport {
337
332
  event: Event.Update,
338
333
  finalizeCallback: async (update: InstanceType<T>, logger = aliasLogger) => {
339
334
  Log.info(`Executing finalize action with alias: ${binding.alias || "no alias provided"}`);
340
- await finalizeCallback(update, logger);
335
+ return await finalizeCallback(update, logger);
341
336
  },
342
337
  };
343
338
  bindings.push(watchBinding);
@@ -12,7 +12,7 @@ import { metricsCollector, MetricsCollector } from "../metrics";
12
12
  import { ModuleConfig, isWatchMode } from "../module";
13
13
  import { mutateProcessor } from "../mutate-processor";
14
14
  import { validateProcessor } from "../validate-processor";
15
- import { PeprControllerStore } from "./store";
15
+ import { StoreController } from "./store";
16
16
  import { ResponseItem, AdmissionRequest } from "../types";
17
17
 
18
18
  if (!process.env.PEPR_NODE_WARNINGS) {
@@ -48,12 +48,12 @@ export class Controller {
48
48
  this.#capabilities = capabilities;
49
49
 
50
50
  // Initialize the Pepr store for each capability
51
- new PeprControllerStore(capabilities, `pepr-${config.uuid}-store`, () => {
51
+ new StoreController(capabilities, `pepr-${config.uuid}-store`, () => {
52
52
  this.#bindEndpoints();
53
53
  onReady && onReady();
54
54
  Log.info("✅ Controller startup complete");
55
55
  // Initialize the schedule store for each capability
56
- new PeprControllerStore(capabilities, `pepr-${config.uuid}-schedule`, () => {
56
+ new StoreController(capabilities, `pepr-${config.uuid}-schedule`, () => {
57
57
  Log.info("✅ Scheduling processed");
58
58
  });
59
59
  });