Update: 将子项目从 submodule 转为完整内容

- 移除 GovAI, nomifun-tauri, 算力盒子 的 submodule 引用
- 添加所有子项目的完整源代码
- 保留原始 .git 为 .git.bak 备份
This commit is contained in:
freedak
2026-07-04 19:20:46 +08:00
parent 54d6465fa7
commit f7a720204a
3360 changed files with 802660 additions and 3 deletions
@@ -0,0 +1,133 @@
//! **P3 W4bcookie storage_state 捕获/恢复 端到端集成**`#[ignore]`,本机/打包 chrome)。
//!
//! 验证 W4bcookie 捕获/恢复机制):
//! - **往返保真**restore 一条全字段 cookie(含 sameSite + 持久 expires)→
//! capture 读回 → 名/值/域/sameSite/expires 全保真(**核心验收:cookie 跨 capture/restore 往返保真**)。
//! - **登录态可灌**restore 的 cookie 真写进 cookie storecapture 读回即证「灌入生效」,
//! 且 navigate 到该域后仍在——浏览器接受了它为该域的 cookie,跨导航存活 = 登录态可经 restore 灌入)。
//! - **默认 context 零回归**capture/restore 走默认 context(不传 browserContextId),机制仍工作。
//!
//! **W4b 不验 localStorage/IndexedDBW4c)也不验磁盘 vault 持久化(W4d)**。本测试只走**内存往返**
//! capture → StorageState → restore)。
//!
//! **为何用 `Storage.getCookies/setCookies` 而非 `Network.getAllCookies`**:见
//! [`nomi_browser_engine::backend::CdpBackend::capture_cookies`] 文档——本 chromiumoxide_cdp 版本无
//! `Network.getAllCookies`,且 `Network.*` 是 session 级无法按 browserContextId 取/设;`Storage.*` 支持
//! `browserContextId`,是正确的 CDP 面。
//!
//! 手动跑(本机 Windows 有系统 Chrome):
//! set NOMIFUN_CHROME_BINARY=...\chrome.exe
//! cargo nextest run -p nomi-browser-engine --run-ignored all -E 'test(w4b)'
//! 跑完核对任务管理器无残留 chromeBuilder kill_on_drop + disposeOnDetach 自动清)。
//!
//! 真实结果(本机首跑 eprintln 出捕到的 cookie——填回任务汇报)。
use nomi_browser_engine::storage_state::{SameSite, StorageState, StorageStateCookie};
use nomi_browser_engine::BrowserEngine;
mod common;
/// 造一条**全字段非默认**的 storage_state cookie(持久 + sameSite=Lax + secure),灌进 context 后
/// 应能原样 capture 回。`name`/`value` 用易辨识串便于断言。
///
/// **注**:不带 CHIPS partitionKey——分区 cookie 的 `Storage.setCookies` 接受依赖 chrome 的 CHIPS 支持
/// 与 topLevelSite 形态,集成里灌非分区 cookie 验主路径(partitionKey 的纯逻辑往返已在
/// `storage_state::tests` 钉死;分区 cookie 真灌入留 W4d/真站验)。
fn login_cookie(name: &str, value: &str) -> StorageStateCookie {
StorageStateCookie {
name: name.into(),
value: value.into(),
// example.com(与下方 navigate 目标同域,验「登录态灌入该域」)。
domain: ".example.com".into(),
path: "/".into(),
// 持久 cookie(远未来过期),非 session——跨导航存活。
expires: 4_102_444_800.0, // 2100-01-01
http_only: false, // 非 httpOnly:若要 document.cookie 验也读得到(本测试以 capture 为主)。
secure: false,
session: false,
same_site: Some(SameSite::Lax),
priority: nomi_browser_engine::storage_state::Priority::Medium,
source_scheme: nomi_browser_engine::storage_state::SourceScheme::NonSecure,
source_port: -1,
partition_key: None,
}
}
/// 在一组 capture 回的 cookie 里按 name 找。
fn find<'a>(state: &'a StorageState, name: &str) -> Option<&'a StorageStateCookie> {
state.cookies.iter().find(|c| c.name == name)
}
/// **往返保真 + 登录态可灌**restore 一条全字段 cookie → capture 读回保真 →
/// navigate 到该域后再 capture 仍在(浏览器接受为该域 cookie,跨导航存活 = 登录态灌入生效)。
#[tokio::test]
#[ignore = "需本机/打包 chromeset NOMIFUN_CHROME_BINARY 后 --run-ignored all"]
async fn w4b_cookie_round_trip_and_login_state_loadable() {
let backend = common::build_backend_for_fixture("w4b-rt").await;
// 1) restore:把一条登录态 cookie 灌进默认 context。
let state = StorageState {
cookies: vec![login_cookie("nomi_session", "login-token-abc123")],
..Default::default()
};
backend
.restore_cookies(&state)
.await
.expect("restore_cookies into default context");
// 2) capture:读回——名/值/域/sameSite/expires 全保真(核心验收:往返保真)。
let captured = backend.capture_cookies().await.expect("capture_cookies");
eprintln!(
"=== w4b captured {} cookie(s) === {:?}",
captured.cookies.len(),
captured.cookies
);
let c = find(&captured, "nomi_session")
.expect("restored cookie must be captured back (login state loaded into context)");
assert_eq!(c.value, "login-token-abc123", "cookie value must round-trip");
assert_eq!(c.domain, ".example.com", "cookie domain must round-trip");
assert_eq!(c.path, "/", "cookie path must round-trip");
assert_eq!(c.same_site, Some(SameSite::Lax), "sameSite must round-trip (not lost/defaulted)");
assert!(!c.session, "persistent cookie must not be a session cookie");
// 持久 cookieexpires 是一个真实的未来时间戳(非 -1/session)。**注**Chrome 把远未来过期时间
// 钳到「~400 天上限」(cookie max-age 政策,RFC 6265bis),故灌 2100 年会被钳到约一年后——这是
// 浏览器正确行为,不是丢字段。验「仍是持久 cookie(expires>0 且远在未来)」而非精确值。
assert!(
c.expires > 1_700_000_000.0,
"persistent cookie must keep a real future expiry (Chrome clamps far-future to ~400d), got {}",
c.expires
);
// 3) 登录态可灌:navigate 到该域后 cookie 仍在 context(浏览器接受为 example.com 的 cookie
// 跨导航存活)——这就是「登录态经 restore 灌入、后续请求带得上」的真实信号。
let nav = backend
.navigate("https://example.com", false)
.await
.expect("navigate to example.com");
eprintln!("=== w4b nav after restore === final_url={}", nav.final_url);
let after_nav = backend.capture_cookies().await.expect("capture after navigate");
assert!(
find(&after_nav, "nomi_session").is_some(),
"restored cookie must survive navigation (login state loadable into the domain): {:?}",
after_nav.cookies
);
}
/// **默认 context 零回归**capture/restore 走默认 context(不传
/// browserContextId),机制仍工作(restore→capture 往返)。
#[tokio::test]
#[ignore = "需本机/打包 chromeset NOMIFUN_CHROME_BINARY 后 --run-ignored all"]
async fn w4b_default_context_capture_restore_works() {
let backend = common::build_backend_for_fixture("w4b-default").await;
let state = StorageState {
cookies: vec![login_cookie("default_ctx_cookie", "v-default")],
..Default::default()
};
backend.restore_cookies(&state).await.expect("restore default context");
let captured = backend.capture_cookies().await.expect("capture default context");
eprintln!("=== w4b default-context captured {} cookie(s) ===", captured.cookies.len());
let c = find(&captured, "default_ctx_cookie")
.expect("default-context cookie must round-trip");
assert_eq!(c.value, "v-default");
}