diff --git a/README.md b/README.md index b29410ae..ec3e7416 100644 --- a/README.md +++ b/README.md @@ -786,6 +786,7 @@ See [`docs/robot-quickstart.md`](./docs/robot-quickstart.md) for the full 4-step ## Reference & Docs +- [International DingTalk (`.io`) guide](./docs/international-region-guide.md) — international login, domestic/international profile switching, isolated testing, and troubleshooting - [Command Index](./docs/command-index.md) — every runtime command with description and when-to-use guidance - [Reference](./docs/reference.md) — environment variables, exit codes, output formats, shell completion - [Architecture](./docs/architecture.md) — static endpoint pipeline, command surface, transport layer diff --git a/README_zh.md b/README_zh.md index b61cb62d..e47544a4 100644 --- a/README_zh.md +++ b/README_zh.md @@ -777,6 +777,7 @@ dws dev connect --channel auto --robot-client-id --robot-client-secret \ + --client-secret +``` + +This mode still requires the user to complete OAuth authorization in a browser; it is not a userless `client_credentials` login. The application must be configured on the international developer platform with the required callback and permissions. Never commit an AppSecret to source control or include it in logs. + +## Verify the login + +```bash +dws auth status --format json +dws profile list --format json +dws contact user get-self +``` + +The last command is a read-only smoke check. If the organization has not enabled CLI access, an organization administrator must enable it or approve the access request on the international developer platform. + +## Use domestic and international profiles together + +```bash +# Domestic (.com) +dws auth login + +# International (.io) +dws auth login --intl + +# Find the stable profile selectors +dws profile list --format json +``` + +Persistently switch profiles: + +```bash +dws profile switch : +``` + +Toggle back to the previous profile: + +```bash +dws profile switch - +``` + +Select a profile for one command without changing the default: + +```bash +dws --profile : contact user get-self +``` + +Do not add `--intl` to business commands. DWS routes official endpoints from the selected profile's Token region. + +## Isolated smoke testing + +Use a separate configuration directory to avoid changing the normal `~/.dws` login state: + +```bash +DWS_CONFIG_DIR=/tmp/dws-intl-smoke ./dws auth login --intl +DWS_CONFIG_DIR=/tmp/dws-intl-smoke ./dws auth status --format json +DWS_CONFIG_DIR=/tmp/dws-intl-smoke ./dws contact user get-self +``` + +Use the same `DWS_CONFIG_DIR` for every command. Use `./dws` for a source build and `dws` for an installed release. + +## Pre-release overrides (maintainers only) + +Normal international users need only `--intl`; they should not set `--pre-url` or `--mcp-url`. + +Maintainers can test the pre-release login/MCP pair with: + +```bash +dws auth login --intl --pre-url https://pre-login.dingtalk.io +``` + +A corresponding `pre-mcp.*` URL is also accepted, and DWS derives the paired `pre-login.*` / `pre-mcp.*` bases. `--mcp-url` explicitly overrides the MCP base URL for that login. + +Pre-release services may require internal network access or allowlisted accounts. `--pre-url` is intended primarily for the MCP-managed credential flow. Do not combine it with direct custom `--client-id/--client-secret` mode unless the pre-release API contract explicitly supports that combination. + +## Troubleshooting + +### The browser still opens a `.com` page + +1. Run `dws auth login --help` and confirm `--intl` is present. +2. For a source checkout, use `./dws` instead of an older installed binary. +3. Confirm the executed command is `dws auth login --intl`. + +### A business command appears to use the wrong region + +Run `dws profile list --format json`, then switch with the exact `:` selector or use the global `--profile` option. For a legacy Token created before region metadata existed, reauthorize it with `dws auth login --intl` for an international account or `dws auth login` for a domestic account. + +### Login succeeds but the command reports missing permission + +This normally means the organization has not enabled CLI access or the application lacks a required permission. It does not by itself indicate a region-routing failure. + +### Should I edit `~/.dws/mcp_url` manually? + +No. Normal users should establish the login with `dws auth login` or `dws auth login --intl`. DWS then routes official endpoints from the selected Token/profile. Manual configuration is reserved for maintainers who explicitly control the target environment. + +## Command reference + +| Scenario | Command | +|---|---| +| Domestic browser login | `dws auth login` | +| International browser login | `dws auth login --intl` | +| International device login | `dws auth login --intl --device` | +| Check auth state | `dws auth status --format json` | +| List profiles | `dws profile list --format json` | +| Persistently switch profile | `dws profile switch :` | +| Toggle to previous profile | `dws profile switch -` | +| Select a profile once | `dws --profile : ` | diff --git a/docs/international-region-guide.zh-CN.md b/docs/international-region-guide.zh-CN.md new file mode 100644 index 00000000..8ad9d3ac --- /dev/null +++ b/docs/international-region-guide.zh-CN.md @@ -0,0 +1,185 @@ +# DWS 国际版(DingTalk `.io`)使用手册 + +本手册适用于使用钉钉国际版账号登录并调用国际站服务的用户。 + +## 核心规则 + +- `dws auth login --intl` 创建或刷新国际版登录,使用 `*.dingtalk.io` 登录、鉴权和 MCP 服务。 +- 不传 `--intl` 时仍使用国内钉钉 `*.dingtalk.com`,原有链路保持不变。 +- `--intl` 只用于登录命令。登录完成后,`contact`、`calendar`、`doc` 等业务命令不需要再传该参数。 +- 每个 Token 会记录登录区域。执行业务命令时,DWS 根据当前或 `--profile` 指定的账号自动选择 `.com` 或 `.io` 网关。 +- `--international` 是 `--intl` 的兼容别名;新脚本推荐使用较短的 `--intl`。 + +## 确认当前版本支持国际版 + +运行: + +```bash +dws auth login --help +``` + +帮助中应包含: + +```text +--intl +--international +``` + +从源码分支验证时,先在仓库根目录构建,并始终使用本次构建的 `./dws`,避免误用系统中已安装的旧版本: + +```bash +make build +./dws auth login --help +``` + +## 国际版登录 + +### 浏览器登录 + +```bash +dws auth login --intl +``` + +DWS 会打开国际版登录页面。完成扫码或账号授权后,登录结果会保存为本机 profile。 + +### 设备码登录 + +适用于 SSH、容器或没有可用浏览器的环境: + +```bash +dws auth login --intl --device +``` + +按照终端提示,在另一台可打开浏览器的设备上完成授权。 + +### 使用自有应用凭证完成用户 OAuth + +```bash +dws auth login --intl \ + --client-id \ + --client-secret +``` + +该模式仍然需要用户在浏览器中完成 OAuth 授权,不是无用户授权的 `client_credentials` 登录。应用必须在国际版开放平台正确配置回调地址和所需权限。不要在命令历史、日志或 PR 中提交真实的 AppSecret。 + +## 验证登录和业务调用 + +查看当前登录状态: + +```bash +dws auth status --format json +``` + +列出本机全部账号并找到当前 profile: + +```bash +dws profile list --format json +``` + +执行一个只读命令验证国际链路,例如: + +```bash +dws contact user get-self +``` + +登录状态正常但业务命令提示组织未开通 CLI 时,需要由国际版组织管理员在国际版开发者平台开启 CLI 访问或完成授权审批。 + +## 国内版和国际版账号并存 + +可以在同一台机器上分别登录国内版和国际版账号: + +```bash +# 国内版(.com) +dws auth login + +# 国际版(.io) +dws auth login --intl + +# 查看稳定的 profile 选择器 +dws profile list --format json +``` + +持久切换账号: + +```bash +dws profile switch : +``` + +切回上一个账号: + +```bash +dws profile switch - +``` + +只为单次命令指定账号,不修改默认账号: + +```bash +dws --profile : contact user get-self +``` + +DWS 会按照选中 profile 的 Token 区域自动选择 `.com` 或 `.io`,不需要在业务命令上追加 `--intl`。 + +## 使用独立配置目录进行验证 + +如果不希望测试登录影响日常使用的 `~/.dws`,可以指定独立配置目录: + +```bash +DWS_CONFIG_DIR=/tmp/dws-intl-smoke ./dws auth login --intl +DWS_CONFIG_DIR=/tmp/dws-intl-smoke ./dws auth status --format json +DWS_CONFIG_DIR=/tmp/dws-intl-smoke ./dws contact user get-self +``` + +请在三条命令中使用同一个 `DWS_CONFIG_DIR`。验证源码分支时使用 `./dws`;验证已安装版本时可改为 `dws`。 + +## 预发参数(仅维护者) + +普通国际版用户只需要 `--intl`,不要配置 `--pre-url` 或 `--mcp-url`。 + +维护者验证预发登录/MCP 链路时可以使用: + +```bash +dws auth login --intl --pre-url https://pre-login.dingtalk.io +``` + +也可以传入对应的 `pre-mcp.*` 地址;DWS 会推导配套的 `pre-login.*` / `pre-mcp.*` 地址。`--mcp-url` 用于显式覆盖本次登录的 MCP base URL。 + +预发环境可能只对内网或特定测试账号开放。`--pre-url` 主要服务于 MCP 托管凭证登录流程;除非预发 API 契约已经明确支持,否则不要把它与自有 `--client-id/--client-secret` 直连模式组合使用。 + +## 常见问题 + +### 仍然打开 `.com` 登录页面 + +1. 运行 `dws auth login --help`,确认当前二进制包含 `--intl`。 +2. 从源码验证时使用 `./dws`,不要误用 PATH 中的旧版本。 +3. 确认实际执行的是 `dws auth login --intl`,而不是普通 `dws auth login`。 + +### 业务命令似乎使用了错误区域 + +先检查当前账号: + +```bash +dws profile list --format json +``` + +然后使用精确的 `:` 切换或通过全局 `--profile` 单次指定。对于在区域字段引入前生成的历史 Token,建议使用正确的登录方式重新授权:国际账号执行 `dws auth login --intl`,国内账号执行 `dws auth login`。 + +### 登录成功但提示没有权限 + +这通常是组织 CLI 准入或应用授权问题,不代表区域路由失败。请确认目标组织已开启 CLI 访问,并且当前应用拥有命令所需权限。 + +### 是否需要手工修改 `~/.dws/mcp_url` + +不需要。正常使用应通过 `dws auth login` 或 `dws auth login --intl` 建立登录态;业务命令会根据选中的 Token/profile 自动路由。手工修改配置只适用于明确了解目标环境的维护者调试场景。 + +## 命令速查 + +| 场景 | 命令 | +|---|---| +| 国内版浏览器登录 | `dws auth login` | +| 国际版浏览器登录 | `dws auth login --intl` | +| 国际版设备码登录 | `dws auth login --intl --device` | +| 查看登录状态 | `dws auth status --format json` | +| 查看所有账号 | `dws profile list --format json` | +| 持久切换账号 | `dws profile switch :` | +| 切回上一个账号 | `dws profile switch -` | +| 单次指定账号 | `dws --profile : ` | diff --git a/internal/app/auth_command.go b/internal/app/auth_command.go index 508c4836..07e58d9b 100644 --- a/internal/app/auth_command.go +++ b/internal/app/auth_command.go @@ -113,12 +113,17 @@ func newAuthLoginCommand(patCaller edition.ToolCaller) *cobra.Command { 支持的登录方式: - OAuth Loopback 流 (默认): 本机自动起 127.0.0.1 监听接收回调,浏览器授权后自动完成 - OAuth 设备流 (--device): 显示 user_code + 短 URL,适合 SSH 远程 / 容器 / 无头环境 + - 自有应用 OAuth (--client-id/--client-secret): 使用指定应用完成用户授权 - 直接提供 Token (--token): 跳过授权,使用已有 token 不支持的登录方式: - 邮箱/密码登录 - 手机号/验证码登录 - - 应用凭证 (AppKey/AppSecret) 直接登录 + - 无用户授权的纯应用凭证 (client_credentials) 登录 + +区域: + - 默认使用国内钉钉 .com 登录与服务端点 + - --intl(或 --international)使用国际版 .io 登录;后续业务命令按所选 profile 自动路由 注意: SSH 远程或无头环境(无本地浏览器可访问远端的 127.0.0.1)请使用 --device, 否则 OAuth 回调会跳到本机不可达的 127.0.0.1 链接,授权完成后无法回写 token。 @@ -126,7 +131,7 @@ func newAuthLoginCommand(patCaller edition.ToolCaller) *cobra.Command { 示例: dws auth login # 本机登录并新增/刷新一个组织 profile dws auth login --profile # 指定本次授权目标组织,不持久切换当前组织 - dws auth login --intl # 使用钉钉国际登录入口 + dws auth login --intl # 使用钉钉国际版 .io 登录入口 dws auth login --intl --pre-url https://pre-login.dingtalk.io dws auth login --intl --pre-url https://pre-mcp.dingtalk.io dws auth login --recommend # 无交互批量授权服务端推荐权限 @@ -318,8 +323,8 @@ func newAuthLoginCommand(patCaller edition.ToolCaller) *cobra.Command { } cmd.Flags().String("token", "", "Access token") cmd.Flags().Bool("device", false, "Use device authorization flow") - cmd.Flags().Bool("intl", false, "Use DingTalk international login") - cmd.Flags().Bool("international", false, "Use DingTalk international login") + cmd.Flags().Bool("intl", false, "Use DingTalk international (.io) login and service endpoints") + cmd.Flags().Bool("international", false, "Use DingTalk international (.io) login and service endpoints") cmd.Flags().String("pre-url", "", "Override pre-release login/MCP base URL for this login") cmd.Flags().String("mcp-url", "", "Override MCP base URL for this login") cmd.Flags().Bool("force", false, "兼容保留;login 默认已忽略缓存并进入授权流程")