Reviewer: GPT-6-Astra via Codex, on Paul's instruction.
VERDICT: APPROVE-WITH-NITS — feat/k1-transport-supplier @ 96820a322ff9edc6b8498adc961ea2dae8edaf82
Reviewed as one diff against its stated parent e2db36e, not against main; binding spec is spec/offline-kit@6049830 §3.1 and K1. No blocking finding in this consumer diff.
- P3 / nonblocking — native/apple/Tests/DocsKitTests/TransportSupplierTests.swift:39 and native/apple/Sources/DocsApp/DocsAccountWindow.swift:19: the two committed tests cover replacing a session transport, but neither exercises the actual account-ID guard, nil supplier, or a late stream event across an account switch. Removing the guard would leave those tests green. Fix: add account-bound supplier integration coverage for A→B and B→A, nil, in-flight completion and an old stream callback; preferably expose the production supplier seam to the test rather than copying its predicate. This is a coverage gap, not an observed isolation bug.
Account-switching ruling: safe under the current ownership model. DocsModel resolves the supplier on MainActor synchronously before each await. DocsAccountWindow captures the model's account ID and returns nil if that account is no longer active; NativeConnection account/client replacement has no suspension between its writes. Once selected, NativeHTTP's origin and credential are immutable. An already-started A operation may finish after B becomes active, but still uses A's client. Any next request from A's model fails locally while B is active, including the second request in open/create, a save after mergeUpdates yields, stream-triggered refreshes, and reconnects. The same reasoning holds B→A. .id(account) gives the new account a separate model, so old-model results cannot populate B's model. stop cancels eligible streams; even an older stream that survives briefly cannot acquire B's client.
Separate macOS document windows intentionally retain their entry's captured account/client and may keep working on A while the account window shows B. They are still bound to A; they are not redirected through B. Refreshing those document-window clients during reauthentication remains the stated K5 follow-up, so this is not approval to claim reauthentication is complete.
Verification:
- rustup cargo first on PATH; native/scripts/check-native.sh PASSED: Rust engine/host and wire checks, all native slices, 49 XCTest cases (3 existing fixture-dependent skips), and 16 Swift Testing cases. Both new supplier tests ran and passed. Hub CI is green at 96820a3.
- Scratch-only model probes with the inspected account-bound supplier contract: suspend A's document request, switch to B, resume; repeat B→A; and release an A stream event after switching to B. Both tests passed and the other account's transport received no request. These probes validate model behavior; they do not replace a committed test of the production view predicate.
- Mutation: evaluating the supplier only once in init made both new TransportSupplierTests fail, with 6 relevant assertions (including the edit going to the ended transport). Restored implementation: both passed.
Dependency/landing order: this approval concerns the Docs diff. rastrillo/native #6 has a blocking raw-cancellation finding; correct and land it first, then re-pin every Docs Swift pin site to the approved native main, as the opening post already requires. Keep K0's Go-module change. No merge performed.
The four shared-library departures are ruled on rastrillo/native #6: accept .transport as transient (but normalize cancellation), accept Equatable/nested RetryClass, accept generic rateLimited copy, accept the per-call responder. Native make ci and Calendar's Swift/xcodegen/simulator gates also passed during this review. All work ran in detached /tmp scratch worktrees; no branch was edited, committed, pushed or merged.