Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
272 changes: 268 additions & 4 deletions apollo-openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ tags:
description: 环境管理相关接口,包括环境查询等功能
- name: Permission Management
description: 权限管理相关接口,包括权限查询等功能
- name: User Management
description: Operations related to user accounts
paths:
/openapi/v1/apps:
post:
Expand Down Expand Up @@ -3645,6 +3647,190 @@ paths:
responses:
'200':
description: '灰度规则更新成功'
headers: {}
/openapi/v1/users:
post:
summary: 创建用户
operationId: createUser
deprecated: false
description: POST /openapi/v1/users
tags:
- User Management
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/OpenUserDTO'
example:
username: "new-user"
userDisplayName: "New User"
password: "P@ssw0rd123"
email: "new-user@example.com"
enabled: 1
responses:
'200':
description: 成功创建用户,返回创建的用户信息
content:
application/json:
schema:
$ref: '#/components/schemas/OpenUserInfoDTO'
example:
userId: "new-user"
name: "New User"
email: "new-user@example.com"
enabled: 1
headers: {}
'400':
description: 请求参数错误(用户名/密码/邮箱为空,或密码强度不足)
content:
application/json:
schema:
type: object
allOf:
- $ref: '#/components/schemas/ExceptionResponse'
'401':
description: 未授权访问
content:
application/json:
schema:
type: object
allOf:
- $ref: '#/components/schemas/ExceptionResponse'
'403':
description: 权限不足或当前用户服务不支持创建用户
content:
application/json:
schema:
type: object
allOf:
- $ref: '#/components/schemas/ExceptionResponse'
'409':
description: 用户名已存在(重复)
content:
application/json:
schema:
type: object
allOf:
- $ref: '#/components/schemas/ExceptionResponse'
get:
summary: 搜索用户列表
operationId: searchUsers
deprecated: false
description: GET /openapi/v1/users
tags:
- User Management
parameters:
- name: keyword
in: query
description: 搜索关键字(匹配用户名或显示名称),为空时返回所有用户
required: false
schema:
type: string
default: ""
- name: includeInactiveUsers
in: query
description: 是否包含已停用的用户
required: false
schema:
type: boolean
default: false
- name: offset
in: query
description: 分页偏移量,从0开始
required: false
schema:
type: integer
default: 0
minimum: 0
- name: limit
in: query
description: 分页大小,取值范围 1~100
required: false
schema:
type: integer
default: 10
minimum: 1
maximum: 100
responses:
'200':
description: 成功获取用户列表
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/OpenUserInfoDTO'
example:
- userId: "apollo"
name: "Apollo Admin"
email: "apollo@example.com"
enabled: 1
- userId: "dev-user"
name: "Dev User"
email: "dev@example.com"
enabled: 1
headers: {}
'400':
description: 请求参数错误(offset或limit超出范围)
content:
application/json:
schema:
type: object
allOf:
- $ref: '#/components/schemas/ExceptionResponse'
'401':
description: 未授权访问
content:
application/json:
schema:
type: object
allOf:
- $ref: '#/components/schemas/ExceptionResponse'
/openapi/v1/users/{userId}:
get:
summary: 根据用户ID获取用户信息
operationId: getUserByUserId
deprecated: false
description: GET /openapi/v1/users/{userId}
tags:
- User Management
parameters:
- name: userId
in: path
description: 用户ID(用户名)
required: true
schema:
type: string
responses:
'200':
description: 成功获取用户信息
content:
application/json:
schema:
$ref: '#/components/schemas/OpenUserInfoDTO'
example:
userId: "apollo"
name: "Apollo Admin"
email: "apollo@example.com"
enabled: 1
headers: {}
'404':
description: 用户不存在
content:
application/json:
schema:
type: object
allOf:
- $ref: '#/components/schemas/ExceptionResponse'
'401':
description: 未授权访问
content:
application/json:
schema:
type: object
allOf:
- $ref: '#/components/schemas/ExceptionResponse'
/openapi/v1/envs:
get:
summary: 获取所有环境
Expand Down Expand Up @@ -5565,19 +5751,26 @@ components:
description: ''
OpenUserInfoDTO:
type: object
description: 用户信息
properties:
userId:
type: string
description: ''
description: 用户ID(即用户名)
example: "apollo"
name:
type: string
description: ''
description: 用户显示名称
example: "Apollo Admin"
email:
type: string
description: ''
description: 用户邮箱
format: email
example: "apollo@example.com"
enabled:
type: integer
description: ''
description: 用户状态:1-启用,0-停用
enum: [0, 1]
example: 1
OpenEnvNamespaceRoleUserDTO:
type: object
properties:
Expand Down Expand Up @@ -5733,4 +5926,75 @@ components:
projectB:
darkMode: true

MultiResponseEntity:
type: object
description: "Reserved for endpoints that return multiple RichResponseEntity items. A response container holding multiple RichResponseEntity objects (intended future use)."
properties:
code:
type: integer
description: Overall HTTP status code
example: 200
entities:
type: array
description: List of rich response entities
items:
$ref: '#/components/schemas/RichResponseEntity'
required:
- code
- entities

RichResponseEntity:
type: object
description: "Reserved for future use as a wrapper for a single response entity with code, message, and body."
properties:
code:
type: integer
description: HTTP status code
example: 200
message:
type: object
description: Response message (can be string or object)
example: "OK"
body:
Comment on lines +5954 to +5958
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Examine the apollo-openapi.yaml file around lines 5954-5958
if [ -f "apollo-openapi.yaml" ]; then
  echo "=== Lines 5950-5970 of apollo-openapi.yaml ===" 
  sed -n '5950,5970p' apollo-openapi.yaml
