Skip to content

Commit 6d8842c

Browse files
committed
feat(view): reserve view namespaces
Signed-off-by: Eli Ma <eli@patch.sh>
1 parent 54be524 commit 6d8842c

19 files changed

Lines changed: 394 additions & 14 deletions

‎Cargo.lock‎

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mega2"
3-
version = "0.41.80"
3+
version = "0.42.0"
44
edition = "2024"
55
license = "MIT OR Apache-2.0"
66
description = "Monorepo engine and Git hosting server for AI agents: trunk-based storage, Git Smart HTTP, Git LFS, OCI registry, and Agent Session Capture"

‎config/config-review.toml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ admin = ["mega2"]
8686
# 且不能是根树保留项(.cedar、.mega_cedar.json、.buckroot、.buckconfig、.git),否则校验失败.
8787
# 只有首次初始化(`service init` 或空库上的首次服务启动)会创建这些目录;事后修改需重启,且不会
8888
# 增删已初始化库的顶层目录.
89+
# .view and .filter are reserved view URL names; exact-case matches are rejected.
90+
# .view 和 .filter 是视图 URL 保留名,按大小写精确匹配时同样拒绝。
8991
root_dirs = ["third-party", "project", "doc", "artifact", "release", "model", "data", "toolchains"]
9092

9193
# Object-ID format for the initial Monorepo graph and live Git service.

‎config/config-storage-only.none.toml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ admin = ["mega2"]
154154
# 每项为唯一的单组件目录名:不含 '/'、'\' 或 NUL,不能是 '.'、'..' 或空串,无首尾
155155
# 空格,且不能是根树保留项(.cedar、.mega_cedar.json、.buckroot、.buckconfig、.git),
156156
# 否则校验失败.
157+
# .view and .filter are reserved view URL names; exact-case matches are rejected.
158+
# .view 和 .filter 是视图 URL 保留名,按大小写精确匹配时同样拒绝。
157159
root_dirs = ["third-party", "project", "doc", "artifact", "release", "model", "data", "toolchains"]
158160

159161
# Object-ID hash for the repo graph / 仓库图的 Object-ID 哈希.

‎config/config-storage-only.toml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ admin = ["mega2"]
154154
# 每项为唯一的单组件目录名:不含 '/'、'\' 或 NUL,不能是 '.'、'..' 或空串,无首尾
155155
# 空格,且不能是根树保留项(.cedar、.mega_cedar.json、.buckroot、.buckconfig、.git),
156156
# 否则校验失败.
157+
# .view and .filter are reserved view URL names; exact-case matches are rejected.
158+
# .view 和 .filter 是视图 URL 保留名,按大小写精确匹配时同样拒绝。
157159
root_dirs = ["third-party", "project", "doc", "artifact", "release", "model", "data", "toolchains"]
158160

159161
# Object-ID hash for the repo graph / 仓库图的 Object-ID 哈希.

‎config/config.toml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ admin = ["mega2"]
8484
# 且不能是根树保留项(.cedar、.mega_cedar.json、.buckroot、.buckconfig、.git),否则校验失败.
8585
# 只有首次初始化(`service init` 或空库上的首次服务启动)会创建这些目录;事后修改需重启,且不会
8686
# 增删已初始化库的顶层目录.
87+
# .view and .filter are reserved view URL names; exact-case matches are rejected.
88+
# .view 和 .filter 是视图 URL 保留名,按大小写精确匹配时同样拒绝。
8789
root_dirs = ["third-party", "project", "doc", "artifact", "release", "model", "data", "toolchains"]
8890

8991
# Object-ID format for the initial Monorepo graph and live Git service.

