feat(ios,android): P2 wave, git panel, token UX, per-host WS token, docs
App layer, four sequential slices (a shared .xcodeproj means adding files regenerates it, so these could not run in parallel): - token UX end to end: pairing prompts for a token when a host 401s, POST /auth validates it, and 204-without-Set-Cookie is correctly read as "this server has auth disabled" rather than "authenticated". A host paired before the token was turned on recovers by re-pairing in place. Remove-host now exists and finally gives PushRegistrar.handleHostRemoved a caller. - project git panel + worktree lifecycle (T-iOS-32) + claude --resume history — the parity gap with Android and the web front end. - terminal search (T-iOS-33) and voice PTT (T-iOS-31) with an epoch guard so a session switch between dictation and confirm cannot inject into the wrong session. - theme + Dynamic Type (T-iOS-34) and web ?join= interop (T-iOS-35). RootView no longer hard-locks .preferredColorScheme(.dark). Also unpins SwiftTerm to 1.15.0 by dropping the local hasActiveSelection that collided with the upstream one, verified green from a fresh derivedDataPath. Includes the two HIGH fixes the security review found: - iOS resolved the WS token host-independently, so a token-gated host sitting next to an open one could never open a terminal and no on-screen remedy could fix it. Now one transport per host; cross-host leakage is structurally impossible since both read paths return only that host's own value. - Android reported the host's own git-credential 401 (git-ops.ts:108, "Push authentication required on the host.") as "your access token is wrong", because a blanket 401 mapping ran ahead of the per-route one. Git-write routes are now ROUTE_DEFINED and keep the server's message. And the doc sync: README/ios README no longer claim the client is unmerged on feat/ios-client, the Clients section finally lists Android, and the plan checkboxes reflect what is actually built. iOS 534 app tests + 452 package tests; Android 687 tests.
This commit is contained in:
@@ -178,6 +178,28 @@ final class ProjectsViewModel {
|
||||
)
|
||||
}
|
||||
|
||||
/// T-iOS-32(C2)· 恢复一条历史会话:**同一条** `attach(null, cwd)` 缝,只把
|
||||
/// bootstrap 换成 `claude --resume <id>\r`(镜像 web
|
||||
/// `public/tabs.ts:918 newTabForResume`)。
|
||||
///
|
||||
/// 两道校验都在铸造 request 之前:cwd 必须是绝对路径(与上面同款纪律),
|
||||
/// 会话 id 必须过 `ProjectResumeCommand` 白名单 —— 那串字节会被拼进一条真的送进
|
||||
/// PTY 的命令行,web 侧没有这层校验,iOS 不复制这个缺口。
|
||||
func requestResumeClaude(cwd: String, sessionId: String) {
|
||||
guard Validation.isAbsoluteCwd(cwd) else {
|
||||
openErrorMessage = ProjectsCopy.openClaudeInvalidPath
|
||||
return
|
||||
}
|
||||
guard let bootstrap = ProjectResumeCommand.bootstrapInput(sessionId: sessionId) else {
|
||||
openErrorMessage = ResumeCopy.notResumable
|
||||
return
|
||||
}
|
||||
openErrorMessage = nil
|
||||
openRequest = ProjectOpenRequest(
|
||||
id: UUID(), host: host, cwd: cwd, bootstrapInput: bootstrap
|
||||
)
|
||||
}
|
||||
|
||||
// MARK: - Detail assembly(详情/差异屏的装配缝)
|
||||
|
||||
func makeDetailViewModel(path: String) -> ProjectDetailViewModel {
|
||||
|
||||
Reference in New Issue
Block a user