@tumbaland/backend-core 1.37.0 → 1.39.0

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 (92) hide show
  1. package/dist/apiKeys/ApiKey.d.ts +23 -3
  2. package/dist/apiKeys/ApiKey.d.ts.map +1 -1
  3. package/dist/apiKeys/ApiKey.js +19 -2
  4. package/dist/apiKeys/ApiKey.js.map +1 -1
  5. package/dist/apiKeys/index.d.ts +2 -2
  6. package/dist/apiKeys/index.d.ts.map +1 -1
  7. package/dist/apiKeys/index.js +5 -1
  8. package/dist/apiKeys/index.js.map +1 -1
  9. package/dist/apiKeys/middleware.d.ts +17 -3
  10. package/dist/apiKeys/middleware.d.ts.map +1 -1
  11. package/dist/apiKeys/middleware.js +71 -34
  12. package/dist/apiKeys/middleware.js.map +1 -1
  13. package/dist/apiKeys/service.d.ts +5 -3
  14. package/dist/apiKeys/service.d.ts.map +1 -1
  15. package/dist/apiKeys/service.js +11 -3
  16. package/dist/apiKeys/service.js.map +1 -1
  17. package/dist/apiKeys/types.d.ts +43 -8
  18. package/dist/apiKeys/types.d.ts.map +1 -1
  19. package/dist/apiKeys/types.js +35 -1
  20. package/dist/apiKeys/types.js.map +1 -1
  21. package/dist/audit/AuditEvent.d.ts +51 -0
  22. package/dist/audit/AuditEvent.d.ts.map +1 -0
  23. package/dist/audit/AuditEvent.js +69 -0
  24. package/dist/audit/AuditEvent.js.map +1 -0
  25. package/dist/audit/actor.d.ts +41 -0
  26. package/dist/audit/actor.d.ts.map +1 -0
  27. package/dist/audit/actor.js +39 -0
  28. package/dist/audit/actor.js.map +1 -0
  29. package/dist/audit/context.d.ts +40 -0
  30. package/dist/audit/context.d.ts.map +1 -0
  31. package/dist/audit/context.js +60 -0
  32. package/dist/audit/context.js.map +1 -0
  33. package/dist/audit/index.d.ts +12 -0
  34. package/dist/audit/index.d.ts.map +1 -0
  35. package/dist/audit/index.js +22 -0
  36. package/dist/audit/index.js.map +1 -0
  37. package/dist/audit/plugin.d.ts +23 -0
  38. package/dist/audit/plugin.d.ts.map +1 -0
  39. package/dist/audit/plugin.js +226 -0
  40. package/dist/audit/plugin.js.map +1 -0
  41. package/dist/audit/reads.d.ts +47 -0
  42. package/dist/audit/reads.d.ts.map +1 -0
  43. package/dist/audit/reads.js +94 -0
  44. package/dist/audit/reads.js.map +1 -0
  45. package/dist/audit/service.d.ts +49 -0
  46. package/dist/audit/service.d.ts.map +1 -0
  47. package/dist/audit/service.js +65 -0
  48. package/dist/audit/service.js.map +1 -0
  49. package/dist/index.d.ts +1 -0
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +1 -0
  52. package/dist/index.js.map +1 -1
  53. package/dist/oauth/models.d.ts +13 -2
  54. package/dist/oauth/models.d.ts.map +1 -1
  55. package/dist/oauth/models.js +19 -0
  56. package/dist/oauth/models.js.map +1 -1
  57. package/dist/oauth/service.d.ts +15 -8
  58. package/dist/oauth/service.d.ts.map +1 -1
  59. package/dist/oauth/service.js +10 -3
  60. package/dist/oauth/service.js.map +1 -1
  61. package/dist/oauth/tokens.d.ts +37 -5
  62. package/dist/oauth/tokens.d.ts.map +1 -1
  63. package/dist/oauth/tokens.js +9 -2
  64. package/dist/oauth/tokens.js.map +1 -1
  65. package/package.json +1 -1
  66. package/src/apiKeys/ApiKey.test.ts +25 -1
  67. package/src/apiKeys/ApiKey.ts +31 -4
  68. package/src/apiKeys/index.ts +16 -2
  69. package/src/apiKeys/middleware.test.ts +126 -20
  70. package/src/apiKeys/middleware.ts +99 -39
  71. package/src/apiKeys/service.test.ts +58 -9
  72. package/src/apiKeys/service.ts +25 -6
  73. package/src/apiKeys/types.ts +63 -8
  74. package/src/audit/AuditEvent.ts +79 -0
  75. package/src/audit/actor.test.ts +95 -0
  76. package/src/audit/actor.ts +68 -0
  77. package/src/audit/context.test.ts +91 -0
  78. package/src/audit/context.ts +83 -0
  79. package/src/audit/index.ts +11 -0
  80. package/src/audit/plugin.test.ts +258 -0
  81. package/src/audit/plugin.ts +254 -0
  82. package/src/audit/reads.test.ts +164 -0
  83. package/src/audit/reads.ts +88 -0
  84. package/src/audit/service.test.ts +115 -0
  85. package/src/audit/service.ts +92 -0
  86. package/src/index.ts +1 -0
  87. package/src/middleware/authMiddleware.test.ts +6 -1
  88. package/src/oauth/models.ts +32 -2
  89. package/src/oauth/service.test.ts +58 -6
  90. package/src/oauth/service.ts +25 -7
  91. package/src/oauth/tokens.test.ts +22 -5
  92. package/src/oauth/tokens.ts +52 -7
