
# 隔离

Rudel 是一个由请求选择的覆盖层系统。选中的请求会使用沙盒数据库表和沙盒主题文件，同时仍通过主机的 WordPress 安装运行。

## 每个沙盒独立隔离

### WordPress 数据表

每个沙盒都会获得一个生成的表前缀：主机前缀加上沙盒 ID 的 MD5 开头七个十六进制字符。

```text
wp_b65338d_options
wp_b65338d_posts
wp_b65338d_users
```

Rudel 会在 WordPress 完成启动前切换 WordPress 表前缀，因此沙盒请求中的每个查询都会读取和写入沙盒副本。

### 用户

`users` 和 `usermeta` 数据表会与其余数据表一同克隆。沙盒创建时会包含主机上的用户和密码；之后，在沙盒中创建、修改或删除用户都不会影响主机，主机上的变更也不会同步到沙盒。

### 当前主题文件

所选主题会复制到沙盒目录：

```text
wp-content/rudel-environments/{environment_id}/themes/{theme_slug}
```

如果该主题是子主题，Rudel 也会复制父主题，以保持模板关系有效。沙盒始终提供创建时记录的主题；在沙盒中切换主题不会产生影响。

## 与主机共享

- WordPress 核心
- 插件文件
- 上传的媒体文件

在主机上安装或更新的插件也会为每个沙盒安装或更新。哪些插件处于启用状态存储在选项表中，因此各沙盒的启用状态彼此独立。在沙盒中上传的文件会存入主机的上传目录。这样可以加快沙盒创建速度，并避免全局替换 `WP_CONTENT_DIR`。

请确保 Rudel 在每个沙盒中始终处于启用状态。邮件阻止和主题覆盖功能由该插件运行；如果在选中沙盒时将其停用，还会从共享的 `wp-config.php` 中移除引导行，从而关闭整个安装中的沙盒选择（[问题 #13](https://github.com/inline0/rudel/issues/13)）。

## 选择沙盒

HTTP 请求通过以下方式选择沙盒：

- `X-Rudel-Environment` 标头（旧版别名 `X-Rudel-Sandbox`）
- `rudel_environment` Cookie（旧版别名 `rudel_sandbox`）

Rudel 不会设置或清除 Cookie。删除 Cookie 即可返回主机；管理栏中的 Sandbox 项会链接到主机 URL，但会保留该 Cookie（[问题 #10](https://github.com/inline0/rudel/issues/10)）。

WP-CLI 命令通过以下方式选择沙盒：

- `RUDEL_ENVIRONMENT` 环境变量
- 主机名以沙盒 ID 开头的 `--url`，例如 `--url=http://alpha-3be7.example.test`

选择器未经身份验证。任何能够访问站点并发送有效沙盒 ID 的客户端都能进入该沙盒，而沙盒 ID（名称加四个十六进制字符）很容易猜到。不要将沙盒选择视为访问控制边界；应在 Web 服务器或网络层面保护公共主机。

## 请求默认行为

对于选中的请求，Rudel 会：

- 通过 `pre_wp_mail` 过滤器阻止出站邮件
- 将 `WP_TEMP_DIR` 设置为沙盒的 `tmp` 目录
- 将 `WP_CACHE_KEY_SALT` 设置为沙盒专属值，使持久对象缓存中的键彼此隔离
- 为沙盒 `debug.log` 提供 `WP_DEBUG` 日志，以及根据沙盒 ID 派生的身份验证密钥和盐

仅当 `wp-config.php` 尚未定义这些常量时，引导程序才会逐一定义它们。标准 `wp-config.php` 会定义 `WP_DEBUG` 以及所有密钥和盐，因此在此类安装上，沙盒请求会使用主机的调试设置、密钥和盐（[问题 #4](https://github.com/inline0/rudel/issues/4)）。由于用户也会被克隆，主机登录 Cookie 在沙盒中可能有效。

## 运行时元数据

Rudel 运行时元数据保存在主机 WordPress 的 MySQL 数据表中：

```text
wp_rudel_environments
wp_rudel_worktrees
```

这些数据表是 Rudel 的权威数据源。环境目录包含受管理的文件和构件，不包含运行时注册表状态。
