create-windy 0.2.34 → 0.3.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/README.md +26 -3
- package/dist/cli.js +8121 -3746
- package/package.json +3 -3
- package/template/.windy-template.json +2 -2
- package/template/AGENTS.md +5 -0
- package/template/README.md +28 -4
- package/template/_gitignore +4 -0
- package/template/apps/agent-server/Dockerfile +1 -0
- package/template/apps/agent-server/README.md +18 -5
- package/template/apps/agent-server/adk_web_agents/__init__.py +1 -0
- package/template/apps/agent-server/adk_web_agents/safe_debug/__init__.py +3 -0
- package/template/apps/agent-server/adk_web_agents/safe_debug/agent.py +40 -0
- package/template/apps/agent-server/pyproject.toml +1 -1
- package/template/apps/agent-server/src/southwind_agent_server/adk_adapter.py +191 -16
- package/template/apps/agent-server/src/southwind_agent_server/adk_failure.py +13 -0
- package/template/apps/agent-server/src/southwind_agent_server/adk_model.py +225 -0
- package/template/apps/agent-server/src/southwind_agent_server/adk_tools.py +76 -0
- package/template/apps/agent-server/src/southwind_agent_server/app.py +1 -2
- package/template/apps/agent-server/tests/__init__.py +1 -0
- package/template/apps/agent-server/tests/openai_provider_test_support.py +131 -0
- package/template/apps/agent-server/tests/test_adk_adapter.py +305 -0
- package/template/apps/agent-server/tests/test_adk_web_agent.py +12 -0
- package/template/apps/agent-server/tests/test_openai_provider.py +7 -123
- package/template/apps/server/package.json +4 -1
- package/template/apps/server/src/agent/run-facade.ts +2 -7
- package/template/apps/server/src/agent/tool-registry.ts +2 -6
- package/template/apps/server/src/application-services.ts +50 -0
- package/template/apps/server/src/audit/drizzle-log-store.ts +25 -0
- package/template/apps/server/src/audit/search-summary.ts +2 -6
- package/template/apps/server/src/auth/credential-restriction.ts +1 -0
- package/template/apps/server/src/auth/password.ts +30 -21
- package/template/apps/server/src/auth/routes.test-support.ts +94 -0
- package/template/apps/server/src/auth/routes.test.ts +51 -78
- package/template/apps/server/src/auth/routes.ts +6 -1
- package/template/apps/server/src/auth/runtime.ts +4 -1
- package/template/apps/server/src/auth/service.ts +25 -7
- package/template/apps/server/src/configuration/bootstrap.ts +20 -1
- package/template/apps/server/src/configuration/definition.test.ts +71 -0
- package/template/apps/server/src/configuration/definition.ts +242 -12
- package/template/apps/server/src/configuration/drizzle-repository.ts +36 -2
- package/template/apps/server/src/configuration/repository.ts +27 -2
- package/template/apps/server/src/configuration/routes.ts +4 -1
- package/template/apps/server/src/configuration/service.test.ts +100 -0
- package/template/apps/server/src/configuration/service.ts +50 -10
- package/template/apps/server/src/data-access/scoped-repository.integration.test.ts +3 -2
- package/template/apps/server/src/data-governance/export/service.ts +2 -6
- package/template/apps/server/src/example-modules.ts +4 -1
- package/template/apps/server/src/guards.ts +18 -5
- package/template/apps/server/src/http/request-source.test.ts +85 -0
- package/template/apps/server/src/http/request-source.ts +90 -0
- package/template/apps/server/src/index.ts +40 -40
- package/template/apps/server/src/license/routes.ts +2 -0
- package/template/apps/server/src/license/runtime-service.ts +10 -11
- package/template/apps/server/src/mcp/adapter.test.ts +3 -2
- package/template/apps/server/src/mcp/adapter.ts +9 -9
- package/template/apps/server/src/mcp/routes.ts +4 -3
- package/template/apps/server/src/module-bootstrap.ts +2 -2
- package/template/apps/server/src/module-host/request-context.ts +6 -6
- package/template/apps/server/src/module-host/storage-scope.ts +2 -9
- package/template/apps/server/src/module-host/user-directory-port.ts +2 -6
- package/template/apps/server/src/notification/channel-adapter.ts +46 -0
- package/template/apps/server/src/notification/delivery-policy.test.ts +59 -0
- package/template/apps/server/src/notification/delivery-policy.ts +37 -0
- package/template/apps/server/src/notification/delivery-repository.ts +198 -0
- package/template/apps/server/src/notification/delivery-worker.test.ts +87 -0
- package/template/apps/server/src/notification/delivery-worker.ts +88 -0
- package/template/apps/server/src/notification/drizzle-management.ts +180 -0
- package/template/apps/server/src/notification/drizzle-query.ts +160 -0
- package/template/apps/server/src/notification/drizzle-repository.integration.test.ts +301 -0
- package/template/apps/server/src/notification/drizzle-repository.ts +156 -90
- package/template/apps/server/src/notification/extension-routes.test.ts +119 -0
- package/template/apps/server/src/notification/extension-routes.ts +111 -0
- package/template/apps/server/src/notification/memory-delivery-repository.ts +137 -0
- package/template/apps/server/src/notification/memory-support.ts +72 -0
- package/template/apps/server/src/notification/preference-repository.ts +95 -0
- package/template/apps/server/src/notification/recipient-directory.ts +104 -0
- package/template/apps/server/src/notification/repository.test.ts +171 -0
- package/template/apps/server/src/notification/repository.ts +179 -32
- package/template/apps/server/src/notification/revision-routes.test.ts +186 -0
- package/template/apps/server/src/notification/route-support.ts +225 -0
- package/template/apps/server/src/notification/routes.test.ts +182 -0
- package/template/apps/server/src/notification/routes.ts +225 -132
- package/template/apps/server/src/notification/service.test.ts +104 -0
- package/template/apps/server/src/notification/service.ts +140 -0
- package/template/apps/server/src/notification/smtp-adapter.test.ts +65 -0
- package/template/apps/server/src/notification/smtp-adapter.ts +68 -0
- package/template/apps/server/src/persistence.integration.test.ts +41 -2
- package/template/apps/server/src/platform-http-runtime.ts +87 -0
- package/template/apps/server/src/route-guards.ts +1 -0
- package/template/apps/server/src/runtime-audit-list.test.ts +39 -0
- package/template/apps/server/src/runtime-development.ts +1 -0
- package/template/apps/server/src/runtime.test.ts +23 -9
- package/template/apps/server/src/runtime.ts +39 -2
- package/template/apps/server/src/scheduler/audit.ts +2 -11
- package/template/apps/server/src/scheduler/definitions.test.ts +6 -0
- package/template/apps/server/src/scheduler/definitions.ts +7 -0
- package/template/apps/server/src/scheduler/recovery-service.ts +2 -11
- package/template/apps/server/src/scheduler/routes.ts +2 -7
- package/template/apps/server/src/search/opensearch-client.test.ts +45 -0
- package/template/apps/server/src/search/opensearch-client.ts +145 -0
- package/template/apps/server/src/search/service.ts +2 -6
- package/template/apps/server/src/settings/routes.ts +15 -3
- package/template/apps/server/src/settings/runtime.ts +10 -1
- package/template/apps/server/src/storage/runtime.ts +13 -0
- package/template/apps/server/src/system/audit-query.ts +33 -4
- package/template/apps/server/src/system/audit-routes.test.ts +58 -4
- package/template/apps/server/src/system/audit-routes.ts +6 -5
- package/template/apps/server/src/system/department-organization.ts +320 -0
- package/template/apps/server/src/system/department-routes.test.ts +207 -48
- package/template/apps/server/src/system/department-routes.ts +114 -33
- package/template/apps/server/src/system/drizzle-repository.ts +15 -7
- package/template/apps/server/src/system/drizzle-scoped-repository.ts +5 -3
- package/template/apps/server/src/system/drizzle-system-configs.ts +319 -0
- package/template/apps/server/src/system/drizzle-system.ts +59 -311
- package/template/apps/server/src/system/drizzle-transaction-context.ts +14 -0
- package/template/apps/server/src/system/identity-route-config.ts +7 -2
- package/template/apps/server/src/system/mutation-runner.ts +23 -0
- package/template/apps/server/src/system/organization-postgres.integration.test.ts +176 -0
- package/template/apps/server/src/system/resource-access-response.ts +12 -6
- package/template/apps/server/src/system/resource-routes.ts +270 -0
- package/template/apps/server/src/system/role-department-scope-policy.ts +55 -0
- package/template/apps/server/src/system/route-helpers.ts +2 -5
- package/template/apps/server/src/system/route-types.ts +12 -3
- package/template/apps/server/src/system/routes-validation.test.ts +26 -0
- package/template/apps/server/src/system/routes.test.ts +10 -2
- package/template/apps/server/src/system/routes.ts +35 -267
- package/template/apps/server/src/system/seed.ts +7 -0
- package/template/apps/server/src/work-order/data-scope.integration.test.ts +9 -2
- package/template/apps/server/src/work-order/opensearch-index.test.ts +97 -0
- package/template/apps/server/src/work-order/opensearch-index.ts +313 -0
- package/template/apps/server/src/work-order/search-provider.ts +60 -1
- package/template/apps/server/src/work-order/service.ts +42 -10
- package/template/apps/web/src/app/error-pages.ts +9 -0
- package/template/apps/web/src/components/auth/PasswordChangeForm.vue +16 -11
- package/template/apps/web/src/components/auth/PasswordChangeForm.webtest.ts +14 -0
- package/template/apps/web/src/components/common/FormDialog.vue +16 -2
- package/template/apps/web/src/components/common/ModalLayout.webtest.ts +20 -1
- package/template/apps/web/src/composables/useGlobalSearch.ts +68 -0
- package/template/apps/web/src/composables/usePlatformSettings.ts +8 -7
- package/template/apps/web/src/layout/GlobalSearchResults.vue +58 -0
- package/template/apps/web/src/layout/NavigationSearchDialog.vue +42 -6
- package/template/apps/web/src/layout/NavigationSearchDialog.webtest.ts +71 -0
- package/template/apps/web/src/layout/NotificationMenu.vue +73 -31
- package/template/apps/web/src/layout/NotificationMenu.webtest.ts +44 -1
- package/template/apps/web/src/layout/NotificationMenuItem.vue +61 -0
- package/template/apps/web/src/layout/NotificationPreferencesDialog.vue +181 -0
- package/template/apps/web/src/layout/NotificationPreferencesDialog.webtest.ts +80 -0
- package/template/apps/web/src/lib/date-time.ts +22 -10
- package/template/apps/web/src/lib/date-time.webtest.ts +9 -1
- package/template/apps/web/src/main.ts +14 -1
- package/template/apps/web/src/pages/auth/ChangePasswordPage.vue +16 -1
- package/template/apps/web/src/pages/configuration/components/ModuleConfigVersionList.vue +1 -0
- package/template/apps/web/src/pages/configuration/components/ModuleConfigurationEditor.vue +10 -0
- package/template/apps/web/src/pages/configuration/components/ModuleConfigurationWorkbench.vue +37 -6
- package/template/apps/web/src/pages/errors/PlatformErrorPage.vue +115 -0
- package/template/apps/web/src/pages/errors/PlatformErrorPage.webtest.ts +44 -0
- package/template/apps/web/src/pages/errors/error-page-extension.ts +26 -0
- package/template/apps/web/src/pages/system/SystemNotificationsPage.vue +136 -68
- package/template/apps/web/src/pages/system/SystemNotificationsPage.webtest.ts +224 -12
- package/template/apps/web/src/pages/system/audit-log-presenter.ts +86 -0
- package/template/apps/web/src/pages/system/audit-time-range.ts +28 -0
- package/template/apps/web/src/pages/system/components/AuditActionCell.vue +10 -69
- package/template/apps/web/src/pages/system/components/AuditActionCell.webtest.ts +20 -27
- package/template/apps/web/src/pages/system/components/AuditLogDetailDialog.vue +134 -0
- package/template/apps/web/src/pages/system/components/AuditLogDetailDialog.webtest.ts +76 -0
- package/template/apps/web/src/pages/system/components/AuditLogFilters.vue +116 -52
- package/template/apps/web/src/pages/system/components/AuditLogFilters.webtest.ts +52 -15
- package/template/apps/web/src/pages/system/components/NotificationHistoryDialog.vue +129 -0
- package/template/apps/web/src/pages/system/components/NotificationManagementCard.vue +91 -0
- package/template/apps/web/src/pages/system/components/NotificationPublishDialog.vue +121 -0
- package/template/apps/web/src/pages/system/components/NotificationPublishForm.vue +162 -1
- package/template/apps/web/src/pages/system/components/SystemResourceActions.vue +68 -0
- package/template/apps/web/src/pages/system/components/SystemResourceEditor.vue +74 -0
- package/template/apps/web/src/pages/system/components/SystemResourceFilters.vue +3 -4
- package/template/apps/web/src/pages/system/components/SystemResourceLoadError.vue +21 -0
- package/template/apps/web/src/pages/system/components/SystemResourceLoadError.webtest.ts +17 -0
- package/template/apps/web/src/pages/system/components/SystemResourcePage.vue +96 -108
- package/template/apps/web/src/pages/system/components/SystemResourcePage.webtest.ts +68 -0
- package/template/apps/web/src/pages/system/components/SystemResourceTable.vue +20 -1
- package/template/apps/web/src/pages/system/components/SystemResourceTable.webtest.ts +28 -7
- package/template/apps/web/src/pages/system/components/department/DepartmentOrganizationForm.vue +210 -0
- package/template/apps/web/src/pages/system/components/department/DepartmentTransitionDialog.vue +112 -0
- package/template/apps/web/src/pages/system/components/user-account/UserAccountForm.vue +17 -4
- package/template/apps/web/src/pages/system/composables/useDepartmentTransitions.ts +79 -0
- package/template/apps/web/src/pages/system/composables/useNotificationPermissions.ts +14 -0
- package/template/apps/web/src/pages/system/composables/useSystemResource.ts +2 -0
- package/template/apps/web/src/pages/system/composables/useSystemResource.webtest.ts +15 -2
- package/template/apps/web/src/pages/system/resource-config.ts +12 -4
- package/template/apps/web/src/router/error-navigation.ts +50 -0
- package/template/apps/web/src/router/error-navigation.webtest.ts +106 -0
- package/template/apps/web/src/router/index.ts +71 -0
- package/template/apps/web/src/router/index.webtest.ts +29 -0
- package/template/apps/web/src/router/manifest-routes.webtest.ts +4 -0
- package/template/apps/web/src/router/shared-scaffold-neutrality.webtest.ts +12 -0
- package/template/apps/web/src/services/auth-api.ts +5 -0
- package/template/apps/web/src/services/http.ts +43 -6
- package/template/apps/web/src/services/http.webtest.ts +70 -0
- package/template/apps/web/src/services/notification-api.ts +85 -2
- package/template/apps/web/src/services/notification-api.webtest.ts +110 -0
- package/template/apps/web/src/services/search-api.ts +39 -0
- package/template/apps/web/src/services/system-api.ts +18 -0
- package/template/apps/web/vitest.config.ts +1 -0
- package/template/docker-compose.yml +66 -0
- package/template/docs/architecture/ai-runtime.md +14 -5
- package/template/docs/architecture/mcp-business-capabilities.md +107 -0
- package/template/docs/architecture/search-provider-protocol.md +38 -2
- package/template/docs/development/custom-error-pages.md +78 -0
- package/template/docs/development/custom-login-page.md +3 -3
- package/template/docs/platform/agent-runtime.md +32 -6
- package/template/docs/platform/agent-tools.md +4 -0
- package/template/docs/platform/audit-reliability.md +46 -2
- package/template/docs/platform/module-configuration.md +13 -4
- package/template/docs/platform/notifications.md +67 -11
- package/template/docs/platform/organization-membership.md +17 -3
- package/template/docs/platform/system-crud-api.md +16 -0
- package/template/docs/platform/web-system-crud.md +6 -2
- package/template/package.json +4 -0
- package/template/packages/config/index.test.ts +45 -0
- package/template/packages/config/package.json +1 -1
- package/template/packages/config/src/platform.ts +169 -48
- package/template/packages/database/drizzle/0035_material_nightshade.sql +10 -0
- package/template/packages/database/drizzle/0036_hesitant_speed.sql +35 -0
- package/template/packages/database/drizzle/0037_absent_nick_fury.sql +2 -0
- package/template/packages/database/drizzle/0038_uneven_wasp.sql +38 -0
- package/template/packages/database/drizzle/meta/0035_snapshot.json +7331 -0
- package/template/packages/database/drizzle/meta/0036_snapshot.json +7436 -0
- package/template/packages/database/drizzle/meta/0037_snapshot.json +7457 -0
- package/template/packages/database/drizzle/meta/0038_snapshot.json +7749 -0
- package/template/packages/database/drizzle/meta/_journal.json +28 -0
- package/template/packages/database/package.json +1 -1
- package/template/packages/database/src/schema/identity.ts +7 -0
- package/template/packages/database/src/schema/notifications.ts +135 -0
- package/template/packages/database/src/schema-notification-delivery.test.ts +54 -0
- package/template/packages/database/src/schema-workflow-notification.test.ts +40 -1
- package/template/packages/modules/package.json +1 -1
- package/template/packages/modules/src/composition-fixtures.test-support.ts +164 -0
- package/template/packages/modules/src/composition.test.ts +5 -158
- package/template/packages/modules/src/system-api-operational.ts +234 -0
- package/template/packages/modules/src/system-api-permissions.ts +14 -181
- package/template/packages/modules/src/system-audit-actions.ts +10 -0
- package/template/packages/modules/src/system-features.ts +1 -1
- package/template/packages/modules/src/system-module-catalog.ts +2 -1
- package/template/packages/modules/src/system-module-tasks.ts +86 -0
- package/template/packages/modules/src/system-modules-access.test.ts +60 -0
- package/template/packages/modules/src/system-modules.test.ts +13 -54
- package/template/packages/modules/src/system-modules.ts +2 -72
- package/template/packages/modules/src/system-permissions.ts +9 -5
- package/template/packages/server-sdk/package.json +1 -1
- package/template/packages/shared/index.ts +1 -0
- package/template/packages/shared/package.json +1 -1
- package/template/packages/shared/src/audit.ts +25 -0
- package/template/packages/shared/src/mcp.test.ts +12 -0
- package/template/packages/shared/src/mcp.ts +7 -0
- package/template/packages/shared/src/module-configuration.ts +5 -0
- package/template/packages/shared/src/notification.ts +92 -1
- package/template/packages/shared/src/password.ts +7 -2
- package/template/packages/shared/src/platform-settings.ts +2 -0
- package/template/packages/storage/package.json +1 -1
- package/template/packages/storage/src/upload-service.test.ts +16 -0
- package/template/packages/storage/src/upload-service.ts +5 -1
- package/template/scripts/notification-postgres-regression.ts +27 -0
|
@@ -220,7 +220,7 @@ describe("系统模块能力注册", () => {
|
|
|
220
220
|
expect(catalogs).toEqual(["组织与权限", "平台配置", "安全与合规", "运维"]);
|
|
221
221
|
});
|
|
222
222
|
|
|
223
|
-
test("
|
|
223
|
+
test("部门创建与迁移处置绑定独立权限、Feature 和审计动作", () => {
|
|
224
224
|
const manifest = systemFoundationModule();
|
|
225
225
|
expect(
|
|
226
226
|
manifest.permissions.some(
|
|
@@ -234,6 +234,18 @@ describe("系统模块能力注册", () => {
|
|
|
234
234
|
featureKey: "system.rbac",
|
|
235
235
|
anonymous: undefined,
|
|
236
236
|
});
|
|
237
|
+
expect(manifest.apiPermissions).toContainEqual({
|
|
238
|
+
method: "POST",
|
|
239
|
+
path: "/api/system/departments/:id/transition",
|
|
240
|
+
permissionKey: "system.department.manage",
|
|
241
|
+
featureKey: "system.rbac",
|
|
242
|
+
anonymous: undefined,
|
|
243
|
+
});
|
|
244
|
+
expect(manifest.auditActions).toContainEqual(
|
|
245
|
+
expect.objectContaining({
|
|
246
|
+
key: "organization.department.transition",
|
|
247
|
+
}),
|
|
248
|
+
);
|
|
237
249
|
});
|
|
238
250
|
|
|
239
251
|
test("所有权限都由 Manifest 提供稳定中文分组元数据", () => {
|
|
@@ -305,59 +317,6 @@ describe("系统模块能力注册", () => {
|
|
|
305
317
|
]);
|
|
306
318
|
});
|
|
307
319
|
// @windy-module system.configuration end
|
|
308
|
-
|
|
309
|
-
test("管理面准入使用独立 Feature 与 access 权限", () => {
|
|
310
|
-
const manifest = systemFoundationModule();
|
|
311
|
-
|
|
312
|
-
expect(manifest.features).toContainEqual(
|
|
313
|
-
expect.objectContaining({ key: "system.admin", enabled: true }),
|
|
314
|
-
);
|
|
315
|
-
expect(manifest.permissions).toContainEqual(
|
|
316
|
-
expect.objectContaining({
|
|
317
|
-
key: "system.admin.access",
|
|
318
|
-
action: "access",
|
|
319
|
-
}),
|
|
320
|
-
);
|
|
321
|
-
expect(manifest.apiPermissions).toContainEqual({
|
|
322
|
-
method: "GET",
|
|
323
|
-
path: "/api/admin/bootstrap",
|
|
324
|
-
permissionKey: "system.admin.access",
|
|
325
|
-
featureKey: "system.admin",
|
|
326
|
-
anonymous: undefined,
|
|
327
|
-
});
|
|
328
|
-
});
|
|
329
|
-
|
|
330
|
-
// @windy-module system.agent begin
|
|
331
|
-
test("MCP Streamable HTTP 入口统一绑定 Agent Feature 与读取权限", () => {
|
|
332
|
-
const bindings = systemFoundationModule().apiPermissions.filter(
|
|
333
|
-
({ path }) => path === "/api/mcp",
|
|
334
|
-
);
|
|
335
|
-
|
|
336
|
-
expect(bindings).toEqual([
|
|
337
|
-
{
|
|
338
|
-
method: "GET",
|
|
339
|
-
path: "/api/mcp",
|
|
340
|
-
permissionKey: "system.agent.read",
|
|
341
|
-
featureKey: "system.agent",
|
|
342
|
-
anonymous: undefined,
|
|
343
|
-
},
|
|
344
|
-
{
|
|
345
|
-
method: "POST",
|
|
346
|
-
path: "/api/mcp",
|
|
347
|
-
permissionKey: "system.agent.read",
|
|
348
|
-
featureKey: "system.agent",
|
|
349
|
-
anonymous: undefined,
|
|
350
|
-
},
|
|
351
|
-
{
|
|
352
|
-
method: "DELETE",
|
|
353
|
-
path: "/api/mcp",
|
|
354
|
-
permissionKey: "system.agent.read",
|
|
355
|
-
featureKey: "system.agent",
|
|
356
|
-
anonymous: undefined,
|
|
357
|
-
},
|
|
358
|
-
]);
|
|
359
|
-
});
|
|
360
|
-
// @windy-module system.agent end
|
|
361
320
|
});
|
|
362
321
|
|
|
363
322
|
function flattenMenuKeys(
|
|
@@ -12,6 +12,7 @@ import { systemAuditActions } from "./system-audit-actions.js";
|
|
|
12
12
|
import { systemDataPolicies } from "./system-data-governance.js";
|
|
13
13
|
// @windy-module system.data-governance end
|
|
14
14
|
import { systemFeatures } from "./system-features.js";
|
|
15
|
+
import { systemModuleTasks } from "./system-module-tasks.js";
|
|
15
16
|
import { systemPermissions } from "./system-permissions.js";
|
|
16
17
|
|
|
17
18
|
export function systemFoundationModule(): ModuleManifest {
|
|
@@ -257,78 +258,7 @@ export function systemFoundationModule(): ModuleManifest {
|
|
|
257
258
|
...systemAgentToolSchemas,
|
|
258
259
|
// @windy-module system.agent end
|
|
259
260
|
],
|
|
260
|
-
tasks:
|
|
261
|
-
// @windy-module system.scheduler begin
|
|
262
|
-
{
|
|
263
|
-
key: "system.scheduler.health-snapshot",
|
|
264
|
-
label: "调度器健康快照",
|
|
265
|
-
description: "周期验证调度、Guard、执行历史和重试链路可用。",
|
|
266
|
-
permissionKey: "system.scheduler.manage",
|
|
267
|
-
featureKey: "system.scheduler",
|
|
268
|
-
intervalSeconds: 300,
|
|
269
|
-
maxAttempts: 3,
|
|
270
|
-
retryDelaySeconds: 30,
|
|
271
|
-
},
|
|
272
|
-
// @windy-module system.scheduler end
|
|
273
|
-
// @windy-module system.bulk-data begin
|
|
274
|
-
{
|
|
275
|
-
key: "system.bulk-data.dispatch",
|
|
276
|
-
label: "批量数据任务派发",
|
|
277
|
-
description: "领取一个已排队或到期重试的批量导入导出任务。",
|
|
278
|
-
permissionKey: "system.bulk-data.manage",
|
|
279
|
-
featureKey: "system.bulk-data",
|
|
280
|
-
intervalSeconds: 5,
|
|
281
|
-
maxAttempts: 3,
|
|
282
|
-
retryDelaySeconds: 30,
|
|
283
|
-
},
|
|
284
|
-
{
|
|
285
|
-
key: "system.bulk-data.cleanup",
|
|
286
|
-
label: "批量数据文件清理",
|
|
287
|
-
description: "清理超过留存期限的源文件、结果和失败明细。",
|
|
288
|
-
permissionKey: "system.bulk-data.manage",
|
|
289
|
-
featureKey: "system.bulk-data",
|
|
290
|
-
intervalSeconds: 3_600,
|
|
291
|
-
maxAttempts: 3,
|
|
292
|
-
retryDelaySeconds: 60,
|
|
293
|
-
},
|
|
294
|
-
// @windy-module system.bulk-data end
|
|
295
|
-
// @windy-module system.storage begin
|
|
296
|
-
{
|
|
297
|
-
key: "system.storage.cleanup",
|
|
298
|
-
label: "文件存储清理",
|
|
299
|
-
description: "清理过期上传、文件、临时分片和超过宽限期的孤儿对象。",
|
|
300
|
-
permissionKey: "system.storage.manage",
|
|
301
|
-
featureKey: "system.storage",
|
|
302
|
-
intervalSeconds: 3_600,
|
|
303
|
-
maxAttempts: 3,
|
|
304
|
-
retryDelaySeconds: 60,
|
|
305
|
-
},
|
|
306
|
-
// @windy-module system.storage end
|
|
307
|
-
// @windy-module system.workflow begin
|
|
308
|
-
{
|
|
309
|
-
key: "system.workflow.timeout-dispatch",
|
|
310
|
-
label: "审批超时派发",
|
|
311
|
-
description: "补偿登记并执行一个到期审批任务,进程重启后继续处理。",
|
|
312
|
-
permissionKey: "system.workflow.manage",
|
|
313
|
-
featureKey: "system.workflow",
|
|
314
|
-
intervalSeconds: 5,
|
|
315
|
-
maxAttempts: 3,
|
|
316
|
-
retryDelaySeconds: 30,
|
|
317
|
-
},
|
|
318
|
-
// @windy-module system.workflow end
|
|
319
|
-
// @windy-module system.data-governance begin
|
|
320
|
-
{
|
|
321
|
-
key: "system.governed-export.dispatch",
|
|
322
|
-
label: "受治理导出派发",
|
|
323
|
-
description: "领取并执行一个已批准的敏感数据导出任务。",
|
|
324
|
-
permissionKey: "system.user.export",
|
|
325
|
-
featureKey: "system.rbac",
|
|
326
|
-
intervalSeconds: 5,
|
|
327
|
-
maxAttempts: 3,
|
|
328
|
-
retryDelaySeconds: 30,
|
|
329
|
-
},
|
|
330
|
-
// @windy-module system.data-governance end
|
|
331
|
-
],
|
|
261
|
+
tasks: systemModuleTasks,
|
|
332
262
|
tools: [
|
|
333
263
|
// @windy-module system.agent begin
|
|
334
264
|
...systemAgentTools,
|
|
@@ -33,6 +33,7 @@ type SystemAction =
|
|
|
33
33
|
| "approve"
|
|
34
34
|
| "export"
|
|
35
35
|
| "reveal"
|
|
36
|
+
| "update"
|
|
36
37
|
| "manage";
|
|
37
38
|
|
|
38
39
|
function permission(
|
|
@@ -54,11 +55,13 @@ function permission(
|
|
|
54
55
|
? "新建"
|
|
55
56
|
: action === "approve"
|
|
56
57
|
? "处理"
|
|
57
|
-
: action === "
|
|
58
|
-
? "
|
|
59
|
-
: action === "
|
|
60
|
-
? "
|
|
61
|
-
: "
|
|
58
|
+
: action === "update"
|
|
59
|
+
? "修改"
|
|
60
|
+
: action === "reveal"
|
|
61
|
+
? "查看明文"
|
|
62
|
+
: action === "export"
|
|
63
|
+
? "治理导出"
|
|
64
|
+
: "管理",
|
|
62
65
|
module: "system",
|
|
63
66
|
moduleLabel: "系统基础设施",
|
|
64
67
|
resource,
|
|
@@ -125,6 +128,7 @@ export const systemPermissions: ModuleManifest["permissions"] = [
|
|
|
125
128
|
// @windy-module system.scheduler end
|
|
126
129
|
// @windy-module system.notification begin
|
|
127
130
|
permission("notification", "read"),
|
|
131
|
+
permission("notification", "update"),
|
|
128
132
|
permission("notification", "manage"),
|
|
129
133
|
// @windy-module system.notification end
|
|
130
134
|
// @windy-module system.bulk-data begin
|
|
@@ -7,6 +7,7 @@ export * from "./src/license-catalog.js";
|
|
|
7
7
|
export * from "./src/json.js";
|
|
8
8
|
export * from "./src/migration.js";
|
|
9
9
|
export * from "./src/migration-bundle-validation.js";
|
|
10
|
+
export * from "./src/mcp.js";
|
|
10
11
|
export * from "./src/module-configuration.js";
|
|
11
12
|
export * from "./src/correlation.js";
|
|
12
13
|
export * from "./src/notification.js";
|
|
@@ -145,11 +145,36 @@ export const AUDIT_ACTION_DEFINITIONS = [
|
|
|
145
145
|
label: "通知发布",
|
|
146
146
|
description: "发布站内通知。",
|
|
147
147
|
},
|
|
148
|
+
{
|
|
149
|
+
key: "notification.schedule",
|
|
150
|
+
label: "通知定时发布",
|
|
151
|
+
description: "创建等待调度器发布的通知。",
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
key: "notification.preference.update",
|
|
155
|
+
label: "通知偏好更新",
|
|
156
|
+
description: "用户更新外部通知渠道和分类偏好。",
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
key: "notification.update",
|
|
160
|
+
label: "通知修改",
|
|
161
|
+
description: "修改已发布通知并保留版本历史。",
|
|
162
|
+
},
|
|
148
163
|
{
|
|
149
164
|
key: "notification.read",
|
|
150
165
|
label: "通知已读",
|
|
151
166
|
description: "用户阅读站内通知。",
|
|
152
167
|
},
|
|
168
|
+
{
|
|
169
|
+
key: "notification.favorite",
|
|
170
|
+
label: "收藏通知",
|
|
171
|
+
description: "用户收藏可见的站内通知。",
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
key: "notification.unfavorite",
|
|
175
|
+
label: "取消收藏通知",
|
|
176
|
+
description: "用户取消收藏可见的站内通知。",
|
|
177
|
+
},
|
|
153
178
|
{
|
|
154
179
|
key: "notification.archive",
|
|
155
180
|
label: "通知归档",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
import { MCP_API_PATH, MCP_ROUTE_PATH, MCP_SERVER_INFO } from "./mcp.js";
|
|
3
|
+
|
|
4
|
+
describe("MCP public contract", () => {
|
|
5
|
+
test("HTTP 路径与 Server 身份使用稳定单一来源", () => {
|
|
6
|
+
expect(MCP_API_PATH).toBe(`/api${MCP_ROUTE_PATH}`);
|
|
7
|
+
expect(MCP_SERVER_INFO).toEqual({
|
|
8
|
+
name: "windy-platform",
|
|
9
|
+
version: "0.1.0",
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
});
|
|
@@ -5,8 +5,11 @@ export type ModuleConfigApplyStatus =
|
|
|
5
5
|
| "applying"
|
|
6
6
|
| "effective"
|
|
7
7
|
| "failed"
|
|
8
|
+
| "pending-restart"
|
|
8
9
|
| "superseded";
|
|
9
10
|
|
|
11
|
+
export type ModuleConfigApplyMode = "live" | "restart";
|
|
12
|
+
|
|
10
13
|
export interface ModuleConfigDiffEntry {
|
|
11
14
|
path: string;
|
|
12
15
|
before?: ModuleConfigValue;
|
|
@@ -18,6 +21,7 @@ export interface ModuleConfigFieldDescriptor {
|
|
|
18
21
|
label: string;
|
|
19
22
|
description: string;
|
|
20
23
|
input: "boolean" | "integer" | "text";
|
|
24
|
+
applyMode?: ModuleConfigApplyMode;
|
|
21
25
|
minimum?: number;
|
|
22
26
|
maximum?: number;
|
|
23
27
|
}
|
|
@@ -42,6 +46,7 @@ export interface ModuleConfigSummary {
|
|
|
42
46
|
label: string;
|
|
43
47
|
fields: ModuleConfigFieldDescriptor[];
|
|
44
48
|
effectiveValues: ModuleConfigValues;
|
|
49
|
+
pendingValues?: ModuleConfigValues;
|
|
45
50
|
effectiveSource: "environment" | "version";
|
|
46
51
|
effectiveVersion?: number;
|
|
47
52
|
latestVersion?: number;
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import type { ISODateTime } from "./primitives.js";
|
|
2
2
|
import type { TargetRef } from "./workflow.js";
|
|
3
3
|
|
|
4
|
-
export type NotificationStatus = "published" | "archived";
|
|
4
|
+
export type NotificationStatus = "scheduled" | "published" | "archived";
|
|
5
|
+
export type ExternalNotificationChannel = "email" | "sms";
|
|
6
|
+
export type NotificationDeliveryStatus =
|
|
7
|
+
| "pending"
|
|
8
|
+
| "processing"
|
|
9
|
+
| "retrying"
|
|
10
|
+
| "delivered"
|
|
11
|
+
| "dead";
|
|
5
12
|
|
|
6
13
|
export interface PlatformNotification {
|
|
7
14
|
id: string;
|
|
@@ -11,6 +18,7 @@ export interface PlatformNotification {
|
|
|
11
18
|
category: string;
|
|
12
19
|
status: NotificationStatus;
|
|
13
20
|
publishedAt: ISODateTime;
|
|
21
|
+
scheduledFor?: ISODateTime;
|
|
14
22
|
createdAt: ISODateTime;
|
|
15
23
|
createdBy: string;
|
|
16
24
|
updatedAt: ISODateTime;
|
|
@@ -19,13 +27,29 @@ export interface PlatformNotification {
|
|
|
19
27
|
archivedBy?: string;
|
|
20
28
|
target?: TargetRef;
|
|
21
29
|
recipientUserId?: string;
|
|
30
|
+
recipientUserIds?: string[];
|
|
22
31
|
recipientRoleCodes?: string[];
|
|
32
|
+
recipientDepartmentIds?: string[];
|
|
33
|
+
includeChildDepartments?: boolean;
|
|
34
|
+
deliveryChannels?: ExternalNotificationChannel[];
|
|
23
35
|
sourceKey?: string;
|
|
36
|
+
revision: number;
|
|
24
37
|
}
|
|
25
38
|
|
|
26
39
|
export interface NotificationInboxItem extends PlatformNotification {
|
|
27
40
|
read: boolean;
|
|
28
41
|
readAt?: ISODateTime;
|
|
42
|
+
favorite: boolean;
|
|
43
|
+
favoritedAt?: ISODateTime;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type NotificationReadFilter = "read" | "unread";
|
|
47
|
+
|
|
48
|
+
export interface NotificationInboxFilters {
|
|
49
|
+
q?: string;
|
|
50
|
+
category?: string;
|
|
51
|
+
read?: NotificationReadFilter;
|
|
52
|
+
favorite?: boolean;
|
|
29
53
|
}
|
|
30
54
|
|
|
31
55
|
export interface PublishNotificationInput {
|
|
@@ -35,12 +59,79 @@ export interface PublishNotificationInput {
|
|
|
35
59
|
category: string;
|
|
36
60
|
target?: TargetRef;
|
|
37
61
|
recipientUserId?: string;
|
|
62
|
+
recipientUserIds?: string[];
|
|
38
63
|
recipientRoleCodes?: string[];
|
|
64
|
+
recipientDepartmentIds?: string[];
|
|
65
|
+
includeChildDepartments?: boolean;
|
|
66
|
+
deliveryChannels?: ExternalNotificationChannel[];
|
|
67
|
+
scheduledFor?: ISODateTime;
|
|
39
68
|
sourceKey?: string;
|
|
40
69
|
}
|
|
41
70
|
|
|
71
|
+
export interface NotificationPreference {
|
|
72
|
+
userId: string;
|
|
73
|
+
enabledChannels: ExternalNotificationChannel[];
|
|
74
|
+
disabledCategories: string[];
|
|
75
|
+
updatedAt?: ISODateTime;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export type UpdateNotificationPreferenceInput = Pick<
|
|
79
|
+
NotificationPreference,
|
|
80
|
+
"enabledChannels" | "disabledCategories"
|
|
81
|
+
>;
|
|
82
|
+
|
|
83
|
+
export interface NotificationAudienceOption {
|
|
84
|
+
id: string;
|
|
85
|
+
label: string;
|
|
86
|
+
code?: string;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface NotificationAudienceOptions {
|
|
90
|
+
users: NotificationAudienceOption[];
|
|
91
|
+
roles: NotificationAudienceOption[];
|
|
92
|
+
departments: NotificationAudienceOption[];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface NotificationDelivery {
|
|
96
|
+
id: string;
|
|
97
|
+
notificationId: string;
|
|
98
|
+
userId: string;
|
|
99
|
+
channel: ExternalNotificationChannel;
|
|
100
|
+
status: NotificationDeliveryStatus;
|
|
101
|
+
attemptCount: number;
|
|
102
|
+
nextAttemptAt: ISODateTime;
|
|
103
|
+
deliveredAt?: ISODateTime;
|
|
104
|
+
lastErrorCode?: string;
|
|
105
|
+
createdAt: ISODateTime;
|
|
106
|
+
updatedAt: ISODateTime;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export type UpdateNotificationInput = Pick<
|
|
110
|
+
PublishNotificationInput,
|
|
111
|
+
"title" | "summary" | "content" | "category"
|
|
112
|
+
>;
|
|
113
|
+
|
|
114
|
+
export interface NotificationRevision extends UpdateNotificationInput {
|
|
115
|
+
notificationId: string;
|
|
116
|
+
revision: number;
|
|
117
|
+
editedAt: ISODateTime;
|
|
118
|
+
editedBy: string;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export interface UpdateNotificationResult {
|
|
122
|
+
notification: PlatformNotification;
|
|
123
|
+
changed: boolean;
|
|
124
|
+
}
|
|
125
|
+
|
|
42
126
|
export interface MarkNotificationReadResult {
|
|
43
127
|
success: true;
|
|
44
128
|
alreadyRead: boolean;
|
|
45
129
|
readAt: ISODateTime;
|
|
46
130
|
}
|
|
131
|
+
|
|
132
|
+
export interface SetNotificationFavoriteResult {
|
|
133
|
+
success: true;
|
|
134
|
+
favorite: boolean;
|
|
135
|
+
changed: boolean;
|
|
136
|
+
favoritedAt?: ISODateTime;
|
|
137
|
+
}
|
|
@@ -2,6 +2,8 @@ export interface PlatformBrandingSettings {
|
|
|
2
2
|
softwareName: string;
|
|
3
3
|
logoUrl?: string;
|
|
4
4
|
description?: string;
|
|
5
|
+
/** Runtime display timezone. It is managed by platform.runtime, not branding storage. */
|
|
6
|
+
timeZone?: string;
|
|
5
7
|
}
|
|
6
8
|
|
|
7
9
|
export const WATERMARK_DENSITIES = ["low", "medium", "high"] as const;
|
|
@@ -191,6 +191,22 @@ describe("UploadService", () => {
|
|
|
191
191
|
service.appendPart(partInput(session.id, 1, 1, bytes("{}"))),
|
|
192
192
|
).rejects.toMatchObject({ code: "UPLOAD_OFFSET_CONFLICT" });
|
|
193
193
|
});
|
|
194
|
+
|
|
195
|
+
test("运行时更新用途策略只影响后续上传会话", async () => {
|
|
196
|
+
const { service } = fixture();
|
|
197
|
+
const original = policies[0]!;
|
|
198
|
+
service.setPolicy({ ...original, maxByteSize: 1 });
|
|
199
|
+
|
|
200
|
+
await expect(
|
|
201
|
+
service.create({
|
|
202
|
+
ownerId: "user_1",
|
|
203
|
+
purpose: "bulk-data",
|
|
204
|
+
filename: "data.json",
|
|
205
|
+
mimeType: "application/json",
|
|
206
|
+
expectedByteSize: 2,
|
|
207
|
+
}),
|
|
208
|
+
).rejects.toMatchObject({ code: "UPLOAD_TOO_LARGE" });
|
|
209
|
+
});
|
|
194
210
|
});
|
|
195
211
|
|
|
196
212
|
function fixture() {
|
|
@@ -37,7 +37,7 @@ export interface CleanupResult {
|
|
|
37
37
|
export class UploadService {
|
|
38
38
|
private readonly now: () => Date;
|
|
39
39
|
private readonly createId: (prefix: "upload" | "file") => string;
|
|
40
|
-
private readonly policies:
|
|
40
|
+
private readonly policies: Map<string, UploadPolicy>;
|
|
41
41
|
|
|
42
42
|
constructor(private readonly options: UploadServiceOptions) {
|
|
43
43
|
this.now = options.now ?? (() => new Date());
|
|
@@ -47,6 +47,10 @@ export class UploadService {
|
|
|
47
47
|
);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
setPolicy(policy: UploadPolicy): void {
|
|
51
|
+
this.policies.set(policy.purpose, { ...policy });
|
|
52
|
+
}
|
|
53
|
+
|
|
50
54
|
async create(input: CreateUploadInput): Promise<UploadSession> {
|
|
51
55
|
const policy = this.requirePolicy(input.purpose);
|
|
52
56
|
const filename = validFilename(input.filename);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
PostgresRegressionHarness,
|
|
3
|
+
runCommand,
|
|
4
|
+
} from "./lib/postgres-regression.js";
|
|
5
|
+
|
|
6
|
+
const postgres = new PostgresRegressionHarness("windy-notification-test");
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
await postgres.start();
|
|
10
|
+
await runCommand(
|
|
11
|
+
[
|
|
12
|
+
"bun",
|
|
13
|
+
"test",
|
|
14
|
+
"apps/server/src/notification/drizzle-repository.integration.test.ts",
|
|
15
|
+
],
|
|
16
|
+
{
|
|
17
|
+
stdout: "inherit",
|
|
18
|
+
stderr: "inherit",
|
|
19
|
+
env: {
|
|
20
|
+
...process.env,
|
|
21
|
+
NOTIFICATION_TEST_DATABASE_URL: postgres.databaseUrl(),
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
);
|
|
25
|
+
} finally {
|
|
26
|
+
await postgres.close();
|
|
27
|
+
}
|