‎docs/configuration.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ One line of purpose and the key entries per section; full comments and defaults
8484
- **`[log]`**: tracing logs. `level` (trace..error), `print_std` (off in production), `with_ansi` (stdout only). All hot-reloadable.
8585
- **`[database]`**: PostgreSQL only (`db_type = "postgres"`). `db_url`, pool `max_connection` / `min_connection`, `acquire_timeout` / `connect_timeout`, `sqlx_logging`. Inject credentials via `MEGA_DATABASE__DB_URL`, not via Vault SecretRef.
8686
- **`[monorepo]`**: `import_dir` (default `/third-party`, the ImportRepo multi-branch exception), `admin`, `root_dirs` (directory initialization), `object_format` (`sha1` by default; `sha256` / `blake3` require Libra), `push_policy` (`trunk` by default, which requires an explicit `git.push_auth`; the review sample is [`config-review.toml`](../config/config-review.toml)), and `max_push_commits` (the trunk push-chain limit). User-visible path and push behavior is in the [User Guide](./user-guide.md); the full key list and defaults are in [`config.toml`](../config/config.toml).
87-
- **Path validation:** `config validate`, service startup, and hot-reload candidates use the same checks and report the invalid field. Each `root_dirs` entry must be a unique single path component: no `/`, `\`, or NUL; not empty, `.` or `..`; no leading or trailing spaces; and not a reserved root entry (`.cedar`, `.mega_cedar.json`, `.buckroot`, `.buckconfig`, or `.git`, case-insensitive). `import_dir` must be a canonical absolute non-root path with no trailing slash, `//`, `.` or `..` segments, NUL, or `\`; its first component must appear in `root_dirs`. Paths under `import_dir` always use ImportRepo semantics, even when `root_dirs` contains that name. `root_dirs` creates directories only during initial setup; changing it later requires a restart and does not add or remove directories in an initialized repository. See the [initialization manual](./manual/monorepo-init.md).
87+
- **Path validation:** `config validate`, service startup, and hot-reload candidates use the same checks and report the invalid field. Each `root_dirs` entry must be a unique single path component: no `/`, `\`, or NUL; not empty, `.` or `..`; no leading or trailing spaces; and not a reserved root entry (`.cedar`, `.mega_cedar.json`, `.buckroot`, `.buckconfig`, or `.git`, case-insensitive). `.view` and `.filter` also cannot be `root_dirs` entries or the first `import_dir` component, and match exact case. `import_dir` must be a canonical absolute non-root path with no trailing slash, `//`, `.` or `..` segments, NUL, or `\`; its first component must appear in `root_dirs`. Paths under `import_dir` always use ImportRepo semantics, even when `root_dirs` contains that name. `root_dirs` creates directories only during initial setup; changing it later requires a restart and does not add or remove directories in an initialized repository. See the [initialization manual](./manual/monorepo-init.md).
88+
- **View reserved names:** `.view` and `.filter` are view URL names reserved by complete, exact-case first-component matching; `.viewer` and `.View` are unaffected, and this rule is independent of `[views].enabled`. Provisioning and product writes return `MONO_PATH_INVALID` for paths beginning with either name, and trunk Git pushes that create those paths are also rejected; review pushes do not use this creation classification, and existing `mega_refs` rows for those paths are caught by the startup check below. Once the view URL entry point ships, those Git URLs are answered by it and do not enter Monorepo dispatch. With `enabled = true`, HTTP and SSH check root-tree entries and every `mega_refs` row before binding (regardless of ref name, CL status, or a leading slash in the path); a conflict or unreadable root tree rejects startup, while `enabled = false` skips the check. Conflict errors list each `root tree entry "<name>"` or `mega_refs path "<path>"` with Rust `{:?}` quoting, include `[views] enabled = false`, `docs/configuration.md`, and `View reserved names`, and contain no value read from configuration. No supported removal path exists for an existing root-tree or `mega_refs` conflict: keep `enabled = false`; this plan provides no cleanup SQL. After upgrade, a `root_dirs` value containing `.view` or `.filter` is rejected and must be renamed or removed; changing configuration does not alter an initialized root tree.
8889
- **`[monorepo.rename]`**: move/rename detection for diff classification: `similarity_threshold` (0-100), `rename_limit` (0 = unlimited).
8990
- **`[pack]`**: receive-pack decode resources. `pack_decode_mem_size` / `pack_decode_disk_size` (K/M/G, KiB/MiB, and percentages supported), `pack_decode_cache_path`, `clean_cache_after_decode`, `channel_message_size`, `save_entry_concurrency`.
9091
- **`[lfs]`**: `[lfs.ssh].http_url` (href base for SSH transfer; LFS payloads still move over HTTP) and `[lfs.local].lfs_file_path`. In trunk mode, LFS authorization follows `git.push_auth`; see the [Deployment Guide](./deployment.md).
@@ -106,7 +107,7 @@ One line of purpose and the key entries per section; full comments and defaults
106107

