diff --git a/Fabric.Backend.Center/src/common/version.ts b/Fabric.Backend.Center/src/common/version.ts new file mode 100644 index 0000000..c8fa5ee --- /dev/null +++ b/Fabric.Backend.Center/src/common/version.ts @@ -0,0 +1,7 @@ +export const FABRIC_PROTOCOL_VERSION = '1'; + +export function normalizeVersion(input?: string): string { + if (!input) return FABRIC_PROTOCOL_VERSION; + const v = input.trim(); + return v; +} diff --git a/Fabric.Backend.Center/src/nodes/nodes.controller.ts b/Fabric.Backend.Center/src/nodes/nodes.controller.ts index 867f8ed..b150778 100644 --- a/Fabric.Backend.Center/src/nodes/nodes.controller.ts +++ b/Fabric.Backend.Center/src/nodes/nodes.controller.ts @@ -6,6 +6,7 @@ import { ForbiddenException, Get, Headers, + HttpException, NotFoundException, Param, ParseIntPipe, @@ -25,6 +26,7 @@ import { signCanonical, verifyRequestTime, } from '../common/hmac'; +import { FABRIC_PROTOCOL_VERSION, normalizeVersion } from '../common/version'; @Controller('nodes') export class NodesController { @@ -40,7 +42,23 @@ export class NodesController { @Headers('x-fabric-signature') signature?: string, @Headers('x-fabric-timestamp') timestamp?: string, @Headers('x-fabric-nonce') nonce?: string, + @Headers('x-fabric-version') fabricVersion?: string, ) { + const requestedVersion = normalizeVersion(fabricVersion); + if (requestedVersion !== FABRIC_PROTOCOL_VERSION) { + throw new HttpException( + { + error: { + code: 'FABRIC_VERSION_NOT_SUPPORTED', + message: `unsupported protocol version: ${requestedVersion}`, + retryable: false, + }, + supportedVersion: FABRIC_PROTOCOL_VERSION, + }, + 400, + ); + } + const secret = process.env.CENTER_SHARED_SECRET as string; if (!signature || !timestamp || !nonce || !verifyRequestTime(timestamp)) { throw new ForbiddenException('invalid hmac headers'); @@ -88,6 +106,7 @@ export class NodesController { return { status: 'accepted', + negotiatedVersion: FABRIC_PROTOCOL_VERSION, node: { id: saved.id, nodeId: saved.nodeId, diff --git a/docs/TODO-backend-center-guild.md b/docs/TODO-backend-center-guild.md index b33d788..dda3af3 100644 --- a/docs/TODO-backend-center-guild.md +++ b/docs/TODO-backend-center-guild.md @@ -66,7 +66,7 @@ - [x] 鉴权方案定稿(node token / HMAC) - [x] 注册握手协议文档化 - [x] 错误码与重试策略统一 -- [ ] 版本协商(`X-Fabric-Version`) +- [x] 版本协商(`X-Fabric-Version`) --- diff --git a/docs/center-guild-handshake-v1.md b/docs/center-guild-handshake-v1.md index 6427618..04bae41 100644 --- a/docs/center-guild-handshake-v1.md +++ b/docs/center-guild-handshake-v1.md @@ -21,6 +21,7 @@ ``` ### Required Headers +- `X-Fabric-Version`: 协议版本,当前固定为 `1` - `X-Fabric-Timestamp`: ISO8601 UTC 时间(如 `2026-05-12T11:00:00.000Z`) - `X-Fabric-Nonce`: 随机字符串(建议 UUID) - `X-Fabric-Signature`: HMAC-SHA256 十六进制串 @@ -84,7 +85,10 @@ signature = HMAC_SHA256_HEX(CENTER_SHARED_SECRET, canonicalString) ## 7. 版本协商(预留) 当前版本:`v1` -后续建议在请求头增加: +当前实现要求请求头: - `X-Fabric-Version: 1` -以支持协议平滑升级。 +若版本不匹配,Center 返回: +- `400` +- `error.code = FABRIC_VERSION_NOT_SUPPORTED` +- `supportedVersion = "1"`