Skip to content

Apple Deployment (macOS & iOS)

Purple8 Graph ships a native Swift client and full SwiftUI app for macOS 14+ and iOS 17+. Everything lives in sdk/swift/ — zero external dependencies.

What's included

TargetTypeDescription
Purple8GraphLibraryPure Swift REST client — Purple8Client with 7 sub-clients, Codable models, AnyJSON, typed errors
Purple8GraphUILibrarySwiftUI screens — License gate, Login, Dashboard, Graph Explorer, Query Builder, Settings
Purple8GraphAppExecutableRunnable macOS / iOS app wrapping the two libraries above

App screens

License gate  →  server URL + Stripe license key validation

Login         →  username/password or API key

Dashboard     →  health, stats, quick Cypher, active journeys
Graph Explorer→  hybrid search → node detail → traversal
Query Builder →  full Cypher editor + dynamic results table
Settings      →  server URL, subscription info, disconnect, deactivate

Run in Xcode

bash
# From the repo root:
open sdk/swift/Package.swift
  1. Xcode opens the package automatically
  2. Select the Purple8GraphApp scheme (top toolbar)
  3. Select My Mac (or a connected iPhone / simulator) as the destination
  4. Press ▶ Run (⌘R)
  5. The license gate appears — enter your server URL and Stripe license key

Requirements

Version
Swift5.9+
Xcode15+
macOS (run)14 Sonoma+
iOS (run)17+
Purple8 Graph server0.23.0+

License gate flow

Every app launch checks for a validated license before showing the login screen:

isLicensed == false         →  LicenseGateView  (paste Stripe key → validate)
isLicensed == true  &&
isAuthenticated == false    →  LoginView         (username/password or API key)
isAuthenticated == true     →  ContentView       (main app)

The validated license key is stored in the system Keychain (not UserDefaults) — encrypted at rest, survives app reinstalls. Deactivating a device removes it from the Keychain so the seat can be transferred.


Distribute for macOS

Step 1 — Archive

Product ▸ Archive

Wait for the archive, then in the Organizer:

Distribute App
  → Developer ID          ← direct download / .dmg (recommended for B2B SaaS)
  → App Store Connect     ← Mac App Store
  → Custom                ← internal / enterprise

For Developer ID you need:

  • Apple Developer Program membership ($99/yr)
  • A Developer ID Application certificate in Keychain
  • Notarization — Xcode handles this automatically during export

The export produces a signed, notarized Purple8 Graph.app.

Step 2 — Wrap in a .dmg

bash
brew install create-dmg

create-dmg \
  --volname "Purple8 Graph" \
  --volicon "path/to/AppIcon.icns" \
  --background "path/to/dmg-background.png" \
  --window-pos 200 120 \
  --window-size 660 400 \
  --icon-size 128 \
  --icon "Purple8 Graph.app" 180 170 \
  --hide-extension "Purple8 Graph.app" \
  --app-drop-link 480 170 \
  "Purple8-Graph-0.23.0.dmg" \
  "path/to/export-folder/"

This produces Purple8-Graph-0.23.0.dmg — a standard drag-and-drop installer ready to email to subscribers.


Distribute for iOS / TestFlight

  1. In Xcode select an iPhone destination (real device or simulator)
  2. Product ▸ Archive
  3. Distribute App ▸ TestFlight — uploads directly to App Store Connect for beta testing

Use as a library in your own app

Add the Swift package as a dependency in Xcode (File → Add Package Dependencies) or in your own Package.swift:

swift
// Local dependency:
.package(path: "../../sdk/swift")

// Remote (after the repo is public):
.package(url: "https://github.com/Redlock666/purple8-graph", from: "0.23.0")

Minimum integration — embed the full SwiftUI app in your own app:

swift
import SwiftUI
import Purple8GraphUI

@main
struct MyApp: App {
    @StateObject private var appState = Purple8AppState()
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(appState)
        }
    }
}

Or use just the REST client without any UI:

swift
import Purple8Graph

let client = Purple8Client(baseURL: URL(string: "https://graph.acme.com")!)
try await client.auth.login(username: "admin", password: "secret")

let node = try await client.nodes.create(
    nodeID: "person_001",
    labels: ["Person"],
    properties: ["name": "Alice", "age": 30]
)

let results = try await client.search.vector(
    queryEmbedding: embedding,
    topK: 5,
    labelFilter: "Person"
)

Architecture

Purple8GraphApp  (executable — @main entry point)
    └── Purple8GraphUI  (SwiftUI library)
            ├── Purple8AppState      @MainActor ObservableObject — owns client, auth, license
            ├── LicenseGateView      Server URL + Stripe key activation
            ├── LicenseValidator     Calls /auth/validate-license → Keychain storage
            ├── LoginView            Username/password or API key
            ├── ContentView          TabView (iOS) / NavigationSplitView (macOS)
            ├── DashboardView        Health indicator, stats, quick Cypher, journeys
            ├── GraphExplorerView    Hybrid search → node detail card → BFS traversal
            ├── QueryBuilderView     Cypher editor → dynamic results table
            └── SettingsView         Server URL, subscription plan, disconnect, deactivate
        └── Purple8Graph  (networking library — no SwiftUI dependency)
                ├── Purple8Client    Facade — 7 sub-clients
                ├── AuthClient       Login, logout, refresh, /auth/me, validate-license
                ├── NodesClient      CRUD + bulk create + count
                ├── EdgesClient      CRUD + existence check
                ├── SearchClient     Vector + hybrid + BM25 search
                ├── QueryClient      Cypher POST /v1/query
                ├── JourneysClient   Start, advance, cancel, audit, list
                ├── KMSClient        Status, list, rotate, disable/enable
                ├── TokenStore       actor — thread-safe token + auto-refresh on 401
                ├── Models           All Codable types + AnyJSON
                └── Errors           Purple8Error enum + HTTP factory

App entitlements

The app is fully sandboxed. The shipped entitlements enable:

EntitlementReason
com.apple.security.app-sandboxRequired for Mac App Store; recommended for Developer ID
com.apple.security.network.clientOutbound URLSession calls to the Purple8 Graph server

For development against a local http:// server, NSAllowsLocalNetworking: true is set in Info.plist — HTTPS exceptions are not needed in production.

Purple8 Graph is proprietary software. All rights reserved.