qwen-code/docs
Shaojin Wen c83265ff36
feat(serve): add --token-qr escape hatch and address-only QR fallback (#12266)
* feat(serve): add --pairing-qr escape hatch and address-only QR fallback

The remote quickstart withholds the token-bearing pairing QR when the bearer
is a stable operator-supplied token and stdout is captured. The suppression
itself is right — a configured long-lived credential must not republish into
collected logs on every restart — but it was silent, had no escape hatch, and
suppressed the QR mechanism together with the secret.

Keep the default, make the withheld case self-explaining and recoverable:

- print a hint naming --pairing-qr when the token-bearing QR is suppressed
- still print an address-only QR in that case (zero marginal disclosure: the
  same URL is printed as text, and the Web Shell auth gate asks for the token)
- add --pairing-qr and the serve.pairingQr setting (honored from user, system,
  and system-defaults scopes only — a workspace file can never push the
  operator's bearer into logs); an explicit flag of either polarity wins, so
  --no-pairing-qr vetoes the setting for one run

Design: docs/design/2026-09-19-serve-pairing-qr-escape-hatch.md

* refactor(serve): rename to --token-qr and harden the QR opt-in

Address the review round on the pairing-QR escape hatch.

Rename: "pairing" already names Local Control's revocable pairing token and
its own QR, while this flag gates the remote-quickstart bearer QR that the
surrounding output calls SECRET. The flag, setting, schema key and docs are
now --token-qr / serve.tokenQr; the schema label and the standing quickstart
design record are corrected with it.

Correctness and diagnostics:

- The explicit veto is now universal — it suppresses the token QR at an
  interactive terminal and for a generated bearer too, instead of silently
  printing the credential anyway. The gate reads the veto signal, not the
  resolved boolean, so a default run (where the caller passes false for
  "nobody asked") keeps printing the QR.
- A requested QR that cannot print is reported rather than dropped: the
  unmounted Web Shell and the loopback bind each get their own stderr line,
  resolved outside the bearer check so a tokenless loopback boot is covered.
- A malformed serve.tokenQr is named on stderr by field and type — never by
  value, since settings strings go through ${VAR} substitution and echoing
  one would republish a mis-keyed bearer into captured logs — and is treated
  as absent instead of aborting the whole boot settings summary, which would
  have downgraded permission mediation to its default over a display knob.
- The workspace-scope exclusion is registered in the single list that drives
  the strip, the ignored-value warning and the dialog filter, so both
  settings pipelines enforce it.

Tests pin the production-default printer shape, the veto on every path, the
two diagnostic causes, the malformed-value redaction, and the scope and
precedence rules.

* test(serve): make the tokenQr default arm hermetic to host settings (#12266)

The first sub-case of 'resolves tokenQr from opts and from boot settings'
omitted deps.bootSettings, so runQwenServe fell through to the real
loadServeFastPathSettings and read the host's operator-scope settings
files. A maintainer with serve.tokenQr: true in a user/system file got a
spurious red. Inject an empty summary so the default-false branch is
pinned independently of the host.

* fix(serve): report ignored workspace serve.tokenQr and resolve one tokenQrMode (#12266)

Address review findings on the token-QR escape hatch:

- Name a workspace-scoped serve.tokenQr on stderr instead of dropping it
  silently: the fast-path loader reports the key via a report-only
  ignoredWorkspaceKeys field and the serve boot names the drop, matching
  the warning the interactive CLI raises through getSettingsWarnings.
- Pass one resolved tokenQrMode ('policy' | 'force' | 'veto') to the
  quickstart printer instead of a tokenQr/tokenQrVetoed boolean pair whose
  two falses meant opposite things one hop apart.
- Emit the suppression hint only once a QR actually renders, so a renderer
  failure no longer pairs it with advice to pass a flag that cannot help.
- Correct the malformed-value rationale (code comment, both design docs,
  test comment): ${QWEN_SERVER_TOKEN} is denylisted and never substituted;
  the real exposure is a literal bearer or a non-denylisted placeholder.
- Make the 'stays quiet' boot arm hermetic to host system settings, and pin
  the Web-Shell-first precedence with a loopback input that detects a
  swapped branch order.
- Point the pre-existing English-only quickstart design at the paired
  escape-hatch design instead of restating the new semantics.

---------

Co-authored-by: qwen-code-dev-bot <qwen-code-dev@service.alibaba.com>
2026-09-22 10:57:21 +00:00
..
assets feat: support workspace display names (#7179) 2026-07-20 15:16:44 +00:00
design feat(serve): add --token-qr escape hatch and address-only QR fallback (#12266) 2026-09-22 10:57:21 +00:00
developers feat(serve): Add opt-in fixed ACP child heap enforcement (#12353) 2026-09-22 10:14:05 +00:00
e2e-tests refactor(core,cli): rename generic Gemini identifiers to Llm (#10124) 2026-08-28 03:05:49 +00:00
images fix(web-shell): render built-in tag icons (#7024) 2026-07-17 15:33:34 +00:00
plans feat(core,docs): add conditional extension rules and cap context warnings (#12034) 2026-09-20 11:20:54 +00:00
superpowers feat(cli): reference prior sessions via @ and add completion tabs (#7302) 2026-07-24 06:11:48 +00:00
users feat(serve): add --token-qr escape hatch and address-only QR fallback (#12266) 2026-09-22 10:57:21 +00:00
verification feat(core,docs): add conditional extension rules and cap context warnings (#12034) 2026-09-20 11:20:54 +00:00
_meta.ts feat: refactor docs 2025-12-05 10:51:57 +08:00
index.md fix: lint issues 2025-12-19 15:52:11 +08:00