agent-workflow-kit-cli 1.3.2 → 1.3.3

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.
Files changed (39) hide show
  1. package/dist/cli/commands/add.js +3 -1
  2. package/dist/cli/commands/init.js +6 -0
  3. package/dist/core/analyzer.js +70 -0
  4. package/dist/core/detector.js +22 -0
  5. package/package.json +1 -1
  6. package/templates/common/AGENTS.md.hbs +4 -0
  7. package/templates/common/GLOBAL_RULES.md +101 -0
  8. package/templates/dotnet/AGENTS.md.hbs +34 -34
  9. package/templates/dotnet/rules/api-structure.md +15 -15
  10. package/templates/dotnet/rules/csharp-style.md +17 -17
  11. package/templates/dotnet/rules/dependency-injection.md +12 -12
  12. package/templates/dotnet/rules/error-handling-validation.md +15 -15
  13. package/templates/dotnet/skills/dotnet-controller/SKILL.md +16 -16
  14. package/templates/express/AGENTS.md.hbs +33 -33
  15. package/templates/express/rules/error-handling.md +18 -18
  16. package/templates/express/rules/express-style.md +19 -19
  17. package/templates/express/rules/router-controller.md +16 -16
  18. package/templates/express/skills/express-endpoint/SKILL.md +14 -14
  19. package/templates/golang/AGENTS.md.hbs +36 -0
  20. package/templates/golang/rules/concurrency.md +71 -0
  21. package/templates/golang/rules/error-handling.md +42 -0
  22. package/templates/golang/rules/golang-style.md +24 -0
  23. package/templates/golang/rules/project-layout.md +39 -0
  24. package/templates/nestjs/AGENTS.md.hbs +29 -29
  25. package/templates/nestjs/rules/module-architecture.md +14 -14
  26. package/templates/nestjs/rules/nestjs-style.md +12 -12
  27. package/templates/nestjs/rules/validation-errors.md +15 -15
  28. package/templates/nestjs/skills/nestjs-module/SKILL.md +15 -15
  29. package/templates/next-js/AGENTS.md.hbs +32 -32
  30. package/templates/next-js/rules/data-fetching-mutations.md +17 -17
  31. package/templates/next-js/rules/next-style.md +17 -17
  32. package/templates/next-js/rules/seo-metadata.md +18 -18
  33. package/templates/next-js/rules/server-client-components.md +17 -17
  34. package/templates/next-js/skills/next-feature/SKILL.md +16 -16
  35. package/templates/rust/AGENTS.md.hbs +34 -0
  36. package/templates/rust/rules/error-handling.md +36 -0
  37. package/templates/rust/rules/memory-concurrency.md +47 -0
  38. package/templates/rust/rules/project-layout.md +49 -0
  39. package/templates/rust/rules/rust-style.md +26 -0
@@ -11,7 +11,7 @@ import { analyzeModule } from "../../core/analyzer.js";
11
11
  import { updateGitignore } from "./init.js";
