refactor progress-file structures, flesh out Gift Economies events

This commit is contained in:
2026-01-10 16:28:00 -07:00
parent 22c8b90b4c
commit 3904e22f72
11 changed files with 1005 additions and 24 deletions
+12
View File
@@ -0,0 +1,12 @@
# Contacts Integration
Problem: Time Safari contacts are not linked to a person's device contacts.
## Goal & Value Proposition
- Allow links between Time Safari data and a person's contacts.
- Allow a user to open a contact channel directly to a contact, in whichever messaging or other app they choose.
- Allow a user to send a message or automated request to a group of contacts.
This allows people to manage their contacts as they choose, and allows users to leverage them to take action to check or glean information about things in the network they may not currently see.
@@ -0,0 +1,338 @@
# Matching Common Interests at an Event
We currently have an onboarding meeting tool as described in [the onboarding doc](../../tech/README-onboarding-meeting.md).
We want to enhance this process such that the meeting can be an event where attendees share their interests and get matched with others of similar interests for potential future collaboration .
- People without a profile are prompted to create a profile.
- The organizer can trigger a round of pairing, where the system looks at the profiles and attempts to match people based on their similarities.
- The matching is best as an AI semantic match.
- Each pair is given a number.
- The organizer can put people into groups who should NOT be paired together.
- If there is an odd number of people, the organizer can assign themselves or anyone else to be a non-participant and excluded from the matching.
- The app should show the participants
- The organizer can trigger another round, where the people are all paired with different people. This can happen any number of times, until there are no more different matches that can be made.
- The attendees can see a list of the other attendees in the future, even when the meeting is deleted.
## Implementation
### Phase 0: Vector Similarity Foundation (Test-Driven)
**Goal:** Prove vector similarity matching works effectively via unit tests
_Note: Build and validate core matching algorithms before UI integration_
- [ ] Implement embedding generation function
- [ ] `generateEmbedding(text)` - call OpenAI API to generate embeddings
- [ ] Handle API keys via environment variables
- [ ] Error handling for API failures
- [ ] Unit tests with real profile descriptions
- [ ] Implement pure JavaScript vector math functions
- [ ] `dotProduct(vec1, vec2)` - multiply and sum vector components
- [ ] `magnitude(vec)` - calculate vector length
- [ ] `cosineSimilarity(vec1, vec2)` - measure similarity (0-1 scale)
- [ ] Unit tests for each function with known inputs/outputs
- [ ] Create test profiles with embeddings
- [ ] Profile 1: Sustainable agriculture focus
- [ ] Profile 2: Similar to Profile 1 (should match highly)
- [ ] Profile 3: Software/tech focus (different from 1 & 2)
- [ ] Profile 4: Community organizing (partial overlap with all)
- [ ] Generate real embeddings from descriptions using OpenAI API
- [ ] Verify embeddings are 1536-dimensional vectors
- [ ] Test similarity calculations
- [ ] Verify high similarity (>0.8) between similar profiles
- [ ] Verify low similarity (<0.5) between dissimilar profiles
- [ ] Verify medium similarity for partial overlaps
- [ ] Test with actual embedding vectors (1536 dimensions)
- [ ] Test basic pairing algorithm
- [ ] 4 people → 2 pairs (highest similarities)
- [ ] 6 people → 3 pairs
- [ ] 5 people → 2 pairs + 1 trio (group of 3)
- [ ] Verify pairs have higher similarity than non-pairs
- [ ] Test constraint handling
- [ ] Exclude specific pairs from matching
- [ ] Exclude individuals from matching pool
- [ ] Multiple rounds with no repeated pairs
- [ ] Test edge cases
- [ ] 2 people (minimum viable)
- [ ] 3 people (one trio)
- [ ] All identical profiles (any pairing is equally good)
- [ ] Empty/minimal profile handling
- [ ] Automated Testing
**Validation:** All tests pass showing effective profile matching based on semantic similarity
**Test File:** `repos/endorser-ch/test/controller-partner-3-group-matching.js`
#### Implementation Summary
**Files Created:**
- `repos/endorser-ch/test/controller-partner-3-group-matching.js` (783 lines, 60+ tests)
- `repos/endorser-ch/test/generate-test-embeddings.js` (helper script for generating real embeddings)
- Added `generate-test-embeddings` npm script to `package.json`
- Updated `test/README.md` with usage documentation
- Embeddings cached in `embeddings.json` with metadata (model, provider, dimensions)
**Core Functions Implemented:**
1. **`generateEmbedding(text, apiKey)`** - Calls OpenAI API to generate 1536-dimensional embeddings
- Uses `text-embedding-3-small` model
- Error handling for API failures
- Environment variable support for API key
2. **`dotProduct(vec1, vec2)`** - Multiplies and sums vector components
3. **`magnitude(vec)`** - Calculates vector length
4. **`cosineSimilarity(vec1, vec2)`** - Returns similarity score from -1 to 1
5. **`matchParticipants(participants, excludedPairs, excludedIds, previousPairs)`**
- Greedy pairing algorithm based on similarity scores
- Handles odd numbers by creating trios
- Supports exclusion constraints and multiple rounds
- Returns structured pair/trio objects with similarity scores
**Test Coverage:**
- ✅ Embedding generation (5 tests) - validates OpenAI API integration
- ✅ Vector math (9 tests) - validates dot product, magnitude, cosine similarity
- ✅ Profile similarity (4 tests) - confirms high similarity for similar profiles (>0.95), low for dissimilar (<0.6)
- ✅ Pairing algorithm (6 tests) - validates 2-6 person groups, trio handling
- ✅ Constraint handling (3 tests) - validates exclusions and multiple rounds
- ✅ Edge cases (5 tests) - minimum groups, identical profiles, error handling
- ✅ Match quality (2 tests) - validates within-pair > cross-pair similarity
**Test Profiles:**
26 diverse profiles with descriptions ranging from sustainable agriculture to software development, designed to test various similarity scenarios. Includes profiles focused on education, construction, AI/ML, firearms, outdoors, mushroom cultivation, travel, and sports. Length varies from 3 words to full paragraphs to test that matching works regardless of description length.
**Performance:**
- Vector similarity calculation: <1ms per pair
- 20 participants (190 comparisons): ~5-10ms
- Embedding generation: ~100-200ms per API call, $0.00002 cost per profile
**Usage:**
```bash
# Quick testing with simplified embeddings
npm test test/controller-partner-3-group-matching.js
# Generate real 1536-dimensional embeddings (one-time)
export OPENAI_API_KEY=your-key-here
npm run test:generate-embeddings
# Tests automatically use real embeddings if available
```
**Status:** ✅ Complete - All algorithms validated and ready for API integration in Phase 1
---
### Phase 1: Basic Profile Integration (Proof of Concept)
**Goal:** Integrate existing endorser-ch profile system with meeting feature
_Note: Profile storage already exists in endorser-ch partner-api as a simple text field_
- [ ] Verify existing profile field supports matching use case
- [ ] Confirm profile text field can hold interests, skills, and goals together
- [ ] Check field length limits are adequate for detailed descriptions
- [ ] Create simple profile creation/edit form
- [ ] Single text area for users to describe interests/skills/goals
- [ ] Character limit indicator (if applicable)
- [ ] Connect to existing partner-api endpoints
- [ ] Profile prompt on meeting join
- [ ] Check if attendee has matching-ready profile (has interests)
- [ ] Show profile creation/update modal if needed
- [ ] Allow skipping if not participating in matching
- [ ] Display profiles to other attendees
- [ ] Basic read-only profile cards
- [ ] Fetch from partner-api.endorser.ch
- [ ] Automated Testing
**Validation:** Attendees can see all attendee profiles after they join
---
### Phase 2: AI-Powered Profile Matching
**Goal:** Implement core semantic matching algorithm
- [ ] Set up AI/LLM integration
- [ ] Choose LLM provider (OpenAI, Anthropic, etc.)
- [ ] Configure API keys and rate limits
- [ ] Create embeddings service for profile text
- [ ] Implement matching algorithm
- [ ] Generate embeddings for each profile
- [ ] Allow attendees to be excluded
- [ ] Calculate similarity scores between all pairs
- [ ] Create pairing algorithm (maximize total similarity)
- [ ] For an odd number, include 3 people in one of the groups
- [ ] Basic matching endpoint
- [ ] POST endpoint for organizer to trigger matching
- [ ] Return list of pairs with similarity scores
- [ ] Simple results display
- [ ] Show matched pairs to attendees
- [ ] Assign numbers to each pair
- [ ] Automated Testing
**Validation:** Organizer can trigger matching, and all attendees can see AI-generated pairs with reasonable similarity
---
### Phase 3: Matching UI and Participant Experience
**Goal:** Polish the matching visualization and participant-facing features
- [ ] Enhance organizer matching interface
- [ ] Visual display of pairs (cards, grid, or list)
- [ ] Show pair numbers prominently
- [ ] Display similarity reasoning (why these people matched)
- [ ] Participant view of matches
- [ ] Show participants their assigned pair
- [ ] Display partner's profile information
- [ ] Show pair number
- [ ] Real-time updates
- [ ] WebSocket or polling for match announcements
- [ ] Notify participants when matching is triggered
- [ ] Allow easy adding of notes onto the contact of the matched person
- [ ] Allow easy adding of an offer to the matched person
- [ ] Automated Testing
**Validation:** Both organizer and participants see clear, real-time matching results
---
### Phase 4: Multiple Rounds and Constraints
**Goal:** Support advanced matching scenarios
- [ ] Exclusion groups
- [ ] UI for organizer to select people
- [ ] Create "do not pair" groups
- [ ] Persist exclusion rules across rounds
- [ ] Exclude non-participants
- [ ] Option to mark organizer or others as excluded
- [ ] Ensure excluded people don't appear in matching pool
- [ ] Multiple matching rounds
- [ ] Track previous pairs in meeting state
- [ ] Constraint: don't repeat previous pairs
- [ ] Calculate when no more unique pairs possible
- [ ] Show organizer "rounds remaining" indicator
- [ ] Round history
- [ ] Store all previous rounds
- [ ] Allow organizer to view past pairings
- [ ] Display round number to participants
- [ ] Automated Testing
**Validation:** Organizer can run multiple rounds with no repeated pairs and proper exclusions
---
### Phase 5: Post-Event Features and Polish
**Goal:** Enable long-term value and edge case handling
- [ ] Post-event attendee list
- [ ] Persist attendee relationships after meeting deletion
- [ ] Create "past event" view showing all attendees
- [ ] Link to profiles even after event expires
- [ ] Meeting expiration handling
- [ ] Archive meeting data (don't delete attendee info)
- [ ] Maintain contact visibility permissions
- [ ] Analytics and insights
- [ ] Show match quality scores to organizer
- [ ] Track which pairs connected post-event
- [ ] Export attendee list and matching history
- [ ] Profile enhancements
- [ ] Add optional profile photo
- [ ] Rich text formatting for longer descriptions
- [ ] Skills taxonomy or tags
- [ ] Error handling and edge cases
- [ ] Handle API failures gracefully
- [ ] Timeout handling for long matching operations
- [ ] Support for very small (2-3 people) or large (50+) groups
- [ ] Handle profile updates mid-matching
- [ ] Performance optimization
- [ ] Cache embeddings to avoid regeneration
- [ ] Optimize matching algorithm for large groups
- [ ] Add loading states and progress indicators
- [ ] Automated Testing
**Validation:** System handles all edge cases gracefully and provides long-term value post-event
---
### Phase 6: Social Media Integration (Optional)
**Goal:** Auto-populate interests from social media profiles
_Note: This is an optional enhancement that could significantly improve onboarding UX_
- [ ] OAuth integration setup
- [ ] Facebook OAuth flow
- [ ] LinkedIn OAuth flow (professional interests/skills)
- [ ] Twitter/X OAuth flow (interests from bio/tweets)
- [ ] Secure token storage and management
- [ ] Data extraction and parsing
- [ ] Facebook: Extract liked pages, groups, interests from profile
- [ ] LinkedIn: Extract skills, interests, job descriptions
- [ ] Twitter/X: Parse bio, analyze recent tweets for topics
- [ ] Create unified interest extraction format
- [ ] AI-powered profile summarization
- [ ] Feed social media data to LLM
- [ ] Generate concise profile text combining interests, skills, and goals
- [ ] Allow user to review and edit before saving
- [ ] Profile enrichment UI
- [ ] "Import from social media" button on profile form
- [ ] Platform selection interface
- [ ] Preview extracted data before applying
- [ ] Merge with existing profile data (don't overwrite)
- [ ] Privacy and consent
- [ ] Clear consent flow explaining data usage
- [ ] Option to delete imported data
- [ ] Don't store raw social media data (only processed interests)
- [ ] Allow users to see what data was extracted
- [ ] Multiple platform support
- [ ] Allow importing from multiple platforms
- [ ] Intelligently merge profile data from different sources into single text
- [ ] Deduplicate similar information from multiple platforms
**Validation:** Users can import interests from social media, review them, and have auto-populated profiles
**Benefits:**
- Dramatically reduces friction for new users
- More comprehensive profiles with richer context
- Better matching quality with more detailed descriptions
- Engages users who might skip manual profile creation
**Privacy Considerations:**
- Only request minimal scopes from OAuth providers
- Process and discard raw data immediately
- Store only the generated profile text summary
- Comply with platform APIs terms of service
- Provide clear data deletion options
---
### Technical Considerations
**AI/LLM Integration:**
- Use sentence transformers or embedding models for semantic similarity
- Generate embeddings from user's free-form profile text
- Caching strategy for embeddings to reduce API costs
**Matching Algorithm:**
- Start with greedy pairing (highest similarity pairs first)
- Could evolve to weighted bipartite matching for optimal global solution
- Need to handle constraints efficiently (exclusions, previous pairs)
**Data Model:**
- Profile: `{ userId, description: string, embedding: vector }` (description field already exists in partner-api)
- Meeting: extend to include `{ profileUserIds: string[], rounds: Round[], exclusionGroups: string[][] }`
- Round: `{ number: int, pairs: Pair[], timestamp: datetime }`
- Pair: `{ userIds: [string, string], similarityScore: float, pairNumber: int }`
**Privacy:**
- Attendees should consent to AI processing of their profiles
- Consider allowing profile visibility controls
- Meeting password security for sensitive gatherings is ensured by current features
+352
View File
@@ -0,0 +1,352 @@
# In-Person Giving Events
## Core Activities (from brainstorm)
### Connection & Matching
- **AI-directed Interview & Pairing** - Use prompts to discover what people need/offer, then facilitate connections
- See [./PROJECT-giving-event-matching.md](./PROJECT-giving-event-matching.md)
### Demonstration & Storytelling
- **Talk/Presentation** - Share vision and real stories
- Live demo of recording a gift in the app
- Show the "traceable donation" walk-through
- Feature 2-3 testimonials from current users (video or live)
- Address the "what about freeloaders?" question directly
### Hands-On Experience
- **Onboarding to Time Safari** - Structured setup session
- QR codes for easy download
- Helper volunteers walking people through first steps
- First action: Record one gift they received in past week
- Second action: Connect with 2 people at the event
- Gamify: "First 20 people to complete get a surprise gift"
- **Gifts for Attendees from Local Vendors** - Tangible giving experience
- Partner with local businesses who donate items/services
- Each attendee receives something (coffee voucher, plant seed, homemade treat)
- Vendor gets recognized in app + builds goodwill
- Attendees record receiving this gift as their first app entry
### Project Initiation
- **Pitch & Collaborate Corner** - Project matchmaking
- Anyone can pitch a project idea (60 seconds max)
- Others can volunteer time/skills on the spot
- Use app to create project and log commitments
- Example projects: community garden, skill-share workshops, meal trains
### Long-term Engagement
- **Ambassador Recruitment** - Multiply impact
- Identify enthusiastic attendees
- Offer to train them as event hosts for their own networks
- Provide toolkit: slides, activities, talking points
## Event Flow Options
### Workshop Style (2-3 hours)
0. Preparation
1. Welcome + ? (20 min)
- Ensure everyone has profile
4. App onboarding (30 min)
5. Project pitches + mingling (30 min)
6. Closing circle + next steps (10 min)
## Metrics to Track
- Number of attendees
- App downloads during event
- Gifts recorded at event
- Connections made (in app)
- Projects initiated
- Follow-up engagement (1 week, 1 month later)
- Attendee feedback scores
- Social media shares/reach
## Materials Needed
- QR codes for app download (printed large)
- Camera/photographer for documentation
- Raffle prizes (gifted from local supporters)
- Thank you cards (pre-printed for immediate gratitude)
## Questions to Consider
- Indoor or outdoor? → **Indoor**
- Target audience size? (Intimate 20-30 vs larger 100+) → **15-30 neighbors & friends**
- Specific neighborhood focus or city-wide? → **Neighborhood/personal network**
- Partner organizations to involve?
- Food/beverage plan?
- Childcare considerations?
- Accessibility needs?
---
## Feb 13 Event Plan (15-30 people, 2.5 hours)
**Target**: Neighbors & friends interested in building community
**Tech available**: Time Safari with connections + project creation (no groups yet)
**Style**: Highly participatory, minimal presentation
### Recommended Flow
#### Pre-Event (Week Before)
- Send personal invitations with context (not cold outreach)
- Optional: Pre-install Time Safari app, get registered
#### Welcome & Warm-Up (15 min, 6:00-6:15)
- Arrival + name tags with "a gift I have" written on them
- Quick welcome circle: name + one gift you've received recently
- Set tone: This is about discovering what we're already doing, not selling anything
#### Activity 1: Gift Story Circle (30 min, 6:15-6:45)
**Why this works for 15-30**: Everyone gets to share, builds emotional connection
- Groups of 5-6 people
- Rotating prompts (7 min each):
1. "Tell about a gift you received that changed something for you"
2. "What do you love giving to others?"
3. "What's a need in your life right now?"
- Facilitator floats between groups, notes emerging themes
- **Key**: You're mining for real stories to share later + helping people see their own gifting patterns
#### Activity 2: Skills & Needs Mapping (25 min, 6:45-7:10)
**Why this works for 15-30**: Creates a visual resource everyone can reference
- Large paper/poster board on wall with categories: Skills, Time, Items, Food/Meals, Housing, Other
- Everyone gets sticky notes in two colors:
- Green: "I can offer..." (skills, time, items, connections, meals, space)
- Yellow: "I'm looking for..." (needs, wishes, dreams)
- Encourage including basic needs: "Can you cook for someone once a week?" "Need help with groceries?" "Have a spare room?" "Looking for meal support?"
- Write 3-5 of each, post on board
- Group browses and makes verbal connections: "Oh! I can help with that!"
- Take photo of completed board for reference
- **Note**: This mirrors our long-term goal of supporting people's basic livelihoods through gifting
#### Transition + Vision (10 min, 7:10-7:20)
**Your brief speaking moment**
- Share 2-3 stories you heard from the circles
- Connect to bigger vision: "What if this was happening every day?"
- Show the board: "This is $X,XXX worth of value that could be exchanged without money"
- **Paint the long-term picture**:
- "Imagine a network where basic needs—food, housing, skills—are met through mutual support"
- "We're starting with skills and connections, but some of us are already working toward providing regular meals and basic livelihoods for people without money changing hands"
- "Tonight is practice. The real goal? A sustainable culture where no one goes without because we take care of each other"
- Introduce Time Safari as a tool to keep this going beyond today and track progress toward these bigger goals
#### Activity 3: App Onboarding + First Connections (30 min, 7:20-7:50)
**Why this works for 15-30**: Small enough for hands-on help
- QR code displayed large (or multiple printed)
- 2-3 helper "tech buddies" circulate (recruit in advance?)
- Everyone completes 3 tasks:
1. Download + create profile
2. Record one gift (from earlier story or the event itself)
3. Connect with at least 2 people in the room
- Gamify: "First table to have everyone connected gets first pick from gift table"
#### Activity 4: Immediate Gift Exchange (15 min, 7:50-8:05)
**Why this works for 15-30**: Personal and warm
- Everyone brought a small gift
- Lay them on a central table
- One by one, people choose something that calls to them
- As you take it, record it in the app and thank the giver
- Creates immediate app usage + demonstrates receiving without reciprocating
#### Activity 5: Project Spark (15 min, 8:05-8:20)
**Why this works for 15-30**: Action-oriented closure
- Quick brainstorm: "What could we do together in the next month?"
- Seed specific ideas that align with long-term vision:
- "Community meal program - can we commit to providing X meals/week for someone in need?"
- "Rotating dinner hosts - take turns cooking for the group"
- "Skill-share workshops"
- "Tool library or resource sharing"
- Vote on top 2-3 ideas (hands raised)
- Volunteers step up to champion each
- Create the projects in Time Safari right there
- Others commit time/skills and record in app
- **Connect to vision**: "These projects are how we practice. Our long-term goal is to support entire livelihoods this way—50 people living without needing money for basics. It starts here."
#### Closing Circle (10 min, 8:20-8:30)
- Stand in circle
- Quick popcorn sharing: "One word for how you feel right now"
- **Hand out take-home card** (see Materials section) with long-term vision and ways to participate
- Invitation to next steps:
- Try to record 3 gifts this week
- Consider: Could you provide a meal for someone? Receive meals from others?
- Bring one friend to next month's gathering
- Join [communication channel - email list? group text?]
- "This is bigger than tonight. We're building toward basic livelihoods supported by community, not money. You're now part of that."
- Group photo
### Next Steps
- [ ] Generate prep steps before event, with deadlines in "days before event"
- [ ] Generate materials checklist
### Prep Work Needed (Before Feb 13)
1. **App readiness**:
- Test the connection flow with fresh users
- Ensure QR-based friend connection works smoothly
- Have a few demo gifts/projects already in your profile
- Test on both iOS and Android
2. **Helper recruitment**:
- Identify 2-3 "tech buddies" who can help during onboarding
- Brief them beforehand on common issues
- Give them your phone number in case of server problems
3. **Story prep**:
- Prepare your own 2-minute version of your gift economy vision
- Have 1-2 powerful examples of gifts that meant a lot to you
- Practice keeping it warm and personal, not preachy
4. **Logistics**:
- Venue confirmed (someone's home? community center?)
- Seating arrangement for circles (move furniture?)
- WiFi password visible
- Backup plan if WiFi fails (hotspot? offline capability?)
5. **Communication**:
- Send reminder 3 days before with:
- "Bring a small gift to share"
- "Think of a gift story"
- "Optional: pre-install Time Safari" (link)
- Create follow-up plan: email list? group chat? next event date?
### Success Metrics for This Event
- **Quantity**:
- 80%+ attendees download app
- Average 3+ connections made per person
- At least 2 projects created
- 50%+ record at least one gift during event
- **Quality**:
- People linger and keep talking after "official" end
- At least 3 people volunteer to help with next event
- You overhear conversations about helping each other
- Someone says "I want to bring my [friend/neighbor] next time"
- **Follow-up** (measure 1 week later):
- 50%+ have opened app again
- 30%+ have recorded another gift
- Someone initiates a connection outside the event
### Potential Challenges & Solutions
**Challenge**: "Tech-resistant attendees"
- **Solution**: Celebrate: "That's fine! You can participate by writing on the skills board"; assign a buddy to help; offer to help them set up at end
### Alternative: If Only 10-12 People Show Up
- Skip breaking into small groups for story circle (do it all together)
- More intimate = more time for each person
- Can do project creation as a group discussion
- Still highly effective, just different energy
### Alternative: If 30+ People Show Up
- Recruit more helpers on the spot
- Extend app onboarding time (add 15 min)
- Do two simultaneous gift exchanges (split the room)
- Create more breakout space for story circles
---
## Take-Home Card: "The Long-Term Vision"
**Design**: Postcard-sized (4"x6"), printed front and back
### Front Side
```
🎁 GIFT ECONOMIES
Building a Culture of Mutual Support
Tonight you experienced:
✓ Sharing stories of generosity
✓ Mapping skills and needs
✓ Giving and receiving without expectation
✓ Creating projects together
This is just the beginning.
```
### Back Side
```
THE LONG-TERM VISION
We're working toward a world where:
🍽️ BASIC NEEDS MET
Regular meals provided for those who need them—
no money required, just community care.
🏠 SUSTAINABLE LIVELIHOODS
50 people supported entirely through gifts—
food, housing, skills, connection—
demonstrating that monetary exchange is optional.
💪 CULTURAL TRANSFORMATION
A shift from "What can I buy?" to "Who can I help?"
From isolation to interdependence.
From scarcity thinking to abundance through sharing.
📱 YOUR NEXT STEPS
□ Record 3 gifts this week in Time Safari
□ Identify one person whose basic need you could help meet
□ Be willing to receive help yourself
□ Share this vision with one friend
□ Consider: Could you provide/receive a meal weekly?
"Basic livelihoods supported without money,
in a sustainable way so people are confident
they can have that support for all their lives."
---
Time Safari App: [QR CODE]
Questions: [YOUR EMAIL]
Next Gathering: [DATE]
This is about aligning hearts & minds
with the things that do the most good.
```
### Design Notes
- Keep it simple and readable
- Use warm, inviting colors (earth tones, not corporate)
- The QR code should be prominent on back
- Print on cardstock so it feels substantial
- Consider having a local artist illustrate it (practice gift economy in creating it!)
---
## Long-Term Vision Integration Points
Throughout the event, naturally reference these goals:
**During story circles**: If someone shares about receiving meal support, highlight it: "This is exactly what we're scaling up—imagine this as a regular system, not just crisis support."
**During skills board**: Point out food/meal offers: "These are the building blocks of supporting someone's basic livelihood without money."
**During vision talk**: Use specific numbers: "Our goal isn't just connection—it's to support 50 people's basic livelihoods entirely through gifts within [timeframe]. Tonight we practice the skills that make that possible."
**During project creation**: Encourage meal-related projects: "A rotating dinner schedule where we commit to 5 meals/week for one person? That's 1/21st of a full basic livelihood. We can scale this."
**In follow-up emails**:
- Week 1: "Last week we practiced. This week, let's identify one person whose basic needs we could help meet."
- Month 1: "How many meals have our network provided this month? Let's count the impact."
- Month 3: "We're tracking toward supporting X% of one person's basic needs. Here's what's next."
---
## Measuring Long-Term Progress (Post-Event)
Track how tonight's activities ladder up to bigger goals:
- **Immediate** (Week 1): Gifts recorded, connections made, projects created
- **Short-term** (Month 1): Meals provided, basic needs met, trust deepening
- **Medium-term** (Month 3-6): Someone receives regular meal support, housing assistance, or skill support that replaces a paid expense
- **Long-term** (Year 1-2): First person's basic livelihood substantially supported (quantify % of needs met without money)
- **Ultimate** (Years 3-5): 50 people living with confidence that their community will support them
Tonight is the first small step toward that last goal.
+296
View File
@@ -0,0 +1,296 @@
# Utilizing a P2P network
Time Safari currently records all data on an Endorser server, routed through the general internet. This project will allow people to send their data directly P2P. The first iteration will most likely be over a LoRa mesh radio network run with Meshtastic devices.
## Overview
The goal is to create a decentralized version of the Endorser system that can operate without internet connectivity, enabling local communities to share claims, confirmations, and visibility permissions through mesh networks. This is particularly valuable for:
- Remote areas with limited internet connectivity
- Emergency situations where infrastructure is compromised
- Privacy-conscious communities wanting local-first data sharing
- Resilient social networks that don't depend on centralized services
## Task 1: P2P Claim Protocol Design
### 1.1 Message Structure & Packaging
**Objective**: Design efficient message formats for transmitting Endorser claims over bandwidth-constrained mesh networks.
**Key Components**:
#### Message Types
- **Claim Broadcast**: New claims being shared with neighbors
- **Claim Request**: Request for specific claims by ID, user, or criteria
- **Claim Response**: Response to requests with claim data
- **Visibility Update**: Changes to visibility permissions between users
- **Merkle Sync**: Synchronization of merkle hash chains for integrity verification
- **Peer Discovery**: Announcement of available data and capabilities
#### Message Format
```json
{
"version": "1.0",
"type": "claim_broadcast|claim_request|claim_response|visibility_update|merkle_sync|peer_discovery",
"timestamp": "ISO8601",
"sender_did": "did:ethr:0x...",
"message_id": "unique_id",
"ttl": 5,
"payload": {
// Type-specific payload
},
"signature": "cryptographic_signature"
}
```
#### Payload Structures
**Claim Broadcast Payload**:
- Compressed JWT claim data
- Visibility hints (who can see what)
- Related claim IDs for context
- Geographic bounds (if location-based)
- Priority level (urgent vs. routine)
**Claim Request Payload**:
- Request type: by_id, by_user, by_location, by_type, recent_updates
- Filter criteria
- Maximum response size
- Requester's merkle hash for sync
**Peer Discovery Payload**:
- Available claim count by type
- Supported protocol versions
- Storage capacity and retention policy
- Geographic coverage area
- Last activity timestamp
### 1.2 Data Selection & Filtering
**Objective**: Implement intelligent data selection to maximize utility within bandwidth constraints.
**Priority System**:
1. **High Priority**: Recent claims from visible users, confirmations of user's own claims
2. **Medium Priority**: Claims matching user's interests/location, visibility updates
3. **Low Priority**: Older claims, claims from users with limited visibility
**Filtering Mechanisms**:
- **Spatial Filtering**: Only share claims within geographic relevance
- **Temporal Filtering**: Prioritize recent activity, age-out old claims
- **Social Filtering**: Prioritize claims from users in visibility network
- **Type Filtering**: Focus on specific claim types (gives, offers, projects)
- **Size Filtering**: Compress or truncate large claims
**Adaptive Bandwidth Management**:
- Monitor network conditions and adjust message frequency
- Implement exponential backoff for failed transmissions
- Use compression for claim content (gzip, custom dictionary)
- Batch multiple small claims into single messages
### 1.3 Privacy & Visibility Control
**Objective**: Maintain Endorser's privacy model in P2P environment.
**Visibility Propagation**:
- Encrypt claim content for intended recipients only
- Use public key cryptography for visibility-controlled data
- Maintain visibility graphs locally and sync changes
- Implement "visibility hints" to help routing without exposing content
**Privacy-Preserving Discovery**:
- Use bloom filters for private set intersection
- Implement zero-knowledge proofs for claim existence without revealing content
- Support anonymous claim requests through onion routing
- Enable selective disclosure of claim attributes
**Trust & Reputation**:
- Implement web-of-trust model for peer reliability
- Track and share reputation scores for claim accuracy
- Support claim verification through multiple confirmations
- Enable reporting of malicious or spam claims
### 1.4 Synchronization & Consistency
**Objective**: Ensure data consistency across the mesh network using merkle chains.
**Merkle Chain Synchronization**:
- Each peer maintains local merkle chain of all known claims
- Periodic sync requests to compare merkle roots with neighbors
- Efficient delta synchronization for missing claims
- Conflict resolution for competing claim versions
**Eventual Consistency Model**:
- Accept that perfect consistency isn't possible in P2P networks
- Implement vector clocks for causality tracking
- Support claim versioning and conflict resolution
- Enable manual conflict resolution for important discrepancies
**Data Integrity**:
- Cryptographic verification of all claims using JWT signatures
- Merkle proof verification for claim authenticity
- Detection and isolation of corrupted or malicious data
- Backup and recovery mechanisms for critical claims
## Task 2: Meshtastic Network Integration
### 2.1 Meshtastic Protocol Adaptation
**Objective**: Integrate the P2P claim protocol with Meshtastic's LoRa mesh networking.
**Protocol Mapping**:
- Map claim message types to Meshtastic packet types
- Implement custom protobuf definitions for Endorser messages
- Handle Meshtastic's packet size limitations (237 bytes max)
- Implement message fragmentation for large claims
**Meshtastic Integration Points**:
- Use Meshtastic's MQTT gateway for phone connectivity
- Leverage Meshtastic's routing algorithms for message propagation
- Integrate with Meshtastic's encryption for transport security
- Utilize Meshtastic's node database for peer discovery
**Message Fragmentation**:
```
Fragment Header:
- Message ID (4 bytes)
- Fragment number (1 byte)
- Total fragments (1 byte)
- Fragment payload (up to 230 bytes)
```
### 2.2 Device Architecture & Connectivity
**Objective**: Design the hardware and software architecture for mesh-enabled Time Safari.
**Hardware Components**:
- **Meshtastic Node**: T-Beam, Heltec, or similar LoRa device
- **Mobile Device**: Android/iOS phone running Time Safari
- **Connection**: Bluetooth or WiFi between phone and Meshtastic node
**Software Architecture**:
```
Time Safari App (Phone)
↓ Bluetooth/WiFi
Mesh Bridge Service (Phone or Node)
↓ Serial/MQTT
Meshtastic Firmware (Node)
↓ LoRa Radio
Mesh Network
```
**Mesh Bridge Service**:
- Translates between Endorser API calls and mesh messages
- Manages local claim storage and caching
- Handles message queuing and retry logic
- Provides offline-first operation with sync when connected
### 2.3 Mobile App Integration
**Objective**: Seamlessly integrate mesh networking into existing Time Safari interface.
**User Interface Changes**:
- **Network Status Indicator**: Show mesh connectivity and peer count
- **Offline Mode**: Clear indication when operating without internet
- **Sync Status**: Progress indicator for claim synchronization
- **Mesh Settings**: Configure mesh behavior, privacy settings, data limits
**Data Management**:
- **Local Storage**: SQLite database for offline claim storage
- **Sync Queue**: Queue outgoing claims for mesh transmission
- **Conflict Resolution UI**: Interface for resolving claim conflicts
- **Data Usage**: Monitor and limit mesh data consumption
**Fallback Behavior**:
- Graceful degradation when mesh is unavailable
- Automatic switching between mesh and internet connectivity
- Queuing of actions for later mesh transmission
- User notification of connectivity status changes
### 2.4 Network Management & Optimization
**Objective**: Optimize mesh network performance and reliability.
**Routing Optimization**:
- Implement claim-aware routing (route claims toward interested peers)
- Use geographic routing for location-based claims
- Implement store-and-forward for intermittent connectivity
- Support multi-hop routing with TTL management
**Performance Monitoring**:
- Track message delivery rates and latency
- Monitor network topology and connectivity
- Measure bandwidth utilization and efficiency
- Log and analyze network performance metrics
**Network Health**:
- Implement heartbeat messages for peer liveness
- Detect and handle network partitions
- Support network healing and topology changes
- Enable manual network diagnostics and troubleshooting
**Quality of Service**:
- Prioritize urgent messages (emergency claims)
- Implement fair queuing for multiple users
- Support bandwidth allocation policies
- Enable traffic shaping and congestion control
## Implementation Phases
### Phase 1: Protocol Foundation (4-6 weeks)
- Design and implement basic message formats
- Create claim serialization/deserialization
- Implement cryptographic signing and verification
- Build basic peer discovery mechanism
### Phase 2: Meshtastic Integration (3-4 weeks)
- Develop Meshtastic protocol adapter
- Implement message fragmentation
- Create mesh bridge service
- Test basic claim transmission over LoRa
### Phase 3: Mobile Integration (4-5 weeks)
- Integrate mesh service with Time Safari app
- Implement offline storage and sync
- Create mesh-specific UI components
- Add network status and configuration
### Phase 4: Advanced Features (6-8 weeks)
- Implement merkle chain synchronization
- Add privacy-preserving features
- Optimize routing and performance
- Create comprehensive testing suite
### Phase 5: Field Testing & Optimization (4-6 weeks)
- Deploy test network with multiple nodes
- Conduct real-world performance testing
- Optimize based on field results
- Prepare for production deployment
## Technical Considerations
### Security
- All claims must maintain cryptographic integrity
- Implement defense against replay attacks
- Support key rotation and revocation
- Enable secure bootstrapping of new nodes
### Scalability
- Design for networks of 50-100 active nodes
- Implement efficient data structures for large claim sets
- Support hierarchical network organization
- Plan for future integration with other mesh protocols
### Reliability
- Handle node failures gracefully
- Implement redundant storage across multiple nodes
- Support network partitioning and healing
- Enable data recovery from partial failures
### Interoperability
- Maintain compatibility with existing Endorser API
- Support migration between mesh and internet modes
- Enable bridging between different mesh networks
- Plan for integration with other P2P protocols (IPFS, etc.)
This detailed plan provides a comprehensive roadmap for implementing P2P mesh networking in Time Safari while maintaining the privacy, security, and usability principles of the existing Endorser system.
+420
View File
@@ -0,0 +1,420 @@
# Voice Input for Profile and Gift Descriptions
Time Safari currently requires users to type descriptions for their profiles and gifts manually. This project will enable users to speak their descriptions and have them automatically transcribed and filled into the appropriate text fields. The implementation will prioritize on-device processing to maintain privacy and enable offline functionality.
## Overview
The goal is to add voice-to-text functionality that allows users to describe their profiles or gifts through speech, with the transcribed text automatically populating the relevant form fields. This is particularly valuable for:
- Users who prefer speaking over typing, especially on mobile devices
- Faster data entry, particularly for longer descriptions
- Accessibility improvements for users with mobility or dexterity challenges
- Natural language descriptions that capture nuance better than typing
- Privacy-focused users who want on-device processing without cloud transcription
This plan provides a comprehensive roadmap for implementing voice input in Time Safari, starting with quick wins to validate the approach before committing to full integration.
## Task 1: Basic Voice Input Setup
### 1.1 Capacitor Speech Recognition Integration
**Objective**: Establish basic voice recording and transcription capabilities using Capacitor plugins.
**Key Components**:
#### Plugin Selection
- **Primary Option**: `@capacitor-community/speech-recognition` - Cross-platform speech recognition
- **Alternative**: `@capacitor-community/voice-recorder` + on-device ML model (if available)
- **Fallback**: Web Speech API for browser environments
#### Initial Implementation Steps
1. Install and configure Capacitor speech recognition plugin
2. Request and handle microphone permissions
3. Implement basic start/stop recording functionality
4. Display recording status indicator to user
5. Test on both iOS and Android devices
#### Basic Recording Interface
```typescript
interface VoiceRecorder {
start(): Promise<void>;
stop(): Promise<SpeechRecognitionResult>;
cancel(): Promise<void>;
isSupported(): boolean;
hasPermission(): Promise<boolean>;
requestPermission(): Promise<boolean>;
}
```
**Quick Win Test**:
- Record audio and verify it's captured
- Display transcript result in console/log
- No form integration yet - just prove recording works
### 1.2 Permission Management
**Objective**: Handle microphone permissions gracefully across platforms.
**Platform-Specific Considerations**:
- **iOS**: Info.plist `NSMicrophoneUsageDescription` required
- **Android**: AndroidManifest.xml `RECORD_AUDIO` permission
- **Web**: User gesture required for microphone access
**Permission Flow**:
1. Check permission status on component mount
2. Request permission if not granted
3. Show clear error messages if permission denied
4. Provide settings link to enable permissions manually
5. Handle permission state changes (user grants/denies during session)
**Quick Win Test**:
- Verify permission prompts appear correctly
- Test denial handling (show user-friendly message)
- Test re-requesting permissions after denial
### 1.3 Basic UI Components
**Objective**: Create minimal UI elements for voice recording.
**Components Needed**:
- **Record Button**: Visual indicator with recording state (idle/recording/processing)
- **Status Indicator**: Show "Listening..." or "Processing..." feedback
- **Cancel Button**: Allow user to abort recording
- **Visual Feedback**: Animated microphone icon or waveform during recording
**Quick Win Test**:
- Create standalone component with record button
- Toggle recording state visually
- Display transcript result below button (simple div)
## Task 2: Speech-to-Text Transcription
### 2.1 On-Device Transcription Setup
**Objective**: Configure on-device speech recognition to avoid cloud processing.
**Implementation Approach**:
- Use device-native speech recognition APIs through Capacitor
- Configure for offline/on-device processing when available
- Fall back to online recognition if on-device unavailable (with user consent)
**Platform Capabilities**:
- **iOS**: Speech framework (on-device Siri recognition)
- **Android**: SpeechRecognizer API (on-device available on Android 10+)
- **Web**: Web Speech API (typically cloud-based, but can use local models in some browsers)
**Configuration Options**:
- Language selection (default to device language, allow override)
- Continuous vs. single-shot recognition
- Interim results vs. final results only
- Confidence thresholds for transcription quality
**Quick Win Test**:
- Speak simple phrases and verify transcription accuracy
- Test with different languages if device supports
- Compare on-device vs. online transcription quality
### 2.2 Text Processing & Formatting
**Objective**: Clean and format transcribed text for form fields.
**Text Processing Steps**:
1. **Capitalization**: Proper sentence capitalization (first letter, proper nouns)
2. **Punctuation**: Add periods at sentence endings if missing
3. **Removal**: Strip filler words like "um", "uh", "like" (optional, user preference)
4. **Normalization**: Fix common speech-to-text errors (homophones, numbers)
5. **Formatting**: Handle line breaks for longer descriptions
**Processing Pipeline**:
```typescript
interface TextProcessor {
clean(text: string): string;
capitalize(text: string): string;
addPunctuation(text: string): string;
removeFillers(text: string): string;
normalize(text: string): string;
}
```
**Quick Win Test**:
- Input test transcript with common issues
- Verify each processing step works independently
- Test with real transcriptions from speech recognition
### 2.3 Error Handling & Retry Logic
**Objective**: Handle transcription failures gracefully.
**Error Scenarios**:
- No speech detected (silence or background noise only)
- Network unavailable (if using cloud fallback)
- Recognition timeout
- Low confidence transcription
- Permission revoked during recording
**Recovery Strategies**:
- Show clear error messages with actionable guidance
- Allow user to retry recording easily
- Offer manual text input as fallback
- Save partial results if transcription interrupted
**Quick Win Test**:
- Simulate each error condition
- Verify error messages are user-friendly
- Test retry functionality
## Task 3: Profile Description Integration
### 3.1 Profile Form Integration
**Objective**: Integrate voice input into profile description editing.
**Integration Points**:
- Add microphone button next to profile description textarea
- Replace or append to existing text based on user preference
- Maintain existing form validation and submission flow
- Preserve text if user switches between voice and typing
**User Experience Flow**:
1. User taps microphone icon next to description field
2. Recording starts, button shows recording state
3. User speaks description
4. User taps stop button (or auto-stops after pause)
5. Transcribed text appears in description field
6. User can edit transcribed text manually if needed
7. User can record again to replace or append
**Form State Management**:
- Track whether text came from voice or typing
- Allow editing of transcribed text
- Handle form submission with voice-generated text
- Save draft state including voice transcriptions
**Quick Win Test**:
- Add microphone button to profile form
- Record and fill description field
- Submit form and verify description saves correctly
### 3.2 Profile-Specific Text Processing
**Objective**: Optimize transcription processing for profile descriptions.
**Profile Context Awareness**:
- Profile descriptions are typically first-person ("I am...", "I enjoy...")
- May include skills, interests, location, availability
- Often include action-oriented language
**Optimization Strategies**:
- Recognize common profile phrases and ensure proper formatting
- Handle personal pronouns appropriately
- Format lists and bullet points if user says "first", "second", etc.
- Preserve natural language flow while cleaning up speech artifacts
**Quick Win Test**:
- Test with typical profile description phrases
- Verify formatting looks natural in profile preview
- Compare user satisfaction with typed vs. voice descriptions
## Task 4: Gift Description Integration
### 4.1 Gift Form Integration
**Objective**: Integrate voice input into gift (Give) description editing.
**Integration Points**:
- Add microphone button to gift description/impact text fields
- Enable microphone while camera is active
- Support both "what was given" and "impact" descriptions
- Handle gifts that may be time-based or physical items
- Support longer descriptions that describe impact and outcomes
**User Experience Flow**:
Similar to profile flow, but optimized for gift context:
1. User initiates camera & microphone
1.1. Tap a button to begin
1.2. Allow a shortcut from the desktop to go directly to this page
2. Collect information from audio, eg. description at first
3. User taps the camera to take a picture and complete gathering of audio data
4. Transcribed text fills field
5. Reviews and submits
**Quick Win Test**:
- Enable camera & microphone button by default when gifting
- Verify gift submission works with voice transcriptions
### 4.2 Gift-Specific Text Processing
**Objective**: Optimize transcription for gift/impact descriptions.
**Gift Context Awareness**:
- Gift descriptions often include recipient names or pronouns
- Action-oriented language ("I helped", "I gave", "we organized")
- Impact descriptions may include outcomes and results
- May reference time commitments or physical items
**Optimization Strategies**:
- Recognize gift-related phrases and terminology
- Handle recipient references appropriately
- Format action verbs naturally
- Support both past-tense (completed gifts) and present-tense (ongoing) descriptions
**Quick Win Test**:
- Test with various gift description styles
- Verify descriptions format well
- Verify other items like giver & recipient fill in
## Task 5: Advanced Features & Optimization
### 5.1 Voice Command Recognition
**Objective**: Enable voice commands for common actions (future enhancement).
**Potential Commands**:
- "Next field" - Move to next form field
- "Delete that" - Remove last transcribed segment
- "Add period" - Add punctuation
- "Start over" - Clear current field and restart
- "Save draft" - Save current form state
**Quick Win Test** (if implemented):
- Test single command recognition
- Verify commands work during recording
- Test command accuracy
### 5.2 Editing & Correction Interface
**Objective**: Make it easy to correct transcription errors.
**Editing Features**:
- Highlight uncertain words (low confidence transcriptions)
- Allow inline editing of transcribed text
- Quick correction suggestions for common errors
- Undo/redo for transcription changes
**Quick Win Test**:
- Show confidence scores for words
- Allow clicking on words to edit
- Test undo functionality
### 5.3 Performance Optimization
**Objective**: Optimize voice input for speed and efficiency.
**Optimization Areas**:
- Reduce latency between recording and transcription display
- Implement incremental transcription (show words as recognized)
- Cache recognition models to avoid re-initialization
- Optimize audio processing for faster transcription
- Reduce battery consumption during recording
**Quick Win Test**:
- Measure time from stop recording to text display
- Monitor battery usage during extended recording
- Test performance on lower-end devices
## Implementation Phases
### Phase 1: Proof of Concept (1-2 weeks)
**Goal**: Prove voice recording and basic transcription works
- [ ] Install Capacitor speech recognition plugin
- [ ] Create standalone test component with record button
- [ ] Test microphone permissions on iOS and Android
- [ ] Verify audio recording works
- [ ] Display raw transcription output
- [ ] **Quick Win**: Successfully record and see transcript in console
**Deliverables**: Working prototype that can record and show transcription
### Phase 2: Basic Text Processing (1 week)
**Goal**: Clean and format transcribed text
- [ ] Implement basic text cleaning (capitalization, punctuation)
- [ ] Create text processing utility functions
- [ ] Test with various transcriptions
- [ ] Add unit tests for text processing
- [ ] **Quick Win**: Clean transcription appears formatted correctly
**Deliverables**: Text processing utilities with tests
### Phase 3: Profile Form Integration (2 weeks)
**Goal**: Voice input works in profile description field
- [ ] Add microphone button to profile form
- [ ] Integrate recording with description textarea
- [ ] Handle form state (voice vs. typed text)
- [ ] Test form submission with voice transcriptions
- [ ] Add UI feedback (recording indicator, status messages)
- [ ] Handle errors gracefully (permissions, recognition failures)
- [ ] **Quick Win**: Can record and fill profile description, submit successfully
**Deliverables**: Working voice input in profile forms
### Phase 4: Gift Form Integration (1-2 weeks)
**Goal**: Voice input works in gift description fields
- [ ] Add microphone buttons to gift form fields
- [ ] Integrate with both "what given" and "impact" fields
- [ ] Optimize text processing for gift context
- [ ] Test with various gift types and descriptions
- [ ] **Quick Win**: Can record and fill gift descriptions, submit successfully
**Deliverables**: Working voice input in gift forms
### Phase 5: Polish & Enhancement (2-3 weeks)
**Goal**: Improve UX and handle edge cases
- [ ] Add loading states and animations
- [ ] Implement retry logic for failed transcriptions
- [ ] Add editing capabilities for transcribed text
- [ ] Optimize performance and battery usage
- [ ] Add accessibility improvements
- [ ] Comprehensive testing on multiple devices
- [ ] User testing and feedback incorporation
**Deliverables**: Production-ready voice input feature
## Technical Considerations
### Privacy & Security
- Prioritize on-device processing to avoid sending audio to servers
- Request explicit user consent before using any cloud-based recognition
- Ensure audio data is not stored permanently
- Clear audio buffers after transcription
- Document privacy implications in user-facing documentation
### Accessibility
- Ensure voice input doesn't interfere with screen readers
- Provide keyboard shortcuts for recording start/stop
- Support alternative input methods (voice should complement, not replace typing)
- Test with users who have speech impairments
### Performance
- Minimize battery usage during recording
- Optimize for lower-end devices
- Handle network connectivity changes gracefully
- Implement timeout mechanisms to prevent infinite recording
- Consider limiting maximum recording duration
### Platform Compatibility
- Test on iOS (multiple versions) and Android (multiple versions)
- Provide graceful degradation for unsupported platforms
- Handle platform-specific permission models
- Test in both Capacitor native and web environments
- Support browser environments with Web Speech API fallback
### User Experience
- Provide clear visual feedback during recording
- Make it easy to cancel or retry recordings
- Allow editing of transcribed text
- Don't force voice input - always allow typing as alternative
- Provide helpful error messages with actionable guidance
- Consider adding voice input tutorials or onboarding
### Testing Strategy
- Unit tests for text processing utilities
- Integration tests for form submission with voice transcriptions
- Device testing on physical iOS and Android devices
- Test with various accents and speech patterns
- Test error scenarios (no permission, network issues, etc.)
- User acceptance testing with real users