Skip to content

Safety Mechanics Quick Start Guide โ€‹

For developers implementing safety features in Lantern


Overview โ€‹

This guide provides a quick reference for implementing the safety features documented in SAFETY_MECHANICS.md. Start here for implementation priorities and key integration points.


Priority Order (MVP โ†’ Full Launch) โ€‹

Phase 1: Block Functionality (4-6 weeks) โญ START HERE โ€‹

Why First: Foundation for all other safety features. Users need ability to control who can interact with them.

Key Files to Create:

  • src/lib/blockService.js - Block/unblock logic
  • src/components/BlockButton.jsx - Reusable block UI component
  • src/components/BlockedUsersList.jsx - Manage blocked users

Key Files to Modify:

  • src/components/Chat.jsx - Add block button to chat menu
  • src/components/WaveManager.jsx - Add block option to wave notifications
  • src/screens/profile/ProfileSettings.jsx - Add "Blocked Users" section

Firestore Collections:

javascript
// Collection: blocks
{
  id: "{userId}_{blockedUserId}",
  userId: "user123",
  blockedUserId: "user456",
  reason: "harassment", // optional
  createdAt: Timestamp,
  platform: "web"
}

Security Rules:

javascript
// Users can only read/write their own blocks
match /blocks/{blockId} {
  allow read, write: if request.auth != null && 
    blockId.matches(request.auth.uid + '_.*');
}

Testing Checklist:

  • [ ] User A blocks User B
  • [ ] User B disappears from User A's lantern hub, waves, chats
  • [ ] User B cannot see User A's lantern or send waves
  • [ ] Block persists across devices (test on phone + desktop)
  • [ ] User A can unblock User B from ProfileSettings
  • [ ] Pattern detection: flag user receiving 5+ blocks

Phase 2: In-App Safety Education (2-3 weeks) โ€‹

Why Second: Low development effort, high user value. Educates users on safety best practices.

Key Files to Create:

  • src/components/SafetyTipsPanel.jsx - Safety education content
  • src/components/SafetyPrompt.jsx - Contextual safety reminders

Key Files to Modify:

  • src/screens/profile/ProfileSettings.jsx - Add "Safety & Privacy" tab
  • src/components/LightLanternForm.jsx - Add safety prompt before first light
  • src/components/WaveManager.jsx - Add safety reminder before accepting first wave

Content to Include:

  • Meeting strangers safely (public places, tell a friend, trust instincts)
  • Recognizing red flags (pushy behavior, asking for money, oversharing)
  • Using safety features (block, report, SOS)
  • Crisis hotline links (domestic violence, suicide prevention, trans lifeline)

Testing Checklist:

  • [ ] Navigate to ProfileSettings โ†’ Safety & Privacy โ†’ see safety tips
  • [ ] First lantern light โ†’ see safety reminder prompt
  • [ ] First wave acceptance โ†’ see "you can block this user" message
  • [ ] All crisis hotline links are correct and functional

Phase 2.5: Platform Bans & Re-Registration Prevention (6-10 weeks) โ€‹

Why Here: Build on Phase 1 block pattern detection. Essential before scaling to prevent abuse at scale.

Key Files to Create:

  • src/lib/banService.js - Account ban/suspension logic
  • src/lib/deviceFingerprint.js - Browser/device fingerprinting utilities
  • src/lib/behavioralFingerprint.js - Behavioral pattern detection
  • src/components/moderation/ModerationDashboard.jsx - Internal tool for reviewing flagged accounts
  • src/components/moderation/BanNotification.jsx - In-app ban notification UI

Key Files to Modify:

  • src/lib/auth.js - Add ban check during signup/login
  • src/screens/auth/SignupFlow.jsx - Check for ban evasion before account creation

Firestore Collections:

javascript
// Collection: banned_accounts
{
  id: "ban123",
  reason: "harassment",
  severity: "permanent", // "warning" | "temporary" | "shadow" | "permanent"
  bannedAt: Timestamp,
  expiresAt: Timestamp, // null for permanent
  appealStatus: "pending" | "upheld" | "overturned",
  
  // Hashed identifiers (for re-registration prevention)
  emailHash: "bcrypt_hash",
  phoneHash: "bcrypt_hash",
  deviceFingerprint: "browser_fingerprint_hash",
  installationId: "uuid",
  
  // Behavioral signatures (anonymized)
  behavioralSignature: {
    typingSpeed: 120, // WPM
    wavingPattern: [9, 14, 22], // Hours of day
    preferredVenues: ["coffee_shop", "bar"]
  }
}

