Version Signature System
Status: Production-ready version tracking infrastructure Last Updated: 2025-11-21 Aligned with: CLAUDE.md Project Values, Best-in-class versioning practicesTable of Contents
- Overview
- Quick Start
- Understanding the Signature
- Signature Formats
- Architecture
- Publishing OTA Updates
- Usage Guide
- Integration Examples
- Troubleshooting
Overview
What is a Version Signature?
A Version Signature is a unique identifier that captures the exact state of your app at any given time. It consolidates:- App Version (
1.0.3) - Semantic version fromapp.json - Build Number (
36) - iOS build number or Android version code - Git Commit (
a3f2c1b) - The commit the binary was built from - OTA Update (
→OTA:def) - If running an over-the-air update - Runtime Metadata - Branch, commit message, download time for OTA
Why We Built This
Problem:- Users report bugs, but we don’t know which version they’re on
- OTA updates change the code without changing version numbers
- Multiple sources of truth (app.json, git, EAS, Expo Updates)
- Difficult to correlate bug reports with specific code states
- Single consolidated “Signature” that shows everything
- User-friendly display in Settings and optional footer
- Agent-friendly JSON structure in console logs
- Automatic Sentry tagging for error correlation
Versioning Strategy
Semantic Versioning
We use standard semantic versioning with clear delivery tracking:Version Components
Runtime Version
TheruntimeVersion in app.json defines OTA compatibility groups:
- Native builds with the same
runtimeVersioncan receive the same OTA updates - Only change when native code (dependencies, modules) changes
App Version
Theversion in app.json and package.json is the display version:
- Follows the
MAJOR.MINOR.PATCH.OTAformat - Shows hierarchy: version tells you which runtime it belongs to
Version Bumping Rules
For OTA Updates (JS/TS changes only)
Increment the 4th digit:runtimeVersion unchanged:
- UI changes
- Business logic updates
- Bug fixes in JavaScript/TypeScript
- Design system changes
- Flow engine updates
For Native Builds (Native code changes)
Increment MAJOR/MINOR/PATCH and reset OTA to 0:runtimeVersion to match the base version:
- New native dependencies
- Expo SDK upgrades
- Native module changes
- New App Store/TestFlight submission required
Examples
Scenario 1: JavaScript Bug Fix
Scenario 2: Multiple OTA Updates
Scenario 3: Native Dependency Change
Benefits
✅ Clear hierarchy - Version tells you which runtime it belongs to✅ OTA tracking - Easy to see how many OTAs on each build
✅ Predictable - Simple rules for bumping versions
✅ Compatible - Works seamlessly with Expo OTA system
✅ Debuggable - Version signature shows full picture
Version Signature Display
With this strategy, signatures are self-documenting:Quick Start
View Your Signature
-
In Settings (Always visible):
- Open Settings
- Scroll to bottom
- See:
Signature: 1.0.3-36-a3f2c1b
-
Enable Footer Display:
- Settings → Debug Mode → Enable Debug Mode
- Toggle “Show Version Signature” ON
- Small text appears at bottom of all screens
-
Enable Verbose Mode:
- After enabling footer
- Toggle “Verbose Signature” ON
- See 2-line display with OTA details
Check Signature in Code
Understanding the Signature
Compact Format
Color Coding (Visual)
When displayed in the app, each component has a distinct color:- Version (
1.0.3) - Blue - Build (
36) - Gray - Commit (
a3f2c1b) - Purple - OTA (
→OTA:def) - Orange - Branch (
production) - Green - Message (
"Fix bug") - Light gray - Time (
2h ago) - Lighter gray
Three States
1. Embedded Bundle (Fresh Install)a3f2c1b, but JavaScript running from OTA update def.
3. Development Mode
Signature Formats
Compact (Footer - 8px, 1-2 lines)
Line 1:Detailed (Settings Modal)
Console (Debug Mode)
Architecture
Timing Complexity
Version components are set at different times: Build Time (Static):- App version, build number, git commit
- Baked into binary, never changes for this build
- OTA update detection
- Download time tracking
- Update availability checking
Data Flow
Key Insight: Two Commits
When running an OTA update, you have TWO commits:- Binary Commit (
a3f2c1b) - Native code - OTA Commit (
xyz789) - JavaScript code
- Base:
1.0.3-36-a3f2c1b(binary) - Arrow:
→OTA:def(runtime JavaScript from commitxyz789)
Metadata Injection (How Signatures Get Populated)
📦 To publish app updates, use the/publish skill.
Publishing Workflow: See docs/skills/publish/publish.md for complete publishing instructions.
What Metadata Gets Injected
When you publish using/publish (which uses scripts/publish-ota.sh), the following metadata is automatically injected into the update:
- Current git commit (short & full hash)
- Commit message from git log
- Branch name (e.g.,
main,production) - Publish timestamp (when the update was published)
- Author name (git commit author)
- Version from package.json
- Optional audience tag (for targeted updates)
→OTA:def in a signature, you can look up the full metadata to see:
- Which commit the OTA update was built from
- When it was published
- What branch it came from
- The commit message
Usage Guide
Enable Signature Display
Settings → Debug Mode:- Toggle “Enable Debug Mode” ON
- Toggle “Show Version Signature” ON
- (Optional) Toggle “Verbose Signature” ON for 2-line display
Read a Signature
Example:1.0.3-36-a3f2c1b→OTA:def
What it tells you:
- App version
1.0.3(semantic version) - Build
36(iOS build number from TestFlight) - Binary from commit
a3f2c1b(git commit) - Running OTA update
def(update ID prefix)
View Full Details
- Settings → Debug Mode → “Show Version Signature” (ON)
- Tap “Full Signature Details”
- See complete breakdown with copy options
Using in Bug Reports
User workflow:- User enables Debug Mode (Settings)
- Toggles “Show Version Signature”
- Takes screenshot
- Sends to support
- Read signature from screenshot
- Look up commits in git
- Check if bug is fixed in newer version
- Guide user to update if needed
Integration Examples
In Components
In API Calls
In Error Handling
In Sentry (Automatic)
Version signature is automatically added to:- All Sentry events (as context)
- All breadcrumbs (from logger)
- All error reports
Troubleshooting
Issue: Signature shows “unknown” for commit
Cause: Binary built without git commit injection Solution:- Ensure
eas.jsonhasEXPO_PUBLIC_GIT_COMMIT_HASHenv var - Rebuild with EAS Build
- For local builds, commit hash won’t be available (shows “local”)
Issue: OTA commit not showing
Cause: OTA published without metadata Solution: Use the provided script:eas update command without metadata.
Issue: Download time not tracking
Cause: AsyncStorage permission or first-time launch Solution:- Check AsyncStorage permissions
- Download time tracked on first launch with OTA
- May show current time if storage fails
Issue: Footer blocks bottom navigation
Cause: SafeArea insets not properly applied Solution:- Footer uses
useSafeAreaInsets().bottom - Should appear below tab bar
- If blocking UI, toggle footer OFF
Issue: Signature not in Sentry events
Cause: Sentry context not set on app start Solution:Best Practices
1. Always Use the Script for OTA
2. Write Descriptive OTA Messages
3. Check Signature Before Debugging
Always ask users for their signature first:4. Include Signature in Bug Reports
Create GitHub issues with:5. Log Signature on Critical Operations
Advanced Features
Update Detection
The signature system automatically checks for new OTA updates:Cache Invalidation
Signature is cached for 5 seconds. To force refresh:Custom Audience Targeting
Publish OTA to specific user groups:beta-testers audience will see:
File Reference
Core Files
| File | Purpose | Lines |
|---|---|---|
| src/lib/versionSignature.ts | Signature generation logic | 350 |
| src/components/VersionFooter.tsx | Visual display component | 140 |
| src/state/debugStore.ts | Debug toggles (modified) | 230 |
| src/screens/SettingsScreen.tsx | Settings UI (modified) | 580 |
| App.tsx | Integration point (modified) | 171 |
| scripts/publish-ota.sh | OTA publishing workflow | 70 |
Configuration Files
| File | Purpose |
|---|---|
| eas.json | Git commit injection (env vars) |
| app.json | Binary metadata (extra field) |
| package.json | OTA publish scripts |
Quick Reference
Common Commands
Support Checklist
When user reports a bug:- ✅ Ask for Signature
- ✅ Look up commits in git
- ✅ Check if bug is fixed in newer commit
- ✅ Guide user to update if needed
- ✅ Check Sentry for related errors with same signature
Related Documentation
- DEBUG_SYSTEM.md - Debug mode and logging
- SENTRY.md - Error monitoring integration
- publish skill - Publishing app updates to Expo
- ARCHITECTURE.md - System architecture
Maintained by: Development Team
Questions? Check CLAUDE.md or Slack #dev-support