feat(control-plane): harden host-scoped reconcile and acceptance evidence

- add batch-scoped reconcile_runs persistence and queries
- route batch detail and reconcile writes through batch_id/host_id
- refresh production boards with host-scope acceptance artifacts
- include latest real-host acceptance evidence for self_service and subscription
This commit is contained in:
phamnazage-jpg
2026-05-18 22:22:22 +08:00
parent 71cbaf5fa6
commit 85d495dd16
332 changed files with 5561 additions and 422 deletions

View File

@@ -10,6 +10,87 @@ paths:
responses:
'200':
description: ok
/api/hosts:
get:
security:
- bearerAuth: []
responses:
'200':
description: list of registered hosts
content:
application/json:
schema:
$ref: '#/components/schemas/ListHostsResponse'
'401':
$ref: '#/components/responses/Unauthorized'
post:
security:
- bearerAuth: []
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateHostRequest'
responses:
'200':
description: host created
content:
application/json:
schema:
$ref: '#/components/schemas/HostInfo'
'401':
$ref: '#/components/responses/Unauthorized'
/api/hosts/{hostID}:
get:
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/HostID'
responses:
'200':
description: host detail
content:
application/json:
schema:
$ref: '#/components/schemas/HostInfo'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
description: host not found
delete:
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/HostID'
responses:
'204':
description: host deleted
'401':
$ref: '#/components/responses/Unauthorized'
'404':
description: host not found
/api/hosts/{hostID}/probe:
post:
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/HostID'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ProbeHostRequest'
responses:
'200':
description: refreshed host capability snapshot
content:
application/json:
schema:
$ref: '#/components/schemas/HostInfo'
'401':
$ref: '#/components/responses/Unauthorized'
/api/packs/install:
post:
security:
@@ -23,84 +104,147 @@ paths:
responses:
'200':
description: pack installed
/api/packs:
get:
security:
- bearerAuth: []
responses:
'200':
description: installed pack list
content:
application/json:
schema:
$ref: '#/components/schemas/ListPacksResponse'
'401':
$ref: '#/components/responses/Unauthorized'
/api/packs/{packID}:
get:
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/PackID'
responses:
'200':
description: pack detail
content:
application/json:
schema:
$ref: '#/components/schemas/PackInfo'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
description: pack not found
/api/packs/{packID}/providers:
get:
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/PackID'
responses:
'200':
description: provider list within pack
content:
application/json:
schema:
$ref: '#/components/schemas/ListPackProvidersResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
description: pack not found
/api/import-batches/{batchID}:
get:
security:
- bearerAuth: []
parameters:
- name: batchID
in: path
required: true
schema:
type: integer
format: int64
- $ref: '#/components/parameters/BatchID'
responses:
'200':
description: batch detail
'401':
$ref: '#/components/responses/Unauthorized'
/api/import-batches/{batchID}/rollback:
post:
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/BatchID'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/RollbackBatchRequest'
responses:
'200':
description: batch rollback summary
content:
application/json:
schema:
$ref: '#/components/schemas/RollbackSummaryResponse'
'401':
$ref: '#/components/responses/Unauthorized'
/api/providers/{providerID}/status:
get:
security:
- bearerAuth: []
parameters:
- name: providerID
in: path
required: true
schema:
type: string
- name: pack_id
in: query
required: false
schema:
type: string
- $ref: '#/components/parameters/ProviderID'
- $ref: '#/components/parameters/PackIDQuery'
- $ref: '#/components/parameters/HostIDQuery'
responses:
'200':
description: provider runtime status
'401':
$ref: '#/components/responses/Unauthorized'
/api/providers/{providerID}/resources:
get:
security:
- bearerAuth: []
parameters:
- name: providerID
in: path
required: true
schema:
type: string
- name: pack_id
in: query
required: false
schema:
type: string
- $ref: '#/components/parameters/ProviderID'
- $ref: '#/components/parameters/PackIDQuery'
- $ref: '#/components/parameters/HostIDQuery'
responses:
'200':
description: provider managed resources snapshot
'401':
$ref: '#/components/responses/Unauthorized'
/api/providers/{providerID}/access/status:
get:
security:
- bearerAuth: []
parameters:
- name: providerID
in: path
required: true
schema:
type: string
- name: pack_id
in: query
required: false
schema:
type: string
- $ref: '#/components/parameters/ProviderID'
- $ref: '#/components/parameters/PackIDQuery'
- $ref: '#/components/parameters/HostIDQuery'
responses:
'200':
description: provider access closure status
'401':
$ref: '#/components/responses/Unauthorized'
/api/providers/{providerID}/import-batches:
get:
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/ProviderID'
- $ref: '#/components/parameters/PackIDQuery'
- $ref: '#/components/parameters/HostIDQuery'
responses:
'200':
description: provider import batch history
content:
application/json:
schema:
$ref: '#/components/schemas/ListImportBatchesResponse'
'401':
$ref: '#/components/responses/Unauthorized'
/api/providers/{providerID}/preview-import:
post:
security:
- bearerAuth: []
parameters:
- name: providerID
in: path
required: true
schema:
type: string
- $ref: '#/components/parameters/ProviderID'
requestBody:
required: true
content:
@@ -115,11 +259,7 @@ paths:
security:
- bearerAuth: []
parameters:
- name: providerID
in: path
required: true
schema:
type: string
- $ref: '#/components/parameters/ProviderID'
requestBody:
required: true
content:
@@ -134,11 +274,7 @@ paths:
security:
- bearerAuth: []
parameters:
- name: providerID
in: path
required: true
schema:
type: string
- $ref: '#/components/parameters/ProviderID'
requestBody:
required: true
content:
@@ -153,11 +289,7 @@ paths:
security:
- bearerAuth: []
parameters:
- name: providerID
in: path
required: true
schema:
type: string
- $ref: '#/components/parameters/ProviderID'
requestBody:
required: true
content:
@@ -167,12 +299,218 @@ paths:
responses:
'200':
description: reconcile summary
/api/providers/{providerID}/access/preview:
post:
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/ProviderID'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AccessPreviewRequest'
responses:
'200':
description: access preview result
content:
application/json:
schema:
$ref: '#/components/schemas/AccessPreviewResponse'
/api/providers/{providerID}/access/assign-subscriptions:
post:
security:
- bearerAuth: []
parameters:
- $ref: '#/components/parameters/ProviderID'
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AssignAccessSubscriptionsRequest'
responses:
'200':
description: access subscription assignment summary
content:
application/json:
schema:
$ref: '#/components/schemas/AssignAccessSubscriptionsResponse'
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
parameters:
HostID:
name: hostID
in: path
required: true
schema:
type: string
PackID:
name: packID
in: path
required: true
schema:
type: string
BatchID:
name: batchID
in: path
required: true
schema:
type: integer
format: int64
ProviderID:
name: providerID
in: path
required: true
schema:
type: string
PackIDQuery:
name: pack_id
in: query
required: false
schema:
type: string
responses:
Unauthorized:
description: missing or invalid admin token
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
schemas:
ErrorResponse:
type: object
properties:
error:
type: object
properties:
code:
type: string
message:
type: string
CreateHostAuth:
type: object
required: [token]
properties:
type:
type: string
enum: [apikey, api_key, bearer]
token:
type: string
CreateHostRequest:
type: object
required: [base_url, auth]
properties:
name:
type: string
base_url:
type: string
auth:
$ref: '#/components/schemas/CreateHostAuth'
ProbeHostRequest:
type: object
required: [auth]
properties:
auth:
$ref: '#/components/schemas/CreateHostAuth'
HostCapabilities:
type: object
properties:
groups:
type: boolean
channels:
type: boolean
plans:
type: boolean
accounts:
type: boolean
account_test:
type: boolean
account_models:
type: boolean
subscriptions:
type: boolean
HostInfo:
type: object
properties:
host_id:
type: string
base_url:
type: string
host_version:
type: string
auth_type:
type: string
status:
type: string
capabilities:
$ref: '#/components/schemas/HostCapabilities'
ListHostsResponse:
type: object
properties:
hosts:
type: array
items:
$ref: '#/components/schemas/HostInfo'
PackInfo:
type: object
properties:
pack_id:
type: string
version:
type: string
vendor:
type: string
target_host:
type: string
min_host_version:
type: string
max_host_version:
type: string
ListPacksResponse:
type: object
properties:
packs:
type: array
items:
$ref: '#/components/schemas/PackInfo'
PackProviderInfo:
type: object
properties:
provider_id:
type: string
display_name:
type: string
platform:
type: string
ListPackProvidersResponse:
type: object
properties:
providers:
type: array
items:
$ref: '#/components/schemas/PackProviderInfo'
ImportBatchInfo:
type: object
properties:
batch_id:
type: integer
format: int64
batch_status:
type: string
access_status:
type: string
ListImportBatchesResponse:
type: object
properties:
batches:
type: array
items:
$ref: '#/components/schemas/ImportBatchInfo'
InstallPackRequest:
type: object
required: [host_base_url, pack_path]
@@ -187,14 +525,19 @@ components:
type: string
PreviewProviderRequest:
type: object
required: [host_base_url, pack_path, keys]
required: [host_id, pack_path, keys]
properties:
host_id:
type: string
host_base_url:
type: string
description: legacy fallback; prefer host_id
host_api_key:
type: string
description: legacy fallback; prefer registered host auth
host_bearer_token:
type: string
description: legacy fallback; prefer registered host auth
pack_path:
type: string
provider_id:
@@ -207,14 +550,19 @@ components:
type: string
ImportProviderRequest:
type: object
required: [host_base_url, pack_path, keys, access_api_key]
required: [host_id, pack_path, keys, access_api_key]
properties:
host_id:
type: string
host_base_url:
type: string
description: legacy fallback; prefer host_id
host_api_key:
type: string
description: legacy fallback; prefer registered host auth
host_bearer_token:
type: string
description: legacy fallback; prefer registered host auth
pack_path:
type: string
provider_id:
@@ -237,29 +585,119 @@ components:
type: integer
RollbackProviderRequest:
type: object
required: [host_base_url, pack_path]
required: [host_id, pack_path]
properties:
host_id:
type: string
host_base_url:
type: string
description: legacy fallback; prefer host_id
host_api_key:
type: string
description: legacy fallback; prefer registered host auth
host_bearer_token:
type: string
description: legacy fallback; prefer registered host auth
pack_path:
type: string
provider_id:
type: string
RollbackBatchRequest:
type: object
required: [auth]
properties:
auth:
$ref: '#/components/schemas/CreateHostAuth'
RollbackSummaryResponse:
type: object
properties:
batch_id:
type: integer
format: int64
deleted_accounts:
type: integer
deleted_plans:
type: integer
deleted_channels:
type: integer
deleted_groups:
type: integer
ReconcileProviderRequest:
type: object
required: [host_base_url, pack_path]
required: [host_id, pack_path]
properties:
host_id:
type: string
host_base_url:
type: string
description: legacy fallback; prefer host_id
host_api_key:
type: string
description: legacy fallback; prefer registered host auth
host_bearer_token:
type: string
description: legacy fallback; prefer registered host auth
pack_path:
type: string
provider_id:
type: string
access_api_key:
type: string
AccessPreviewRequest:
type: object
properties:
provider_id:
type: string
pack_id:
type: string
host_id:
type: string
mode:
type: string
AccessPreviewResponse:
type: object
properties:
provider_id:
type: string
mode:
type: string
available:
type: boolean
message:
type: string
AssignAccessSubscriptionsRequest:
type: object
required: [host_id, pack_path, access_api_key]
properties:
host_id:
type: string
pack_path:
type: string
provider_id:
type: string
host_base_url:
type: string
description: legacy fallback; prefer host_id
host_api_key:
type: string
description: legacy fallback; prefer registered host auth
host_bearer_token:
type: string
description: legacy fallback; prefer registered host auth
access_api_key:
type: string
subscription_users:
type: array
items:
type: string
subscription_days:
type: integer
AssignAccessSubscriptionsResponse:
type: object
properties:
provider_id:
type: string
assigned:
type: integer
access_status:
type: string