mirror of
https://github.com/iflytek/skillhub.git
synced 2026-08-27 11:14:59 +00:00
305 lines
11 KiB
YAML
305 lines
11 KiB
YAML
openapi: 3.0.3
|
|
info:
|
|
title: SkillHub CLI Authentication API
|
|
version: 1.0.0
|
|
description: >-
|
|
Authentication contract for CLI identity and public skill reads. A valid
|
|
Bearer credential overrides a Web Session identity. Once the Bearer scheme
|
|
is used, the credential must be valid: empty, malformed, unknown, expired,
|
|
or revoked Bearer credentials return HTTP 401 and never fall back to the
|
|
Session or anonymous access. An absent Authorization header or an
|
|
unsupported scheme such as Basic preserves a valid Web Session. Without a
|
|
Session, public reads use anonymous visibility and whoami returns HTTP 401.
|
|
servers:
|
|
- url: /
|
|
tags:
|
|
- name: CLI Authentication
|
|
- name: CLI Skills
|
|
paths:
|
|
/api/cli/v1/auth/whoami:
|
|
get:
|
|
tags: [CLI Authentication]
|
|
summary: Return the current CLI identity
|
|
operationId: cliWhoAmI
|
|
description: Requires a valid Bearer credential or Web Session. Bearer takes priority over Session; invalid Bearer returns 401 without Session fallback. An absent or non-Bearer Authorization header preserves Session, but returns 401 when no Session exists.
|
|
security:
|
|
- bearerAuth: []
|
|
- sessionAuth: []
|
|
responses:
|
|
'200':
|
|
description: Authenticated CLI identity
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CliWhoAmIEnvelope'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
/api/cli/v1/skills/search:
|
|
get:
|
|
tags: [CLI Skills]
|
|
summary: Search CLI-installable skills
|
|
operationId: cliSearchSkills
|
|
description: Valid Bearer overrides Web Session. Invalid Bearer returns 401 without Session fallback. An absent or non-Bearer Authorization header preserves Session; without Session, the request uses anonymous public visibility.
|
|
security:
|
|
- {}
|
|
- sessionAuth: []
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: q
|
|
in: query
|
|
required: false
|
|
schema: {type: string}
|
|
example: pdf
|
|
description: Optional search text.
|
|
- name: limit
|
|
in: query
|
|
required: false
|
|
schema: {type: integer, format: int32, default: 20}
|
|
example: 20
|
|
description: Maximum number of results.
|
|
responses:
|
|
'200':
|
|
description: Search result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CliSearchEnvelope'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
/api/cli/v1/skills/{namespace}/{slug}/resolve:
|
|
get:
|
|
tags: [CLI Skills]
|
|
summary: Resolve a skill version
|
|
operationId: cliResolveSkill
|
|
description: Valid Bearer overrides Web Session. Invalid Bearer returns 401 without Session fallback. An absent or non-Bearer Authorization header preserves Session; without Session, the request uses anonymous public visibility.
|
|
security:
|
|
- {}
|
|
- sessionAuth: []
|
|
- bearerAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/Namespace'
|
|
- $ref: '#/components/parameters/Slug'
|
|
- name: version
|
|
in: query
|
|
required: false
|
|
schema: {type: string}
|
|
example: 1.0.0
|
|
description: Optional exact version; omitted resolves latest.
|
|
responses:
|
|
'200':
|
|
description: Resolved version
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CliResolveEnvelope'
|
|
'400':
|
|
$ref: '#/components/responses/BadRequest'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
/api/cli/v1/skills/{namespace}/{slug}/download:
|
|
get:
|
|
tags: [CLI Skills]
|
|
summary: Download the latest installable skill version
|
|
operationId: cliDownloadLatestSkill
|
|
description: Valid Bearer overrides Web Session. Invalid Bearer returns 401 without Session fallback. An absent or non-Bearer Authorization header preserves Session; without Session, the request uses anonymous public visibility.
|
|
security:
|
|
- {}
|
|
- sessionAuth: []
|
|
- bearerAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/Namespace'
|
|
- $ref: '#/components/parameters/Slug'
|
|
responses:
|
|
'200':
|
|
$ref: '#/components/responses/Download'
|
|
'302':
|
|
$ref: '#/components/responses/DownloadRedirect'
|
|
'400':
|
|
$ref: '#/components/responses/BadRequest'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'503':
|
|
$ref: '#/components/responses/StorageUnavailable'
|
|
/api/cli/v1/skills/{namespace}/{slug}/versions/{version}/download:
|
|
get:
|
|
tags: [CLI Skills]
|
|
summary: Download an exact installable skill version
|
|
operationId: cliDownloadSkillVersion
|
|
description: Valid Bearer overrides Web Session. Invalid Bearer returns 401 without Session fallback. An absent or non-Bearer Authorization header preserves Session; without Session, the request uses anonymous public visibility.
|
|
security:
|
|
- {}
|
|
- sessionAuth: []
|
|
- bearerAuth: []
|
|
parameters:
|
|
- $ref: '#/components/parameters/Namespace'
|
|
- $ref: '#/components/parameters/Slug'
|
|
- $ref: '#/components/parameters/Version'
|
|
responses:
|
|
'200':
|
|
$ref: '#/components/responses/Download'
|
|
'302':
|
|
$ref: '#/components/responses/DownloadRedirect'
|
|
'400':
|
|
$ref: '#/components/responses/BadRequest'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'503':
|
|
$ref: '#/components/responses/StorageUnavailable'
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: SkillHub API token
|
|
description: API token issued by SkillHub. A valid token overrides Web Session; invalid lifecycle states all return the same 401 response without Session fallback.
|
|
sessionAuth:
|
|
type: apiKey
|
|
in: cookie
|
|
name: SESSION
|
|
description: Spring Session browser identity. It is preserved when Authorization is absent or uses a non-Bearer scheme, and is overridden by a valid Bearer token.
|
|
parameters:
|
|
Namespace:
|
|
name: namespace
|
|
in: path
|
|
required: true
|
|
schema: {type: string}
|
|
example: global
|
|
description: Namespace slug.
|
|
Slug:
|
|
name: slug
|
|
in: path
|
|
required: true
|
|
schema: {type: string}
|
|
example: pdf-parser
|
|
description: Skill slug.
|
|
Version:
|
|
name: version
|
|
in: path
|
|
required: true
|
|
schema: {type: string}
|
|
example: 1.0.0
|
|
description: Exact semantic version.
|
|
responses:
|
|
Download:
|
|
description: ZIP package stream
|
|
headers:
|
|
Content-Disposition:
|
|
schema: {type: string}
|
|
description: Attachment filename.
|
|
content:
|
|
application/zip:
|
|
schema: {type: string, format: binary}
|
|
DownloadRedirect:
|
|
description: Redirect to a presigned object-storage URL
|
|
headers:
|
|
Location:
|
|
schema: {type: string, format: uri}
|
|
BadRequest:
|
|
description: Namespace, skill, or version cannot be resolved.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ErrorEnvelope'}
|
|
Unauthorized:
|
|
description: No valid supported identity is present where required, or the Bearer credential is empty, malformed, unknown, expired, revoked, or belongs to an unavailable user. Invalid Bearer never falls back to Web Session.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ErrorEnvelope'}
|
|
example:
|
|
code: 401
|
|
msg: Authentication required
|
|
data: null
|
|
timestamp: '2026-07-28T00:00:00Z'
|
|
requestId: req-123
|
|
Forbidden:
|
|
description: Credential is valid but token scope or resource permission is insufficient.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ErrorEnvelope'}
|
|
example:
|
|
code: 403
|
|
msg: Forbidden
|
|
data: null
|
|
timestamp: '2026-07-28T00:00:00Z'
|
|
requestId: req-123
|
|
StorageUnavailable:
|
|
description: Object storage is unavailable.
|
|
content:
|
|
application/json:
|
|
schema: {$ref: '#/components/schemas/ErrorEnvelope'}
|
|
schemas:
|
|
Envelope:
|
|
type: object
|
|
required: [code, msg, data, timestamp, requestId]
|
|
properties:
|
|
code: {type: integer, format: int32}
|
|
msg: {type: string}
|
|
data: {type: object, nullable: true}
|
|
timestamp: {type: string, format: date-time}
|
|
requestId: {type: string, example: req-123}
|
|
ErrorEnvelope:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Envelope'
|
|
- type: object
|
|
properties:
|
|
data: {type: object, nullable: true, example: null}
|
|
CliWhoAmIEnvelope:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Envelope'
|
|
- type: object
|
|
properties:
|
|
data:
|
|
$ref: '#/components/schemas/CliWhoAmI'
|
|
CliWhoAmI:
|
|
type: object
|
|
required: [handle, displayName, email]
|
|
properties:
|
|
handle: {type: string, example: user-123}
|
|
displayName: {type: string, example: CLI User}
|
|
email: {type: string, format: email, nullable: true, example: cli@example.com, description: Email address when available; the required field is null when the account has no email.}
|
|
CliSearchEnvelope:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Envelope'
|
|
- type: object
|
|
properties:
|
|
data:
|
|
$ref: '#/components/schemas/CliSearchResult'
|
|
CliSearchResult:
|
|
type: object
|
|
required: [items, total, limit]
|
|
properties:
|
|
items:
|
|
type: array
|
|
items: {$ref: '#/components/schemas/CliSearchItem'}
|
|
total: {type: integer, format: int64, example: 1}
|
|
limit: {type: integer, format: int32, example: 20}
|
|
CliSearchItem:
|
|
type: object
|
|
required: [namespace, slug, latestVersion]
|
|
properties:
|
|
namespace: {type: string, example: global}
|
|
slug: {type: string, example: pdf-parser}
|
|
latestVersion: {type: string, example: 1.2.0}
|
|
summary: {type: string, nullable: true, example: Parse PDF files}
|
|
CliResolveEnvelope:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Envelope'
|
|
- type: object
|
|
properties:
|
|
data:
|
|
$ref: '#/components/schemas/CliResolveResult'
|
|
CliResolveResult:
|
|
type: object
|
|
required: [namespace, slug, version, versionId, fingerprint, downloadUrl]
|
|
properties:
|
|
namespace: {type: string, example: global}
|
|
slug: {type: string, example: pdf-parser}
|
|
version: {type: string, example: 1.2.0}
|
|
versionId: {type: integer, format: int64, example: 42}
|
|
fingerprint: {type: string, example: 'sha256:abc123'}
|
|
downloadUrl: {type: string, example: /api/v1/skills/global/pdf-parser/versions/1.2.0/download}
|