@okrlinkhub/agent-bridge 3.0.1 → 3.0.2
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/README.md +25 -0
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +47 -0
- package/dist/client/index.js.map +1 -1
- package/dist/component/_generated/api.d.ts +2 -0
- package/dist/component/_generated/api.d.ts.map +1 -1
- package/dist/component/_generated/api.js.map +1 -1
- package/dist/component/_generated/component.d.ts +92 -0
- package/dist/component/_generated/component.d.ts.map +1 -1
- package/dist/component/gateway.d.ts +12 -0
- package/dist/component/gateway.d.ts.map +1 -1
- package/dist/component/gateway.js +36 -0
- package/dist/component/gateway.js.map +1 -1
- package/dist/component/linking.d.ts +106 -0
- package/dist/component/linking.d.ts.map +1 -0
- package/dist/component/linking.js +322 -0
- package/dist/component/linking.js.map +1 -0
- package/dist/component/schema.d.ts +61 -1
- package/dist/component/schema.d.ts.map +1 -1
- package/dist/component/schema.js +35 -0
- package/dist/component/schema.js.map +1 -1
- package/package.json +1 -1
- package/src/client/index.ts +69 -0
- package/src/client/linking.test.ts +145 -0
- package/src/component/_generated/api.ts +2 -0
- package/src/component/_generated/component.ts +114 -0
- package/src/component/gateway.ts +36 -0
- package/src/component/linking.ts +377 -0
- package/src/component/schema.ts +37 -0
package/src/client/index.ts
CHANGED
|
@@ -38,6 +38,7 @@ export interface AgentBridgeFunctionMetadata {
|
|
|
38
38
|
description?: string;
|
|
39
39
|
riskLevel?: "low" | "medium" | "high";
|
|
40
40
|
category?: string;
|
|
41
|
+
authMode?: "service" | "user";
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
export interface AgentBridgeConfig {
|
|
@@ -156,6 +157,8 @@ type RegisterRoutesOptions = {
|
|
|
156
157
|
pathPrefix?: string;
|
|
157
158
|
serviceKeys?: Record<string, string>;
|
|
158
159
|
serviceKeysEnvVar?: string;
|
|
160
|
+
auditHashSaltEnvVar?: string;
|
|
161
|
+
linkingMode?: "component_api_only";
|
|
159
162
|
};
|
|
160
163
|
|
|
161
164
|
export function registerRoutes(
|
|
@@ -165,10 +168,17 @@ export function registerRoutes(
|
|
|
165
168
|
options?: RegisterRoutesOptions,
|
|
166
169
|
) {
|
|
167
170
|
const prefix = options?.pathPrefix ?? "/agent";
|
|
171
|
+
const linkingMode = options?.linkingMode ?? "component_api_only";
|
|
172
|
+
if (linkingMode !== "component_api_only") {
|
|
173
|
+
throw new Error(`Unsupported linkingMode: ${linkingMode}`);
|
|
174
|
+
}
|
|
168
175
|
const configuredServiceKeys = resolveConfiguredServiceKeys({
|
|
169
176
|
serviceKeys: options?.serviceKeys,
|
|
170
177
|
serviceKeysEnvVar: options?.serviceKeysEnvVar ?? "AGENT_BRIDGE_SERVICE_KEYS_JSON",
|
|
171
178
|
});
|
|
179
|
+
const auditHashSalt =
|
|
180
|
+
readRuntimeEnv(options?.auditHashSaltEnvVar ?? "AGENT_BRIDGE_AUDIT_HASH_SALT") ??
|
|
181
|
+
"";
|
|
172
182
|
const normalizedConfig = normalizeAgentBridgeConfig(bridgeConfig);
|
|
173
183
|
const availableFunctionKeys = Object.keys(normalizedConfig.functions);
|
|
174
184
|
|
|
@@ -234,6 +244,10 @@ export function registerRoutes(
|
|
|
234
244
|
}
|
|
235
245
|
|
|
236
246
|
const startTime = Date.now();
|
|
247
|
+
const linkAuditContext = await extractLinkAuditContextFromRequest({
|
|
248
|
+
request,
|
|
249
|
+
auditHashSalt,
|
|
250
|
+
});
|
|
237
251
|
try {
|
|
238
252
|
const args = body.args ?? {};
|
|
239
253
|
let result: unknown;
|
|
@@ -262,6 +276,7 @@ export function registerRoutes(
|
|
|
262
276
|
result,
|
|
263
277
|
duration: Date.now() - startTime,
|
|
264
278
|
timestamp: Date.now(),
|
|
279
|
+
...linkAuditContext,
|
|
265
280
|
});
|
|
266
281
|
|
|
267
282
|
return jsonResponse({ success: true, result }, 200);
|
|
@@ -277,8 +292,10 @@ export function registerRoutes(
|
|
|
277
292
|
functionKey,
|
|
278
293
|
args: body.args ?? {},
|
|
279
294
|
error: errorMessage,
|
|
295
|
+
errorCode: "bridge_execution_error",
|
|
280
296
|
duration: Date.now() - startTime,
|
|
281
297
|
timestamp: Date.now(),
|
|
298
|
+
...linkAuditContext,
|
|
282
299
|
});
|
|
283
300
|
|
|
284
301
|
return jsonResponse({ success: false, error: errorMessage }, 500);
|
|
@@ -443,6 +460,58 @@ function readRuntimeEnv(name: string): string | undefined {
|
|
|
443
460
|
return trimmed.length > 0 ? trimmed : undefined;
|
|
444
461
|
}
|
|
445
462
|
|
|
463
|
+
async function extractLinkAuditContextFromRequest(args: {
|
|
464
|
+
request: Request;
|
|
465
|
+
auditHashSalt: string;
|
|
466
|
+
}): Promise<{
|
|
467
|
+
linkedProvider?: string;
|
|
468
|
+
providerUserIdHash?: string;
|
|
469
|
+
appUserSubjectHash?: string;
|
|
470
|
+
linkStatus?: string;
|
|
471
|
+
}> {
|
|
472
|
+
const linkedProvider =
|
|
473
|
+
args.request.headers.get("X-Agent-Link-Provider")?.trim().toLowerCase() || undefined;
|
|
474
|
+
const providerUserIdRaw =
|
|
475
|
+
args.request.headers.get("X-Agent-Link-Provider-User-Id")?.trim() || undefined;
|
|
476
|
+
const appUserSubjectRaw =
|
|
477
|
+
args.request.headers.get("X-Agent-Link-User-Subject")?.trim() || undefined;
|
|
478
|
+
const linkStatus = args.request.headers.get("X-Agent-Link-Status")?.trim() || undefined;
|
|
479
|
+
const providerUserIdHash = providerUserIdRaw
|
|
480
|
+
? await hashAuditIdentifier(providerUserIdRaw, args.auditHashSalt)
|
|
481
|
+
: undefined;
|
|
482
|
+
const appUserSubjectHash = appUserSubjectRaw
|
|
483
|
+
? await hashAuditIdentifier(appUserSubjectRaw, args.auditHashSalt)
|
|
484
|
+
: undefined;
|
|
485
|
+
const auditContext: {
|
|
486
|
+
linkedProvider?: string;
|
|
487
|
+
providerUserIdHash?: string;
|
|
488
|
+
appUserSubjectHash?: string;
|
|
489
|
+
linkStatus?: string;
|
|
490
|
+
} = {};
|
|
491
|
+
if (linkedProvider) {
|
|
492
|
+
auditContext.linkedProvider = linkedProvider;
|
|
493
|
+
}
|
|
494
|
+
if (providerUserIdHash) {
|
|
495
|
+
auditContext.providerUserIdHash = providerUserIdHash;
|
|
496
|
+
}
|
|
497
|
+
if (appUserSubjectHash) {
|
|
498
|
+
auditContext.appUserSubjectHash = appUserSubjectHash;
|
|
499
|
+
}
|
|
500
|
+
if (linkStatus) {
|
|
501
|
+
auditContext.linkStatus = linkStatus;
|
|
502
|
+
}
|
|
503
|
+
return auditContext;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
async function hashAuditIdentifier(value: string, salt: string): Promise<string> {
|
|
507
|
+
const encoder = new TextEncoder();
|
|
508
|
+
const input = encoder.encode(`${salt}:${value}`);
|
|
509
|
+
const digest = await crypto.subtle.digest("SHA-256", input);
|
|
510
|
+
return Array.from(new Uint8Array(digest))
|
|
511
|
+
.map((byte) => byte.toString(16).padStart(2, "0"))
|
|
512
|
+
.join("");
|
|
513
|
+
}
|
|
514
|
+
|
|
446
515
|
function resolveConfiguredServiceKeys(args: {
|
|
447
516
|
serviceKeys?: Record<string, string>;
|
|
448
517
|
serviceKeysEnvVar: string;
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, test, vi } from "vitest";
|
|
2
|
+
import { components, initConvexTest } from "./setup.test.js";
|
|
3
|
+
|
|
4
|
+
describe("component linking lifecycle", () => {
|
|
5
|
+
beforeEach(() => {
|
|
6
|
+
vi.useFakeTimers();
|
|
7
|
+
vi.setSystemTime(new Date("2026-01-01T10:00:00.000Z"));
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
vi.useRealTimers();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("upsert + resolve are idempotent and appKey scoped", async () => {
|
|
15
|
+
const t = initConvexTest();
|
|
16
|
+
|
|
17
|
+
const first = await t.mutation(components.agentBridge.linking.upsertLink, {
|
|
18
|
+
provider: "discord",
|
|
19
|
+
providerUserId: "user-123",
|
|
20
|
+
appKey: "CRM",
|
|
21
|
+
appUserSubject: "convex-user-a",
|
|
22
|
+
expiresInDays: 30,
|
|
23
|
+
metadata: { source: "discord-command" },
|
|
24
|
+
});
|
|
25
|
+
expect(first.created).toBe(true);
|
|
26
|
+
|
|
27
|
+
const second = await t.mutation(components.agentBridge.linking.upsertLink, {
|
|
28
|
+
provider: "discord",
|
|
29
|
+
providerUserId: "user-123",
|
|
30
|
+
appKey: "crm",
|
|
31
|
+
appUserSubject: "convex-user-b",
|
|
32
|
+
expiresInDays: 30,
|
|
33
|
+
});
|
|
34
|
+
expect(second.created).toBe(false);
|
|
35
|
+
expect(second.linkId).toBe(first.linkId);
|
|
36
|
+
|
|
37
|
+
const resolved = await t.mutation(components.agentBridge.linking.resolveLink, {
|
|
38
|
+
provider: "discord",
|
|
39
|
+
providerUserId: "user-123",
|
|
40
|
+
appKey: "crm",
|
|
41
|
+
});
|
|
42
|
+
expect(resolved.ok).toBe(true);
|
|
43
|
+
if (!resolved.ok) {
|
|
44
|
+
throw new Error("Expected resolve to succeed");
|
|
45
|
+
}
|
|
46
|
+
expect(resolved.link.appUserSubject).toBe("convex-user-b");
|
|
47
|
+
|
|
48
|
+
const wrongApp = await t.mutation(components.agentBridge.linking.resolveLink, {
|
|
49
|
+
provider: "discord",
|
|
50
|
+
providerUserId: "user-123",
|
|
51
|
+
appKey: "billing",
|
|
52
|
+
});
|
|
53
|
+
expect(wrongApp.ok).toBe(false);
|
|
54
|
+
if (wrongApp.ok) {
|
|
55
|
+
throw new Error("Expected app scoped lookup to fail");
|
|
56
|
+
}
|
|
57
|
+
expect(wrongApp.errorCode).toBe("link_not_found");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("revoke marks link as revoked", async () => {
|
|
61
|
+
const t = initConvexTest();
|
|
62
|
+
const created = await t.mutation(components.agentBridge.linking.upsertLink, {
|
|
63
|
+
provider: "telegram",
|
|
64
|
+
providerUserId: "tg-77",
|
|
65
|
+
appKey: "crm",
|
|
66
|
+
appUserSubject: "convex-user-77",
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const revokeResult = await t.mutation(components.agentBridge.linking.revokeLink, {
|
|
70
|
+
linkId: created.linkId,
|
|
71
|
+
});
|
|
72
|
+
expect(revokeResult.revoked).toBe(true);
|
|
73
|
+
|
|
74
|
+
const resolved = await t.mutation(components.agentBridge.linking.resolveLink, {
|
|
75
|
+
provider: "telegram",
|
|
76
|
+
providerUserId: "tg-77",
|
|
77
|
+
appKey: "crm",
|
|
78
|
+
});
|
|
79
|
+
expect(resolved.ok).toBe(false);
|
|
80
|
+
if (resolved.ok) {
|
|
81
|
+
throw new Error("Expected revoked link to fail");
|
|
82
|
+
}
|
|
83
|
+
expect(resolved.errorCode).toBe("link_revoked");
|
|
84
|
+
expect(resolved.statusCode).toBe(410);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("expired links are detected and converted to expired status", async () => {
|
|
88
|
+
const t = initConvexTest();
|
|
89
|
+
await t.mutation(components.agentBridge.linking.upsertLink, {
|
|
90
|
+
provider: "discord",
|
|
91
|
+
providerUserId: "exp-1",
|
|
92
|
+
appKey: "crm",
|
|
93
|
+
appUserSubject: "convex-user-exp",
|
|
94
|
+
expiresInDays: 1,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
vi.setSystemTime(new Date("2026-01-03T10:00:00.000Z"));
|
|
98
|
+
const resolved = await t.mutation(components.agentBridge.linking.resolveLink, {
|
|
99
|
+
provider: "discord",
|
|
100
|
+
providerUserId: "exp-1",
|
|
101
|
+
appKey: "crm",
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
expect(resolved.ok).toBe(false);
|
|
105
|
+
if (resolved.ok) {
|
|
106
|
+
throw new Error("Expected expired link to fail");
|
|
107
|
+
}
|
|
108
|
+
expect(resolved.errorCode).toBe("link_expired");
|
|
109
|
+
expect(resolved.statusCode).toBe(410);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
test("resolveLink applies per-link rate limiting", async () => {
|
|
113
|
+
const t = initConvexTest();
|
|
114
|
+
await t.mutation(components.agentBridge.linking.upsertLink, {
|
|
115
|
+
provider: "discord",
|
|
116
|
+
providerUserId: "rl-1",
|
|
117
|
+
appKey: "crm",
|
|
118
|
+
appUserSubject: "convex-user-rl",
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const first = await t.mutation(components.agentBridge.linking.resolveLink, {
|
|
122
|
+
provider: "discord",
|
|
123
|
+
providerUserId: "rl-1",
|
|
124
|
+
appKey: "crm",
|
|
125
|
+
maxRequestsPerWindow: 1,
|
|
126
|
+
windowSeconds: 60,
|
|
127
|
+
});
|
|
128
|
+
expect(first.ok).toBe(true);
|
|
129
|
+
|
|
130
|
+
const second = await t.mutation(components.agentBridge.linking.resolveLink, {
|
|
131
|
+
provider: "discord",
|
|
132
|
+
providerUserId: "rl-1",
|
|
133
|
+
appKey: "crm",
|
|
134
|
+
maxRequestsPerWindow: 1,
|
|
135
|
+
windowSeconds: 60,
|
|
136
|
+
});
|
|
137
|
+
expect(second.ok).toBe(false);
|
|
138
|
+
if (second.ok) {
|
|
139
|
+
throw new Error("Expected second resolve to be rate limited");
|
|
140
|
+
}
|
|
141
|
+
expect(second.errorCode).toBe("link_rate_limited");
|
|
142
|
+
expect(second.statusCode).toBe(429);
|
|
143
|
+
expect(second.retryAfterSeconds).toBeGreaterThanOrEqual(1);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import type * as agentBridgeUtils from "../agentBridgeUtils.js";
|
|
12
12
|
import type * as agents from "../agents.js";
|
|
13
13
|
import type * as gateway from "../gateway.js";
|
|
14
|
+
import type * as linking from "../linking.js";
|
|
14
15
|
import type * as permissions from "../permissions.js";
|
|
15
16
|
|
|
16
17
|
import type {
|
|
@@ -24,6 +25,7 @@ const fullApi: ApiFromModules<{
|
|
|
24
25
|
agentBridgeUtils: typeof agentBridgeUtils;
|
|
25
26
|
agents: typeof agents;
|
|
26
27
|
gateway: typeof gateway;
|
|
28
|
+
linking: typeof linking;
|
|
27
29
|
permissions: typeof permissions;
|
|
28
30
|
}> = anyApi as any;
|
|
29
31
|
|
|
@@ -107,10 +107,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
107
107
|
"internal",
|
|
108
108
|
{
|
|
109
109
|
agentId: string;
|
|
110
|
+
appUserSubjectHash?: string;
|
|
110
111
|
args: any;
|
|
111
112
|
duration: number;
|
|
112
113
|
error?: string;
|
|
114
|
+
errorCode?: string;
|
|
113
115
|
functionKey: string;
|
|
116
|
+
linkStatus?: string;
|
|
117
|
+
linkedProvider?: string;
|
|
118
|
+
providerUserIdHash?: string;
|
|
119
|
+
rateLimited?: boolean;
|
|
114
120
|
result?: any;
|
|
115
121
|
serviceId?: string;
|
|
116
122
|
timestamp: number;
|
|
@@ -130,10 +136,16 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
130
136
|
Array<{
|
|
131
137
|
_id: string;
|
|
132
138
|
agentId: string;
|
|
139
|
+
appUserSubjectHash?: string;
|
|
133
140
|
args: any;
|
|
134
141
|
duration: number;
|
|
135
142
|
error?: string;
|
|
143
|
+
errorCode?: string;
|
|
136
144
|
functionKey: string;
|
|
145
|
+
linkStatus?: string;
|
|
146
|
+
linkedProvider?: string;
|
|
147
|
+
providerUserIdHash?: string;
|
|
148
|
+
rateLimited?: boolean;
|
|
137
149
|
result?: any;
|
|
138
150
|
serviceId?: string;
|
|
139
151
|
timestamp: number;
|
|
@@ -141,6 +153,108 @@ export type ComponentApi<Name extends string | undefined = string | undefined> =
|
|
|
141
153
|
Name
|
|
142
154
|
>;
|
|
143
155
|
};
|
|
156
|
+
linking: {
|
|
157
|
+
listLinks: FunctionReference<
|
|
158
|
+
"query",
|
|
159
|
+
"internal",
|
|
160
|
+
{
|
|
161
|
+
appKey?: string;
|
|
162
|
+
limit?: number;
|
|
163
|
+
provider?: string;
|
|
164
|
+
status?: "active" | "revoked" | "expired";
|
|
165
|
+
},
|
|
166
|
+
Array<{
|
|
167
|
+
_id: string;
|
|
168
|
+
appKey: string;
|
|
169
|
+
appUserSubject: string;
|
|
170
|
+
createdAt: number;
|
|
171
|
+
expiresAt?: number;
|
|
172
|
+
lastUsedAt?: number;
|
|
173
|
+
metadata?: any;
|
|
174
|
+
provider: string;
|
|
175
|
+
providerUserId: string;
|
|
176
|
+
refreshTokenCiphertext?: string;
|
|
177
|
+
refreshTokenExpiresAt?: number;
|
|
178
|
+
revokedAt?: number;
|
|
179
|
+
status: "active" | "revoked" | "expired";
|
|
180
|
+
tokenVersion?: number;
|
|
181
|
+
updatedAt: number;
|
|
182
|
+
}>,
|
|
183
|
+
Name
|
|
184
|
+
>;
|
|
185
|
+
resolveLink: FunctionReference<
|
|
186
|
+
"mutation",
|
|
187
|
+
"internal",
|
|
188
|
+
{
|
|
189
|
+
appKey: string;
|
|
190
|
+
extendExpiryDaysOnUse?: number;
|
|
191
|
+
maxRequestsPerWindow?: number;
|
|
192
|
+
provider: string;
|
|
193
|
+
providerUserId: string;
|
|
194
|
+
windowSeconds?: number;
|
|
195
|
+
},
|
|
196
|
+
| {
|
|
197
|
+
link: {
|
|
198
|
+
_id: string;
|
|
199
|
+
appKey: string;
|
|
200
|
+
appUserSubject: string;
|
|
201
|
+
createdAt: number;
|
|
202
|
+
expiresAt?: number;
|
|
203
|
+
lastUsedAt?: number;
|
|
204
|
+
metadata?: any;
|
|
205
|
+
provider: string;
|
|
206
|
+
providerUserId: string;
|
|
207
|
+
refreshTokenCiphertext?: string;
|
|
208
|
+
refreshTokenExpiresAt?: number;
|
|
209
|
+
revokedAt?: number;
|
|
210
|
+
status: "active" | "revoked" | "expired";
|
|
211
|
+
tokenVersion?: number;
|
|
212
|
+
updatedAt: number;
|
|
213
|
+
};
|
|
214
|
+
ok: true;
|
|
215
|
+
}
|
|
216
|
+
| {
|
|
217
|
+
errorCode:
|
|
218
|
+
| "link_not_found"
|
|
219
|
+
| "link_revoked"
|
|
220
|
+
| "link_expired"
|
|
221
|
+
| "link_rate_limited";
|
|
222
|
+
ok: false;
|
|
223
|
+
retryAfterSeconds?: number;
|
|
224
|
+
statusCode: number;
|
|
225
|
+
},
|
|
226
|
+
Name
|
|
227
|
+
>;
|
|
228
|
+
revokeLink: FunctionReference<
|
|
229
|
+
"mutation",
|
|
230
|
+
"internal",
|
|
231
|
+
{
|
|
232
|
+
appKey?: string;
|
|
233
|
+
linkId?: string;
|
|
234
|
+
provider?: string;
|
|
235
|
+
providerUserId?: string;
|
|
236
|
+
},
|
|
237
|
+
{ linkId?: string; revoked: boolean },
|
|
238
|
+
Name
|
|
239
|
+
>;
|
|
240
|
+
upsertLink: FunctionReference<
|
|
241
|
+
"mutation",
|
|
242
|
+
"internal",
|
|
243
|
+
{
|
|
244
|
+
appKey: string;
|
|
245
|
+
appUserSubject: string;
|
|
246
|
+
expiresInDays?: number;
|
|
247
|
+
metadata?: any;
|
|
248
|
+
provider: string;
|
|
249
|
+
providerUserId: string;
|
|
250
|
+
refreshTokenCiphertext?: string;
|
|
251
|
+
refreshTokenExpiresAt?: number;
|
|
252
|
+
tokenVersion?: number;
|
|
253
|
+
},
|
|
254
|
+
{ created: boolean; expiresAt?: number; linkId: string },
|
|
255
|
+
Name
|
|
256
|
+
>;
|
|
257
|
+
};
|
|
144
258
|
permissions: {
|
|
145
259
|
listAgentPermissions: FunctionReference<
|
|
146
260
|
"query",
|
package/src/component/gateway.ts
CHANGED
|
@@ -105,7 +105,13 @@ export const logAccess = mutation({
|
|
|
105
105
|
args: v.any(),
|
|
106
106
|
result: v.optional(v.any()),
|
|
107
107
|
error: v.optional(v.string()),
|
|
108
|
+
errorCode: v.optional(v.string()),
|
|
108
109
|
duration: v.number(),
|
|
110
|
+
linkedProvider: v.optional(v.string()),
|
|
111
|
+
providerUserIdHash: v.optional(v.string()),
|
|
112
|
+
appUserSubjectHash: v.optional(v.string()),
|
|
113
|
+
linkStatus: v.optional(v.string()),
|
|
114
|
+
rateLimited: v.optional(v.boolean()),
|
|
109
115
|
timestamp: v.number(),
|
|
110
116
|
},
|
|
111
117
|
returns: v.null(),
|
|
@@ -118,7 +124,13 @@ export const logAccess = mutation({
|
|
|
118
124
|
args: args.args,
|
|
119
125
|
result: args.result,
|
|
120
126
|
error: args.error,
|
|
127
|
+
errorCode: args.errorCode,
|
|
121
128
|
duration: args.duration,
|
|
129
|
+
linkedProvider: args.linkedProvider,
|
|
130
|
+
providerUserIdHash: args.providerUserIdHash,
|
|
131
|
+
appUserSubjectHash: args.appUserSubjectHash,
|
|
132
|
+
linkStatus: args.linkStatus,
|
|
133
|
+
rateLimited: args.rateLimited,
|
|
122
134
|
});
|
|
123
135
|
return null;
|
|
124
136
|
},
|
|
@@ -144,7 +156,13 @@ export const queryAccessLog = query({
|
|
|
144
156
|
args: v.any(),
|
|
145
157
|
result: v.optional(v.any()),
|
|
146
158
|
error: v.optional(v.string()),
|
|
159
|
+
errorCode: v.optional(v.string()),
|
|
147
160
|
duration: v.number(),
|
|
161
|
+
linkedProvider: v.optional(v.string()),
|
|
162
|
+
providerUserIdHash: v.optional(v.string()),
|
|
163
|
+
appUserSubjectHash: v.optional(v.string()),
|
|
164
|
+
linkStatus: v.optional(v.string()),
|
|
165
|
+
rateLimited: v.optional(v.boolean()),
|
|
148
166
|
}),
|
|
149
167
|
),
|
|
150
168
|
handler: async (ctx, args) => {
|
|
@@ -173,7 +191,13 @@ export const queryAccessLog = query({
|
|
|
173
191
|
args: l.args,
|
|
174
192
|
result: l.result,
|
|
175
193
|
error: l.error,
|
|
194
|
+
errorCode: l.errorCode,
|
|
176
195
|
duration: l.duration,
|
|
196
|
+
linkedProvider: l.linkedProvider,
|
|
197
|
+
providerUserIdHash: l.providerUserIdHash,
|
|
198
|
+
appUserSubjectHash: l.appUserSubjectHash,
|
|
199
|
+
linkStatus: l.linkStatus,
|
|
200
|
+
rateLimited: l.rateLimited,
|
|
177
201
|
}));
|
|
178
202
|
}
|
|
179
203
|
|
|
@@ -196,7 +220,13 @@ export const queryAccessLog = query({
|
|
|
196
220
|
args: l.args,
|
|
197
221
|
result: l.result,
|
|
198
222
|
error: l.error,
|
|
223
|
+
errorCode: l.errorCode,
|
|
199
224
|
duration: l.duration,
|
|
225
|
+
linkedProvider: l.linkedProvider,
|
|
226
|
+
providerUserIdHash: l.providerUserIdHash,
|
|
227
|
+
appUserSubjectHash: l.appUserSubjectHash,
|
|
228
|
+
linkStatus: l.linkStatus,
|
|
229
|
+
rateLimited: l.rateLimited,
|
|
200
230
|
}));
|
|
201
231
|
}
|
|
202
232
|
|
|
@@ -218,7 +248,13 @@ export const queryAccessLog = query({
|
|
|
218
248
|
args: l.args,
|
|
219
249
|
result: l.result,
|
|
220
250
|
error: l.error,
|
|
251
|
+
errorCode: l.errorCode,
|
|
221
252
|
duration: l.duration,
|
|
253
|
+
linkedProvider: l.linkedProvider,
|
|
254
|
+
providerUserIdHash: l.providerUserIdHash,
|
|
255
|
+
appUserSubjectHash: l.appUserSubjectHash,
|
|
256
|
+
linkStatus: l.linkStatus,
|
|
257
|
+
rateLimited: l.rateLimited,
|
|
222
258
|
}));
|
|
223
259
|
},
|
|
224
260
|
});
|