Skip to content

Commit 418eacc

Browse files
committed
docs: align purge and repository contracts
1 parent 8c6b895 commit 418eacc

16 files changed

Lines changed: 195 additions & 67 deletions

content/blog/design/repo-yaml-catalog-json.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ moved, a version was deprecated, or a provenance statement changed.
6060

6161
`catalog.json` materializes policy against the local repository. For every
6262
variant it records the exact filename, byte count, SHA-256, qcow2 virtual size,
63-
boot contract, source user, and immutable upstream fallback.
63+
boot contract, source user, and immutable upstream provenance.
6464

6565
Those fields come from scanning the artifact, not from copying values out of
6666
the YAML. Build forces qcow2 parsing, rejects backing files, external data,
@@ -135,10 +135,11 @@ application artifacts and checksum manifest. The two key sets are intentionally
135135
independent: permission to publish a VM image must not imply permission to ship
136136
a new Farrow binary, or vice versa.
137137

138-
Ordinary public builds also compile no private development mirror as a default.
139-
They begin with the embedded Catalog and its immutable HTTPS upstream URLs. A
140-
public mirror can become a compiled default only after the mirror itself is
141-
live. Source configuration, generated Catalog, uploaded artifacts, signing,
138+
Ordinary public builds default to `https://repo.pigsty.io/farrow` and expose
139+
`--mirror` for `https://repo.pigsty.cc/farrow`; `--repo` remains the explicit
140+
custom override. Once selected, that repository is the only artifact source.
141+
Embedded Catalog upstream URLs retain provenance but never become a hidden
142+
fallback. Source configuration, generated Catalog, uploaded artifacts, signing,
142143
and public availability remain separate release gates.
143144

144145
That is the larger design principle: policy should be pleasant to review, but

content/blog/design/repo-yaml-catalog-json.zh.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ images:
5353
## `catalog.json`:仓库能够证明什么
5454

5555
`catalog.json` 把策略落实到本地仓库。每个 Variant 都包含准确文件名、字节数、SHA-256、
56-
qcow2 Virtual Size、Boot Contract、Source User 与 Immutable Upstream Fallback
56+
qcow2 Virtual Size、Boot Contract、Source User 与 Immutable Upstream Provenance
5757

5858
这些字段来自扫描 Artifact,而不是从 YAML 复制。Build 会强制解析 qcow2,拒绝 Backing File、
5959
External Data、Encryption 与未知 Incompatible Feature,执行结构检查后才原子替换 Catalog。
@@ -110,9 +110,10 @@ Base Image 变为只读,Node Root Disk 使用 Overlay,因此普通 VM 写入
110110
Image Catalog Key 授权镜像策略;Release Signing 证明 Farrow 应用工件与 Checksum Manifest。
111111
两组 Key 刻意独立:有权发布 VM Image 不应自动获得发布 Farrow Binary 的权限,反之亦然。
112112

113-
普通 Public Build 也不会把私有开发 Mirror 编译成默认值,而是从 Embedded Catalog 及其
114-
Immutable HTTPS Upstream 开始。只有 Public Mirror 本身已经上线,它才可以成为 Compiled
115-
Default。源码配置、生成 Catalog、上传 Artifact、签名与公开可用性仍是彼此独立的发布门禁。
113+
普通 Public Build 默认使用 `https://repo.pigsty.io/farrow`,并通过 `--mirror` 显式选择
114+
`https://repo.pigsty.cc/farrow`;`--repo` 仍是自定义覆盖。仓库一旦选定,它就是唯一工件源;
115+
Embedded Catalog 的 Upstream URL 继续提供溯源,但绝不会变成隐藏回退。源码配置、生成
116+
Catalog、上传 Artifact、签名与公开可用性仍是彼此独立的发布门禁。
116117

117118
更大的设计原则是:策略应当便于人类审查,而关于已发布字节的事实必须可生成、可复现,并能
118119
被独立验证。

content/docs/about/engineering.md

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,18 @@ and its `origin` remote because GoReleaser records repository identity.
4848

4949
## Image normalization
5050

