@axiom-lattice/gateway 8.4.0 → 9.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 (56) hide show
  1. package/dist/{a2a-TDZ3TT6H.mjs → a2a-YLKZE5JG.mjs} +6 -4
  2. package/dist/{a2a-standard-INVCUSAW.mjs → a2a-standard-MD7WNDTP.mjs} +41 -126
  3. package/dist/a2a-standard-MD7WNDTP.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-W3YH4S6G.mjs → chunk-SIMEG2JT.mjs} +19 -2
  7. package/dist/chunk-SIMEG2JT.mjs.map +1 -0
  8. package/dist/embed/{embed-page-AgentDetailSideApp-TQEJK6ZF.js → embed-page-AgentDetailSideApp-6RYNHS5F.js} +1 -1
  9. package/dist/embed/embed-page-AgentGovernanceWorkbench-UAPXF3SZ.js +1 -0
  10. package/dist/embed/{embed-page-LangfuseDashboard-7OANGQXY.js → embed-page-LangfuseDashboard-ZYGZNW7P.js} +1 -1
  11. package/dist/embed/{embed-page-MessageGraph-KJPQWTHE.js → embed-page-MessageGraph-S2P3WACC.js} +1 -1
  12. package/dist/embed/{embed-page-ReactChart-2CAIM4JD.js → embed-page-ReactChart-I3UZVE4Z.js} +1 -1
  13. package/dist/embed/{embed-page-SkillFlow-243MXRXC.js → embed-page-SkillFlow-JMIJ46FX.js} +1 -1
  14. package/dist/embed/{embed-page-TasksSideApp-OA7CULHS.js → embed-page-TasksSideApp-IVFEFLSH.js} +1 -1
  15. package/dist/embed/{embed-page-ThreadMaintenancePanel-Z4424X3J.js → embed-page-ThreadMaintenancePanel-KQPPAEWJ.js} +1 -1
  16. package/dist/embed/{embed-page-TopologyRuntimeView-THTCZUS7.js → embed-page-TopologyRuntimeView-XCFQ23HF.js} +1 -1
  17. package/dist/embed/embed-page-WorkflowAutomationView-UTKCKP75.js +3 -0
  18. package/dist/embed/embed-page-chunk-5X4MNQAW.js +242 -0
  19. package/dist/embed/{embed-page-chunk-JMP7EQEF.js → embed-page-chunk-77CQOFKU.js} +1 -1
  20. package/dist/embed/{embed-page-chunk-RKQJBKN2.js → embed-page-chunk-7VDAOX3D.js} +1 -1
  21. package/dist/embed/{embed-page-chunk-FZX4A32D.js → embed-page-chunk-MD4U4DHC.js} +1 -1
  22. package/dist/embed/embed-page-chunk-RANB2CUO.js +3 -0
  23. package/dist/embed/{embed-page-chunk-L2EGVVJS.js → embed-page-chunk-RVIS6CKE.js} +1 -1
  24. package/dist/embed/embed-page-chunk-SEOTZ4Q7.js +6829 -0
  25. package/dist/embed/{embed-page-chunk-W5OP2CZG.js → embed-page-chunk-TCVPYXPL.js} +2 -2
  26. package/dist/embed/embed-page-chunk-WHGU76CU.js +211 -0
  27. package/dist/embed/{embed-page-chunk-LDQGH44H.js → embed-page-chunk-ZZFTCBM6.js} +1 -1
  28. package/dist/embed/embed-page-en-4HSTKY4Q.js +1 -0
  29. package/dist/embed/embed-page-en-MIVBTEEL.js +1 -0
  30. package/dist/embed/embed-page-zh-7PJNJJZY.js +1 -0
  31. package/dist/embed/embed-page-zh-UZ4GPIU7.js +1 -0
  32. package/dist/embed/embed-page.js +1 -1
  33. package/dist/embed/mcp-app-page.js +10 -10
  34. package/dist/index.js +1415 -1265
  35. package/dist/index.js.map +1 -1
  36. package/dist/index.mjs +224 -372
  37. package/dist/index.mjs.map +1 -1
  38. package/dist/{open-exposure-BPLYUIX6.mjs → open-exposure-HGYT5VFC.mjs} +5 -6
  39. package/dist/open-exposure-HGYT5VFC.mjs.map +1 -0
  40. package/package.json +7 -7
  41. package/dist/a2a-standard-INVCUSAW.mjs.map +0 -1
  42. package/dist/chunk-OBODBHIS.mjs +0 -230
  43. package/dist/chunk-OBODBHIS.mjs.map +0 -1
  44. package/dist/chunk-W3YH4S6G.mjs.map +0 -1
  45. package/dist/embed/embed-page-AgentGovernanceWorkbench-II2MRGCG.js +0 -1
  46. package/dist/embed/embed-page-WorkflowAutomationView-YDIDG35E.js +0 -3
  47. package/dist/embed/embed-page-chunk-7ULTMRM2.js +0 -211
  48. package/dist/embed/embed-page-chunk-OMN6G52V.js +0 -3
  49. package/dist/embed/embed-page-chunk-VYS3TAK4.js +0 -242
  50. package/dist/embed/embed-page-chunk-Z6KWW64I.js +0 -6837
  51. package/dist/embed/embed-page-en-D4M3DPFT.js +0 -1
  52. package/dist/embed/embed-page-en-JOTELYAL.js +0 -1
  53. package/dist/embed/embed-page-zh-BPO6ZSJM.js +0 -1
  54. package/dist/embed/embed-page-zh-NEXLMDHF.js +0 -1
  55. package/dist/open-exposure-BPLYUIX6.mjs.map +0 -1
  56. /package/dist/{a2a-TDZ3TT6H.mjs.map → a2a-YLKZE5JG.mjs.map} +0 -0
package/dist/index.mjs CHANGED
@@ -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,
@@ -11000,8 +11003,9 @@ function createProjectCollaborationInitializer(deps) {
11000
11003
  };
11001
11004
  }
