@southwind-ai/modules 0.1.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/index.ts +8 -0
- package/package.json +23 -0
- package/src/catalog-validation.ts +123 -0
- package/src/composition.ts +344 -0
- package/src/manifest.ts +92 -0
- package/src/menu-composition.ts +54 -0
- package/src/registry.ts +53 -0
- package/src/system-admin-routes.ts +136 -0
- package/src/system-agent-tools.ts +28 -0
- package/src/system-api-binding.ts +37 -0
- package/src/system-api-data-governance.ts +21 -0
- package/src/system-api-permissions.ts +344 -0
- package/src/system-audit-actions.ts +70 -0
- package/src/system-data-governance.ts +30 -0
- package/src/system-features.ts +145 -0
- package/src/system-governed-export-bindings.ts +31 -0
- package/src/system-module-catalog.ts +250 -0
- package/src/system-modules.ts +335 -0
- package/src/system-permissions.ts +142 -0
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { featureKey, licenseVersionKey } from "@southwind-ai/shared";
|
|
2
|
+
import type { ModuleManifest } from "./manifest.js";
|
|
3
|
+
|
|
4
|
+
// @windy-module system.scheduler begin
|
|
5
|
+
const standardAndAdvanced = ["standard", "advanced"].map(licenseVersionKey);
|
|
6
|
+
// @windy-module system.scheduler end
|
|
7
|
+
const advancedOnly = [licenseVersionKey("advanced")];
|
|
8
|
+
|
|
9
|
+
export const systemFeatures: ModuleManifest["features"] = [
|
|
10
|
+
feature(
|
|
11
|
+
"system.admin",
|
|
12
|
+
"Windy 管理面",
|
|
13
|
+
"平台管理员、运维与授权审计人员使用的控制面准入能力。",
|
|
14
|
+
),
|
|
15
|
+
feature(
|
|
16
|
+
"system.rbac",
|
|
17
|
+
"RBAC 权限链路",
|
|
18
|
+
"用户、角色、权限点与数据范围的统一访问控制链路。",
|
|
19
|
+
),
|
|
20
|
+
feature(
|
|
21
|
+
"system.profile",
|
|
22
|
+
"个人设置",
|
|
23
|
+
"当前账号维护姓名、邮箱和手机等个人资料。",
|
|
24
|
+
),
|
|
25
|
+
// @windy-module system.settings begin
|
|
26
|
+
feature("system.settings", "全局设置", "平台软件名、Logo 等全局品牌配置。"),
|
|
27
|
+
// @windy-module system.settings end
|
|
28
|
+
// @windy-module system.configuration begin
|
|
29
|
+
feature(
|
|
30
|
+
"system.config",
|
|
31
|
+
"配置版本",
|
|
32
|
+
"受控管理模块配置的版本、应用状态、差异与回滚。",
|
|
33
|
+
),
|
|
34
|
+
// @windy-module system.configuration end
|
|
35
|
+
// @windy-module system.search begin
|
|
36
|
+
feature(
|
|
37
|
+
"system.search",
|
|
38
|
+
"平台功能搜索",
|
|
39
|
+
"搜索当前账号有权访问的平台菜单和功能入口。",
|
|
40
|
+
),
|
|
41
|
+
// @windy-module system.search end
|
|
42
|
+
// @windy-module system.settings begin
|
|
43
|
+
feature(
|
|
44
|
+
"system.watermark",
|
|
45
|
+
"页面水印",
|
|
46
|
+
"带身份信息的页面水印与用户显示偏好。",
|
|
47
|
+
),
|
|
48
|
+
// @windy-module system.settings end
|
|
49
|
+
// @windy-module system.license begin
|
|
50
|
+
feature(
|
|
51
|
+
"system.license",
|
|
52
|
+
"License 验证",
|
|
53
|
+
"客户 License 安装、验签、到期限制与运行状态检查。",
|
|
54
|
+
),
|
|
55
|
+
// @windy-module system.license end
|
|
56
|
+
// @windy-module system.audit begin
|
|
57
|
+
feature(
|
|
58
|
+
"system.audit",
|
|
59
|
+
"审计日志",
|
|
60
|
+
"记录关键配置、权限拒绝与业务操作,支持安全追溯。",
|
|
61
|
+
),
|
|
62
|
+
// @windy-module system.audit end
|
|
63
|
+
// @windy-module system.storage begin
|
|
64
|
+
feature(
|
|
65
|
+
"system.storage",
|
|
66
|
+
"文件与对象存储",
|
|
67
|
+
"受控文件上传、续传、下载、过期和底层对象生命周期。",
|
|
68
|
+
),
|
|
69
|
+
// @windy-module system.storage end
|
|
70
|
+
// @windy-module system.agent begin
|
|
71
|
+
feature(
|
|
72
|
+
"system.agent",
|
|
73
|
+
"Agent Tool",
|
|
74
|
+
"让受控 Agent 在权限、Feature 与审计保护下调用平台工具。",
|
|
75
|
+
),
|
|
76
|
+
// @windy-module system.agent end
|
|
77
|
+
// @windy-module system.operations begin
|
|
78
|
+
feature(
|
|
79
|
+
"system.ops",
|
|
80
|
+
"运维总览",
|
|
81
|
+
"集中查看服务、数据库、缓存与调度任务的运行状态。",
|
|
82
|
+
),
|
|
83
|
+
// @windy-module system.operations end
|
|
84
|
+
// @windy-module system.notification begin
|
|
85
|
+
feature(
|
|
86
|
+
"system.notification",
|
|
87
|
+
"站内通知",
|
|
88
|
+
"站内通知发布、管理、阅读和已读状态闭环。",
|
|
89
|
+
),
|
|
90
|
+
// @windy-module system.notification end
|
|
91
|
+
// @windy-module system.workflow begin
|
|
92
|
+
feature(
|
|
93
|
+
"system.workflow",
|
|
94
|
+
"最小审批",
|
|
95
|
+
"候选角色领取、转交、决定、取消和到期终结的通用审批能力。",
|
|
96
|
+
),
|
|
97
|
+
// @windy-module system.workflow end
|
|
98
|
+
// @windy-module system.scheduler begin
|
|
99
|
+
{
|
|
100
|
+
...feature(
|
|
101
|
+
"system.scheduler",
|
|
102
|
+
"定时任务执行器",
|
|
103
|
+
"平台定时任务调度、重试、手动执行和历史追踪。",
|
|
104
|
+
),
|
|
105
|
+
allowedLicenseVersions: standardAndAdvanced,
|
|
106
|
+
},
|
|
107
|
+
// @windy-module system.scheduler end
|
|
108
|
+
// @windy-module system.bulk-data begin
|
|
109
|
+
{
|
|
110
|
+
...feature(
|
|
111
|
+
"system.bulk-data",
|
|
112
|
+
"批量数据任务",
|
|
113
|
+
"受控的大批量导入、导出、失败明细和结果留存。",
|
|
114
|
+
),
|
|
115
|
+
allowedLicenseVersions: advancedOnly,
|
|
116
|
+
},
|
|
117
|
+
// @windy-module system.bulk-data end
|
|
118
|
+
{
|
|
119
|
+
...feature(
|
|
120
|
+
"system.ruoyi-compat",
|
|
121
|
+
"RuoYi-Vue 兼容层",
|
|
122
|
+
"可选适配旧 RuoYi-Vue 数据与接口,不影响平台标准模型。",
|
|
123
|
+
),
|
|
124
|
+
visible: "hidden",
|
|
125
|
+
enabled: false,
|
|
126
|
+
stage: "internal",
|
|
127
|
+
allowedLicenseVersions: advancedOnly,
|
|
128
|
+
},
|
|
129
|
+
];
|
|
130
|
+
|
|
131
|
+
function feature(
|
|
132
|
+
key: string,
|
|
133
|
+
label: string,
|
|
134
|
+
description?: string,
|
|
135
|
+
): ModuleManifest["features"][number] {
|
|
136
|
+
return {
|
|
137
|
+
key: featureKey(key),
|
|
138
|
+
label,
|
|
139
|
+
module: "system",
|
|
140
|
+
description,
|
|
141
|
+
visible: "visible",
|
|
142
|
+
enabled: true,
|
|
143
|
+
stage: "stable",
|
|
144
|
+
};
|
|
145
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ApiPermissionBinding } from "@southwind-ai/shared";
|
|
2
|
+
import { binding } from "./system-api-binding.js";
|
|
3
|
+
|
|
4
|
+
export function governedUserExportBindings(): ApiPermissionBinding[] {
|
|
5
|
+
return [
|
|
6
|
+
binding(
|
|
7
|
+
"POST",
|
|
8
|
+
"/api/system/users/exports",
|
|
9
|
+
"system.user.export",
|
|
10
|
+
"system.rbac",
|
|
11
|
+
),
|
|
12
|
+
binding(
|
|
13
|
+
"GET",
|
|
14
|
+
"/api/system/users/exports/:id",
|
|
15
|
+
"system.user.export",
|
|
16
|
+
"system.rbac",
|
|
17
|
+
),
|
|
18
|
+
binding(
|
|
19
|
+
"POST",
|
|
20
|
+
"/api/system/users/exports/:id/cancel",
|
|
21
|
+
"system.user.export",
|
|
22
|
+
"system.rbac",
|
|
23
|
+
),
|
|
24
|
+
binding(
|
|
25
|
+
"GET",
|
|
26
|
+
"/api/system/users/exports/:id/download",
|
|
27
|
+
"system.user.export",
|
|
28
|
+
"system.rbac",
|
|
29
|
+
),
|
|
30
|
+
];
|
|
31
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import type { MenuNode } from "@southwind-ai/shared";
|
|
2
|
+
import type { ModuleFactory, ModuleManifest } from "./manifest.js";
|
|
3
|
+
import { systemFoundationModule } from "./system-modules.js";
|
|
4
|
+
|
|
5
|
+
interface SystemModuleDefinition {
|
|
6
|
+
name: string;
|
|
7
|
+
version: string;
|
|
8
|
+
label: string;
|
|
9
|
+
description: string;
|
|
10
|
+
resources: readonly string[];
|
|
11
|
+
permissionKeys?: readonly string[];
|
|
12
|
+
excludedPermissionKeys?: readonly string[];
|
|
13
|
+
featureKeys: readonly string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const systemModuleDefinitions = [
|
|
17
|
+
{
|
|
18
|
+
name: "system",
|
|
19
|
+
version: "0.1.0",
|
|
20
|
+
label: "系统核心",
|
|
21
|
+
description: "管理面准入、Feature 治理、数据库基线与审计动作目录。",
|
|
22
|
+
resources: ["admin", "feature"],
|
|
23
|
+
featureKeys: ["system.admin", "system.ruoyi-compat"],
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: "system.identity",
|
|
27
|
+
version: "0.1.0",
|
|
28
|
+
label: "身份与权限",
|
|
29
|
+
description: "用户、角色、部门、菜单、字典、个人资料和数据范围。",
|
|
30
|
+
resources: ["user", "role", "department", "menu", "dict", "profile"],
|
|
31
|
+
excludedPermissionKeys: ["system.user.reveal", "system.user.export"],
|
|
32
|
+
featureKeys: ["system.rbac", "system.profile"],
|
|
33
|
+
},
|
|
34
|
+
// @windy-module system.settings begin
|
|
35
|
+
{
|
|
36
|
+
name: "system.settings",
|
|
37
|
+
version: "0.1.0",
|
|
38
|
+
label: "平台设置",
|
|
39
|
+
description: "品牌设置、Logo 与页面水印。",
|
|
40
|
+
resources: ["settings", "watermark"],
|
|
41
|
+
featureKeys: ["system.settings", "system.watermark"],
|
|
42
|
+
},
|
|
43
|
+
// @windy-module system.settings end
|
|
44
|
+
// @windy-module system.configuration begin
|
|
45
|
+
{
|
|
46
|
+
name: "system.configuration",
|
|
47
|
+
version: "0.1.0",
|
|
48
|
+
label: "配置版本",
|
|
49
|
+
description: "类型化模块配置、版本、差异、应用与回滚。",
|
|
50
|
+
resources: ["config"],
|
|
51
|
+
featureKeys: ["system.config"],
|
|
52
|
+
},
|
|
53
|
+
// @windy-module system.configuration end
|
|
54
|
+
// @windy-module system.license begin
|
|
55
|
+
{
|
|
56
|
+
name: "system.license",
|
|
57
|
+
version: "0.1.0",
|
|
58
|
+
label: "License",
|
|
59
|
+
description: "License 安装、验签、到期限制与版本授权。",
|
|
60
|
+
resources: ["license"],
|
|
61
|
+
featureKeys: ["system.license"],
|
|
62
|
+
},
|
|
63
|
+
// @windy-module system.license end
|
|
64
|
+
// @windy-module system.audit begin
|
|
65
|
+
{
|
|
66
|
+
name: "system.audit",
|
|
67
|
+
version: "0.1.0",
|
|
68
|
+
label: "审计日志",
|
|
69
|
+
description: "关键操作、权限拒绝和系统异常的安全追溯。",
|
|
70
|
+
resources: ["audit"],
|
|
71
|
+
featureKeys: ["system.audit"],
|
|
72
|
+
},
|
|
73
|
+
// @windy-module system.audit end
|
|
74
|
+
// @windy-module system.storage begin
|
|
75
|
+
{
|
|
76
|
+
name: "system.storage",
|
|
77
|
+
version: "0.1.0",
|
|
78
|
+
label: "文件存储",
|
|
79
|
+
description: "上传、续传、下载与对象生命周期管理。",
|
|
80
|
+
resources: ["storage"],
|
|
81
|
+
featureKeys: ["system.storage"],
|
|
82
|
+
},
|
|
83
|
+
// @windy-module system.storage end
|
|
84
|
+
// @windy-module system.agent begin
|
|
85
|
+
{
|
|
86
|
+
name: "system.agent",
|
|
87
|
+
version: "0.1.0",
|
|
88
|
+
label: "Agent Tool",
|
|
89
|
+
description: "受 Feature、RBAC 和审计保护的 Agent 工具调用。",
|
|
90
|
+
resources: ["agent"],
|
|
91
|
+
featureKeys: ["system.agent"],
|
|
92
|
+
},
|
|
93
|
+
// @windy-module system.agent end
|
|
94
|
+
// @windy-module system.operations begin
|
|
95
|
+
{
|
|
96
|
+
name: "system.operations",
|
|
97
|
+
version: "0.1.0",
|
|
98
|
+
label: "运维与调度",
|
|
99
|
+
description: "服务、数据库、缓存、磁盘与在线会话监控。",
|
|
100
|
+
resources: ["ops"],
|
|
101
|
+
featureKeys: ["system.ops"],
|
|
102
|
+
},
|
|
103
|
+
// @windy-module system.operations end
|
|
104
|
+
// @windy-module system.scheduler begin
|
|
105
|
+
{
|
|
106
|
+
name: "system.scheduler",
|
|
107
|
+
version: "0.1.0",
|
|
108
|
+
label: "任务调度",
|
|
109
|
+
description: "定时任务注册、执行、重试、历史与恢复。",
|
|
110
|
+
resources: ["scheduler"],
|
|
111
|
+
featureKeys: ["system.scheduler"],
|
|
112
|
+
},
|
|
113
|
+
// @windy-module system.scheduler end
|
|
114
|
+
// @windy-module system.notification begin
|
|
115
|
+
{
|
|
116
|
+
name: "system.notification",
|
|
117
|
+
version: "0.1.0",
|
|
118
|
+
label: "站内通知",
|
|
119
|
+
description: "通知发布、阅读、归档与状态管理。",
|
|
120
|
+
resources: ["notification"],
|
|
121
|
+
featureKeys: ["system.notification"],
|
|
122
|
+
},
|
|
123
|
+
// @windy-module system.notification end
|
|
124
|
+
// @windy-module system.workflow begin
|
|
125
|
+
{
|
|
126
|
+
name: "system.workflow",
|
|
127
|
+
version: "0.1.0",
|
|
128
|
+
label: "审批工作流",
|
|
129
|
+
description: "审批领取、转交、决定、取消与超时补偿。",
|
|
130
|
+
resources: ["workflow"],
|
|
131
|
+
featureKeys: ["system.workflow"],
|
|
132
|
+
},
|
|
133
|
+
// @windy-module system.workflow end
|
|
134
|
+
// @windy-module system.bulk-data begin
|
|
135
|
+
{
|
|
136
|
+
name: "system.bulk-data",
|
|
137
|
+
version: "0.1.0",
|
|
138
|
+
label: "批量数据",
|
|
139
|
+
description: "批量导入导出、失败明细、结果留存与清理。",
|
|
140
|
+
resources: ["bulk-data"],
|
|
141
|
+
featureKeys: ["system.bulk-data"],
|
|
142
|
+
},
|
|
143
|
+
// @windy-module system.bulk-data end
|
|
144
|
+
// @windy-module system.search begin
|
|
145
|
+
{
|
|
146
|
+
name: "system.search",
|
|
147
|
+
version: "0.1.0",
|
|
148
|
+
label: "平台搜索",
|
|
149
|
+
description: "权限感知的功能搜索与业务 SearchProvider 聚合。",
|
|
150
|
+
resources: ["search"],
|
|
151
|
+
featureKeys: ["system.search"],
|
|
152
|
+
},
|
|
153
|
+
// @windy-module system.search end
|
|
154
|
+
// @windy-module system.data-governance begin
|
|
155
|
+
{
|
|
156
|
+
name: "system.data-governance",
|
|
157
|
+
version: "0.1.0",
|
|
158
|
+
label: "数据治理",
|
|
159
|
+
description: "敏感字段投影、明文访问与受治理导出。",
|
|
160
|
+
resources: [],
|
|
161
|
+
permissionKeys: ["system.user.reveal", "system.user.export"],
|
|
162
|
+
featureKeys: [],
|
|
163
|
+
},
|
|
164
|
+
// @windy-module system.data-governance end
|
|
165
|
+
] as const satisfies readonly SystemModuleDefinition[];
|
|
166
|
+
|
|
167
|
+
export type SystemModuleName = (typeof systemModuleDefinitions)[number]["name"];
|
|
168
|
+
|
|
169
|
+
export const systemModuleFactories: readonly ModuleFactory[] =
|
|
170
|
+
systemModuleDefinitions.map(
|
|
171
|
+
(definition) => () => createSystemCapabilityModule(definition),
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
export function systemModuleManifests(): ModuleManifest[] {
|
|
175
|
+
return systemModuleFactories.map((factory) => factory());
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
export function systemModuleManifest(name: SystemModuleName): ModuleManifest {
|
|
179
|
+
const definition = systemModuleDefinitions.find((item) => item.name === name);
|
|
180
|
+
if (!definition) throw new Error(`未知系统模块:${name}`);
|
|
181
|
+
return createSystemCapabilityModule(definition);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function createSystemCapabilityModule(
|
|
185
|
+
definition: SystemModuleDefinition,
|
|
186
|
+
): ModuleManifest {
|
|
187
|
+
const aggregate = systemFoundationModule();
|
|
188
|
+
const ownsPermission = (permissionKey: string) =>
|
|
189
|
+
!definition.excludedPermissionKeys?.includes(permissionKey) &&
|
|
190
|
+
(Boolean(definition.permissionKeys?.includes(permissionKey)) ||
|
|
191
|
+
definition.resources.includes(permissionResource(permissionKey)));
|
|
192
|
+
const ownsFeature = (featureKey: string | undefined) =>
|
|
193
|
+
Boolean(featureKey && definition.featureKeys.includes(featureKey));
|
|
194
|
+
const ownsGuard = (guard: { permissionKey?: string; featureKey?: string }) =>
|
|
195
|
+
guard.permissionKey
|
|
196
|
+
? ownsPermission(guard.permissionKey)
|
|
197
|
+
: ownsFeature(guard.featureKey);
|
|
198
|
+
const isCore = definition.name === "system";
|
|
199
|
+
|
|
200
|
+
return {
|
|
201
|
+
name: definition.name,
|
|
202
|
+
version: definition.version,
|
|
203
|
+
label: definition.label,
|
|
204
|
+
description: definition.description,
|
|
205
|
+
dependencies: isCore ? [] : ["system"],
|
|
206
|
+
menus: selectMenus(aggregate.menus, ownsGuard),
|
|
207
|
+
adminRoutes: aggregate.adminRoutes.filter(ownsGuard),
|
|
208
|
+
permissions: aggregate.permissions
|
|
209
|
+
.filter(({ key }) => ownsPermission(key))
|
|
210
|
+
.map((permission) => ({
|
|
211
|
+
...permission,
|
|
212
|
+
module: definition.name,
|
|
213
|
+
moduleLabel: definition.label,
|
|
214
|
+
})),
|
|
215
|
+
apiPermissions: aggregate.apiPermissions.filter(ownsGuard),
|
|
216
|
+
features: aggregate.features
|
|
217
|
+
.filter(({ key }) => ownsFeature(key))
|
|
218
|
+
.map((feature) => ({ ...feature, module: definition.name })),
|
|
219
|
+
migrations: isCore ? aggregate.migrations : [],
|
|
220
|
+
schemaExports: isCore ? aggregate.schemaExports : [],
|
|
221
|
+
tasks: aggregate.tasks.filter(ownsGuard),
|
|
222
|
+
tools: aggregate.tools.filter(ownsGuard),
|
|
223
|
+
providers: aggregate.providers.filter(ownsGuard),
|
|
224
|
+
dataPolicies:
|
|
225
|
+
definition.name === "system.data-governance"
|
|
226
|
+
? aggregate.dataPolicies
|
|
227
|
+
: [],
|
|
228
|
+
auditActions: isCore ? aggregate.auditActions : [],
|
|
229
|
+
metadata: { kind: "platform-capability" },
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
function permissionResource(permissionKey: string): string {
|
|
234
|
+
const parts = permissionKey.split(".");
|
|
235
|
+
return parts.length >= 3 ? parts.slice(1, -1).join(".") : "";
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function selectMenus(
|
|
239
|
+
menus: readonly MenuNode[],
|
|
240
|
+
ownsGuard: (guard: {
|
|
241
|
+
permissionKey?: string;
|
|
242
|
+
featureKey?: string;
|
|
243
|
+
}) => boolean,
|
|
244
|
+
): MenuNode[] {
|
|
245
|
+
return menus.flatMap((menu) => {
|
|
246
|
+
const children = selectMenus(menu.children || [], ownsGuard);
|
|
247
|
+
if (!children.length && !ownsGuard(menu)) return [];
|
|
248
|
+
return [{ ...menu, children: children.length ? children : undefined }];
|
|
249
|
+
});
|
|
250
|
+
}
|