Files
2026-09-22 13:46:36 +07:00

156 lines
5.6 KiB
YAML

# CTR-nn · contracts/openapi/<module>.yaml — OpenAPI 3.1
# Nguồn: ICD_<P> §3 (IF-nnn) · API_<US> của BA · SRS §4.1 (mã lỗi) · SEC §3 (quyền)
# Quy ước: ICD §1 — số lớn là string, thời gian date-time UTC, lỗi nghiệp vụ 4xx, phân trang theo ADR-nnn
openapi: 3.1.0
info:
title: <Module> API
version: 1.0.0
description: |
Contract cho IF-nnn. Tài liệu này THẮNG bảng mô tả trong ICD/API khi lệch.
Mã lỗi theo SRS §4.1; quyền theo SEC §3.
servers:
- url: https://api.<domain>/v1
description: production
- url: https://api-stg.<domain>/v1
description: staging
tags:
- name: <resource>
security:
- bearerAuth: []
paths:
/<resource>:
get:
operationId: <module>.list<Resource>
summary: <Mục đích một câu — khớp ICD §3.x>
tags: [<resource>]
x-if: IF-nnn
x-roles: [ROLE-01, ROLE-02]
x-error-codes: [E-<DOMAIN>-0401, E-<DOMAIN>-0403, E-<DOMAIN>-0503]
parameters:
- $ref: '#/components/parameters/PageCursor'
- $ref: '#/components/parameters/PageSize'
responses:
'200':
description: Danh sách
content:
application/json:
schema:
$ref: '#/components/schemas/<Resource>Page'
examples:
ok:
value: { items: [], nextCursor: null, hasNext: false }
'401': { $ref: '#/components/responses/Unauthorized' }
'403': { $ref: '#/components/responses/Forbidden' }
'503': { $ref: '#/components/responses/Unavailable' }
post:
operationId: <module>.create<Resource>
summary: <Mục đích>
tags: [<resource>]
x-if: IF-nnn
x-roles: [ROLE-01]
x-idempotency: header Idempotency-Key, giữ 24h (ADR-nnn)
x-error-codes: [E-<DOMAIN>-0400, E-<DOMAIN>-0409, E-<DOMAIN>-0503]
parameters:
- $ref: '#/components/parameters/IdempotencyKey'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/<Resource>Create'
examples:
ok:
value: { name: "Cửa hàng 01" }
responses:
'201':
description: Đã tạo
content:
application/json:
schema: { $ref: '#/components/schemas/<Resource>' }
'200':
description: Trùng Idempotency-Key — trả bản ghi cũ, không tạo mới
content:
application/json:
schema: { $ref: '#/components/schemas/<Resource>' }
'400': { $ref: '#/components/responses/BadRequest' }
'409': { $ref: '#/components/responses/Conflict' }
'503': { $ref: '#/components/responses/Unavailable' }
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
bearerFormat: JWT
parameters:
IdempotencyKey:
name: Idempotency-Key
in: header
required: true
schema: { type: string, maxLength: 64 }
PageCursor:
name: cursor
in: query
schema: { type: string }
PageSize:
name: size
in: query
schema: { type: integer, minimum: 1, maximum: 100, default: 20 }
schemas:
Id:
type: string
description: Số lớn truyền dạng string (ICD §1 điểm 1)
pattern: '^[0-9a-f-]{36}$'
Money:
type: object
required: [amount, currency]
properties:
amount: { type: string, pattern: '^-?[0-9]+(\.[0-9]{1,2})?$', description: 'decimal dạng string' }
currency: { type: string, minLength: 3, maxLength: 3, example: VND }
Error:
type: object
required: [code, message]
properties:
code: { type: string, pattern: '^E-[A-Z]+-[0-9]{4}$', description: 'Mã lỗi SRS §4.1' }
message: { type: string, description: 'Text hiển thị theo SRS §4.2 hoặc mã để client dịch (ICD §1 điểm 6)' }
details:
type: array
items:
type: object
properties:
field: { type: string }
code: { type: string }
<Resource>:
type: object
required: [id, createdAt]
properties:
id: { $ref: '#/components/schemas/Id' }
createdAt: { type: string, format: date-time, description: 'UTC ISO-8601' }
<Resource>Create:
type: object
required: [name]
properties:
name: { type: string, minLength: 1, maxLength: 40, description: '40 code point — khớp FLD-<SCR>-nn' }
<Resource>Page:
type: object
required: [items, hasNext]
properties:
items: { type: array, items: { $ref: '#/components/schemas/<Resource>' } }
nextCursor: { type: [string, 'null'] }
hasNext: { type: boolean }
responses:
BadRequest:
description: Sai dữ liệu vào
content: { application/json: { schema: { $ref: '#/components/schemas/Error' }, example: { code: E-<DOMAIN>-0400, message: "…" } } }
Unauthorized:
description: Hết phiên
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
Forbidden:
description: Không đủ quyền — client không xoá dữ liệu đã nhập (ICD §6)
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
Conflict:
description: Vi phạm ràng buộc nghiệp vụ (BR-nnn)
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }
Unavailable:
description: Phụ thuộc hỏng/timeout (FAIL FM-nn) — client cho thử lại, giữ dữ liệu đã nhập
content: { application/json: { schema: { $ref: '#/components/schemas/Error' } } }