Skip to content

feat: add workspaces with isolated channels, members, and invite system#193

Merged
mahata merged 2 commits intomainfrom
opencode/sunny-pixel
Apr 8, 2026
Merged

feat: add workspaces with isolated channels, members, and invite system#193
mahata merged 2 commits intomainfrom
opencode/sunny-pixel

Conversation

@mahata
Copy link
Copy Markdown
Owner

@mahata mahata commented Apr 8, 2026

Summary

  • Add workspace support with path-based routing (/w/:slug/...), per-workspace admin roles, invite links (1-hour expiry, multi-use), and one Durable Object per workspace for WebSocket connections
  • Existing data auto-migrates into a seeded default workspace; new users with no workspaces auto-join default
  • All channels, messages, and memberships are fully isolated per workspace

Database changes

  • 3 new tables: workspaces, workspace_members, workspace_invites
  • channels table rebuilt with workspace_id NOT NULL column (unique index now scoped to (workspace_id, name))
  • Migration 0002 uses PRAGMA defer_foreign_keys to safely handle the table rebuild on D1
  • Drizzle snapshot JSON added for migration 0002

New files

  • hono/auth/requireWorkspaceMember.ts / requireWorkspaceAdmin.ts — middleware
  • hono/routes/workspaces.ts — workspace CRUD
  • hono/routes/workspaceAdmin.ts — admin routes (invites, members)
  • hono/routes/workspaceInvite.ts — invite acceptance
  • hono/components/WorkspacesPage.tsx + CSS — workspace list UI

Modified files

  • hono/app.tsx — new route registrations and workspace middleware
  • hono/routes/channels.ts, messages.ts, ws.ts — scoped under /w/:slug/
  • hono/routes/index.tsx — workspace redirect logic
  • hono/components/ChatPage.tsx — workspace context in UI
  • hono/static/ChatPage.ts — workspace-scoped API URLs
  • hono/db/schema.ts — 3 new tables, modified channels
  • e2e/app.spec.ts — updated page title assertion

Testing

  • 112 unit tests passing, lint clean, build successful
  • Migration tested against local D1 (fresh install) and production D1 (upgrade with existing data)
  • Already deployed to production (mlack.uk)

Introduce workspace support with path-based routing (/w/:slug/...), per-workspace
admin roles, invite links with 1-hour expiration, and one Durable Object per
workspace for WebSocket connections. Existing data auto-migrates into a seeded
'default' workspace. Migration uses PRAGMA defer_foreign_keys to handle the
channels table rebuild safely on D1.
Copilot AI review requested due to automatic review settings April 8, 2026 08:03
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class workspace support across the app, including workspace-scoped routing (/w/:slug/...), isolated data access, admin/member roles, and invite-based onboarding.

Changes:

  • Introduces workspaces, workspace_members, and workspace_invites tables plus a migration to backfill existing data into a seeded default workspace.
  • Updates channel/message/WS routes and client-side API calls to be workspace-scoped under /w/:slug/....
  • Adds workspace UI (workspace list page) and admin endpoints for invite/member management, plus updated tests.
