| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 1 | 14 | 8 | 4% |
| Commands | 0 | 2 | 0 | 0% |
| Section tags | 0 | 3 | 1 | 0% |
What each file covers
Sections
1 shared · 14 only in A · 8 only in B- − Copilot instructions
- − General recommendations for working with Aspire
- − Running the application
- − Checking resources
- − Listing integrations
- − Debugging issues
- − Other Aspire MCP tools
- − Playwright MCP server
- − Updating the app host
- − Persistent containers
- − Aspire workload
- − Official documentation
- − BMAD AI 工作流
- − 与 CodeSpirit 规范集成
- + PermissionAttribute 特性
- + IHasPermissionService
- + AuditableEntityBase
- + IMultiTenant 接口
- + SQL 注入防护
- + CORS 配置
- + CSRF/XSS 防护
- + JWT 配置
- 获取帮助
Commands
0 shared · 2 only in A · 0 only in B- − dotnet tool install --global dotnet-outdated-tool
- − dotnet-outdated
Section tags
0 shared · 3 only in A · 1 only in B- − code-style
- − agent-behaviour
- − docs
- + database
Line diff
xin-lai/CodeSpirit · AGENTS.md
@@ −1 @@
1# Copilot instructions
2
3This repository is set up to use Aspire. Aspire is an orchestrator for the entire application and will take care of configuring dependencies, building, and running the application. The resources that make up the application are defined in `apphost.cs` including application code and external dependencies.
4
5## General recommendations for working with Aspire
61. Before making any changes always run the apphost using `aspire run` and inspect the state of resources to make sure you are building from a known state.
71. Changes to the _apphost.cs_ file will require a restart of the application to take effect.
82. Make changes incrementally and run the aspire application using the `aspire run` command to validate changes.
93. Use the Aspire MCP tools to check the status of resources and debug issues.
10
11## Running the application
12To run the application run the following command:
13
14```
15aspire run
16```
17
18If there is already an instance of the application running it will prompt to stop the existing instance. You only need to restart the application if code in `apphost.cs` is changed, but if you experience problems it can be useful to reset everything to the starting state.
19
20## Checking resources
21To check the status of resources defined in the app model use the _list resources_ tool. This will show you the current state of each resource and if there are any issues. If a resource is not running as expected you can use the _execute resource command_ tool to restart it or perform other actions.
22
23## Listing integrations
24IMPORTANT! When a user asks you to add a resource to the app model you should first use the _list integrations_ tool to get a list of the current versions of all the available integrations. You should try to use the version of the integration which aligns with the version of the Aspire.AppHost.Sdk. Some integration versions may have a preview suffix. Once you have identified the correct integration you should always use the _get integration docs_ tool to fetch the latest documentation for the integration and follow the links to get additional guidance.
25
26## Debugging issues
27IMPORTANT! Aspire is designed to capture rich logs and telemetry for all resources defined in the app model. Use the following diagnostic tools when debugging issues with the application before making changes to make sure you are focusing on the right things.
28
291. _list structured logs_; use this tool to get details about structured logs.
302. _list console logs_; use this tool to get details about console logs.
313. _list traces_; use this tool to get details about traces.
324. _list trace structured logs_; use this tool to get logs related to a trace
33
34## Other Aspire MCP tools
35
361. _select apphost_; use this tool if working with multiple app hosts within a workspace.
372. _list apphosts_; use this tool to get details about active app hosts.
38
39## Playwright MCP server
40
41The playwright MCP server has also been configured in this repository and you should use it to perform functional investigations of the resources defined in the app model as you work on the codebase. To get endpoints that can be used for navigation using the playwright MCP server use the list resources tool.
42
43## Updating the app host
44The user may request that you update the Aspire apphost. You can do this using the `aspire update` command. This will update the apphost to the latest version and some of the Aspire specific packages in referenced projects, however you may need to manually update other packages in the solution to ensure compatibility. You can consider using the `dotnet-outdated` with the users consent. To install the `dotnet-outdated` tool use the following command:
45
46```
47dotnet tool install --global dotnet-outdated-tool
48```
49
50## Persistent containers
51IMPORTANT! Consider avoiding persistent containers early during development to avoid creating state management issues when restarting the app.
52
53## Aspire workload
54IMPORTANT! The aspire workload is obsolete. You should never attempt to install or use the Aspire workload.
55
56## Official documentation
57IMPORTANT! Always prefer official documentation when available. The following sites contain the official documentation for Aspire and related components
58
591. https://aspire.dev
602. https://learn.microsoft.com/dotnet/aspire
613. https://nuget.org (for specific integration package details)
62
63## BMAD AI 工作流
64
65本项目已集成 BMAD (Breakthrough Method of Agile AI-Driven Development) 完整工作流,用于结构化的软件开发生命周期管理。
66
67### 快速开始
68
691. **小型任务/Bug 修复** (Quick Flow):
70 - `/quick-spec` - 创建技术规范
71 - `/quick-dev` - 实现变更
72 - `/code-review` - 代码审查
73
742. **完整功能开发** (Full Flow):
75 - `/product-brief` - 产品需求简报
76 - `/create-prd` - 创建 PRD
77 - `/create-architecture` - 架构设计
78 - `/create-epics-and-stories` - 拆分为 Epic 和 Story
79 - `/sprint-planning` - Sprint 规划
80 - `/dev-story` - 实现 Story
81 - `/code-review` - 代码审查
82 - `/retrospective` - 复盘
83
84### 与 CodeSpirit 规范集成
85
86BMAD 工作流已配置为自动遵循 CodeSpirit 的所有开发规范(位于 `.cursor/rules/`)。在使用 BMAD 时:
87
88- PRD 会自动考虑多租户、多数据库、AI 功能等项目特性
89- 架构设计会遵循依赖注入、缓存策略等规范
90- Story 实现会应用正确的命名约定、DTO 设计、控制器规范等
91- 代码审查会执行 CodeSpirit 特定的审查清单
92
93### 获取帮助
94
95任何时候,输入 `/bmad-help` 可获取上下文相关的指导。
96
97详细使用指南请参考:
98- **[BMAD 使用教程](Docs/bmad/bmad-tutorial.md)** - 完整的综合教程(推荐新手阅读)
99- [BMAD 工作流指南](Docs/bmad/bmad-workflow-guide.md) - 详细的工作流使用指南
100- [BMAD 团队培训指南](Docs/bmad/bmad-team-guide.md) - 团队培训材料
101- [BMAD 集成技能](.cursor/skills/bmad-integration/SKILL.md) - BMAD 与 CodeSpirit 集成
102- [项目上下文文档](project-context.md) - 项目上下文和规范引用
xin-lai/CodeSpirit · .cursor/rules/security.mdc
@@ +1 @@
1---
2description: CodeSpirit 安全规范 - 权限系统、审计实体、多租户隔离、数据保护
3globs:
4 - "**/Entities/**/*.cs"
5 - "**/*Entity*.cs"
6 - "**/Authorization/**/*.cs"
7 - "*Service*.cs"
8alwaysApply: false
9---
10
11# 安全规范
12
13> 📖 控制器级别的安全特性(`[Authorize]`、`[AllowAnonymous]`、`[NoAudit]`、`[Audit]`)参见 [controller.mdc](mdc:.cursor/rules/controller.mdc)
14
15## 权限系统架构
16
17### 权限代码格式
18
19权限代码由系统自动生成,格式为:`{module}_{controller}_{action}`
20
21```
22exam_questions_getList // 考试模块-题目控制器-获取列表
23identity_users_create // 身份模块-用户控制器-创建
24```
25
26### PermissionAttribute 特性
27
28用于自定义权限名称、描述和继承关系:
29
30```csharp
31using CodeSpirit.Core.Attributes;
32
33[HttpPut("{id}")]
34[Permission(
35 Name = "exam_questions_update", // 自定义权限代码
36 DisplayName = "更新题目", // 显示名称
37 Description = "允许更新题目内容", // 权限描述
38 Parent = "exam_questions", // 父级权限
39 AllowInheritedPermissions = new[] { "exam_questions_manage" } // 继承权限
40)]
41[DisplayName("更新题目")]
42public async Task<ActionResult<ApiResponse<QuestionDto>>> Update(
43 long id, [FromBody] UpdateQuestionDto dto)
44{
45 // 拥有 exam_questions_manage 权限的用户也可以执行此操作
46}
47```
48
49### 权限继承机制
50
51`AllowInheritedPermissions` 允许配置权限继承,用户拥有任一继承权限时可访问当前接口:
52
53```csharp
54// 方法级别继承
55[Permission(AllowInheritedPermissions = new[] { "Question.Manage", "Question.Admin" })]
56public async Task<ActionResult> UpdateQuestion(long id) { }
57```
58
59### IHasPermissionService
60
61服务层权限检查:
62
63```csharp
64public class QuestionService : IScopedDependency
65{
66 private readonly IHasPermissionService _permissionService;
67
68 public QuestionService(IHasPermissionService permissionService)
69 {
70 _permissionService = permissionService;
71 }
72
73 public async Task<bool> CanManageQuestionAsync()
74 {
75 // 检查用户是否拥有指定权限
76 return _permissionService.HasPermission("exam_questions_manage");
77 }
78
79 public async Task<bool> CanAccessModuleAsync()
80 {
81 // 检查导航权限(仅检查一二级权限)
82 return _permissionService.HasNavigationPermission("exam_questions");
83 }
84}
85```
86
87## 审计实体
88
89### AuditableEntityBase
90
91实体继承 `AuditableEntityBase<TKey>` 自动记录审计信息:
92
93```csharp
94using CodeSpirit.Shared.Entities;
95
96public class Question : AuditableEntityBase<long>, IMultiTenant
97{
98 // 自动记录以下字段(由框架自动填充):
99 // - CreatedBy (long) 创建人ID
100 // - CreatedAt (DateTime) 创建时间
101 // - UpdatedBy (long?) 更新人ID
102 // - UpdatedAt (DateTime?) 更新时间
103 // - IsDeleted (bool) 软删除标记
104 // - DeletedBy (long?) 删除人ID
105 // - DeletedAt (DateTime?) 删除时间
106
107 public string Content { get; set; } = string.Empty;
108 public string TenantId { get; set; } = string.Empty; // 多租户支持
109}
110```
111
112### 实体审计接口
113
114| 接口 | 说明 | 包含字段 |
115|-----|------|---------|
116| `ICreatable` | 创建审计 | `CreatedBy`, `CreatedAt` |
117| `IUpdatable` | 更新审计 | `UpdatedBy`, `UpdatedAt` |
118| `ISoftDelete` | 软删除 | `IsDeleted`, `DeletedBy`, `DeletedAt` |
119| `IFullAuditable` | 完整审计 | 以上全部 |
120
121## 多租户数据隔离
122
123### IMultiTenant 接口
124
125实体实现 `IMultiTenant` 接口,自动应用租户数据过滤:
126
127```csharp
128using CodeSpirit.Core;
129
130public class Question : AuditableEntityBase<long>, IMultiTenant
131{
132 public string TenantId { get; set; } = string.Empty; // 注意:类型为 string
133 public string Content { get; set; } = string.Empty;
134}
135```
136
137### 租户过滤行为
138
139```csharp
140// 查询时自动应用租户过滤器,无需手动添加 Where 条件
141public async Task<List<QuestionDto>> GetListAsync()
142{
143 var entities = await _dbContext.Questions
144 .ToListAsync(); // ✅ 自动过滤当前租户的数据
145 return _mapper.Map<List<QuestionDto>>(entities);
146}
147
148// ❌ 禁止:手动添加租户过滤(除非明确需要跨租户查询)
149public async Task<List<QuestionDto>> GetListAsync()
150{
151 var entities = await _dbContext.Questions
152 .Where(q => q.TenantId == _currentTenant.Id) // 不需要
153 .ToListAsync();
154}
155```
156
157## 数据保护
158
159### 排除敏感字段
160
161DTO 中排除不应返回给客户端的字段:
162
163```csharp
164using Newtonsoft.Json;
165using CodeSpirit.Amis.Attributes.Columns;
166
167public class UserDto
168{
169 public long Id { get; set; }
170 public string Username { get; set; } = string.Empty;
171
172 [JsonIgnore] // 不在 API 响应中返回
173 public string PasswordHash { get; set; } = string.Empty;
174
175 [IgnoreColumn] // 不在列表表格中显示
176 public string InternalNote { get; set; } = string.Empty;
177}
178```
179
180### 密码安全存储
181
182密码必须使用哈希存储,禁止明文:
183
184```csharp
185// ✅ 正确:存储密码哈希
186user.PasswordHash = _passwordHasher.HashPassword(user, password);
187
188// ❌ 禁止:明文存储密码
189user.Password = password;
190```
191
192## SQL 注入防护
193
194使用 EF Core 参数化查询(默认安全):
195
196```csharp
197// ✅ 安全:EF Core 自动参数化
198public async Task<Question?> GetByCodeAsync(string code)
199{
200 return await _dbContext.Questions
201 .FirstOrDefaultAsync(q => q.Code == code);
202}
203
204// ✅ 安全:使用参数化 SQL
205public async Task<List<Question>> SearchAsync(string keyword)
206{
207 return await _dbContext.Questions
208 .FromSqlInterpolated($"SELECT * FROM Questions WHERE Content LIKE {$"%{keyword}%"}")
209 .ToListAsync();
210}
211
212// ❌ 危险:字符串拼接(禁止)
213public async Task<Question?> GetByCodeAsync(string code)
214{
215 var sql = $"SELECT * FROM Questions WHERE Code = '{code}'"; // SQL 注入风险!
216 return await _dbContext.Questions.FromSqlRaw(sql).FirstOrDefaultAsync();
217}
218```
219
220## 日志安全
221
222### 敏感信息脱敏
223
224日志中禁止记录敏感信息:
225
226```csharp
227// ✅ 安全:只记录必要信息
228_logger.LogInformation("用户登录: {Username}, IP: {IpAddress}",
229 username,
230 ipAddress);
231
232// ✅ 安全:使用脱敏字符串
233_logger.LogInformation("API密钥验证: {MaskedKey}",
234 $"{apiKey[..4]}****{apiKey[^4..]}");
235
236// ❌ 危险:记录密码(禁止)
237_logger.LogInformation("用户登录: {Username}, Password: {Password}",
238 username, password);
239
240// ❌ 危险:记录完整 Token(禁止)
241_logger.LogInformation("Token: {Token}", token);
242```
243
244### 异常日志处理
245
246```csharp
247try
248{
249 await _service.ProcessAsync(data);
250}
251catch (Exception ex)
252{
253 // ✅ 记录异常但不暴露敏感上下文
254 _logger.LogError(ex, "处理数据失败: EntityId={EntityId}", data.Id);
255 throw; // 重新抛出,由统一异常处理器处理
256}
257```
258
259## CORS 配置
260
261框架统一配置 CORS,API 项目无需单独配置:
262
263```csharp
264// CommonApiServiceExtensions 已配置
265app.UseCors("AllowSpecificOriginsWithCredentials");
266```
267
268自定义配置(仅在特殊需求时):
269
270```csharp
271// appsettings.json
272{
273 "Cors": {
274 "AllowedOrigins": ["https://yourdomain.com"],
275 "AllowCredentials": true
276 }
277}
278```
279
280## CSRF/XSS 防护
281
282- **CSRF**: API 使用 JWT 认证,天然防御 CSRF 攻击
283- **XSS**: AMIS 框架自动转义输出,后端无需手动处理
284
285## 安全配置
286
287### JWT 配置
288
289```json
290{
291 "Jwt": {
292 "SecretKey": "your-secret-key-at-least-32-characters",
293 "Issuer": "CodeSpirit",
294 "Audience": "CodeSpirit",
295 "ExpireMinutes": 120,
296 "RefreshExpireMinutes": 10080
297 }
298}
299```
300
301### 审计配置
302
303```json
304{
305 "Audit": {
306 "Enabled": true,
307 "LogRequestParams": true,
308 "LogResponseData": false,
309 "SensitiveData": {
310 "Enabled": true,
311 "SensitiveFieldPatterns": ["password", "token", "apiKey", "secret"],
312 "ExcludedFields": ["password", "newPassword", "confirmPassword"]
313 }
314 }
315}
316```
317
318## 禁止事项
319
320| 禁止 | 原因 | 正确做法 |
321|-----|------|---------|
322| 明文存储密码 | 安全风险 | 使用密码哈希 |
323| SQL 字符串拼接 | SQL 注入风险 | EF Core 参数化查询 |
324| 日志记录密码/Token | 信息泄露 | 只记录必要标识信息 |
325| 手动租户过滤 | 可能遗漏 | 使用 `IMultiTenant` 自动过滤 |
326| DTO 返回密码字段 | 信息泄露 | 使用 `[JsonIgnore]` 排除 |
327
328## 安全检查清单
329
330- [ ] 实体继承 `AuditableEntityBase` 实现自动审计
331- [ ] 多租户实体实现 `IMultiTenant` 接口
332- [ ] DTO 中使用 `[JsonIgnore]` 排除敏感字段
333- [ ] 密码使用哈希存储
334- [ ] 数据库查询使用 EF Core 参数化(避免 `FromSqlRaw` 拼接)
335- [ ] 日志中不记录密码、Token 等敏感信息
336- [ ] 敏感操作配置权限检查
337- [ ] 定期审查权限配置和审计日志
338
339## 参考文件
340
341- 权限特性: [PermissionAttribute.cs](mdc:Src/CodeSpirit.Core/Attributes/PermissionAttribute.cs)
342- 权限服务: [IHasPermissionService.cs](mdc:Src/CodeSpirit.Core/Authorization/IHasPermissionService.cs)
343- 审计实体基类: [AuditableEntityBase.cs](mdc:Src/CodeSpirit.Shared/Entities/AuditableEntityBase.cs)
344- 多租户接口: [IMultiTenant.cs](mdc:Src/CodeSpirit.Core/IMultiTenant.cs)
345- 审计组件: [CodeSpirit.Audit/README.md](mdc:Src/Components/CodeSpirit.Audit/README.md)
346- 控制器规范: [controller.mdc](mdc:.cursor/rules/controller.mdc)
347
@@ −1 +1 @@
1−# Copilot instructions
1+---
2+description: CodeSpirit 安全规范 - 权限系统、审计实体、多租户隔离、数据保护
3+globs:
4+ - "**/Entities/**/*.cs"
5+ - "**/*Entity*.cs"
6+ - "**/Authorization/**/*.cs"
7+ - "*Service*.cs"
8+alwaysApply: false
9+---
210
3−This repository is set up to use Aspire. Aspire is an orchestrator for the entire application and will take care of configuring dependencies, building, and running the application. The resources that make up the application are defined in `apphost.cs` including application code and external dependencies.
11+# 安全规范
412
5−## General recommendations for working with Aspire
6−1. Before making any changes always run the apphost using `aspire run` and inspect the state of resources to make sure you are building from a known state.
7−1. Changes to the _apphost.cs_ file will require a restart of the application to take effect.
8−2. Make changes incrementally and run the aspire application using the `aspire run` command to validate changes.
9−3. Use the Aspire MCP tools to check the status of resources and debug issues.
13+> 📖 控制器级别的安全特性(`[Authorize]`、`[AllowAnonymous]`、`[NoAudit]`、`[Audit]`)参见 [controller.mdc](mdc:.cursor/rules/controller.mdc)
1014
11−## Running the application
12−To run the application run the following command:
15+## 权限系统架构
1316
17+### 权限代码格式
18+
19+权限代码由系统自动生成,格式为:`{module}_{controller}_{action}`
20+
1421 ```
15−aspire run
22+exam_questions_getList // 考试模块-题目控制器-获取列表
23+identity_users_create // 身份模块-用户控制器-创建
1624 ```
1725
18−If there is already an instance of the application running it will prompt to stop the existing instance. You only need to restart the application if code in `apphost.cs` is changed, but if you experience problems it can be useful to reset everything to the starting state.
26+### PermissionAttribute 特性
1927
20−## Checking resources
21−To check the status of resources defined in the app model use the _list resources_ tool. This will show you the current state of each resource and if there are any issues. If a resource is not running as expected you can use the _execute resource command_ tool to restart it or perform other actions.
28+用于自定义权限名称、描述和继承关系:
2229
23−## Listing integrations
24−IMPORTANT! When a user asks you to add a resource to the app model you should first use the _list integrations_ tool to get a list of the current versions of all the available integrations. You should try to use the version of the integration which aligns with the version of the Aspire.AppHost.Sdk. Some integration versions may have a preview suffix. Once you have identified the correct integration you should always use the _get integration docs_ tool to fetch the latest documentation for the integration and follow the links to get additional guidance.
30+```csharp
31+using CodeSpirit.Core.Attributes;
2532
26−## Debugging issues
27−IMPORTANT! Aspire is designed to capture rich logs and telemetry for all resources defined in the app model. Use the following diagnostic tools when debugging issues with the application before making changes to make sure you are focusing on the right things.
33+[HttpPut("{id}")]
34+[Permission(
35+ Name = "exam_questions_update", // 自定义权限代码
36+ DisplayName = "更新题目", // 显示名称
37+ Description = "允许更新题目内容", // 权限描述
38+ Parent = "exam_questions", // 父级权限
39+ AllowInheritedPermissions = new[] { "exam_questions_manage" } // 继承权限
40+)]
41+[DisplayName("更新题目")]
42+public async Task<ActionResult<ApiResponse<QuestionDto>>> Update(
43+ long id, [FromBody] UpdateQuestionDto dto)
44+{
45+ // 拥有 exam_questions_manage 权限的用户也可以执行此操作
46+}
47+```
2848
29−1. _list structured logs_; use this tool to get details about structured logs.
30−2. _list console logs_; use this tool to get details about console logs.
31−3. _list traces_; use this tool to get details about traces.
32−4. _list trace structured logs_; use this tool to get logs related to a trace
49+### 权限继承机制
3350
34−## Other Aspire MCP tools
51+`AllowInheritedPermissions` 允许配置权限继承,用户拥有任一继承权限时可访问当前接口:
3552
36−1. _select apphost_; use this tool if working with multiple app hosts within a workspace.
37−2. _list apphosts_; use this tool to get details about active app hosts.
53+```csharp
54+// 方法级别继承
55+[Permission(AllowInheritedPermissions = new[] { "Question.Manage", "Question.Admin" })]
56+public async Task<ActionResult> UpdateQuestion(long id) { }
57+```
3858
39−## Playwright MCP server
59+### IHasPermissionService
4060
41−The playwright MCP server has also been configured in this repository and you should use it to perform functional investigations of the resources defined in the app model as you work on the codebase. To get endpoints that can be used for navigation using the playwright MCP server use the list resources tool.
61+服务层权限检查:
4262
43−## Updating the app host
44−The user may request that you update the Aspire apphost. You can do this using the `aspire update` command. This will update the apphost to the latest version and some of the Aspire specific packages in referenced projects, however you may need to manually update other packages in the solution to ensure compatibility. You can consider using the `dotnet-outdated` with the users consent. To install the `dotnet-outdated` tool use the following command:
63+```csharp
64+public class QuestionService : IScopedDependency
65+{
66+ private readonly IHasPermissionService _permissionService;
4567
68+ public QuestionService(IHasPermissionService permissionService)
69+ {
70+ _permissionService = permissionService;
71+ }
72+
73+ public async Task<bool> CanManageQuestionAsync()
74+ {
75+ // 检查用户是否拥有指定权限
76+ return _permissionService.HasPermission("exam_questions_manage");
77+ }
78+
79+ public async Task<bool> CanAccessModuleAsync()
80+ {
81+ // 检查导航权限(仅检查一二级权限)
82+ return _permissionService.HasNavigationPermission("exam_questions");
83+ }
84+}
4685 ```
47−dotnet tool install --global dotnet-outdated-tool
86+
87+## 审计实体
88+
89+### AuditableEntityBase
90+
91+实体继承 `AuditableEntityBase<TKey>` 自动记录审计信息:
92+
93+```csharp
94+using CodeSpirit.Shared.Entities;
95+
96+public class Question : AuditableEntityBase<long>, IMultiTenant
97+{
98+ // 自动记录以下字段(由框架自动填充):
99+ // - CreatedBy (long) 创建人ID
100+ // - CreatedAt (DateTime) 创建时间
101+ // - UpdatedBy (long?) 更新人ID
102+ // - UpdatedAt (DateTime?) 更新时间
103+ // - IsDeleted (bool) 软删除标记
104+ // - DeletedBy (long?) 删除人ID
105+ // - DeletedAt (DateTime?) 删除时间
106+
107+ public string Content { get; set; } = string.Empty;
108+ public string TenantId { get; set; } = string.Empty; // 多租户支持
109+}
48110 ```
49111
50−## Persistent containers
51−IMPORTANT! Consider avoiding persistent containers early during development to avoid creating state management issues when restarting the app.
112+### 实体审计接口
52113
53−## Aspire workload
54−IMPORTANT! The aspire workload is obsolete. You should never attempt to install or use the Aspire workload.
114+| 接口 | 说明 | 包含字段 |
115+|-----|------|---------|
116+| `ICreatable` | 创建审计 | `CreatedBy`, `CreatedAt` |
117+| `IUpdatable` | 更新审计 | `UpdatedBy`, `UpdatedAt` |
118+| `ISoftDelete` | 软删除 | `IsDeleted`, `DeletedBy`, `DeletedAt` |
119+| `IFullAuditable` | 完整审计 | 以上全部 |
55120
56−## Official documentation
57−IMPORTANT! Always prefer official documentation when available. The following sites contain the official documentation for Aspire and related components
121+## 多租户数据隔离
58122
59−1. https://aspire.dev
60−2. https://learn.microsoft.com/dotnet/aspire
61−3. https://nuget.org (for specific integration package details)
123+### IMultiTenant 接口
62124
63−## BMAD AI 工作流
125+实体实现 `IMultiTenant` 接口,自动应用租户数据过滤:
64126
65−本项目已集成 BMAD (Breakthrough Method of Agile AI-Driven Development) 完整工作流,用于结构化的软件开发生命周期管理。
127+```csharp
128+using CodeSpirit.Core;
66129
67−### 快速开始
130+public class Question : AuditableEntityBase<long>, IMultiTenant
131+{
132+ public string TenantId { get; set; } = string.Empty; // 注意:类型为 string
133+ public string Content { get; set; } = string.Empty;
134+}
135+```
68136
69−1. **小型任务/Bug 修复** (Quick Flow):
70− - `/quick-spec` - 创建技术规范
71− - `/quick-dev` - 实现变更
72− - `/code-review` - 代码审查
137+### 租户过滤行为
73138
74−2. **完整功能开发** (Full Flow):
75− - `/product-brief` - 产品需求简报
76− - `/create-prd` - 创建 PRD
77− - `/create-architecture` - 架构设计
78− - `/create-epics-and-stories` - 拆分为 Epic 和 Story
79− - `/sprint-planning` - Sprint 规划
80− - `/dev-story` - 实现 Story
81− - `/code-review` - 代码审查
82− - `/retrospective` - 复盘
139+```csharp
140+// 查询时自动应用租户过滤器,无需手动添加 Where 条件
141+public async Task<List<QuestionDto>> GetListAsync()
142+{
143+ var entities = await _dbContext.Questions
144+ .ToListAsync(); // ✅ 自动过滤当前租户的数据
145+ return _mapper.Map<List<QuestionDto>>(entities);
146+}
83147
84−### 与 CodeSpirit 规范集成
148+// ❌ 禁止:手动添加租户过滤(除非明确需要跨租户查询)
149+public async Task<List<QuestionDto>> GetListAsync()
150+{
151+ var entities = await _dbContext.Questions
152+ .Where(q => q.TenantId == _currentTenant.Id) // 不需要
153+ .ToListAsync();
154+}
155+```
85156
86−BMAD 工作流已配置为自动遵循 CodeSpirit 的所有开发规范(位于 `.cursor/rules/`)。在使用 BMAD 时:
157+## 数据保护
87158
88−- PRD 会自动考虑多租户、多数据库、AI 功能等项目特性
89−- 架构设计会遵循依赖注入、缓存策略等规范
90−- Story 实现会应用正确的命名约定、DTO 设计、控制器规范等
91−- 代码审查会执行 CodeSpirit 特定的审查清单
159+### 排除敏感字段
92160
93−### 获取帮助
161+DTO 中排除不应返回给客户端的字段:
94162
95−任何时候,输入 `/bmad-help` 可获取上下文相关的指导。
163+```csharp
164+using Newtonsoft.Json;
165+using CodeSpirit.Amis.Attributes.Columns;
96166
97−详细使用指南请参考:
98−- **[BMAD 使用教程](Docs/bmad/bmad-tutorial.md)** - 完整的综合教程(推荐新手阅读)
99−- [BMAD 工作流指南](Docs/bmad/bmad-workflow-guide.md) - 详细的工作流使用指南
100−- [BMAD 团队培训指南](Docs/bmad/bmad-team-guide.md) - 团队培训材料
101−- [BMAD 集成技能](.cursor/skills/bmad-integration/SKILL.md) - BMAD 与 CodeSpirit 集成
102−- [项目上下文文档](project-context.md) - 项目上下文和规范引用
167+public class UserDto
168+{
169+ public long Id { get; set; }
170+ public string Username { get; set; } = string.Empty;
171+
172+ [JsonIgnore] // 不在 API 响应中返回
173+ public string PasswordHash { get; set; } = string.Empty;
174+
175+ [IgnoreColumn] // 不在列表表格中显示
176+ public string InternalNote { get; set; } = string.Empty;
177+}
178+```
179+
180+### 密码安全存储
181+
182+密码必须使用哈希存储,禁止明文:
183+
184+```csharp
185+// ✅ 正确:存储密码哈希
186+user.PasswordHash = _passwordHasher.HashPassword(user, password);
187+
188+// ❌ 禁止:明文存储密码
189+user.Password = password;
190+```
191+
192+## SQL 注入防护
193+
194+使用 EF Core 参数化查询(默认安全):
195+
196+```csharp
197+// ✅ 安全:EF Core 自动参数化
198+public async Task<Question?> GetByCodeAsync(string code)
199+{
200+ return await _dbContext.Questions
201+ .FirstOrDefaultAsync(q => q.Code == code);
202+}
203+
204+// ✅ 安全:使用参数化 SQL
205+public async Task<List<Question>> SearchAsync(string keyword)
206+{
207+ return await _dbContext.Questions
208+ .FromSqlInterpolated($"SELECT * FROM Questions WHERE Content LIKE {$"%{keyword}%"}")
209+ .ToListAsync();
210+}
211+
212+// ❌ 危险:字符串拼接(禁止)
213+public async Task<Question?> GetByCodeAsync(string code)
214+{
215+ var sql = $"SELECT * FROM Questions WHERE Code = '{code}'"; // SQL 注入风险!
216+ return await _dbContext.Questions.FromSqlRaw(sql).FirstOrDefaultAsync();
217+}
218+```
219+
220+## 日志安全
221+
222+### 敏感信息脱敏
223+
224+日志中禁止记录敏感信息:
225+
226+```csharp
227+// ✅ 安全:只记录必要信息
228+_logger.LogInformation("用户登录: {Username}, IP: {IpAddress}",
229+ username,
230+ ipAddress);
231+
232+// ✅ 安全:使用脱敏字符串
233+_logger.LogInformation("API密钥验证: {MaskedKey}",
234+ $"{apiKey[..4]}****{apiKey[^4..]}");
235+
236+// ❌ 危险:记录密码(禁止)
237+_logger.LogInformation("用户登录: {Username}, Password: {Password}",
238+ username, password);
239+
240+// ❌ 危险:记录完整 Token(禁止)
241+_logger.LogInformation("Token: {Token}", token);
242+```
243+
244+### 异常日志处理
245+
246+```csharp
247+try
248+{
249+ await _service.ProcessAsync(data);
250+}
251+catch (Exception ex)
252+{
253+ // ✅ 记录异常但不暴露敏感上下文
254+ _logger.LogError(ex, "处理数据失败: EntityId={EntityId}", data.Id);
255+ throw; // 重新抛出,由统一异常处理器处理
256+}
257+```
258+
259+## CORS 配置
260+
261+框架统一配置 CORS,API 项目无需单独配置:
262+
263+```csharp
264+// CommonApiServiceExtensions 已配置
265+app.UseCors("AllowSpecificOriginsWithCredentials");
266+```
267+
268+自定义配置(仅在特殊需求时):
269+
270+```csharp
271+// appsettings.json
272+{
273+ "Cors": {
274+ "AllowedOrigins": ["https://yourdomain.com"],
275+ "AllowCredentials": true
276+ }
277+}
278+```
279+
280+## CSRF/XSS 防护
281+
282+- **CSRF**: API 使用 JWT 认证,天然防御 CSRF 攻击
283+- **XSS**: AMIS 框架自动转义输出,后端无需手动处理
284+
285+## 安全配置
286+
287+### JWT 配置
288+
289+```json
290+{
291+ "Jwt": {
292+ "SecretKey": "your-secret-key-at-least-32-characters",
293+ "Issuer": "CodeSpirit",
294+ "Audience": "CodeSpirit",
295+ "ExpireMinutes": 120,
296+ "RefreshExpireMinutes": 10080
297+ }
298+}
299+```
300+
301+### 审计配置
302+
303+```json
304+{
305+ "Audit": {
306+ "Enabled": true,
307+ "LogRequestParams": true,
308+ "LogResponseData": false,
309+ "SensitiveData": {
310+ "Enabled": true,
311+ "SensitiveFieldPatterns": ["password", "token", "apiKey", "secret"],
312+ "ExcludedFields": ["password", "newPassword", "confirmPassword"]
313+ }
314+ }
315+}
316+```
317+
318+## 禁止事项
319+
320+| 禁止 | 原因 | 正确做法 |
321+|-----|------|---------|
322+| 明文存储密码 | 安全风险 | 使用密码哈希 |
323+| SQL 字符串拼接 | SQL 注入风险 | EF Core 参数化查询 |
324+| 日志记录密码/Token | 信息泄露 | 只记录必要标识信息 |
325+| 手动租户过滤 | 可能遗漏 | 使用 `IMultiTenant` 自动过滤 |
326+| DTO 返回密码字段 | 信息泄露 | 使用 `[JsonIgnore]` 排除 |
327+
328+## 安全检查清单
329+
330+- [ ] 实体继承 `AuditableEntityBase` 实现自动审计
331+- [ ] 多租户实体实现 `IMultiTenant` 接口
332+- [ ] DTO 中使用 `[JsonIgnore]` 排除敏感字段
333+- [ ] 密码使用哈希存储
334+- [ ] 数据库查询使用 EF Core 参数化(避免 `FromSqlRaw` 拼接)
335+- [ ] 日志中不记录密码、Token 等敏感信息
336+- [ ] 敏感操作配置权限检查
337+- [ ] 定期审查权限配置和审计日志
338+
339+## 参考文件
340+
341+- 权限特性: [PermissionAttribute.cs](mdc:Src/CodeSpirit.Core/Attributes/PermissionAttribute.cs)
342+- 权限服务: [IHasPermissionService.cs](mdc:Src/CodeSpirit.Core/Authorization/IHasPermissionService.cs)
343+- 审计实体基类: [AuditableEntityBase.cs](mdc:Src/CodeSpirit.Shared/Entities/AuditableEntityBase.cs)
344+- 多租户接口: [IMultiTenant.cs](mdc:Src/CodeSpirit.Core/IMultiTenant.cs)
345+- 审计组件: [CodeSpirit.Audit/README.md](mdc:Src/Components/CodeSpirit.Audit/README.md)
346+- 控制器规范: [controller.mdc](mdc:.cursor/rules/controller.mdc)
347+
