eleven / messenger Public

Clone
git clone https://amadan.net/eleven/messenger

Plain git — no account needed to clone.

Download

Download this file

1import Foundation
2
3// πŸ€– Where "home" is. Production (https://home.elevenmessenger.com) is the only
4// answer a Release build can give β€” the override below compiles out entirely β€”
5// but Debug builds (device installs, simulators, Mac dev alts) may aim at the
6// dev clone (https://home.dev.elevenmessenger.com) so native sign-in and vault
7// sync can be exercised without touching real accounts. Resolution order:
8//
9// 1. LCHAT_HOME_BASE in the process environment (an Xcode scheme, a
10// simctl/devicectl launch, a shell `open` of a Mac build), then
11// 2. the `home_base_override` string in standard UserDefaults β€” on Mac alts
12// that's per-bundle-id, which is exactly right: each alt keeps its own
13// aim (`defaults write com.elevenmessenger.messenger.mac.alt-<slug>
14// home_base_override https://home.dev.elevenmessenger.com`), then
15// 3. production.
16//
17// Resolved ONCE per launch so every surface β€” HomeClient, the ceremony's rpID,
18// the browser-handoff links, HomeSessionStore's scoping β€” agrees for the whole
19// run; changing the override means relaunching (matching how the ClickLab
20// default is read).
21public enum HomeBase {
22 public static let production = URL(string: "https://home.elevenmessenger.com")!
23
24 /// The resolved base every home surface builds URLs from.
25 public static let url: URL = resolve()
26
27 /// The WebAuthn relying-party id β€” the base's host, which is what the
28 /// production default always was. An overridden base's ceremonies bind to
29 /// ITS host (the dev clone serves its own AASA; the Debug entitlements
30 /// carry the extra webcredentials association).
31 public static var rpID: String { url.host ?? "home.elevenmessenger.com" }
32
33 /// A per-base suffix for scoping stored home state ("" on production, so
34 /// existing sessions keep their account name). The dev home has entirely
35 /// separate accounts, so a session minted against one base must never be
36 /// replayed against another β€” HomeSessionStore appends this to its
37 /// Keychain account to keep them apart.
38 public static var storageSuffix: String {
39 guard url != production else { return "" }
40 let host = url.host ?? "?"
41 return url.port.map { "#\(host):\($0)" } ?? "#\(host)"
42 }
43
44 private static func resolve() -> URL {
45 #if DEBUG
46 if let url = normalize(ProcessInfo.processInfo.environment["LCHAT_HOME_BASE"]) {
47 return url
48 }
49 if let url = normalize(UserDefaults.standard.string(forKey: "home_base_override")) {
50 return url
51 }
52 #endif
53 return production
54 }
55
56 #if DEBUG
57 /// Accept a full URL or a bare host (https assumed); reject anything a
58 /// URLRequest couldn't use, so a typo'd default falls back to production
59 /// rather than wedging every home call.
60 private static func normalize(_ raw: String?) -> URL? {
61 guard let raw else { return nil }
62 let trimmed = raw.trimmingCharacters(in: .whitespacesAndNewlines)
63 guard !trimmed.isEmpty else { return nil }
64 let withScheme = trimmed.contains("://") ? trimmed : "https://" + trimmed
65 guard let url = URL(string: withScheme), url.host != nil else { return nil }
66 return url
67 }
68 #endif
69}
70