@bevel-software/platform-core-backend 0.3.0 → 0.3.1

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 (27) hide show
  1. package/dist/core/create-core-services.d.ts.map +1 -1
  2. package/dist/core/create-core-services.js +5 -0
  3. package/dist/core/create-core-services.js.map +1 -1
  4. package/dist/modules/auth/account.routes.d.ts +2 -2
  5. package/dist/modules/auth/account.routes.d.ts.map +1 -1
  6. package/dist/modules/auth/account.routes.js +3 -0
  7. package/dist/modules/auth/account.routes.js.map +1 -1
  8. package/dist/modules/mcp/manual-failure-memo.d.ts +38 -0
  9. package/dist/modules/mcp/manual-failure-memo.d.ts.map +1 -0
  10. package/dist/modules/mcp/manual-failure-memo.js +65 -0
  11. package/dist/modules/mcp/manual-failure-memo.js.map +1 -0
  12. package/dist/modules/mcp/mcp.service.d.ts +12 -0
  13. package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
  14. package/dist/modules/mcp/mcp.service.js +37 -4
  15. package/dist/modules/mcp/mcp.service.js.map +1 -1
  16. package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts +3 -0
  17. package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts.map +1 -1
  18. package/dist/modules/secrets-vault/db-secrets-vault.service.js +28 -0
  19. package/dist/modules/secrets-vault/db-secrets-vault.service.js.map +1 -1
  20. package/package.json +2 -2
  21. package/src/core/create-core-services.ts +5 -0
  22. package/src/modules/auth/__tests__/account.routes.test.ts +16 -3
  23. package/src/modules/auth/account.routes.ts +8 -2
  24. package/src/modules/mcp/__tests__/manual-failure-memo.test.ts +54 -0
  25. package/src/modules/mcp/manual-failure-memo.ts +67 -0
  26. package/src/modules/mcp/mcp.service.ts +1007 -973
  27. package/src/modules/secrets-vault/db-secrets-vault.service.ts +30 -0
@@ -95,6 +95,27 @@ export class DbSecretsVaultService implements ISecretsVaultService {
95
95
  return this.cryptoInstance;
96
96
  }
97
97
 
98
+ // ── Mutation listeners ─────────────────────────────────────────────────────
99
+ // Notified after any secret mutation: `userId` for a per-user secret, null
100
+ // for a SHARED one (affects every user). Lets caches keyed on credential
101
+ // validity (e.g. the MCP proxy's manual-failure memo) invalidate the moment
102
+ // a credential changes instead of waiting out a TTL.
103
+ private readonly mutationListeners: Array<(userId: string | null) => void> = [];
104
+
105
+ onMutation(listener: (userId: string | null) => void): void {
106
+ this.mutationListeners.push(listener);
107
+ }
108
+
109
+ private notifyMutation(userId: string | null): void {
110
+ for (const listener of this.mutationListeners) {
111
+ try {
112
+ listener(userId);
113
+ } catch (err) {
114
+ console.warn('[vault] mutation listener failed:', err instanceof Error ? err.message : err);
115
+ }
116
+ }
117
+ }
118
+
98
119
  async list(userId: string): Promise<SecretSummary[]> {
99
120
  const rows = await this.db
100
121
  .select()
@@ -130,6 +151,7 @@ export class DbSecretsVaultService implements ISecretsVaultService {
130
151
  set: { kind: 'static', label, valueEncrypted, oauthMeta: null, updatedAt: new Date() },
131
152
  })
132
153
  .returning();
154
+ this.notifyMutation(userId);
133
155
  return this.toSummary(row);
134
156
  }
135
157
 
@@ -153,6 +175,7 @@ export class DbSecretsVaultService implements ISecretsVaultService {
153
175
  set: { kind: 'oauth', label, valueEncrypted, oauthMeta, updatedAt: new Date() },
154
176
  })
155
177
  .returning();
178
+ this.notifyMutation(userId);
156
179
  return this.toSummary(row);
157
180
  }
158
181
 
@@ -162,6 +185,7 @@ export class DbSecretsVaultService implements ISecretsVaultService {
162
185
  .where(and(eq(secrets.id, id), eq(secrets.userId, userId)))
163
186
  .returning({ id: secrets.id });
164
187
  if (res.length === 0) throw new SecretNotFoundError(id);
188
+ this.notifyMutation(userId);
165
189
  }
166
190
 
167
191
  async putSharedStatic(input: PutSharedStaticSecretInput): Promise<SecretSummary> {
@@ -186,6 +210,7 @@ export class DbSecretsVaultService implements ISecretsVaultService {
186
210
  set: { kind: 'static', label, valueEncrypted, oauthMeta: null, updatedAt: new Date() },
187
211
  })
188
212
  .returning();
213
+ this.notifyMutation(null);
189
214
  return this.toSummary(row);
190
215
  }
191
216
 
@@ -195,6 +220,7 @@ export class DbSecretsVaultService implements ISecretsVaultService {
195
220
  .where(and(isNull(secrets.userId), eq(secrets.key, key)))
196
221
  .returning({ id: secrets.id });
197
222
  if (res.length === 0) throw new SecretNotFoundError(key);
223
+ this.notifyMutation(null);
198
224
  }
199
225
 
200
226
  async removeUserByKey(userId: string, key: string): Promise<void> {
@@ -203,6 +229,7 @@ export class DbSecretsVaultService implements ISecretsVaultService {
203
229
  .where(and(eq(secrets.userId, userId), eq(secrets.key, key)))
204
230
  .returning({ id: secrets.id });
205
231
  if (res.length === 0) throw new SecretNotFoundError(key);
232
+ this.notifyMutation(userId);
206
233
  }
207
234
 
208
235
  async statusFor(userId: string, keys: string[]): Promise<SecretConfigStatus[]> {
@@ -319,6 +346,8 @@ export class DbSecretsVaultService implements ISecretsVaultService {
319
346
  .update(secrets)
320
347
  .set({ valueEncrypted: this.crypto().encrypt(JSON.stringify(next)), updatedAt: new Date() })
321
348
  .where(and(eq(secrets.id, id), eq(secrets.userId, userId)));
349
+ // Fresh tokens just landed — let credential-validity caches retry NOW.
350
+ this.notifyMutation(userId);
322
351
  }
323
352
 
324
353
  async putSharedOAuthClientSecret(input: {
@@ -345,6 +374,7 @@ export class DbSecretsVaultService implements ISecretsVaultService {
345
374
  targetWhere: isNull(secrets.userId),
346
375
  set: { kind: 'oauth', valueEncrypted, oauthMeta, updatedAt: new Date() },
347
376
  });
377
+ this.notifyMutation(null);
348
378
  }
349
379
 
350
380
  async beginToolOAuthByKey(input: {