51-
`packaging/image-pipeline/` accepts an explicit local qcow2 source; it never
52-
downloads or uploads. It copies and hashes the source, forces qcow2 parsing,
53-
rejects backing/external/encrypted/unknown features, runs `qemu-img check`, and
54-
can perform a no-network offline Guest mutation in an explicit QEMU sandbox.
55-
UID/GID 88 collisions are rejected rather than rewritten ambiguously.
51+
The low-level `packaging/image-pipeline/build.sh` accepts an explicit local
52+
qcow2 source and never downloads or uploads. It copies and hashes the source,
53+
forces qcow2 parsing, rejects backing/external/encrypted/unknown features, runs
54+
`qemu-img check`, and can perform a no-network offline Guest mutation in an
55+
explicit QEMU sandbox. UID/GID 88 collisions are rejected rather than rewritten
56+
ambiguously.
57+
58+
`build-official.py` adds a fixed digest-pinned wrapper for Debian 12/13 and
59+
Rocky Linux 8/9 on amd64/arm64. It may fetch only the locked source and offline
60+
package inputs, then emits unsigned `testing` candidates and can assemble a
61+
separate candidate repository. Native smoke, repeat-build comparison,
62+
production signing, upload, and Catalog activation remain later gates.
5663

5764
Catalog bytes are exported with:
5865

content/docs/about/engineering.zh.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,15 @@ GoReleaser 会记录仓库身份。
4242

4343
## 镜像归一化
4444

45-
`packaging/image-pipeline/` 只接受显式本地 qcow2,不下载也不上传。它复制并哈希源文件,
46-
强制 qcow2 解析,拒绝 Backing/External/Encryption/未知 Feature,运行 `qemu-img check`
47-
并可在显式 QEMU Sandbox 中做无网络 Offline Guest Mutation。UID/GID 88 冲突会拒绝,
48-
不会含糊改写。
45+
底层 `packaging/image-pipeline/build.sh` 只接受显式本地 qcow2,不下载也不上传。它复制并
46+
哈希源文件,强制 qcow2 解析,拒绝 Backing/External/Encryption/未知 Feature,运行
47+
`qemu-img check`,并可在显式 QEMU Sandbox 中做无网络 Offline Guest Mutation。
48+
UID/GID 88 冲突会拒绝,不会含糊改写。
49+
50+
`build-official.py` 为 Debian 12/13、Rocky Linux 8/9 的 amd64/arm64 目标增加固定、
51+
摘要锁定的 Wrapper。它只允许获取锁定的源镜像与离线软件包输入,输出未签名的 `testing`
52+
Candidate,并可组装独立候选仓库。真机 Smoke、双构建比较、生产签名、上传与 Catalog
53+
激活仍是后续门禁。
4954

5055
Catalog 逐字节导出命令:
5156

content/docs/reference/cli.md

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ structured usage error; explicit `--help` always renders human help.
2828
| Area | Commands |
2929
|---|---|
3030
| Prepare | `setup`, `init`, `validate`, `doctor` |
31-
| Lifecycle | `plan`, `up`, `start`, `stop`, `restart`, `reload`, `recreate`, `status`, `destroy` |
31+
| Lifecycle | `plan`, `up`, `start`, `stop`, `restart`, `reload`, `recreate`, `status`, `destroy`, `purge` |
3232
| Access | `ssh`, `exec`, `logs`, `provision`, `ssh-config`, `hosts install/uninstall` |
3333
| Images | `update`, `image list/info/pull/import/sync/prune/reset`, `repo scan/build/verify` |
3434
| Host network | `network status/install/uninstall` |
@@ -49,9 +49,11 @@ Frequently used commands have scoped aliases:
4949
| `ssh-config` | `sc` | `image` | `images`, `im` |
5050
| `doctor` | `dt` | `network` | `n`, `net` |
5151
| `exec` / `logs` | `ex` / `l` | `version` | `ver` |
52+
| `purge` | `rm` | | |
5253

