Skip to Content
Archived · These docs describe Solid(ar)ity 1.x and are no longer updated. Solidarity now builds creds → creds.id
Usage GuideApp Features

App Features

Solidarity uses three main tabs to organize all functionality. Below is the screen structure, key components, and corresponding code for each tab.

Tab Structure

┌──────────────┬──────────────┬──────────────┐ │ People │ Share │ Me │ │ person.2 │ qrcode │ person.text │ │ .fill │ .viewfinder │ .rectangle │ └──────────────┴──────────────┴──────────────┘

Code: solidarity/Views/Common/MainTabView.swift

TabViewDescription
PeoplePeopleListView.swiftContact list, face-to-face exchange entry
ShareSharingTabView.swiftQR Code display + proximity radar
MeMeTabView.swiftIdentity credential management, proof presentation

The QR Scanner is in the top-left of Share Tab → ScanTabView.swift.


Tab 1 — People

Main Screen [PL-1] People List

┌─ Navigation Bar ────────────────────────┐ │ People [+] [↔ Exchange] │ ├─────────────────────────────────────────┤ │ 🔍 Search │ ├─ Verified ──────────────────────────────┤ │ 👤 Mei ✅ 2025-03-15 │ │ Sprout Labs · Designer │ │ "Met at DID workshop!" │ ├─ Contacts ──────────────────────────────┤ │ 👤 Alice Wang │ │ (imported from phone contacts) │ └──────────────────────────────────────────┘

Components:

  • Verified section — contacts exchanged face-to-face (isVerified = true), shows exchange date and ephemeral message snippet
  • Contacts section — imported or manually added contacts
  • [↔ Exchange] → EX-1 Discovery (face-to-face exchange flow)
  • [+] → PL-3 manually add contact

Empty states:

  • No contacts at all [PL-1e] → CTA “Import phone contacts”
  • Has contacts but no verified [PL-1v] → “No face-to-face verified contacts yet” + [Exchange Cards]

Code: solidarity/Views/PeopleViews/PeopleListView.swift


Person Detail [PL-2]

┌─ Navigation Bar ────────────────────────┐ │ [← Back] Mei [Share] [Edit] │ ├──────────────────────────────────────────┤ │ [Avatar] │ │ Mei │ │ Sprout Labs · Product Designer │ │ ✅ Verified · 2025-03-15 │ │ 📍 ETHGlobal Taipei │ ├─ Ephemeral Message ─────────────────────┤ │ 💬 You wrote to Mei: │ │ "Met at DID workshop!" │ │ 💬 Mei wrote to you: │ │ "Great meeting you! 🙌" │ ├─ Contact Info ──────────────────────────┤ │ 📧 [email protected] │ │ 📱 0912-345-678 │ │ 🔗 linkedin.com/in/mei │ ├─ Actions ───────────────────────────────┤ │ [Call] [Email] [Share Contact] │ └──────────────────────────────────────────┘

The ephemeral message section only appears for isVerified = true contacts.


Tab 2 — Share

Main Screen SharingTabView

┌─ Navigation Bar ──────────────────────────┐ │ [📷 Scan] Share │ ├────────────────────────────────────────────┤ │ │ │ [Your Business Card QR Code] │ │ │ │ ┌─────────────────────────────────┐ │ │ │ [QR Code] │ │ │ └─────────────────────────────────┘ │ │ │ │ Ming · Acme Corp │ │ │ │ [Radar / Nearby] [Share Link] │ └────────────────────────────────────────────┘

Components:

  • QR Code display — outputs one of three formats based on sharingFormat
  • [📷 Scan] — top-left scanner entry → ScanTabView
  • [Radar] — launch proximity matching → MatchingView

Code:

  • solidarity/Views/SharingViews/SharingTabView.swift
  • solidarity/Services/Card/QRCodeGenerationService.swift
  • solidarity/Views/MatchViews/MatchingView.swift

QR Scanner [SC-1] ScanTabView

┌──────────────────────────────────────────┐ │ [Full-screen camera] │ │ │ │ ┌────────────┐ │ │ │ QR frame │ │ │ └────────────┘ │ │ │ │ Scan QR Code │ │ Present proof · Receive credential │ │ · Verify others │ └──────────────────────────────────────────┘

QR Router [SC-2] — parses QR payload and routes:

QR PrefixActionTarget Screen
openid4vp://Present ProofPR-1 Proof Request Review
VP token (JWT)Verify ProofVF-1 Verification Result
solidarity-verify://Self-hosted verifier deep linkVF-1
VCF formatAdd contactPL-3 pre-filled
UnrecognizedErrorinline toast

