feat(ql3): add bounded copilot product client

This commit is contained in:
whyour
2026-08-16 02:15:21 +08:00
parent e5a3d83a8d
commit 0e85cbdeb6
12 changed files with 2123 additions and 11 deletions
@@ -0,0 +1,639 @@
const assert = require('node:assert/strict');
const { spawn } = require('node:child_process');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const { test } = require('node:test');
const { createServer } = require('node:https');
const packageRoot = path.resolve(__dirname, '..');
const cliPath = path.join(packageRoot, 'dist', 'copilot-client', 'cli.js');
const fixtureRoot = path.resolve(
packageRoot,
'../ql3-cluster-control/test/fixtures/mtls',
);
const caFixture = path.join(fixtureRoot, 'ca-cert.pem');
const certificateFixture = path.join(fixtureRoot, 'server-cert.pem');
const privateKeyFixture = path.join(fixtureRoot, 'server-key.pem');
const {
CLUSTER_COPILOT_CLIENT_CONFIG_SCHEMA,
ClusterCopilotClientRemoteError,
executeClusterCopilotClient,
probeClusterCopilotClientReadiness,
validateClusterCopilotClientConfiguration,
} = require('../dist/copilot-client/client.js');
const {
CLUSTER_COPILOT_CLIENT_COMMAND_SCHEMA,
CLUSTER_COPILOT_FAILURE_DIAGNOSIS_CANCELLATION_RESPONSE_SCHEMA,
CLUSTER_COPILOT_FAILURE_DIAGNOSIS_INSPECTION_RESPONSE_SCHEMA,
CLUSTER_COPILOT_FAILURE_DIAGNOSIS_OUTPUT_READ_RESPONSE_SCHEMA,
CLUSTER_COPILOT_FAILURE_DIAGNOSIS_REQUEST_SCHEMA,
CLUSTER_COPILOT_FAILURE_DIAGNOSIS_RESPONSE_SCHEMA,
normalizeClusterCopilotClientCommand,
prepareClusterCopilotClientRequest,
validateClusterCopilotClientResponse,
} = require('../dist/copilot-client/contracts.js');
const credential = `ql3c_credential-1_${Buffer.alloc(32, 7).toString('base64url')}`;
const baseCommand = {
schema: CLUSTER_COPILOT_CLIENT_COMMAND_SCHEMA,
projectId: 'project-1',
sourceRunId: 'source-run-1',
requestId: 'diagnosis-request-1',
};
function privateFile(directory, name, contents) {
const filePath = path.join(directory, name);
fs.writeFileSync(filePath, contents, { mode: 0o600 });
return fs.realpathSync(filePath);
}
function temporaryDirectory(t) {
const directory = fs.realpathSync(
fs.mkdtempSync(path.join(os.tmpdir(), 'ql3-copilot-client-')),
);
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
return directory;
}
function configuration(directory, port) {
const caFile = privateFile(
directory,
'ca.pem',
fs.readFileSync(caFixture),
);
return privateFile(
directory,
'client.json',
JSON.stringify({
schema: CLUSTER_COPILOT_CLIENT_CONFIG_SCHEMA,
endpoint: `https://localhost:${port}/`,
servername: 'localhost',
caFile,
requestTimeoutMs: 2_000,
}),
);
}
function commandFile(directory, name, operation, extra = {}) {
return privateFile(
directory,
`${name}.json`,
JSON.stringify({ ...baseCommand, operation, ...extra }),
);
}
function jsonResponse(response, statusCode, requestId, body, headers = {}) {
const bytes = Buffer.from(JSON.stringify(body));
response.writeHead(statusCode, {
'content-type': 'application/json; charset=utf-8',
'content-length': String(bytes.length),
...(requestId === null ? {} : { 'x-request-id': requestId }),
...headers,
});
response.end(bytes);
}
async function startServer(handler) {
const server = createServer(
{
key: fs.readFileSync(privateKeyFixture),
cert: fs.readFileSync(certificateFixture),
minVersion: 'TLSv1.3',
maxVersion: 'TLSv1.3',
},
handler,
);
await new Promise((resolvePromise, reject) => {
server.once('error', reject);
server.listen(0, '127.0.0.1', resolvePromise);
});
return {
port: server.address().port,
close: () =>
new Promise((resolvePromise, reject) => {
server.close((error) =>
error ? reject(error) : resolvePromise(),
);
}),
};
}
function runCli(args) {
return new Promise((resolvePromise, reject) => {
const child = spawn(process.execPath, [cliPath, ...args], {
cwd: packageRoot,
stdio: ['ignore', 'pipe', 'pipe'],
});
const stdout = [];
const stderr = [];
child.stdout.on('data', (chunk) => stdout.push(chunk));
child.stderr.on('data', (chunk) => stderr.push(chunk));
child.once('error', reject);
child.once('close', (status, signal) => {
resolvePromise({
status,
signal,
stdout: Buffer.concat(stdout).toString('utf8'),
stderr: Buffer.concat(stderr).toString('utf8'),
});
});
});
}
function diagnoseResponse(overrides = {}) {
return {
schema: CLUSTER_COPILOT_FAILURE_DIAGNOSIS_RESPONSE_SCHEMA,
requestId: baseCommand.requestId,
status: 'created',
replayed: false,
sourceRunId: baseCommand.sourceRunId,
diagnosisRunId: 'diagnosis-run-1',
outcome: 'succeeded',
stage: 'model',
reason: null,
outputArtifact: {
artifactId: 'cdo:artifact-1',
artifactDigest: 'a'.repeat(64),
},
...overrides,
};
}
function inspectionResponse(overrides = {}) {
return {
schema: CLUSTER_COPILOT_FAILURE_DIAGNOSIS_INSPECTION_RESPONSE_SCHEMA,
status: 'running',
projectId: baseCommand.projectId,
sourceRunId: baseCommand.sourceRunId,
requestId: baseCommand.requestId,
diagnosisRunId: 'diagnosis-run-1',
outcome: null,
stage: null,
reason: null,
outputAvailable: false,
admittedAtMs: 100,
finalizedAtMs: null,
usage: null,
...overrides,
};
}
function outputResponse() {
return {
schema: CLUSTER_COPILOT_FAILURE_DIAGNOSIS_OUTPUT_READ_RESPONSE_SCHEMA,
status: 'available',
projectId: baseCommand.projectId,
sourceRunId: baseCommand.sourceRunId,
requestId: baseCommand.requestId,
diagnosisRunId: 'diagnosis-run-1',
reference: {
artifactId: 'cdo:artifact-1',
artifactDigest: 'a'.repeat(64),
contentDigest: 'b'.repeat(64),
outputBytes: Buffer.byteLength('diagnosis'),
sealedAtMs: 200,
},
result: {
text: 'diagnosis',
finishReason: 'stop',
usage: { inputTokens: 3, outputTokens: 2, totalTokens: 5 },
},
};
}
function cancellationResponse() {
return {
schema: CLUSTER_COPILOT_FAILURE_DIAGNOSIS_CANCELLATION_RESPONSE_SCHEMA,
status: 'accepted',
convergence: 'terminal',
projectId: baseCommand.projectId,
sourceRunId: baseCommand.sourceRunId,
requestId: baseCommand.requestId,
diagnosisRunId: 'diagnosis-run-1',
runStatus: 'cancelled',
outcome: 'cancelled',
runVersion: 7,
eventSequence: 7,
cancelRequestedAtMs: 500,
cancelReason: 'user',
};
}
test('normalizes only the four bounded commands and derives exact requests', () => {
const commands = [
{ ...baseCommand, operation: 'diagnose', traceId: 'trace-1' },
{ ...baseCommand, operation: 'inspect' },
{ ...baseCommand, operation: 'output' },
{
...baseCommand,
operation: 'cancel',
mutationId: '11111111-1111-4111-8111-111111111111',
},
];
for (const command of commands) {
const normalized = normalizeClusterCopilotClientCommand(command);
assert.deepEqual(normalized, command);
assert.equal(Object.isFrozen(normalized), true);
}
assert.deepEqual(prepareClusterCopilotClientRequest(commands[0]), {
method: 'POST',
path: '/api/v3/projects/project-1/runs/source-run-1/copilot/failure-diagnoses',
requestId: baseCommand.requestId,
body: {
schema: CLUSTER_COPILOT_FAILURE_DIAGNOSIS_REQUEST_SCHEMA,
traceId: 'trace-1',
},
acceptedStatusCodes: [200, 201],
});
assert.deepEqual(
prepareClusterCopilotClientRequest(commands[2], 'transport-read-1'),
{
method: 'GET',
path: '/api/v3/projects/project-1/runs/source-run-1/copilot/failure-diagnoses/diagnosis-request-1/output',
requestId: 'transport-read-1',
body: null,
acceptedStatusCodes: [200],
},
);
assert.throws(() =>
normalizeClusterCopilotClientCommand({ ...commands[0], model: 'private' }),
);
assert.throws(() =>
prepareClusterCopilotClientRequest(commands[1], '../invalid'),
);
});
test('validates exact target-bound response state for every operation', () => {
const diagnose = { ...baseCommand, operation: 'diagnose', traceId: 'trace-1' };
const inspect = { ...baseCommand, operation: 'inspect' };
const output = { ...baseCommand, operation: 'output' };
const cancel = {
...baseCommand,
operation: 'cancel',
mutationId: '11111111-1111-4111-8111-111111111111',
};
assert.equal(
validateClusterCopilotClientResponse(diagnoseResponse(), diagnose).status,
'created',
);
assert.equal(
validateClusterCopilotClientResponse(inspectionResponse(), inspect).status,
'running',
);
assert.equal(
validateClusterCopilotClientResponse(
inspectionResponse({
status: 'terminal',
outcome: 'succeeded',
stage: 'model',
outputAvailable: true,
finalizedAtMs: 200,
usage: {
inputTokens: 3,
outputTokens: 2,
totalTokens: 5,
currency: 'USD',
costMicros: 7,
},
}),
inspect,
).status,
'terminal',
);
assert.equal(
validateClusterCopilotClientResponse(outputResponse(), output).result.text,
'diagnosis',
);
assert.equal(
validateClusterCopilotClientResponse(cancellationResponse(), cancel)
.status,
'accepted',
);
assert.equal(
validateClusterCopilotClientResponse(
diagnoseResponse({ status: 'existing', replayed: true }),
diagnose,
).replayed,
true,
);
assert.equal(
validateClusterCopilotClientResponse(
{
...cancellationResponse(),
status: 'already_requested',
convergence: 'model_in_flight',
runStatus: 'running',
outcome: null,
runVersion: 6,
eventSequence: 6,
},
cancel,
).convergence,
'model_in_flight',
);
assert.throws(() =>
validateClusterCopilotClientResponse(
diagnoseResponse({ schema: 'qinglong/drift@v1' }),
diagnose,
),
);
assert.throws(() =>
validateClusterCopilotClientResponse(
diagnoseResponse({ projectId: 'widened' }),
diagnose,
),
);
assert.throws(() =>
validateClusterCopilotClientResponse(
inspectionResponse({ projectId: 'other-project' }),
inspect,
),
);
const invalidOutput = outputResponse();
invalidOutput.reference.outputBytes += 1;
assert.throws(() =>
validateClusterCopilotClientResponse(invalidOutput, output),
);
assert.throws(() =>
validateClusterCopilotClientResponse(
cancellationResponse(),
{ ...cancel, requestId: 'other-request' },
),
);
});
test('uses TLS 1.3, Bearer credential and exact request identities end to end', async (t) => {
const seen = [];
const server = await startServer((request, response) => {
const chunks = [];
request.on('data', (chunk) => chunks.push(chunk));
request.on('end', () => {
const body = Buffer.concat(chunks).toString('utf8');
seen.push({
method: request.method,
url: request.url,
authorization: request.headers.authorization,
requestId: request.headers['x-request-id'],
body: body === '' ? null : JSON.parse(body),
peerCertificate: request.socket.getPeerCertificate(),
});
const requestId = request.headers['x-request-id'];
if (request.url === '/readyz') {
assert.equal(request.headers.authorization, undefined);
jsonResponse(response, 200, null, { status: 'ready' });
} else if (request.method === 'POST' && request.url.endsWith('/cancellation')) {
jsonResponse(response, 202, requestId, cancellationResponse());
} else if (request.method === 'POST') {
jsonResponse(response, 201, requestId, diagnoseResponse());
} else if (request.url.endsWith('/output')) {
jsonResponse(response, 200, requestId, outputResponse());
} else {
jsonResponse(response, 200, requestId, inspectionResponse());
}
});
});
t.after(() => server.close());
const directory = temporaryDirectory(t);
const configFile = configuration(directory, server.port);
const credentialFile = privateFile(directory, 'credential', credential);
assert.deepEqual(validateClusterCopilotClientConfiguration(configFile), {
schemaVersion: 1,
transport: 'https',
clientCertificate: 'forbidden',
});
assert.deepEqual(await probeClusterCopilotClientReadiness(configFile), {
schemaVersion: 1,
transport: 'https',
ready: true,
});
const operations = [
['diagnose', { traceId: 'trace-1' }, baseCommand.requestId],
['inspect', {}, 'transport-read-1'],
['output', {}, 'transport-read-2'],
[
'cancel',
{ mutationId: '11111111-1111-4111-8111-111111111111' },
'11111111-1111-4111-8111-111111111111',
],
];
for (const [operation, extra, expectedRequestId] of operations) {
const result = await executeClusterCopilotClient(
{
configFile,
commandFile: commandFile(directory, operation, operation, extra),
credentialFile,
},
{ createRequestId: () => expectedRequestId },
);
assert.equal(result.operation, operation);
assert.equal(result.requestId, expectedRequestId);
}
assert.equal(seen.length, 5);
for (const request of seen.slice(1)) {
assert.equal(request.authorization, `Bearer ${credential}`);
assert.equal(request.peerCertificate.subject, undefined);
}
assert.deepEqual(seen[1].body, {
schema: CLUSTER_COPILOT_FAILURE_DIAGNOSIS_REQUEST_SCHEMA,
traceId: 'trace-1',
});
assert.equal(seen[2].body, null);
assert.equal(seen[3].body, null);
assert.deepEqual(seen[4].body, {
schema: 'qinglong/run-cancellation@v1',
mutationId: '11111111-1111-4111-8111-111111111111',
});
});
test('fails closed on weak files, request-id drift and low-sensitive remote errors', async (t) => {
let mode = 'readiness-drift';
const server = await startServer((request, response) => {
request.resume();
request.on('end', () => {
if (mode === 'readiness-drift') {
jsonResponse(response, 200, null, { status: 'ready', widened: true });
return;
}
if (mode === 'drift') {
jsonResponse(response, 201, 'wrong-request', diagnoseResponse());
return;
}
jsonResponse(
response,
429,
request.headers['x-request-id'],
{ code: 'copilot_rate_limited', reason: 'private detail' },
{ 'retry-after': '30' },
);
});
});
t.after(() => server.close());
const directory = temporaryDirectory(t);
const configFile = configuration(directory, server.port);
const command = commandFile(directory, 'diagnose', 'diagnose', {
traceId: 'trace-1',
});
const credentialFile = privateFile(directory, 'credential', credential);
const paths = { configFile, commandFile: command, credentialFile };
await assert.rejects(probeClusterCopilotClientReadiness(configFile), {
code: 'QL3_CLUSTER_COPILOT_CLIENT_REQUEST_FAILED',
});
mode = 'drift';
await assert.rejects(executeClusterCopilotClient(paths), {
code: 'QL3_CLUSTER_COPILOT_CLIENT_REQUEST_FAILED',
});
mode = 'remote';
await assert.rejects(
executeClusterCopilotClient(paths),
(error) => {
assert.equal(error instanceof ClusterCopilotClientRemoteError, true);
assert.equal(error.statusCode, 429);
assert.equal(error.responseCode, 'copilot_rate_limited');
assert.equal(error.requestId, baseCommand.requestId);
assert.equal(error.retryAfterSeconds, 30);
assert.equal(JSON.stringify(error).includes('private detail'), false);
return true;
},
);
const cli = await runCli([
`--config=${configFile}`,
`--command=${command}`,
`--credential=${credentialFile}`,
]);
assert.equal(cli.status, 1);
assert.equal(cli.stdout, '');
assert.deepEqual(JSON.parse(cli.stderr), {
schemaVersion: 1,
component: 'qinglong3-cluster-copilot-client',
event: 'command_failed',
code: 'QL3_CLUSTER_COPILOT_CLIENT_REMOTE_REJECTED',
statusCode: 429,
responseCode: 'copilot_rate_limited',
requestId: baseCommand.requestId,
retryAfterSeconds: 30,
});
assert.equal(cli.stderr.includes(credential), false);
assert.equal(cli.stderr.includes('private detail'), false);
assert.equal(cli.stderr.includes(directory), false);
fs.chmodSync(credentialFile, 0o644);
await assert.rejects(executeClusterCopilotClient(paths), {
code: 'QL3_CLUSTER_COPILOT_CLIENT_CONFIG_INVALID',
});
});
test('CLI help, usage and explicit output success remain deterministic', async (t) => {
const help = await runCli(['--help']);
assert.equal(help.status, 0);
assert.match(help.stdout, /^Usage: ql3-copilot-client /);
assert.equal(help.stderr, '');
const usage = await runCli([]);
assert.equal(usage.status, 64);
assert.equal(usage.stdout, '');
assert.equal(
JSON.parse(usage.stderr).code,
'QL3_CLUSTER_COPILOT_CLIENT_USAGE_INVALID',
);
const server = await startServer((request, response) => {
request.resume();
request.on('end', () => {
jsonResponse(
response,
200,
request.headers['x-request-id'],
outputResponse(),
);
});
});
t.after(() => server.close());
const directory = temporaryDirectory(t);
const result = await runCli([
`--config=${configuration(directory, server.port)}`,
`--command=${commandFile(directory, 'output', 'output')}`,
`--credential=${privateFile(directory, 'credential', credential)}`,
]);
assert.equal(result.status, 0, result.stderr);
assert.equal(result.stderr, '');
const fact = JSON.parse(result.stdout);
assert.equal(fact.operation, 'output');
assert.equal(fact.result.result.text, 'diagnosis');
assert.equal(fact.component, 'qinglong3-cluster-copilot-client');
});
test('rejects response framing drift, oversized bodies, aborts and timeouts', async (t) => {
let mode = 'content-type';
const server = await startServer((request, response) => {
response.on('error', () => {});
request.resume();
request.on('end', () => {
if (mode === 'timeout') return;
if (mode === 'abort') {
response.writeHead(200, {
'content-type': 'application/json; charset=utf-8',
'x-request-id': request.headers['x-request-id'],
});
response.write('{"schema":');
response.destroy();
return;
}
if (mode === 'oversized') {
response.writeHead(200, {
'content-type': 'application/json; charset=utf-8',
'x-request-id': request.headers['x-request-id'],
});
response.end(Buffer.alloc(2 * 1024 * 1024 + 1, 0x20));
return;
}
const body = Buffer.from(JSON.stringify(diagnoseResponse()));
response.writeHead(201, {
'content-type': 'text/plain',
'content-length': String(body.length),
'x-request-id': request.headers['x-request-id'],
});
response.end(body);
});
});
t.after(() => server.close());
const directory = temporaryDirectory(t);
const caFile = privateFile(
directory,
'ca.pem',
fs.readFileSync(caFixture),
);
const configFile = privateFile(
directory,
'client.json',
JSON.stringify({
schema: CLUSTER_COPILOT_CLIENT_CONFIG_SCHEMA,
endpoint: `https://localhost:${server.port}/`,
servername: 'localhost',
caFile,
requestTimeoutMs: 1_000,
}),
);
const paths = {
configFile,
commandFile: commandFile(directory, 'diagnose', 'diagnose', {
traceId: 'trace-1',
}),
credentialFile: privateFile(directory, 'credential', credential),
};
for (const failureMode of [
'content-type',
'oversized',
'abort',
'timeout',
]) {
mode = failureMode;
await assert.rejects(executeClusterCopilotClient(paths), {
code: 'QL3_CLUSTER_COPILOT_CLIENT_REQUEST_FAILED',
});
}
});
@@ -54,6 +54,9 @@ const {
const {
validateClusterAuthenticatedManagementClientConfiguration,
} = require('../dist/management-support/pluginPackageManagementClient.js');
const {
CLUSTER_COPILOT_CLIENT_CONFIG_SCHEMA,
} = require('../dist/copilot-client/client.js');
function runCli(args) {
return spawnSync(process.execPath, [cliPath, ...args], {
@@ -121,6 +124,41 @@ async function startReadinessServer(status) {
};
}
async function startCopilotReadinessServer(status) {
const server = createServer(
{
key: fs.readFileSync(localhostPrivateKeyFixture),
cert: fs.readFileSync(localhostCertificateFixture),
minVersion: 'TLSv1.3',
maxVersion: 'TLSv1.3',
},
(request, response) => {
assert.equal(request.method, 'GET');
assert.equal(request.url, '/readyz');
assert.equal(request.headers.authorization, undefined);
const body = Buffer.from(JSON.stringify({ status: status.value }));
response.writeHead(status.value === 'ready' ? 200 : 503, {
'content-type': 'application/json; charset=utf-8',
'content-length': String(body.length),
});
response.end(body);
},
);
await new Promise((resolvePromise, reject) => {
server.once('error', reject);
server.listen(0, '127.0.0.1', resolvePromise);
});
return {
port: server.address().port,
close: () =>
new Promise((resolvePromise, reject) => {
server.close((error) =>
error ? reject(error) : resolvePromise(),
);
}),
};
}
function privateFile(directory, name, contents) {
const filePath = path.join(directory, name);
fs.writeFileSync(filePath, contents, { mode: 0o600 });
@@ -193,6 +231,17 @@ function validContextFixture(t) {
'/api/v3/plugin-packages/management',
'forbidden',
);
const copilotConfig = privateFile(
directory,
'copilot-client.json',
JSON.stringify({
schema: CLUSTER_COPILOT_CLIENT_CONFIG_SCHEMA,
endpoint: 'https://copilot.example.test:8443/',
servername: 'copilot.example.test',
caFile,
requestTimeoutMs: 1_000,
}),
);
const kubeconfigFile = privateFile(
directory,
'kubeconfig.json',
@@ -236,6 +285,7 @@ function validContextFixture(t) {
}),
);
const commands = {
copilot: { configFile: copilotConfig },
package: { configFile: packageConfig },
'package-kubernetes': { configFile: packageConfig, kubernetesFile },
'worker-credential': {
@@ -283,7 +333,7 @@ function validContextFixture(t) {
test('catalog exposes only reviewed remote clients from the same package', () => {
assert.equal(manifest.bin['ql3-cluster-admin'], 'dist/product-cli/cli.js');
assert.equal(QINGLONG3_CLUSTER_PRODUCT_COMMANDS.length, 7);
assert.equal(QINGLONG3_CLUSTER_PRODUCT_COMMANDS.length, 8);
assert.equal(
new Set(QINGLONG3_CLUSTER_PRODUCT_COMMANDS.map(({ name }) => name)).size,
QINGLONG3_CLUSTER_PRODUCT_COMMANDS.length,
@@ -324,6 +374,7 @@ test('help and version are bounded installation-derived product facts', () => {
const help = qingLong3ClusterProductHelp();
assert.match(help, /^Usage: ql3-cluster-admin <command> \[arguments\]/);
assert.match(help, /\n run\s+retry or stop Runs/);
assert.match(help, /\n copilot\s+diagnose, inspect, read or cancel Runs/);
assert.match(help, /Server, migration, recovery, executor and key-custody/);
assert.equal(help.includes('plugin-package-manage'), false);
assert.equal(
@@ -558,8 +609,9 @@ test('validates the complete operator context offline without operational author
schemaVersion: 1,
component: 'qinglong3-cluster-product-cli',
event: 'context_valid',
commandCount: 7,
commandCount: 8,
commands: [
{ name: 'copilot', transport: 'https', clientCertificate: 'forbidden' },
{ name: 'package', transport: 'https', clientCertificate: 'forbidden' },
{
name: 'package-kubernetes',
@@ -671,6 +723,68 @@ test('probes a context with fixed read-only readiness semantics and exit status'
assert.equal(fact.commands[0].status, 'not_ready');
});
test('probes Copilot context through its separate unauthenticated readiness contract', async (t) => {
const status = { value: 'ready' };
const server = await startCopilotReadinessServer(status);
t.after(() => server.close());
const directory = fs.realpathSync(
fs.mkdtempSync(path.join(os.tmpdir(), 'ql3-copilot-probe-context-')),
);
t.after(() => fs.rmSync(directory, { recursive: true, force: true }));
const caFile = privateFile(
directory,
'ca.pem',
fs.readFileSync(localhostCaFixture),
);
const configFile = privateFile(
directory,
'copilot.json',
JSON.stringify({
schema: CLUSTER_COPILOT_CLIENT_CONFIG_SCHEMA,
endpoint: `https://localhost:${server.port}/`,
servername: 'localhost',
caFile,
requestTimeoutMs: 1_000,
}),
);
const contextFile = privateFile(
directory,
'operator-context.json',
JSON.stringify({
schemaVersion: 1,
commands: { copilot: { configFile } },
}),
);
const ready = await runCliAsync([
'context',
'probe',
`--context=${contextFile}`,
]);
assert.equal(ready.status, 0, ready.stderr);
assert.equal(ready.stderr, '');
assert.deepEqual(JSON.parse(ready.stdout), {
schemaVersion: 1,
component: 'qinglong3-cluster-product-cli',
event: 'context_probed',
commandCount: 1,
commands: [{ name: 'copilot', transport: 'https', status: 'ready' }],
allReady: true,
requestMethod: 'GET',
requestPath: '/readyz',
mutation: false,
});
status.value = 'not_ready';
const notReady = await runCliAsync([
'context',
'probe',
`--context=${contextFile}`,
]);
assert.equal(notReady.status, 69);
assert.equal(JSON.parse(notReady.stdout).allReady, false);
});
test('context validation fails closed for invalid client configuration and syntax', (t) => {
const fixture = validContextFixture(t);
fs.writeFileSync(fixture.commands.run.configFile, '{}', { mode: 0o600 });