// Collection: moderation_queue
{
  id: "flag123",
  userId: "user123",
  flagReason: "multiple_blocks", // "multiple_blocks" | "spam" | "reported"
  flaggedAt: Timestamp,
  evidence: {
    blockCount: 7,
    blockReasons: ["harassment", "spam", "harassment"],
    reportCount: 3
  },
  status: "pending" | "reviewed" | "dismissed",
  reviewedBy: "moderator_id",
  reviewedAt: Timestamp,
  action: "warning" | "suspension" | "shadow_ban" | "permanent_ban" | "no_action"
}

Re-Registration Prevention Strategy:

Layer 1: Email/Phone Hashing

javascript
// src/lib/banService.js
import bcrypt from 'bcrypt'

export async function checkEmailBanned(email) {
  const emailHash = await bcrypt.hash(email.toLowerCase(), 10)
  
  const bannedRef = collection(db, 'banned_accounts')
  const q = query(bannedRef, where('emailHash', '==', emailHash))
  const snapshot = await getDocs(q)
  
  return !snapshot.empty
}

Layer 2: Device Fingerprinting

javascript
// src/lib/deviceFingerprint.js
export function generateDeviceFingerprint() {
  const fingerprint = {
    userAgent: navigator.userAgent,
    language: navigator.language,
    screenResolution: `${screen.width}x${screen.height}`,
    timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
    platform: navigator.platform,
    // Hash components together
    hash: hashComponents([...])
  }
  return fingerprint.hash
}

Layer 3: Behavioral Fingerprinting

javascript
// src/lib/behavioralFingerprint.js
export function analyzeTypingPattern(keystrokes) {
  // Measure time between keystrokes
  const intervals = []
  for (let i = 1; i < keystrokes.length; i++) {
    intervals.push(keystrokes[i].timestamp - keystrokes[i-1].timestamp)
  }
  
  return {
    avgInterval: intervals.reduce((a,b) => a+b) / intervals.length,
    stdDev: calculateStdDev(intervals),
    typingSpeed: calculateWPM(keystrokes)
  }
}

export function comparePatterns(pattern1, pattern2) {
  // Calculate similarity score (0-100)
  const speedSimilarity = 1 - Math.abs(pattern1.typingSpeed - pattern2.typingSpeed) / Math.max(pattern1.typingSpeed, pattern2.typingSpeed)
  // ... more comparisons
  return similarityScore
}

Account Creation Flow with Ban Check:

javascript
// src/screens/auth/SignupFlow.jsx
async function handleSignup(email, phone) {
  // 1. Check email hash
  const emailBanned = await checkEmailBanned(email)
  if (emailBanned) {
    throw new Error("This email cannot be used")
  }
  
  // 2. Check phone hash (if provided)
  if (phone) {
    const phoneBanned = await checkPhoneBanned(phone)
    if (phoneBanned) {
      throw new Error("This phone number cannot be used")
    }
  }
  
  // 3. Get device fingerprint
  const deviceFP = generateDeviceFingerprint()
  const deviceBanned = await checkDeviceBanned(deviceFP)
  if (deviceBanned) {
    // Don't block immediately (false positives), but flag for review
    await flagForReview(email, deviceFP, "banned_device_match")
  }
  
  // 4. Create account (monitor behavioral patterns for 7 days)
  const user = await createAccount(email, phone, deviceFP)
  
  // 5. Start behavioral monitoring
  await startBehavioralMonitoring(user.id, deviceFP)
}

Moderation Dashboard (Internal Tool):

  • View flagged accounts in queue
  • See evidence (block count, reasons, reports, behavioral patterns)
  • Take action (warn, suspend, shadow ban, permanent ban)
  • Document decision with notes
  • Send notification to user

Testing Checklist:

  • [ ] User receives 5 blocks โ†’ flagged for moderation review
  • [ ] User receives 10 blocks โ†’ automatic 7-day suspension
  • [ ] Moderator reviews flagged account โ†’ can warn/suspend/ban
  • [ ] Banned user receives email notification with reason
  • [ ] Banned user tries signup with same email โ†’ rejected
  • [ ] Banned user tries signup with new email, same device โ†’ flagged for review
  • [ ] Banned user tries signup with new email, new device โ†’ behavioral monitoring detects match after 3 days
  • [ ] False positive: Legitimate user on shared device not auto-banned
  • [ ] Appeals process: User appeals ban โ†’ different moderator reviews โ†’ decision communicated within 7 days

Privacy Safeguards:

  • Only store hashed emails/phones (cannot reverse)
  • Device fingerprints anonymized (no PII)
  • Behavioral patterns aggregated (not keystroke-level detail)
  • Ban data retention: 1 year, then deleted
  • GDPR compliance: User can request data deletion (ban remains active)

Phase 3: Safe Spaces Partnership (8-12 weeks) โ€‹

Why Third: Requires external partnerships and legal agreements. Start outreach early but implement after Phases 1-2.

Key Files to Create:

  • src/lib/safeSpacesService.js - Safe space search and alerting
  • src/components/SafeSpaceMap.jsx - Map view of nearby safe spaces
  • src/components/SafeSpaceCard.jsx - Display safe space details

