feat(macOS): add gateway password auth support and fix Swift 6.2 concurrency

- Add CLAWDIS_GATEWAY_PASSWORD to launchd plist environment
- Read password from gateway.remote.password config in client
- Fix Swift 6.2 sending parameter violations in config save functions
- Add password parameter to GatewayConnection.Config type
- GatewayChannel now sends password in connect auth params
- GatewayEndpointStore and GatewayLaunchAgentManager read password from config
- CLI gateway client reads password from remote config and env
This commit is contained in:
Jefferson Nunn
2026-01-01 21:34:46 -06:00
parent 9387ecf043
commit fe87d6d8be
12 changed files with 203 additions and 61 deletions

View File

@@ -40,7 +40,7 @@ struct GatewayAgentInvocation: Sendable {
actor GatewayConnection {
static let shared = GatewayConnection()
typealias Config = (url: URL, token: String?)
typealias Config = (url: URL, token: String?, password: String?)
enum Method: String, Sendable {
case agent
@@ -83,6 +83,7 @@ actor GatewayConnection {
private var client: GatewayChannelActor?
private var configuredURL: URL?
private var configuredToken: String?
private var configuredPassword: String?
private var subscribers: [UUID: AsyncStream<GatewayPush>.Continuation] = [:]
private var lastSnapshot: HelloOk?
@@ -103,7 +104,7 @@ actor GatewayConnection {
timeoutMs: Double? = nil) async throws -> Data
{
let cfg = try await self.configProvider()
await self.configure(url: cfg.url, token: cfg.token)
await self.configure(url: cfg.url, token: cfg.token, password: cfg.password)
guard let client else {
throw NSError(domain: "Gateway", code: 0, userInfo: [NSLocalizedDescriptionKey: "gateway not configured"])
}
@@ -149,7 +150,7 @@ actor GatewayConnection {
try await Task.sleep(nanoseconds: UInt64(delayMs) * 1_000_000)
do {
let cfg = try await self.configProvider()
await self.configure(url: cfg.url, token: cfg.token)
await self.configure(url: cfg.url, token: cfg.token, password: cfg.password)
guard let client = self.client else {
throw NSError(
domain: "Gateway",
@@ -209,7 +210,7 @@ actor GatewayConnection {
/// Ensure the underlying socket is configured (and replaced if config changed).
func refresh() async throws {
let cfg = try await self.configProvider()
await self.configure(url: cfg.url, token: cfg.token)
await self.configure(url: cfg.url, token: cfg.token, password: cfg.password)
}
func shutdown() async {
@@ -264,8 +265,8 @@ actor GatewayConnection {
}
}
private func configure(url: URL, token: String?) async {
if self.client != nil, self.configuredURL == url, self.configuredToken == token {
private func configure(url: URL, token: String?, password: String?) async {
if self.client != nil, self.configuredURL == url, self.configuredToken == token, self.configuredPassword == password {
return
}
if let client {
@@ -275,12 +276,14 @@ actor GatewayConnection {
self.client = GatewayChannelActor(
url: url,
token: token,
password: password,
session: self.sessionBox,
pushHandler: { [weak self] push in
await self?.handle(push: push)
})
self.configuredURL = url
self.configuredToken = token
self.configuredPassword = password
}
private func handle(push: GatewayPush) {