Files
Termind/Frameworks/TermindApplication/HostRepository.swift
T
Kaede Akino 9a36fde226 fix(pro): enforce protocol-aware host admission before mutation
Distinguish SSH route admission from Telnet target admission and wire
Telnet access and automatic Wake hooks. Await entitlement resolution for
manual Wake and duplication before host or credential mutation.

Use explicit protocol-extension forwarding overloads so existential
single-argument calls cannot bypass the concrete admission witness.
Remove dead paywall state and update obsolete quota/date test fixtures.
Validation: 81 focused macOS and 58 focused iOS tests passed.
2026-10-17 09:50:55 +08:00

68 lines
2.0 KiB
Swift

import Foundation
import TermindDomain
import struct TermindDomain.Host
public nonisolated enum HostUseCase: Hashable, Sendable {
case preferredTerminal
case sshTerminal
case telnetTerminal
case sftp
case jumpHost
case metrics
case portForwarding
case snippetExecution
case keyExport
public var protocolRequirement: HostProtocolRequirement {
switch self {
case .preferredTerminal: .anyTerminal
case .telnetTerminal: .telnet
case .sshTerminal, .sftp, .jumpHost, .metrics, .portForwarding, .snippetExecution, .keyExport: .ssh
}
}
public func accessProtocol(for host: Host) -> HostTerminalProtocol {
switch self {
case .preferredTerminal: host.preferredTerminalProtocol ?? .ssh
case .telnetTerminal: .telnet
default: .ssh
}
}
}
public nonisolated struct HostProtocolUnavailableError: LocalizedError, Equatable, Sendable {
public var useCase: HostUseCase
public init(useCase: HostUseCase) { self.useCase = useCase }
public var errorDescription: String? {
switch useCase.protocolRequirement {
case .anyTerminal: String(localized: "No terminal protocol is enabled for this Host.")
case .ssh: String(localized: "SSH is disabled for this Host.")
case .telnet: String(localized: "Telnet is disabled for this Host.")
}
}
}
public nonisolated struct HostLibrarySnapshot: Equatable, Sendable {
public var hosts: [Host]
public var groups: [HostGroup]
public static let empty = HostLibrarySnapshot(hosts: [], groups: [])
public init(hosts: [Host], groups: [HostGroup]) {
self.hosts = hosts
self.groups = groups
}
}
@MainActor
public protocol HostRepository: AnyObject {
func snapshot() throws -> RepositoryChange<HostLibrarySnapshot>
func refresh() throws
func requestHostDeletion(_ hostID: Host.ID) throws
func clearReferencesForDeletedHost(_ hostID: Host.ID) throws
func finalizeHostDeletion(_ hostID: Host.ID) throws
}