107108
## 5. Fail-closed startup validation
108109

109-
`Config::validate` and `AppContext::new` reject invalid configuration at startup. The [Deployment Guide](./deployment.md) covers trunk / storage-only prerequisites, including `cedar.enforcement = "off"`, no open CLs, no non-terminal `push_queue` rows, an explicit `push_auth` compatible with the selected mode, and `ssh_receive_pack = false`. Other examples include unknown or removed fields, invalid `cedar.enforcement` values, the reserved anonymous principal in `monorepo.admin`, optional services enabled outside storage-only mode, out-of-range `storage_events` values, non-canonical filters, and SecretRef namespace mismatches. Secret values are never included in error messages.
110+
`Config::validate` and `AppContext::new` reject invalid configuration at startup. The [Deployment Guide](./deployment.md) covers trunk / storage-only prerequisites, including `cedar.enforcement = "off"`, no open CLs, no non-terminal `push_queue` rows, an explicit `push_auth` compatible with the selected mode, and `ssh_receive_pack = false`. Other examples include unknown or removed fields, invalid `cedar.enforcement` values, the reserved anonymous principal in `monorepo.admin`, optional services enabled outside storage-only mode, out-of-range `storage_events` values, non-canonical filters, and SecretRef namespace mismatches. Secret values are never included in error messages. With `[views].enabled = true`, services also check the reserved names `.view` and `.filter` before binding; see “View reserved names” in §4.
110111

111112
## 6. `config validate`
112113