@@ -1,7 +1,13 @@
1
1
  import { randomUUID } from 'crypto';
2
2
  import jwt from 'jsonwebtoken';
3
3
  import { requireEnv } from '../config/env';
4
- import { isApiKeyScope, type ApiKeyScope } from '../apiKeys/types';
4
+ import {
5
+ isApiKeyScope,
6
+ readTenants,
7
+ type ApiKeyScope,
8
+ type ApiKeyTenant,
9
+ type Tenant
10
+ } from '../apiKeys/types';
5
11
 
6
12
  /**
7
13
  * Access tokens for the OAuth flow that lets an assistant connect to Tumbaland.
@@ -27,8 +33,33 @@ export interface AccessTokenClaims {
27
33
  aud: string;
28
34
  iss: string;
29
35
  scope: string;
30
- /** the tenant the token is pinned to; null means the user's personal data */
31
- groupId: string | null;
36
+ /** every tenant this token may act in */
37
+ tenants: Tenant[];
38
+ /** the one it acts in when a call names none */
39
+ defaultTenant: Tenant;
40
+ /**
41
+ * What each tenant is called, for a client that has to offer the choice.
42
+ *
43
+ * Carried on the token because the only place these names are known is the
44
+ * consent screen that rendered them, and the MCP server — which has to name
45
+ * the choice to a model — cannot reach group-service. A snapshot: a group
46
+ * renamed after the connection was made shows its old name until reconnect,
47
+ * which is the same trade the owner's name on an API key already makes.
48
+ */
49
+ tenantNames: Record<Tenant, string>;
50
+ /** the single tenant an older token was pinned to; read by `readTenants` */
51
+ groupId?: string | null;
52
+ /**
53
+ * Which app this token was issued to.
54
+ *
55
+ * `jti` identifies the token and rotates every hour, so it cannot stand in for
56
+ * the connection — an audit trail built on it would show a different actor
57
+ * each time the assistant refreshed. The client id is stable for the life of
58
+ * the grant, and the name is snapshotted alongside it for the same reason the
59
+ * tenant names are: nothing downstream can look it up.
60
+ */
61
+ clientId: string;
62
+ clientName: string;
32
63
  email: string;
33
64
  name: string;
34
65
  typ: typeof ACCESS_TOKEN_TYPE;
@@ -45,7 +76,11 @@ export interface MintAccessTokenInput {
45
76
  resource: string;
46
77
  issuer: string;
47
78
  scopes: ApiKeyScope[];
48
- groupId: string | null;
79
+ tenants: Tenant[];
80
+ defaultTenant: Tenant;
81
+ tenantNames: Record<Tenant, string>;
82
+ clientId: string;
83
+ clientName: string;
49
84
  }
50
85
 
51
86
  export interface MintedAccessToken {
@@ -63,7 +98,11 @@ export const mintAccessToken = (input: MintAccessTokenInput): MintedAccessToken
63
98
  aud: input.resource,
64
99
  iss: input.issuer,
65
100
  scope,
66
- groupId: input.groupId,
101
+ tenants: input.tenants,
102
+ defaultTenant: input.defaultTenant,
103
+ tenantNames: input.tenantNames,
104
+ clientId: input.clientId,
105
+ clientName: input.clientName,
67
106
  email: input.email,
68
107
  name: input.name,
69
108
  typ: ACCESS_TOKEN_TYPE,
@@ -83,7 +122,10 @@ export interface AccessTokenVerification {
83
122
  email?: string;
84
123
  name?: string;
85
124
  scopes?: ApiKeyScope[];
86
- groupId?: string | null;
125
+ tenants?: ApiKeyTenant;
126
+ tenantNames?: Record<Tenant, string>;
127
+ clientId?: string;
128
+ clientName?: string;
87
129
  }
88
130
 
89
131
  /**
@@ -118,7 +160,10 @@ export const verifyAccessToken = (
118
160
  email: claims.email ?? '',
119
161
  name: claims.name ?? '',
120
162
  scopes: (claims.scope ?? '').split(' ').filter(isApiKeyScope),
121
- groupId: claims.groupId ?? null
163
+ tenants: readTenants(claims),
164
+ tenantNames: claims.tenantNames ?? {},
165
+ clientId: claims.clientId,
166
+ clientName: claims.clientName
122
167
  };
123
168
  };
124
169