@opengeni/db 4.4.0-canary.0 → 4.4.0-canary.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/dist/canonical-human-identities.js +4 -3
- package/dist/{chunk-2ZMTQVTR.js → chunk-2KOLL33E.js} +2 -2
- package/dist/chunk-45CP2YKY.js +1062 -0
- package/dist/chunk-45CP2YKY.js.map +1 -0
- package/dist/{chunk-6TKL3GQO.js → chunk-5UUWZDAV.js} +6531 -6480
- package/dist/chunk-5UUWZDAV.js.map +1 -0
- package/dist/{chunk-QLA3UQNX.js → chunk-6IJD3XXF.js} +17 -3
- package/dist/chunk-6IJD3XXF.js.map +1 -0
- package/dist/{chunk-232VC2LW.js → chunk-6V3HDEMR.js} +2 -2
- package/dist/{chunk-M7PSMVFF.js → chunk-CHBLBEU6.js} +2 -2
- package/dist/chunk-M4PKBJRS.js +20318 -0
- package/dist/chunk-M4PKBJRS.js.map +1 -0
- package/dist/chunk-S2TZ3F4L.js +237 -0
- package/dist/chunk-S2TZ3F4L.js.map +1 -0
- package/dist/{chunk-UK57QA2H.js → chunk-UOXWVP3T.js} +2 -2
- package/dist/{chunk-GVZJ7XSR.js → chunk-WFU6PS54.js} +11 -4
- package/dist/chunk-WFU6PS54.js.map +1 -0
- package/dist/{chunk-THJGMEK5.js → chunk-XJP7KJ6U.js} +121 -66
- package/dist/chunk-XJP7KJ6U.js.map +1 -0
- package/dist/connection-token-resolver.d.ts +2 -0
- package/dist/database.d.ts +2 -0
- package/dist/editable-artifact-durable-export.js +3 -2
- package/dist/editable-artifact-durable-export.js.map +1 -1
- package/dist/editable-artifacts.js +4 -3
- package/dist/external-identities.d.ts +1 -0
- package/dist/external-membership-operations.d.ts +44 -0
- package/dist/governed-learning-evaluator.d.ts +1 -14
- package/dist/host-mcp-bindings.d.ts +4 -0
- package/dist/host-mcp-resolvers.d.ts +47 -0
- package/dist/host-mcp-task-authority.d.ts +2 -6
- package/dist/index.d.ts +29 -31
- package/dist/index.js +8616 -8321
- package/dist/index.js.map +1 -1
- package/dist/knowledge-document-preparation.d.ts +56 -0
- package/dist/knowledge-entries-schema.d.ts +2479 -0
- package/dist/knowledge-entries.d.ts +421 -0
- package/dist/knowledge-indexing.d.ts +99 -0
- package/dist/knowledge-migration.d.ts +6 -0
- package/dist/managed-auth-session-sets.js +4 -3
- package/dist/mcp-operations.js +3 -2
- package/dist/mcp-operations.js.map +1 -1
- package/dist/migrate.js +2 -1
- package/dist/provision-roles.js +1 -1
- package/dist/retained-provider-commands.js +3 -2
- package/dist/retained-provider-commands.js.map +1 -1
- package/dist/runtime-posture.d.ts +7 -7
- package/dist/schema.d.ts +115 -12
- package/dist/schema.js +26 -1
- package/dist/session-background-commands.js +5 -4
- package/dist/session-command-output.js +8 -6
- package/dist/session-command-output.js.map +1 -1
- package/dist/session-event-slices.js +6 -4
- package/dist/session-event-slices.js.map +1 -1
- package/dist/session-mcp-credential-rotation.js +5 -4
- package/dist/session-mcp-credential-rotation.js.map +1 -1
- package/dist/session-tenancy.js +4 -3
- package/dist/video-generation.js +4 -3
- package/dist/workspace-artifacts.d.ts +1 -0
- package/dist/workspace-instruction-policies-schema.d.ts +21 -2
- package/dist/workspace-instruction-policies.d.ts +1 -1
- package/dist/workspace-membership-access.d.ts +11 -0
- package/dist/workspace-tool-defaults.js +5 -4
- package/dist/workspace-tool-defaults.js.map +1 -1
- package/drizzle/0461_unified_knowledge.sql +2859 -0
- package/drizzle/0462_agent_instruction_non_destructive_edits.sql +212 -0
- package/drizzle/0463_host_mcp_resolver_registration.sql +111 -0
- package/drizzle/0464_external_workspace_membership_operations.sql +166 -0
- package/package.json +6 -6
- package/src/connection-token-resolver.ts +75 -6
- package/src/database.ts +12 -1
- package/src/external-identities.ts +1 -0
- package/src/external-membership-operations.ts +134 -0
- package/src/governed-learning-evaluator.ts +0 -69
- package/src/host-mcp-binding-match.ts +1 -0
- package/src/host-mcp-bindings.ts +24 -1
- package/src/host-mcp-resolvers.ts +266 -0
- package/src/host-mcp-task-authority.ts +11 -10
- package/src/index.ts +307 -128
- package/src/knowledge-document-preparation.ts +90 -0
- package/src/knowledge-entries-schema.ts +264 -0
- package/src/knowledge-entries.ts +860 -0
- package/src/knowledge-indexing.ts +126 -0
- package/src/knowledge-migration.ts +761 -0
- package/src/knowledge-source-sync.ts +46 -7
- package/src/migrate.ts +19 -0
- package/src/provision-roles.ts +23 -57
- package/src/runtime-posture.ts +103 -7
- package/src/schema.ts +15 -3
- package/src/skills.ts +4 -0
- package/src/video-generation.ts +14 -0
- package/src/workspace-artifacts.ts +2 -0
- package/src/workspace-instruction-policies-schema.ts +1 -0
- package/src/workspace-membership-access.ts +61 -0
- package/dist/chunk-6TKL3GQO.js.map +0 -1
- package/dist/chunk-EYF6MH6C.js +0 -4772
- package/dist/chunk-EYF6MH6C.js.map +0 -1
- package/dist/chunk-GSBONN55.js +0 -533
- package/dist/chunk-GSBONN55.js.map +0 -1
- package/dist/chunk-GVZJ7XSR.js.map +0 -1
- package/dist/chunk-QLA3UQNX.js.map +0 -1
- package/dist/chunk-THJGMEK5.js.map +0 -1
- /package/dist/{chunk-2ZMTQVTR.js.map → chunk-2KOLL33E.js.map} +0 -0
- /package/dist/{chunk-232VC2LW.js.map → chunk-6V3HDEMR.js.map} +0 -0
- /package/dist/{chunk-M7PSMVFF.js.map → chunk-CHBLBEU6.js.map} +0 -0
- /package/dist/{chunk-UK57QA2H.js.map → chunk-UOXWVP3T.js.map} +0 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
import { createHmac, randomUUID } from "node:crypto";
|
|
2
|
+
import { sql } from "drizzle-orm";
|
|
3
|
+
import { stableJson } from "@opengeni/contracts";
|
|
4
|
+
import {
|
|
5
|
+
HostMcpResolver,
|
|
6
|
+
HostMcpResolverSource,
|
|
7
|
+
PutHostMcpResolverRequest,
|
|
8
|
+
RevokeHostMcpResolverRequest,
|
|
9
|
+
} from "@opengeni/contracts/host-mcp-resolvers";
|
|
10
|
+
import { rawRows, setSubjectRlsContext, withRlsContext, type Database } from "./database";
|
|
11
|
+
import { encryptEnvironmentValue, decryptEnvironmentValue } from "./environment-crypto";
|
|
12
|
+
|
|
13
|
+
export class HostMcpResolverError extends Error {
|
|
14
|
+
constructor(
|
|
15
|
+
readonly status: 403 | 404 | 409,
|
|
16
|
+
message: string,
|
|
17
|
+
) {
|
|
18
|
+
super(message);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
type Actor = { accountId: string; subjectId: string };
|
|
22
|
+
type Row = {
|
|
23
|
+
id: string;
|
|
24
|
+
account_id: string;
|
|
25
|
+
external_source: string;
|
|
26
|
+
url: string;
|
|
27
|
+
secret_encrypted: string;
|
|
28
|
+
timeout_ms: number;
|
|
29
|
+
generation: number | string;
|
|
30
|
+
status: string;
|
|
31
|
+
created_at: Date | string;
|
|
32
|
+
updated_at: Date | string;
|
|
33
|
+
};
|
|
34
|
+
const project = (row: Row): HostMcpResolver =>
|
|
35
|
+
HostMcpResolver.parse({
|
|
36
|
+
id: row.id,
|
|
37
|
+
organizationId: row.account_id,
|
|
38
|
+
externalSource: row.external_source,
|
|
39
|
+
url: row.url,
|
|
40
|
+
timeoutMs: row.timeout_ms,
|
|
41
|
+
generation: Number(row.generation),
|
|
42
|
+
status: row.status,
|
|
43
|
+
createdAt: new Date(row.created_at).toISOString(),
|
|
44
|
+
updatedAt: new Date(row.updated_at).toISOString(),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/** Caller proves service-key provenance at the public authentication boundary.
|
|
48
|
+
* Recheck the exact live key under lock, including receipt replay. */
|
|
49
|
+
async function administered<T>(
|
|
50
|
+
db: Database,
|
|
51
|
+
actor: Actor,
|
|
52
|
+
use: (tx: Database) => Promise<T>,
|
|
53
|
+
): Promise<T> {
|
|
54
|
+
return withRlsContext(db, { accountId: actor.accountId, workspaceId: null }, async (tx) => {
|
|
55
|
+
await setSubjectRlsContext(tx, actor.subjectId);
|
|
56
|
+
const [key] = await rawRows(
|
|
57
|
+
tx,
|
|
58
|
+
sql`select id from api_keys where account_id = ${actor.accountId}::uuid
|
|
59
|
+
and 'api_key:' || id::text = ${actor.subjectId} and workspace_id is null and credential_kind = 'organization'
|
|
60
|
+
and revoked_at is null and (expires_at is null or expires_at > clock_timestamp())
|
|
61
|
+
and permissions ? 'account:admin' for share`,
|
|
62
|
+
);
|
|
63
|
+
if (!key) throw new HostMcpResolverError(403, "organization service administration required");
|
|
64
|
+
await tx.execute(
|
|
65
|
+
sql`select pg_advisory_xact_lock(hashtextextended(${`host-mcp-resolvers:${actor.accountId}`}, 0))`,
|
|
66
|
+
);
|
|
67
|
+
return use(tx);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export async function getHostMcpResolver(
|
|
72
|
+
db: Database,
|
|
73
|
+
actor: Actor,
|
|
74
|
+
source: string,
|
|
75
|
+
): Promise<HostMcpResolver> {
|
|
76
|
+
const externalSource = HostMcpResolverSource.parse(source);
|
|
77
|
+
return administered(db, actor, async (tx) => {
|
|
78
|
+
const [row] = await rawRows<Row>(
|
|
79
|
+
tx,
|
|
80
|
+
sql`select * from host_mcp_resolvers where account_id = ${actor.accountId}::uuid and external_source = ${externalSource}`,
|
|
81
|
+
);
|
|
82
|
+
if (!row) throw new HostMcpResolverError(404, "resolver unavailable");
|
|
83
|
+
return project(row);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export async function mutateHostMcpResolver(
|
|
88
|
+
db: Database,
|
|
89
|
+
actor: Actor,
|
|
90
|
+
input: {
|
|
91
|
+
externalSource: string;
|
|
92
|
+
encryptionKey: Uint8Array;
|
|
93
|
+
legacyConfigured: boolean;
|
|
94
|
+
} & (
|
|
95
|
+
| { kind: "put"; request: PutHostMcpResolverRequest }
|
|
96
|
+
| { kind: "revoke"; request: RevokeHostMcpResolverRequest }
|
|
97
|
+
),
|
|
98
|
+
): Promise<HostMcpResolver> {
|
|
99
|
+
const externalSource = HostMcpResolverSource.parse(input.externalSource);
|
|
100
|
+
const putRequest = input.kind === "put" ? PutHostMcpResolverRequest.parse(input.request) : null;
|
|
101
|
+
const operation = putRequest ?? RevokeHostMcpResolverRequest.parse(input.request);
|
|
102
|
+
const digest = createHmac("sha256", input.encryptionKey)
|
|
103
|
+
.update("opengeni:host-mcp-resolver-operation:v1\0")
|
|
104
|
+
.update(stableJson({ actor, externalSource, kind: input.kind, request: operation }))
|
|
105
|
+
.digest("hex");
|
|
106
|
+
return administered(db, actor, async (tx) => {
|
|
107
|
+
const [receipt] = await rawRows<{ request_digest: string; result: unknown }>(
|
|
108
|
+
tx,
|
|
109
|
+
sql`select request_digest, result from host_mcp_resolver_operations
|
|
110
|
+
where account_id = ${actor.accountId}::uuid and operation_id = ${operation.operationId}::uuid`,
|
|
111
|
+
);
|
|
112
|
+
if (receipt) {
|
|
113
|
+
if (receipt.request_digest !== digest)
|
|
114
|
+
throw new HostMcpResolverError(409, "resolver operation conflicts");
|
|
115
|
+
// Return historical metadata only; never restore old configuration or secrets.
|
|
116
|
+
return HostMcpResolver.parse(receipt.result);
|
|
117
|
+
}
|
|
118
|
+
const [current] = await rawRows<Row>(
|
|
119
|
+
tx,
|
|
120
|
+
sql`select * from host_mcp_resolvers where account_id = ${actor.accountId}::uuid and external_source = ${externalSource} for update`,
|
|
121
|
+
);
|
|
122
|
+
if ((current ? Number(current.generation) : 0) !== operation.expectedGeneration)
|
|
123
|
+
throw new HostMcpResolverError(409, "resolver generation changed");
|
|
124
|
+
let row: Row | undefined;
|
|
125
|
+
if (putRequest) {
|
|
126
|
+
const request = putRequest;
|
|
127
|
+
const [existing] = await rawRows(
|
|
128
|
+
tx,
|
|
129
|
+
sql`select id from host_mcp_resolvers where account_id = ${actor.accountId}::uuid limit 1`,
|
|
130
|
+
);
|
|
131
|
+
if (!existing && input.legacyConfigured && !request.acknowledgeLegacyRoutingReplacement)
|
|
132
|
+
throw new HostMcpResolverError(
|
|
133
|
+
409,
|
|
134
|
+
"first registration requires explicit legacy routing replacement acknowledgement",
|
|
135
|
+
);
|
|
136
|
+
const id = current?.id ?? randomUUID();
|
|
137
|
+
const generation = request.expectedGeneration + 1;
|
|
138
|
+
const encrypted = encryptEnvironmentValue(
|
|
139
|
+
input.encryptionKey,
|
|
140
|
+
JSON.stringify({
|
|
141
|
+
version: 1,
|
|
142
|
+
id,
|
|
143
|
+
accountId: actor.accountId,
|
|
144
|
+
externalSource,
|
|
145
|
+
generation,
|
|
146
|
+
url: request.url,
|
|
147
|
+
bearerToken: request.bearerToken,
|
|
148
|
+
}),
|
|
149
|
+
);
|
|
150
|
+
[row] = current
|
|
151
|
+
? await rawRows<Row>(
|
|
152
|
+
tx,
|
|
153
|
+
sql`update host_mcp_resolvers set url = ${request.url}, secret_encrypted = ${encrypted}, timeout_ms = ${request.timeoutMs}, generation = ${generation}, status = 'active', updated_at = clock_timestamp() where id = ${id}::uuid returning *`,
|
|
154
|
+
)
|
|
155
|
+
: await rawRows<Row>(
|
|
156
|
+
tx,
|
|
157
|
+
sql`insert into host_mcp_resolvers (id, account_id, external_source, url, secret_encrypted, timeout_ms, generation, status) values (${id}::uuid, ${actor.accountId}::uuid, ${externalSource}, ${request.url}, ${encrypted}, ${request.timeoutMs}, 1, 'active') returning *`,
|
|
158
|
+
);
|
|
159
|
+
} else {
|
|
160
|
+
if (!current) throw new HostMcpResolverError(404, "resolver unavailable");
|
|
161
|
+
[row] = await rawRows<Row>(
|
|
162
|
+
tx,
|
|
163
|
+
sql`update host_mcp_resolvers set status = 'revoked', generation = generation + 1, updated_at = clock_timestamp() where id = ${current.id}::uuid returning *`,
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
if (!row) throw new Error("resolver mutation unavailable");
|
|
167
|
+
const result = project(row);
|
|
168
|
+
await tx.execute(sql`insert into host_mcp_resolver_operations (account_id, operation_id, actor_subject_id, request_digest, result)
|
|
169
|
+
values (${actor.accountId}::uuid, ${operation.operationId}::uuid, ${actor.subjectId}, ${digest}, ${JSON.stringify(result)}::jsonb)`);
|
|
170
|
+
return result;
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export type HostMcpResolverRoute =
|
|
175
|
+
| { mode: "legacy" }
|
|
176
|
+
| { mode: "denied" }
|
|
177
|
+
| {
|
|
178
|
+
mode: "namespace";
|
|
179
|
+
id: string;
|
|
180
|
+
generation: number;
|
|
181
|
+
accountId: string;
|
|
182
|
+
workspaceId: string;
|
|
183
|
+
externalSource: string;
|
|
184
|
+
url: string;
|
|
185
|
+
bearerToken: string;
|
|
186
|
+
timeoutMs: number;
|
|
187
|
+
};
|
|
188
|
+
/** Runtime lookup, not tool authority. Failure must never be interpreted as legacy. */
|
|
189
|
+
export async function resolveHostMcpResolverRoute(
|
|
190
|
+
db: Database,
|
|
191
|
+
input: { accountId: string; workspaceId: string },
|
|
192
|
+
encryptionKey: Uint8Array | null,
|
|
193
|
+
): Promise<HostMcpResolverRoute> {
|
|
194
|
+
return withRlsContext(
|
|
195
|
+
db,
|
|
196
|
+
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
197
|
+
async (tx) => {
|
|
198
|
+
const [workspace] = await rawRows<{ external_source: string | null }>(
|
|
199
|
+
tx,
|
|
200
|
+
sql`select external_source from workspaces where id = ${input.workspaceId}::uuid and account_id = ${input.accountId}::uuid`,
|
|
201
|
+
);
|
|
202
|
+
if (!workspace) return { mode: "denied" };
|
|
203
|
+
const [any] = await rawRows(
|
|
204
|
+
tx,
|
|
205
|
+
sql`select id from host_mcp_resolvers where account_id = ${input.accountId}::uuid limit 1`,
|
|
206
|
+
);
|
|
207
|
+
if (!any) return { mode: "legacy" };
|
|
208
|
+
if (!workspace.external_source || !encryptionKey) return { mode: "denied" };
|
|
209
|
+
const [row] = await rawRows<Row>(
|
|
210
|
+
tx,
|
|
211
|
+
sql`select * from host_mcp_resolvers where account_id = ${input.accountId}::uuid and external_source = ${workspace.external_source} and status = 'active'`,
|
|
212
|
+
);
|
|
213
|
+
if (!row) return { mode: "denied" };
|
|
214
|
+
const bundle = JSON.parse(decryptEnvironmentValue(encryptionKey, row.secret_encrypted));
|
|
215
|
+
if (
|
|
216
|
+
bundle.version !== 1 ||
|
|
217
|
+
bundle.id !== row.id ||
|
|
218
|
+
bundle.accountId !== input.accountId ||
|
|
219
|
+
bundle.externalSource !== workspace.external_source ||
|
|
220
|
+
bundle.generation !== Number(row.generation) ||
|
|
221
|
+
bundle.url !== row.url ||
|
|
222
|
+
typeof bundle.bearerToken !== "string" ||
|
|
223
|
+
!bundle.bearerToken ||
|
|
224
|
+
/[\r\n]/u.test(bundle.bearerToken)
|
|
225
|
+
)
|
|
226
|
+
throw new Error("resolver secret binding invalid");
|
|
227
|
+
return {
|
|
228
|
+
mode: "namespace",
|
|
229
|
+
id: row.id,
|
|
230
|
+
generation: Number(row.generation),
|
|
231
|
+
accountId: input.accountId,
|
|
232
|
+
workspaceId: input.workspaceId,
|
|
233
|
+
externalSource: workspace.external_source,
|
|
234
|
+
url: row.url,
|
|
235
|
+
bearerToken: bundle.bearerToken,
|
|
236
|
+
timeoutMs: row.timeout_ms,
|
|
237
|
+
};
|
|
238
|
+
},
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export async function hostMcpResolverRouteIsCurrent(
|
|
243
|
+
db: Database,
|
|
244
|
+
input: { accountId: string; workspaceId: string },
|
|
245
|
+
route: HostMcpResolverRoute,
|
|
246
|
+
): Promise<boolean> {
|
|
247
|
+
if (route.mode === "denied") return false;
|
|
248
|
+
return withRlsContext(
|
|
249
|
+
db,
|
|
250
|
+
{ accountId: input.accountId, workspaceId: input.workspaceId },
|
|
251
|
+
async (tx) => {
|
|
252
|
+
const [row] =
|
|
253
|
+
route.mode === "legacy"
|
|
254
|
+
? await rawRows(
|
|
255
|
+
tx,
|
|
256
|
+
sql`select w.id from workspaces w where w.id = ${input.workspaceId}::uuid and w.account_id = ${input.accountId}::uuid and not exists (select 1 from host_mcp_resolvers r where r.account_id = w.account_id)`,
|
|
257
|
+
)
|
|
258
|
+
: await rawRows(
|
|
259
|
+
tx,
|
|
260
|
+
sql`select r.id from host_mcp_resolvers r join workspaces w on w.account_id = r.account_id and w.external_source = r.external_source
|
|
261
|
+
where w.id = ${input.workspaceId}::uuid and r.account_id = ${input.accountId}::uuid and r.external_source = ${route.externalSource} and r.id = ${route.id}::uuid and r.generation = ${route.generation} and r.status = 'active'`,
|
|
262
|
+
);
|
|
263
|
+
return Boolean(row);
|
|
264
|
+
},
|
|
265
|
+
);
|
|
266
|
+
}
|
|
@@ -9,6 +9,8 @@ import {
|
|
|
9
9
|
HostMcpTaskAuthority,
|
|
10
10
|
HostMcpBindingDefinition,
|
|
11
11
|
HostMcpOwnerSubject,
|
|
12
|
+
hostMcpBindingMatchesSelection,
|
|
13
|
+
type HostMcpBindingSelection,
|
|
12
14
|
} from "@opengeni/contracts/host-mcp-bindings";
|
|
13
15
|
import { getScheduledTaskRevisionAuthority } from "./scheduled-task-revision-authority";
|
|
14
16
|
import { getHostMcpLiveAttempt } from "./live-session-attempt";
|
|
@@ -287,11 +289,7 @@ export async function inheritHostMcpTaskAuthoritiesFromAttempt(
|
|
|
287
289
|
db: Database,
|
|
288
290
|
task: ScheduledTask,
|
|
289
291
|
source: { sessionId: string; turnId: string; attemptId: string; executionGeneration: number },
|
|
290
|
-
configured:
|
|
291
|
-
bindingId: string;
|
|
292
|
-
bindingGeneration: number;
|
|
293
|
-
definition: HostMcpBindingDefinition;
|
|
294
|
-
}>,
|
|
292
|
+
configured: HostMcpBindingSelection[],
|
|
295
293
|
): Promise<void> {
|
|
296
294
|
const proof = await getScheduledTaskRevisionAuthority(db, {
|
|
297
295
|
accountId: task.accountId,
|
|
@@ -333,12 +331,13 @@ export async function inheritHostMcpTaskAuthoritiesFromAttempt(
|
|
|
333
331
|
const selected: SelectedHostMcpTaskGrant[] = [];
|
|
334
332
|
for (const row of rows) {
|
|
335
333
|
const a = HostMcpAcceptedAuthority.parse(row.canonical_snapshot);
|
|
336
|
-
const server = configured.find((c) => c.
|
|
334
|
+
const server = configured.find((c) => c.serverId === a.definition.serverId);
|
|
337
335
|
if (!server) continue;
|
|
338
336
|
if (
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
337
|
+
!hostMcpBindingMatchesSelection(
|
|
338
|
+
{ id: a.bindingId, generation: a.bindingGeneration, definition: a.definition },
|
|
339
|
+
server,
|
|
340
|
+
)
|
|
342
341
|
)
|
|
343
342
|
throw new HostMcpDelegationAuthorityError("Host task source destination changed");
|
|
344
343
|
const delegation = await getHostMcpDelegation(tx, owner, a.delegationId);
|
|
@@ -373,7 +372,9 @@ export async function inheritHostMcpTaskAuthoritiesFromAttempt(
|
|
|
373
372
|
selected.push({
|
|
374
373
|
delegationId: a.delegationId,
|
|
375
374
|
generation: a.delegationGeneration,
|
|
376
|
-
|
|
375
|
+
bindingId: a.bindingId,
|
|
376
|
+
bindingGeneration: a.bindingGeneration,
|
|
377
|
+
definition: a.definition,
|
|
377
378
|
});
|
|
378
379
|
}
|
|
379
380
|
return selected;
|