@guandata/guancli 1.0.67 → 1.0.68

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Changelog
2
2
 
3
+ ## @guandata/guancli 1.0.68 - 2026-10-19
4
+
5
+ - 新增 ChatBI 报告编排的订阅查询、运行记录查询与手动触发命令,沿用现有会话认证。
6
+ - 保留报告接口原始响应,改进接口兼容、JSON 错误输出及并发读取异常反馈。
7
+
3
8
  ## @guandata/guancli 1.0.67 - 2026-10-15
4
9
 
5
10
  - 表单写入后明确提示刷新目标数据集,并区分数据刷新与字段结构同步。
package/README.md CHANGED
@@ -45,6 +45,11 @@ guancli chatbi query --theme-name "经营主题" --message "最近30天营业收
45
45
 
46
46
  ## 版本更新
47
47
 
48
+ ### @guandata/guancli 1.0.68
49
+
50
+ - 新增 ChatBI 报告编排的订阅查询、运行记录查询与手动触发命令,沿用现有会话认证。
51
+ - 保留报告接口原始响应,改进接口兼容、JSON 错误输出及并发读取异常反馈。
52
+
48
53
  ### @guandata/guancli 1.0.67
49
54
 
50
55
  - 表单写入后明确提示刷新目标数据集,并区分数据刷新与字段结构同步。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@guandata/guancli",
3
- "version": "1.0.67",
3
+ "version": "1.0.68",
4
4
  "description": "观远 BI 命令行工具 - 通过 API 操作 ETL、数据集、页面、表单等资源,并提供 ChatBI 问数/洞察能力",
5
5
  "bin": {
6
6
  "guancli": "bin/run.js"
@@ -42,11 +42,11 @@
42
42
  "node": ">=14"
43
43
  },
44
44
  "optionalDependencies": {
45
- "@guandata/guancli-darwin-arm64": "1.0.67",
46
- "@guandata/guancli-darwin-x64": "1.0.67",
47
- "@guandata/guancli-linux-x64": "1.0.67",
48
- "@guandata/guancli-linux-arm64": "1.0.67",
49
- "@guandata/guancli-win32-x64": "1.0.67"
45
+ "@guandata/guancli-darwin-arm64": "1.0.68",
46
+ "@guandata/guancli-darwin-x64": "1.0.68",
47
+ "@guandata/guancli-linux-x64": "1.0.68",
48
+ "@guandata/guancli-linux-arm64": "1.0.68",
49
+ "@guandata/guancli-win32-x64": "1.0.68"
50
50
  },
