Skip to content

Commit cca52cc

Browse files
committed
test(config): isolate legacy environment rejection checks
Run the existing OAuth and mail rejection cases in exact child processes so their deprecated environment keys cannot contaminate concurrent config validation. Preserve production rejection behavior and original assertions. FIX-MTR-13 is a local child of REL-MTR-ENV-01. Original controlled evidence and the combined AF1 validation are retained with historical STOP records. Only validate.rs and the six declared governance files belong to this commit; the three FIX-MTR-12 sources remain unstaged. MTR-104 still owes the complete final C/D and is the sole versioned publisher. Local Claude ER03/ER05/H0 PASS: c0ce5ca0-a75a-4798-8ea9-791b5104aefd. Review output SHA256: 7d76b018923d6b6b0d03713d29fdce635a4b560b99d7c8594aad7305d98c8bde. Signed-off-by: ELi Ma <eli@patch.sh>
1 parent 1a9cd76 commit cca52cc

7 files changed

Lines changed: 211 additions & 30 deletions

File tree

‎docs/plan/README.md‎

Lines changed: 3 additions & 1 deletion
Large diffs are not rendered by default.

‎docs/plan/plan-20261015.md‎

Lines changed: 23 additions & 11 deletions
Large diffs are not rendered by default.

‎docs/plan/plan-long.md‎

Lines changed: 4 additions & 2 deletions
Large diffs are not rendered by default.

‎docs/plan/plan-status.md‎

Lines changed: 5 additions & 3 deletions
Large diffs are not rendered by default.

‎docs/refactoring/protocol.md‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
> **AF1实际终态与子卡提交前沿(2026-10-25T14:33:05.791314+00:00):** DIAG-MTR-01最终自身Claude R2 a3f7bd2d PASS及signed/DCO本地提交1a9cd767已核,未推送。REL-MTR-ENV-01 R7已采纳;组合AF1十阶段exit0、五完整模块101+73+11+4+3=192唯一PASS,root于14:24:46Z核实际新编译产物、原107库名称owner及资源终态,未手工清理。FIX-MTR-13/12各自最终增量ER05与精确localcommit待;MTR-104完整C/D尚未准入。现行链99→DIAG→FIX13→FIX12→104→102→103→11→40→13→39→92→12/H1→LTR10→11→12→LTR01/H2,另有95/93→102;其余H0~H6不变。正式17/118、0/26、17/144不变,外部资格1/4。Libra FIX04 A1全量10761/21原ignored/2原生flake、源B与本地Claude e76e3d02 PASS已核,仅locally-accepted,C/D待;两flake根因未证,资格完成前按具名P2补FIX/DEFER及真实基线证据。FIX02旧C1 STOP/stash与FIX03后继保持;原REL-MTR-FIX-01退出、FIX3耗尽预算及全部旧STOP不复位。
2+
13
> **REL-MTR-ENV-01实际采纳与组合源准备(2026-10-25T13:23:46.846168+00:00):** DIAG-MTR-01 D1实际GO,七阶段exit0、root资源/来源后检与ownClaude06c202a4 PASS已核;仅证明受控Request机制,不证明历史Interrupted/交错/C2。REL-MTR-ENV-01切换R1/R2/R3/R4/R5/R6失败原件保留;实际R7 ed5d6a31-7828-40e2-bc13-2442d0932b57 于2026-10-25T13:21:47.060495+00:00 五项PASS,root已采纳;2026-10-25T13:23:18.332588+00:00 在独立legacy clone精确形成四测试文件组合树并同步21份治理。没有新AF1/C claim或提交/push;最终采纳文本自身审查及DIAG精确本地签名提交仍待。现行完整执行链:MTR-99→DIAG-MTR-01→FIX-MTR-13→FIX-MTR-12→MTR-104→MTR-102→MTR-103→MTR-11→MTR-40→MTR-13→MTR-39→MTR-92→MTR-12/H1→LTR-10→LTR-11→LTR-12→LTR-01/H2。另有MTR-95/MTR-93→MTR-102;H0~H6其余原边不变。正式17/118、0/26、17/144不变。Libra外部资格1/4;FIX04恢复R2 session15ccf47d于12:26:41Z四PASS,root采纳及精确恢复12:28:09Z已完成;执行审c8ad29bf于12:37:57Z四PASS,A1于12:38:25.742703Z已claim,终态/自身ER05/C/D尚未取得。FIX02旧C1 STOP及stash988ded20保留;FIX01→FIX04→FIX02→FIX03不替代H1。
24