5354
`up`, `ssh`, `init`, `start`, `stop`, `restart`, `reload`, `provision`,
54-
`hosts`, and `completion` have no aliases. Inside a namespace, `hosts` and
55+
`hosts`, and `completion` have no aliases. `purge` uses `rm` as its explicit
56+
whole-deployment disposal alias. Inside a namespace, `hosts` and
5557
`network` use `i`/`u` for install/uninstall; `network status` uses `st`; and
5658
`image` maps `list=ls`, `info=in`, `pull=p`, `prune=pr`, `sync=sy`,
5759
and `import=i`. `image reset` keeps `reset-manifest` as a compatibility alias.
@@ -75,7 +77,8 @@ is command-scoped; `-f` is deliberately not a global flag:
7577
| `-v`, `--verbose` | bounded diagnostics on stderr |
7678
| `-c`, `--cidr` | select the RFC1918 `/24` for generated `init`/`setup` templates or host-network inspection/install |
7779
| `-f`, `--file` | select an Inventory for commands that read desired state |
78-
| `-r`, `--repo` | choose an image/artifact repository for commands that resolve downloads |
80+
| `-r`, `--repo` | choose an image/artifact repository; overrides `--mirror` and `FARROW_REPO` |
81+
| `--mirror` | use the China official repository for setup, Catalog, and image-resolving lifecycle commands |
7982
| `-m`, `--mode` | select `host` or `shared` where the command exposes the macOS network mode |
8083
| `-d`, `--dry-run` | show a setup/image plan without changing state |
8184
| `-y`, `--yes` | apply a displayed host/setup/image plan |
@@ -85,12 +88,20 @@ is command-scoped; `-f` is deliberately not a global flag:
8588
| `--delete-persistent` | during whole destroy, also delete retained data disks; invalid with node selectors |
8689
| `--purge` | whole-deployment disposal: delete disks, keys, and deployment state; keep images |
8790

88-
Rare or safety-widening controls such as `--force`, `--rollback`, `--remove`,
89-
`--allow-downgrade`, `--sudo`, `--delete-persistent`, and `--purge` are
91+
Rare, selection, or safety-widening controls such as `--mirror`, `--force`,
92+
`--rollback`, `--remove`, `--allow-downgrade`, `--sudo`,
93+
`--delete-persistent`, and `--purge` are
9094
long-only. On commands that read an Inventory, `-f` always selects a file;
9195
`logs -f` retains the conventional `--follow`. `-n` always means `--no-wait`,
9296
and `-d` always means a dry run.
9397

98+
`farrow purge` (alias `farrow rm`) is the no-confirmation shortcut for
99+
`farrow destroy --force --purge`. It accepts no nodes or Inventory, removes the
100+
complete deployment plus persistent disks, keys, state, and the default SSH
101+
fragment, and keeps images and the host network. With no deployment it succeeds
102+
without changing the image cache. Missing state never authorizes deletion of
103+
residual node artifacts whose identity cannot be proven.
104+
94105
If a failing command has not already emitted a richer typed result, structured
95106
mode writes one object containing `error` and `message` before returning the
96107
documented non-zero exit code. Existing typed failure results are never followed

content/docs/reference/cli.zh.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ JSON/YAML 模式下,空命名空间返回结构化用法错误。显式 `--hel
2727
| 范围 | 命令 |
2828
|---|---|
2929
| 准备 | `setup``init``validate``doctor` |
30-
| 生命周期 | `plan``up``start``stop``restart``reload``recreate``status``destroy` |
30+
| 生命周期 | `plan``up``start``stop``restart``reload``recreate``status``destroy``purge` |
3131
| 访问 | `ssh``exec``logs``provision``ssh-config``hosts install/uninstall` |
3232
| 镜像 | `update``image list/info/pull/import/sync/prune/reset``repo scan/build/verify` |
3333
| 宿主网络 | `network status/install/uninstall` |
@@ -47,9 +47,11 @@ JSON/YAML 模式下,空命名空间返回结构化用法错误。显式 `--hel
4747
| `ssh-config` | `sc` | `image` | `images``im` |
4848
| `doctor` | `dt` | `network` | `n``net` |
4949
| `exec` / `logs` | `ex` / `l` | `version` | `ver` |
50+
| `purge` | `rm` | | |
5051

