📄 Token Service – Interface Contract¶
Token Service cung cấp các API trung tâm để phát hành, làm mới, thu hồi và xác minh token (access/refresh/JWT) theo chuẩn của hệ thống DX-VAS.
📌 Tổng quan API¶
| Method | Endpoint | Mô tả | Bảo mật | Ghi chú |
|---|---|---|---|---|
| POST | /v1/token |
Cấp token mới dựa trên thông tin người dùng | 🔒 Auth | Được gọi bởi auth-service/sub |
| POST | /v1/token/refresh |
Làm mới token bằng refresh token | 🔒 | Gọi trực tiếp từ client |
| POST | /v1/token/revoke |
Thu hồi 1 token cụ thể hoặc theo sub |
🔒 | Sử dụng Redis để blacklist jti |
| POST | /v1/token/introspect |
Kiểm tra tính hợp lệ của token | 🔒 Internal | Sử dụng bởi api-gateway |
| GET | /.well-known/jwks.json |
Trả về public keys để xác thực chữ ký JWT | 🔓 Public | Dùng cho các service verify token |
Quy ước path versioning
Mọi endpoint của Token Service tuân định dạng/v{major}/…– ví dụ
/v1/token,/v1/token/refresh. Quy tắc này lấy từ ADR-009 (API Governance)
và ADR-013 (Path Naming Convention) để đảm bảo khả năng thay đổi phiên bản mà
không phá vỡ client.
✅ 1. POST /v1/token/issue¶
🎯 Mục đích¶
Phát hành cặp token (access_token, refresh_token) mới cho user đã được xác thực trước đó. API này được gọi nội bộ bởi auth-service (Master hoặc Sub) sau khi xác thực danh tính người dùng thành công.
🔐 Headers yêu cầu¶
| Tên Header | Bắt buộc | Mô tả |
|---|---|---|
X-Request-ID |
✅ | ID truy vết request, sẽ được trả về trong meta.trace_id. |
X-Tenant-ID |
✅ | Định danh tenant đang thực hiện yêu cầu. |
Content-Type |
✅ | application/json |
Authorization |
✅ | Token xác thực của service gọi đến (ví dụ: service account token của Auth Service), chứng minh quyền được gọi token.issue. |
📥 Request Body¶
{
"sub": "user-123",
"roles": ["teacher"],
"permissions": ["report.view_login_by_tenant"],
"session_id": "sess-abc-123",
"login_method": "otp",
"session_metadata": {
"ip": "113.23.45.12",
"device_type": "android",
"user_agent": "Mozilla/5.0"
}
}
| Trường | Bắt buộc | Kiểu DL | Mô tả |
|---|---|---|---|
sub |
✅ | string | Global User ID của người dùng cần cấp token. |
roles |
✅ | array | Danh sách các role_code của người dùng trong tenant hiện tại. |
permissions |
✅ | array | Danh sách các permission_code người dùng có. |
session_id |
✅ | string | ID của phiên đăng nhập, lấy từ bảng auth_sessions. |
login_method |
✅ | string | google / otp / local |
session_metadata |
❌ | object | IP, thiết bị, trình duyệt (ghi log) |
📤 Response¶
{
"data": {
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600
},
"meta": {
"trace_id": "req-uuid",
"timestamp": "2025-06-07T14:35:00Z"
}
}
📤 Response Headers¶
| Header | Mô tả |
|---|---|
X-Request-ID |
Echo lại ID request |
X-Tenant-ID |
Echo lại tenant |
🧪 Response Example (200)¶
HTTP/1.1 200 OK
X-Request-ID: abc123
X-Tenant-ID: vas-001
Content-Type: application/json
{
"data": {
"access_token": "eyJhbGciOi...",
"refresh_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 3600
},
"meta": {
"trace_id": "abc123",
"timestamp": "2025-06-07T14:35:00Z"
}
}
❌ Error Responses¶
| HTTP | code | message |
|---|---|---|
| 400 | common.validation_error |
Token yêu cầu không hợp lệ |
| 401 | auth.unauthorized |
Không có quyền phát hành token |
| 403 | auth.tenant.mismatch |
Tenant không khớp với user |
| 422 | common.validation_error |
JSON hợp lệ nhưng không thoả điều kiện nghiệp vụ |
| 429 | common.rate_limited |
Vượt ngưỡng RPS/burst (theo ADR-022) |
| 500 | common.internal_error |
Lỗi hệ thống nội bộ |
❗ Note: Tất cả lỗi đều trả về dưới dạng
ErrorEnvelopetheo ADR-011
✅ 2. POST /v1/token/refresh¶
🎯 Mục đích¶
Phát hành cặp token mới dựa trên refresh_token hợp lệ. API này cho phép client duy trì đăng nhập mà không cần nhập lại mật khẩu. Được gọi trực tiếp từ client (mobile/web app) hoặc từ auth-service/sub.
🔐 Headers yêu cầu¶
| Tên Header | Bắt buộc | Mô tả |
|---|---|---|
X-Request-ID |
✅ | ID truy vết request |
X-Tenant-ID |
✅ | Tenant hiện hành |
Content-Type |
✅ | application/json |
Authorization |
✅ | Bearer <refresh_token> – được cấp từ lần đăng nhập trước |
📥 Request Body¶
| Trường | Bắt buộc | Kiểu DL | Mô tả |
|---|---|---|---|
session_id |
✅ | string | ID phiên cần làm mới token |
📤 Response¶
{
"data": {
"access_token": "eyJhbGciOi...",
"refresh_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 3600
},
"meta": {
"trace_id": "abc123",
"timestamp": "2025-06-07T15:00:00Z"
}
}
📤 Response Headers¶
| Header | Mô tả |
|---|---|
X-Request-ID |
Echo lại ID request |
X-Tenant-ID |
Echo lại tenant |
🧪 Response Example (200)¶
HTTP/1.1 200 OK
X-Request-ID: abc123
X-Tenant-ID: vas-001
Content-Type: application/json
{
"data": {
"access_token": "eyJhbGciOi...",
"refresh_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 3600
},
"meta": {
"trace_id": "abc123",
"timestamp": "2025-06-07T15:00:00Z"
}
}
❌ Error Responses¶
| HTTP | code | message |
|---|---|---|
| 400 | auth.refresh.invalid |
Token refresh không hợp lệ hoặc đã hết hạn |
| 401 | auth.unauthorized |
Không có quyền làm mới token |
| 403 | auth.session.revoked |
Phiên đã bị thu hồi hoặc bị chặn |
| 404 | auth.session.not_found |
Không tìm thấy phiên tương ứng |
| 422 | common.validation_error |
JSON hợp lệ nhưng không thoả điều kiện nghiệp vụ |
| 429 | common.rate_limited |
Vượt ngưỡng RPS/burst (theo ADR-022) |
| 500 | common.internal_error |
Lỗi hệ thống |
❗ Ghi chú: Đáp ứng chuẩn ADR-011 - Error Format
✅ 3. POST /v1/token/revoke¶
🎯 Mục đích¶
Thu hồi một phiên đăng nhập (session) cụ thể, chấm dứt hiệu lực của cả access token và refresh token tương ứng.
API này được sử dụng khi người dùng chủ động đăng xuất khỏi một thiết bị cụ thể hoặc toàn bộ hệ thống.
🔐 Headers yêu cầu¶
| Tên Header | Bắt buộc | Mô tả |
|---|---|---|
X-Request-ID |
✅ | ID truy vết request |
X-Tenant-ID |
✅ | Tenant hiện hành |
Content-Type |
✅ | application/json |
Authorization |
✅ | Access Token hợp lệ để xác định sub thực hiện yêu cầu |
📥 Request Body¶
| Trường | Bắt buộc | Kiểu DL | Mô tả |
|---|---|---|---|
session_id |
✅ | string | ID của phiên cần thu hồi |
📤 Response (204 No Content)¶
✅ Không có response body nếu thành công. Phản hồi 204 thể hiện rằng session đã được thu hồi (hoặc không tồn tại nhưng xử lý idempotent).
❌ Error Responses¶
| HTTP | code | message |
|---|---|---|
| 400 | auth.revoke.invalid |
Dữ liệu yêu cầu không hợp lệ |
| 401 | auth.unauthorized |
Không có quyền thu hồi phiên |
| 403 | auth.session.forbidden |
Session không thuộc về user hiện tại |
| 404 | auth.session.not_found |
Không tìm thấy session được yêu cầu |
| 422 | common.validation_error |
JSON hợp lệ nhưng không thoả điều kiện nghiệp vụ |
| 429 | common.rate_limited |
Vượt ngưỡng RPS/burst (theo ADR-022) |
| 500 | common.internal_error |
Lỗi hệ thống nội bộ |
❗ Note: Mọi lỗi đều sử dụng chuẩn
ErrorEnvelopetừ ADR-011
✅ 4. POST /v1/token/introspect¶
🎯 Mục đích¶
Kiểm tra tính hợp lệ của một access token hoặc refresh token. Trả về metadata nếu hợp lệ, hoặc trạng thái active: false nếu không hợp lệ.
API được dùng chủ yếu bởi các hệ thống backend như API Gateway hoặc các service phụ trợ muốn xác minh thông tin token (khi không dùng JWKS trực tiếp).
🔐 Headers yêu cầu¶
| Tên Header | Bắt buộc | Mô tả |
|---|---|---|
X-Request-ID |
✅ | ID truy vết request |
X-Tenant-ID |
✅ | Tenant hiện hành |
Content-Type |
✅ | application/json |
Authorization |
✅ | Access token có quyền introspect token (thường là hệ thống nội bộ) |
📥 Request Body¶
| Trường | Bắt buộc | Kiểu DL | Mô tả |
|---|---|---|---|
token |
✅ | string | JWT token cần kiểm tra |
📤 Response (200 OK)¶
Trường active cho biết token có hợp lệ không. Nếu active: false, các trường còn lại có thể rỗng hoặc không tồn tại.
{
"active": true,
"sub": "user-123",
"aud": "dx-vas",
"exp": 1711111111,
"iat": 1711100000,
"scope": "read write",
"token_type": "access",
"session_id": "session-abc-uuid",
"client_id": "frontend-app",
"login_method": "otp",
"meta": {
"device_type": "web",
"ip_address": "192.168.1.10",
"user_agent": "Mozilla/5.0"
}
}
| Trường | Mô tả |
|---|---|
active |
Token hợp lệ (true) hay không (false) |
sub |
ID người dùng |
exp, iat |
Thời điểm hết hạn / phát hành |
token_type |
access / refresh |
session_id |
Gắn với bảng auth_sessions |
meta |
Dữ liệu bổ sung (IP, thiết bị, agent...) |
login_method |
Phương thức đăng nhập ban đầu của session (otp, google, local) |
❌ Error Responses¶
| HTTP | code | message |
|---|---|---|
| 400 | auth.introspect.invalid |
Token đầu vào không hợp lệ |
| 401 | auth.unauthorized |
Không có quyền introspect token |
| 422 | common.validation_error |
JSON hợp lệ nhưng không thoả điều kiện nghiệp vụ |
| 429 | common.rate_limited |
Vượt ngưỡng RPS/burst (theo ADR-022) |
| 500 | common.internal_error |
Lỗi hệ thống |
❗ API trả về
200 OKvớiactive: falsenếu token không hợp lệ – không trả về401để đảm bảo không tiết lộ thông tin cho attacker.
✅ 5. GET /.well-known/jwks.json¶
🎯 Mục đích¶
Cung cấp danh sách public key hiện hành dùng để xác minh chữ ký JWT do token-service phát hành.
Endpoint này phục vụ cho việc verify token phía client, API Gateway, hoặc các service khác thông qua kid trong header của JWT.
🔓 Authorization¶
- ❌ Không yêu cầu xác thực
- ✅ Public endpoint, có thể được truy cập bởi bất kỳ hệ thống nào cần verify chữ ký
📤 Response (200 OK)¶
{
"keys": [
{
"kty": "RSA",
"kid": "2024-rotation-1",
"use": "sig",
"alg": "RS256",
"n": "uA6kkl5e8fKNS3k0_4ZFnN...",
"e": "AQAB"
},
{
"kty": "RSA",
"kid": "2023-fallback",
"use": "sig",
"alg": "RS256",
"n": "zN9uhNfUJ73hdJs0_qlmv...",
"e": "AQAB"
}
]
}
| Trường | Mô tả |
|---|---|
kid |
Key ID – dùng để khớp với kid trong JWT header |
alg |
Thuật toán chữ ký – thường là RS256 |
kty |
Loại key, ví dụ RSA |
use |
Mục đích – ở đây là "sig" để ký token |
n, e |
Thành phần của public key (modulus và exponent) |
♻️ Rotation và cache¶
- Các public key sẽ được xoay vòng định kỳ theo chính sách từ 03-cr-token-service.md
- Thời gian cache:
max-age=3600(1h) khuyến nghị để tránh gọi lại liên tục
✅ Ứng dụng¶
- Các service hoặc gateway chỉ cần lấy public key từ endpoint này và lưu vào cache.
- Sử dụng thư viện xác thực JWT (như
jsonwebtoken,pyjwt,jose) để verify chữ ký dựa trênkid.
🔐 Ghi chú về /jwks.json và Caching Strategy¶
-
Endpoint
/.well-known/jwks.jsonlà public, không yêu cầu xác thực, và được các service khác sử dụng để verify chữ ký JWT. -
Để tăng hiệu suất và giảm tải cho
token-service, trong môi trường Production, endpoint này nên được cache bởi Public API Gateway hoặc CDN (như Cloudflare, Cloud CDN).
🔄 Gợi ý cấu hình caching:¶
| Header | Giá trị đề xuất | Mô tả |
|---|---|---|
Cache-Control |
public, max-age=3600 |
Cho phép cache trong 1 giờ |
ETag |
"<fingerprint>" |
Cho phép client check bằng If-None-Match |
Last-Modified |
ISO timestamp |
Hỗ trợ cache theo thời gian cập nhật |
🔐 JWKS chỉ nên thay đổi khi rotate public keys. Khi đó cần
purge cachehoặc invalidate.
📌 Nếu triển khai trên GCP API Gateway, bạn có thể dùng cấu hình x-google-backend.cacheControl hoặc gắn cache layer riêng tại Cloud CDN.
paths:
/.well-known/jwks.json:
get:
summary: JWKS public keys
responses:
'200':
headers:
Cache-Control:
schema:
type: string
example: public, max-age=3600
📎 ENUM sử dụng¶
Trong quá trình thiết kế API của token-service, một số enum đã được chuẩn hóa để đảm bảo tính rõ ràng, mở rộng và hỗ trợ tốt cho UI/UX, kiểm thử và i18n. Dưới đây là danh sách các enum đang được sử dụng.
1. token_type¶
| Giá trị | Mô tả |
|---|---|
access |
Token truy cập, có thời hạn ngắn (~15 phút) |
refresh |
Token làm mới, dùng để lấy access token mới |
🔐 Enum này được dùng trong response của
/v1/token/introspectđể phân biệt loại token đang được kiểm tra.
2. grant_type¶
| Giá trị | Mô tả |
|---|---|
password |
Đăng nhập qua email/password truyền thống |
refresh_token |
Làm mới token thông qua refresh token |
jwt_bearer |
Grant flow nội bộ sử dụng JWT đã được xác thực trước đó |
🔄 Enum này giúp mở rộng cho các luồng xác thực OAuth2 trong tương lai.
3. device_type¶
| Giá trị | Mô tả |
|---|---|
web |
Trình duyệt web thông thường |
android |
Thiết bị Android |
ios |
Thiết bị iOS |
📱 Được dùng trong metadata của
auth_sessionsvà introspection response để phục vụ thống kê, cảnh báo bảo mật, và phân tích hành vi người dùng.
4. session_status (dự phòng cho mở rộng tương lai)¶
| Giá trị | Mô tả |
|---|---|
active |
Phiên đang hoạt động và có thể sử dụng |
revoked |
Phiên đã bị thu hồi bởi người dùng hoặc hệ thống |
expired |
Phiên đã hết hạn theo thời gian cấu hình |
⏳ Enum này sẽ hữu ích nếu hệ thống mở rộng logic quản lý session nâng cao.
5. login_method¶
| Giá trị | Mô tả |
|---|---|
google |
Đăng nhập bằng Google OAuth2 |
otp |
Đăng nhập bằng mã OTP |
local |
Đăng nhập bằng tài khoản nội bộ |
🔐 Dùng để xác định phương thức xác thực đã được sử dụng khi phát hành token/session.
📎 Permission Mapping¶
Mặc dù token-service không trực tiếp quản lý người dùng hoặc phân quyền truy cập tài nguyên, nhưng vẫn cần định nghĩa rõ các quyền (permissions) áp dụng cho các hệ thống gọi đến các endpoint đặc thù như introspect hoặc revoke. Điều này đảm bảo kiểm soát truy cập, tuân thủ nguyên tắc Principle of Least Privilege (ADR-004, ADR-006, ADR-007).
> Note: Event names follow ADR-030 (*.v1)¶
🔒 Các permission áp dụng cho token-service¶
| Permission Key | Mô tả | Endpoint yêu cầu |
|---|---|---|
token.generate |
Cho phép tạo access token / refresh token (nội bộ) | POST /v1/token |
token.refresh |
Cho phép làm mới access token thông qua refresh token | POST /v1/token/refresh |
token.revoke |
Cho phép thu hồi (revoke) một session token cụ thể | POST /v1/token/revoke |
token.introspect |
Cho phép kiểm tra thông tin và trạng thái của token | POST /v1/token/introspect |
token.jwks.read |
Quyền public, không cần auth – dùng cho GET /.well-known/jwks.json |
❌ (public) |
📌 Trong hầu hết các trường hợp,
token-servicehoạt động như service nội bộ nên các quyền này được kiểm tra bằng service-to-service authentication (JWT có embedded scope/permission claim).
🧩 Ví dụ cấu trúc claim permissions trong access token:¶
{
"sub": "user-abc-123",
"scope": "read write",
"permissions": [
"user.read",
"token.introspect",
"token.revoke"
],
"aud": "dx-vas",
"exp": 1712345678
}
✅ Áp dụng trong OpenAPI¶
Mỗi operation trong openapi.yaml nên khai báo custom field:
Hoặc nếu operation không cần quyền cụ thể (ví dụ: /.well-known/jwks.json) thì không cần khai báo permission.
🛡️ Error Codes & Envelope¶
Tất cả lỗi được trả về dưới dạng chuẩn ErrorEnvelope (ADR-011), đảm bảo nhất quán trong toàn hệ thống.
{
"error": {
"code": "token.expired",
"message": "Token has expired"
},
"meta": {
"trace_id": "a1b2c3",
"timestamp": "2025-06-07T10:30:00Z"
}
}
🔒 Bảng mã lỗi chi tiết¶
Mã lỗi (error.code) |
Mô tả | HTTP Status | Áp dụng cho endpoint |
|---|---|---|---|
token.invalid |
Access token không hợp lệ | 401 | /v1/token/introspect |
token.expired |
Token đã hết hạn | 401 | /v1/token/refresh, introspect |
token.revoked |
Token đã bị thu hồi | 401 | /v1/token/refresh, introspect |
token.unknown_jti |
Token không nằm trong danh sách thu hồi | 400 | /v1/token/revoke |
session.not_found |
Không tìm thấy phiên đăng nhập | 404 | /v1/token/revoke |
session.inactive |
Phiên đăng nhập đã bị hủy | 403 | /v1/token/refresh, /v1/token/revoke |
jwks.not_found |
Không tìm thấy khoá công khai JWKS | 500 | /.well-known/jwks.json |
common.validation_error |
Dữ liệu gửi lên không hợp lệ | 400 | Mọi endpoint POST |
common.missing_param |
Thiếu tham số bắt buộc (grant_type, refresh_token) |
400 | /v1/token, /v1/token/refresh |
common.unauthorized |
Thiếu token hoặc token không hợp lệ | 401 | Tất cả endpoint bảo vệ |
common.forbidden |
Không đủ quyền thực hiện hành động | 403 | Theo x-required-permission |
common.validation_error |
JSON hợp lệ nhưng không thoả điều kiện nghiệp vụ | 422 | Mọi endpoint |
common.rate_limited |
Vượt ngưỡng RPS/burst (theo ADR-022) | 429 | Mọi endpoint |
common.internal_error |
Lỗi không xác định từ phía server | 500 | Mọi endpoint |
Response Headers – Rate Limiting (ADR-022)¶
| Header | Description | Example |
|---|---|---|
RateLimit-Limit |
Giới hạn tối đa request trong 1 cửa sổ (per tenant / client). | 120 |
RateLimit-Remaining |
Số request còn lại trong cửa sổ hiện tại. Chỉ xuất hiện khi còn > 0. | 17 |
Retry-After |
Thời gian (giây) cần chờ trước khi gửi lại request, kèm theo HTTP 429. | 42 |
> Header RateLimit-Remaining và Retry-After được trả về khi gần hết hoặc đã vượt quá ngưỡng, tuân theo khuyến nghị ADR-022 SLA/SLO Monitoring.¶
📌 Mọi lỗi đều trả về kèm X-Request-ID trong response headers và được ghi log (audit + cloud logging).
📝 Ví dụ Curl¶
Dưới đây là các ví dụ curl minh họa cách sử dụng các API chính của token-service. Các ví dụ này dùng để kiểm thử nhanh, tích hợp CI pipeline, hoặc hướng dẫn frontend/backend team tích hợp.
🔑 1. Đăng nhập để lấy token mới¶
curl -X POST https://api.truongvietanh.edu.vn/v1/token \
-H "Content-Type: application/json" \
-H "X-Request-ID: req-001" \
-H "X-Tenant-ID: vas-primary" \
-H "Authorization: Bearer <service-token>" \
-d '{
"sub": "user-123",
"roles": ["teacher"],
"permissions": ["report.view_login_by_tenant"],
"session_id": "sess-abc-123",
"login_method": "otp",
"session_metadata": {
"ip": "113.23.45.12",
"device_type": "android"
}
}'
📌 Trả về access_token + refresh_token nếu hợp lệ.
♻️ 2. Làm mới token¶
curl -X POST https://api.truongvietanh.edu.vn/v1/token/refresh \
-H "Content-Type: application/json" \
-H "X-Request-ID: req-002" \
-H "X-Tenant-ID: vas-truongvietanh" \
-d '{
"refresh_token": "eyJhbGciOiJIUzI1NiIsIn..."
}'
📌 Trả về cặp token mới nếu refresh token hợp lệ.
🛑 3. Thu hồi token (logout toàn bộ thiết bị)¶
curl -X POST https://api.truongvietanh.edu.vn/v1/token/revoke \
-H "Authorization: Bearer <access_token>" \
-H "X-Request-ID: req-003" \
-H "X-Tenant-ID: vas-truongvietanh" \
-d '{}'
📌 Thu hồi session hiện tại (access + refresh token).
🧐 4. Kiểm tra token (introspect)¶
curl -X POST https://api.truongvietanh.edu.vn/v1/token/introspect \
-H "Authorization: Bearer <access_token>" \
-H "X-Request-ID: req-004" \
-H "X-Tenant-ID: vas-truongvietanh" \
-d '{
"token": "eyJhbGciOiJIUzI1NiIsIn..."
}'
📌 Trả về thông tin token, trạng thái (active/revoked/expired), claims.
🔐 5. Lấy JWKS key¶
📌 Trả về public key JWKS để hệ thống khác verify chữ ký JWT.
🧪 Ghi chú¶
X-Request-IDlà bắt buộc để trace log.X-Tenant-IDgiúp multi-tenant isolation (bắt buộc).- Bạn có thể test JWT validity với jwt.io.
- Token mẫu để test có thể lấy từ Auth Web hoặc Dev Tool gắn với
auth-service.
📚 Tài liệu liên quan¶
🔖 Các Quyết định Kiến trúc (ADR)¶
- ADR-003 Secrets Management: Quy trình lưu trữ & xoay khóa bí mật an toàn.
- ADR-004 Security Policy: Chính sách bảo mật tổng thể.
- ADR-005 Environment Configuration Strategy: Chuẩn tách cấu hình –
SERVICE__SECTION__KEY. - ADR-006 Auth Strategy: Chiến lược xác thực người dùng và cấp phát token.
- ADR-009 API Governance: Quy tắc versioning, naming và style REST.
- ADR-011 API Error Format: Quy ước mã lỗi & thông điệp lỗi (
namespace.snake_case). - ADR-012 Response Structure: Chuẩn hóa cấu trúc JSON response cho API.
- ADR-018 Release Approval Policy: Quy trình phê duyệt phát hành.
- ADR-022 SLA & SLO Monitoring: Khung giám sát & định nghĩa SLO.
- ADR-023 Schema Migration Strategy: 3-phase migration (Prepare → Transition → Cleanup).
- ADR-024 Data Anonymization & Retention: Ẩn danh PII và TTL dữ liệu.
- ADR-026 Hard-Delete Policy: Quy trình xoá vĩnh viễn & purge log.
- ADR-030 Event Schema Governance: Đặt tên & version sự kiện
*.v{n}.