@fateforge/archery-cli 1.0.4 → 1.0.6
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/.agent/CLI-SPEC.md +26 -11
- package/.agent/CLI-SPEC_zh.md +7 -3
- package/.agent/SEC-SPEC.md +14 -9
- package/.agent/SEC-SPEC_zh.md +2 -2
- package/CHANGELOG.md +30 -0
- package/README.md +6 -0
- package/README_zh.md +6 -0
- package/docs/LIVE-SMOKE-EVIDENCE.md +31 -0
- package/package.json +7 -7
- package/skills/archery-cli/SKILL.md +36 -11
- package/skills/archery-cli/reference/workflow.md +18 -4
package/.agent/CLI-SPEC.md
CHANGED
|
@@ -134,6 +134,7 @@ Error codes and exit codes must align:
|
|
|
134
134
|
- `E_CONFLICT` -> 6
|
|
135
135
|
- `E_NETWORK` / `E_RATE_LIMITED` / `E_SERVER` -> 7
|
|
136
136
|
- `E_TIMEOUT` -> 8
|
|
137
|
+
- `E_INTEGRITY` -> 1 (release integrity failure: missing/invalid signature or checksum mismatch; **non-retryable**, see §14)
|
|
137
138
|
- `E_HUMAN_REQUIRED` -> 9 (optional, only when §16.3 is enabled)
|
|
138
139
|
|
|
139
140
|
When the failure comes from an upstream HTTP call, map the status onto the
|
|
@@ -635,17 +636,31 @@ Version notification contract:
|
|
|
635
636
|
|
|
636
637
|
Release verification baseline:
|
|
637
638
|
|
|
638
|
-
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
639
|
+
- **Mandatory signature verification, no skip path**: the binary self-update path
|
|
640
|
+
MUST verify the Sigstore signature on `checksums.txt` in-process, then verify
|
|
641
|
+
the archive SHA256 against it. A missing signature bundle, a signature that does
|
|
642
|
+
not verify, or a checksum mismatch all fail closed — there is no "can't verify,
|
|
643
|
+
proceed anyway" degradation. The whole chain surfaces `E_INTEGRITY` (exit 1,
|
|
644
|
+
non-retryable): a forged or corrupt release is not a transient blip to retry.
|
|
645
|
+
- **Verifier embedded, no user-environment dependency**: verification happens
|
|
646
|
+
inside the tool binary (Go via `sigstore-go`, Python inside the frozen binary
|
|
647
|
+
via `sigstore`) with **no external cosign** and nothing pre-installed on the
|
|
648
|
+
machine. The TUF trust root is bootstrapped from the library's embedded
|
|
649
|
+
`root.json`, not fetched on first-use trust (TOFU).
|
|
650
|
+
- **New bundle format**: the signing side produces a Sigstore protobuf bundle
|
|
651
|
+
(`checksums.txt.sigstore.json`) via `cosign sign-blob --new-bundle-format`, which
|
|
652
|
+
the in-process verifier consumes; the legacy cosign bundle format is not accepted.
|
|
653
|
+
- **Identity binding**: verifiers bind the certificate SAN to this repo's tagged
|
|
654
|
+
release workflow (`…/release.yml@refs/tags/v*`, anchored `^…$`) and validate the
|
|
655
|
+
GitHub OIDC issuer. When the target tag is known, pin the exact identity (stronger
|
|
656
|
+
than a regexp).
|
|
657
|
+
- **Cross-language parity**: Go binaries and Python frozen binaries follow the same
|
|
658
|
+
self-update contract — download archive → in-process signature verify → checksum
|
|
659
|
+
→ replace binary. Package managers do not own integrity.
|
|
660
|
+
- Update results carry `signature_status` (`verified` on success; any failure exits
|
|
661
|
+
via the error envelope) and `signature_verified` (true only when in-process
|
|
662
|
+
Sigstore verification actually ran and succeeded). Never imply checksum
|
|
663
|
+
verification is a signature.
|
|
649
664
|
|
|
650
665
|
- After `update --confirm <token>` succeeds, return `previous_version` and `current_version` in `data`.
|
|
651
666
|
- Also hint in the result: `run "changelog --since <previous_version>" to see what changed`.
|
package/.agent/CLI-SPEC_zh.md
CHANGED
|
@@ -131,6 +131,7 @@
|
|
|
131
131
|
- `E_CONFLICT` -> 6
|
|
132
132
|
- `E_NETWORK` / `E_RATE_LIMITED` / `E_SERVER` -> 7
|
|
133
133
|
- `E_TIMEOUT` -> 8
|
|
134
|
+
- `E_INTEGRITY` -> 1(发布完整性失败:签名缺失/无效或 checksum 不符;**非重试**,见 §14)
|
|
134
135
|
- `E_HUMAN_REQUIRED` -> 9(可选,仅启用 §16.3 时)
|
|
135
136
|
|
|
136
137
|
当错误来自上游 HTTP 调用时,按状态码映射到错误码,让 agent 能从 `error.code` +
|
|
@@ -583,9 +584,12 @@ update 必须遵守的契约:
|
|
|
583
584
|
|
|
584
585
|
release 校验基线:
|
|
585
586
|
|
|
586
|
-
-
|
|
587
|
-
-
|
|
588
|
-
-
|
|
587
|
+
- **强制签名验证,无跳过路径**:二进制自更新路径必须在进程内验证 `checksums.txt` 的 Sigstore 签名,再用它校验归档 SHA256。签名 bundle 缺失、签名验不过、checksum 不符,一律**失败关闭**,不存在"验不了就放行"的降级。整条链对外返回 `E_INTEGRITY`(exit 1,非重试)——伪造或损坏的发布不该被当成可重试的瞬时错误。
|
|
588
|
+
- **验证器内置、不依赖用户环境**:验证在工具二进制内完成(Go 用 `sigstore-go`,Python 冻结二进制内用 `sigstore`),**不外挂 cosign**,不依赖机器上预装任何东西。TUF 信任根从库内嵌的 `root.json` 引导(不是 TOFU 现拉现信)。
|
|
589
|
+
- **新版 bundle 格式**:签名侧用 `cosign sign-blob --new-bundle-format` 产出 Sigstore protobuf bundle(`checksums.txt.sigstore.json`),与进程内验证器对齐;旧版 cosign bundle 格式不被接受。
|
|
590
|
+
- **身份绑定**:验证端把证书 SAN 绑定到本仓库的 tagged release workflow(`…/release.yml@refs/tags/v*`,锚定 `^…$`)并校验 GitHub OIDC issuer。已知目标 tag 时可绑精确身份,强于正则。
|
|
591
|
+
- **跨语言统一**:Go 二进制与 Python 冻结二进制走同一套自更新契约——都是"下载归档 → 进程内验签 → checksum → 替换二进制",包管理器不参与完整性。
|
|
592
|
+
- update 结果携带 `signature_status`(成功即 `verified`;异常一律走 error envelope 中止)与 `signature_verified`(仅当进程内 Sigstore 验证真实执行且成功时为 true)。不能把 checksum 校验伪装成签名校验。
|
|
589
593
|
|
|
590
594
|
- `update --confirm <token>` 成功后,结果 `data` 中返回 `previous_version` 与 `current_version`。
|
|
591
595
|
- 同时在结果中提示:`run "changelog --since <previous_version>" to see what changed`。
|
package/.agent/SEC-SPEC.md
CHANGED
|
@@ -97,15 +97,20 @@ Fallback and channel rules:
|
|
|
97
97
|
|
|
98
98
|
## 5. Supply chain (applies to anything distributed)
|
|
99
99
|
|
|
100
|
-
- **Integrity verification
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
100
|
+
- **Integrity verification, mandatory and no-skip**: binary self-update MUST verify
|
|
101
|
+
the Sigstore signature on `checksums.txt` **in-process** (the verifier is embedded
|
|
102
|
+
in the tool binary — Go via `sigstore-go`, Python inside the frozen binary via
|
|
103
|
+
`sigstore` — with **no external cosign** and no user-environment dependency), then
|
|
104
|
+
verify the archive SHA256. A missing/invalid signature or a checksum mismatch
|
|
105
|
+
**fails closed** with no "can't verify, proceed anyway" degradation, surfacing
|
|
106
|
+
`E_INTEGRITY` (non-retryable). A checksum proves bytes match a checksum file; only
|
|
107
|
+
the signature proves the checksum file came from the publisher.
|
|
108
|
+
- **Signed release material**: release pipelines sign `checksums.txt` with
|
|
109
|
+
Sigstore/Cosign keyless signing from the tagged GitHub Actions release workflow
|
|
110
|
+
using `--new-bundle-format` (a Sigstore protobuf bundle the in-process verifier
|
|
111
|
+
consumes). Verification binds the signature to the expected repository workflow
|
|
112
|
+
identity (anchored `^…$`) and GitHub OIDC issuer; the TUF trust root is
|
|
113
|
+
bootstrapped from the library's embedded root, not TOFU.
|
|
109
114
|
- **Dependency locking + audit**: commit a lockfile; CI runs `npm audit` / `pip-audit` and blocks high-severity dependencies.
|
|
110
115
|
- **Traceable builds**: release artifacts are built by CI from tagged source, no hand-uploaded unknown binaries.
|
|
111
116
|
- **No remote scripts in postinstall**: don't execute code freshly pulled from the network at install time.
|
package/.agent/SEC-SPEC_zh.md
CHANGED
|
@@ -88,8 +88,8 @@ Agent 侧约定(同时写进 SKILL-SPEC 的用法):
|
|
|
88
88
|
|
|
89
89
|
## 5. 供应链(凡分发即适用)
|
|
90
90
|
|
|
91
|
-
-
|
|
92
|
-
- **签名发布材料**:release pipeline
|
|
91
|
+
- **完整性校验,强制且无跳过**:二进制自更新必须**在进程内**验证 `checksums.txt` 的 Sigstore 签名(验证器内置工具二进制,Go 用 `sigstore-go`、Python 冻结二进制内用 `sigstore`,**不外挂 cosign**、不依赖用户环境),再用它校验归档 SHA256。签名缺失/验不过/checksum 不符一律**失败关闭**,没有"验不了就放行"的降级;对外返回 `E_INTEGRITY`(非重试)。checksum 只能证明字节与 checksum 文件一致,签名才能证明 checksum 文件来自发布者。
|
|
92
|
+
- **签名发布材料**:release pipeline 由 tagged GitHub Actions release workflow 用 Sigstore/Cosign keyless 模式以 `--new-bundle-format` 签署 `checksums.txt`(产出 Sigstore protobuf bundle),与进程内验证器对齐。验证时绑定到预期仓库 workflow 身份(锚定 `^…$`)和 GitHub OIDC issuer;TUF 信任根从库内嵌 root 引导,不 TOFU。
|
|
93
93
|
- **依赖锁定 + 审计**:提交 lockfile;CI 跑 `npm audit` / `pip-audit` 一类,高危依赖阻断。
|
|
94
94
|
- **构建可追溯**:发布产物由 CI 从打了 tag 的源码构建,不手工上传不明二进制。
|
|
95
95
|
- **不在 postinstall 跑远程脚本**:安装期不执行从网络现拉的代码。
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,36 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.0.6] - 2026-06-16
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- `update` now verifies the release Sigstore signature on `checksums.txt` **in-process** (embedded `sigstore-go`, bootstrapped from the embedded TUF trust root) instead of shelling out to an external `cosign`. Verification is mandatory and fail-closed: a missing signature bundle, a signature that does not verify against this repo's tagged release-workflow identity, or a checksum mismatch all refuse the update — there is no skip path. Releases are now signed with `cosign sign-blob --new-bundle-format`.
|
|
13
|
+
|
|
14
|
+
### Security
|
|
15
|
+
|
|
16
|
+
- Release-integrity failures (missing/invalid signature or checksum mismatch) now return the non-retryable `E_INTEGRITY` error code (exit 1) instead of a retryable network code, so an agent treats a possible supply-chain issue as a hard stop rather than retrying.
|
|
17
|
+
|
|
18
|
+
## [1.0.5] - 2026-06-16
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **`--read-only` global switch (and `ARCHERY_CLI_READONLY` env var).** When set, every write command is refused at the shared write chokepoint with an `E_FORBIDDEN` envelope (exit 4) — before the dry-run preview or any network call. Read commands are unaffected. This lets an agent run safely against production with writes hard-disabled regardless of `--dry-run`/`--confirm`. `doctor` and `context` report the current read-only state.
|
|
23
|
+
- **2FA detection + `--otp` (and `ARCHERY_CLI_OTP`).** Session login now understands Archery's two-factor flow. If an account has 2FA enabled, `/authenticate/` accepts the password but does not log in (it returns a `session_key` in `data` with no `sessionid` cookie); the CLI now detects this:
|
|
24
|
+
- With `--otp <6-digit code>` it completes the login via `POST /api/v1/user/2fa/` and caches the resulting session, so **subsequent commands need no OTP** until the session expires.
|
|
25
|
+
- Without an OTP it fails fast with the new **`E_2FA_REQUIRED`** code (exit 9, "human required") and a clear hint to retry with `--otp`, instead of the old opaque "session login failed".
|
|
26
|
+
- 2FA codes are ~30s-lived: generate the code immediately before running. The cached `sessionid` (keyring) is reused afterwards, so OTP is a one-time cost per session.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- **`workflow detail` reworked to surface execution results.** Detail now reads the execution/review result rows from `/sqlworkflow/detail_content/` and exposes them as `result[]` (each row carries `stage`, `stageStatus`, `errLevel`, `error`, `affectedRows`, `executeTime`), plus the string `statusCode` (e.g. `workflow_exception`) backfilled from the workflow list. An agent can now see **why an execution failed** (e.g. `Invalid remote backup information`) straight from the CLI instead of opening the web UI. SQL content is reconstructed from the rows, with inception wrapper statements filtered out.
|
|
31
|
+
- **Unified instance/group flags for `workflow submit` / `sqlcheck` / `auto-review`.** Session mode now also accepts the numeric `--instance` (ID) and `--group` (ID), resolving them to names via the instance/resource-group lists — the same flags JWT mode already used, so agents no longer have to remember a different flag set per transport. The name flags (`--instance-name` / `--group-name`) still work and win when both are given; an unknown ID fails with a clear `E_NOT_FOUND`.
|
|
32
|
+
- **Skill schema-discovery guidance.** The Skill now steers agents to locate tables/columns by **meaning** via `dict tables` / `dict table-info` (which carry table and column comments) instead of `instance resource` / `instance describe` (bare names only), with an explicit "stop guessing, ask the user" rule when no matching column exists. Fixes all `dict` examples that omitted the required `--db-type`, which fail with `Instance.DoesNotExist` on Archery v1.8.5.
|
|
33
|
+
|
|
34
|
+
### Notes
|
|
35
|
+
|
|
36
|
+
- **DDL execution and backups.** Executing a DDL workflow with backup enabled needs Archery's backup feature configured (`enable_backup_switch` on and a reachable backup database). On environments without it, execution fails with `Invalid remote backup information` — this is an Archery configuration prerequisite, not a CLI bug. Either have a DBA configure the backup database, or submit with backup disabled (`--backup=false`).
|
|
37
|
+
|
|
8
38
|
## [1.0.4] - 2026-06-16
|
|
9
39
|
|
|
10
40
|
### Added
|
package/README.md
CHANGED
|
@@ -41,6 +41,10 @@ PowerShell uses `$env:NAME = "value"` for the same environment variables. Keep r
|
|
|
41
41
|
|
|
42
42
|
**Dual-mode transport — usable by ordinary developer accounts.** By default the CLI logs in and talks to Archery over its **web session + AJAX endpoints** (`/authenticate/`, `/sqlworkflow_list/`, `/sqlquery/`, …). This path works on every Archery version and for plain accounts, where the `/api/v1` REST surface is typically closed (`403`) or simply not enabled. REST + JWT is kept as an opt-in advanced mode: pass `--mode jwt` or set `mode: jwt` on a region. Mode precedence is `--mode` flag → region config → `session` default. Verified live against `hhyo/archery:v1.8.5` with an ordinary account.
|
|
43
43
|
|
|
44
|
+
**Read-only mode.** Pass `--read-only` (or set `ARCHERY_CLI_READONLY` to any non-empty value) to hard-disable every write command. Writes are refused at the shared chokepoint with an `E_FORBIDDEN` envelope (exit 4) before any network call, regardless of `--dry-run`/`--confirm`; read commands are unaffected. Use it to run safely against production. `doctor` and `context` report the active state.
|
|
45
|
+
|
|
46
|
+
**Two-factor auth.** For accounts with 2FA enabled, supply a fresh 6-digit code with `--otp <code>` (or `ARCHERY_CLI_OTP`). The CLI detects when Archery requires a second factor and, without a code, fails fast with `E_2FA_REQUIRED` (exit 9) and a hint to retry with `--otp`. Codes are ~30s-lived, so generate one immediately before running; the resulting session is cached, so later commands need no OTP until it expires.
|
|
47
|
+
|
|
44
48
|
Worst-case risk tier: **T2 high** - can execute and manage SQL workflows against configured database instances. See [SECURITY.md](SECURITY.md) and [.agent/SEC-SPEC.md](.agent/SEC-SPEC.md).
|
|
45
49
|
|
|
46
50
|
## Capabilities
|
|
@@ -86,6 +90,8 @@ Config location: `~/.archery-cli/config.json`.
|
|
|
86
90
|
| `ARCHERY_CLI_USERNAME` | Username |
|
|
87
91
|
| `ARCHERY_CLI_PASSWORD` | Password |
|
|
88
92
|
| `ARCHERY_CLI_REGION` | Active region/profile |
|
|
93
|
+
| `ARCHERY_CLI_READONLY` | Any non-empty value disables all write commands (same as `--read-only`) |
|
|
94
|
+
| `ARCHERY_CLI_OTP` | 6-digit 2FA code for accounts with two-factor auth (same as `--otp`) |
|
|
89
95
|
| `NO_COLOR` | Disable colored text output when text mode is explicitly requested |
|
|
90
96
|
|
|
91
97
|
Saved credentials, when supported, are encrypted or stored in the OS credential store. Environment variables take precedence and are the preferred path for short-lived Agent sessions.
|
package/README_zh.md
CHANGED
|
@@ -41,6 +41,10 @@ PowerShell 使用 `$env:NAME = "value"` 设置同样的环境变量。真实密
|
|
|
41
41
|
|
|
42
42
|
**双模传输 —— 普通开发者账号即可用。** CLI **默认走 Archery 网页端的 session + AJAX 端点**(`/authenticate/`、`/sqlworkflow_list/`、`/sqlquery/` 等)登录和请求。这条路径在所有 Archery 版本、对普通账号都可用;而 `/api/v1` REST 面通常对普通账号关闭(`403`)或根本未开启。REST + JWT 作为可选的高级模式保留:传 `--mode jwt` 或在 region 配置 `mode: jwt` 即可。模式优先级为 `--mode` 参数 → region 配置 → 默认 `session`。已在 `hhyo/archery:v1.8.5` 上用普通账号真机验证。
|
|
43
43
|
|
|
44
|
+
**只读模式。** 传 `--read-only`(或将 `ARCHERY_CLI_READONLY` 设为任意非空值)即可硬禁用所有写命令。写命令会在统一入口处被拒,返回 `E_FORBIDDEN`(退出码 4),且发生在任何网络调用之前,不受 `--dry-run`/`--confirm` 影响;读命令不受影响。适合在生产环境安全运行。`doctor` 和 `context` 会显示当前是否只读。
|
|
45
|
+
|
|
46
|
+
**二次验证(2FA)。** 对开启了 2FA 的账号,用 `--otp <验证码>`(或 `ARCHERY_CLI_OTP`)传入新鲜的 6 位验证码。CLI 会检测到 Archery 要求二次验证;若未提供验证码,会立即失败并返回 `E_2FA_REQUIRED`(退出码 9),提示用 `--otp` 重试。验证码有效期约 30 秒,请在运行前即时生成;验证成功后会话会被缓存,后续命令在会话过期前无需再次输入 OTP。
|
|
47
|
+
|
|
44
48
|
最坏情况风险等级:**T2 高风险** - 可对已配置数据库实例执行和管理 SQL 工单。参见 [SECURITY.md](SECURITY.md) 和 [.agent/SEC-SPEC.md](.agent/SEC-SPEC.md)。
|
|
45
49
|
|
|
46
50
|
## 能力
|
|
@@ -86,6 +90,8 @@ README 只做地图,不做完整手册。Agent 在执行任务命令前,应
|
|
|
86
90
|
| `ARCHERY_CLI_USERNAME` | 用户名 |
|
|
87
91
|
| `ARCHERY_CLI_PASSWORD` | 密码 |
|
|
88
92
|
| `ARCHERY_CLI_REGION` | 当前区域/profile |
|
|
93
|
+
| `ARCHERY_CLI_READONLY` | 任意非空值即禁用所有写命令(等价于 `--read-only`) |
|
|
94
|
+
| `ARCHERY_CLI_OTP` | 开启 2FA 账号的 6 位验证码(等价于 `--otp`) |
|
|
89
95
|
| `NO_COLOR` | 显式使用 text 模式时禁用彩色输出 |
|
|
90
96
|
|
|
91
97
|
支持保存凭据时,凭据会加密或进入 OS 凭据库。环境变量优先级更高,也是短生命周期 Agent 会话的推荐方式。
|
|
@@ -361,6 +361,37 @@ intermittently returned `用户名或密码错误`. Using `http://127.0.0.1:9123
|
|
|
361
361
|
defect; the session login flow itself (GET csrf → POST authenticate → cookie)
|
|
362
362
|
matches the verified curl flow byte-for-byte.
|
|
363
363
|
|
|
364
|
+
## 2026-06-16 — 1.0.5 features (read-only, 2FA, param unification, detail rework)
|
|
365
|
+
|
|
366
|
+
Verified against the same `tools-e2e-archery` container (`hhyo/archery:v1.8.5`,
|
|
367
|
+
base `http://localhost:9123`) with the ordinary superuser account `cli_verify`,
|
|
368
|
+
binary built from this working tree (`go build -o /tmp/a.exe ./cmd/archery-cli`),
|
|
369
|
+
`ARCHERY_CLI_NO_KEYRING=1`.
|
|
370
|
+
|
|
371
|
+
### Result by feature
|
|
372
|
+
|
|
373
|
+
| Feature | Status | Evidence |
|
|
374
|
+
|---------|--------|----------|
|
|
375
|
+
| `--read-only` reflected in `doctor` | live (read) | PASS — `doctor` JSON shows `readOnly:true` and a `read-only` warn check; `auth` still `pass` (logged in to the real server). |
|
|
376
|
+
| `--read-only` reflected in `context` | live (read) | PASS — `context.data.readOnly == true`. |
|
|
377
|
+
| `--read-only` refuses a write | live | PASS — `workflow submit ... --read-only --dry-run` → `E_FORBIDDEN`, exit 4, before any network call. |
|
|
378
|
+
| `ARCHERY_CLI_READONLY` env | live | PASS — read command (`workflow list`) succeeds under the env var; the env is a pure read-allow path. |
|
|
379
|
+
| Param unification: `--instance`/`--group` IDs (session) | live | PASS — `workflow submit --instance 1 --group 1 --dry-run` preview resolves `instanceName:e2e-mysql`, `groupName:smoke-rg`; confirm submitted real workflow id 4. |
|
|
380
|
+
| Unknown instance ID | live | PASS — `--instance 999` → `E_NOT_FOUND` (exit 3) with a clear "check 'instance list'" message. |
|
|
381
|
+
| `workflow detail` result rework | live | PASS — `detail 4` returns `result[]` (real auto-review rejection "仅支持DML和DDL语句…") + `statusCode:workflow_autoreviewwrong` + numeric `status:3`. |
|
|
382
|
+
| `--otp` harmless for non-2FA account | live | PASS — passing `--otp 000000` for `cli_verify` (no 2FA) does not break login; the OTP path only fires when the server signals 2FA. |
|
|
383
|
+
| 2FA detection + `--otp` completion | **mock only** | The `cli_verify` account has **no 2FA enabled**, so the 2FA login branch cannot be exercised live. Covered by unit tests `TestEnsureSession_2FARequiredNoOTP` / `2FAWithOTPSucceeds` / `2FAWrongOTP` against an httptest server that mimics v1.8.5's `/authenticate/` (status 0 + `data` session_key, no sessionid) and `/api/v1/user/2fa/`. **Honest gap: the real `/api/v1/user/2fa/` round-trip is not live-verified.** |
|
|
384
|
+
|
|
385
|
+
Test workflow id 4 was cancelled after verification (`workflow cancel 4`) to
|
|
386
|
+
leave the container clean.
|
|
387
|
+
|
|
388
|
+
### Honesty notes
|
|
389
|
+
|
|
390
|
+
- **Race detector not run on this host:** `go test -race` needs cgo + gcc, which
|
|
391
|
+
are unavailable on the verifier machine. The non-race suite (`go test ./...`)
|
|
392
|
+
is fully green, and `golangci-lint run` reports 0 issues.
|
|
393
|
+
- **2FA is mock-verified only** for the reason above.
|
|
394
|
+
|
|
364
395
|
## Reproduce
|
|
365
396
|
|
|
366
397
|
```bash
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fateforge/archery-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6",
|
|
4
4
|
"description": "Archery SQL audit CLI for AI Agents - manage SQL workflows, queries, instances, diagnostics, and data dictionaries with a machine-readable contract",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"archery",
|
|
@@ -26,12 +26,12 @@
|
|
|
26
26
|
"archery-cli": "scripts/run.js"
|
|
27
27
|
},
|
|
28
28
|
"optionalDependencies": {
|
|
29
|
-
"@fateforge/archery-cli-darwin-arm64": "1.0.
|
|
30
|
-
"@fateforge/archery-cli-darwin-x64": "1.0.
|
|
31
|
-
"@fateforge/archery-cli-linux-arm64": "1.0.
|
|
32
|
-
"@fateforge/archery-cli-linux-x64": "1.0.
|
|
33
|
-
"@fateforge/archery-cli-win32-arm64": "1.0.
|
|
34
|
-
"@fateforge/archery-cli-win32-x64": "1.0.
|
|
29
|
+
"@fateforge/archery-cli-darwin-arm64": "1.0.5",
|
|
30
|
+
"@fateforge/archery-cli-darwin-x64": "1.0.5",
|
|
31
|
+
"@fateforge/archery-cli-linux-arm64": "1.0.5",
|
|
32
|
+
"@fateforge/archery-cli-linux-x64": "1.0.5",
|
|
33
|
+
"@fateforge/archery-cli-win32-arm64": "1.0.5",
|
|
34
|
+
"@fateforge/archery-cli-win32-x64": "1.0.5"
|
|
35
35
|
},
|
|
36
36
|
"files": [
|
|
37
37
|
"scripts/run.js",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: archery-cli
|
|
3
|
-
version: "1.0.
|
|
3
|
+
version: "1.0.6"
|
|
4
4
|
description: "Archery SQL audit platform CLI for managing SQL workflows, queries, instances, diagnostics. Use when the user asks about SQL审核, database operations, Archery platform management, or needs to submit/review/execute SQL against database instances."
|
|
5
5
|
license: MIT
|
|
6
6
|
user-invocable: true
|
|
7
|
-
metadata: {"requires":{"bins":["archery-cli"],"min_version":"1.0.
|
|
7
|
+
metadata: {"requires":{"bins":["archery-cli"],"min_version":"1.0.6"}}
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# archery-cli
|
|
@@ -58,6 +58,10 @@ First-time setup: ask user for Archery URL + credentials, then run `archery-cli
|
|
|
58
58
|
| Dangerous writes | If `reference` shows `requiresDangerous`, include `--dangerous` in both dry-run and confirm commands |
|
|
59
59
|
| Discovery | `archery-cli reference` is the machine truth for params, `write`, `requiresConfirmation`, `requiresDangerous`, `riskLevel`, output schemas, and errors |
|
|
60
60
|
| Transport | Defaults to **session** mode (Archery web AJAX endpoints) — works for ordinary accounts on all versions. REST + JWT is opt-in via `--mode jwt` or a region's `mode: jwt`. Precedence: `--mode` flag → region config → `session`. |
|
|
61
|
+
| Read-only | Pass `--read-only` (or set `ARCHERY_CLI_READONLY`) to hard-disable all writes; they fail with `E_FORBIDDEN` (exit 4) before any network call. Use it when the task is read-only/analysis. |
|
|
62
|
+
| 2FA | If a command fails with `E_2FA_REQUIRED` (exit 9), the account has 2FA on. Ask the user for a fresh 6-digit code and retry the **same** command with `--otp <code>` (codes last ~30s). The session is then cached, so later commands need no OTP. |
|
|
63
|
+
| Instance/group IDs | `workflow submit/sqlcheck/auto-review` accept either `--instance`/`--group` (numeric IDs, resolved automatically) **or** `--instance-name`/`--group-name`. IDs work in both transport modes. |
|
|
64
|
+
| Schema discovery | To locate a table/column by **meaning** (not its exact name), use `dict tables` → `{name, comment}` then `dict table-info` → per-column `column_comment`: those carry the human labels (e.g. `班级学生表`, `性别`). `instance resource`/`instance describe` return **bare names with no comments** — use them only when you already know the exact identifier. Already know the table name but not which instance holds it? `instance table-instances --table <name>`. `dict` needs `--instance <name>` (not ID) **and** `--db-type <mysql/...>` (db-type is required on v1.8.5; omitting it fails with `Instance.DoesNotExist`). |
|
|
61
65
|
|
|
62
66
|
## Trigger list
|
|
63
67
|
|
|
@@ -99,7 +103,8 @@ First-time setup: ask user for Archery URL + credentials, then run `archery-cli
|
|
|
99
103
|
| Review slow queries | `archery-cli slowquery review --instance mydb --start "2024-01-01 00:00:00" --end "2024-01-31 23:59:59"` |
|
|
100
104
|
| List processes | `archery-cli diagnostic process --instance mydb` |
|
|
101
105
|
| List binlog files | `archery-cli binlog list --instance mydb` |
|
|
102
|
-
|
|
|
106
|
+
| Find a table/column by meaning | `archery-cli dict tables --instance mydb --db test --db-type mysql` (scan `comment`), then `dict table-info ... --table t` (scan `column_comment`) |
|
|
107
|
+
| Browse tables | `archery-cli dict tables --instance mydb --db test --db-type mysql` |
|
|
103
108
|
| Test instance connectivity | `archery-cli instance test-instance --instance 1 --compact` |
|
|
104
109
|
| Create a database on an instance | `archery-cli instance create-db --instance 1 --db reporting --owner alice --dangerous --dry-run`, then `--dangerous --confirm <token>` |
|
|
105
110
|
| Create a database account | `archery-cli instance create-user --instance 1 --user app --host '%' --password '...' --dangerous --dry-run`, then `--dangerous --confirm <token>` |
|
|
@@ -177,6 +182,7 @@ Check `ok` first, then act on exit code:
|
|
|
177
182
|
| 6 | `E_CONFLICT` | Stale or invalid token | Re-run `--dry-run`, get fresh token, retry |
|
|
178
183
|
| 7 | `E_NETWORK`/`E_RATE_LIMIT`/`E_SERVER` | Transient error | Back off and retry |
|
|
179
184
|
| 8 | `E_TIMEOUT` | Timeout | Back off and retry |
|
|
185
|
+
| 9 | `E_2FA_REQUIRED` | Account needs a 2FA code | Ask user for a fresh 6-digit code, retry same command with `--otp <code>` (~30s validity) |
|
|
180
186
|
|
|
181
187
|
## Permission and security boundary declarations
|
|
182
188
|
|
|
@@ -218,8 +224,13 @@ archery-cli workflow detail 42
|
|
|
218
224
|
# After approval, execute
|
|
219
225
|
archery-cli workflow execute 42 --mode auto --dangerous --dry-run
|
|
220
226
|
archery-cli workflow execute 42 --mode auto --dangerous --confirm ct_...
|
|
227
|
+
|
|
228
|
+
# If execution fails, `workflow detail 42` now shows the reason in result[]:
|
|
229
|
+
archery-cli workflow detail 42 --compact # look at result[].error / statusCode
|
|
221
230
|
```
|
|
222
231
|
|
|
232
|
+
**DDL execution + backups.** If a DDL execution fails with `result[].error = "Invalid remote backup information"`, the target Archery environment has not configured backups (no `enable_backup_switch` / no reachable backup database). This is an **Archery configuration prerequisite, not a CLI bug**. Either ask a DBA to configure the backup database, or submit the workflow with backup disabled (`--backup=false`). The cause is visible directly from `workflow detail` (as of 1.0.5), so check `result[]` before escalating.
|
|
233
|
+
|
|
223
234
|
### 2. Query a database and analyze results
|
|
224
235
|
|
|
225
236
|
```bash
|
|
@@ -269,23 +280,37 @@ archery-cli diagnostic kill --instance prod-mysql --threads "12345,12346" --dang
|
|
|
269
280
|
|
|
270
281
|
### 5. Browse data dictionary and table structure
|
|
271
282
|
|
|
283
|
+
**Locating a table/column from a vague ask** (e.g. "how old is 张三") — the comment is your map, don't guess at names:
|
|
284
|
+
|
|
285
|
+
```bash
|
|
286
|
+
# 1. Scan table comments to find the table that matches the concept ("学生")
|
|
287
|
+
archery-cli dict tables --instance prod-mysql --db mydb --db-type mysql --compact
|
|
288
|
+
# → [{"name":"students","comment":"班级学生表"}, ...]
|
|
289
|
+
|
|
290
|
+
# 2. Scan column comments to map the concept to a column ("年龄")
|
|
291
|
+
archery-cli dict table-info --instance prod-mysql --db mydb --db-type mysql --table students --compact
|
|
292
|
+
# → if no age/birthday column exists, STOP guessing — ask the user or derive it.
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Prefer the two steps above over `instance resource` (bare names) and `instance describe` (no comments) whenever the user names a **concept**, not an exact identifier. `dict` requires `--db-type` on v1.8.5.
|
|
296
|
+
|
|
272
297
|
```bash
|
|
273
298
|
# List all tables in a database
|
|
274
|
-
archery-cli dict tables --instance prod-mysql --db mydb
|
|
299
|
+
archery-cli dict tables --instance prod-mysql --db mydb --db-type mysql
|
|
275
300
|
|
|
276
|
-
# Show table metadata and indexes
|
|
277
|
-
archery-cli dict table-info --instance prod-mysql --db mydb --table orders
|
|
301
|
+
# Show table metadata and indexes (includes column_comment)
|
|
302
|
+
archery-cli dict table-info --instance prod-mysql --db mydb --db-type mysql --table orders
|
|
278
303
|
|
|
279
|
-
# Describe table columns
|
|
304
|
+
# Describe table columns (bare structure, no comments — use when the name is already known)
|
|
280
305
|
archery-cli instance describe --instance prod-mysql --db mydb --table orders
|
|
281
306
|
|
|
282
307
|
# List views, triggers, procedures
|
|
283
|
-
archery-cli dict views --instance prod-mysql --db mydb
|
|
284
|
-
archery-cli dict triggers --instance prod-mysql --db mydb
|
|
285
|
-
archery-cli dict procedures --instance prod-mysql --db mydb
|
|
308
|
+
archery-cli dict views --instance prod-mysql --db mydb --db-type mysql
|
|
309
|
+
archery-cli dict triggers --instance prod-mysql --db mydb --db-type mysql
|
|
310
|
+
archery-cli dict procedures --instance prod-mysql --db mydb --db-type mysql
|
|
286
311
|
|
|
287
312
|
# Export data dictionary as HTML
|
|
288
|
-
archery-cli dict export --instance prod-mysql --db mydb --format raw > dict.html
|
|
313
|
+
archery-cli dict export --instance prod-mysql --db mydb --db-type mysql --format raw > dict.html
|
|
289
314
|
```
|
|
290
315
|
|
|
291
316
|
### 6. Binlog parsing and data recovery
|
|
@@ -46,11 +46,17 @@ archery-cli workflow sqlcheck --instance 1 --db mydb --sql "ALTER TABLE users AD
|
|
|
46
46
|
|------|------|-------------|
|
|
47
47
|
| `--fields` | string | Comma-separated output fields |
|
|
48
48
|
|
|
49
|
+
`workflow detail` returns the execution/review result rows in `result[]` (each
|
|
50
|
+
`{stage, stageStatus, errLevel, error, affectedRows, executeTime}`) plus the
|
|
51
|
+
string `statusCode` (e.g. `workflow_exception`). When an execution failed, the
|
|
52
|
+
reason is in `result[].error` — read it before escalating.
|
|
53
|
+
|
|
49
54
|
### `workflow sqlcheck` flags
|
|
50
55
|
|
|
51
56
|
| Flag | Type | Required | Description |
|
|
52
57
|
|------|------|----------|-------------|
|
|
53
|
-
| `--instance` | int |
|
|
58
|
+
| `--instance` | int | one of | Target instance ID (resolved to a name in session mode) |
|
|
59
|
+
| `--instance-name` | string | one of | Target instance name (session mode; wins over `--instance`) |
|
|
54
60
|
| `--db` | string | yes | Target database name |
|
|
55
61
|
| `--sql` | string | yes | SQL to check |
|
|
56
62
|
|
|
@@ -71,13 +77,21 @@ archery-cli workflow submit --name "Add email index" --instance 1 --db mydb \
|
|
|
71
77
|
| Flag | Type | Required | Default | Description |
|
|
72
78
|
|------|------|----------|---------|-------------|
|
|
73
79
|
| `--name` | string | yes | -- | Workflow title |
|
|
74
|
-
| `--instance` | int |
|
|
80
|
+
| `--instance` | int | one of | -- | Target instance ID (resolved to a name in session mode) |
|
|
81
|
+
| `--instance-name` | string | one of | -- | Target instance name (session mode; wins over `--instance`) |
|
|
75
82
|
| `--db` | string | yes | -- | Target database name |
|
|
76
83
|
| `--sql` | string | yes | -- | SQL content |
|
|
77
|
-
| `--group` | int |
|
|
78
|
-
| `--
|
|
84
|
+
| `--group` | int | one of | (auto) | Resource group ID (resolved to a name in session mode) |
|
|
85
|
+
| `--group-name` | string | one of | -- | Resource group name (session mode; wins over `--group`) |
|
|
86
|
+
| `--backup` | bool | no | true | Require backup before execution (needs Archery backups configured; see note below) |
|
|
79
87
|
| `--demand-url` | string | no | -- | Related demand/requirement URL |
|
|
80
88
|
|
|
89
|
+
> **Backup prerequisite:** with `--backup=true` (the default), DDL execution
|
|
90
|
+
> needs Archery's backup feature configured (`enable_backup_switch` + a reachable
|
|
91
|
+
> backup DB). Without it, execution fails with `Invalid remote backup
|
|
92
|
+
> information` (visible in `workflow detail` → `result[].error`). Submit with
|
|
93
|
+
> `--backup=false` to skip backups, or have a DBA configure the backup database.
|
|
94
|
+
|
|
81
95
|
### Audit (approve or reject) a workflow
|
|
82
96
|
|
|
83
97
|
```bash
|