35
> **历史R7候选快照(采纳前):** **环境修复聚合资格切换R7候选(2026-10-25T13:18:15.748263+00:00,仓外待审):** DIAG-MTR-01 D1实际GO,七阶段exit0、root资源/来源后检与ownClaude06c202a4 PASS已核;仅证明受控Request机制,不证明历史Interrupted/交错/C2。REL-MTR-ENV-01切换R1/R2/R3/R4/R5/R6实质G13 PASS但ER03/文档/H0总FAIL,原件保留;本R7将MTR01的H0~H6映射、SSOT §1 H0单审、两正文依赖登记与五索引对齐,并补Libra修订记录及显式历史来源说明;旧资格计划文件仍具名保留待FIX03受控整合,仍仓外待审、未正式合源/claim AF1或C。候选完整执行链:MTR-99→DIAG-MTR-01→FIX-MTR-13→FIX-MTR-12→MTR-104→MTR-102→MTR-103→MTR-11→MTR-40→MTR-13→MTR-39→MTR-92→MTR-12/H1→LTR-10→LTR-11→LTR-12→LTR-01/H2。另有MTR-95/MTR-93→MTR-102;H0~H6其余原边不变。正式17/118、0/26、17/144不变。Libra外部资格1/4;FIX04恢复R2 session15ccf47d于12:26:41Z四PASS,root采纳及精确恢复12:28:09Z已完成;执行审c8ad29bf于12:37:57Z四PASS,A1于12:38:25.742703Z已claim,终态/自身ER05/C/D尚未取得。FIX02旧C1 STOP及stash988ded20保留;FIX01→FIX04→FIX02→FIX03不替代H1。

‎docs/refactoring/traces.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
> **AF1实际终态与子卡提交前沿(2026-10-25T14:33:05.791314+00:00):** DIAG-MTR-01最终自身Claude R2 a3f7bd2d PASS及signed/DCO本地提交1a9cd767已核,未推送。REL-MTR-ENV-01 R7已采纳;组合AF1十阶段exit0、五完整模块101+73+11+4+3=192唯一PASS,root于14:24:46Z核实际新编译产物、原107库名称owner及资源终态,未手工清理。FIX-MTR-13/12各自最终增量ER05与精确localcommit待;MTR-104完整C/D尚未准入。现行链99→DIAG→FIX13→FIX12→104→102→103→11→40→13→39→92→12/H1→LTR10→11→12→LTR01/H2,另有95/93→102;其余H0~H6不变。正式17/118、0/26、17/144不变,外部资格1/4。Libra FIX04 A1全量10761/21原ignored/2原生flake、源B与本地Claude e76e3d02 PASS已核,仅locally-accepted,C/D待;两flake根因未证,资格完成前按具名P2补FIX/DEFER及真实基线证据。FIX02旧C1 STOP/stash与FIX03后继保持;原REL-MTR-FIX-01退出、FIX3耗尽预算及全部旧STOP不复位。
2+
13
> **REL-MTR-ENV-01实际采纳与组合源准备(2026-10-25T13:23:46.846168+00:00):** DIAG-MTR-01 D1实际GO,七阶段exit0、root资源/来源后检与ownClaude06c202a4 PASS已核;仅证明受控Request机制,不证明历史Interrupted/交错/C2。REL-MTR-ENV-01切换R1/R2/R3/R4/R5/R6失败原件保留;实际R7 ed5d6a31-7828-40e2-bc13-2442d0932b57 于2026-10-25T13:21:47.060495+00:00 五项PASS,root已采纳;2026-10-25T13:23:18.332588+00:00 在独立legacy clone精确形成四测试文件组合树并同步21份治理。没有新AF1/C claim或提交/push;最终采纳文本自身审查及DIAG精确本地签名提交仍待。现行完整执行链:MTR-99→DIAG-MTR-01→FIX-MTR-13→FIX-MTR-12→MTR-104→MTR-102→MTR-103→MTR-11→MTR-40→MTR-13→MTR-39→MTR-92→MTR-12/H1→LTR-10→LTR-11→LTR-12→LTR-01/H2。另有MTR-95/MTR-93→MTR-102;H0~H6其余原边不变。正式17/118、0/26、17/144不变。Libra外部资格1/4;FIX04恢复R2 session15ccf47d于12:26:41Z四PASS,root采纳及精确恢复12:28:09Z已完成;执行审c8ad29bf于12:37:57Z四PASS,A1于12:38:25.742703Z已claim,终态/自身ER05/C/D尚未取得。FIX02旧C1 STOP及stash988ded20保留;FIX01→FIX04→FIX02→FIX03不替代H1。
24

