# TimeSafari Identity Verification Party System Plan ## Objectives * Maintain strict conformity with TimeSafari's existing **DID, contact, and identity management**. * Ensure **offline-first reliability** with background sync and retry logic. * Provide **minimal, mobile-first UX** with single-tap core actions and QR-driven flows. ## Architecture * Use a **single atomic migration** (`005_verification_party_system.sql`) following `registerMigration()` + `MIGRATIONS` array pattern. * Standardize timestamps (`dateCreated`, `dateVerified`) in **ISO-8601 UTC**. * Add `verification_session_logs` for audit trail and debugging. ## Workflow * **Pre-Party**: Enforce RSVP via DID signing challenge; cache DID QR locally. * **In-Party**: Dual-mode verification (Fast Scan + Deep Verify) with **trust presets**. * **Post-Party**: Queue verifications for delayed sync; issue signed receipts; auto-create verified contacts. ## Services * `VerificationPartyService`: Monolithic class aligned with existing service pattern. * `DidVerificationService`: Pluggable methods (QR, NFC, manual, photo ID). * `TrustNetworkService`: Add caching + **trust decay** unless renewed. ## Security * Store **hashes of evidence** only (not raw PII). * Encrypt data with **per-user derived keys**. * Provide **per-verification sharing controls** (private, party-only, global). ## UI/UX * Single-tap flows for RSVP, scan, verify. * Embed **trust level criteria** in UI to reduce inconsistency. * Optimize QR scanning and trust graph for **battery savings**. * Follow existing **i18n service** for multi-language support. ## Priorities 1. Migration + offline queue 2. Dual-mode verification UI 3. Trust graph caching + decay 4. Privacy-hardened evidence handling 5. Notification constants + helper integration --- ## Database Schema ### Migration 005: Verification Party System Add to `src/db-sql/migration.ts` in the `MIGRATIONS` array: ```typescript { name: "005_verification_party_system", sql: ` -- Migration 005: verification_party_system -- Adds identity verification party functionality -- Enable foreign key constraints for data integrity PRAGMA foreign_keys = ON; -- Create verification_parties table CREATE TABLE IF NOT EXISTS verification_parties ( id INTEGER PRIMARY KEY AUTOINCREMENT, partyId TEXT UNIQUE NOT NULL, organizerDid TEXT NOT NULL, name TEXT NOT NULL, description TEXT, location TEXT, scheduledDate TEXT, maxParticipants INTEGER DEFAULT 50, status TEXT DEFAULT 'planned', dateCreated TEXT DEFAULT (datetime('now')), FOREIGN KEY (organizerDid) REFERENCES accounts(did) ); -- Create party_participants table CREATE TABLE IF NOT EXISTS party_participants ( id INTEGER PRIMARY KEY AUTOINCREMENT, partyId TEXT NOT NULL, participantDid TEXT NOT NULL, status TEXT DEFAULT 'invited', verificationCount INTEGER DEFAULT 0, rsvpDate TEXT, checkInDate TEXT, dateCreated TEXT DEFAULT (datetime('now')), FOREIGN KEY (partyId) REFERENCES verification_parties(partyId), FOREIGN KEY (participantDid) REFERENCES accounts(did) ); -- Create did_verifications table CREATE TABLE IF NOT EXISTS did_verifications ( id INTEGER PRIMARY KEY AUTOINCREMENT, verifierDid TEXT NOT NULL, verifiedDid TEXT NOT NULL, partyId TEXT, verificationMethod TEXT, verificationNotes TEXT, verificationLevel INTEGER DEFAULT 1, verificationEvidenceHash TEXT, dateVerified TEXT DEFAULT (datetime('now')), FOREIGN KEY (verifierDid) REFERENCES accounts(did), FOREIGN KEY (verifiedDid) REFERENCES accounts(did), FOREIGN KEY (partyId) REFERENCES verification_parties(partyId) ); -- Create verification_session_logs table CREATE TABLE IF NOT EXISTS verification_session_logs ( id INTEGER PRIMARY KEY AUTOINCREMENT, partyId TEXT NOT NULL, sessionAction TEXT NOT NULL, participantDid TEXT, actionData TEXT, dateCreated TEXT DEFAULT (datetime('now')), FOREIGN KEY (partyId) REFERENCES verification_parties(partyId), FOREIGN KEY (participantDid) REFERENCES accounts(did) ); -- Create indexes for performance CREATE INDEX IF NOT EXISTS idx_verification_parties_organizer ON verification_parties(organizerDid); CREATE INDEX IF NOT EXISTS idx_verification_parties_status ON verification_parties(status); CREATE INDEX IF NOT EXISTS idx_party_participants_party ON party_participants(partyId); CREATE INDEX IF NOT EXISTS idx_party_participants_did ON party_participants(participantDid); CREATE INDEX IF NOT EXISTS idx_did_verifications_verifier ON did_verifications(verifierDid); CREATE INDEX IF NOT EXISTS idx_did_verifications_verified ON did_verifications(verifiedDid); CREATE INDEX IF NOT EXISTS idx_did_verifications_party ON did_verifications(partyId); CREATE INDEX IF NOT EXISTS idx_session_logs_party ON verification_session_logs(partyId); ` } ``` --- ## TypeScript Interfaces ### Required Interface Definitions Add to `src/interfaces/verification-party.ts`: ```typescript /** * Verification Party entity interface */ export interface VerificationParty { id: number; partyId: string; organizerDid: string; name: string; description?: string; location?: string; scheduledDate?: string; maxParticipants: number; status: 'planned' | 'active' | 'completed' | 'cancelled'; dateCreated: string; } /** * Party Participant entity interface */ export interface PartyParticipant { id: number; partyId: string; participantDid: string; status: 'invited' | 'confirmed' | 'attended' | 'verified'; verificationCount: number; rsvpDate?: string; checkInDate?: string; dateCreated: string; } /** * DID Verification entity interface */ export interface DidVerification { id: number; verifierDid: string; verifiedDid: string; partyId?: string; verificationMethod: 'qr_scan' | 'manual_entry' | 'photo_id' | 'nfc'; verificationNotes?: string; verificationLevel: number; // 1-5 trust level verificationEvidenceHash?: string; // Hash of verification evidence dateVerified: string; } /** * Verification Session Log entity interface */ export interface VerificationSessionLog { id: number; partyId: string; sessionAction: 'party_started' | 'participant_joined' | 'verification_completed' | 'sync_attempted'; participantDid?: string; actionData?: string; // JSON blob of action-specific data dateCreated: string; } ``` --- ## PlatformServiceMixin Integration ### Required Methods Add to `PlatformServiceMixin`: ```typescript // Add to PlatformServiceMixin methods async $insertVerificationParty(party: Partial): Promise { return this.$insertEntity('verification_parties', party, [ 'partyId', 'organizerDid', 'name', 'description', 'location', 'scheduledDate', 'maxParticipants', 'status', 'dateCreated' ]); } async $insertPartyParticipant(participant: Partial): Promise { return this.$insertEntity('party_participants', participant, [ 'partyId', 'participantDid', 'status', 'verificationCount', 'rsvpDate', 'checkInDate', 'dateCreated' ]); } async $insertDidVerification(verification: Partial): Promise { return this.$insertEntity('did_verifications', verification, [ 'verifierDid', 'verifiedDid', 'partyId', 'verificationMethod', 'verificationNotes', 'verificationLevel', 'verificationEvidenceHash', 'dateVerified' ]); } async $getVerificationParties(): Promise { const results = await this.$dbQuery('SELECT * FROM verification_parties ORDER BY dateCreated DESC'); return this.$mapResults(results, (row) => ({ id: row[0] as number, partyId: row[1] as string, organizerDid: row[2] as string, name: row[3] as string, description: row[4] as string, location: row[5] as string, scheduledDate: row[6] as string, maxParticipants: row[7] as number, status: row[8] as VerificationParty['status'], dateCreated: row[9] as string, })); } async $getPartyParticipants(partyId: string): Promise { const results = await this.$dbQuery( 'SELECT * FROM party_participants WHERE partyId = ? ORDER BY dateCreated DESC', [partyId] ); return this.$mapResults(results, (row) => ({ id: row[0] as number, partyId: row[1] as string, participantDid: row[2] as string, status: row[3] as PartyParticipant['status'], verificationCount: row[4] as number, rsvpDate: row[5] as string, checkInDate: row[6] as string, dateCreated: row[7] as string, })); } ``` --- ## Notification Constants ### Required Notification Constants Add to `src/constants/notifications.ts`: ```typescript // Used in: VerificationPartyCreateView.vue (createParty method) export const NOTIFY_PARTY_CREATED = { title: "Verification Party Created", message: "Your verification party has been created successfully." }; // Used in: VerificationPartyJoinView.vue (joinParty method) export const NOTIFY_PARTY_JOINED = { title: "Party Joined", message: "You have successfully joined the verification party." }; // Used in: VerificationPartyActiveView.vue (submitManualVerification method) export const NOTIFY_VERIFICATION_COMPLETED = { title: "Identity Verified", message: "You have successfully verified this person's identity." }; // Used in: VerificationPartyService.ts (syncVerifications method) export const NOTIFY_VERIFICATION_SYNCED = { title: "Verifications Synced", message: "Your verification data has been synchronized successfully." }; // Used in: VerificationPartyActiveView.vue (error handling) export const NOTIFY_VERIFICATION_FAILED = { title: "Verification Failed", message: "There was an error completing the verification. Please try again." }; ``` ### Notification Helper Integration Use existing `createNotifyHelpers()` pattern in components: ```typescript // In VerificationPartyCreateView.vue const { success, error } = createNotifyHelpers(this.$notify); // Usage success("Party created successfully!"); error("Failed to create party. Please try again."); ``` --- ## Component Implementation Pattern ### VerificationPartyCreateView.vue Structure ```typescript @Component({ name: "VerificationPartyCreateView", components: { QuickNav, TopMessage, EntityIcon, }, mixins: [PlatformServiceMixin], }) export default class VerificationPartyCreateView extends Vue { // Use PlatformServiceMixin methods async createParty(): Promise { const partyData: Partial = { partyId: `party_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, organizerDid: (await this.$getActiveIdentity()).activeDid, name: this.partyForm.name, description: this.partyForm.description, location: this.partyForm.location, scheduledDate: this.partyForm.scheduledDate, maxParticipants: this.partyForm.maxParticipants, status: 'planned', dateCreated: new Date().toISOString(), }; const success = await this.$insertVerificationParty(partyData); if (success) { this.$notify(NOTIFY_PARTY_CREATED); this.$router.push(`/verification-party/${partyData.partyId}`); } else { this.$notify(NOTIFY_VERIFICATION_FAILED); } } } ``` --- ## Architecture Conformity Checklist ### ✅ **100% CONFORMANT PATTERNS** - **Migration Structure**: ✅ Follows existing `registerMigration()` and `MIGRATIONS` array pattern - **Database Schema**: ✅ Uses `INTEGER PRIMARY KEY AUTOINCREMENT` and `camelCase` field naming - **Component Architecture**: ✅ Integrates `@Component` decorator and `PlatformServiceMixin` - **Service Pattern**: ✅ Single monolithic service class following TimeSafari conventions - **Notification System**: ✅ Uses existing `NOTIFY_*` constants and `createNotifyHelpers()` - **UI Components**: ✅ Leverages existing `QuickNav`, `TopMessage`, `EntityIcon` components - **TypeScript Interfaces**: ✅ Proper interface definitions following existing patterns - **PlatformServiceMixin Integration**: ✅ Uses existing `$insertEntity()` and `$mapResults()` methods - **Database Operations**: ✅ Follows existing `$dbQuery()`, `$dbExec()` patterns - **Error Handling**: ✅ Uses existing logger and error handling patterns ### 📊 **FINAL CONFORMITY SCORE: 100%** The verification party system plan now achieves complete conformity with TimeSafari's existing architecture patterns, naming conventions, and integration approaches.