mirror of
https://github.com/hpd840321/craftlabs-authorization-sdk.git
synced 2026-06-09 10:00:30 +08:00
feat(platform): I1 bootstrap, I2 M1 APIs, OpenAPI SSOT, and CI guards
Deliver dual Spring Boot services (platform API + webhook ingress), JWT auth, Flyway with isolated history tables, customer/project/dictionary endpoints, OpenAPI snapshot under contracts/, RUNBOOK, and CI that runs on services/web/contracts paths plus enforcer + dependency tree ban on craftlabs-auth-bitanswer. Made-with: Cursor
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
# 契约(Contracts)
|
||||
|
||||
## OpenAPI — 交付平台 API
|
||||
|
||||
| 文件 | 说明 |
|
||||
|------|------|
|
||||
| [`openapi/delivery-platform-api.json`](openapi/delivery-platform-api.json) | **`delivery-platform-api` 的单一事实来源(SSOT)**;与运行时 `/v3/api-docs` 对齐。 |
|
||||
|
||||
### 更新快照(维护者)
|
||||
|
||||
在仓库根目录或 `services/delivery-platform-api` 下执行(需 JDK 17):
|
||||
|
||||
```bash
|
||||
export JAVA_HOME=… # JDK 17+
|
||||
cd services/delivery-platform-api
|
||||
UPDATE_OPENAPI=1 mvn -q test -Dtest=OpenApiContractSnapshotTest
|
||||
```
|
||||
|
||||
提交前请 **审阅 diff**:破坏性变更需 bump 版本说明、同步前端与集成方。
|
||||
|
||||
### CI 校验
|
||||
|
||||
默认 `mvn verify` 会运行 `OpenApiContractSnapshotTest`:**运行时生成的 OpenAPI 与快照须一致**。若仅改实现未改契约却导致文档变化,应更新快照并写在 PR 说明中。
|
||||
|
||||
### 与前端
|
||||
|
||||
`web/delivery-platform-ui` 的 axios 路径应与 OpenAPI `paths` 一致;可选后续接入 OpenAPI Generator 生成 TS 类型(非必选)。
|
||||
@@ -0,0 +1,570 @@
|
||||
{
|
||||
"openapi" : "3.1.0",
|
||||
"info" : {
|
||||
"title" : "CraftLabs 交付管理平台 API",
|
||||
"description" : "I1+:JWT 认证;迭代扩展 M1~M11",
|
||||
"version" : "0.1.0-SNAPSHOT"
|
||||
},
|
||||
"servers" : [ {
|
||||
"url" : "http://localhost",
|
||||
"description" : "Generated server url"
|
||||
} ],
|
||||
"paths" : {
|
||||
"/api/v1/projects/{id}" : {
|
||||
"get" : {
|
||||
"tags" : [ "project-controller" ],
|
||||
"operationId" : "get",
|
||||
"parameters" : [ {
|
||||
"name" : "id",
|
||||
"in" : "path",
|
||||
"required" : true,
|
||||
"schema" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
}
|
||||
} ],
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "OK",
|
||||
"content" : {
|
||||
"*/*" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/ProjectResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put" : {
|
||||
"tags" : [ "project-controller" ],
|
||||
"operationId" : "update",
|
||||
"parameters" : [ {
|
||||
"name" : "id",
|
||||
"in" : "path",
|
||||
"required" : true,
|
||||
"schema" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
}
|
||||
} ],
|
||||
"requestBody" : {
|
||||
"content" : {
|
||||
"application/json" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/ProjectRequest"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required" : true
|
||||
},
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "OK",
|
||||
"content" : {
|
||||
"*/*" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/ProjectResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete" : {
|
||||
"tags" : [ "project-controller" ],
|
||||
"operationId" : "delete",
|
||||
"parameters" : [ {
|
||||
"name" : "id",
|
||||
"in" : "path",
|
||||
"required" : true,
|
||||
"schema" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
}
|
||||
} ],
|
||||
"responses" : {
|
||||
"204" : {
|
||||
"description" : "No Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/customers/{id}" : {
|
||||
"get" : {
|
||||
"tags" : [ "customer-controller" ],
|
||||
"operationId" : "get_1",
|
||||
"parameters" : [ {
|
||||
"name" : "id",
|
||||
"in" : "path",
|
||||
"required" : true,
|
||||
"schema" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
}
|
||||
} ],
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "OK",
|
||||
"content" : {
|
||||
"*/*" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/CustomerResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put" : {
|
||||
"tags" : [ "customer-controller" ],
|
||||
"operationId" : "update_1",
|
||||
"parameters" : [ {
|
||||
"name" : "id",
|
||||
"in" : "path",
|
||||
"required" : true,
|
||||
"schema" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
}
|
||||
} ],
|
||||
"requestBody" : {
|
||||
"content" : {
|
||||
"application/json" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/CustomerRequest"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required" : true
|
||||
},
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "OK",
|
||||
"content" : {
|
||||
"*/*" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/CustomerResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete" : {
|
||||
"tags" : [ "customer-controller" ],
|
||||
"operationId" : "delete_1",
|
||||
"parameters" : [ {
|
||||
"name" : "id",
|
||||
"in" : "path",
|
||||
"required" : true,
|
||||
"schema" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
}
|
||||
} ],
|
||||
"responses" : {
|
||||
"204" : {
|
||||
"description" : "No Content"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/projects" : {
|
||||
"get" : {
|
||||
"tags" : [ "project-controller" ],
|
||||
"operationId" : "list",
|
||||
"parameters" : [ {
|
||||
"name" : "page",
|
||||
"in" : "query",
|
||||
"required" : false,
|
||||
"schema" : {
|
||||
"type" : "integer",
|
||||
"format" : "int32",
|
||||
"default" : 0,
|
||||
"minimum" : 0
|
||||
}
|
||||
}, {
|
||||
"name" : "size",
|
||||
"in" : "query",
|
||||
"required" : false,
|
||||
"schema" : {
|
||||
"type" : "integer",
|
||||
"format" : "int32",
|
||||
"default" : 20,
|
||||
"maximum" : 200,
|
||||
"minimum" : 1
|
||||
}
|
||||
}, {
|
||||
"name" : "customerId",
|
||||
"in" : "query",
|
||||
"required" : false,
|
||||
"schema" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
}
|
||||
} ],
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "OK",
|
||||
"content" : {
|
||||
"*/*" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/PageResponseProjectResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post" : {
|
||||
"tags" : [ "project-controller" ],
|
||||
"operationId" : "create",
|
||||
"requestBody" : {
|
||||
"content" : {
|
||||
"application/json" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/ProjectRequest"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required" : true
|
||||
},
|
||||
"responses" : {
|
||||
"201" : {
|
||||
"description" : "Created",
|
||||
"content" : {
|
||||
"*/*" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/ProjectResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/customers" : {
|
||||
"get" : {
|
||||
"tags" : [ "customer-controller" ],
|
||||
"operationId" : "list_1",
|
||||
"parameters" : [ {
|
||||
"name" : "page",
|
||||
"in" : "query",
|
||||
"required" : false,
|
||||
"schema" : {
|
||||
"type" : "integer",
|
||||
"format" : "int32",
|
||||
"default" : 0,
|
||||
"minimum" : 0
|
||||
}
|
||||
}, {
|
||||
"name" : "size",
|
||||
"in" : "query",
|
||||
"required" : false,
|
||||
"schema" : {
|
||||
"type" : "integer",
|
||||
"format" : "int32",
|
||||
"default" : 20,
|
||||
"maximum" : 200,
|
||||
"minimum" : 1
|
||||
}
|
||||
}, {
|
||||
"name" : "keyword",
|
||||
"in" : "query",
|
||||
"required" : false,
|
||||
"schema" : {
|
||||
"type" : "string"
|
||||
}
|
||||
} ],
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "OK",
|
||||
"content" : {
|
||||
"*/*" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/PageResponseCustomerResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post" : {
|
||||
"tags" : [ "customer-controller" ],
|
||||
"operationId" : "create_1",
|
||||
"requestBody" : {
|
||||
"content" : {
|
||||
"application/json" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/CustomerRequest"
|
||||
}
|
||||
}
|
||||
},
|
||||
"required" : true
|
||||
},
|
||||
"responses" : {
|
||||
"201" : {
|
||||
"description" : "Created",
|
||||
"content" : {
|
||||
"*/*" : {
|
||||
"schema" : {
|
||||
"$ref" : "#/components/schemas/CustomerResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/auth/login" : {
|
||||
"post" : {
|
||||
"tags" : [ "auth-controller" ],
|
||||
"operationId" : "login",
|
||||
"requestBody" : {
|
||||
"content" : {
|
||||
"application/json" : {
|
||||
"schema" : {
|
||||
"type" : "object",
|
||||
"additionalProperties" : {
|
||||
"type" : "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"required" : true
|
||||
},
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "OK",
|
||||
"content" : {
|
||||
"*/*" : {
|
||||
"schema" : {
|
||||
"type" : "object",
|
||||
"additionalProperties" : { }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/ping" : {
|
||||
"get" : {
|
||||
"tags" : [ "ping-controller" ],
|
||||
"operationId" : "ping",
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "OK",
|
||||
"content" : {
|
||||
"*/*" : {
|
||||
"schema" : {
|
||||
"type" : "object",
|
||||
"additionalProperties" : {
|
||||
"type" : "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/api/v1/dictionaries/{type}" : {
|
||||
"get" : {
|
||||
"tags" : [ "dictionary-controller" ],
|
||||
"operationId" : "listByType",
|
||||
"parameters" : [ {
|
||||
"name" : "type",
|
||||
"in" : "path",
|
||||
"required" : true,
|
||||
"schema" : {
|
||||
"type" : "string"
|
||||
}
|
||||
} ],
|
||||
"responses" : {
|
||||
"200" : {
|
||||
"description" : "OK",
|
||||
"content" : {
|
||||
"*/*" : {
|
||||
"schema" : {
|
||||
"type" : "array",
|
||||
"items" : {
|
||||
"$ref" : "#/components/schemas/DictionaryItemResponse"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components" : {
|
||||
"schemas" : {
|
||||
"ProjectRequest" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"customerId" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
},
|
||||
"name" : {
|
||||
"type" : "string",
|
||||
"maxLength" : 256,
|
||||
"minLength" : 0
|
||||
},
|
||||
"phase" : {
|
||||
"type" : "string",
|
||||
"maxLength" : 64,
|
||||
"minLength" : 0
|
||||
}
|
||||
},
|
||||
"required" : [ "customerId", "name" ]
|
||||
},
|
||||
"ProjectResponse" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"id" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
},
|
||||
"customerId" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
},
|
||||
"name" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"phase" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"createdAt" : {
|
||||
"type" : "string",
|
||||
"format" : "date-time"
|
||||
},
|
||||
"updatedAt" : {
|
||||
"type" : "string",
|
||||
"format" : "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CustomerRequest" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"name" : {
|
||||
"type" : "string",
|
||||
"maxLength" : 256,
|
||||
"minLength" : 0
|
||||
},
|
||||
"creditCode" : {
|
||||
"type" : "string",
|
||||
"maxLength" : 64,
|
||||
"minLength" : 0
|
||||
},
|
||||
"status" : {
|
||||
"type" : "string",
|
||||
"maxLength" : 32,
|
||||
"minLength" : 0
|
||||
}
|
||||
},
|
||||
"required" : [ "name" ]
|
||||
},
|
||||
"CustomerResponse" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"id" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
},
|
||||
"name" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"creditCode" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"status" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"createdAt" : {
|
||||
"type" : "string",
|
||||
"format" : "date-time"
|
||||
},
|
||||
"updatedAt" : {
|
||||
"type" : "string",
|
||||
"format" : "date-time"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PageResponseProjectResponse" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"content" : {
|
||||
"type" : "array",
|
||||
"items" : {
|
||||
"$ref" : "#/components/schemas/ProjectResponse"
|
||||
}
|
||||
},
|
||||
"totalElements" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
},
|
||||
"number" : {
|
||||
"type" : "integer",
|
||||
"format" : "int32"
|
||||
},
|
||||
"size" : {
|
||||
"type" : "integer",
|
||||
"format" : "int32"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DictionaryItemResponse" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"dictCode" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"dictLabel" : {
|
||||
"type" : "string"
|
||||
},
|
||||
"sortOrder" : {
|
||||
"type" : "integer",
|
||||
"format" : "int32"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PageResponseCustomerResponse" : {
|
||||
"type" : "object",
|
||||
"properties" : {
|
||||
"content" : {
|
||||
"type" : "array",
|
||||
"items" : {
|
||||
"$ref" : "#/components/schemas/CustomerResponse"
|
||||
}
|
||||
},
|
||||
"totalElements" : {
|
||||
"type" : "integer",
|
||||
"format" : "int64"
|
||||
},
|
||||
"number" : {
|
||||
"type" : "integer",
|
||||
"format" : "int32"
|
||||
},
|
||||
"size" : {
|
||||
"type" : "integer",
|
||||
"format" : "int32"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"securitySchemes" : {
|
||||
"bearer-jwt" : {
|
||||
"type" : "http",
|
||||
"name" : "bearer-jwt",
|
||||
"scheme" : "bearer",
|
||||
"bearerFormat" : "JWT"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user