fix(lastleg): complete relabel document contract and regression gates

This commit is contained in:
2026-09-09 12:54:14 +08:00
parent ac3ce3703e
commit 655237e37f
19 changed files with 474 additions and 23 deletions
@@ -0,0 +1,125 @@
openapi: 3.0.3
info:
title: 海外换标 PDF 文件内部契约
version: 1.0.0
description: >-
File 只保存文件并强制客户、业务类型、业务ID与文件ID复合归属。
OVERSEAS_RELABEL_TOTAL_DOCUMENT 的 businessId 为 application.id;
OVERSEAS_RELABEL_ITEM_DOCUMENT 的 businessId 为 item.id。
Lastleg 必须先校验申请与明细存在、明细所属申请及其客户归属、业务状态和权限。
客户归属未知时失败关闭,不得使用平台归属或替代业务ID。
security:
- InternalServiceToken: []
paths:
/internal/file/v1/business-files/{tenantId}/{businessType}/{businessId}:
parameters:
- $ref: '#/components/parameters/TenantId'
- $ref: '#/components/parameters/BusinessType'
- $ref: '#/components/parameters/BusinessId'
post:
summary: 上传换标总文件或单品文件
description: 非空 PDF,Content-Type 必须为 application/pdf,内容需有 PDF 签名,最大 10MiB(10485760字节,含边界)。
parameters:
- name: X-Operator-Id
in: header
required: true
schema: {type: integer, format: int64, minimum: 1}
requestBody:
required: true
content:
multipart/form-data:
schema:
type: object
required: [file]
properties:
file: {type: string, format: binary}
encoding:
file: {contentType: application/pdf}
responses:
'200':
description: 统一响应体;业务失败按 code 判断
content:
application/json:
schema: {$ref: '#/components/schemas/MetadataEnvelope'}
'403': {description: 内部令牌无效}
/internal/file/v1/business-files/{tenantId}/{businessType}/{businessId}/{fileId}:
parameters:
- $ref: '#/components/parameters/TenantId'
- $ref: '#/components/parameters/BusinessType'
- $ref: '#/components/parameters/BusinessId'
- $ref: '#/components/parameters/FileId'
get:
summary: 校验复合归属并读取元数据
responses:
'200':
description: 仅返回全部归属字段匹配且有效的文件,未匹配按统一业务错误返回
content:
application/json:
schema: {$ref: '#/components/schemas/MetadataEnvelope'}
'403': {description: 内部令牌无效}
/internal/file/v1/business-files/{tenantId}/{businessType}/{businessId}/{fileId}/content:
parameters:
- $ref: '#/components/parameters/TenantId'
- $ref: '#/components/parameters/BusinessType'
- $ref: '#/components/parameters/BusinessId'
- $ref: '#/components/parameters/FileId'
get:
summary: 校验复合归属并下载 PDF
responses:
'200':
description: 文件内容;Content-Disposition 附件下载,Cache-Control no-store
content:
application/pdf:
schema: {type: string, format: binary}
'403': {description: 内部令牌无效}
components:
schemas:
MetadataEnvelope:
type: object
required: [code, data]
properties:
code: {type: string}
message: {type: string, nullable: true}
data: {$ref: '#/components/schemas/Metadata'}
Metadata:
type: object
required: [fileId, ownerScope, tenantId, businessType, businessId, fileName, sha256, contentType, sizeBytes]
properties:
fileId: {type: string, pattern: '^[1-9][0-9]*$'}
ownerScope: {type: string, enum: [CUSTOMER]}
tenantId: {type: string, pattern: '^[1-9][0-9]*$'}
businessType: {type: string, enum: [OVERSEAS_RELABEL_TOTAL_DOCUMENT, OVERSEAS_RELABEL_ITEM_DOCUMENT]}
businessId: {type: string, pattern: '^[1-9][0-9]*$'}
fileName: {type: string}
sha256: {type: string, pattern: '^[0-9a-f]{64}$'}
contentType: {type: string, enum: [application/pdf]}
sizeBytes: {type: integer, format: int64, minimum: 1, maximum: 10485760}
createdAt: {type: string, description: 持久化上传时间LocalDateTime,无时区偏移}
securitySchemes:
InternalServiceToken:
type: apiKey
in: header
name: X-Internal-Service-Token
parameters:
TenantId:
name: tenantId
in: path
required: true
schema: {type: integer, format: int64, minimum: 1}
BusinessType:
name: businessType
in: path
required: true
schema:
type: string
enum: [OVERSEAS_RELABEL_TOTAL_DOCUMENT, OVERSEAS_RELABEL_ITEM_DOCUMENT]
BusinessId:
name: businessId
in: path
required: true
schema: {type: string, pattern: '^[1-9][0-9]*$'}
FileId:
name: fileId
in: path
required: true
schema: {type: integer, format: int64, minimum: 1}