@pikku/mongodb 0.12.5 → 0.12.6

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @pikku/mongodb
2
2
 
3
+ ## 0.12.6
4
+
5
+ ### Patch Changes
6
+
7
+ - 4b5c75b: feat(auth-js): wire OIDC config (issuer/tenantId) as variables, expand provider registry
8
+ - Move `issuer` and `tenantId` out of the secret blob for OIDC providers (auth0, okta, azure-ad, keycloak, cognito, microsoft-entra-id) — they are public config URLs, not secrets. Now registered via `wireVariable` and loaded at runtime via `services.variables.get()`.
9
+ - Expand provider registry from 13 to 31 providers: reddit, notion, instagram, zoom, figma, tiktok, threads, patreon, dropbox, bitbucket, hubspot, salesforce, atlassian, strava, keycloak, cognito, microsoft-entra-id added.
10
+ - `serialize-auth-gen` emits `wireVariable({...})` declarations and `services.variables.get()` calls in the generated factory for OIDC providers.
11
+ - Integration verifier exercises real `/auth/providers` endpoint with `LocalSecretService` + `LocalVariablesService`, including a spy test proving `services.variables.get('AUTH0_ISSUER')` is called at request time.
12
+
13
+ - Updated dependencies [4b5c75b]
14
+ - Updated dependencies [4b5c75b]
15
+ - @pikku/core@0.12.27
16
+
3
17
  ## 0.12.5
4
18
 
5
19
  ### Patch Changes
