@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 +14 -0
- package/dist/src/mongodb-agent-run-service.d.ts +1 -0
- package/dist/src/mongodb-agent-run-service.js +4 -1
- package/dist/src/mongodb-channel-store.d.ts +3 -0
- package/dist/src/mongodb-channel-store.js +10 -0
- package/dist/src/mongodb-secret-service.d.ts +3 -3
- package/dist/src/mongodb-secret-service.js +18 -7
- package/dist/src/mongodb-workflow-service.d.ts +13 -13
- package/dist/src/mongodb-workflow-service.js +13 -13
- package/package.json +5 -2
- package/src/mongodb-agent-run-service.ts +6 -1
- package/src/mongodb-channel-store.ts +17 -0
- package/src/mongodb-secret-service.ts +24 -17
- package/src/mongodb-services.test.ts +2 -2
- package/src/mongodb-workflow-service.ts +25 -13
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
|
|
@@ -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<
|
|
25
|
-
getSecretJSON<R = {}>(key: string): Promise<R>;
|
|
24
|
+
getSecret<T = string>(key: string): Promise<T>;
|
|
26
25
|
hasSecret(key: string): Promise<boolean>;
|
|
27
|
-
|
|
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
|
|
68
|
-
const
|
|
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
|
-
|
|
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
|
-
|
|
19
|
-
|
|
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
|
-
|
|
28
|
-
|
|
27
|
+
protected setStepRunningImpl(stepId: string): Promise<void>;
|
|
28
|
+
protected setStepScheduledImpl(stepId: string): Promise<void>;
|
|
29
29
|
private insertHistoryRecord;
|
|
30
30
|
private getTimestampFieldForStatus;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
45
|
-
|
|
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
|
-
|
|
48
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
312
|
+
async setBranchTakenImpl(stepId, branchKey) {
|
|
313
313
|
await this.steps.updateOne({ _id: stepId }, { $set: { branchTaken: branchKey, updatedAt: new Date() } });
|
|
314
314
|
}
|
|
315
|
-
async
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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<
|
|
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<
|
|
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
|
|
115
|
-
const
|
|
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.
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
585
|
+
protected async updateWorkflowVersionStatusImpl(
|
|
574
586
|
name: string,
|
|
575
587
|
graphHash: string,
|
|
576
588
|
status: WorkflowVersionStatus
|