else
  echo "File not found at root, searching for it..."
  find . -name "apollo-openapi.yaml" -type f
fi

Repository: apolloconfig/apollo-openapi

Length of output: 621


🌐 Web query:

OpenAPI 3.0 specification example validation must conform to schema type

💡 Result:

In OpenAPI 3.0.x, example values are not required (“MUST”) to conform to the schema type, but they are expected/encouraged to.

  • Media Type Object (content.*.example / content.*.examples): the spec says each example “SHOULD match” the media type and the specified schema (if present)—so it’s a recommendation, not a hard requirement. [1]
  • Example Object (components.examples.*.value): the spec says the example value is expected to be compatible with the associated schema type, and tools MAY choose to validate and reject incompatible examples. [2]

So: spec-wise, non-conforming examples don’t make the OAS 3.0 document invalid, but many linters/validators can (optionally) enforce example-vs-schema compatibility. [2]

Sources:
[1] OpenAPI Spec 3.0.3 – Media Type Object (example/examples “SHOULD match” schema) (spec.openapis.org)
[2] OpenAPI Spec 3.0.1 – Example Object (compatibility expected; tooling MAY validate) (spec.openapis.org)

Citations:


🌐 Web query:

OpenAPI 3.0 oneOf vs anyOf for union types string or object best practices

💡 Result:

oneOf vs anyOf (OpenAPI 3.0) — what to use for “string or object”

  • Prefer oneOf for union types (either this schema or that schema), because it means the instance must validate against exactly one option (exclusive OR). This is the clearest intent for “string-or-object”. [1][2]
  • Use anyOf sparingly for structural unions, because it means the instance may validate against one or more options, which can create ambiguity and inconsistent tooling/validator behavior when schemas overlap. Many guidance sources recommend avoiding anyOf for “either/or” payload shapes. [1][2]

Practical rule for string | object

  • If the alternatives are different JSON types (e.g., type: string vs type: object), then oneOf and anyOf behave the same in practice (the instance can’t be both a string and an object). Still, oneOf is the better signal to humans/tools that it’s a true union. [3][2]

Best-practice schema pattern (OpenAPI 3.0)

MyField:
  oneOf:
    - type: string
      description: ID reference form
    - type: object
      additionalProperties: false
      required: [id]
      properties:
        id:
          type: string
      description: Expanded object form

Tips to keep it robust:

  • Make the object variant strict and distinguishable (e.g., required, additionalProperties: false) to avoid accidental overlap in more complex unions. [1]
  • If your union is object-vs-object, add a discriminating property (often a "type" with an enum) and consider OpenAPI’s discriminator to improve tooling/SDK generation. (Discriminator is defined for use with oneOf/anyOf/allOf.) [4]

Why not type: [string, object] in OAS 3.0?

OpenAPI 3.0’s Schema Object does not support multiple types via a type array, so unions should be modeled with oneOf/anyOf. [5]

Sources: Redocly guidance on preferring oneOf and avoiding anyOf for structural alternatives [1]; Swagger docs on oneOf/anyOf semantics [2]; StackOverflow note that anyOf can often be replaced by oneOf when types differ [3]; OpenAPI spec on discriminator usage with composition keywords [4]; OAS 3.0.1 spec note that multiple types via an array are not supported [5].


Align RichResponseEntity.message schema with its documented payload type.

The message property is declared as type: object, but its example is a string ("OK"), and the description indicates it can be either string or object. While OpenAPI 3.0 does not strictly require examples to conform to the declared schema, this mismatch will likely trigger validation warnings in linters and generate inconsistent client code. Per OpenAPI best practices, use oneOf to explicitly model the union type.

🔧 Proposed fix
     RichResponseEntity:
       type: object
       description: "Reserved for future use as a wrapper for a single response entity with code, message, and body."
       properties:
         code:
           type: integer
           description: HTTP status code
           example: 200
         message:
-          type: object
+          oneOf:
+            - type: string
+            - type: object
           description: Response message (can be string or object)
           example: "OK"
         body:
           type: object
           description: Response payload (generic type T)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apollo-openapi.yaml` around lines 5954 - 5958, Replace the current fixed
object schema for RichResponseEntity.message with a union using oneOf that
allows either a string or an object (e.g., oneOf: - type: string; - type: object
/ or a $ref to the existing object schema), update the description to reflect
"string or object" and adjust the example(s) to match the oneOf (provide an
example for the string case and/or an exampleObject entry for the object case)
so linters and code generators see a proper union type; locate the message
property under the RichResponseEntity schema to make these edits.

type: object
description: Response payload (generic type T)
required:
- code
- message

OpenUserDTO:
type: object
description: 用于创建用户的请求体 DTO
properties:
username:
type: string
description: 用户名(登录账号),创建时必填
example: "new-user"
userDisplayName:
type: string
description: 用户显示名称,若不填则默认使用 username
example: "New User"
password:
type: string
description: 用户密码,创建时必填,需满足密码强度要求
format: password
writeOnly: true
example: "P@ssw0rd123"
email:
type: string
description: 用户邮箱,创建时必填
format: email
example: "new-user@example.com"
enabled:
type: integer
description: 用户状态:1-启用,0-停用,默认为1
enum: [0, 1]
default: 1
example: 1
required:
- username
- password
- email


servers: []