feat: let an installation choose its update source, and adopt a plain directory

config.yaml gains an optional update section (remote / remote_url / branch). The
resolver keeps its default - whatever remote this tree already tracks - and the
explicit choice wins when set, which is also what lets a tarball installation
that never saw git get on the update rails at all.

- RemoteURL is fetched straight into a ref namespace of its own, so a URL source
  cannot be shadowed by a same-named remote's stale refs. ValidRemoteURL allowlists
  https/http/ssh/git/file and local absolute paths, and rejects git's ext::
  transport (which executes commands) before anything reaches argv.
- Adopt connects a plain directory to the source. Preview is side-effect free (the
  fetch happens in a throwaway bare repository) and lists every local file whose
  content the target would replace, plus the operator content that is put aside.
  The confirmed run inits, adds origin, stashes operator content, keeps every
  replaced file under .update-backup/<ts>/overwritten/ so "the update ate my edit"
  has an address, lands the target content, sets upstream, rebuilds the binary.
  A failure removes only the .git it created itself; once the content has landed
  the tree stays adopted even if the build fails.
- Console/API: the status envelope carries the configured source;
  POST /system/update/source writes it through the same config path every other
  setting uses (validated, audited); POST /system/update/adopt is preview-then-job,
  with the job's kind recorded. OpenAPI updated; RBAC rides the existing
  update:apply prefix and the route inventory stays green.

Tests: URL-mode check/apply against real repositories (including the address
beating a remote name), URL validation table, and the full adoption story -
preview touches nothing, operator content survives, the replaced edit is in the
backup, and the adopted tree updates and rolls back like any other installation.
This commit is contained in:
Sycun committed 2026-10-07 12:46:32 +08:00
1 parent dc5c4d6a75
commit acd84cd525
12 files changed
+1125 -50

No files matched your search

+12
View File
@@ -589,3 +589,15 @@ project:
fact_index_path_max_runes: 10000
fact_summary_max_runes: 24000
default_inject_deprecated: false
# ============================================
# 一键更新(可选)
# ============================================
# 更新源:不配置时,更新跟随本目录自己跟踪的 git 远端;配置后按这里指定的来源更新。
# remote 与 remote_url 二选一(页面保存时两者互斥;都手写时以 remote_url 为准)。
# 非 git 目录(解压/打包安装)配置地址后,可在控制台「一键更新」页执行「接入更新源」,
# 把目录变成跟踪该仓库的 git 工作树,此后按正常安装一键更新。
# update:
# remote: origin # 用已有远端名指定(mine/origin/upstream/任意名)
# remote_url: https://github.com/AIPentest/CyberStrikeAI.git # 或直接给仓库地址
# branch: main # 要跟踪的分支;留空按 upstream/当前分支推断