11002
11005
  var WorkspaceController = class {
11003
- constructor(projectCollaboration) {
11006
+ constructor(projectCollaboration, projectAccess) {
11004
11007
  this.projectCollaboration = projectCollaboration;
11008
+ this.projectAccess = projectAccess;
11005
11009
  this.workspaceStore = getStoreLattice16("default", "workspace").store;
11006
11010
  this.projectStore = getStoreLattice16("default", "project").store;
11007
11011
  const roomStore = getStoreLattice16("default", "projectRoom").store;
@@ -11043,6 +11047,48 @@ var WorkspaceController = class {
11043
11047
  }
11044
11048
  return request.headers["x-tenant-id"] || "default";
11045
11049
  }
11050
+ requireActor(request, reply) {
11051
+ const user = request.user;
11052
+ if (!user?.id || !user.tenantId) {
11053
+ void reply.status(401).send({
11054
+ success: false,
11055
+ code: "UNAUTHORIZED",
11056
+ error: "Unauthorized"
11057
+ });
11058
+ return null;
11059
+ }
11060
+ return { tenantId: user.tenantId, userId: user.id };
11061
+ }
11062
+ accessService() {
11063
+ if (!this.projectAccess) {
11064
+ throw new Error("Project access service is not configured");
11065
+ }
11066
+ return this.projectAccess;
11067
+ }
11068
+ async requireReadableProject(actor3, workspaceId, projectId, capability2) {
11069
+ try {
11070
+ const result = await this.accessService().requireExistingProjectAccess({
11071
+ tenantId: actor3.tenantId,
11072
+ userId: actor3.userId,
11073
+ projectId,
11074
+ capability: capability2
11075
+ });
11076
+ if (result.project.workspaceId !== workspaceId) return null;
11077
+ return result.project;
11078
+ } catch (error) {
11079
+ if (error instanceof ProjectCollaborationError && (error.code === "PROJECT_ACCESS_DENIED" || error.code === "PROJECT_NOT_FOUND")) {
11080
+ return null;
11081
+ }
11082
+ throw error;
11083
+ }
11084
+ }
11085
+ projectNotFound(reply) {
11086
+ return reply.status(404).send({
11087
+ success: false,
11088
+ code: "PROJECT_NOT_FOUND",
11089
+ error: "Project not found"
11090
+ });
11091
+ }
11046
11092
  // ==================== Workspace CRUD ====================
11047
11093
  async listWorkspaces(request, reply) {
11048
11094
  const tenantId = this.getTenantId(request);
@@ -11100,14 +11146,18 @@ var WorkspaceController = class {
11100
11146
  }
11101
11147
  // ==================== Project CRUD ====================
11102
11148
  async listProjects(request, reply) {
11103
- const tenantId = this.getTenantId(request);
11149
+ const actor3 = this.requireActor(request, reply);
11150
+ if (!actor3) return;
11104
11151
  const { workspaceId } = request.params;
11105
11152
  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, {
11153
+ await this.ensureTrainingProject(actor3.tenantId, workspaceId);
11154
+ await this.publicRoom.ensure(actor3.tenantId, workspaceId);
11155
+ const projects = await this.accessService().listReadableProjects({
11156
+ tenantId: actor3.tenantId,
11157
+ userId: actor3.userId,
11158
+ workspaceId,
11109
11159
  kind: kindFilter
11110
- }) : await this.projectStore.getProjectsByWorkspace(tenantId, workspaceId);
11160
+ });
11111
11161
  return { success: true, data: projects };
11112
11162
  }
11113
11163
  /**
@@ -11132,13 +11182,9 @@ var WorkspaceController = class {
11132
11182
  });
11133
11183
  }
11134
11184
  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";
11185
+ const actor3 = this.requireActor(request, reply);
11186
+ if (!actor3) return;
11187
+ const tenantId = actor3.tenantId;
11142
11188
  const { workspaceId } = request.params;
11143
11189
  const data = request.body;
11144
11190
  if (writesCapabilityBundleIds(data.config)) {
@@ -11148,9 +11194,9 @@ var WorkspaceController = class {
11148
11194
  message: CAPABILITY_BUNDLE_CONFIG_MESSAGE
11149
11195
  });
11150
11196
  }
11151
- if (user?.id && this.projectCollaboration) {
11197
+ if (this.projectCollaboration) {
11152
11198
  try {
11153
- const authorized = await this.projectCollaboration.authorizeCreator({ tenantId, userId: user.id });
11199
+ const authorized = await this.projectCollaboration.authorizeCreator({ tenantId, userId: actor3.userId });
11154
11200
  if (!authorized) {
11155
11201
  return reply.status(403).send({ success: false, code: "TENANT_ACCESS_DENIED", error: "Tenant access denied" });
11156
11202
  }
@@ -11161,7 +11207,7 @@ var WorkspaceController = class {
11161
11207
  console.error({
11162
11208
  event: "project:collaboration-preflight-failed",
11163
11209
  tenantId,
11164
- userId: user.id,
11210
+ userId: actor3.userId,
11165
11211
  errorName: error instanceof Error ? error.name : "UnknownError"
11166
11212
  });
11167
11213
  return reply.status(500).send({
@@ -11179,42 +11225,72 @@ var WorkspaceController = class {
11179
11225
  id3,
11180
11226
  data
11181
11227
  );
11182
- if (user?.id && this.projectCollaboration) {
11228
+ if (this.projectCollaboration) {
11183
11229
  try {
11184
- await this.projectCollaboration.initialize({ tenantId, userId: user.id, project });
11230
+ await this.projectCollaboration.initialize({ tenantId, userId: actor3.userId, project });
11185
11231
  } catch (error) {
11186
- const phase = error instanceof ProjectCollaborationInitializationError ? error.phase : "owner";
11232
+ const phase = error instanceof ProjectCollaborationInitializationError ? error.phase : void 0;
11233
+ let rolledBack = false;
11234
+ if (phase === "owner") {
11235
+ try {
11236
+ rolledBack = await this.projectStore.deleteProject(tenantId, project.id);
11237
+ if (!rolledBack) {
11238
+ console.error({
11239
+ event: "project:owner-initialization-rollback-missed",
11240
+ tenantId,
11241
+ projectId: project.id
11242
+ });
11243
+ }
11244
+ } catch (cleanupError) {
11245
+ console.error({
11246
+ event: "project:owner-initialization-rollback-failed",
11247
+ tenantId,
11248
+ projectId: project.id,
11249
+ errorName: cleanupError instanceof Error ? cleanupError.name : "UnknownError"
11250
+ });
11251
+ }
11252
+ }
11187
11253
  console.error({
11188
11254
  event: "project:collaboration-initialization-failed",
11189
11255
  phase,
11190
11256
  tenantId,
11191
11257
  projectId: project.id,
11192
- userId: user.id,
11258
+ userId: actor3.userId,
11193
11259
  errorName: error instanceof Error ? error.name : "UnknownError"
11194
11260
  });
11195
11261
  return reply.status(500).send({
11196
11262
  success: false,
11197
11263
  error: "Internal server error",
11198
- code: phase === "owner" ? "PROJECT_OWNER_INITIALIZATION_FAILED" : "PROJECT_ROOM_INITIALIZATION_FAILED",
11264
+ code: phase === "owner" ? "PROJECT_OWNER_INITIALIZATION_FAILED" : phase === "room" ? "PROJECT_ROOM_INITIALIZATION_FAILED" : "PROJECT_COLLABORATION_INITIALIZATION_FAILED",
11199
11265
  projectId: project.id,
11200
- retryable: phase === "room"
11266
+ retryable: phase === "room" || rolledBack
11201
11267
  });
11202
11268
  }
11203
11269
  }
11204
11270
  return reply.status(201).send({ success: true, data: project });
11205
11271
  }
11206
11272
  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
- }
11273
+ const actor3 = this.requireActor(request, reply);
11274
+ if (!actor3) return;
11275
+ const project = await this.requireReadableProject(
11276
+ actor3,
11277
+ request.params.workspaceId,
11278
+ request.params.projectId,
11279
+ "read"
11280
+ );
11281
+ if (!project) return this.projectNotFound(reply);
11213
11282
  return { success: true, data: project };
11214
11283
  }
11215
11284
  async updateProject(request, reply) {
11216
- const tenantId = this.getTenantId(request);
11217
- const { projectId } = request.params;
11285
+ const actor3 = this.requireActor(request, reply);
11286
+ if (!actor3) return;
11287
+ const project = await this.requireReadableProject(
11288
+ actor3,
11289
+ request.params.workspaceId,
11290
+ request.params.projectId,
11291
+ "manage"
11292
+ );
11293
+ if (!project) return this.projectNotFound(reply);
11218
11294
  const updates = request.body;
11219
11295
  if (writesCapabilityBundleIds(updates.config)) {
11220
11296
  return reply.status(400).send({
@@ -11223,36 +11299,35 @@ var WorkspaceController = class {
11223
11299
  message: CAPABILITY_BUNDLE_CONFIG_MESSAGE
11224
11300
  });
11225
11301
  }
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
- }
11302
+ if (project.id === workspacePublicRoomProjectId(actor3.tenantId, project.workspaceId) && (updates.kind !== void 0 || updates.name !== void 0)) {
11303
+ return reply.status(409).send({
11304
+ success: false,
11305
+ error: "The workspace public room cannot be renamed or reclassified"
11306
+ });
11234
11307
  }
11235
- const project = await this.projectStore.updateProject(
11236
- tenantId,
11237
- projectId,
11308
+ const updated = await this.projectStore.updateProject(
11309
+ actor3.tenantId,
11310
+ project.id,
11238
11311
  updates
11239
11312
  );
11240
- if (!project) {
11241
- return reply.status(404).send({ success: false, error: "Project not found" });
11242
- }
11243
- return { success: true, data: project };
11313
+ if (!updated) return this.projectNotFound(reply);
11314
+ return { success: true, data: updated };
11244
11315
  }
11245
11316
  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
- }
11317
+ const actor3 = this.requireActor(request, reply);
11318
+ if (!actor3) return;
11319
+ const project = await this.requireReadableProject(
11320
+ actor3,
11321
+ request.params.workspaceId,
11322
+ request.params.projectId,
11323
+ "manage"
11324
+ );
11325
+ if (!project) return this.projectNotFound(reply);
11326
+ const { workspaceId } = request.params;
11252
11327
  if (project.kind === "training") {
11253
11328
  const training = await this.projectStore.getProjectsByWorkspace(
11254
- tenantId,
11255
- workspaceId,
11329
+ actor3.tenantId,
11330
+ project.workspaceId,
11256
11331
  { kind: "training" }
11257
11332
  );
11258
11333
  if (training.length <= 1) {
@@ -11262,16 +11337,14 @@ var WorkspaceController = class {
11262
11337
  });
11263
11338
  }
11264
11339
  }
11265
- if (project.id === workspacePublicRoomProjectId(tenantId, project.workspaceId ?? workspaceId)) {
11340
+ if (project.id === workspacePublicRoomProjectId(actor3.tenantId, project.workspaceId ?? workspaceId)) {
11266
11341
  return reply.status(409).send({
11267
11342
  success: false,
11268
11343
  error: "The workspace public room cannot be deleted"
11269
11344
  });
11270
11345
  }
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
- }
11346
+ const deleted = await this.projectStore.deleteProject(actor3.tenantId, project.id);
11347
+ if (!deleted) return this.projectNotFound(reply);
11275
11348
  return { success: true };
11276
11349
  }
11277
11350
  // ==================== File Operations ====================
@@ -11909,8 +11982,8 @@ var WorkspaceController = class {
11909
11982
  }
11910
11983
  }
11911
11984
  };
11912
- function registerWorkspaceRoutes(app2, projectCollaboration) {
11913
- const controller = new WorkspaceController(projectCollaboration);
11985
+ function registerWorkspaceRoutes(app2, projectCollaboration, projectAccess) {
11986
+ const controller = new WorkspaceController(projectCollaboration, projectAccess);
11914
11987
  app2.get("/api/workspaces", controller.listWorkspaces.bind(controller));
11915
11988
  app2.post("/api/workspaces", controller.createWorkspace.bind(controller));
11916
11989
  app2.get(
@@ -11977,250 +12050,12 @@ function registerWorkspaceRoutes(app2, projectCollaboration) {
11977
12050
  return controller;
11978
12051
  }
11979
12052
 
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
12053
  // src/controllers/database-configs.ts
12219
12054
  import {
12220
12055
  getStoreLattice as getStoreLattice17,
12221
12056
  sqlDatabaseManager
12222
12057
  } from "@axiom-lattice/core";
12223
- import { randomUUID as randomUUID15 } from "crypto";
12058
+ import { randomUUID as randomUUID14 } from "crypto";
12224
12059
  function getTenantId16(request) {
12225
12060
  const userTenantId = request.user?.tenantId;
12226
12061
  if (userTenantId) {
@@ -12298,7 +12133,7 @@ async function createDatabaseConfig(request, reply) {
12298
12133
  message: "Database configuration with this key already exists"
12299
12134
  };
12300
12135
  }
12301
- const id3 = body.id || randomUUID15();
12136
+ const id3 = body.id || randomUUID14();
12302
12137
  const config = await store2.createConfig(tenantId, id3, body);
12303
12138
  try {
12304
12139
  sqlDatabaseManager.registerDatabase(tenantId, config.key, config.config);
@@ -12503,7 +12338,7 @@ import {
12503
12338
  metricsServerManager as metricsServerManager2,
12504
12339
  SemanticMetricsClient as SemanticMetricsClient2
12505
12340
  } from "@axiom-lattice/core";
12506
- import { randomUUID as randomUUID16 } from "crypto";
12341
+ import { randomUUID as randomUUID15 } from "crypto";
12507
12342
  function getTenantId17(request) {
12508
12343
  const userTenantId = request.user?.tenantId;
12509
12344
  if (userTenantId) {
@@ -12584,7 +12419,7 @@ async function createMetricsServerConfig(request, reply) {
12584
12419
  message: "selectedDataSources is required for semantic metrics servers"
12585
12420
  };
12586
12421
  }
12587
- const id3 = body.id || randomUUID16();
12422
+ const id3 = body.id || randomUUID15();
12588
12423
  const configData = {
12589
12424
  key: body.key,
12590
12425
  name: body.name,
@@ -13247,7 +13082,7 @@ import {
13247
13082
  McpLatticeManager,
13248
13083
  convertToConnection
13249
13084
  } from "@axiom-lattice/core";
13250
- import { randomUUID as randomUUID17 } from "crypto";
13085
+ import { randomUUID as randomUUID16 } from "crypto";
13251
13086
 
13252
13087
  // src/services/mcpConfigSync.ts
13253
13088
  var MCP_CONFIG_CHANGED_TOPIC = "mcp-config-changed";
@@ -13366,7 +13201,7 @@ async function createMcpServerConfig(request, reply) {
13366
13201
  message: "MCP server configuration with this key already exists"
13367
13202
  };
13368
13203
  }
13369
- const id3 = body.id || randomUUID17();
13204
+ const id3 = body.id || randomUUID16();
13370
13205
  const config = await store2.createConfig(tenantId, id3, body);
13371
13206
  try {
13372
13207
  await connectAndRegisterTools(config);
@@ -15677,7 +15512,7 @@ function registerChannelRoutes(app2, dependencies) {
15677
15512
  }
15678
15513
 
15679
15514
  // src/controllers/channel-installations.ts
15680
- import { randomUUID as randomUUID18 } from "crypto";
15515
+ import { randomUUID as randomUUID17 } from "crypto";
15681
15516
  import {
15682
15517
  descriptorDataValue
15683
15518
  } from "@axiom-lattice/protocols";
@@ -15898,7 +15733,7 @@ async function createChannelInstallation(request, reply) {
15898
15733
  };
15899
15734
  }
15900
15735
  const store2 = await getInstallationStore();
15901
- const installationId = randomUUID18();
15736
+ const installationId = randomUUID17();
15902
15737
  const createInput = {
15903
15738
  channel: body.channel,
15904
15739
  name: body.name,
@@ -16890,7 +16725,7 @@ async function getLocalA2ATemplates(_request, reply) {
16890
16725
  }
16891
16726
 
16892
16727
  // src/routes/a2a-test-connection.ts
16893
- import { randomUUID as randomUUID19 } from "crypto";
16728
+ import { randomUUID as randomUUID18 } from "crypto";
16894
16729
  function describeTestConnectionError(error, agentCardUrl) {
16895
16730
  if (!(error instanceof Error)) {
16896
16731
  return `Failed to fetch agent card from ${agentCardUrl}: ${String(error)}`;
@@ -16930,7 +16765,7 @@ async function ensureLocalRuntimeForConnectionTest(localRuntime, agentCardUrl) {
16930
16765
  return { error: portValidation.error };
16931
16766
  }
16932
16767
  const state = await localA2AService.startProvider(
16933
- `test-${randomUUID19()}`,
16768
+ `test-${randomUUID18()}`,
16934
16769
  testRuntime
16935
16770
  );
16936
16771
  if (state.status === "running") return { runtimeId: state.runtimeId };
@@ -17363,13 +17198,13 @@ function snapshotEnsureInput(input) {
17363
17198
  import { createHash as createHash3 } from "crypto";
17364
17199
 
17365
17200
  // src/services/collaboration/ProjectTaskRunService.ts
17366
- import { randomUUID as randomUUID21 } from "crypto";
17201
+ import { randomUUID as randomUUID20 } from "crypto";
17367
17202
  import {
17368
17203
  createTaskRunBridge
17369
17204
  } from "@axiom-lattice/core";
17370
17205
 
17371
17206
  // src/services/collaboration/ProjectTaskRunPlanner.ts
17372
- import { randomUUID as randomUUID20 } from "crypto";
17207
+ import { randomUUID as randomUUID19 } from "crypto";
17373
17208
 
17374
17209
  // src/services/collaboration/ProjectTaskRunProtocol.ts
17375
17210
  import {
@@ -17685,7 +17520,7 @@ var ProjectTaskRunPlanner = class {
17685
17520
  } catch (error) {
17686
17521
  throw asPlanError(error);
17687
17522
  }
17688
- const inputId = (this.deps.idFactory ?? randomUUID20)();
17523
+ const inputId = (this.deps.idFactory ?? randomUUID19)();
17689
17524
  const actor3 = input.actor ?? SYSTEM_ACTOR;
17690
17525
  const userId = actor3.startsWith("user:") && actor3.length > "user:".length ? actor3.slice("user:".length) : void 0;
17691
17526
  const trustedContext = {
@@ -17828,7 +17663,7 @@ var ProjectTaskRunService = class {
17828
17663
  ...deps.idFactory === void 0 ? {} : { idFactory: deps.idFactory }
17829
17664
  });
17830
17665
  this.runBridge = createTaskRunBridge({ lifecycle: deps.lifecycle });
17831
- this.idFactory = deps.idFactory ?? randomUUID21;
17666
+ this.idFactory = deps.idFactory ?? randomUUID20;
17832
17667
  this.log = deps.log ?? { warn: () => void 0 };
17833
17668
  }
17834
17669
  /**
@@ -19185,7 +19020,7 @@ var AgentWebAppService = class {
19185
19020
  }
19186
19021
  async create(context, input) {
19187
19022
  await this.validateAssistant(context, input.assistantId);
19188
- const normalized = await this.validateConfig(context.tenantId, input);
19023
+ const normalized = await this.validateConfig(context, input);
19189
19024
  return this.deps.webAppStore.create(context.tenantId, normalized);
19190
19025
  }
19191
19026
  async list(context, assistantId) {
@@ -19212,7 +19047,7 @@ var AgentWebAppService = class {
19212
19047
  identity: patch.identity ?? current3.identity
19213
19048
  };
19214
19049
  await this.validateAssistant(context, current3.assistantId);
19215
- const validated = await this.validateConfig(context.tenantId, effective);
19050
+ const validated = await this.validateConfig(context, effective, current3);
19216
19051
  const update = {
19217
19052
  ...patch.name !== void 0 ? { name: validated.name } : {},
19218
19053
  ...Object.prototype.hasOwnProperty.call(patch, "description") ? { description: validated.description } : {},
@@ -19225,7 +19060,7 @@ var AgentWebAppService = class {
19225
19060
  }
19226
19061
  async enable(context, webAppId) {
19227
19062
  const current3 = await this.requireAuthorizedWebApp(context, webAppId);
19228
- await this.validateConfig(context.tenantId, current3);
19063
+ await this.validateConfig(context, current3, current3);
19229
19064
  return this.writeSnapshot(context, current3, { status: "active" });
19230
19065
  }
19231
19066
  async disable(context, webAppId) {
@@ -19247,7 +19082,7 @@ var AgentWebAppService = class {
19247
19082
  if (await this.deps.configuredAgentResolver.exists(context.tenantId, assistantId)) return;
19248
19083
  throw new AgentWebAppError("ASSISTANT_NOT_FOUND", 404, "Assistant not found");
19249
19084
  }
19250
- async validateConfig(tenantId, input) {
19085
+ async validateConfig(context, input, existing) {
19251
19086
  const allowedProjectIds = [...new Set(input.scope.allowedProjectIds)];
19252
19087
  if (!allowedProjectIds.length || !allowedProjectIds.includes(input.scope.defaultProjectId)) {
19253
19088
  throw new AgentWebAppError("PROJECT_SCOPE_INVALID", 400, "Default project must be in the project allowlist");
@@ -19255,13 +19090,28 @@ var AgentWebAppService = class {
19255
19090
  if (!input.features.projectSelector && allowedProjectIds.length !== 1) {
19256
19091
  throw new AgentWebAppError("PROJECT_SCOPE_INVALID", 400, "Disabled project selection requires exactly one project");
19257
19092
  }
19093
+ const existingIds = new Set(existing?.scope.allowedProjectIds ?? []);
19258
19094
  for (const projectId of allowedProjectIds) {
19259
- if (!await this.deps.projectStore.getProjectById(tenantId, projectId)) {
19095
+ if (!await this.deps.projectStore.getProjectById(context.tenantId, projectId)) {
19260
19096
  throw new AgentWebAppError("PROJECT_NOT_FOUND", 404, "Project not found");
19261
19097
  }
19098
+ if (existingIds.has(projectId)) continue;
19099
+ try {
19100
+ await this.deps.projectAccess.requireExistingProjectAccess({
19101
+ tenantId: context.tenantId,
19102
+ userId: context.userId,
19103
+ projectId,
19104
+ capability: "read"
19105
+ });
19106
+ } catch (error) {
19107
+ if (error instanceof ProjectCollaborationError) {
19108
+ throw new AgentWebAppError("PROJECT_NOT_FOUND", 404, "Project not found");
19109
+ }
19110
+ throw error;
19111
+ }
19262
19112
  }
19263
19113
  const scope = await this.validateModels(
19264
- tenantId,
19114
+ context.tenantId,
19265
19115
  input.scope,
19266
19116
  input.features.modelSelector
19267
19117
  );
@@ -19470,7 +19320,7 @@ import { createHmac as createHmac3 } from "crypto";
19470
19320
  import { z as z5, ZodError as ZodError2 } from "zod";
19471
19321
 
19472
19322
  // src/services/agent-web-app/AgentWebAppRuntimeService.ts
19473
- import { createHash as createHash4, randomUUID as randomUUID22 } from "crypto";
19323
+ import { createHash as createHash4, randomUUID as randomUUID21 } from "crypto";
19474
19324
  import { MessageChunkTypes as MessageChunkTypes3, parseAgentWebAppGenUIBlock, buildAffinityMissChunk as buildAffinityMissChunk2 } from "@axiom-lattice/protocols";
19475
19325
  import { getReplicaId as getReplicaId7, getThreadRunOwner as getThreadRunOwner2, normalizeAgentInterrupts as normalizeAgentInterrupts2 } from "@axiom-lattice/core";
19476
19326
  function isRecord9(value) {
@@ -19768,7 +19618,7 @@ ${formatFileRefsSection(refs)}` : input.content;
19768
19618
  const userDigest = createHash4("sha256").update(userId, "utf8").digest("hex");
19769
19619
  const contentDigest = createHash4("sha256").update(file.bytes).digest("hex");
19770
19620
  const displayName = file.name;
19771
- const physicalName = `${randomUUID22()}-${sanitizePhysicalFilename(file.name)}`;
19621
+ const physicalName = `${randomUUID21()}-${sanitizePhysicalFilename(file.name)}`;
19772
19622
  const saved = await this.deps.saveProjectFile({
19773
19623
  tenantId: runtime.webApp.tenantId,
19774
19624
  workspaceId: runtime.project.workspaceId,
@@ -19929,7 +19779,7 @@ ${formatFileRefsSection(refs)}` : input.content;
19929
19779
  const thread = await this.deps.threadStore.createThread(
19930
19780
  runtime.webApp.tenantId,
19931
19781
  runtime.webApp.assistantId,
19932
- randomUUID22(),
19782
+ randomUUID21(),
19933
19783
  { metadata: this.metadata(runtime, userId, normalizeLabel(rawLabel)) }
19934
19784
  );
19935
19785
  return toRuntimeThread(thread);
@@ -21339,7 +21189,7 @@ function registerCapabilityBundleRoutes(app2, controller) {
21339
21189
  import { ZodError as ZodError3 } from "zod";
21340
21190
 
21341
21191
  // src/services/model-provider/ModelProviderService.ts
21342
- import { randomUUID as randomUUID23 } from "crypto";
21192
+ import { randomUUID as randomUUID22 } from "crypto";
21343
21193
  import { toModelKey } from "@axiom-lattice/protocols";
21344
21194
  import {
21345
21195
  assertSafeUpstreamUrl,
@@ -21678,7 +21528,7 @@ var unsafeReasonToErrorCode = {
21678
21528
  var ModelProviderService = class {
21679
21529
  constructor(deps) {
21680
21530
  this.deps = deps;
21681
- this.idFactory = deps.idFactory ?? (() => randomUUID23());
21531
+ this.idFactory = deps.idFactory ?? (() => randomUUID22());
21682
21532
  }
21683
21533
  /**
21684
21534
  * List the tenant's provider configurations.
@@ -22869,12 +22719,12 @@ async function handleModelProviderChanged(payload, reconcile) {
22869
22719
  }
22870
22720
 
22871
22721
  // src/services/collaboration/ProjectRoomService.ts
22872
- import { randomUUID as randomUUID24 } from "crypto";
22722
+ import { randomUUID as randomUUID23 } from "crypto";
22873
22723
  var ProjectRoomService = class {
22874
22724
  /** Creates a project room service from explicitly injected collaborators. */
22875
22725
  constructor(deps) {
22876
22726
  this.deps = deps;
22877
- this.idFactory = deps.idFactory ?? randomUUID24;
22727
+ this.idFactory = deps.idFactory ?? randomUUID23;
22878
22728
  }
22879
22729
  /**
22880
22730
  * Authorizes read access and ensures the project's main room.
@@ -22934,7 +22784,7 @@ var ProjectRoomService = class {
22934
22784
  };
22935
22785
 
22936
22786
  // src/services/collaboration/ProjectMembershipService.ts
22937
- import { randomUUID as randomUUID25 } from "crypto";
22787
+ import { randomUUID as randomUUID24 } from "crypto";
22938
22788
  var ProjectMembershipServiceError = class extends Error {
22939
22789
  constructor(code, statusCode, message) {
22940
22790
  super(message);
@@ -22943,14 +22793,14 @@ var ProjectMembershipServiceError = class extends Error {
22943
22793
  this.name = "ProjectMembershipServiceError";
22944
22794
  }
22945
22795
  };
22946
- var membershipConflictNames2 = /* @__PURE__ */ new Set(["DuplicateProjectMembershipError", "ProjectMembershipIdConflictError"]);
22796
+ var membershipConflictNames = /* @__PURE__ */ new Set(["DuplicateProjectMembershipError", "ProjectMembershipIdConflictError"]);
22947
22797
  function isMembershipConflict(error) {
22948
- return error instanceof Error && membershipConflictNames2.has(error.name);
22798
+ return error instanceof Error && membershipConflictNames.has(error.name);
22949
22799
  }
22950
22800
  var ProjectMembershipService = class {
22951
22801
  constructor(deps) {
22952
22802
  this.deps = deps;
22953
- this.idFactory = deps.idFactory ?? randomUUID25;
22803
+ this.idFactory = deps.idFactory ?? randomUUID24;
22954
22804
  this.mutationMutex = deps.projectMutationMutex ?? projectMutationMutex;
22955
22805
  }
22956
22806
  async list(actor3) {
@@ -23080,7 +22930,7 @@ var ProjectMembershipService = class {
23080
22930
  };
23081
22931
 
23082
22932
  // src/services/collaboration/ProjectRosterService.ts
23083
- import { randomUUID as randomUUID26 } from "crypto";
22933
+ import { randomUUID as randomUUID25 } from "crypto";
23084
22934
  var ProjectRosterServiceError = class extends Error {
23085
22935
  /** Creates a stable roster service error. */
23086
22936
  constructor(code, statusCode, message) {
@@ -23099,7 +22949,7 @@ var ProjectRosterService = class {
23099
22949
  /** Creates a roster service from explicitly injected collaborators. */
23100
22950
  constructor(deps) {
23101
22951
  this.deps = deps;
23102
- this.idFactory = deps.idFactory ?? randomUUID26;
22952
+ this.idFactory = deps.idFactory ?? randomUUID25;
23103
22953
  this.mutationMutex = deps.projectMutationMutex ?? projectMutationMutex;
23104
22954
  }
23105
22955
  /**
@@ -23206,7 +23056,7 @@ var ProjectRosterService = class {
23206
23056
  const agent = (await this.deps.agents.list(actor3.tenantId, actor3.userId)).find((item) => item.assistantId === assistantId);
23207
23057
  if (!agent || agent.ownerUserId !== void 0) throw new ProjectRosterServiceError("ASSISTANT_NOT_FOUND", 404, "Agent not found");
23208
23058
  const room = await this.deps.roomStore.ensureMainRoom({
23209
- id: randomUUID26(),
23059
+ id: randomUUID25(),
23210
23060
  tenantId: actor3.tenantId,
23211
23061
  workspaceId: project.workspaceId,
23212
23062
  projectId: actor3.projectId,
@@ -23550,7 +23400,7 @@ function virtualPublicProjectBot(project, room, agent, mentionName, now) {
23550
23400
  }
23551
23401
 
23552
23402
  // src/services/collaboration/RoomMessageService.ts
23553
- import { createHash as createHash6, randomUUID as randomUUID27 } from "crypto";
23403
+ import { createHash as createHash6, randomUUID as randomUUID26 } from "crypto";
23554
23404
 
23555
23405
  // src/services/collaboration/ProjectBotMembershipSnapshot.ts
23556
23406
  import { snapshotExactRecord as snapshotExactRecord5 } from "@axiom-lattice/protocols";
@@ -23639,7 +23489,7 @@ var RoomMessageService = class {
23639
23489
  constructor(deps, options = {}) {
23640
23490
  this.deps = deps;
23641
23491
  this.idempotentOutcomes = /* @__PURE__ */ new Map();
23642
- this.idFactory = deps.idFactory ?? randomUUID27;
23492
+ this.idFactory = deps.idFactory ?? randomUUID26;
23643
23493
  const limit = options.idempotentOutcomeLimit ?? 1e3;
23644
23494
  if (!Number.isSafeInteger(limit) || limit < 1) throw new RangeError("idempotentOutcomeLimit must be a positive safe integer");
23645
23495
  this.idempotentOutcomeLimit = limit;
@@ -23925,7 +23775,7 @@ import { ZodError as ZodError4 } from "zod";
23925
23775
  import { toProjectRoomPublicMessage } from "@axiom-lattice/protocols";
23926
23776
 
23927
23777
  // src/services/collaboration/RoomInterruptService.ts
23928
- import { randomUUID as randomUUID28 } from "crypto";
23778
+ import { randomUUID as randomUUID27 } from "crypto";
23929
23779
  var RESUMABLE_TASK_INTERRUPT_CODES = /* @__PURE__ */ new Set([
23930
23780
  "PROJECT_TASK_NOT_RESUMABLE",
23931
23781
  "PROJECT_TASK_NOT_READY",
@@ -23963,7 +23813,7 @@ var RoomInterruptService = class {
23963
23813
  /** Creates the service from explicitly injected stores and dispatcher. */
23964
23814
  constructor(deps) {
23965
23815
  this.deps = deps;
23966
- this.idFactory = deps.idFactory ?? randomUUID28;
23816
+ this.idFactory = deps.idFactory ?? randomUUID27;
23967
23817
  }
23968
23818
  /** Resolves a pending clarify interrupt with no answers. */
23969
23819
  async skip(input) {
@@ -24326,7 +24176,7 @@ async function execute(reply, operation) {
24326
24176
  }
24327
24177
 
24328
24178
  // src/routes/cospace.ts
24329
- import { randomUUID as randomUUID29 } from "crypto";
24179
+ import { randomUUID as randomUUID28 } from "crypto";
24330
24180
  import { ZodError as ZodError6 } from "zod";
24331
24181
  import {
24332
24182
  generateDirectHumanProjectId,
@@ -24360,7 +24210,7 @@ async function computeUnread(deps, tenantId, userId, roomId, lastMessage) {
24360
24210
  });
24361
24211
  }
24362
24212
  function registerCoSpaceRoutes(app2, deps) {
24363
- const idFactory = deps.idFactory ?? (() => randomUUID29());
24213
+ const idFactory = deps.idFactory ?? (() => randomUUID28());
24364
24214
  app2.get(
24365
24215
  "/api/workspaces/:workspaceId/rooms",
24366
24216
  async (request, reply) => {
@@ -25327,7 +25177,7 @@ function exactValues(value, required, optional = []) {
25327
25177
  }
25328
25178
 
25329
25179
  // src/services/collaboration/CoordinatorWakeNotifier.ts
25330
- import { randomUUID as randomUUID30 } from "crypto";
25180
+ import { randomUUID as randomUUID29 } from "crypto";
25331
25181
  import {
25332
25182
  snapshotExactRecord as snapshotExactRecord7
25333
25183
  } from "@axiom-lattice/protocols";
@@ -25343,7 +25193,7 @@ var CoordinatorWakeNotifier = class {
25343
25193
  this.accepted = /* @__PURE__ */ new Set();
25344
25194
  this.maxPending = deps.maxPending ?? 1024;
25345
25195
  if (!Number.isSafeInteger(this.maxPending) || this.maxPending < 1) throw new RangeError("maxPending must be a positive safe integer");
25346
- this.idFactory = deps.idFactory ?? randomUUID30;
25196
+ this.idFactory = deps.idFactory ?? randomUUID29;
25347
25197
  }
25348
25198
  /** Admits one notification without awaiting any store or dispatch operation. */
25349
25199
  handle(value, anchorMessageId) {
@@ -27274,7 +27124,7 @@ function isRecord10(value) {
27274
27124
  import { taskLifecycleNotifier } from "@axiom-lattice/core";
27275
27125
 
27276
27126
  // src/services/collaboration/ProjectRoomEventBroker.ts
27277
- import { randomUUID as randomUUID31 } from "crypto";
27127
+ import { randomUUID as randomUUID30 } from "crypto";
27278
27128
  import {
27279
27129
  parseProjectRoomEventId,
27280
27130
  ProjectRoomBrokerCapacityError,
@@ -27305,7 +27155,7 @@ var ProjectRoomEventBroker = class {
27305
27155
  this.subscriberCount = 0;
27306
27156
  this.usageClock = 0;
27307
27157
  this.closed = false;
27308
- this.epoch = options.epoch ?? randomUUID31();
27158
+ this.epoch = options.epoch ?? randomUUID30();
27309
27159
  if (!UUID_PATTERN.test(this.epoch)) {
27310
27160
  throw new TypeError("Project Room event epoch must be a lowercase canonical UUID");
27311
27161
  }
@@ -28959,6 +28809,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
28959
28809
  const taskWorkItemStore = getStoreLattice28("default", "taskWorkItem").store;
28960
28810
  const projectTaskEnabled = options.projectTaskEnabled ?? process.env.AXIOM_PROJECT_TASK_EXECUTION_ENABLED !== "false";
28961
28811
  const accessService = new ProjectAccessService({ projectStore, membershipStore: projectMembershipStore, userTenantLinkStore });
28812
+ setA2AProjectAccess(accessService);
28962
28813
  const realtimeMode = resolveProjectRoomRealtimeMode();
28963
28814
  const realtimeLog = options.projectTaskLog ?? { warn: () => void 0 };
28964
28815
  const roomMessageRetention = createRoomMessageRetentionJob({
@@ -29139,7 +28990,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
29139
28990
  });
29140
28991
  }
29141
28992
  if (projectTaskComposition) app2.addHook("onClose", async () => projectTaskComposition.lease.release());
29142
- const taskThreadService = projectTaskComposition?.lease.runtime.threads ?? new ProjectTaskThreadService({ threads: threadStore, idFactory: randomUUID32 });
28993
+ const taskThreadService = projectTaskComposition?.lease.runtime.threads ?? new ProjectTaskThreadService({ threads: threadStore, idFactory: randomUUID31 });
29143
28994
  const taskLifecycle = projectTaskComposition?.lease.runtime.lifecycle ?? createTaskLifecycleService({ taskStore, workItemStore: taskWorkItemStore });
29144
28995
  const reassignmentAuthorizer = createProjectTaskReassignmentAuthorizer(
29145
28996
  new ProjectTaskOwnerPolicy(projectBotMembershipStore),
@@ -29320,7 +29171,8 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
29320
29171
  configuredAgentResolver: createConfiguredAgentResolver({
29321
29172
  hydrate: (tenantId) => agentLatticeManager5.initializeStoredAssistantsForTenant(tenantId),
29322
29173
  has: (tenantId, assistantId) => agentLatticeManager5.hasAgentLatticeWithTenant(tenantId, assistantId)
29323
- })
29174
+ }),
29175
+ projectAccess: accessService
29324
29176
  })
29325
29177
  });
29326
29178
  registerAgentWebAppRuntimeRoutes(app2, {
@@ -29330,7 +29182,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
29330
29182
  userTenantLinkStore,
29331
29183
  ensureCoordinator: (scope) => coordinatorEnsurer.ensure(scope),
29332
29184
  log: realtimeLog
29333
- })),
29185
+ }), accessService),
29334
29186
  taskController: createTaskController({
29335
29187
  access: {
29336
29188
  requireProjectAccess: async (input) => {
@@ -29626,7 +29478,7 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
29626
29478
  userTenantLinkStore,
29627
29479
  ensureCoordinator: (scope) => coordinatorEnsurer.ensure(scope),
29628
29480
  log: realtimeLog
29629
- }));
29481
+ }), accessService);
29630
29482
  registerDatabaseConfigRoutes(app2);
29631
29483
  registerMetricsServerConfigRoutes(app2);
29632
29484
  connectionRoutes(app2);
@@ -29824,7 +29676,7 @@ function tryCreateProjectTaskRuntime(input) {
29824
29676
  function createRuntime(input, stores, log2) {
29825
29677
  const controller = new AbortController();
29826
29678
  const mutex = new ProjectTaskExecutionMutex();
29827
- const threads = new ProjectTaskThreadService({ threads: input.threadStore, idFactory: randomUUID32 });
29679
+ const threads = new ProjectTaskThreadService({ threads: input.threadStore, idFactory: randomUUID31 });
29828
29680
  const lifecycle = createTaskLifecycleService({ taskStore: input.taskStore, workItemStore: input.taskWorkItemStore });
29829
29681
  const projection = new RoomProjectionService({
29830
29682
  messages: input.projectRoomMessageStore,
@@ -29833,7 +29685,7 @@ function createRuntime(input, stores, log2) {
29833
29685
  warnings: input.taskWorkItemStore,
29834
29686
  log: log2,
29835
29687
  realtime: input.realtime,
29836
- idFactory: randomUUID32
29688
+ idFactory: randomUUID31
29837
29689
  });
29838
29690
  const runService = new ProjectTaskRunService({
29839
29691
  tasks: input.taskStore,
@@ -30657,7 +30509,7 @@ var collectionRegistration = {
30657
30509
 
30658
30510
  // src/export_registrations/channel-installation.registration.ts
30659
30511
  import { getStoreLattice as getStoreLattice35 } from "@axiom-lattice/core";
30660
- import { randomUUID as randomUUID33 } from "crypto";
30512
+ import { randomUUID as randomUUID32 } from "crypto";
30661
30513
  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
30514
  var PUBLIC_CHANNELS = /* @__PURE__ */ new Set(["lark", "email", "slack", "wechat", "wecom"]);
30663
30515
  function isPublicChannel(channel) {
@@ -30819,7 +30671,7 @@ var channelInstallationRegistration = {
30819
30671
  }
30820
30672
  id3 = sourceId;
30821
30673
  } else {
30822
- id3 = randomUUID33();
30674
+ id3 = randomUUID32();
30823
30675
  }
30824
30676
  await store2.createInstallation(tenantId, id3, createInput);
30825
30677
  return { newId: id3 };
@@ -31379,7 +31231,7 @@ function createAuditLoggerMiddleware() {
31379
31231
  import { setBindingRegistry, setMenuRegistry, setEvalRunService } from "@axiom-lattice/core";
31380
31232
 
31381
31233
  // src/channels/wecom/WecomChannelAdapter.ts
31382
- import { randomUUID as randomUUID34 } from "crypto";
31234
+ import { randomUUID as randomUUID33 } from "crypto";
31383
31235
  import { z as z13 } from "zod";
31384
31236
  import * as WecomAiBot from "@wecom/aibot-node-sdk";
31385
31237
 
@@ -31743,7 +31595,7 @@ function streamIdFor(replyTarget) {
31743
31595
  const key = replyKeyForTarget(replyTarget);
31744
31596
  let streamId = streamIdsByReqId.get(key);
31745
31597
  if (!streamId) {
31746
- streamId = randomUUID34();
31598
+ streamId = randomUUID33();
31747
31599
  streamIdsByReqId.set(key, streamId);
31748
31600
  if (streamIdsByReqId.size > MAX_TRACKED_STREAMS) {
31749
31601
  const oldest = streamIdsByReqId.keys().next().value;
@@ -33038,7 +32890,7 @@ import {
33038
32890
  snapshotExactRecord as snapshotExactRecord15,
33039
32891
  MessageChunkTypes as MessageChunkTypes4
33040
32892
  } from "@axiom-lattice/protocols";
33041
- import { randomUUID as randomUUID35 } from "crypto";
32893
+ import { randomUUID as randomUUID34 } from "crypto";
33042
32894
 
33043
32895
  // src/services/channel-reply/channelReplyRuntimeRegistry.ts
33044
32896
  var active;
@@ -33393,7 +33245,7 @@ var _MessageRouter = class _MessageRouter {
33393
33245
  }
33394
33246
  if (!threadId) {
33395
33247
  const threadStore = getStoreLattice39("default", "thread").store;
33396
- const newThreadId = randomUUID35();
33248
+ const newThreadId = randomUUID34();
33397
33249
  console.log({
33398
33250
  event: "dispatch:thread:create",
33399
33251
  agentId,
@@ -33432,7 +33284,7 @@ var _MessageRouter = class _MessageRouter {
33432
33284
  senderId: message.sender.id,
33433
33285
  contentLength: message.content.text.length
33434
33286
  }, "Dispatching to agent");
33435
- const inputMessageId = randomUUID35();
33287
+ const inputMessageId = randomUUID34();
33436
33288
  const replyTarget = internalRoom ? correlatedRoomReplyTarget(message.replyTarget, inputMessageId) : message.replyTarget;
33437
33289
  const replyAdapter = replyTarget ? this.adapterRegistry.get(replyTarget.adapterChannel) : void 0;
33438
33290
  if (options.trustedMessageOptions && (!this.trustedDispatcher || !replyTarget || !replyAdapter)) {
@@ -33629,7 +33481,7 @@ var _MessageRouter = class _MessageRouter {
33629
33481
  };
33630
33482
  const runLedger = getStoreLattice39("default", "agentRun").store;
33631
33483
  const jobStore = getStoreLattice39("default", "channelReplyJob").store;
33632
- const runId = randomUUID35();
33484
+ const runId = randomUUID34();
33633
33485
  await jobStore.create({
33634
33486
  runId,
33635
33487
  tenantId,
@@ -34281,7 +34133,7 @@ async function prepareProjectTaskRuntime(runtime, log2) {
34281
34133
  import { setPluginDeploymentService } from "@axiom-lattice/core";
34282
34134
 
34283
34135
  // src/services/plugins/PluginDeploymentService.ts
34284
- import { randomUUID as randomUUID36 } from "crypto";
34136
+ import { randomUUID as randomUUID35 } from "crypto";
34285
34137
  import {
34286
34138
  PLUGIN_HOST_DIR,
34287
34139
  PluginDeploymentRuntimeRegistry
@@ -34425,7 +34277,7 @@ var PluginDeploymentService = class {
34425
34277
  const failedAt = this.nowIso();
34426
34278
  await this.store.upsert(
34427
34279
  this.buildRecord({
34428
- id: existing?.id ?? randomUUID36(),
34280
+ id: existing?.id ?? randomUUID35(),
34429
34281
  tenantId,
34430
34282
  pluginType,
34431
34283
  pluginVersion: manifest.version,
@@ -34447,7 +34299,7 @@ var PluginDeploymentService = class {
34447
34299
  );
34448
34300
  }
34449
34301
  const record = this.buildRecord({
34450
- id: existing?.id ?? randomUUID36(),
34302
+ id: existing?.id ?? randomUUID35(),
34451
34303
  tenantId,
34452
34304
  pluginType,
34453
34305
  pluginVersion: manifest.version,
@@ -38639,8 +38491,8 @@ var start = async (config) => {
38639
38491
  });
38640
38492
  try {
38641
38493
  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");
38494
+ const { registerA2AStandardRoutes } = await import("./a2a-standard-MD7WNDTP.mjs");
38495
+ const a2a = await import("./a2a-YLKZE5JG.mjs");
38644
38496
  const a2aKeyStore = getStoreLattice42("default", "a2aApiKey").store;
38645
38497
  const assistantStore = getStoreLattice42("default", "assistant").store;
38646
38498
  const projectStore = getStoreLattice42("default", "project").store;
@@ -38674,7 +38526,7 @@ var start = async (config) => {
38674
38526
  const { registerOpenCatalogRoutes } = await import("./open-catalog-NVGP6SQP.mjs");
38675
38527
  const { registerOpenFilesRoutes } = await import("./open-files-JPB2NBL6.mjs");
38676
38528
  const { registerOpenAuditRoutes } = await import("./open-audit-UJ3NXCGW.mjs");
38677
- const { registerOpenExposureRoutes } = await import("./open-exposure-BPLYUIX6.mjs");
38529
+ const { registerOpenExposureRoutes } = await import("./open-exposure-HGYT5VFC.mjs");
38678
38530
  const { openLattice } = await import("./openLattice-D5YTSZBY.mjs");
38679
38531
  const { createKbProvider } = await import("./kbProvider-2D6DZ34N.mjs");
38680
38532
  const { createOpenSandboxProvider } = await import("./sandboxProvider-FILMFVIM.mjs");