5152
`up``ssh``init``start``stop``restart``reload``provision``hosts`
52-
`completion` 没有别名。命名空间内部,`hosts``network` 的 install/uninstall 使用
53+
`completion` 没有别名。`purge` 使用 `rm` 作为明确的整套 Deployment 处置别名。
54+
命名空间内部,`hosts``network` 的 install/uninstall 使用
5355
`i`/`u``network status` 使用 `st``image` 使用 `list=ls``info=in``pull=p`
5456
`prune=pr``sync=sy``import=i``image reset` 保留 `reset-manifest` 作为兼容别名。
5557

@@ -71,7 +73,8 @@ JSON/YAML 模式下,空命名空间返回结构化用法错误。显式 `--hel
7173
| `-v``--verbose` | stderr 有界诊断 |
7274
| `-c``--cidr` |`init`/`setup` 生成模板或宿主网络检查/安装选择 RFC1918 `/24` |
7375
| `-f``--file` | 为读取期望状态的命令选择 Inventory |
74-
| `-r``--repo` | 为需要解析下载的命令选择镜像/制品仓库 |
76+
| `-r``--repo` | 选择镜像/制品仓库;覆盖 `--mirror``FARROW_REPO` |
77+
| `--mirror` | 为 setup、Catalog 与需要解析镜像的生命周期命令选择中国官方仓库 |
7578
| `-m``--mode` | 在提供该参数的命令中选择 macOS `host`/`shared` 网络模式 |
7679
| `-d``--dry-run` | 只展示 setup/image 计划,不改变状态 |
7780
| `-y``--yes` | 应用已展示的宿主/setup/image 计划 |
@@ -81,11 +84,16 @@ JSON/YAML 模式下,空命名空间返回结构化用法错误。显式 `--hel
8184
| `--delete-persistent` | 整体销毁时也删持久盘;不能与节点选择器一起使用 |
8285
| `--purge` | 整体处置:删除磁盘、密钥与 deployment 状态,保留镜像 |
8386

84-
`--force``--rollback``--remove``--allow-downgrade``--sudo`
87+
`--mirror``--force``--rollback``--remove``--allow-downgrade``--sudo`
8588
`--delete-persistent``--purge` 等低频或扩大风险边界的参数只保留长版本。读取
8689
Inventory 的命令中 `-f` 始终选择文件;`logs -f` 保留惯用的 `--follow`
8790
`-n` 始终表示 `--no-wait``-d` 始终表示 Dry-run。
8891

92+
`farrow purge`(别名 `farrow rm`)是不经确认的
93+
`farrow destroy --force --purge` 快捷路径。它不接受节点或 Inventory,删除整套 Deployment、
94+
持久盘、密钥、状态和默认 SSH Fragment,保留镜像与宿主网络。没有 Deployment 时幂等成功;
95+
缺少状态文件绝不会授权按路径删除无法证明身份的遗留节点工件。
96+
8997
如果失败命令尚未输出更丰富的类型化结果,结构化模式会先输出一份包含 `error`
9098
`message` 的对象,再返回约定的非零退出码;已经携带失败状态的结果后面绝不会追加第二份
9199
JSON/YAML 文档。

content/docs/reference/image-pipeline.md

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ weight: 40
55
icon: fa-solid fa-shield-halved
66
---
77

8-
`packaging/image-pipeline/` accepts one already-downloaded immutable qcow2 and
9-
an independently obtained SHA-256. It never downloads, uploads, touches Farrow
10-
runtime/network state, reads signing keys, or marks an image `supported`.
8+
The low-level `packaging/image-pipeline/build.sh` accepts one already-downloaded
9+
immutable qcow2 and an independently obtained SHA-256. It never downloads,
10+
uploads, touches Farrow runtime/network state, reads signing keys, or marks an
11+
image `supported`.
1112

1213
## Modes
1314

@@ -20,6 +21,34 @@ runtime/network state, reads signing keys, or marks an image `supported`.
2021
removes keys/history/host identity/cloud-init cache, restores targeted SELinux
2122
labels, and reads back a deterministic marker.
2223

