Switch to prefixed IDs and tell agents which Mac a message came from

This commit is contained in:
Ian Gulliver
2026-10-20 23:15:19 -07:00
parent f1296ba13d
commit 59bf17189d
42 changed files with 770 additions and 145 deletions
+1 -1
View File
@@ -101,7 +101,7 @@ func errorText(_ error: any Error) -> String {
return String(describing: e)
}
private let clientID = UUID().uuidString
private let clientID = newID("cli")
let macName = Host.current().localizedName ?? ProcessInfo.processInfo.hostName
final class API: Sendable {
+1 -1
View File
@@ -545,7 +545,7 @@ struct ComposerView: View {
let imgs = images.take(draftKey)
text = ""
let sent = drafts.startSend(draftKey, value, imgs.count)
let sendID = UUID().uuidString
let sendID = newID("snd")
let cancel = chat.team ? { true } : chat.builder.showPending(value, imgs, sendID)
let sessionId = m.live?.id
Task {
+39
View File
@@ -38,6 +38,45 @@ final class DraftSend {
}
}
@MainActor
func migrateRecordIDs() {
var changed = false
for v in fetchRecords(FetchDescriptor<VisitRecord>()) where migratedID("tsk", v.taskId) != v.taskId {
v.taskId = migratedID("tsk", v.taskId)
changed = true
}
let composerKey = { (key: String) in
key.hasPrefix("message:") ? "message:" + migratedID("tsk", String(key.dropFirst("message:".count))) : migratedID("tsk", key)
}
let task = { (key: String) in migratedID("tsk", key) }
let item = { (key: String) in migratedID("inb", key) }
func rekey<V>(_ d: [String: V], _ f: (String) -> String) -> [String: V] {
Dictionary(d.map { (f($0.key), $0.value) }) { a, _ in a }
}
for record in fetchRecords(FetchDescriptor<DraftRecord>()) {
guard var saved = try? JSONDecoder().decode(Saved.self, from: record.json) else {
continue
}
let comments = saved.comments ?? [:]
let moved = saved.composer.keys.contains { composerKey($0) != $0 } || saved.checked.keys.contains { item($0) != $0 } || saved.texts.keys.contains { item($0) != $0 } || comments.keys.contains { task($0) != $0 }
guard moved else {
continue
}
saved.composer = rekey(saved.composer, composerKey)
saved.checked = rekey(saved.checked, item)
saved.texts = rekey(saved.texts, item)
saved.comments = saved.comments.map { rekey($0, task) }
guard let json = try? JSONEncoder().encode(saved) else {
continue
}
record.json = json
changed = true
}
if changed {
saveRecords()
}
}
func draftOrigin(_ origin: URL) -> String {
let c = URLComponents(url: origin, resolvingAgainstBaseURL: false)!
let scheme = (c.scheme ?? "https").lowercased()
+1 -1
View File
@@ -28,7 +28,7 @@ final class Forwards {
}
var c = URLComponents()
c.scheme = "http"
c.host = "\(slug(key.name).isEmpty ? "preview" : slug(key.name))-\(taskId.prefix(6)).localhost"
c.host = "\(slug(key.name).isEmpty ? "preview" : slug(key.name))-\(taskId.lowercased()).localhost"
c.port = local
c.path = "/"
return c.url
+22
View File
@@ -0,0 +1,22 @@
import CryptoKit
import Foundation
private let idAlphabet = Array("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
func newID(_ prefix: String) -> String {
prefix + String((0..<11).map { _ in idAlphabet.randomElement()! })
}
// IDs from before prefixed IDs were 12 lowercase hex characters; the server renamed each to this same derivation.
func migratedID(_ prefix: String, _ old: String) -> String {
guard old.count == 12, old.allSatisfy({ "0123456789abcdef".contains($0) }) else {
return old
}
var n = SHA256.hash(data: Data(old.utf8)).prefix(8).reduce(UInt64(0)) { $0 << 8 | UInt64($1) }
var out = ""
for _ in 0..<11 {
out.append(idAlphabet[Int(n % UInt64(idAlphabet.count))])
n /= UInt64(idAlphabet.count)
}
return prefix + out
}
+2
View File
@@ -21,6 +21,7 @@ final class Servers {
@ObservationIgnored var openWindow: (() -> Void)?
private init() {
migrateRecordIDs()
load()
current = origins.first
Task {
@@ -30,6 +31,7 @@ final class Servers {
}
synced(event, end)
if event.type == .import {
migrateRecordIDs()
for connection in connections.values {
connection.store?.drafts?.reload()
}