‎docs/configuration.zh.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ mega2 --config /etc/mega2/config.toml config secret check redis.url \
8484
- **`[log]`**:tracing 日志。`level`(trace..error)、`print_std`(生产关)、`with_ansi`(仅 stdout)。全部热加载。
8585
- **`[database]`**:仅支持 PostgreSQL(`db_type = "postgres"`)。`db_url`、连接池 `max_connection` / `min_connection`、`acquire_timeout` / `connect_timeout`、`sqlx_logging`。凭据用 `MEGA_DATABASE__DB_URL` 注入,不走 Vault SecretRef。
8686
- **`[monorepo]`**:`import_dir`(默认 `/third-party`,ImportRepo 多分支例外)、`admin`、`root_dirs`(初始化目录)、`object_format`(默认 `sha1`;`sha256` / `blake3` 为 Libra 扩展)、`push_policy`(默认 `trunk`,需显式设置 `git.push_auth`;review 形态示例见 [`config-review.toml`](../config/config-review.toml))和 `max_push_commits`(trunk 推送链上限)。目录生成细节见 [`manual/monorepo-init.zh.md`](./manual/monorepo-init.zh.md);完整配置项见 [`config/config.toml`](../config/config.toml)。
87-
- **路径校验:**`config validate`、服务启动和热重载候选使用同一套校验,并在失败时指出字段。`root_dirs` 每项必须是唯一的单组件目录名:不得含 `/`、`\` 或 NUL;不得为空、`.` 或 `..`;不得有首尾空格;也不得与保留根条目重名(`.cedar`、`.mega_cedar.json`、`.buckroot`、`.buckconfig`、`.git`,大小写不敏感)。`import_dir` 必须是规范的绝对非根路径,不得有尾斜杠、`//`、`.` 或 `..` 路径段、NUL 或 `\`;其首组件必须列在 `root_dirs` 中。`import_dir` 下的路径始终按 ImportRepo 语义处理,即使 `root_dirs` 中有同名项。`root_dirs` 只在首次初始化时创建目录;之后修改需要重启,也不会增删已初始化仓库的目录。详情见[初始化手册](./manual/monorepo-init.zh.md)。
87+
- **路径校验:**`config validate`、服务启动和热重载候选使用同一套校验,并在失败时指出字段。`root_dirs` 每项必须是唯一的单组件目录名:不得含 `/`、`\` 或 NUL;不得为空、`.` 或 `..`;不得有首尾空格;也不得与保留根条目重名(`.cedar`、`.mega_cedar.json`、`.buckroot`、`.buckconfig`、`.git`,大小写不敏感)。`.view`、`.filter` 同样不能作为 `root_dirs` 条目或 `import_dir` 首段,且按大小写精确匹配。`import_dir` 必须是规范的绝对非根路径,不得有尾斜杠、`//`、`.` 或 `..` 路径段、NUL 或 `\`;其首组件必须列在 `root_dirs` 中。`import_dir` 下的路径始终按 ImportRepo 语义处理,即使 `root_dirs` 中有同名项。`root_dirs` 只在首次初始化时创建目录;之后修改需要重启,也不会增删已初始化仓库的目录。详情见[初始化手册](./manual/monorepo-init.zh.md)。
88+
- **视图保留名:**`.view`、`.filter` 是视图 URL 保留名,按完整首段与大小写精确匹配;`.viewer`、`.View` 不受影响,且此规则与 `[views].enabled` 无关。路径开通和产品写对首段为它们的路径返回 `MONO_PATH_INVALID`,trunk 形态下创建这类路径的 Git 推送同样被拒绝;review 形态推送不经过这一创建分类,这类路径上已有的 `mega_refs` 行由下述启动检查拦截。视图 URL 入口上线后,此类 Git URL 由视图入口应答,不再进入 Monorepo 分派。`enabled = true` 时,HTTP 与 SSH 在绑定监听前检查根树顶层条目和全部 `mega_refs`(不论 ref 名、是否 CL、path 是否带前导 `/`);命中或读不到根树即拒绝启动,`enabled = false` 时不检查。冲突错误逐项以 Rust `{:?}` 引号转义列出 `root tree entry "<名字>"` 或 `mega_refs path "<path>"`,并含 `[views] enabled = false`、`docs/configuration.md` 与 `View reserved names`;错误不含任何从配置读取的值。根树或 `mega_refs` 已有冲突没有受支持的移除入口:这类部署只能保持 `enabled = false`,本计划不提供清理 SQL。升级后 `root_dirs` 含 `.view`、`.filter` 的配置会被拒绝,须先改名或移除;已初始化根树不会随配置变更。
8889
- **`[monorepo.rename]`**:diff 分类的移动 / 改名检测:`similarity_threshold`(0-100)、`rename_limit`(0 = 不限制)。
8990
- **`[pack]`**:receive-pack 解码资源。`pack_decode_mem_size` / `pack_decode_disk_size`(支持 K/M/G、KiB/MiB 与百分比)、`pack_decode_cache_path`、`clean_cache_after_decode`、`channel_message_size`、`save_entry_concurrency`。
9091
- **`[lfs]`**:`[lfs.ssh].http_url`(SSH 传输的 href 底座,LFS 文件仍走 HTTP)、`[lfs.local].lfs_file_path`。trunk 下 LFS 鉴权随 `git.push_auth`,见 [`deploy-trunk.md`](./deploy-trunk.md) §6。
@@ -106,7 +107,7 @@ mega2 --config /etc/mega2/config.toml config secret check redis.url \
106107

107108
## 5. 启动期 fail-closed 校验
108109

109-
`Config::validate` 和 `AppContext::new` 会在启动时拒绝不合规配置。trunk / storage-only 模式的 7 项不变式清单以 [`deploy-trunk.md`](./deploy-trunk.md) §1 为准,包括 `cedar.enforcement = off`、没有未关闭的 CL、`push_queue` 中没有非终态记录、显式设置且与模式匹配的 `push_auth`,以及 `ssh_receive_pack = false`。其他拒绝项包括未知或已移除字段、非法的 `cedar.enforcement` 值、`monorepo.admin` 中的保留匿名主体、在 storage-only 之外启用 `[oci]` / `[agent_capture]` / `[storage_events]`、越界的 `storage_events` 数值、非规范过滤器和不匹配的 SecretRef 命名空间。错误文本遵循 [`errors.md`](./errors.md) 的约定,不包含密钥值。
110+
`Config::validate` 和 `AppContext::new` 会在启动时拒绝不合规配置。trunk / storage-only 模式的 7 项不变式清单以 [`deploy-trunk.md`](./deploy-trunk.md) §1 为准,包括 `cedar.enforcement = off`、没有未关闭的 CL、`push_queue` 中没有非终态记录、显式设置且与模式匹配的 `push_auth`,以及 `ssh_receive_pack = false`。其他拒绝项包括未知或已移除字段、非法的 `cedar.enforcement` 值、`monorepo.admin` 中的保留匿名主体、在 storage-only 之外启用 `[oci]` / `[agent_capture]` / `[storage_events]`、越界的 `storage_events` 数值、非规范过滤器和不匹配的 SecretRef 命名空间。错误文本遵循 [`errors.md`](./errors.md) 的约定,不包含密钥值。`[views].enabled = true` 时,服务在绑定监听之前还检查保留名 `.view`、`.filter`;见第 4 节「视图保留名」。
110111

