- Added request/response flow diagrams to api-design and api-gateway-advanced skills for better visualization of processes. - Introduced configuration loading flow in configuration-management skill to clarify the configuration process. - Included error propagation flow in error-handling-patterns skill to illustrate error handling across layers. - Enhanced various skills with additional diagrams to improve understanding of complex concepts. These updates aim to provide clearer guidance and improve the overall documentation experience for developers.
579 lines
19 KiB
Markdown
579 lines
19 KiB
Markdown
# Thiết Kế API RESTful
|
|
|
|
RESTful API design standards for GoodGo microservices. Use when creating new API endpoints, designing DTOs, implementing controllers, writing OpenAPI documentation, or standardizing API responses.
|
|
> Tiêu chuẩn thiết kế API RESTful cho các microservices của GoodGo. Sử dụng khi tạo endpoint API mới, thiết kế DTOs, triển khai controllers, viết tài liệu OpenAPI, hoặc chuẩn hóa response API.
|
|
|
|
## Tổng Quan
|
|
|
|
This skill covers the RESTful API design patterns and standards used across all GoodGo microservices. It ensures consistency, predictability, and maintainability of APIs through standardized URL structures, HTTP methods, response formats, error handling, and DTO validation.
|
|
|
|
Skill này bao gồm các pattern và tiêu chuẩn thiết kế API RESTful được sử dụng trong tất cả các microservices của GoodGo. Nó đảm bảo tính nhất quán, dự đoán được và dễ bảo trì của APIs thông qua cấu trúc URL chuẩn hóa, HTTP methods, định dạng response, xử lý lỗi và validation DTO.
|
|
|
|
## Khi Nào Sử Dụng
|
|
|
|
Use this skill when:
|
|
- Creating new API endpoints
|
|
- Designing request/response DTOs
|
|
- Implementing controllers and routes
|
|
- Writing OpenAPI/Swagger documentation
|
|
- Standardizing error responses
|
|
- Implementing pagination, filtering, and sorting
|
|
- Setting up API versioning
|
|
- Designing resource relationships
|
|
|
|
Sử dụng skill này khi:
|
|
- Tạo endpoint API mới
|
|
- Thiết kế DTOs cho request/response
|
|
- Triển khai controllers và routes
|
|
- Viết tài liệu OpenAPI/Swagger
|
|
- Chuẩn hóa error responses
|
|
- Triển khai pagination, filtering và sorting
|
|
- Thiết lập API versioning
|
|
- Thiết kế quan hệ giữa các resources
|
|
|
|
## Khái Niệm Chính
|
|
|
|
### Luồng Request/Response
|
|
|
|
Sơ đồ sau minh họa cách một request đi qua các lớp của API:
|
|
|
|
The following diagram illustrates how a request flows through the API layers:
|
|
|
|
```mermaid
|
|
sequenceDiagram
|
|
participant Client
|
|
participant Middleware
|
|
participant Controller
|
|
participant Service
|
|
participant Repository
|
|
participant Database
|
|
|
|
Client->>Middleware: HTTP Request
|
|
Middleware->>Middleware: Authentication<br/>Rate Limiting<br/>Validation
|
|
Middleware->>Controller: Validated Request
|
|
Controller->>Controller: Parse DTO<br/>Extract Params
|
|
Controller->>Service: Business Logic Call
|
|
Service->>Repository: Data Access Call
|
|
Repository->>Database: Query Execution
|
|
Database-->>Repository: Data Result
|
|
Repository-->>Service: Entity/Entities
|
|
Service-->>Controller: Business Result
|
|
Controller->>Controller: Transform to DTO<br/>Format Response
|
|
Controller-->>Middleware: Response Object
|
|
Middleware-->>Client: HTTP Response
|
|
```
|
|
|
|
### Cấu Trúc Phân Cấp API
|
|
|
|
Sơ đồ sau cho thấy cấu trúc phân cấp của các RESTful API endpoints:
|
|
|
|
The following diagram shows the hierarchical structure of RESTful API endpoints:
|
|
|
|
```mermaid
|
|
graph TD
|
|
A[API Base URL<br/>https://api.goodgo.com] --> B[Version<br/>/v1]
|
|
B --> C[Resource Collection<br/>/users]
|
|
B --> D[Resource Collection<br/>/orders]
|
|
B --> E[Resource Collection<br/>/products]
|
|
|
|
C --> F[Resource Instance<br/>/users/:id]
|
|
C --> G[Sub-Resource<br/>/users/:id/orders]
|
|
|
|
F --> H[GET /users/:id<br/>Retrieve user]
|
|
F --> I[PUT /users/:id<br/>Update user]
|
|
F --> J[DELETE /users/:id<br/>Delete user]
|
|
|
|
C --> K[GET /users<br/>List users]
|
|
C --> L[POST /users<br/>Create user]
|
|
|
|
G --> M[GET /users/:id/orders<br/>List user orders]
|
|
G --> N[POST /users/:id/orders<br/>Create order]
|
|
|
|
style A fill:#e1f5ff
|
|
style B fill:#b3e5fc
|
|
style C fill:#81d4fa
|
|
style D fill:#81d4fa
|
|
style E fill:#81d4fa
|
|
style F fill:#4fc3f7
|
|
style G fill:#4fc3f7
|
|
```
|
|
|
|
### Cấu Trúc URL
|
|
|
|
URLs follow a hierarchical resource-based structure with versioning.
|
|
|
|
URLs tuân theo cấu trúc phân cấp dựa trên resource với versioning.
|
|
|
|
```
|
|
https://api.goodgo.com/v1/{resource}/{id}/{sub-resource}
|
|
|
|
Examples:
|
|
GET /v1/users # List users / Liệt kê users
|
|
POST /v1/users # Create user / Tạo user
|
|
GET /v1/users/123 # Get user by ID / Lấy user theo ID
|
|
PUT /v1/users/123 # Update user / Cập nhật user
|
|
DELETE /v1/users/123 # Delete user / Xóa user
|
|
GET /v1/users/123/orders # Get user's orders / Lấy orders của user
|
|
POST /v1/users/123/orders # Create order for user / Tạo order cho user
|
|
```
|
|
|
|
### Phương Thức HTTP
|
|
|
|
- **GET**: Retrieve resource(s) - Safe, Idempotent / Lấy resource(s) - An toàn, Idempotent
|
|
- **POST**: Create new resource - Not idempotent / Tạo resource mới - Không idempotent
|
|
- **PUT**: Full update - Idempotent / Cập nhật toàn bộ - Idempotent
|
|
- **PATCH**: Partial update - Idempotent / Cập nhật một phần - Idempotent
|
|
- **DELETE**: Remove resource - Idempotent / Xóa resource - Idempotent
|
|
|
|
### Định Dạng Response Chuẩn
|
|
|
|
All API responses follow a consistent structure with `success`, `data`, and optional `metadata` fields.
|
|
|
|
Tất cả API responses tuân theo cấu trúc nhất quán với các trường `success`, `data`, và `metadata` tùy chọn.
|
|
|
|
## Các Pattern Thường Dùng
|
|
|
|
### Pattern Response Thành Công
|
|
|
|
```typescript
|
|
interface SuccessResponse<T> {
|
|
success: true;
|
|
data: T;
|
|
message?: string;
|
|
timestamp?: string;
|
|
pagination?: {
|
|
total: number;
|
|
skip: number;
|
|
take: number;
|
|
};
|
|
}
|
|
```
|
|
|
|
**Example from codebase / Ví dụ từ codebase**:
|
|
|
|
```typescript
|
|
// services/iam-service/src/modules/identity/user/user.controller.ts
|
|
res.json({
|
|
success: true,
|
|
data: {
|
|
users: result.users,
|
|
pagination: {
|
|
total: result.total,
|
|
skip: filters.skip,
|
|
take: filters.take,
|
|
},
|
|
},
|
|
});
|
|
```
|
|
|
|
### Pattern Response Lỗi
|
|
|
|
```typescript
|
|
interface ErrorResponse {
|
|
success: false;
|
|
error: {
|
|
code: string;
|
|
message: string;
|
|
details?: any;
|
|
field?: string;
|
|
};
|
|
timestamp?: string;
|
|
}
|
|
```
|
|
|
|
**Example from codebase / Ví dụ từ codebase**:
|
|
|
|
```typescript
|
|
// services/iam-service/src/modules/identity/user/user.controller.ts
|
|
if (error instanceof z.ZodError) {
|
|
res.status(400).json({
|
|
success: false,
|
|
error: {
|
|
code: 'VALIDATION_ERROR',
|
|
message: 'Invalid filters',
|
|
details: error.errors,
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
```
|
|
|
|
### Mã Trạng Thái HTTP
|
|
|
|
```typescript
|
|
// Mã thành công
|
|
200 OK // GET, PUT, PATCH success
|
|
201 Created // POST success with resource creation
|
|
204 No Content // DELETE success
|
|
|
|
// Lỗi client
|
|
// Dữ liệu request không hợp lệ
|
|
// Thiếu/sai xác thực
|
|
// Xác thực hợp lệ nhưng không có quyền
|
|
// Resource không tồn tại
|
|
// Xung đột resource (trùng lặp)
|
|
// Lỗi validation
|
|
|
|
// Lỗi server
|
|
// Lỗi server không mong đợi
|
|
// Lỗi dịch vụ bên ngoài
|
|
// Dịch vụ tạm thời không khả dụng
|
|
```
|
|
|
|
### DTOs với Zod Validation
|
|
|
|
DTOs use Zod for runtime validation with bilingual error messages.
|
|
|
|
DTOs sử dụng Zod cho validation runtime với thông báo lỗi song ngữ.
|
|
|
|
**Example from codebase / Ví dụ từ codebase**:
|
|
|
|
```typescript
|
|
// services/iam-service/src/modules/identity/identity.dto.ts
|
|
import { z } from 'zod';
|
|
|
|
export const CreateOrganizationDto = z.object({
|
|
name: z.string().min(1, 'Organization name is required / Tên tổ chức là bắt buộc').max(255),
|
|
domain: z.string().email().optional().or(z.string().min(1).max(255).optional()),
|
|
parentId: z.string().optional(),
|
|
settings: z.record(z.any()).optional(),
|
|
});
|
|
|
|
export type CreateOrganizationDto = z.infer<typeof CreateOrganizationDto>;
|
|
|
|
export const UserFiltersDto = z.object({
|
|
organizationId: z.string().optional(),
|
|
isActive: z.boolean().optional(),
|
|
emailVerified: z.boolean().optional(),
|
|
search: z.string().optional(),
|
|
skip: z.number().int().min(0).default(0),
|
|
take: z.number().int().min(1).max(100).default(20),
|
|
});
|
|
```
|
|
|
|
### Pattern Triển Khai Controller
|
|
|
|
**Example from codebase / Ví dụ từ codebase**:
|
|
|
|
```typescript
|
|
// services/iam-service/src/modules/identity/user/user.controller.ts
|
|
export class UserManagementController {
|
|
/**
|
|
List users
|
|
* VI: Liệt kê users
|
|
*/
|
|
async list(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const filters = UserFiltersDto.parse({
|
|
organizationId: req.query.organizationId as string,
|
|
isActive: req.query.isActive === 'true' ? true : req.query.isActive === 'false' ? false : undefined,
|
|
emailVerified: req.query.emailVerified === 'true' ? true : req.query.emailVerified === 'false' ? false : undefined,
|
|
search: req.query.search as string,
|
|
skip: parseInt(req.query.skip as string) || 0,
|
|
take: parseInt(req.query.take as string) || 20,
|
|
});
|
|
|
|
const result = await userManagementService.searchUsers(filters);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: {
|
|
users: result.users,
|
|
pagination: {
|
|
total: result.total,
|
|
skip: filters.skip,
|
|
take: filters.take,
|
|
},
|
|
},
|
|
});
|
|
} catch (error: any) {
|
|
if (error instanceof z.ZodError) {
|
|
res.status(400).json({
|
|
success: false,
|
|
error: {
|
|
code: 'VALIDATION_ERROR',
|
|
message: 'Invalid filters',
|
|
details: error.errors,
|
|
},
|
|
});
|
|
return;
|
|
}
|
|
|
|
res.status(500).json({
|
|
success: false,
|
|
error: {
|
|
code: 'LIST_USERS_FAILED',
|
|
message: error.message || 'Failed to list users',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
Get user by ID
|
|
* VI: Lấy user theo ID
|
|
*/
|
|
async get(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const { id } = req.params;
|
|
const user = await userManagementService.getUser(id);
|
|
|
|
res.json({
|
|
success: true,
|
|
data: user,
|
|
});
|
|
} catch (error: any) {
|
|
if (error instanceof NotFoundError) {
|
|
res.status(404).json(error.toApiResponse());
|
|
return;
|
|
}
|
|
|
|
res.status(500).json({
|
|
success: false,
|
|
error: {
|
|
code: 'GET_USER_FAILED',
|
|
message: error.message || 'Failed to get user',
|
|
},
|
|
});
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Luồng Xử Lý Lỗi
|
|
|
|
Sơ đồ sau minh họa luồng xử lý lỗi trong API:
|
|
|
|
The following diagram illustrates the error handling flow in the API:
|
|
|
|
```mermaid
|
|
flowchart TD
|
|
A[Request Received] --> B{Validation<br/>Middleware}
|
|
B -->|Invalid| C[ValidationError]
|
|
B -->|Valid| D[Controller]
|
|
|
|
D --> E{Business Logic}
|
|
E -->|Not Found| F[NotFoundError]
|
|
E -->|Unauthorized| G[UnauthorizedError]
|
|
E -->|Forbidden| H[ForbiddenError]
|
|
E -->|Conflict| I[ConflictError]
|
|
E -->|Success| J[Return Success Response]
|
|
|
|
E -->|Unexpected Error| K[Generic Error]
|
|
|
|
C --> L[Error Handler<br/>Middleware]
|
|
F --> L
|
|
G --> L
|
|
H --> L
|
|
I --> L
|
|
K --> L
|
|
|
|
L --> M{Error Type?}
|
|
M -->|ValidationError| N[400 Bad Request<br/>VALIDATION_ERROR]
|
|
M -->|UnauthorizedError| O[401 Unauthorized<br/>UNAUTHORIZED]
|
|
M -->|ForbiddenError| P[403 Forbidden<br/>FORBIDDEN]
|
|
M -->|NotFoundError| Q[404 Not Found<br/>NOT_FOUND]
|
|
M -->|ConflictError| R[409 Conflict<br/>CONFLICT]
|
|
M -->|Unknown Error| S{Development<br/>Mode?}
|
|
|
|
S -->|Yes| T[500 Internal Error<br/>INTERNAL_ERROR<br/>+ Stack Trace]
|
|
S -->|No| U[500 Internal Error<br/>INTERNAL_ERROR<br/>Generic Message]
|
|
|
|
N --> V[Format Error Response<br/>success: false<br/>error: code, message, details]
|
|
O --> V
|
|
P --> V
|
|
Q --> V
|
|
R --> V
|
|
T --> V
|
|
U --> V
|
|
|
|
V --> W[Log Error<br/>Server-Side]
|
|
W --> X[Send HTTP Response]
|
|
J --> X
|
|
|
|
style A fill:#e1f5ff
|
|
style J fill:#c8e6c9
|
|
style L fill:#fff9c4
|
|
style V fill:#ffccbc
|
|
style X fill:#e1f5ff
|
|
```
|
|
|
|
### Xử Lý Lỗi với Custom Error Classes
|
|
|
|
**Example from codebase / Ví dụ từ codebase**:
|
|
|
|
```typescript
|
|
// services/iam-service/src/errors/http-error.ts
|
|
export class HttpError extends Error {
|
|
public readonly statusCode: number;
|
|
public readonly errorCode: string;
|
|
public readonly isOperational: boolean;
|
|
public readonly details?: any;
|
|
|
|
constructor(
|
|
message: string,
|
|
statusCode: number = 500,
|
|
errorCode: string = 'INTERNAL_ERROR',
|
|
isOperational: boolean = true,
|
|
details?: any
|
|
) {
|
|
super(message);
|
|
this.name = this.constructor.name;
|
|
this.statusCode = statusCode;
|
|
this.errorCode = errorCode;
|
|
this.isOperational = isOperational;
|
|
this.details = details;
|
|
Error.captureStackTrace(this, this.constructor);
|
|
}
|
|
|
|
toApiResponse() {
|
|
return {
|
|
success: false,
|
|
error: {
|
|
code: this.errorCode,
|
|
message: this.message,
|
|
...(this.details && { details: this.details }),
|
|
},
|
|
timestamp: new Date().toISOString(),
|
|
};
|
|
}
|
|
}
|
|
|
|
export class NotFoundError extends HttpError {
|
|
constructor(resource: string = 'Resource / Tài nguyên', details?: any) {
|
|
super(`${resource} not found / ${resource} không tìm thấy`, 404, 'NOT_FOUND', true, details);
|
|
}
|
|
}
|
|
|
|
export class ValidationError extends HttpError {
|
|
constructor(message: string = 'Validation failed / Validation thất bại', details?: any) {
|
|
super(message, 422, 'VALIDATION_ERROR', true, details);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Thực Hành Tốt Nhất
|
|
|
|
### Đặt Tên Resource
|
|
|
|
- ✅ Use plural nouns (`/users` not `/user`) / Sử dụng danh từ số nhiều
|
|
- ✅ Use kebab-case for multi-word resources (`/user-profiles`) / Sử dụng kebab-case cho resource nhiều từ
|
|
- ✅ Keep URLs as short as possible / Giữ URLs ngắn gọn nhất có thể
|
|
- ❌ Avoid verbs in URLs (use HTTP methods instead) / Tránh động từ trong URLs (dùng HTTP methods thay thế)
|
|
|
|
### Phiên Bản Hóa
|
|
|
|
- ✅ Include version in URL (`/v1/users`) / Bao gồm version trong URL
|
|
- ✅ Maintain backward compatibility / Duy trì tương thích ngược
|
|
- ✅ Deprecate old versions gracefully with warnings / Ngừng hỗ trợ các version cũ một cách lịch sự với cảnh báo
|
|
|
|
### Bảo Mật
|
|
|
|
- ✅ Always use HTTPS / Luôn sử dụng HTTPS
|
|
- ✅ Implement rate limiting / Triển khai rate limiting
|
|
- ✅ Validate all inputs with DTOs / Validate tất cả inputs với DTOs
|
|
- ✅ Use proper authentication/authorization middleware / Sử dụng middleware xác thực/ủy quyền phù hợp
|
|
- ✅ Never expose sensitive data in responses / Không bao giờ expose dữ liệu nhạy cảm trong responses
|
|
|
|
### Hiệu Năng
|
|
|
|
- ✅ Implement pagination for lists (use `skip` and `take`) / Triển khai pagination cho danh sách
|
|
- ✅ Use field filtering when possible (`select` in Prisma) / Sử dụng field filtering khi có thể
|
|
- ✅ Cache responses appropriately / Cache responses phù hợp
|
|
- ✅ Compress responses (gzip) / Nén responses (gzip)
|
|
|
|
### Tài Liệu
|
|
|
|
- ✅ Keep OpenAPI spec up to date / Giữ OpenAPI spec cập nhật
|
|
- ✅ Include examples in documentation / Bao gồm ví dụ trong tài liệu
|
|
- ✅ Document error responses / Tài liệu hóa error responses
|
|
- ✅ Version your documentation / Phiên bản hóa tài liệu
|
|
|
|
### Xử Lý Lỗi
|
|
|
|
- ✅ Use consistent error response format / Sử dụng định dạng error response nhất quán
|
|
- ✅ Provide actionable error messages / Cung cấp thông báo lỗi có thể hành động
|
|
- ✅ Include error codes for programmatic handling / Bao gồm error codes cho xử lý lập trình
|
|
- ✅ Log errors server-side, don't expose stack traces in production / Log lỗi phía server, không expose stack traces trong production
|
|
|
|
## Ví Dụ Từ Dự Án
|
|
|
|
### Ví Dụ Controller
|
|
|
|
- **User Management**: [`services/iam-service/src/modules/identity/user/user.controller.ts`](../../../services/iam-service/src/modules/identity/user/user.controller.ts)
|
|
- **Feature Controller**: [`services/iam-service/src/modules/feature/feature.controller.ts`](../../../services/iam-service/src/modules/feature/feature.controller.ts)
|
|
- **RBAC Controller**: [`services/iam-service/src/modules/rbac/rbac.controller.ts`](../../../services/iam-service/src/modules/rbac/rbac.controller.ts)
|
|
|
|
### Ví Dụ DTO
|
|
|
|
- **Identity DTOs**: [`services/iam-service/src/modules/identity/identity.dto.ts`](../../../services/iam-service/src/modules/identity/identity.dto.ts)
|
|
- **Auth DTOs**: [`services/iam-service/src/modules/auth/auth.dto.ts`](../../../services/iam-service/src/modules/auth/auth.dto.ts)
|
|
- **RBAC DTOs**: [`services/iam-service/src/modules/rbac/rbac.dto.ts`](../../../services/iam-service/src/modules/rbac/rbac.dto.ts)
|
|
|
|
### Ví Dụ Xử Lý Lỗi
|
|
|
|
- **HTTP Error Classes**: [`services/iam-service/src/errors/http-error.ts`](../../../services/iam-service/src/errors/http-error.ts)
|
|
- **Error Middleware**: [`services/iam-service/src/middlewares/error.middleware.ts`](../../../services/iam-service/src/middlewares/error.middleware.ts)
|
|
|
|
## Tham Khảo Nhanh
|
|
|
|
### Bảng Tra Cứu Định Dạng Response
|
|
|
|
| Scenario / Tình Huống | Status Code | Response Structure / Cấu Trúc Response |
|
|
|----------------------|-------------|----------------------------------------|
|
|
| Success (GET) | 200 | `{ success: true, data: {...} }` |
|
|
| Success (POST) | 201 | `{ success: true, data: {...} }` |
|
|
| Success (DELETE) | 200 | `{ success: true, message: "..." }` |
|
|
| Validation Error / Lỗi Validation | 400/422 | `{ success: false, error: { code, message, details } }` |
|
|
| Not Found | 404 | `{ success: false, error: { code: "NOT_FOUND", message } }` |
|
|
| Unauthorized | 401 | `{ success: false, error: { code: "UNAUTHORIZED", message } }` |
|
|
| Forbidden | 403 | `{ success: false, error: { code: "FORBIDDEN", message } }` |
|
|
| Server Error / Lỗi Server | 500 | `{ success: false, error: { code: "INTERNAL_ERROR", message } }` |
|
|
|
|
### Pattern DTO Thường Dùng
|
|
|
|
```typescript
|
|
// DTO Tạo
|
|
const CreateDto = z.object({
|
|
requiredField: z.string().min(1),
|
|
optionalField: z.string().optional(),
|
|
});
|
|
|
|
// DTO Cập Nhật (tất cả fields tùy chọn)
|
|
const UpdateDto = z.object({
|
|
field1: z.string().optional(),
|
|
field2: z.number().optional(),
|
|
});
|
|
|
|
// DTO Query/Filter
|
|
const QueryDto = z.object({
|
|
page: z.number().int().min(1).default(1),
|
|
limit: z.number().int().min(1).max(100).default(20),
|
|
search: z.string().optional(),
|
|
sortBy: z.string().optional(),
|
|
order: z.enum(['asc', 'desc']).default('desc'),
|
|
});
|
|
```
|
|
|
|
## Skills Liên Quan
|
|
|
|
- **[Database Prisma](./database-prisma.md)**: For database operations and repository patterns / Cho các thao tác database và repository patterns
|
|
- **[Security](./security.md)**: For authentication, authorization, and security best practices / Cho xác thực, ủy quyền và thực hành bảo mật tốt nhất
|
|
- **[Testing Patterns](./testing-patterns.md)**: For testing API endpoints / Cho test API endpoints
|
|
- **[Documentation](./documentation.md)**: For writing API documentation / Cho viết tài liệu API
|
|
|
|
## Tài Nguyên
|
|
|
|
### Tài Liệu Bên Ngoài
|
|
|
|
- [REST API Design Best Practices](https://restfulapi.net/)
|
|
- [HTTP Status Codes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)
|
|
- [Zod Documentation](https://zod.dev/)
|
|
- [OpenAPI Specification](https://swagger.io/specification/)
|
|
|
|
### Tài Liệu Nội Bộ
|
|
|
|
- [API Reference](../api/openapi/iam-service.yaml)
|
|
- [Service Communication](../architecture/service-communication.md)
|
|
- [Project Rules](./project-rules.md)
|