24+
## Official candidate matrix
25+
26+
`build-official.py` wraps the same offline boundary for a fixed eight-target
27+
matrix: Debian 12/13 and Rocky Linux 8/9, each on amd64 and arm64. Every
28+
upstream qcow2, RPM/DEB input, release name, digest, and source epoch is pinned
29+
in `official-v1.json`.
30+
31+
```bash
32+
./packaging/image-pipeline/build-official.py --list
33+
34+
./packaging/image-pipeline/build-official.py \
35+
--source-cache /absolute/source-cache \
36+
--package-cache /absolute/package-cache \
37+
--output /absolute/existing-output-root \
38+
--target d13/arm64 --fetch
39+
```
40+
41+
Without `--fetch`, every locked input must already exist in the two canonical
42+
cache directories. With it, the wrapper downloads only the pinned HTTPS URLs
43+
and rejects any digest mismatch before invoking offline normalization. Debian
44+
12/13 install the locked XFS userspace closure; Rocky Linux 8 installs the
45+
locked Python/SELinux closure, and Rocky Linux 9 needs no extra package input.
46+
47+
Each result remains an unsigned `testing` candidate. Supplying all eight bundle
48+
roots to `--assemble-from` creates a new candidate static repository and runs
49+
`farrow repo build` plus `verify`; this still does not perform native smoke,
50+
signing, upload, or Catalog publication.
51+
2352
```bash
2453
SOURCE_DATE_EPOCH=1787486400
2554

content/docs/reference/image-pipeline.zh.md

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ weight: 40
55
icon: fa-solid fa-shield-halved
66
---
77

8-
`packaging/image-pipeline/` 接受一份已下载的不可变 qcow2 与独立获得的 SHA-256。它绝不
9-
下载、上传、修改 Farrow 运行时/网络状态、读取签名密钥,也不会把镜像标成 `supported`
8+
底层 `packaging/image-pipeline/build.sh` 接受一份已下载的不可变 qcow2 与独立获得的
9+
SHA-256。它绝不下载、上传、修改 Farrow 运行时/网络状态、读取签名密钥,也不会把镜像
10+
标成 `supported`
1011

1112
## 模式
1213

@@ -17,6 +18,31 @@ icon: fa-solid fa-shield-halved
1718
Root SSH,清理密钥/历史/Host Identity/cloud-init Cache,恢复定向 SELinux Label,
1819
并回读确定性 Marker。
1920

21+
## 官方 Candidate 矩阵
22+
23+
`build-official.py` 在同一离线边界上封装固定的八目标矩阵:Debian 12/13 与 Rocky Linux
24+
8/9,各自覆盖 amd64、arm64。每份上游 qcow2、RPM/DEB 输入、Release 名称、Digest 与
25+
Source Epoch 都锁定在 `official-v1.json`
26+
27+
```bash
28+
./packaging/image-pipeline/build-official.py --list
29+
30+
./packaging/image-pipeline/build-official.py \
31+
--source-cache /absolute/source-cache \
32+
--package-cache /absolute/package-cache \
33+
--output /absolute/existing-output-root \
34+
--target d13/arm64 --fetch
35+
```
36+
37+
不加 `--fetch` 时,全部锁定输入必须已经位于两个 Canonical Cache 目录;加上后,Wrapper
38+
也只下载固定 HTTPS URL,并在调用离线归一化前拒绝任何 Digest 不匹配。Debian 12/13
39+
安装锁定的 XFS 用户态闭包;Rocky Linux 8 安装锁定的 Python/SELinux 闭包;Rocky Linux 9
40+
不需要额外软件包输入。
41+
42+
每份结果仍是未签名的 `testing` Candidate。把八个 Bundle Root 全部传给
43+
`--assemble-from` 会创建新的候选静态仓库,并运行 `farrow repo build``verify`;这仍不
44+
包含真机 Smoke、签名、上传或 Catalog 发布。
45+
2046
```bash
2147
SOURCE_DATE_EPOCH=1787486400
2248

0 commit comments

Comments
 (0)