feat: move session sharing and collab rooms into a plugin (B12)

This commit is contained in:
LukeGus committed 2026-09-23 23:42:46 -05:00
1 parent 791d8656a1
commit a276f6898c
207 files changed
+35771 -11072

No files matched your search

-139
View File
@@ -756,70 +756,6 @@ export const sessionRecordings = sqliteTable(
],
);
export const sessionShares = sqliteTable(
"session_shares",
{
id: text("id").primaryKey(),
hostId: integer("host_id")
.notNull()
.references(() => hosts.id, { onDelete: "cascade" }),
ownerUserId: text("owner_user_id")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
protocol: text("protocol").notNull(),
// Live-session binding: TerminalSessionManager's session.id for SSH, or
// guacd's own guacamoleConnectionId for rdp/vnc/telnet. Neither is a DB
// row (process-local, in-memory) so this intentionally has no FK.
sessionId: text("session_id").notNull(),
tabInstanceId: text("tab_instance_id"),
shareType: text("share_type").notNull(), // "link" | "user"
targetUserId: text("target_user_id").references(() => users.id, {
onDelete: "cascade",
}),
linkToken: text("link_token").unique(),
permissionLevel: text("permission_level").notNull().default("read-only"),
createdAt: text("created_at")
.notNull()
.default(sql`CURRENT_TIMESTAMP`),
expiresAt: text("expires_at").notNull(),
revokedAt: text("revoked_at"),
lastJoinedAt: text("last_joined_at"),
joinCount: integer("join_count").notNull().default(0),
},
// Resolved from the live session on join, and listed per host.
(table) => [
index("idx_session_shares_session_id").on(table.sessionId),
index("idx_session_shares_host_id").on(table.hostId),
],
);
export const sessionShareParticipants = sqliteTable(
"session_share_participants",
{
id: integer("id").primaryKey({ autoIncrement: true }),
shareId: text("share_id")
.notNull()
.references(() => sessionShares.id, { onDelete: "cascade" }),
userId: text("user_id").references(() => users.id, {
onDelete: "cascade",
}),
guestLabel: text("guest_label"),
joinedAt: text("joined_at")
.notNull()
.default(sql`CURRENT_TIMESTAMP`),
leftAt: text("left_at"),
},
);
export const opksshTokens = sqliteTable(
"opkssh_tokens",
{
@@ -1568,81 +1504,6 @@ export const aiProposals = sqliteTable(
// --- collab rooms ---
/**
* A collaboration room: a group of users watching one "stage" - the live
* session the current presenter is showing. The stage points at a
* shareType="room" row in session_shares, so transport, gating, recording and
* expiry all reuse the session-sharing machinery.
*/
export const collabRooms = sqliteTable(
"collab_rooms",
{
id: text("id").primaryKey(),
name: text("name").notNull(),
ownerUserId: text("owner_user_id")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
// Persistent rooms survive being emptied and can be re-used; one-off
// rooms are ended explicitly and never listed again.
persistent: integer("persistent", { mode: "boolean" })
.notNull()
.default(false),
presenterUserId: text("presenter_user_id").references(() => users.id, {
onDelete: "set null",
}),
stageProtocol: text("stage_protocol"),
stageHostId: integer("stage_host_id").references(() => hosts.id, {
onDelete: "set null",
}),
stageShareId: text("stage_share_id").references(() => sessionShares.id, {
onDelete: "set null",
}),
// Set = anonymous guests may watch the stage through this token.
guestLinkToken: text("guest_link_token"),
createdAt: text("created_at")
.notNull()
.default(sql`CURRENT_TIMESTAMP`),
endedAt: text("ended_at"),
},
(table) => [
index("idx_collab_rooms_owner").on(table.ownerUserId),
uniqueIndex("idx_collab_rooms_guest_token").on(table.guestLinkToken),
],
);
export const collabRoomMembers = sqliteTable(
"collab_room_members",
{
id: integer("id").primaryKey({ autoIncrement: true }),
roomId: text("room_id")
.notNull()
.references(() => collabRooms.id, { onDelete: "cascade" }),
userId: text("user_id")
.notNull()
.references(() => users.id, { onDelete: "cascade" }),
// "host" runs the room: invites, force-switches the presenter, ends it.
roomRole: text("room_role").notNull().default("member"),
addedBy: text("added_by").references(() => users.id, {
onDelete: "set null",
}),
createdAt: text("created_at")
.notNull()
.default(sql`CURRENT_TIMESTAMP`),
},
(table) => [
uniqueIndex("idx_collab_room_members_room_user").on(
table.roomId,
table.userId,
),
index("idx_collab_room_members_user").on(table.userId),
],
);
// --- secret sources ---
/**