feat(device-pod-cli): v0.2 hwpod prefers HWLAB_API_KEY over legacy key
- authHeaders now reads HWLAB_API_KEY (env or --apiKey/--bearerToken) first; only when hwl_live_ prefix is present - when both are set, HWLAB_API_KEY wins and x-hwlab-device-pod-api-key is suppressed - new test asserts the precedence using a fake API key against a local http server - help auth hint updated to mention the preferred credential
This commit is contained in:
@@ -699,3 +699,44 @@ function serverUrl(server: ReturnType<typeof createServer>) {
|
||||
if (!address || typeof address === "string") throw new Error("server address is unavailable");
|
||||
return `http://127.0.0.1:${address.port}`;
|
||||
}
|
||||
|
||||
test("device-pod-cli prefers HWLAB_API_KEY over HWLAB_DEVICE_POD_API_KEY when both are set", async () => {
|
||||
const seen: any[] = [];
|
||||
const server = createServer((request, response) => {
|
||||
let chunks: Buffer[] = [];
|
||||
request.on("data", (chunk) => chunks.push(chunk));
|
||||
request.on("end", () => {
|
||||
const body = JSON.parse(Buffer.concat(chunks).toString("utf8") || "{}");
|
||||
seen.push({
|
||||
url: request.url,
|
||||
method: request.method,
|
||||
devicePodKey: request.headers["x-hwlab-device-pod-api-key"] ?? null,
|
||||
authorization: request.headers["authorization"] ?? null
|
||||
});
|
||||
response.writeHead(200, { "content-type": "application/json" });
|
||||
response.end(JSON.stringify({ ok: true, status: "ok", devicePods: [], count: 0 }));
|
||||
});
|
||||
});
|
||||
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
|
||||
try {
|
||||
const port = server.address().port;
|
||||
const result = await runDevicePodCli(["profile", "list"], {
|
||||
env: {
|
||||
HWLAB_RUNTIME_API_URL: `http://127.0.0.1:${port}`,
|
||||
HWLAB_RUNTIME_NAMESPACE: "hwlab-v02",
|
||||
HWLAB_RUNTIME_LANE: "v02",
|
||||
HWLAB_RUNTIME_ENDPOINT_LOCKED: "1",
|
||||
HWLAB_CODE_AGENT_ASSEMBLED_RUNTIME: "1",
|
||||
HWLAB_DEVICE_POD_API_KEY: "device-pod-api-key-a",
|
||||
HWLAB_API_KEY: "hwl_live_user-default-key-1234567890"
|
||||
},
|
||||
now: () => "2026-06-03T00:00:00.000Z"
|
||||
});
|
||||
assert.equal(result.exitCode, 0);
|
||||
assert.equal(seen.length, 1);
|
||||
assert.equal(seen[0].devicePodKey, null);
|
||||
assert.equal(seen[0].authorization, "Bearer hwl_live_user-default-key-1234567890");
|
||||
} finally {
|
||||
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -60,7 +60,7 @@ function help() {
|
||||
localProfileAuthority: false,
|
||||
configuration: {
|
||||
apiBaseUrl: "auto-located from assembled HWLAB_RUNTIME_* / HWLAB_DEVICE_POD_* env; manual endpoint arguments are rejected when HWLAB_RUNTIME_ENDPOINT_LOCKED=1",
|
||||
auth: "assembled HWLAB_DEVICE_POD_API_KEY for AgentRun; browser cookie or explicit user session for local debug"
|
||||
auth: "preferred HWLAB_API_KEY (hwl_live_...) for AgentRun and CLI; legacy HWLAB_DEVICE_POD_API_KEY or cookie session for transition",
|
||||
},
|
||||
usage: [
|
||||
"hwpod profile list",
|
||||
@@ -565,7 +565,10 @@ const uartJsonRpcOptionKeys = [
|
||||
];
|
||||
function defaultOperation(surface: string) { return surface === "workspace" ? "ls" : surface === "debug-probe" ? "status" : "read"; }
|
||||
async function authHeaders(parsed: ParsedArgs, env: EnvLike, endpoint: any) {
|
||||
const apiKey = text(parsed.devicePodApiKey ?? env.HWLAB_DEVICE_POD_API_KEY);
|
||||
const userApiKey = text(parsed.apiKey ?? parsed.bearerToken ?? env.HWLAB_API_KEY ?? env.HWLAB_BEARER_TOKEN);
|
||||
const legacyDevicePodApiKey = text(parsed.devicePodApiKey ?? env.HWLAB_DEVICE_POD_API_KEY);
|
||||
const useUserApiKey = userApiKey.startsWith("hwl_live_");
|
||||
const apiKey = useUserApiKey ? "" : legacyDevicePodApiKey;
|
||||
const explicitCookie = text(parsed.cookie ?? env.HWLAB_SESSION_COOKIE);
|
||||
const sessionToken = text(parsed.sessionToken ?? env.HWLAB_CLOUD_API_SESSION_TOKEN ?? env.HWLAB_SESSION_TOKEN);
|
||||
const bearer = text(parsed.bearerToken ?? env.HWLAB_BEARER_TOKEN);
|
||||
@@ -573,6 +576,7 @@ async function authHeaders(parsed: ParsedArgs, env: EnvLike, endpoint: any) {
|
||||
const cookie = explicitCookie || stateCookie;
|
||||
return clean({
|
||||
...(apiKey ? { "x-hwlab-device-pod-api-key": apiKey } : {}),
|
||||
...(useUserApiKey ? { authorization: `Bearer ${userApiKey}` } : {}),
|
||||
...(cookie ? { cookie: cookie.includes("=") ? cookie : `hwlab_session=${encodeURIComponent(cookie)}` } : {}),
|
||||
...(sessionToken ? { "x-hwlab-session-token": sessionToken } : {}),
|
||||
...(bearer ? { authorization: `Bearer ${bearer}` } : {})
|
||||
|
||||
Reference in New Issue
Block a user