11/**
2- * Self-contained Bailian console login: the plugin speaks the console's
3- * callback protocol itself instead of shelling out to `bl auth login --console`.
2+ * Self-contained Bailian console login: the plugin drives the console's browser
3+ * login itself and persists what comes back, rather than shelling out to the
4+ * `bl` CLI.
45 *
5- * Why not the CLI: it hard-codes `needApiKey: !hasApiKey`, so once any api key
6- * is stored it never asks the console to issue a fresh one — you end up pairing
7- * an old account's key with a new account's workspace id, and nothing warns
8- * you. Driving the flow here lets us always pass `needapikey=true`, so the key
9- * and the workspace id both come from the account that just signed in, and the
10- * values land straight in the dsh stores without transiting the CLI's
11- * `~/.bailian/config.json`.
6+ * Driving the flow here lets it always request a freshly issued api key, so the
7+ * key and the workspace id both come from the account that just signed in, and
8+ * the values land straight in the dsh stores.
129 *
13- * Protocol (mirrors the CLI's implementation): bind a loopback-only port, open
14- * `<console>/console-login?notice=127.0.0.1:<port>?state=<state>&needapikey=true`,
15- * then accept one callback carrying the credentials as query parameters or a
16- * JSON / form-encoded body. Note the URL shape: `state` is part of the `notice`
17- * value (separated by `?`), not a sibling query parameter.
10+ * Shape of the flow: bind a loopback-only port, open the console login page
11+ * pointed at that port, then accept one callback carrying the credentials as
12+ * query parameters or a JSON / form-encoded body.
1813 */
1914
2015import { execFile } from "node:child_process" ;
@@ -30,12 +25,12 @@ const CONSOLE_ORIGINS: Record<string, string> = {
3025/** How long the loopback listener waits for the browser callback. */
3126const LOGIN_TIMEOUT_MS = 15 * 60 * 1000 ;
3227
33- /** Upper bound on a callback body, matching the CLI's limit . */
28+ /** Upper bound on a callback body. */
3429const MAX_CALLBACK_BODY = 65536 ;
3530
3631/** Credentials the console callback can carry. */
3732export interface ConsoleLoginCredentials {
38- /** Freshly issued DashScope api key (`needapikey=true` asks for one) . */
33+ /** Freshly issued DashScope api key. */
3934 apiKey ?: string ;
4035 /** Workspace id of the account that signed in. */
4136 workspaceId ?: string ;
@@ -95,8 +90,8 @@ function readBody(req: http.IncomingMessage): Promise<string> {
9590
9691/**
9792 * Parse a callback body as JSON (optionally wrapped in `data`) or as form
98- * encoding. Content-type is a hint only — the CLI falls back to trying both,
99- * and so do we, because the console has shipped both shapes .
93+ * encoding. Content-type is a hint only: both shapes occur in practice, so both
94+ * are attempted .
10095 * @param raw - the raw request body.
10196 * @returns the flattened fields; an unparseable body yields no fields.
10297 */
@@ -278,8 +273,8 @@ export async function startConsoleLogin(opts: {
278273 return { status : "failed" , reason } ;
279274 }
280275
281- // `state` rides inside the `notice` value, and `needapikey=true` is the whole
282- // point: it makes the console issue a key for the account signing in .
276+ // Ask for a freshly issued key, so the key and the workspace id cannot end up
277+ // belonging to two different accounts .
283278 const origin =
284279 ( opts . site !== undefined ? CONSOLE_ORIGINS [ opts . site ] : undefined ) ?? CONSOLE_ORIGINS . domestic ! ;
285280 const loginUrl =
0 commit comments