@allbluecn/web-app 0.10.3 → 0.11.1
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/package.json +24 -11
- package/public/favicon-dark.svg +1 -0
- package/public/favicon.ico +0 -0
- package/public/favicon.svg +1 -0
- package/public/logo/allblue-logo-app-icon.svg +7 -0
- package/public/logo/allblue-logo-dark-square.svg +4 -0
- package/public/logo/allblue-logo-dark.png +0 -0
- package/public/logo/allblue-logo-dark.svg +4 -0
- package/public/logo/allblue-logo-light-square.svg +4 -0
- package/public/logo/allblue-logo-light.png +0 -0
- package/public/logo/allblue-logo-light.svg +4 -0
- package/src/__tests__/bench/baselines/format-timestamp.json +44 -0
- package/src/__tests__/bench/core-hot-path.bench.ts +71 -0
- package/src/__tests__/integration/db-crud.integration.test.ts +79 -0
- package/src/__tests__/integration/login-email-acceptance.test.ts +202 -0
- package/src/__tests__/integration/login-email-p2-acceptance.test.ts +142 -0
- package/src/__tests__/rejects-tothrow-regression.test.ts +31 -0
- package/src/__tests__/security/ai/prompt-injection.test.ts +105 -0
- package/src/__tests__/security/ssrf-url-whitelist.test.ts +54 -0
- package/src/__tests__/security/xss-sanitize.test.ts +99 -0
- package/src/__tests__/setup.ts +9 -0
- package/src/__tests__/visual/__screenshots__/theme-surface.vrt.test.tsx/theme-surface-dark-baseline-1-chromium-darwin.png +0 -0
- package/src/__tests__/visual/__screenshots__/theme-surface.vrt.test.tsx/theme-surface-light-baseline-1-chromium-darwin.png +0 -0
- package/src/__tests__/visual/__screenshots__/user-avatar.vrt.test.tsx/user-avatar-initial-fallback-baseline-1-chromium-darwin.png +0 -0
- package/src/__tests__/visual/theme-surface.vrt.test.tsx +54 -0
- package/src/__tests__/visual/user-avatar.vrt.test.tsx +32 -0
- package/src/components/auth/icon-input.tsx +9 -1
- package/src/components/auth/password-input.tsx +9 -1
- package/src/components/changelog/changelog-page.tsx +44 -1
- package/src/components/error/global-error-boundary.tsx +2 -2
- package/src/components/forms/app-field.tsx +3 -1
- package/src/components/knowledge/general-groups.ts +15 -0
- package/src/components/knowledge/kb-filter-popover.tsx +143 -0
- package/src/components/knowledge/knowledge-toolbar.tsx +17 -21
- package/src/components/knowledge-public/legal-compliance-editor.tsx +4 -2
- package/src/components/layout/sidebar-03/__tests__/nav-workspace.test.tsx +9 -6
- package/src/components/layout/sidebar-03/app-sidebar.tsx +4 -15
- package/src/components/layout/sidebar-03/nav-knowledge.tsx +19 -17
- package/src/components/layout/sidebar-03/nav-workspace.tsx +20 -22
- package/src/components/notifications/settings-notifications.tsx +41 -1
- package/src/components/settings/personal-team/account/settings-profile.tsx +68 -1
- package/src/components/shared-kit/avatars/notion-avatar.tsx +2 -1
- package/src/components/shared-kit/icons/__tests__/lucide-curated-icons.test.ts +2 -2
- package/src/components/shared-kit/icons/__tests__/lucide-icon-picker.test.tsx +3 -2
- package/src/components/shared-kit/icons/lucide-icon-picker/curated-icons.ts +5 -10
- package/src/components/shared-kit/icons/lucide-icon-picker/lucide-icon-by-name.tsx +3 -3
- package/src/components/shared-kit/theme/theme-surface.tsx +52 -0
- package/src/components/story/relations/general-groups.ts +1 -15
- package/src/components/story/relations/knowledge-select-dialog.tsx +13 -87
- package/src/components/story/story-list-view.tsx +7 -1
- package/src/components/tiptap/node/table-node/ui/table-move-row-column-button/use-table-move-row-column.ts +0 -2
- package/src/components/workspace/__tests__/activity/workspace-activity-card.test.tsx +36 -0
- package/src/components/workspace/__tests__/contribution/workspace-contribution-card.test.tsx +17 -0
- package/src/components/workspace/__tests__/dialogs/create-workspace-dialog.test.tsx +63 -0
- package/src/components/workspace/__tests__/dialogs/delete-workspace-options.test.tsx +89 -0
- package/src/components/workspace/__tests__/dialogs/edit-workspace-dialog.test.tsx +68 -0
- package/src/components/workspace/__tests__/header/workspace-header.test.tsx +40 -0
- package/src/components/workspace/__tests__/kb/workspace-kb-card.test.tsx +154 -0
- package/src/components/workspace/__tests__/members/workspace-member-item.test.tsx +24 -0
- package/src/components/workspace/__tests__/members/workspace-members-manager.test.tsx +51 -0
- package/src/components/workspace/__tests__/projects/workspace-project-list.test.tsx +46 -0
- package/src/components/workspace/{create-workspace-dialog.tsx → dialogs/create-workspace-dialog.tsx} +1 -1
- package/src/components/workspace/{edit-workspace-dialog.tsx → dialogs/edit-workspace-dialog.tsx} +1 -1
- package/src/components/workspace/kb/workspace-kb-card.tsx +594 -0
- package/src/components/workspace/kb/workspace-kb-manage-dialog.tsx +174 -0
- package/src/components/workspace/kb/workspace-quick-doc-dialog.tsx +431 -0
- package/src/components/workspace/{workspace-members-manager.tsx → members/workspace-members-manager.tsx} +78 -40
- package/src/lib/__tests__/edition-desktop.test.ts +23 -0
- package/src/lib/__tests__/msw-sample.test.ts +68 -0
- package/src/lib/__tests__/pgvector.test.ts +2 -2
- package/src/lib/app-version.ts +1 -1
- package/src/lib/auth/auth.config.ts +123 -99
- package/src/lib/changelog/sdk-versions.ts +21 -21
- package/src/lib/collections/knowledge/knowledge-bases-collection.ts +3 -1
- package/src/lib/collections/reference/workspaces-collection.ts +3 -1
- package/src/lib/edition-desktop.ts +22 -0
- package/src/lib/fetch-json.ts +23 -0
- package/src/{components/workspace/workspace-kb-card.tsx → lib/i18n/resolver.ts} +6 -12
- package/src/lib/sanitize.ts +14 -1
- package/src/lib/session.ts +10 -2
- package/src/lib/vector-store/__tests__/factory.test.ts +1 -1
- package/src/lib/vector-store/__tests__/sqlite-vec-store.test.ts +2 -2
- package/src/plugins/core/tags/__tests__/tags.test.ts +10 -10
- package/src/routeTree.gen.ts +114 -0
- package/src/routes/__root.tsx +20 -3
- package/src/routes/__tests__/-auth-schemas.test.ts +62 -0
- package/src/routes/__tests__/-edition-routing.test.tsx +18 -5
- package/src/routes/__tests__/route-tree-structure.test.ts +66 -0
- package/src/routes/_login/changelog/confirm/route.lazy.tsx +72 -0
- package/src/routes/_login/changelog/confirm/route.tsx +28 -0
- package/src/routes/_login/email-unsubscribe/route.lazy.tsx +76 -0
- package/src/routes/_login/email-unsubscribe/route.tsx +28 -0
- package/src/routes/_login/forgot-password/route.lazy.tsx +2 -1
- package/src/routes/_login/login/route.lazy.tsx +4 -2
- package/src/routes/_login/register/route.lazy.tsx +28 -17
- package/src/routes/_login/register/route.tsx +8 -1
- package/src/routes/_login/reset-password/route.lazy.tsx +4 -2
- package/src/routes/_login/schemas/-auth.ts +30 -7
- package/src/routes/_login/verify-email/route.lazy.tsx +82 -0
- package/src/routes/_login/verify-email/route.tsx +28 -0
- package/src/routes/_nav/knowledge/compliance/index.lazy.tsx +5 -2
- package/src/routes/_nav/knowledge/index.lazy.tsx +1 -1
- package/src/routes/_nav/knowledge/laws/index.lazy.tsx +5 -2
- package/src/routes/_nav/route.tsx +26 -0
- package/src/routes/_nav/workspaces/$workspaceId/route.lazy.tsx +13 -11
- package/src/routes/_nav/workspaces/$workspaceId/route.tsx +4 -2
- package/src/routes/_nav/workspaces/$workspaceId/settings/route.lazy.tsx +1 -1
- package/src/routes/_nav/workspaces/index.lazy.tsx +3 -3
- package/src/routes/_public/index/route.tsx +2 -1
- package/src/routes/api/auth/desktop-callback.ts +2 -2
- package/src/routes/api/billing-webhook.ts +4 -0
- package/src/routes/api/cron/changelog-release.ts +100 -0
- package/src/routes/api/cron/subscription-reminders.ts +110 -0
- package/src/routes/api.auth.$.ts +3 -5
- package/src/server/__tests__/agent-crud.test.ts +4 -4
- package/src/server/__tests__/auth-registration.test.ts +60 -0
- package/src/server/__tests__/chat-conversations.test.ts +1 -3
- package/src/server/__tests__/fetch-guard.test.ts +99 -0
- package/src/server/__tests__/permissions.test.ts +1 -3
- package/src/server/__tests__/resources.team-seats.test.ts +2 -0
- package/src/server/__tests__/skill-crud.test.ts +3 -3
- package/src/server/ai-gateway/__tests__/ai-output-guard.test.ts +95 -0
- package/src/server/ai-gateway/__tests__/kb-context-guard.test.ts +136 -0
- package/src/server/ai-gateway/__tests__/knowledge-search-fence.test.ts +240 -0
- package/src/server/ai-gateway/__tests__/llm-fence.test.ts +125 -0
- package/src/server/ai-gateway/__tests__/run-store.test.ts +52 -0
- package/src/server/ai-gateway/ai-output-guard.ts +77 -0
- package/src/server/ai-gateway/index.ts +5 -0
- package/src/server/ai-gateway/kb-context-guard.ts +46 -0
- package/src/server/ai-gateway/llm-fence.ts +82 -0
- package/src/server/ai-gateway/persistence/run-store.ts +19 -0
- package/src/server/ai-gateway/story-prompt.ts +4 -2
- package/src/server/ai-gateway/tools/definitions.ts +12 -6
- package/src/server/ai-gateway/tools/server.ts +97 -54
- package/src/server/auth-registration.ts +40 -0
- package/src/server/billing-email.ts +39 -0
- package/src/server/builtin-project.ts +21 -0
- package/src/server/email/__tests__/deliverability.test.ts +68 -0
- package/src/server/email/__tests__/index.test.ts +32 -0
- package/src/server/email/__tests__/outbox.test.tsx +129 -0
- package/src/server/email/__tests__/product-templates.test.tsx +106 -0
- package/src/server/email/__tests__/registry.test.tsx +50 -0
- package/src/server/email/deliverability.ts +57 -0
- package/src/server/email/drivers/console.ts +11 -0
- package/src/server/email/drivers/resend.ts +31 -0
- package/src/server/email/drivers/smtp.ts +27 -0
- package/src/server/email/index.ts +56 -0
- package/src/server/email/outbox.ts +141 -0
- package/src/server/email/preferences.ts +20 -0
- package/src/server/email/registry.ts +38 -0
- package/src/server/email/sender.ts +36 -13
- package/src/server/email/templates/_base/button.tsx +12 -0
- package/src/server/email/templates/_base/email-layout.tsx +117 -0
- package/src/server/email/templates/_base/theme-fonts.tsx +43 -0
- package/src/server/email/templates/_base/theme.ts +22 -0
- package/src/server/email/templates/auth/reset-password.tsx +58 -0
- package/src/server/email/templates/auth/verify-email.tsx +59 -0
- package/src/server/email/templates/auth/welcome.tsx +49 -0
- package/src/server/email/templates/billing/payment-receipt.tsx +51 -0
- package/src/server/email/templates/billing/subscription-canceled.tsx +51 -0
- package/src/server/email/templates/billing/subscription-ending.tsx +51 -0
- package/src/server/email/templates/notification/mirror.tsx +50 -0
- package/src/server/email/templates/product/changelog-confirm.tsx +53 -0
- package/src/server/email/templates/product/changelog-release.tsx +65 -0
- package/src/server/email/templates/team/apply-notify.tsx +53 -0
- package/src/server/email/templates/team/approved.tsx +53 -0
- package/src/server/email/templates/team/invite.tsx +57 -0
- package/src/server/fetch-guard.ts +170 -0
- package/src/server/middlewares/security-headers.ts +122 -0
- package/src/server/notifications/__tests__/email-mirror.test.ts +193 -0
- package/src/server/notifications/__tests__/verify-reminder.test.ts +94 -0
- package/src/server/notifications/notification-service.ts +71 -1
- package/src/server/notifications/verify-reminder.ts +55 -0
- package/src/server/oauth-config.ts +59 -0
- package/src/server/serverFns/__tests__/auth-server-schemas.test.ts +168 -0
- package/src/server/serverFns/__tests__/billing.test.ts +263 -0
- package/src/server/serverFns/__tests__/email-verification.test.ts +149 -0
- package/src/server/serverFns/__tests__/link-preview.test.ts +239 -0
- package/src/server/serverFns/__tests__/project-kb.test.ts +3 -3
- package/src/server/serverFns/__tests__/project-team-assign.test.ts +1 -1
- package/src/server/serverFns/__tests__/story-comments.test.ts +265 -0
- package/src/server/serverFns/__tests__/story-crud-archive-detail.test.ts +266 -0
- package/src/server/serverFns/__tests__/story-crud-labels-users.test.ts +227 -0
- package/src/server/serverFns/__tests__/story-crud.test.ts +526 -0
- package/src/server/serverFns/__tests__/story-links.test.ts +262 -0
- package/src/server/serverFns/__tests__/story-list-query.test.ts +259 -0
- package/src/server/serverFns/__tests__/story-reactions.test.ts +230 -0
- package/src/server/serverFns/__tests__/story-tree.test.ts +317 -0
- package/src/server/serverFns/__tests__/story-types.test.ts +294 -0
- package/src/server/serverFns/__tests__/team-accept.test.ts +6 -6
- package/src/server/serverFns/__tests__/team-invitation.test.ts +5 -5
- package/src/server/serverFns/__tests__/team-join-request.test.ts +8 -8
- package/src/server/serverFns/__tests__/update-seats.test.ts +4 -4
- package/src/server/serverFns/__tests__/workspace-kb-idor.test.ts +160 -0
- package/src/server/serverFns/__tests__/workspace-kb-utils.test.ts +54 -0
- package/src/server/serverFns/__tests__/workspace-kb.test.ts +348 -0
- package/src/server/serverFns/__tests__/workspace.test.ts +28 -8
- package/src/server/serverFns/auth/email-verification.ts +132 -0
- package/src/server/serverFns/auth/forgot-password.ts +22 -2
- package/src/server/serverFns/auth/providers.ts +4 -3
- package/src/server/serverFns/auth/register.ts +63 -19
- package/src/server/serverFns/auth/registration-mode.ts +23 -0
- package/src/server/serverFns/auth/reset-password.ts +1 -1
- package/src/server/serverFns/auth/{invitation.ts → verify-reminder.ts} +9 -26
- package/src/server/serverFns/changelog/__tests__/subscribe.test.ts +119 -0
- package/src/server/serverFns/changelog/subscribe.ts +89 -0
- package/src/server/serverFns/email-unsubscribe.ts +66 -0
- package/src/server/serverFns/iteration/__tests__/iteration-crud.test.ts +3 -5
- package/src/server/serverFns/iteration/__tests__/iteration-stories.test.ts +1 -1
- package/src/server/serverFns/iteration/__tests__/iteration-transfer.test.ts +2 -2
- package/src/server/serverFns/kb-doc-search.ts +111 -0
- package/src/server/serverFns/knowledge-public/compliance/create.ts +2 -1
- package/src/server/serverFns/knowledge-public/legal/create.ts +2 -1
- package/src/server/serverFns/notifications.ts +10 -0
- package/src/server/serverFns/story/__tests__/bulk.test.ts +1 -1
- package/src/server/serverFns/story/__tests__/label-suggest-fn.test.ts +2 -6
- package/src/server/serverFns/story/__tests__/story-assoc.test.ts +2 -4
- package/src/server/serverFns/story/__tests__/story-dependencies.test.ts +2 -2
- package/src/server/serverFns/story/__tests__/story-groups.test.ts +2 -2
- package/src/server/serverFns/story/kb-general-consts.ts +39 -0
- package/src/server/serverFns/story/kb-general.ts +30 -17
- package/src/server/serverFns/story/story-assoc.ts +13 -103
- package/src/server/serverFns/story/story-crud.ts +2 -5
- package/src/server/serverFns/story/story-groups.ts +4 -13
- package/src/server/serverFns/team.ts +50 -12
- package/src/server/serverFns/workspace-kb-utils.ts +138 -0
- package/src/server/serverFns/workspace-kb.ts +403 -0
- package/src/server/serverFns/workspace.ts +4 -1
- package/src/shared/ai-cli/__tests__/adapter.test.ts +67 -0
- package/src/shared/ai-cli/__tests__/cli-detector.test.ts +99 -0
- package/src/shared/ai-cli/adapter.ts +2 -2
- package/src/shared/ai-cli/cli-detector.ts +18 -9
- package/src/start.ts +2 -1
- package/src/styles/globals.css +114 -0
- package/src/types/jest-dom-vitest.d.ts +8 -7
- package/vite.shared.ts +105 -4
- package/public/file.svg +0 -1
- package/public/globe.svg +0 -1
- package/public/window.svg +0 -1
- package/src/lib/__tests__/cli-detector.test.ts +0 -80
- /package/src/components/workspace/{workspace-activity-card.tsx → activity/workspace-activity-card.tsx} +0 -0
- /package/src/components/workspace/{workspace-contribution-card.tsx → contribution/workspace-contribution-card.tsx} +0 -0
- /package/src/components/workspace/{delete-workspace-options.tsx → dialogs/delete-workspace-options.tsx} +0 -0
- /package/src/components/workspace/{workspace-header.tsx → header/workspace-header.tsx} +0 -0
- /package/src/components/workspace/{workspace-member-item.tsx → members/workspace-member-item.tsx} +0 -0
- /package/src/components/workspace/{workspace-project-list.tsx → projects/workspace-project-list.tsx} +0 -0
|
@@ -10,7 +10,7 @@ export const SDK_GROUPS: SdkGroup[] = [
|
|
|
10
10
|
"name": "@tanstack/react-start",
|
|
11
11
|
"displayName": "TanStack Start",
|
|
12
12
|
"version": "v1.168.49",
|
|
13
|
-
"lastUpdate": "Sep
|
|
13
|
+
"lastUpdate": "Sep 11, 2026",
|
|
14
14
|
"source": "apps/web/package.json#dependencies",
|
|
15
15
|
"docsUrl": "https://tanstack.com/start/latest"
|
|
16
16
|
},
|
|
@@ -18,7 +18,7 @@ export const SDK_GROUPS: SdkGroup[] = [
|
|
|
18
18
|
"name": "@tanstack/react-router",
|
|
19
19
|
"displayName": "TanStack Router",
|
|
20
20
|
"version": "v1.170.32",
|
|
21
|
-
"lastUpdate": "Sep
|
|
21
|
+
"lastUpdate": "Sep 11, 2026",
|
|
22
22
|
"source": "apps/web/package.json#dependencies",
|
|
23
23
|
"docsUrl": "https://tanstack.com/router/latest"
|
|
24
24
|
},
|
|
@@ -26,7 +26,7 @@ export const SDK_GROUPS: SdkGroup[] = [
|
|
|
26
26
|
"name": "@tanstack/react-query",
|
|
27
27
|
"displayName": "TanStack Query",
|
|
28
28
|
"version": "v5.102.8",
|
|
29
|
-
"lastUpdate": "Sep
|
|
29
|
+
"lastUpdate": "Sep 11, 2026",
|
|
30
30
|
"source": "apps/web/package.json#dependencies",
|
|
31
31
|
"docsUrl": "https://tanstack.com/query/latest"
|
|
32
32
|
},
|
|
@@ -34,7 +34,7 @@ export const SDK_GROUPS: SdkGroup[] = [
|
|
|
34
34
|
"name": "@tanstack/ai",
|
|
35
35
|
"displayName": "TanStack AI",
|
|
36
36
|
"version": "v0.52.0",
|
|
37
|
-
"lastUpdate": "Sep
|
|
37
|
+
"lastUpdate": "Sep 11, 2026",
|
|
38
38
|
"source": "apps/web/package.json#dependencies",
|
|
39
39
|
"docsUrl": "https://tanstack.com/ai/latest"
|
|
40
40
|
},
|
|
@@ -42,7 +42,7 @@ export const SDK_GROUPS: SdkGroup[] = [
|
|
|
42
42
|
"name": "@tanstack/react-table",
|
|
43
43
|
"displayName": "TanStack Table",
|
|
44
44
|
"version": "v9.2.3",
|
|
45
|
-
"lastUpdate": "Sep
|
|
45
|
+
"lastUpdate": "Sep 11, 2026",
|
|
46
46
|
"source": "apps/web/package.json#dependencies",
|
|
47
47
|
"docsUrl": "https://tanstack.com/table/latest"
|
|
48
48
|
},
|
|
@@ -50,7 +50,7 @@ export const SDK_GROUPS: SdkGroup[] = [
|
|
|
50
50
|
"name": "@tanstack/react-form",
|
|
51
51
|
"displayName": "TanStack Form",
|
|
52
52
|
"version": "v2.0.0-alpha.2",
|
|
53
|
-
"lastUpdate": "Sep
|
|
53
|
+
"lastUpdate": "Sep 11, 2026",
|
|
54
54
|
"source": "apps/web/package.json#dependencies",
|
|
55
55
|
"docsUrl": "https://tanstack.com/form/latest"
|
|
56
56
|
},
|
|
@@ -58,7 +58,7 @@ export const SDK_GROUPS: SdkGroup[] = [
|
|
|
58
58
|
"name": "@tanstack/charts",
|
|
59
59
|
"displayName": "TanStack Charts",
|
|
60
60
|
"version": "v0.16.0",
|
|
61
|
-
"lastUpdate": "Sep
|
|
61
|
+
"lastUpdate": "Sep 11, 2026",
|
|
62
62
|
"source": "apps/admin/package.json#dependencies",
|
|
63
63
|
"docsUrl": "https://tanstack.com/charts/latest"
|
|
64
64
|
},
|
|
@@ -66,7 +66,7 @@ export const SDK_GROUPS: SdkGroup[] = [
|
|
|
66
66
|
"name": "@tanstack/react-pacer",
|
|
67
67
|
"displayName": "TanStack Pacer",
|
|
68
68
|
"version": "v0.23.0",
|
|
69
|
-
"lastUpdate": "Sep
|
|
69
|
+
"lastUpdate": "Sep 11, 2026",
|
|
70
70
|
"source": "apps/web/package.json#dependencies",
|
|
71
71
|
"docsUrl": "https://tanstack.com/pacer/latest"
|
|
72
72
|
},
|
|
@@ -74,7 +74,7 @@ export const SDK_GROUPS: SdkGroup[] = [
|
|
|
74
74
|
"name": "@tanstack/react-hotkeys",
|
|
75
75
|
"displayName": "TanStack Hotkeys",
|
|
76
76
|
"version": "v0.10.0",
|
|
77
|
-
"lastUpdate": "Sep
|
|
77
|
+
"lastUpdate": "Sep 11, 2026",
|
|
78
78
|
"source": "apps/web/package.json#dependencies",
|
|
79
79
|
"docsUrl": "https://tanstack.com/hotkeys/latest"
|
|
80
80
|
},
|
|
@@ -82,7 +82,7 @@ export const SDK_GROUPS: SdkGroup[] = [
|
|
|
82
82
|
"name": "@tanstack/react-virtual",
|
|
83
83
|
"displayName": "TanStack Virtual",
|
|
84
84
|
"version": "v3.14.10",
|
|
85
|
-
"lastUpdate": "Sep
|
|
85
|
+
"lastUpdate": "Sep 11, 2026",
|
|
86
86
|
"source": "apps/admin/package.json#dependencies",
|
|
87
87
|
"docsUrl": "https://tanstack.com/virtual/latest"
|
|
88
88
|
}
|
|
@@ -95,15 +95,15 @@ export const SDK_GROUPS: SdkGroup[] = [
|
|
|
95
95
|
"items": [
|
|
96
96
|
{
|
|
97
97
|
"name": "@allbluecn/web-app",
|
|
98
|
-
"version": "v0.
|
|
99
|
-
"lastUpdate": "Sep
|
|
98
|
+
"version": "v0.11.1",
|
|
99
|
+
"lastUpdate": "Sep 12, 2026",
|
|
100
100
|
"source": "apps/web/package.json",
|
|
101
101
|
"docsUrl": "https://github.com/allbluecn/allblue"
|
|
102
102
|
},
|
|
103
103
|
{
|
|
104
104
|
"name": "@allbluecn/kernel",
|
|
105
|
-
"version": "v0.
|
|
106
|
-
"lastUpdate": "Sep
|
|
105
|
+
"version": "v0.8.0",
|
|
106
|
+
"lastUpdate": "Sep 12, 2026",
|
|
107
107
|
"source": "packages/kernel/package.json",
|
|
108
108
|
"docsUrl": "https://github.com/allbluecn/allblue"
|
|
109
109
|
}
|
|
@@ -117,42 +117,42 @@ export const SDK_GROUPS: SdkGroup[] = [
|
|
|
117
117
|
{
|
|
118
118
|
"name": "Vite",
|
|
119
119
|
"version": "v8.1.5",
|
|
120
|
-
"lastUpdate": "Sep
|
|
120
|
+
"lastUpdate": "Sep 11, 2026",
|
|
121
121
|
"source": "apps/web/package.json#devDependencies",
|
|
122
122
|
"docsUrl": "https://vite.dev/"
|
|
123
123
|
},
|
|
124
124
|
{
|
|
125
125
|
"name": "Node.js",
|
|
126
126
|
"version": "v24.19.0",
|
|
127
|
-
"lastUpdate": "Sep
|
|
127
|
+
"lastUpdate": "Sep 11, 2026",
|
|
128
128
|
"source": ".nvmrc",
|
|
129
129
|
"docsUrl": "https://nodejs.org/"
|
|
130
130
|
},
|
|
131
131
|
{
|
|
132
132
|
"name": "Prisma",
|
|
133
133
|
"version": "v7.8.0",
|
|
134
|
-
"lastUpdate": "Sep
|
|
134
|
+
"lastUpdate": "Sep 11, 2026",
|
|
135
135
|
"source": "packages/database/package.json#devDependencies",
|
|
136
136
|
"docsUrl": "https://www.prisma.io/docs"
|
|
137
137
|
},
|
|
138
138
|
{
|
|
139
139
|
"name": "shadcn UI",
|
|
140
140
|
"version": "v1.2.4",
|
|
141
|
-
"lastUpdate": "Sep
|
|
141
|
+
"lastUpdate": "Sep 11, 2026",
|
|
142
142
|
"source": "apps/web/package.json#dependencies",
|
|
143
143
|
"docsUrl": "https://ui.shadcn.com/"
|
|
144
144
|
},
|
|
145
145
|
{
|
|
146
146
|
"name": "TipTap",
|
|
147
147
|
"version": "v3.27.4",
|
|
148
|
-
"lastUpdate": "Sep
|
|
148
|
+
"lastUpdate": "Sep 11, 2026",
|
|
149
149
|
"source": "apps/web/package.json#dependencies",
|
|
150
150
|
"docsUrl": "https://tiptap.dev/"
|
|
151
151
|
},
|
|
152
152
|
{
|
|
153
153
|
"name": "Lucide React",
|
|
154
|
-
"version": "v1.
|
|
155
|
-
"lastUpdate": "Sep
|
|
154
|
+
"version": "v1.43.0",
|
|
155
|
+
"lastUpdate": "Sep 11, 2026",
|
|
156
156
|
"source": "apps/web/package.json#dependencies",
|
|
157
157
|
"docsUrl": "https://lucide.dev/"
|
|
158
158
|
}
|
|
@@ -20,10 +20,12 @@ import { queryCollectionOptions } from '@tanstack/query-db-collection'
|
|
|
20
20
|
import { listKnowledgeFn } from '@/server/serverFns/knowledge'
|
|
21
21
|
import { getQueryClient } from '@/lib/query-client-seam'
|
|
22
22
|
|
|
23
|
+
export const KNOWLEDGE_BASES_QUERY_KEY = ['knowledge-bases'] as const
|
|
24
|
+
|
|
23
25
|
export const knowledgeBasesCollection = createCollection(
|
|
24
26
|
queryCollectionOptions({
|
|
25
27
|
id: 'knowledge-bases',
|
|
26
|
-
queryKey:
|
|
28
|
+
queryKey: KNOWLEDGE_BASES_QUERY_KEY,
|
|
27
29
|
queryFn: () => listKnowledgeFn(),
|
|
28
30
|
getKey: (item: { id: string }) => item.id,
|
|
29
31
|
queryClient: getQueryClient(),
|
|
@@ -20,10 +20,12 @@ import { queryCollectionOptions } from '@tanstack/query-db-collection'
|
|
|
20
20
|
import { listPinnedWorkspacesBriefFn } from '@/server/serverFns/workspace'
|
|
21
21
|
import { getQueryClient } from '@/lib/query-client-seam'
|
|
22
22
|
|
|
23
|
+
export const WORKSPACES_QUERY_KEY = ['workspaces'] as const
|
|
24
|
+
|
|
23
25
|
export const workspacesCollection = createCollection(
|
|
24
26
|
queryCollectionOptions({
|
|
25
27
|
id: 'workspaces',
|
|
26
|
-
queryKey:
|
|
28
|
+
queryKey: WORKSPACES_QUERY_KEY,
|
|
27
29
|
queryFn: () => listPinnedWorkspacesBriefFn(),
|
|
28
30
|
getKey: (item: { id: string }) => item.id,
|
|
29
31
|
queryClient: getQueryClient(),
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
// AllBlue - 理想之海
|
|
3
|
+
// Copyright (C) 2026 AllBlue Contributors
|
|
4
|
+
//
|
|
5
|
+
// This program is free software: you can redistribute it and/or modify
|
|
6
|
+
// it under the terms of the GNU Affero General Public License as published by
|
|
7
|
+
// the Free Software Foundation, either version 3 of the License, or
|
|
8
|
+
// (at your option) any later version.
|
|
9
|
+
//
|
|
10
|
+
// This program is distributed in the hope that it will be useful,
|
|
11
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
13
|
+
// GNU Affero General Public License for more details.
|
|
14
|
+
//
|
|
15
|
+
// You should have received a copy of the GNU Affero General Public License
|
|
16
|
+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
|
+
|
|
18
|
+
// beforeLoad 同构执行(SSR + 客户端导航),不能读 process.env;
|
|
19
|
+
// Vite define 已注入 import.meta.env.VITE_DEPLOY_TARGET(见 vite.shared.ts)
|
|
20
|
+
export function isDesktopEdition(): boolean {
|
|
21
|
+
return import.meta.env.VITE_DEPLOY_TARGET === 'desktop'
|
|
22
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 带默认超时与 JSON 解析的 fetch 封装(供客户端 SDK / 工具函数复用)。
|
|
3
|
+
*
|
|
4
|
+
* 默认超时 10s:接口调用应在 10 秒内返回;超过视为网络/服务异常,
|
|
5
|
+
* 由上层(React Query 等)触发重试或降级。
|
|
6
|
+
*
|
|
7
|
+
* 调用方可传入自己的 AbortSignal 覆盖默认超时(如与外层 Promise.race
|
|
8
|
+
* 联动,或用 AbortController 手动取消),不会被默认超时覆盖。
|
|
9
|
+
*
|
|
10
|
+
* @throws 当响应非 2xx 时抛 `Error`,消息含 URL 与 HTTP 状态码,便于日志定位。
|
|
11
|
+
*/
|
|
12
|
+
export async function fetchJson<T>(url: string, init?: RequestInit): Promise<T> {
|
|
13
|
+
const res = await fetch(url, {
|
|
14
|
+
...init,
|
|
15
|
+
headers: {
|
|
16
|
+
"content-type": "application/json",
|
|
17
|
+
...(init?.headers ?? {}),
|
|
18
|
+
},
|
|
19
|
+
signal: init?.signal ?? AbortSignal.timeout(10_000),
|
|
20
|
+
})
|
|
21
|
+
if (!res.ok) throw new Error(`fetchJson ${url} 失败:HTTP ${res.status}`)
|
|
22
|
+
return (await res.json()) as T
|
|
23
|
+
}
|
|
@@ -15,17 +15,11 @@
|
|
|
15
15
|
// You should have received a copy of the GNU Affero General Public License
|
|
16
16
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
import
|
|
18
|
+
// paraglide 动态 key 解析:静态具名导出(m.xxx)覆盖不到的运行时拼接 key 场景。
|
|
19
|
+
import * as messages from "@/paraglide/messages.js";
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
<LayoutGrid className="size-4 text-muted-foreground" />
|
|
26
|
-
<h2 className="text-base font-semibold">{m.workspace_home_kbTitle()}</h2>
|
|
27
|
-
</div>
|
|
28
|
-
<p className="py-4 text-center text-sm text-muted-foreground">{m.workspace_home_kbPlaceholder()}</p>
|
|
29
|
-
</div>
|
|
30
|
-
);
|
|
21
|
+
/** 按消息 key 取文案;未知 key 原样返回(便于发现缺失) */
|
|
22
|
+
export function t(key: string): string {
|
|
23
|
+
const fn = (messages as unknown as Record<string, unknown>)[key];
|
|
24
|
+
return typeof fn === "function" ? (fn as () => string)() : key;
|
|
31
25
|
}
|
package/src/lib/sanitize.ts
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import DOMPurify from 'isomorphic-dompurify'
|
|
2
2
|
|
|
3
|
+
// HTML 清理:默认配置(html + svg + mathMl profile 均启用),
|
|
4
|
+
// 覆盖富文本 diff、附件预览等 7 处 HTML 渲染场景。
|
|
3
5
|
export function sanitize(html: string): string {
|
|
4
6
|
return DOMPurify.sanitize(html)
|
|
5
|
-
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// SVG 清理:头像渲染(NotionAvatar)专用。
|
|
10
|
+
// 显式复用默认配置——DOMPurify 默认 profile 已包含 SVG 滤镜元素
|
|
11
|
+
// (<defs>/<filter>/<feMorphology>/<feFlood>/<feComposite>/<feMerge>/<feMergeNode>),
|
|
12
|
+
// 同时清除 <script>/on*/javascript: 等 XSS 载荷。
|
|
13
|
+
// 禁止改成 USE_PROFILES: { svg: true }——严格 SVG profile 会移除全部 fe* 滤镜元素,
|
|
14
|
+
// 头像轮廓辉光(feMorphology+feFlood+feComposite+feMerge)会失效渲染白屏。
|
|
15
|
+
// 结构完整性由 __tests__/security/xss-sanitize.test.ts 的双向断言锁定。
|
|
16
|
+
export function sanitizeSvg(svg: string): string {
|
|
17
|
+
return DOMPurify.sanitize(svg)
|
|
18
|
+
}
|
package/src/lib/session.ts
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
import { getSession } from 'start-authjs'
|
|
19
19
|
import type { AuthSession } from 'start-authjs'
|
|
20
|
-
import {
|
|
20
|
+
import { getAuthConfig } from './auth/auth.config'
|
|
21
21
|
|
|
22
22
|
export type SessionUser = NonNullable<AuthSession['user']> & {
|
|
23
23
|
id?: string
|
|
@@ -40,5 +40,13 @@ export type Session = Omit<AuthSession, 'user'> & { user?: SessionUser | null }
|
|
|
40
40
|
|
|
41
41
|
export async function getCurrentSession(request?: Request): Promise<Session | null> {
|
|
42
42
|
if (!request) return null
|
|
43
|
-
|
|
43
|
+
try {
|
|
44
|
+
return (await getSession(request, await getAuthConfig())) as Session | null
|
|
45
|
+
} catch (error) {
|
|
46
|
+
// JWT 解密失败(AUTH_SECRET 轮换 / 跨应用同名 cookie 污染)等效于无 session:
|
|
47
|
+
// 返回 null 走未登录分支;@auth/core 会自行清理坏 cookie。
|
|
48
|
+
// 不兜底时 JWTSessionError 会炸穿所有未捕获的调用点(route beforeLoad / serverFn)。
|
|
49
|
+
console.warn('[session] 读取 session 失败(坏 cookie 或 auth 配置异常),降级为未登录:', error instanceof Error ? error.message : error)
|
|
50
|
+
return null
|
|
51
|
+
}
|
|
44
52
|
}
|
|
@@ -54,6 +54,6 @@ describe("getVectorStore 工厂", () => {
|
|
|
54
54
|
|
|
55
55
|
it("未知 VECTOR_BACKEND 抛错", async () => {
|
|
56
56
|
process.env.VECTOR_BACKEND = "unknown_backend";
|
|
57
|
-
await expect(getVectorStore()).rejects.
|
|
57
|
+
await expect(getVectorStore()).rejects.toThrow("未知 VECTOR_BACKEND");
|
|
58
58
|
});
|
|
59
59
|
});
|
|
@@ -131,13 +131,13 @@ describe("sqliteVecStore", () => {
|
|
|
131
131
|
it("非法表名/列名抛错", async () => {
|
|
132
132
|
await expect(
|
|
133
133
|
sqliteVecStore.searchByVector([1, 0, 0, 0], "evil" as never)
|
|
134
|
-
).rejects.
|
|
134
|
+
).rejects.toThrow("非法表名");
|
|
135
135
|
await expect(
|
|
136
136
|
sqliteVecStore.deleteEmbeddings(
|
|
137
137
|
"knowledge_embeddings",
|
|
138
138
|
"evil" as never,
|
|
139
139
|
"x"
|
|
140
140
|
)
|
|
141
|
-
).rejects.
|
|
141
|
+
).rejects.toThrow("非法删除过滤列");
|
|
142
142
|
});
|
|
143
143
|
});
|
|
@@ -140,7 +140,7 @@ describe('listTagsFn', () => {
|
|
|
140
140
|
it('未登录时抛 UnauthorizedError', async () => {
|
|
141
141
|
mocks.getCurrentSession.mockResolvedValue(null)
|
|
142
142
|
|
|
143
|
-
await expect(listTagsFn()).rejects.
|
|
143
|
+
await expect(listTagsFn()).rejects.toThrow(/UNAUTHORIZED/)
|
|
144
144
|
})
|
|
145
145
|
})
|
|
146
146
|
|
|
@@ -194,7 +194,7 @@ describe('createTagFn', () => {
|
|
|
194
194
|
it('未登录时抛 UnauthorizedError', async () => {
|
|
195
195
|
mocks.getCurrentSession.mockResolvedValue(null)
|
|
196
196
|
|
|
197
|
-
await expect(createTagFn({ data: { name: 'AI' } })).rejects.
|
|
197
|
+
await expect(createTagFn({ data: { name: 'AI' } })).rejects.toThrow(/UNAUTHORIZED/)
|
|
198
198
|
})
|
|
199
199
|
})
|
|
200
200
|
|
|
@@ -227,7 +227,7 @@ describe('updateTagFn', () => {
|
|
|
227
227
|
mocks.getCurrentSession.mockResolvedValue({ user: { id: 'user-1' } })
|
|
228
228
|
mocks.findFirst.mockResolvedValue(null)
|
|
229
229
|
|
|
230
|
-
await expect(updateTagFn({ data: { id: 't-other', name: 'X' } })).rejects.
|
|
230
|
+
await expect(updateTagFn({ data: { id: 't-other', name: 'X' } })).rejects.toThrow(/FORBIDDEN/)
|
|
231
231
|
expect(mocks.update).not.toHaveBeenCalled()
|
|
232
232
|
})
|
|
233
233
|
|
|
@@ -237,13 +237,13 @@ describe('updateTagFn', () => {
|
|
|
237
237
|
.mockResolvedValueOnce({ id: 't1', name: 'AI', userId: 'user-1' })
|
|
238
238
|
.mockResolvedValueOnce({ id: 't2', name: 'AI-New', userId: 'user-1' })
|
|
239
239
|
|
|
240
|
-
await expect(updateTagFn({ data: { id: 't1', name: 'AI-New' } })).rejects.
|
|
240
|
+
await expect(updateTagFn({ data: { id: 't1', name: 'AI-New' } })).rejects.toThrow(/TAG_NAME_CONFLICT/)
|
|
241
241
|
})
|
|
242
242
|
|
|
243
243
|
it('未登录时抛 UnauthorizedError', async () => {
|
|
244
244
|
mocks.getCurrentSession.mockResolvedValue(null)
|
|
245
245
|
|
|
246
|
-
await expect(updateTagFn({ data: { id: 't1', name: 'X' } })).rejects.
|
|
246
|
+
await expect(updateTagFn({ data: { id: 't1', name: 'X' } })).rejects.toThrow(/UNAUTHORIZED/)
|
|
247
247
|
})
|
|
248
248
|
})
|
|
249
249
|
|
|
@@ -258,7 +258,7 @@ describe('deleteTagFn', () => {
|
|
|
258
258
|
mocks.getCurrentSession.mockResolvedValue({ user: { id: 'user-1' } })
|
|
259
259
|
mocks.findFirst.mockResolvedValue(null)
|
|
260
260
|
|
|
261
|
-
await expect(deleteTagFn({ data: { id: 't-other' } })).rejects.
|
|
261
|
+
await expect(deleteTagFn({ data: { id: 't-other' } })).rejects.toThrow(/FORBIDDEN/)
|
|
262
262
|
expect(mocks.update).not.toHaveBeenCalled()
|
|
263
263
|
})
|
|
264
264
|
|
|
@@ -279,7 +279,7 @@ describe('deleteTagFn', () => {
|
|
|
279
279
|
it('未登录时抛 UnauthorizedError', async () => {
|
|
280
280
|
mocks.getCurrentSession.mockResolvedValue(null)
|
|
281
281
|
|
|
282
|
-
await expect(deleteTagFn({ data: { id: 't1' } })).rejects.
|
|
282
|
+
await expect(deleteTagFn({ data: { id: 't1' } })).rejects.toThrow(/UNAUTHORIZED/)
|
|
283
283
|
})
|
|
284
284
|
})
|
|
285
285
|
|
|
@@ -329,7 +329,7 @@ describe('reorderTagsFn', () => {
|
|
|
329
329
|
it('未登录时抛 UnauthorizedError', async () => {
|
|
330
330
|
mocks.getCurrentSession.mockResolvedValue(null)
|
|
331
331
|
|
|
332
|
-
await expect(reorderTagsFn({ data: { orderedIds: ['t1'] } })).rejects.
|
|
332
|
+
await expect(reorderTagsFn({ data: { orderedIds: ['t1'] } })).rejects.toThrow(/UNAUTHORIZED/)
|
|
333
333
|
})
|
|
334
334
|
})
|
|
335
335
|
|
|
@@ -342,7 +342,7 @@ describe('assignTagsToPrdFn', () => {
|
|
|
342
342
|
mocks.getCurrentSession.mockResolvedValue({ user: { id: 'user-1' } })
|
|
343
343
|
mocks.prdFindFirst.mockResolvedValue(null)
|
|
344
344
|
|
|
345
|
-
await expect(assignTagsToPrdFn({ data: { prdId: 'p1', tagIds: ['t1'] } })).rejects.
|
|
345
|
+
await expect(assignTagsToPrdFn({ data: { prdId: 'p1', tagIds: ['t1'] } })).rejects.toThrow(/FORBIDDEN/)
|
|
346
346
|
})
|
|
347
347
|
|
|
348
348
|
it('校验 tagId 不属于自己时抛 FORBIDDEN', async () => {
|
|
@@ -350,7 +350,7 @@ describe('assignTagsToPrdFn', () => {
|
|
|
350
350
|
mocks.prdFindFirst.mockResolvedValue({ id: 'p1' })
|
|
351
351
|
mocks.findFirst.mockResolvedValue(null)
|
|
352
352
|
|
|
353
|
-
await expect(assignTagsToPrdFn({ data: { prdId: 'p1', tagIds: ['t-other'] } })).rejects.
|
|
353
|
+
await expect(assignTagsToPrdFn({ data: { prdId: 'p1', tagIds: ['t-other'] } })).rejects.toThrow(/FORBIDDEN/)
|
|
354
354
|
})
|
|
355
355
|
|
|
356
356
|
it('事务内 diff 增删', async () => {
|