35
> **历史R7候选快照(采纳前):** **环境修复聚合资格切换R7候选(2026-10-25T13:18:15.748263+00:00,仓外待审):** DIAG-MTR-01 D1实际GO,七阶段exit0、root资源/来源后检与ownClaude06c202a4 PASS已核;仅证明受控Request机制,不证明历史Interrupted/交错/C2。REL-MTR-ENV-01切换R1/R2/R3/R4/R5/R6实质G13 PASS但ER03/文档/H0总FAIL,原件保留;本R7将MTR01的H0~H6映射、SSOT §1 H0单审、两正文依赖登记与五索引对齐,并补Libra修订记录及显式历史来源说明;旧资格计划文件仍具名保留待FIX03受控整合,仍仓外待审、未正式合源/claim AF1或C。候选完整执行链:MTR-99→DIAG-MTR-01→FIX-MTR-13→FIX-MTR-12→MTR-104→MTR-102→MTR-103→MTR-11→MTR-40→MTR-13→MTR-39→MTR-92→MTR-12/H1→LTR-10→LTR-11→LTR-12→LTR-01/H2。另有MTR-95/MTR-93→MTR-102;H0~H6其余原边不变。正式17/118、0/26、17/144不变。Libra外部资格1/4;FIX04恢复R2 session15ccf47d于12:26:41Z四PASS,root采纳及精确恢复12:28:09Z已完成;执行审c8ad29bf于12:37:57Z四PASS,A1于12:38:25.742703Z已claim,终态/自身ER05/C/D尚未取得。FIX02旧C1 STOP及stash988ded20保留;FIX01→FIX04→FIX02→FIX03不替代H1。
@@ -166,7 +168,7 @@ Libra 将工作期间捕获的脱敏记录写入 traces Git 历史,Mega2 接
166168

167169
| 交接 | 生产方 | 消费方与先后约束 | 放行凭据 |
168170
|---|---|---|---|
169-
| H0 契约冻结 | 两仓 root 当前联合治理审查;Mega2 MTR-01 登记 | 两仓实现前置;LTR-00 已取消后续验收,不再作为生产者 | 本会话按用户明确单审指令,两份计划及本契约由真实本地Claude对最终冻结输入明确PASS;冻结revision/hash与两仓真实基线。只覆盖reviewer数量和工具,保留所有来源/自身ER05/完整C/D/预算门;本轮REL-MTR-ENV-01与H0由Mega计划ENV-R1具名登记,未取得终态不得放行。 **历史列(R6审查终态2026-10-25T13:15:51.139351Z之前的原文):** 两份计划及本契约联合 Claude 与隔离 Codex PASS;冻结 revision/hash 与两仓基线 |
171+
| H0 契约冻结 | 两仓 root 当前联合治理审查;Mega2 MTR-01 登记 | 两仓实现前置;LTR-00 已取消后续验收,不再作为生产者 | 本会话按用户明确单审指令,两份计划及本契约由真实本地Claude对最终冻结输入明确PASS;冻结revision/hash与两仓真实基线。只覆盖reviewer数量和工具,保留所有来源/自身ER05/完整C/D/预算门;本轮REL-MTR-ENV-01已由R7 ed5d6a31真实五PASS/root采纳,DIAG最终文本R2 a3f7bd2d PASS并本地提交1a9cd767;组合AF1已核192唯一PASS,两个child当前最终输入的增量ER05/H0和精确localcommit仍待,MTR104 C/D未准入。 **历史适用性快照(13:15:51Z之前):** 本轮REL-MTR-ENV-01与H0由Mega计划ENV-R1具名登记,未取得终态不得放行。 **历史列(R6审查终态2026-10-25T13:15:51.139351Z之前的原文):** 两份计划及本契约联合 Claude 与隔离 Codex PASS;冻结 revision/hash 与两仓基线 |
170172
| H1 Git 服务可用 | Mega2 MTR-12,前置 MTR-13 普通 clone 隔离 | Libra LTR-10/11/12 实现 scoped push,由 LTR-01 发布;LTR-02 clone 验收 | HTTP+SSH scope/auth/FF/对象隔离验收及发布凭据,或明确的受审本地双传输 fixture;不得以最后收口作为服务启动条件 |
171173
| H2 scoped push 可用 | Libra LTR-01 | Mega2 MTR-14 起以真实 Libra 输入重建索引及验收 | 客户端发布凭据或受审本地 fixture;持久 source/epoch 和失败重试收据 |
172174
| H3 查询服务可用 | Mega2 MTR-20 | Libra LTR-13/19 capability/readiness、LTR-24 target resolve、LTR-14/15/20 导航筛选、LTR-03/04/25/05 checkpoint/search/准入/read | 列表、关键词、预算读取与水位契约的实际验收;服务版本/fixture 明确 |

