@axiom-lattice/gateway 4.1.5 → 4.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +338 -91
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +337 -90
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
package/dist/index.mjs
CHANGED
|
@@ -32,7 +32,7 @@ import staticPlugin from "@fastify/static";
|
|
|
32
32
|
import path3 from "path";
|
|
33
33
|
|
|
34
34
|
// src/routes/index.ts
|
|
35
|
-
import { randomUUID as
|
|
35
|
+
import { randomUUID as randomUUID19 } from "crypto";
|
|
36
36
|
import {
|
|
37
37
|
descriptorDataValue as descriptorDataValue3,
|
|
38
38
|
snapshotExactRecord as snapshotExactRecord13,
|
|
@@ -5221,6 +5221,113 @@ import { getStoreLattice as getStoreLattice6 } from "@axiom-lattice/core";
|
|
|
5221
5221
|
import { SandboxFilesystem, FilesystemBackend } from "@axiom-lattice/core";
|
|
5222
5222
|
import { getSandBoxManager as getSandBoxManager3 } from "@axiom-lattice/core";
|
|
5223
5223
|
import { v4 as uuidv42 } from "uuid";
|
|
5224
|
+
|
|
5225
|
+
// src/services/collaboration/RoomCoordinatorProvisioner.ts
|
|
5226
|
+
var ROOM_COORDINATOR_KEY = "room-coordinator";
|
|
5227
|
+
var RoomCoordinatorProvisioner = class {
|
|
5228
|
+
/** Creates a provisioner over the tenant-scoped assistant store operations. */
|
|
5229
|
+
constructor(deps) {
|
|
5230
|
+
this.deps = deps;
|
|
5231
|
+
}
|
|
5232
|
+
/**
|
|
5233
|
+
* Ensures the Room Coordinator assistant exists, reusing an existing record
|
|
5234
|
+
* and reconciling concurrent create races by rereading the winner.
|
|
5235
|
+
*
|
|
5236
|
+
* @param tenantId Tenant to provision the coordinator for.
|
|
5237
|
+
* @returns The persisted Room Coordinator assistant.
|
|
5238
|
+
*/
|
|
5239
|
+
async ensure(tenantId) {
|
|
5240
|
+
const existing = await this.deps.getAssistantById(tenantId, ROOM_COORDINATOR_KEY);
|
|
5241
|
+
if (existing) return existing;
|
|
5242
|
+
try {
|
|
5243
|
+
return await this.deps.createAssistant(tenantId, ROOM_COORDINATOR_KEY, {
|
|
5244
|
+
name: "Room Coordinator",
|
|
5245
|
+
description: "Coordinates project room conversations and organizes room work.",
|
|
5246
|
+
graphDefinition: {}
|
|
5247
|
+
});
|
|
5248
|
+
} catch (error) {
|
|
5249
|
+
const winner = await this.deps.getAssistantById(tenantId, ROOM_COORDINATOR_KEY);
|
|
5250
|
+
if (winner) return winner;
|
|
5251
|
+
throw error;
|
|
5252
|
+
}
|
|
5253
|
+
}
|
|
5254
|
+
};
|
|
5255
|
+
|
|
5256
|
+
// src/services/collaboration/WorkspacePublicRoomService.ts
|
|
5257
|
+
import { createHash } from "crypto";
|
|
5258
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
5259
|
+
var WORKSPACE_PUBLIC_ROOM_PROJECT_PREFIX = "workspace_public_";
|
|
5260
|
+
var PUBLIC_ROOM_PROJECT_NAME = "General";
|
|
5261
|
+
var PUBLIC_ROOM_PROJECT_DESCRIPTION = "Public room for everyone in the workspace";
|
|
5262
|
+
function workspacePublicRoomProjectId(tenantId, workspaceId) {
|
|
5263
|
+
const hash = createHash("sha256").update([tenantId, workspaceId].join(":")).digest("hex");
|
|
5264
|
+
return `${WORKSPACE_PUBLIC_ROOM_PROJECT_PREFIX}${hash}`;
|
|
5265
|
+
}
|
|
5266
|
+
var WorkspacePublicRoomService = class {
|
|
5267
|
+
/** Creates the service from explicitly injected stores and provisioners. */
|
|
5268
|
+
constructor(deps) {
|
|
5269
|
+
this.deps = deps;
|
|
5270
|
+
this.idFactory = deps.idFactory ?? randomUUID5;
|
|
5271
|
+
}
|
|
5272
|
+
/**
|
|
5273
|
+
* Returns the workspace's public room project and room, creating them on first call.
|
|
5274
|
+
*
|
|
5275
|
+
* @param tenantId Tenant owning the workspace.
|
|
5276
|
+
* @param workspaceId Workspace hosting the public room.
|
|
5277
|
+
* @returns The ensured project and room.
|
|
5278
|
+
*/
|
|
5279
|
+
async ensure(tenantId, workspaceId) {
|
|
5280
|
+
const projectId = workspacePublicRoomProjectId(tenantId, workspaceId);
|
|
5281
|
+
const project = await this.ensureProject(tenantId, workspaceId, projectId);
|
|
5282
|
+
const room = await this.deps.ensureMainRoom({
|
|
5283
|
+
id: this.idFactory(),
|
|
5284
|
+
tenantId,
|
|
5285
|
+
workspaceId,
|
|
5286
|
+
projectId,
|
|
5287
|
+
name: project.name
|
|
5288
|
+
});
|
|
5289
|
+
await this.ensureCoordinatorBot(tenantId, workspaceId, projectId, room.id);
|
|
5290
|
+
return { project, room };
|
|
5291
|
+
}
|
|
5292
|
+
async ensureProject(tenantId, workspaceId, projectId) {
|
|
5293
|
+
const existing = await this.deps.getProjectById(tenantId, projectId);
|
|
5294
|
+
if (existing && existing.kind === "public") return existing;
|
|
5295
|
+
try {
|
|
5296
|
+
return await this.deps.createProject(tenantId, workspaceId, projectId, {
|
|
5297
|
+
name: PUBLIC_ROOM_PROJECT_NAME,
|
|
5298
|
+
description: PUBLIC_ROOM_PROJECT_DESCRIPTION,
|
|
5299
|
+
kind: "public"
|
|
5300
|
+
});
|
|
5301
|
+
} catch (error) {
|
|
5302
|
+
const winner = await this.deps.getProjectById(tenantId, projectId);
|
|
5303
|
+
if (winner && winner.kind === "public") return winner;
|
|
5304
|
+
throw Object.assign(new Error("Workspace public room project could not be ensured"), { cause: error });
|
|
5305
|
+
}
|
|
5306
|
+
}
|
|
5307
|
+
async ensureCoordinatorBot(tenantId, workspaceId, projectId, roomId) {
|
|
5308
|
+
const coordinator = await this.deps.ensureCoordinator(tenantId);
|
|
5309
|
+
const existing = await this.deps.findBotByAssistant(tenantId, projectId, coordinator.id);
|
|
5310
|
+
if (existing && existing.status !== "removed") return;
|
|
5311
|
+
const saved = await this.deps.saveBot({
|
|
5312
|
+
id: this.idFactory(),
|
|
5313
|
+
tenantId,
|
|
5314
|
+
workspaceId,
|
|
5315
|
+
projectId,
|
|
5316
|
+
roomId,
|
|
5317
|
+
assistantId: coordinator.id,
|
|
5318
|
+
role: "coordinator",
|
|
5319
|
+
title: coordinator.name,
|
|
5320
|
+
mentionName: ROOM_COORDINATOR_KEY,
|
|
5321
|
+
status: "active",
|
|
5322
|
+
roomThreadId: this.idFactory()
|
|
5323
|
+
});
|
|
5324
|
+
if (saved.kind === "coordinator_conflict" || saved.kind === "mention_conflict") {
|
|
5325
|
+
throw new Error(`Workspace public room coordinator bot could not be ensured: ${saved.kind}`);
|
|
5326
|
+
}
|
|
5327
|
+
}
|
|
5328
|
+
};
|
|
5329
|
+
|
|
5330
|
+
// src/controllers/workspace.ts
|
|
5224
5331
|
var MAX_ZIP_ENTRIES = 1e4;
|
|
5225
5332
|
var MAX_ZIP_FILE_SIZE = 100 * 1024 * 1024;
|
|
5226
5333
|
var MAX_ZIP_TOTAL_SIZE = 512 * 1024 * 1024;
|
|
@@ -5355,6 +5462,21 @@ var WorkspaceController = class {
|
|
|
5355
5462
|
this.projectCollaboration = projectCollaboration;
|
|
5356
5463
|
this.workspaceStore = getStoreLattice6("default", "workspace").store;
|
|
5357
5464
|
this.projectStore = getStoreLattice6("default", "project").store;
|
|
5465
|
+
const roomStore = getStoreLattice6("default", "projectRoom").store;
|
|
5466
|
+
const botMembershipStore = getStoreLattice6("default", "projectBotMembership").store;
|
|
5467
|
+
const assistantStore = getStoreLattice6("default", "assistant").store;
|
|
5468
|
+
const coordinatorProvisioner = new RoomCoordinatorProvisioner({
|
|
5469
|
+
getAssistantById: assistantStore.getAssistantById.bind(assistantStore),
|
|
5470
|
+
createAssistant: assistantStore.createAssistant.bind(assistantStore)
|
|
5471
|
+
});
|
|
5472
|
+
this.publicRoom = new WorkspacePublicRoomService({
|
|
5473
|
+
getProjectById: this.projectStore.getProjectById.bind(this.projectStore),
|
|
5474
|
+
createProject: this.projectStore.createProject.bind(this.projectStore),
|
|
5475
|
+
ensureMainRoom: roomStore.ensureMainRoom.bind(roomStore),
|
|
5476
|
+
findBotByAssistant: botMembershipStore.findByAssistant.bind(botMembershipStore),
|
|
5477
|
+
saveBot: botMembershipStore.save.bind(botMembershipStore),
|
|
5478
|
+
ensureCoordinator: (tenantId) => coordinatorProvisioner.ensure(tenantId)
|
|
5479
|
+
});
|
|
5358
5480
|
}
|
|
5359
5481
|
getTenantId(request) {
|
|
5360
5482
|
const userTenantId = request.user?.tenantId;
|
|
@@ -5428,6 +5550,7 @@ var WorkspaceController = class {
|
|
|
5428
5550
|
const { workspaceId } = request.params;
|
|
5429
5551
|
const kindFilter = request.query.kind;
|
|
5430
5552
|
await this.ensureTrainingProject(tenantId, workspaceId);
|
|
5553
|
+
await this.publicRoom.ensure(tenantId, workspaceId);
|
|
5431
5554
|
const projects = kindFilter ? await this.projectStore.getProjectsByWorkspace(tenantId, workspaceId, {
|
|
5432
5555
|
kind: kindFilter
|
|
5433
5556
|
}) : await this.projectStore.getProjectsByWorkspace(tenantId, workspaceId);
|
|
@@ -5471,6 +5594,12 @@ var WorkspaceController = class {
|
|
|
5471
5594
|
message: CAPABILITY_BUNDLE_CONFIG_MESSAGE
|
|
5472
5595
|
});
|
|
5473
5596
|
}
|
|
5597
|
+
if (data.kind === "public") {
|
|
5598
|
+
return reply.status(409).send({
|
|
5599
|
+
success: false,
|
|
5600
|
+
error: "The public room project is managed automatically"
|
|
5601
|
+
});
|
|
5602
|
+
}
|
|
5474
5603
|
if (user?.id && this.projectCollaboration) {
|
|
5475
5604
|
try {
|
|
5476
5605
|
const authorized = await this.projectCollaboration.authorizeCreator({ tenantId, userId: user.id });
|
|
@@ -5546,6 +5675,21 @@ var WorkspaceController = class {
|
|
|
5546
5675
|
message: CAPABILITY_BUNDLE_CONFIG_MESSAGE
|
|
5547
5676
|
});
|
|
5548
5677
|
}
|
|
5678
|
+
if (updates.kind !== void 0) {
|
|
5679
|
+
const existingProject = await this.projectStore.getProjectById(tenantId, projectId);
|
|
5680
|
+
if (existingProject && updates.kind === "public") {
|
|
5681
|
+
return reply.status(409).send({
|
|
5682
|
+
success: false,
|
|
5683
|
+
error: "kind public is reserved for the workspace public room"
|
|
5684
|
+
});
|
|
5685
|
+
}
|
|
5686
|
+
if (existingProject?.kind === "public") {
|
|
5687
|
+
return reply.status(409).send({
|
|
5688
|
+
success: false,
|
|
5689
|
+
error: "The public room project classification cannot be changed"
|
|
5690
|
+
});
|
|
5691
|
+
}
|
|
5692
|
+
}
|
|
5549
5693
|
const project = await this.projectStore.updateProject(
|
|
5550
5694
|
tenantId,
|
|
5551
5695
|
projectId,
|
|
@@ -5576,6 +5720,12 @@ var WorkspaceController = class {
|
|
|
5576
5720
|
});
|
|
5577
5721
|
}
|
|
5578
5722
|
}
|
|
5723
|
+
if (project.kind === "public") {
|
|
5724
|
+
return reply.status(409).send({
|
|
5725
|
+
success: false,
|
|
5726
|
+
error: "The public room project cannot be deleted"
|
|
5727
|
+
});
|
|
5728
|
+
}
|
|
5579
5729
|
const deleted = await this.projectStore.deleteProject(tenantId, projectId);
|
|
5580
5730
|
if (!deleted) {
|
|
5581
5731
|
return reply.status(404).send({ success: false, error: "Project not found" });
|
|
@@ -6281,7 +6431,7 @@ import {
|
|
|
6281
6431
|
getStoreLattice as getStoreLattice7,
|
|
6282
6432
|
sqlDatabaseManager
|
|
6283
6433
|
} from "@axiom-lattice/core";
|
|
6284
|
-
import { randomUUID as
|
|
6434
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
6285
6435
|
function getTenantId9(request) {
|
|
6286
6436
|
const userTenantId = request.user?.tenantId;
|
|
6287
6437
|
if (userTenantId) {
|
|
@@ -6359,7 +6509,7 @@ async function createDatabaseConfig(request, reply) {
|
|
|
6359
6509
|
message: "Database configuration with this key already exists"
|
|
6360
6510
|
};
|
|
6361
6511
|
}
|
|
6362
|
-
const id3 = body.id ||
|
|
6512
|
+
const id3 = body.id || randomUUID6();
|
|
6363
6513
|
const config = await store.createConfig(tenantId, id3, body);
|
|
6364
6514
|
try {
|
|
6365
6515
|
sqlDatabaseManager.registerDatabase(tenantId, config.key, config.config);
|
|
@@ -6564,7 +6714,7 @@ import {
|
|
|
6564
6714
|
metricsServerManager as metricsServerManager2,
|
|
6565
6715
|
SemanticMetricsClient as SemanticMetricsClient2
|
|
6566
6716
|
} from "@axiom-lattice/core";
|
|
6567
|
-
import { randomUUID as
|
|
6717
|
+
import { randomUUID as randomUUID7 } from "crypto";
|
|
6568
6718
|
function getTenantId10(request) {
|
|
6569
6719
|
const userTenantId = request.user?.tenantId;
|
|
6570
6720
|
if (userTenantId) {
|
|
@@ -6645,7 +6795,7 @@ async function createMetricsServerConfig(request, reply) {
|
|
|
6645
6795
|
message: "selectedDataSources is required for semantic metrics servers"
|
|
6646
6796
|
};
|
|
6647
6797
|
}
|
|
6648
|
-
const id3 = body.id ||
|
|
6798
|
+
const id3 = body.id || randomUUID7();
|
|
6649
6799
|
const configData = {
|
|
6650
6800
|
key: body.key,
|
|
6651
6801
|
name: body.name,
|
|
@@ -9152,7 +9302,7 @@ function registerChannelRoutes(app2, dependencies) {
|
|
|
9152
9302
|
}
|
|
9153
9303
|
|
|
9154
9304
|
// src/controllers/channel-installations.ts
|
|
9155
|
-
import { randomUUID as
|
|
9305
|
+
import { randomUUID as randomUUID8 } from "crypto";
|
|
9156
9306
|
import {
|
|
9157
9307
|
descriptorDataValue
|
|
9158
9308
|
} from "@axiom-lattice/protocols";
|
|
@@ -9356,7 +9506,7 @@ async function createChannelInstallation(request, reply) {
|
|
|
9356
9506
|
};
|
|
9357
9507
|
}
|
|
9358
9508
|
const store = await getInstallationStore();
|
|
9359
|
-
const installationId =
|
|
9509
|
+
const installationId = randomUUID8();
|
|
9360
9510
|
const createInput = {
|
|
9361
9511
|
channel: body.channel,
|
|
9362
9512
|
name: body.name,
|
|
@@ -10316,7 +10466,7 @@ async function getLocalA2ATemplates(_request, reply) {
|
|
|
10316
10466
|
}
|
|
10317
10467
|
|
|
10318
10468
|
// src/routes/a2a-test-connection.ts
|
|
10319
|
-
import { randomUUID as
|
|
10469
|
+
import { randomUUID as randomUUID9 } from "crypto";
|
|
10320
10470
|
function describeTestConnectionError(error, agentCardUrl) {
|
|
10321
10471
|
if (!(error instanceof Error)) {
|
|
10322
10472
|
return `Failed to fetch agent card from ${agentCardUrl}: ${String(error)}`;
|
|
@@ -10356,7 +10506,7 @@ async function ensureLocalRuntimeForConnectionTest(localRuntime, agentCardUrl) {
|
|
|
10356
10506
|
return { error: portValidation.error };
|
|
10357
10507
|
}
|
|
10358
10508
|
const state = await localA2AService.startProvider(
|
|
10359
|
-
`test-${
|
|
10509
|
+
`test-${randomUUID9()}`,
|
|
10360
10510
|
testRuntime
|
|
10361
10511
|
);
|
|
10362
10512
|
if (state.status === "running") return { runtimeId: state.runtimeId };
|
|
@@ -10446,7 +10596,7 @@ import { snapshotExactRecord as snapshotExactRecord3 } from "@axiom-lattice/prot
|
|
|
10446
10596
|
import { ProjectTaskOwnerPolicyError, projectTaskAdmissionNotifier } from "@axiom-lattice/core";
|
|
10447
10597
|
|
|
10448
10598
|
// src/services/collaboration/ProjectAccessService.ts
|
|
10449
|
-
import { randomUUID as
|
|
10599
|
+
import { randomUUID as randomUUID10 } from "crypto";
|
|
10450
10600
|
var ProjectCollaborationError = class extends Error {
|
|
10451
10601
|
/** Creates a project collaboration error. */
|
|
10452
10602
|
constructor(code, statusCode, message) {
|
|
@@ -10472,7 +10622,7 @@ var ProjectAccessService = class {
|
|
|
10472
10622
|
/** Creates a project access service from explicitly injected stores. */
|
|
10473
10623
|
constructor(deps) {
|
|
10474
10624
|
this.deps = deps;
|
|
10475
|
-
this.idFactory = deps.idFactory ??
|
|
10625
|
+
this.idFactory = deps.idFactory ?? randomUUID10;
|
|
10476
10626
|
}
|
|
10477
10627
|
/** Returns the project and active membership when the user has the requested capability. */
|
|
10478
10628
|
async requireProjectAccess(input) {
|
|
@@ -10480,6 +10630,9 @@ var ProjectAccessService = class {
|
|
|
10480
10630
|
if (!project) {
|
|
10481
10631
|
throw new ProjectCollaborationError("PROJECT_NOT_FOUND", 404, "Project not found");
|
|
10482
10632
|
}
|
|
10633
|
+
if (project.kind === "public") {
|
|
10634
|
+
return this.requirePublicProjectAccess(project, input);
|
|
10635
|
+
}
|
|
10483
10636
|
const membership = await this.deps.membershipStore.findByUser(
|
|
10484
10637
|
input.tenantId,
|
|
10485
10638
|
input.projectId,
|
|
@@ -10524,10 +10677,13 @@ var ProjectAccessService = class {
|
|
|
10524
10677
|
this.requireCapability(racedMembership, input.capability);
|
|
10525
10678
|
return { project, membership: racedMembership };
|
|
10526
10679
|
}
|
|
10527
|
-
/** Authorizes
|
|
10680
|
+
/** Authorizes an already-existing membership, or any tenant member for public rooms; never mutates persistence. */
|
|
10528
10681
|
async requireExistingProjectAccess(input) {
|
|
10529
10682
|
const project = await this.deps.projectStore.getProjectById(input.tenantId, input.projectId);
|
|
10530
10683
|
if (!project) throw new ProjectCollaborationError("PROJECT_NOT_FOUND", 404, "Project not found");
|
|
10684
|
+
if (project.kind === "public") {
|
|
10685
|
+
return this.requireExistingPublicProjectAccess(project, input);
|
|
10686
|
+
}
|
|
10531
10687
|
const membership = await this.deps.membershipStore.findByUser(
|
|
10532
10688
|
input.tenantId,
|
|
10533
10689
|
input.projectId,
|
|
@@ -10537,6 +10693,87 @@ var ProjectAccessService = class {
|
|
|
10537
10693
|
this.requireCapability(membership, input.capability);
|
|
10538
10694
|
return { project, membership };
|
|
10539
10695
|
}
|
|
10696
|
+
/** Authorizes roster visibility: read for public rooms, manage elsewhere. */
|
|
10697
|
+
async requireRosterAccess(input) {
|
|
10698
|
+
const project = await this.deps.projectStore.getProjectById(input.tenantId, input.projectId);
|
|
10699
|
+
if (!project) throw new ProjectCollaborationError("PROJECT_NOT_FOUND", 404, "Project not found");
|
|
10700
|
+
return this.requireProjectAccess({
|
|
10701
|
+
...input,
|
|
10702
|
+
capability: project.kind === "public" ? "read" : "manage"
|
|
10703
|
+
});
|
|
10704
|
+
}
|
|
10705
|
+
async requirePublicProjectAccess(project, input) {
|
|
10706
|
+
const membership = await this.deps.membershipStore.findByUser(
|
|
10707
|
+
input.tenantId,
|
|
10708
|
+
input.projectId,
|
|
10709
|
+
input.userId
|
|
10710
|
+
);
|
|
10711
|
+
if (membership?.status === "active") {
|
|
10712
|
+
this.requireCapability(membership, input.capability);
|
|
10713
|
+
return { project, membership };
|
|
10714
|
+
}
|
|
10715
|
+
const materialized = await this.materializePublicMembership(input);
|
|
10716
|
+
this.requireCapability(materialized, input.capability);
|
|
10717
|
+
return { project, membership: materialized };
|
|
10718
|
+
}
|
|
10719
|
+
async requireExistingPublicProjectAccess(project, input) {
|
|
10720
|
+
const membership = await this.deps.membershipStore.findByUser(
|
|
10721
|
+
input.tenantId,
|
|
10722
|
+
input.projectId,
|
|
10723
|
+
input.userId
|
|
10724
|
+
);
|
|
10725
|
+
if (membership?.status === "active") {
|
|
10726
|
+
this.requireCapability(membership, input.capability);
|
|
10727
|
+
return { project, membership };
|
|
10728
|
+
}
|
|
10729
|
+
if (membership) this.accessDenied();
|
|
10730
|
+
const tenantLink = await this.deps.userTenantLinkStore.getLink(input.userId, input.tenantId);
|
|
10731
|
+
if (!tenantLink) this.accessDenied();
|
|
10732
|
+
const role = tenantLink.role === "owner" || tenantLink.role === "admin" ? "admin" : "member";
|
|
10733
|
+
const synthetic = {
|
|
10734
|
+
id: `public:${input.userId}`,
|
|
10735
|
+
tenantId: input.tenantId,
|
|
10736
|
+
projectId: input.projectId,
|
|
10737
|
+
userId: input.userId,
|
|
10738
|
+
role,
|
|
10739
|
+
status: "active",
|
|
10740
|
+
joinedAt: project.createdAt,
|
|
10741
|
+
updatedAt: project.updatedAt
|
|
10742
|
+
};
|
|
10743
|
+
this.requireCapability(synthetic, input.capability);
|
|
10744
|
+
return { project, membership: synthetic };
|
|
10745
|
+
}
|
|
10746
|
+
async materializePublicMembership(input) {
|
|
10747
|
+
const tenantLink = await this.deps.userTenantLinkStore.getLink(input.userId, input.tenantId);
|
|
10748
|
+
if (!tenantLink) this.accessDenied();
|
|
10749
|
+
const existing = await this.deps.membershipStore.findByUser(
|
|
10750
|
+
input.tenantId,
|
|
10751
|
+
input.projectId,
|
|
10752
|
+
input.userId
|
|
10753
|
+
);
|
|
10754
|
+
if (existing) this.accessDenied();
|
|
10755
|
+
const role = tenantLink.role === "owner" || tenantLink.role === "admin" ? "admin" : "member";
|
|
10756
|
+
try {
|
|
10757
|
+
return await this.deps.membershipStore.create({
|
|
10758
|
+
id: this.idFactory(),
|
|
10759
|
+
tenantId: input.tenantId,
|
|
10760
|
+
projectId: input.projectId,
|
|
10761
|
+
userId: input.userId,
|
|
10762
|
+
role,
|
|
10763
|
+
status: "active"
|
|
10764
|
+
});
|
|
10765
|
+
} catch (error) {
|
|
10766
|
+
if (isProjectMembershipConflict(error)) {
|
|
10767
|
+
const raced = await this.deps.membershipStore.findByUser(
|
|
10768
|
+
input.tenantId,
|
|
10769
|
+
input.projectId,
|
|
10770
|
+
input.userId
|
|
10771
|
+
);
|
|
10772
|
+
if (raced?.status === "active") return raced;
|
|
10773
|
+
}
|
|
10774
|
+
throw error;
|
|
10775
|
+
}
|
|
10776
|
+
}
|
|
10540
10777
|
requireCapability(membership, capability2) {
|
|
10541
10778
|
if (!allowedRoles[capability2].has(membership.role)) this.accessDenied();
|
|
10542
10779
|
}
|
|
@@ -11759,7 +11996,7 @@ function invalidRequest(reply, statusCode) {
|
|
|
11759
11996
|
import { z as z5, ZodError as ZodError2 } from "zod";
|
|
11760
11997
|
|
|
11761
11998
|
// src/services/agent-web-app/AgentWebAppRuntimeService.ts
|
|
11762
|
-
import { createHash, randomUUID as
|
|
11999
|
+
import { createHash as createHash2, randomUUID as randomUUID11 } from "crypto";
|
|
11763
12000
|
import { MessageChunkTypes as MessageChunkTypes3, parseAgentWebAppGenUIBlock } from "@axiom-lattice/protocols";
|
|
11764
12001
|
function isRecord2(value) {
|
|
11765
12002
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -11882,10 +12119,10 @@ ${formatFileRefsSection(refs)}` : input.content;
|
|
|
11882
12119
|
const runtime = await this.resolveOwnedRuntime(webAppId, userId, threadId, selection);
|
|
11883
12120
|
this.requireNamedFeature(runtime.webApp.features.attachments, "Attachments are disabled");
|
|
11884
12121
|
if (!this.deps.saveProjectFile || !this.deps.attachmentRefs) this.fail("INTERNAL_ERROR", 500, "Attachment service is unavailable");
|
|
11885
|
-
const userDigest =
|
|
11886
|
-
const contentDigest =
|
|
12122
|
+
const userDigest = createHash2("sha256").update(userId, "utf8").digest("hex");
|
|
12123
|
+
const contentDigest = createHash2("sha256").update(file.bytes).digest("hex");
|
|
11887
12124
|
const displayName = file.name;
|
|
11888
|
-
const physicalName = `${
|
|
12125
|
+
const physicalName = `${randomUUID11()}-${sanitizePhysicalFilename(file.name)}`;
|
|
11889
12126
|
const saved = await this.deps.saveProjectFile({
|
|
11890
12127
|
tenantId: runtime.webApp.tenantId,
|
|
11891
12128
|
workspaceId: runtime.project.workspaceId,
|
|
@@ -12037,7 +12274,7 @@ ${formatFileRefsSection(refs)}` : input.content;
|
|
|
12037
12274
|
const thread = await this.deps.threadStore.createThread(
|
|
12038
12275
|
runtime.webApp.tenantId,
|
|
12039
12276
|
runtime.webApp.assistantId,
|
|
12040
|
-
|
|
12277
|
+
randomUUID11(),
|
|
12041
12278
|
{ metadata: this.metadata(runtime, userId, normalizeLabel(rawLabel)) }
|
|
12042
12279
|
);
|
|
12043
12280
|
return toRuntimeThread(thread);
|
|
@@ -12089,7 +12326,7 @@ function implicitThreadId(runtime, userId) {
|
|
|
12089
12326
|
userId,
|
|
12090
12327
|
runtime.project.id
|
|
12091
12328
|
]);
|
|
12092
|
-
const bytes =
|
|
12329
|
+
const bytes = createHash2("sha256").update(canonicalTuple, "utf8").digest().subarray(0, 16);
|
|
12093
12330
|
bytes[6] = bytes[6] & 15 | 128;
|
|
12094
12331
|
bytes[8] = bytes[8] & 63 | 128;
|
|
12095
12332
|
const hex = bytes.toString("hex");
|
|
@@ -12357,7 +12594,7 @@ function isMultipartRequestError(error) {
|
|
|
12357
12594
|
}
|
|
12358
12595
|
|
|
12359
12596
|
// src/services/agent-web-app/AgentWebAppAttachmentRef.ts
|
|
12360
|
-
import { createCipheriv, createDecipheriv, createHash as
|
|
12597
|
+
import { createCipheriv, createDecipheriv, createHash as createHash3, randomBytes as randomBytes2 } from "crypto";
|
|
12361
12598
|
var TTL_MS = 15 * 6e4;
|
|
12362
12599
|
function resolveAgentWebAppAttachmentSecret(consoleSecret) {
|
|
12363
12600
|
return process.env.WEB_APP_ATTACHMENT_SECRET || process.env.AUTH_TOKEN_SECRET || process.env.JWT_SECRET || consoleSecret;
|
|
@@ -12366,7 +12603,7 @@ var AgentWebAppAttachmentRefService = class {
|
|
|
12366
12603
|
constructor(secret, now = Date.now) {
|
|
12367
12604
|
this.now = now;
|
|
12368
12605
|
if (!secret) throw new Error("Attachment signing secret is required");
|
|
12369
|
-
this.key =
|
|
12606
|
+
this.key = createHash3("sha256").update(secret, "utf8").digest();
|
|
12370
12607
|
}
|
|
12371
12608
|
sign(input) {
|
|
12372
12609
|
const payload = {
|
|
@@ -12428,7 +12665,7 @@ function decodeCanonical(value, expectedBytes) {
|
|
|
12428
12665
|
return decoded;
|
|
12429
12666
|
}
|
|
12430
12667
|
function digestUser(userId) {
|
|
12431
|
-
return
|
|
12668
|
+
return createHash3("sha256").update(userId, "utf8").digest("hex");
|
|
12432
12669
|
}
|
|
12433
12670
|
function isAttachmentPayload(value) {
|
|
12434
12671
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
|
|
@@ -12788,12 +13025,12 @@ function registerCapabilityBundleRoutes(app2, controller) {
|
|
|
12788
13025
|
}
|
|
12789
13026
|
|
|
12790
13027
|
// src/services/collaboration/ProjectRoomService.ts
|
|
12791
|
-
import { randomUUID as
|
|
13028
|
+
import { randomUUID as randomUUID12 } from "crypto";
|
|
12792
13029
|
var ProjectRoomService = class {
|
|
12793
13030
|
/** Creates a project room service from explicitly injected collaborators. */
|
|
12794
13031
|
constructor(deps) {
|
|
12795
13032
|
this.deps = deps;
|
|
12796
|
-
this.idFactory = deps.idFactory ??
|
|
13033
|
+
this.idFactory = deps.idFactory ?? randomUUID12;
|
|
12797
13034
|
}
|
|
12798
13035
|
/** Authorizes read access and atomically ensures the project's main room. */
|
|
12799
13036
|
async ensureMainRoom(input) {
|
|
@@ -12812,7 +13049,7 @@ var ProjectRoomService = class {
|
|
|
12812
13049
|
};
|
|
12813
13050
|
|
|
12814
13051
|
// src/services/collaboration/ProjectMembershipService.ts
|
|
12815
|
-
import { randomUUID as
|
|
13052
|
+
import { randomUUID as randomUUID13 } from "crypto";
|
|
12816
13053
|
var ProjectMembershipServiceError = class extends Error {
|
|
12817
13054
|
constructor(code, statusCode, message) {
|
|
12818
13055
|
super(message);
|
|
@@ -12828,11 +13065,13 @@ function isMembershipConflict(error) {
|
|
|
12828
13065
|
var ProjectMembershipService = class {
|
|
12829
13066
|
constructor(deps) {
|
|
12830
13067
|
this.deps = deps;
|
|
12831
|
-
this.idFactory = deps.idFactory ??
|
|
13068
|
+
this.idFactory = deps.idFactory ?? randomUUID13;
|
|
12832
13069
|
this.mutationMutex = deps.projectMutationMutex ?? projectMutationMutex;
|
|
12833
13070
|
}
|
|
12834
13071
|
async list(actor2) {
|
|
12835
|
-
await this.
|
|
13072
|
+
await this.deps.accessService.requireRosterAccess(actor2);
|
|
13073
|
+
const membership = await this.deps.membershipStore.findByUser(actor2.tenantId, actor2.projectId, actor2.userId);
|
|
13074
|
+
if (!membership || membership.status !== "active") this.accessDenied();
|
|
12836
13075
|
return this.deps.membershipStore.list(actor2.tenantId, actor2.projectId);
|
|
12837
13076
|
}
|
|
12838
13077
|
async add(actor2, input) {
|
|
@@ -12952,7 +13191,7 @@ var ProjectMembershipService = class {
|
|
|
12952
13191
|
};
|
|
12953
13192
|
|
|
12954
13193
|
// src/services/collaboration/ProjectRosterService.ts
|
|
12955
|
-
import { randomUUID as
|
|
13194
|
+
import { randomUUID as randomUUID14 } from "crypto";
|
|
12956
13195
|
var ProjectRosterServiceError = class extends Error {
|
|
12957
13196
|
/** Creates a stable roster service error. */
|
|
12958
13197
|
constructor(code, statusCode, message) {
|
|
@@ -12969,7 +13208,7 @@ var ProjectRosterService = class {
|
|
|
12969
13208
|
/** Creates a roster service from explicitly injected collaborators. */
|
|
12970
13209
|
constructor(deps) {
|
|
12971
13210
|
this.deps = deps;
|
|
12972
|
-
this.idFactory = deps.idFactory ??
|
|
13211
|
+
this.idFactory = deps.idFactory ?? randomUUID14;
|
|
12973
13212
|
this.mutationMutex = deps.projectMutationMutex ?? projectMutationMutex;
|
|
12974
13213
|
}
|
|
12975
13214
|
/** Lists all bot memberships visible to a project reader. */
|
|
@@ -13189,7 +13428,7 @@ var ProjectRosterService = class {
|
|
|
13189
13428
|
};
|
|
13190
13429
|
|
|
13191
13430
|
// src/services/collaboration/RoomMessageService.ts
|
|
13192
|
-
import { createHash as
|
|
13431
|
+
import { createHash as createHash4, randomUUID as randomUUID15 } from "crypto";
|
|
13193
13432
|
|
|
13194
13433
|
// src/services/collaboration/ProjectBotMembershipSnapshot.ts
|
|
13195
13434
|
import { snapshotExactRecord as snapshotExactRecord4 } from "@axiom-lattice/protocols";
|
|
@@ -13278,7 +13517,7 @@ var RoomMessageService = class {
|
|
|
13278
13517
|
constructor(deps, options = {}) {
|
|
13279
13518
|
this.deps = deps;
|
|
13280
13519
|
this.idempotentOutcomes = /* @__PURE__ */ new Map();
|
|
13281
|
-
this.idFactory = deps.idFactory ??
|
|
13520
|
+
this.idFactory = deps.idFactory ?? randomUUID15;
|
|
13282
13521
|
const limit = options.idempotentOutcomeLimit ?? 1e3;
|
|
13283
13522
|
if (!Number.isSafeInteger(limit) || limit < 1) throw new RangeError("idempotentOutcomeLimit must be a positive safe integer");
|
|
13284
13523
|
this.idempotentOutcomeLimit = limit;
|
|
@@ -13459,7 +13698,7 @@ var RoomMessageService = class {
|
|
|
13459
13698
|
let idempotencyKey;
|
|
13460
13699
|
if (value.requestIdempotencyKey !== void 0) {
|
|
13461
13700
|
if (typeof value.requestIdempotencyKey !== "string" || !/^[\x21-\x7e]{1,200}$/.test(value.requestIdempotencyKey.trim())) throw new RoomMessageServiceError("INVALID_MESSAGE", 400, "Invalid idempotency key");
|
|
13462
|
-
idempotencyKey = `room-human:${actor2.userId}:${
|
|
13701
|
+
idempotencyKey = `room-human:${actor2.userId}:${createHash4("sha256").update(value.requestIdempotencyKey.trim(), "utf8").digest("hex")}`;
|
|
13463
13702
|
}
|
|
13464
13703
|
return { text, mentions, botIds, ...value.replyToMessageId === void 0 ? {} : { replyToMessageId: value.replyToMessageId }, ...idempotencyKey === void 0 ? {} : { idempotencyKey } };
|
|
13465
13704
|
}
|
|
@@ -13516,7 +13755,7 @@ function cloneRoomMessage(message) {
|
|
|
13516
13755
|
};
|
|
13517
13756
|
}
|
|
13518
13757
|
function fingerprintRequest(input) {
|
|
13519
|
-
return
|
|
13758
|
+
return createHash4("sha256").update(JSON.stringify({
|
|
13520
13759
|
text: input.text,
|
|
13521
13760
|
mentions: input.mentions,
|
|
13522
13761
|
replyToMessageId: input.replyToMessageId ?? null
|
|
@@ -13685,45 +13924,12 @@ async function execute(reply, operation) {
|
|
|
13685
13924
|
}
|
|
13686
13925
|
|
|
13687
13926
|
// src/routes/cospace.ts
|
|
13688
|
-
import { randomUUID as
|
|
13927
|
+
import { randomUUID as randomUUID16 } from "crypto";
|
|
13689
13928
|
import { ZodError as ZodError5 } from "zod";
|
|
13690
13929
|
import {
|
|
13691
13930
|
generateDirectHumanProjectId,
|
|
13692
13931
|
generateDirectBotProjectId
|
|
13693
13932
|
} from "@axiom-lattice/core";
|
|
13694
|
-
|
|
13695
|
-
// src/services/collaboration/RoomCoordinatorProvisioner.ts
|
|
13696
|
-
var ROOM_COORDINATOR_KEY = "room-coordinator";
|
|
13697
|
-
var RoomCoordinatorProvisioner = class {
|
|
13698
|
-
/** Creates a provisioner over the tenant-scoped assistant store operations. */
|
|
13699
|
-
constructor(deps) {
|
|
13700
|
-
this.deps = deps;
|
|
13701
|
-
}
|
|
13702
|
-
/**
|
|
13703
|
-
* Ensures the Room Coordinator assistant exists, reusing an existing record
|
|
13704
|
-
* and reconciling concurrent create races by rereading the winner.
|
|
13705
|
-
*
|
|
13706
|
-
* @param tenantId Tenant to provision the coordinator for.
|
|
13707
|
-
* @returns The persisted Room Coordinator assistant.
|
|
13708
|
-
*/
|
|
13709
|
-
async ensure(tenantId) {
|
|
13710
|
-
const existing = await this.deps.getAssistantById(tenantId, ROOM_COORDINATOR_KEY);
|
|
13711
|
-
if (existing) return existing;
|
|
13712
|
-
try {
|
|
13713
|
-
return await this.deps.createAssistant(tenantId, ROOM_COORDINATOR_KEY, {
|
|
13714
|
-
name: "Room Coordinator",
|
|
13715
|
-
description: "Coordinates project room conversations and organizes room work.",
|
|
13716
|
-
graphDefinition: {}
|
|
13717
|
-
});
|
|
13718
|
-
} catch (error) {
|
|
13719
|
-
const winner = await this.deps.getAssistantById(tenantId, ROOM_COORDINATOR_KEY);
|
|
13720
|
-
if (winner) return winner;
|
|
13721
|
-
throw error;
|
|
13722
|
-
}
|
|
13723
|
-
}
|
|
13724
|
-
};
|
|
13725
|
-
|
|
13726
|
-
// src/routes/cospace.ts
|
|
13727
13933
|
var CoSpaceAuthError = class extends Error {
|
|
13728
13934
|
constructor() {
|
|
13729
13935
|
super(...arguments);
|
|
@@ -13739,7 +13945,7 @@ function getActor2(request) {
|
|
|
13739
13945
|
return { tenantId: user.tenantId, userId: user.id };
|
|
13740
13946
|
}
|
|
13741
13947
|
function registerCoSpaceRoutes(app2, deps) {
|
|
13742
|
-
const idFactory = deps.idFactory ?? (() =>
|
|
13948
|
+
const idFactory = deps.idFactory ?? (() => randomUUID16());
|
|
13743
13949
|
app2.get(
|
|
13744
13950
|
"/api/workspaces/:workspaceId/rooms",
|
|
13745
13951
|
async (request, reply) => {
|
|
@@ -13764,6 +13970,7 @@ function registerCoSpaceRoutes(app2, deps) {
|
|
|
13764
13970
|
);
|
|
13765
13971
|
const accessibleProjects = [];
|
|
13766
13972
|
for (const project of allProjects) {
|
|
13973
|
+
if (project.kind === "public") continue;
|
|
13767
13974
|
const membership = await deps.membershipStore.findByUser(
|
|
13768
13975
|
actor2.tenantId,
|
|
13769
13976
|
project.id,
|
|
@@ -13817,6 +14024,34 @@ function registerCoSpaceRoutes(app2, deps) {
|
|
|
13817
14024
|
const bTime = b.lastMessage?.createdAt?.getTime() ?? 0;
|
|
13818
14025
|
return bTime - aTime;
|
|
13819
14026
|
});
|
|
14027
|
+
const publicRoom = await deps.publicRoom.ensure(actor2.tenantId, params.workspaceId);
|
|
14028
|
+
if (publicRoom) {
|
|
14029
|
+
const publicMessages = await deps.messageStore.list({
|
|
14030
|
+
tenantId: actor2.tenantId,
|
|
14031
|
+
roomId: publicRoom.room.id,
|
|
14032
|
+
limit: 1
|
|
14033
|
+
});
|
|
14034
|
+
const publicMemberships = await deps.membershipStore.list(
|
|
14035
|
+
actor2.tenantId,
|
|
14036
|
+
publicRoom.project.id
|
|
14037
|
+
);
|
|
14038
|
+
const publicParticipantNames = [];
|
|
14039
|
+
for (const m of publicMemberships) {
|
|
14040
|
+
if (m.status !== "active") continue;
|
|
14041
|
+
const user = await deps.userStore.getUserById(m.userId);
|
|
14042
|
+
if (user) {
|
|
14043
|
+
publicParticipantNames.push(user.name);
|
|
14044
|
+
}
|
|
14045
|
+
}
|
|
14046
|
+
rooms.unshift({
|
|
14047
|
+
project: publicRoom.project,
|
|
14048
|
+
room: publicRoom.room,
|
|
14049
|
+
lastMessage: publicMessages[0],
|
|
14050
|
+
participantCount: publicMemberships.filter((m) => m.status === "active").length,
|
|
14051
|
+
participantNames: publicParticipantNames,
|
|
14052
|
+
isPublic: true
|
|
14053
|
+
});
|
|
14054
|
+
}
|
|
13820
14055
|
return { data: { rooms } };
|
|
13821
14056
|
});
|
|
13822
14057
|
}
|
|
@@ -14573,7 +14808,7 @@ function exactValues(value, required, optional = []) {
|
|
|
14573
14808
|
}
|
|
14574
14809
|
|
|
14575
14810
|
// src/services/collaboration/CoordinatorWakeNotifier.ts
|
|
14576
|
-
import { randomUUID as
|
|
14811
|
+
import { randomUUID as randomUUID17 } from "crypto";
|
|
14577
14812
|
import { isProjectLifecycleTask as isProjectLifecycleTask2 } from "@axiom-lattice/core";
|
|
14578
14813
|
import {
|
|
14579
14814
|
snapshotExactRecord as snapshotExactRecord6
|
|
@@ -14590,7 +14825,7 @@ var CoordinatorWakeNotifier = class {
|
|
|
14590
14825
|
this.accepted = /* @__PURE__ */ new Set();
|
|
14591
14826
|
this.maxPending = deps.maxPending ?? 1024;
|
|
14592
14827
|
if (!Number.isSafeInteger(this.maxPending) || this.maxPending < 1) throw new RangeError("maxPending must be a positive safe integer");
|
|
14593
|
-
this.idFactory = deps.idFactory ??
|
|
14828
|
+
this.idFactory = deps.idFactory ?? randomUUID17;
|
|
14594
14829
|
}
|
|
14595
14830
|
/** Admits one notification without awaiting any store or dispatch operation. */
|
|
14596
14831
|
handle(value) {
|
|
@@ -15460,7 +15695,7 @@ function validRecoveryRow(row, task, thread) {
|
|
|
15460
15695
|
}
|
|
15461
15696
|
|
|
15462
15697
|
// src/services/collaboration/ProjectTaskObserver.ts
|
|
15463
|
-
import { createHash as
|
|
15698
|
+
import { createHash as createHash5 } from "crypto";
|
|
15464
15699
|
import {
|
|
15465
15700
|
isProjectLifecycleTask as isProjectLifecycleTask4,
|
|
15466
15701
|
parseExternalDependency as parseExternalDependency2
|
|
@@ -16000,7 +16235,7 @@ var ProjectTaskObserver = class {
|
|
|
16000
16235
|
action: "activity",
|
|
16001
16236
|
summary: "Project task recovery warning",
|
|
16002
16237
|
detail: { type: "project_task_recovery_warning", phase, message },
|
|
16003
|
-
eventKey: `project-task-recovery-warning:${task.id}:${phase}:${
|
|
16238
|
+
eventKey: `project-task-recovery-warning:${task.id}:${phase}:${createHash5("sha256").update(message).digest("hex")}`
|
|
16004
16239
|
});
|
|
16005
16240
|
}
|
|
16006
16241
|
async safeWarning(task, phase, error) {
|
|
@@ -16067,7 +16302,7 @@ var ProjectTaskObserver = class {
|
|
|
16067
16302
|
}
|
|
16068
16303
|
}
|
|
16069
16304
|
async persistOverflowWarning(event) {
|
|
16070
|
-
const scopeDigest =
|
|
16305
|
+
const scopeDigest = createHash5("sha256").update(JSON.stringify([event.tenantId, event.workspaceId, event.projectId])).digest("hex");
|
|
16071
16306
|
try {
|
|
16072
16307
|
await this.deps.workItems.createIfAbsentByEventKey({
|
|
16073
16308
|
tenantId: event.tenantId,
|
|
@@ -16168,7 +16403,7 @@ function combineSignals(left, right) {
|
|
|
16168
16403
|
}
|
|
16169
16404
|
|
|
16170
16405
|
// src/services/collaboration/RoomProjectionService.ts
|
|
16171
|
-
import { createHash as
|
|
16406
|
+
import { createHash as createHash6 } from "crypto";
|
|
16172
16407
|
import { isProjectLifecycleTask as isProjectLifecycleTask5 } from "@axiom-lattice/core";
|
|
16173
16408
|
import {
|
|
16174
16409
|
PROJECT_TASK_LIFECYCLE_ACTIONS,
|
|
@@ -16341,7 +16576,7 @@ function safeRepairIdentity(value, scope) {
|
|
|
16341
16576
|
return taskId && eventKey && tenantId === scope.tenantId && workspaceId === scope.workspaceId && projectId === scope.projectId ? { taskId, eventKey } : void 0;
|
|
16342
16577
|
}
|
|
16343
16578
|
function tupleKey(prefix, values) {
|
|
16344
|
-
const digest =
|
|
16579
|
+
const digest = createHash6("sha256").update(JSON.stringify(values)).digest("hex");
|
|
16345
16580
|
return `${prefix}:${digest}`;
|
|
16346
16581
|
}
|
|
16347
16582
|
function parseProjectionInput(taskValue, itemValue) {
|
|
@@ -16524,7 +16759,7 @@ function isRecord4(value) {
|
|
|
16524
16759
|
import { taskLifecycleNotifier } from "@axiom-lattice/core";
|
|
16525
16760
|
|
|
16526
16761
|
// src/services/collaboration/ProjectRoomEventBroker.ts
|
|
16527
|
-
import { randomUUID as
|
|
16762
|
+
import { randomUUID as randomUUID18 } from "crypto";
|
|
16528
16763
|
import {
|
|
16529
16764
|
parseProjectRoomEventId,
|
|
16530
16765
|
ProjectRoomBrokerCapacityError,
|
|
@@ -16553,7 +16788,7 @@ var ProjectRoomEventBroker = class {
|
|
|
16553
16788
|
this.subscriberCount = 0;
|
|
16554
16789
|
this.usageClock = 0;
|
|
16555
16790
|
this.closed = false;
|
|
16556
|
-
this.epoch = options.epoch ??
|
|
16791
|
+
this.epoch = options.epoch ?? randomUUID18();
|
|
16557
16792
|
if (!UUID_PATTERN.test(this.epoch)) {
|
|
16558
16793
|
throw new TypeError("Project Room event epoch must be a lowercase canonical UUID");
|
|
16559
16794
|
}
|
|
@@ -16871,7 +17106,7 @@ function snapshotJson(value, ancestors = /* @__PURE__ */ new Set()) {
|
|
|
16871
17106
|
}
|
|
16872
17107
|
|
|
16873
17108
|
// src/services/collaboration/ProjectRoomRealtimePublisher.ts
|
|
16874
|
-
import { createHash as
|
|
17109
|
+
import { createHash as createHash7 } from "crypto";
|
|
16875
17110
|
import {
|
|
16876
17111
|
snapshotExactRecord as snapshotExactRecord10,
|
|
16877
17112
|
snapshotProjectRoomBotMembershipRealtime,
|
|
@@ -16952,7 +17187,7 @@ var BrokerProjectRoomRealtimePublisher = class {
|
|
|
16952
17187
|
try {
|
|
16953
17188
|
event = build();
|
|
16954
17189
|
if (!event) throw new Error("Invalid Project Room realtime projection");
|
|
16955
|
-
const dedupeKey =
|
|
17190
|
+
const dedupeKey = createHash7("sha256").update(JSON.stringify([type, event.scope.tenantId, event.scope.projectId, event.scope.roomId, event.sourceKey])).digest("hex");
|
|
16956
17191
|
if (this.sourceKeys.has(dedupeKey)) return;
|
|
16957
17192
|
this.deps.broker.publish(event.scope, event.draft);
|
|
16958
17193
|
this.sourceKeys.set(dedupeKey, true);
|
|
@@ -17891,12 +18126,24 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
17891
18126
|
});
|
|
17892
18127
|
}
|
|
17893
18128
|
if (projectTaskComposition) app2.addHook("onClose", async () => projectTaskComposition.lease.release());
|
|
17894
|
-
const taskThreadService = projectTaskComposition?.lease.runtime.threads ?? new ProjectTaskThreadService({ threads: threadStore, idFactory:
|
|
18129
|
+
const taskThreadService = projectTaskComposition?.lease.runtime.threads ?? new ProjectTaskThreadService({ threads: threadStore, idFactory: randomUUID19 });
|
|
17895
18130
|
const taskLifecycle = projectTaskComposition?.lease.runtime.lifecycle ?? createTaskLifecycleService({ taskStore, workItemStore: taskWorkItemStore });
|
|
17896
18131
|
const reassignmentAuthorizer = createProjectTaskReassignmentAuthorizer(
|
|
17897
18132
|
new ProjectTaskOwnerPolicy(projectBotMembershipStore),
|
|
17898
18133
|
(input) => validateReassignmentThread(threadStore, input)
|
|
17899
18134
|
);
|
|
18135
|
+
const coordinatorProvisioner = new RoomCoordinatorProvisioner({
|
|
18136
|
+
getAssistantById: assistantStore.getAssistantById.bind(assistantStore),
|
|
18137
|
+
createAssistant: assistantStore.createAssistant.bind(assistantStore)
|
|
18138
|
+
});
|
|
18139
|
+
const publicRoomService = new WorkspacePublicRoomService({
|
|
18140
|
+
getProjectById: projectStore.getProjectById.bind(projectStore),
|
|
18141
|
+
createProject: projectStore.createProject.bind(projectStore),
|
|
18142
|
+
ensureMainRoom: projectRoomStore.ensureMainRoom.bind(projectRoomStore),
|
|
18143
|
+
findBotByAssistant: projectBotMembershipStore.findByAssistant.bind(projectBotMembershipStore),
|
|
18144
|
+
saveBot: projectBotMembershipStore.save.bind(projectBotMembershipStore),
|
|
18145
|
+
ensureCoordinator: (tenantId) => coordinatorProvisioner.ensure(tenantId)
|
|
18146
|
+
});
|
|
17900
18147
|
registerProjectRoomRoutes(app2, { roomService, membershipService, messageService });
|
|
17901
18148
|
registerProjectRosterRoutes(app2, { service: rosterService });
|
|
17902
18149
|
registerCoSpaceRoutes(app2, {
|
|
@@ -17935,14 +18182,14 @@ var registerLatticeRoutes = (app2, channelDeps, options = {}) => {
|
|
|
17935
18182
|
findByAssistant: projectBotMembershipStore.findByAssistant.bind(projectBotMembershipStore),
|
|
17936
18183
|
save: projectBotMembershipStore.save.bind(projectBotMembershipStore)
|
|
17937
18184
|
},
|
|
17938
|
-
coordinatorProvisioner
|
|
17939
|
-
getAssistantById: assistantStore.getAssistantById.bind(assistantStore),
|
|
17940
|
-
createAssistant: assistantStore.createAssistant.bind(assistantStore)
|
|
17941
|
-
}),
|
|
18185
|
+
coordinatorProvisioner,
|
|
17942
18186
|
rosterService: {
|
|
17943
18187
|
addBot: async (actor2, input) => {
|
|
17944
18188
|
await rosterService.add(actor2, input);
|
|
17945
18189
|
}
|
|
18190
|
+
},
|
|
18191
|
+
publicRoom: {
|
|
18192
|
+
ensure: (tenantId, workspaceId) => publicRoomService.ensure(tenantId, workspaceId)
|
|
17946
18193
|
}
|
|
17947
18194
|
});
|
|
17948
18195
|
registerCapabilityBundleRoutes(app2, new CapabilityBundleController({
|
|
@@ -18383,7 +18630,7 @@ function tryCreateProjectTaskRuntime(input) {
|
|
|
18383
18630
|
function createRuntime(input, stores, log2) {
|
|
18384
18631
|
const controller = new AbortController();
|
|
18385
18632
|
const mutex = new ProjectTaskExecutionMutex();
|
|
18386
|
-
const threads = new ProjectTaskThreadService({ threads: input.threadStore, idFactory:
|
|
18633
|
+
const threads = new ProjectTaskThreadService({ threads: input.threadStore, idFactory: randomUUID19 });
|
|
18387
18634
|
const lifecycle = createTaskLifecycleService({ taskStore: input.taskStore, workItemStore: input.taskWorkItemStore });
|
|
18388
18635
|
const projection = new RoomProjectionService({
|
|
18389
18636
|
messages: input.projectRoomMessageStore,
|
|
@@ -18392,7 +18639,7 @@ function createRuntime(input, stores, log2) {
|
|
|
18392
18639
|
warnings: input.taskWorkItemStore,
|
|
18393
18640
|
log: log2,
|
|
18394
18641
|
realtime: input.realtime,
|
|
18395
|
-
idFactory:
|
|
18642
|
+
idFactory: randomUUID19
|
|
18396
18643
|
});
|
|
18397
18644
|
const agentFor = (task, thread) => agentInstanceManager6.getAgent({
|
|
18398
18645
|
tenant_id: task.tenantId,
|
|
@@ -19217,7 +19464,7 @@ var collectionRegistration = {
|
|
|
19217
19464
|
|
|
19218
19465
|
// src/export_registrations/channel-installation.registration.ts
|
|
19219
19466
|
import { getStoreLattice as getStoreLattice23 } from "@axiom-lattice/core";
|
|
19220
|
-
import { randomUUID as
|
|
19467
|
+
import { randomUUID as randomUUID20 } from "crypto";
|
|
19221
19468
|
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;
|
|
19222
19469
|
var PUBLIC_CHANNELS = /* @__PURE__ */ new Set(["lark", "email", "slack", "wechat"]);
|
|
19223
19470
|
function isPublicChannel(channel) {
|
|
@@ -19376,7 +19623,7 @@ var channelInstallationRegistration = {
|
|
|
19376
19623
|
}
|
|
19377
19624
|
id3 = sourceId;
|
|
19378
19625
|
} else {
|
|
19379
|
-
id3 =
|
|
19626
|
+
id3 = randomUUID20();
|
|
19380
19627
|
}
|
|
19381
19628
|
await store.createInstallation(tenantId, id3, createInput);
|
|
19382
19629
|
return { newId: id3 };
|
|
@@ -20264,7 +20511,7 @@ import {
|
|
|
20264
20511
|
snapshotExactArray as snapshotExactArray3,
|
|
20265
20512
|
snapshotExactRecord as snapshotExactRecord14
|
|
20266
20513
|
} from "@axiom-lattice/protocols";
|
|
20267
|
-
import { randomUUID as
|
|
20514
|
+
import { randomUUID as randomUUID21 } from "crypto";
|
|
20268
20515
|
var BindingNotFoundError = class extends Error {
|
|
20269
20516
|
constructor(message) {
|
|
20270
20517
|
super(message);
|
|
@@ -20579,7 +20826,7 @@ var MessageRouter = class {
|
|
|
20579
20826
|
}
|
|
20580
20827
|
if (!threadId) {
|
|
20581
20828
|
const threadStore = getStoreLattice26("default", "thread").store;
|
|
20582
|
-
const newThreadId =
|
|
20829
|
+
const newThreadId = randomUUID21();
|
|
20583
20830
|
console.log({
|
|
20584
20831
|
event: "dispatch:thread:create",
|
|
20585
20832
|
agentId,
|
|
@@ -20625,7 +20872,7 @@ var MessageRouter = class {
|
|
|
20625
20872
|
workspace_id: binding?.workspaceId || "",
|
|
20626
20873
|
project_id: binding?.projectId || ""
|
|
20627
20874
|
});
|
|
20628
|
-
const inputMessageId =
|
|
20875
|
+
const inputMessageId = randomUUID21();
|
|
20629
20876
|
const replyTarget = internalRoom ? correlatedRoomReplyTarget(message.replyTarget, inputMessageId) : message.replyTarget;
|
|
20630
20877
|
const replyAdapter = replyTarget ? this.adapterRegistry.get(replyTarget.adapterChannel) : void 0;
|
|
20631
20878
|
if (options.trustedMessageOptions && (!this.trustedDispatcher || !replyTarget || !replyAdapter)) {
|