Key Files to Modify:

  • src/lib/venueService.js - Add safe space fields to venue data model
  • src/screens/dashboard/Dashboard.jsx - Add safe space search option

Partnership Process:

  1. Create partnership application form (Google Forms or Typeform)
  2. Vet organizations (501(c)(3) status, references, background checks)
  3. Legal agreements (liability waivers, privacy commitments, alert response SLAs)
  4. Onboarding training (how to respond to SOS alerts, user privacy expectations)
  5. Add to Firestore with encrypted contact details

Firestore Collections:

javascript
// Collection: safe_spaces
{
  id: "safeSpace123",
  name: "The San Diego LGBT Community Center",
  type: "lgbtq_center",
  address: "3909 Centre St, San Diego, CA 92103",
  location: new GeoPoint(32.7537, -117.1628),
  contactPhone: "619-692-2077", // encrypted
  contactEmail: "safety@thecentersd.org",
  services: ["crisis_intervention", "counseling", "safe_space"],
  operatingHours: {
    monday: "9am-9pm",
    tuesday: "9am-9pm",
    // ...
  },
  acceptsSOSAlerts: true,
  publiclyListed: true, // false for confidential addresses (DV shelters)
  fundingTier: 1, // $500/month
  totalAlertsReceived: 0,
  avgResponseTime: null
}

San Diego Pilot Partners (Target: 5-10 organizations): These are example organizations identified for the San Diego pilot. Actual partners will be determined during implementation based on availability, interest, and compatibility with Lantern's mission.

Potential partner types:

  • LGBTQ+: Local LGBTQ+ community centers and resource organizations
  • Domestic Violence: Women's shelters and family violence prevention centers
  • Mental Health: Crisis intervention services and walk-in counseling centers
  • Community: Neighborhood safety organizations and mutual aid networks

Note: Contact information and specific organizations should be verified during implementation as these details can change.

Testing Checklist:

  • [ ] Search for safe spaces โ†’ see nearest options with distance
  • [ ] Tap safe space โ†’ see details (services, hours, contact info)
  • [ ] Map view shows safe spaces within 5 miles
  • [ ] Confidential addresses (DV shelters) are NOT shown on public map

Phase 4: SOS Emergency System (12-16 weeks) โ€‹

Why Last: Most complex feature requiring native APIs, legal review, and extensive testing. Build after foundation is solid.

Key Files to Create:

  • src/lib/sosService.js - SOS activation/deactivation logic
  • src/lib/recordingService.js - Audio/video recording via Web APIs
  • src/lib/emergencyContacts.js - Contact management and notifications
  • src/components/SOSButton.jsx - Prominent SOS button component
  • src/components/SOSActivationModal.jsx - Two-stage confirmation screen
  • src/components/SOSActiveNotification.jsx - Persistent notification during active SOS
  • src/components/EmergencyContactsManager.jsx - Add/edit/remove contacts

Key Files to Modify:

  • src/components/dashboard/DashboardNavigation.jsx - Add SOS button (left side, red, always visible)
  • src/screens/profile/ProfileSettings.jsx - Add "Emergency Contacts" section

Web APIs Required:

  • navigator.mediaDevices.getUserMedia() - Camera/microphone access
  • MediaRecorder - Audio/video recording
  • navigator.geolocation.watchPosition() - Real-time GPS tracking
  • Blob + URL.createObjectURL() - Local recording storage
  • Firebase Cloud Functions - SMS/email notifications

Firestore Collections:

javascript
// Collection: sos_incidents
{
  id: "sos123",
  userId: "user123",
  status: "active", // "active" | "resolved" | "cancelled"
  activatedAt: Timestamp,
  deactivatedAt: null,
  location: new GeoPoint(32.7157, -117.1611),
  venue: "Balboa Park",
  recordingUrl: null, // encrypted blob URL (after upload)
  incidentReport: null,
  notifiedContacts: ["contact1", "contact2"],
  notifiedSafeSpaces: ["safeSpace123"]
}

// Collection: emergency_contacts
{
  id: "contact123",
  userId: "user123",
  name: "Jane Doe",
  phone: "+1-619-555-1234",
  email: "jane@example.com",
  relationship: "friend", // "friend" | "family" | "partner" | "roommate"
  verified: false, // true if contact confirmed via SMS/email
  createdAt: Timestamp
}

Emergency Actions Flow:

  1. User taps SOS button โ†’ Confirmation modal appears
  2. User confirms โ†’ Immediate actions triggered:
    • Start audio/video recording (save to local IndexedDB)
    • Begin real-time GPS tracking (update every 30 seconds)
    • Send SMS/push to emergency contacts: "[Name] activated Lantern SOS at [Location]"
    • Alert nearest safe space (if within 5 miles)
    • Optionally call 911 (if user enabled in settings)
  3. Show persistent notification: "SOS ACTIVE - Recording and sharing location"
  4. User can deactivate by entering PIN/passphrase
  5. Post-deactivation: Prompt for incident report (optional)

