initial commit: Proximity iOS app proposal, full Swift code scaffold, reference backend, testing docs, generated Xcode project

This commit is contained in:
2026-08-12 00:22:01 +00:00
commit 9d1b0f8dd9
52 changed files with 6271 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
import Foundation
/// A single end-to-end encrypted message within a revealed connection.
struct ChatMessage: Identifiable, Codable, Hashable {
let id: UUID
let connectionID: UUID
let senderID: String
let ciphertext: Data
let sentAt: Date
var deliveredAt: Date?
var readAt: Date?
init(
id: UUID = UUID(),
connectionID: UUID,
senderID: String,
ciphertext: Data,
sentAt: Date = Date()
) {
self.id = id
self.connectionID = connectionID
self.senderID = senderID
self.ciphertext = ciphertext
self.sentAt = sentAt
}
}

View File

@@ -0,0 +1,35 @@
import Foundation
/// A fully revealed, mutually-consented connection between two present users.
///
/// Connections can **only** be created from a mutual `Encounter`. There is no
/// path to create one online you must have been physically near each other.
struct Connection: Identifiable, Codable, Hashable {
let id: UUID
let encounterID: UUID
let remoteUserID: String
let displayName: String
let createdAt: Date
let lastMessageAt: Date?
/// The E2E session key used for this conversation.
let sessionKeyID: String
init(
id: UUID = UUID(),
encounterID: UUID,
remoteUserID: String,
displayName: String,
createdAt: Date = Date(),
lastMessageAt: Date? = nil,
sessionKeyID: String
) {
self.id = id
self.encounterID = encounterID
self.remoteUserID = remoteUserID
self.displayName = displayName
self.createdAt = createdAt
self.lastMessageAt = lastMessageAt
self.sessionKeyID = sessionKeyID
}
}

View File

@@ -0,0 +1,49 @@
import Foundation
/// The physical range band a user is open to connecting within.
///
/// Each tier maps to a different sensing technology. The tiers are ordered so
/// higher tiers *include* lower ones (being open "in the area" also means
/// you're open "nearby" and "right here").
enum DistanceTier: Int, CaseIterable, Identifiable, Codable {
/// 09 m. Ultra-wideband (Nearby Interaction). "This exact person."
case rightHere = 1
/// 10100 m. Bluetooth Low Energy / iBeacon. "This room, this block."
case nearby = 2
/// 100 m50 mi. Server-relayed, opt-in coarse location. "This neighborhood."
case inTheArea = 3
var id: Int { rawValue }
var title: String {
switch self {
case .rightHere: return "Right Here"
case .nearby: return "Nearby"
case .inTheArea: return "In the Area"
}
}
var subtitle: String {
switch self {
case .rightHere: return "09 m · UWB"
case .nearby: return "10100 m · BLE"
case .inTheArea: return "100 m50 mi · Network"
}
}
/// The primary engine used for this tier.
var engine: ProximityEngine {
switch self {
case .rightHere: return .uwb
case .nearby: return .ble
case .inTheArea: return .beacon
}
}
/// Higher tiers include lower ones.
func includes(_ other: DistanceTier) -> Bool {
self.rawValue >= other.rawValue
}
}

View File

@@ -0,0 +1,55 @@
import Foundation
/// A real-world encounter between two present users.
///
/// An encounter is deliberately **anonymous** until both parties mutually
/// consent to reveal. Until then it is a "silhouette" a proof that two
/// humans were physically near each other, with no identity attached.
struct Encounter: Identifiable, Codable, Hashable {
let id: UUID
let remoteAnonToken: String
let timestamp: Date
let tier: DistanceTier
let engine: ProximityEngine
/// Coarse geohash (optional). Never precise location.
var geohash: String?
/// The relationship state of this encounter.
var status: EncounterStatus
/// A human-readable hint, e.g. "Cafe on 5th Ave" if the user tagged it.
var placeHint: String?
init(
id: UUID = UUID(),
remoteAnonToken: String,
timestamp: Date = Date(),
tier: DistanceTier,
engine: ProximityEngine,
geohash: String? = nil,
status: EncounterStatus = .silhouette,
placeHint: String? = nil
) {
self.id = id
self.remoteAnonToken = remoteAnonToken
self.timestamp = timestamp
self.tier = tier
self.engine = engine
self.geohash = geohash
self.status = status
self.placeHint = placeHint
}
}
/// Relationship lifecycle of an encounter.
enum EncounterStatus: String, Codable, Hashable {
/// Seen but not yet acknowledged. A silhouette.
case silhouette
/// This user has sent a "wave" (interest) but the other hasn't replied.
case waved
/// Both parties waved identities revealed, chat unlocked.
case mutual
/// One party declined or blocked. Permanently removed from the graph.
case declined
}

View File

@@ -0,0 +1,18 @@
import Foundation
/// The underlying sensing technology powering a connection tier.
enum ProximityEngine: String, CaseIterable, Codable {
case uwb // Nearby Interaction (U1/U2 chip)
case ble // Core Bluetooth
case beacon // Core Location (iBeacon region monitoring)
case nfc // Core NFC (tap-to-connect)
var displayName: String {
switch self {
case .uwb: return "Ultra-Wideband"
case .ble: return "Bluetooth"
case .beacon: return "Beacon"
case .nfc: return "NFC"
}
}
}

View File

@@ -0,0 +1,21 @@
import Foundation
/// The moment two present users mutually acknowledge each other.
///
/// This is the emotional climax of the product the instant two strangers
/// who were physically near each other both chose to be seen, and their
/// silhouettes resolve into people. Everything else in the app exists to
/// create this moment.
struct Reveal: Identifiable {
let id: UUID
/// The encounter that produced this reveal.
let encounter: Encounter
/// The connection created by mutual consent.
let connection: Connection
init(encounter: Encounter, connection: Connection) {
self.id = connection.id
self.encounter = encounter
self.connection = connection
}
}

View File

@@ -0,0 +1,33 @@
import Foundation
/// The user's own local identity and preferences.
///
/// Deliberately minimal: Proximity collects the *least* data needed to connect
/// humans. There is no profile photo, no bio, no social graph import.
struct UserProfile: Codable {
var id: UUID
var displayName: String
var publicKey: Data
/// Master "open to connection" state.
var isOpenToConnect: Bool
/// Preferred radius tier.
var radiusTier: DistanceTier
/// When true, the user is present but invisible to others.
var isIncognito: Bool
/// When true, the user is not discoverable at all.
var isBlocked: Bool
static let empty = UserProfile(
id: UUID(),
displayName: "",
publicKey: Data(),
isOpenToConnect: false,
radiusTier: .rightHere,
isIncognito: false,
isBlocked: false
)
}