@bevel-software/platform-core-backend 0.2.1 → 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 (31) hide show
  1. package/dist/core/create-core-server.d.ts.map +1 -1
  2. package/dist/core/create-core-server.js +3 -2
  3. package/dist/core/create-core-server.js.map +1 -1
  4. package/dist/core/create-core-services.d.ts.map +1 -1
  5. package/dist/core/create-core-services.js +5 -0
  6. package/dist/core/create-core-services.js.map +1 -1
  7. package/dist/modules/auth/account.routes.d.ts +7 -8
  8. package/dist/modules/auth/account.routes.d.ts.map +1 -1
  9. package/dist/modules/auth/account.routes.js +34 -8
  10. package/dist/modules/auth/account.routes.js.map +1 -1
  11. package/dist/modules/mcp/manual-failure-memo.d.ts +38 -0
  12. package/dist/modules/mcp/manual-failure-memo.d.ts.map +1 -0
  13. package/dist/modules/mcp/manual-failure-memo.js +65 -0
  14. package/dist/modules/mcp/manual-failure-memo.js.map +1 -0
  15. package/dist/modules/mcp/mcp.service.d.ts +12 -0
  16. package/dist/modules/mcp/mcp.service.d.ts.map +1 -1
  17. package/dist/modules/mcp/mcp.service.js +37 -4
  18. package/dist/modules/mcp/mcp.service.js.map +1 -1
  19. package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts +3 -0
  20. package/dist/modules/secrets-vault/db-secrets-vault.service.d.ts.map +1 -1
  21. package/dist/modules/secrets-vault/db-secrets-vault.service.js +28 -0
  22. package/dist/modules/secrets-vault/db-secrets-vault.service.js.map +1 -1
  23. package/package.json +2 -2
  24. package/src/core/create-core-server.ts +7 -2
  25. package/src/core/create-core-services.ts +5 -0
  26. package/src/modules/auth/__tests__/account.routes.test.ts +40 -1
  27. package/src/modules/auth/account.routes.ts +38 -7
  28. package/src/modules/mcp/__tests__/manual-failure-memo.test.ts +54 -0
  29. package/src/modules/mcp/manual-failure-memo.ts +67 -0
  30. package/src/modules/mcp/mcp.service.ts +1007 -973
  31. package/src/modules/secrets-vault/db-secrets-vault.service.ts +30 -0
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Short-lived memo of manual-registration FAILURES, keyed per (user, manual).
3
+ *
4
+ * Registering a `.tool` manual with a present-but-broken credential (an
5
+ * expired OAuth session, a revoked key) fails with a live network round-trip —
6
+ * and sessions are rebuilt constantly (every external MCP connection runs a
7
+ * full discovery), so one stale credential otherwise re-dials its provider on
8
+ * every build, forever. Besides the log noise, each failed attempt on the
9
+ * MCP transport layer's long-lived shared session leaks an abort listener
10
+ * upstream — the memo starves that loop.
11
+ *
12
+ * Failures are remembered for a few minutes only: a repaired credential is
13
+ * picked up at the next build after expiry (or immediately after a restart).
14
+ * Successes are never cached here — this is a circuit breaker, not a catalog
15
+ * cache. Expired entries are pruned opportunistically so the map stays
16
+ * bounded by the number of DISTINCT recently-failing (user, manual) pairs.
17
+ */
18
+ export class ManualFailureMemo {
19
+ private readonly failures = new Map<string, { message: string; expiresAt: number }>();
20
+
21
+ constructor(
22
+ private readonly ttlMs: number = 5 * 60_000,
23
+ private readonly now: () => number = Date.now,
24
+ ) {}
25
+
26
+ private key(userId: string, manualName: string): string {
27
+ return `${userId} ${manualName}`;
28
+ }
29
+
30
+ /** The remembered failure message when (user, manual) failed recently; undefined otherwise. */
31
+ recentFailure(userId: string, manualName: string): string | undefined {
32
+ const now = this.now();
33
+ for (const [k, entry] of this.failures) {
34
+ if (entry.expiresAt <= now) this.failures.delete(k);
35
+ }
36
+ return this.failures.get(this.key(userId, manualName))?.message;
37
+ }
38
+
39
+ recordFailure(userId: string, manualName: string, message: string): void {
40
+ this.failures.set(this.key(userId, manualName), {
41
+ message,
42
+ expiresAt: this.now() + this.ttlMs,
43
+ });
44
+ }
45
+
46
+ /** Forget a pair (e.g. after a successful registration proves the credential works again). */
47
+ clear(userId: string, manualName: string): void {
48
+ this.failures.delete(this.key(userId, manualName));
49
+ }
50
+
51
+ /**
52
+ * Forget every failure for one user — called when their secrets change, so a
53
+ * just-repaired credential is retried on the VERY NEXT build instead of
54
+ * waiting out the TTL.
55
+ */
56
+ clearUser(userId: string): void {
57
+ const prefix = `${userId} `;
58
+ for (const k of this.failures.keys()) {
59
+ if (k.startsWith(prefix)) this.failures.delete(k);
60
+ }
61
+ }
62
+
63
+ /** Forget everything — a SHARED secret changed, which can affect any user. */
64
+ clearAll(): void {
65
+ this.failures.clear();
66
+ }
67
+ }