@fateforge/archery-cli 1.0.3 → 1.0.5
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/AGENT.md +1 -1
- package/.agent/AGENT_zh.md +1 -1
- package/.agent/CLI-SPEC.md +121 -7
- package/.agent/CLI-SPEC_zh.md +121 -7
- package/.agent/SEC-SPEC.md +3 -3
- package/.agent/SEC-SPEC_zh.md +3 -3
- package/CHANGELOG.md +40 -0
- package/README.md +11 -3
- package/README_zh.md +11 -3
- package/docs/LIVE-SMOKE-EVIDENCE.md +244 -0
- package/package.json +7 -7
- package/skills/archery-cli/SKILL.md +50 -17
- package/skills/archery-cli/reference/workflow.md +18 -4
package/.agent/AGENT.md
CHANGED
|
@@ -34,7 +34,7 @@ Run in order; close out each step against the matching spec's checklist:
|
|
|
34
34
|
2. **Define the contract** (→ CLI-SPEC.md): implement the envelope, exit-code mapping, and error taxonomy *before* the first command. This is the foundation, not an afterthought.
|
|
35
35
|
3. **Build the self-description set** (→ CLI-SPEC.md §11): `reference` / `context` / `doctor` / `changelog`. `changelog` is derived from CHANGELOG.md and embedded at build time.
|
|
36
36
|
4. **Implement commands**: query commands support `--fields` / `--compact` / pagination; write commands go through dry-run/confirm.
|
|
37
|
-
5. **Evaluate optional patterns** (→ CLI-SPEC.md §
|
|
37
|
+
5. **Evaluate optional patterns** (→ CLI-SPEC.md §16, as needed): tokens expire? → credential lifecycle; long-running jobs? → async jobs; QR/captcha/approval? → human-in-the-loop. Do it only if you need it.
|
|
38
38
|
6. **Set the security tier** (→ SEC-SPEC.md): classify T0/T1/T2, then apply injection defense, least privilege, credential-at-rest, and supply chain by tier.
|
|
39
39
|
7. **Write the Skill** (→ SKILL-SPEC.md): frontmatter (with `requires.bins` + `min_version`), trigger list, error decision tree, usage playbooks.
|
|
40
40
|
8. **Set up distribution** (→ shared REPO-SPEC.md §4b): npm wrapper (`scripts/{run,prepare-npm-platform-packages}.js`), binary not committed.
|
package/.agent/AGENT_zh.md
CHANGED
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
2. **定契约**(→ CLI-SPEC):先实现 envelope、exit code 映射、错误分类,再写第一个命令。这是地基,不要后补。
|
|
35
35
|
3. **建自描述四件套**(→ CLI-SPEC §11):`reference` / `context` / `doctor` / `changelog`。`changelog` 从 CHANGELOG.md 派生、构建时嵌入。
|
|
36
36
|
4. **实现命令**:查询命令支持 `--fields` / `--compact` / 分页;写命令走 dry-run/confirm。
|
|
37
|
-
5. **评估可选模式**(→ CLI-SPEC §
|
|
37
|
+
5. **评估可选模式**(→ CLI-SPEC §16,按需):令牌会过期?→ 凭证生命周期;有长任务?→ 异步 job;要扫码/验证码/审批?→ 人工介入。用得上才做,用不上跳过。
|
|
38
38
|
6. **定安全档**(→ SEC-SPEC):先判 T0/T1/T2 风险档,按档套用注入防护、最小权限、凭证落盘、供应链。
|
|
39
39
|
7. **写 Skill**(→ SKILL-SPEC):frontmatter(含 `requires.bins` + `min_version`)、触发清单、错误决策树、用法剧本。
|
|
40
40
|
8. **配分发**(→ 共享 REPO-SPEC §4b):npm 壳(`scripts/{run,prepare-npm-platform-packages}.js`),二进制不入库。
|
package/.agent/CLI-SPEC.md
CHANGED
|
@@ -123,7 +123,7 @@ Conventions:
|
|
|
123
123
|
| 6 | Precondition conflict or invalid token | re-read state, then retry |
|
|
124
124
|
| 7 | Retryable transient error (network/rate-limit/server) | back off and retry |
|
|
125
125
|
| 8 | Timeout | back off and retry |
|
|
126
|
-
| 9 | Human action required (see §
|
|
126
|
+
| 9 | Human action required (see §16.3, optional) | relay to the user, run `resume` once done |
|
|
127
127
|
|
|
128
128
|
Error codes and exit codes must align:
|
|
129
129
|
|
|
@@ -134,7 +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_HUMAN_REQUIRED` -> 9 (optional, only when §
|
|
137
|
+
- `E_HUMAN_REQUIRED` -> 9 (optional, only when §16.3 is enabled)
|
|
138
138
|
|
|
139
139
|
When the failure comes from an upstream HTTP call, map the status onto the
|
|
140
140
|
taxonomy so the agent can tell failure modes apart from `error.code` +
|
|
@@ -651,11 +651,120 @@ Release verification baseline:
|
|
|
651
651
|
- Also hint in the result: `run "changelog --since <previous_version>" to see what changed`.
|
|
652
652
|
- Agent convention: after self-update, before continuing, read `changelog --since <old version>` (see the SKILL-SPEC recipe).
|
|
653
653
|
|
|
654
|
-
## 15.
|
|
654
|
+
## 15. Batch operations
|
|
655
|
+
|
|
656
|
+
Many write workflows need to act on a batch of objects in one call (close many issues, send to many openids, run one SQL across many instances). A batch command is still **one** agent-facing command with **one** envelope, **one** confirm token, and **one** aggregated result — never a loop the agent has to drive. The contract below is identical whether the batch is served by a native upstream bulk endpoint (class A) or by a client-side loop (class B); the agent must not be able to tell which.
|
|
657
|
+
|
|
658
|
+
### 15.1 Plural inputs
|
|
659
|
+
|
|
660
|
+
- Batch targets use a plural flag: `--ids`, `--symbols`, `--instances`, `--openids`, etc.
|
|
661
|
+
- Each plural flag accepts both **comma-separated** (`--ids 1,2,3`) and **repeatable** (`--ids 1 --ids 2 --ids 3`) forms; the two are equivalent and may be mixed.
|
|
662
|
+
- A single value degrades gracefully: `--ids 1` is a valid batch of one, same envelope as a batch of many. Where a singular flag (`--symbol`) already exists, keep it as a compatibility alias of the plural and declare it deprecated in reference; do not run two divergent code paths.
|
|
663
|
+
- De-duplicate targets before executing and preserve input order in the result `items[]` so the agent can zip results back to inputs deterministically.
|
|
664
|
+
- An empty target list is a usage error (`E_VALIDATION`, exit 2), not a silent no-op.
|
|
665
|
+
|
|
666
|
+
### 15.2 Dry-run summary for a batch
|
|
667
|
+
|
|
668
|
+
`--dry-run` on a batch returns **what will happen to N objects** before any write, plus a single `confirm_token` that covers the whole batch:
|
|
669
|
+
|
|
670
|
+
```json
|
|
671
|
+
{
|
|
672
|
+
"ok": true,
|
|
673
|
+
"schema_version": "1.0",
|
|
674
|
+
"data": {
|
|
675
|
+
"preview": {
|
|
676
|
+
"action": "close",
|
|
677
|
+
"total": 3,
|
|
678
|
+
"targets": ["1042", "1043", "1044"],
|
|
679
|
+
"changes": [
|
|
680
|
+
{ "action": "close", "resource": "issue", "id": "1042" },
|
|
681
|
+
{ "action": "close", "resource": "issue", "id": "1043" },
|
|
682
|
+
{ "action": "close", "resource": "issue", "id": "1044" }
|
|
683
|
+
]
|
|
684
|
+
},
|
|
685
|
+
"confirm_token": "ct_9f2a...",
|
|
686
|
+
"expires_at": "2026-06-15T12:00:00Z"
|
|
687
|
+
},
|
|
688
|
+
"meta": { "duration_ms": 0 }
|
|
689
|
+
}
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
- The preview must state the operation and the full target set, so a human or agent can audit the blast radius before confirming.
|
|
693
|
+
- The token binds the **whole resolved target set** (plus command path, args, account, permission context per §7), so adding or removing a target invalidates it with `E_CONFLICT`.
|
|
694
|
+
|
|
695
|
+
### 15.3 One confirm token covers the whole batch, consumed once
|
|
696
|
+
|
|
697
|
+
- A single `--confirm <token>` from the batch dry-run authorizes the entire batch; the agent does not confirm per item.
|
|
698
|
+
- The token is **single-use** exactly as in §9: it is fingerprinted and marked consumed before the write runs, and any replay is rejected with `E_CONFLICT` ("token already used; re-run `--dry-run`"). This reuses each repo's existing single-consumption confirm infrastructure — batch adds no new token mechanism.
|
|
699
|
+
- On a partial batch failure the token stays consumed; the agent re-runs `--dry-run` (which now resolves to the still-pending targets) rather than replaying the old token.
|
|
700
|
+
|
|
701
|
+
### 15.4 Dangerous batches: `--dangerous` two-step gate
|
|
702
|
+
|
|
703
|
+
Irreversible or high-blast-radius batches — bulk `delete`, MR `merge`, mass send / broadcast — require an extra gate **on top of** dry-run → confirm:
|
|
704
|
+
|
|
705
|
+
- The command must be invoked with `--dangerous`; without it the command fails with `E_CONFIRMATION_REQUIRED` (exit 5) even when a valid confirm token is present.
|
|
706
|
+
- This is a two-step human-intent gate: `--dangerous` declares intent, the confirm token authorizes the specific resolved batch. Both are required; neither alone executes.
|
|
707
|
+
- Reference marks these commands `dangerous: true`, and their `examples[]` show the `--dangerous` form.
|
|
708
|
+
- Tools may layer stricter local policy on a dangerous batch (e.g. per-item confirm, default `--continue-on-error false`, or night-time dry-run-only); such overrides must be declared in reference, not hidden.
|
|
709
|
+
|
|
710
|
+
### 15.5 Per-item aggregated result, no whole-batch rollback
|
|
711
|
+
|
|
712
|
+
Batch results aggregate per item. A partial failure does **not** roll back succeeded items:
|
|
713
|
+
|
|
714
|
+
```json
|
|
715
|
+
{
|
|
716
|
+
"ok": true,
|
|
717
|
+
"schema_version": "1.0",
|
|
718
|
+
"data": {
|
|
719
|
+
"items": [
|
|
720
|
+
{ "target": "1042", "ok": true },
|
|
721
|
+
{ "target": "1043", "ok": true },
|
|
722
|
+
{
|
|
723
|
+
"target": "1044",
|
|
724
|
+
"ok": false,
|
|
725
|
+
"error": { "code": "E_NOT_FOUND", "retryable": false }
|
|
726
|
+
}
|
|
727
|
+
],
|
|
728
|
+
"summary": { "total": 3, "succeeded": 2, "failed": 1 }
|
|
729
|
+
},
|
|
730
|
+
"meta": { "duration_ms": 0 }
|
|
731
|
+
}
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
- Each `items[]` entry carries `target` (the input identifier — `id`, `symbol`, `instance`, …; use the natural key, not an array index), `ok`, and on failure `error` with the same `{ code, retryable }` taxonomy as the top-level envelope (§6).
|
|
735
|
+
- `summary` always reports `{ total, succeeded, failed }`. The counts must equal the item tally.
|
|
736
|
+
- Top-level `ok` is `true` when the batch executed and produced a result, even with per-item failures; per-item status lives in `items[]`. Reserve top-level `ok: false` for a batch that could not run at all (bad args, auth, no targets). Do not hide other items' status because one failed (consistent with §9).
|
|
737
|
+
- `--continue-on-error` controls whether the batch keeps going after the first item failure; **default `true`** (best-effort, finish the batch). Set `--continue-on-error false` to stop at the first failure — already-applied items stay applied (no rollback), and `summary` reflects only attempted items, with the unattempted remainder reported (e.g. `skipped`) so the agent can resume. Dangerous batches may flip the default to `false`; declare it in reference.
|
|
738
|
+
|
|
739
|
+
### 15.6 Upstream caps: client-side auto-chunking
|
|
740
|
+
|
|
741
|
+
When the native bulk endpoint has a per-call limit, the command splits the batch into chunks and submits them sequentially, presenting a single command to the agent:
|
|
742
|
+
|
|
743
|
+
- Known caps: Jira `/issue/bulk`, agile `backlog/issue` and `sprint/{id}/issue` ≤ 50; WeChat openid batches ≤ 100, mass-send openid lists per upstream limit. The command must chunk to the cap; it must not pass a too-large batch straight through and let the upstream 400.
|
|
744
|
+
- Chunking is invisible in the contract: still one envelope, one `confirm_token`, one aggregated `items[]`/`summary` across all chunks.
|
|
745
|
+
- A chunk-level failure is mapped back onto the affected `items[]`; one failed chunk does not fail the whole command (subject to `--continue-on-error`).
|
|
746
|
+
- Keep the chunk size in one shared helper per tool so the cap cannot drift between commands sharing an endpoint.
|
|
747
|
+
|
|
748
|
+
### 15.7 A/B classes, one external contract
|
|
749
|
+
|
|
750
|
+
- **Class A** uses a native upstream bulk endpoint (true server-side batch, possibly atomic per the upstream).
|
|
751
|
+
- **Class B** loops client-side over single-target calls because no native bulk exists.
|
|
752
|
+
- The external contract is identical for both: plural inputs, dry-run summary, single confirm token, dangerous gate, aggregated `items[]`/`summary`, and `--continue-on-error`. The agent cannot and need not tell A from B.
|
|
753
|
+
- Atomicity is **not** part of the external contract. A class-B (or capped, chunked class-A) batch must not claim upstream atomicity; where the upstream genuinely is non-atomic or order-unstable, say so in the output schema / reference rather than implying a transaction.
|
|
754
|
+
|
|
755
|
+
### 15.8 Self-description for batch commands
|
|
756
|
+
|
|
757
|
+
Every batch command carries a real `output_schema` and runnable `examples[]` (per §11):
|
|
758
|
+
|
|
759
|
+
- The schema declares the `items[]` shape (`target`, `ok`, `error{code,retryable}`) and the `summary{total,succeeded,failed}` shape, with attacker-controllable keys listed in `untrusted_fields` (`_untrusted`).
|
|
760
|
+
- `examples[]` show the plural-input dry-run then confirm pair; dangerous batches include `--dangerous`.
|
|
761
|
+
- These must pass the reference guard (non-empty schema + at least one example per leaf command) and count toward FCC (§13) like any other public behavior.
|
|
762
|
+
|
|
763
|
+
## 16. Optional patterns (enable as needed)
|
|
655
764
|
|
|
656
765
|
These three patterns are **not for everyone**: implement them if your tool needs them, ignore them otherwise — zero overhead. They let the spec scale with tool complexity — a simple tool stays light, a complex tool need not reinvent the wheel. Each is marked "when applicable."
|
|
657
766
|
|
|
658
|
-
###
|
|
767
|
+
### 16.1 Credential lifecycle (when tokens expire)
|
|
659
768
|
|
|
660
769
|
**When applicable**: credentials are not static but expire / need refresh — OAuth access_token (WeChat Official Account ~2h), cookie / session (Xiaohongshu), temporary STS credentials, etc. Tools with static username/password skip this section.
|
|
661
770
|
|
|
@@ -677,7 +786,7 @@ These three patterns are **not for everyone**: implement them if your tool needs
|
|
|
677
786
|
- `doctor` adds a `check: "credentials"` item; for near-expiry give `warn` + a renew `fix`.
|
|
678
787
|
- Refresh tokens and secrets are always redacted — never in stdout / stderr / details.
|
|
679
788
|
|
|
680
|
-
###
|
|
789
|
+
### 16.2 Async job lifecycle (long jobs: submit -> poll -> fetch result)
|
|
681
790
|
|
|
682
791
|
**When applicable**: the operation can't return a result synchronously — async SQL execution / approval (Archery), bulk send, scrape/crawl jobs, large exports. Commands that return results synchronously skip this section.
|
|
683
792
|
|
|
@@ -702,7 +811,7 @@ These three patterns are **not for everyone**: implement them if your tool needs
|
|
|
702
811
|
- A `failed` result uses the standard error envelope; `retryable` indicates whether the whole job can be retried.
|
|
703
812
|
- Submission of a write-type long job still goes through `dry-run → confirm`; the `job_id` is created only after confirm.
|
|
704
813
|
|
|
705
|
-
###
|
|
814
|
+
### 16.3 Human-in-the-loop checkpoints (when a human must scan / solve captcha / approve)
|
|
706
815
|
|
|
707
816
|
**When applicable**: a step mid-flow must be completed by a human — QR login / captcha (Xiaohongshu), approver sign-off (Archery), secondary confirmation. Fully automated tools skip this section.
|
|
708
817
|
|
|
@@ -726,7 +835,7 @@ These three patterns are **not for everyone**: implement them if your tool needs
|
|
|
726
835
|
- `details.action` is a stable enum describing what the human must do; `details.resume` gives the command to continue after the human is done.
|
|
727
836
|
- Agent convention: on `E_HUMAN_REQUIRED` → relay `message` and the required action to the user → wait for them → run `resume`; do not auto-retry.
|
|
728
837
|
|
|
729
|
-
##
|
|
838
|
+
## 17. Design checklist
|
|
730
839
|
|
|
731
840
|
> Items marked `(optional)` only apply when the corresponding optional pattern is enabled.
|
|
732
841
|
|
|
@@ -748,6 +857,11 @@ These three patterns are **not for everyone**: implement them if your tool needs
|
|
|
748
857
|
- [ ] (with self-update) post-update returns previous/current version and hints to read changelog
|
|
749
858
|
- [ ] Query commands support `fields` / `compact`
|
|
750
859
|
- [ ] List commands support pagination or explicitly state none is needed
|
|
860
|
+
- [ ] Batch commands take plural inputs (`--ids`/`--symbols`/…), comma-separated or repeatable, single value degrades
|
|
861
|
+
- [ ] Batch dry-run summarizes the full target set; one confirm token covers and is consumed once for the whole batch
|
|
862
|
+
- [ ] Dangerous batches (delete / merge / mass-send) require the `--dangerous` two-step gate
|
|
863
|
+
- [ ] Batch results aggregate `items[].{target,ok,error{code,retryable}}` + `summary{total,succeeded,failed}`, no whole-batch rollback, `--continue-on-error` default true
|
|
864
|
+
- [ ] Capped upstream bulk auto-chunks client-side under one command; A/B classes share one external contract; batch commands ship real `output_schema` + `examples`
|
|
751
865
|
- [ ] Functional Contract Coverage is 100% for public README / Skill / reference / help / context / doctor / changelog / update behavior
|
|
752
866
|
- [ ] Stable releases have recorded live smoke/E2E evidence; otherwise the tool declares `beta`
|
|
753
867
|
- [ ] All times ISO 8601 UTC
|
package/.agent/CLI-SPEC_zh.md
CHANGED
|
@@ -120,7 +120,7 @@
|
|
|
120
120
|
| 6 | 前置条件冲突或 token 失效 | 重新读取状态后重试 |
|
|
121
121
|
| 7 | 可重试瞬时错误(网络/限流/服务端) | 退避后重试 |
|
|
122
122
|
| 8 | 超时 | 退避后重试 |
|
|
123
|
-
| 9 | 需人工介入(见 §
|
|
123
|
+
| 9 | 需人工介入(见 §16.3,可选) | 转述给用户,待其完成后跑 `resume` |
|
|
124
124
|
|
|
125
125
|
错误码与 exit code 必须一致:
|
|
126
126
|
|
|
@@ -131,7 +131,7 @@
|
|
|
131
131
|
- `E_CONFLICT` -> 6
|
|
132
132
|
- `E_NETWORK` / `E_RATE_LIMITED` / `E_SERVER` -> 7
|
|
133
133
|
- `E_TIMEOUT` -> 8
|
|
134
|
-
- `E_HUMAN_REQUIRED` -> 9(可选,仅启用 §
|
|
134
|
+
- `E_HUMAN_REQUIRED` -> 9(可选,仅启用 §16.3 时)
|
|
135
135
|
|
|
136
136
|
当错误来自上游 HTTP 调用时,按状态码映射到错误码,让 agent 能从 `error.code` +
|
|
137
137
|
`retryable` 区分失败类型——不要把所有 4xx 都塌缩成 `E_NETWORK`:
|
|
@@ -591,11 +591,120 @@ release 校验基线:
|
|
|
591
591
|
- 同时在结果中提示:`run "changelog --since <previous_version>" to see what changed`。
|
|
592
592
|
- Agent 约定:自更新后、继续干活前,先读 `changelog --since <旧版本>`(见 SKILL-SPEC 配方)。
|
|
593
593
|
|
|
594
|
-
## 15.
|
|
594
|
+
## 15. 批量操作(Batch operations)
|
|
595
|
+
|
|
596
|
+
很多写操作的现实工作流需要一次对**一批**对象执行(关一批 issue、群发给一批 openid、对一批实例跑同一条 SQL)。批量命令对 Agent 仍是**一条**命令、**一个** envelope、**一个** confirm token、**一份**聚合结果——绝不是要 Agent 自己驱动的循环。下面的契约无论该批量由上游原生 bulk 端点服务(A 类)还是客户端循环实现(B 类)都完全一致;Agent 不应、也不需要分辨是哪一类。
|
|
597
|
+
|
|
598
|
+
### 15.1 复数入参
|
|
599
|
+
|
|
600
|
+
- 批量目标用复数参数:`--ids`、`--symbols`、`--instances`、`--openids` 等。
|
|
601
|
+
- 每个复数参数同时接受 **comma-separated**(`--ids 1,2,3`)与 **repeatable**(`--ids 1 --ids 2 --ids 3`)两种写法;二者等价,可混用。
|
|
602
|
+
- 单值优雅退化:`--ids 1` 是合法的「批量一个」,与批量多个同形 envelope。已存在单数参数(`--symbol`)的,保留为复数的兼容别名并在 reference 标 deprecated,不维护两条分叉代码路径。
|
|
603
|
+
- 执行前对目标去重,并在结果 `items[]` 中保持输入顺序,使 Agent 能确定性地把结果对回输入。
|
|
604
|
+
- 空目标列表是用法错误(`E_VALIDATION`,exit 2),不是静默 no-op。
|
|
605
|
+
|
|
606
|
+
### 15.2 批量的 dry-run 汇总
|
|
607
|
+
|
|
608
|
+
批量的 `--dry-run` 在任何写之前返回**将对 N 个对象做什么**,并给出一个覆盖整批的 `confirm_token`:
|
|
609
|
+
|
|
610
|
+
```json
|
|
611
|
+
{
|
|
612
|
+
"ok": true,
|
|
613
|
+
"schema_version": "1.0",
|
|
614
|
+
"data": {
|
|
615
|
+
"preview": {
|
|
616
|
+
"action": "close",
|
|
617
|
+
"total": 3,
|
|
618
|
+
"targets": ["1042", "1043", "1044"],
|
|
619
|
+
"changes": [
|
|
620
|
+
{ "action": "close", "resource": "issue", "id": "1042" },
|
|
621
|
+
{ "action": "close", "resource": "issue", "id": "1043" },
|
|
622
|
+
{ "action": "close", "resource": "issue", "id": "1044" }
|
|
623
|
+
]
|
|
624
|
+
},
|
|
625
|
+
"confirm_token": "ct_9f2a...",
|
|
626
|
+
"expires_at": "2026-06-15T12:00:00Z"
|
|
627
|
+
},
|
|
628
|
+
"meta": { "duration_ms": 0 }
|
|
629
|
+
}
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
- preview 必须说明操作与完整目标集合,让人或 Agent 在确认前审计影响范围(blast radius)。
|
|
633
|
+
- token 绑定**整个已解析的目标集合**(外加命令路径、参数、账号、权限上下文,见 §7),增减任一目标即令其失效并返回 `E_CONFLICT`。
|
|
634
|
+
|
|
635
|
+
### 15.3 单个 confirm token 覆盖整批,且单次消费
|
|
636
|
+
|
|
637
|
+
- 批量 dry-run 给出的单个 `--confirm <token>` 授权整批;Agent 不逐项确认。
|
|
638
|
+
- token **单次消费**,与 §9 完全一致:写执行前记录指纹并标记已消费,任何重放以 `E_CONFLICT` 拒绝(「token 已用过,请重新 `--dry-run`」)。这沿用各仓现有的 confirm 单次消费基础设施——批量不新增任何 token 机制。
|
|
639
|
+
- 批量部分失败后,token 仍保持已消费;Agent 重新 `--dry-run`(此时只解析到仍待处理的目标),而不是重放旧 token。
|
|
640
|
+
|
|
641
|
+
### 15.4 危险批量:`--dangerous` 两步闸门
|
|
642
|
+
|
|
643
|
+
不可逆或高影响范围的批量——批量 `delete`、MR `merge`、群发 / 广播——在 dry-run → confirm **之上**再加一道闸门:
|
|
644
|
+
|
|
645
|
+
- 命令必须带 `--dangerous` 调用;不带时即使持有有效 confirm token,命令也以 `E_CONFIRMATION_REQUIRED`(exit 5)失败。
|
|
646
|
+
- 这是两步人意闸门:`--dangerous` 声明意图,confirm token 授权具体已解析的那一批。两者缺一不可,任何一个单独都不执行。
|
|
647
|
+
- reference 把这些命令标 `dangerous: true`,其 `examples[]` 展示 `--dangerous` 形式。
|
|
648
|
+
- 工具可在危险批量上叠加更严格的本地策略(如逐项 confirm、默认 `--continue-on-error false`、夜间仅 dry-run);此类覆盖必须在 reference 声明,不得暗藏。
|
|
649
|
+
|
|
650
|
+
### 15.5 逐项聚合结果,不整体回滚
|
|
651
|
+
|
|
652
|
+
批量结果按项聚合。部分失败**不**回滚已成功的项:
|
|
653
|
+
|
|
654
|
+
```json
|
|
655
|
+
{
|
|
656
|
+
"ok": true,
|
|
657
|
+
"schema_version": "1.0",
|
|
658
|
+
"data": {
|
|
659
|
+
"items": [
|
|
660
|
+
{ "target": "1042", "ok": true },
|
|
661
|
+
{ "target": "1043", "ok": true },
|
|
662
|
+
{
|
|
663
|
+
"target": "1044",
|
|
664
|
+
"ok": false,
|
|
665
|
+
"error": { "code": "E_NOT_FOUND", "retryable": false }
|
|
666
|
+
}
|
|
667
|
+
],
|
|
668
|
+
"summary": { "total": 3, "succeeded": 2, "failed": 1 }
|
|
669
|
+
},
|
|
670
|
+
"meta": { "duration_ms": 0 }
|
|
671
|
+
}
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
- 每个 `items[]` 项带 `target`(输入标识——`id`、`symbol`、`instance`……;用自然键,不用数组下标)、`ok`,失败时带 `error`,其 `{ code, retryable }` 分类与顶层 envelope(§6)一致。
|
|
675
|
+
- `summary` 始终报告 `{ total, succeeded, failed }`,计数必须与 item 实际数量相等。
|
|
676
|
+
- 只要批量执行并产出结果,顶层 `ok` 即为 `true`,即便存在逐项失败;逐项状态在 `items[]` 里。顶层 `ok: false` 仅保留给整批根本无法执行的情况(参数错、鉴权、无目标)。不要因为单项失败而隐藏其他项状态(与 §9 一致)。
|
|
677
|
+
- `--continue-on-error` 控制首个失败后是否继续;**默认 `true`**(尽力而为,跑完整批)。设 `--continue-on-error false` 在首个失败处停止——已应用的项保持已应用(不回滚),`summary` 只反映已尝试的项,未尝试的剩余项要报告出来(如 `skipped`),让 Agent 可续跑。危险批量可把默认翻成 `false`,需在 reference 声明。
|
|
678
|
+
|
|
679
|
+
### 15.6 上游有上限:客户端自动分批
|
|
680
|
+
|
|
681
|
+
当原生 bulk 端点有单次调用上限时,命令把批量切成多块顺序提交,对 Agent 仍呈现为一条命令:
|
|
682
|
+
|
|
683
|
+
- 已知上限:Jira `/issue/bulk`、agile `backlog/issue` 与 `sprint/{id}/issue` ≤ 50;微信 openid 批量 ≤ 100,群发 openid 列表按上游上限。命令必须按上限分批,不得把超限批量直接透传让上游 400。
|
|
684
|
+
- 分批在契约里不可见:跨所有块仍是一个 envelope、一个 `confirm_token`、一份聚合 `items[]`/`summary`。
|
|
685
|
+
- 块级失败映射回受影响的 `items[]`;单块失败不令整条命令失败(受 `--continue-on-error` 约束)。
|
|
686
|
+
- 把分批大小收敛到每个工具的一个共享 helper 里,避免共用同一端点的命令间上限漂移。
|
|
687
|
+
|
|
688
|
+
### 15.7 A/B 两类,对外契约一致
|
|
689
|
+
|
|
690
|
+
- **A 类**用上游原生 bulk 端点(真服务端批量,上游可能原子)。
|
|
691
|
+
- **B 类**因无原生 bulk,客户端对单目标调用做循环。
|
|
692
|
+
- 对外契约对两类完全一致:复数入参、dry-run 汇总、单 confirm token、危险闸门、聚合 `items[]`/`summary`、`--continue-on-error`。Agent 无法也无需分辨 A 与 B。
|
|
693
|
+
- 原子性**不**是对外契约的一部分。B 类(或被分批的、有上限的 A 类)批量不得宣称上游原子;上游确实非原子或顺序不稳定时,在 output schema / reference 里如实说明,而不是暗示事务语义。
|
|
694
|
+
|
|
695
|
+
### 15.8 批量命令的自描述
|
|
696
|
+
|
|
697
|
+
每个批量命令带真实的 `output_schema` 与可运行 `examples[]`(见 §11):
|
|
698
|
+
|
|
699
|
+
- schema 声明 `items[]` 形状(`target`、`ok`、`error{code,retryable}`)与 `summary{total,succeeded,failed}` 形状,攻击者可控的键列入 `untrusted_fields`(`_untrusted`)。
|
|
700
|
+
- `examples[]` 展示复数入参的 dry-run 再 confirm 这一对;危险批量带 `--dangerous`。
|
|
701
|
+
- 这些必须通过 reference 守卫(每个叶子命令非空 schema + 至少一条 example),并像其他公开行为一样计入 FCC(§13)。
|
|
702
|
+
|
|
703
|
+
## 16. 可选模式(按需启用)
|
|
595
704
|
|
|
596
705
|
以下三种模式**不是人人必做**:工具用得上就照这里实现,用不上就忽略,零负担。它们让规范随工具复杂度伸缩——简单工具保持轻,复杂工具不必重新发明轮子。每条都标了「何时适用」。
|
|
597
706
|
|
|
598
|
-
###
|
|
707
|
+
### 16.1 凭证生命周期(令牌会过期时)
|
|
599
708
|
|
|
600
709
|
**何时适用**:凭证不是静态的,而是会过期 / 需刷新的——OAuth access_token(微信公众号约 2h)、cookie / session(小红书)、临时 STS 凭证等。静态用户名密码的工具跳过本节。
|
|
601
710
|
|
|
@@ -617,7 +726,7 @@ release 校验基线:
|
|
|
617
726
|
- `doctor` 增一项 `check: "credentials"`,对临近过期给 `warn` + 续期 `fix`。
|
|
618
727
|
- 刷新令牌、secret 一律脱敏,绝不出现在 stdout / stderr / details。
|
|
619
728
|
|
|
620
|
-
###
|
|
729
|
+
### 16.2 异步任务生命周期(长任务:提交 -> 轮询 -> 取结果)
|
|
621
730
|
|
|
622
731
|
**何时适用**:操作不能同步返回结果——SQL 异步执行 / 审批(Archery)、批量群发、采集 / 爬取任务、大导出。同步即得结果的命令跳过本节。
|
|
623
732
|
|
|
@@ -642,7 +751,7 @@ release 校验基线:
|
|
|
642
751
|
- `failed` 的结果用标准 error envelope,`retryable` 指明能否重试整个任务。
|
|
643
752
|
- 写类长任务的提交仍走 `dry-run → confirm`;confirm 后才落 `job_id`。
|
|
644
753
|
|
|
645
|
-
###
|
|
754
|
+
### 16.3 人工介入检查点(需要人来扫码 / 验证码 / 审批时)
|
|
646
755
|
|
|
647
756
|
**何时适用**:流程中途必须由人完成某步——扫码登录 / 验证码(小红书)、审批人放行(Archery)、二次确认等。全自动工具跳过本节。
|
|
648
757
|
|
|
@@ -666,7 +775,7 @@ release 校验基线:
|
|
|
666
775
|
- `details.action` 用稳定枚举说明需要人做什么,`details.resume` 给出人工完成后的续跑命令。
|
|
667
776
|
- Agent 约定:收到 `E_HUMAN_REQUIRED` → 向用户转述 `message` 与所需动作 → 等用户完成 → 跑 `resume`,不自动重试。
|
|
668
777
|
|
|
669
|
-
##
|
|
778
|
+
## 17. 设计检查清单
|
|
670
779
|
|
|
671
780
|
> 标 `(可选)` 的仅当对应可选模式启用时才需勾。
|
|
672
781
|
|
|
@@ -688,6 +797,11 @@ release 校验基线:
|
|
|
688
797
|
- [ ] (含 self-update 时)更新后回传 previous/current 版本并提示读 changelog
|
|
689
798
|
- [ ] 查询命令支持 `fields` / `compact`
|
|
690
799
|
- [ ] 列表命令支持分页或明确说明无需分页
|
|
800
|
+
- [ ] 批量命令用复数入参(`--ids`/`--symbols`/…),comma-separated 或 repeatable,单值退化
|
|
801
|
+
- [ ] 批量 dry-run 汇总完整目标集;单个 confirm token 覆盖整批且单次消费
|
|
802
|
+
- [ ] 危险批量(delete / merge / 群发)需 `--dangerous` 两步闸门
|
|
803
|
+
- [ ] 批量结果聚合 `items[].{target,ok,error{code,retryable}}` + `summary{total,succeeded,failed}`,不整体回滚,`--continue-on-error` 默认 true
|
|
804
|
+
- [ ] 有上限的原生 bulk 由客户端自动分批、对外单条命令;A/B 两类对外契约一致;批量命令带真实 `output_schema` + `examples`
|
|
691
805
|
- [ ] README / Skill / reference / help / context / doctor / changelog / update 中声明的公开行为达到 100% 功能契约覆盖率
|
|
692
806
|
- [ ] Stable release 有真实环境 smoke/E2E 记录;否则工具声明为 `beta`
|
|
693
807
|
- [ ] 所有时间为 ISO 8601 UTC
|
package/.agent/SEC-SPEC.md
CHANGED
|
@@ -93,7 +93,7 @@ Fallback and channel rules:
|
|
|
93
93
|
explicitly.
|
|
94
94
|
- **Minimal memory residency**: discard after use, don't log, don't put in
|
|
95
95
|
stdout/stderr.
|
|
96
|
-
- Token acquire / refresh / expiry lifecycle is in `CLI-SPEC.md §
|
|
96
|
+
- Token acquire / refresh / expiry lifecycle is in `CLI-SPEC.md §16.1`; this section only covers "how to store static data at rest safely."
|
|
97
97
|
|
|
98
98
|
## 5. Supply chain (applies to anything distributed)
|
|
99
99
|
|
|
@@ -116,8 +116,8 @@ Fallback and channel rules:
|
|
|
116
116
|
|----------------|---------------|
|
|
117
117
|
| Output redaction (password / token / cookie out of stdout·stderr·details·audit) | `CLI-SPEC.md §10` |
|
|
118
118
|
| Write dry-run → confirm, token bound to operation | `CLI-SPEC.md §7` |
|
|
119
|
-
| Credential acquire / refresh / expiry lifecycle | `CLI-SPEC.md §
|
|
120
|
-
| Human-in-the-loop (QR / captcha / approval) | `CLI-SPEC.md §
|
|
119
|
+
| Credential acquire / refresh / expiry lifecycle | `CLI-SPEC.md §16.1` |
|
|
120
|
+
| Human-in-the-loop (QR / captcha / approval) | `CLI-SPEC.md §16.3` |
|
|
121
121
|
| Skill permission tiers, only trusted-source Skills | `SKILL-SPEC.md` |
|
|
122
122
|
| No committed secrets, third-party trademark notice, pre-publish check | `REPO-SPEC.md` (OPEN_SOURCE_CHECKLIST / NOTICE) |
|
|
123
123
|
|
package/.agent/SEC-SPEC_zh.md
CHANGED
|
@@ -84,7 +84,7 @@ Agent 侧约定(同时写进 SKILL-SPEC 的用法):
|
|
|
84
84
|
的保护来自用户目录的默认 ACL,或者干脆没有秘密文件(即 keyring 模式)。除非
|
|
85
85
|
显式设置 ACL,否则不要在 Windows 上声称「仅属主可读」。
|
|
86
86
|
- **内存最小驻留**:用完即弃,不写日志、不进 stdout/stderr。
|
|
87
|
-
- 令牌的获取 / 刷新 / 过期生命周期见 `CLI-SPEC.md §
|
|
87
|
+
- 令牌的获取 / 刷新 / 过期生命周期见 `CLI-SPEC.md §16.1`,本节只管「静态落盘怎么存才安全」。
|
|
88
88
|
|
|
89
89
|
## 5. 供应链(凡分发即适用)
|
|
90
90
|
|
|
@@ -100,8 +100,8 @@ Agent 侧约定(同时写进 SKILL-SPEC 的用法):
|
|
|
100
100
|
|--------|---------|
|
|
101
101
|
| 输出脱敏(密码 / token / cookie 不入 stdout·stderr·details·audit) | `CLI-SPEC.md §10` |
|
|
102
102
|
| 写操作 dry-run → confirm,token 绑定操作内容 | `CLI-SPEC.md §7` |
|
|
103
|
-
| 凭证获取 / 刷新 / 过期生命周期 | `CLI-SPEC.md §
|
|
104
|
-
| 人工介入(扫码 / 验证码 / 审批) | `CLI-SPEC.md §
|
|
103
|
+
| 凭证获取 / 刷新 / 过期生命周期 | `CLI-SPEC.md §16.1` |
|
|
104
|
+
| 人工介入(扫码 / 验证码 / 审批) | `CLI-SPEC.md §16.3` |
|
|
105
105
|
| Skill 权限分层、仅用可信来源 Skill | `SKILL-SPEC.md` |
|
|
106
106
|
| 不提交密钥、第三方商标声明、首推前体检 | `REPO-SPEC.md`(OPEN_SOURCE_CHECKLIST / NOTICE) |
|
|
107
107
|
|
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,46 @@ 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.5] - 2026-06-16
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **`--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.
|
|
13
|
+
- **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:
|
|
14
|
+
- 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.
|
|
15
|
+
- 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".
|
|
16
|
+
- 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.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **`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.
|
|
21
|
+
- **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`.
|
|
22
|
+
- **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.
|
|
23
|
+
|
|
24
|
+
### Notes
|
|
25
|
+
|
|
26
|
+
- **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`).
|
|
27
|
+
|
|
28
|
+
## [1.0.4] - 2026-06-16
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- **Dual-mode transport — default `session`, REST `jwt` optional.** Login and every request now run over Archery's web (session + AJAX) endpoints by default, so a **plain developer account** can drive the CLI. REST + JWT is kept as an opt-in advanced mode via `--mode jwt` (a persistent flag) or a region's `mode` config. Mode precedence is `--mode` flag → region config → `session` default.
|
|
33
|
+
- **Why:** Archery's `/api/v1` REST surface is closed to ordinary accounts (`403`) and is not enabled on older or most real-world deployments. The web session path (`/authenticate/`, `/sqlworkflow_list/`, `/sqlquery/`, …) works on **all versions and for ordinary accounts**, which is what most users actually have.
|
|
34
|
+
- **Live-verified** against a local `hhyo/archery:v1.8.5` container with an ordinary (`cli_verify`) account: commands that return `403` under REST — `workflow list`, `instance list`, `user list`, `query log`, and others — all return `200` with real data over the session path.
|
|
35
|
+
- **New operational commands** (learned from real Archery ops Skills), all supported on the session path:
|
|
36
|
+
- `instance create-db` — create a database on an instance.
|
|
37
|
+
- `instance create-user` — create a database account.
|
|
38
|
+
- `instance grant` — grant/revoke privileges (`--op grant|revoke`).
|
|
39
|
+
- `instance test-instance` — connectivity probe.
|
|
40
|
+
- `user resourcegroup-add` — add users/instances to a resource group.
|
|
41
|
+
- `workflow audit-list` — list workflows awaiting audit.
|
|
42
|
+
- `workflow auto-review` — classify SQL by the auto-review rules and optionally approve compliant workflows.
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- All 54 existing business commands now resolve over the session path by default; the JWT/REST path remains available unchanged via `--mode jwt`.
|
|
47
|
+
|
|
8
48
|
## [1.0.3] - 2026-06-15
|
|
9
49
|
|
|
10
50
|
### Added
|
package/README.md
CHANGED
|
@@ -39,18 +39,24 @@ PowerShell uses `$env:NAME = "value"` for the same environment variables. Keep r
|
|
|
39
39
|
|
|
40
40
|
`archery-cli` is designed for AI Agents first. JSON is the default output, the live command surface is discoverable through `archery-cli reference`, and mutating flows use a non-interactive `--dry-run` to `--confirm <confirm_token>` sequence where the tool supports writes.
|
|
41
41
|
|
|
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
|
+
|
|
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
|
+
|
|
42
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).
|
|
43
49
|
|
|
44
50
|
## Capabilities
|
|
45
51
|
|
|
46
52
|
| Area | Commands | Agent use |
|
|
47
53
|
|------|----------|-----------|
|
|
48
|
-
| SQL workflows | `workflow list / submit / detail / audit / execute / cancel / sqlcheck` | Submit, review, execute, and cancel SQL workflow operations. |
|
|
54
|
+
| SQL workflows | `workflow list / submit / detail / audit / audit-list / auto-review / execute / cancel / sqlcheck` | Submit, review, auto-review, execute, and cancel SQL workflow operations. |
|
|
49
55
|
| Queries | `query run / explain / log / favorite / generate` | Run controlled SQL queries and inspect query history. |
|
|
50
|
-
| Instances | `instance list / detail / resource / describe / create / update / delete` | Inspect and manage
|
|
56
|
+
| Instances | `instance list / detail / resource / describe / create / update / delete / create-db / create-user / grant / test-instance` | Inspect and manage instances, databases, accounts, and privileges. |
|
|
51
57
|
| Diagnostics | `diagnostic process / kill / tablespace / locks / transactions` | Inspect runtime database health and controlled diagnostic actions. |
|
|
52
58
|
| Binlog and archive | `binlog list / parse / purge`, `archive list / apply / audit / switch / once / log` | Operate Archery binlog and archive workflows. |
|
|
53
|
-
| Dictionary and users | `dict ...`, `user
|
|
59
|
+
| Dictionary and users | `dict ...`, `user list / groups / resource-groups / resourcegroup-add`, `auth ...`, `context`, `doctor`, `reference`, `changelog`, `update` | Discover metadata, manage resource groups, account state, and the live command contract. |
|
|
54
60
|
|
|
55
61
|
The README is intentionally a map, not the full manual. Agents should call `archery-cli reference --compact` for exact flags, schemas, permissions, exit codes, and error codes before executing task commands.
|
|
56
62
|
|
|
@@ -84,6 +90,8 @@ Config location: `~/.archery-cli/config.json`.
|
|
|
84
90
|
| `ARCHERY_CLI_USERNAME` | Username |
|
|
85
91
|
| `ARCHERY_CLI_PASSWORD` | Password |
|
|
86
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`) |
|
|
87
95
|
| `NO_COLOR` | Disable colored text output when text mode is explicitly requested |
|
|
88
96
|
|
|
89
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
|
@@ -39,18 +39,24 @@ PowerShell 使用 `$env:NAME = "value"` 设置同样的环境变量。真实密
|
|
|
39
39
|
|
|
40
40
|
`archery-cli` 是 AI Agent 优先的 CLI。默认输出 JSON,实时命令面通过 `archery-cli reference` 发现;支持写操作的命令使用非交互的 `--dry-run` 到 `--confirm <confirm_token>` 流程。
|
|
41
41
|
|
|
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
|
+
|
|
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
|
+
|
|
42
48
|
最坏情况风险等级:**T2 高风险** - 可对已配置数据库实例执行和管理 SQL 工单。参见 [SECURITY.md](SECURITY.md) 和 [.agent/SEC-SPEC.md](.agent/SEC-SPEC.md)。
|
|
43
49
|
|
|
44
50
|
## 能力
|
|
45
51
|
|
|
46
52
|
| 领域 | 命令 | Agent 用法 |
|
|
47
53
|
|------|------|------------|
|
|
48
|
-
| SQL 工单 | `workflow list / submit / detail / audit / execute / cancel / sqlcheck` |
|
|
54
|
+
| SQL 工单 | `workflow list / submit / detail / audit / audit-list / auto-review / execute / cancel / sqlcheck` | 提交、审核、自动审核、执行和取消 SQL 工单。 |
|
|
49
55
|
| 查询 | `query run / explain / log / favorite / generate` | 执行受控 SQL 查询并查看查询历史。 |
|
|
50
|
-
| 实例 | `instance list / detail / resource / describe / create / update / delete
|
|
56
|
+
| 实例 | `instance list / detail / resource / describe / create / update / delete / create-db / create-user / grant / test-instance` | 查看和管理实例、数据库、账号与权限。 |
|
|
51
57
|
| 诊断 | `diagnostic process / kill / tablespace / locks / transactions` | 查看数据库运行状态并执行受控诊断操作。 |
|
|
52
58
|
| Binlog 与归档 | `binlog list / parse / purge`, `archive list / apply / audit / switch / once / log` | 操作 Archery binlog 与归档流程。 |
|
|
53
|
-
| 字典与账号 | `dict ...`, `user
|
|
59
|
+
| 字典与账号 | `dict ...`, `user list / groups / resource-groups / resourcegroup-add`, `auth ...`, `context`, `doctor`, `reference`, `changelog`, `update` | 发现元数据、管理资源组、账号状态和实时命令契约。 |
|
|
54
60
|
|
|
55
61
|
README 只做地图,不做完整手册。Agent 在执行任务命令前,应调用 `archery-cli reference --compact` 获取准确的 flags、schemas、权限、退出码和错误码。
|
|
56
62
|
|
|
@@ -84,6 +90,8 @@ README 只做地图,不做完整手册。Agent 在执行任务命令前,应
|
|
|
84
90
|
| `ARCHERY_CLI_USERNAME` | 用户名 |
|
|
85
91
|
| `ARCHERY_CLI_PASSWORD` | 密码 |
|
|
86
92
|
| `ARCHERY_CLI_REGION` | 当前区域/profile |
|
|
93
|
+
| `ARCHERY_CLI_READONLY` | 任意非空值即禁用所有写命令(等价于 `--read-only`) |
|
|
94
|
+
| `ARCHERY_CLI_OTP` | 开启 2FA 账号的 6 位验证码(等价于 `--otp`) |
|
|
87
95
|
| `NO_COLOR` | 显式使用 text 模式时禁用彩色输出 |
|
|
88
96
|
|
|
89
97
|
支持保存凭据时,凭据会加密或进入 OS 凭据库。环境变量优先级更高,也是短生命周期 Agent 会话的推荐方式。
|
|
@@ -13,6 +13,90 @@ from scratch for this acceptance.
|
|
|
13
13
|
asserted. JWT cached in the OS keyring; session-mode commands authenticate
|
|
14
14
|
via the Django form login.
|
|
15
15
|
|
|
16
|
+
## 2026-06-15 — `instance` group, session (AJAX) path
|
|
17
|
+
|
|
18
|
+
Live run of every `instance` leaf command against the running
|
|
19
|
+
`tools-e2e-archery` (`hhyo/archery:v1.8.5`, the production version) on
|
|
20
|
+
`localhost:9123`, default **session** mode, superuser `cli_verify`. Reads
|
|
21
|
+
verified end-to-end; session-native writes (`create-db`, `create-user`,
|
|
22
|
+
`grant`) really submitted against `e2e-mysql` (instance #1) and cleaned up;
|
|
23
|
+
REST-only writes verified through dry-run + contract.
|
|
24
|
+
|
|
25
|
+
### Result by command
|
|
26
|
+
|
|
27
|
+
| Command | Transport | Status | Note |
|
|
28
|
+
|---|---|---|---|
|
|
29
|
+
| `instance list` | `POST /instance/list/` | **live PASS** | returns `e2e-mysql`; `--db-type`, `--search`, text table all OK |
|
|
30
|
+
| `instance detail <id>` | `POST /instance/list/` (scan) | **live PASS** | found #1; #999 → clean `E_NOT_FOUND` 404 |
|
|
31
|
+
| `instance resource --type database\|table\|column` | `GET /instance/instance_resource/` | **live PASS** | uses `tb_name`; rows normalized to `{name:…}` |
|
|
32
|
+
| `instance describe` | `POST /instance/describetable/` | **live PASS** | v1.8.5 returns `SHOW CREATE TABLE` (column_list + rows zipped); `Create Table`/`Comment` tagged untrusted |
|
|
33
|
+
| `instance users [--saved]` | `POST /instance/user/list` (no trailing slash) | **live PASS** | rows at top level, not under `data`; privileges tagged untrusted |
|
|
34
|
+
| `instance test-instance` | `POST /check/instance/` | **live PASS** | `reachable:true` |
|
|
35
|
+
| `instance create-db` | `POST /instance/database/create/` | **live PASS** | real DB created + dropped; owner required by the view |
|
|
36
|
+
| `instance create-user` | `POST /instance/user/create/` | **live PASS** | real account created (`password1==password2`) + dropped |
|
|
37
|
+
| `instance grant` (grant/revoke, global/db) | `POST /instance/user/grant/` | **live PASS** | executed GRANT/REVOKE SQL returned + tagged untrusted |
|
|
38
|
+
| `instance create` | `POST /api/v1/instance/` | **dry-run PASS; real = REST-only** | session has no AJAX CRUD route; real submit needs `--mode jwt` |
|
|
39
|
+
| `instance update <id>` | `PUT /api/v1/instance/<id>/` | **dry-run PASS; real = REST-only** | same as create |
|
|
40
|
+
| `instance delete <id>` | `DELETE /api/v1/instance/<id>/` | **dry-run PASS; real = REST-only** | same as create |
|
|
41
|
+
| `instance import --file` | `POST /api/v1/instance/` per row | **dry-run PASS; real = REST-only** | CSV/JSON manifest preview correct |
|
|
42
|
+
|
|
43
|
+
`create`/`update`/`delete`/`import` are REST-only by design: v1.8.5's
|
|
44
|
+
`views.instance` only renders an HTML page and the UI edits instances via Django
|
|
45
|
+
admin (`/admin/sql/instance/…`); the programmatic CRUD route is DRF
|
|
46
|
+
`/api/v1/instance/`, which requires JWT. In session mode their dry-run/confirm
|
|
47
|
+
contract is correct and the real submit honestly surfaces `E_AUTH` until
|
|
48
|
+
`--mode jwt` is used.
|
|
49
|
+
|
|
50
|
+
### Defects found and fixed by this run
|
|
51
|
+
|
|
52
|
+
1. **Stale session cookie poisoned lazy re-login.** When `ensureSession` fell
|
|
53
|
+
through to a fresh form-login with an already-authenticated `sessionid` in
|
|
54
|
+
the jar, Archery's `/authenticate/` took a branch returning a `session_key`
|
|
55
|
+
in `data` with no new `Set-Cookie`, so `hasSessionCookie()` stayed false and
|
|
56
|
+
login spuriously failed with `session login failed: ok`. Fix: clear
|
|
57
|
+
`sessionid`/`csrftoken` from the jar before a fresh form-login so it always
|
|
58
|
+
starts clean (`clearSessionCookies`, `internal/api/client.go`).
|
|
59
|
+
2. **`instance grant` emitted invalid SQL.** The grant view splices `user_host`
|
|
60
|
+
straight into `GRANT … TO <x>`, so the friendly `user@host` produced
|
|
61
|
+
`… TO e2e_probe@%;` → MySQL `1064` syntax error near `'%'`. Fix: normalize
|
|
62
|
+
`--user-host` to the backtick-quoted `` `user`@`host` `` form (pass an
|
|
63
|
+
already-quoted value through), with host defaulting to `%` (`quoteUserHost`,
|
|
64
|
+
`cmd/instance.go`; covered by `TestQuoteUserHost`).
|
|
65
|
+
|
|
66
|
+
### Note
|
|
67
|
+
|
|
68
|
+
`instance resource --type database` is served behind Archery's `@cache_page`
|
|
69
|
+
(Redis `…insRes…` key), so a freshly dropped database lingers in the list until
|
|
70
|
+
the cache expires — a server-side cache, not a CLI defect.
|
|
71
|
+
## 2026-06-16 — `user` group, v1.8.5 session path
|
|
72
|
+
|
|
73
|
+
Live-verified the `user` command group against `hhyo/archery:v1.8.5`
|
|
74
|
+
(`tools-e2e-archery`, the company production version) on `localhost:9123`,
|
|
75
|
+
authenticated as the superuser `cli_verify` via the default session transport
|
|
76
|
+
(lazy Django form login; credentials supplied through `ARCHERY_CLI_*` env vars,
|
|
77
|
+
`ARCHERY_CLI_NO_KEYRING=1`). Endpoints cross-checked against the container's
|
|
78
|
+
`sql/urls.py`, `sql/user.py`, and `sql/resource_group.py`.
|
|
79
|
+
|
|
80
|
+
| Command | Transport | Status | Notes |
|
|
81
|
+
|---|---|---|---|
|
|
82
|
+
| `user list` | session `GET /user/list/` | **live** | 2 users; client-side `--search`/`--offset`/`--limit` and `has_more` verified; table + JSON envelopes correct |
|
|
83
|
+
| `user resource-groups` | session `POST /group/group/` | **live** | 1 group `smoke-rg`; server-side `--search` match + empty-set verified; `activeUsers`/`bindUsers` are 0 in session projection (documented) |
|
|
84
|
+
| `user groups` | session gate → JWT `GET /api/v1/user/group/` | **live** | session mode returns a clean `E_NOT_FOUND` gate (no session JSON route in v1.8.5); JWT path returns 5/6 groups parsed correctly |
|
|
85
|
+
| `user resourcegroup-add` | session `POST /group/addrelation/` | **live** | dry-run `confirm_token` → confirm added user 2 to group 1; upstream membership change verified in DB; validation guards (`--type`/`--ids`/bad id/`--group`) all return `E_VALIDATION`; cleaned up after |
|
|
86
|
+
|
|
87
|
+
**Defects found:** none. The `user` implementation matched v1.8.5 routes and
|
|
88
|
+
payload shapes exactly; all four leaf commands passed on the session path
|
|
89
|
+
(plus the JWT fallback for `groups`).
|
|
90
|
+
|
|
91
|
+
**Verification-only deployment toggles (restored after):**
|
|
92
|
+
- `api_user_whitelist` temporarily `1,2` (added `cli_verify` id 2) to exercise
|
|
93
|
+
the JWT `user groups` path — the REST API gates non-whitelisted users with
|
|
94
|
+
403 `IsInUserWhitelist`, which is a deployment config, not a CLI defect.
|
|
95
|
+
Restored to `1`.
|
|
96
|
+
- `cli_verify` (id 2) temporarily added to resource group `smoke-rg` (id 1) by
|
|
97
|
+
the `resourcegroup-add` confirm run; removed afterward (members back to
|
|
98
|
+
`[admin]`).
|
|
99
|
+
|
|
16
100
|
## 2026-06-15 — batch commands (`--ids` / `--instances` / `--file`)
|
|
17
101
|
|
|
18
102
|
Smoke for the new client-side batch contract (CLI-SPEC §15) against the same
|
|
@@ -148,6 +232,166 @@ resource groups. With an unassociated instance Archery returns
|
|
|
148
232
|
`{"status":1,"msg":"你所在组未关联该实例","data":[]}`; this is an Archery
|
|
149
233
|
authorization config, not a CLI defect.
|
|
150
234
|
|
|
235
|
+
## 2026-06-15 — `query` group, session path (v1.8.5)
|
|
236
|
+
|
|
237
|
+
Full live verification of the `query` command group against
|
|
238
|
+
`hhyo/archery:v1.8.5` on `localhost:9123` (= company production version), using
|
|
239
|
+
a superuser (`cli_verify`) in session mode (the default). Credentials supplied
|
|
240
|
+
via `ARCHERY_CLI_URL`/`USERNAME`/`PASSWORD`; each call performs the Django form
|
|
241
|
+
login (GET `/login/` → POST `/authenticate/`) then the AJAX request with
|
|
242
|
+
`X-CSRFToken`. No credentials, hostnames, or real query contents reproduced
|
|
243
|
+
here.
|
|
244
|
+
|
|
245
|
+
### Result by command
|
|
246
|
+
|
|
247
|
+
| Command | Mode | Result |
|
|
248
|
+
|---|---|---|
|
|
249
|
+
| `query log` | **live (read)** | PASS — offset envelope (`count`/`has_more`/`items`) and `total` agree; `sql`/`alias` tagged `_untrusted`; `--star` filter reflects favorite state. `username` is empty because v1.8.5's `_querylog` returns a blank `user_display` (server data, not a CLI defect). |
|
|
250
|
+
| `query explain` | **live (read)** | PASS — `EXPLAIN SELECT 1` returns the zipped plan (`plan[]` of `{col:val}`, `_untrusted`); a non-EXPLAIN statement now surfaces the server reason. Required a CLI fix (see below). |
|
|
251
|
+
| `query run` | **live (high-risk write)** | PASS — `--dangerous` gate refuses even `--dry-run` without it (`E_CONFIRMATION_REQUIRED`); dry-run emits `preview` + `confirm_token`; confirmed real `SELECT` returns `columns`/`rows`/`row_count` with `rows` tagged `_untrusted`. Batch `--instances` aggregates `items[]` + `summary`; text format renders. SELECT-only, no DB state changed. |
|
|
252
|
+
| `query favorite` | **live (write)** | PASS — dry-run preview + `confirm_token`; confirmed star (with `--alias`) visible via `query log --star` (`favorite:true`); unstarred afterward to leave the env clean (`--star` count back to 0). |
|
|
253
|
+
| `query generate` | **contract (gated)** | PASS — fails fast with `E_NOT_FOUND` (exit 3); confirmed server-side `POST /query/generate_sql/` returns HTTP 404 on v1.8.5, so the gate matches reality. |
|
|
254
|
+
|
|
255
|
+
### Defect found and fixed by this run
|
|
256
|
+
|
|
257
|
+
1. **`query explain` buried the server reason on rejection.** On a non-EXPLAIN
|
|
258
|
+
statement the view returns `{"status":1,"msg":"仅支持explain开头的语句…","data":[]}`
|
|
259
|
+
— `data` is an empty **array**, but the CLI decoded `data` straight into the
|
|
260
|
+
`{column_list, rows}` object struct, so JSON unmarshal failed first and the
|
|
261
|
+
user saw `cannot unmarshal array into … queryExplainDataSet` instead of the
|
|
262
|
+
real message. Fixed by decoding `data` as `json.RawMessage` and binding it to
|
|
263
|
+
the typed struct only **after** the `status` check passes (the
|
|
264
|
+
`json.RawMessage` deferred-decode pattern already used by `dict`/`instance`/
|
|
265
|
+
`workflow`). Success path (object) unchanged; rejection path now surfaces
|
|
266
|
+
`msg`. Covered by `TestQueryExplainResponseDecode` (now exercises both the
|
|
267
|
+
object success shape and the `data:[]` rejection envelope).
|
|
268
|
+
|
|
269
|
+
## 2026-06-15 — `workflow` group, session path (v1.8.5)
|
|
270
|
+
|
|
271
|
+
Full live verification of the `workflow` command group against
|
|
272
|
+
`hhyo/archery:v1.8.5` on `localhost:9123` (= company production version), using
|
|
273
|
+
a superuser (`cli_verify`) in session mode (the default). Credentials supplied
|
|
274
|
+
via `ARCHERY_CLI_URL`/`USERNAME`/`PASSWORD`; each call performs the Django form
|
|
275
|
+
login then the AJAX request with `X-CSRFToken`. No credentials, hostnames, or
|
|
276
|
+
real workflow contents reproduced here.
|
|
277
|
+
|
|
278
|
+
### Result by command
|
|
279
|
+
|
|
280
|
+
| Command | Mode | Result |
|
|
281
|
+
|---|---|---|
|
|
282
|
+
| `workflow list` | **live (read)** | PASS — `/sqlworkflow_list/` offset envelope (`items`/`count`/`total`/`has_more`); `--status`/`--search`/`--limit`/`--offset` applied; `title` tagged `_untrusted`; row `statusCode`/`status` mapped. |
|
|
283
|
+
| `workflow audit-list` | **live (read)** | PASS — `/sqlworkflow_list_audit/` same shape; empty set when nothing pending. |
|
|
284
|
+
| `workflow detail <id>` | **live (read)** | PASS — `/sqlworkflow/detail_content/`; SQL content reconstructed from the review rows, `sql`+`title` `_untrusted`. Metadata fields (title/db/created) are blank by design — v1.8.5's `detail_content` returns only review rows, no metadata endpoint exists (documented in `workflow.go`). |
|
|
285
|
+
| `workflow sqlcheck` | **live (read)** | PASS — `/simplecheck/` returns per-statement `{errlevel,level,message,stagestatus,affected_rows,sql}`; `SELECT` correctly rejected (DML/DDL only), clean DDL → `errlevel 0`, keyword DDL → `errlevel 1` warning. |
|
|
286
|
+
| `workflow auto-review` (classify) | **live (read)** | PASS — same `/simplecheck/` engine; clean DDL → `compliant:true blocked:0`, warning DDL → `compliant:false blocked:1` (`verdict:block` on the non-zero `errlevel` row). |
|
|
287
|
+
| `workflow submit` | **live (write)** | PASS — dry-run `preview`+`confirm_token`; confirmed real submit → `/autoreview/` 302 redirect, workflow id parsed from `Location`; new workflow visible via `list` at `workflow_manreviewing`. Medium-tier (no `--dangerous`). |
|
|
288
|
+
| `workflow audit` (single) | **live (reversible)** | PASS — dry-run preview; confirmed `--action pass` → `/passed/`; status advanced to `workflow_review_pass`. `--action cancel` correctly routes to the Cancel view. |
|
|
289
|
+
| `workflow audit --ids` (batch) | **live (reversible)** | PASS — shared single `confirm_token`, `items[]`+`summary{total,succeeded,failed,skipped}`; two workflows passed, `succeeded:2`. |
|
|
290
|
+
| `workflow auto-review --execute` | **live (reversible)** | PASS — classified compliant, then approved the listed `--ids` via the batch audit path (shared confirm token, `succeeded:1`). Without `--execute` it stays a read-only classify. |
|
|
291
|
+
| `workflow execute` | **live drive + contract (high-risk)** | PARTIAL — `--dangerous` double-gate verified (dry-run without it → `E_CONFIRMATION_REQUIRED`); dry-run `preview`+`confirm_token`; confirmed execute reaches the real engine (`/execute/`, status transitions). Terminal status is `workflow_exception` because GoInception's own backup requires MySQL binlog, which is **off** in this `mysql:5.7` e2e container (`binlog日志未开启,无法备份`) — an environment constraint, not a CLI defect. No DDL was applied (engine failed at the CHECKED stage). CLI contract fully verified. |
|
|
292
|
+
| `workflow cancel` | **live (reversible)** | PASS — dry-run preview; confirmed `/cancel/` with `cancel_remark`; status → `workflow_abort`. |
|
|
293
|
+
| `workflow list --mode jwt` | **contract** | PASS — REST path returns a clean `E_FORBIDDEN` (session auth is not a Bearer token); JWT is opt-in and out of scope for the session run. |
|
|
294
|
+
|
|
295
|
+
### Defects found and fixed by this run
|
|
296
|
+
|
|
297
|
+
None. Every `workflow` session-mode endpoint and payload matched v1.8.5 as
|
|
298
|
+
shipped; no `archery-cli` code change was needed for the workflow group.
|
|
299
|
+
|
|
300
|
+
### Environment provisioning (not CLI changes)
|
|
301
|
+
|
|
302
|
+
The fresh e2e container had no workflow-capable data, so the following Archery
|
|
303
|
+
config was provisioned in the isolated container to exercise the write path
|
|
304
|
+
(reversible, no CLI code involved). The blockers were surfaced cleanly by the
|
|
305
|
+
CLI before each fix:
|
|
306
|
+
|
|
307
|
+
1. **GoInception unconfigured** (`connect() argument 1 must be str, not None`) —
|
|
308
|
+
set `go_inception_host=goinception`, `go_inception_port=4000` (the reachable
|
|
309
|
+
`tools-e2e-goinception` container).
|
|
310
|
+
2. **Instance had no tags** (`你所在组未关联该实例`) — added the `can_write` /
|
|
311
|
+
`can_read` tags to `e2e-mysql`, which the submit RBAC check requires.
|
|
312
|
+
3. **No audit flow** (`Column 'audit_auth_groups' cannot be null`) — created a
|
|
313
|
+
`WorkflowAuditSetting` for the resource group (workflow_type 2 = sqlreview)
|
|
314
|
+
and an auth group `cli_verify_auditors` containing the verify user.
|
|
315
|
+
|
|
316
|
+
All verification workflows (and their audit/log records) were deleted from the
|
|
317
|
+
container afterward; no `cli_verify*` tables were created on the target DB
|
|
318
|
+
(execute never reached the apply stage). The enabling config above was left in
|
|
319
|
+
place so the shared e2e stack stays workflow-capable.
|
|
320
|
+
|
|
321
|
+
## 2026-06-15 — `dict` group, session path (v1.8.5)
|
|
322
|
+
|
|
323
|
+
Real-machine verification of the `dict` command group against
|
|
324
|
+
`tools-e2e-archery` (`hhyo/archery:v1.8.5`) as `cli_verify` (superuser), session
|
|
325
|
+
mode. Target instance `e2e-mysql` (mysql), db `archery` (45 tables). No secrets
|
|
326
|
+
recorded.
|
|
327
|
+
|
|
328
|
+
### Result by command
|
|
329
|
+
|
|
330
|
+
| Command | Class | Result |
|
|
331
|
+
| --- | --- | --- |
|
|
332
|
+
| `dict tables` | live (read) | PASS — `--instance e2e-mysql --db archery --db-type mysql` returns 45 tables, `{ok,data:{instance,db,tables[],count}}` envelope; `tables[].comment` tagged `_untrusted`. |
|
|
333
|
+
| `dict table-info` | live (read) | PASS — `--table sql_instance` returns `meta_data`/`desc`/`index`/`create_sql`; text mode renders Metadata/Columns/Indexes tables. |
|
|
334
|
+
| `dict export` | live (read) | PASS — `--db archery` streams the table-structure HTML FileResponse (≈254 KB); raw/text print it verbatim, JSON wraps it in `{format:"html",content}`. |
|
|
335
|
+
| `dict views` | gate (contract) | PASS — no `/data_dictionary/view_list/` route in v1.8.5; fails fast with `E_NOT_FOUND` + upgrade message (exit 3), never touches upstream. |
|
|
336
|
+
| `dict triggers` | gate (contract) | PASS — same gate for `trigger_list`. |
|
|
337
|
+
| `dict procedures` | gate (contract) | PASS — same gate for `procedure_list`. |
|
|
338
|
+
|
|
339
|
+
Gate honesty confirmed against `sql/urls.py` in the container: v1.8.5 ships only
|
|
340
|
+
`table_list`, `table_info`, `export` under `data_dictionary/`.
|
|
341
|
+
|
|
342
|
+
### Defect found and fixed by this run
|
|
343
|
+
|
|
344
|
+
**`--db-type` was optional but the v1.8.5 view requires it.** `table_list` and
|
|
345
|
+
`table_info` resolve the instance via
|
|
346
|
+
`Instance.objects.get(instance_name=…, db_type=…)` — `db_type` is part of the
|
|
347
|
+
lookup key. The CLI sent `db_type` only when the flag was present, so the common
|
|
348
|
+
case (omitting it) returned `{"status":1,"msg":"Instance.DoesNotExist"}` and
|
|
349
|
+
surfaced as a confusing `E_VALIDATION`. Fix: `--db-type` is now **required** for
|
|
350
|
+
`dict tables` and `dict table-info` (validated before the request), with a guard
|
|
351
|
+
test (`TestDictDbTypeRequired`) and updated flag help. `dict export` is
|
|
352
|
+
unaffected — its view keys on `user_instances(...).get(instance_name=…)` with no
|
|
353
|
+
`db_type`, so the CLI correctly omits it there.
|
|
354
|
+
|
|
355
|
+
### Environment note (not a CLI change)
|
|
356
|
+
|
|
357
|
+
`localhost` resolves to IPv6 `::1` on the verifier host, where the GET /login/
|
|
358
|
+
csrftoken and the POST /authenticate/ landed on different bindings and login
|
|
359
|
+
intermittently returned `用户名或密码错误`. Using `http://127.0.0.1:9123`
|
|
360
|
+
(IPv4) made session login deterministic. This is a host DNS artifact, not a CLI
|
|
361
|
+
defect; the session login flow itself (GET csrf → POST authenticate → cookie)
|
|
362
|
+
matches the verified curl flow byte-for-byte.
|
|
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
|
+
|
|
151
395
|
## Reproduce
|
|
152
396
|
|
|
153
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.5",
|
|
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.5"
|
|
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.5"}}
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# archery-cli
|
|
@@ -13,8 +13,8 @@ Archery SQL audit platform CLI for AI Agents. Manage SQL workflows, queries, ins
|
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
15
|
# Please install archery-cli and use it for all Archery SQL audit platform operations going forward.
|
|
16
|
-
#
|
|
17
|
-
|
|
16
|
+
# Install CLI
|
|
17
|
+
npm install -g @fateforge/archery-cli
|
|
18
18
|
|
|
19
19
|
# Install CLI Skill (required) -- copies into your agent-supported skills directory
|
|
20
20
|
npx skills add fatecannotbealtered/archery-cli -y -g
|
|
@@ -57,6 +57,11 @@ First-time setup: ask user for Archery URL + credentials, then run `archery-cli
|
|
|
57
57
|
| Writes | `--dry-run` first, inspect `data.preview`, then retry with `--confirm <confirm_token>` from `data.confirm_token` |
|
|
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
|
+
| 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`). |
|
|
60
65
|
|
|
61
66
|
## Trigger list
|
|
62
67
|
|
|
@@ -98,7 +103,15 @@ First-time setup: ask user for Archery URL + credentials, then run `archery-cli
|
|
|
98
103
|
| Review slow queries | `archery-cli slowquery review --instance mydb --start "2024-01-01 00:00:00" --end "2024-01-31 23:59:59"` |
|
|
99
104
|
| List processes | `archery-cli diagnostic process --instance mydb` |
|
|
100
105
|
| List binlog files | `archery-cli binlog list --instance mydb` |
|
|
101
|
-
|
|
|
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` |
|
|
108
|
+
| Test instance connectivity | `archery-cli instance test-instance --instance 1 --compact` |
|
|
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>` |
|
|
110
|
+
| Create a database account | `archery-cli instance create-user --instance 1 --user app --host '%' --password '...' --dangerous --dry-run`, then `--dangerous --confirm <token>` |
|
|
111
|
+
| Grant/revoke privileges | `archery-cli instance grant --instance 1 --user-host "app@'%'" --op grant --level db --db app --privs SELECT,INSERT --dangerous --dry-run`, then `--dangerous --confirm <token>` |
|
|
112
|
+
| Add members to a resource group | `archery-cli user resourcegroup-add --group 1 --type user --ids 3,4 --dry-run`, then `--confirm <token>` |
|
|
113
|
+
| List workflows awaiting audit | `archery-cli workflow audit-list --limit 20 --compact` |
|
|
114
|
+
| Auto-review SQL (optionally approve) | `archery-cli workflow auto-review --instance-name prod --db app --sql "UPDATE ..." --compact` |
|
|
102
115
|
| Run one SQL across many instances | `archery-cli query run --instances a,b,c --db app --sql "SELECT COUNT(*) FROM t" --dangerous --dry-run`, then `--dangerous --confirm <token>` |
|
|
103
116
|
| Batch-onboard instances from a file | `archery-cli instance import --file instances.csv --dangerous --dry-run`, then `--dangerous --confirm <token>` |
|
|
104
117
|
| Batch audit / execute workflows | `archery-cli workflow audit --ids 42,43 --action pass --dry-run` · `archery-cli workflow execute --ids 42,43 --dangerous --dry-run` |
|
|
@@ -122,7 +135,7 @@ archery-cli query run --instance prod --db app --sql "UPDATE ..." --dangerous --
|
|
|
122
135
|
archery-cli query run --instance prod --db app --sql "UPDATE ..." --dangerous --confirm ct_...
|
|
123
136
|
```
|
|
124
137
|
|
|
125
|
-
Write commands include `auth login`, `auth logout`, `workflow submit`, `workflow audit`, `workflow execute`, `workflow cancel`, `query run`, `query favorite`, `instance create`, `instance import`, `instance update`, `instance delete`, `diagnostic kill`, `binlog parse`, `binlog purge`, `archive apply`, `archive audit`, `archive switch`, `archive once`, and `update`. Run `archery-cli reference` for the definitive installed-version list.
|
|
138
|
+
Write commands include `auth login`, `auth logout`, `workflow submit`, `workflow audit`, `workflow auto-review --execute`, `workflow execute`, `workflow cancel`, `query run`, `query favorite`, `instance create`, `instance import`, `instance update`, `instance delete`, `instance create-db`, `instance create-user`, `instance grant`, `user resourcegroup-add`, `diagnostic kill`, `binlog parse`, `binlog purge`, `archive apply`, `archive audit`, `archive switch`, `archive once`, and `update`. Run `archery-cli reference` for the definitive installed-version list.
|
|
126
139
|
|
|
127
140
|
## Batch operations
|
|
128
141
|
|
|
@@ -169,14 +182,15 @@ Check `ok` first, then act on exit code:
|
|
|
169
182
|
| 6 | `E_CONFLICT` | Stale or invalid token | Re-run `--dry-run`, get fresh token, retry |
|
|
170
183
|
| 7 | `E_NETWORK`/`E_RATE_LIMIT`/`E_SERVER` | Transient error | Back off and retry |
|
|
171
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) |
|
|
172
186
|
|
|
173
187
|
## Permission and security boundary declarations
|
|
174
188
|
|
|
175
189
|
| Tier | Commands | Notes |
|
|
176
190
|
|------|----------|-------|
|
|
177
|
-
| Read | `workflow list/detail/sqlcheck`, `query explain/log/generate`, `instance list/detail/resource/describe`, `slowquery review/history/optimize`, `diagnostic process/tablespace/locks/transactions`, `binlog list`, `archive list/log`, `dict *`, `user list/groups/resource-groups`, `auth status`, `context`, `doctor`, `reference`, `changelog` | Safe, no external writes |
|
|
178
|
-
| Write (medium) | `auth login/logout`, `workflow submit/audit/cancel`, `query favorite`, `binlog parse`, `archive audit/switch`, `update` | Requires `--dry-run` then `--confirm` |
|
|
179
|
-
| Write (high) | `query run`, `workflow execute`, `instance create/import/update/delete`, `binlog purge`, `archive apply/once` | Requires `--dangerous --dry-run` then `--dangerous --confirm`; confirm with user before executing |
|
|
191
|
+
| Read | `workflow list/detail/sqlcheck/audit-list`, `workflow auto-review` (without `--execute`), `query explain/log/generate`, `instance list/detail/resource/describe/test-instance`, `slowquery review/history/optimize`, `diagnostic process/tablespace/locks/transactions`, `binlog list`, `archive list/log`, `dict *`, `user list/groups/resource-groups`, `auth status`, `context`, `doctor`, `reference`, `changelog` | Safe, no external writes |
|
|
192
|
+
| Write (medium) | `auth login/logout`, `workflow submit/audit/cancel`, `workflow auto-review --execute`, `query favorite`, `user resourcegroup-add`, `binlog parse`, `archive audit/switch`, `update` | Requires `--dry-run` then `--confirm` |
|
|
193
|
+
| Write (high) | `query run`, `workflow execute`, `instance create/import/update/delete/create-db/create-user/grant`, `binlog purge`, `archive apply/once` | Requires `--dangerous --dry-run` then `--dangerous --confirm`; confirm with user before executing |
|
|
180
194
|
| Dangerous (critical) | `diagnostic kill` | Requires `--dangerous --dry-run` then `--dangerous --confirm`; kills database threads |
|
|
181
195
|
|
|
182
196
|
- The agent cannot self-escalate permissions.
|
|
@@ -210,8 +224,13 @@ archery-cli workflow detail 42
|
|
|
210
224
|
# After approval, execute
|
|
211
225
|
archery-cli workflow execute 42 --mode auto --dangerous --dry-run
|
|
212
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
|
|
213
230
|
```
|
|
214
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
|
+
|
|
215
234
|
### 2. Query a database and analyze results
|
|
216
235
|
|
|
217
236
|
```bash
|
|
@@ -261,23 +280,37 @@ archery-cli diagnostic kill --instance prod-mysql --threads "12345,12346" --dang
|
|
|
261
280
|
|
|
262
281
|
### 5. Browse data dictionary and table structure
|
|
263
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
|
+
|
|
264
297
|
```bash
|
|
265
298
|
# List all tables in a database
|
|
266
|
-
archery-cli dict tables --instance prod-mysql --db mydb
|
|
299
|
+
archery-cli dict tables --instance prod-mysql --db mydb --db-type mysql
|
|
267
300
|
|
|
268
|
-
# Show table metadata and indexes
|
|
269
|
-
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
|
|
270
303
|
|
|
271
|
-
# Describe table columns
|
|
304
|
+
# Describe table columns (bare structure, no comments — use when the name is already known)
|
|
272
305
|
archery-cli instance describe --instance prod-mysql --db mydb --table orders
|
|
273
306
|
|
|
274
307
|
# List views, triggers, procedures
|
|
275
|
-
archery-cli dict views --instance prod-mysql --db mydb
|
|
276
|
-
archery-cli dict triggers --instance prod-mysql --db mydb
|
|
277
|
-
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
|
|
278
311
|
|
|
279
312
|
# Export data dictionary as HTML
|
|
280
|
-
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
|
|
281
314
|
```
|
|
282
315
|
|
|
283
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
|