import Foundation enum AppSection: String, CaseIterable, Identifiable, Hashable { case overview case requests case activity case account var id: String { rawValue } var title: String { switch self { case .overview: "Passport" case .requests: "Requests" case .activity: "Activity" case .account: "Account" } } var systemImage: String { switch self { case .overview: "person.crop.square.fill" case .requests: "checklist.checked" case .activity: "clock.arrow.trianglehead.counterclockwise.rotate.90" case .account: "person.crop.circle.fill" } } } enum NotificationPermissionState: String, CaseIterable, Identifiable { case unknown case allowed case provisional case denied var id: String { rawValue } var title: String { switch self { case .unknown: "Not Asked Yet" case .allowed: "Enabled" case .provisional: "Delivered Quietly" case .denied: "Disabled" } } var systemImage: String { switch self { case .unknown: "bell" case .allowed: "bell.badge.fill" case .provisional: "bell.badge" case .denied: "bell.slash.fill" } } var summary: String { switch self { case .unknown: "The app has not asked for notification delivery yet." case .allowed: "Alerts can break through immediately when a request arrives." case .provisional: "Notifications can be delivered quietly until the user promotes them." case .denied: "Approval events stay in-app until the user re-enables notifications." } } } struct BootstrapContext { let suggestedQRCodePayload: String } struct DashboardSnapshot { let profile: MemberProfile let requests: [ApprovalRequest] let notifications: [AppNotification] } struct SignInResult { let session: AuthSession let snapshot: DashboardSnapshot } struct MemberProfile: Identifiable, Hashable { let id: UUID let name: String let handle: String let organization: String let deviceCount: Int let recoverySummary: String init( id: UUID = UUID(), name: String, handle: String, organization: String, deviceCount: Int, recoverySummary: String ) { self.id = id self.name = name self.handle = handle self.organization = organization self.deviceCount = deviceCount self.recoverySummary = recoverySummary } } struct AuthSession: Identifiable, Hashable { let id: UUID let deviceName: String let originHost: String let pairedAt: Date let tokenPreview: String let pairingCode: String init( id: UUID = UUID(), deviceName: String, originHost: String, pairedAt: Date, tokenPreview: String, pairingCode: String ) { self.id = id self.deviceName = deviceName self.originHost = originHost self.pairedAt = pairedAt self.tokenPreview = tokenPreview self.pairingCode = pairingCode } } enum ApprovalRequestKind: String, CaseIterable, Hashable { case signIn case accessGrant case elevatedAction var title: String { switch self { case .signIn: "Sign-In" case .accessGrant: "Access Grant" case .elevatedAction: "Elevated Action" } } var systemImage: String { switch self { case .signIn: "qrcode.viewfinder" case .accessGrant: "key.fill" case .elevatedAction: "shield.lefthalf.filled" } } } enum ApprovalRisk: String, Hashable { case routine case elevated var title: String { switch self { case .routine: "Routine" case .elevated: "Elevated" } } var summary: String { switch self { case .routine: "Routine access to profile or sign-in scopes." case .elevated: "Sensitive access that can sign, publish, or unlock privileged actions." } } var guidance: String { switch self { case .routine: "Review the origin and scope list, then approve if the session matches the device you expect." case .elevated: "Treat this like a privileged operation. Verify the origin, the requested scopes, and whether the action is time-bound before approving." } } } enum ApprovalStatus: String, Hashable { case pending case approved case rejected var title: String { switch self { case .pending: "Pending" case .approved: "Approved" case .rejected: "Rejected" } } var systemImage: String { switch self { case .pending: "clock.badge" case .approved: "checkmark.circle.fill" case .rejected: "xmark.circle.fill" } } } struct ApprovalRequest: Identifiable, Hashable { let id: UUID let title: String let subtitle: String let source: String let createdAt: Date let kind: ApprovalRequestKind let risk: ApprovalRisk let scopes: [String] var status: ApprovalStatus init( id: UUID = UUID(), title: String, subtitle: String, source: String, createdAt: Date, kind: ApprovalRequestKind, risk: ApprovalRisk, scopes: [String], status: ApprovalStatus ) { self.id = id self.title = title self.subtitle = subtitle self.source = source self.createdAt = createdAt self.kind = kind self.risk = risk self.scopes = scopes self.status = status } var scopeSummary: String { if scopes.isEmpty { return "No scopes listed" } let suffix = scopes.count == 1 ? "" : "s" return "\(scopes.count) requested scope\(suffix)" } var trustHeadline: String { switch (kind, risk) { case (.signIn, .routine): "Low-friction sign-in request" case (.signIn, .elevated): "Privileged sign-in request" case (.accessGrant, _): "Token grant request" case (.elevatedAction, _): "Sensitive action request" } } var trustDetail: String { switch kind { case .signIn: "This request usually creates or refreshes a session token for a browser, CLI, or device." case .accessGrant: "This request issues scoped access for a service or automation that wants to act on your behalf." case .elevatedAction: "This request performs a privileged action such as signing, publishing, or creating short-lived credentials." } } } enum AppNotificationKind: String, Hashable { case approval case security case system var title: String { switch self { case .approval: "Approval" case .security: "Security" case .system: "System" } } var systemImage: String { switch self { case .approval: "checkmark.seal.fill" case .security: "shield.fill" case .system: "sparkles" } } var summary: String { switch self { case .approval: "Decision and approval activity" case .security: "Pairing and security posture updates" case .system: "Product and environment status messages" } } } struct AppNotification: Identifiable, Hashable { let id: UUID let title: String let message: String let sentAt: Date let kind: AppNotificationKind var isUnread: Bool init( id: UUID = UUID(), title: String, message: String, sentAt: Date, kind: AppNotificationKind, isUnread: Bool ) { self.id = id self.title = title self.message = message self.sentAt = sentAt self.kind = kind self.isUnread = isUnread } } enum AppError: LocalizedError { case invalidQRCode case requestNotFound var errorDescription: String? { switch self { case .invalidQRCode: "That QR payload is not valid for idp.global sign-in." case .requestNotFound: "The selected request could not be found." } } }