Show a summary per file
File Description
hono/types.ts Adds workspace-related types and context variables.
hono/static/ChatPage.ts Scopes REST API calls under /w/:slug/api.
hono/routes/ws.ts Moves WS endpoint to /w/:slug/ws and namespaces Durable Object by workspace slug.
hono/routes/ws.test.ts Updates WS route tests for workspace-scoped paths and DO name.
hono/routes/workspaces.ts Adds endpoints to list/create workspaces.
hono/routes/workspaceInvite.ts Adds invite acceptance flow for joining a workspace.
hono/routes/workspaceAdmin.ts Adds admin endpoints for invites and member role management.
hono/routes/messages.ts Scopes messages endpoint under workspace and validates channel belongs to workspace.
hono/routes/messages.test.ts Updates tests for workspace-scoped messages endpoint.
hono/routes/index.tsx Adds workspace selection/redirect logic and /w/:slug chat page rendering.
hono/routes/index.test.tsx Updates/extends tests for workspace redirect and workspace chat route behavior.
hono/routes/channels.ts Scopes channel endpoints under workspace and enforces workspace isolation.
hono/routes/channels.test.ts Updates tests for workspace-scoped channel endpoints.
hono/deployment.test.ts Ensures new routes/components can be imported for deployment compatibility.
hono/db/seed.sql Seeds default workspace and workspace-scoped general channel.
hono/db/schema.ts Adds new workspace tables and rebuilds channels with workspace_id + scoped uniqueness.
hono/db/migrations/meta/0002_snapshot.json Drizzle snapshot for the new schema/migration.
hono/db/migrations/meta/_journal.json Registers migration 0002_add_workspaces.
hono/db/migrations/0002_add_workspaces.sql Creates new tables, seeds default, rebuilds/migrates channels, backfills workspace members.
hono/components/WorkspacesPage.tsx Adds server-rendered workspace list page.
hono/components/WorkspacesPage.css Styling for the workspace list UI.
hono/components/ChatPage.tsx Adds workspace context (title/header + data attributes) to chat page.
hono/components/ChatPage.test.ts Updates/extends tests for workspace-scoped ChatPage rendering.
hono/auth/requireWorkspaceMember.ts Adds middleware to enforce workspace membership and load workspace context.
hono/auth/requireWorkspaceAdmin.ts Adds middleware to enforce admin role within a workspace.
hono/app.tsx Registers new routes and applies workspace membership middleware to /w/:slug/....
e2e/app.spec.ts Updates title assertion for workspace-scoped chat page.

Copilot's findings

  • Files reviewed: 27/27 changed files
  • Comments generated: 7

Comment thread hono/types.ts Outdated
Comment on lines +49 to +50
workspace: Workspace;
workspaceMember: WorkspaceMember;
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variables marks workspace and workspaceMember as always present, but they’re only set by requireWorkspaceMember for /w/:slug... routes. On routes like /api/workspaces (which only uses requireUser) these values will be undefined at runtime while TypeScript treats them as defined, which can lead to unsafe c.get("workspace") usage. Make these variables optional (or split Env types for workspace-scoped vs global routes) so the typing matches reality.

Suggested change
workspace: Workspace;
workspaceMember: WorkspaceMember;
workspace?: Workspace;
workspaceMember?: WorkspaceMember;

