create-windy 0.2.33 → 0.3.0
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/dist/cli.js +173 -17
- package/package.json +1 -1
- package/template/.agents/skills/windy-business-module/SKILL.md +10 -1
- package/template/.windy-template.json +2 -2
- package/template/AGENTS.md +9 -0
- package/template/README.md +3 -1
- package/template/apps/agent-server/Dockerfile +1 -0
- package/template/apps/agent-server/README.md +28 -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 +63 -3
- package/template/apps/agent-server/src/southwind_agent_server/contracts.py +35 -0
- package/template/apps/agent-server/src/southwind_agent_server/engine.py +2 -0
- package/template/apps/agent-server/src/southwind_agent_server/openai_engine.py +31 -3
- package/template/apps/agent-server/src/southwind_agent_server/openai_provider.py +22 -9
- package/template/apps/agent-server/src/southwind_agent_server/provider_audit.py +144 -0
- package/template/apps/agent-server/src/southwind_agent_server/provider_governance.py +227 -0
- package/template/apps/agent-server/src/southwind_agent_server/service.py +1 -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_api.py +16 -1
- package/template/apps/agent-server/tests/test_openai_provider.py +79 -0
- package/template/apps/agent-server/tests/test_provider_governance.py +215 -0
- package/template/apps/server/package.json +4 -1
- package/template/apps/server/src/agent/provider-input-governance.test.ts +82 -0
- package/template/apps/server/src/agent/provider-input-governance.ts +140 -0
- package/template/apps/server/src/agent/remote-runtime.test.ts +22 -0
- package/template/apps/server/src/agent/remote-runtime.ts +1 -0
- package/template/apps/server/src/agent/run-contracts.ts +2 -0
- package/template/apps/server/src/agent/run-facade.test.ts +52 -2
- package/template/apps/server/src/agent/run-facade.ts +38 -9
- 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.ts +44 -3
- 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 +45 -45
- 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/module-bootstrap.ts +2 -2
- package/template/apps/server/src/module-host/initialize-contracts.ts +6 -0
- package/template/apps/server/src/module-host/initialize.ts +30 -44
- package/template/apps/server/src/module-host/request-context.ts +29 -23
- package/template/apps/server/src/module-host/resource-file-policies.test.ts +197 -0
- package/template/apps/server/src/module-host/resource-file-policies.ts +108 -0
- package/template/apps/server/src/module-host/route-declaration.ts +45 -0
- package/template/apps/server/src/module-host/route-installer.ts +27 -3
- package/template/apps/server/src/module-host/storage-port.test.ts +170 -1
- package/template/apps/server/src/module-host/storage-port.ts +134 -1
- package/template/apps/server/src/module-host/storage-scope.ts +89 -0
- package/template/apps/server/src/module-host/tool-handlers.test.ts +305 -0
- package/template/apps/server/src/module-host/tool-handlers.ts +38 -4
- package/template/apps/server/src/module-host/user-directory-composition.test.ts +126 -0
- package/template/apps/server/src/module-host/user-directory-port.test.ts +238 -0
- package/template/apps/server/src/module-host/user-directory-port.ts +139 -0
- package/template/apps/server/src/module-host.ts +4 -0
- 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/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 +2 -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/built-in-roles.ts +1 -0
- 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.ts +37 -9
- 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/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 +70 -36
- 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/SystemResourcePage.vue +91 -98
- 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 +68 -0
- package/template/docs/architecture/ai-egress.md +49 -7
- package/template/docs/architecture/ai-runtime.md +34 -6
- package/template/docs/architecture/data-scope-query-enforcement.md +4 -0
- package/template/docs/architecture/object-storage.md +22 -2
- 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 +76 -7
- package/template/docs/platform/audit-reliability.md +46 -2
- package/template/docs/platform/business-user-directory.md +82 -0
- 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/ai-operation-composition.test.ts +68 -0
- package/template/packages/modules/src/ai-operation-composition.ts +115 -0
- package/template/packages/modules/src/manifest.ts +26 -0
- package/template/packages/modules/src/provider-data-policy-composition.test.ts +74 -0
- package/template/packages/modules/src/system-api-permissions.ts +54 -0
- package/template/packages/modules/src/system-audit-actions.ts +15 -0
- package/template/packages/modules/src/system-features.ts +6 -1
- package/template/packages/modules/src/system-module-catalog.test.ts +16 -0
- package/template/packages/modules/src/system-module-catalog.ts +28 -4
- package/template/packages/modules/src/system-modules.test.ts +13 -1
- package/template/packages/modules/src/system-modules.ts +12 -0
- package/template/packages/modules/src/system-permissions.ts +11 -5
- package/template/packages/server-sdk/index.ts +11 -0
- package/template/packages/server-sdk/package.json +3 -2
- package/template/packages/server-sdk/src/ai-operation-registration.ts +2 -1
- package/template/packages/server-sdk/src/module-host.ts +8 -0
- package/template/packages/server-sdk/src/request-context.ts +2 -0
- package/template/packages/server-sdk/src/storage-port.ts +66 -0
- package/template/packages/server-sdk/src/tool-registration.ts +6 -0
- package/template/packages/server-sdk/src/user-directory-port.ts +42 -0
- package/template/packages/shared/package.json +1 -1
- package/template/packages/shared/src/audit.ts +25 -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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Agent Runtime 接入与运行
|
|
2
2
|
|
|
3
|
-
更新时间:2026-07-
|
|
3
|
+
更新时间:2026-07-26。
|
|
4
4
|
|
|
5
5
|
Windy 的 Agent Runtime 是可选平台能力。业务模块声明稳定的 AI Operation 和允许调用的
|
|
6
6
|
Tool;Southwind AI Server 负责身份、Feature、Permission、License、Scope、Execution
|
|
@@ -9,6 +9,8 @@ Grant 与审计;独立 Agent Server 只负责模型循环、canonical event
|
|
|
9
9
|
|
|
10
10
|
## 当前可用边界
|
|
11
11
|
|
|
12
|
+
- 真实业务 Run 使用 Google ADK 2.5 `Runner`、`InMemorySessionService`、`LlmAgent`
|
|
13
|
+
与 `Event`;ADK 类型只存在于 Python Adapter 内,外部 HTTP/SSE 契约不变。
|
|
12
14
|
- OpenAI-compatible `/chat/completions` Provider,支持流式文本和 function calling。
|
|
13
15
|
- `QWEN_API_KEY` 使用服务端 `SecretRef`,只在 Provider Adapter 发请求前解析。
|
|
14
16
|
- 公网 Endpoint 必须为 HTTPS,并精确命中
|
|
@@ -37,12 +39,34 @@ providerEgress: {
|
|
|
37
39
|
mode: "configured-endpoint",
|
|
38
40
|
deploymentKey: "ai.openai-compatible",
|
|
39
41
|
},
|
|
42
|
+
providerDataPolicy: {
|
|
43
|
+
inputFields: [
|
|
44
|
+
{
|
|
45
|
+
jsonPointer: "/content",
|
|
46
|
+
classification: "internal",
|
|
47
|
+
dlpAction: "redact",
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
envelopeFields: [
|
|
51
|
+
{
|
|
52
|
+
field: "instructions",
|
|
53
|
+
classification: "internal",
|
|
54
|
+
dlpAction: "reject",
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
field: "user-prompt",
|
|
58
|
+
classification: "internal",
|
|
59
|
+
dlpAction: "redact",
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
},
|
|
40
63
|
toolNetworkPolicy: {
|
|
41
64
|
mode: "forbidden",
|
|
42
65
|
},
|
|
43
66
|
```
|
|
44
67
|
|
|
45
|
-
Provider URL 与 Secret 不在 Manifest 或浏览器 DTO 中;
|
|
68
|
+
Provider URL 与 Secret 不在 Manifest 或浏览器 DTO 中;Server 只把 `inputFields`
|
|
69
|
+
选出的治理后输入交给 Handler,Agent Server 只允许当前启动
|
|
46
70
|
配置的 Deployment。Tool policy 缺省为 forbidden,且不继承 Provider egress。完整
|
|
47
71
|
威胁模型、兼容行为与尚未覆盖项见
|
|
48
72
|
[Agent Provider 与 Tool 网络边界](../architecture/ai-egress.md)。
|
|
@@ -104,6 +128,7 @@ QWEN_API_URL=https://dashscope-intl.aliyuncs.com/compatible-mode/v1
|
|
|
104
128
|
QWEN_API_KEY=<服务端密钥>
|
|
105
129
|
QWEN_MODEL=qwen-plus
|
|
106
130
|
AI_PROVIDER_HTTPS_HOST_ALLOWLIST=dashscope-intl.aliyuncs.com
|
|
131
|
+
AI_PROVIDER_AUDIT_RETENTION_DAYS=90
|
|
107
132
|
|
|
108
133
|
# 可选安全上限
|
|
109
134
|
# AI_PROVIDER_CONNECT_TIMEOUT_MS=5000
|
|
@@ -125,10 +150,52 @@ bun run dev:agent
|
|
|
125
150
|
```text
|
|
126
151
|
GET http://agent-server:8080/health/live
|
|
127
152
|
GET http://agent-server:8080/health/ready
|
|
153
|
+
GET http://agent-server:8080/health/provider-governance
|
|
128
154
|
```
|
|
129
155
|
|
|
130
156
|
`ready` 会访问 Provider 的 `/models`。失败只返回稳定错误,不回显 Provider body、
|
|
131
157
|
Authorization、Secret、Endpoint query 或底层异常文本。
|
|
158
|
+
`provider-governance` 需要内部 Bearer Token,只返回留存、允许/拒绝/脱敏和 TTL 清理
|
|
159
|
+
聚合,不返回 Run ID、prompt 或正文。
|
|
160
|
+
|
|
161
|
+
## 字段治理迁移
|
|
162
|
+
|
|
163
|
+
启用 `providerEgress.mode=configured-endpoint` 的既有业务 Operation 必须同时新增
|
|
164
|
+
`providerDataPolicy`。升级后缺少策略会在 Manifest Composition 阶段以
|
|
165
|
+
`Provider 字段发送 allowlist 缺失` fail fast,不会静默发送或降级放行。
|
|
166
|
+
|
|
167
|
+
迁移时先枚举业务 input schema 中确实需要出境的最小 JSON Pointer;为每个字段声明
|
|
168
|
+
分类与 `reject/redact`。再枚举 outbound envelope:无 Tool 的单轮问答通常只需要
|
|
169
|
+
`instructions` 和 `user-prompt`;Tool schema、模型上一轮 Tool Call 和 Tool result
|
|
170
|
+
分别需要 `tool-definitions`、`provider-output`、`tool-results`。不要为消除启动错误
|
|
171
|
+
一次性允许全部字段。原始 input 会在进入 `prepare` 前裁剪,因此 Handler 必须只依赖
|
|
172
|
+
allowlist 中的字段。
|
|
173
|
+
|
|
174
|
+
Agent profile 还必须挂载 `AI_PROVIDER_AUDIT_STORE_PATH`。create-windy Starter 使用
|
|
175
|
+
`/app/data/agent/provider-audit.sqlite3` 并复用单副本持久卷;自行维护 Compose 的项目
|
|
176
|
+
需要显式补齐该变量。未配置时 Provider 启动 fail closed,并给出缺失变量名。
|
|
177
|
+
|
|
178
|
+
## Developer-only ADK Web
|
|
179
|
+
|
|
180
|
+
ADK Web 使用独立 profile 启动:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
bun run dev:adk-web
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
访问地址为 `http://127.0.0.1:8000`。Compose 服务在容器内监听 `0.0.0.0:8000`,
|
|
187
|
+
但端口只发布到宿主机 `127.0.0.1`。普通 `dev`、`agent` profile 和生产 Compose 均不
|
|
188
|
+
包含该服务。
|
|
189
|
+
|
|
190
|
+
该界面明确显示“Windy ADK 开发调试(无业务工具)”,并只加载一个确定性 Agent:
|
|
191
|
+
|
|
192
|
+
- 不读取 `QWEN_*`、Provider URL/Secret 或 `AGENT_SERVER_INTERNAL_TOKEN`;
|
|
193
|
+
- 不注册业务 Tool,不连接 Tool Host 或业务 Repository;
|
|
194
|
+
- 不接收 Actor、Scope 或 Execution Grant;
|
|
195
|
+
- 只用于观察 ADK Web、Session 和 Event,不代表真实业务 Operation。
|
|
196
|
+
|
|
197
|
+
真实业务调试必须继续从 canonical Run API 发起并提供 Southwind AI Server 签发的
|
|
198
|
+
Execution Grant;不能通过 ADK Web 补造或绕过这条授权链。
|
|
132
199
|
|
|
133
200
|
## 客户端协议
|
|
134
201
|
|
|
@@ -145,15 +212,17 @@ SSE 事件包括 `output.delta`、`tool.requested`、`tool.completed`、usage,
|
|
|
145
212
|
`run.completed`、`run.failed` 或 `run.cancelled` 终态。断线后使用已确认 sequence 作为
|
|
146
213
|
cursor 恢复;不要重新创建 Run 或重复执行 Tool。
|
|
147
214
|
|
|
148
|
-
## 从 create-windy 0.2.
|
|
215
|
+
## 从 create-windy 0.2.34 升级到 0.3.0
|
|
149
216
|
|
|
150
|
-
|
|
217
|
+
`0.2.34 → 0.3.0` 使用连续 recipe,不需要逐个安装中间 CLI。确认 npm registry 已能
|
|
218
|
+
解析精确的 `0.3.0` artifact 后,先检查计划,再应用:
|
|
151
219
|
|
|
152
220
|
```bash
|
|
153
|
-
bunx --bun create-windy@0.
|
|
154
|
-
bunx --bun create-windy@0.
|
|
221
|
+
bunx --bun create-windy@0.3.0 update --check
|
|
222
|
+
bunx --bun create-windy@0.3.0 update
|
|
155
223
|
bun install
|
|
156
224
|
```
|
|
157
225
|
|
|
158
226
|
升级器会更新受管模板文件;本地修改产生冲突时会 fail closed 并保留事务备份,不会静默
|
|
159
|
-
覆盖。升级后按上面的环境变量启用 `agent` profile
|
|
227
|
+
覆盖。升级后按上面的环境变量启用 `agent` profile;`agent-debug` 仍只用于无业务 Tool
|
|
228
|
+
的本机调试。自动化部署应固定精确版本,不能用未核验的 `latest` 替代。
|
|
@@ -17,11 +17,53 @@
|
|
|
17
17
|
|
|
18
18
|
批量任务派发器每 5 秒轮询一次。定时执行返回 `claimed: false` 代表没有业务任务可领取,Scheduler 完成并立即丢弃这条 idle run,也不写 `task.execute` 审计;人工触发即使没有领取任务仍保留执行历史和 `task.trigger` / `task.execute`,真实领取、失败、重试和 Guard 拒绝同样完整留痕。idle 判定由任务定义显式声明,普通任务不会自动套用。
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
审计页面支持关键字、操作者、动作以及本地开始/结束分钟筛选。操作者候选来自最近
|
|
21
|
+
100 条审计记录,动作候选来自 Module Composition 形成的稳定动作目录,并以中文名称和
|
|
22
|
+
说明展示;筛选请求继续传递稳定 action key。`datetime-local` 输入按用户浏览器本地时区
|
|
23
|
+
转换为 ISO:开始分钟使用 `00.000` 秒,结束分钟包含至 `59.999` 秒。内存与 PostgreSQL
|
|
24
|
+
Reader 使用同一组含边界时间;时间不是完整 ISO 或开始晚于结束时返回
|
|
25
|
+
`400 INVALID_AUDIT_TIME_RANGE`。
|
|
26
|
+
|
|
27
|
+
关键字 `q` 会做 NFKC、首尾空白和连续空白规范化,最长 120 个字符。搜索范围包括动作
|
|
28
|
+
Key、操作者 ID/名称、目标类型/ID/标签、IP、message、module、requestId,以及已经过
|
|
29
|
+
审计脱敏并持久化的 metadata 文本。PostgreSQL 查询使用参数绑定并把 `%`、`_` 和反斜线
|
|
30
|
+
当作普通字符,不执行客户端表达式,也不查询登录 Session、业务明文表或未持久化请求体。
|
|
31
|
+
列表和导出共享完全相同的 `q`、操作者、动作与时间筛选;导出的
|
|
32
|
+
`includeScheduler` 默认关闭,只有显式勾选时才包含调度器事件。
|
|
21
33
|
|
|
22
34
|
常规审计列表在服务端固定排除 `system_scheduler` 执行身份产生的日志,客户端不能构造参数绕过;调度执行结果统一到定时任务的执行历史查看。审计导出提供“包含定时器日志”选项,默认关闭,只影响本次导出,不改变页面列表状态。
|
|
23
35
|
|
|
24
|
-
|
|
36
|
+
动作列直接显示中文动作名,并优先使用 event.message、target、module 与已记录 metadata
|
|
37
|
+
组成一行操作摘要;CRUD、搜索、功能开关和 Agent Tool 等常见动作提供稳定中文表达,
|
|
38
|
+
未知业务动作保留 action key、对象和实际上下文,不推断未记录事实。“查看详情”使用
|
|
39
|
+
shadcn-vue Dialog,以安全纯文本展示动作说明、结果、操作者、IP、时间、操作对象、
|
|
40
|
+
message、module、requestId、User-Agent 和已脱敏 metadata,不使用 `v-html`。
|
|
41
|
+
非空通用资源搜索记录 `data.search`;审计列表自身不递归记录搜索。自由文本可能包含
|
|
42
|
+
手机号或邮箱,因此部署方应把审计访问权限、保留期和导出权限视为敏感数据治理边界;
|
|
43
|
+
默认字段名脱敏不等于自由文本内容脱敏。
|
|
44
|
+
|
|
45
|
+
## HTTP 请求来源与可信代理
|
|
46
|
+
|
|
47
|
+
平台 HTTP 审计的 IP 与 User-Agent 来自当前请求,不写回认证 Resolver 返回的 Session
|
|
48
|
+
Actor。Bun `server.requestIP(request)` 提供的直接对端先经过 IP 规范化;User-Agent
|
|
49
|
+
去除首尾空白并最多保留 1024 个字符。所有由 Guard、平台 Route、业务 Module 与
|
|
50
|
+
Agent Tool 在该请求内产生的审计事件,都通过 `RequestGuardContext` 复制这份来源。
|
|
51
|
+
|
|
52
|
+
默认 `WINDY_TRUST_PROXY=false`,此时无条件忽略客户端提交的 `X-Forwarded-For`,只记录
|
|
53
|
+
合法的直接对端 IP。只有同时满足以下条件时才采用转发来源:
|
|
54
|
+
|
|
55
|
+
1. `WINDY_TRUST_PROXY=true`;
|
|
56
|
+
2. 直接对端是 loopback,或在 `WINDY_TRUSTED_PROXY_IPS` 的逗号分隔精确 IP 列表内;
|
|
57
|
+
3. `X-Forwarded-For` 只包含一个合法 IPv4/IPv6 地址。
|
|
58
|
+
|
|
59
|
+
多段转发链、非法地址或不受信直接对端均退回直接对端 IP。当前策略有意不猜测多级代理
|
|
60
|
+
链;部署多个反向代理时,应由最后一个受信代理清洗并输出单一客户端地址。配置了
|
|
61
|
+
`WINDY_TRUSTED_PROXY_IPS` 却未显式启用信任、布尔值不是 `true/false`、或列表含非法
|
|
62
|
+
IP 时,Server 启动 fail closed。
|
|
63
|
+
|
|
64
|
+
数据库 schema 早已包含 `audit_logs.ip` 与 `user_agent`,因此本功能无需 migration。
|
|
65
|
+
历史日志、非 HTTP 后台事件,以及升级前未复制请求来源的事件仍可能没有 IP 或
|
|
66
|
+
User-Agent,管理端明确显示“未记录”,不会用当前 Session 或其它字段猜测补齐。
|
|
25
67
|
|
|
26
68
|
每次 PostgreSQL 写入默认最多尝试 3 次。重试间隔按指数增长,并受最大间隔约束,不会无限重试或无限阻塞请求。恢复队列也有最大条数;队列已满等同于队列不可用,关键动作会失败。
|
|
27
69
|
|
|
@@ -77,6 +119,8 @@ License 上传仍只记录候选摘要、可识别的 License ID、公钥 ID 和
|
|
|
77
119
|
| `WINDY_AUDIT_QUEUE_FILE` | `./data/audit/recovery-queue.json` | 关键事件恢复文件 |
|
|
78
120
|
| `WINDY_AUDIT_QUEUE_SIZE` | `1000` | 关键恢复队列最大事件数,上限 `100000` |
|
|
79
121
|
| `AUDIT_REDACT_FIELDS` | 空 | 在默认敏感字段之外追加的逗号分隔字段名 |
|
|
122
|
+
| `WINDY_TRUST_PROXY` | `false` | 是否允许从受信直接代理读取单一转发 IP |
|
|
123
|
+
| `WINDY_TRUSTED_PROXY_IPS` | 空 | 受信直接代理的精确 IP,逗号分隔 |
|
|
80
124
|
|
|
81
125
|
生产环境未配置审计持久化 writer 时,关键动作不会回退为内存 best-effort,而是直接 fail closed。普通审计仍维持业务可用性,但健康状态会显示写入失败。
|
|
82
126
|
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# 业务模块只读用户目录
|
|
2
|
+
|
|
3
|
+
## Ownership 与 Seam
|
|
4
|
+
|
|
5
|
+
用户账号、启停状态、部门关系和数据范围属于 `system.identity`。业务模块需要选择案件
|
|
6
|
+
成员、协作人或负责人时,不得导入 Admin Repository、Drizzle schema 或 Server 内部
|
|
7
|
+
`RequestActor`。稳定 seam 是 `ModuleRequestContext.userDirectory`,其公开 Interface
|
|
8
|
+
只有一个方法:
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
const page = await context.userDirectory.list({
|
|
12
|
+
page: 1,
|
|
13
|
+
pageSize: 20,
|
|
14
|
+
q: "张",
|
|
15
|
+
});
|
|
16
|
+
// page.items: Array<{ id: string; displayName: string }>
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
这个深 Module 把授权、范围、状态过滤、搜索、分页、投影和审计藏在宿主 Adapter 中,
|
|
20
|
+
业务调用方只需学习查询条件与稳定错误码。删除该 Module 会迫使每个业务模块重复实现
|
|
21
|
+
同一组安全约束,因此该 seam 提供了跨模块的 leverage 和维护 locality。
|
|
22
|
+
|
|
23
|
+
## 安全不变量
|
|
24
|
+
|
|
25
|
+
- Actor、租户、部门和 Data Scope 只来自已验证请求的宿主
|
|
26
|
+
`RequestGuardContext`。Interface 不接受这些字段;HTTP body/query 中同名字段不能覆盖。
|
|
27
|
+
- V1 的 `tenantId` 是宿主 nominal `ScopeContext` 中的固定
|
|
28
|
+
`single-tenant`,不是忽略租户。`tenant` grant 仍经 Repository predicate 执行;未来
|
|
29
|
+
多租户只替换宿主 Adapter,不扩大业务 Interface。
|
|
30
|
+
- `all`、`tenant`、`department`、`department-and-children`、`custom` 和 `self`
|
|
31
|
+
都编译为用户 Repository 的查询条件,与启用状态、搜索、count 和分页共用同一个
|
|
32
|
+
`WHERE`。缺少 nominal `ScopeContext` 时返回 `data-scope-denied`,不会回退全量。
|
|
33
|
+
- 只返回启用、未删除用户的 `id` 和 `displayName`。部门、用户名、联系方式、角色、
|
|
34
|
+
凭据状态和审计字段不跨 seam 暴露。
|
|
35
|
+
- 调用者必须同时具备启用的 `system.user-directory` Feature 和
|
|
36
|
+
`system.user-directory.read` Permission。拒绝走统一 `security.denied` 审计。
|
|
37
|
+
- 每次成功查询在返回结果前以 critical 策略持久化
|
|
38
|
+
`system.user-directory.query`,元数据只含页码、页大小、结果数和总数,不记录搜索词
|
|
39
|
+
或返回用户明细;生产审计不可用时查询 fail closed。
|
|
40
|
+
- 页码与页大小必须为正整数;页码最多 10000、页大小最多 100,搜索词必须是最多 100
|
|
41
|
+
字符的字符串。非法输入返回 `USER_DIRECTORY_INVALID_QUERY`。
|
|
42
|
+
|
|
43
|
+
## 业务角色接入
|
|
44
|
+
|
|
45
|
+
业务 `ModuleRolePreset` 只能注册本模块命名空间内的 Permission,不能夹带
|
|
46
|
+
`system.user-directory.read` 绕过平台 ownership。部署管理员应在角色管理中显式为
|
|
47
|
+
需要选择用户的办案角色授予该平台 Permission,并根据角色配置 `all`、`tenant`、
|
|
48
|
+
部门、`custom` 或 `self` 数据范围。
|
|
49
|
+
|
|
50
|
+
业务 Handler 不要把浏览器提交的 `actorId`、`tenantId`、`departmentId` 或 scope
|
|
51
|
+
转发为授权参数:
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
handler: async (context) => {
|
|
55
|
+
const page = await context.userDirectory.list({
|
|
56
|
+
page: Number(context.query.page || 1),
|
|
57
|
+
pageSize: Number(context.query.pageSize || 20),
|
|
58
|
+
q: context.query.q,
|
|
59
|
+
});
|
|
60
|
+
return page;
|
|
61
|
+
};
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
未挂载平台 Adapter 时返回 `USER_DIRECTORY_UNAVAILABLE`;Permission 或 Feature 拒绝
|
|
65
|
+
返回 `USER_DIRECTORY_FORBIDDEN`。业务路由可以把稳定错误码映射为自己的 HTTP 错误
|
|
66
|
+
语义,但不得捕获后改用 Admin 用户接口或裸 Repository。
|
|
67
|
+
|
|
68
|
+
## 生成与升级
|
|
69
|
+
|
|
70
|
+
`packages/server-sdk` 的 Interface、Server Adapter、Composition Root、Manifest、
|
|
71
|
+
本文件和 Starter skill 都是 Windy 模板受管内容。新项目自动生成这些文件;既有项目
|
|
72
|
+
由 `windy update` 通过 Base/Ours/Theirs 创建新增文件并合并 Composition Root。
|
|
73
|
+
升级后由管理员授予 Permission,再由 project-owned 业务 Handler 调用 Port;升级器
|
|
74
|
+
不会自动修改客户业务角色或业务页面。
|
|
75
|
+
|
|
76
|
+
运维排查顺序:
|
|
77
|
+
|
|
78
|
+
1. 确认 `system.user-directory` 在 Feature 管理中启用;
|
|
79
|
+
2. 确认 Actor 拥有 `system.user-directory.read`;
|
|
80
|
+
3. 检查 Actor 的角色数据范围与部门关系;
|
|
81
|
+
4. 查询 `security.denied` 和 `system.user-directory.query` 审计;
|
|
82
|
+
5. 若返回 `USER_DIRECTORY_UNAVAILABLE`,检查 Starter Composition Root 是否完成升级。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 类型化模块配置与 Secret 边界
|
|
2
2
|
|
|
3
|
-
更新时间:2026-07-
|
|
3
|
+
更新时间:2026-07-26。
|
|
4
4
|
|
|
5
5
|
## 目标与边界
|
|
6
6
|
|
|
@@ -54,16 +54,25 @@ Secret 配置分成引用和运行时值两层:
|
|
|
54
54
|
- `applying`:版本已入库,正在调用模块 Apply Adapter;
|
|
55
55
|
- `effective`:当前生效版本,同模块同时只能有一个;
|
|
56
56
|
- `failed`:schema 已通过但运行时应用失败,稳定错误不包含底层异常正文;
|
|
57
|
+
- `pending-restart`:版本已持久化但包含需重启字段,当前进程不冒充已生效;下次启动校验并应用成功后提升为 `effective`;
|
|
57
58
|
- `superseded`:曾经生效,已被后续版本替代。
|
|
58
59
|
|
|
59
60
|
版本号由 PostgreSQL transaction 内的 module-key advisory lock 分配,唯一索引继续提供最终并发保护。应用成功后,Repository 在事务内把旧 `effective` 标为 `superseded` 并把新版本标为 `effective`;应用失败只标记新版本为 `failed`,原生效版本不变。Server 启动时先读取每个已注册模块的生效版本并通过同一 schema 与 Apply Adapter 恢复,再建立 foundation 和探活运行时。
|
|
60
61
|
|
|
61
|
-
|
|
62
|
+
当前 `platform.runtime` 白名单包括:
|
|
62
63
|
|
|
63
64
|
- `enableAI`:更新 foundation 平台能力投影;
|
|
64
65
|
- `cache.healthTimeoutMs`:后续 Redis 探活按最新值创建 probe。
|
|
66
|
+
- `security.sessionTtlSeconds`:即时影响新签发会话,已有会话保持原过期时间;
|
|
67
|
+
- `security.passwordMinLength/passwordMaxLength`:即时影响 Argon2 密码修改、重置校验和密码页服务端策略;
|
|
68
|
+
- `storage.bulkDataMaxByteSize/storage.brandingLogoMaxByteSize`:即时影响后续上传会话;
|
|
69
|
+
- `regional.timeZone`:即时影响公共平台设置投影和 Web 后续日期格式化;
|
|
70
|
+
- `mail.enabled/host/port/secure/fromAddress/connectTimeoutMs`:保存为
|
|
71
|
+
`pending-restart`,下次 Server 启动后进入 typed runtime config。
|
|
65
72
|
|
|
66
|
-
|
|
73
|
+
同一版本只要变更了需重启字段,就整体等待重启,避免一部分字段先应用造成原子性错觉。旧版本缺少后来新增的字段时,Apply Adapter 使用当前环境基线补齐,再经过完整 schema 校验;因此升级不要求回写历史行。数据库、Redis URL、SMTP URL、License 机器码、签名 Token 和 Vault Token 等 Secret 或引用均不进入版本表、diff、普通 API、管理界面或审计 metadata。`MAIL_SMTP_URL` 仍只由 env SecretResolver 注入进程内配置。
|
|
74
|
+
|
|
75
|
+
邮件字段由通知模块的标准 SMTP Adapter 在 Server 组合根消费。`mail.enabled=false` 时不注册邮件渠道;启用后可使用 env-only `MAIL_SMTP_URL`,或使用 `host/port/secure/fromAddress/connectTimeoutMs` 建立传输。保存配置仍是 `pending-restart`,只有重启后新建的 Adapter 才读取新值。配置存在不等于必然送达:实际结果由持久 outbox、用户偏好、收件地址和 SMTP 响应共同决定。短信供应商实现不属于平台配置,业务项目必须通过通知 ChannelAdapter Port 注入,平台不会猜供应商报文。
|
|
67
76
|
|
|
68
77
|
## 回滚、权限与审计
|
|
69
78
|
|
|
@@ -71,7 +80,7 @@ Secret 配置分成引用和运行时值两层:
|
|
|
71
80
|
|
|
72
81
|
配置读取要求 `system.config.read`,创建版本和回滚要求 `system.config.manage`;菜单、Web Router 和所有四个 API 绑定统一引用 `system.config` Feature 与 System Module Manifest。mutation 在改配置前先写 `critical` intent 审计,审计不可持久化或进入恢复队列时返回 `503 AUDIT_UNAVAILABLE` 且不创建版本。结果审计只记录 module Key、版本、状态、回滚来源和 changed paths,不记录 before/after 值、请求值、Secret 或 `SecretRef`。
|
|
73
82
|
|
|
74
|
-
管理端 `/system/configurations`
|
|
83
|
+
管理端 `/system/configurations` 只根据服务端字段描述生成编辑表单,显示每个字段即时/重启语义、环境/版本来源、生效版本、diff、失败或等待重启状态和历史;回滚必须经过带原因的显式确认。编辑值或原因未保存时,路由离开和刷新分别使用应用 Dialog 与原生 `beforeunload` 保护,保存失败会保留当前输入。
|
|
75
84
|
|
|
76
85
|
## 运维与验证
|
|
77
86
|
|
|
@@ -2,32 +2,88 @@
|
|
|
2
2
|
|
|
3
3
|
## 产品行为
|
|
4
4
|
|
|
5
|
-
通知管理页 `/system/notifications`
|
|
5
|
+
通知管理页 `/system/notifications` 提供广播或定向发布、定时发布、已发布公告修改、不可变版本历史、外部投递状态与归档管理,不是普通用户收件箱。能否修改只取决于当前 Actor 是否通过角色获得独立的 `system.notification.update` 权限;管理页访问、发布、历史查询和归档继续使用 `system.notification.manage`。普通 `system.notification.read` 用户可以在收件箱阅读、筛选、标记已读、维护个人收藏,并设置邮件、短信与分类偏好。
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
普通用户收件箱由 `GET /api/notifications` 提供服务端分页与筛选:
|
|
8
|
+
|
|
9
|
+
- `page`、`pageSize` 保持原有契约,默认每页 10 条、上限 100 条;
|
|
10
|
+
- `q` 在标题、摘要、正文和分类中做不区分大小写的关键词匹配;
|
|
11
|
+
- `category` 按分类精确筛选;
|
|
12
|
+
- `read=read|unread` 筛选当前用户的已读或未读通知;
|
|
13
|
+
- `favorite=true|false` 筛选当前用户的收藏或未收藏通知。
|
|
14
|
+
|
|
15
|
+
筛选条件使用 AND 组合。服务端先按当前 Actor 的用户 ID、角色和所属部门确定可见通知;部门受众可选择递归包含子部门。用户、角色和部门范围按“或”合并,全部留空时广播。列表查询与总数查询复用同一组条件,`total` 表示筛选后的可见总数,分页不会退化为客户端全量加载。
|
|
16
|
+
|
|
17
|
+
管理页通过页头的“发布新通知”按钮打开发布对话框。管理员从服务端受控目录选择用户、角色或部门,可选择是否包含子部门、未来发布时间和外部渠道;API 不接受邮箱或手机号等任意投递地址。发布、偏好和编辑对话框都执行未保存保护:关闭、路由离开和浏览器刷新不会静默丢失输入,保存失败时留在原编辑态。
|
|
8
18
|
|
|
9
19
|
管理列表与用户收件箱共享平台分页契约:默认每页 10 条,服务端上限 100;管理页允许输入范围内任意正整数页大小,并按跨页连续序号展示通知。已发布通知的刷新操作固定在列表右上角,仅显示刷新图标,通过立即出现的组件库 Tooltip 和 `aria-label` 提供名称;加载期间图标旋转且按钮不可重复提交。
|
|
10
20
|
|
|
11
|
-
|
|
21
|
+
管理员编辑标题、摘要、正文或分类后,服务端在同一事务中更新当前公告并追加新版本;客户端不能指定版本号、修改人或修改时间。内容完全相同时返回 `changed: false`,不会增加版本或重复写审计。并发修改通过行锁串行化,版本号从当前值单调递增。归档后的公告不再允许修改,但仍可分页查看全部历史。编辑对话框存在未保存内容时,关闭、切换路由、刷新或关闭标签页都会触发确认保护。
|
|
22
|
+
|
|
23
|
+
平台业务端口仍可创建携带通用 `TargetRef` 的用户或角色通知;当前最小审批工作流使用稳定 `sourceKey` 去重。无论人工还是业务发布,收件箱查询、已读和收藏写入都会按当前 Actor 重新执行最终可见性校验。
|
|
12
24
|
|
|
13
|
-
|
|
25
|
+
站内通知始终保留,个人偏好只控制外部渠道。外部投递的确定顺序固定为:强制类别优先,其次类别退订,最后取“发布者请求渠道”与“用户启用渠道”的交集;未保存偏好时普通类别默认不向外部发送。当前默认把“安全”作为强制类别,但仍不会增加发布者未请求的渠道。收藏与已读不参与渠道策略。
|
|
26
|
+
|
|
27
|
+
邮件渠道使用 Server 组合根注入的标准 SMTP Adapter,唯一配置来源是类型化 `platformConfig.mail`;`MAIL_SMTP_URL` 仍是 env-only Secret,不进入普通 API、页面、审计或 outbox。短信只定义类型化 `NotificationChannelAdapter` Port:平台不知道供应商报文时不猜格式,未注入 Adapter 的短信投递会明确进入 `dead / CHANNEL_NOT_CONFIGURED`,业务项目可在组合根注入供应商实现。
|
|
14
28
|
|
|
15
29
|
## 生命周期与数据
|
|
16
30
|
|
|
17
|
-
- `platform_notifications`
|
|
31
|
+
- `platform_notifications` 保存内容、状态、计划/实际发布时间、用户/角色/部门受众、是否包含子部门、请求渠道和审计字段;业务端口还可写入 TargetRef 与唯一 source key。
|
|
32
|
+
- `platform_notifications.revision` 保存当前版本号;`notification_revisions` 以“通知 ID + 版本号”为复合主键保存每次完整内容快照、修改时间与修改人。发布即形成 v1,历史只追加不覆盖。
|
|
18
33
|
- `notification_reads` 以“通知 ID + 用户 ID”为复合主键保存已读时间,重复点击幂等。
|
|
19
|
-
-
|
|
34
|
+
- `notification_favorites` 以“通知 ID + 用户 ID”为复合主键保存收藏时间。收藏与已读是两份独立回执:收藏不会自动已读,阅读或取消收藏也不会改写另一份状态。
|
|
35
|
+
- `notification_preferences` 按用户保存启用的外部渠道和退订分类;客户端不能修改其他用户的偏好。
|
|
36
|
+
- `notification_delivery_outbox` 按“通知 + 用户 + 渠道”唯一保存持久投递。Worker 使用 `FOR UPDATE SKIP LOCKED`、lease token、过期租约回收和有界指数退避;成功进入 `delivered`,不可重试、地址缺失或超过上限进入 `dead`。outbox 只保存用户 ID 和通知内容,不保存 SMTP Secret,也不接受客户端地址快照。
|
|
37
|
+
- 管理操作使用归档而不是物理删除。归档后通知立即退出用户收件箱,但通知历史、操作者信息和既有已读、收藏回执继续保留。
|
|
20
38
|
- 无数据库时仅允许开发态内存 Repository;生产部署必须配置 `DATABASE_URL` 并执行迁移。
|
|
21
39
|
|
|
40
|
+
## 收藏 API 与安全边界
|
|
41
|
+
|
|
42
|
+
- `PUT /api/notifications/:id/favorite` 把当前用户状态设为收藏;
|
|
43
|
+
- `DELETE /api/notifications/:id/favorite` 把当前用户状态设为未收藏;
|
|
44
|
+
- 两个命令都幂等,响应中的 `changed` 只在本次请求真实改变状态时为 `true`;
|
|
45
|
+
- Repository 在写入或删除个人回执前必须重新校验通知仍为已发布状态且对当前 Actor 可见;
|
|
46
|
+
- 收藏记录始终使用 Guard 解析出的 Actor ID,客户端不能指定用户 ID;
|
|
47
|
+
- 未知、已归档或对 Actor 不可见的通知统一返回 `404`,避免通过猜测通知 ID 探测受众;
|
|
48
|
+
- 快速重复收藏只允许一个插入成功,快速重复取消收藏最多删除一次。
|
|
49
|
+
|
|
50
|
+
## 定向、偏好与投递 API
|
|
51
|
+
|
|
52
|
+
- `GET /api/system/notifications/audience-options` 返回当前启用的用户、角色和部门最小投影,要求 `system.notification.manage`;
|
|
53
|
+
- `POST /api/system/notifications` 可提交受众、`includeChildDepartments`、`scheduledFor` 与 `deliveryChannels`;未来时间创建 `scheduled` 通知,调度器到期后以条件更新激活,重复 tick 不会重复发布或投递;
|
|
54
|
+
- `GET/PUT /api/notifications/preferences` 只读取或更新当前 Actor 偏好,要求 `system.notification.read`;
|
|
55
|
+
- `GET /api/system/notifications/:id/deliveries` 查询外部投递状态,要求 `system.notification.manage`;
|
|
56
|
+
- `system.notification.dispatch` 每 5 秒发布到期通知并领取 outbox。投递时再次从受控用户目录解析当前邮箱或手机号,停用用户或缺失地址不会被发送。
|
|
57
|
+
|
|
58
|
+
## 修改与历史 API
|
|
59
|
+
|
|
60
|
+
- `PUT /api/system/notifications/:id` 修改仍处于已发布状态的公告,正文结构与发布接口兼容,响应为 `{ notification, changed }`;
|
|
61
|
+
- `GET /api/system/notifications/:id/revisions?page=1&pageSize=10` 按版本号倒序返回不可变历史、修改人和 ISO 8601 修改时间,并返回筛选前该公告的历史总数;
|
|
62
|
+
- 修改接口要求 `system.notification.update`,历史接口要求 `system.notification.manage`;两者都要求 `system.notification` Feature,缺少对应角色权限时返回 `403`;
|
|
63
|
+
- 未知公告返回 `404`;归档公告的修改也返回 `404`,避免暴露额外生命周期细节,历史查询仍可用;
|
|
64
|
+
- 修改输入只接受标题、摘要、正文和分类,沿用发布接口的必填与长度限制;Actor、时间和版本号全部由服务端生成。
|
|
65
|
+
|
|
22
66
|
## Feature、RBAC 与审计
|
|
23
67
|
|
|
24
68
|
能力基础 Key 为 `system.notification`:
|
|
25
69
|
|
|
26
|
-
-
|
|
27
|
-
-
|
|
70
|
+
- 用户收件箱、已读和个人收藏接口要求 `system.notification.read`;
|
|
71
|
+
- 修改要求独立的 `system.notification.update`;后台列表、发布、历史查询和归档要求 `system.notification.manage`,两项权限可以分别赋予角色;
|
|
28
72
|
- 菜单、Router、Header、Server API 都引用 Manifest 中的同一 Feature / Permission Key;
|
|
29
73
|
- Feature 或权限不可用时 Header 隐藏且不发请求,Server 仍执行最终 Guard;
|
|
30
|
-
-
|
|
31
|
-
-
|
|
74
|
+
- 管理端受众只接受受控目录 ID/角色 code,不接受外部地址;猜测通知 ID 不能绕过已读或收藏可见性检查;
|
|
75
|
+
- 立即发布记录 `notification.publish`,定时创建记录 `notification.schedule`,偏好更新记录 `notification.preference.update`;修改、阅读、收藏和归档沿用既有审计动作。审计 metadata 不记录地址、正文或 SMTP Secret。
|
|
76
|
+
|
|
77
|
+
发布、修改和归档使用关键审计写入策略。普通已读与收藏使用常规审计,避免审计存储短暂降级时阻止用户消费通知。
|
|
78
|
+
|
|
79
|
+
## 升级与迁移
|
|
80
|
+
|
|
81
|
+
个人收藏由 migration `0035_material_nightshade.sql` 引入,公告版本由 `0036_hesitant_speed.sql` 引入。`0038_uneven_wasp.sql` 新增定时/多受众/渠道字段、用户偏好和持久 outbox;旧通知默认保持立即发布、广播且不请求外部渠道。升级平台或通过 Windy 生命周期更新下游项目后:
|
|
82
|
+
|
|
83
|
+
1. 先审阅生成边界与 `windy update --dry-run` 结果,不手工覆盖 Windy-managed 文件;
|
|
84
|
+
2. 在切换新版 Server 前按生产发布流程备份数据库;
|
|
85
|
+
3. 使用生产唯一入口 `DATABASE_URL=... bun run db:migrate` 应用最新 migration;
|
|
86
|
+
4. 运行 `bun run test:db:migrations` 可验证 fresh migration 与重复执行幂等;
|
|
87
|
+
5. migration 成功后再发布应用。旧客户端仍可只传 `page/pageSize`,无需同步上线筛选、收藏、修改或历史调用;旧公告首次修改会从已回填的 v1 继续递增。
|
|
32
88
|
|
|
33
|
-
|
|
89
|
+
真实 PostgreSQL 回归可执行 `bun run scripts/notification-postgres-regression.ts`,覆盖 fresh migration、组织子树可见性、偏好持久化、outbox lease 防伪与重建 Repository 后的投递状态。
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
Windy V1 采用单组织、单租户的企业私有化模型。canonical schema 保留 RuoYi-Vue 兼容导入所需的部门树、用户主部门和角色自定义部门范围,但新模块不得直接依赖旧 `sys_dept` 或其它 `sys_*` 表。
|
|
6
6
|
|
|
7
|
-
- `departments.parent_id`
|
|
7
|
+
- `departments.parent_id` 表示上级部门,只有平台根组织为空;
|
|
8
8
|
- `users.department_id` 表示用户唯一主部门;
|
|
9
9
|
- `roles.data_scope` 和 `roles.department_ids` 表示角色数据范围策略;
|
|
10
10
|
- 岗位、兼职部门和多组织成员关系属于后续独立模型,不复用 `department_id` 暗中表达。
|
|
@@ -20,7 +20,21 @@ Windy V1 采用单组织、单租户的企业私有化模型。canonical schema
|
|
|
20
20
|
- `system.department.create`:调用受限的 `POST /api/system/departments/quick`;
|
|
21
21
|
- `system.department.manage`:兼容既有管理员,调用通用部门创建接口。
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
快捷创建只接收名称、编码、必选上级和排序,成功后刷新部门列表并自动选中新部门。`system.department.create` 与既有 `system.department.read/manage` 使用同一能力基础 Key `system.department`,接口继续经过 `system.rbac` Feature Guard,并写入 `crud.create` 审计事件。没有创建或管理权限时,表单只显示部门选择,不渲染快捷入口。
|
|
24
|
+
|
|
25
|
+
## 组织树强不变量
|
|
26
|
+
|
|
27
|
+
Windy V1 只允许一个未删除根组织。`0037_absent_nick_fury.sql` 通过 PostgreSQL partial unique index 约束根节点数量,并用 check constraint 拒绝直接把部门设为自身上级;Service 在写入前继续覆盖数据库无法表达的整棵树规则:
|
|
28
|
+
|
|
29
|
+
- 新部门必须选择一个启用上级,不能通过通用或快捷 API 创建第二个根;
|
|
30
|
+
- 根组织不能移动、停用或删除;
|
|
31
|
+
- 部门不能移动到自身或任意下级,异常旧树的遍历使用 visited set 有界终止;
|
|
32
|
+
- 角色 `custom` 数据范围至少选择一个启用部门,未知或停用部门返回 `INVALID_ROLE_DEPARTMENT_SCOPE`;
|
|
33
|
+
- 部门仍有直接下级、未删除用户或角色自定义部门范围时,普通停用和删除返回 `DEPARTMENT_MIGRATION_REQUIRED`,响应包含三类引用计数。
|
|
34
|
+
|
|
35
|
+
管理端处置部门使用 `POST /api/system/departments/:id/transition`。请求明确给出 `disable` 或 `delete` 以及启用的迁移目标;Server 会拒绝当前节点和其下级作为目标,然后把直接下级的 `parentId`、用户主部门和角色 `departmentIds` 一起迁移,再完成停用或软删除。操作写入 `organization.department.transition` 审计事件,元数据只记录动作、目标 ID 和迁移计数。
|
|
36
|
+
|
|
37
|
+
用户、角色和部门写操作共享同一个组织 mutation coordinator。无数据库开发模式使用进程内串行;PostgreSQL 使用固定 advisory transaction lock,因此多个 Server 实例的互相移动、用户归属写入和部门处置也按同一事实顺序判定。`bun run test:db:organization` 在 PostgreSQL 17 覆盖唯一根约束、双实例循环竞态和用户归属竞态;`bun run test:db:data-scope` 继续验证组织树调整后数据范围查询不漂移。
|
|
24
38
|
|
|
25
39
|
## 权限边界
|
|
26
40
|
|
|
@@ -28,4 +42,4 @@ Windy V1 采用单组织、单租户的企业私有化模型。canonical schema
|
|
|
28
42
|
|
|
29
43
|
当前用户资源已接入类型化数据访问上下文。Actor Resolver 从全部启用角色生成 `all`、`tenant`、`department`、`department-and-children`、`self` 或 `custom` grant;多个角色按可见集合并集计算。用户列表、总数、搜索、分页、导出、按 ID 读取、更新、删除和组织移动使用同一约束,跨部门猜测 ID 返回稳定的 `data-scope-denied`,不会只依赖 Web 隐藏。
|
|
30
44
|
|
|
31
|
-
详细接入契约见 [数据访问范围](./data-access-control.md)
|
|
45
|
+
详细接入契约见 [数据访问范围](./data-access-control.md)。没有明确 `ownerId` / `departmentId` 归属的资源不会自动套用部门范围。ORG-02 只覆盖单组织、用户唯一主部门和角色自定义部门范围;岗位、兼职部门与多组织成员关系仍是明确的后续模型,不在本轮暗中扩展。
|
|
@@ -8,6 +8,7 @@ Server 端已提供系统基础模块 Repository API,用于打通权限、查
|
|
|
8
8
|
默认无数据库时使用内存 Repository;配置 `DATABASE_URL` 后,系统资源 CRUD 会切换为 Drizzle Repository,并把用户、角色、部门、菜单、字典和功能开关持久化到 PostgreSQL。
|
|
9
9
|
|
|
10
10
|
<!-- @windy-module system.license begin -->
|
|
11
|
+
|
|
11
12
|
选择离线 License 模块时,原型 License 兼容记录也会持久化到 PostgreSQL。
|
|
12
13
|
<!-- @windy-module system.license end -->
|
|
13
14
|
|
|
@@ -19,9 +20,13 @@ Server 端已提供系统基础模块 Repository API,用于打通权限、查
|
|
|
19
20
|
- `menus`:菜单。
|
|
20
21
|
- `dictionaries`:字典。
|
|
21
22
|
- `features`:功能开关。
|
|
23
|
+
|
|
22
24
|
<!-- @windy-module system.license begin -->
|
|
25
|
+
|
|
23
26
|
- `licenses`:License 记录。
|
|
27
|
+
|
|
24
28
|
<!-- @windy-module system.license end -->
|
|
29
|
+
|
|
25
30
|
- `audit-logs`:审计日志查询。
|
|
26
31
|
|
|
27
32
|
## 路由
|
|
@@ -34,6 +39,7 @@ GET /api/system/:resource/export
|
|
|
34
39
|
GET /api/system/:resource/:id
|
|
35
40
|
POST /api/system/:resource
|
|
36
41
|
POST /api/system/departments/quick
|
|
42
|
+
POST /api/system/departments/:id/transition
|
|
37
43
|
POST /api/system/:resource/import
|
|
38
44
|
PUT /api/system/:resource/:id
|
|
39
45
|
DELETE /api/system/:resource/:id
|
|
@@ -68,12 +74,17 @@ GET /api/system/audit-logs
|
|
|
68
74
|
|
|
69
75
|
- 读操作:`system.<resource>.read`。
|
|
70
76
|
- 用户表单快捷创建部门:`system.department.create`;既有通用部门创建仍要求 `system.department.manage`。
|
|
77
|
+
- 部门迁移后停用或删除:`system.department.manage`;接口绑定 `system.rbac` Feature 并记录 `organization.department.transition`。
|
|
71
78
|
- 写操作:`system.<resource>.manage`。
|
|
72
79
|
- 审计日志:`system.audit.read`。
|
|
73
80
|
- 系统资源默认绑定 `system.rbac` Feature,审计日志绑定 `system.audit`。
|
|
81
|
+
|
|
74
82
|
<!-- @windy-module system.license begin -->
|
|
83
|
+
|
|
75
84
|
- License 资源绑定 `system.license`。
|
|
85
|
+
|
|
76
86
|
<!-- @windy-module system.license end -->
|
|
87
|
+
|
|
77
88
|
- Guard 固定按 Entitlement、动态 Feature Flag、RBAC 顺序判定。Feature 声明了 `requiredEntitlement` 但 License 快照缺失该能力、开关关闭/隐藏或用户缺少权限时,路由返回带稳定 `reason` 的 `403`,并记录 `security.denied`。
|
|
78
89
|
|
|
79
90
|
配置 `DATABASE_URL` 后,Admin Web 使用 `/api/auth/login` 签发的 `windy.sid` HttpOnly Cookie;明确的非浏览器集成使用 `/api/auth/api/login` 独立签发的 Bearer Token。Server 只用 Token hash 查询未过期、未吊销的服务端会话,再从数据库活跃用户和角色聚合权限。开发 Token 必须显式配置,且 `NODE_ENV=production` 时强制关闭;完整说明见 [客户业务平台认证与会话](./platform-authentication.md)。
|
|
@@ -86,12 +97,17 @@ GET /api/system/audit-logs
|
|
|
86
97
|
- Feature Guard 在配置数据库时按请求、按 Key 读取运行态;同一请求缓存结果,下一请求重新读取。开发无数据库时回退 Manifest,生产无数据库或读取失败时 fail closed。
|
|
87
98
|
- CRUD 成功和权限拒绝会先进入进程内审计 sink;配置 `DATABASE_URL` 后由可靠写入器写入 PostgreSQL `audit_logs`。普通事件持续失败时业务继续并告警;用户、角色、License 与 Feature Flag 等关键变更必须落库或进入本地原子恢复队列。策略、状态和恢复步骤见 [平台审计可靠写入](./audit-reliability.md)。
|
|
88
99
|
- 密码登录、服务端会话、退出和吊销已闭环;通用用户 CRUD 不读写或返回密码 hash,密码更新走受权限保护的认证 API。
|
|
100
|
+
|
|
89
101
|
<!-- @windy-module system.license begin -->
|
|
102
|
+
|
|
90
103
|
- 正式运行时 License 通过 `/api/license/runtime` 查看,并通过 `/api/license/runtime/install` 复用 SDK 验签和单槽原子替换;通用 `legacy_licenses` CRUD 只保留为显式原型兼容面,不能提供生产授权。
|
|
91
104
|
- License 限制模式只对显式列举的系统资源 JSON 导出放行,导出仍需通过原有 Feature 与 RBAC Guard;其它 API、Agent Tool 和后台任务先由 License Guard 阻断。
|
|
105
|
+
|
|
92
106
|
<!-- @windy-module system.license end -->
|
|
107
|
+
|
|
93
108
|
- `feature_flags` 的 Drizzle 路径已补齐完整审计字段和软删除列;`0005` migration 会回填既有数据的 `created_by` 后再设置非空约束。
|
|
94
109
|
- 通用系统资源仍保留同步 JSON 文件能力;字典已额外接入后台 NDJSON 任务、本人进度查询、失败明细和结果留存,Web 字典页默认使用后台工作流。其它实体尚未注册批量处理器。
|
|
110
|
+
- 用户、角色和部门禁止通用 JSON 导入,避免绕过账号、数据范围和组织树强不变量;部门备份导出仍可用于现场核查。
|
|
95
111
|
|
|
96
112
|
## 已完成补强与后续边界
|
|
97
113
|
|
|
@@ -9,7 +9,7 @@ Web 端已从单页静态首页推进为带真实会话的 Router 应用壳:
|
|
|
9
9
|
- 侧边栏菜单可点击跳转,并按当前路由高亮。
|
|
10
10
|
- 顶部面包屑读取 route meta 标题。
|
|
11
11
|
- 顶部账号菜单展示当前 Actor 并提供服务端退出;401 会全局清理会话并返回登录页。
|
|
12
|
-
-
|
|
12
|
+
- 顶部通知入口读取服务端通知收件箱,可打开正文并跨设备保存当前用户已读与个人收藏回执;无 `system.notification.read` 权限或 Feature 关闭时不显示入口,也不会请求通知 API。后台通知管理页负责发布、修改、查看不可变历史和归档,普通用户不能修改公告。
|
|
13
13
|
|
|
14
14
|
## 页面范围
|
|
15
15
|
|
|
@@ -59,8 +59,12 @@ POST /api/system/bulk-data/dictionaries/import
|
|
|
59
59
|
POST /api/system/bulk-data/dictionaries/export
|
|
60
60
|
GET /api/notifications
|
|
61
61
|
POST /api/notifications/:id/read
|
|
62
|
+
PUT /api/notifications/:id/favorite
|
|
63
|
+
DELETE /api/notifications/:id/favorite
|
|
62
64
|
GET /api/system/notifications
|
|
63
65
|
POST /api/system/notifications
|
|
66
|
+
PUT /api/system/notifications/:id
|
|
67
|
+
GET /api/system/notifications/:id/revisions
|
|
64
68
|
DELETE /api/system/notifications/:id
|
|
65
69
|
```
|
|
66
70
|
|
|
@@ -84,7 +88,7 @@ VITE_DEV_ADMIN_TOKEN=<显式开发 Token>
|
|
|
84
88
|
- Feature 开关成功修改会写入 `feature.update`,可在审计日志页通过“功能开关变更”直接查看。
|
|
85
89
|
- 系统资源表和字典后台任务表加载时保留表头与列宽,并显示带 `animate-pulse` 的骨架行;加载失败和空数据仍使用各自独立状态。
|
|
86
90
|
- 全局水印与业务页面范围默认开启。管理员在“全局设置”中维护总开关、低/中/高密度,并勾选用户名、姓名、手机号、邮箱或最多 80 个字符的自定义内容;保存写入审计并立即成为所有用户的只读策略。客户端按旋转文本包围盒自动计算平铺尺寸与安全间距,长内容和高密度模式也不会相互重叠。用户应用端不提供开关,也不使用 localStorage。`system.watermark` Feature 控制最终生效态,管理区另需 `system.watermark.read/manage` 权限。水印使用专用审计顶层覆盖 Sidebar、Drawer、Overlay 和 Modal,同时保持 `pointer-events-none`。服务端只向当前用户自己的会话响应补充这些身份字段。
|
|
87
|
-
- 站内通知由 PostgreSQL `platform_notifications` 和 `
|
|
91
|
+
- 站内通知由 PostgreSQL `platform_notifications`、`notification_revisions`、`notification_reads` 和 `notification_favorites` 持久化;管理人员可在 `/system/notifications` 广播发布、修改、查看版本历史和归档,用户从 Header 收件箱阅读正文并幂等写入相互独立的已读、收藏回执。修改会生成带服务端时间和 Actor 的完整不可变快照,无内容变化不增加版本。普通用户 API 支持关键词、分类、已读和收藏的服务端组合筛选,列表与 `total` 使用同一可见性范围。归档是生命周期操作,不物理删除通知、版本或回执。
|
|
88
92
|
- 字典页已切换为后台 NDJSON 导入导出,展示本人任务状态、进度、重试和终态文件下载;其它系统资源仍保留小数据同步 JSON 入口。详细契约见 [批量导入导出后台任务](./bulk-data-jobs.md)。当前 artifact 存在 10 MiB、50,000 行和 256 KiB 单行上限,扩大容量前需要对象存储 Adapter。
|
|
89
93
|
- 审计日志配置 `DATABASE_URL` 后读取 PostgreSQL `audit_logs`。可靠写入器提供有界重试、降级状态、关键事件本地恢复队列和健康信息;页面仍只读,且不会展示恢复队列中的事件正文。
|
|
90
94
|
- 运维页的定时任务来自真实代码注册和 PostgreSQL 状态,不允许在线编辑任务代码。当前基线的 `stale` 只做观察告警和人工处置提示,不会自动终止或重试。
|
package/template/package.json
CHANGED
|
@@ -16,6 +16,8 @@
|
|
|
16
16
|
"dev:web": "bun run --cwd apps/web dev",
|
|
17
17
|
"dev:server": "bun run --cwd apps/server dev",
|
|
18
18
|
"dev:agent": "docker compose --profile agent up --build",
|
|
19
|
+
"dev:adk-web": "docker compose --profile agent-debug up --build adk-web-debug",
|
|
20
|
+
"dev:search": "OPENSEARCH_URL=http://opensearch:9200 docker compose --profile search up --build",
|
|
19
21
|
"dev:license": "bun run --cwd apps/license dev",
|
|
20
22
|
"dev:license:docker": "docker compose --profile license up license",
|
|
21
23
|
"dev:signing": "bun run --cwd apps/signing-service dev",
|
|
@@ -28,6 +30,8 @@
|
|
|
28
30
|
"db:migrate": "drizzle-kit migrate --config drizzle.config.ts",
|
|
29
31
|
"test:db:auth": "bun run scripts/auth-postgres-regression.ts",
|
|
30
32
|
"test:db:data-scope": "bun run scripts/data-scope-postgres-regression.ts",
|
|
33
|
+
"test:db:organization": "bun run scripts/organization-postgres-regression.ts",
|
|
34
|
+
"test:db:notification": "bun run scripts/notification-postgres-regression.ts",
|
|
31
35
|
"test:db:governance": "bun run scripts/governance-postgres-regression.ts",
|
|
32
36
|
"test:db:legacy-license": "bun run scripts/legacy-license-migration-regression.ts",
|
|
33
37
|
"test:db:license-bootstrap": "bun run scripts/license-bootstrap-postgres-regression.ts",
|