@a5c-ai/krate 5.0.1-staging.660d2b90f → 5.0.1-staging.69cb593ea

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 (118) hide show
  1. package/Dockerfile +31 -29
  2. package/bin/krate-demo.mjs +0 -0
  3. package/bin/krate-server.mjs +0 -0
  4. package/dist/krate-controller-ui.json +808 -10
  5. package/dist/krate-lifecycle.json +1 -1
  6. package/dist/krate-runtime-snapshot.json +223 -53
  7. package/dist/krate-summary.json +40 -3
  8. package/docs/agents/gaps-agent-mux-to-krate-crds.md +298 -0
  9. package/docs/architecture-v2.md +431 -0
  10. package/docs/openapi.yaml +1275 -0
  11. package/docs/requirements-v2.md +238 -0
  12. package/docs/sdk-api-reference.md +782 -0
  13. package/docs/system-spec-v2.md +352 -0
  14. package/docs/todos.md +4 -0
  15. package/docs/web-console-spec.md +433 -0
  16. package/package.json +1 -1
  17. package/scripts/validate-ui.mjs +305 -207
  18. package/src/agent-adapter-controller.js +169 -0
  19. package/src/agent-approval-controller.js +47 -0
  20. package/src/agent-dispatch-controller.js +130 -7
  21. package/src/agent-gateway-config-controller.js +147 -0
  22. package/src/agent-memory-controller.js +357 -0
  23. package/src/agent-memory-import.js +327 -0
  24. package/src/agent-memory-query.js +292 -0
  25. package/src/agent-memory-repository-source-controller.js +255 -0
  26. package/src/agent-mux-client.js +1 -1
  27. package/src/agent-permission-review.js +102 -14
  28. package/src/agent-project-controller.js +117 -0
  29. package/src/agent-provider-config-controller.js +150 -0
  30. package/src/agent-secret-config-grant-controller.js +282 -0
  31. package/src/agent-session-transcript-controller.js +189 -0
  32. package/src/agent-stack-controller.js +52 -1
  33. package/src/agent-subagent-controller.js +160 -0
  34. package/src/agent-transport-binding-controller.js +121 -0
  35. package/src/agent-trigger-controller.js +273 -0
  36. package/src/agent-workspace-controller.js +702 -0
  37. package/src/agent-writeback-controller.js +302 -0
  38. package/src/api-controller.js +338 -3
  39. package/src/async-controller.js +207 -0
  40. package/src/audit-controller.js +191 -0
  41. package/src/auth.js +48 -6
  42. package/src/controller-client.js +112 -38
  43. package/src/controller-ui.js +96 -16
  44. package/src/data-plane.js +3 -2
  45. package/src/event-bus.js +61 -0
  46. package/src/external/conflict-controller.js +225 -0
  47. package/src/external/github/auth.js +96 -0
  48. package/src/external/github/cicd.js +180 -0
  49. package/src/external/github/git-forge.js +240 -0
  50. package/src/external/github/index.js +144 -0
  51. package/src/external/github/issue-tracking.js +163 -0
  52. package/src/external/provider-adapter.js +161 -0
  53. package/src/external/provider-resource-factory.js +161 -0
  54. package/src/external/sync-controller.js +235 -0
  55. package/src/external/webhook-controller.js +144 -0
  56. package/src/external/write-controller.js +283 -0
  57. package/src/gitea-backend.js +36 -0
  58. package/src/gitea-service.js +173 -0
  59. package/src/http-server.js +226 -0
  60. package/src/index.js +27 -0
  61. package/src/kubernetes-controller-async.js +531 -0
  62. package/src/kubernetes-controller.js +156 -84
  63. package/src/notification-controller.js +178 -0
  64. package/src/org-scoping.js +5 -0
  65. package/src/resource-model.js +26 -8
  66. package/src/runner-controller.js +272 -0
  67. package/src/snapshot-cache.js +157 -0
  68. package/tests/agent-adapter-controller.test.js +361 -0
  69. package/tests/agent-dispatch-controller.test.js +139 -0
  70. package/tests/agent-gateway-config-controller.test.js +386 -0
  71. package/tests/agent-memory-controller.test.js +308 -0
  72. package/tests/agent-memory-import-snapshot.test.js +477 -0
  73. package/tests/agent-memory-query.test.js +404 -0
  74. package/tests/agent-memory-repository-source.test.js +514 -0
  75. package/tests/agent-permission-review-v2.test.js +317 -0
  76. package/tests/agent-project-controller.test.js +302 -0
  77. package/tests/agent-provider-config-controller.test.js +376 -0
  78. package/tests/agent-resources.test.js +35 -19
  79. package/tests/agent-secret-config-grant.test.js +231 -0
  80. package/tests/agent-session-transcript-controller.test.js +499 -0
  81. package/tests/agent-subagent-controller.test.js +201 -0
  82. package/tests/agent-transport-binding-controller.test.js +294 -0
  83. package/tests/agent-trigger-routes.test.js +190 -0
  84. package/tests/agent-trigger-sources.test.js +245 -0
  85. package/tests/agent-workspace-controller.test.js +181 -0
  86. package/tests/agent-writeback.test.js +292 -0
  87. package/tests/approval-persistence.test.js +171 -0
  88. package/tests/async-controller.test.js +252 -0
  89. package/tests/audit-controller.test.js +227 -0
  90. package/tests/codespace-controller.test.js +318 -0
  91. package/tests/controller-client.test.js +133 -0
  92. package/tests/deployment.test.js +43 -29
  93. package/tests/e2e/lifecycle.test.js +5 -2
  94. package/tests/event-bus-integration.test.js +190 -0
  95. package/tests/external-github-forge.test.js +560 -0
  96. package/tests/external-github-issues-cicd.test.js +520 -0
  97. package/tests/external-integration.test.js +470 -0
  98. package/tests/external-persistence.test.js +340 -0
  99. package/tests/external-provider-adapter.test.js +365 -0
  100. package/tests/external-resource-model.test.js +215 -0
  101. package/tests/external-webhook-sync.test.js +287 -0
  102. package/tests/external-write-conflict.test.js +353 -0
  103. package/tests/gitea-service.test.js +253 -0
  104. package/tests/health-check-real.test.js +165 -0
  105. package/tests/integration/full-flow.test.js +266 -0
  106. package/tests/krate.test.js +58 -6
  107. package/tests/memory-search-wiring.test.js +270 -0
  108. package/tests/notification-controller.test.js +196 -0
  109. package/tests/notification-integration.test.js +179 -0
  110. package/tests/org-scoping.test.js +687 -0
  111. package/tests/runner-controller.test.js +327 -0
  112. package/tests/runner-integration.test.js +231 -0
  113. package/tests/session-cookie-hmac.test.js +151 -0
  114. package/tests/snapshot-performance.test.js +315 -0
  115. package/tests/sse-events.test.js +107 -0
  116. package/tests/webhook-trigger.test.js +198 -0
  117. package/tests/workspace-volumes.test.js +312 -0
  118. package/tests/writeback-persistence.test.js +207 -0