51
51
  "publishConfig": {
52
52
  "registry": "https://registry.npmjs.org/",
@@ -59,12 +59,15 @@ guancli 是 BI 资源的**查询分析入口**,并支持 Form 表单填报 CRU
59
59
 
60
60
  ## 按需读取资料
61
61
 
62
+ 同一 profile 的跨对象读取遇到业务状态 `1017`(`AUTH_SESSION_CONFLICT`)时,停止派发剩余并发、等待已启动请求结束,丢弃该批所有不完整结果。协调一个有效会话后,按原始完整对象清单串行重取;再次冲突则终止并报告,不能将其判成资源不存在。CLI 只对 GET/HEAD/OPTIONS 在本地已缓存同一身份的新 token 时重试一次,不会因 1017 重新登录,也不会自动重放写请求。批次取消与重取由调用方编排;CLI 不自动协调其他独立进程。详见 `references/auth-and-config.md`。
63
+
62
64
  | 场景 | 先读 |
63
65
  |---|---|
64
66
  | 首次登录、PAT、profile、Token、配置文件 | `references/auth-and-config.md` |
65
67
  | ETL / 数据集 / 页面搜索、get、血缘、输出说明、故障排查 | `references/resource-query.md` |
66
68
  | 数据集 preview、card preview、筛选、日期粒度、排序、动态参数、动态维度、输出格式 | `references/preview-and-output.md` |
67
69
  | Form CRUD、子表、ChatBI 主题问数/洞察 | `references/form-chatbi.md` |
70
+ | ChatBI 报告列表、触发已有订阅、运行历史与历史重跑 | `references/report-composer.md` |
68
71
  | 指标与指标树全量命令 | `references/metric-commands.md` |
69
72
  | 指标泛化查询参数与示例 | `references/metric-generic-query.md` |
70
73
  | 请求转发配置生成、创建、调用与安全边界 | `references/gateway.md` |
@@ -97,6 +97,16 @@ ChatBI 统一复用当前 profile 的 `base_url` 和 uIdToken/OIDC Access Token
97
97
 
98
98
  ## Token 管理
99
99
 
100
+ ### 并发会话冲突(1017)
101
+
102
+ BI 响应 `error.status=1017` 表示认证会话冲突。CLI 将其标记为 `AUTH_SESSION_CONFLICT`,保留 HTTP 状态、业务状态和服务端信息。该分类依据结构化业务码,不匹配 `message` 或 `messageKey` 文案;兼容普通请求返回 HTTP 200 + 1017 错误信封。
103
+
104
+ 密码或 uIdToken profile 的 GET/HEAD/OPTIONS 遇到 1017 时,CLI 只读回本地配置:仅当 profile 名称、base URL、认证方式、Domain、Login ID、已存密码全部一致且存在不同的有效 token 时,使用该 token 重试当前请求一次。配置读取失败、身份变化、没有新 token、只读凭据客户端或重试再次失败时,直接返回错误。1017 不触发密码登录或 OIDC 刷新;写请求、multipart 和下载不会因 1017 自动重新登录/重放。其他 401 的原有重试策略保持不变。
105
+
106
+ `fetch` 的结构化错误 gate(`GUANCLI_STRUCTURED_ERROR=1`)与 batch `apiError` 增加可选字段:`code: "AUTH_SESSION_CONFLICT"`、`retryable: true`、`retryAction: "serial_refetch_batch"`。`retryable` 表示调用方协调后的可恢复性,不授权自动重放写请求。旧生产方不带这些字段时,仍可按 `businessStatus=1017` 判定;`clifetch.IsAuthSessionConflict(err)` 封装该判断。未命中 1017 的输出与退出码保持原行为,失败仍为非零退出码。
107
+
108
+ 跨对象审计的调用方遇到此错误应停止派发新并发、取消或等待已启动请求结束,丢弃本批所有结果。单独协调一个有效会话后,按完整对象清单串行重取一次;再次冲突则终止并报告。CLI 的单请求重试不保证一批对象形成原子快照,也不会取消其他独立进程。
109
+
100
110
  - 密码登录方式:Token 过期后自动调用 sign-in API 刷新。
101
111
  - OIDC 自管 Token:请求前主动刷新;Refresh Token 失效时 macOS/Windows 自动进行浏览器登录,Linux/未适配平台提示手动执行 `auth login --oidc`。读请求遇到 401 最多刷新并重试一次,写请求只刷新不重放。
102
112
  - OIDC 上游 Token:环境变量优先于上游钥匙串和本地凭据;过期或 401 时提示上游刷新,不使用上游 Refresh Token。
@@ -206,3 +206,8 @@ guancli chatbi insight --theme-id "<theme_id>" --message "分析最近30天营
206
206
  - `insight` 输出 L2 markdown;如返回 `GuanViz.json`,CLI 会自动降级成 markdown 表格
207
207
  - ChatBI 命令复用当前 profile 的 `uIdToken`
208
208
  - 默认超时 300 秒、轮询间隔 2 秒;必要时可传 `--timeout-ms` / `--poll-interval-ms`
209
+
210
+ ### 报告编排
211
+
212
+ `guancli chatbi report-composer` 支持列报告、触发已有订阅和查询运行历史。
213
+ 参数、输出契约和历史重跑的后端契约见 [report-composer.md](report-composer.md)。
@@ -0,0 +1,101 @@
1
+ # ChatBI 报告编排
2
+
3
+ 复用现有 `guancli --profile <name>`、uIdToken/OIDC 和 ChatBI Public API 地址推导。
4
+ 不新增环境变量或 token/cookie 参数。与现有 ChatBI 命令一致,当前不支持 PAT 和内部 OAuth2 应用 Token。
5
+
6
+ ## 命令
7
+
8
+ ```bash
9
+ guancli chatbi report-composer list
10
+ guancli chatbi report-composer list --page 2 --page-size 20 --search-text 经营 -f json
11
+ guancli chatbi report-composer trigger-subscription --report-id <report_id> --subscription-id <id> --dry-run
12
+ guancli chatbi report-composer trigger-subscription --report-id <report_id> --subscription-id <id>
13
+ guancli chatbi report-composer trigger-subscription --report-id <report_id> --subscription-id <id> --run-as-user-id alice --run-as-user-id bob
14
+ guancli chatbi report-composer runs --report-id <report_id> --subscription-id <id> --status failed --limit 100 --offset 0 --json
15
+ ```
16
+
17
+ - 报告和订阅 ID 从 `list` 获取;没有订阅的报告不能触发。权限、发件人范围和当前状态由服务端裁决。
18
+ - 不传 `--run-as-user-id` 时触发订阅下全部已配置发件人。重复使用此参数指定多个用户,不按逗号拆分。
19
+ - `--dry-run` 只构建请求,不调用后端,不证明权限或最终业务可执行。
20
+ - 手动触发成功只表示请求已提交/排队。通过 `runs` 查看生成和通知结果;飞书机器人实际收到消息才是送达证据。
21
+ - 使用profile推导地址时,手动触发先通过只读报告列表确定基址;只有404/405才尝试下一候选地址,认证、权限或服务异常直接停止。不会探测主题权限。写请求只提交一次,不进行跨地址fallback或网络/服务错误自动重试;触发与历史重跑禁止自动跟随HTTP重定向(包括307/308),遇到重定向返回带原HTTP状态的JSON错误,先查询runs确认首个地址是否已受理;认证刷新后也不自动重放触发请求,应先查询运行历史再决定是否重试。
22
+ - 列表支持404/405基址探测;运行历史先通过只读列表定位地址,实际查询失败(包括资源404)不转向另一基址;OIDC过期时,运行历史作为只读POST允许刷新后重试一次。
23
+ - `runs` 保留服务端顺序,每次只取一页;翻页由调用方控制,并发运行期间不承诺跨页快照一致性。
24
+ - 可用状态包括 `pending`、`running`、`success`、`failed`、`notification_failed`、`partial_success`;状态最终由服务端校验。
25
+ - `error_message` 是失败摘要,`notification_summary.skipped_recipients` 包含跳过的收件人及原因。
26
+ - 当前只支持查询和触发已有报告订阅,不支持编辑/改名,禁止删除重建来模拟编辑。
27
+
28
+ ## 输出契约
29
+
30
+ - `-f json` / `--json`:后端业务 `data`,保留未知字段和完整数字 ID,不通过展示表头构造 JSON。
31
+ - `--raw`:完整后端响应 envelope,优先于 JSON/格式选择;跳过业务 data 字段和分页结构的适配/校验,保留原始 JSON 以诊断协议漂移。HTTP 错误、缺失成功 code 或非零业务 code 仍按错误协议失败。
32
+ - 默认列表/运行历史使用表格,支持全局 table/csv/excel/expanded;默认触发输出后端 message 和触发警告。
33
+ - 运行历史兼容两种已记录契约:`data: {data: [...], total: N}`,以及 data-synapse `data: [...], total: N`。后者在业务 JSON 中规范化为 `{data: [...], total: N}`,raw 保留原始位置。
34
+ - 旧后端列表只有 `data.reports` 时,默认 `list` 原样返回完整列表,不伪造分页字段。请求非默认页、每页数量或搜索时,必须返回完整分页元数据,否则明确报契约不匹配;不在客户端模仿服务端搜索或分页。
35
+ - 必需对象/数组、行标识和分页字段缺失或类型不匹配时失败;空数组有效。
36
+ - `report-composer`命令失败时stdout为空、stderr为单行JSON、退出码为1,且不附加Cobra文本或usage。格式为`{"error":{"message":"...","http_status":403,"code":403}}`。`message`必有;`http_status`和`code`直接来自后端结构化错误,仅存在且非零时输出。参数/配置/协议等本地错误只带message。错误协议与`--json`/`-f`/`--raw`无关,其他已有命令的错误行为保持不变。
37
+
38
+ ## 历史重跑
39
+
40
+ ```bash
41
+ guancli chatbi report-composer trigger-subscription --report-id <report_id> --subscription-id <id> --run-id <run_id> --dry-run
42
+ guancli chatbi report-composer trigger-subscription --report-id <report_id> --subscription-id <id> --run-id <run_id>
43
+ ```
44
+
45
+ `--run-id` 必须为正整数,不能与 `--run-as-user-id` 同时使用。后端按指定历史运行选择重跑对象;
46
+ 用户组发件人按当前成员重新展开,因此不承诺复制历史成员快照。权限、历史记录归属和发件人合法性由服务端校验。
47
+ 不自动重试重跑请求;提交后查询 `runs` 确认最终状态。
48
+
49
+ 后端契约来源:2026-10-15读取 chatbitest 的 `/api/chat/openapi.json`,
50
+ `/public-api/report-composer-subscription/manual-trigger` 的请求模型明确包含正整数 `run_id`。
51
+ 真实 Public API 对不存在的 `run_id=999999` 返回404“执行记录不存在”,确认字段被服务端处理。
52
+ 先前本地 data-synapse 模型不含此字段,已落后于该部署版本,不能作为当前环境不支持的依据。
53
+ 旧版后端可能忽略未知字段;使用历史重跑前须确认目标部署支持此契约,不支持时应升级后端。
54
+
55
+ ## Domain and Contract / 交付门禁
56
+
57
+ 需求来源:[GuanCLI 支持规则报告订阅触发需求说明](https://guandata.yuque.com/bavrc2/ai7sgq/ytm8u33kq4gu11pz)。
58
+ 报告和运行历史参考本地 data-nexus 路由;历史重跑以目标部署的实时 OpenAPI及行为验证为准。
59
+
60
+ | CLI 默认入口 | 对照到的 data-synapse 路由 | 权限/验证状态 |
61
+ |---|---|---|
62
+ | GET /api/chat/public-api/report-composer/reports | GET /report-composer/reports | chatbitest列表、分页、搜索验证通过;无权对照待验证 |
63
+ | POST /api/chat/public-api/report-composer-subscription/manual-trigger | POST /report-composer-subscription/manual-trigger | chatbitest普通触发run160成功且用户确认飞书收件;重跑另行记录 |
64
+ | POST /api/chat/public-api/report-composer-subscription/list-runs | POST /report-composer-subscription/list-runs | chatbitest运行历史、分页及失败筛选通过 |
65
+
66
+ 上述路径相对于默认基址;实际沿用已有 profile 地址推导。没有新增假定旧端点 fallback。
67
+ 本地 Python 路由存在不能证明 BI Public API 入口及 PAT 纳管已完成;尚未找到目标版本生效的 Spring Controller 和权限映射证据。
68
+ 当前 CLI 延续拒绝 PAT 的行为,不宣称这些接口默认授予 PAT 权限。
69
+ CLI验证、目标部署、PAT纳管和真实消息送达分别记录;单用户测试不等于无权/PAT对照通过。
70
+
71
+ ## 2026-10-18 权限门禁核查
72
+
73
+ - 检查 BI 仓库 `galaxy-backend/guandata-core` 的 master `4d8e64c524bd269cb44890bb32a17e5116cf5195`:仓库代码搜索 `report-composer` 未命中,已读取 Spring Controller 目录及 `ReverseProxyNgController`。这只记录本次检索范围,不能证明目标部署没有路由,也不能将 master 当作 chatbitest 的部署版本。
74
+ - data-nexus `0508f3d675b8cda50e482ad594f44d012468b425` 的 `report_composer_router.py`、`report_composer_subscription_router.py` 明确注册三个 Public API;`list_runs` 与 `manual_trigger` 调用 `_ensure_subscription_editor_access`,要求报告编排编辑角色并检查报告 owner 权限。此为服务端业务权限证据,不是 PAT 权限项/default grant 的证明。
75
+ - 同一份 data-synapse 源码的 `TokenMiddleware` 已有 PAT 分支,因此不能仅凭当前 CLI 拒绝 PAT 宣称“产品不支持 PAT”。该源码与目标部署是否一致尚未确认。
76
+ - 现有 chatbitest profile 使用账密/uIdToken;未找到同用户、同 Domain 的现成 PAT profile。未改动配置、鉴权或创建新 Token,也未使用其他环境的 PAT 代替对照。
77
+
78
+ **PAT 交付证据仍未完成**:需取得 chatbitest 对应部署版本的入口/代理路由及适用的 Spring Controller 证据、三个 method/path 的 PAT 权限项与默认授权映射,再完成同用户/Domain/资源的 uIdToken–PAT 有权/无权/不存在对照;写入还需预检、真实触发及回读。若产品设计明确不支持 PAT,则需提供权威说明。当前不具备这些证据,不能据此宣称已支持或完成 PAT 交付,也不据此认定存在权限漏洞。
79
+
80
+ ### 本轮验收范围
81
+
82
+ 用户在本轮权限核查后明确确认:“先用非pat模式验证就可以了”。本轮使用既有 `chatbitest` profile 的 uIdToken 路径验收,不新增 PAT 支持,不修改鉴权配置、账号资格或 Domain 策略。上述 PAT 对照不再作为本轮非 PAT 验收的阻塞项;后续启用或宣称 PAT 能力时,仍须补齐其门禁证据。
83
+
84
+ ### 同一测试账号的实时权限核对(2026-10-18)
85
+
86
+ 通过既有 `chatbitest` profile 查询,未创建或修改任何权限/Token:
87
+
88
+ - `GET /api/user/profile`:Domain `guanbi`,账号角色为 admin,`privilege.report_composer=[read,update,auth]`,但 `patEligible=false`。
89
+ - `GET /api/report_composer/OWNER/9fc491e4-465c-4f56-a313-332b8c21ea08/check_auth`:`effect=true`,确认该账号拥有测试报告的 OWNER 权限。
90
+ - `GET /api/personal-access-token/candidates`:返回14项,不含 `pId=375 / report_composer`。因此不能将当前情况解释为“用户本身没有报告权限”,也不能宣称报告权限默认覆盖 PAT。
91
+ - BI master 上的 `ReportComposerResourceNgController` 确认底层 ACL 路由使用下划线 `/report_composer/{privilegeName}/{reportId}/check_auth` 和 `/report_composer/list`,均声明 `Resource.REPORT_COMPOSER + READ`;`V461__DML_init_report_composer_permission` 将 `report_composer` 映射为权限项375。它们是 data-synapse 依赖的 BI ACL 接口,不能冒充三个短横线 Public API 本身的 Spring 路由。
92
+ - 同一 master 的 `cli_pat_scope.json` 不含375;`PatPermissionScopeService.candidatesFor` 按“用户权限 ∩ Domain策略”计算候选,创建时拒绝超出候选的 scope。结合运行时响应,目前该账号/Domain无法选择报告编排 PAT 权限;这不是产品永久不支持 PAT 的权威结论。
93
+ - 目标 `server-version` 返回 `8.3.2_codex_GALAXY-39889-auto-credit-activation_2026092414_00`,未返回源码SHA;同名分支检索无结果。掌天只读查询不可用(502),因此部署SHA及代理链仍未对齐。本次未修改账号生成资格、Domain策略或服务端鉴权。
94
+
95
+ 源码核查入口:[BI master](https://gitlab.mayidata.com/galaxy-backend/guandata-core/-/tree/4d8e64c524bd269cb44890bb32a17e5116cf5195/modules/server_ng/src/main/java/com/guandata/controllers)、[data-synapse 路由](https://gitlab.mayidata.com/zijie0/data-nexus/-/tree/0508f3d675b8cda50e482ad594f44d012468b425/services/data-synapse/data_synapse/router)。
96
+
97
+ ## 地址定位与提交的一致性
98
+
99
+ 推导基址的触发和运行历史查询流程为“只读定位→一次写入”,只读结果仅确认对应地址可用,不作为权限或订阅合法性的最终裁决。
100
+ 不合并多个基址的业务结果,也不承诺两次请求间状态不变;真实写请求仍由服务端校验最新权限、发件人和订阅状态。
101
+ 只读定位失败时不提交写入;写入失败时不自动转向另一基址。使用精确基址创建的client无需额外定位。