Legal Requirements:

  • Update Terms of Service to disclose recording functionality
  • Check state recording laws (one-party vs two-party consent)
  • GDPR/CCPA compliance for location data processing
  • Liability waivers for safe space partnerships

Testing Checklist:

  • [ ] Tap SOS โ†’ see confirmation modal
  • [ ] Confirm โ†’ recording starts (verify microphone icon in browser)
  • [ ] Location sharing active (verify GPS coordinates updating)
  • [ ] Emergency contacts receive SMS with live location link
  • [ ] Nearest safe space receives alert (if within 5 miles)
  • [ ] Recording saves to IndexedDB (check DevTools โ†’ Application โ†’ IndexedDB)
  • [ ] Deactivate SOS โ†’ recording stops, location sharing ends
  • [ ] Incident report form appears post-deactivation
  • [ ] Recording uploads to Firebase Storage (encrypted)

Key Integration Points โ€‹

Dashboard.jsx โ€‹

javascript
// Add to imports
import { blockUser, isUserBlocked } from '../lib/blockService'

// Filter blocked users from waves and connections
const visibleWaves = incomingWaves.filter(wave => 
  !isUserBlocked(currentUser.uid, wave.senderId)
)

const visibleConnections = activeConnections.filter(conn =>
  !isUserBlocked(currentUser.uid, conn.userId)
)

Chat.jsx โ€‹

javascript
// Add block button to menu
<button
  onClick={() => {
    setShowMenu(false)
    handleBlockUser(connection.userId)
  }}
  className="w-full px-4 py-3 text-left text-orange-400 hover:bg-orange-500/10 flex items-center gap-2"
>
  <Shield size={16} />
  Block User
</button>

WaveManager.jsx โ€‹

javascript
// Add block button to wave notifications
<button
  onClick={() => onBlock(wave.senderId)}
  className="flex-1 bg-red-500/20 hover:bg-red-500/30 border border-red-500/40 text-red-400 rounded-xl py-3 font-medium flex items-center justify-center gap-2"
>
  <Shield size={18} />
  Block
</button>

ProfileSettings.jsx โ€‹

javascript
// Add Blocked Users section
<div className="border-t border-neutral-800 pt-6">
  <h4 className="text-white font-medium mb-2 flex items-center gap-2">
    <Shield className="w-5 h-5 text-amber-400" />
    Blocked Users
  </h4>
  <BlockedUsersList userId={currentUser.uid} />
</div>

// Add Emergency Contacts section
<div className="border-t border-neutral-800 pt-6 mt-6">
  <h4 className="text-white font-medium mb-2 flex items-center gap-2">
    <AlertTriangle className="w-5 h-5 text-red-400" />
    Emergency Contacts
  </h4>
  <EmergencyContactsManager userId={currentUser.uid} />
</div>

Common Patterns โ€‹

Block Confirmation Modal โ€‹

javascript
const handleBlockUser = async (targetUserId) => {
  const confirmed = window.confirm(
    "Block this user? They won't be able to see you or interact with you. This action can be undone in Settings."
  )
  
  if (!confirmed) return
  
  try {
    await blockUser(currentUser.uid, targetUserId)
    // Close chat/wave notification
    onClose()
    // Show success notification
    showNotification({ type: 'success', text: 'User blocked' })
  } catch (error) {
    console.error('Error blocking user:', error)
    showNotification({ type: 'error', text: 'Failed to block user' })
  }
}

Filter Blocked Users from Queries โ€‹

javascript
// In any service fetching users/waves/lanterns
export async function getActiveLanterns(userId) {
  const blockedUsers = await getBlockedUserIds(userId)
  
  const lanternsRef = collection(db, 'lanterns')
  const q = query(
    lanternsRef,
    where('status', '==', 'active'),
    where('userId', 'not-in', blockedUsers) // Firestore supports up to 30 items in not-in
  )
  
  // Note: If >30 blocked users, perform client-side filtering:
  const allLanterns = await getDocs(q)
  return allLanterns.docs
    .map(doc => ({ id: doc.id, ...doc.data() }))
    .filter(lantern => !blockedUsers.includes(lantern.userId))
}

Resources โ€‹


Questions or Issues? โ€‹

If you encounter problems implementing safety features:

  1. Review SAFETY_MECHANICS.md for detailed requirements
  2. Check existing security patterns in src/lib/ services
  3. Consult Firebase documentation for Firestore security rules
  4. For legal questions (recording consent, liability), consult legal team

Remember: Safety features are mission-critical. Take time to implement correctly, test thoroughly, and prioritize user protection over speed.

Built with VitePress