@@ -0,0 +1,121 @@
1
+ // Agent Transport Binding Controller — Slice 1.2b
2
+ // Manages AgentTransportBinding resources: connection config validation,
3
+ // health status tracking, and reconnect policy enforcement.
4
+
5
+ export const AGENT_TRANSPORT_BINDING_CONTROLLER_BOUNDARY = {
6
+ role: 'agent-transport-binding-controller',
7
+ scope: 'AgentTransportBinding lifecycle: validation, connection status tracking, reconnect policy enforcement',
8
+ owns: ['binding validation', 'connection status tracking', 'reconnect policy enforcement'],
9
+ delegatesTo: ['resource-model', 'agent-adapter-controller'],
10
+ mustNotOwn: ['secret values', 'dispatch execution', 'Agent Mux sessions', 'adapter implementation']
11
+ };
12
+
13
+ const VALID_PROTOCOLS = ['stdio', 'http', 'websocket', 'unix'];
14
+
15
+ const DEFAULT_RECONNECT_POLICY = Object.freeze({
16
+ maxRetries: 3,
17
+ backoffMs: 1000,
18
+ maxBackoffMs: 30000
19
+ });
20
+
21
+ /**
22
+ * Validate an AgentTransportBinding resource. Returns { valid, errors }.
23
+ * @param {object} resource
24
+ * @returns {{ valid: boolean, errors: string[] }}
25
+ */
26
+ export function validateAgentTransportBinding(resource) {
27
+ const errors = [];
28
+
29
+ // Guard against null/undefined resource
30
+ if (resource == null) {
31
+ errors.push('resource must not be null or undefined');
32
+ return { valid: false, errors };
33
+ }
34
+
35
+ // Validate metadata.name
36
+ if (!resource?.metadata?.name) {
37
+ errors.push('metadata.name is required');
38
+ }
39
+
40
+ const spec = resource?.spec || {};
41
+
42
+ // Validate adapterRef
43
+ if (!spec.adapterRef) {
44
+ errors.push('spec.adapterRef is required');
45
+ }
46
+
47
+ // Validate endpoint
48
+ if (!spec.endpoint) {
49
+ errors.push('spec.endpoint is required');
50
+ }
51
+
52
+ // Validate protocol
53
+ const protocol = spec.protocol;
54
+ if (!protocol) {
55
+ errors.push(`spec.protocol is required; valid protocols are: ${VALID_PROTOCOLS.join(', ')}`);
56
+ } else if (!VALID_PROTOCOLS.includes(protocol)) {
57
+ errors.push(`spec.protocol "${protocol}" is not supported; valid protocols are: ${VALID_PROTOCOLS.join(', ')}`);
58
+ }
59
+
60
+ return { valid: errors.length === 0, errors };
61
+ }
62
+
63
+ /**
64
+ * Factory that returns an AgentTransportBinding controller instance.
65
+ */
66
+ export function createAgentTransportBindingController() {
67
+ return {
68
+ role: 'agent-transport-binding-controller',
69
+
70
+ /**
71
+ * Validate an AgentTransportBinding resource.
72
+ * @param {object} resource
73
+ * @returns {{ valid: boolean, errors: string[] }}
74
+ */
75
+ validate(resource) {
76
+ return validateAgentTransportBinding(resource);
77
+ },
78
+
79
+ /**
80
+ * Return the current connection status for a transport binding.
81
+ * Reads from resource.status.connectionStatus when available,
82
+ * otherwise returns 'unknown'.
83
+ * @param {object} resource
84
+ * @returns {{ bindingName: string, connectionStatus: string }}
85
+ */
86
+ getConnectionStatus(resource) {
87
+ if (resource == null) {
88
+ throw new Error('resource must not be null or undefined');
89
+ }
90
+ const bindingName = resource?.metadata?.name;
91
+ const connectionStatus = resource?.status?.connectionStatus ?? 'unknown';
92
+ return { bindingName, connectionStatus };
93
+ },
94
+
95
+ /**
96
+ * Return the reconnect policy for a transport binding.
97
+ * Merges spec.reconnectPolicy values with defaults.
98
+ * @param {object} resource
99
+ * @returns {{ maxRetries: number, backoffMs: number, maxBackoffMs: number }}
100
+ */
101
+ getReconnectPolicy(resource) {
102
+ if (resource == null) {
103
+ throw new Error('resource must not be null or undefined');
104
+ }
105
+ const specPolicy = resource?.spec?.reconnectPolicy ?? {};
106
+ return {
107
+ maxRetries: specPolicy.maxRetries ?? DEFAULT_RECONNECT_POLICY.maxRetries,
108
+ backoffMs: specPolicy.backoffMs ?? DEFAULT_RECONNECT_POLICY.backoffMs,
109
+ maxBackoffMs: specPolicy.maxBackoffMs ?? DEFAULT_RECONNECT_POLICY.maxBackoffMs
110
+ };
111
+ },
112
+
113
+ /**
114
+ * Return the list of supported protocol types.
115
+ * @returns {string[]}
116
+ */
117
+ getSupportedProtocols() {
118
+ return [...VALID_PROTOCOLS];
119
+ }
120
+ };
121
+ }
@@ -1,5 +1,218 @@
1
1
  import { createResource, clone } from './resource-model.js';
