feat(ql3): add generic worker management entry

This commit is contained in:
whyour
2026-08-20 13:30:06 +08:00
parent 4a4fa85f51
commit af5d5bfc0b
20 changed files with 1191 additions and 42 deletions
@@ -15,6 +15,7 @@ import { TextDecoder } from 'node:util';
export type ClusterAuthenticatedManagementClientKind =
| 'package'
| 'worker'
| 'worker-credential'
| 'automation'
| 'approval'
@@ -34,6 +35,10 @@ const MANAGEMENT_CLIENT_POLICIES: Readonly<
managementPath: '/api/v3/plugin-packages/management',
clientCertificate: 'forbidden',
}),
worker: Object.freeze({
managementPath: '/api/v3/workers/management',
clientCertificate: 'required',
}),
'worker-credential': Object.freeze({
managementPath: '/api/v3/worker-credentials/management',
clientCertificate: 'required',
@@ -147,7 +152,9 @@ export function readCanonicalFile(
throw configurationFailure();
}
} catch (error) {
if (error instanceof ClusterPluginPackageManagementClientConfigurationError) {
if (
error instanceof ClusterPluginPackageManagementClientConfigurationError
) {
throw error;
}
throw configurationFailure();
@@ -209,7 +216,9 @@ export function readCanonicalFile(
return bytes;
} catch (error) {
bytes?.fill(0);
if (error instanceof ClusterPluginPackageManagementClientConfigurationError) {
if (
error instanceof ClusterPluginPackageManagementClientConfigurationError
) {
throw error;
}
throw configurationFailure();
@@ -349,7 +358,10 @@ export function prepareClusterAuthenticatedManagementClientConfiguration(
throw configurationFailure();
}
} catch (error) {
if (error instanceof ClusterPluginPackageManagementClientConfigurationError) {
if (
error instanceof
ClusterPluginPackageManagementClientConfigurationError
) {
throw error;
}
throw configurationFailure();
@@ -380,7 +392,9 @@ export function prepareClusterAuthenticatedManagementClientConfiguration(
caBytes?.fill(0);
clientCertificateBytes?.fill(0);
clientPrivateKeyBytes?.fill(0);
if (error instanceof ClusterPluginPackageManagementClientConfigurationError) {
if (
error instanceof ClusterPluginPackageManagementClientConfigurationError
) {
throw error;
}
throw configurationFailure();
@@ -408,11 +422,10 @@ export function validateClusterAuthenticatedManagementClientConfiguration(
): Readonly<ClusterAuthenticatedManagementClientConfigurationSummary> {
const policy = MANAGEMENT_CLIENT_POLICIES[kind];
if (policy === undefined) throw configurationFailure();
const prepared =
prepareClusterAuthenticatedManagementClientKindConfiguration(
configFile,
kind,
);
const prepared = prepareClusterAuthenticatedManagementClientKindConfiguration(
configFile,
kind,
);
try {
return Object.freeze({
schemaVersion: 1,
@@ -85,6 +85,7 @@ export const CLUSTER_PLUGIN_PACKAGE_MANAGEMENT_PATH =
'/api/v3/plugin-packages/management';
export const CLUSTER_WORKER_CREDENTIAL_MANAGEMENT_PATH =
'/api/v3/worker-credentials/management';
export const CLUSTER_WORKER_MANAGEMENT_PATH = '/api/v3/workers/management';
export const CLUSTER_AUTOMATION_MANAGEMENT_PATH =
'/api/v3/automations/management';
export const CLUSTER_APPROVAL_MANAGEMENT_PATH = '/api/v3/approvals/management';
@@ -94,6 +95,7 @@ export const CLUSTER_RUN_MANAGEMENT_PATH = '/api/v3/runs/management';
export type ClusterAuthenticatedManagementPath =
| typeof CLUSTER_PLUGIN_PACKAGE_MANAGEMENT_PATH
| typeof CLUSTER_WORKER_CREDENTIAL_MANAGEMENT_PATH
| typeof CLUSTER_WORKER_MANAGEMENT_PATH
| typeof CLUSTER_AUTOMATION_MANAGEMENT_PATH
| typeof CLUSTER_APPROVAL_MANAGEMENT_PATH
| typeof CLUSTER_MODEL_PROVIDER_CREDENTIAL_MANAGEMENT_PATH
@@ -101,6 +103,7 @@ export type ClusterAuthenticatedManagementPath =
const MANAGEMENT_PATHS = new Set<ClusterAuthenticatedManagementPath>([
CLUSTER_PLUGIN_PACKAGE_MANAGEMENT_PATH,
CLUSTER_WORKER_CREDENTIAL_MANAGEMENT_PATH,
CLUSTER_WORKER_MANAGEMENT_PATH,
CLUSTER_AUTOMATION_MANAGEMENT_PATH,
CLUSTER_APPROVAL_MANAGEMENT_PATH,
CLUSTER_MODEL_PROVIDER_CREDENTIAL_MANAGEMENT_PATH,
@@ -143,6 +146,7 @@ export interface StartClusterPluginPackageManagementHttpOptions {
readonly transport: ClusterAuthenticatedManagementTransport;
readonly identities: ClusterPluginPackageIdentityKeysetFile;
readonly managementPath?: ClusterAuthenticatedManagementPath;
readonly compatibleManagementPaths?: readonly ClusterAuthenticatedManagementPath[];
readonly limits?: ClusterPluginPackageManagementHttpLimits;
readonly now?: () => number;
readonly createRequestId?: () => string;
@@ -547,7 +551,8 @@ function responseError(error: unknown): HttpRequestError {
error instanceof ClusterApprovalManagementTransportAuthenticationError ||
error instanceof
ClusterModelProviderCredentialManagementTransportAuthenticationError ||
error instanceof ClusterModelProviderCredentialManagementAuthenticationError ||
error instanceof
ClusterModelProviderCredentialManagementAuthenticationError ||
error instanceof ClusterRunManagementTransportAuthenticationError
) {
return new HttpRequestError(401, 'authentication_required');
@@ -573,7 +578,8 @@ function responseError(error: unknown): HttpRequestError {
error instanceof WorkerCredentialManagementAuthorizationError ||
error instanceof ClusterAutomationManagementAuthorizationError ||
error instanceof ClusterApprovalManagementTransportAuthorizationError ||
error instanceof ClusterModelProviderCredentialManagementAuthorizationError ||
error instanceof
ClusterModelProviderCredentialManagementAuthorizationError ||
error instanceof ClusterRunManagementAuthorizationError
) {
return new HttpRequestError(403, 'forbidden');
@@ -665,6 +671,7 @@ export async function startClusterPluginPackageManagementHttp(
'transport',
'identities',
'managementPath',
'compatibleManagementPaths',
'limits',
'now',
'createRequestId',
@@ -711,6 +718,12 @@ export async function startClusterPluginPackageManagementHttp(
typeof options.identities.reload !== 'function' ||
(options.managementPath !== undefined &&
!MANAGEMENT_PATHS.has(options.managementPath)) ||
(options.compatibleManagementPaths !== undefined &&
(!Array.isArray(options.compatibleManagementPaths) ||
options.managementPath !== CLUSTER_WORKER_MANAGEMENT_PATH ||
options.compatibleManagementPaths.length !== 1 ||
options.compatibleManagementPaths[0] !==
CLUSTER_WORKER_CREDENTIAL_MANAGEMENT_PATH)) ||
(options.now !== undefined && typeof options.now !== 'function') ||
(options.createRequestId !== undefined &&
typeof options.createRequestId !== 'function') ||
@@ -721,6 +734,10 @@ export async function startClusterPluginPackageManagementHttp(
const limits = reviewedLimits(options.limits);
const managementPath =
options.managementPath ?? CLUSTER_PLUGIN_PACKAGE_MANAGEMENT_PATH;
const managementPaths = new Set<ClusterAuthenticatedManagementPath>([
managementPath,
...(options.compatibleManagementPaths ?? []),
]);
const now = options.now ?? Date.now;
const createRequestId = options.createRequestId ?? randomUUID;
const clientCertificateRequired =
@@ -824,7 +841,10 @@ export async function startClusterPluginPackageManagementHttp(
) {
throw new HttpRequestError(401, 'client_certificate_required');
}
if (request.method !== 'POST' || url !== managementPath) {
if (
request.method !== 'POST' ||
!managementPaths.has(url as ClusterAuthenticatedManagementPath)
) {
throw new HttpRequestError(404, 'not_found');
}
if (availability !== 'ready') {