Copilot uses AI. Check for mistakes.
Comment thread hono/routes/index.tsx Outdated
Comment on lines +31 to +34
await db.insert(workspaceMembers).values({
workspaceId: defaultWorkspace.id,
userEmail: user.email,
role: "member",
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New users with zero workspace memberships are inserted into the default workspace with role member. On a fresh install there may be no existing workspace admins (migration only promotes an existing member during upgrade), which means nobody can create invites or new workspaces and the system can’t be bootstrapped. Consider making the first member of the default workspace an admin when no members exist yet (or relax the workspace-creation restriction).

Suggested change
await db.insert(workspaceMembers).values({
workspaceId: defaultWorkspace.id,
userEmail: user.email,
role: "member",
const existingDefaultWorkspaceMembers = await db
.select({ userEmail: workspaceMembers.userEmail })
.from(workspaceMembers)
.where(eq(workspaceMembers.workspaceId, defaultWorkspace.id));
const initialRole = existingDefaultWorkspaceMembers.length === 0 ? "admin" : "member";
await db.insert(workspaceMembers).values({
workspaceId: defaultWorkspace.id,
userEmail: user.email,
role: initialRole,

Copilot uses AI. Check for mistakes.
Comment thread hono/routes/index.tsx Outdated
Comment on lines +66 to +71
const user = session.get("user") as User | undefined;

if (!user) {
return c.redirect("/auth/login");
}

Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because requireWorkspaceMember is applied to /w/:slug in app.tsx, unauthenticated requests to /w/:slug will return a JSON 401 from the middleware, so this handler’s redirect-to-login branch is unreachable and the behavior for page routes is inconsistent with / (which redirects). Either remove the redundant session check here or adjust the middleware/page routing so unauthenticated users get an HTML redirect instead of JSON.

Suggested change
const user = session.get("user") as User | undefined;
if (!user) {
return c.redirect("/auth/login");
}
const user = session.get("user") as User;

Copilot uses AI. Check for mistakes.
Comment thread hono/routes/workspaces.ts Outdated
Comment on lines +28 to +32
const workspaceIds = memberships.map((m) => m.workspaceId);
const allWorkspaces = await db.select().from(workspaces);
const userWorkspaces = allWorkspaces
.filter((w) => workspaceIds.includes(w.id))
.map((w) => {
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This endpoint loads all workspaces and filters them in JS. That does unnecessary DB work and won’t scale as workspace count grows. Prefer selecting only the user’s workspaces in SQL (e.g., where inArray(workspaces.id, workspaceIds) or a join from workspace_members to workspaces).

Copilot uses AI. Check for mistakes.
Comment thread hono/db/seed.sql Outdated
@@ -1 +1,2 @@
INSERT INTO channels (name, created_by_email) VALUES ('general', 'system');
INSERT OR IGNORE INTO workspaces (name, slug, created_by_email) VALUES ('Default', 'default', 'system');
INSERT OR IGNORE INTO channels (name, workspace_id, created_by_email) VALUES ('general', 1, 'system');
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seed.sql hard-codes workspace_id = 1 when inserting the general channel. If the default workspace’s id isn’t 1 (e.g., if data already exists or autoincrement has advanced), this will create a channel pointing at the wrong/non-existent workspace. Use a subquery to look up the workspace id by slug (or insert the workspace with an explicit id).

Suggested change
INSERT OR IGNORE INTO channels (name, workspace_id, created_by_email) VALUES ('general', 1, 'system');
INSERT OR IGNORE INTO channels (name, workspace_id, created_by_email)
SELECT 'general', id, 'system'
FROM workspaces
WHERE slug = 'default';

Copilot uses AI. Check for mistakes.
Comment on lines +35 to +43
<ul className="workspace-list">
{workspaceList.map((w) => (
<li className="workspace-item">
<a href={`/w/${w.slug}`} className="workspace-link">
<span className="workspace-name">{w.name}</span>
<span className="workspace-slug">/{w.slug}</span>
{w.role === "admin" && <span className="workspace-badge admin">Admin</span>}
</a>
</li>
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The list rendering is missing a stable key on the <li> (or the <a>) element. This produces React/JSX warnings and can cause incorrect DOM diffing if the list changes. Add a key (e.g., w.id or w.slug) to the mapped element.

Copilot uses AI. Check for mistakes.
Comment on lines +9 to +13
workspaceInviteRoute.get("/w/:slug/invite/:code", requireUser, async (c) => {
try {
const db = getDb(c.env.DB);
const user = c.get("user");
const slug = c.req.param("slug");
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Invite acceptance is implemented as a GET that mutates server state (inserts workspace/channel membership). This can be triggered unintentionally by link prefetching/crawlers and also enables “forced join” if a logged-in user is induced to load the URL. Consider serving a confirmation page on GET and performing the mutation on POST (with CSRF), or otherwise ensuring idempotent/non-mutating GET behavior.

Copilot uses AI. Check for mistakes.
…vite security

- Make workspace/workspaceMember optional in Variables type to match runtime
- First user auto-joining default workspace now becomes admin (bootstrap fix)
- Remove unreachable auth check in /w/:slug (middleware already handles it)
- Replace select-all-then-filter with SQL inner join for workspace queries
- Use subquery in seed.sql instead of hardcoded workspace_id=1
- Convert invite acceptance from mutating GET to GET confirmation + POST
@mahata mahata merged commit 467fb35 into main Apr 8, 2026
3 checks passed
@mahata mahata deleted the opencode/sunny-pixel branch April 8, 2026 08:19
mahata added a commit that referenced this pull request Apr 8, 2026
…194)

* feat: add deployment tagging, GitHub Releases, and PR template

Add a post-deploy step to deploy.yml that creates a git tag
(deploy-YYYY-MM-DD-SHA) and a GitHub Release with auto-generated
notes after each successful production deployment. This provides
a clear history of which commits were deployed and when.

Add a default PR template with a pre-deploy checklist covering
CI status, migration review, secrets, and Durable Objects state.

* Update .github/workflows/deploy.yml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: scope contents:write permission to deploy job only

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/b28d6893-dc36-48da-a24d-589cb4ad8e05

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* deps-dev(deps-dev): bump @cloudflare/workers-types (#164)

Bumps [@cloudflare/workers-types](https://github.com/cloudflare/workerd) from 4.20260317.1 to 4.20260329.1.
- [Release notes](https://github.com/cloudflare/workerd/releases)
- [Changelog](https://github.com/cloudflare/workerd/blob/main/RELEASE.md)
- [Commits](https://github.com/cloudflare/workerd/commits)

---
updated-dependencies:
- dependency-name: "@cloudflare/workers-types"
  dependency-version: 4.20260329.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore: add conventional-commit skill for Copilot

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* deps(deps): bump hono in the production-dependencies group (#168)

Bumps the production-dependencies group with 1 update: [hono](https://github.com/honojs/hono).


Updates `hono` from 4.12.9 to 4.12.11
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](honojs/hono@v4.12.9...v4.12.11)

---
updated-dependencies:
- dependency-name: hono
  dependency-version: 4.12.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps(deps): bump the development-dependencies group with 11 updates (#169)

Bumps the development-dependencies group with 11 updates:

| Package | From | To |
| --- | --- | --- |
| [@biomejs/biome](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@playwright/test](https://github.com/microsoft/playwright) | `1.58.2` | `1.59.1` |
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `24.12.0` | `24.12.2` |
| [@biomejs/cli-darwin-arm64](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@biomejs/cli-darwin-x64](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@biomejs/cli-linux-arm64-musl](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@biomejs/cli-linux-arm64](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@biomejs/cli-linux-x64-musl](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@biomejs/cli-linux-x64](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@biomejs/cli-win32-arm64](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |
| [@biomejs/cli-win32-x64](https://github.com/biomejs/biome/tree/HEAD/packages/@biomejs/biome) | `2.4.9` | `2.4.10` |


Updates `@biomejs/biome` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@playwright/test` from 1.58.2 to 1.59.1
- [Release notes](https://github.com/microsoft/playwright/releases)
- [Commits](microsoft/playwright@v1.58.2...v1.59.1)

Updates `@types/node` from 24.12.0 to 24.12.2
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

Updates `@biomejs/cli-darwin-arm64` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@biomejs/cli-darwin-x64` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@biomejs/cli-linux-arm64-musl` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@biomejs/cli-linux-arm64` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@biomejs/cli-linux-x64-musl` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@biomejs/cli-linux-x64` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@biomejs/cli-win32-arm64` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

Updates `@biomejs/cli-win32-x64` from 2.4.9 to 2.4.10
- [Release notes](https://github.com/biomejs/biome/releases)
- [Changelog](https://github.com/biomejs/biome/blob/main/packages/@biomejs/biome/CHANGELOG.md)
- [Commits](https://github.com/biomejs/biome/commits/@biomejs/biome@2.4.10/packages/@biomejs/biome)

---
updated-dependencies:
- dependency-name: "@biomejs/biome"
  dependency-version: 2.4.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@playwright/test"
  dependency-version: 1.59.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
- dependency-name: "@types/node"
  dependency-version: 24.12.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-darwin-arm64"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-darwin-x64"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-linux-arm64-musl"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-linux-arm64"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-linux-x64-musl"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-linux-x64"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-win32-arm64"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: "@biomejs/cli-win32-x64"
  dependency-version: 2.4.10
  dependency-type: indirect
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps(deps): bump tinyglobby from 0.2.14 to 0.2.15 (#170)

Bumps [tinyglobby](https://github.com/SuperchupuDev/tinyglobby) from 0.2.14 to 0.2.15.
- [Release notes](https://github.com/SuperchupuDev/tinyglobby/releases)
- [Changelog](https://github.com/SuperchupuDev/tinyglobby/blob/main/CHANGELOG.md)
- [Commits](SuperchupuDev/tinyglobby@0.2.14...0.2.15)

---
updated-dependencies:
- dependency-name: tinyglobby
  dependency-version: 0.2.15
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps(deps): bump @emnapi/runtime from 1.9.1 to 1.9.2 (#172)

Bumps [@emnapi/runtime](https://github.com/toyobayashi/emnapi) from 1.9.1 to 1.9.2.
- [Release notes](https://github.com/toyobayashi/emnapi/releases)
- [Commits](toyobayashi/emnapi@v1.9.1...v1.9.2)

---
updated-dependencies:
- dependency-name: "@emnapi/runtime"
  dependency-version: 1.9.2
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps(deps): bump vite from 7.0.5 to 7.3.1 (#171)

Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.0.5 to 7.3.1.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.3.1/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.3.1
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps(deps): bump tinyspy from 4.0.3 to 4.0.4 (#173)

Bumps [tinyspy](https://github.com/tinylibs/tinyspy) from 4.0.3 to 4.0.4.
- [Release notes](https://github.com/tinylibs/tinyspy/releases)
- [Commits](tinylibs/tinyspy@v4.0.3...v4.0.4)

---
updated-dependencies:
- dependency-name: tinyspy
  dependency-version: 4.0.4
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* deps-dev(deps-dev): bump @cloudflare/workers-types (#174)

Bumps [@cloudflare/workers-types](https://github.com/cloudflare/workerd) from 4.20260329.1 to 4.20260405.1.
- [Release notes](https://github.com/cloudflare/workerd/releases)
- [Changelog](https://github.com/cloudflare/workerd/blob/main/RELEASE.md)
- [Commits](https://github.com/cloudflare/workerd/commits)

---
updated-dependencies:
- dependency-name: "@cloudflare/workers-types"
  dependency-version: 4.20260405.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps-dev(deps-dev): bump wrangler from 4.77.0 to 4.79.0 (#178)

Bumps [wrangler](https://github.com/cloudflare/workers-sdk/tree/HEAD/packages/wrangler) from 4.77.0 to 4.79.0.
- [Release notes](https://github.com/cloudflare/workers-sdk/releases)
- [Commits](https://github.com/cloudflare/workers-sdk/commits/wrangler@4.79.0/packages/wrangler)

---
updated-dependencies:
- dependency-name: wrangler
  dependency-version: 4.79.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* deps(deps): bump drizzle-orm from 0.45.1 to 0.45.2 (#165)

Bumps [drizzle-orm](https://github.com/drizzle-team/drizzle-orm) from 0.45.1 to 0.45.2.
- [Release notes](https://github.com/drizzle-team/drizzle-orm/releases)
- [Commits](drizzle-team/drizzle-orm@0.45.1...0.45.2)

---
updated-dependencies:
- dependency-name: drizzle-orm
  dependency-version: 0.45.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: resolve duplicate @types/node@24.12.2 in pnpm-lock.yaml (#175)

* deps(deps): bump expect-type from 1.2.2 to 1.3.0

Bumps [expect-type](https://github.com/mmkal/expect-type) from 1.2.2 to 1.3.0.
- [Release notes](https://github.com/mmkal/expect-type/releases)
- [Commits](mmkal/expect-type@v1.2.2...v1.3.0)

---
updated-dependencies:
- dependency-name: expect-type
  dependency-version: 1.3.0
  dependency-type: indirect
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix: resolve duplicate @types/node@24.12.2 in pnpm-lock.yaml by updating @types/node to ^24.12.2

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/75387082-98f8-4f32-a101-e17460603972

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* chore: merge main into branch, resolve @playwright/test version conflict

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/93366234-814a-46ee-b2fd-3d5296eeaa11

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* feat: add mlack.uk custom domain route to production

* fix: resolve duplicate @types/node@24.12.2 in pnpm-lock.yaml (#176)

* deps(deps): bump postcss from 8.5.6 to 8.5.8

Bumps [postcss](https://github.com/postcss/postcss) from 8.5.6 to 8.5.8.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](postcss/postcss@8.5.6...8.5.8)

---
updated-dependencies:
- dependency-name: postcss
  dependency-version: 8.5.8
  dependency-type: indirect
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* fix: resolve duplicate @types/node@24.12.2 in pnpm-lock.yaml after merging main

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/ee849a11-8ea0-46b7-8001-8e30404fc116

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* deps(deps): bump vite from 7.0.5 to 7.3.2 (#183)

Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.0.5 to 7.3.2.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/v7.3.2/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v7.3.2/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 7.3.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* feat: add Electron desktop client (#184)

* feat: add Electron desktop client with notifications and system tray

Add an Electron wrapper that loads the existing mlack web app in a
native desktop window. Includes:
- System tray icon with show/quit context menu
- Native OS notifications for new messages when window is unfocused
- WebSocket message interception via injected script
- Persistent cookie sessions across app restarts
- electron-builder config for macOS, Windows, and Linux packaging
- Workspace integration with root-level electron:dev/build/package scripts

* Update electron/src/notifications.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update electron/src/tray.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update electron/src/preload.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: disable electron-builder publish to prevent channel crash (#186)

* deps-dev(deps-dev): bump electron from 35.7.5 to 39.8.5 (#185)

Bumps [electron](https://github.com/electron/electron) from 35.7.5 to 39.8.5.
- [Release notes](https://github.com/electron/electron/releases)
- [Commits](electron/electron@v35.7.5...v39.8.5)

---
updated-dependencies:
- dependency-name: electron
  dependency-version: 39.8.5
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* docs: clarify Copilot CLI review command path usage (#187)

* chore: replace security-auditor agent with Copilot CLI reviews

Remove the dedicated security-auditor OpenCode agent and add a Copilot CLI
review step to AGENTS.md instead. This gives multi-model review coverage
(Opus 4.6 writes, GPT-5.4 reviews) and runs per-task rather than per-file
to keep the workflow efficient.

* docs: clarify copilot CLI file path placeholder

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/8cef0ef9-23e7-4daf-9bc5-6af13accf40c

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* deps(deps): bump hono from 4.12.11 to 4.12.12 (#189)

Bumps [hono](https://github.com/honojs/hono) from 4.12.11 to 4.12.12.
- [Release notes](https://github.com/honojs/hono/releases)
- [Commits](honojs/hono@v4.12.11...v4.12.12)

---
updated-dependencies:
- dependency-name: hono
  dependency-version: 4.12.12
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix: enforce existing Git tag guard in electron release workflow (#188)

* feat: add GitHub Actions workflow for Electron desktop releases

Add a manual-dispatch workflow that builds MLack Desktop binaries for
macOS (.dmg), Windows (.nsis), and Linux (.AppImage) in parallel, then
creates a GitHub Release with all artifacts attached.

Includes version validation, duplicate release check, branch guard
(main only), scoped permissions, and concurrency protection.

* fix: validate existing git tags in electron release workflow

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/9f1592bd-764d-4005-8c02-81a5c88659a2

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* fix: check existing release tags with git ls-remote

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/9f1592bd-764d-4005-8c02-81a5c88659a2

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* fix: resolve Electron release build failures (#190)

* fix: resolve Electron release build failures

- Replace 16x16 placeholder icon with 512x512 PNG and generate .icns
  (macOS) and .ico (Windows) files to meet electron-builder requirements
- Move version update step after dependency install so npm is available
  from the project's Node.js version rather than the runner default

* Update .github/workflows/electron-release.yml

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* fix: write explicit newline when updating Electron package version in release workflow (#191)

* fix: avoid lifecycle scripts when updating electron package version

Replace pnpm version with a direct JSON file write to prevent Electron
from launching during the version update step, which fails on Linux CI
due to SUID sandbox configuration.

* fix: use explicit newline char when writing electron package version

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/b04db865-e846-4b04-8b58-959693015c66

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* docs: align README Node.js prerequisite with Node 24 upgrade (#192)

* chore: upgrade Node.js to 24 and remove corepack

Node.js 24 no longer bundles corepack, so remove the corepack enable
steps from all CI workflows and drop the packageManager field from
package.json. Update .node-version and AGENTS.md to reflect Node 24.

* fix: install pnpm via pnpm/action-setup in CI workflows

Node.js 24 no longer bundles corepack, so pnpm must be installed
explicitly. Add pnpm/action-setup@v4 before actions/setup-node in
every CI job.

* docs: update README Node.js prerequisite to v24

Agent-Logs-Url: https://github.com/mahata/mlack/sessions/21f73092-2de8-4e30-b7eb-4dd8f51484dc

Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>

* feat: add workspaces with isolated channels, members, and invite system (#193)

* feat: add workspaces with isolated channels, members, and invite system

Introduce workspace support with path-based routing (/w/:slug/...), per-workspace
admin roles, invite links with 1-hour expiration, and one Durable Object per
workspace for WebSocket connections. Existing data auto-migrates into a seeded
'default' workspace. Migration uses PRAGMA defer_foreign_keys to handle the
channels table rebuild safely on D1.

* fix: address PR review feedback — type safety, SQL efficiency, and invite security

- Make workspace/workspaceMember optional in Variables type to match runtime
- First user auto-joining default workspace now becomes admin (bootstrap fix)
- Remove unreachable auth check in /w/:slug (middleware already handles it)
- Replace select-all-then-filter with SQL inner join for workspace queries
- Use subquery in seed.sql instead of hardcoded workspace_id=1
- Convert invite acceptance from mutating GET to GET confirmation + POST

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: mahata <23497+mahata@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants