SPB Git

spb/zyquo-router Public MIT

One local endpoint, every AI provider — a private OpenAI-compatible LLM gateway for your Mac (170 models, 12 providers).

Swift 95.7% Python 2.3% Shell 1.2% Makefile 0.9%
2.1 KB · 68 lines swift
Raw Blame History
1//2//  APIKeyRecord.swift3//  Zyquo Router4//5//  Author: Simon-Pierre Boucher6//  Mail: contact@spboucher.ai7//8//  A local router API key (`zyquo-sk-…`). The plaintext token is shown once at9//  creation and never stored — only its SHA-256 hash persists.10//1112import CryptoKit13import Foundation1415struct APIKeyRecord: Codable, Identifiable, Hashable, Sendable {16    let id: UUID17    var name: String18    /// Hex SHA-256 of the full token.19    var tokenHash: String20    /// First 12 characters of the token, for display ("zyquo-sk-a1b…").21    var tokenPrefix: String22    var enabled: Bool23    var createdAt: Date24    /// Requests per minute; nil = unlimited.25    var rateLimitPerMinute: Int?26    /// Namespaced model IDs this key may use; nil = all models.27    var allowedModels: Set<String>?2829    init(30        id: UUID = UUID(),31        name: String,32        tokenHash: String,33        tokenPrefix: String,34        enabled: Bool = true,35        createdAt: Date = Date(),36        rateLimitPerMinute: Int? = nil,37        allowedModels: Set<String>? = nil38    ) {39        self.id = id40        self.name = name41        self.tokenHash = tokenHash42        self.tokenPrefix = tokenPrefix43        self.enabled = enabled44        self.createdAt = createdAt45        self.rateLimitPerMinute = rateLimitPerMinute46        self.allowedModels = allowedModels47    }4849    /// Generates a fresh token and its record. The token is returned exactly once.50    static func generate(name: String) -> (record: APIKeyRecord, token: String) {51        let random = Data((0..<24).map { _ in UInt8.random(in: 0...255) })52        let token = "zyquo-sk-" + random.base64EncodedString()53            .replacingOccurrences(of: "+", with: "a")54            .replacingOccurrences(of: "/", with: "b")55            .replacingOccurrences(of: "=", with: "")56        let record = APIKeyRecord(57            name: name,58            tokenHash: Self.hash(token),59            tokenPrefix: String(token.prefix(12))60        )61        return (record, token)62    }6364    static func hash(_ token: String) -> String {65        SHA256.hash(data: Data(token.utf8)).map { String(format: "%02x", $0) }.joined()66    }67}68