111112
## 6. `config validate`
112113

‎docs/errors.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ use crate::common::errors::{ApiError, MegaError, RvError};
116116
|---|---|---|---|
117117
| `NotAllowed { path, allowed_roots, import_dir }` | `MONO_PATH_NOT_ALLOWED` | 400 | 目标路径不在任何 `root_dirs` 之下,或位于 `import_dir` 之下(import 优先:ImportRepo 由推送创建) |
118118
| `Uninitialized { path }` | `MONO_PATH_UNINITIALIZED` | 409 | 合法根下的路径尚未开通;消息点名 `mega2 path provision --server <url> <path>` 与 `POST /api/v1/path/provision` |
119-
| `Invalid { path, reason }` | `MONO_PATH_INVALID` | 400 | 路径非规范(相对、`.` / `..` 段、重复或尾斜杠)、含 NUL / `\` / 其它控制字符(JSON 严格入口),或为根 `/`(分类原语的判定;产品写落点为 `/` 时按 `NotAllowed` 返回,见 ADR-FU-06) |
119+
| `Invalid { path, reason }` | `MONO_PATH_INVALID` | 400 | 路径非规范(相对、`.` / `..` 段、重复或尾斜杠)、含 NUL / `\` / 其它控制字符(JSON 严格入口),或为根 `/`(分类原语的判定;产品写落点为 `/` 时按 `NotAllowed` 返回,见 ADR-FU-06),或首段为视图保留名 `.view` / `.filter`(路径开通与产品写) |
120120
| `Conflict { path, component }` | `MONO_PATH_CONFLICT` | 409 | 路径上的某个组件已存在且不是目录 |
121121

122122
文本格式(Git 面与 API 面同一文本):`Display` = `"<CODE>: <人读消息>"`,恒为单行——路径以带引号的转义形式出现(`Uninitialized` 开通命令里的路径只转义、不加引号),根名、原因等其余片段中的控制字符(换行、NUL 等)按 `\n` / `\0` 形式转义,保证能放进 Git `ng` 行且无法伪造多行输出。产品写经 `GitError` 返回时,`MegaError::PathPolicy` 转为 `[code:400|409] <文本>`(`PathPolicyError::http_status`),`ApiError` 据此设置状态并剥去标记;裸 `PathPolicyError` 与 `MegaError::PathPolicy` 则按类型映射且原样输出(不再从文本中解析 `[code:…]`,路径里出现该字样也不会截断消息)。三条通道的 `err_message` 都是原文。Git report-status 的 `ng` 行与 API `err_message` 都携带这段原文,客户端可按冒号前的码分支;码是公开契约,改名需 minor 版本并更新本节。`NotAllowed` 只列出允许的根(`/<name>`,排序)与 ImportRepo 目录,任何变体都不包含配置文件路径、`base_dir`、数据库 / Redis / 对象存储地址或凭据。

‎docs/manual/monorepo-init.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ not split entries on `/` to create nested directories. The validator rejects
152152
entries containing `/`, `\`, or NUL; empty entries, `.` and `..`; leading or
153153
trailing spaces; duplicates; and reserved root names (`.cedar`,
154154
`.mega_cedar.json`, `.buckroot`, `.buckconfig`, and `.git`, case-insensitive).
155+
`.view` and `.filter` are exact-case view URL reserved names (unlike case-insensitive `.git`) and are also rejected.
155156
It also requires `import_dir` to be a canonical absolute non-root path without
156157
a trailing slash, `//`, `.` or `..` segments, NUL, or `\`. Its first
157158
component must be in `root_dirs`; for example, `root_dirs = ["project"]` with

0 commit comments

Comments
 (0)