2
2
 
3
+ // ── Cron validation helpers ───────────────────────────────────────────────────
4
+
5
+ /**
6
+ * Validate a 5-field cron expression (minute hour dom month dow).
7
+ * Each field must be a non-empty string composed only of digits, '*', '/', '-', and ','.
8
+ * @param {string} expr
9
+ * @returns {{ valid: boolean, error?: string }}
10
+ */
11
+ export function validateCronExpression(expr) {
12
+ if (typeof expr !== 'string' || expr.trim() === '') {
13
+ return { valid: false, error: 'Cron expression must be a non-empty string' };
14
+ }
15
+ const fields = expr.trim().split(/\s+/);
16
+ if (fields.length !== 5) {
17
+ return { valid: false, error: `Cron expression must have exactly 5 fields (got ${fields.length})` };
18
+ }
19
+ // Each field: digits, *, /, -, , only
20
+ const fieldPattern = /^(\*|(\d+|\*)(\/\d+)?)(-(\d+|\*)(\/\d+)?)?(,(\*|(\d+|\*)(\/\d+)?)(-(\d+|\*)(\/\d+)?)?)*$/;
21
+ // Simpler but robust: allow only [0-9*/,-] characters and at least one valid character
22
+ const validChars = /^[0-9*/,\-]+$/;
23
+ for (let i = 0; i < fields.length; i++) {
24
+ if (!validChars.test(fields[i])) {
25
+ return { valid: false, error: `Invalid character in cron field ${i + 1}: "${fields[i]}"` };
26
+ }
27
+ }
28
+ return { valid: true };
29
+ }
30
+
31
+ /**
32
+ * Calculate the next run date/time after `fromDate` for a valid cron expression.
33
+ * Uses a lightweight iterative approach (no external deps) — minute-level precision.
34
+ * Returns null if the expression is invalid.
35
+ * @param {string} cronExpr
36
+ * @param {Date} [fromDate]
37
+ * @returns {Date|null}
38
+ */
39
+ export function calculateNextRun(cronExpr, fromDate) {
40
+ const validation = validateCronExpression(cronExpr);
41
+ if (!validation.valid) return null;
42
+
43
+ const fields = cronExpr.trim().split(/\s+/);
44
+ const [minuteF, hourF, domF, monthF, dowF] = fields;
45
+
46
+ function matchesField(value, fieldStr, min, max) {
47
+ if (fieldStr === '*') return true;
48
+ const parts = fieldStr.split(',');
49
+ return parts.some(part => {
50
+ if (part.includes('/')) {
51
+ const [range, step] = part.split('/');
52
+ const stepNum = parseInt(step, 10);
53
+ const start = range === '*' ? min : parseInt(range.split('-')[0], 10);
54
+ const end = range === '*' ? max : (range.includes('-') ? parseInt(range.split('-')[1], 10) : max);
55
+ if (isNaN(stepNum)) return false;
56
+ for (let v = start; v <= end; v += stepNum) {
57
+ if (v === value) return true;
58
+ }
59
+ return false;
60
+ }
61
+ if (part.includes('-')) {
62
+ const [lo, hi] = part.split('-').map(Number);
63
+ return value >= lo && value <= hi;
64
+ }
65
+ return parseInt(part, 10) === value;
66
+ });
67
+ }
68
+
69
+ // Start from the next minute after fromDate
70
+ const base = fromDate ? new Date(fromDate) : new Date();
71
+ base.setSeconds(0, 0);
72
+ base.setMinutes(base.getMinutes() + 1);
73
+
74
+ // Iterate up to 366 days * 24 * 60 = ~527,040 minutes
75
+ const MAX_ITER = 527040;
76
+ const candidate = new Date(base);
77
+ for (let i = 0; i < MAX_ITER; i++) {
78
+ const min = candidate.getUTCMinutes();
79
+ const hour = candidate.getUTCHours();
80
+ const dom = candidate.getUTCDate();
81
+ const month = candidate.getUTCMonth() + 1; // 1-12
82
+ const dow = candidate.getUTCDay(); // 0-6
83
+
84
+ if (
85
+ matchesField(month, monthF, 1, 12) &&
86
+ matchesField(dom, domF, 1, 31) &&
87
+ matchesField(dow, dowF, 0, 6) &&
88
+ matchesField(hour, hourF, 0, 23) &&
89
+ matchesField(min, minuteF, 0, 59)
90
+ ) {
91
+ return new Date(candidate);
92
+ }
93
+ candidate.setMinutes(candidate.getMinutes() + 1);
94
+ }
95
+
96
+ return null; // No match found within a year
97
+ }
98
+
99
+ // ── Webhook trigger validation ────────────────────────────────────────────────
100
+
101
+ /**
102
+ * Validate a webhook trigger configuration.
103
+ * @param {{ url: string, secretRef?: string }} config
104
+ * @returns {{ valid: boolean, error?: string }}
105
+ */
106
+ export function validateWebhookTrigger(config) {
107
+ if (!config || typeof config !== 'object') {
108
+ return { valid: false, error: 'Webhook trigger config must be an object' };
109
+ }
110
+ if (!config.url || typeof config.url !== 'string' || config.url.trim() === '') {
111
+ return { valid: false, error: 'Webhook trigger config must include a non-empty url' };
112
+ }
113
+ // Only http/https urls are allowed
114
+ try {
115
+ const parsed = new URL(config.url);
116
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
117
+ return { valid: false, error: `Webhook url scheme must be http or https (got "${parsed.protocol.replace(':', '')}")` };
118
+ }
119
+ } catch {
120
+ return { valid: false, error: `Webhook url is not a valid URL: "${config.url}"` };
121
+ }
122
+ return { valid: true };
123
+ }
124
+
125
+ // ── Comment trigger validation ────────────────────────────────────────────────
126
+
127
+ /**
128
+ * Validate a comment-based trigger configuration.
129
+ * @param {{ pattern: string, repos?: string[] }} config
130
+ * @returns {{ valid: boolean, error?: string }}
131
+ */
132
+ export function validateCommentTrigger(config) {
133
+ if (!config || typeof config !== 'object') {
134
+ return { valid: false, error: 'Comment trigger config must be an object' };
135
+ }
136
+ if (!('pattern' in config) || typeof config.pattern !== 'string' || config.pattern.trim() === '') {
137
+ return { valid: false, error: 'Comment trigger config must include a non-empty pattern string' };
138
+ }
139
+ return { valid: true };
140
+ }
141
+
142
+ // ── Label trigger validation ──────────────────────────────────────────────────
143
+
144
+ const VALID_LABEL_ACTIONS = ['labeled', 'unlabeled'];
145
+
146
+ /**
147
+ * Validate a label-based trigger configuration.
148
+ * @param {{ labels: string[], action?: string }} config
149
+ * @returns {{ valid: boolean, error?: string }}
150
+ */
151
+ export function validateLabelTrigger(config) {
152
+ if (!config || typeof config !== 'object') {
153
+ return { valid: false, error: 'Label trigger config must be an object' };
154
+ }
155
+ if (!Array.isArray(config.labels) || config.labels.length === 0) {
156
+ return { valid: false, error: 'Label trigger config must include a non-empty labels array' };
157
+ }
158
+ if (config.action !== undefined && !VALID_LABEL_ACTIONS.includes(config.action)) {
159
+ return { valid: false, error: `Label trigger action must be one of: ${VALID_LABEL_ACTIONS.join(', ')} (got "${config.action}")` };
160
+ }
161
+ return { valid: true };
162
+ }
163
+
164
+ // ── Source type detection ─────────────────────────────────────────────────────
165
+
166
+ /**
167
+ * Determine the source type for a trigger rule based on its spec.
168
+ * @param {{ spec?: object }} rule
169
+ * @returns {'cron'|'webhook'|'comment'|'label'|'event'|'unknown'}
170
+ */
171
+ export function getTriggerSourceType(rule) {
172
+ const spec = rule?.spec || {};
173
+ if (spec.cronExpression !== undefined) return 'cron';
174
+ if (spec.webhookTrigger !== undefined) return 'webhook';
175
+ if (spec.commentTrigger !== undefined) return 'comment';
176
+ if (spec.labelTrigger !== undefined) return 'label';
177
+ if (spec.sources !== undefined) return 'event';
178
+ return 'unknown';
179
+ }
180
+
181
+ // ── Trigger rule validation ───────────────────────────────────────────────────
182
+
183
+ /**
184
+ * Validate an AgentTriggerRule resource, including source-specific sub-configs.
185
+ * @param {object} rule
186
+ * @returns {{ valid: boolean, errors: string[] }}
187
+ */
188
+ export function validateTriggerRule(rule) {
189
+ const errors = [];
190
+ const spec = rule?.spec || {};
191
+ const sourceType = getTriggerSourceType(rule);
192
+
193
+ if (sourceType === 'cron') {
194
+ const cronResult = validateCronExpression(spec.cronExpression);
195
+ if (!cronResult.valid) errors.push(`cronExpression: ${cronResult.error}`);
196
+ } else if (sourceType === 'webhook') {
197
+ const webhookResult = validateWebhookTrigger(spec.webhookTrigger);
198
+ if (!webhookResult.valid) errors.push(`webhookTrigger: ${webhookResult.error}`);
199
+ } else if (sourceType === 'comment') {
200
+ const commentResult = validateCommentTrigger(spec.commentTrigger);
201
+ if (!commentResult.valid) errors.push(`commentTrigger: ${commentResult.error}`);
202
+ } else if (sourceType === 'label') {
203
+ const labelResult = validateLabelTrigger(spec.labelTrigger);
204
+ if (!labelResult.valid) errors.push(`labelTrigger: ${labelResult.error}`);
205
+ } else if (sourceType === 'event') {
206
+ if (!Array.isArray(spec.sources) || spec.sources.length === 0) {
207
+ errors.push('sources: must be a non-empty array');
208
+ }
209
+ } else {
210
+ errors.push('spec must include at least one of: cronExpression, webhookTrigger, commentTrigger, labelTrigger, or sources');
211
+ }
212
+
213
+ return { valid: errors.length === 0, errors };
214
+ }
215
+
3
216
  export const AGENT_TRIGGER_CONTROLLER_BOUNDARY = {
4
217
  role: 'agent-trigger-controller',
5
218
  scope: 'Event normalization, rule matching, deduplication, and dispatch creation',
@@ -54,6 +267,66 @@ export function createAgentTriggerController(options = {}) {
54
267
  return execution;
55
268
  },
56
269
 
270
+ /**
271
+ * Evaluate a normalized inbound webhook event against a set of AgentTriggerRule resources.
272
+ *
273
+ * A rule matches when ALL of:
274
+ * 1. rule.spec.enabled !== false
275
+ * 2. rule.spec.webhookTrigger.events includes event.eventType (or is absent/['*'])
276
+ * 3. rule.spec.webhookTrigger.repository (if set) equals event.repository
277
+ * 4. rule.spec.webhookTrigger.action (if set) equals event.action
278
+ *
279
+ * Duplicate rule names are deduplicated (first occurrence wins).
280
+ *
281
+ * @param {{ eventType: string, repository?: string, ref?: string, action?: string, provider?: string }} event
282
+ * @param {object[]} [rules] Array of AgentTriggerRule resources
283
+ * @returns {{ matchingRules: object[], dispatchIntents: object[] }}
284
+ */
285
+ evaluateWebhookEvent(event, rules) {
286
+ if (!rules || rules.length === 0) {
287
+ return { matchingRules: [], dispatchIntents: [] };
288
+ }
289
+
290
+ const seen = new Set();
291
+ const matchingRules = [];
292
+ const dispatchIntents = [];
293
+
294
+ for (const rule of rules) {
295
+ const ruleName = rule.metadata?.name;
296
+
297
+ // Deduplication
298
+ if (seen.has(ruleName)) continue;
299
+ seen.add(ruleName);
300
+
301
+ // 1. Enabled check
302
+ if (rule.spec?.enabled === false) continue;
303
+
304
+ const wh = rule.spec?.webhookTrigger;
305
+ // Rule must have a webhookTrigger spec to be considered
306
+ if (!wh) continue;
307
+
308
+ // 2. Event type match
309
+ const events = wh.events;
310
+ if (events && !(events.includes('*') || events.includes(event.eventType))) continue;
311
+
312
+ // 3. Repository filter
313
+ if (wh.repository && wh.repository !== event.repository) continue;
314
+
315
+ // 4. Action filter
316
+ if (wh.action && wh.action !== event.action) continue;
317
+
318
+ matchingRules.push(rule);
319
+ dispatchIntents.push({
320
+ rule,
321
+ event,
322
+ agentStack: rule.spec.agentStack,
323
+ taskKind: rule.spec.taskKind || 'diagnostic',
324
+ });
325
+ }
326
+
327
+ return { matchingRules, dispatchIntents };
328
+ },
329
+
57
330
  async processEvent({ event, resources, namespace = 'default', organizationRef = 'default' }) {
58
331
  const evaluations = this.evaluateEvent({ event, resources });
59
332
  const executions = [];