12
12
  export async function runAdd(stack, options) {
13
13
  const targetStack = stack.toLowerCase();
14
- const validStacks = ["spring-boot", "react-ts", "next-js", "nestjs", "express", "fastapi", "python-ai", "dotnet"];
14
+ const validStacks = ["spring-boot", "react-ts", "next-js", "nestjs", "express", "fastapi", "python-ai", "dotnet", "golang", "rust"];
15
15
  if (!validStacks.includes(targetStack)) {
16
16
  console.error(chalk.red(`Error: Invalid stack '${stack}'. Supported stacks are: ${validStacks.join(", ")}`));
17
17
  process.exit(1);
@@ -40,7 +40,9 @@ export async function runAdd(stack, options) {
40
40
  // 3. Write or Update AGENTS.md and/or GEMINI.md in the target directory
41
41
  const geminiPath = path.join(targetDir, "GEMINI.md");
42
42
  const agentsPath = path.join(targetDir, "AGENTS.md");
43
+ const globalRules = await readStaticTemplateFile("common/GLOBAL_RULES.md").catch(() => "");
43
44
  const moduleAgentsContent = await renderTemplate("common/AGENTS.md.hbs", {
45
+ globalRules,
44
46
  stackContent,
45
47
  });
46
48
  if (options.agent === "antigravity" || options.agent === "both") {
@@ -183,7 +183,9 @@ export async function runInit(options) {
183
183
  }
184
184
  if (modules.length === 0) {
185
185
  console.log(chalk.yellow("No standard stacks detected automatically. Creating general agent guidelines at root."));
186
+ const globalRules = await readStaticTemplateFile("common/GLOBAL_RULES.md").catch(() => "");
186
187
  const finalAgentsContent = await renderTemplate("common/AGENTS.md.hbs", {
188
+ globalRules,
187
189
  stackContent: "",
188
190
  });
189
191
  if (options.agent === "antigravity" || options.agent === "both") {
@@ -219,7 +221,9 @@ export async function runInit(options) {
219
221
  const targetFileName = isAntigravity ? "GEMINI.md" : "AGENTS.md";
220
222
  monorepoContent += `- **${mod.name}** (${mod.stacks.join(", ")}): Stack rules and guidelines are located at [${mod.name}/${targetFileName}](file:///${mod.dir.replace(/\\/g, "/")}/${targetFileName})\n`;
221
223
  }
224
+ const globalRules = await readStaticTemplateFile("common/GLOBAL_RULES.md").catch(() => "");
222
225
  const rootAgentsContent = await renderTemplate("common/AGENTS.md.hbs", {
226
+ globalRules,
223
227
  stackContent: monorepoContent.trim(),
224
228
  });
225
229
  const rootGeminiPath = path.join(cwd, "GEMINI.md");
@@ -276,7 +280,9 @@ export async function runInit(options) {
276
280
  // Render agent files for this module
277
281
  const geminiPath = path.join(mod.dir, "GEMINI.md");
278
282
  const agentsPath = path.join(mod.dir, "AGENTS.md");
283
+ const globalRules = await readStaticTemplateFile("common/GLOBAL_RULES.md").catch(() => "");
279
284
  const moduleAgentsContent = await renderTemplate("common/AGENTS.md.hbs", {
285
+ globalRules,
280
286
  stackContent,
281
287
  });
282
288
  if (options.agent === "antigravity" || options.agent === "both") {
@@ -519,6 +519,12 @@ export async function analyzeModule(dir, stacks) {
519
519
  else if (stack === "dotnet") {
520
520
  context["dotnet"] = await analyzeDotnet(dir);
521
521
  }
522
+ else if (stack === "golang") {
523
+ context["golang"] = await analyzeGolang(dir);
524
+ }
525
+ else if (stack === "rust") {
526
+ context["rust"] = await analyzeRust(dir);
527
+ }
522
528
  }
523
529
  return context;
524
530
  }
@@ -605,3 +611,67 @@ async function findCsprojFiles(dir) {
605
611
  await traverse(dir);
606
612
  return files;
607
613
  }
614
+ async function analyzeGolang(dir) {
615
+ let goVersion = "1.22";
616
+ let moduleName = path.basename(dir);
617
+ try {
618
+ const goModPath = path.join(dir, "go.mod");
619
+ const content = await fs.readFile(goModPath, "utf8");
620
+ const lines = content.split("\n");
621
+ for (const line of lines) {
622
+ const trimmed = line.trim();
623
+ if (trimmed.startsWith("module ")) {
624
+ moduleName = trimmed.replace("module ", "").trim();
625
+ }
626
+ else if (trimmed.startsWith("go ")) {
627
+ goVersion = trimmed.replace("go ", "").trim();
628
+ }
629
+ }
630
+ }
631
+ catch {
632
+ // Keep default
633
+ }
634
+ return { goVersion, moduleName };
635
+ }
636
+ async function analyzeRust(dir) {
637
+ let projectName = path.basename(dir);
638
+ let rustEdition = "2021";
639
+ let isWorkspace = false;
640
+ try {
641
+ const cargoTomlPath = path.join(dir, "Cargo.toml");
642
+ const content = await fs.readFile(cargoTomlPath, "utf8");
643
+ if (content.includes("[workspace]")) {
644
+ isWorkspace = true;
645
+ }
646
+ // Very basic parsing for name and edition
647
+ const lines = content.split("\n");
648
+ let inPackageSection = false;
649
+ for (const line of lines) {
650
+ const trimmed = line.trim();
651
+ if (trimmed.startsWith("[package]")) {
652
+ inPackageSection = true;
653
+ }
654
+ else if (trimmed.startsWith("[")) {
655
+ inPackageSection = false;
656
+ }
657
+ if (inPackageSection) {
658
+ if (trimmed.startsWith("name")) {
659
+ const match = trimmed.match(/name\s*=\s*"(.*)"/);
660
+ if (match && match[1]) {
661
+ projectName = match[1];
662
+ }
663
+ }
664
+ else if (trimmed.startsWith("edition")) {
665
+ const match = trimmed.match(/edition\s*=\s*"(.*)"/);
666
+ if (match && match[1]) {
667
+ rustEdition = match[1];
668
+ }
669
+ }
670
+ }
671
+ }
672
+ }
673
+ catch {
674
+ // Keep default
675
+ }
676
+ return { projectName, rustEdition, isWorkspace };
677
+ }
@@ -130,6 +130,28 @@ async function detectProjectStackDirect(cwd) {
130
130
  catch {
131
131
  // Ignore
132
132
  }
133
+ // 5. Detect Golang (go.mod)
134
+ try {
135
+ const goModPath = path.join(cwd, "go.mod");
136
+ const stat = await fs.stat(goModPath);
137
+ if (stat.isFile()) {
138
+ stacks.push("golang");
139
+ }
140
+ }
141
+ catch {
142
+ // Ignore
143
+ }
144
+ // 6. Detect Rust (Cargo.toml)
145
+ try {
146
+ const cargoTomlPath = path.join(cwd, "Cargo.toml");
147
+ const stat = await fs.stat(cargoTomlPath);
148
+ if (stat.isFile()) {
149
+ stacks.push("rust");
150
+ }
151
+ }
152
+ catch {
153
+ // Ignore
154
+ }
133
155
  return stacks;
134
156
  }
135
157
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-workflow-kit-cli",
3
- "version": "1.3.2",
3
+ "version": "1.3.3",
4
4
  "description": "AI-Ready Repository Workflow Generator & Guideline Optimizer for Codex and Antigravity",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,3 +1,7 @@
1
+ {{{globalRules}}}
2
+
3
+ ---
4
+
1
5
  # Repository Agent Guidelines
2
6
 
3
7
  This repository implements the `agent-workflow-kit-cli` standards.
@@ -0,0 +1,101 @@
1
+ # UNIVERSAL GLOBAL RULES (GLOBAL_RULES.md)
2
+
3
+ NOTICE TO AI AGENT: All source code generated in this project – regardless of language, framework, or architecture (Frontend, Backend, AI Agent) – must strictly adhere to the following 4 pillars of engineering rules. Any violations will result in code rejection.
4
+
5
+ ---
6
+
7
+ ## 🏛️ PILLAR 1: DATABASE & MIGRATION GOVERNANCE
8
+ The main goal is to protect data integrity, prevent data loss in Production environments, and optimize core query performance.
9
+
10
+ ### 1.1 Strict No Auto-Sync in Production
11
+ - **Rule:** Never use properties or commands that automatically synchronize schema changes directly to the database in a Production environment (e.g., `synchronize: true` in TypeORM/Hibernate, `prisma db push`, `sequelize.sync()`, or GORM's `db.AutoMigrate()` running automatically at startup).
12
+ - **Mandatory Solution:** All structural changes (adding columns, modifying types, dropping tables, creating indices) must be written in independent, timestamped migration files (e.g., `YYYYMMDDHHMMSS_migration_name`).
13
+ - **Workflow:** Migration files must be verified locally and executed only via the ORM/Driver CLI tool prior to production deployment.
14
+
15
+ ### 1.2 Strict Indexing Strategy
16
+ - **Prerequisite:** Any column frequently appearing in `WHERE` clauses, `JOIN` conditions, or `ORDER BY` statements in large-scale growing tables (e.g., `user_id`, `status`, `created_at`) must be indexed.
17
+ - **Write Prevention:** Avoid indexing columns indiscriminately. For columns with high-frequency updates (`INSERT`/`UPDATE`/`DELETE`), redundant indices will severely degrade write performance.
18
+ - **Unique Constraints:** Identity fields requiring uniqueness (e.g., `email`, `username`, `phone_number`) must be configured with a `UNIQUE` index at the Database level, not just validated in the Application code.
19
+
20
+ ### 1.3 Eliminate N+1 Query Issues
21
+ - **Issue:** Never query child relations inside loops (`for`, `while`, `forEach`) for a list of records (e.g., fetching 100 courses and looping 100 times to execute SQL to get the instructor for each course).
22
+ - **Solution:** Use Eager Loading (direct SQL `JOIN`s, or pre-fetching methods like `.Include()` in EF Core, `Preload` in GORM, `select_related` / `prefetch_related` in Python) to retrieve all relational data in a single query.
23
+
24
+ ### 1.4 Connection Pool Management
25
+ - All database connections must go through a Connection Pool. The AI Agent must not manually open/close connections per request.
26
+ - You must configure explicit limits: `max_connections` (maximum connections), `idle_timeout` (unused connection release time), and `max_lifetime` to prevent database server resource exhaustion.
27
+
28
+ ---
29
+
30
+ ## 🛡️ PILLAR 2: SECURITY & AUTH HARDENING
31
+ Ensure the system is immune to vulnerabilities listed in the OWASP Top 10.
32
+
33
+ ### 2.1 Zero Hardcoded Secrets
34
+ - **Strict Prohibition:** Never write database connection strings, third-party API Keys (e.g., OpenAI, Stripe), JWT secrets, or system passwords directly into the codebase.
35
+ - **Implementation:** All sensitive values must be loaded into the application via Environment Variables or System Env.
36
+ - **Documentation:** Every project must include a `.env.example` file listing all required environment keys with empty values, guiding others on how to configure the project.
37
+
38
+ ### 2.2 JWT Lifecycle & Storage Standards (JSON Web Token)
39
+ - **Access Token:** Configure a short lifespan (minimum 15 minutes, maximum 1 hour) to reduce the window of vulnerability if the token is compromised.
40
+ - **Refresh Token:** Must have a longer expiration (7 days to 30 days) and must be stored in an `HttpOnly`, `Secure`, `SameSite=Strict` cookie on the client side. Storing Refresh Tokens in `localStorage` or `sessionStorage` is strictly prohibited to prevent account takeover via XSS.
41
+
42
+ ### 2.3 Input Validation & Injection Defense
43
+ - **Mass Assignment Defense (Overposting):** Never map client request objects (e.g., `req.body`) directly to database update statements without filtering. Data must be validated and filtered using DTOs (Data Transfer Objects), Pydantic Schemas, or Struct validations.
44
+ - **SQL Injection Defense:** All database queries must use Parameterized Queries (Prepared Statements). String concatenation to construct dynamic SQL/NoSQL queries is strictly prohibited.
45
+
46
+ ### 2.4 CORS & Rate Limiting
47
+ - **CORS:** Using `Origin: '*'` is strictly prohibited in Production. A whitelist of permitted frontend domains must be explicitly defined.
48
+ - **Rate Limiting:** Sensitive or resource-intensive endpoints (e.g., Login, Register, Forgot Password, Send OTP, LLM AI generation APIs) must be protected by rate-limiting middleware (e.g., maximum 5 requests/minute/IP) to defend against DoS and brute-force attacks.
49
+
50
+ ---
51
+
52
+ ## 🚦 PILLAR 3: OBSERVABILITY & STRUCTURED LOGS
53
+ Transition the system from blind debugging to proactive monitoring using structured log data.
54
+
55
+ ### 3.1 Structured Logging Standards
56
+ - Printing raw text directly to the console (e.g., `console.log()`, `fmt.Println()`, `print()`, or `println!()`) is prohibited in Production.
57
+ - **Mandatory Format:** All logs written to stdout/stderr must use JSON format so that Log Aggregators (ELK Stack, Grafana Loki, Datadog) can automatically parse and index them.
58
+ - **Required fields in every JSON log line:**
59
+ ```json
60
+ {
61
+ "timestamp": "2026-06-13T16:00:00.000Z",
62
+ "level": "ERROR",
63
+ "trace_id": "c4b37d89-9821-47d3-b12a-7e61a4b9812f",
64
+ "context": "PaymentService",
65
+ "message": "Failed to connect to Stripe payment gateway",
66
+ "error_details": {
67
+ "code": "STRIPE_TIMEOUT",
68
+ "stack": "Error: Timeout after 5000ms at StripeClient.request..."
69
+ }
70
+ }
71
+ ```
72
+
73
+ ### 3.2 Strict Log Levels
74
+ The AI Agent must select the appropriate log level for every event:
75
+ - **DEBUG:** Detailed execution flow tracing during development (must be automatically disabled or hidden in Production).
76
+ - **INFO:** Normal but important system events (e.g., Server started on port 8080, cache cleanup completed).
77
+ - **WARN:** Abnormal situations that do not fail the request (e.g., user entered incorrect password, third-party API responded slowly but succeeded).
78
+ - **ERROR:** Severe errors that terminate request execution and require developer intervention (e.g., database connection loss, invoice file write failure, logic errors).
79
+
80
+ ### 3.3 Masking PII (Personally Identifiable Information)
81
+ - Never print sensitive PII into public log systems.
82
+ - Fields containing passwords, credit card numbers, national IDs/passports, and access/refresh tokens must be masked (e.g., converted to `*`) or omitted from the logged objects.
83
+
84
+ ---
85
+
86
+ ## 📦 PILLAR 4: CONTAINER & CI/CD GUARDRAILS
87
+ Ensure applications can be deployed automatically onto Cloud environments (Kubernetes, AWS, Docker Swarm) efficiently and securely.
88
+
89
+ ### 4.1 Mandatory Multi-Stage Builds
90
+ Every Dockerfile must consist of at least 2 stages:
91
+ - **Stage 1 (Build Stage):** Use a base image containing all necessary tools (SDKs, Compilers, devDependencies) to compile the source code and install packages.
92
+ - **Stage 2 (Production Runtime Stage):** Copy only compiled assets and production dependencies (e.g., `dist` folder, compiled binary, node production modules) from Stage 1. This final image must not contain raw source code or development utilities, minimizing bundle size.
93
+
94
+ ### 4.2 Principle of Least Privilege
95
+ - **No Root User:** Never run container processes using the default `root` user. Running containers as root introduces severe security risks in case of container escape vulnerabilities.
96
+ - **Solution:** Initialize a non-privileged user in the Dockerfile (e.g., `USER node` in Node.js, or `useradd -u 1001 appuser` in Go/Rust) and grant appropriate execution permissions to this user.
97
+
98
+ ### 4.3 Health Check API
99
+ - All backend services must expose a dedicated health check endpoint (e.g., `GET /health` or `GET /ready`).
100
+ - This endpoint must check downstream connectivity (e.g., Database, Redis) and return HTTP Status `503 Service Unavailable` if unhealthy.
101
+ - Use the `HEALTHCHECK` directive in the Dockerfile so orchestrators like Kubernetes can detect failures and automatically restart unhealthy containers (Self-healing).
@@ -1,53 +1,53 @@
1
- ## 🗺️ Hướng Dẫn Phát Triển .NET (C#)
1
+ ## 🗺️ .NET (C#) Development Guide
2
2
 
3
- Dự án này một ứng dụng .NET (C#), được tổ chức và cấu hình như sau:
4
- - **Tên Solution:** `{{solutionName}}`
5
- - **Phiên bản .NET:** `net{{dotnetVersion}}`
6
- - **Các dự án thành phần:**
3
+ This project is a .NET (C#) application configured as follows:
4
+ - **Solution Name:** `{{solutionName}}`
5
+ - **.NET Version:** `net{{dotnetVersion}}`
6
+ - **Application Projects:**
7
7
  {{#each projectNames}}
8
8
  - `{{this}}`
9
9
  {{/each}}
10
- - **Các dự án kiểm thử (Test Projects):**
10
+ - **Test Projects:**
11
11
  {{#each testProjects}}
12
12
  - `{{this}}`
13
13
  {{/each}}
14
14
 
15
15
  ---
16
16
 
17
- ### 🔄 Vòng Đời Phát Triển Tác Nhân (Agent Development Lifecycle)
18
- Tác nhân AI phải thực hiện tất cả các nhiệm vụ .NET theo quy trình 5 bước sau:
19
- 1. **Thiết kế & Lập trình:** Triển khai các lớp nghiệp vụ tuân thủ cấu trúc Clean Architecture / Onion Architecture. Đặt Core Logic trong Application/Domain layer độc lập.
20
- 2. **Kiểm thử Toàn diện:** Viết unit test cho các Service sử dụng xUnit Moq.
21
- 3. **Chất lượng nguồn:** Chạy các lệnh kiểm tra lỗi cú pháp và kiểu dữ liệu:
22
- - Chạy Build kiểm tra: `dotnet build`
23
- - Chạy Kiểm thử: `dotnet test`
24
- 4. **Quản lý Thư viện:** Thêm các gói NuGet mới qua lệnh: `dotnet add package [tên_gói]`.
17
+ ### 🔄 Agent Development Lifecycle
18
+ The AI Agent must execute all .NET tasks following this 5-step workflow:
19
+ 1. **Design & Implementation:** Implement business logic adhering to Clean Architecture / Onion Architecture principles. Maintain Core Logic in decoupled Application/Domain layers.
20
+ 2. **Comprehensive Testing:** Write unit tests for Services using xUnit and Moq.
21
+ 3. **Code Quality & Verification:** Run build and test execution commands:
22
+ - Build Check: `dotnet build`
23
+ - Test Execution: `dotnet test`
24
+ 4. **Package Management:** Add new NuGet dependencies using the command: `dotnet add package [package_name]`.
25
25
 
26
26
  ---
27
27
 
28
- ### 🏗️ Kiến Trúc Hệ Thống Bản Mẫu (Template Blueprint)
29
- Vui lòng tham khảo các tài liệu quy tắc chi tiết dưới đây:
30
- - Quy ước coding style chuẩn C#, PascalCase, camelCase tiền tố Interface: `@csharp-style.md`
31
- - Quy định đăng ký và sử dụng Dependency Injection (Transient, Scoped, Singleton): `@dependency-injection.md`
32
- - Phân định trách nhiệm API Controller điều phối luồng xử lý: `@api-structure.md`
33
- - Cấu hình FluentValidation middleware xử ngoại lệ tập trung: `@error-handling-validation.md`
34
- - Quy trình từng bước sinh mới API Controller, DTO, Request Validator: `@SKILL.md`
28
+ ### 🏗️ Template Blueprint
29
+ Refer to the detailed rules below:
30
+ - C# coding style, PascalCase, camelCase, and Interface prefixes: `@csharp-style.md`
31
+ - Dependency Injection lifetimes (Transient, Scoped, Singleton) registration: `@dependency-injection.md`
32
+ - API Controller responsibilities and execution dispatch: `@api-structure.md`
33
+ - FluentValidation setups and centralized exception handling middleware: `@error-handling-validation.md`
34
+ - Scaffolding a new API Controller, DTO, and Request Validator: `@SKILL.md`
35
35
 
36
36
  ---
37
37
 
38
- ### 🏛️ Quy Tắc Phát Triển Nghiêm Ngặt
38
+ ### 🏛️ Strict Development Rules
39
39
 
40
- #### 1. Kiến Trúc Sạch (Clean Architecture)
41
- Phân tách ràng các tầng trách nhiệm:
42
- - **Domain:** Chứa Entities, Value Objects, Domain Logic. Tuyệt đối không phụ thuộc vào bất kỳ thư viện ngoài nào.
43
- - **Application:** Chứa Interfaces, DTOs, Use Cases (Services/Queries/Commands). Chỉ phụ thuộc vào Domain layer.
44
- - **Infrastructure:** Chứa Data Access (EF Core), External Services. Phụ thuộc vào Application layer.
45
- - **Presentation (API):** Chứa Controllers, Middlewares. Điểm khởi chạy của ứng dụng.
40
+ #### 1. Clean Architecture Layers
41
+ Strictly separate concerns across application boundaries:
42
+ - **Domain:** Houses Entities, Value Objects, and core Domain Logic. Must remain free of external package references.
43
+ - **Application:** Houses Interfaces, DTOs, and Use Cases (Services/Queries/Commands). Depends only on the Domain layer.
44
+ - **Infrastructure:** Houses Data Access (EF Core DbContext) and External Integrations. Depends on the Application layer.
45
+ - **Presentation (API):** Houses Controllers, Filters, and Middlewares. The entrypoint of the execution runtime.
46
46
 
47
- #### 2. Đăng Ký Dependency Injection (DI)
48
- - Sử dụng constructor injection để tiêm các dịch vụ cần thiết qua các interface.
49
- - Tuyệt đối cấm sử dụng Service Locator pattern ( dụ: giải quyết dependencies thủ công qua `IServiceProvider` trong runtime).
47
+ #### 2. Dependency Injection (DI) Registration
48
+ - Inject all downstream services using constructor parameters via interfaces.
49
+ - Never use the Service Locator pattern (e.g., manually resolving dependencies at runtime using `IServiceProvider`).
50
50
 
51
- #### 3. Kiểm Thử Dữ Liệu Tự Động Với FluentValidation
52
- - Toàn bộ dữ liệu đầu vào của API Request phải được kiểm duyệt tự động thông qua các class Validator thừa kế từ `AbstractValidator<T>` của thư viện FluentValidation.
53
- - Không viết code validate thủ công bằng các câu lệnh `if` rải rác trong Controller.
51
+ #### 3. Validation with FluentValidation
52
+ - Validate all incoming request DTOs using validators inheriting from FluentValidation's `AbstractValidator<T>`.
53
+ - Do not write manual validation statements scattered across Controller methods.
@@ -1,25 +1,25 @@
1
- # Cấu Trúc Lớp Presentation (API Controllers)
1
+ # Presentation Layer Structure (API Controllers)
2
2
 
3
- Tài liệu này quy định cấu trúc trách nhiệm của API Controllers trong tầng Presentation của ứng dụng .NET.
3
+ This document defines the structure and responsibilities of API Controllers inside the Presentation layer of a .NET application.
4
4
 
5
5
  ---
6
6
 
7
- ## 🏛️ Trách Nhiệm Của API Controller
8
- API Controller chịu trách nhiệm:
9
- 1. Nhận yêu cầu HTTP (HTTP Requests) từ client.
10
- 2. Ánh xạ các tham số URL, Query String, hoặc Request Body vào các DTO tương ứng.
11
- 3. Chuyển giao các tham số đó sang tầng Application (Services/Queries/Commands).
12
- 4. Nhận lại kết quả phản hồi Client thông qua các mã trạng thái HTTP phù hợp (200 OK, 201 Created, 400 Bad Request, 404 Not Found, v.v.).
7
+ ## 🏛️ API Controller Responsibilities
8
+ An API Controller is responsible for:
9
+ 1. Receiving incoming HTTP requests from clients.
10
+ 2. Mapping URL parameters, query strings, or request bodies into target request DTOs.
11
+ 3. Delegating request processing to the Application layer (Services/Queries/Commands).
12
+ 4. Receiving results and responding to the client using appropriate HTTP status codes (e.g., `200 OK`, `201 Created`, `400 Bad Request`, `404 Not Found`).
13
13
 
14
14
  ---
15
15
 
16
- ## 🚦 Quy Tắc Phát Triển
17
- - **Controller mỏng (Thin Controllers):** Controllers không chứa bất kỳ logic nghiệp vụ, tính toán thuật toán, hay truy vấn DB trực tiếp. 100% logic đó phải nằm dưới Application layer.
18
- - **Không tiêm DbContext vào Controller:** DbContext phải được che giấu dưới Infrastructure / Repository layer. Tầng Presentation tuyệt đối không gọi DbContext.
19
- - **Sử dụng DTO thay Entity trực tiếp:**
20
- - Không nhận trực tiếp Domain Entities làm đầu vào của Controller.
21
- - Không trả trực tiếp Domain Entities về cho Client để tránh lộ cấu trúc DB hoặc lỗi cyclic references. Luôn ánh xạ qua các lớp DTO (Data Transfer Objects).
22
- - **Cấu hình định tuyến Route rõ ràng:** Sử dụng attribute routing để khai báo ràng phương thức HTTP và endpoint:
16
+ ## 🚦 Development Rules
17
+ - **Thin Controllers:** Controllers must not contain business logic, algorithmic calculations, or direct database queries. 100% of this logic must reside in the Application layer.
18
+ - **Do Not Inject DbContext into Controllers:** Keep `DbContext` encapsulated within the Infrastructure / Repository layers. The Presentation layer must never access `DbContext` directly.
19
+ - **Use DTOs Instead of Domain Entities:**
20
+ - Never accept raw Domain Entities as Controller input parameters.
21
+ - Never return raw Domain Entities directly to the client to prevent exposing the database schema or triggering cyclic reference errors. Always map records to DTO (Data Transfer Object) classes.
22
+ - **Explicit Route Declarations:** Use attribute routing to clearly declare HTTP methods and endpoints:
23
23
  ```csharp
24
24
  [ApiController]
25
25
  [Route("api/v1/[controller]")]
@@ -1,27 +1,27 @@
1
- # Quy Ước Viết Mã C# (C# Coding Style & Conventions)
1
+ # C# Coding Style & Conventions
2
2
 
3
- Tài liệu này đặc tả quy chuẩn coding style, đặt tên biến, tên lớp và cách tổ chức file nguồn trong dự án .NET.
3
+ This document specifies standard coding styles, naming patterns, and source file organization conventions in .NET projects.
4
4
 
5
5
  ---
6
6
 
7
- ## 🏷️ Quy Ước Đặt Tên (Naming Conventions)
7
+ ## 🏷️ Naming Conventions
8
8
 
9
- ### Quy tắc đặt tên Lớp và Thành phần
10
- - **PascalCase:** Áp dụng cho Class, Struct, Record, Enum, Interface, Method, Public Properties.
11
- - * dụ:* `UserService`, `GetActiveUsers()`, `CreatedDate`.
12
- - **Interface Prefix:** Tên Interface bắt buộc phải bắt đầu bằng chữ cái `I`.
13
- - * dụ:* `IUserService`, `IUserRepository`.
14
- - **camelCase:** Áp dụng cho tham số đầu vào của hàm (method arguments) các biến cục bộ (local variables).
15
- - * dụ:* `userId`, `requestPayload`.
16
- - **Private Fields Prefix:** Các trường dữ liệu private trong Class phải viết bằng camelCase bắt đầu bằng dấu gạch dưới `_`.
17
- - * dụ:* `private readonly IUserRepository _userRepository;`.
9
+ ### Class & Component Naming Rules
10
+ - **PascalCase:** Use for Classes, Structs, Records, Enums, Interfaces, Methods, and Public Properties.
11
+ - *Examples:* `UserService`, `GetActiveUsers()`, `CreatedDate`.
12
+ - **Interface Prefix:** Interface names must start with the uppercase letter `I`.
13
+ - *Examples:* `IUserService`, `IUserRepository`.
14
+ - **camelCase:** Use for method arguments and local variables.
15
+ - *Examples:* `userId`, `requestPayload`.
16
+ - **Private Fields Prefix:** Private fields inside classes must use `camelCase` and start with an underscore `_`.
17
+ - *Example:* `private readonly IUserRepository _userRepository;`.
18
18
 
19
19
  ---
20
20
 
21
- ## 📦 Tổ Chức Mã Nguồn & Định Dạng
22
- - **Namespaces:** Đặt namespace phản ánh cấu trúc thư mục của dự án để đảm bảo tính dễ tìm kiếm.
23
- - * dụ:* `ProjectName.Application.Services`.
24
- - **File Scoped Namespaces:** Sử dụng cú pháp namespace phạm vi file (File-scoped namespace) của C# 10+ để giảm cấp thụt lề thụt dòng không cần thiết:
21
+ ## 📦 File Structure & Formatting
22
+ - **Namespaces:** Match namespaces with the physical directory structure to ensure easy discovery.
23
+ - *Example:* `ProjectName.Application.Services`.
24
+ - **File-Scoped Namespaces:** Use C# 10+ file-scoped namespaces to reduce unnecessary indentation levels:
25
25
  ```csharp
26
26
  namespace ProjectName.Application.Services;
27
27
 
@@ -30,4 +30,4 @@ Tài liệu này đặc tả quy chuẩn coding style, đặt tên biến, tên
30
30
  // ...
31
31
  }
32
32
  ```
33
- - **Sắp xếp Usings:** Đặt các chỉ thị `using` hệ thống (`System.*`) lên trước, tiếp theo các thư viện bên thứ ba, cuối cùng các dự án nội bộ.
33
+ - **Sorting Usings:** Organize `using` directives by placing system namespaces (`System.*`) first, followed by third-party packages, and internal project dependencies last.
@@ -1,14 +1,14 @@
1
- # Đăng Ký & Sử Dụng Dependency Injection (DI)
1
+ # Dependency Injection (DI) Configurations
2
2
 
3
- Tài liệu này hướng dẫn cách cấu hình tiêm phụ thuộc trong các ứng dụng .NET Core.
3
+ This document details guidelines for configuring and consuming dependency injection in .NET Core applications.
4
4
 
5
5
  ---
6
6
 
7
- ## 💉 Constructor Injection (Tiêm qua Hàm khởi tạo)
8
- - **Quy tắc bắt buộc:** Luôn luôn giải quyết các phụ thuộc của Class thông qua Constructor. Gán chúng vào các trường private readonly tiền tố gạch dưới `_`.
9
- - Tuyệt đối không dùng Service Locator (không gọi `app.Services.GetService<T>()` hay tiêm `IServiceProvider` để lấy service động tại runtime).
7
+ ## 💉 Constructor Injection
8
+ - **Mandatory Rule:** Always resolve class dependencies using constructor parameters. Assign them to private readonly fields prefixed with an underscore `_`.
9
+ - Never use the Service Locator pattern (do not call `app.Services.GetService<T>()` or inject `IServiceProvider` to dynamically resolve services at runtime).
10
10
 
11
- * **Không hợp lệ (❌ Nghiêm cấm):**
11
+ * **Invalid (❌ Prohibited):**
12
12
  ```csharp
13
13
  public class OrderService
14
14
  {
@@ -26,7 +26,7 @@ Tài liệu này hướng dẫn cách cấu hình và tiêm phụ thuộc trong
26
26
  }
27
27
  }
28
28
  ```
29
- * **Hợp lệ (✔️ Khuyến khích):**
29
+ * **Valid (✔️ Recommended):**
30
30
  ```csharp
31
31
  public class OrderService : IOrderService
32
32
  {
@@ -47,8 +47,8 @@ Tài liệu này hướng dẫn cách cấu hình và tiêm phụ thuộc trong
47
47
 
48
48
  ---
49
49
 
50
- ## ⚙️ Đăng Ký Vòng Đời Dịch Vụ (Service Lifetimes)
51
- Lựa chọn đúng vòng đời khi đăng dịch vụ trong `Program.cs`:
52
- 1. **Transient (`AddTransient<I, T>()`):** Tạo mới mỗi khi được yêu cầu. Dành cho các dịch vụ nhẹ, không lưu trạng thái (Stateless Services).
53
- 2. **Scoped (`AddScoped<I, T>()`):** Tạo mới một lần cho mỗi HTTP Request. Thích hợp cho Repository, Database Context (`DbContext`), các dịch vụ nghiệp vụ.
54
- 3. **Singleton (`AddSingleton<I, T>()`):** Tạo một lần duy nhất cho toàn bộ vòng đời ứng dụng. Dành cho caching in-memory, cấu hình hệ thống, helper dùng chung.
50
+ ## ⚙️ Service Lifetimes Registration
51
+ Register dependencies with the appropriate lifetime scopes inside `Program.cs`:
52
+ 1. **Transient (`AddTransient<I, T>()`):** Instantiated every time they are requested. Use for lightweight, stateless services.
53
+ 2. **Scoped (`AddScoped<I, T>()`):** Instantiated once per HTTP request context. Recommended for repositories, database contexts (`DbContext`), and business services.
54
+ 3. **Singleton (`AddSingleton<I, T>()`):** Instantiated once and shared across the entire application lifetime. Use for in-memory caching, system configurations, and thread-safe helper services.
@@ -1,15 +1,15 @@
1
- # Xử Ngoại Lệ Tập Trung & Xác Thực Tự Động (FluentValidation)
1
+ # Unified Exception Handling & Automated Validation (FluentValidation)
2
2
 
3
- Tài liệu này quy định cấu hình xử ngoại lệ tập trung qua Middleware xác thực dữ liệu đầu vào bằng thư viện FluentValidation trong ứng dụng .NET.
3
+ This document defines configurations for centralized exception handling using Middleware and incoming request validation using the FluentValidation library in .NET applications.
4
4
 
5
5
  ---
6
6
 
7
- ## 🛡️ Xác Thực Dữ Liệu Tự Động Với FluentValidation
8
- - **Quy tắc:** Mọi API Request nhận dữ liệu phức tạp phải đi kèm một Validator kế thừa từ `AbstractValidator<T>` để định nghĩa các ràng buộc dữ liệu.
9
- - Cấu hình FluentValidation để tự động kiểm duyệt trả về lỗi 400 Bad Request cho Client nếu dữ liệu không khớp, tránh viết các câu lệnh `if` lặp lại.
7
+ ## 🛡️ Automated Validation with FluentValidation
8
+ - **Rule:** Every API request representing complex input data payloads must have a corresponding validator class inheriting from `AbstractValidator<T>` to declare validation rules.
9
+ - Configure FluentValidation to automatically intercept invalid requests and return an HTTP `400 Bad Request` payload to the client, preventing repetitive manual validation checks inside Controllers.
10
10
 
11
11
  ```csharp
12
- // dụ về một Validator
12
+ // Example of a Validator class
13
13
  using FluentValidation;
14
14
 
15
15
  public class CreateCourseRequestValidator : AbstractValidator<CreateCourseRequestDto>
@@ -17,32 +17,32 @@ Tài liệu này quy định cấu hình xử lý ngoại lệ tập trung qua M
17
17
  public CreateCourseRequestValidator()
18
18
  {
19
19
  RuleFor(x => x.Title)
20
- .NotEmpty().WithMessage("Tiêu đề khóa học không được để trống.")
21
- .MaximumLength(150).WithMessage("Tiêu đề không được vượt quá 150 ký tự.");
20
+ .NotEmpty().WithMessage("Course title cannot be empty.")
21
+ .MaximumLength(150).WithMessage("Title must not exceed 150 characters.");
22
22
 
23
23
  RuleFor(x => x.Price)
24
- .GreaterThanOrEqualTo(0).WithMessage("Giá khóa học không được nhỏ hơn 0.");
24
+ .GreaterThanOrEqualTo(0).WithMessage("Course price cannot be less than 0.");
25
25
  }
26
26
  }
27
27
  ```
28
28
 
29
29
  ---
30
30
 
31
- ## 🚨 Xử Lỗi Tập Trung (Global Exception Middleware)
32
- - **Quy tắc:** Tuyệt đối không để lộ các ngoại lệ thô của hệ thống (lỗi DB, stack traces) cho Client với lỗi 500.
33
- - Xây dựng một Middleware toàn cục (`ExceptionHandlingMiddleware`) hoặc sử dụng tính năng `IExceptionHandler` trong .NET 8+ để bắt toàn bộ các lỗi xảy ra trong ứng dụng và định dạng lại thành cấu trúc JSON chuẩn:
31
+ ## 🚨 Centralized Exception Handling (Global Exception Middleware)
32
+ - **Rule:** Never expose raw system exceptions (such as database faults, file system errors, or stack traces) directly to clients as HTTP 500 errors.
33
+ - Build a global middleware (`ExceptionHandlingMiddleware`) or implement `IExceptionHandler` in .NET 8+ to intercept all unhandled exceptions and format them into a standard JSON payload:
34
34
 
35
35
  ```json
36
36
  {
37
37
  "success": false,
38
38
  "statusCode": 500,
39
39
  "timestamp": "2026-06-13T07:42:00.000Z",
40
- "message": "Đã xảy ra lỗi hệ thống. Vui lòng liên hệ quản trị viên."
40
+ "message": "An internal server error occurred. Please contact the administrator."
41
41
  }
42
42
  ```
43
43
 
44
44
  ```csharp
45
- // Cấu trúc Exception Handling Middleware tiêu chuẩn
45
+ // Standard Global Exception Handling Middleware
46
46
  public class ExceptionHandlingMiddleware
47
47
  {
48
48
  private readonly RequestDelegate _next;
@@ -77,7 +77,7 @@ Tài liệu này quy định cấu hình xử lý ngoại lệ tập trung qua M
77
77
  success = false,
78
78
  statusCode = context.Response.StatusCode,
79
79
  timestamp = DateTime.UtcNow,
80
- message = "Đã xảy ra lỗi hệ thống. Vui lòng liên hệ quản trị viên."
80
+ message = "An internal server error occurred. Please contact the administrator."
81
81
  };
82
82
 
83
83
  return context.Response.WriteAsJsonAsync(response);