Code: solidarity/Views/ScanViews/ScanTabView.swift, solidarity/Services/Card/QRCodeScanService.swift


Tab 3 — Me

Main Screen [Me-1] Me Overview

┌─ Navigation Bar ────────────────────────┐ │ My Identity [⚙️] │ ├──────────────────────────────────────────┤ │ [Avatar] │ │ Ming │ │ did:key:z6Mk... (tap to reveal) │ ├─ My Identity Cards ────────────────────┤ │ ┌───────────────────────────────────┐ │ │ │ 🛂 Passport 🟢 Government │ │ │ │ Trust: ROC Ministry of Foreign │ │ │ │ Affairs · ZKP Verified ✓ │ │ │ │ [View Details →] │ │ │ └───────────────────────────────────┘ │ │ ┌───────────────────────────────────┐ │ │ │ 🕸️ Social Graph ⚪ Self-Issued │ │ │ │ 47 face-to-face verified contacts │ │ │ │ [View Details →] │ │ │ └───────────────────────────────────┘ │ ├─ What I Can Prove ─────────────────────┤ │ ┌───────────────────────────────────┐ │ │ │ 🟢 I'm 18+ [Present →]│ │ │ │ Source: Passport · ZKP │ │ │ ├───────────────────────────────────┤ │ │ │ 🟢 I'm a real human [Present →]│ │ │ │ Source: Passport · ZKP │ │ │ └───────────────────────────────────┘ │ ├─ Add More ─────────────────────────────┤ │ [+ Scan Passport] [+ Import Credential]│ └──────────────────────────────────────────┘

Trust level badges:

  • 🟢 Government — passport ZKP verified
  • 🔵 Institution — institution-issued VC (v2)
  • ⚪ Self-issued — social graph and other self-issued VCs

[Present →] → [PR-1b] Self-Initiated QR Display, shows Smart QR for verifier to scan.

Code: solidarity/Views/MeViews/MeTabView.swift


Settings [ST-1] (accessed via ⚙️ in Me Tab)

┌─ Navigation Bar ────────────────────────┐ │ [← Back] Settings │ ├─ Account ───────────────────────────────┤ │ Device key: ✅ Created │ │ Cross-device sync: ✅ iCloud Keychain │ ├─ Security ──────────────────────────────┤ │ Social Recovery: ✅ Set (5 guardians) │ ├─ Backup ────────────────────────────────┤ │ iCloud Backup [Toggle] │ ├─ Import / Export ──────────────────────┤ │ [Import VCF Contacts] │ │ [Export All Data] → Face ID confirm │ │ [Export Social Graph] → Face ID confirm │ ├─ Advanced ──────────────────────────────┤ │ [View My DIDs] │ │ [Regenerate ZK Proof] │ └──────────────────────────────────────────┘

Code: solidarity/Views/SettingsViews/ (multiple settings screens)


Data Models

Contact

// solidarity/Models/Contact.swift @Model class Contact { var name: String var isVerified: Bool = false // true only for face-to-face exchanges var verifiedAt: Date? var didPublicKey: String? // peer's DID public key var exchangeSignature: Data? // peer's exchange signature var myExchangeSignature: Data? // my exchange signature (for Graph Export) var myEphemeralMessage: String? // message I wrote to them var theirEphemeralMessage: String? // message they wrote to me var source: String // "imported" | "exchanged" | "manual" }

IdentityCard

// solidarity/Models/IdentityEntities.swift @Model class IdentityCard { var type: String // "passport" | "socialGraph" | "imported" var trustLevel: String // "government" | "institution" | "selfIssued" var issuerName: String // "ROC Ministry of Foreign Affairs" var verificationMethod: String // "ZKP Verified" | "NFC Verified" var rawVC: Data // serialized W3C VC }

Screen ID Index (42 screens)

IDScreenTab / ContextPriority
O-1 ~ O-5Onboarding flowOnboardingP0/P1
PL-1, PL-1e, PL-1vPeople ListPeopleP0
PL-2, PL-3Person Detail / Add ContactPeopleP0
EX-1 ~ EX-5Face-to-face exchange flowPeople (modal)P0
SC-1, SC-2Scan Camera + RouterShareP0
VF-1, VF-1c, VF-WVerification resultsShared ModalP0
Me-1, Me-1e, Me-2, Me-3Me overview + credential detailMeP0/P1
PP-1 ~ PP-4Passport Scan sub-flowShared ModalP0
PR-1, PR-1b, PR-2, PR-3Proof presentation flowShared ModalP0
GR-1, GR-2Social Graph credential + exportMe / ModalP0/P1
SR-1, SR-2, SR-3Social RecoveryShared ModalP1
ST-1SettingsMe (push)P1