b16e9f0bd1
Plan 0 (workspaces): add workspaces + workspace_memberships schema, extend JWT/Actor/claims with primary_workspace_id, seed default workspace per tenant, thread workspace_id through tenant monitoring quota. Plan A (desktop skeleton): new Electron app (apps/desktop-client) with main/ preload/renderer, shared Vue component package (packages/ui-shared), and server surface — desktop client registration + token rotation + heartbeat, SSE task event stream, desktop accounts/tasks/content handlers, publish job endpoint, and supporting repositories, services, sqlc queries, and migrations. Hard cutover per plan: remove browser-extension monitoring callback endpoints, stub legacy media API in admin-web, and delete monitoring_callback_handler.go.
44 lines
1.5 KiB
SQL
44 lines
1.5 KiB
SQL
CREATE TABLE workspaces (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
tenant_id BIGINT NOT NULL REFERENCES tenants(id),
|
|
name TEXT NOT NULL,
|
|
slug TEXT NOT NULL,
|
|
is_default BOOLEAN NOT NULL DEFAULT FALSE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
UNIQUE (tenant_id, slug)
|
|
);
|
|
|
|
CREATE UNIQUE INDEX idx_workspaces_tenant_default
|
|
ON workspaces (tenant_id)
|
|
WHERE is_default = TRUE;
|
|
|
|
CREATE TABLE workspace_memberships (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
workspace_id BIGINT NOT NULL REFERENCES workspaces(id) ON DELETE CASCADE,
|
|
user_id BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
tenant_id BIGINT NOT NULL REFERENCES tenants(id),
|
|
role TEXT NOT NULL DEFAULT 'member',
|
|
is_primary BOOLEAN NOT NULL DEFAULT FALSE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
UNIQUE (workspace_id, user_id)
|
|
);
|
|
|
|
CREATE UNIQUE INDEX idx_memberships_user_primary
|
|
ON workspace_memberships (user_id)
|
|
WHERE is_primary = TRUE;
|
|
|
|
INSERT INTO workspaces (tenant_id, name, slug, is_default)
|
|
SELECT id, 'Default', 'default', TRUE
|
|
FROM tenants
|
|
ON CONFLICT (tenant_id, slug) DO NOTHING;
|
|
|
|
INSERT INTO workspace_memberships (workspace_id, user_id, tenant_id, role, is_primary)
|
|
SELECT w.id, tm.user_id, tm.tenant_id, 'member', TRUE
|
|
FROM tenant_memberships tm
|
|
JOIN workspaces w
|
|
ON w.tenant_id = tm.tenant_id
|
|
AND w.is_default = TRUE
|
|
WHERE tm.deleted_at IS NULL
|
|
ON CONFLICT (workspace_id, user_id) DO NOTHING;
|