@@ -8,6 +8,7 @@ export declare class MongoDBAgentRunService implements AgentRunService {
8
8
  constructor(db: Db);
9
9
  listThreads(options?: {
10
10
  agentName?: string;
11
+ resourceId?: string;
11
12
  limit?: number;
12
13
  offset?: number;
13
14
  }): Promise<AIThread[]>;
@@ -10,8 +10,11 @@ export class MongoDBAgentRunService {
10
10
  this.runs = db.collection('ai_run');
11
11
  }
12
12
  async listThreads(options) {
13
- const { agentName, limit = 50, offset = 0 } = options ?? {};
13
+ const { agentName, resourceId, limit = 50, offset = 0 } = options ?? {};
14
14
  let filter = {};
15
+ if (resourceId) {
16
+ filter.resourceId = resourceId;
17
+ }
15
18
  if (agentName) {
16
19
  const threadIds = await this.runs.distinct('threadId', {
17
20
  agentName,
@@ -14,5 +14,8 @@ export declare class MongoDBChannelStore extends ChannelStore {
14
14
  getChannel(channelId: string): Promise<Channel & {
15
15
  pikkuUserId?: string;
16
16
  }>;
17
+ setState(channelId: string, state: unknown): Promise<void>;
18
+ getState(channelId: string): Promise<unknown | undefined>;
19
+ clearState(channelId: string): Promise<void>;
17
20
  close(): Promise<void>;
18
21
  }
@@ -48,5 +48,15 @@ export class MongoDBChannelStore extends ChannelStore {
48
48
  pikkuUserId: row.pikkuUserId ?? undefined,
49
49
  };
50
50
  }
51
+ async setState(channelId, state) {
52
+ await this.channels.updateOne({ _id: channelId }, { $set: { state } });
53
+ }
54
+ async getState(channelId) {
55
+ const row = await this.channels.findOne({ _id: channelId }, { projection: { state: 1 } });
56
+ return row?.state ?? undefined;
57
+ }
58
+ async clearState(channelId) {
59
+ await this.channels.updateOne({ _id: channelId }, { $unset: { state: '' } });
60
+ }
51
61
  async close() { }
52
62
  }
@@ -21,10 +21,10 @@ export declare class MongoDBSecretService implements SecretService {
21
21
  init(): Promise<void>;
22
22
  private logAudit;
23
23
  private getKEK;
24
- getSecret(key: string): Promise<string>;
25
- getSecretJSON<R = {}>(key: string): Promise<R>;
24
+ getSecret<T = string>(key: string): Promise<T>;
26
25
  hasSecret(key: string): Promise<boolean>;
27
- setSecretJSON(key: string, value: unknown): Promise<void>;
26
+ setSecret(key: string, value: unknown): Promise<void>;
28
27
  deleteSecret(key: string): Promise<void>;
28
+ getSecrets(keys: string[]): Promise<Record<string, unknown>>;
29
29
  rotateKEK(): Promise<number>;
30
30
  }
@@ -56,17 +56,12 @@ export class MongoDBSecretService {
56
56
  await this.logAudit(key, 'read');
57
57
  return result;
58
58
  }
59
- async getSecretJSON(key) {
60
- const raw = await this.getSecret(key);
61
- return JSON.parse(raw);
62
- }
63
59
  async hasSecret(key) {
64
60
  const count = await this.secrets.countDocuments({ _id: key }, { limit: 1 });
65
61
  return count > 0;
66
62
  }
67
- async setSecretJSON(key, value) {
68
- const plaintext = JSON.stringify(value);
69
- const { ciphertext, wrappedDEK } = await envelopeEncrypt(this.key, plaintext);
63
+ async setSecret(key, value) {
64
+ const { ciphertext, wrappedDEK } = await envelopeEncrypt(this.key, value);
70
65
  const now = new Date();
71
66
  await this.secrets.updateOne({ _id: key }, {
72
67
  $set: {
@@ -86,6 +81,22 @@ export class MongoDBSecretService {
86
81
  await this.secrets.deleteOne({ _id: key });
87
82
  await this.logAudit(key, 'delete');
88
83
  }
84
+ async getSecrets(keys) {
85
+ const rows = await this.secrets
86
+ .find({ _id: { $in: keys } })
87
+ .toArray();
88
+ const out = {};
89
+ for (const row of rows) {
90
+ try {
91
+ const kek = this.getKEK(row.keyVersion);
92
+ out[row._id] = await envelopeDecrypt(kek, row.ciphertext, row.wrappedDek);
93
+ }
94
+ catch {
95
+ // skip secrets that fail to decrypt
96
+ }
97
+ }
98
+ return out;
99
+ }
89
100
  async rotateKEK() {
90
101
  if (!this.previousKey) {
91
102
  throw new Error('No previousKey configured — nothing to rotate from');
@@ -10,13 +10,13 @@ export declare class MongoDBWorkflowService extends PikkuWorkflowService {
10
10
  private versions;
11
11
  constructor(db: Db);
12
12
  init(): Promise<void>;
13
- createRun(workflowName: string, input: any, inline: boolean, graphHash: string, wire: WorkflowRunWire, options?: {
13
+ protected createRunImpl(workflowName: string, input: any, inline: boolean, graphHash: string, wire: WorkflowRunWire, options?: {
14
14
  deterministic?: boolean;
15
15
  plannedSteps?: WorkflowPlannedStep[];
16
16
  }): Promise<string>;
17
17
  getRun(id: string): Promise<WorkflowRun | null>;
18
- updateRunStatus(id: string, status: WorkflowStatus, output?: any, error?: SerializedError): Promise<void>;
19
- insertStepState(runId: string, stepName: string, rpcName: string | null, data: any, stepOptions?: {
18
+ protected updateRunStatusImpl(id: string, status: WorkflowStatus, output?: any, error?: SerializedError): Promise<void>;
19
+ protected insertStepStateImpl(runId: string, stepName: string, rpcName: string | null, data: any, stepOptions?: {
20
20
  retries?: number;
21
21
  retryDelay?: string | number;
22
22
  }): Promise<StepState>;
@@ -24,14 +24,14 @@ export declare class MongoDBWorkflowService extends PikkuWorkflowService {
24
24
  getRunHistory(runId: string): Promise<Array<StepState & {
25
25
  stepName: string;
26
26
  }>>;
27
- setStepRunning(stepId: string): Promise<void>;
28
- setStepScheduled(stepId: string): Promise<void>;
27
+ protected setStepRunningImpl(stepId: string): Promise<void>;
28
+ protected setStepScheduledImpl(stepId: string): Promise<void>;
29
29
  private insertHistoryRecord;
30
30
  private getTimestampFieldForStatus;
31
- setStepChildRunId(stepId: string, childRunId: string): Promise<void>;
32
- setStepResult(stepId: string, result: any): Promise<void>;
33
- setStepError(stepId: string, error: Error): Promise<void>;
34
- createRetryAttempt(stepId: string, status: 'pending' | 'running'): Promise<StepState>;
31
+ protected setStepChildRunIdImpl(stepId: string, childRunId: string): Promise<void>;
32
+ protected setStepResultImpl(stepId: string, result: any): Promise<void>;
33
+ protected setStepErrorImpl(stepId: string, error: Error): Promise<void>;
34
+ protected createRetryAttemptImpl(stepId: string, status: 'pending' | 'running'): Promise<StepState>;
35
35
  withRunLock<T>(id: string, fn: () => Promise<T>): Promise<T>;
36
36
  withStepLock<T>(_runId: string, _stepName: string, fn: () => Promise<T>): Promise<T>;
37
37
  getCompletedGraphState(runId: string): Promise<{
@@ -41,11 +41,11 @@ export declare class MongoDBWorkflowService extends PikkuWorkflowService {
41
41
  }>;
42
42
  getNodesWithoutSteps(runId: string, nodeIds: string[]): Promise<string[]>;
43
43
  getNodeResults(runId: string, nodeIds: string[]): Promise<Record<string, any>>;
44
- setBranchTaken(stepId: string, branchKey: string): Promise<void>;
45
- updateRunState(runId: string, name: string, value: unknown): Promise<void>;
44
+ protected setBranchTakenImpl(stepId: string, branchKey: string): Promise<void>;
45
+ protected updateRunStateImpl(runId: string, name: string, value: unknown): Promise<void>;
46
46
  getRunState(runId: string): Promise<Record<string, unknown>>;
47
- upsertWorkflowVersion(name: string, graphHash: string, graph: any, source: string, status?: WorkflowVersionStatus): Promise<void>;
48
- updateWorkflowVersionStatus(name: string, graphHash: string, status: WorkflowVersionStatus): Promise<void>;
47
+ protected upsertWorkflowVersionImpl(name: string, graphHash: string, graph: any, source: string, status?: WorkflowVersionStatus): Promise<void>;
48
+ protected updateWorkflowVersionStatusImpl(name: string, graphHash: string, status: WorkflowVersionStatus): Promise<void>;
49
49
  getWorkflowVersion(name: string, graphHash: string): Promise<{
50
50
  graph: any;
51
51
  source: string;
@@ -28,7 +28,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
28
28
  await this.versions.createIndex({ workflowName: 1, graphHash: 1 }, { unique: true });
29
29
  this.initialized = true;
30
30
  }
31
- async createRun(workflowName, input, inline, graphHash, wire, options) {
31
+ async createRunImpl(workflowName, input, inline, graphHash, wire, options) {
32
32
  const id = crypto.randomUUID();
33
33
  const now = new Date();
34
34
  await this.runs.insertOne({
@@ -52,7 +52,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
52
52
  async getRun(id) {
53
53
  return this.runService.getRun(id);
54
54
  }
55
- async updateRunStatus(id, status, output, error) {
55
+ async updateRunStatusImpl(id, status, output, error) {
56
56
  await this.runs.updateOne({ _id: id }, {
57
57
  $set: {
58
58
  status,
@@ -62,7 +62,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
62
62
  },
63
63
  });
64
64
  }
65
- async insertStepState(runId, stepName, rpcName, data, stepOptions) {
65
+ async insertStepStateImpl(runId, stepName, rpcName, data, stepOptions) {
66
66
  const stepId = crypto.randomUUID();
67
67
  const now = new Date();
68
68
  await this.steps.insertOne({
@@ -119,7 +119,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
119
119
  async getRunHistory(runId) {
120
120
  return this.runService.getRunHistory(runId);
121
121
  }
122
- async setStepRunning(stepId) {
122
+ async setStepRunningImpl(stepId) {
123
123
  await this.steps.updateOne({ _id: stepId }, { $set: { status: 'running', updatedAt: new Date() } });
124
124
  const latestHistory = await this.stepHistory
125
125
  .find({ workflowStepId: stepId })
@@ -130,7 +130,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
130
130
  await this.stepHistory.updateOne({ _id: latestHistory[0]._id }, { $set: { status: 'running' } });
131
131
  }
132
132
  }
133
- async setStepScheduled(stepId) {
133
+ async setStepScheduledImpl(stepId) {
134
134
  await this.steps.updateOne({ _id: stepId }, { $set: { status: 'scheduled', updatedAt: new Date() } });
135
135
  }
136
136
  async insertHistoryRecord(stepId, status, result, error) {
@@ -167,7 +167,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
167
167
  return 'createdAt';
168
168
  }
169
169
  }
170
- async setStepChildRunId(stepId, childRunId) {
170
+ async setStepChildRunIdImpl(stepId, childRunId) {
171
171
  await this.steps.updateOne({ _id: stepId }, {
172
172
  $set: {
173
173
  childRunId,
@@ -175,7 +175,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
175
175
  },
176
176
  });
177
177
  }
178
- async setStepResult(stepId, result) {
178
+ async setStepResultImpl(stepId, result) {
179
179
  await this.steps.updateOne({ _id: stepId }, {
180
180
  $set: {
181
181
  status: 'succeeded',
@@ -193,7 +193,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
193
193
  await this.stepHistory.updateOne({ _id: latestHistory[0]._id }, { $set: { status: 'succeeded', result } });
194
194
  }
195
195
  }
196
- async setStepError(stepId, error) {
196
+ async setStepErrorImpl(stepId, error) {
197
197
  const serializedError = {
198
198
  message: error.message,
199
199
  stack: error.stack,
@@ -216,7 +216,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
216
216
  await this.stepHistory.updateOne({ _id: latestHistory[0]._id }, { $set: { status: 'failed', error: serializedError } });
217
217
  }
218
218
  }
219
- async createRetryAttempt(stepId, status) {
219
+ async createRetryAttemptImpl(stepId, status) {
220
220
  await this.steps.updateOne({ _id: stepId }, {
221
221
  $set: {
222
222
  status,
@@ -309,10 +309,10 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
309
309
  }
310
310
  return results;
311
311
  }
312
- async setBranchTaken(stepId, branchKey) {
312
+ async setBranchTakenImpl(stepId, branchKey) {
313
313
  await this.steps.updateOne({ _id: stepId }, { $set: { branchTaken: branchKey, updatedAt: new Date() } });
314
314
  }
315
- async updateRunState(runId, name, value) {
315
+ async updateRunStateImpl(runId, name, value) {
316
316
  if (!/^[a-zA-Z0-9_]+$/.test(name)) {
317
317
  throw new Error('Invalid state key name');
318
318
  }
@@ -329,7 +329,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
329
329
  return {};
330
330
  return row.state ?? {};
331
331
  }
332
- async upsertWorkflowVersion(name, graphHash, graph, source, status) {
332
+ async upsertWorkflowVersionImpl(name, graphHash, graph, source, status) {
333
333
  await this.versions.updateOne({ workflowName: name, graphHash }, {
334
334
  $setOnInsert: {
335
335
  workflowName: name,
@@ -341,7 +341,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
341
341
  },
342
342
  }, { upsert: true });
343
343
  }
344
- async updateWorkflowVersionStatus(name, graphHash, status) {
344
+ async updateWorkflowVersionStatusImpl(name, graphHash, status) {
345
345
  await this.versions.updateOne({ workflowName: name, graphHash }, { $set: { status } });
346
346
  }
347
347
  async getWorkflowVersion(name, graphHash) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/mongodb",
3
- "version": "0.12.5",
3
+ "version": "0.12.6",
4
4
  "author": "yasser.fadl@gmail.com",
5
5
  "license": "MIT",
6
6
  "module": "dist/src/index.js",
@@ -17,7 +17,7 @@
17
17
  "prepublishOnly": "yarn build"
18
18
  },
19
19
  "peerDependencies": {
20
- "@pikku/core": "^0.12.19"
20
+ "@pikku/core": "^0.12.27"
21
21
  },
22
22
  "dependencies": {
23
23
  "mongodb": "^6.12.0"
@@ -26,5 +26,8 @@
26
26
  "mongodb": "^6.12.0",
27
27
  "mongodb-memory-server": "^10.4.0",
28
28
  "typescript": "^5.9"
29
+ },
30
+ "exports": {
31
+ ".": "./dist/src/index.js"
29
32
  }
30
33
  }
@@ -70,13 +70,18 @@ export class MongoDBAgentRunService implements AgentRunService {
70
70
 
71
71
  async listThreads(options?: {
72
72
  agentName?: string
73
+ resourceId?: string
73
74
  limit?: number
74
75
  offset?: number
75
76
  }): Promise<AIThread[]> {
76
- const { agentName, limit = 50, offset = 0 } = options ?? {}
77
+ const { agentName, resourceId, limit = 50, offset = 0 } = options ?? {}
77
78
 
78
79
  let filter: Record<string, any> = {}
79
80
 
81
+ if (resourceId) {
82
+ filter.resourceId = resourceId
83
+ }
84
+
80
85
  if (agentName) {
81
86
  const threadIds = await this.runs.distinct('threadId', {
82
87
  agentName,
@@ -8,6 +8,7 @@ interface ChannelDoc {
8
8
  createdAt: Date
9
9
  openingData: any
10
10
  pikkuUserId: string | null
11
+ state?: unknown
11
12
  lastWire: Date
12
13
  }
13
14
 
@@ -88,5 +89,21 @@ export class MongoDBChannelStore extends ChannelStore {
88
89
  }
89
90
  }
90
91
 
92
+ public async setState(channelId: string, state: unknown): Promise<void> {
93
+ await this.channels.updateOne({ _id: channelId }, { $set: { state } })
94
+ }
95
+
96
+ public async getState(channelId: string): Promise<unknown | undefined> {
97
+ const row = await this.channels.findOne(
98
+ { _id: channelId },
99
+ { projection: { state: 1 } }
100
+ )
101
+ return row?.state ?? undefined
102
+ }
103
+
104
+ public async clearState(channelId: string): Promise<void> {
105
+ await this.channels.updateOne({ _id: channelId }, { $unset: { state: '' } })
106
+ }
107
+
91
108
  public async close(): Promise<void> {}
92
109
  }
@@ -87,36 +87,23 @@ export class MongoDBSecretService implements SecretService {
87
87
  throw new Error(`No KEK available for key_version ${version}`)
88
88
  }
89
89
 
90
- async getSecret(key: string): Promise<string> {
90
+ async getSecret<T = string>(key: string): Promise<T> {
91
91
  const row = await this.secrets.findOne({ _id: key })
92
92
  if (!row) throw new Error('Requested secret not found')
93
93
 
94
94
  const kek = this.getKEK(row.keyVersion)
95
- const result = await envelopeDecrypt<string>(
96
- kek,
97
- row.ciphertext,
98
- row.wrappedDek
99
- )
95
+ const result = await envelopeDecrypt<T>(kek, row.ciphertext, row.wrappedDek)
100
96
  await this.logAudit(key, 'read')
101
97
  return result
102
98
  }
103
99
 
104
- async getSecretJSON<R = {}>(key: string): Promise<R> {
105
- const raw = await this.getSecret(key)
106
- return JSON.parse(raw) as R
107
- }
108
-
109
100
  async hasSecret(key: string): Promise<boolean> {
110
101
  const count = await this.secrets.countDocuments({ _id: key }, { limit: 1 })
111
102
  return count > 0
112
103
  }
113
104
 
114
- async setSecretJSON(key: string, value: unknown): Promise<void> {
115
- const plaintext = JSON.stringify(value)
116
- const { ciphertext, wrappedDEK } = await envelopeEncrypt(
117
- this.key,
118
- plaintext
119
- )
105
+ async setSecret(key: string, value: unknown): Promise<void> {
106
+ const { ciphertext, wrappedDEK } = await envelopeEncrypt(this.key, value)
120
107
  const now = new Date()
121
108
 
122
109
  await this.secrets.updateOne(
@@ -144,6 +131,26 @@ export class MongoDBSecretService implements SecretService {
144
131
  await this.logAudit(key, 'delete')
145
132
  }
146
133
 
134
+ async getSecrets(keys: string[]): Promise<Record<string, unknown>> {
135
+ const rows = await this.secrets
136
+ .find({ _id: { $in: keys } } as any)
137
+ .toArray()
138
+ const out: Record<string, unknown> = {}
139
+ for (const row of rows) {
140
+ try {
141
+ const kek = this.getKEK(row.keyVersion)
142
+ out[row._id] = await envelopeDecrypt(
143
+ kek,
144
+ row.ciphertext,
145
+ row.wrappedDek
146
+ )
147
+ } catch {
148
+ // skip secrets that fail to decrypt
149
+ }
150
+ }
151
+ return out
152
+ }
153
+
147
154
  async rotateKEK(): Promise<number> {
148
155
  if (!this.previousKey) {
149
156
  throw new Error('No previousKey configured — nothing to rotate from')
@@ -71,7 +71,7 @@ function registerTests(name: string, getDb: () => Db) {
71
71
  auditReads: true,
72
72
  })
73
73
  await service.init()
74
- await service.setSecretJSON('audit-test', 'value')
74
+ await service.setSecret('audit-test', 'value')
75
75
  await service.getSecret('audit-test')
76
76
  await service.deleteSecret('audit-test')
77
77
 
@@ -94,7 +94,7 @@ function registerTests(name: string, getDb: () => Db) {
94
94
  auditReads: false,
95
95
  })
96
96
  await service.init()
97
- await service.setSecretJSON('no-read-audit', 'value')
97
+ await service.setSecret('no-read-audit', 'value')
98
98
  await service.getSecret('no-read-audit')
99
99
 
100
100
  const logs = await getDb()
@@ -110,7 +110,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
110
110
  this.initialized = true
111
111
  }
112
112
 
113
- async createRun(
113
+ protected async createRunImpl(
114
114
  workflowName: string,
115
115
  input: any,
116
116
  inline: boolean,
@@ -148,7 +148,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
148
148
  return this.runService.getRun(id)
149
149
  }
150
150
 
151
- async updateRunStatus(
151
+ protected async updateRunStatusImpl(
152
152
  id: string,
153
153
  status: WorkflowStatus,
154
154
  output?: any,
@@ -167,7 +167,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
167
167
  )
168
168
  }
169
169
 
170
- async insertStepState(
170
+ protected async insertStepStateImpl(
171
171
  runId: string,
172
172
  stepName: string,
173
173
  rpcName: string | null,
@@ -243,7 +243,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
243
243
  return this.runService.getRunHistory(runId)
244
244
  }
245
245
 
246
- async setStepRunning(stepId: string): Promise<void> {
246
+ protected async setStepRunningImpl(stepId: string): Promise<void> {
247
247
  await this.steps.updateOne(
248
248
  { _id: stepId },
249
249
  { $set: { status: 'running', updatedAt: new Date() } }
@@ -263,7 +263,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
263
263
  }
264
264
  }
265
265
 
266
- async setStepScheduled(stepId: string): Promise<void> {
266
+ protected async setStepScheduledImpl(stepId: string): Promise<void> {
267
267
  await this.steps.updateOne(
268
268
  { _id: stepId },
269
269
  { $set: { status: 'scheduled', updatedAt: new Date() } }
@@ -313,7 +313,10 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
313
313
  }
314
314
  }
315
315
 
316
- async setStepChildRunId(stepId: string, childRunId: string): Promise<void> {
316
+ protected async setStepChildRunIdImpl(
317
+ stepId: string,
318
+ childRunId: string
319
+ ): Promise<void> {
317
320
  await this.steps.updateOne(
318
321
  { _id: stepId },
319
322
  {
@@ -325,7 +328,10 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
325
328
  )
326
329
  }
327
330
 
328
- async setStepResult(stepId: string, result: any): Promise<void> {
331
+ protected async setStepResultImpl(
332
+ stepId: string,
333
+ result: any
334
+ ): Promise<void> {
329
335
  await this.steps.updateOne(
330
336
  { _id: stepId },
331
337
  {
@@ -352,7 +358,10 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
352
358
  }
353
359
  }
354
360
 
355
- async setStepError(stepId: string, error: Error): Promise<void> {
361
+ protected async setStepErrorImpl(
362
+ stepId: string,
363
+ error: Error
364
+ ): Promise<void> {
356
365
  const serializedError: SerializedError = {
357
366
  message: error.message,
358
367
  stack: error.stack,
@@ -385,7 +394,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
385
394
  }
386
395
  }
387
396
 
388
- async createRetryAttempt(
397
+ protected async createRetryAttemptImpl(
389
398
  stepId: string,
390
399
  status: 'pending' | 'running'
391
400
  ): Promise<StepState> {
@@ -512,14 +521,17 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
512
521
  return results
513
522
  }
514
523
 
515
- async setBranchTaken(stepId: string, branchKey: string): Promise<void> {
524
+ protected async setBranchTakenImpl(
525
+ stepId: string,
526
+ branchKey: string
527
+ ): Promise<void> {
516
528
  await this.steps.updateOne(
517
529
  { _id: stepId },
518
530
  { $set: { branchTaken: branchKey, updatedAt: new Date() } }
519
531
  )
520
532
  }
521
533
 
522
- async updateRunState(
534
+ protected async updateRunStateImpl(
523
535
  runId: string,
524
536
  name: string,
525
537
  value: unknown
@@ -547,7 +559,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
547
559
  return row.state ?? {}
548
560
  }
549
561
 
550
- async upsertWorkflowVersion(
562
+ protected async upsertWorkflowVersionImpl(
551
563
  name: string,
552
564
  graphHash: string,
553
565
  graph: any,
@@ -570,7 +582,7 @@ export class MongoDBWorkflowService extends PikkuWorkflowService {
570
582
  )
571
583
  }
572
584
 
573
- async updateWorkflowVersionStatus(
585
+ protected async updateWorkflowVersionStatusImpl(
574
586
  name: string,
575
587
  graphHash: string,
576
588
  status: WorkflowVersionStatus