@axiom-lattice/gateway 8.4.0 → 10.0.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 (64) hide show
  1. package/dist/{a2a-TDZ3TT6H.mjs → a2a-YLKZE5JG.mjs} +6 -4
  2. package/dist/{a2a-standard-INVCUSAW.mjs → a2a-standard-NOAVPYXJ.mjs} +42 -127
  3. package/dist/a2a-standard-NOAVPYXJ.mjs.map +1 -0
  4. package/dist/chunk-NYYSBNDG.mjs +575 -0
  5. package/dist/chunk-NYYSBNDG.mjs.map +1 -0
  6. package/dist/{chunk-2SR4F3ZD.mjs → chunk-PHWGCRW2.mjs} +2 -1
  7. package/dist/{chunk-2SR4F3ZD.mjs.map → chunk-PHWGCRW2.mjs.map} +1 -1
  8. package/dist/{chunk-W3YH4S6G.mjs → chunk-SIMEG2JT.mjs} +19 -2
  9. package/dist/chunk-SIMEG2JT.mjs.map +1 -0
  10. package/dist/embed/{embed-page-AgentDetailSideApp-TQEJK6ZF.js → embed-page-AgentDetailSideApp-X5HKDN3N.js} +1 -1
  11. package/dist/embed/embed-page-AgentGovernanceWorkbench-MFXL7BOW.js +1 -0
  12. package/dist/embed/{embed-page-LangfuseDashboard-7OANGQXY.js → embed-page-LangfuseDashboard-NPYFMKK3.js} +1 -1
  13. package/dist/embed/{embed-page-MessageGraph-KJPQWTHE.js → embed-page-MessageGraph-JUCEXYLU.js} +1 -1
  14. package/dist/embed/{embed-page-ReactChart-2CAIM4JD.js → embed-page-ReactChart-2QJ3QRBH.js} +1 -1
  15. package/dist/embed/{embed-page-SkillFlow-243MXRXC.js → embed-page-SkillFlow-PFEXQ75Z.js} +1 -1
  16. package/dist/embed/{embed-page-TasksSideApp-OA7CULHS.js → embed-page-TasksSideApp-SBHVHNVT.js} +1 -1
  17. package/dist/embed/{embed-page-ThreadMaintenancePanel-Z4424X3J.js → embed-page-ThreadMaintenancePanel-LCCRUA75.js} +1 -1
  18. package/dist/embed/{embed-page-TopologyRuntimeView-THTCZUS7.js → embed-page-TopologyRuntimeView-ATA23XXF.js} +1 -1
  19. package/dist/embed/embed-page-WorkflowAutomationView-OVGOUVXH.js +3 -0
  20. package/dist/embed/embed-page-chunk-7F5BSMP3.js +211 -0
  21. package/dist/embed/embed-page-chunk-HLBQ5JKL.js +6968 -0
  22. package/dist/embed/{embed-page-chunk-RKQJBKN2.js → embed-page-chunk-HUH33Z2E.js} +1 -1
  23. package/dist/embed/embed-page-chunk-LZ4ITV3M.js +242 -0
  24. package/dist/embed/{embed-page-chunk-LDQGH44H.js → embed-page-chunk-ODTY6SE7.js} +1 -1
  25. package/dist/embed/embed-page-chunk-Q7Z7MHOM.js +76 -0
  26. package/dist/embed/embed-page-chunk-QOPHOXA7.js +3 -0
  27. package/dist/embed/{embed-page-chunk-FZX4A32D.js → embed-page-chunk-RFF7S4H5.js} +5 -5
  28. package/dist/embed/{embed-page-chunk-L2EGVVJS.js → embed-page-chunk-VNRFN74K.js} +1 -1
  29. package/dist/embed/{embed-page-chunk-JMP7EQEF.js → embed-page-chunk-WE6PZS2N.js} +1 -1
  30. package/dist/embed/{embed-page-en-DNDGCPMA.js → embed-page-en-4HTY4XK4.js} +1 -1
  31. package/dist/embed/embed-page-en-KZQZS4JN.js +1 -0
  32. package/dist/embed/embed-page-en-VHD2WUUG.js +1 -0
  33. package/dist/embed/embed-page-zh-A7DSGF6P.js +1 -0
  34. package/dist/embed/embed-page-zh-KSZOJPOV.js +1 -0
  35. package/dist/embed/{embed-page-zh-2H4EB3F3.js → embed-page-zh-UHTZEW5G.js} +1 -1
  36. package/dist/embed/embed-page.js +1 -1
  37. package/dist/embed/mcp-app-page.js +76 -15
  38. package/dist/index.js +1699 -1498
  39. package/dist/index.js.map +1 -1
  40. package/dist/index.mjs +241 -382
  41. package/dist/index.mjs.map +1 -1
  42. package/dist/{open-27ZPLBIW.mjs → open-PCOORPQ5.mjs} +63 -16
  43. package/dist/open-PCOORPQ5.mjs.map +1 -0
  44. package/dist/{open-exposure-BPLYUIX6.mjs → open-exposure-HGYT5VFC.mjs} +5 -6
  45. package/dist/open-exposure-HGYT5VFC.mjs.map +1 -0
  46. package/package.json +18 -13
  47. package/dist/a2a-standard-INVCUSAW.mjs.map +0 -1
  48. package/dist/chunk-OBODBHIS.mjs +0 -230
  49. package/dist/chunk-OBODBHIS.mjs.map +0 -1
  50. package/dist/chunk-W3YH4S6G.mjs.map +0 -1
  51. package/dist/embed/embed-page-AgentGovernanceWorkbench-II2MRGCG.js +0 -1
  52. package/dist/embed/embed-page-WorkflowAutomationView-YDIDG35E.js +0 -3
  53. package/dist/embed/embed-page-chunk-7ULTMRM2.js +0 -211
  54. package/dist/embed/embed-page-chunk-OMN6G52V.js +0 -3
  55. package/dist/embed/embed-page-chunk-VYS3TAK4.js +0 -242
  56. package/dist/embed/embed-page-chunk-W5OP2CZG.js +0 -15
  57. package/dist/embed/embed-page-chunk-Z6KWW64I.js +0 -6837
  58. package/dist/embed/embed-page-en-D4M3DPFT.js +0 -1
  59. package/dist/embed/embed-page-en-JOTELYAL.js +0 -1
  60. package/dist/embed/embed-page-zh-BPO6ZSJM.js +0 -1
  61. package/dist/embed/embed-page-zh-NEXLMDHF.js +0 -1
  62. package/dist/open-27ZPLBIW.mjs.map +0 -1
  63. package/dist/open-exposure-BPLYUIX6.mjs.map +0 -1
  64. /package/dist/{a2a-TDZ3TT6H.mjs.map → a2a-YLKZE5JG.mjs.map} +0 -0
package/dist/index.mjs CHANGED
@@ -33,7 +33,7 @@ import {
33
33
  setRunTaskWakePublisher,
34
34
  setRunTaskWakeStatsSource,
35
35
  wakeRunTaskQueue
36
- } from "./chunk-2SR4F3ZD.mjs";
36
+ } from "./chunk-PHWGCRW2.mjs";
37
37
  import {
38
38
  claimDedupKey,
39
39
  createRateLimitService,
@@ -48,23 +48,26 @@ import "./chunk-EXPERMZR.mjs";
48
48
  import {
49
49
  CollectionService
50
50
  } from "./chunk-PWHUWFXL.mjs";
51
- import {
52
- getMcpUiResourceResolver,
53
- listTenantPlugins,
54
- registerMcpAppRoutes,
55
- resolveTenantPluginByType
56
- } from "./chunk-T2HIWZGP.mjs";
57
- import "./chunk-XUWD4VKY.mjs";
58
51
  import {
59
52
  A2A_KEY_CHANGED_TOPIC,
53
+ ProjectAccessService,
54
+ ProjectCollaborationError,
60
55
  handleA2AKeyChanged,
61
56
  publishA2AKeyChanged,
62
- refreshStoreKeyMap
63
- } from "./chunk-OBODBHIS.mjs";
57
+ refreshStoreKeyMap,
58
+ setA2AProjectAccess
59
+ } from "./chunk-NYYSBNDG.mjs";
64
60
  import {
65
61
  A2AAuthService,
66
62
  parseEnvKeys
67
63
  } from "./chunk-LCM4OQTI.mjs";
64
+ import {
65
+ getMcpUiResourceResolver,
66
+ listTenantPlugins,
67
+ registerMcpAppRoutes,
68
+ resolveTenantPluginByType
69
+ } from "./chunk-T2HIWZGP.mjs";
70
+ import "./chunk-XUWD4VKY.mjs";
68
71
  import "./chunk-MFWTGNQR.mjs";