‎src/config/validate.rs‎

Lines changed: 171 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2348,6 +2348,155 @@ mod tests {
23482348
isolated_config(std::env::temp_dir().join("mega2-config-validate-tests"))
23492349
}
23502350

2351+
fn legacy_env_test_child_phase(test_name: &str) -> Option<String> {
2352+
match std::env::var("MEGA2_LEGACY_ENV_TEST_CHILD") {
2353+
Err(std::env::VarError::NotPresent) => None,
2354+
Ok(name) => {
2355+
assert_eq!(name, test_name, "child test name");
2356+
Some(std::env::var("MEGA2_LEGACY_ENV_TEST_PHASE").expect("child phase"))
2357+
}
2358+
Err(std::env::VarError::NotUnicode(_)) => panic!("invalid child test name"),
2359+
}
2360+
}
2361+
2362+
fn run_legacy_env_test_child(test_name: &str, phase: &str, values: &[(&str, &str)]) {
2363+
use std::{
2364+
io::Read,
2365+
process::{Child, Command, Stdio},
2366+
sync::atomic::{AtomicBool, Ordering},
2367+
thread,
2368+
time::{Duration, Instant},
2369+
};
2370+
2371+
const OAUTH_KEYS: [&str; 3] = [
2372+
"MEGA_OAUTH__CAMPSITE_API_DOMAIN",
2373+
"MEGA_OAUTH__TINYSHIP_API_DOMAIN",
2374+
"MEGA_OAUTH__API_STORE_BACKEND",
2375+
];
2376+
let snapshot = || {
2377+
std::env::vars_os()
2378+
.filter(|(key, _)| {
2379+
OAUTH_KEYS
2380+
.iter()
2381+
.any(|name| key.as_os_str() == std::ffi::OsStr::new(name))
2382+
|| key.to_string_lossy().starts_with("MEGA_MAIL__")
2383+
})
2384+
.collect::<std::collections::BTreeMap<_, _>>()
2385+
};
2386+
const OUTPUT_LIMIT: u64 = 1024 * 1024;
2387+
struct ChildGuard(Child);
2388+
impl Drop for ChildGuard {
2389+
fn drop(&mut self) {
2390+
let _ = self.0.kill();
2391+
let _ = self.0.wait();
2392+
}
2393+
}
2394+
2395+
let before = snapshot();
2396+
let mut command = Command::new(std::env::current_exe().expect("test binary"));
2397+
command
2398+
.args([
2399+
"--exact",
2400+
test_name,
2401+
"--nocapture",
2402+
"--test-threads=1",
2403+
"--color=never",
2404+
])
2405+
.env("MEGA2_LEGACY_ENV_TEST_CHILD", test_name)
2406+
.env("MEGA2_LEGACY_ENV_TEST_PHASE", phase)
2407+
.stdin(Stdio::null())
2408+
.stdout(Stdio::piped())
2409+
.stderr(Stdio::piped());
2410+
for key in OAUTH_KEYS {
2411+
command.env_remove(key);
2412+
}
2413+
for key in before.keys() {
2414+
command.env_remove(key);
2415+
}
2416+
for (key, value) in values {
2417+
command.env(key, value);
2418+
}
2419+
let mut child = ChildGuard(
2420+
command
2421+
.spawn()
2422+
.expect("spawn isolated legacy environment test"),
2423+
);
2424+
let stdout = child.0.stdout.take().expect("child stdout");
2425+
let stderr = child.0.stderr.take().expect("child stderr");
2426+
let too_large = AtomicBool::new(false);
2427+
let deadline = Instant::now() + Duration::from_secs(20);
2428+
let read = |stream: Box<dyn Read + Send>| {
2429+
let mut bytes = Vec::new();
2430+
stream
2431+
.take(OUTPUT_LIMIT + 1)
2432+
.read_to_end(&mut bytes)
2433+
.expect("read child output");
2434+
if bytes.len() as u64 > OUTPUT_LIMIT {
2435+
too_large.store(true, Ordering::Release);
2436+
}
2437+
bytes
2438+
};
2439+
let (status, stdout, stderr) = thread::scope(|scope| {
2440+
let stdout = scope.spawn(|| read(Box::new(stdout)));
2441+
let stderr = scope.spawn(|| read(Box::new(stderr)));
2442+
let result = loop {
2443+
if too_large.load(Ordering::Acquire) {
2444+
break Err("isolated legacy environment test output limit exceeded");
2445+
}
2446+
if Instant::now() >= deadline {
2447+
break Err("isolated legacy environment test exceeded 20 seconds");
2448+
}
2449+
if snapshot() != before {
2450+
break Err(
2451+
"isolated legacy environment test changed parent legacy environment",
2452+
);
2453+
}
2454+
match child.0.try_wait() {
2455+
Ok(Some(status)) => break Ok(status),
2456+
Ok(None) => thread::sleep(Duration::from_millis(5)),
2457+
Err(_) => break Err("could not wait for isolated legacy environment test"),
2458+
}
2459+
};
2460+
// Close pipes before joining readers, including every failure path.
2461+
if result.is_err() {
2462+
let _ = child.0.kill();
2463+
let _ = child.0.wait();
2464+
}
2465+
(
2466+
result,
2467+
stdout.join().expect("stdout reader"),
2468+
stderr.join().expect("stderr reader"),
2469+
)
2470+
});
2471+
assert!(
2472+
stdout.len() as u64 <= OUTPUT_LIMIT && stderr.len() as u64 <= OUTPUT_LIMIT,
2473+
"child output limit"
2474+
);
2475+
let stdout = String::from_utf8_lossy(&stdout);
2476+
let stderr = String::from_utf8_lossy(&stderr);
2477+
assert!(
2478+
status
2479+
.expect("isolated legacy environment test completion")
2480+
.success(),
2481+
"{stdout}\n{stderr}"
2482+
);
2483+
assert_eq!(
2484+
stdout
2485+
.lines()
2486+
.filter(|line| *line == format!("test {test_name} ... ok"))
2487+
.count(),
2488+
1,
2489+
"{stdout}"
2490+
);
2491+
assert!(
2492+
stdout
2493+
.lines()
2494+
.any(|line| line.starts_with("test result: ok. 1 passed; 0 failed; 0 ignored;")),
2495+
"{stdout}"
2496+
);
2497+
assert!(snapshot() == before, "parent legacy environment changed");
2498+
}
2499+
23512500
fn assert_views_validation_error(config: Config, field: &str) {
23522501
let err = config
23532502
.validate()
@@ -2951,15 +3100,20 @@ mod tests {
29513100

29523101
#[test]
29533102
fn config_validate_rejects_legacy_oauth_environment_variables() {
2954-
use crate::config::testing::{EnvVarGuard, env_lock};
2955-
2956-
let lock = env_lock();
3103+
const TEST_NAME: &str =
3104+
"config::validate::tests::config_validate_rejects_legacy_oauth_environment_variables";
3105+
match legacy_env_test_child_phase(TEST_NAME) {
3106+
None => {
3107+
run_legacy_env_test_child(
3108+
TEST_NAME,
3109+
"oauth",
3110+
&[("MEGA_OAUTH__CAMPSITE_API_DOMAIN", "http://legacy.example")],
3111+
);
3112+
return;
3113+
}
3114+
Some(phase) => assert_eq!(phase, "oauth", "child phase"),
3115+
}
29573116
let config = valid_config();
2958-
let _var = EnvVarGuard::set(
2959-
&lock,
2960-
"MEGA_OAUTH__CAMPSITE_API_DOMAIN",
2961-
"http://legacy.example",
2962-
);
29633117
let err = config
29643118
.validate()
29653119
.expect_err("legacy MEGA_OAUTH__CAMPSITE_API_DOMAIN should fail validate");
@@ -2971,11 +3125,16 @@ mod tests {
29713125

29723126
#[test]
29733127
fn config_validate_rejects_legacy_mail_environment_variables() {
2974-
use crate::config::testing::{EnvVarGuard, env_lock};
2975-
2976-
let lock = env_lock();
3128+
const TEST_NAME: &str =
3129+
"config::validate::tests::config_validate_rejects_legacy_mail_environment_variables";
3130+
match legacy_env_test_child_phase(TEST_NAME) {
3131+
None => {
3132+
run_legacy_env_test_child(TEST_NAME, "mail", &[("MEGA_MAIL__ENABLED", "true")]);
3133+
return;
3134+
}
3135+
Some(phase) => assert_eq!(phase, "mail", "child phase"),
3136+
}
29773137
let config = valid_config();
2978-
let _var = EnvVarGuard::set(&lock, "MEGA_MAIL__ENABLED", "true");
29793138
let err = config
29803139
.validate()
29813140
.expect_err("legacy MEGA_MAIL__ENABLED should fail validate");

0 commit comments

Comments
 (0)