feat(ios): access-token support + git-panel endpoints across the package layer

APIClient (77 -> 125 tests, coverage 92.22%): POST /auth probe with the four
distinct outcomes from the frozen contract, Cookie/Accept landed at the same
single header choke point that already enforces Origin-iff-G, plus the whole
project-ops surface the server has had since late July and iOS consumed none of:
/projects/log, /projects/pr, /projects/worktree/state, git stage/commit/push/
fetch, worktree create/remove/prune, GET /sessions, follow-up queue.

HostRegistry (30 -> 73 tests, 88.12% -> 92.49%): per-host token in the Keychain
under the existing SecItemShim conventions (device-only, never synchronizable),
charset/length validated at the boundary, old token-less records still decode.

SessionCore (93 -> 108 tests, 96.74%): the WS upgrade carries the cookie from
the same point that writes Origin, and a 401 handshake is a terminal
.unauthorized -- never entering the backoff loop, since retrying one wrong
shared token is a brute-force generator against the server's 10/min limiter.
This commit is contained in:
Yaojia Wang
2026-07-30 12:45:26 +02:00
parent c4f8b5b47f
commit 850531fd07
33 changed files with 4191 additions and 106 deletions

View File

@@ -25,4 +25,28 @@ enum Fixtures {
static func makeSuiteName() -> String {
"HostRegistryTests." + UUID().uuidString
}
// MARK: - Access-token fixtures (coordination doc §1.1)
/// 22 chars exercising EVERY class of the frozen charset
/// `[A-Za-z0-9._~+/=-]` (upper/lower/digit/`.`/`_`/`~`/`+`/`/`/`=`/`-`),
/// comfortably above the 16-char minimum. Test-only value not a secret.
static let validTokenString = "A9z._~+/=-Abcdef012345"
/// A second, distinct valid token (for "replaced/other host" assertions).
static let otherValidTokenString = "Zy8-=/+~_.9876543210fedcba"
/// Builds a valid token; traps loudly if a fixture string is malformed
/// (a broken fixture must fail the suite, not silently skip assertions).
static func makeToken(_ raw: String = Fixtures.validTokenString) -> AccessToken {
guard let token = AccessToken(rawValue: raw) else {
fatalError("test fixture token invalid: length \(raw.count)")
}
return token
}
/// A repeated-character token of an exact length (length-boundary tests).
static func tokenString(length: Int) -> String {
String(repeating: "a", count: length)
}
}