feat(browser): unify site credentials with browser profiles (BR-2)

- Inject the site account Cookie (manual + auto-login session, session wins)
  into the camofox profile before the first tab opens; password accounts
  without a session run refresh-login first; API Key sites are skipped.
- Cookie expired after injection -> credential.status=expired; cookie
  accounts go to waiting/login_required ("log in once, applies site-wide").
- Write back site-domain cookies from the browser on handover, session close,
  every 10 min of activity, and from refresh-login when the stored cookie is
  invalid (verified before saving). user_info.cookieOrigin records
  source=browser; source shown as manual/login/browser in the origin view.
- New camofox plugin umt-cookies (GET/POST /umt/sessions/:userId/cookies
  under the access key); profile dir 0700/files 0600 in the desktop image.
- Single entry: sources-identity/service/credentials.ts.
- Real check: HHClub cookie injected into a fresh profile -> home page
  logged in (logout link present), 5 cookies read back.

Requires rebuilding umt-browser-desktop (docker compose build camofox &&
docker compose up -d camofox) to take effect.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-09-29 15:25:07 +08:00
1 parent 901b01d1a1
commit 28974d1e1a
58 files changed
+2843 -1112

No files matched your search

+17
View File
@@ -1,6 +1,7 @@
import type {
BrowserCapabilities,
BrowserControlLease,
BrowserCookie,
BrowserHealth,
BrowserLeaseHolderKind,
BrowserProviderKind,
@@ -65,6 +66,18 @@ export interface BrowserProvider {
* 只读,不要求自动化控制权;上游不支持 evaluate 时返回 null。
*/
pageMetrics(ref: TabRef): Promise<PageMetrics | null>;
// ── BR-2 凭据统一 ──
/**
* 把 Cookie 写进该 profile 的浏览器上下文(并落盘到 profile)。上游没有可用的 Cookie 接口时报
* BrowserError("not_implemented")。Cookie 值不进日志与错误信息。
*/
setCookies?(profileKey: string, cookies: BrowserCookie[]): Promise<{ count: number }>;
/**
* 读该 profile 作用于这些地址的 Cookie(活动上下文优先,否则读 profile 落盘文件);没有时返回空数组。
* 上游没有接口时报 BrowserError("not_implemented")。
*/
getCookies?(profileKey: string, urls: string[]): Promise<BrowserCookie[]>;
}
export interface PageMetrics {
@@ -106,12 +119,16 @@ export interface OpenSessionRequest {
/** 可选初始地址,同样受 budget 约束 */
initialUrl?: string;
budget: NavigationBudget;
/** 打开前先注入的 Cookie(站点账号登录态,BR-2);注入失败不阻止打开,结果见 OpenSessionResult.cookies */
cookies?: BrowserCookie[];
}
export interface OpenSessionResult {
session: BrowserSession;
tab: BrowserTab;
navigation: NavigationResult | null;
/** 传了 cookies 时:injected = 注入个数;unsupported = 上游没有 Cookie 接口;failed = 请求失败 */
cookies?: { status: "injected" | "unsupported" | "failed"; count: number };
}
/** 会话内标签页定位;tabId 缺省 = 会话当前标签页 */