69
72
  import {
70
73
  createOrphanRecoveryRuntime,
@@ -90,7 +93,7 @@ import staticPlugin from "@fastify/static";
90
93
  import path4 from "path";
91
94
 
92
95
  // src/routes/index.ts
93
- import { randomUUID as randomUUID32 } from "crypto";
96
+ import { randomUUID as randomUUID31 } from "crypto";
94
97
  import {
95
98
  descriptorDataValue as descriptorDataValue3,
96
99
  snapshotExactRecord as snapshotExactRecord14,
@@ -3857,7 +3860,10 @@ function createRunLifecycleHandlers(deps = {}) {
3857
3860
  const tenantId = getTenantId4(request);
3858
3861
  const { assistantId, threadId } = request.params;
3859
3862
  if (!await ownsThread(tenantId, assistantId, threadId)) {
3860
- return notFound2(reply, THREAD_NOT_FOUND2, "Thread not found");
3863
+ if (!await isNewThread(tenantId, threadId)) {
3864
+ return notFound2(reply, THREAD_NOT_FOUND2, "Thread not found");
3865
+ }
3866
+ return reply.status(200).send({ success: true, data: { runs: [] } });
3861
3867
  }
3862
3868
  const activeOnly = request.query.active === "true" || request.query.active === "1";
3863
3869
  const source = request.query.source;
@@ -11000,8 +11006,9 @@ function createProjectCollaborationInitializer(deps) {
11000
11006
  };
11001
11007
  }
11002
11008
  var WorkspaceController = class {
11003
- constructor(projectCollaboration) {
11009
+ constructor(projectCollaboration, projectAccess) {
11004
11010
  this.projectCollaboration = projectCollaboration;
11011
+ this.projectAccess = projectAccess;
11005
11012
  this.workspaceStore = getStoreLattice16("default", "workspace").store;
11006
11013
  this.projectStore = getStoreLattice16("default", "project").store;
11007
11014
  const roomStore = getStoreLattice16("default", "projectRoom").store;
@@ -11043,6 +11050,48 @@ var WorkspaceController = class {
11043
11050
  }
11044
11051
  return request.headers["x-tenant-id"] || "default";
11045
11052
  }
11053
+ requireActor(request, reply) {
11054
+ const user = request.user;
11055
+ if (!user?.id || !user.tenantId) {
11056
+ void reply.status(401).send({
11057
+ success: false,
11058
+ code: "UNAUTHORIZED",
11059
+ error: "Unauthorized"
11060
+ });
11061
+ return null;
11062
+ }
11063
+ return { tenantId: user.tenantId, userId: user.id };
11064
+ }
11065
+ accessService() {
11066
+ if (!this.projectAccess) {
11067
+ throw new Error("Project access service is not configured");
11068
+ }
11069
+ return this.projectAccess;
11070
+ }
11071
+ async requireReadableProject(actor3, workspaceId, projectId, capability2) {
11072
+ try {
11073
+ const result = await this.accessService().requireExistingProjectAccess({
11074
+ tenantId: actor3.tenantId,
11075
+ userId: actor3.userId,
11076
+ projectId,
11077
+ capability: capability2
11078
+ });
11079
+ if (result.project.workspaceId !== workspaceId) return null;
11080
+ return result.project;
11081
+ } catch (error) {
11082
+ if (error instanceof ProjectCollaborationError && (error.code === "PROJECT_ACCESS_DENIED" || error.code === "PROJECT_NOT_FOUND")) {
11083
+ return null;
11084
+ }
11085
+ throw error;
11086
+ }
11087
+ }
11088
+ projectNotFound(reply) {
11089
+ return reply.status(404).send({
11090
+ success: false,
11091
+ code: "PROJECT_NOT_FOUND",
11092
+ error: "Project not found"
11093
+ });
11094
+ }
11046
11095
  // ==================== Workspace CRUD ====================
11047
11096
  async listWorkspaces(request, reply) {
11048
11097
  const tenantId = this.getTenantId(request);
@@ -11100,14 +11149,18 @@ var WorkspaceController = class {
11100
11149
  }
11101
11150
  // ==================== Project CRUD ====================
11102
11151
  async listProjects(request, reply) {
11103
- const tenantId = this.getTenantId(request);
11152
+ const actor3 = this.requireActor(request, reply);
11153
+ if (!actor3) return;
11104
11154
  const { workspaceId } = request.params;
11105
11155
  const kindFilter = request.query.kind;
11106
- await this.ensureTrainingProject(tenantId, workspaceId);
11107
- await this.publicRoom.ensure(tenantId, workspaceId);
11108
- const projects = kindFilter ? await this.projectStore.getProjectsByWorkspace(tenantId, workspaceId, {
11156
+ await this.ensureTrainingProject(actor3.tenantId, workspaceId);
11157
+ await this.publicRoom.ensure(actor3.tenantId, workspaceId);
11158
+ const projects = await this.accessService().listReadableProjects({
11159
+ tenantId: actor3.tenantId,
11160
+ userId: actor3.userId,
11161
+ workspaceId,
11109
11162
  kind: kindFilter
11110
- }) : await this.projectStore.getProjectsByWorkspace(tenantId, workspaceId);
11163
+ });
11111
11164
  return { success: true, data: projects };
11112
11165
  }
11113
11166
  /**
@@ -11132,13 +11185,9 @@ var WorkspaceController = class {
11132
11185
  });
11133
11186
  }
11134
11187
  async createProject(request, reply) {
11135
- const user = request.user;
11136
- const requestedTenantId = request.query?.tenantId ?? request.headers["x-tenant-id"];
11137
- const selectedTenantId = requestedTenantId === void 0 ? void 0 : String(requestedTenantId);
11138
- if (user?.tenantId && selectedTenantId && user.tenantId !== selectedTenantId) {
11139
- return reply.status(403).send({ success: false, code: "TENANT_ACCESS_DENIED", error: "Tenant access denied" });
11140
- }
11141
- const tenantId = user?.tenantId ?? selectedTenantId ?? "default";
11188
+ const actor3 = this.requireActor(request, reply);
11189
+ if (!actor3) return;
11190
+ const tenantId = actor3.tenantId;
11142
11191
  const { workspaceId } = request.params;
11143
11192
  const data = request.body;
11144
11193
  if (writesCapabilityBundleIds(data.config)) {
@@ -11148,9 +11197,9 @@ var WorkspaceController = class {
11148
11197
  message: CAPABILITY_BUNDLE_CONFIG_MESSAGE
11149
11198
  });
11150
11199
  }
11151
- if (user?.id && this.projectCollaboration) {
11200
+ if (this.projectCollaboration) {
11152
11201
  try {
11153
- const authorized = await this.projectCollaboration.authorizeCreator({ tenantId, userId: user.id });
11202
+ const authorized = await this.projectCollaboration.authorizeCreator({ tenantId, userId: actor3.userId });
11154
11203
  if (!authorized) {
11155
11204
  return reply.status(403).send({ success: false, code: "TENANT_ACCESS_DENIED", error: "Tenant access denied" });
11156
11205
  }
@@ -11161,7 +11210,7 @@ var WorkspaceController = class {
11161
11210
  console.error({
11162
11211
  event: "project:collaboration-preflight-failed",
11163
11212
  tenantId,
11164
- userId: user.id,
11213
+ userId: actor3.userId,
11165
11214
  errorName: error instanceof Error ? error.name : "UnknownError"
11166
11215
  });
11167
11216
  return reply.status(500).send({
@@ -11179,42 +11228,72 @@ var WorkspaceController = class {
11179
11228
  id3,
11180
11229
  data
11181
11230
  );
11182
- if (user?.id && this.projectCollaboration) {
11231
+ if (this.projectCollaboration) {
11183
11232
  try {
11184
- await this.projectCollaboration.initialize({ tenantId, userId: user.id, project });
11233
+ await this.projectCollaboration.initialize({ tenantId, userId: actor3.userId, project });
11185
11234
  } catch (error) {
11186
- const phase = error instanceof ProjectCollaborationInitializationError ? error.phase : "owner";
11235
+ const phase = error instanceof ProjectCollaborationInitializationError ? error.phase : void 0;
11236
+ let rolledBack = false;
11237
+ if (phase === "owner") {
11238
+ try {
11239
+ rolledBack = await this.projectStore.deleteProject(tenantId, project.id);
11240
+ if (!rolledBack) {
11241
+ console.error({
11242
+ event: "project:owner-initialization-rollback-missed",
11243
+ tenantId,
11244
+ projectId: project.id
11245
+ });
11246
+ }
11247
+ } catch (cleanupError) {
11248
+ console.error({
11249
+ event: "project:owner-initialization-rollback-failed",
11250
+ tenantId,
11251
+ projectId: project.id,
11252
+ errorName: cleanupError instanceof Error ? cleanupError.name : "UnknownError"
11253
+ });
11254
+ }
11255
+ }
11187
11256
  console.error({
11188
11257
  event: "project:collaboration-initialization-failed",
11189
11258
  phase,
11190
11259
  tenantId,
11191
11260
  projectId: project.id,
11192
- userId: user.id,
11261
+ userId: actor3.userId,
11193
11262
  errorName: error instanceof Error ? error.name : "UnknownError"
11194
11263
  });
11195
11264
  return reply.status(500).send({
11196
11265
  success: false,
11197
11266
  error: "Internal server error",
11198
- code: phase === "owner" ? "PROJECT_OWNER_INITIALIZATION_FAILED" : "PROJECT_ROOM_INITIALIZATION_FAILED",
11267
+ code: phase === "owner" ? "PROJECT_OWNER_INITIALIZATION_FAILED" : phase === "room" ? "PROJECT_ROOM_INITIALIZATION_FAILED" : "PROJECT_COLLABORATION_INITIALIZATION_FAILED",
11199
11268
  projectId: project.id,
11200
- retryable: phase === "room"
11269
+ retryable: phase === "room" || rolledBack
11201
11270
  });
11202
11271
  }
11203
11272
  }
11204
11273
  return reply.status(201).send({ success: true, data: project });
11205
11274
  }
11206
11275
  async getProject(request, reply) {
11207
- const tenantId = this.getTenantId(request);
11208
- const { projectId } = request.params;
11209
- const project = await this.projectStore.getProjectById(tenantId, projectId);
11210
- if (!project) {
11211
- return reply.status(404).send({ success: false, error: "Project not found" });
11212
- }
11276
+ const actor3 = this.requireActor(request, reply);
11277
+ if (!actor3) return;
11278
+ const project = await this.requireReadableProject(
11279
+ actor3,
11280
+ request.params.workspaceId,
11281
+ request.params.projectId,
11282
+ "read"
11283
+ );
11284
+ if (!project) return this.projectNotFound(reply);
11213
11285
  return { success: true, data: project };
11214
11286
  }
11215
11287
  async updateProject(request, reply) {
11216
- const tenantId = this.getTenantId(request);
11217
- const { projectId } = request.params;
11288
+ const actor3 = this.requireActor(request, reply);
11289
+ if (!actor3) return;
11290
+ const project = await this.requireReadableProject(
11291
+ actor3,
11292
+ request.params.workspaceId,
11293
+ request.params.projectId,
11294
+ "manage"
11295
+ );
11296
+ if (!project) return this.projectNotFound(reply);
11218
11297
  const updates = request.body;
11219
11298
  if (writesCapabilityBundleIds(updates.config)) {
11220
11299
  return reply.status(400).send({
@@ -11223,36 +11302,35 @@ var WorkspaceController = class {
11223
11302
  message: CAPABILITY_BUNDLE_CONFIG_MESSAGE
11224
11303
  });
11225
11304
  }
11226
- if (updates.kind !== void 0) {
11227
- const existingProject = await this.projectStore.getProjectById(tenantId, projectId);
11228
- if (existingProject && existingProject.id === workspacePublicRoomProjectId(tenantId, existingProject.workspaceId)) {
11229
- return reply.status(409).send({
11230
- success: false,
11231
- error: "The workspace public room classification cannot be changed"
11232
- });
11233
- }
11305
+ if (project.id === workspacePublicRoomProjectId(actor3.tenantId, project.workspaceId) && (updates.kind !== void 0 || updates.name !== void 0)) {
11306
+ return reply.status(409).send({
11307
+ success: false,
11308
+ error: "The workspace public room cannot be renamed or reclassified"
11309
+ });
11234
11310
  }
11235
- const project = await this.projectStore.updateProject(
11236
- tenantId,
11237
- projectId,
11311
+ const updated = await this.projectStore.updateProject(
11312
+ actor3.tenantId,
11313
+ project.id,
11238
11314
  updates
11239
11315
  );
11240
- if (!project) {
11241
- return reply.status(404).send({ success: false, error: "Project not found" });
11242
- }
11243
- return { success: true, data: project };
11316
+ if (!updated) return this.projectNotFound(reply);
11317
+ return { success: true, data: updated };
11244
11318
  }
11245
11319
  async deleteProject(request, reply) {
11246
- const tenantId = this.getTenantId(request);
11247
- const { workspaceId, projectId } = request.params;
11248
- const project = await this.projectStore.getProjectById(tenantId, projectId);
11249
- if (!project) {
11250
- return reply.status(404).send({ success: false, error: "Project not found" });
11251
- }
11320
+ const actor3 = this.requireActor(request, reply);
11321
+ if (!actor3) return;
11322
+ const project = await this.requireReadableProject(
11323
+ actor3,
11324
+ request.params.workspaceId,
11325
+ request.params.projectId,
11326
+ "manage"
11327
+ );
11328
+ if (!project) return this.projectNotFound(reply);
11329
+ const { workspaceId } = request.params;
11252
11330
  if (project.kind === "training") {
11253
11331
  const training = await this.projectStore.getProjectsByWorkspace(
11254
- tenantId,
11255
- workspaceId,
11332
+ actor3.tenantId,
11333
+ project.workspaceId,
11256
11334
  { kind: "training" }
11257
11335
  );
11258
11336
  if (training.length <= 1) {
@@ -11262,16 +11340,14 @@ var WorkspaceController = class {
11262
11340
  });
11263
11341
  }
11264
11342
  }
11265
- if (project.id === workspacePublicRoomProjectId(tenantId, project.workspaceId ?? workspaceId)) {
11343
+ if (project.id === workspacePublicRoomProjectId(actor3.tenantId, project.workspaceId ?? workspaceId)) {
11266
11344
  return reply.status(409).send({
11267
11345
  success: false,
11268
11346
  error: "The workspace public room cannot be deleted"
11269
11347
  });
11270
11348
  }
11271
- const deleted = await this.projectStore.deleteProject(tenantId, projectId);
11272
- if (!deleted) {
11273
- return reply.status(404).send({ success: false, error: "Project not found" });
11274
- }
11349
+ const deleted = await this.projectStore.deleteProject(actor3.tenantId, project.id);
11350
+ if (!deleted) return this.projectNotFound(reply);
11275
11351
  return { success: true };
11276
11352
  }
11277
11353
  // ==================== File Operations ====================
@@ -11909,8 +11985,8 @@ var WorkspaceController = class {
11909
11985
  }
11910
11986
  }
11911
11987
  };
11912
- function registerWorkspaceRoutes(app2, projectCollaboration) {
11913
- const controller = new WorkspaceController(projectCollaboration);
11988
+ function registerWorkspaceRoutes(app2, projectCollaboration, projectAccess) {
11989
+ const controller = new WorkspaceController(projectCollaboration, projectAccess);
11914
11990
  app2.get("/api/workspaces", controller.listWorkspaces.bind(controller));
11915
11991
  app2.post("/api/workspaces", controller.createWorkspace.bind(controller));
11916
11992
  app2.get(
@@ -11977,250 +12053,12 @@ function registerWorkspaceRoutes(app2, projectCollaboration) {
11977
12053
  return controller;
11978
12054
  }
11979
12055
 
11980
- // src/services/collaboration/ProjectAccessService.ts
11981
- import { randomUUID as randomUUID14 } from "crypto";
11982
- var ProjectCollaborationError = class extends Error {
11983
- /** Creates a project collaboration error. */
11984
- constructor(code, statusCode, message) {
11985
- super(message);
11986
- this.code = code;
11987
- this.statusCode = statusCode;
11988
- this.name = "ProjectCollaborationError";
11989
- }
11990
- };
11991
- var allowedRoles = {
11992
- read: /* @__PURE__ */ new Set(["owner", "admin", "member", "viewer"]),
11993
- send: /* @__PURE__ */ new Set(["owner", "admin", "member"]),
11994
- manage: /* @__PURE__ */ new Set(["owner", "admin"])
11995
- };
11996
- var membershipConflictNames = /* @__PURE__ */ new Set([
11997
- "DuplicateProjectMembershipError",
11998
- "ProjectMembershipIdConflictError"
11999
- ]);
12000
- function isProjectMembershipConflict(error) {
12001
- return error instanceof Error && membershipConflictNames.has(error.name);
12002
- }
12003
- var ProjectAccessService = class {
12004
- /** Creates a project access service from explicitly injected stores. */
12005
- constructor(deps) {
12006
- this.deps = deps;
12007
- this.idFactory = deps.idFactory ?? randomUUID14;
12008
- }
12009
- /** Returns the project and active membership when the user has the requested capability. */
12010
- async requireProjectAccess(input) {
12011
- const project = await this.deps.projectStore.getProjectById(input.tenantId, input.projectId);
12012
- if (!project) {
12013
- throw new ProjectCollaborationError("PROJECT_NOT_FOUND", 404, "Project not found");
12014
- }
12015
- if (project.kind === "public") {
12016
- return this.requirePublicProjectAccess(project, input);
12017
- }
12018
- const membership = await this.deps.membershipStore.findByUser(
12019
- input.tenantId,
12020
- input.projectId,
12021
- input.userId
12022
- );
12023
- if (project.kind === "personal") {
12024
- if (!this.isActiveMembership(membership, input)) this.accessDenied();
12025
- this.requireCapability(membership, input.capability);
12026
- return { project, membership };
12027
- }
12028
- if (this.isActiveMembership(membership, input) && this.hasCapability(membership, input.capability)) {
12029
- return { project, membership };
12030
- }
12031
- const tenantAdmin = await this.tenantAdminMembership(project, input);
12032
- if (this.isActiveMembership(membership, input)) {
12033
- if (tenantAdmin) return { project, membership: tenantAdmin };
12034
- this.requireCapability(membership, input.capability);
12035
- }
12036
- const memberships = await this.deps.membershipStore.list(input.tenantId, input.projectId);
12037
- if (memberships.length !== 0) {
12038
- if (tenantAdmin) return { project, membership: tenantAdmin };
12039
- this.accessDenied();
12040
- }
12041
- if (!tenantAdmin) this.accessDenied();
12042
- let claim;
12043
- try {
12044
- claim = await this.deps.membershipStore.createInitialOwner({
12045
- id: this.idFactory(),
12046
- tenantId: input.tenantId,
12047
- projectId: input.projectId,
12048
- userId: input.userId
12049
- });
12050
- } catch (error) {
12051
- if (isProjectMembershipConflict(error)) {
12052
- throw new ProjectCollaborationError(
12053
- "PROJECT_MEMBERSHIP_CONFLICT",
12054
- 409,
12055
- "Project membership could not be initialized"
12056
- );
12057
- }
12058
- throw error;
12059
- }
12060
- if (claim.kind === "created" || claim.kind === "existing") {
12061
- return { project, membership: claim.membership };
12062
- }
12063
- const racedMembership = await this.deps.membershipStore.findByUser(
12064
- input.tenantId,
12065
- input.projectId,
12066
- input.userId
12067
- );
12068
- if (racedMembership?.status !== "active") this.accessDenied();
12069
- this.requireCapability(racedMembership, input.capability);
12070
- return { project, membership: racedMembership };
12071
- }
12072
- /** Authorizes an already-existing membership, or any tenant member for public rooms; never mutates persistence. */
12073
- async requireExistingProjectAccess(input) {
12074
- const project = await this.deps.projectStore.getProjectById(input.tenantId, input.projectId);
12075
- if (!project) throw new ProjectCollaborationError("PROJECT_NOT_FOUND", 404, "Project not found");
12076
- if (project.kind === "public") {
12077
- return this.requireExistingPublicProjectAccess(project, input);
12078
- }
12079
- const membership = await this.deps.membershipStore.findByUser(
12080
- input.tenantId,
12081
- input.projectId,
12082
- input.userId
12083
- );
12084
- const activeMembership = this.isActiveMembership(membership, input) ? membership : void 0;
12085
- if (project.kind === "personal") {
12086
- if (!activeMembership) this.accessDenied();
12087
- this.requireCapability(activeMembership, input.capability);
12088
- return { project, membership: activeMembership };
12089
- }
12090
- if (activeMembership && this.hasCapability(activeMembership, input.capability)) {
12091
- return { project, membership: activeMembership };
12092
- }
12093
- const tenantAdmin = await this.tenantAdminMembership(project, input);
12094
- if (tenantAdmin) return { project, membership: tenantAdmin };
12095
- if (activeMembership) this.requireCapability(activeMembership, input.capability);
12096
- this.accessDenied();
12097
- }
12098
- /**
12099
- * Authorizes roster visibility for any active participant (owner/admin/member/viewer).
12100
- * Mutating the roster requires `manage` separately; reading it never does, because every
12101
- * room participant needs the member list to render the room and derive their own capabilities.
12102
- */
12103
- async requireRosterAccess(input) {
12104
- const project = await this.deps.projectStore.getProjectById(input.tenantId, input.projectId);
12105
- if (!project) throw new ProjectCollaborationError("PROJECT_NOT_FOUND", 404, "Project not found");
12106
- return this.requireProjectAccess({
12107
- ...input,
12108
- capability: "read"
12109
- });
12110
- }
12111
- async requirePublicProjectAccess(project, input) {
12112
- const membership = await this.deps.membershipStore.findByUser(
12113
- input.tenantId,
12114
- input.projectId,
12115
- input.userId
12116
- );
12117
- if (membership?.status === "active") {
12118
- if (this.hasCapability(membership, input.capability)) return { project, membership };
12119
- const tenantAdmin = await this.tenantAdminMembership(project, input);
12120
- if (tenantAdmin) return { project, membership: tenantAdmin };
12121
- this.requireCapability(membership, input.capability);
12122
- return { project, membership };
12123
- }
12124
- const materialized = await this.materializePublicMembership(input);
12125
- this.requireCapability(materialized, input.capability);
12126
- return { project, membership: materialized };
12127
- }
12128
- async requireExistingPublicProjectAccess(project, input) {
12129
- const membership = await this.deps.membershipStore.findByUser(
12130
- input.tenantId,
12131
- input.projectId,
12132
- input.userId
12133
- );
12134
- if (membership?.status === "active") {
12135
- if (this.hasCapability(membership, input.capability)) return { project, membership };
12136
- const tenantAdmin = await this.tenantAdminMembership(project, input);
12137
- if (tenantAdmin) return { project, membership: tenantAdmin };
12138
- this.requireCapability(membership, input.capability);
12139
- return { project, membership };
12140
- }
12141
- if (membership) this.accessDenied();
12142
- const tenantLink = await this.deps.userTenantLinkStore.getLink(input.userId, input.tenantId);
12143
- if (!tenantLink) this.accessDenied();
12144
- const role = tenantLink.role === "owner" || tenantLink.role === "admin" ? "admin" : "member";
12145
- const synthetic = {
12146
- id: `public:${input.userId}`,
12147
- tenantId: input.tenantId,
12148
- projectId: input.projectId,
12149
- userId: input.userId,
12150
- role,
12151
- status: "active",
12152
- joinedAt: project.createdAt,
12153
- updatedAt: project.updatedAt
12154
- };
12155
- this.requireCapability(synthetic, input.capability);
12156
- return { project, membership: synthetic };
12157
- }
12158
- async materializePublicMembership(input) {
12159
- const tenantLink = await this.deps.userTenantLinkStore.getLink(input.userId, input.tenantId);
12160
- if (!tenantLink) this.accessDenied();
12161
- const existing = await this.deps.membershipStore.findByUser(
12162
- input.tenantId,
12163
- input.projectId,
12164
- input.userId
12165
- );
12166
- if (existing) this.accessDenied();
12167
- const role = tenantLink.role === "owner" || tenantLink.role === "admin" ? "admin" : "member";
12168
- try {
12169
- return await this.deps.membershipStore.create({
12170
- id: this.idFactory(),
12171
- tenantId: input.tenantId,
12172
- projectId: input.projectId,
12173
- userId: input.userId,
12174
- role,
12175
- status: "active"
12176
- });
12177
- } catch (error) {
12178
- if (isProjectMembershipConflict(error)) {
12179
- const raced = await this.deps.membershipStore.findByUser(
12180
- input.tenantId,
12181
- input.projectId,
12182
- input.userId
12183
- );
12184
- if (raced?.status === "active") return raced;
12185
- }
12186
- throw error;
12187
- }
12188
- }
12189
- hasCapability(membership, capability2) {
12190
- return allowedRoles[capability2].has(membership.role);
12191
- }
12192
- requireCapability(membership, capability2) {
12193
- if (!this.hasCapability(membership, capability2)) this.accessDenied();
12194
- }
12195
- async tenantAdminMembership(project, input) {
12196
- if (project.kind === "personal") return void 0;
12197
- const tenantLink = await this.deps.userTenantLinkStore.getLink(input.userId, input.tenantId);
12198
- if (tenantLink?.role !== "owner" && tenantLink?.role !== "admin") return void 0;
12199
- return {
12200
- id: `tenant-admin:${input.userId}`,
12201
- tenantId: input.tenantId,
12202
- projectId: project.id,
12203
- userId: input.userId,
12204
- role: "admin",
12205
- status: "active",
12206
- joinedAt: project.createdAt,
12207
- updatedAt: project.updatedAt
12208
- };
12209
- }
12210
- isActiveMembership(membership, input) {
12211
- return membership != null && membership.tenantId === input.tenantId && membership.projectId === input.projectId && membership.userId === input.userId && membership.status === "active";
12212
- }
12213
- accessDenied() {
12214
- throw new ProjectCollaborationError("PROJECT_ACCESS_DENIED", 403, "Project access denied");
12215
- }
12216
- };
12217
-
12218
12056
  // src/controllers/database-configs.ts
12219
12057
  import {
12220
12058
  getStoreLattice as getStoreLattice17,
12221
12059
  sqlDatabaseManager
12222
12060
  } from "@axiom-lattice/core";
12223
- import { randomUUID as randomUUID15 } from "crypto";
12061
+ import { randomUUID as randomUUID14 } from "crypto";
12224
12062
  function getTenantId16(request) {
12225
12063
  const userTenantId = request.user?.tenantId;
12226
12064
  if (userTenantId) {
@@ -12298,7 +12136,7 @@ async function createDatabaseConfig(request, reply) {
12298
12136
  message: "Database configuration with this key already exists"
12299
12137
  };
12300
12138
  }
12301
- const id3 = body.id || randomUUID15();
12139
+ const id3 = body.id || randomUUID14();
12302
12140
  const config = await store2.createConfig(tenantId, id3, body);
12303
12141
  try {
12304
12142
  sqlDatabaseManager.registerDatabase(tenantId, config.key, config.config);
@@ -12503,7 +12341,7 @@ import {
12503
12341
  metricsServerManager as metricsServerManager2,
12504
12342
  SemanticMetricsClient as SemanticMetricsClient2
12505
12343
  } from "@axiom-lattice/core";
12506
- import { randomUUID as randomUUID16 } from "crypto";
12344
+ import { randomUUID as randomUUID15 } from "crypto";
12507
12345
  function getTenantId17(request) {
12508
12346
  const userTenantId = request.user?.tenantId;
12509
12347
  if (userTenantId) {
@@ -12584,7 +12422,7 @@ async function createMetricsServerConfig(request, reply) {
12584
12422
  message: "selectedDataSources is required for semantic metrics servers"
12585
12423
  };
12586
12424
  }
12587
- const id3 = body.id || randomUUID16();
12425
+ const id3 = body.id || randomUUID15();
12588
12426
  const configData = {
12589
12427
  key: body.key,
12590
12428
  name: body.name,
@@ -13101,11 +12939,11 @@ var createBody = z2.object({
13101
12939
  key: z2.string().min(1),
13102
12940
  name: z2.string().min(1),
13103
12941
  description: z2.string().optional(),
13104
- config: z2.record(z2.unknown())
12942
+ config: z2.record(z2.string(), z2.unknown())
13105
12943
  });
13106
12944
  var testOrDiscoverBody = z2.object({
13107
12945
  key: z2.string().optional(),
13108
- config: z2.record(z2.unknown()).optional()
12946
+ config: z2.record(z2.string(), z2.unknown()).optional()
13109
12947
  });
13110
12948
  function getTenant(request) {
13111
12949
  const userTenantId = request.user?.tenantId;
@@ -13202,7 +13040,7 @@ function connectionRoutes(fastify2) {
13202
13040
  return reply.status(400).send(err);
13203
13041
  }
13204
13042
  if (err instanceof z2.ZodError) {
13205
- return reply.status(400).send({ error: err.errors });
13043
+ return reply.status(400).send({ error: err.issues });
13206
13044
  }
13207
13045
  return reply.status(500).send({
13208
13046
  ok: false,
@@ -13230,7 +13068,7 @@ function connectionRoutes(fastify2) {
13230
13068
  return reply.status(400).send(err);
13231
13069
  }
13232
13070
  if (err instanceof z2.ZodError) {
13233
- return reply.status(400).send({ error: err.errors });
13071
+ return reply.status(400).send({ error: err.issues });
13234
13072
  }
13235
13073
  return reply.status(500).send({
13236
13074
  error: err instanceof Error ? err.message : String(err)
@@ -13247,7 +13085,7 @@ import {
13247
13085
  McpLatticeManager,
13248
13086
  convertToConnection
13249
13087
  } from "@axiom-lattice/core";
13250
- import { randomUUID as randomUUID17 } from "crypto";
13088
+ import { randomUUID as randomUUID16 } from "crypto";
13251
13089
 
13252
13090
  // src/services/mcpConfigSync.ts
13253
13091
  var MCP_CONFIG_CHANGED_TOPIC = "mcp-config-changed";
@@ -13366,7 +13204,7 @@ async function createMcpServerConfig(request, reply) {
13366
13204
  message: "MCP server configuration with this key already exists"
13367
13205
  };
13368
13206
  }
13369
- const id3 = body.id || randomUUID17();
13207
+ const id3 = body.id || randomUUID16();
13370
13208
  const config = await store2.createConfig(tenantId, id3, body);
13371
13209
  try {
13372
13210
  await connectAndRegisterTools(config);
@@ -13528,13 +13366,17 @@ async function testMcpServerConnection(request, reply) {
13528
13366
  try {
13529
13367
  const testKey = `__test_${key}_${Date.now()}`;
13530
13368
  const connection = convertToConnection(config.config);
13531
- const { latency } = await McpLatticeManager.testConnection(testKey, connection);
13369
+ const { latency, protocolVersion } = await McpLatticeManager.testConnection(
13370
+ testKey,
13371
+ connection
13372
+ );
13532
13373
  return {
13533
13374
  success: true,
13534
13375
  message: "Connection test successful",
13535
13376
  data: {
13536
13377
  connected: true,
13537
- latency
13378
+ latency,
13379
+ ...protocolVersion ? { protocolVersion } : {}
13538
13380
  }
13539
13381
  };
13540
13382
  } catch (error) {
@@ -15677,7 +15519,7 @@ function registerChannelRoutes(app2, dependencies) {
15677
15519
  }
15678
15520
 
15679
15521
  // src/controllers/channel-installations.ts
15680
- import { randomUUID as randomUUID18 } from "crypto";
15522
+ import { randomUUID as randomUUID17 } from "crypto";
15681
15523
  import {
15682
15524
  descriptorDataValue
15683
15525
  } from "@axiom-lattice/protocols";
@@ -15898,7 +15740,7 @@ async function createChannelInstallation(request, reply) {
15898
15740
  };
15899
15741
  }
15900
15742
  const store2 = await getInstallationStore();
15901
- const installationId = randomUUID18();
15743
+ const installationId = randomUUID17();
15902
15744
  const createInput = {
15903
15745
  channel: body.channel,
15904
15746
  name: body.name,
@@ -16890,7 +16732,7 @@ async function getLocalA2ATemplates(_request, reply) {
16890
16732
  }
16891
16733
 
16892
16734
  // src/routes/a2a-test-connection.ts
16893
- import { randomUUID as randomUUID19 } from "crypto";
16735
+ import { randomUUID as randomUUID18 } from "crypto";
16894
16736
  function describeTestConnectionError(error, agentCardUrl) {
16895
16737
  if (!(error instanceof Error)) {
16896
16738
  return `Failed to fetch agent card from ${agentCardUrl}: ${String(error)}`;
@@ -16930,7 +16772,7 @@ async function ensureLocalRuntimeForConnectionTest(localRuntime, agentCardUrl) {
16930
16772
  return { error: portValidation.error };
16931
16773
  }
16932
16774
  const state = await localA2AService.startProvider(
16933
- `test-${randomUUID19()}`,
16775
+ `test-${randomUUID18()}`,
16934
16776
  testRuntime
16935
16777
  );
16936
16778
  if (state.status === "running") return { runtimeId: state.runtimeId };
@@ -17363,13 +17205,13 @@ function snapshotEnsureInput(input) {
17363
17205
  import { createHash as createHash3 } from "crypto";
17364
17206
 
17365
17207
  // src/services/collaboration/ProjectTaskRunService.ts
17366
- import { randomUUID as randomUUID21 } from "crypto";
17208
+ import { randomUUID as randomUUID20 } from "crypto";
17367
17209
  import {
17368
17210
  createTaskRunBridge
17369
17211
  } from "@axiom-lattice/core";
17370
17212
 
17371
17213
  // src/services/collaboration/ProjectTaskRunPlanner.ts
17372
- import { randomUUID as randomUUID20 } from "crypto";
17214
+ import { randomUUID as randomUUID19 } from "crypto";
17373
17215
 
17374
17216
  // src/services/collaboration/ProjectTaskRunProtocol.ts
17375
17217
  import {
@@ -17685,7 +17527,7 @@ var ProjectTaskRunPlanner = class {
17685
17527
  } catch (error) {
17686
17528
  throw asPlanError(error);
17687
17529
  }
17688
- const inputId = (this.deps.idFactory ?? randomUUID20)();
17530
+ const inputId = (this.deps.idFactory ?? randomUUID19)();
17689
17531
  const actor3 = input.actor ?? SYSTEM_ACTOR;
17690
17532
  const userId = actor3.startsWith("user:") && actor3.length > "user:".length ? actor3.slice("user:".length) : void 0;
17691
17533
  const trustedContext = {
@@ -17828,7 +17670,7 @@ var ProjectTaskRunService = class {
17828
17670
  ...deps.idFactory === void 0 ? {} : { idFactory: deps.idFactory }
17829
17671
  });
17830
17672
  this.runBridge = createTaskRunBridge({ lifecycle: deps.lifecycle });
17831
- this.idFactory = deps.idFactory ?? randomUUID21;
17673
+ this.idFactory = deps.idFactory ?? randomUUID20;
17832
17674
  this.log = deps.log ?? { warn: () => void 0 };
17833
17675
  }
17834
17676
  /**
@@ -19185,7 +19027,7 @@ var AgentWebAppService = class {
19185
19027
  }
19186
19028
  async create(context, input) {
19187
19029
  await this.validateAssistant(context, input.assistantId);
19188
- const normalized = await this.validateConfig(context.tenantId, input);
19030
+ const normalized = await this.validateConfig(context, input);
19189
19031
  return this.deps.webAppStore.create(context.tenantId, normalized);
19190
19032
  }
19191
19033
  async list(context, assistantId) {
@@ -19212,7 +19054,7 @@ var AgentWebAppService = class {
19212
19054
  identity: patch.identity ?? current3.identity
19213
19055
  };
19214
19056
  await this.validateAssistant(context, current3.assistantId);
19215
- const validated = await this.validateConfig(context.tenantId, effective);
19057
+ const validated = await this.validateConfig(context, effective, current3);
19216
19058
  const update = {
19217
19059
  ...patch.name !== void 0 ? { name: validated.name } : {},
19218
19060
  ...Object.prototype.hasOwnProperty.call(patch, "description") ? { description: validated.description } : {},
@@ -19225,7 +19067,7 @@ var AgentWebAppService = class {
19225
19067
  }
19226
19068
  async enable(context, webAppId) {
19227
19069
  const current3 = await this.requireAuthorizedWebApp(context, webAppId);
19228
- await this.validateConfig(context.tenantId, current3);
19070
+ await this.validateConfig(context, current3, current3);
19229
19071
  return this.writeSnapshot(context, current3, { status: "active" });
19230
19072
  }
19231
19073
  async disable(context, webAppId) {
@@ -19247,7 +19089,7 @@ var AgentWebAppService = class {
19247
19089
  if (await this.deps.configuredAgentResolver.exists(context.tenantId, assistantId)) return;
19248
19090
  throw new AgentWebAppError("ASSISTANT_NOT_FOUND", 404, "Assistant not found");
19249
19091
  }
19250
- async validateConfig(tenantId, input) {
19092
+ async validateConfig(context, input, existing) {
19251
19093
  const allowedProjectIds = [...new Set(input.scope.allowedProjectIds)];
19252
19094
  if (!allowedProjectIds.length || !allowedProjectIds.includes(input.scope.defaultProjectId)) {
19253
19095
  throw new AgentWebAppError("PROJECT_SCOPE_INVALID", 400, "Default project must be in the project allowlist");
@@ -19255,13 +19097,28 @@ var AgentWebAppService = class {
19255
19097
  if (!input.features.projectSelector && allowedProjectIds.length !== 1) {
19256
19098
  throw new AgentWebAppError("PROJECT_SCOPE_INVALID", 400, "Disabled project selection requires exactly one project");
19257
19099
  }
19100
+ const existingIds = new Set(existing?.scope.allowedProjectIds ?? []);
19258
19101
  for (const projectId of allowedProjectIds) {
19259
- if (!await this.deps.projectStore.getProjectById(tenantId, projectId)) {
19102
+ if (!await this.deps.projectStore.getProjectById(context.tenantId, projectId)) {
19260
19103
  throw new AgentWebAppError("PROJECT_NOT_FOUND", 404, "Project not found");
19261
19104
  }
19105
+ if (existingIds.has(projectId)) continue;
19106
+ try {
19107
+ await this.deps.projectAccess.requireExistingProjectAccess({
19108
+ tenantId: context.tenantId,
19109
+ userId: context.userId,
19110
+ projectId,
19111
+ capability: "read"
19112
+ });
19113
+ } catch (error) {
19114
+ if (error instanceof ProjectCollaborationError) {
19115
+ throw new AgentWebAppError("PROJECT_NOT_FOUND", 404, "Project not found");
19116
+ }
19117
+ throw error;
19118
+ }
19262
19119
  }
19263
19120
  const scope = await this.validateModels(
19264
- tenantId,
19121
+ context.tenantId,
19265
19122
  input.scope,
19266
19123
  input.features.modelSelector
19267
19124
  );
@@ -19470,7 +19327,7 @@ import { createHmac as createHmac3 } from "crypto";
19470
19327
  import { z as z5, ZodError as ZodError2 } from "zod";
19471
19328
 
19472
19329
  // src/services/agent-web-app/AgentWebAppRuntimeService.ts
19473
- import { createHash as createHash4, randomUUID as randomUUID22 } from "crypto";
19330
+ import { createHash as createHash4, randomUUID as randomUUID21 } from "crypto";
19474
19331
  import { MessageChunkTypes as MessageChunkTypes3, parseAgentWebAppGenUIBlock, buildAffinityMissChunk as buildAffinityMissChunk2 } from "@axiom-lattice/protocols";
19475
19332
  import { getReplicaId as getReplicaId7, getThreadRunOwner as getThreadRunOwner2, normalizeAgentInterrupts as normalizeAgentInterrupts2 } from "@axiom-lattice/core";
19476
19333
  function isRecord9(value) {
@@ -19768,7 +19625,7 @@ ${formatFileRefsSection(refs)}` : input.content;
19768
19625
  const userDigest = createHash4("sha256").update(userId, "utf8").digest("hex");
19769
19626
  const contentDigest = createHash4("sha256").update(file.bytes).digest("hex");
19770
19627
  const displayName = file.name;
19771
- const physicalName = `${randomUUID22()}-${sanitizePhysicalFilename(file.name)}`;
19628
+ const physicalName = `${randomUUID21()}-${sanitizePhysicalFilename(file.name)}`;
19772
19629
  const saved = await this.deps.saveProjectFile({
19773
19630
  tenantId: runtime.webApp.tenantId,
19774
19631
  workspaceId: runtime.project.workspaceId,
@@ -19929,7 +19786,7 @@ ${formatFileRefsSection(refs)}` : input.content;
19929
19786
  const thread = await this.deps.threadStore.createThread(
19930
19787
  runtime.webApp.tenantId,
19931
19788
  runtime.webApp.assistantId,
19932
- randomUUID22(),
19789
+ randomUUID21(),
19933
19790
  { metadata: this.metadata(runtime, userId, normalizeLabel(rawLabel)) }
19934
19791
  );
19935
19792
  return toRuntimeThread(thread);
@@ -21206,7 +21063,7 @@ var createSchema = z8.object({ name: z8.string(), description: z8.string().optio
21206
21063
  var updateSchema = createSchema.partial().extend({ expectedUpdatedAt: z8.string().optional() });
21207
21064
  var bundleIdSchema = z8.string().uuid();
21208
21065
  var bundleParamsSchema = z8.object({ bundleId: bundleIdSchema });
21209
- var projectSchema = z8.object({ bundleIds: z8.array(bundleIdSchema), expectedRevisions: z8.record(z8.string()).optional() }).strict();
21066
+ var projectSchema = z8.object({ bundleIds: z8.array(bundleIdSchema), expectedRevisions: z8.record(z8.string(), z8.string()).optional() }).strict();
21210
21067
  function tenant(request, authRequired2) {
21211
21068
  const authenticated = request.user?.tenantId;
21212
21069
  const header2 = request.headers["x-tenant-id"];
@@ -21339,7 +21196,7 @@ function registerCapabilityBundleRoutes(app2, controller) {
21339
21196
  import { ZodError as ZodError3 } from "zod";
21340
21197
 
21341
21198
  // src/services/model-provider/ModelProviderService.ts
21342
- import { randomUUID as randomUUID23 } from "crypto";
21199
+ import { randomUUID as randomUUID22 } from "crypto";
21343
21200
  import { toModelKey } from "@axiom-lattice/protocols";
21344
21201
  import {
21345
21202
  assertSafeUpstreamUrl,
@@ -21678,7 +21535,7 @@ var unsafeReasonToErrorCode = {
21678
21535
  var ModelProviderService = class {
21679
21536
  constructor(deps) {
21680
21537
  this.deps = deps;
21681
- this.idFactory = deps.idFactory ?? (() => randomUUID23());
21538
+ this.idFactory = deps.idFactory ?? (() => randomUUID22());
21682
21539
  }
21683
21540
  /**
21684
21541
  * List the tenant's provider configurations.
@@ -22869,12 +22726,12 @@ async function handleModelProviderChanged(payload, reconcile) {
22869
22726
  }
22870
22727
 
22871
22728
  // src/services/collaboration/ProjectRoomService.ts
22872
- import { randomUUID as randomUUID24 } from "crypto";
22729
+ import { randomUUID as randomUUID23 } from "crypto";
22873
22730
  var ProjectRoomService = class {
22874
22731
  /** Creates a project room service from explicitly injected collaborators. */
22875
22732
  constructor(deps) {
22876
22733
  this.deps = deps;
22877
- this.idFactory = deps.idFactory ?? randomUUID24;
22734
+ this.idFactory = deps.idFactory ?? randomUUID23;
22878
22735
  }
22879
22736
  /**
22880
22737
  * Authorizes read access and ensures the project's main room.
@@ -22934,7 +22791,7 @@ var ProjectRoomService = class {
22934
22791
  };
22935
22792
 
22936
22793
  // src/services/collaboration/ProjectMembershipService.ts
22937
- import { randomUUID as randomUUID25 } from "crypto";
22794
+ import { randomUUID as randomUUID24 } from "crypto";
22938
22795
  var ProjectMembershipServiceError = class extends Error {
22939
22796
  constructor(code, statusCode, message) {
22940
22797
  super(message);
@@ -22943,14 +22800,14 @@ var ProjectMembershipServiceError = class extends Error {
22943
22800
  this.name = "ProjectMembershipServiceError";
22944
22801
  }
22945
22802
  };
22946
- var membershipConflictNames2 = /* @__PURE__ */ new Set(["DuplicateProjectMembershipError", "ProjectMembershipIdConflictError"]);
22803
+ var membershipConflictNames = /* @__PURE__ */ new Set(["DuplicateProjectMembershipError", "ProjectMembershipIdConflictError"]);
22947
22804
  function isMembershipConflict(error) {
22948
- return error instanceof Error && membershipConflictNames2.has(error.name);
22805
+ return error instanceof Error && membershipConflictNames.has(error.name);
22949
22806
  }
22950
22807
  var ProjectMembershipService = class {
22951
22808
  constructor(deps) {
22952
22809
  this.deps = deps;
22953
- this.idFactory = deps.idFactory ?? randomUUID25;
22810
+ this.idFactory = deps.idFactory ?? randomUUID24;
22954
22811
  this.mutationMutex = deps.projectMutationMutex ?? projectMutationMutex;
22955
22812
  }
22956
22813
  async list(actor3) {
@@ -23080,7 +22937,7 @@ var ProjectMembershipService = class {
23080
22937
  };
23081
22938
 
23082
22939
  // src/services/collaboration/ProjectRosterService.ts
23083
- import { randomUUID as randomUUID26 } from "crypto";
22940
+ import { randomUUID as randomUUID25 } from "crypto";
23084
22941
  var ProjectRosterServiceError = class extends Error {
23085
22942
  /** Creates a stable roster service error. */
23086
22943
  constructor(code, statusCode, message) {
@@ -23099,7 +22956,7 @@ var ProjectRosterService = class {
23099
22956
  /** Creates a roster service from explicitly injected collaborators. */
23100
22957
  constructor(deps) {
23101
22958
  this.deps = deps;
23102
- this.idFactory = deps.idFactory ?? randomUUID26;
22959
+ this.idFactory = deps.idFactory ?? randomUUID25;
23103
22960
  this.mutationMutex = deps.projectMutationMutex ?? projectMutationMutex;
23104
22961
  }
23105
22962
  /**
@@ -23206,7 +23063,7 @@ var ProjectRosterService = class {
23206
23063
  const agent = (await this.deps.agents.list(actor3.tenantId, actor3.userId)).find((item) => item.assistantId === assistantId);
23207
23064
  if (!agent || agent.ownerUserId !== void 0) throw new ProjectRosterServiceError("ASSISTANT_NOT_FOUND", 404, "Agent not found");
23208
23065
  const room = await this.deps.roomStore.ensureMainRoom({
23209
- id: randomUUID26(),
23066
+ id: randomUUID25(),
23210
23067
  tenantId: actor3.tenantId,
23211
23068
  workspaceId: project.workspaceId,
23212
23069
  projectId: actor3.projectId,
@@ -23550,7 +23407,7 @@ function virtualPublicProjectBot(project, room, agent, mentionName, now) {
23550
23407
  }
23551
23408
 
23552
23409
  // src/services/collaboration/RoomMessageService.ts
23553
- import { createHash as createHash6, randomUUID as randomUUID27 } from "crypto";
23410
+ import { createHash as createHash6, randomUUID as randomUUID26 } from "crypto";
23554
23411
 
23555
23412
  // src/services/collaboration/ProjectBotMembershipSnapshot.ts
23556
23413
  import { snapshotExactRecord as snapshotExactRecord5 } from "@axiom-lattice/protocols";
@@ -23639,7 +23496,7 @@ var RoomMessageService = class {
23639
23496
  constructor(deps, options = {}) {
23640
23497
  this.deps = deps;
23641
23498
  this.idempotentOutcomes = /* @__PURE__ */ new Map();
23642
- this.idFactory = deps.idFactory ?? randomUUID27;
23499
+ this.idFactory = deps.idFactory ?? randomUUID26;
23643
23500
  const limit = options.idempotentOutcomeLimit ?? 1e3;
23644
23501
  if (!Number.isSafeInteger(limit) || limit < 1) throw new RangeError("idempotentOutcomeLimit must be a positive safe integer");
23645
23502
  this.idempotentOutcomeLimit = limit;
@@ -23925,7 +23782,7 @@ import { ZodError as ZodError4 } from "zod";
23925
23782
  import { toProjectRoomPublicMessage } from "@axiom-lattice/protocols";
23926
23783
 
23927
23784
  // src/services/collaboration/RoomInterruptService.ts
23928
- import { randomUUID as randomUUID28 } from "crypto";
23785
+ import { randomUUID as randomUUID27 } from "crypto";
23929
23786
  var RESUMABLE_TASK_INTERRUPT_CODES = /* @__PURE__ */ new Set([
23930
23787
  "PROJECT_TASK_NOT_RESUMABLE",
23931
23788
  "PROJECT_TASK_NOT_READY",
@@ -23963,7 +23820,7 @@ var RoomInterruptService = class {
23963
23820
  /** Creates the service from explicitly injected stores and dispatcher. */
23964
23821
  constructor(deps) {
23965
23822
  this.deps = deps;
23966
- this.idFactory = deps.idFactory ?? randomUUID28;
23823
+ this.idFactory = deps.idFactory ?? randomUUID27;
23967
23824
  }
23968
23825
  /** Resolves a pending clarify interrupt with no answers. */
23969
23826
  async skip(input) {
@@ -24326,7 +24183,7 @@ async function execute(reply, operation) {
24326
24183
  }
24327
24184
 
24328
24185
  // src/routes/cospace.ts
24329
- import { randomUUID as randomUUID29 } from "crypto";
24186
+ import { randomUUID as randomUUID28 } from "crypto";
24330
24187
  import { ZodError as ZodError6 } from "zod";
24331
24188
  import {
24332
24189
  generateDirectHumanProjectId,
@@ -24360,7 +24217,7 @@ async function computeUnread(deps, tenantId, userId, roomId, lastMessage) {
24360
24217
  });
24361
24218
  }
24362
24219
  function registerCoSpaceRoutes(app2, deps) {
24363
- const idFactory = deps.idFactory ?? (() => randomUUID29());
24220
+ const idFactory = deps.idFactory ?? (() => randomUUID28());
24364
24221
  app2.get(
24365
24222
  "/api/workspaces/:workspaceId/rooms",
24366
24223
  async (request, reply) => {
@@ -25327,7 +25184,7 @@ function exactValues(value, required, optional = []) {
25327
25184
  }
25328
25185
 
25329
25186
  // src/services/collaboration/CoordinatorWakeNotifier.ts
25330
- import { randomUUID as randomUUID30 } from "crypto";
25187
+ import { randomUUID as randomUUID29 } from "crypto";
25331
25188
  import {
25332
25189
  snapshotExactRecord as snapshotExactRecord7
25333
25190
  } from "@axiom-lattice/protocols";
@@ -25343,7 +25200,7 @@ var CoordinatorWakeNotifier = class {
25343
25200
  this.accepted = /* @__PURE__ */ new Set();
25344
25201
  this.maxPending = deps.maxPending ?? 1024;
25345
25202
  if (!Number.isSafeInteger(this.maxPending) || this.maxPending < 1) throw new RangeError("maxPending must be a positive safe integer");
25346
- this.idFactory = deps.idFactory ?? randomUUID30;
25203
+ this.idFactory = deps.idFactory ?? randomUUID29;
25347
25204
  }
25348
25205
  /** Admits one notification without awaiting any store or dispatch operation. */
25349
25206
  handle(value, anchorMessageId) {
@@ -27274,7 +27131,7 @@ function isRecord10(value) {
27274
27131
  import { taskLifecycleNotifier } from "@axiom-lattice/core";
27275
27132
 
27276
27133
  // src/services/collaboration/ProjectRoomEventBroker.ts
27277
- import { randomUUID as randomUUID31 } from "crypto";
27134
+ import { randomUUID as randomUUID30 } from "crypto";
27278
27135
  import {
27279
27136
  parseProjectRoomEventId,
27280
27137
  ProjectRoomBrokerCapacityError,
@@ -27305,7 +27162,7 @@ var ProjectRoomEventBroker = class {
27305
27162
  this.subscriberCount = 0;
27306
27163
  this.usageClock = 0;
27307
27164
  this.closed = false;
27308
- this.epoch = options.epoch ?? randomUUID31();
27165
+ this.epoch = options.epoch ?? randomUUID30();
27309
27166
  if (!UUID_PATTERN.test(this.epoch)) {
27310
27167
  throw new TypeError("Project Room event epoch must be a lowercase canonical UUID");
27311
27168
  }
@@ -28959,6 +28816,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
28959
28816
  const taskWorkItemStore = getStoreLattice28("default", "taskWorkItem").store;
28960
28817
  const projectTaskEnabled = options.projectTaskEnabled ?? process.env.AXIOM_PROJECT_TASK_EXECUTION_ENABLED !== "false";
28961
28818
  const accessService = new ProjectAccessService({ projectStore, membershipStore: projectMembershipStore, userTenantLinkStore });
28819
+ setA2AProjectAccess(accessService);
28962
28820
  const realtimeMode = resolveProjectRoomRealtimeMode();
28963
28821
  const realtimeLog = options.projectTaskLog ?? { warn: () => void 0 };
28964
28822
  const roomMessageRetention = createRoomMessageRetentionJob({
@@ -29139,7 +28997,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
29139
28997
  });
29140
28998
  }
29141
28999
  if (projectTaskComposition) app2.addHook("onClose", async () => projectTaskComposition.lease.release());
29142
- const taskThreadService = projectTaskComposition?.lease.runtime.threads ?? new ProjectTaskThreadService({ threads: threadStore, idFactory: randomUUID32 });
29000
+ const taskThreadService = projectTaskComposition?.lease.runtime.threads ?? new ProjectTaskThreadService({ threads: threadStore, idFactory: randomUUID31 });
29143
29001
  const taskLifecycle = projectTaskComposition?.lease.runtime.lifecycle ?? createTaskLifecycleService({ taskStore, workItemStore: taskWorkItemStore });
29144
29002
  const reassignmentAuthorizer = createProjectTaskReassignmentAuthorizer(
29145
29003
  new ProjectTaskOwnerPolicy(projectBotMembershipStore),
@@ -29320,7 +29178,8 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
29320
29178
  configuredAgentResolver: createConfiguredAgentResolver({
29321
29179
  hydrate: (tenantId) => agentLatticeManager5.initializeStoredAssistantsForTenant(tenantId),
29322
29180
  has: (tenantId, assistantId) => agentLatticeManager5.hasAgentLatticeWithTenant(tenantId, assistantId)
29323
- })
29181
+ }),
29182
+ projectAccess: accessService
29324
29183
  })
29325
29184
  });
29326
29185
  registerAgentWebAppRuntimeRoutes(app2, {
@@ -29330,7 +29189,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
29330
29189
  userTenantLinkStore,
29331
29190
  ensureCoordinator: (scope) => coordinatorEnsurer.ensure(scope),
29332
29191
  log: realtimeLog
29333
- })),
29192
+ }), accessService),
29334
29193
  taskController: createTaskController({
29335
29194
  access: {
29336
29195
  requireProjectAccess: async (input) => {
@@ -29626,7 +29485,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
29626
29485
  userTenantLinkStore,
29627
29486
  ensureCoordinator: (scope) => coordinatorEnsurer.ensure(scope),
29628
29487
  log: realtimeLog
29629
- }));
29488
+ }), accessService);
29630
29489
  registerDatabaseConfigRoutes(app2);
29631
29490
  registerMetricsServerConfigRoutes(app2);
29632
29491
  connectionRoutes(app2);
@@ -29824,7 +29683,7 @@ function tryCreateProjectTaskRuntime(input) {
29824
29683
  function createRuntime(input, stores, log2) {
29825
29684
  const controller = new AbortController();
29826
29685
  const mutex = new ProjectTaskExecutionMutex();
29827
- const threads = new ProjectTaskThreadService({ threads: input.threadStore, idFactory: randomUUID32 });
29686
+ const threads = new ProjectTaskThreadService({ threads: input.threadStore, idFactory: randomUUID31 });
29828
29687
  const lifecycle = createTaskLifecycleService({ taskStore: input.taskStore, workItemStore: input.taskWorkItemStore });
29829
29688
  const projection = new RoomProjectionService({
29830
29689
  messages: input.projectRoomMessageStore,
@@ -29833,7 +29692,7 @@ function createRuntime(input, stores, log2) {
29833
29692
  warnings: input.taskWorkItemStore,
29834
29693
  log: log2,
29835
29694
  realtime: input.realtime,
29836
- idFactory: randomUUID32
29695
+ idFactory: randomUUID31
29837
29696
  });
29838
29697
  const runService = new ProjectTaskRunService({
29839
29698
  tasks: input.taskStore,
@@ -30657,7 +30516,7 @@ var collectionRegistration = {
30657
30516
 
30658
30517
  // src/export_registrations/channel-installation.registration.ts
30659
30518
  import { getStoreLattice as getStoreLattice35 } from "@axiom-lattice/core";
30660
- import { randomUUID as randomUUID33 } from "crypto";
30519
+ import { randomUUID as randomUUID32 } from "crypto";
30661
30520
  var UUID_PATTERN2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
30662
30521
  var PUBLIC_CHANNELS = /* @__PURE__ */ new Set(["lark", "email", "slack", "wechat", "wecom"]);
30663
30522
  function isPublicChannel(channel) {
@@ -30819,7 +30678,7 @@ var channelInstallationRegistration = {
30819
30678
  }
30820
30679
  id3 = sourceId;
30821
30680
  } else {
30822
- id3 = randomUUID33();
30681
+ id3 = randomUUID32();
30823
30682
  }
30824
30683
  await store2.createInstallation(tenantId, id3, createInput);
30825
30684
  return { newId: id3 };
@@ -31379,7 +31238,7 @@ function createAuditLoggerMiddleware() {
31379
31238
  import { setBindingRegistry, setMenuRegistry, setEvalRunService } from "@axiom-lattice/core";
31380
31239
 
31381
31240
  // src/channels/wecom/WecomChannelAdapter.ts
31382
- import { randomUUID as randomUUID34 } from "crypto";
31241
+ import { randomUUID as randomUUID33 } from "crypto";
31383
31242
  import { z as z13 } from "zod";
31384
31243
  import * as WecomAiBot from "@wecom/aibot-node-sdk";
31385
31244
 
@@ -31743,7 +31602,7 @@ function streamIdFor(replyTarget) {
31743
31602
  const key = replyKeyForTarget(replyTarget);
31744
31603
  let streamId = streamIdsByReqId.get(key);
31745
31604
  if (!streamId) {
31746
- streamId = randomUUID34();
31605
+ streamId = randomUUID33();
31747
31606
  streamIdsByReqId.set(key, streamId);
31748
31607
  if (streamIdsByReqId.size > MAX_TRACKED_STREAMS) {
31749
31608
  const oldest = streamIdsByReqId.keys().next().value;
@@ -33038,7 +32897,7 @@ import {
33038
32897
  snapshotExactRecord as snapshotExactRecord15,
33039
32898
  MessageChunkTypes as MessageChunkTypes4
33040
32899
  } from "@axiom-lattice/protocols";
33041
- import { randomUUID as randomUUID35 } from "crypto";
32900
+ import { randomUUID as randomUUID34 } from "crypto";
33042
32901
 
33043
32902
  // src/services/channel-reply/channelReplyRuntimeRegistry.ts
33044
32903
  var active;
@@ -33393,7 +33252,7 @@ var _MessageRouter = class _MessageRouter {
33393
33252
  }
33394
33253
  if (!threadId) {
33395
33254
  const threadStore = getStoreLattice39("default", "thread").store;
33396
- const newThreadId = randomUUID35();
33255
+ const newThreadId = randomUUID34();
33397
33256
  console.log({
33398
33257
  event: "dispatch:thread:create",
33399
33258
  agentId,
@@ -33432,7 +33291,7 @@ var _MessageRouter = class _MessageRouter {
33432
33291
  senderId: message.sender.id,
33433
33292
  contentLength: message.content.text.length
33434
33293
  }, "Dispatching to agent");
33435
- const inputMessageId = randomUUID35();
33294
+ const inputMessageId = randomUUID34();
33436
33295
  const replyTarget = internalRoom ? correlatedRoomReplyTarget(message.replyTarget, inputMessageId) : message.replyTarget;
33437
33296
  const replyAdapter = replyTarget ? this.adapterRegistry.get(replyTarget.adapterChannel) : void 0;
33438
33297
  if (options.trustedMessageOptions && (!this.trustedDispatcher || !replyTarget || !replyAdapter)) {
@@ -33629,7 +33488,7 @@ var _MessageRouter = class _MessageRouter {
33629
33488
  };
33630
33489
  const runLedger = getStoreLattice39("default", "agentRun").store;
33631
33490
  const jobStore = getStoreLattice39("default", "channelReplyJob").store;
33632
- const runId = randomUUID35();
33491
+ const runId = randomUUID34();
33633
33492
  await jobStore.create({
33634
33493
  runId,
33635
33494
  tenantId,
@@ -34281,7 +34140,7 @@ async function prepareProjectTaskRuntime(runtime, log2) {
34281
34140
  import { setPluginDeploymentService } from "@axiom-lattice/core";
34282
34141
 
34283
34142
  // src/services/plugins/PluginDeploymentService.ts
34284
- import { randomUUID as randomUUID36 } from "crypto";
34143
+ import { randomUUID as randomUUID35 } from "crypto";
34285
34144
  import {
34286
34145
  PLUGIN_HOST_DIR,
34287
34146
  PluginDeploymentRuntimeRegistry
@@ -34425,7 +34284,7 @@ var PluginDeploymentService = class {
34425
34284
  const failedAt = this.nowIso();
34426
34285
  await this.store.upsert(
34427
34286
  this.buildRecord({
34428
- id: existing?.id ?? randomUUID36(),
34287
+ id: existing?.id ?? randomUUID35(),
34429
34288
  tenantId,
34430
34289
  pluginType,
34431
34290
  pluginVersion: manifest.version,
@@ -34447,7 +34306,7 @@ var PluginDeploymentService = class {
34447
34306
  );
34448
34307
  }
34449
34308
  const record = this.buildRecord({
34450
- id: existing?.id ?? randomUUID36(),
34309
+ id: existing?.id ?? randomUUID35(),
34451
34310
  tenantId,
34452
34311
  pluginType,
34453
34312
  pluginVersion: manifest.version,
@@ -38639,8 +38498,8 @@ var start = async (config) => {
38639
38498
  });
38640
38499
  try {
38641
38500
  const { A2AAuthService: A2AAuthService2, parseEnvKeys: parseEnvKeys2 } = await import("./A2AAuthService-UKN53ZGP.mjs");
38642
- const { registerA2AStandardRoutes } = await import("./a2a-standard-INVCUSAW.mjs");
38643
- const a2a = await import("./a2a-TDZ3TT6H.mjs");
38501
+ const { registerA2AStandardRoutes } = await import("./a2a-standard-NOAVPYXJ.mjs");
38502
+ const a2a = await import("./a2a-YLKZE5JG.mjs");
38644
38503
  const a2aKeyStore = getStoreLattice42("default", "a2aApiKey").store;
38645
38504
  const assistantStore = getStoreLattice42("default", "assistant").store;
38646
38505
  const projectStore = getStoreLattice42("default", "project").store;
@@ -38669,12 +38528,12 @@ var start = async (config) => {
38669
38528
  });
38670
38529
  }
38671
38530
  try {
38672
- const { registerOpenRoutes } = await import("./open-27ZPLBIW.mjs");
38531
+ const { registerOpenRoutes } = await import("./open-PCOORPQ5.mjs");
38673
38532
  const { registerOpenSessionRoutes } = await import("./open-session-CLZT3HVG.mjs");
38674
38533
  const { registerOpenCatalogRoutes } = await import("./open-catalog-NVGP6SQP.mjs");
38675
38534
  const { registerOpenFilesRoutes } = await import("./open-files-JPB2NBL6.mjs");
38676
38535
  const { registerOpenAuditRoutes } = await import("./open-audit-UJ3NXCGW.mjs");
38677
- const { registerOpenExposureRoutes } = await import("./open-exposure-BPLYUIX6.mjs");
38536
+ const { registerOpenExposureRoutes } = await import("./open-exposure-HGYT5VFC.mjs");
38678
38537
  const { openLattice } = await import("./openLattice-D5YTSZBY.mjs");
38679
38538
  const { createKbProvider } = await import("./kbProvider-2D6DZ34N.mjs");
38680
38539
  const { createOpenSandboxProvider } = await import("./sandboxProvider-FILMFVIM.mjs");