feat: give the update source a page, and the adopt flow its preview

The console page grows an update-source section: what is in effect and where it
comes from (config.yaml or the tree's own tracking), an edit form for the three
fields, and - for a directory that is not a git installation - the adopt entry.
Adopt is preview-first: the plan lists what would be replaced and what would be
kept, the confirm dialog carries the counts, and the restart tick is the same one
an update uses. A refused save shows the server's own sentence (a remote name and
an address together, an ext:: address) instead of a generic failure, and the typed
values survive the failed save and the polling redraws.

zh/EN/RU dictionaries carry the 27 new keys; the console page's contract tests
grow to 29 (source rendering and save body, the refusal path, adopt gating by
installation kind, preview-then-confirm); docs/README describe choosing a source
and connecting an unpacked installation.
This commit is contained in:
Sycun committed 2026-10-07 12:49:15 +08:00
1 parent acd84cd525
commit 27c1ff6573
12 files changed
+461 -5

No files matched your search

+9
View File
@@ -86,6 +86,15 @@ kept. For a fork this is the only path that does not overwrite you with somebody
source is modified locally or the branch has diverged it refuses and says why instead of forcing.
See [the developer guide](developer-guide.md) for the full semantics.
The source is chosen either in the `update` section of `config.yaml` (`remote` or `remote_url`, plus
an optional `branch`) or right on the console page: the official repository, your own fork, or
somebody else's second-development repository are all just this one setting; unset, it follows the
remote this directory already tracks. An installation unpacked from a Release archive (no `.git`)
can be connected from the same page: the preview lists the files the target would replace and the
operator content that is kept, replaced files are backed up under
`.update-backup/<timestamp>/overwritten/`, and confirming turns the directory into a normal
installation with one-click updates.
`upgrade.sh` still works and is now a thin shell over that implementation, with two paths decided by
the installation kind:
+29
View File
@@ -65,6 +65,35 @@ first remote when none of those names exists), and the branch defaults to what t
shell over the same implementation: when this directory is a git work tree it just calls
`./cyberstrike-ai -update`.
### Choosing the source (the update section of config.yaml)
Unset, the rules above apply; set, the explicit choice wins:
```yaml
update:
remote: origin # an existing remote name (mine/origin/upstream/anything), or remote_url instead
# remote_url: https://github.com/AIPentest/CyberStrikeAI.git
branch: main # optional; defaults to @{upstream} / the current branch
```
The console page edits and saves all three. Saving validates: remote and branch names go through the
same allowlist an update uses, and the address allowlist is https/http/ssh/git/file plus local
absolute paths - git's `ext::` transport executes commands and is rejected outright. Following the
official repository, your own fork, or somebody else's second-development repository is exactly the
choice this section expresses.
### Connecting a non-git installation (the tarball kind)
An installation that started as an unpacked Release archive has no `.git`; once a source is saved it
can be connected from the same page: the preview fetches in a throwaway repository and first lists
**the local files the target would replace** and **the operator content that will be kept**; on
confirm the directory becomes a git work tree (`git init`, origin added, the target branch checked
out), every replaced file is kept under `.update-backup/<timestamp>/overwritten/`, operator content
is stashed and restored as usual, and the binary is rebuilt. From then on it is a normal
installation with one-click update and rollback - but note there is no git history before the
connection, so the connection itself has no earlier commit to roll back to; the first real update
writes the first rollback point.
### The four refusals
| situation | reason | meaning and what to do |
+6
View File
@@ -186,6 +186,12 @@ knowledge_base/ data/ config.yaml` 等运维者内容先暂存再放回,结果
跑 fork 时这是唯一不会"用别人的代码覆盖自己"的路径;本地源码有改动或分支已分叉时它会拒绝并说明原因,
而不是硬来。细节见 [开发者指南](developer-guide.md) 的「一键更新」一节。
更新源可以在 `config.yaml` 的 `update` 段指定(`remote` 或 `remote_url`,可带 `branch`),也可以直接在
控制台「一键更新」页填写保存:想跟随官方仓库、自己的二开或别人的二开,改的都是这一处;不配置时跟随
本目录自己跟踪的远端。**用 Release 包解压安装、目录里没有 git 的**,配好地址后在同一页点「预览并接入」:
预览先列出会被目标版本替换的文件与会保留的运维者内容,被替换的都会备份在
`.update-backup/<时间戳>/overwritten/`,确认后目录成为可一键更新的正常安装。
`upgrade.sh` 仍然可用,它现在只是这条实现的薄壳,并按安装形态分两条路:
- **本目录是 git 工作树**:直接调用 `./cyberstrike-ai -update`(还没有二进制时先
+24
View File
@@ -67,6 +67,30 @@ go run ./cmd/server --config config.yaml
remote 里取(都不在时取第一个 remote),分支默认取当前分支 `@{upstream}` 指向的名字(没有 upstream 时用当前分支名)。
`upgrade.sh` 现在只是这条实现的薄壳:本目录是 git 工作树时它直接调 `./cyberstrike-ai -update`。
### 选择更新源(config.yaml 的 update 段)
不配置时按上面的规则跟随本树;配置后显式来源优先:
```yaml
update:
remote: origin # 已有远端名(mine/origin/upstream/任意名),与 remote_url 二选一
# remote_url: https://github.com/AIPentest/CyberStrikeAI.git
branch: main # 可选;留空按 upstream/当前分支推断
```
控制台的「一键更新」页可以直接编辑并保存这三项。服务端保存时校验:远端名与分支名走与更新同一套白名单,
地址只允许 https/http/ssh/git/file:// 与本机绝对路径——git 的 `ext::` 传输会执行命令,一律拒绝。
想让这套安装跟随官方仓库、自己的二开或别人的二开,改的都是这一处。
### 接入非 git 安装(解压/打包装的那类)
一开始用 Release 包解压安装、目录里没有 `.git` 的,配好上面的地址后可在同一页执行「预览并接入」:
预览在临时仓库里 fetch,先列出**会被目标版本替换的本机文件**与**会保留的运维者内容**;确认后目录接入
成为 git 工作树(`git init` + 添加 origin + 落地目标分支),被替换的文件全部留底在
`.update-backup/<时间戳>/overwritten/`,运维者内容照旧先暂存再放回,随后重编译二进制。
接入后它就是正常安装,一键更新与回滚都可用了;注意接入前没有 git 历史,因此「接入」本身没有可回滚的
上一提交,第一个回滚点由接入后的第一次更新写下。
### 四种拒绝场景
| 场景 | reason | 含义与处理 |